Jusene's Blog

ansible api接口调试

字数统计: 1.2k阅读时长: 6 min
2017/04/16 Share

ansible

ansible是自动化运维工具,越来越多的底层自动化采用ansible的接口来实现,这个工具也提供可以提供了调用的api接口,ansible官网提供原始的api接口调用实例。

1
#!/usr/bin/env python
2
3
import json
4
from collections import namedtuple
5
from ansible.parsing.dataloader import DataLoader
6
from ansible.vars import VariableManager
7
from ansible.inventory import Inventory
8
from ansible.playbook.play import Play
9
from ansible.executor.task_queue_manager import TaskQueueManager
10
from ansible.plugins.callback import CallbackBase
11
12
class ResultCallback(CallbackBase):
13
    """A sample callback plugin used for performing an action as results come in
14
15
    If you want to collect all results into a single object for processing at
16
    the end of the execution, look into utilizing the ``json`` callback plugin
17
    or writing your own custom callback plugin
18
    """
19
    def v2_runner_on_ok(self, result, **kwargs):
20
        """Print a json representation of the result
21
22
        This method could store the result in an instance attribute for retrieval later
23
        """
24
        host = result._host
25
        print json.dumps({host.name: result._result}, indent=4)
26
27
Options = namedtuple('Options', ['connection', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check'])
28
# initialize needed objects
29
variable_manager = VariableManager()
30
loader = DataLoader()
31
options = Options(connection='local', module_path='/path/to/mymodules', forks=100, become=None, become_method=None, become_user=None, check=False)
32
passwords = dict(vault_pass='secret')
33
34
# Instantiate our ResultCallback for handling results as they come in
35
results_callback = ResultCallback()
36
37
# create inventory and pass to var manager
38
inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list='localhost')
39
variable_manager.set_inventory(inventory)
40
41
# create play with tasks
42
play_source =  dict(
43
        name = "Ansible Play",
44
        hosts = 'localhost',
45
        gather_facts = 'no',
46
        tasks = [
47
            dict(action=dict(module='shell', args='ls'), register='shell_out'),
48
            dict(action=dict(module='debug', args=dict(msg='{{shell_out.stdout}}')))
49
         ]
50
    )
51
play = Play().load(play_source, variable_manager=variable_manager, loader=loader)
52
53
# actually run it
54
tqm = None
55
try:
56
    tqm = TaskQueueManager(
57
              inventory=inventory,
58
              variable_manager=variable_manager,
59
              loader=loader,
60
              options=options,
61
              passwords=passwords,
62
              stdout_callback=results_callback,  # Use our custom callback instead of the ``default`` callback plugin
63
          )
64
    result = tqm.run(play)
65
finally:
66
    if tqm is not None:
67
        tqm.cleanup()

解析下这个api接口示例:

  1. 导入必要的模块

    1
    import json
    2
    from collections import namedtuple
    3
    from ansible.parsing.dataloader import DataLoader
    4
    from ansible.vars import VariableManager
    5
    from ansible.inventory import Inventory
    6
    from ansible.playbook.play import Play
    7
    from ansible.executor.task_queue_manager import TaskQueueManager
    8
    from ansible.plugins.callback import CallbackBase
  2. 定义要使用的命名空间
    改部分是api接口的初始化,传入必要的参数。

    1
    Options = namedtuple('Options', ['connection', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check'])
    2
    # initialize needed objects
    3
    variable_manager = VariableManager()
    4
    loader = DataLoader()
    5
    options = Options(connection='local', module_path='/path/to/mymodules', forks=100, become=None, become_method=None, become_user=None, check=False)
    6
    passwords = dict(vault_pass='secret')
    7
    8
    # Instantiate our ResultCallback for handling results as they come in
    9
    results_callback = ResultCallback()
    10
    11
    # create inventory and pass to var manager
    12
    inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list='localhost')
    13
    variable_manager.set_inventory(inventory)
  3. 编写执行的命令

    1
    play_source =  dict(
    2
            name = "Ansible Play",
    3
            hosts = 'localhost',
    4
            gather_facts = 'no',
    5
            tasks = [
    6
                dict(action=dict(module='shell', args='ls'), register='shell_out'),
    7
                dict(action=dict(module='debug', args=dict(msg='{{shell_out.stdout}}')))
    8
             ]
    9
        )
    10
    play = Play().load(play_source, variable_manager=variable_manager, loader=loader)
  4. 把上面的命令放入执行队列中执行

    1
    tqm = None
    2
    try:
    3
        tqm = TaskQueueManager(
    4
                  inventory=inventory,
    5
                  variable_manager=variable_manager,
    6
                  loader=loader,
    7
                  options=options,
    8
                  passwords=passwords,
    9
                  stdout_callback=results_callback,  # Use our custom callback instead of the ``default`` callback plugin
    10
              )
    11
        result = tqm.run(play)
    12
    finally:
    13
        if tqm is not None:
    14
            tqm.cleanup()

自己修改的api接口

1
#!/usr/bin/env python  
2
# -*- coding: UTF-8 -*-  
3
import json  
4
from collections import namedtuple  
5
from ansible.parsing.dataloader import DataLoader  
6
from ansible.vars import VariableManager  
7
from ansible.inventory import Inventory  
8
from ansible.playbook.play import Play  
9
from ansible.executor.task_queue_manager import TaskQueueManager  
10
from ansible.plugins.callback import CallbackBase  
11
       
12
class ResultCallback(CallbackBase):  
13
        host = result._host  
14
        print (json.dumps({host.name: result._result}, indent=4))  
15
      
16
      
17
def ansibleRun(host_list,task_list):  
18
    Options = namedtuple('Options',  
19
                             ['connection','module_path','forks','remote_user','private_key_file',  
20
                              'ssh_common_args','ssh_extra_args','sftp_extra_args','scp_extra_args',  
21
                              'become','become_method','become_user','verbosity','check'])  
22
      
23
 
24
    variable_manager = VariableManager()  
25
    loader = DataLoader()  
26
    options = Options(  connection='smart',module_path=None,  
27
                            forks=100,remote_user=None,private_key_file=None,ssh_common_args=None,ssh_extra_args=None,  
28
                            sftp_extra_args=None,scp_extra_args=None,become=None,become_method=None,  
29
                            become_user=None,verbosity=None,check=False  
30
                         )  
31
      
32
    passwords = dict()  
33
    results_callback = ResultCallback()  
34
    inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=host_list)  
35
    variable_manager.set_inventory(inventory)  
36
      
37
    play_source =  dict(  
38
                name = "Ansible Play",  
39
                hosts = host_list,  
40
                gather_facts = 'no',  
41
                tasks = task_list  
42
            )  
43
    play = Play().load(play_source, variable_manager=variable_manager, loader=loader)  
44
      
45
    tqm = None  
46
    try:  
47
            tqm = TaskQueueManager(  
48
                    inventory=inventory,variable_manager=variable_manager,  
49
                    loader=loader,options=options,passwords=passwords,  
50
                    stdout_callback=results_callback,  
51
                )  
52
            result = tqm.run(play)  
53
    finally:  
54
            if tqm is not None:  
55
                tqm.cleanup()  
56
      
57
if __name__ == '__main__':  
58
        host_list = ['10.14.86.177', '10.14.86.178']  
59
        tasks_list = [  
60
            dict(action=dict(module='command', args='pwd')),  
61
            dict(action=dict(module='shell', args='python sleep.py')),  
62
            dict(action=dict(module='synchronize', args='src=/home/op/test dest=/home/opt/ delete=yes')),  
63
        ]  
64
        ansibleRun(host_list,tasks_list)

这样的调用只适合临时命令调用,如果我们需要执行大量自动化任务,需要修改的大量代码,所以我们需要可以封装称调用playbook的方式来使用。

1
#!/usr/bin/env python  
2
# -*- coding: UTF-8 -*-
3
4
import os
5
import sys
6
from collections import namedtuple
7
form ansible.parsing.dataloader import DataLoader
8
from ansible.vars import VariableManager
9
from ansible.inventory import Inventory
10
from ansible.executor.playbook_executor import PlaybookExecutor
11
from ansible.utils.display import log_file
12
13
variable_manager = VariableManager()  
14
loader = DataLoader()
15
16
inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list='/etc/ansible/hosts')
17
18
Options = namedtuple('Options',
19
						['listtags','listtasks','listhosts','synatx','connections','module_path','forks','private_key_file','ssh_common_args',
20
						'ssh_extra_args','sftp_extra_args','scp_extra_args','become','become_method','become_user','verbosity','check'])
21
22
opotions=Opotions(listtags=False,listtasks=False,listhosts=False,synatx=False,connections='smart',module_path=None,forks=100,private_key_file=None,ssh_common_args=None,
23
						ssh_extra_args=None,sftp_extra_args=None,scp_extra_args=None,become=False,become_method=None,become_user=None,verbosity=None,check=False)
24
25
playbook_path='ping.yml'
26
vaiable_manager.extra_vars={'aa':'xx'}
27
if not os.path.exists(playbook_path):
28
	print('[WARING]:The playbook does not exitst')
29
	sys.exit()
30
31
passwords={}
32
33
pbex=PlaybookExecutor(playbook=[playbook_path],inventory=inventory,variable_manager=variable_manager,loader=loader,opotions=opotions,passwords=passwords)
34
code=pbex.run()
35
stats=pbex._tqm_.stats
36
hosts=sorted(stats.processed.keys())
37
result=[{h:stats.summarize(h)} for h in hosts]
38
results={'code':code,'result':result,'playbook':playbook_path}
39
print(results)

这样的api接口虽然可以返回执行结果,但是无法返回ansible的执行日志,无法快速定位playbook的bug所在,也是无法得到最终用户的认可的,如果我们需要,我们就需要修改其源码了,后续我还需要测试。

CATALOG
  1. 1. ansible
  2. 2. 自己修改的api接口