zoukankan      html  css  js  c++  java
  • ansible 2.4+ allinone 接口

    参考/整理/改写 allinone接口 ,实现playbook,adhoc 调用。

    日志部分待完善

    #!/usr/bin/env python
    # -*- coding=utf-8 -*-
    
    # leaning ansbile api ing~
    
    import json, sys, os
    import logging
    from ansible import constants
    from collections import namedtuple
    from ansible.parsing.dataloader import DataLoader
    from ansible.inventory.manager import InventoryManager
    from ansible.vars.manager import VariableManager
    from ansible.inventory.host import Host, Group
    from ansible.plugins.callback import CallbackBase
    from ansible.playbook.play import Play
    from ansible.executor.task_queue_manager import TaskQueueManager
    from ansible.executor.playbook_executor import PlaybookExecutor
    
    
    class MyInventory():
    
        '''
        resource = [{'hostid': '1231', 'hostname': 'h1', 'hostip': '1.1.1.1'},
                    {'hostid': '2345', 'hostname': 'h2', 'hostip': '2.2.2.2'},
                    ]
        resource = {'groupname1': {
            'hosts': [
                {'hostid': '1231', 'hostname': 'h1', 'hostip': '1.1.1.1'},
                {'hostid': '2231', 'hostname': 'h2', 'hostip': '1.1.1.2'},
                     ],
            'groupvars': {"k1":"v1"}
                                  },
                    'groupname2': {'hosts': [], 'groupvars': {}},
                                  }
        '''
    
        # edit ori code  ansible/inventory/manage.pay line215  try if C.InventoryManager_PARSE_NOSOURCE:pass
        constants.InventoryManager_PARSE_NOSOURCE=True
        def __init__(self,resource):
            self.resource=resource
            self.loader=DataLoader()
            # self.inventory=InventoryManager(loader=self.loader,sources=['/etc/ansible/hosts'])
            self.inventory=InventoryManager(loader=self.loader)
            self.variable_manager=VariableManager(loader=self.loader,inventory=self.inventory)
            self._parse(self.resource)
    
        def _parse(self,resource):
            if isinstance(resource,list):
                self._addGroupHosts(self.resource)
            elif isinstance(resource,dict):
                # logging.info('parsing resuorce: %s'%(self.resource))
                for groupname,hosts_and_groupvars in self.resource.items():
                    print("[1] groupname: %s |hostsandvars: %s"%(groupname,hosts_and_groupvars))                                                    # debug [1]
                    self._addGroupHosts(hosts_and_groupvars.get('hosts'),groupname,hosts_and_groupvars.get('groupvars'))
    
            else:
                logging.error('resource error ,need dict or list')
    
        def _addGroupHosts(self,hosts,groupname='default',groupvars=None):
            self.inventory.add_group(group=groupname)
            group=Group(groupname)
            if groupvars:
                for k,v in groupvars.items():
                    group.set_variable(k,v)
    
            # hosts=[{'hostid':'123','hostname':'h1','hostip':'192.168.188.20'}
            for host in hosts:
                hostid=host.get('hostid')
                hostname=host.get('hostname')
                hostip=host.get('hostip')
                username=host.get('username')
                password=host.get('password')
                port=host.get('port',22)
                sshkey=host.get('sshkey')
                if hostname:
                    self.inventory.add_host(host=hostname,group=groupname)   # by default, indentify by hostname and need
                    hostobj= self.inventory.get_host(hostname=hostname)     # add host= , get hostname=
    
                    self.variable_manager.set_host_variable(host=hostobj,varname='ansible_ssh_host',value=hostip)
                    self.variable_manager.set_host_variable(host=hostobj,varname='ansible_ssh_port',value=port)
                    self.variable_manager.set_host_variable(host=hostobj,varname='ansible_ssh_user',value=username)
                    self.variable_manager.set_host_variable(host=hostobj,varname='ansible_ssh_pass',value=password)
                    self.variable_manager.set_host_variable(host=hostobj,varname='ansible_ssh_private_key_file',value=sshkey)
    
                    # TODO: other vars such as become-method-user-pass
                    #hostobj.set_variable('ansible_ssh_port',port)
                    for k,v in host.items():
                        if k not in ['hostip','port','username','password','sshkey']:
                            hostobj.set_variable(k,v)
                else:
                    logging.warning('resource error:cant get hostname from | %s'%resource)
    
        def testcase(self):
            print(self.inventory.get_groups_dict())
            host=self.inventory.get_host(hostname='h1')
            print(self.variable_manager.get_vars(host=host))
    
    
    class ADhocCallback(CallbackBase):
        def __init__(self, *args, **kwargs):
            super(ADhocCallback, self).__init__(*args, **kwargs)
            self.result_row={'ok':{},'failed':{},'unreachable':{}}
    
        def v2_runner_on_ok(self, result,  *args, **kwargs):
            self.result_row['ok'][result._host.get_name()] = result._result
            logging.info('===v2_runner_on_ok===host=%s===result=%s' % (result._host.get_name(), result._result))
    
    
        def v2_runner_on_unreachable(self, result,*args,**kwargs):
            self.result_row['unreachable'][result._host.get_name()]=result._result
    
        def v2_runner_on_failed(self, result,  *args, **kwargs):
            self.result_row['failed'][result._host.get_name()]=result._result
    
    
    class PlayBookCallback(CallbackBase):
        # CALLBACK_VERSION = 2.0
        def __init__(self, *args, **kwargs):
            super(PlayBookCallback, self).__init__(*args, **kwargs)
            self.result_row={'ok':{},'failed':{},'unreachable':{},'skipped':{},'status':{}}
    
        def v2_runner_on_ok(self, result,  *args, **kwargs):
            # print(result._host.get_name())
            # print("run on ok %s"%result._result)
            self.result_row['ok'][result._host.get_name()] = result._result
    
        def v2_runner_on_unreachable(self, result,*args,**kwargs):
            self.result_row['unreachable'][result._host.get_name()]=result._result
    
        def v2_runner_on_failed(self, result,  *args, **kwargs):
            self.result_row['failed'][result._host.get_name()]=result._result
    
        def v2_runner_on_skipped(self, result):
            self.result_row['skipped'][result._host.get_name()]=result._result
    
        def v2_playbook_on_stats(self, stats):
            # print(stats)
            hosts = sorted(stats.processed.keys())
            for h in hosts:
                t = stats.summarize(h)
                self.result_row['status'][h] = {
                                           "ok":t['ok'],
                                           "changed" : t['changed'],
                                           "unreachable":t['unreachable'],
                                           "skipped":t['skipped'],
                                           "failed":t['failures']
                                       }
    
    
    
    
    class Runner():
        def __init__(self,resource=None):
            self.resource = resource
            self.inventory = None
            self.variable_manager = None
            self.loader = None
            self.options = None
            self.passwords = None
            self.callback = None
            self.__initializeData()
            self.results_raw = None
    
        def __initializeData(self):
            Options = namedtuple('Options', ['connection','module_path', 'forks', 'timeout',  'remote_user',
                    'ask_pass', 'private_key_file', 'ssh_common_args', 'ssh_extra_args', 'sftp_extra_args',
                    'scp_extra_args', 'become', 'become_method', 'become_user', 'ask_value_pass', 'verbosity',
                    'check', 'listhosts', 'listtasks', 'listtags', 'syntax','diff'])
            self.options = Options(connection='smart', module_path=None, forks=100, timeout=10,
                    remote_user='root', ask_pass=False, private_key_file=None, ssh_common_args=None, ssh_extra_args=None,
                    sftp_extra_args=None, scp_extra_args=None, become=None, become_method=None,
                    become_user='root', ask_value_pass=False, verbosity=None, check=False, listhosts=False,
                    listtasks=False, listtags=False, syntax=False, diff=True)
            self.passwords = dict(sshpass=None, becomepass=None)
            self.loader = DataLoader()
    
            # case1: no resource , use /etc/ansible/hosts
            if self.resource:
                myinventory = MyInventory(self.resource)
                self.inventory=myinventory.inventory
                self.variable_manager=myinventory.variable_manager
    
        def run_model(self, host_list, module_name, module_args):
            """
            ansible group1 -m shell -a 'ls /tmp'
            """
            self.callback = ADhocCallback()
            play_source = dict(
                    name="Ansible Play",
                    hosts=host_list,
                    gather_facts='no',
                    tasks=[dict(action=dict(module=module_name, args=module_args))]
            )
            play = Play().load(play_source, variable_manager=self.variable_manager, loader=self.loader)
            tqm = None
            try:
                tqm = TaskQueueManager(
                        inventory=self.inventory,
                        variable_manager=self.variable_manager,
                        loader=self.loader,
                        options=self.options,
                        passwords=self.passwords,
                        stdout_callback = "minimal",
                )
                tqm._stdout_callback = self.callback
                constants.HOST_KEY_CHECKING = False #关闭第一次使用ansible连接客户端是输入命令
                tqm.run(play)
                self.results_raw=self.callback.result_row
            except Exception as err:
                print(err)
            finally:
                if tqm is not None:
                    tqm.cleanup()
    
        def run_playbook(self,playbookpath,extra_vars=None,localhostlist=None):
            # TODO log now is mixing in hostsresult . => play n/group /task n /
    
            # case1: no resource , use /etc/ansible/hosts
            if localhostlist:
                self.inventory=InventoryManager(loader=self.loader,sources=localhostlist)
                self.variable_manager = VariableManager(loader=self.loader, inventory=self.inventory)
    
            self.callback=PlayBookCallback()
            try:
                # if self.redisKey:self.callback = PlayBookResultsCollectorToSave(self.redisKey,self.logId)
                if extra_vars:self.variable_manager.extra_vars = extra_vars
                executor = PlaybookExecutor(
                    playbooks=[playbookpath],
                    inventory=self.inventory,
                    variable_manager=self.variable_manager,
                    loader=self.loader,
                    options=self.options,
                    passwords=self.passwords,
                )
                executor._tqm._stdout_callback = self.callback
                constants.HOST_KEY_CHECKING = False #关闭第一次使用ansible连接客户端是输入命令
                executor.run()
                self.results_raw=self.callback.result_row
            except Exception as err:
                return False
    
    
    def _example1():
        # test inventory
        resource={'group1':{'hosts':[{'hostid':'123','hostname':'h1','hostip':'192.168.188.200','username':'root',
                                      'password':'admin','port':'22','sshkey':'','k1':'v1'},
                                     {'hostid': '223', 'hostname': 'h2', 'hostip': '192.168.188.201', 'username': 'root',
                                      'password': '1qaz@WSX', 'port': '22', 'sshkey': '',},
                                     ],
                            'groupvars':{"g1key":"g1value"}},
                  }
        # test inventory
        iobj=MyInventory(resource)
        iobj.testcase()
    
    
    def _example2():
        # server playbook +  server inventory
        runner = Runner()
        runner.run_playbook(playbookpath='/etc/ansible/myplay.yaml', localhostlist=['/etc/ansible/hosts'])
        result = runner.results_raw
        print(json.dumps(result, indent=4))
    
    
    def _example3():
        # server playbook  + dynamic inventory
        resource={'group1':{'hosts':[{'hostid':'123','hostname':'h1','hostip':'192.168.188.200','username':'root',
                                      'password':'admin','port':'22','sshkey':'','k1':'v1'},
                                     {'hostid': '223', 'hostname': 'h2', 'hostip': '192.168.188.201', 'username': 'root',
                                      'password': '1qaz@WSX', 'port': '22', 'sshkey': '',},
                                     ],
                            'groupvars':{"g1key":"g1value"}},
                  }
        runner = Runner(resource)
        runner.run_playbook(playbookpath='/etc/ansible/myplay.yaml')
    
    
    
    def _example4():
        #  use adhoc  + dynamic inventory
        resource={'group1':{'hosts':[{'hostid':'123','hostname':'h1','hostip':'192.168.188.200','username':'root',
                                      'password':'admin','port':'22','sshkey':'','k1':'v1'},
                                     {'hostid': '223', 'hostname': 'h2', 'hostip': '192.168.188.201', 'username': 'root',
                                      'password': '1qaz@WSX', 'port': '22', 'sshkey': '',},
                                     ],
                            'groupvars':{"g1key":"g1value"}},
                  }
        runner = Runner(resource)
        runner.run_model(host_list=['h2'], module_name='shell', module_args='ls /tmp')
        result = runner.results_raw
        print(result)
    
    
    if __name__ == '__main__':
    
    
        # _example1()
        # _example2()
        # _example3()
        _example4()
  • 相关阅读:
    干掉 LaTeX !用BookDown写本书
    Java面试指北!13个认证授权常见面试题/知识点总结!| JavaGuide
    写了个简洁的Typora+Markdown简历模板
    有哪些可以提高代码质量的书籍推荐?
    京东数科面试真题:常见的 IO 模型有哪些?Java 中的 BIO、NIO、AIO 有啥区别?
    国内有哪些顶级技术团队的博客值得推荐?
    两万字长文总结,梳理 Java 入门进阶那些事
    藏在栈里的金丝雀
    surging 如何使用流媒体服务
    低代码平台--基于surging开发微服务编排流程引擎构思
  • 原文地址:https://www.cnblogs.com/infaaf/p/9534332.html
Copyright © 2011-2022 走看看