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博客 ” ,链接:http://blog.itpub.net/30109892/viewspace-2063898/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/30109892/viewspace-2063898/