直接上效果图

提交之后可以看到

点击SQL详情

点击处理详情记录了inception审核的内容,然后可以点击手动,执行,打回功能,回滚暂时没写

结果如上都已经很清楚了,那么下面我们看实现过程,因为这是个人自己玩的项目,并没有上线,所以就本着简单的原则设计了下
django涉及的models几张表如下

# -*- coding: utf-8 -*-
from __future__ import unicode_literalsfrom django.db import models
from utils.basemodels import  BaseModel
from crm.models import  User# Create your models here.class Instance(models.Model):ENVS=(('dev','开发'),('test','测试'),('prod','生产'))name=models.CharField(max_length=100,verbose_name='实例名称')host=models.CharField(max_length=100,verbose_name='实例对应的IP地址')port=models.IntegerField(verbose_name='实例端口')create_user=models.ForeignKey(User,verbose_name='实例创建用户',on_delete=models.SET_NULL,blank=True,null=True)dbrole=models.CharField(max_length=100,choices=((1,'master'),(0,'slave')),verbose_name='主从角色关系')cluster=models.IntegerField(choices=((0,'单实例'),(1,'集群')),verbose_name='是否为集群0:否 1:是')env=models.CharField(max_length=100,choices=ENVS,verbose_name='实例环境')createtime = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')updatetime = models.DateTimeField(auto_now=True, verbose_name='修改时间')remark = models.TextField(default='', null=True, blank=True, verbose_name='备注')def __str__(self):return  self.nameclass Meta:db_table='instance'verbose_name='MySQL实例表'verbose_name_plural=verbose_namemanaged = Truepermissions = (('installsinglemysql','安装单实例MySQL'),('installmultimysql','安装多实例MySQL'),)class DbInfo(models.Model):ENVS = (('dev', '开发'), ('test', '测试'), ('prod', '生产'))name=models.CharField(max_length=100,verbose_name='实例名称')host = models.CharField(max_length=100, verbose_name='实例对应的IP地址')port = models.IntegerField(verbose_name='实例端口')dbname=models.CharField(max_length=100,verbose_name='数据库名')dbrole = models.CharField(max_length=100,choices=((1,'master'),(0,'slave')), verbose_name='主从角色关系')env = models.CharField(max_length=100,choices=ENVS, verbose_name='实例环境')createtime = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')def __str__(self):return  '%s-%s-%s-%s'%(self.get_env_display(),self.dbname,self.get_dbrole_display(),self.host)class Meta:db_table='dbinfo'verbose_name='数据库表'verbose_name_plural=verbose_namedef get_env(self):return  self.get_env_display()from django.contrib.auth.models import  Permission
class DbAssign(models.Model):ENVS = (('dev', '开发'), ('test', '测试'), ('prod', '生产'))name = models.CharField(max_length=100, verbose_name='实例名称')host = models.CharField(max_length=100, verbose_name='实例对应的IP地址')port = models.IntegerField(verbose_name='实例端口')dbname = models.CharField(max_length=100,verbose_name='数据库名')dbrole = models.CharField(max_length=100,choices=(('master', '主'), ('slave', '从')), verbose_name='主从角色关系')env = models.CharField(max_length=100,choices=ENVS, verbose_name='实例环境')group=models.ManyToManyField(Permission,verbose_name='可使用此数据库的组')def __str__(self):return self.dbnameclass Meta:db_table='dbassign'verbose_name='数据库权限分配'verbose_name_plural=verbose_nameclass InceptSql(models.Model):STATUS = ((-3, u'已打回'),(-2, u'已回滚'),(-1, u'待执行'),(0, u'已执行'),(1, u'执行失败'),(2, u'已手工执行'),)ENVS = (('dev', '开发'), ('test', '测试'), ('prod', '生产'))db = models.ForeignKey(DbInfo, on_delete=models.CASCADE)commiter = models.ForeignKey(User,on_delete=models.CASCADE,verbose_name='代码提交人',related_name='commiter')sql_content = models.TextField(verbose_name='提交的SQL代码')env = models.CharField(max_length=8, choices=ENVS,verbose_name='SQL应用环境')treater = models.ForeignKey(User,null=True,blank=True,on_delete=models.CASCADE,verbose_name='代码执行人',related_name='treater')status = models.IntegerField(default=-1, choices=STATUS)execute_errors = models.TextField(default='', null=True, blank=True)exe_affected_rows = models.CharField(max_length=10, null=True, blank=True)roll_affected_rows = models.CharField(max_length=10, null=True, blank=True)rollback_opid = models.TextField(null=True, blank=True)rollback_db = models.CharField(max_length=100, null=True, blank=True)inception_detail = models.TextField(default='', null=True, blank=True, verbose_name='inception详情')createtime = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')updatetime = models.DateTimeField(auto_now=True, verbose_name='修改时间')remark = models.TextField(default='', null=True, blank=True, verbose_name='备注')class Meta:db_table = 'inceptsql'verbose_name = '数据库Inception'verbose_name_plural = verbose_namemanaged = Truepermissions = (('sqlcheck', 'MySQL脚本上线审核'),('sqlexecute', 'MySQL脚本普通执行'),('pt-osc', 'pt-osc执行'),('gh-ost', 'gh-ost执行'),('sqlrollback', 'MySQL脚本回退'),('sqlmanual', 'MySQL脚本手工执行'),)def __str__(self):return  '%s-%s-%s'%(self.id,self.get_env_display(),self.db)class InceptStep(models.Model):work_order = models.ForeignKey(InceptSql, on_delete=models.CASCADE)user = models.ForeignKey(User, null=True, blank=True, on_delete=models.CASCADE,verbose_name='工单处理人员')createtime = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')updatetime = models.DateTimeField(auto_now=True, verbose_name='修改时间')remark = models.TextField(default='', null=True, blank=True, verbose_name='备注')

目前dbassign这张表没有使用
数据库inception审核需要安装inception,但是由于inception需要安装很多组件,我安装了goInception,很好移植安装,安装完成之后按照配置要求启动goInception,链接
goinception

vue前端展示页面code:

在这里插入代码片<template><div><el-table :data="tableformData" style="width: 100%;text-align:center"  :header-cell-style="{textAlign: 'center'}" :cell-style="{ textAlign: 'center' }" border><el-table-column prop="id" label="ID" width="50"></el-table-column><el-table-column prop="createtime" label="提交时间" :formatter="formatCreatetime" width="200"></el-table-column><el-table-column prop="commitername" label="提交人" width="70"></el-table-column><el-table-column prop="env" label="环境" width="100"><template slot-scope="scope"><el-tag :type="envtype(scope.row)"disable-transitions>{{scope.row.envdisplay}}</el-tag></template></el-table-column><!-- <el-table-column prop="sql_content"  label="工单SQL" width="300"  show-overflow-tooltip></el-table-column> --><el-table-column label="工单SQL"  align="center" width="150"><!-- <template slot-scope="scope"><el-popover placement="top-start" title="工单SQL" width="250" trigger="hover" ><div style="white-space: pre-line;">{{scope.row.sql_content}}</div><span slot="reference">{{ scope.row.sql_content.substr(0,25)+'...' }}</span></el-popover></template> --><template slot-scope="scope"><el-button size="mini"type=""@click="getSQLContent(scope.$index, scope.row)">SQL详情</el-button></template></el-table-column><el-table-column  label="数据库信息" width="200" ><template slot-scope="scope"><el-popover placement="top-start"  width="400" trigger="hover" ><div style="white-space: pre-line;">{{scope.row.dbinfo}}</div><span slot="reference">{{ scope.row.dbinfo.substr(0,10)+'...' }}</span></el-popover></template></el-table-column><el-table-column prop="updatetime" label="更新时间" :formatter="formatUpdatetime" width="180"></el-table-column><el-table-column prop="statusdisplay" label="工单状态"  width="150"></el-table-column><el-table-column  label="流程" width="100"><template slot-scope="scope"><el-button size="mini"type=""@click="handleFlow(scope.$index, scope.row)">流程</el-button></template></el-table-column><el-table-column label="操作" width="300"><template slot-scope="scope"><div style="display: flex;justify-content: space-around;"><!-- <el-dropdown><el-button type="primary" size="mini">执行<i class="el-icon-arrow-down el-icon--right"></i></el-button><el-dropdown-menu slot="dropdown"><el-dropdown-item @click.native="handleExec(scope.$index, scope.row)">原生执行</el-dropdown-item><el-dropdown-item @click.native="handlePtOsc(scope.$index, scope.row)">PT-OSC</el-dropdown-item><el-dropdown-item @click.native="handleGhOst(scope.$index, scope.row)">GH-OST</el-dropdown-item><el-dropdown-item @click.native="handleManual(scope.$index, scope.row)">手动执行</el-dropdown-item></el-dropdown-menu>
</el-dropdown> --><el-buttonsize="mini"type="success":disabled="disshow(scope.row)"@click="handleManual(scope.$index, scope.row)">手动</el-button><el-buttonsize="mini"type="primary":disabled="disshow(scope.row)"@click="handleExec(scope.$index, scope.row)">执行</el-button><el-buttonsize="mini"type="warning":disabled="disshow(scope.row)"@click="handleCancel(scope.$index, scope.row)">打回</el-button><el-buttonsize="mini"type="danger"@click="handleRollback(scope.$index, scope.row)">回滚</el-button></div></template></el-table-column><el-table-column  label="inception" ><template slot-scope="scope"><el-button size="mini"type=""@click="ShowInceptionDetail(scope.$index, scope.row)">处理详情</el-button></template></el-table-column></el-table><el-dialog center title="工单流程" :visible.sync="WorkFlowVisible" width="50%"><el-timeline><el-timeline-itemv-for="wf in workflow":key="wf.id":index="wf.id":timestamp="wf.createtime|fdatetime">用户:{{wf.username}}-{{ wf.remark }}</el-timeline-item></el-timeline></el-dialog><el-dialog center title="Inception详情" :visible.sync="InceptionVisible" width="50%"><divstyle="border:0px;padding:3px;width:100%;height:300px;white-space: nowrap;overflow-x:auto;overflow-y:auto;"><strong  v-for="icr in inceptionres":key="icr.order_id":index="icr.order_id">   [{{icr}}]<br></strong></div></el-dialog><el-dialog center title="工单SQL内容" :visible.sync="sqlconentVisible" width="50%"><divstyle="border:0px;padding:3px;width:100%;height:300px;white-space:pre-line;overflow:scroll; width:100%;"><strong>{{sqlcontent}}</strong></div></el-dialog><el-dialog center title="SQL回滚语句" :visible.sync="sqlRollbackVisible" width="50%"><divstyle="border:0px;padding:3px;width:100%;height:300px;white-space:pre-line;overflow:scroll; width:100%;"><strong>{{rollbackres}}</strong></div></el-dialog><el-pagination style="text-align: center; "@size-change="handleSizeChange"@current-change="handleCurrentChange":current-page.sync="currentPage":page-sizes="pagesizes":page-size="pagesize"layout="total,sizes, prev, pager, next":total=total></el-pagination></div>
</template>
<script>
import moment from 'moment';
import {InceptionCheck,InceptionExecute,InceptionRollback,InceptionManual,InceptionPtOsc,InceptionGhOst,Inception,InceptionDetail,InceptionStepDetail} from '@/api/MySQL/goInception'
export default {name: "inception",data() {return {workflow:null,WorkFlowVisible:false,InceptionVisible:false,sqlconentVisible:false,sqlRollbackVisible:false,inceptionres:null,rollbackres:null,sqlcontent:null,tableData:null,loading:false,total:null,currentPage:1,pagesize:10,pagesizes:[5,10, 20, 30, 50,100],formInline: {name: '',host: ''},};},async created(){await this.getInceptionList()//  console.log(this)},filters:{fdatetime(value){return moment(value).format('YYYY-MM-DD HH:mm:ss')}},methods: {disshow(row){if(row.status===2||row.status==='-3'||row.status===0){return true}else{return false}},handleClick(index,row) {console.log(row,index)alert('button click'+JSON.stringify(row));},handleSizeChange(pagesize) {this.pagesize = pagesize;},handleCurrentChange(currentPage) {this.currentPage = currentPage;},getIndex(index) {let currentIndex = (this.currentPage - 1) * this.pagesize + index + 1;if (currentIndex < 10) {return `0${index + 1}`;}return (this.currentPage - 1) * this.pagesize + index + 1;},formatDbrole(row){return row.dbrole === 0 ? "从" : row.dbrole === 1 ? "主" : "未填写";},formatCreatetime(row){return  moment(row.createtime).format('YYYY-MM-DD HH:mm:ss')},formatUpdatetime(row){return  moment(row.updatetime).format('YYYY-MM-DD HH:mm:ss')},statustype(row){if(row.status===0||row.status===2||row.status===3||row.status===4){return 'success'}else if(row.status===-1){return 'info'}else if(row.status===-2){return 'warning'}else{return 'danger'}},envtype(row){if(row.env==='dev'){return 'dev'}else if(row.env==='test'){return 'success'}else if(row.env==='prod'){return 'danger'}},handleFlow(index,row){this.WorkFlowVisible=!this.WorkFlowVisiblelet pdata={work_order:row.id}InceptionStepDetail(pdata).then(res=>{//  console.log(res)this.workflow=res})},getSQLContent(index,row){this.sqlcontent=row.sql_contentthis.sqlconentVisible=!this.sqlconentVisible},ShowInceptionDetail(index,row){if(row.inception_detail.length>0){this.inceptionres=JSON.parse(row.inception_detail)this.InceptionVisible=!this.InceptionVisible}else{this.$message({type: 'error',message: '此工单没有inception相关信息'});}},handleExec(index, row) {this.$prompt('请输入处理意见', '', {inputType:'Text',confirmButtonText: '确定',cancelButtonText: '取消',}).then(async({ value }) => {this.remark=valuethis.remark=this.remark!==null ?this.remark :'MySQL原生执行器执行'let pdata={id:row.id,userid:this.$store.state.permission.userid,remark:this.remark}await InceptionExecute(pdata).then(res=>{console.log("res的值是:"+res.status)if(res.status===0){this.disexec=truethis.discanc=truethis.dismanu=truethis.$message({type: 'success',message: 'MySQL原生命令执行成功!'});}else{this.$message({type: 'error',message: 'MySQL原生命令执行失败'});}}).catch(err=>{this.$message({type: 'error',message: 'API接口InceptionExecute调用报错'+err});})await this.getInceptionList()}).catch(() => {this.$message({type: 'info',message: '暂时放弃'});       });},handleCancel(index, row) {this.disexec=truethis.discanc=truethis.dismanu=trueconsole.log(index, row);},async handleManual(index, row) {this.$prompt('请输入处理意见', '', {inputType:'Text',confirmButtonText: '确定',cancelButtonText: '取消',}).then(async({ value }) => {this.remark=valuethis.remark=this.remark!==null ?this.remark :'SQL语句已线下执行'let pdata={id:row.id,userid:this.$store.state.permission.userid,remark:this.remark}await InceptionManual(pdata).then(res=>{if(res.status===0){this.disexec=truethis.discanc=truethis.dismanu=truethis.$message({type: 'success',message: 'MySQL命令已手动执行'});}else{this.$message({type: 'error',message: 'MySQL手动执行失败'});}}).catch(err=>{this.$message({type: 'error',message: 'API接口InceptionManual调用报错'+err});})await this.getInceptionList()}).catch(() => {this.$message({type: 'info',message: '暂时放弃'});       });},handleRollback(index, row) {let pdata={id:row.id,inception_detail:JSON.parse(row.inception_detail)}InceptionRollback(pdata).then(res=>{console.log(res)this.rollbackres=resthis.sqlRollbackVisible=!this.sqlRollbackVisible}).catch(err=>{console.log(err)})},async getInceptionList(){let res= await Inception()this.tableData=resthis.total=this.tableData.length},async onSubmit() {// console.log('submit!',!this.formInline.host,!this.formInline.name);let params={name:this.formInline.name,host:this.formInline.host}await DbInfoSearch(params).then(res=>{this.tableData=resthis.total=this.tableData.length}).catch(err=>{alert("报错了,报错信息为",err)})}},computed:{tableformData(){if(this.tableData===null){}else{return this.tableData.slice((this.currentPage - 1) * this.pagesize,this.currentPage * this.pagesize);}},}
};
</script>
<style>
.el-table .cell {white-space: pre-line;
}
</style>

sqlcheck.vue:

<template>
<div>
<el-form ref="form" :model="form" label-width="80px">
<div style="display: flex;justify-content: space-around;"><div class="in-coder-panel" style="width:60%"><div style="width:100%"><h1 style="margin:20px">请输入上线要上线的SQL语句:</h1><el-form-item label="SQL"  prop="sqlcontent" required><el-input type="textarea"  rows="10" cols="140" v-model="form.sqlcontent"></el-input></el-form-item><el-form-item label="备注" prop="comment" ><el-input type="textarea"  rows="2" cols="140" v-model="form.comment"></el-input></el-form-item></div></div><div style="width:40%"><div style="width:100%"><h1 style="margin:20px">选择执行条件:</h1><el-form-item label="环境" prop="env"><el-radio-group v-model="form.env"><el-radio label="开发"></el-radio><el-radio label="测试"></el-radio><el-radio label="生产"></el-radio></el-radio-group></el-form-item><el-form-item label="数据库" required><el-select v-model="form.dbtag" placeholder="请选择数据库" ><el-option v-for="item in form.dblist" :label="item.label" :value="item.value" :key="item.id"></el-option></el-select></el-form-item></div></div>
</div>
<el-form-item label="操作"><el-button style="margin-left:200px" type="primary" @click="submitForm('form')">审核</el-button><el-button style="margin-left:200px" @click="resetForm('form')">重置</el-button></el-form-item>
</el-form><el-dialog center title="失败信息" :visible.sync="CheckFailVisible" width="50%"><divv-for="cfr in checkfailres":key="cfr.id":index="cfr.id"><strong  v-if="cfr.error_level!==0">   SQL语句:{{cfr.sql}}-----报错信息:{{ cfr.error_message }}</strong></div></el-dialog>
</div>
</template><script type="text/ecmascript-6">import {DbInfoEnvSearch} from '@/api/MySQL/dbinfo'
import {InceptionCheck} from '@/api/MySQL/goInception'
export default {name: 'sql-check',data () {return {checkfailres:null,CheckFailVisible:false,form: {dblist: '',comment: '',sqlcontent: '',env: '开发',dbtag:''},}},mounted () {},watch:{'form.env':{async handler(newenv, oldenv) {this.form.dbtag=''// console.log('form.env changed',newenv);let envsel=newenv === '开发' ? "dev" : newenv === '测试'  ? "test" : "prod";let params={env:envsel}let res=await DbInfoEnvSearch(params)let arraydblist=[]let concatvalue=''let concatlabel=''res.forEach((i)=>{if(i.dbrole===1){concatlabel=i.name+'-'+i.host+'-'+i.port+'-'+i.dbnameconcatvalue={host:i.host,port:i.port,db:i.id,dbname:i.dbname}arraydblist.push({value:concatvalue,label:concatlabel,id:i.id,host:i.host,port:i.port,dbname:i.dbname})}})// console.log(arraydblist)this.form.dblist=arraydblist},immediate: true,deep: true},},methods: {submitForm(form) {this.$refs[form].validate(async (valid) => {if (valid) {console.log('fortag的值是:'+this.form.dbtag,this.form.dbtag.length)if(this.form.dbtag.length===0){this.$message({type: 'error',message: '请选择执行数据库!'});}// alert(JSON.stringify(this.form));// console.log(this.$store.state.permission.userid)else{let subform={comment:this.form.comment, sqlcontent:this.form.sqlcontent,env: this.form.env,dbtag:this.form.dbtag,userid:this.$store.state.permission.userid}await InceptionCheck(subform).then(res=>{if(res.status===0){this.$message({type: 'success',message: '工单添加成功!'});}else{this.checkfailres=res.failreasonthis.CheckFailVisible=!this.CheckFailVisibleconsole.log(this.checkfailres)this.$message({type: 'error',message: '工单添加失败,请检查SQL语句!'});}})}} else {console.log('error submit!!');return false;}});},resetForm(form) {this.$refs[form].resetFields();}}}
</script>

goinception.js

import axios from '@/config/httpConfig'export function InceptionCheck(data){return axios.post('/inception/check/',data)
}export function InceptionExecute(data){return axios.post('/inception/'+data.id+'/execute/',data)
}export function InceptionRollback(data){return axios.post('/inception/'+data.id+'/rollback/',data)
}export function InceptionManual(data){return axios.post('/inception/'+data.id+'/manual/',data)
}export function Inception(){return axios.get('/inception/')
}export function InceptionDetail(id){return axios.get('/inception/'+id+'/')
}export function InceptionStepDetail(data){return axios.post('/inceptstep/workflow/',data)
}

instance.js

import axios from '@/config/httpConfig'export function InstanceList(){return axios.get('/instance/')
}export function InstanceDetail(id){return axios.get('/instance/'+id+'/')
}export function InstanceAdd(data){return axios.post('/instance/',data)
}
export function InstanceDel(id){return axios.delete('/instance/'+id+'/')
}
export function InstancePut(data){return axios.put('/instance/',data)
}export function installsinglemysql(data){return axios.post('/singleinstall/',data)
}export function installmultimysql(data){return axios.post('/multiinstall/',data)
}

后端django实现代码:

# -*- coding: utf-8 -*-
from __future__ import unicode_literalsfrom django.http import JsonResponse
from django.shortcuts import render# Create your views here.from sqlmng.serializers import  InstanceModelSerializer,DbAssignModelSerializer,DbInfoModelSerializer,InceptSqlModelSerializer,InceptStepModelSerializer
from sqlmng.models import Instance,DbInfo,DbAssign,InceptSql,InceptStep
from utils.dbtools.mysql_single_install import full_single_install
from utils.dbtools.mysql_multi_install import  full_multil_install
from utils.dbtools.MySQLdb import MysqlHelper
from crm.models import  User
from django.db.models.signals import post_save
from django.dispatch import receiver
import configparsercnf = configparser.ConfigParser()
from  restful_test.settings import INCEPTION_DIR
cnf.read(INCEPTION_DIR)
inception_host=cnf.get('inception','inception_host')
inception_backup_host=cnf.get('inception','inception_backup_host')
inception_backup_port=cnf.get('inception','inception_backup_port')
inception_backup_user=cnf.get('inception','inception_backup_user')
inception_backup_password=cnf.get('inception','inception_backup_password')
from django.core.exceptions import PermissionDeniedfrom rest_framework.response import Response
from utils.jwt_auth import  parse_payload
from rest_framework.decorators import actionfrom rest_framework.viewsets import  ModelViewSet
from rest_framework.views import  APIViewimport pymysqlclass InstanceModelViewSet(ModelViewSet):queryset = Instance.objects.all()serializer_class = InstanceModelSerializerclass DbInfoModelViewSet(ModelViewSet):queryset = DbInfo.objects.all()serializer_class = DbInfoModelSerializerfilter_fields = ('name', 'host','env')import  json
class InceptSqlModelViewSet(ModelViewSet):queryset =InceptSql.objects.all()serializer_class = InceptSqlModelSerializer@action(detail=False,methods=['POST'])def check(self,request):data=request.dataprint("data的值是",data)host=data['dbtag']['host']port=data['dbtag']['port']dbname = data['dbtag']['dbname']db=data['dbtag']['db']env=''if data['env']=='开发':env='dev'if data['env']=='测试':env='test'if data['env']=='生产':env='prod'comment=data['comment']userid=data['userid']username=User.objects.get(id=userid).username# print('username的值是:',username)sqlcontent=data['sqlcontent']sql = '''/*--user=dbadmin;--password=dbadmin;--host={};--checked=1;--port={};*/inception_magic_start;use {};{}inception_magic_commit;'''.format(host,port,dbname,sqlcontent)conn = pymysql.connect(host='%s'%(inception_host), user='', passwd='',db='', port=4000, charset="utf8mb4")cur = conn.cursor()cur.execute(sql)result = cur.fetchall()print("=========================")res_list = [dict(zip([i[0] for i in cur.description], j)) for j in result]print("+++++++++++++++++++++++++")print(res_list)errlen=len([i for i in res_list if i['error_level'] != 0])cur.close()conn.close()if errlen==0:sdata={'db':db,'commiter':userid,'sql_content':sqlcontent,'env':env,'remark':comment,'inception_detail':json.dumps(res_list)}serializer =InceptSqlModelSerializer(data=sdata)# 判断发序列是否正确res = serializer.is_valid()if res:serializer.save()return Response({'status': 0})else:print(serializer.errors)return Response({'status': 1})else:return Response({'status':1,'failreason':res_list})@action(detail=True, methods=['POST'])def execute(self, request,pk):'''检查用户是否有对inception执行的权限'''if request.user.is_anonymous:token = request.META.get('HTTP_AUTHORIZATION', '')user = parse_payload(token)request.user = userres = request.user.roles.values_list('permissions__permission__content_type__app_label','permissions__permission__codename')# print(res)perms_list = ['.'.join(i) for i in res if i[0] != None]perms = ('sqlmng.sqlexecute',)if set(perms) <= set(perms_list):obj = self.get_object()print(pk, obj.sql_content, obj.pk)# return Response("执行脚本成功")data = request.datauserid = data['userid']remark = data['remark']# print(data)sql = '''/*--user=dbadmin;--password=dbadmin;--host={};--execute=1;--backup=1;--port={};*/inception_magic_start;use {};{}inception_magic_commit;'''.format(obj.db.host, obj.db.port, obj.db.dbname, obj.sql_content)conn = pymysql.connect(host='%s'%(inception_host), user='', passwd='',db='', port=4000, charset="utf8mb4")cur = conn.cursor()cur.execute(sql)result = cur.fetchall()print("=========================")res_list = [dict(zip([i[0] for i in cur.description], j)) for j in result]print("+++++++++++++++++++++++++")print(res_list)errlen = len([i for i in res_list if i['error_level'] != 0])cur.close()conn.close()if errlen == 0:sdata = {'work_order': obj.pk, 'user': userid, 'remark': remark}serializer = InceptStepModelSerializer(data=sdata)# 判断发序列是否正确res = serializer.is_valid()if res:serializer.save()obj.inception_detail = json.dumps(res_list)obj.treater = User.objects.get(id=userid)obj.status = 0obj.save()return Response({'status': 0})else:print(serializer.errors)obj.treater = User.objects.get(id=userid)obj.inception_detail = json.dumps(res_list)obj.status = 1obj.save()return Response({'status': 1})else:return Response({'status': 1})else:raise PermissionDenied@action(detail=True, methods=['POST'])def rollback(self, request,pk):data = request.dataprint(type(data['inception_detail']))try:backup_list = [dict(zip(['sequence','backup_dbname'],[j['sequence'],j['backup_dbname']])) for j in data['inception_detail'] if j['backup_dbname']]dbname=backup_list[0]['backup_dbname']condition=[(i['sequence']) for i in backup_list]print(condition)mydb=MysqlHelper(inception_backup_host,inception_backup_user,inception_backup_password,dbname,inception_backup_port)sql='''select opid_time,tablename from $_$inception_backup_information$_$;'''res=mydb.get_all(sql)res_filter=[i for i in res if i[0] in condition]print(res_filter)sqlset=['''select b.rollback_statement  from $_$inception_backup_information$_$ a,%s b where a.opid_time='%s' and a.opid_time=b.opid_time and a.tablename='%s';'''%(j[1],j[0],j[1])  for j in res_filter ]resset=[mydb.get_all(stam) for stam in  sqlset]print(len(resset))sqlres=''for i in resset:for j in i:sqlres+='\n'sqlres+=j[0]return Response(sqlres)except Exception as e:return Response("回滚语句生成失败,请检查是否进行备份,联系DBA大数据开发组")@action(detail=True, methods=['POST'])def manual(self, request,pk):if request.user.is_anonymous:token = request.META.get('HTTP_AUTHORIZATION', '')user = parse_payload(token)request.user = userres = request.user.roles.values_list('permissions__permission__content_type__app_label','permissions__permission__codename')# print(res)perms_list = ['.'.join(i) for i in res if i[0] != None]perms = ('sqlmng.sqlmanual',)if set(perms) <= set(perms_list):data = request.dataprint(data)obj = self.get_object()userid = data['userid']remark = data['remark']sdata = {'work_order': obj.pk, 'user': userid, 'remark': remark}serializer = InceptStepModelSerializer(data=sdata)obj.treater = User.objects.get(id=userid)obj.status = 2obj.save()res = serializer.is_valid()if res:serializer.save()return Response({'status': 0})else:return Response({'status': 1})else:raise  PermissionDenied@receiver(post_save,sender=InceptSql)
def inceptionflow_handler(sender,**kwargs):work_order=kwargs.get('instance').iduser=kwargs.get('instance').commiter.idtreater = kwargs.get('instance').treaterremark = kwargs.get('instance').remarkif treater:sdata={'work_order':work_order,'user':treater,'remark':remark}else:sdata={'work_order': work_order, 'user': user, 'remark': remark}serializer=InceptStepModelSerializer(data=sdata)if serializer.is_valid():serializer.save()else:print(serializer.errors)# print(kwargs.get('instance').id,kwargs.get('instance').sql_content)class InceptStepModelViewSet(ModelViewSet):queryset = InceptStep.objects.all()serializer_class = InceptStepModelSerializer@action(detail=False, methods=['POST'])def workflow(self,request):data=request.dataprint(data)work_order=data['work_order']res=self.get_queryset().filter(work_order=work_order).order_by('-createtime')ser=InceptStepModelSerializer(instance=res,many=True)return  Response(ser.data)# return JsonResponse(json.dumps(list(res.values()),cls=DateEncoder),safe=False)class DbAssignModelViewSet(ModelViewSet):queryset = DbAssign.objects.all()serializer_class = DbAssignModelSerializerclass SingleInstanceInstall(APIView):permission_classes = ()def post(self,request):if request.user.is_anonymous:token = request.META.get('HTTP_AUTHORIZATION', '')user = parse_payload(token)request.user = userres = request.user.roles.values_list('permissions__permission__content_type__app_label','permissions__permission__codename')# print(res)perms_list = ['.'.join(i) for i in res if i[0] != None]perms = ('sqlmng.installsinglemysql',)if set(perms) <= set(perms_list):res=request.dataprint('res的结果结果集是:',res)full_single_install(res['host'],res['port'])# print(res)return Response(res)else:raise  PermissionDenieddef get(self,request):print(request.user)print(request.user.has_perm('sqlmng.installsinglemysql'))perms=('sqlmng.installsinglemysql',)res = request.user.roles.values_list('permissions__permission__content_type__app_label','permissions__permission__codename')# print(res)perms_list = ['.'.join(i) for i in res if i[0] != None]if set(perms) <= set(perms_list):return Response("可以调用installsinglemysql方法")# In case the 403 handler should be called raise the exceptionelse:raise PermissionDeniedclass MultiInstanceInstall(APIView):permission_classes = ()def post(self,request):if request.user.is_anonymous:token = request.META.get('HTTP_AUTHORIZATION', '')user = parse_payload(token)request.user = userres = request.user.roles.values_list('permissions__permission__content_type__app_label','permissions__permission__codename')# print(res)perms_list = ['.'.join(i) for i in res if i[0] != None]perms = ('sqlmng.installmultimysql',)if set(perms) <= set(perms_list):res=request.dataprint('res的结果结果集是:',res)full_multil_install(res['master'],res['slave'],res['port'])# print(res)return Response(res)else:raise  PermissionDenieddef get(self,request):print(request.user)print(request.user.has_perm('sqlmng.installmultimysql'))perms=('sqlmng.installmultimysql',)res = request.user.roles.values_list('permissions__permission__content_type__app_label','permissions__permission__codename')# print(res)perms_list = ['.'.join(i) for i in res if i[0] != None]if set(perms) <= set(perms_list):return Response("可以调用installmultimysql方法")# In case the 403 handler should be called raise the exceptionelse:raise PermissionDenied

基于restframework的基础上我们需要自己定义一些url,作为api接口是用,action价值体现在这,可以基于detail也可以不基于,receiver可以理解成触发器,触发某种事件的时候会自动执行
url.py

from rest_framework import  routers
router=routers.DefaultRouter()
from .views import DbInfoModelViewSet,DbAssignModelViewSet,InstanceModelViewSet,SingleInstanceInstall,MultiInstanceInstall,InceptSqlModelViewSet,InceptStepModelViewSet
router.register('dbinfo',DbInfoModelViewSet)
router.register('dbassign',DbAssignModelViewSet)
router.register('instance',InstanceModelViewSet)
router.register('inception',InceptSqlModelViewSet)
router.register('inceptstep',InceptStepModelViewSet)
from django.conf.urls import  url,include
urlpatterns = [url(r'^',include(router.urls)),url('^singleinstall',SingleInstanceInstall.as_view()),url('^multiinstall', MultiInstanceInstall.as_view())
]

以上为这个项目实施的关键代码

MySQL审核神器Inception相关推荐

  1. Yearning和inception搭建MySQL审核平台

    Yearning和inception搭建MySQL审核平台 前言 采用开源Yearning和inception开源软件,搭建用于MYSQL审核及线上MYSQL语句更新的审核平台. 功能说明 Yearn ...

  2. mysql 审核引擎 goInception 的基本使用

    mysql 审核引擎 goInception 的基本使用 官网地址 https://github.com/hanchuanchuan/goInception 安装 git clone https:// ...

  3. inception mysql 审核_mysql 审核引擎 goInception 的基本使用

    官网地址 github.com 安装 git clone https://github.com/hanchuanchuan/goInception.git cd goInception 修改配置 开启 ...

  4. sql自动审核工具-inception

    [inception使用规范及说明文档](http://mysql-inception.github.io/inception-document/usage/) [代码仓库](https://gith ...

  5. 【推荐】Mysql优化神器(值得一用)

    前言 ❝ 今天逛github时,发现了这款对 SQL 进行优化和改写的自动化工具sora.感觉挺不错的,就下载学习了一下.这个工具支持的功能比较多,可以作为我们日常开发中的一款辅助工具,现在我就把它推 ...

  6. MySql优化神器 Explain工具介绍

    使用EXPLAIN关键字可以模拟优化器执行SQL语句,分析查询语句或是结构的性能瓶颈.在select语句之前增加explaion关键字,MySQL会在查询上设置一个标记,执行查询会返回执行计划的信息, ...

  7. mysql galera cluster实现vip_2019年学MySQL,最佳的10本新书

    程序员书库(ID:OpenSourceTop) 编译 书单来自:https://bookauthority.org/books/new-mysql-books.https://createwebsit ...

  8. MySQL DBA的必备参考,两位数据库资深专家呕心沥血之作

    DBA 精神:责任心.服务心.沟通心.学习心,进取心和分享心.   java学习 成长思维导图:骆驼祥子思维导图 - GitMind 互联网发展至今,开源软件已经深入人心,并且受到广泛的支持和响应,很 ...

  9. Yearning-SQL审核平台

    Yearning-SQL审核平台 调研平台俩个 archeryd-SQL审核查询平台 https://archerydms.com/ yearning-SQL审核查询平台 http://yearnin ...

最新文章

  1. ios xmlrpc
  2. [转载] 信息系统项目管理挂靠合同(协议)范例2
  3. bashrc与profile的相关知识
  4. [工具]更新音乐下载软件工具音乐下载网站
  5. 机器学习从入门到精通系列之BP神经网络理论知识详解
  6. 10 个常用的软件架构模式
  7. 文件上传案例阻塞问题
  8. 数据中心缩小是因为外包和云计算吗
  9. CSS自定义消息提示
  10. leetcode1442. 形成两个异或相等数组的三元组数目
  11. PHP使用empty检查函数返回结果时报Fatal error: Can't use function return value in write context的问题...
  12. atoi java,leetcode题目8: 字符串转换整数 (atoi)(java)
  13. mysql正则防注入_防止sql注入的方法
  14. JAVAapi—数据库连接
  15. ironbot智能编程机器人_小小工程师启蒙教练就选IronBot机器人套件
  16. 电脑装两个硬盘在计算机只显示一个,电脑有两个硬盘,如何去掉机械硬盘中的那套系统?...
  17. 行杂记之Zookeeper SessionTimeOut分析
  18. QIP.ru即时通讯服务3300万明文密码被泄
  19. 编译程序和解释程序的区别
  20. ADB及shell命令总结

热门文章

  1. python tkinter Entry的使用
  2. 一个嵌入式牛人学习经历
  3. 同济大学计算机系拿奖学分绩点,萌新必看NO.8|关于学分绩点奖学金,你想知道的都在这里...
  4. 浅析GIS行业地图绘制基本要求
  5. 电子设计硬件知识要点(1) 电阻、电容、电感、二极管、三极管
  6. C++11:lambda表达式
  7. Linux计划任务介绍
  8. 线性代数:置换、转置矩阵和向量空间
  9. placement new的用法
  10. datalist图片九宫显示