+
欢迎升级到 TELEPORT v${app_ver.TP_SERVER_VER} 社区版!现在还剩下一点点操作需要执行!
-
-
+
+
第一步:升级数据库
+
-
升级TELEPORT服务
-
+
+
-
第一步:升级数据库
-
-
-
-
-
已完成!
-
是的,没有第二步了,升级操作已经完成了!刷新页面即可进入Teleport主界面啦~~
-
-
-
+
+
+
已完成!
+
是的,没有第二步啦,升级已经完成!刷新页面即可登录 TELEPORT 啦~~
-
-
-<%block name="embed_js">
-
-%block>
diff --git a/server/www/teleport/webroot/app/base/database/create.py b/server/www/teleport/webroot/app/base/database/create.py
index 6de0e82..d24212f 100644
--- a/server/www/teleport/webroot/app/base/database/create.py
+++ b/server/www/teleport/webroot/app/base/database/create.py
@@ -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
diff --git a/server/www/teleport/webroot/app/base/database/upgrade.py b/server/www/teleport/webroot/app/base/database/upgrade.py
new file mode 100644
index 0000000..6a8a886
--- /dev/null
+++ b/server/www/teleport/webroot/app/base/database/upgrade.py
@@ -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))
+ )
diff --git a/server/www/teleport/webroot/app/base/db.py b/server/www/teleport/webroot/app/base/db.py
index 291964f..8608b21 100644
--- a/server/www/teleport/webroot/app/base/db.py
+++ b/server/www/teleport/webroot/app/base/db.py
@@ -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):
"""
diff --git a/server/www/teleport/webroot/app/controller/__init__.py b/server/www/teleport/webroot/app/controller/__init__.py
index ca48d37..d121189 100755
--- a/server/www/teleport/webroot/app/controller/__init__.py
+++ b/server/www/teleport/webroot/app/controller/__init__.py
@@ -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),
diff --git a/server/www/teleport/webroot/app/controller/auth.py b/server/www/teleport/webroot/app/controller/auth.py
index 2ca9d2a..b022dcd 100644
--- a/server/www/teleport/webroot/app/controller/auth.py
+++ b/server/www/teleport/webroot/app/controller/auth.py
@@ -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', '/'))