ansible api集成模块

ansible api 实现本地、动态加载Inventory

支持ad_hoc 执行,本地playbook执行

import shutil
import json
from ansible.parsing.dataloader import DataLoader
from ansible.playbook.play import Play
from ansible.executor.task_queue_manager import TaskQueueManager
from ansible.executor.playbook_executor import PlaybookExecutor
from ansible.plugins.callback import CallbackBase
from ansible.inventory.manager import InventoryManager
from ansible.vars.manager import VariableManager
from ansible.utils.path import unfrackpath
from ansible import constants as C
from ansible.errors import AnsibleError
from ansible import context
from optparse import Values
from multiprocessing import cpu_count
import time

###########################
## ansible version:2.8.2 ##
###########################


class Inventory_var:


    class My_InventoryManager(InventoryManager):

        def parse_sources(self, cache=False):

            parsed = False

            for source in self._sources:

                if source:
                    if ',' not in source:
                        source = unfrackpath(source, follow=False)
                    parse = self.parse_source(source, cache=cache)
                    if parse and not parsed:
                        parsed = True

            if parsed:

                self._inventory.reconcile_inventory()
            else:

                if C.INVENTORY_UNPARSED_IS_FAILED:
                    raise AnsibleError("No inventory was parsed, please check your configuration and options.")

    def __init__(self, loader,):

        self.loader = loader
        self.inventory = self.My_InventoryManager(loader=self.loader, sources=None)

    def local_inventory(self, local_resource):
        self.inventory = InventoryManager(loader=self.loader, sources=local_resource)
        self.variable_manager = VariableManager(loader=self.loader, inventory=self.inventory)
        return self

    def __add_dynamic_inventory(self, hosts, groupname, ):


        self.inventory.add_group(group=groupname)

        for host in hosts:
            ip = host.get("ip")
            hostport = host.get("port")
            self.inventory.add_host(host=ip, group=groupname, port=hostport)
            self.inventory.add_host(host=ip, group='all', port=hostport)

    def __set_variable(self, hosts,):

        for host in hosts:
            my_host = self.inventory.get_host(hostname=host.get("ip"))
            hostname = host.get("hostname")

            self.variable_manager.set_host_variable(host=my_host,varname='ansible_ssh_host',value= host.get('ip', hostname))
            self.variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_port', value=host.get("port"))
            self.variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_user', value=host.get("username"))
            self.variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_pass', value=host.get("password"))
            self.variable_manager.set_host_variable(host=my_host, varname='ansible_ssh_private_key_file', value= host.get("ssh_key"))

            for key, value in host.items():
                if key not in ["hostname", "port", "username", "password"]:
                    self.variable_manager.set_host_variable(host=my_host, varname=key, value=value,)

    def dynamic_inventory(self, dynamic_resource: dict):


        if isinstance(dynamic_resource, dict):
            for groupname, hosts_and_vars in dynamic_resource.items():
                self.__add_dynamic_inventory(hosts=hosts_and_vars.get("hosts"), groupname=groupname,)
            self.variable_manager = VariableManager(loader=self.loader, inventory=self.inventory)
            for groupname, hosts_and_vars in dynamic_resource.items():
                self.__set_variable(hosts=hosts_and_vars.get("hosts"))
        return self

class ResultCallback(CallbackBase):

    def __init__(self,log:list, *args, **kwargs,):
        super(ResultCallback, self).__init__(*args, **kwargs)
        self.log = log

    def logmanager(self,result,):

        self.result_json = ({ result._host.name: result._result})
        self.log.append(self.result_json)


    def v2_runner_on_ok(self, result, **kwargs):

        self.logmanager(result)

    def v2_runner_on_failed(self, result, ignore_errors=False):
        self.logmanager(result)

    def v2_runner_on_skipped(self, result):
        #if C.DISPLAY_SKIPPED_HOSTS:
            self.logmanager(result)

    def v2_runner_on_unreachable(self, result):
        self.logmanager(result)

class Play_source:

    def __init__(self,name:str,hosts,tasks:list,gather_facts='no'):

        self.source = dict(
            name=name,
            hosts=hosts,
            gather_facts=gather_facts,
            # dict(action=dict(module='debug', args=dict(msg='{{shell_out.stdout}}')))
            tasks=[
                dict(action=dict(module=task['module'], args=task['args']),register='shell_out',)
                for task in tasks
            ]
        )

class Ansible_scheduler:

    def __init__(self,loader,inventory_var:Inventory_var ,options,password=None,extra_vars= dict()):

        self.loader = loader
        self.inventory_var = inventory_var
        self.options = Values(options)
        context._init_global_context(self.options)

        self.password = password


    def run_moudle(self,play_source:Play_source,log=[]):

        play = Play().load(play_source.source, variable_manager=self.inventory_var.variable_manager, loader=self.loader,)
        tqm = None

        try:
            tqm = TaskQueueManager(
                inventory=self.inventory_var.inventory,
                variable_manager=self.inventory_var.variable_manager,
                loader=self.loader,
                passwords=self.password,
                stdout_callback=ResultCallback(log=log),
            )
            result = tqm.run(play)
        finally:

            if tqm is not None:
                tqm.cleanup()

            shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)
        #result = self.log[:]
        #self.log = []
        return  log


    def run_playbook(self, playbook_path:list,log=[]):

        # self.variable_manager.extra_vars = {'customer': 'test', 'disabled': 'yes'}
        C.DEFAULT_STDOUT_CALLBACK = ResultCallback(log=log)
        playbook = PlaybookExecutor(playbooks=playbook_path,
                                    inventory=self.inventory_var.inventory,
                                    variable_manager=self.inventory_var.variable_manager,
                                    loader=self.loader,
                                    passwords=self.password,

                                    )
        playbook.run()
        return log

class Options:
    def __init__(self,options:dict,):
        self.options = options
        #

        self.options.setdefault('verbosity', options.get('verbosity', 0))
        self.options.setdefault('check', options.get('check', False))
        self.options.setdefault('diff', options.get('diff', False))
        self.options.setdefault('extra_vars', options.get('extra_vars', {}))
        self.options.setdefault('fork', options.get('fork', cpu_count()))
        self.options.setdefault('inventory', options.get('inventory', None))
        self.options.setdefault('connection', options.get('connection', 'smart'))
        self.options.setdefault('timeout', options.get('timeout', 10))
        self.options.setdefault('remote_user', options.get('remote_user', None))
        self.options.setdefault('ask_pass', options.get('ask_pass', False))
        self.options.setdefault('private_key_file', options.get('private_key_file', None))
        self.options.setdefault('ask_vault_pass', options.get('ask_vault_pass', False))
        self.options.setdefault('vault_password_files', options.get('vault_password_files', []))
        self.options.setdefault('vault_ids', options.get('vault_ids', []))
        self.options.setdefault('module_path', options.get('module_path', None))
        self.options.setdefault('listtasks', options.get('listtasks', None))
        self.options.setdefault('listtags', options.get('listtags', None))
        self.options.setdefault('step', options.get('step', None))
        self.options.setdefault('start_at_task', options.get('start_at_task', None))
        self.options.setdefault('args', options.get('args', None))
        self.options.setdefault('force_handlers', options.get('force_handlers', False))
        self.options.setdefault('flush_cache', options.get('flush_cache', None))

        self.options.setdefault('tags', options.get('tags', ['all']))
        self.options.setdefault('skip_tags', options.get('skip_tags', []))
        self.options.setdefault('syntax', options.get('syntax', None))
        self.options.setdefault('listhosts', options.get('listhosts', None))
        self.options.setdefault('subset', options.get('subset', None))
        self.options.setdefault('listtasks', options.get('listtasks', None))
        self.options.setdefault('listtags', options.get('listtags', None))

        self.options.setdefault('sftp_extra_args', options.get('sftp_extra_args', ''))
        self.options.setdefault('scp_extra_args', options.get('scp_extra_args', ''))
        self.options.setdefault('ssh_extra_args', options.get('ssh_extra_args', ''))
        self.options.setdefault('ssh_common_args', options.get('ssh_common_args', ''))
        self.options.setdefault('become', options.get('become', False))
        self.options.setdefault('become_method', options.get('become_method', 'sudo'))
        self.options.setdefault('become_user', options.get('become_user', None))
        self.options.setdefault('become_ask_pass', options.get('become_ask_pass', False))

def lock(task_func):

    def run(self, *args, **kwargs):
        try:
            if self.locked:
                self.log_manager({'logid':'task','log':'task locking'})
            else:
                self.locked = True
                self.log_manager({'logid':'task','log':'task running'})
                task_func(self, *args, **kwargs)
                self.locked = False
        except Exception as e:
            self.locked = False
            self.log_manager({'logid':'task','log':'task erro','erro':str(e)})
    return run

class Ansible_manager:

    # task locking
    # task running
    # task erro


    def __init__(self,local_resource:list,dynamic_esource:list,):

        self.loader = DataLoader()
        self.Inventory_var = Inventory_var(self.loader)
        [ self.Inventory_var.local_inventory(source) for source in local_resource  ]
        [ self.Inventory_var.dynamic_inventory(source) for source in dynamic_esource ]
        self.options = {}
        self.Ansible_scheduler = Ansible_scheduler(loader=self.loader,inventory_var=self.Inventory_var,
                                                   options=Options(self.options).options)
        self.locked = False
        pass

    def set_inventory_var(self,local_resource:list,dynamic_esource:list,):
        self.Inventory_var = Inventory_var(self.loader)
        [self.Inventory_var.local_inventory(source) for source in local_resource]
        [self.Inventory_var.dynamic_inventory(source) for source in dynamic_esource]
        self.Ansible_scheduler = Ansible_scheduler(loader=self.loader, inventory_var=self.Inventory_var,
                                                   options=Options(self.options).options)

    def set_options(self,options:dict):
        self.options = options
        self.Ansible_scheduler = Ansible_scheduler(loader=self.loader, inventory_var=self.Inventory_var,
                                                   options=Options(self.options).options)


    @lock
    def ad_hoc(self,name:str,hostlist:list,tasks:list):
        if not len(name) or not len(hostlist) or not len(tasks):
            print('The variable cannot be empty')
            raise Exception

        # tasks = [{'module':'shell','args':'sleep 5;hostname'}]
        play_source = Play_source(name=name, hosts=hostlist, tasks=tasks)
        result = self.Ansible_scheduler.run_moudle(play_source)
        self.log_manager({'logid':str(time.time()).replace('.',''),'taskname':name,'log':result})

    @lock
    def run_playbook_from_file(self,name:str,playbook_path):
        if not len(name) or not len(playbook_path):
            print('The variable cannot be empty')
            raise Exception

        result = self.Ansible_scheduler.run_playbook(playbook_path=playbook_path)
        self.log_manager({'logid':str(time.time()).replace('.',''),'taskname':name,'log':result})



    def log_manager(self, log):
        print(json.dumps(log, indent=4))
        pass





if __name__ == '__main__':

    resource = [{
        "dynamic_host": {
            "hosts": [
                {'username': u'root', 'password': '123456', 'ip': '192.168.0.105', 'hostname': '192', 'port': '22'},
                {'username': u'root', 'password': '123465', 'ip': 'localhost', 'hostname': '150', 'port': '22'},

            ],

        }
    },
    ]

    local_resource = ['/home/lozone/pycharm_project/plugins/ansible/hostslist', ]
    playbook_path = ['/home/lozone/pycharm_project/plugins/ansible/f1.yml','/home/lozone/pycharm_project/plugins/ansible/f2.yml']

    Ansible_manager = Ansible_manager(local_resource=local_resource,dynamic_esource=resource)

    Ansible_manager.set_options({})

    tasks = [{'module': 'shell', 'args': 'touch /tmp/x1'},{'module': 'shell', 'args': 'touch /tmp/x2;'}]


    Ansible_manager.ad_hoc(name='test',hostlist=['localhost','192.168.0.105'],tasks=tasks)
    Ansible_manager.run_playbook_from_file(name='test1',playbook_path=playbook_path)




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值