Пример #1
0
def timingtask(request):
    workflowId = request.POST.get('workflowid')
    run_date = request.POST.get('run_date')
    if run_date is None or workflowId is None:
        context = {'errMsg': '时间不能为空'}
        return render(request, 'error.html', context)
    elif run_date < datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'):
        context = {'errMsg': '时间不能小于当前时间'}
        return render(request, 'error.html', context)
    workflowDetail = workflow.objects.get(id=workflowId)
    if workflowDetail.status not in [Const.workflowStatus['pass'], Const.workflowStatus['timingtask']]:
        context = {'errMsg': '必须为审核通过或者定时执行状态'}
        return render(request, 'error.html', context)

    run_date = datetime.datetime.strptime(run_date, "%Y-%m-%d %H:%M:%S")
    url = getDetailUrl(request) + str(workflowId) + '/'
    job_id = Const.workflowJobprefix['sqlreview'] + '-' + str(workflowId)

    # 使用事务保持数据一致性
    try:
        with transaction.atomic():
            # 将流程状态修改为定时执行
            workflowDetail.status = Const.workflowStatus['timingtask']
            workflowDetail.save()
            # 调用添加定时任务
            add_sqlcronjob(job_id, run_date, workflowId, url)
    except Exception as msg:
        context = {'errMsg': msg}
        return render(request, 'error.html', context)
    return HttpResponseRedirect(reverse('sql:detail', args=(workflowId,)))
Пример #2
0
def passed(request):
    workflowId = request.POST['workflowid']
    if workflowId == '' or workflowId is None:
        context = {'errMsg': 'workflowId参数为空.'}
        return render(request, 'error.html', context)
    workflowId = int(workflowId)
    workflowDetail = workflow.objects.get(id=workflowId)
    toPerson1 = workflowDetail.to_person
    #toPerson字符串转换成列表
    toPerson = ast.literal_eval(toPerson1)
    url = getDetailUrl(request) + str(workflowId) + '/'
    try:
        listAllReviewMen = json.loads(workflowDetail.review_man)
    except ValueError:
        listAllReviewMen = (workflowDetail.review_man,)

    # 服务器端二次验证,正在执行人工审核动作的当前登录用户必须为审核人. 避免攻击或被接口测试工具强行绕过
    loginUser = request.session.get('login_username', False)
    if loginUser is None or loginUser not in listAllReviewMen:
        context = {'errMsg': '当前登录用户不是审核人,请重新登录.'}
        return render(request, 'error.html', context)

    # 服务器端二次验证,当前工单状态必须为等待人工审核
    if workflowDetail.status != Const.workflowStatus['manreviewing']:
        context = {'errMsg': '当前工单状态不是等待人工审核中,请刷新当前页面!'}
        return render(request, 'error.html', context)

    # 将流程状态修改为审核通过,并更新reviewok_time字段
    workflowDetail.status = Const.workflowStatus['pass']
    workflowDetail.reviewok_time = timezone.now()
    workflowDetail.audit_remark = ''
    workflowDetail.save()

    # 如果审核通过了了,则根据settings.py里的配置决定是否给提交者和DBA一封邮件提醒.DBA需要知晓审核并执行过的单子
    if hasattr(settings, 'MAIL_ON_OFF') == True:
        if getattr(settings, 'MAIL_ON_OFF') == "on":
            # 给主、副审核人,申请人,DBA各发一封邮件
            engineer = workflowDetail.engineer
            reviewMen = workflowDetail.review_man
            workflowStatus = workflowDetail.status
            workflowName = workflowDetail.workflow_name
            # objEngineer = users.objects.get(username=engineer)
            strTitle = "SQL上线工单审核通过#" + str(workflowId) + ",请DBA审核执行!"
            strContent = "发起人:" + engineer + "\n审核人:" + reviewMen + "\n工单地址:" + url + "\n工单名称: " + workflowName + "\n审核结果:" + workflowStatus
            reviewManAddr = [email['email'] for email in
                             users.objects.filter(username__in=listAllReviewMen).values('email')]
            dbaAddr = [email['email'] for email in users.objects.filter(role='DBA').values('email')]
            objEngineer = users.objects.get(username=engineer)
            toperson = list(toPerson)
            Eemail = [objEngineer.email]
            listCcAddr = dbaAddr + Eemail + toperson + reviewManAddr
            allperson = list(set(listCcAddr)) 
            # mailSender.sendEmail(strTitle, strContent, [objEngineer.email], listCcAddr=listCcAddr)
            mailSender.sendEmail(strTitle, strContent, allperson)

    return HttpResponseRedirect(reverse('sql:detail', args=(workflowId,)))
Пример #3
0
def execute(request):
    workflowId = request.POST['workflowid']
    if workflowId == '' or workflowId is None:
        context = {'errMsg': 'workflowId参数为空.'}
        return render(request, 'error.html', context)

    workflowId = int(workflowId)
    workflowDetail = workflow.objects.get(id=workflowId)
    clusterName = workflowDetail.cluster_name
    url = getDetailUrl(request) + str(workflowId) + '/'

    # 服务器端二次验证,当前工单状态必须为审核通过状态
    if workflowDetail.status != Const.workflowStatus['pass']:
        context = {'errMsg': '当前工单状态不是审核通过,请刷新当前页面!'}
        return render(request, 'error.html', context)

    # 将流程状态修改为执行中,并更新reviewok_time字段
    workflowDetail.status = Const.workflowStatus['executing']
    workflowDetail.reviewok_time = timezone.now()
    # 执行之前重新split并check一遍,更新SHA1缓存;因为如果在执行中,其他进程去做这一步操作的话,会导致inception core dump挂掉
    try:
        splitReviewResult = inceptionDao.sqlautoReview(
            workflowDetail.sql_content,
            workflowDetail.cluster_name,
            isSplit='yes')
    except Exception as msg:
        context = {'errMsg': msg}
        return render(request, 'error.html', context)
    workflowDetail.review_content = json.dumps(splitReviewResult)
    try:
        workflowDetail.save()
    except Exception:
        # 关闭后重新获取连接,防止超时
        connection.close()
        workflowDetail.save()

    # 采取异步回调的方式执行语句,防止出现持续执行中的异常
    t = Thread(target=execute_call_back, args=(workflowId, clusterName, url))
    t.start()

    return HttpResponseRedirect(reverse('sql:detail', args=(workflowId, )))
Пример #4
0
def autoreview(request):
    workflowid = request.POST.get('workflowid')
    sqlContent = request.POST['sql_content']
    workflowName = request.POST['workflow_name']
    clusterName = request.POST['cluster_name']
    isBackup = request.POST['is_backup']
    reviewMan = request.POST['review_man']
    subReviewMen = request.POST.get('sub_review_man', '')
    listAllReviewMen = (reviewMan, subReviewMen)

    # 服务器端参数验证
    if sqlContent is None or workflowName is None or clusterName is None or isBackup is None or reviewMan is None:
        context = {'errMsg': '页面提交参数可能为空'}
        return render(request, 'error.html', context)
    sqlContent = sqlContent.rstrip()
    if sqlContent[-1] != ";":
        context = {'errMsg': "SQL语句结尾没有以;结尾,请后退重新修改并提交!"}
        return render(request, 'error.html', context)

    # 交给inception进行自动审核
    try:
        result = inceptionDao.sqlautoReview(sqlContent, clusterName)
    except Exception as msg:
        context = {'errMsg': msg}
        return render(request, 'error.html', context)
    if result is None or len(result) == 0:
        context = {'errMsg': 'inception返回的结果集为空!可能是SQL语句有语法错误'}
        return render(request, 'error.html', context)
    # 要把result转成JSON存进数据库里,方便SQL单子详细信息展示
    jsonResult = json.dumps(result)

    # 遍历result,看是否有任何自动审核不通过的地方,一旦有,则为自动审核不通过;没有的话,则为等待人工审核状态
    workflowStatus = Const.workflowStatus['manreviewing']
    for row in result:
        if row[2] == 2:
            # 状态为2表示严重错误,必须修改
            workflowStatus = Const.workflowStatus['autoreviewwrong']
            break
        elif re.match(r"\w*comments\w*", row[4]):
            workflowStatus = Const.workflowStatus['autoreviewwrong']
            break

    # 存进数据库里
    engineer = request.session.get('login_username', False)
    if not workflowid:
        Workflow = workflow()
        Workflow.create_time = timezone.now()
    else:
        Workflow = workflow.objects.get(id=int(workflowid))
    Workflow.workflow_name = workflowName
    Workflow.engineer = engineer
    Workflow.review_man = json.dumps(listAllReviewMen, ensure_ascii=False)
    Workflow.status = workflowStatus
    Workflow.is_backup = isBackup
    Workflow.review_content = jsonResult
    Workflow.cluster_name = clusterName
    Workflow.sql_content = sqlContent
    Workflow.execute_result = ''
    Workflow.audit_remark = ''
    Workflow.save()
    workflowId = Workflow.id

    # 自动审核通过了,才发邮件
    if workflowStatus == Const.workflowStatus['manreviewing']:
        # 如果进入等待人工审核状态了,则根据settings.py里的配置决定是否给审核人发一封邮件提醒.
        if hasattr(settings, 'MAIL_ON_OFF') == True:
            if getattr(settings, 'MAIL_ON_OFF') == "on":
                url = getDetailUrl(request) + str(workflowId) + '/'

                # 发一封邮件
                strTitle = "新的SQL上线工单提醒 # " + str(workflowId)
                strContent = "发起人:" + engineer + "\n审核人:" + str(
                    listAllReviewMen) + "\n工单地址:" + url + "\n工单名称: " + workflowName + "\n具体SQL:" + sqlContent
                reviewManAddr = [email['email'] for email in
                                 users.objects.filter(username__in=listAllReviewMen).values('email')]
                mailSender.sendEmail(strTitle, strContent, reviewManAddr)
            else:
                # 不发邮件
                pass

    return HttpResponseRedirect(reverse('sql:detail', args=(workflowId,)))
Пример #5
0
def cancel(request):
    workflowId = request.POST['workflowid']
    if workflowId == '' or workflowId is None:
        context = {'errMsg': 'workflowId参数为空.'}
        return render(request, 'error.html', context)

    workflowId = int(workflowId)
    workflowDetail = workflow.objects.get(id=workflowId)
    reviewMan = workflowDetail.review_man
    try:
        listAllReviewMen = json.loads(reviewMan)
    except ValueError:
        listAllReviewMen = (reviewMan,)

    audit_remark = request.POST.get('audit_remark')
    if audit_remark is None:
        context = {'errMsg': '驳回原因不能为空'}
        return render(request, 'error.html', context)

    # 服务器端二次验证,如果正在执行终止动作的当前登录用户,不是发起人也不是审核人,并且不是DBA,则异常.
    loginUser = request.session.get('login_username', False)
    loginUserOb = users.objects.get(username=loginUser)
    if loginUser not in listAllReviewMen and loginUser != workflowDetail.engineer and loginUserOb.role != 'DBA':
        context = {'errMsg': '当前登录用户不是审核人也不是发起人,请重新登录.'}
        return render(request, 'error.html', context)

    # 服务器端二次验证,如果当前单子状态是结束状态,则不能发起终止
    if workflowDetail.status in (
            Const.workflowStatus['abort'], Const.workflowStatus['finish'], Const.workflowStatus['autoreviewwrong'],
            Const.workflowStatus['exception']):
        return HttpResponseRedirect(reverse('sql:detail', args=(workflowId,)))

    # 删除定时执行job
    if workflowDetail.status == Const.workflowStatus['timingtask']:
        job_id = Const.workflowJobprefix['sqlreview'] + '-' + str(workflowId)
        del_sqlcronjob(job_id)
    # 将流程状态修改为人工终止流程
    workflowDetail.status = Const.workflowStatus['abort']
    workflowDetail.audit_remark = audit_remark
    workflowDetail.save()

    # 如果人工终止了,则根据settings.py里的配置决定是否给提交者和审核人发邮件提醒。如果是发起人终止流程,则给主、副审核人各发一封;如果是审核人终止流程,则给发起人发一封邮件,并附带说明此单子被拒绝掉了,需要重新修改.
    if hasattr(settings, 'MAIL_ON_OFF') == True:
        if getattr(settings, 'MAIL_ON_OFF') == "on":
            url = getDetailUrl(request) + str(workflowId) + '/'

            engineer = workflowDetail.engineer
            workflowStatus = workflowDetail.status
            workflowName = workflowDetail.workflow_name
            if loginUser == engineer:
                strTitle = "发起人主动终止SQL上线工单流程 # " + str(workflowId)
                strContent = "发起人:" + engineer + "\n审核人:" + reviewMan + "\n工单地址:" + url + "\n工单名称: " + workflowName + "\n执行结果:" + workflowStatus + "\n提醒:发起人主动终止流程"
                reviewManAddr = [email['email'] for email in
                                 users.objects.filter(username__in=listAllReviewMen).values('email')]
                mailSender.sendEmail(strTitle, strContent, reviewManAddr)
            else:
                objEngineer = users.objects.get(username=engineer)
                strTitle = "SQL上线工单被拒绝执行 # " + str(workflowId)
                strContent = "发起人:" + engineer + "\n审核人:" + reviewMan + "\n工单地址:" + url + "\n工单名称: " + workflowName + "\n执行结果:" + workflowStatus + "\n提醒:此工单被拒绝执行,请登陆重新提交或修改工单"
                mailSender.sendEmail(strTitle, strContent, [objEngineer.email])
        else:
            # 不发邮件
            pass

    return HttpResponseRedirect(reverse('sql:detail', args=(workflowId,)))
Пример #6
0
def autoreview(request):
    workflowid = request.POST.get('workflowid')
    sqlContent = request.POST['sql_content']
    workflowName = request.POST['workflow_name']
    clusterName = request.POST['cluster_name']
    isBackup = request.POST['is_backup']
    is_data_modified = request.POST['is_data_modified']

    reviewAuditor = request.POST.get('review_man_auditor', '')
    reviewDBA = request.POST.get('review_man_DBA', '')

    # 获取邮件抄送人
    email_cc_source = request.POST.get('email_cc_list', '')
    email_cc = []
    for cc in email_cc_source.split(','):
        email_cc.append(cc.strip())

    if len(reviewAuditor) > 0:
        reviewMan = reviewAuditor
        listAllReviewMen = (reviewMan, )
    if len(reviewDBA) > 0:
        subReviewMen = reviewDBA
        listAllReviewMen = (subReviewMen, )
    if len(reviewAuditor) == 0 and len(reviewDBA) == 0:
        listAllReviewMen = ()

    # 服务器端参数验证
    if sqlContent is None or workflowName is None or clusterName is None or isBackup is None or reviewAuditor is None or reviewDBA is None:
        context = {'errMsg': '页面提交参数可能为空'}
        return render(request, 'error.html', context)
    sqlContent = sqlContent.rstrip()
    if sqlContent[-1] != ";":
        context = {'errMsg': "SQL语句结尾没有以;结尾,请后退重新修改并提交!"}
        return render(request, 'error.html', context)

    # 交给inception进行自动审核
    try:
        result = inceptionDao.sqlautoReview(sqlContent, clusterName)
    except Exception as msg:
        context = {'errMsg': msg}
        return render(request, 'error.html', context)
    if result is None or len(result) == 0:
        context = {'errMsg': 'inception返回的结果集为空!可能是SQL语句有语法错误'}
        return render(request, 'error.html', context)
    # 要把result转成JSON存进数据库里,方便SQL单子详细信息展示
    jsonResult = json.dumps(result)

    # 遍历result,看是否有任何自动审核不通过的地方,一旦有,则为自动审核不通过;没有的话,则为等待人工审核状态
    workflowStatus = Const.workflowStatus['manreviewing']
    for row in result:
        if row[2] == 2:
            # 状态为2表示严重错误,必须修改
            workflowStatus = Const.workflowStatus['autoreviewwrong']
            break
        elif re.match(r"\w*comments\w*", row[4]):
            workflowStatus = Const.workflowStatus['autoreviewwrong']
            break

    # 存进数据库里
    engineer = request.session.get('login_username', False)
    if not workflowid:
        Workflow = workflow()
        Workflow.create_time = timezone.now()
    else:
        Workflow = workflow.objects.get(id=int(workflowid))
    Workflow.workflow_name = workflowName
    Workflow.engineer = engineer
    Workflow.review_man = json.dumps(listAllReviewMen, ensure_ascii=False)

    # 对于测试、beta环境的数据订正,取消审核人
    if len(reviewAuditor) == 0 and len(reviewDBA) == 0:
        workflowStatus = Const.workflowStatus['pass']
        Workflow.status = workflowStatus
    else:
        Workflow.status = workflowStatus

    Workflow.is_backup = isBackup
    Workflow.is_data_modified = is_data_modified
    Workflow.review_content = jsonResult
    Workflow.cluster_name = clusterName
    Workflow.sql_content = sqlContent
    Workflow.execute_result = ''
    Workflow.audit_remark = ''
    Workflow.email_cc = json.dumps(email_cc, ensure_ascii=False)
    Workflow.save()
    workflowId = Workflow.id

    # 获取审核人的微信id
    if listAllReviewMen:
        reviewman_wechat = users.objects.get(username=listAllReviewMen[0])
        wechat_auditor_userid = reviewman_wechat.outer_id
        wechat_userid = []
        wechat_userid.append(wechat_auditor_userid)
    else:
        wechat_userid = False

    # 获取抄送人微信
    if wechat_userid != False:
        workflowDetaiL = workflow.objects.get(id=workflowId)
        cc_list = json.loads(workflowDetaiL.email_cc)
        for cc_name in cc_list:
            cc_name_list = [
                outer_id['outer_id'] for outer_id in users.objects.filter(
                    display=str(cc_name)).values('outer_id')
            ]
            for cc_addr in cc_name_list:
                wechat_userid.append(cc_addr)
    # 获取所有DBA微信
    if wechat_userid != False:
        allDBA = users.objects.filter(role='DBA')
        for dba in allDBA:
            wechat_userid.append(dba.outer_id)

    # 自动审核通过了,才发邮件
    if workflowStatus == Const.workflowStatus['manreviewing']:
        # 如果进入等待人工审核状态了,则根据settings.py里的配置决定是否给审核人发一封邮件提醒.
        if hasattr(settings, 'MAIL_ON_OFF') == True:
            if getattr(settings, 'MAIL_ON_OFF') == "on":
                url_origin = getDetailUrl(request) + str(workflowId) + '/'
                url = url_origin.replace('127.0.0.1:8000', '172.31.0.68')

                # 发一封邮件
                strTitle = "新的SQL上线工单提醒 # " + str(workflowId)
                strContent = "发起人:" + engineer + "\n审核人:" + str(
                    listAllReviewMen
                ) + "\n工单环境:" + "生产环境" + "\n工单地址:" + url + "\n工单名称: " + workflowName + "\n具体SQL:" + sqlContent
                reviewManAddr = [
                    email['email'] for email in users.objects.filter(
                        username__in=listAllReviewMen).values('email')
                ]

                # 获取抄送人邮件地址
                workflowDetaiL = workflow.objects.get(id=workflowId)
                cc_list = json.loads(workflowDetaiL.email_cc)
                for cc_name in cc_list:
                    cc_name_list = [
                        email['email'] for email in users.objects.filter(
                            display=str(cc_name)).values('email')
                    ]
                    for cc_addr in cc_name_list:
                        reviewManAddr.append(cc_addr)
                mailSender.sendEmail(strTitle, strContent, reviewManAddr)

                # 发送企业微信
                wechat_userid = list(filter(lambda x: x != '', wechat_userid))

                # 发送企业微信
                if wechat_userid:
                    wechatTitle = "新的SQL上线工单提醒 # " + str(workflowId)
                    Content = "发起人:" + engineer + "\n审核人:" + str(
                        listAllReviewMen
                    ) + "\n工单地址:" + url + "\n工单名称: " + workflowName + "\n具体SQL:" + sqlContent
                    wechatContent = "<div class=\"normal\">" + Content + "</div>"

                    # 获取企业微信的access_token
                    Token = wechatSender.GetToken("xxx", "xxx")
                    message = wechatTitle.encode("utf-8") + '\n'.encode(
                        'utf8') + wechatContent.encode("utf-8")
                    wechatSender.SendMessage(Token, wechat_userid,
                                             wechatTitle.encode("utf-8"),
                                             wechatContent.encode("utf-8"),
                                             url)

            else:
                # 不发邮件
                pass

    return HttpResponseRedirect(reverse('sql:detail', args=(workflowId, )))
Пример #7
0
def cancel(request):
    workflowId = request.POST['workflowid']
    if workflowId == '' or workflowId is None:
        context = {'errMsg': 'workflowId参数为空.'}
        return render(request, 'error.html', context)

    workflowId = int(workflowId)
    workflowDetail = workflow.objects.get(id=workflowId)
    reviewMan = workflowDetail.review_man
    try:
        listAllReviewMen = json.loads(reviewMan)
    except ValueError:
        listAllReviewMen = (reviewMan, )

    audit_remark = request.POST.get('audit_remark')
    if audit_remark is None:
        context = {'errMsg': '驳回原因不能为空'}
        return render(request, 'error.html', context)

    # 服务器端二次验证,如果正在执行终止动作的当前登录用户,不是发起人也不是审核人,并且不是DBA,则异常.
    loginUser = request.session.get('login_username', False)
    loginUserOb = users.objects.get(username=loginUser)
    if loginUser not in listAllReviewMen and loginUser != workflowDetail.engineer and loginUserOb.role != 'DBA':
        context = {'errMsg': '当前登录用户不是审核人也不是发起人,请重新登录.'}
        return render(request, 'error.html', context)

    # 服务器端二次验证,如果当前单子状态是结束状态,则不能发起终止
    if workflowDetail.status in (Const.workflowStatus['abort'],
                                 Const.workflowStatus['finish'],
                                 Const.workflowStatus['autoreviewwrong'],
                                 Const.workflowStatus['exception']):
        return HttpResponseRedirect(reverse('sql:detail', args=(workflowId, )))

    # 删除定时执行job
    if workflowDetail.status == Const.workflowStatus['timingtask']:
        job_id = Const.workflowJobprefix['sqlreview'] + '-' + str(workflowId)
        del_sqlcronjob(job_id)
    # 将流程状态修改为人工终止流程
    workflowDetail.status = Const.workflowStatus['abort']
    workflowDetail.audit_remark = audit_remark
    workflowDetail.save()

    # 如果人工终止了,则根据settings.py里的配置决定是否给提交者和审核人发邮件提醒。如果是发起人终止流程,则给主、副审核人各发一封;如果是审核人终止流程,则给发起人发一封邮件,并附带说明此单子被拒绝掉了,需要重新修改.
    if hasattr(settings, 'MAIL_ON_OFF') == True:
        if getattr(settings, 'MAIL_ON_OFF') == "on":
            url_origin = getDetailUrl(request) + str(workflowId) + '/'
            url = url_origin.replace('127.0.0.1:8000', '172.31.0.68')

            engineer = workflowDetail.engineer
            workflowStatus = workflowDetail.status
            workflowName = workflowDetail.workflow_name
            if loginUser == engineer:
                strTitle = "发起人主动终止SQL上线工单流程 # " + str(workflowId)
                strContent = "发起人:" + engineer + "\n审核人:" + reviewMan + "\n工单地址:" + url + "\n工单名称: " + workflowName + "\n执行结果:" + workflowStatus + "\n提醒:发起人主动终止流程"
                reviewManAddr = [
                    email['email'] for email in users.objects.filter(
                        username__in=listAllReviewMen).values('email')
                ]
                mailSender.sendEmail(strTitle, strContent, reviewManAddr)

                # 获取审核人的微信id
                if listAllReviewMen:
                    reviewman_wechat = users.objects.get(
                        username=listAllReviewMen[0])
                    wechat_auditor_userid = reviewman_wechat.outer_id
                    wechat_userid = []
                    wechat_userid.append(wechat_auditor_userid)
                else:
                    wechat_userid = False

                # 发送企业微信
                wechat_userid = list(filter(lambda x: x != '', wechat_userid))

                if wechat_userid:
                    wechatTitle = "发起人主动终止SQL上线工单流程 # " + str(workflowId)
                    Content = "发起人:" + engineer + "\n审核人:" + reviewMan + "\n工单地址:" + url + "\n工单名称: " + workflowName + "\n执行结果:" + workflowStatus + "\n提醒:发起人主动终止流程"
                    wechatContent = "<div class=\"normal\">" + Content + "</div>"

                    # 获取企业微信的access_token
                    Token = wechatSender.GetToken("xxx", "xxx")
                    message = wechatTitle.encode("utf-8") + '\n'.encode(
                        'utf8') + wechatContent.encode("utf-8")
                    wechatSender.SendMessage(Token, wechat_userid,
                                             wechatTitle.encode("utf-8"),
                                             wechatContent.encode("utf-8"),
                                             url)

            else:
                objEngineer = users.objects.get(username=engineer)
                strTitle = "SQL上线工单被拒绝执行 # " + str(workflowId)
                strContent = "发起人:" + engineer + "\n审核人:" + reviewMan + "\n工单地址:" + url + "\n工单名称: " + workflowName + "\n执行结果:" + workflowStatus + "\n提醒:此工单被拒绝执行,请登陆重新提交或修改工单"
                mailSender.sendEmail(strTitle, strContent, [objEngineer.email])

                # 获取审核人的微信id
                reviewman_wechat = users.objects.get(
                    username=workflowDetail.engineer)
                wechat_auditor_userid = reviewman_wechat.outer_id
                wechat_userid = []
                wechat_userid.append(wechat_auditor_userid)

                # 发送企业微信
                wechat_userid = list(filter(lambda x: x != '', wechat_userid))

                if wechat_userid:
                    wechatTitle = "SQL上线工单被拒绝执行 # " + str(workflowId)
                    Content = "发起人:" + engineer + "\n审核人:" + reviewMan + "\n工单地址:" + url + "\n工单名称: " + workflowName + "\n执行结果:" + workflowStatus + "\n提醒:此工单被拒绝执行,请登陆重新提交或修改工单"
                    wechatContent = "<div class=\"normal\">" + Content + "</div>"

                    # 获取企业微信的access_token
                    Token = wechatSender.GetToken("xxx", "xxx")
                    message = wechatTitle.encode("utf-8") + '\n'.encode(
                        'utf8') + wechatContent.encode("utf-8")
                    wechatSender.SendMessage(Token, wechat_userid,
                                             wechatTitle.encode("utf-8"),
                                             wechatContent.encode("utf-8"),
                                             url)

        else:
            # 不发邮件
            pass

    return HttpResponseRedirect(reverse('sql:detail', args=(workflowId, )))
Пример #8
0
def execute(request):
    workflowId = request.POST['workflowid']
    if workflowId == '' or workflowId is None:
        context = {'errMsg': 'workflowId参数为空.'}
        return render(request, 'error.html', context)

    workflowId = int(workflowId)
    workflowDetail = workflow.objects.get(id=workflowId)
    # 获取审核人
    try:
        listAllReviewMen = json.loads(workflowDetail.review_man)
    except ValueError:
        listAllReviewMen = (workflowDetail.review_man, )

    clusterName = workflowDetail.cluster_name
    url_origin = getDetailUrl(request) + str(workflowId) + '/'
    url = url_origin.replace('127.0.0.1:8000', '172.31.0.68')

    # 服务器端二次验证,当前工单状态必须为审核通过状态
    if workflowDetail.status != Const.workflowStatus['pass']:
        context = {'errMsg': '当前工单状态不是审核通过,请刷新当前页面!'}
        return render(request, 'error.html', context)

    # 获取生产数据库的标志位
    executeDB = master_config.objects.get(cluster_name=clusterName)

    # 对于生产环境,不真正执行,采用手工方式执行,只是更新标准位
    if executeDB.is_product == 1:
        try:
            workflowDetail.status = '已正常结束'
            workflowDetail.execute_result = workflowDetail.review_content.replace(
                'Audit completed', 'Execute Successfully')
            workflowDetail.save()

            # 给主、副审核人,申请人,DBA各发一封邮件
            engineer = workflowDetail.engineer
            reviewMen = workflowDetail.review_man
            workflowStatus = workflowDetail.status
            workflowName = workflowDetail.workflow_name
            objEngineer = users.objects.get(username=engineer)
            strTitle = "SQL上线工单执行完毕 # " + str(workflowId)
            strContent = "发起人:" + engineer + "\n审核人:" + reviewMen + "\n工单地址:" + url + "\n工单名称: " + workflowName + "\n执行结果:" + workflowStatus
            reviewManAddr = [
                email['email'] for email in users.objects.filter(
                    username__in=listAllReviewMen).values('email')
            ]
            dbaAddr = [
                email['email']
                for email in users.objects.filter(role='DBA').values('email')
            ]
            # 获取抄送人邮件地址
            workflowDetaiL = workflow.objects.get(id=workflowId)
            cc_list = json.loads(workflowDetaiL.email_cc)
            for cc_name in cc_list:
                cc_name_list = [
                    email['email'] for email in users.objects.filter(
                        display=str(cc_name)).values('email')
                ]
                for cc_addr in cc_name_list:
                    reviewManAddr.append(cc_addr)
            listCcAddr = reviewManAddr + dbaAddr

            mailSender.sendEmail(strTitle,
                                 strContent, [objEngineer.email],
                                 listCcAddr=listCcAddr)

            # 获取发起人的微信id
            reviewman_wechat = users.objects.get(
                username=workflowDetail.engineer)
            wechat_engineer_userid = reviewman_wechat.outer_id
            wechat_userid = []
            wechat_userid.append(wechat_engineer_userid)

            # 获取审核人的微信id
            reviewman_wechat = users.objects.get(username=listAllReviewMen[0])
            wechat_auditor_userid = reviewman_wechat.outer_id
            wechat_userid.append(wechat_auditor_userid)

            # 发送企业微信
            wechat_userid = list(filter(lambda x: x != '', wechat_userid))

            if wechat_userid:
                wechatTitle = "SQL上线工单执行完毕 # " + str(workflowId)
                Content = "发起人:" + engineer + "\n审核人:" + reviewMen + "\n工单地址:" + url + "\n工单名称: " + workflowName + "\n执行结果:" + workflowStatus
                wechatContent = "<div class=\"normal\">" + Content + "</div>"

                # 获取企业微信的access_token
                Token = wechatSender.GetToken("xxx", "xxx")
                message = wechatTitle.encode("utf-8") + '\n'.encode(
                    'utf8') + wechatContent.encode("utf-8")
                wechatSender.SendMessage(Token, wechat_userid,
                                         wechatTitle.encode("utf-8"),
                                         wechatContent.encode("utf-8"), url)

        except Exception:
            # 关闭后重新获取连接,防止超时
            connection.close()
            workflowDetail.save()

    elif executeDB.is_product == 0:

        # 将流程状态修改为执行中,并更新reviewok_time字段
        workflowDetail.status = Const.workflowStatus['executing']
        workflowDetail.reviewok_time = timezone.now()
        # 执行之前重新split并check一遍,更新SHA1缓存;因为如果在执行中,其他进程去做这一步操作的话,会导致inception core dump挂掉
        try:
            splitReviewResult = inceptionDao.sqlautoReview(
                workflowDetail.sql_content,
                workflowDetail.cluster_name,
                isSplit='yes')
        except Exception as msg:
            context = {'errMsg': msg}
            return render(request, 'error.html', context)
        workflowDetail.review_content = json.dumps(splitReviewResult)
        try:
            workflowDetail.save()
        except Exception:
            # 关闭后重新获取连接,防止超时
            connection.close()
            workflowDetail.save()

        # 采取异步回调的方式执行语句,防止出现持续执行中的异常
        t = Thread(target=execute_call_back,
                   args=(workflowId, clusterName, url))
        t.start()

    return HttpResponseRedirect(reverse('sql:detail', args=(workflowId, )))
Пример #9
0
def passed(request):
    workflowId = request.POST['workflowid']
    if workflowId == '' or workflowId is None:
        context = {'errMsg': 'workflowId参数为空.'}
        return render(request, 'error.html', context)
    workflowId = int(workflowId)
    workflowDetail = workflow.objects.get(id=workflowId)
    url_origin = getDetailUrl(request) + str(workflowId) + '/'
    url = url_origin.replace('127.0.0.1:8000', '172.31.0.68')
    try:
        listAllReviewMen = json.loads(workflowDetail.review_man)
    except ValueError:
        listAllReviewMen = (workflowDetail.review_man, )

    # 服务器端二次验证,正在执行人工审核动作的当前登录用户必须为审核人. 避免攻击或被接口测试工具强行绕过
    loginUser = request.session.get('login_username', False)
    listDBA = [
        username['username']
        for username in users.objects.filter(role='DBA').values('username')
    ]
    if loginUser not in listDBA:
        if loginUser is None or loginUser not in listAllReviewMen:
            context = {'errMsg': '当前登录用户不是审核人,请重新登录.'}
            return render(request, 'error.html', context)

    # 服务器端二次验证,当前工单状态必须为等待人工审核
    if workflowDetail.status != Const.workflowStatus['manreviewing']:
        context = {'errMsg': '当前工单状态不是等待人工审核中,请刷新当前页面!'}
        return render(request, 'error.html', context)

    # 将流程状态修改为审核通过,并更新reviewok_time字段
    workflowDetail.status = Const.workflowStatus['pass']
    workflowDetail.reviewok_time = timezone.now()
    workflowDetail.audit_remark = ''

    # 更新审核人
    listReviewMen = (loginUser, )
    workflowDetail.review_man = json.dumps(listReviewMen, ensure_ascii=False)
    workflowDetail.save()

    # 获取发起人的微信id
    reviewman_wechat = users.objects.get(username=workflowDetail.engineer)
    wechat_auditor_userid = reviewman_wechat.outer_id
    wechat_userid = []
    if wechat_auditor_userid:
        wechat_userid.append(wechat_auditor_userid)

    # 如果审核通过了了,则根据settings.py里的配置决定是否给提交者和DBA一封邮件提醒.DBA需要知晓审核并执行过的单子
    if hasattr(settings, 'MAIL_ON_OFF') == True:
        if getattr(settings, 'MAIL_ON_OFF') == "on":
            # 给主、副审核人,申请人,DBA各发一封邮件
            engineer = workflowDetail.engineer
            reviewMen = workflowDetail.review_man
            workflowStatus = workflowDetail.status
            workflowName = workflowDetail.workflow_name
            objEngineer = users.objects.get(username=engineer)
            strTitle = "SQL上线工单审核通过 # " + str(workflowId)
            strContent = "发起人:" + engineer + "\n审核人:" + reviewMen + "\n工单地址:" + url + "\n工单名称: " + workflowName + "\n审核结果:" + workflowStatus
            reviewManAddr = [
                email['email'] for email in users.objects.filter(
                    username__in=listAllReviewMen).values('email')
            ]
            dbaAddr = [
                email['email']
                for email in users.objects.filter(role='DBA').values('email')
            ]
            listCcAddr = reviewManAddr + dbaAddr
            mailSender.sendEmail(strTitle,
                                 strContent, [objEngineer.email],
                                 listCcAddr=listCcAddr)

            # 发送企业微信
            wechat_userid = list(filter(lambda x: x != '', wechat_userid))

            if wechat_userid:
                wechatTitle = "SQL上线工单审核通过 # " + str(workflowId)
                Content = "发起人:" + engineer + "\n审核人:" + reviewMen + "\n工单地址:" + url + "\n工单名称: " + workflowName + "\n审核结果:" + workflowStatus
                wechatContent = "<div class=\"normal\">" + Content + "</div>"

                # 获取企业微信的access_token
                Token = wechatSender.GetToken("xxx", "xxx")
                message = wechatTitle.encode("utf-8") + '\n'.encode(
                    'utf8') + wechatContent.encode("utf-8")
                wechatSender.SendMessage(Token, wechat_userid,
                                         wechatTitle.encode("utf-8"),
                                         wechatContent.encode("utf-8"), url)

    return HttpResponseRedirect(reverse('sql:detail', args=(workflowId, )))