mirror of https://github.com/tp4a/teleport
Merge branch 'feature/upgrade-db' into dev
commit
2414d143ff
|
@ -1060,6 +1060,8 @@ def disk_io_counters(perdisk=False):
|
|||
# ...unless (Linux 2.6) the line refers to a partition instead
|
||||
# of a disk, in which case the line has less fields (7):
|
||||
# "3 1 hda1 8 8 8 8"
|
||||
# 4.18+ has 4 fields added:
|
||||
# "3 0 hda 8 8 8 8 8 8 8 8 8 8 8 0 0 0 0"
|
||||
# See:
|
||||
# https://www.kernel.org/doc/Documentation/iostats.txt
|
||||
# https://www.kernel.org/doc/Documentation/ABI/testing/procfs-diskstats
|
||||
|
@ -1074,7 +1076,7 @@ def disk_io_counters(perdisk=False):
|
|||
reads = int(fields[2])
|
||||
(reads_merged, rbytes, rtime, writes, writes_merged,
|
||||
wbytes, wtime, _, busy_time, _) = map(int, fields[4:14])
|
||||
elif flen == 14:
|
||||
elif flen == 14 or flen == 18:
|
||||
# Linux 2.6+, line referring to a disk
|
||||
name = fields[2]
|
||||
(reads, reads_merged, rbytes, rtime, writes, writes_merged,
|
||||
|
|
|
@ -0,0 +1,317 @@
|
|||
"use strict";
|
||||
|
||||
$app.on_init = function (cb_stack, cb_args) {
|
||||
$app.dom = {
|
||||
btn_upgrade: $('#btn-upgrade'),
|
||||
steps_detail: $('#steps-detail'),
|
||||
// db_info: $('#db-info'),
|
||||
// account: $('#sysadmin-account'),
|
||||
// email: $('#sysadmin-email'),
|
||||
// password: $('#password'),
|
||||
// password2: $('#password-again'),
|
||||
message: $('#message'),
|
||||
step2: $('#step2')
|
||||
};
|
||||
|
||||
$app._make_info = function (key, value) {
|
||||
return '<tr><td class="key">' + key + ':</td><td class="value">' + value + '</td></tr>';
|
||||
};
|
||||
|
||||
// var html = [];
|
||||
// if ($app.options.db.type === DB_TYPE_SQLITE) {
|
||||
// html.push($app._make_info('数据库类型', 'SQLite'));
|
||||
// html.push($app._make_info('数据库文件', $app.options.db.sqlite_file));
|
||||
// } else if ($app.options.db.type === DB_TYPE_MYSQL) {
|
||||
// html.push($app._make_info('数据库类型', 'MySQL'));
|
||||
// html.push($app._make_info('MySQL主机', $app.options.db.mysql_host));
|
||||
// html.push($app._make_info('MySQL端口', $app.options.db.mysql_port));
|
||||
// html.push($app._make_info('数据库名称', $app.options.db.mysql_db));
|
||||
// html.push($app._make_info('用户名', $app.options.db.mysql_user));
|
||||
//
|
||||
// var _t = [];
|
||||
// _t.push('<div class="alert alert-warning">');
|
||||
// _t.push('<i class="fas fa-exclamation-triangle"></i> 注意:请确保您在执行后续创建操作之前,已经在MySQL中使用 <span class="bold">UTF8字符集</span> 创建了库“');
|
||||
// _t.push($app.options.db.mysql_db);
|
||||
// _t.push('”,并且用户“');
|
||||
// _t.push($app.options.db.mysql_user);
|
||||
// _t.push('”拥有在此库创建表的权限!');
|
||||
// _t.push('</div>');
|
||||
// $app.dom.db_info.after(_t.join(''));
|
||||
// } else {
|
||||
// html.push($app._make_info('数据库类型', '<span class="error">未知的数据库类型,请检查您的配置文件!</span>'));
|
||||
// $app.dom.btn_upgrade.attr('disabled', 'disabled').hide();
|
||||
// }
|
||||
// $app.dom.db_info.append(html.join(''));
|
||||
|
||||
$app.hide_op_box = function () {
|
||||
$app.dom.message.hide();
|
||||
};
|
||||
|
||||
$app.show_op_box = function (op_type, op_msg) {
|
||||
$app.dom.message.html(op_msg);
|
||||
$app.dom.message.removeClass().addClass('op_box op_' + op_type);
|
||||
$app.dom.message.show();
|
||||
};
|
||||
|
||||
$app.dom.btn_upgrade.click(function () {
|
||||
// var str_account = $app.dom.account.val();
|
||||
// var str_email = $app.dom.email.val();
|
||||
// var str_password = $app.dom.password.val();
|
||||
// var str_password2 = $app.dom.password2.val();
|
||||
//
|
||||
// if (str_account.length === 0) {
|
||||
// $app.show_op_box('error', '请填写系统管理员登录账号名称!');
|
||||
// $app.dom.account.focus();
|
||||
// return;
|
||||
// }
|
||||
// if (str_email.length === 0) {
|
||||
// $app.show_op_box('error', '请填写系统管理员的电子邮件地址!');
|
||||
// $app.dom.email.focus();
|
||||
// return;
|
||||
// }
|
||||
// if (!tp_is_email(str_email)) {
|
||||
// $app.show_op_box('error', '电子邮件地址格式错啦,你会收不到邮件的!');
|
||||
// $app.dom.email.focus();
|
||||
// return;
|
||||
// }
|
||||
// if (str_password.length === 0) {
|
||||
// $app.show_op_box('error', '请设置系统管理员登录密码!');
|
||||
// $app.dom.password.focus();
|
||||
// return;
|
||||
// }
|
||||
// if (str_password2.length === 0) {
|
||||
// $app.show_op_box('error', '请再次输入系统管理员登录密码!');
|
||||
// $app.dom.password.focus();
|
||||
// return;
|
||||
// }
|
||||
// if (str_password !== str_password2) {
|
||||
// $app.show_op_box('error', '两次输入的密码不一致!');
|
||||
// $app.dom.password2.focus().select();
|
||||
// return;
|
||||
// }
|
||||
|
||||
$app.dom.btn_upgrade.attr('disabled', 'disabled').hide();
|
||||
$app.hide_op_box();
|
||||
$app.dom.steps_detail.show();
|
||||
|
||||
$tp.ajax_post_json('/maintenance/rpc', {cmd: 'upgrade_db'},
|
||||
function (ret) {
|
||||
if (ret.code === TPE_OK) {
|
||||
|
||||
var cb_stack = CALLBACK_STACK.create();
|
||||
cb_stack
|
||||
.add_delay(500, $app.get_task_ret, {task_id: ret.data.task_id})
|
||||
.exec();
|
||||
}
|
||||
|
||||
},
|
||||
function () {
|
||||
// $app.show_message('error', '无法连接到服务器!');
|
||||
$app.show_op_box('error', '无法连接到服务器!');
|
||||
}
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
$app.get_task_ret = function (cb_stack, cb_args) {
|
||||
var task_id = cb_args.task_id || 0;
|
||||
if (task_id === 0) {
|
||||
console.log('task-id', task_id);
|
||||
return;
|
||||
}
|
||||
|
||||
$tp.ajax_post_json('/maintenance/rpc', {cmd: 'get_task_ret', 'tid': task_id},
|
||||
function (ret) {
|
||||
if (ret.code === TPE_OK) {
|
||||
|
||||
// show step progress.
|
||||
var all_ok = true;
|
||||
var steps = ret.data.steps;
|
||||
$app.dom.steps_detail.empty();
|
||||
|
||||
var html = [];
|
||||
var icon_class = '';
|
||||
var err_class = '';
|
||||
for (var i = 0; i < steps.length; ++i) {
|
||||
if (steps[i].stat === 0)
|
||||
icon_class = 'fa-check';
|
||||
else
|
||||
icon_class = 'fa-cog fa-spin';
|
||||
|
||||
if (steps[i].code !== 0) {
|
||||
icon_class = 'fa-exclamation-circle';
|
||||
err_class = ' class="error"';
|
||||
steps[i].msg += ' 失败!';
|
||||
all_ok = false;
|
||||
}
|
||||
else {
|
||||
err_class = '';
|
||||
}
|
||||
|
||||
html.push('<p');
|
||||
html.push(err_class);
|
||||
html.push('><i class="fa ');
|
||||
html.push(icon_class);
|
||||
html.push('"></i> ');
|
||||
html.push(steps[i].msg);
|
||||
html.push('</p>')
|
||||
}
|
||||
$app.dom.steps_detail.html(html.join(''));
|
||||
$('html').animate({scrollTop: $(document).height()}, 300);
|
||||
|
||||
if (!ret.data.running) {
|
||||
if (all_ok) {
|
||||
|
||||
$tp.ajax_post_json('/auth/do-logout', {},
|
||||
function () {
|
||||
},
|
||||
function () {
|
||||
}
|
||||
);
|
||||
|
||||
$app.dom.step2.show('fast', function () {
|
||||
// 确保页面滚动到最低端,使得下一步提示能够被看到。
|
||||
$('html').animate({scrollTop: $(document).height()}, 300);
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
cb_stack
|
||||
.add_delay(500, $app.get_task_ret, {task_id: task_id})
|
||||
.exec();
|
||||
}
|
||||
|
||||
},
|
||||
function () {
|
||||
$app.show_op_box('error', '无法连接到服务器!');
|
||||
}
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
cb_stack.exec();
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ywl.on_init = function (cb_stack, cb_args) {
|
||||
ywl.dom = {
|
||||
btn_upgrade_db: $('#btn-upgrade-db'),
|
||||
steps_detail: $('#steps-detail')
|
||||
};
|
||||
|
||||
ywl.dom.btn_upgrade_db.click(function () {
|
||||
|
||||
ywl.dom.btn_upgrade_db.attr('disabled', 'disabled').hide();
|
||||
ywl.dom.steps_detail.show();
|
||||
|
||||
console.log('upgrade-db-click');
|
||||
ywl.ajax_post_json('/maintenance/rpc', {cmd: 'upgrade_db'},
|
||||
function (ret) {
|
||||
console.log('upgrade-db:', ret);
|
||||
if (ret.code === 0) {
|
||||
|
||||
var cb_stack = CALLBACK_STACK.create();
|
||||
cb_stack
|
||||
.add(ywl.get_task_ret, {task_id: ret.data.task_id})
|
||||
.add(ywl.delay_exec, {delay_ms: 500})
|
||||
.exec();
|
||||
}
|
||||
|
||||
},
|
||||
function () {
|
||||
ywl.show_message('error', '无法连接到服务器!');
|
||||
}
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
ywl.get_task_ret = function (cb_stack, cb_args) {
|
||||
var task_id = cb_args.task_id || 0;
|
||||
if (task_id === 0) {
|
||||
console.log('task-id', task_id);
|
||||
return;
|
||||
}
|
||||
|
||||
ywl.ajax_post_json('/maintenance/rpc', {cmd: 'get_task_ret', 'tid': task_id},
|
||||
function (ret) {
|
||||
console.log('get_task_ret:', ret);
|
||||
if (ret.code === 0) {
|
||||
|
||||
// show step progress.
|
||||
var steps = ret.data.steps;
|
||||
ywl.dom.steps_detail.empty();
|
||||
|
||||
var html = [];
|
||||
var icon_class = '';
|
||||
var err_class = '';
|
||||
for(var i = 0; i < steps.length; ++i) {
|
||||
if(steps[i].code !== 0) {
|
||||
err_class = ' class="error"';
|
||||
icon_class = 'fa-times-circle';
|
||||
}
|
||||
else {
|
||||
err_class = '';
|
||||
icon_class = 'fa-check';
|
||||
}
|
||||
|
||||
if(steps[i].stat === 0)
|
||||
;//icon_class = 'fa-check';
|
||||
else
|
||||
icon_class = 'fa-cog fa-spin';
|
||||
|
||||
html.push('<p');
|
||||
html.push(err_class);
|
||||
html.push('><i class="fa ');
|
||||
html.push(icon_class);
|
||||
html.push('"></i> ');
|
||||
html.push(steps[i].msg);
|
||||
html.push('</p>')
|
||||
}
|
||||
ywl.dom.steps_detail.html(html.join(''));
|
||||
|
||||
|
||||
if (!ret.data.running) {
|
||||
$('#step2').show('fast');
|
||||
return;
|
||||
}
|
||||
|
||||
cb_stack
|
||||
.add(ywl.get_task_ret, {task_id: task_id})
|
||||
.add(ywl.delay_exec, {delay_ms: 500})
|
||||
.exec();
|
||||
}
|
||||
|
||||
},
|
||||
function () {
|
||||
ywl.show_message('error', '无法连接到服务器!');
|
||||
}
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
cb_stack.exec();
|
||||
};
|
|
@ -1,180 +1,43 @@
|
|||
<%!
|
||||
import app.app_ver as app_ver
|
||||
page_title_ = '升级TELEPORT服务'
|
||||
%>
|
||||
<%inherit file="../page_maintenance_base.mako"/>
|
||||
|
||||
<%block name="breadcrumb">
|
||||
<%inherit file="../page_single_base.mako"/>
|
||||
|
||||
<%block name="extend_js_file">
|
||||
<script type="text/javascript" src="${ static_url('js/maintenance/upgrade.js') }"></script>
|
||||
</%block>
|
||||
|
||||
<%block name="page_header">
|
||||
<div class="container-fluid top-navbar">
|
||||
<div class="brand"><a href="/" target="_blank"><span class="site-logo"></span></a></div>
|
||||
<div class="breadcrumb-container">
|
||||
<ol class="breadcrumb">
|
||||
<li><i class="fa fa-cog fa-fw"></i> ${self.attr.page_title_}</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</%block>
|
||||
|
||||
<%block name="embed_css">
|
||||
<style type="text/css">
|
||||
.container {
|
||||
background-color: #fff;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 200%;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 160%;
|
||||
}
|
||||
.steps-detail {
|
||||
display: none;
|
||||
margin:10px;
|
||||
padding:10px;
|
||||
border:1px solid #b4b4b4;
|
||||
background-color: #dcdcdc;
|
||||
}
|
||||
.steps-detail p {
|
||||
padding-left:5px;
|
||||
margin:2px 0 2px 1px;
|
||||
}
|
||||
.steps-detail p.error {
|
||||
color:#ffffff;
|
||||
margin:2px 0 2px 0;
|
||||
background-color: #cc3632;
|
||||
border:1px solid #9c2a26;
|
||||
}
|
||||
</style>
|
||||
</%block>
|
||||
|
||||
## Begin Main Body.
|
||||
|
||||
<div class="page-content">
|
||||
<div class="content-box">
|
||||
<p class="welcome-message"><i class="fa fa-heart"></i> <span>欢迎升级到 TELEPORT v${app_ver.TP_SERVER_VER} 社区版!现在还剩下一点点操作需要执行!</span></p>
|
||||
|
||||
<div class="content_box">
|
||||
<div class="container">
|
||||
|
||||
<h1>升级TELEPORT服务</h1>
|
||||
<hr/>
|
||||
|
||||
<h2>第一步:升级数据库</h2>
|
||||
<div>
|
||||
<div>
|
||||
<button id="btn-upgrade-db" type="button" class="btn btn-primary"><i class="fa fa-wrench fa-fw"></i> 开始升级</button>
|
||||
</div>
|
||||
<h2><i class="fa fa-chevron-right"></i> 第一步:升级数据库</h2>
|
||||
<button id="btn-upgrade" type="button" class="btn btn-primary"><i class="fa fa-wrench fa-fw"></i> 执行</button>
|
||||
|
||||
<div id="steps-detail" class="steps-detail"></div>
|
||||
</div>
|
||||
<div><p id="message" class="op_box" style="display:none;"></p></div>
|
||||
|
||||
|
||||
<div id="step2" style="display:none;">
|
||||
<hr/>
|
||||
<h2>已完成!</h2>
|
||||
<p>是的,没有第二步了,升级操作已经完成了!刷新页面即可进入Teleport主界面啦~~</p>
|
||||
<h2><i class="fa fa-chevron-right"></i> 已完成!</h2>
|
||||
<p>是的,没有第二步啦,升级已经完成!刷新页面即可登录 TELEPORT 啦~~</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<%block name="embed_js">
|
||||
<script type="text/javascript">
|
||||
"use strict";
|
||||
|
||||
ywl.on_init = function (cb_stack, cb_args) {
|
||||
ywl.dom = {
|
||||
btn_upgrade_db: $('#btn-upgrade-db'),
|
||||
steps_detail: $('#steps-detail')
|
||||
};
|
||||
|
||||
ywl.dom.btn_upgrade_db.click(function () {
|
||||
|
||||
ywl.dom.btn_upgrade_db.attr('disabled', 'disabled').hide();
|
||||
ywl.dom.steps_detail.show();
|
||||
|
||||
console.log('upgrade-db-click');
|
||||
ywl.ajax_post_json('/maintenance/rpc', {cmd: 'upgrade_db'},
|
||||
function (ret) {
|
||||
console.log('upgrade-db:', ret);
|
||||
if (ret.code === 0) {
|
||||
|
||||
var cb_stack = CALLBACK_STACK.create();
|
||||
cb_stack
|
||||
.add(ywl.get_task_ret, {task_id: ret.data.task_id})
|
||||
.add(ywl.delay_exec, {delay_ms: 500})
|
||||
.exec();
|
||||
}
|
||||
|
||||
},
|
||||
function () {
|
||||
ywl.show_message('error', '无法连接到服务器!');
|
||||
}
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
ywl.get_task_ret = function (cb_stack, cb_args) {
|
||||
var task_id = cb_args.task_id || 0;
|
||||
if (task_id === 0) {
|
||||
console.log('task-id', task_id);
|
||||
return;
|
||||
}
|
||||
|
||||
ywl.ajax_post_json('/maintenance/rpc', {cmd: 'get_task_ret', 'tid': task_id},
|
||||
function (ret) {
|
||||
console.log('get_task_ret:', ret);
|
||||
if (ret.code === 0) {
|
||||
|
||||
// show step progress.
|
||||
var steps = ret.data.steps;
|
||||
ywl.dom.steps_detail.empty();
|
||||
|
||||
var html = [];
|
||||
var icon_class = '';
|
||||
var err_class = '';
|
||||
for(var i = 0; i < steps.length; ++i) {
|
||||
if(steps[i].code !== 0) {
|
||||
err_class = ' class="error"';
|
||||
icon_class = 'fa-times-circle';
|
||||
}
|
||||
else {
|
||||
err_class = '';
|
||||
icon_class = 'fa-check';
|
||||
}
|
||||
|
||||
if(steps[i].stat === 0)
|
||||
;//icon_class = 'fa-check';
|
||||
else
|
||||
icon_class = 'fa-cog fa-spin';
|
||||
|
||||
html.push('<p');
|
||||
html.push(err_class);
|
||||
html.push('><i class="fa ');
|
||||
html.push(icon_class);
|
||||
html.push('"></i> ');
|
||||
html.push(steps[i].msg);
|
||||
html.push('</p>')
|
||||
}
|
||||
ywl.dom.steps_detail.html(html.join(''));
|
||||
|
||||
|
||||
if (!ret.data.running) {
|
||||
$('#step2').show('fast');
|
||||
return;
|
||||
}
|
||||
|
||||
cb_stack
|
||||
.add(ywl.get_task_ret, {task_id: task_id})
|
||||
.add(ywl.delay_exec, {delay_ms: 500})
|
||||
.exec();
|
||||
}
|
||||
|
||||
},
|
||||
function () {
|
||||
ywl.show_message('error', '无法连接到服务器!');
|
||||
}
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
cb_stack.exec();
|
||||
};
|
||||
</script>
|
||||
</%block>
|
||||
|
|
|
@ -82,6 +82,7 @@ class DatabaseInit:
|
|||
|
||||
def _create_core_server(self):
|
||||
""" 核心服务(为分布式准备)
|
||||
v7 新增
|
||||
特别注意:分布式部署时,核心服务的RPC通讯端口仅允许来自web服务的IP访问
|
||||
"""
|
||||
|
||||
|
@ -152,7 +153,7 @@ class DatabaseInit:
|
|||
f.append('`surname` varchar(64) DEFAULT ""')
|
||||
# type 1=本地账号,2=LDAP(待扩展)
|
||||
f.append('`type` int(11) DEFAULT 1')
|
||||
# ldap_dn: 用户的ldap全路径名称,仅用于LDAP导入的用户
|
||||
# ldap_dn: 用户的ldap全路径名称,仅用于LDAP导入的用户(v7版新增)
|
||||
f.append('`ldap_dn` varchar(128) DEFAULT ""')
|
||||
# avatar: 用户头像图片地址
|
||||
f.append('`avatar` varchar(64) DEFAULT ""')
|
||||
|
@ -186,6 +187,11 @@ class DatabaseInit:
|
|||
# last_ip: 最近一次成功登录IP
|
||||
f.append('`last_ip` varchar(40) DEFAULT ""')
|
||||
|
||||
# valid_from: 有效期起始时间,为0则不限(v7版新增)
|
||||
f.append('`valid_from` int(11) DEFAULT 0')
|
||||
# valid_to: 有效期终止时间,为0则不限(v7版新增)
|
||||
f.append('`valid_to` int(11) DEFAULT 0')
|
||||
|
||||
# creator_id: 创建者的用户id,0=系统默认创建
|
||||
f.append('`creator_id` int(11) DEFAULT 0')
|
||||
# create_time: 创建时间
|
||||
|
@ -321,11 +327,11 @@ class DatabaseInit:
|
|||
|
||||
# 下面三个主机相关字段用于显示(注意更新host表时同步更新此字段)
|
||||
|
||||
# host_ip: 主机IP地址
|
||||
# host_ip: 主机IP地址(v7版新增)
|
||||
f.append('`host_ip` varchar(40) NOT NULL')
|
||||
# router_ip: 路由IP
|
||||
# router_ip: 路由IP(v7版新增)
|
||||
f.append('`router_ip` varchar(40) DEFAULT ""')
|
||||
# router_port: 路由端口
|
||||
# router_port: 路由端口(v7版新增)
|
||||
f.append('`router_port` int(11) DEFAULT 0')
|
||||
|
||||
# protocol_type: 协议类型,0=?,1=SSH,2=RDP,3=TELNET
|
||||
|
@ -737,13 +743,13 @@ class DatabaseInit:
|
|||
# id: 自增主键
|
||||
f.append('`id` integer PRIMARY KEY {}'.format(self.db.auto_increment))
|
||||
|
||||
# core_uuid:
|
||||
# core_sn:(v7版新增)
|
||||
f.append('`core_sn` varchar(5) DEFAULT "0000"')
|
||||
|
||||
# flag: 是否已审查/是否要永久保留,异或方式设置,0=初始,1=已审查,2=要永久保留
|
||||
f.append('`flag` int(11) DEFAULT 0')
|
||||
|
||||
# reason: 本次运维的原因
|
||||
# reason: 本次运维的原因(v7版新增)
|
||||
f.append('`reason` varchar(255) DEFAULT ""')
|
||||
|
||||
# sid: 会话ID
|
||||
|
|
|
@ -0,0 +1,223 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# from app.const import *
|
||||
# from app.logic.auth.password import tp_password_generate_secret
|
||||
# from app.base.utils import tp_timestamp_utc_now
|
||||
from app.base.logger import log
|
||||
# import shutil
|
||||
|
||||
|
||||
class DatabaseUpgrade:
|
||||
def __init__(self, db, step_begin, step_end):
|
||||
self.db = db
|
||||
self.step_begin = step_begin
|
||||
self.step_end = step_end
|
||||
|
||||
def do_upgrade(self):
|
||||
for i in range(self.db.DB_VERSION):
|
||||
if self.db.current_ver < i + 1:
|
||||
_f_name = '_upgrade_to_v{}'.format(i + 1)
|
||||
if _f_name in dir(self):
|
||||
if self.__getattribute__(_f_name)():
|
||||
self.db.current_ver = i + 1
|
||||
else:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def _db_exec(self, msg, sql):
|
||||
_step = self.step_begin(msg)
|
||||
|
||||
ret = False
|
||||
if type(sql) == str:
|
||||
ret = self.db.exec(sql)
|
||||
elif type(sql) == list or type(sql) == set:
|
||||
for s in sql:
|
||||
ret = self.db.exec(s)
|
||||
if not ret:
|
||||
break
|
||||
else:
|
||||
raise RuntimeError('[FAILED] internal error.')
|
||||
|
||||
if not ret:
|
||||
self.step_end(_step, -1)
|
||||
raise RuntimeError('[FAILED] {}'.format(sql))
|
||||
else:
|
||||
self.step_end(_step, 0)
|
||||
|
||||
def _upgrade_to_v7(self):
|
||||
# 注意:v2.x的最后版本时,数据库版本号为v6,但是v3.0.0技术预览版未升级数据库版本号,仍然为v6
|
||||
# 因此升级时要做检查,如果是当前数据库版本号为v6,要进一步判断是否为v2.x系列的数据库。
|
||||
# 服务端升级到v3.2.2时,数据库有部分调整
|
||||
_step = self.step_begin('检查数据库版本 v7...')
|
||||
|
||||
try:
|
||||
# 检查是否是 v2.x 版本的数据库(也是v6版数据库)
|
||||
# 依据为,v3.x的服务端开始,数据库中有 tp_role 数据表。
|
||||
ret = self.db.is_table_exists('{}role'.format(self.db.table_prefix))
|
||||
if ret is None:
|
||||
self.step_end(_step, -1, '无法连接到数据库')
|
||||
return False
|
||||
elif not ret:
|
||||
self.step_end(_step, -1, '抱歉,不支持从v2.x升级到v3.x,数据库不兼容!请卸载旧版本,全新安装新版本!')
|
||||
return True
|
||||
except:
|
||||
log.e('failed.\n')
|
||||
self.step_end(_step, -1)
|
||||
return False
|
||||
|
||||
self.step_end(_step, 0, '需要升级')
|
||||
|
||||
try:
|
||||
# 1. 创建缺失的 core_server 表
|
||||
_step = self.step_begin(' - 检查 core_server 数据表...')
|
||||
ret = self.db.is_table_exists('{}core_server'.format(self.db.table_prefix))
|
||||
if ret is None:
|
||||
self.step_end(_step, -1, '无法连接到数据库')
|
||||
return False
|
||||
elif not ret:
|
||||
_step = self.step_begin(' - 创建数据表 core_server...')
|
||||
self._v7_create_core_server()
|
||||
self._db_exec(
|
||||
' - 设置本机核心服务配置项...',
|
||||
'INSERT INTO `{}core_server` (`sn`, `secret`, `ip`, `port`, `state`) VALUES '
|
||||
'("0000", "", "127.0.0.1", 52080, 1);'
|
||||
''.format(self.db.table_prefix)
|
||||
)
|
||||
self.step_end(_step, 0)
|
||||
|
||||
# 2. 检查 user 表中是否有 ldap_dn/valid_from/valid_to 字段
|
||||
_step = self.step_begin(' - 检查 user 数据表 ldap_dn 字段...')
|
||||
ret = self.db.is_field_exists('{}user'.format(self.db.table_prefix), 'ldap_dn')
|
||||
if ret is None:
|
||||
self.step_end(_step, -1, '无法连接到数据库')
|
||||
return False
|
||||
elif not ret:
|
||||
if not self.db.exec('ALTER TABLE `{}user` ADD `ldap_dn` VARCHAR(128) DEFAULT ""'.format(self.db.table_prefix)):
|
||||
self.step_end(_step, -1, '失败')
|
||||
return False
|
||||
else:
|
||||
self.step_end(_step, 0)
|
||||
|
||||
_step = self.step_begin(' - 检查 user 数据表 valid_from 字段...')
|
||||
ret = self.db.is_field_exists('{}user'.format(self.db.table_prefix), 'valid_from')
|
||||
if ret is None:
|
||||
self.step_end(_step, -1, '无法连接到数据库')
|
||||
return False
|
||||
elif not ret:
|
||||
if not self.db.exec('ALTER TABLE `{}user` ADD `valid_from` INT(11) DEFAULT 0'.format(self.db.table_prefix)):
|
||||
self.step_end(_step, -1, '失败')
|
||||
return False
|
||||
else:
|
||||
self.step_end(_step, 0)
|
||||
|
||||
_step = self.step_begin(' - 检查 user 数据表 valid_to 字段...')
|
||||
ret = self.db.is_field_exists('{}user'.format(self.db.table_prefix), 'valid_to')
|
||||
if ret is None:
|
||||
self.step_end(_step, -1, '无法连接到数据库')
|
||||
return False
|
||||
elif not ret:
|
||||
if not self.db.exec('ALTER TABLE `{}user` ADD `valid_to` INT(11) DEFAULT 0'.format(self.db.table_prefix)):
|
||||
self.step_end(_step, -1, '失败')
|
||||
return False
|
||||
else:
|
||||
self.step_end(_step, 0)
|
||||
|
||||
# 3. 检查 acc 表中是否有 host_ip/router_ip/router_port 字段
|
||||
_step = self.step_begin(' - 检查 acc 数据表 host_ip 字段...')
|
||||
ret = self.db.is_field_exists('{}acc'.format(self.db.table_prefix), 'host_ip')
|
||||
if ret is None:
|
||||
self.step_end(_step, -1, '无法连接到数据库')
|
||||
return False
|
||||
elif not ret:
|
||||
if not self.db.exec('ALTER TABLE `{}acc` ADD `host_ip` VARCHAR(40) DEFAULT ""'.format(self.db.table_prefix)):
|
||||
self.step_end(_step, -1, '失败')
|
||||
return False
|
||||
self.step_end(_step, 0)
|
||||
|
||||
_step = self.step_begin(' - 检查 acc 数据表 router_ip 字段...')
|
||||
ret = self.db.is_field_exists('{}acc'.format(self.db.table_prefix), 'router_ip')
|
||||
if ret is None:
|
||||
self.step_end(_step, -1, '无法连接到数据库')
|
||||
return False
|
||||
elif not ret:
|
||||
if not self.db.exec('ALTER TABLE `{}acc` ADD `router_ip` VARCHAR(40) DEFAULT ""'.format(self.db.table_prefix)):
|
||||
self.step_end(_step, -1, '失败')
|
||||
return False
|
||||
self.step_end(_step, 0)
|
||||
|
||||
_step = self.step_begin(' - 检查 acc 数据表 router_port 字段...')
|
||||
ret = self.db.is_field_exists('{}acc'.format(self.db.table_prefix), 'router_port')
|
||||
if ret is None:
|
||||
self.step_end(_step, -1, '无法连接到数据库')
|
||||
return False
|
||||
elif not ret:
|
||||
if not self.db.exec('ALTER TABLE `{}acc` ADD `router_port` INT(11) DEFAULT 0'.format(self.db.table_prefix)):
|
||||
self.step_end(_step, -1, '失败')
|
||||
return False
|
||||
self.step_end(_step, 0)
|
||||
|
||||
# 4. 检查 record 表中是否有 core_sn/reason 字段
|
||||
_step = self.step_begin(' - 检查 record 数据表 core_sn 字段...')
|
||||
ret = self.db.is_field_exists('{}record'.format(self.db.table_prefix), 'core_sn')
|
||||
if ret is None:
|
||||
self.step_end(_step, -1, '无法连接到数据库')
|
||||
return False
|
||||
elif not ret:
|
||||
if not self.db.exec('ALTER TABLE `{}record` ADD `core_sn` VARCHAR(5) DEFAULT "0000"'.format(self.db.table_prefix)):
|
||||
self.step_end(_step, -1, '失败')
|
||||
return False
|
||||
self.step_end(_step, 0)
|
||||
|
||||
_step = self.step_begin(' - 检查 record 数据表 reason 字段...')
|
||||
ret = self.db.is_field_exists('{}record'.format(self.db.table_prefix), 'reason')
|
||||
if ret is None:
|
||||
self.step_end(_step, -1, '无法连接到数据库')
|
||||
return False
|
||||
elif not ret:
|
||||
if not self.db.exec('ALTER TABLE `{}record` ADD `reason` VARCHAR(255) DEFAULT ""'.format(self.db.table_prefix)):
|
||||
self.step_end(_step, -1, '失败')
|
||||
return False
|
||||
self.step_end(_step, 0)
|
||||
|
||||
_step = self.step_begin(' - 更新数据库版本号...')
|
||||
if not self.db.exec('UPDATE `{}config` SET `value`="7" WHERE `name`="db_ver";'.format(self.db.table_prefix)):
|
||||
self.step_end(_step, -1, '无法更新数据库版本号')
|
||||
return False
|
||||
self.step_end(_step, 0)
|
||||
|
||||
_step = self.step_begin('升级到 v7 完成')
|
||||
self.step_end(_step, 0)
|
||||
|
||||
return True
|
||||
|
||||
except:
|
||||
log.e('failed.\n')
|
||||
self.step_end(_step, -1)
|
||||
return False
|
||||
|
||||
def _v7_create_core_server(self):
|
||||
""" 核心服务(为分布式准备)
|
||||
v7 新增
|
||||
特别注意:分布式部署时,核心服务的RPC通讯端口仅允许来自web服务的IP访问
|
||||
"""
|
||||
|
||||
f = list()
|
||||
|
||||
# id: 自增主键
|
||||
f.append('`id` integer PRIMARY KEY {}'.format(self.db.auto_increment))
|
||||
# sn: 核心服务主机编号(4位数字构成的字符串,全0表示运行在与web服务同一台主机上)
|
||||
f.append('`sn` varchar(5) NOT NULL')
|
||||
# desc: 核心服务主机描述
|
||||
f.append('`desc` varchar(255) DEFAULT ""')
|
||||
# secret: 核心服务主机密钥(核心服务主机需要配置此密钥才能连接web服务)
|
||||
f.append('`secret` varchar(64) DEFAULT ""')
|
||||
# ip: 核心服务主机的RPC服务IP和端口,用于合成RPC访问地址,例如 http://127.0.0.1:52080/rpc
|
||||
f.append('`ip` varchar(128) NOT NULL')
|
||||
f.append('`port` int(11) DEFAULT 0')
|
||||
# state: 状态,1=正常,2=禁用,3=离线,4=重启中,5=版本不匹配
|
||||
f.append('`state` int(3) DEFAULT 1')
|
||||
self._db_exec(
|
||||
' - 创建核心服务器表...',
|
||||
'CREATE TABLE `{}core_server` ({});'.format(self.db.table_prefix, ','.join(f))
|
||||
)
|
|
@ -12,7 +12,7 @@ from app.base.configs import tp_cfg
|
|||
from app.base.utils import AttrDict, tp_make_dir
|
||||
from app.base.logger import log
|
||||
from .database.create import DatabaseInit
|
||||
# from .database.upgrade import DatabaseUpgrade
|
||||
from .database.upgrade import DatabaseUpgrade
|
||||
from .database.export import export_database
|
||||
|
||||
__all__ = ['get_db', 'SQL']
|
||||
|
@ -23,7 +23,8 @@ __all__ = ['get_db', 'SQL']
|
|||
|
||||
class TPDatabase:
|
||||
# 注意,每次调整数据库结构,必须增加版本号,并且在升级接口中编写对应的升级操作
|
||||
DB_VERSION = 6
|
||||
# 20190123: server-v3.2.2, db-v7
|
||||
DB_VERSION = 7
|
||||
|
||||
DB_TYPE_UNKNOWN = 0
|
||||
DB_TYPE_SQLITE = 1
|
||||
|
@ -267,15 +268,15 @@ class TPDatabase:
|
|||
log.e('database create and initialize failed.\n')
|
||||
return False
|
||||
|
||||
# def upgrade_database(self, step_begin, step_end):
|
||||
# log.v('start database upgrade process.\n')
|
||||
# if DatabaseUpgrade(self, step_begin, step_end).do_upgrade():
|
||||
# log.v('database upgraded.\n')
|
||||
# self.need_upgrade = False
|
||||
# return True
|
||||
# else:
|
||||
# log.e('database upgrade failed.\n')
|
||||
# return False
|
||||
def upgrade_database(self, step_begin, step_end):
|
||||
log.v('start database upgrade process.\n')
|
||||
if DatabaseUpgrade(self, step_begin, step_end).do_upgrade():
|
||||
log.v('database upgraded.\n')
|
||||
self.need_upgrade = False
|
||||
return True
|
||||
else:
|
||||
log.e('database upgrade failed.\n')
|
||||
return False
|
||||
|
||||
def alter_table(self, table_names, field_names=None):
|
||||
"""
|
||||
|
|
|
@ -276,7 +276,7 @@ controllers = [
|
|||
# - 初始安装设置(新安装,未创建数据库时自动跳转到此页面)
|
||||
(r'/maintenance/install', maintenance.InstallHandler),
|
||||
# - 升级(数据库版本发生变化时跳转到此页面)
|
||||
# (r'/maintenance/upgrade', maintenance.UpgradeHandler),
|
||||
(r'/maintenance/upgrade', maintenance.UpgradeHandler),
|
||||
# - [json] 维护过程中页面与后台的通讯接口
|
||||
(r'/maintenance/rpc', maintenance.RpcHandler),
|
||||
|
||||
|
|
|
@ -17,8 +17,8 @@ class LoginHandler(TPBaseHandler):
|
|||
if tp_cfg().app_mode == APP_MODE_MAINTENANCE and get_db().need_create:
|
||||
_user = {
|
||||
'id': 0,
|
||||
'username': 'installer',
|
||||
'surname': '安装程序',
|
||||
'username': 'maintainer',
|
||||
'surname': '系统维护-安装',
|
||||
'role_id': 0,
|
||||
'role': '',
|
||||
'privilege': TP_PRIVILEGE_SYS_CONFIG,
|
||||
|
@ -28,6 +28,20 @@ class LoginHandler(TPBaseHandler):
|
|||
self.redirect('/maintenance/install')
|
||||
return
|
||||
|
||||
if tp_cfg().app_mode == APP_MODE_MAINTENANCE and get_db().need_upgrade:
|
||||
_user = {
|
||||
'id': 0,
|
||||
'username': 'maintainer',
|
||||
'surname': '系统维护-升级',
|
||||
'role_id': 0,
|
||||
'role': '',
|
||||
'privilege': TP_PRIVILEGE_SYS_CONFIG,
|
||||
'_is_login': True
|
||||
}
|
||||
self.set_session('user', _user)
|
||||
self.redirect('/maintenance/upgrade')
|
||||
return
|
||||
|
||||
_user = self.get_current_user()
|
||||
_ref = quote(self.get_argument('ref', '/'))
|
||||
|
||||
|
|
Loading…
Reference in New Issue