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,)))
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,)))
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, )))
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,)))
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,)))
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, )))
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, )))
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, )))
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, )))