编者:Matlon
Ansible 作为新出现的运维工具,是基于Python开发的,糅合了众多老牌运维工具的优点,实现了批量操作系统配置、批量程序的部署、批量运行命令等功能。在几个月前发布了2.0版本,变化比较大,大部分被重写,所以许多地方需要重新研究。
如下,我们先看一下之前API的部分代码:
-
import ansible.runner
-
runner = ansible.runner.Runner(
-
module_name='ping',
-
module_args='',
-
pattern='web*',
-
forks=10)datastructure = runner.run()
使用runner 模块就可以调用ansible,执行一系列任务,但在2.0,这就变得比较困难了,首先看如下2.0的API的目录结构:
在2.0中,仍然使用和之前相同的run()方法,但其不在runner模块中了,而在executor模块,它的基本类名是PlaybookExecutor,部分代码如下:
-
def __init__(self, playbooks, inventory, variable_manager, loader, options, passwords):
-
-
self._playbooks = playbooks #获取playbook的地址
-
-
self._inventory = inventory #获取主机列表
-
-
self._variable_manager = variable_manager #获取额外的变量
-
-
self._loader = loader
-
-
self._options = options
-
-
self.passwords = passwords
-
-
self._unreachable_hosts = dict()
-
-
if options.listhosts or options.listtasks or options.listtags or options.syntax
-
-
self._tqm = None
-
-
else:
-
-
self._tqm = TaskQueueManager(inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=self.passwords #通过调用任务管理器来执行playbook
所有的调度逻辑由run()来实现,playbook中的task由TaskQueueManager与taskExecutor来管理执行,暂时不需要理解,我们现在只需要去了解inventory和playbook如何获取,就可以简单执行,进到inventory目录,找到它的主要模块,
-
def __init__(self, loader,variable_manager,host_list=C.DEFAULT_HOST_LIST):
inventory 可以传参,参数的格式和类型需要考虑,解析如下:
#如果是str,根据逗号来区分并且去除空格,放到list里面
-
if isinstance(host_list, string_types):
-
if "," in host_list:
-
host_list = host_list.split(",")
-
host_list = [ h for h in host_list if h and h.strip() ]
#host_list没有传入参数时,默认是去找/etc/ansible/hosts文件的
-
if host_list is None:
-
pass
#如果是list类型,直接解析
-
elif isinstance(host_list, list):
-
for h in host_list:
-
(host, port) = parse_address(h, allow_ranges=False)
-
all.add_host(Host(host, port))
#如果你指定host位置,它会从你的指定文件读入的,如果是hosts脚本,需返回一个json格式的对象。
-
elif self._loader.path_exists(host_list):
-
if self.is_directory(host_list):
-
# Ensure basedir is inside the directory
-
host_list = os.path.join(self.host_list, "")
-
self.parser = InventoryDirectory(loader=self._loader, groups=self.groups, filename=host_list) #group一般设为all、ungrouped
-
else:
-
self.parser = get_file_parser(host_list, self.groups, self._loader)
-
vars_loader.add_directory(self.basedir(), with_subdir=True)
综上:我们只要给inventory传入特定格式的参数,就可以处理host_list
之后,再看playbook如何传入,进入playbook 目录,找到playbook的初始化模块,有一个load()函数,就是获取playbook的文件路径,来加载playbook,如下:
-
def load(file_name, variable_manager=None, loader=None):
-
pb = Playbook(loader=loader)
-
pb._load_playbook_data(file_name=file_name, variable_manager=variable_manager)
-
return pb
当然,也可以运行单个play,在playbook目录可以看到有一个play的模块,同样是load方法,只不过它获取的是一个dict类型对象,如下:
-
play_data = dict(
-
name = "Ansible play",
-
hosts = "localhost",
-
tasks = [
-
dict(action=dict(module='shell',args='ls'),register='shell_out')
-
]
-
)
-
-
play = Play.load(play_data,variable_manager=variable_manager,loader=loader)
最终,可以得到如下API脚本:
-
#!/bin/env python
-
import os
-
import sys
-
import json
-
from collections import namedtuple
-
from ansible.parsing.dataloader import DataLoader
-
from ansible.vars import VariableManager
-
from ansible.inventory import Inventory
-
from ansible.executor.playbook_executor import PlaybookExecutor
-
def install(request):
-
if 'ip' in request.GET:
-
ip = request.GET['ip']
-
host = []
-
host.append(ip) #传入一个host列表
-
variable_manager = VariableManager()
-
loader = DataLoader()
-
inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=host)
-
playbook_path = '/etc/ansible/main.yml #传入一个playbook路径
-
Options = namedtuple('Options', ['listtags', 'listtasks', 'listhosts', 'syntax', 'connection','module_path', 'forks', 'remote_user', 'private_key_file','ssh_common_args','ssh_extra_args','sftp_extra_args', 'scp_extra_args', 'become', 'become_method', 'become_user', 'verbosity', 'check'])
-
options = Options(listtags=False, listtasks=False, listhosts=False, syntax=False, connection='ssh', module_path=None, forks=100, remote_user='root, private_key_file=None, ssh_common_args=None, ssh_extra_args=None,
sftp_extra_args=None, scp_extra_args=None, become=True,
become_method=None, become_user='root', verbosity=None, check=False)
passwords = {}
pbex = PlaybookExecutor(playbooks=[playbook_path],
inventory=inventory, variable_manager=variable_manager, loader=loader,
options=options, passwords=passwords)
results = pbex.run() #返回的结果是数字,不同的结果对应不同的数字
return 1
else:
return 0
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/30109892/viewspace-2063898/
,如需转载,请注明出处,否则将追究法律责任。