Django+ansible+ajax实现自动化部署,djangoansible


目前公司部署环境都是手动进行部署或者写个shell脚本进行部署,但是感觉这样还是比较麻烦的,所以最近我考虑了下将部署集成到运维平台进行自动化

实现效果:

这个是我第一次想到的版本 当我点击部署的时候后端执行异步部署,部署完成之后返回结果当部署失败的时候有利于我们排错,后续更新如何实时返回结果,有利于我们如何知道实时执行情况

首先前端页面的代码特殊的地方就是ajax的代码 置于美化 排版 各需所好 我这里只将ajax的代码,ajax的代码主要是为了异步执行后端代码的作用:

<script>
  $("#submit").on('click',function(){    #submit对应按钮的id号  触发点击的时候执行js脚本
      $('#dict_result').html('')  #每次执行完成之后 在不刷新页面的情况下 如果再次进行部署的话 前面部署的结果将会保留 所以我这里清除了前一次部署的记录 
      $('#dict_result1').html('')
      $('#dict_result2').html('')
    $.ajax({
      url:"/Get_data",  #异步操作的url 这里指的是http://url/Get_data
      type:"POST", #post请求
      data:{
        hosts:$("#hosts").val(),  #获取id为hosts的控件的值
        software:$("#software").val() #获取id为software的控件的值
      },
      success:function(data){   
        var obj=JSON.parse(data) #将数据json格式化
        $('#dict_result').html(JSON.stringify(obj.result.success)) #获取结果分别是失败成功以及取不到
        $('#dict_result1').html(JSON.stringify(obj.result.failed))
        $('#dict_result2').html(JSON.stringify(obj.result.unreachable))
        $('#loading').hide(); #隐藏加载图标
      }
    })
  })

</script>
部署中的状态 :
部署完成的状态:


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)

相关内容

    暂无相关文章