diff --git a/plugins/migration_api/ico.png b/plugins/migration_api/ico.png new file mode 100644 index 000000000..f82867608 Binary files /dev/null and b/plugins/migration_api/ico.png differ diff --git a/plugins/migration_api/index.html b/plugins/migration_api/index.html new file mode 100755 index 000000000..f1ea0e228 --- /dev/null +++ b/plugins/migration_api/index.html @@ -0,0 +1,223 @@ + +
+
+
+
    +
  • 1

    填写信息

  • +
  • 2

    检测环境

  • +
  • 3

    选择数据

  • +
  • 4

    一键迁移

  • +
+
+
+
\ No newline at end of file diff --git a/plugins/migration_api/index.py b/plugins/migration_api/index.py new file mode 100755 index 000000000..15fe59413 --- /dev/null +++ b/plugins/migration_api/index.py @@ -0,0 +1,270 @@ +# coding:utf-8 + +import sys +import io +import os +import time +import re + +sys.path.append(os.getcwd() + "/class/core") +import mw + +app_debug = False +if mw.isAppleSystem(): + app_debug = True + + +def getPluginName(): + return 'migration_api' + + +def getPluginDir(): + return mw.getPluginDir() + '/' + getPluginName() + + +def getServerDir(): + return mw.getServerDir() + '/' + getPluginName() + + +def getInitDFile(): + if app_debug: + return '/tmp/' + getPluginName() + return '/etc/init.d/' + getPluginName() + + +def getConf(): + path = getServerDir() + "/init.d/memcached" + return path + + +def getConfEnv(): + path = getServerDir() + "/memcached.env" + return path + + +def getConfTpl(): + path = getPluginDir() + "/init.d/memcached.tpl" + return path + + +def getMemPort(): + path = getServerDir() + '/memcached.env' + content = mw.readFile(path) + rep = 'PORT\s*=\s*(\d*)' + tmp = re.search(rep, content) + return tmp.groups()[0] + + +def getArgs(): + args = sys.argv[2:] + tmp = {} + args_len = len(args) + + if args_len == 1: + t = args[0].strip('{').strip('}') + t = t.split(':') + tmp[t[0]] = t[1] + elif args_len > 1: + for i in range(len(args)): + t = args[i].split(':') + tmp[t[0]] = t[1] + + return tmp + + +def checkArgs(data, ck=[]): + for i in range(len(ck)): + if not ck[i] in data: + return (False, mw.returnJson(False, '参数:(' + ck[i] + ')没有!')) + return (True, mw.returnJson(True, 'ok')) + + +def status(): + return 'start' + + +def initDreplace(): + + file_tpl = getConfTpl() + service_path = mw.getServerDir() + + initD_path = getServerDir() + '/init.d' + if not os.path.exists(initD_path): + os.mkdir(initD_path) + file_bin = initD_path + '/memcached' + + if not os.path.exists(file_bin): + content = mw.readFile(file_tpl) + content = content.replace('{$SERVER_PATH}', service_path) + mw.writeFile(file_bin, content) + mw.execShell('chmod +x ' + file_bin) + + # systemd + systemDir = mw.systemdCfgDir() + systemService = systemDir + '/memcached.service' + systemServiceTpl = getPluginDir() + '/init.d/memcached.service.tpl' + if os.path.exists(systemDir) and not os.path.exists(systemService): + service_path = mw.getServerDir() + se_content = mw.readFile(systemServiceTpl) + se_content = se_content.replace('{$SERVER_PATH}', service_path) + mw.writeFile(systemService, se_content) + mw.execShell('systemctl daemon-reload') + + envFile = getServerDir() + '/memcached.env' + if not os.path.exists(envFile): + wbody = "IP=127.0.0.1\n" + wbody = wbody + "PORT=11211\n" + wbody = wbody + "USER=root\n" + wbody = wbody + "MAXCONN=1024\n" + wbody = wbody + "CACHESIZE=1024\n" + wbody = wbody + "OPTIONS=''\n" + mw.writeFile(envFile, wbody) + + return file_bin + + +def memOp(method): + file = initDreplace() + + if not mw.isAppleSystem(): + data = mw.execShell('systemctl ' + method + ' ' + getPluginName()) + if data[1] == '': + return 'ok' + return data[1] + + data = mw.execShell(file + ' ' + method) + if data[1] == '': + return 'ok' + return data[1] + + +def start(): + return memOp('start') + + +def stop(): + return memOp('stop') + + +def restart(): + return memOp('restart') + + +def reload(): + return memOp('reload') + + +def runInfo(): + # 获取memcached状态 + import telnetlib + import re + port = getMemPort() + try: + tn = telnetlib.Telnet('127.0.0.1', int(port)) + tn.write(b"stats\n") + tn.write(b"quit\n") + data = tn.read_all() + if type(data) == bytes: + data = data.decode('utf-8') + data = data.replace('STAT', '').replace('END', '').split("\n") + result = {} + res = ['cmd_get', 'get_hits', 'get_misses', 'limit_maxbytes', 'curr_items', 'bytes', + 'evictions', 'limit_maxbytes', 'bytes_written', 'bytes_read', 'curr_connections'] + for d in data: + if len(d) < 3: + continue + t = d.split() + if not t[0] in res: + continue + result[t[0]] = int(t[1]) + result['hit'] = 1 + if result['get_hits'] > 0 and result['cmd_get'] > 0: + result['hit'] = float(result['get_hits']) / \ + float(result['cmd_get']) * 100 + + conf = mw.readFile(getServerDir() + '/memcached.env') + result['bind'] = re.search('IP=(.+)', conf).groups()[0] + result['port'] = int(re.search('PORT=(\d+)', conf).groups()[0]) + result['maxconn'] = int(re.search('MAXCONN=(\d+)', conf).groups()[0]) + result['cachesize'] = int( + re.search('CACHESIZE=(\d+)', conf).groups()[0]) + return mw.getJson(result) + except Exception as e: + return mw.getJson({}) + + +def saveConf(): + + args = getArgs() + data = checkArgs(args, ['ip', 'port', 'maxconn', 'maxsize']) + if not data[0]: + return data[1] + + envFile = getServerDir() + '/memcached.env' + + wbody = "IP=" + args['ip'] + "\n" + wbody = wbody + "PORT=" + args['port'] + "\n" + wbody = wbody + "USER=root\n" + wbody = wbody + "MAXCONN=" + args['maxconn'] + "\n" + wbody = wbody + "CACHESIZE=" + args['maxconn'] + "\n" + wbody = wbody + "OPTIONS=''\n" + mw.writeFile(envFile, wbody) + + restart() + return 'save ok' + + +def initdStatus(): + if mw.isAppleSystem(): + return "Apple Computer does not support" + + shell_cmd = 'systemctl status ' + \ + getPluginName() + ' | grep loaded | grep "enabled;"' + data = mw.execShell(shell_cmd) + if data[0] == '': + return 'fail' + return 'ok' + + +def initdInstall(): + if mw.isAppleSystem(): + return "Apple Computer does not support" + + mw.execShell('systemctl enable ' + getPluginName()) + return 'ok' + + +def initdUinstall(): + if not app_debug: + if mw.isAppleSystem(): + return "Apple Computer does not support" + + mw.execShell('systemctl disable ' + getPluginName()) + return 'ok' + +if __name__ == "__main__": + func = sys.argv[1] + if func == 'status': + print(status()) + elif func == 'start': + print(start()) + elif func == 'stop': + print(stop()) + elif func == 'restart': + print(restart()) + elif func == 'reload': + print(reload()) + elif func == 'initd_status': + print(initdStatus()) + elif func == 'initd_install': + print(initdInstall()) + elif func == 'initd_uninstall': + print(initdUinstall()) + elif func == 'run_info': + print(runInfo()) + elif func == 'conf_env': + print(getConfEnv()) + elif func == 'save_conf': + print(saveConf()) + else: + print('error') diff --git a/plugins/migration_api/info.json b/plugins/migration_api/info.json new file mode 100755 index 000000000..9d6a94b4b --- /dev/null +++ b/plugins/migration_api/info.json @@ -0,0 +1,18 @@ +{ + "sort": 7, + "ps": "一键迁移", + "name": "migration_api", + "title": "一键迁移", + "shell": "install.sh", + "versions":["1.0"], + "updates":["1.0"], + "tip": "soft", + "checks": "server/migration_api", + "path":"server/migration_api", + "display": 1, + "author": "midoks", + "date": "2022-01-17", + "home": "https://github.com/midoks/mdserver-web", + "type": 0, + "pid": "4" +} \ No newline at end of file diff --git a/plugins/migration_api/install.sh b/plugins/migration_api/install.sh new file mode 100755 index 000000000..9a1ad2098 --- /dev/null +++ b/plugins/migration_api/install.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin +export PATH + +curPath=`pwd` +rootPath=$(dirname "$curPath") +rootPath=$(dirname "$rootPath") +serverPath=$(dirname "$rootPath") + +install_tmp=${rootPath}/tmp/mw_install.pl + +VERSION=1.0 + +Install_App(){ + mkdir -p $serverPath/migration_api + echo "${VERSION}" > $serverPath/migration_api/version.pl + echo '正在安装脚本文件...' > $install_tmp +} + +Uninstall_App() +{ + rm -rf $serverPath/migration_api +} + +action=$1 +if [ "${1}" == 'install' ];then + Install_App +else + Uninstall_App +fi diff --git a/plugins/migration_api/js/app.js b/plugins/migration_api/js/app.js new file mode 100755 index 000000000..c28750855 --- /dev/null +++ b/plugins/migration_api/js/app.js @@ -0,0 +1,58 @@ +function maPost(method,args,callback){ + var _args = null; + if (typeof(args) == 'string'){ + _args = JSON.stringify(toArrayObject(args)); + } else { + _args = JSON.stringify(args); + } + + var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 }); + $.post('/plugins/run', {name:'migration_api', func:method, args:_args}, function(data) { + layer.close(loadT); + if (!data.status){ + layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']}); + return; + } + + if(typeof(callback) == 'function'){ + callback(data); + } + },'json'); +} + +function maAsyncPost(method,args){ + var _args = null; + if (typeof(args) == 'string'){ + _args = JSON.stringify(toArrayObject(args)); + } else { + _args = JSON.stringify(args); + } + return syncPost('/plugins/run', {name:'migration_api', func:method, args:_args}); +} + +function maPostCallbak(method, args, callback){ + var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 }); + + var req_data = {}; + req_data['name'] = 'migration_api'; + req_data['func'] = method; + args['version'] = '1.0'; + + if (typeof(args) == 'string'){ + req_data['args'] = JSON.stringify(toArrayObject(args)); + } else { + req_data['args'] = JSON.stringify(args); + } + + $.post('/plugins/callback', req_data, function(data) { + layer.close(loadT); + if (!data.status){ + layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']}); + return; + } + + if(typeof(callback) == 'function'){ + callback(data); + } + },'json'); +}