【堡垒机】第9章——堡垒机后台处理批量任务

ajax发送命令

  <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
        <button type="button" id="submit_task_confirm" onclick="submit_task(this,'/api/multitask/cmd/')" class="btn btn-primary">确定执行</button>
      </div>

    function submit_task(ele,post_url){
            //console.log(ele);
            $(ele).attr('disabled','true');

            $.post(post_url, postDic,function(callback){
                console.log(callback);
                if (callback != 'TaskCreatingError'){
                    $("#modal_content").html("任务创建成功! 任务编号:" + callback);
                    $("#modal_content").attr("style","color:green;font:bold");
                    $(".task_result").html("");
                    $("#file-download-to-local").attr("task_id",callback); // only works when task_type = file_get
                    GetTaskResult(callback,'refresh');
                }else{
                    $("#modal_content").html("任务创建失败,请查看相关日志进行调试!");
                    $("#modal_content").attr("style","color:red;font:bold")

                }
                });
    }

api接口

url(r'multitask/cmd/$', views.multitask_cmd,name='multitask_cmd'),
@login_required
def multitask_cmd(request):
    #print '==post:',request.POST
    multi_task = host_mgr.MultiTask('run_cmd',request)
    task_id = multi_task.run()	# 执行run方法
    if task_id:
        return HttpResponse(task_id)
    else:
        return HttpResponse("TaskCreatingError")

class MultiTask(object):
    def __init__(self,task_type,request_ins):
        self.request = request_ins
        self.task_type = task_type

    def run(self):
        return self.parse_args()
    def parse_args(self):
        #print '==>parse_args:', self.request.POST
        task_func = getattr(self,self.task_type)
        return task_func()

    def terminate_task(self):
        task_id = self.request.POST.get('task_id')
        assert task_id.isdigit()
        task_obj = models.TaskLog.objects.get(id=int(task_id))
        res_msg = ''
        try:
            os.killpg(task_obj.task_pid,signal.SIGTERM)
            res_msg = 'Task %s has terminated!' % task_id
        except OSError as e:
            res_msg = "Error happened when tries to terminate task %s , err_msg[%s]" % (task_id,str(e))
        return  res_msg

    def run_cmd(self):
        cmd = self.request.POST.get("cmd")
        host_ids =[int(i.split('host_')[-1]) for i in json.loads(self.request.POST.get("selected_hosts"))]
        task_expire_time = self.request.POST.get("expire_time")
        exec_hosts = models.BindHosts.objects.filter(id__in=host_ids)
        random_str = self.request.POST.get('local_file_path')
        task_obj= self.create_task_log('cmd',exec_hosts,task_expire_time,cmd,random_str)
        #'-task_type', 'cmd', '-task_id', '15', '-expire', '30', '-task', 'ifconfig', '-uid', '1']
        print("-->run cmd:",cmd,host_ids)
        p = subprocess.Popen(['python3',
                             settings.MultiTaskScript,
                             '-task_type','cmd',
                             '-expire',task_expire_time,
                             '-uid',str(self.request.user.id) ,
                             '-task',cmd ,
                             '-task_id', str(task_obj.id)
                             ],
                             preexec_fn=os.setsid)

        task_obj.task_pid = p.pid
        task_obj.save()
        return task_obj.id

调用python脚本,并格式化参数

if __name__ == '__main__':
    require_args= ['-task_type','-task_id','-expire','-uid']
    lack_args = [arg for arg in require_args if arg not in sys.argv[1:]]
    if len(lack_args) >0:
        sys.exit("lack args of: %s"% lack_args)
    task_type = sys.argv[sys.argv.index('-task_type')+1]
    if task_type =='cmd':
        require_args= ['-task',]
    # elif task_type == 'file_send':
    #     require_args = ['-local','-remote']
    elif task_type == 'file_get':
        require_args = ['-remote',]

    lack_args = [arg for arg in require_args if arg not in sys.argv[1:]]
    if len(lack_args) >0:
        sys.exit("lack args of: %s"% lack_args)

    task_id = sys.argv[sys.argv.index('-task_id')+1]
    expire_time = sys.argv[sys.argv.index('-expire')+1]

    if task_type =='cmd':
        content = sys.argv[sys.argv.index('-task')+1]
    else:
        content = sys.argv
    uid = sys.argv[sys.argv.index('-uid')+1]
    task_obj = models.TaskLog.objects.get(id=int(task_id))
    connection.close()

    Pool = multiprocessing.Pool(processes=settings.MaxTaskProcesses)
    res_list = []

    if task_type == 'cmd':
        task_func = cmd_exec
    elif task_type == 'file_send' or task_type == 'file_get':
        task_func = file_tranfer_exec
    else:
        sys.exit("wrong task_type")
    for h in task_obj.hosts.select_related():
        p = Pool.apply_async(task_func,args=(task_id,h.id,uid,content))
        res_list.append(p)

    #get result
    Pool.close()
    Pool.join()
    #for res in res_list:
    #    res.get()

执行前端传递的cmd命令,并将结果存入数据库

__author__ = 'jieli'

import global_settings
import json
import traceback
import paramiko
from CrazyEye import settings
import django
django.setup()
from web import models
from django.db import connection
import sys,time,os
import multiprocessing

def cmd_exec(task_id,bind_host_id,user_id,cmd ):
    bind_host = models.BindHosts.objects.get(id=bind_host_id)
    s = paramiko.SSHClient()
    s.load_system_host_keys()
    s.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    try:
        if bind_host.host_user.auth_method == 'ssh-password':
            s.connect(bind_host.host.ip_addr,
                      int(bind_host.host.port),
                      bind_host.host_user.username,
                      bind_host.host_user.password,
                      timeout=5)
        else:#rsa_key

            key = paramiko.RSAKey.from_private_key_file(settings.RSA_PRIVATE_KEY_FILE)
            s.connect(bind_host.host.ip_addr,
                      int(bind_host.host.port),
                      bind_host.host_user.username,
                      pkey=key,
                      timeout=5)
        stdin,stdout,stderr = s.exec_command(cmd)
        result = stdout.read(),stderr.read()
        if any(result):
            #cmd_result = filter(lambda x:len(x.strip())>0,result)[0]
            cmd_result = result[0] if result[0] else result[1]
        else:
            cmd_result = b'execution has no output!'
        res_status = 'success'
        print('----------- HOST:%s  IP:%s -------------' %(bind_host.host.hostname,bind_host.host.ip_addr) )

        # for line in cmd_result.decode():
        #     print(line)
        print(cmd_result.decode())
        s.close()
    except Exception as e:
    #except ValueError as e:
        print('----------- HOST:%s  IP:%s -------------' %(bind_host.host.hostname,bind_host.host.ip_addr))
        print('\033[31;1mError:%s\033[0m' % e)
        print(traceback.print_exc())
        cmd_result = e
        res_status = 'failed'
    log_obj = models.TaskLogDetail.objects.get(child_of_task_id= int(task_id), bind_host_id=bind_host.id)
    log_obj.event_log = cmd_result
    log_obj.result= res_status
    log_obj.save()

执行cmd命令后,返回任务id给前端,前端根据任务id获得cmd任务执行结果

获取结果API

    def get_task_result(self,detail=True):
        '''get multi run task result'''
        task_id = self.request.GET.get('task_id')
        log_dic ={
            #'summary':{},
            'detail':{}
        }
        task_obj = models.TaskLog.objects.get(id=int(task_id))
        task_detail_obj_list = models.TaskLogDetail.objects.filter(child_of_task_id=task_obj.id)
        log_dic['summary']={
            'id':task_obj.id ,
            'start_time': task_obj.start_time,
            'end_time': task_obj.end_time,
            'task_type': task_obj.task_type,
            'host_num': task_obj.hosts.select_related().count(),
            'finished_num': task_detail_obj_list.filter(result='success').count(),
            'failed_num': task_detail_obj_list.filter(result='failed').count(),
            'unknown_num': task_detail_obj_list.filter(result='unknown').count(),
            'content': task_obj.cmd,
            'expire_time':task_obj.expire_time
        }

        if detail:
            for log in task_detail_obj_list:
                log_dic['detail'][log.id] = {
                    'date': log.date ,
                    'bind_host_id':log.bind_host_id,
                    'host_id': log.bind_host.host.id,
                    'hostname': log.bind_host.host.hostname,
                    'ip_addr': log.bind_host.host.ip_addr,
                    'username': log.bind_host.host_user.username,
                    'system' : log.bind_host.host.system_type,
                    'event_log': log.event_log,
                    'result': log.result,
                    'note': log.note
                }

        return json.dumps(log_dic,default=json_date_handler)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值