mysql支持功能完成,还需要对安装页面进行调整。

pull/32/head
Apex Liu 2017-05-22 02:40:45 +08:00
parent 47f86aee8e
commit 233702811e
14 changed files with 1345 additions and 1055 deletions

View File

@ -13,7 +13,7 @@
# LOG_LEVEL_ERROR 4 log error message only.
log-level=2
debug=0
debug-mode=0
; 'replay-path' define the replay file location. if not set, default location
; to $INSTDIR%/data/replay/

View File

@ -1,36 +1,52 @@
; codec: utf-8
[common]
;ip=0.0.0.0
; ip=0.0.0.0
; port listen by web server, default to 7190.
; DO NOT FORGET update common::web-server-rpc in core.ini if you modified this setting.
; port=7190
port=7190
; 'log-file' define the log file location. if not set, default location
; to $INSTDIR%/log/tpweb.log
;log-file=/var/log/teleport/tpweb.log
; log file of web server, default to /var/log/teleport/tpweb.log
; log-file=/var/log/teleport/tpweb.log
# log-level can be 0 ~ 4, default value is 2.
# LOG_LEVEL_DEBUG 0 log every-thing.
# LOG_LEVEL_VERBOSE 1 log every-thing but without debug message.
# LOG_LEVEL_INFO 2 log infomation/warning/error message.
# LOG_LEVEL_WARN 3 log warning and error message.
# LOG_LEVEL_ERROR 4 log error message only.
log-level=2
; `log-level` can be 0 ~ 4, default to 2.
; LOG_LEVEL_DEBUG 0 log every-thing.
; LOG_LEVEL_VERBOSE 1 log every-thing but without debug message.
; LOG_LEVEL_INFO 2 log information/warning/error message.
; LOG_LEVEL_WARN 3 log warning and error message.
; LOG_LEVEL_ERROR 4 log error message only.
; log-level=2
; 0/1. default to 0.
; in debug mode, log-level set to 0 and trace call stack while exception raise.
; in debug mode, `log-level` force to 0 and trace call stack when exception raised.
; debug-mode=0
debug-mode=0
; `core-server-rpc` is the rpc interface of core server.
; DO NOT FORGET update this setting if you modified rpc::bind-port in core.ini.
; core-server-rpc=http://127.0.0.1:52080/rpc
core-server-rpc=http://127.0.0.1:52080/rpc
[database]
; sqlite/mysql
type=sqlite
;sqlite-file=/var/lib/teleport/data/ts_db.db
; database in use, should be sqlite/mysql, default to sqlite.
; type=sqlite
; sqlite-file=/var/lib/teleport/data/ts_db.db
; mysql-host=127.0.0.1
; mysql-port=3306
; mysql-db=teleport
; mysql-prefix=tp_
; mysql-user=teleport
; mysql-password=password
;mysql-host=127.0.0.1
;mysql-port=3306
;mysql-db=teleport
;mysql-prefix=tp_
;mysql-user=user
;mysql-password=password

View File

@ -373,10 +373,12 @@ class AppConfig(BaseAppConfig):
def _on_init(self):
self.set_default('common::ip', '0.0.0.0', 'ip=0.0.0.0')
self.set_default('common::port', 7190, 'port=7190')
self.set_default('common::port', 7190,
'port listen by web server, default to 7190.\n'
'DO NOT FORGET update common::web-server-rpc in core.ini if you modified this setting.\n'
'port=7190')
self.set_default('common::log-file', None,
'`log-file` define the log file location. if not set, default location\n'
'to %APPROOT%/log/web.log\n'
'log file of web server, default to /var/log/teleport/tpweb.log\n'
'log-file=/var/log/teleport/tpweb.log'
)
self.set_default('common::log-level', 2,
@ -385,50 +387,117 @@ class AppConfig(BaseAppConfig):
'LOG_LEVEL_VERBOSE 1 log every-thing but without debug message.\n'
'LOG_LEVEL_INFO 2 log information/warning/error message.\n'
'LOG_LEVEL_WARN 3 log warning and error message.\n'
'LOG_LEVEL_ERROR 4 log error message only.'
'LOG_LEVEL_ERROR 4 log error message only.\n'
'log-level=2'
)
self.set_default('common::debug-mode', 0,
'default to `no`.\n'
'in debug mode, `log-level` force to 0 and trace call stack when exception raised.'
'0/1. default to 0.\n'
'in debug mode, `log-level` force to 0 and trace call stack when exception raised.\n'
'debug-mode=0'
)
self.set_default('common::core-server-rpc', 'http://127.0.0.1:52080/rpc',
'`core-server-rpc` is the rpc interface of core server.\n'
'DO NOT FORGET update this setting if you modified rpc::bind-port in core.ini.'
'DO NOT FORGET update this setting if you modified rpc::bind-port in core.ini.\n'
'core-server-rpc=http://127.0.0.1:52080/rpc'
)
self.set_default('database::type', 'sqlite',
'database in use, should be sqlite/mysql, default to sqlite.\n'
'type=sqlite'
)
self.set_default('database::sqlite-file', None,
'sqlite-file=/var/lib/teleport/data/ts_db.db'
)
# self.set_default('database::mysql-host', None,
# 'mysql-host=127.0.0.1\n'
# 'mysql-port=3306\n'
# 'mysql-db=teleport\n'
# 'mysql-prefix=tp_\n'
# 'mysql-user=teleport\n'
# 'mysql-password=password'
# )
self.set_default('database::mysql-host', '127.0.0.1', 'mysql-host=127.0.0.1')
self.set_default('database::mysql-port', 3306, 'mysql-port=3306')
self.set_default('database::mysql-db', 'teleport', 'mysql-db=teleport')
self.set_default('database::mysql-prefix', 'tp_', 'mysql-prefix=tp_')
self.set_default('database::mysql-user', 'teleport', 'mysql-user=teleport')
self.set_default('database::mysql-password', None, 'mysql-password=password')
def _on_get_save_info(self):
return [
{'common': ['ip', 'port', 'log-file', 'log-level', 'debug-mode', 'core-server-rpc']},
{'database': ['type', 'sqlite-file', 'mysql-host', 'mysql-port', 'mysql-db', 'mysql-prefix', 'mysql-user', 'mysql-password']}
]
def _on_load(self, cfg_parser):
if 'common' not in cfg_parser:
log.e('invalid config file, need `common` section.\n')
return False
if 'database' not in cfg_parser:
log.e('invalid config file, need `database` section.\n')
return False
_comm = cfg_parser['common']
_sec = cfg_parser['common']
_tmp_int = _comm.getint('log-level', -1)
_tmp_int = _sec.getint('log-level', -1)
if log.LOG_DEBUG <= _tmp_int <= log.LOG_ERROR:
self.set_kv('common::log-level', _tmp_int)
log.set_attribute(min_level=self.common.log_level)
_tmp_bool = _comm.getint('debug-mode', False)
_tmp_bool = _sec.getint('debug-mode', False)
self.set_kv('common::debug-mode', _tmp_bool)
if _tmp_bool:
log.set_attribute(min_level=log.LOG_DEBUG, trace_error=log.TRACE_ERROR_FULL)
_tmp_str = _comm.get('ip', '0.0.0.0')
_tmp_str = _sec.get('ip', None)
if _tmp_str is not None:
self.set_kv('common::ip', _tmp_str)
_tmp_int = _comm.getint('port', -1)
_tmp_int = _sec.getint('port', -1)
if -1 != _tmp_int:
self.set_kv('common::port', _tmp_int)
_tmp_str = _comm.get('log-file', None)
_tmp_str = _sec.get('log-file', None)
if _tmp_str is not None:
self.set_kv('common::log-file', _tmp_str)
_tmp_str = _sec.get('core-server-rpc', None)
if _tmp_str is not None:
self.set_kv('common::core-server-rpc', _tmp_str)
_sec = cfg_parser['database']
_tmp_str = _sec.get('type', None)
if _tmp_str is not None:
self.set_kv('database::type', _tmp_str)
_tmp_str = _sec.get('sqlite-file', None)
if _tmp_str is not None:
self.set_kv('database::sqlite-file', _tmp_str)
_tmp_str = _sec.get('mysql-host', None)
if _tmp_str is not None:
self.set_kv('database::mysql-host', _tmp_str)
_tmp_int = _sec.getint('mysql-port', -1)
if _tmp_int != -1:
self.set_kv('database::mysql-port', _tmp_int)
_tmp_str = _sec.get('mysql-db', None)
if _tmp_str is not None:
self.set_kv('database::mysql-db', _tmp_str)
_tmp_str = _sec.get('mysql-prefix', None)
if _tmp_str is not None:
self.set_kv('database::mysql-prefix', _tmp_str)
_tmp_str = _sec.get('mysql-user', None)
if _tmp_str is not None:
self.set_kv('database::mysql-user', _tmp_str)
_tmp_str = _sec.get('mysql-password', None)
if _tmp_str is not None:
self.set_kv('database::mysql-password', _tmp_str)
return True
def update_core(self, conf_data):
@ -477,6 +546,7 @@ class AppConfig(BaseAppConfig):
return True
def app_cfg():
import builtins
if '__app_cfg__' not in builtins.__dict__:
@ -491,33 +561,33 @@ def app_cfg():
# return builtins.__dict__['__web_config__']
if __name__ == '__main__':
cfg = AppConfig()
cfg.set_default('common::log-file', 'E:/test/log/web.log')
cfg.load('E:/test/config/web.ini')
cfg.aaa = 'this is aaa'
cfg.bbb = 123
cfg.ccc = False
print('----usage--------------------')
print(cfg.common.port)
print(cfg.get_str('aaa'))
print(cfg.get_str('bbb'))
print(cfg.get_str('ccc'))
print('----usage--------------------')
print(cfg.get_int('aaa'))
print(cfg.get_int('bbb'))
print(cfg.get_int('ccc'))
print('----usage--------------------')
print(cfg.get_bool('aaa'))
print(cfg.get_bool('bbb'))
print(cfg.get_bool('ccc'))
print('----usage--------------------')
print(cfg.common)
print('----usage--------------------')
print(cfg.aaa)
print(cfg.bbb)
print(cfg.ccc)
cfg.save('E:/test/config/web-new.ini')
cfg.save()
# if __name__ == '__main__':
# cfg = AppConfig()
# cfg.set_default('common::log-file', 'E:/test/log/web.log')
# cfg.load('E:/test/config/web.ini')
# cfg.aaa = 'this is aaa'
# cfg.bbb = 123
# cfg.ccc = False
#
# print('----usage--------------------')
# print(cfg.common.port)
# print(cfg.get_str('aaa'))
# print(cfg.get_str('bbb'))
# print(cfg.get_str('ccc'))
# print('----usage--------------------')
# print(cfg.get_int('aaa'))
# print(cfg.get_int('bbb'))
# print(cfg.get_int('ccc'))
# print('----usage--------------------')
# print(cfg.get_bool('aaa'))
# print(cfg.get_bool('bbb'))
# print(cfg.get_bool('ccc'))
# print('----usage--------------------')
# print(cfg.common)
# print('----usage--------------------')
# print(cfg.aaa)
# print(cfg.bbb)
# print(cfg.ccc)
#
# cfg.save('E:/test/config/web-new.ini')
# cfg.save()

View File

@ -76,20 +76,20 @@ class WebServerCore:
# 尝试通过CORE-JSON-RPC获取core服务的配置主要是ssh/rdp/telnet的端口以及录像文件存放路径
self._get_core_server_config()
if not web_session().init():
log.e('can not initialize session manager.\n')
_db = get_db()
if not _db.init():
log.e('can not initialize database interface.\n')
return 0
# TODO: 根据配置文件来决定使用什么数据库(初始安装时还没有配置数据库信息)
_db = get_db()
if not _db.init({'type': _db.DB_TYPE_SQLITE, 'file': os.path.join(cfg.data_path, 'ts_db.db')}):
log.e('initialize database interface failed.\n')
return False
if _db.need_create or _db.need_upgrade:
cfg.app_mode = APP_MODE_MAINTENANCE
else:
cfg.app_mode = APP_MODE_NORMAL
if not web_session().init():
log.e('can not initialize session manager.\n')
return 0
settings = {
#
'cookie_secret': '8946svdABGD345fg98uhIaefEBePIfegOIakjFH43oETzK',

View File

@ -18,32 +18,32 @@ def _db_exec(db, step_begin, step_end, msg, sql):
def create_and_init(db, step_begin, step_end):
try:
_db_exec(db, step_begin, step_end, '创建表 account', """CREATE TABLE `{}account` (
`account_id` integer PRIMARY KEY AUTOINCREMENT,
`account_id` integer PRIMARY KEY {},
`account_type` int(11) DEFAULT 0,
`account_name` varchar(32) DEFAULT NULL,
`account_pwd` varchar(32) DEFAULT NULL,
`account_pwd` varchar(128) DEFAULT NULL,
`account_status` int(11) DEFAULT 0,
`account_lock` int(11) DEFAULT 0,
`account_desc` varchar(255)
);""".format(db.table_prefix))
);""".format(db.table_prefix, db.auto_increment))
_db_exec(db, step_begin, step_end, '创建表 auth', """CREATE TABLE `{}auth`(
`auth_id` INTEGER PRIMARY KEY AUTOINCREMENT,
`auth_id` INTEGER PRIMARY KEY {},
`account_name` varchar(256),
`host_id` INTEGER,
`host_auth_id` int(11) NOT NULL
);""".format(db.table_prefix))
);""".format(db.table_prefix, db.auto_increment))
# 注意这个key表原名为cert考虑到其中存放的是ssh密钥对与证书无关因此改名为key
# 这也是升级到数据库版本5的标志
_db_exec(db, step_begin, step_end, '创建表 key', """CREATE TABLE `{}key` (
`cert_id` integer PRIMARY KEY AUTOINCREMENT,
`cert_id` integer PRIMARY KEY {},
`cert_name` varchar(256),
`cert_pub` varchar(2048) DEFAULT '',
`cert_pri` varchar(4096) DEFAULT '',
`cert_desc` varchar(256)
);
""".format(db.table_prefix))
""".format(db.table_prefix, db.auto_increment))
_db_exec(db, step_begin, step_end, '创建表 config', """CREATE TABLE `{}config` (
`name` varchar(256) NOT NULL,
@ -52,23 +52,23 @@ PRIMARY KEY (`name` ASC)
);""".format(db.table_prefix))
_db_exec(db, step_begin, step_end, '创建表 group', """CREATE TABLE `{}group` (
`group_id` integer PRIMARY KEY AUTOINCREMENT,
`group_id` integer PRIMARY KEY {},
`group_name` varchar(255) DEFAULT''
);""".format(db.table_prefix))
);""".format(db.table_prefix, db.auto_increment))
_db_exec(db, step_begin, step_end, '创建表 host_info', """CREATE TABLE `{}host_info`(
`host_id` integer PRIMARY KEY AUTOINCREMENT,
`host_id` integer PRIMARY KEY {},
`group_id` int(11) DEFAULT 0,
`host_sys_type` int(11) DEFAULT 1,
`host_ip` varchar(32) DEFAULT '',
`host_port` int(11) DEFAULT 0,
`protocol` int(11) DEFAULT 0,
`host_lock` int(11) DEFAULT 0,
`host_desc` DEFAULT ''
);""".format(db.table_prefix))
`host_desc` varchar(256) DEFAULT ''
);""".format(db.table_prefix, db.auto_increment))
_db_exec(db, step_begin, step_end, '创建表 auth_info', """CREATE TABLE `{}auth_info`(
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
`id` INTEGER PRIMARY KEY {},
`host_id` INTEGER,
`auth_mode` INTEGER,
`user_name` varchar(256),
@ -77,10 +77,10 @@ PRIMARY KEY (`name` ASC)
`cert_id` INTEGER,
`encrypt` INTEGER,
`log_time` varchar(60)
);""".format(db.table_prefix))
);""".format(db.table_prefix, db.auto_increment))
_db_exec(db, step_begin, step_end, '创建表 key', """CREATE TABLE `{}log` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
`id` INTEGER PRIMARY KEY {},
`session_id` varchar(32),
`account_name` varchar(64),
`host_ip` varchar(32),
@ -93,7 +93,7 @@ PRIMARY KEY (`name` ASC)
`begin_time` INTEGER,
`end_time` INTEGER,
`log_time` varchar(64)
);""".format(db.table_prefix))
);""".format(db.table_prefix, db.auto_increment))
_admin_sec_password = sec_generate_password('admin')

View File

@ -43,11 +43,11 @@ class DatabaseUpgrade:
return True
self.step_end(_step, 0, '需要升级到v2')
if self.db.db_source['type'] == self.db.DB_TYPE_SQLITE:
if self.db.db_type == self.db.DB_TYPE_SQLITE:
_step = self.step_begin(' - 备份数据库文件')
_bak_file = '{}.before-v1-to-v2'.format(self.db.db_source['file'])
_bak_file = '{}.before-v1-to-v2'.format(self.db.sqlite_file)
if not os.path.exists(_bak_file):
shutil.copy(self.db.db_source['file'], _bak_file)
shutil.copy(self.db.sqlite_file, _bak_file)
self.step_end(_step, 0)
# 将原来的普通用户的account_type从 0 改为 1
@ -108,11 +108,11 @@ class DatabaseUpgrade:
return True
self.step_end(_step, 0, '需要升级到v3')
if self.db.db_source['type'] == self.db.DB_TYPE_SQLITE:
if self.db.db_type == self.db.DB_TYPE_SQLITE:
_step = self.step_begin(' - 备份数据库文件')
_bak_file = '{}.before-v2-to-v3'.format(self.db.db_source['file'])
_bak_file = '{}.before-v2-to-v3'.format(self.db.sqlite_file)
if not os.path.exists(_bak_file):
shutil.copy(self.db.db_source['file'], _bak_file)
shutil.copy(self.db.sqlite_file, _bak_file)
self.step_end(_step, 0)
_step = self.step_begin(' - 调整数据表...')
@ -145,19 +145,19 @@ class DatabaseUpgrade:
# 新建两个表,用于拆分原来的 ts_host 表
if not self.db.exec("""CREATE TABLE `{}host_info` (
`host_id` integer PRIMARY KEY AUTOINCREMENT,
`host_id` integer PRIMARY KEY {},
`group_id` int(11) DEFAULT 0,
`host_sys_type` int(11) DEFAULT 1,
`host_ip` varchar(32) DEFAULT '',
`pro_port` varchar(256) NULL,
`host_lock` int(11) DEFAULT 0,
`host_desc` varchar(128) DEFAULT ''
);""".format(self.db.table_prefix)):
);""".format(self.db.table_prefix, self.db.auto_increment)):
self.step_end(_step, -1)
return False
if not self.db.exec("""CREATE TABLE `{}auth_info` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
`id` INTEGER PRIMARY KEY {},
`host_id` INTEGER,
`pro_type` INTEGER,
`auth_mode` INTEGER,
@ -166,7 +166,7 @@ class DatabaseUpgrade:
`cert_id` INTEGER,
`encrypt` INTEGER,
`log_time` varchar(60)
);""".format(self.db.table_prefix)):
);""".format(self.db.table_prefix, self.db.auto_increment)):
self.step_end(_step, -1)
return False
@ -246,11 +246,11 @@ class DatabaseUpgrade:
return True
self.step_end(_step, 0, '需要升级到v4')
if self.db.db_source['type'] == self.db.DB_TYPE_SQLITE:
if self.db.db_type == self.db.DB_TYPE_SQLITE:
_step = self.step_begin(' - 备份数据库文件')
_bak_file = '{}.before-v3-to-v4'.format(self.db.db_source['file'])
_bak_file = '{}.before-v3-to-v4'.format(self.db.sqlite_file)
if not os.path.exists(_bak_file):
shutil.copy(self.db.db_source['file'], _bak_file)
shutil.copy(self.db.sqlite_file, _bak_file)
self.step_end(_step, 0)
_step = self.step_begin(' - 为telnet增加默认配置')
@ -380,16 +380,16 @@ class DatabaseUpgrade:
# 将整理好的数据写入新的临时表
# 先创建三个临时表
if not self.db.exec("""CREATE TABLE `{}auth_tmp` (
`auth_id` INTEGER PRIMARY KEY AUTOINCREMENT,
`auth_id` INTEGER PRIMARY KEY {},
`account_name` varchar(256),
`host_id` INTEGER,
`host_auth_id` int(11) NOT NULL
);""".format(self.db.table_prefix)):
);""".format(self.db.table_prefix, self.db.auto_increment)):
self.step_end(_step, -1, '无法创建认证数据临时表')
return False
if not self.db.exec("""CREATE TABLE `{}host_info_tmp` (
`host_id` integer PRIMARY KEY AUTOINCREMENT,
`host_id` integer PRIMARY KEY {},
`group_id` int(11) DEFAULT 0,
`host_sys_type` int(11) DEFAULT 1,
`host_ip` varchar(32) DEFAULT '',
@ -397,12 +397,12 @@ class DatabaseUpgrade:
`protocol` int(11) DEFAULT 0,
`host_lock` int(11) DEFAULT 0,
`host_desc` DEFAULT ''
);""".format(self.db.table_prefix)):
);""".format(self.db.table_prefix, self.db.auto_increment)):
self.step_end(_step, -1, '无法创建主机信息数据临时表')
return False
if not self.db.exec("""CREATE TABLE `{}auth_info_tmp` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
`id` INTEGER PRIMARY KEY {},
`host_id` INTEGER,
`auth_mode` INTEGER,
`user_name` varchar(256),
@ -411,7 +411,7 @@ class DatabaseUpgrade:
`cert_id` INTEGER,
`encrypt` INTEGER,
`log_time` varchar(60)
);""".format(self.db.table_prefix)):
);""".format(self.db.table_prefix, self.db.auto_increment)):
self.step_end(_step, -1, '无法创建认证信息数据临时表')
return False

View File

@ -2,10 +2,12 @@
import os
import sqlite3
import pymysql
import threading
import builtins
from eom_app.app.configs import app_cfg
from eom_common.eomcore import utils
from eom_common.eomcore.logger import log
from .database.create import create_and_init
@ -26,11 +28,20 @@ class TPDatabase:
if '__teleport_db__' in builtins.__dict__:
raise RuntimeError('TPDatabase object exists, you can not create more than one instance.')
self.db_source = {'type': self.DB_TYPE_UNKNOWN}
self.db_type = self.DB_TYPE_UNKNOWN
self.sqlite_file = ''
self.mysql_host = ''
self.mysql_port = 0
self.mysql_db = ''
self.mysql_user = ''
self.mysql_password = ''
self.need_create = False # 数据尚未存在,需要创建
self.need_upgrade = False # 数据库已存在但版本较低,需要升级
self.current_ver = 0
self.auto_increment = ''
self._table_prefix = ''
self._conn_pool = None
@ -38,22 +49,20 @@ class TPDatabase:
def table_prefix(self):
return self._table_prefix
def init(self, db_source):
self.db_source = db_source
if db_source['type'] == self.DB_TYPE_MYSQL:
log.e('MySQL not supported yet.')
def init(self):
cfg = app_cfg()
if 'sqlite' == cfg.database.type:
if cfg.database.sqlite_file is None:
cfg.set_default('database::sqlite-file', os.path.join(cfg.data_path, 'ts_db.db'))
if not self._init_sqlite(cfg.database.sqlite_file):
return False
elif 'mysql' == cfg.database.type:
if not self._init_mysql(cfg.database.mysql_host, cfg.database.mysql_port,
cfg.database.mysql_db, cfg.database.mysql_prefix,
cfg.database.mysql_user, cfg.database.mysql_password):
return False
elif db_source['type'] == self.DB_TYPE_SQLITE:
self._table_prefix = 'ts_'
self._conn_pool = TPSqlitePool(db_source['file'])
if not os.path.exists(db_source['file']):
log.w('database need create.\n')
self.need_create = True
return True
else:
log.e('Unknown database type: {}'.format(db_source['type']))
log.e('unknown database type `{}`, support sqlite/mysql now.\n'.format(cfg.database.type))
return False
# 看看数据库中是否存在指定的数据表(如果不存在,可能是一个空数据库文件),则可能是一个新安装的系统
@ -81,13 +90,86 @@ class TPDatabase:
return True
def _init_sqlite(self, db_file):
self.db_type = self.DB_TYPE_SQLITE
self.auto_increment = 'AUTOINCREMENT'
self.sqlite_file = db_file
self._table_prefix = 'ts_'
self._conn_pool = TPSqlitePool(db_file)
if not os.path.exists(db_file):
log.w('database need create.\n')
self.need_create = True
return True
return True
def _init_mysql(self, mysql_host, mysql_port, mysql_db, mysql_prefix, mysql_user, mysql_password):
self.db_type = self.DB_TYPE_MYSQL
self.auto_increment = 'AUTO_INCREMENT'
self._table_prefix = mysql_prefix
self.mysql_host = mysql_host
self.mysql_port = mysql_port
self.mysql_db = mysql_db
self.mysql_user = mysql_user
self.mysql_password = mysql_password
self._conn_pool = TPMysqlPool(mysql_host, mysql_port, mysql_db, mysql_user, mysql_password)
return True
# def init__(self, db_source):
# self.db_source = db_source
#
# if db_source['type'] == self.DB_TYPE_MYSQL:
# log.e('MySQL not supported yet.')
# return False
# elif db_source['type'] == self.DB_TYPE_SQLITE:
# self._table_prefix = 'ts_'
# self._conn_pool = TPSqlitePool(db_source['file'])
#
# if not os.path.exists(db_source['file']):
# log.w('database need create.\n')
# self.need_create = True
# return True
# else:
# log.e('Unknown database type: {}'.format(db_source['type']))
# return False
#
# # 看看数据库中是否存在指定的数据表(如果不存在,可能是一个空数据库文件),则可能是一个新安装的系统
# # ret = self.query('SELECT COUNT(*) FROM `sqlite_master` WHERE `type`="table" AND `name`="{}account";'.format(self._table_prefix))
# ret = self.is_table_exists('{}group'.format(self._table_prefix))
# if ret is None or not ret:
# log.w('database need create.\n')
# self.need_create = True
# return True
#
# # 尝试从配置表中读取当前数据库版本号(如果不存在,说明是比较旧的版本了)
# ret = self.query('SELECT `value` FROM `{}config` WHERE `name`="db_ver";'.format(self._table_prefix))
# if ret is None or 0 == len(ret):
# self.current_ver = 1
# else:
# self.current_ver = int(ret[0][0])
#
# if self.current_ver < self.DB_VERSION:
# log.w('database need upgrade.\n')
# self.need_upgrade = True
# return True
#
# # DO TEST
# # self.alter_table('ts_account', [['account_id', 'id'], ['account_type', 'type']])
#
# return True
def is_table_exists(self, table_name):
"""
判断指定的表是否存在
@param table_name: string
@return: None or Boolean
"""
if self.db_source['type'] == self.DB_TYPE_SQLITE:
if self.db_type == self.DB_TYPE_SQLITE:
ret = self.query('SELECT COUNT(*) FROM `sqlite_master` WHERE `type`="table" AND `name`="{}";'.format(table_name))
if ret is None:
return None
@ -96,8 +178,13 @@ class TPDatabase:
if ret[0][0] == 0:
return False
return True
elif self.db_source['type'] == self.DB_TYPE_MYSQL:
elif self.db_type == self.DB_TYPE_MYSQL:
# select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='dbname' and TABLE_NAME='tablename' ;
ret = self.query('SELECT TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA="{}" and TABLE_NAME="{}";'.format(self.mysql_db, table_name))
if len(ret) == 0:
return None
else:
return True
else:
log.e('Unknown database type.\n')
return None
@ -118,23 +205,26 @@ class TPDatabase:
# log.d('[db] cost {} seconds.\n'.format(_end - _start))
return ret
def last_insert_id(self):
return self._conn_pool.last_insert_id()
def create_and_init(self, step_begin, step_end):
log.v('start database create and initialization process.\n')
if self.db_source['type'] == self.DB_TYPE_SQLITE:
db_path = os.path.dirname(self.db_source['file'])
if self.db_type == self.DB_TYPE_SQLITE:
db_path = os.path.dirname(self.sqlite_file)
if not os.path.exists(db_path):
utils.make_dir(db_path)
if not os.path.exists(db_path):
log.e('can not create folder `{}` to store database file.\n'.format(db_path))
return False
# 创建一个空数据文件这样才能进行connect。
if not os.path.exists(self.db_source['file']):
if not os.path.exists(self.sqlite_file):
try:
with open(self.db_source['file'], 'w') as f:
with open(self.sqlite_file, 'w') as f:
pass
except:
log.e('can not create db file `{}`.\n'.format(self.db_source['file']))
log.e('can not create db file `{}`.\n'.format(self.sqlite_file))
return False
if create_and_init(self, step_begin, step_end):
@ -163,7 +253,7 @@ class TPDatabase:
@return: None or Boolean
"""
# TODO: 此函数尚未完成
if self.db_source['type'] == self.DB_TYPE_SQLITE:
if self.db_type == self.DB_TYPE_SQLITE:
if not isinstance(table_names, list) and field_names is None:
log.w('nothing to do.\n')
return False
@ -203,7 +293,7 @@ class TPDatabase:
# return ret
pass
elif self.db_source['type'] == self.DB_TYPE_MYSQL:
elif self.db_type == self.DB_TYPE_MYSQL:
log.e('mysql not supported yet.\n')
return False
else:
@ -228,6 +318,12 @@ class TPDatabasePool:
return False
return self._do_exec(_conn, sql)
def last_insert_id(self):
_conn = self._get_connect()
if _conn is None:
return -1
return self._last_insert_id(_conn)
def _get_connect(self):
with self._locker:
thread_id = threading.get_ident()
@ -249,6 +345,8 @@ class TPDatabasePool:
def _do_exec(self, conn, sql):
return None
def _last_insert_id(self, conn):
return -1
class TPSqlitePool(TPDatabasePool):
def __init__(self, db_file):
@ -272,8 +370,70 @@ class TPSqlitePool(TPDatabasePool):
cursor.execute(sql)
db_ret = cursor.fetchall()
return db_ret
except sqlite3.OperationalError:
# log.e('_do_query() error.\n')
# except sqlite3.OperationalError:
# # log.e('_do_query() error.\n')
# return None
except Exception as e:
log.e('[sqlite] _do_query() failed: {}\n'.format(e.__str__()))
finally:
cursor.close()
def _do_exec(self, conn, sql):
cursor = conn.cursor()
try:
cursor.execute(sql)
conn.commit()
return True
# except sqlite3.OperationalError as e:
except Exception as e:
log.e('[sqlite] _do_exec() failed: {}\n'.format(e.__str__()))
return False
finally:
cursor.close()
def _last_insert_id(self, conn):
cursor = conn.cursor()
try:
cursor.execute('SELECT last_insert_rowid();')
db_ret = cursor.fetchall()
return db_ret[0][0]
except Exception as e:
log.e('[sqlite] _last_insert_id() failed: {}\n'.format(e.__str__()))
return -1
finally:
cursor.close()
class TPMysqlPool(TPDatabasePool):
def __init__(self, host, port, db_name, user, password):
super().__init__()
self._host = host
self._port = port
self._db_name = db_name
self._user = user
self._password = password
def _do_connect(self):
try:
return pymysql.connect(host=self._host,
user=self._user,
passwd=self._password,
db=self._db_name,
port=self._port,
connect_timeout=3.0,
charset='utf8')
except Exception as e:
log.e('[mysql] connect [{}:{}] failed: {}\n'.format(self._host, self._port, e.__str__()))
return None
def _do_query(self, conn, sql):
cursor = conn.cursor()
try:
cursor.execute(sql)
db_ret = cursor.fetchall()
return db_ret
except Exception as e:
log.e('[mysql] _do_query() failed: {}\n'.format(e.__str__()))
return None
finally:
cursor.close()
@ -284,9 +444,21 @@ class TPSqlitePool(TPDatabasePool):
cursor.execute(sql)
conn.commit()
return True
except sqlite3.OperationalError:
# log.e('_do_exec() error.\n')
return False
except Exception as e:
log.e('[mysql] _do_exec() failed: {}\n'.format(e.__str__()))
return None
finally:
cursor.close()
def _last_insert_id(self, conn):
cursor = conn.cursor()
try:
cursor.execute('SELECT LAST_INSERT_ID();')
db_ret = cursor.fetchall()
return db_ret[0][0]
except Exception as e:
log.e('[sqlite] _last_insert_id() failed: {}\n'.format(e.__str__()))
return -1
finally:
cursor.close()

View File

@ -32,21 +32,21 @@ class IndexHandler(TPBaseAdminAuthHandler):
cfg.update_core(None)
_db = get_db()
# database = '未知'
db = _db.db_source
# if _db.db_source['type'] == _db.DB_TYPE_SQLITE:
# database = 'SQLite{}'.format(_db.db_source['file'])
# el
if _db.db_source['type'] == _db.DB_TYPE_MYSQL:
# database = 'MySQL'
del db['password']
db = {'type': _db.db_type}
if _db.db_type == _db.DB_TYPE_SQLITE:
db['sqlite_file'] = _db.sqlite_file
elif _db.db_type == _db.DB_TYPE_MYSQL:
db['mysql_host'] = _db.mysql_host
db['mysql_port'] = _db.mysql_port
db['mysql_db'] = _db.mysql_db
db['mysql_user'] = _db.mysql_user
param = {
'core': cfg.core,
'web': {
'version': TS_VER,
'core_server_rpc': cfg.common.core_server_rpc,
# 'database': database,
'db': db
}
}

View File

@ -19,7 +19,19 @@ class IndexHandler(TPBaseUserAuthHandler):
class InstallHandler(TPBaseAdminAuthHandler):
def get(self):
if get_db().need_create:
self.render('maintenance/install.mako')
_db = get_db()
db = {'type': _db.db_type}
if _db.db_type == _db.DB_TYPE_SQLITE:
db['sqlite_file'] = _db.sqlite_file
elif _db.db_type == _db.DB_TYPE_MYSQL:
db['mysql_host'] = _db.mysql_host
db['mysql_port'] = _db.mysql_port
db['mysql_user'] = _db.mysql_user
db['mysql_db'] = _db.mysql_db
param = {'db': db}
self.render('maintenance/install.mako', page_param=json.dumps(param))
elif get_db().need_upgrade:
return self.redirect('/maintenance/upgrade')
else:

View File

@ -378,11 +378,10 @@ def add_host(args, must_not_exists=True):
if not ret:
return -101
sql = 'SELECT last_insert_rowid()'
db_ret = db.query(sql)
if db_ret is None:
host_id = db.last_insert_id()
if host_id == -1:
return -102
host_id = db_ret[0][0]
else:
return host_id
@ -636,11 +635,10 @@ def sys_user_add(args):
if not ret:
return -101
sql = 'SELECT last_insert_rowid()'
db_ret = db.query(sql)
if db_ret is None:
user_id = db.last_insert_id()
if user_id == -1:
return -102
user_id = db_ret[0][0]
else:
return user_id

View File

@ -183,11 +183,10 @@ def session_begin(sid, acc_name, host_ip, sys_type, host_port, auth_mode, user_n
if not ret:
return -101
sql = 'SELECT last_insert_rowid()'
db_ret = db.query(sql)
if db_ret is None:
user_id = db.last_insert_id()
if user_id == -1:
return -102
user_id = db_ret[0][0]
else:
return user_id
except:

View File

@ -406,10 +406,9 @@ ywl.on_host_table_created = function (tbl) {
pro_port = row_data.pro_port;
}
if (pro_type === PROTOCOL_TYPE_RDP) {
host_port = ts_rdp_port;
size = parseInt($(this).parent().parent().find('#dlg-rdp-size select').val())
size = parseInt($(this).parent().parent().find('#dlg-rdp-size select').val());
if ($(this).parent().parent().find('#dlg-action-rdp-console').is(':checked')) {
rdp_console = 1;
} else {
@ -1339,9 +1338,12 @@ ywl.create_sys_user = function (tbl) {
if (auth_mode === AUTH_TYPE_PASSWORD) {
user_pswd = dlg_sys_user.user_pswd;
} else if (auth_mode === AUTH_TYPE_SSHKEY) {
if (_.isNull(dlg_sys_user.cert_id)) {
ywl.notify_error('请选择一个SSH私钥如SSH私钥列表为空请在密钥管理页面中增加');
return;
}
cert_id = parseInt(dlg_sys_user.cert_id);
} else {
}
var host_id = parseInt(dlg_sys_user.host_id);
var host_auth_id = parseInt(dlg_sys_user.host_auth_id);

View File

@ -18,14 +18,19 @@ ywl.on_init = function (cb_stack, cb_args) {
html.push(ywl._make_info('核心服务版本', ywl.page_options.core.version));
}
var db_type = '未知';
if (ywl.page_options.web.db.type === DB_TYPE_SQLITE) {
db_type = 'SQLite' + ywl.page_options.web.db.file + '';
html.push(ywl._make_info('数据库类型', 'SQLite'));
html.push(ywl._make_info('sqlite-file', ywl.page_options.web.db.sqlite_file));
} else if (ywl.page_options.web.db.type === DB_TYPE_MYSQL) {
db_type = 'MySQL';
html.push(ywl._make_info('数据库类型', 'MySQL'));
html.push(ywl._make_info('mysql-host', ywl.page_options.web.db.mysql_host));
html.push(ywl._make_info('mysql-port', ywl.page_options.web.db.mysql_port));
html.push(ywl._make_info('mysql-db', ywl.page_options.web.db.mysql_db));
html.push(ywl._make_info('mysql-user', ywl.page_options.web.db.mysql_user));
} else {
html.push(ywl._make_info('数据库类型', '未知'));
}
html.push(ywl._make_info('数据库类型', db_type));
html.push(ywl._make_info('核心服务通讯地址', ywl.page_options.web.core_server_rpc));
if (ywl.page_options.core.detected) {
html.push(ywl._make_info('WEB服务通讯地址', ywl.page_options.core.web_server_rpc));

View File

@ -43,6 +43,10 @@
background-color: #cc3632;
border: 1px solid #9c2a26;
}
#sqlite-info, #mysql-info {
display: none;
}
</style>
</%block>
@ -60,7 +64,9 @@
<div>
<p>请选择要使用的数据库类型暂时仅支持sqlite其它类型开发中</p>
<input id="db-sqlite" type="radio" checked="checked" name="database" value="sqlite"/> <label for="db-sqlite">SQLite</label><br/>
<input id="db-mysql" type="radio" name="database" value="mysql" disabled="disabled"/> <label for="db-mysql">MySQL开发中暂不支持</label>
<input id="db-mysql" type="radio" name="database" value="mysql"/> <label for="db-mysql">MySQL开发中暂不支持</label>
<div id="sqlite-info"></div>
<div id="mysql-info"></div>
<div>
<button id="btn-create-db" type="button" class="btn btn-primary"><i class="fa fa-wrench fa-fw"></i> 开始创建</button>
</div>
@ -83,13 +89,23 @@
<%block name="embed_js">
<script type="text/javascript">
"use strict";
ywl.add_page_options(${ page_param });
ywl.on_init = function (cb_stack, cb_args) {
ywl.dom = {
btn_create_db: $('#btn-create-db'),
steps_detail: $('#steps-detail')
steps_detail: $('#steps-detail'),
sqlite_info: $('#sqlite-info'),
mysql_info: $('#mysql-info')
};
if (ywl.page_options.db.type === DB_TYPE_SQLITE) {
} else if (ywl.page_options.db.type === DB_TYPE_MYSQL) {
} else {
ywl.show_message('error', '未知的数据库类型,请检查您的配置文件!');
ywl.dom.btn_create_db.attr('disabled', 'disabled').hide();
}
ywl.dom.btn_create_db.click(function () {
ywl.dom.btn_create_db.attr('disabled', 'disabled').hide();