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()
  • 相关阅读:
    未进入Kali Linux系统修改修改密码的方法
    SQL 修改字段名,数据类型,增加字段
    在 SAE 上部署 ThinkPHP 5.0 RC4
    在 C# 里使用 F# 的 option 变量
    Retinex图像增强和暗通道去雾的关系及其在hdr色调恢复上的应用
    暗通道去雾算法的python实现
    解析hdr图像文件的python实现
    博客说明
    retinex图像增强算法的研究
    我知道的JavaScript设计模式(桥接)应用之验证器
  • 原文地址:https://www.cnblogs.com/infaaf/p/9534332.html
Copyright © 2011-2022 走看看