目前公司部署环境都是手动进行部署或者写个shell脚本进行部署,但是感觉这样还是比较麻烦的,所以最近我考虑了下将部署集成到运维平台进行自动化
实现效果:
这个是我第一次想到的版本 当我点击部署的时候后端执行异步部署,部署完成之后返回结果当部署失败的时候有利于我们排错,后续更新如何实时返回结果,有利于我们如何知道实时执行情况
首先前端页面的代码特殊的地方就是ajax的代码 置于美化 排版 各需所好 我这里只将ajax的代码,ajax的代码主要是为了异步执行后端代码的作用:
部署中的状态 : 部署完成的状态: django 后端的代码: ansible函数是进入界面的渲染 Get_data函数是部署的代码以及结果的获取
def ansible(request): import os,re from itertools import islice InventoryFile='wls/static/hosts' f=open(InventoryFile) #InventoryFile里有host的列表 hosts=[] for line in f.readlines(): if re.match(r'\[.*\]',line): pass else: hosts.append(line) f.close() softwares = [] for root, dirs, files in os.walk('wls/static/yaml/'): #部署的ansible的剧本 for i in files: if re.match(r'.*\.retry',i): pass else: softwares.append(i) return render(request, 'form/ansible.html',{ 'softwares':softwares, 将两个值渲染到前端 'hosts':hosts }) def Get_data(request): #获取数据 import os,re from itertools import islice # ip = request.POST('ip') ip=str(request.POST.getlist('hosts')) #获取前端传递的值 software=request.POST.getlist('software')#获取前端传递的值 os.system('chmod 600 wls/static/gitlabilanni.gitlabilanni') #给与key权限 License = 'wls/static/gitlabilanni.gitlabilanni' #key目录 InventoryFile='wls/static/hosts' if ip != [] and software != []: installfile = 'wls/static/yaml/%s' % (software[0]) a=ansinstall.MyRunner(InventoryFile,ip,installfile,License) result=a.Install() wo=a.get_result() #执行安装 else: wo='' f=open(InventoryFile) hosts=[line.strip('\n') for line in islice(f,1,None)] f.close() softwares = [] for root, dirs, files in os.walk('wls/static/yaml/'): for i in files: if re.match(r'.*\.retry',i): pass else: softwares.append(i) return HttpResponse(json.dumps({ 'result':wo #返回结果 })) 还有就是ansible api接口 如果没接口 一切都是扯淡 以下是我写的ansible api接口 这个接口重写了代码,以下是2.4的ansible api接口,至于这个API接口我不多做解释,不懂可以看下官方文档。
#!/usr/bin/env python import json from collections import namedtuple from ansible.parsing.dataloader import DataLoader from ansible.vars.manager import VariableManager from ansible.inventory.manager import InventoryManager 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 from tempfile import NamedTemporaryFile class ResultCallback(CallbackBase): """A sample callback plugin used for performing an action as results come in If you want to collect all results into a single object for processing at the end of the execution, look into utilizing the ``json`` callback plugin or writing your own custom callback plugin """ def __init__(self, *args, **kwargs): super(ResultCallback, 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 MyRunner(object): def __init__(self,InventoryFile,Host,installfile,License): self.InventoryFile=InventoryFile self.Host=Host self.installfile=installfile self.License=License def Install(self): self.loader = DataLoader() self.results_callback = ResultCallback() self.inventory = InventoryManager(loader=self.loader,sources=self.InventoryFile,) variable_manager = VariableManager(loader=self.loader, inventory=self.inventory) variable_manager.extra_vars={"Host":self.Host} Options = namedtuple('Options', ['connection', 'remote_user', 'ask_sudo_pass', 'verbosity', 'ack_pass', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check', 'listhosts', 'listtasks', 'listtags', 'syntax', 'sudo_user', 'sudo', 'diff', 'private_key_file', ]) options = Options(connection='smart', remote_user='admin', ack_pass=None, sudo_user='root', forks=100, sudo='yes', ask_sudo_pass=False, verbosity=0, module_path=None, become=True, become_method='sudo', become_user='root', check=None, listhosts=None, listtasks=None, listtags=None, syntax=None, diff=None, private_key_file=self.License, ) # actually run it tqm = None try: playbook = PlaybookExecutor(playbooks=[self.installfile],inventory=self.inventory, variable_manager=variable_manager, loader=self.loader,options=options,passwords=None) playbook._tqm._stdout_callback=self.results_callback result = playbook.run() finally: if tqm is not None: tqm.cleanup() def get_result(self): self.results_raw = {'success': {}, 'failed': {}, 'unreachable': {}} for host, result in self.results_callback.host_ok.items(): self.results_raw['success'][host] = result._result for host, result in self.results_callback.host_failed.items(): self.results_raw['failed'][host] = result._result['msg'] for host, result in self.results_callback.host_unreachable.items(): self.results_raw['unreachable'][host] = result._result['msg'] if self.results_raw == None: self.results_raw={'Messages':'test'} return self.results_raw if __name__=='__main__': installfile='static/yaml/pm2' InventoryFile='/tmp/123' Host='10.1.31.45' License='/root/gitlabilanni.gitlabilanni' a=MyRunner(InventoryFile,Host,installfile,License) result=a.Install() wo=a.get_result() print(wo)