2.x的ansible api和1.x的api差别是很大的
在1.x中
import ansible.runner
import json
runner = ansible.runner.Runner(
module_name='ping', # 模块名
module_args='', # 模块参数
pattern='all', # 目标机器的pattern
forks=10
)
datastructure = runner.run()
data = json.dumps(datastructure,indent=4)
from ansible import callbacks
from ansible import utils
from ansible.playbook import PlayBook
stats = callbacks.AggregateStats()
callback = callbacks.PlaybookCallbacks()
runner_callbacks = callbacks.PlaybookRunnerCallbacks(stats)
pb = ansible.playbook.PlayBook(
playbook="tasks.yml",
stats=stats,
callbacks=playbook_cb,
runner_callbacks=runner_cb,
check=True
)
pb.run()
以上是1.x的ad_hoc和playbook的api调用比较简单直接
但是2.x的api相当于自己编写runner方法
下面就是ansible2.0的ad_hoc和playbook,并且重写了返回结果和Inventory,ansible结果返回Json对象
#!/usr/local/python27/bin/python
#encoding:utf8
import json,sys,os
from collections import namedtuple
from ansible.parsing.dataloader import DataLoader
from ansible.vars import VariableManager
from ansible.inventory import Inventory,Host,Group
from ansible.playbook.play import Play
from ansible.executor.task_queue_manager import TaskQueueManager
from ansible.plugins.callback import CallbackBase
from ansible.executor.playbook_executor import PlaybookExecutor
class MyInventory(Inventory):
def __init__(self, resource, loader, variable_manager):
self.resource = resource
self.inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=[])
self.dynamic_inventory()
def add_dynamic_group(self, hosts, groupname, groupvars=None):
my_group = Group(name=groupname)
if groupvars:
for key, value in groupvars.iteritems():
my_group.set_variable(key, value)
for host in hosts:
# set connection variables
hostname = host.get("hostname")
hostip = host.get('ip', hostname)
hostport = host.get("port")
username = host.get("username")
password = host.get("password")
ssh_key = host.get("ssh_key")
my_host = Host(name=hostname, port=hostport)
my_host.set_variable('ansible_ssh_host', hostip)
my_host.set_variable('ansible_ssh_port', hostport)
my_host.set_variable('ansible_ssh_user', username)
my_host.set_variable('ansible_ssh_pass', password)
my_host.set_variable('ansible_ssh_private_key_file', ssh_key)
for key, value in host.iteritems():
if key not in ["hostname", "port", "username", "password"]:
my_host.set_variable(key, value)
my_group.add_host(my_host)
self.inventory.add_group(my_group)
def dynamic_inventory(self):
if isinstance(self.resource, list):
self.add_dynamic_group(self.resource, 'default_group')
elif isinstance(self.resource, dict):
for groupname, hosts_and_vars in self.resource.iteritems():
self.add_dynamic_group(hosts_and_vars.get("hosts"), groupname,
hosts_and_vars.get("vars"))
class ModelResultsCollector(CallbackBase):
def __init__(self, *args, **kwargs):
super(ModelResultsCollector, self).__init__(*args, **kwargs)
self.host_ok = {}
self.host_unreachable = {}
self.host_failed = {}
def v2_runner_on_unreachable(self, result):
self.host_unreachable[result._host.get_name()] = result
def v2_runner_on_ok(self, result, *args, **kwargs):
self.host_ok[result._host.get_name()] = result
def v2_runner_on_failed(self, result, *args, **kwargs):
self.host_failed[result._host.get_name()] = result
class PlayBookResultsCollector(CallbackBase):
CALLBACK_VERSION = 2.0
def __init__(self,taskList, *args, **kwargs):
super(PlayBookResultsCollector, self).__init__(*args, **kwargs)
self.task_ok = {}
self.task_skipped = {}
self.task_failed = {}
self.task_status = {}
self.task_unreachable = {}
def v2_runner_on_ok(self, result, *args, **kwargs):
if taskList.has_key(result._host.get_name()):
data = {}
data['task'] = str(result._task).replace("TASK: ","")
taskList[result._host.get_name()].get('ok').append(data)
self.task_ok[result._host.get_name()] = taskList[result._host.get_name()]['ok']
def v2_runner_on_failed(self, result, *args, **kwargs):
if taskList.has_key(result._host.get_name()):
data = {}
data['task'] = str(result._task).replace("TASK: ","")
msg = result._result.get('stderr')
if msg is None:
results = result._result.get('results')
if result:
task_item = {}
for rs in results:
msg = rs.get('msg')
if msg:
task_item[rs.get('item')] = msg
data['msg'] = task_item
taskList[result._host.get_name()]['failed'].append(data)
else:
msg = result._result.get('msg')
data['msg'] = msg
taskList[result._host.get_name()].get('failed').append(data)
else:
data['msg'] = msg
taskList[result._host.get_name()].get('failed').append(data)
self.task_failed[result._host.get_name()] = taskList[result._host.get_name()]['failed']
def v2_runner_on_unreachable(self, result):
self.task_unreachable[result._host.get_name()] = result
def v2_runner_on_skipped(self, result):
if taskList.has_key(result._host.get_name()):
data = {}
data['task'] = str(result._task).replace("TASK: ","")
taskList[result._host.get_name()].get('skipped').append(data)
self.task_ok[result._host.get_name()] = taskList[result._host.get_name()]['skipped']
def v2_playbook_on_stats(self, stats):
hosts = sorted(stats.processed.keys())
for h in hosts:
t = stats.summarize(h)
self.task_status[h] = {
"ok":t['ok'],
"changed" : t['changed'],
"unreachable":t['unreachable'],
"skipped":t['skipped'],
"failed":t['failures']
}
class MyRunner(object):
def __init__(self,resource,*args, **kwargs):
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 = {}
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'])
self.variable_manager = VariableManager()
self.loader = DataLoader()
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)
self.passwords = dict(sshpass=None, becomepass=None)
self.inventory = MyInventory(self.resource, self.loader, self.variable_manager).inventory
self.variable_manager.set_inventory(self.inventory)
def run_model(self, host_list, module_name, module_args):
"""
run module from andible ad-hoc.
module_name: ansible module_name
module_args: ansible module args
"""
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
self.callback = ModelResultsCollector()
try:
tqm = TaskQueueManager(
inventory=self.inventory,
variable_manager=self.variable_manager,
loader=self.loader,
options=self.options,
passwords=self.passwords,
)
tqm._stdout_callback = self.callback
result = tqm.run(play)
finally:
if tqm is not None:
tqm.cleanup()
def run_playbook(self, host_list, playbook_path, ):
"""
run ansible palybook
"""
global taskList
taskList = {}
for host in host_list:
taskList[host] = {}
taskList[host]['ok'] = []
taskList[host]['failed'] = []
taskList[host]['skppied'] = []
try:
self.callback = PlayBookResultsCollector(taskList)
executor = PlaybookExecutor(
playbooks=[playbook_path], inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader,
options=self.options, passwords=self.passwords,
)
executor._tqm._stdout_callback = self.callback
executor.run()
except Exception as e:
print e
return False
def get_model_result(self):
self.results_raw = {'success':{}, 'failed':{}, 'unreachable':{}}
for host, result in self.callback.host_ok.items():
self.results_raw['success'][host] = result._result
for host, result in self.callback.host_failed.items():
self.results_raw['failed'][host] = result._result
for host, result in self.callback.host_unreachable.items():
self.results_raw['unreachable'][host]= result._result
return json.dumps(self.results_raw)
def get_playbook_result(self):
self.results_raw = {'skipped':{}, 'failed':{}, 'ok':{},"status":{},'unreachable':{}}
for host, result in self.callback.task_ok.items():
self.results_raw['ok'][host] = result
for host, result in self.callback.task_failed.items():
self.results_raw['failed'][host] = result
for host, result in self.callback.task_status.items():
self.results_raw['status'][host] = result
for host, result in self.callback.task_skipped.items():
self.results_raw['skipped'][host] = result
for host, result in self.callback.task_unreachable.items():
self.results_raw['unreachable'][host] = result._result
return json.dumps(self.results_raw)
if __name__ == '__main__':
module_resource = [
{"hostname": "192.168.222.139", "port": "22", "username": "root", "password": "123456"},
{"hostname": "192.168.222.140", "port": "22", "username": "root", "password": "123456"},
{"hostname": "192.168.222.141", "port": "22", "username": "root", "password": "123456"},
{"hostname": "192.168.222.142", "port": "22", "username": "root", "password": "123456"}
]
playbook_resource = {
"cluster": { #定义的动态主机名,需要跟playbook里面的hosts对应
"hosts": [
{"hostname": "192.168.222.139", "port": "22"},
{"hostname": "192.168.222.142", "port": "22"}
],
}
}
result = MyRunner(module_resource) #resource可以是列表或者字典形式,如果做了ssh-key认证,就不会通过账户密码方式认证
result.run_model(host_list=["192.168.222.139","192.168.222.140","192.168.222.142"],module_name='ping',module_args="")
data = result.get_model_result()
print data
print '============================================================================'
result1 = MyRunner(playbook_resource) #resource可以是列表或者字典形式,如果做了ssh-key认证,就不会通过账户密码方式认证
result1.run_playbook(["192.168.222.139","192.168.222.142"],playbook_path='apiplaybook.yml')
data1 = result1.get_playbook_result()
print data1
执行结果
[root@web2 version2]# ./all.py
{"failed": {}, "success": {"192.168.222.140": {"invocation": {"module_args": {"data": null}}, "_ansible_parsed": true, "changed": false, "ping": "pong", "_ansible_no_log": false}, "192.168.222.142": {"invocation": {"module_args": {"data": null}}, "_ansible_parsed": true, "changed": false, "ping": "pong", "_ansible_no_log": false}, "192.168.222.139": {"invocation": {"module_args": {"data": null}}, "_ansible_parsed": true, "changed": false, "ping": "pong", "_ansible_no_log": false}}, "unreachable": {}}
======================================================================================================
{"status": {"192.168.222.139": {"unreachable": 0, "skipped": 0, "changed": 1, "ok": 2, "failed": 0}, "192.168.222.142": {"unreachable": 0, "skipped": 0, "changed": 1, "ok": 2, "failed": 0}}, "failed": {}, "skipped": {}, "ok": {"192.168.222.139": [{"task": "Gathering Facts"}, {"task": "command"}], "192.168.222.142": [{"task": "Gathering Facts"}, {"task": "command"}]}, "unreachable": {}}
对于用惯了1.x的api同学需要适应一下2.x的api