从零打造企业内部Ansible自动化管理平台-第一章(Api)-渲染不变的昨天
source link: https://blog.51cto.com/breaklinux/2485043
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
从零打造企业内部Ansible自动化管理平台-第一章(Api)
从零打造企业内部Ansible自动化管理平台-第一章
一. 背景;
随着中下企业技术的快速技术迭代,以及微服务分布式架构的普及,传统运维系统运维环境治理方面,系统初始化,环境部署,环境一致性困难较大. 由此 ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,
实现了批量系统配置、批量程序部署、环境快速部署迭代,批量运行命令等功能。
Ansible 工作原理和关联模块介绍:
ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。主要包括:
(1)、连接插件connection plugins:负责和被监控端实现通信;
(2)、host inventory:指定操作的主机,是一个配置文件里面定义监控的主机;
(3)、各种模块核心模块、command模块、自定义模块;
(4)、借助于插件完成记录日志邮件等功能;
(5)、playbook:剧本执行多个任务时,非必需可以让节点一次性运行多个任务。
二. 本章概述:
本文主要描述ansible 2.7.2 版本官方python 3 版本Api 封装, (内容:Ansible 数据结构返回,host inventory动态主机,playbook 执行返回)
三. 原生ansible-api 封装代码部分;
官网参考连接: https://docs.ansible.com/ansible/latest/dev_guide/developing_api.html
完整项目代码请移步到githup: https://github.com/breaklinux/devops-bmc-api/
四.项目内部设计如下图:
五.项目示例代码如下:
1.封装Ansible-api 实际代码片段如下:
"""
@author:lijx
@contact: [email protected]
@site: https://blog.51cto.com/breaklinux
@version: 1.0
@githup:https://github.com/breaklinux/devops-bmc-api/
"""
import json
from collections import namedtuple
from ansible.executor.task_queue_manager import TaskQueueManager
from ansible.inventory.manager import InventoryManager
from ansible.parsing.dataloader import DataLoader
from ansible.playbook.play import Play
from ansible.plugins.callback import CallbackBase
from ansible.vars.manager import VariableManager
from ansible.errors import AnsibleParserError
class ResultCallback(CallbackBase):
def __init__(self, *args, **kwargs):
super(ResultCallback, self).__init__(*args, **kwargs)
self.host_ok = {}
self.host_unreachable = {}
self.host_failed = {}
def v2_runner_on_ok(self, result, **kwargs):
self.host_ok[result._host.get_name()] = result
host = result._host
print(json.dumps({host.name: result._result}, indent=4))
def v2_runner_on_unreachable(self, result):
self.host_unreachable[result._host.get_name()] = result
def v2_runner_on_failed(self, result, *args, **kwargs):
self.host_failed[result._host.get_name()] = result
class AnsibleApi(object):
def __init__(self, resource, user, becomeuser, playvars={}, *args, **kwargs):
self._resource = resource
self._user = user
self._becomeuser = becomeuser
self.inventory = None
self.playvars = playvars # add
self.variable_manager = None
self.loader = None
self.options = None
self.passwords = None
self.callback = None
self.__initializeAnsibleData()
self.results_raw = {}
def __initializeAnsibleData(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', 'diff'])
self.options = Options(connection='ssh', module_path=None, forks=100, timeout=5,
remote_user=self._user, ask_pass=False, private_key_file=None, ssh_common_args=None,
ssh_extra_args=None, sftp_extra_args=None, scp_extra_args=None, become=True,
become_method='sudo',
become_user=self._becomeuser, ask_value_pass=False, verbosity=None, check=False,
listhosts=False,
listtasks=False, listtags=False, syntax=False, diff=False)
self.loader = DataLoader()
self.passwords = dict(sshpass=None, becomepass=None)
self.inventory = InventoryManager(loader=self.loader, sources=self._resource)
self.variable_manager = VariableManager(loader=self.loader, inventory=self.inventory)
self.variable_manager.extra_vars = self.playvars
def run(self, host_list, module_name, module_args, ):
play_source = dict(
name="Ansible Play For At 20190104",
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 = ResultCallback()
try:
tqm = TaskQueueManager(
inventory=self.inventory,
variable_manager=self.variable_manager,
loader=self.loader,
options=self.options,
passwords=self.passwords,
stdout_callback="default",
)
tqm._stdout_callback = self.callback
result = tqm.run(play)
finally:
if tqm is not None:
tqm.cleanup()
def playbookRun(self, playbook_path):
from ansible.executor.playbook_executor import PlaybookExecutor
playbook = PlaybookExecutor(playbooks=playbook_path,
inventory=self.inventory,
variable_manager=self.variable_manager,
loader=self.loader,
options=self.options,
passwords=self.passwords)
self.callback = ResultCallback()
playbook._tqm._stdout_callback = self.callback
try:
result = playbook.run()
except AnsibleParserError:
code = 1001
results = {'playbook': playbook_path, 'msg': playbook_path + 'playbook have syntax error', 'flag': False}
return code, results
def get_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['msg']
return self.results_raw
def get_result_v2(self):
self.results_raw = {'success': list(), 'failed': list(), 'unreachable': list()}
for host, result in self.callback.host_ok.items():
self.results_raw['success'].append({"ip": host, "result": result._result})
for host, result in self.callback.host_failed.items():
self.results_raw['failed'].append({"ip": host, "result": result._result})
for host, result in self.callback.host_unreachable.items():
self.results_raw['unreachable'].append({"ip": host, "result": result._result['msg']})
return self.results_raw
if __name__ == "__main__":
print("Ansible Api By 20190104 Ansible Version: 2.7.5 Test Ok")
2. Inventory动态主机代码如下;
#!/usr/bin/env python36
"""
@author:lijx
@contact: [email protected]
@site: https://blog.51cto.com/breaklinux
@version: 1.0
"""
from flask import request, Response
import requests
import os
HERE = os.path.abspath(__file__)
HOME_DIR = os.path.split(os.path.split(HERE)[0])[0]
script_path = os.path.join(HOME_DIR, "tools")
def getHostInventoryData(url):
import json
gethostdata = requests.get(url)
getdata = gethostdata.json()["data"]
data = dict()
l=[]
for i in getdata:
l.append(i["group"])
groups = set(l)
gdata=str(groups)
data["all"] = {"children": gdata}
data["_meta"] = {"hostvars": {}}
for group in groups:
data[group] = dict()
data[group]["hosts"] = list()
for x in getdata:
if x["group"] == group:
data[group]["hosts"].append(x["instanceip"])
return json.dumps(data, indent=5)
def HostApi():
getInventoryUrl = "http://192.168.58.14:5000/ansible/host/v1"
import json
import configparser
data = json.loads(getHostInventoryData(getInventoryUrl))
config = configparser.ConfigParser(allow_no_value=True)
for i in data:
if i != "all" and i != "_meta":
config.add_section(i)
for h in data[i]["hosts"]:
config.set(i, h)
config.write(open("%s/static_hosts"%script_path, "w"))
return True
if __name__ == "__main__":
from optparse import OptionParser
getInventoryUrl = "http://192.168.58.14:5000/ansible/host/v1" ###获取动态主机接口###
parse = OptionParser()
parse.add_option("-l", "--list", action="store_true", dest="list", default=False)
(option, arges) = parse.parse_args()
if option.list:
print(getHostInventoryData(getInventoryUrl))
else:
import json
print(json.loads(getHostInventoryData(getInventoryUrl)))
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK