• 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()
  • 相关阅读:
    MongoDB存储时间
    如何在博客园随笔中增加章节导航
    如何优雅地从CSDN转载文章
    线段树详解(原理、实现与应用)
    Codeforces 1076D——最短路算法
    顶点支配、独立与覆盖
    CodeForces
    数据结构一——顺序表
    平面图的基本概念及性质
    编程之美——一摞烙饼的排序(暴搜+剪枝)
  • 原文地址:https://www.cnblogs.com/infaaf/p/9534332.html
Copyright © 2020-2023  润新知