mysql主从加入新的同步方式

pull/321/head
midoks 2 years ago
parent e53e5cd672
commit 22acce8bc0
  1. 12
      plugins/mysql/conf/mysql.sql
  2. 2
      plugins/mysql/index.html
  3. 217
      plugins/mysql/index.py
  4. 253
      plugins/mysql/js/mysql.js
  5. 4
      route/static/app/public.js

@ -40,4 +40,16 @@ CREATE TABLE IF NOT EXISTS `slave_id_rsa` (
`addtime` TEXT
);
-- drop table `slave_user`;
CREATE TABLE IF NOT EXISTS `slave_sync_user` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`ip` TEXT,
`port` TEXT,
`user` TEXT,
`pass` TEXT,
`mode` TEXT,
`cmd` TEXT,
`addtime` TEXT
);

@ -53,7 +53,7 @@
.conf_p span {
display: inline-block;
margin-right: 10px;
width: 135px;
width: 115px;
text-align: right;
}
</style>

@ -133,14 +133,8 @@ def pSqliteDb(dbname='databases'):
csql_list = csql.split(';')
for index in range(len(csql_list)):
conn.execute(csql_list[index], ())
else:
# 现有run
# conn = mw.M(dbname).dbPos(getServerDir(), name)
# csql = mw.readFile(getPluginDir() + '/conf/mysql.sql')
# csql_list = csql.split(';')
# for index in range(len(csql_list)):
# conn.execute(csql_list[index], ())
conn = mw.M(dbname).dbPos(getServerDir(), name)
conn = mw.M(dbname).dbPos(getServerDir(), name)
return conn
@ -2103,6 +2097,123 @@ def getSlaveSSHList(version=''):
return mw.getJson(data)
def getSlaveSyncUserByIp(version=''):
args = getArgs()
data = checkArgs(args, ['ip'])
if not data[0]:
return data[1]
ip = args['ip']
conn = pSqliteDb('slave_sync_user')
data = conn.field('ip,port,user,pass,mode,cmd').where(
"ip=?", (ip,)).select()
return mw.returnJson(True, 'ok', data)
def addSlaveSyncUser(version=''):
import base64
args = getArgs()
data = checkArgs(args, ['ip'])
if not data[0]:
return data[1]
ip = args['ip']
if ip == "":
return mw.returnJson(True, 'ok')
data = checkArgs(args, ['port', 'user', 'pass', 'mode'])
if not data[0]:
return data[1]
cmd = args['cmd']
port = args['port']
user = args['user']
apass = args['pass']
mode = args['mode']
addTime = time.strftime('%Y-%m-%d %X', time.localtime())
conn = pSqliteDb('slave_sync_user')
data = conn.field('ip').where("ip=?", (ip,)).select()
if len(data) > 0:
res = conn.where("ip=?", (ip,)).save(
'port,user,pass,mode,cmd', (port, user, apass, mode, cmd))
else:
conn.add('ip,port,user,cmd,user,pass,mode,addtime',
(ip, port, user, cmd, user, apass, mode, addTime))
return mw.returnJson(True, '设置成功!')
def delSlaveSyncUser(version=''):
args = getArgs()
data = checkArgs(args, ['ip'])
if not data[0]:
return data[1]
ip = args['ip']
conn = pSqliteDb('slave_sync_user')
conn.where("ip=?", (ip,)).delete()
return mw.returnJson(True, '删除成功!')
def getSlaveSyncUserList(version=''):
args = getArgs()
data = checkArgs(args, ['page', 'page_size'])
if not data[0]:
return data[1]
page = int(args['page'])
page_size = int(args['page_size'])
conn = pSqliteDb('slave_sync_user')
limit = str((page - 1) * page_size) + ',' + str(page_size)
field = 'id,ip,port,user,pass,cmd,addtime'
clist = conn.field(field).limit(limit).order('id desc').select()
count = conn.count()
data = {}
_page = {}
_page['count'] = count
_page['p'] = page
_page['row'] = page_size
_page['tojs'] = args['tojs']
data['page'] = mw.getPage(_page)
data['data'] = clist
return mw.getJson(data)
def getSyncModeFile():
return getServerDir() + "/sync.mode"
def getSlaveSyncMode(version):
sync_mode = getSyncModeFile()
if os.path.exists(sync_mode):
mode = mw.readFile(sync_mode).strip()
return mw.returnJson(True, 'ok', mode)
return mw.returnJson(False, 'fail')
def setSlaveSyncMode(version):
args = getArgs()
data = checkArgs(args, ['mode'])
if not data[0]:
return data[1]
mode = args['mode']
sync_mode = getSyncModeFile()
if mode == 'none':
os.remove(sync_mode)
else:
mw.writeFile(sync_mode, mode)
return mw.returnJson(True, '设置成功', mode)
def getSlaveSSHByIp(version=''):
args = getArgs()
data = checkArgs(args, ['ip'])
@ -2160,7 +2271,7 @@ def delSlaveSSH(version=''):
conn = pSqliteDb('slave_id_rsa')
conn.where("ip=?", (ip,)).delete()
return mw.returnJson(True, 'ok')
return mw.returnJson(True, '删除SSH成功!')
def updateSlaveSSH(version=''):
@ -2205,6 +2316,47 @@ def getSlaveSyncCmd(version=''):
def initSlaveStatus(version=''):
mode_file = getSyncModeFile()
if not os.path.exists(mode_file):
return mw.returnJson(False, '需要先设置同步配置')
mode = mw.readFile(mode_file)
if mode == 'ssh':
return initSlaveStatusSSH(version)
if mode == 'sync-user':
return initSlaveStatusSyncUser(version)
def initSlaveStatusSyncUser(version=''):
conn = pSqliteDb('slave_sync_user')
data = conn.field('ip,port,user,pass,mode,cmd').find()
if len(data) < 1:
return mw.returnJson(False, '需要先添加同步用户配置!')
# print(data)
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) > 0:
return mw.returnJson(False, '已经初始化好了zz...')
u = data
mode_name = 'classic'
if u['mode'] == '1':
mode_name = 'gtid'
local_mode = recognizeDbMode()
if local_mode != mode_name:
return mw.returnJson(False, '同步模式不一致!')
t = db.query(u['cmd'])
# print(t)
db.query("start slave user='{}' password='{}';".format(
u['user'], u['pass']))
return mw.returnJson(True, '初始化成功!')
def initSlaveStatusSSH(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) > 0:
@ -2214,7 +2366,7 @@ def initSlaveStatus(version=''):
data = conn.field('ip,port,id_rsa').find()
if len(data) < 1:
return mw.returnJson(False, '需要先配置【[主]SSH配置】!')
return mw.returnJson(False, '需要先添加SSH配置!')
SSH_PRIVATE_KEY = "/tmp/t_ssh.txt"
ip = data['ip']
@ -2273,6 +2425,39 @@ def initSlaveStatus(version=''):
def setSlaveStatus(version=''):
mode_file = getSyncModeFile()
if not os.path.exists(mode_file):
return mw.returnJson(False, '需要先设置同步配置')
mode = mw.readFile(mode_file)
if mode == 'ssh':
return setSlaveStatusSSH(version)
if mode == 'sync-user':
return setSlaveStatusSyncUser(version)
def setSlaveStatusSyncUser(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
if len(dlist) == 0:
return mw.returnJson(False, '需要手动添加同步账户或者执行初始化!')
if len(dlist) > 0 and (dlist[0]["Slave_IO_Running"] == 'Yes' or dlist[0]["Slave_SQL_Running"] == 'Yes'):
db.query('stop slave')
else:
ip = dlist[0]['Master_Host']
conn = pSqliteDb('slave_sync_user')
data = conn.field('ip,port,user,pass,mode,cmd').find()
if len(data) == 0:
return mw.returnJson(False, '没有数据无法重启!')
user = data['user']
apass = data['pass']
db.query("start slave user='{}' password='{}';".format(user, apass))
return mw.returnJson(True, '设置成功!')
def setSlaveStatusSSH(version=''):
db = pMysqlDb()
dlist = db.query('show slave status')
@ -2653,6 +2838,18 @@ if __name__ == "__main__":
print(delSlaveSSH(version))
elif func == 'update_slave_ssh':
print(updateSlaveSSH(version))
elif func == 'get_slave_sync_user_list':
print(getSlaveSyncUserList(version))
elif func == 'get_slave_sync_user_by_ip':
print(getSlaveSyncUserByIp(version))
elif func == 'add_slave_sync_user':
print(addSlaveSyncUser(version))
elif func == 'del_slave_sync_user':
print(delSlaveSyncUser(version))
elif func == 'get_slave_sync_mode':
print(getSlaveSyncMode(version))
elif func == 'set_slave_sync_mode':
print(setSlaveSyncMode(version))
elif func == 'init_slave_status':
print(initSlaveStatus(version))
elif func == 'set_slave_status':

@ -1821,8 +1821,23 @@ function addSlaveSSH(ip=''){
function delSlaveSSH(ip){
myPost('del_slave_ssh', {ip:ip}, function(rdata){
var rdata = $.parseJSON(rdata.data);
layer.msg(rdata.msg, {icon: rdata.status ? 1 : 2});
getSlaveSSHPage();
showMsg(rdata.msg,function(){
if (rdata.status){
getSlaveSSHPage();
}
},{icon: rdata.status ? 1 : 2}, 600);
});
}
function delSlaveSyncUser(ip){
myPost('del_slave_sync_user', {ip:ip}, function(rdata){
var rdata = $.parseJSON(rdata.data);
showMsg(rdata.msg,function(){
if (rdata.status){
getSlaveSyncUserPage();
}
},{icon: rdata.status ? 1 : 2}, 600);
});
}
@ -1872,6 +1887,238 @@ function getSlaveSSHPage(page=1){
}
function addSlaveSyncUser(ip=''){
myPost('get_slave_sync_user_by_ip', {ip:ip}, function(rdata){
var rdata = $.parseJSON(rdata.data);
var ip = '127.0.0.1';
var port = "22";
var cmd = '';
var user = 'input_sync_user';
var pass = 'input_sync_pwd';
var mode = '0';
if (rdata.data.length>0){
ip = rdata.data[0]['ip'];
port = rdata.data[0]['port'];
cmd = rdata.data[0]['cmd'];
user = rdata.data[0]['user'];
pass = rdata.data[0]['pass'];
mode = rdata.data[0]['mode'];
}
var index = layer.open({
type: 1,
area: ['500px','470px'],
title: '同步账户',
closeBtn: 1,
shift: 5,
shadeClose: true,
btn:["确认","取消"],
content: "<form class='bt-form pd20'>\
<div class='line'><span class='tname'>IP</span><div class='info-r'><input name='ip' class='bt-input-text mr5' type='text' style='width:330px;' value='"+ip+"'></div></div>\
<div class='line'><span class='tname'>端口</span><div class='info-r'><input name='port' class='bt-input-text mr5' type='number' style='width:330px;' value='"+port+"'></div></div>\
<div class='line'><span class='tname'>同步账户</span><div class='info-r'><input name='user' class='bt-input-text mr5' type='text' style='width:330px;' value='"+user+"'></div></div>\
<div class='line'><span class='tname'>同步密码</span><div class='info-r'><input name='pass' class='bt-input-text mr5' type='text' style='width:330px;' value='"+pass+"'></div></div>\
<div class='line'>\
<span class='tname'>CMD[可选]</span>\
<div class='info-r'><textarea class='bt-input-text mr5' row='20' cols='30' name='cmd' style='width:330px;height:150px;'></textarea></div>\
</div>\
<input type='hidden' name='mode' value='"+mode+"' />\
</form>",
success:function(){
$('textarea[name="cmd"]').html(cmd);
$('textarea[name="cmd"]').change(function(){
var val = $(this).val();
var vlist = val.split(',');
var a = {};
for (var i in vlist) {
var tmp = toTrim(vlist[i]);
var tmp_a = tmp.split(" ");
var real_tmp = tmp_a[tmp_a.length-1];
var kv = real_tmp.split("=");
a[kv[0]] = kv[1].replace("'",'').replace("'",'');
}
$('input[name="ip"]').val(a['MASTER_HOST']);
$('input[name="port"]').val(a['MASTER_PORT']);
$('input[name="user"]').val(a['MASTER_USER']);
$('input[name="pass"]').val(a['MASTER_PASSWORD']);
console.log(a['MASTER_AUTO_POSITION'],typeof(a['MASTER_AUTO_POSITION']));
if (typeof(a['MASTER_AUTO_POSITION']) != 'undefined' ){
$('input[name="mode"]').val('1');
}
});
},
yes:function(index){
var ip = $('input[name="ip"]').val();
var port = $('input[name="port"]').val();
var user = $('input[name="user"]').val();
var pass = $('input[name="pass"]').val();
var cmd = $('textarea[name="cmd"]').val();
var mode = $('input[name="mode"]').val();
var data = {ip:ip,port:port,cmd:cmd,user:user,pass:pass,mode:mode};
myPost('add_slave_sync_user', data, function(ret_data){
layer.close(index);
var rdata = $.parseJSON(ret_data.data);
showMsg(rdata.msg,function(){
if (rdata.status){
getSlaveSyncUserPage();
}
},{icon: rdata.status ? 1 : 2},600);
});
}
});
});
}
function getSlaveSyncUserPage(page=1){
var _data = {};
_data['page'] = page;
_data['page_size'] = 5;
_data['tojs'] ='getSlaveSyncUserPage';
myPost('get_slave_sync_user_list', _data, function(data){
var layerId = null;
var rdata = [];
try {
rdata = $.parseJSON(data.data);
} catch(e) {
console.log(e);
}
var list = '';
var user_list = rdata['data'];
for (i in user_list) {
var ip = user_list[i]['ip'];
var port = user_list[i]['port'];
var user = user_list[i]['user'];
var apass = user_list[i]['pass'];
var cmd = '未设置';
if (user_list[i]['cmd']!=''){
cmd = '已设置';
}
list += '<tr><td>'+ip+'</td>\
<td>'+port+'</td>\
<td>'+user+'</td>\
<td>'+apass+'</td>\
<td>'+cmd+'</td>\
<td>\
<a class="btlink" onclick="addSlaveSyncUser(\''+ip+'\');">修改</a> | \
<a class="btlink" onclick="delSlaveSyncUser(\''+ip+'\');">删除</a>\
</td>\
</tr>';
}
$('.get-slave-ssh-list tbody').html(list);
$('.dataTables_paginate_4').html(rdata['page']);
});
}
function getSlaveCfg(){
myPost('get_slave_sync_mode', '', function(data){
var rdata = $.parseJSON(data.data);
var mode_none = 'success';
var mode_ssh = 'danger';
var mode_sync_user = 'danger';
if(rdata.status){
var mode_none = 'danger';
if (rdata.data == 'ssh'){
var mode_ssh = 'success';
var mode_sync_user = 'danger';
} else {
var mode_ssh = 'danger';
var mode_sync_user = 'success';
}
}
layerId = layer.open({
type: 1,
title: '同步配置',
area: ['400px','180px'],
content:"<div class='bt-form pd20 c6'>\
<p class='conf_p'>\
<span class='f14 c6 mr20'>当前从库同步模式</span>\
<b class='f14 c6 mr20'></b>\
<button class='btn btn-"+mode_none+" btn-xs slave-db-mode btn-none'></button>\
<button class='btn btn-"+mode_ssh+" btn-xs slave-db-mode btn-ssh'>SSH</button>\
<button class='btn btn-"+mode_sync_user+" btn-xs slave-db-mode btn-sync-user'>同步账户</button>\
</p>\
<hr />\
<p class='conf_p'>\
<span class='f14 c6 mr20'>配置设置</span>\
<b class='f14 c6 mr20'></b>\
<button class='btn btn-success btn-xs btn-slave-ssh'>SSH</button>\
<button class='btn btn-success btn-xs btn-slave-user'>同步账户</button>\
</p>\
</div>",
success:function(){
$('.btn-slave-ssh').click(function(){
getSlaveSSHList();
});
$('.btn-slave-user').click(function(){
getSlaveUserList();
});
$('.slave-db-mode').click(function(){
var _this = this;
var mode = 'none';
if ($(this).hasClass('btn-ssh')){
mode = 'ssh';
}
if ($(this).hasClass('btn-sync-user')){
mode = 'sync-user';
}
myPost('set_slave_sync_mode', {mode:mode}, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg,function(){
$('.slave-db-mode').remove('btn-success').addClass('btn-danger');
$(_this).removeClass('btn-danger').addClass('btn-success');
},{icon:rdata.status?1:2},2000);
});
});
}
});
});
}
function getSlaveUserList(){
var page = '<div class="dataTables_paginate_4 dataTables_paginate paging_bootstrap page" style="margin-top:0px;"></div>';
page += '<div class="table_toolbar" style="left:0px;"><span class="sync btn btn-default btn-sm" onclick="addSlaveSyncUser()" title="">添加同步账户</span></div>';
layerId = layer.open({
type: 1,
title: '同步账户列表',
area: '500px',
content:"<div class='bt-form pd20 c6'>\
<div class='divtable mtb10'>\
<div><table class='table table-hover get-slave-ssh-list'>\
<thead><tr><th>IP</th><th>PORT</th><th></th><th></th><th>CMD</th><th></th></tr></thead>\
<tbody></tbody>\
</table></div>\
"+page +"\
</div>\
</div>",
success:function(){
getSlaveSyncUserPage(1);
}
});
}
function getSlaveSSHList(page=1){
var page = '<div class="dataTables_paginate_4 dataTables_paginate paging_bootstrap page" style="margin-top:0px;"></div>';
@ -2110,7 +2357,7 @@ function masterOrSlaveConf(version=''){
<p class="conf_p">\
<span class="f14 c6 mr20">Slave[]配置</span><span class="f14 c6 mr20"></span>\
<button class="btn '+(!rdata.slave_status ? 'btn-danger' : 'btn-success')+' btn-xs btn-slave">'+(!rdata.slave_status ? '未启动' : '已启动') +'</button>\
<button class="btn btn-success btn-xs" onclick="getSlaveSSHList()" >[]SSH配置</button>\
<button class="btn btn-success btn-xs" onclick="getSlaveCfg()" >同步配置</button>\
<button class="btn btn-success btn-xs" onclick="initSlaveStatus()" >初始化</button>\
</p>\
<hr/>\

@ -16,6 +16,10 @@ function toSize(a) {
}
}
function toTrim(x) {
return x.replace(/^\s+|\s+$/gm,'');
}
function inArray(f, arr){
for (var i = 0; i < arr.length; i++) {
if (f == arr[i]) {

Loading…
Cancel
Save