-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathrunner.py
171 lines (141 loc) · 5.44 KB
/
runner.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#!/usr/bin/env python
# coding:utf8
from collections import namedtuple
from ansible.parsing.dataloader import DataLoader
from ansible.vars import VariableManager
from ansible.playbook.play import Play
from ansible.executor.task_queue_manager import TaskQueueManager
from ansible.plugins.callback import CallbackBase
import ansible.constants as C
from ansible.errors import AnsibleError
from ansible.utils.vars import load_extra_vars
from ansible.utils.vars import load_options_vars
from myinventory import MyInventory
__all__ = ["Runner"]
# free to report host to `known_hosts` file.
C.HOST_KEY_CHECKING = False
# class Options
Options = namedtuple("Options", [
'connection', 'module_path', 'private_key_file', "remote_user", "timeout",
'forks', 'become', 'become_method', 'become_user', 'check', "extra_vars",
]
)
class ResultCallback(CallbackBase):
"""
Custom Callback
"""
def __init__(self):
self.result_q = dict(contacted={}, dark={})
def gather_result(self, n, res):
self.result_q[n].update({res._host.name: res._result})
def v2_runner_on_ok(self, result):
self.gather_result("contacted", result)
def v2_runner_on_failed(self, result, ignore_errors=False):
self.gather_result("dark", result)
def v2_runner_on_unreachable(self, result):
self.gather_result("dark", result)
def v2_runner_on_skipped(self, result):
self.gather_result("dark", result)
def v2_playbook_on_task_start(self, task, is_conditional):
pass
def v2_playbook_on_play_start(self, play):
pass
class Runner(object):
"""
仿照ansible1.9 的python API,制作的ansible2.0 API的简化版本。
参数说明:
inventory:: 仓库对象,可以是列表,逗号间隔的ip字符串,可执行文件. 默认/etc/ansible/hosts
module_name:: 指定要使用的模块
module_args:: 模块参数
forks:: 并发数量, 默认5
timeout:: 连接等待超时时间,默认10秒
pattern:: 模式匹配,指定要连接的主机名, 默认all
remote_user:: 指定连接用户, 默认root
private_key_files:: 指定私钥文件
"""
def __init__(
self,
hosts=C.DEFAULT_HOST_LIST,
module_name=C.DEFAULT_MODULE_NAME, # * command
module_args=C.DEFAULT_MODULE_ARGS, # * 'cmd args'
forks=C.DEFAULT_FORKS, # 5
timeout=C.DEFAULT_TIMEOUT, # SSH timeout = 10s
pattern="all", # all
remote_user=C.DEFAULT_REMOTE_USER, # root
module_path=None, # dirs of custome modules
connection_type="smart",
become=None,
become_method=None,
become_user=None,
check=False,
passwords=None,
extra_vars = None,
private_key_file=None
):
# storage & defaults
self.pattern = pattern
self.variable_manager = VariableManager()
self.loader = DataLoader()
self.module_name = module_name
self.module_args = module_args
self.check_module_args()
self.gather_facts = 'no'
self.resultcallback = ResultCallback()
self.options = Options(
connection=connection_type,
timeout=timeout,
module_path=module_path,
forks=forks,
become=become,
become_method=become_method,
become_user=become_user,
check=check,
remote_user=remote_user,
extra_vars=extra_vars or [],
private_key_file=private_key_file,
)
self.variable_manager.extra_vars = load_extra_vars(loader=self.loader, options=self.options)
self.variable_manager.options_vars = load_options_vars(self.options)
self.passwords = passwords or {}
self.inventory = MyInventory(host_list=hosts)
self.variable_manager.set_inventory(self.inventory)
self.play_source = dict(
name="Ansible Ad-hoc",
hosts=self.pattern,
gather_facts=self.gather_facts,
tasks=[dict(action=dict(
module=self.module_name, args=self.module_args))]
)
self.play = Play().load(
self.play_source, variable_manager=self.variable_manager,
loader=self.loader)
self.runner = TaskQueueManager(
inventory=self.inventory,
variable_manager=self.variable_manager,
loader=self.loader,
options=self.options,
passwords=self.passwords,
stdout_callback=self.resultcallback
)
# ** end __init__() **
def run(self):
if not self.inventory.list_hosts("all"):
raise AnsibleError("Inventory is empty.")
if not self.inventory.list_hosts(self.pattern):
raise AnsibleError(
"pattern: %s dose not match any hosts." % self.pattern)
try:
self.runner.run(self.play)
except Exception as e:
raise Exception(e)
else:
return self.resultcallback.result_q
finally:
if self.runner:
self.runner.cleanup()
if self.loader:
self.loader.cleanup_all_tmp_files()
def check_module_args(self):
if self.module_name in C.MODULE_REQUIRE_ARGS and not self.module_args:
err = "No argument passed to '%s' module." % self.module_name
raise AnsibleError(err)