支持全量的数据库导入导出(仅数据,不含表结构)。

pull/32/head
Apex Liu 2017-05-31 19:00:31 +08:00
parent 10090648ff
commit 22900ebf9f
6 changed files with 218 additions and 25 deletions

View File

@ -866,7 +866,7 @@ int SshSession::_on_client_shell_request(ssh_session session, ssh_channel channe
// ); // );
// ssh_channel_write(channel, buf, strlen(buf)); // ssh_channel_write(channel, buf, strlen(buf));
// //
return SSH_ERROR; return 1;
} }
EXLOGD("[ssh] client request shell\n"); EXLOGD("[ssh] client request shell\n");
@ -874,14 +874,14 @@ int SshSession::_on_client_shell_request(ssh_session session, ssh_channel channe
TS_SSH_CHANNEL_INFO *srv_info = _this->_get_srv_channel(channel); TS_SSH_CHANNEL_INFO *srv_info = _this->_get_srv_channel(channel);
if (NULL == srv_info || NULL == srv_info->channel) { if (NULL == srv_info || NULL == srv_info->channel) {
EXLOGE("[ssh] when client request shell, not found server channel.\n"); EXLOGE("[ssh] when client request shell, not found server channel.\n");
return SSH_ERROR; return 1;
} }
srv_info->type = TS_SSH_CHANNEL_TYPE_SHELL; srv_info->type = TS_SSH_CHANNEL_TYPE_SHELL;
TS_SSH_CHANNEL_INFO *cli_info = _this->_get_cli_channel(srv_info->channel); TS_SSH_CHANNEL_INFO *cli_info = _this->_get_cli_channel(srv_info->channel);
if (NULL == cli_info || NULL == cli_info->channel) { if (NULL == cli_info || NULL == cli_info->channel) {
EXLOGE("[ssh] when client request shell, not found client channel.\n"); EXLOGE("[ssh] when client request shell, not found client channel.\n");
return SSH_ERROR; return 1;
} }
cli_info->type = TS_SSH_CHANNEL_TYPE_SHELL; cli_info->type = TS_SSH_CHANNEL_TYPE_SHELL;

View File

@ -8,33 +8,28 @@ TppSshEnv::TppSshEnv()
TppSshEnv::~TppSshEnv() TppSshEnv::~TppSshEnv()
{} {}
bool TppSshEnv::_on_init(TPP_INIT_ARGS* args) bool TppSshEnv::_on_init(TPP_INIT_ARGS* args) {
{
ex_path_join(replay_path, false, L"ssh", NULL); ex_path_join(replay_path, false, L"ssh", NULL);
ExIniSection* ps = args->cfg->GetSection(L"protocol-ssh"); ExIniSection* ps = args->cfg->GetSection(L"protocol-ssh");
if (NULL == ps) if (NULL == ps) {
{
EXLOGE("[ssh] invalid config(2).\n"); EXLOGE("[ssh] invalid config(2).\n");
return false; return false;
} }
ex_wstr tmp; ex_wstr tmp;
if (!ps->GetStr(L"bind-ip", tmp)) if (!ps->GetStr(L"bind-ip", tmp)) {
{
bind_ip = TS_SSH_PROXY_HOST; bind_ip = TS_SSH_PROXY_HOST;
} }
else else {
{
ex_wstr2astr(tmp, bind_ip); ex_wstr2astr(tmp, bind_ip);
} }
EXLOGW("[ssh] bind-ip: %s\n", bind_ip.c_str());
if (!ps->GetInt(L"bind-port", bind_port)) if (!ps->GetInt(L"bind-port", bind_port)) {
{
bind_port = TS_SSH_PROXY_PORT; bind_port = TS_SSH_PROXY_PORT;
} }
EXLOGW(L"[ssh] bind-port: %d\n", bind_port);
EXLOGW(L"[ssh] listen on %s:%d\n", bind_ip.c_str(), bind_port);
return true; return true;
} }

View File

@ -0,0 +1,166 @@
# -*- coding: utf-8 -*-
import time
from eom_app.app.util import sec_generate_password
from eom_common.eomcore.logger import log
def _db_exec(db, step_begin, step_end, msg, sql):
_step = step_begin(msg)
ret = db.exec(sql)
if not ret:
step_end(_step, -1)
raise RuntimeError('[FAILED] {}'.format(sql))
else:
step_end(_step, 0)
def _export_table(db, table_name, fields):
ret = ['', '-- table: {}'.format(table_name), '-- fields: {}'.format(', '.join(fields)), 'TRUNCATE TABLE `{}`;'.format(table_name)]
fields_str = '`,`'.join(fields)
sql = 'SELECT `{}` FROM `{}{}`'.format(fields_str, db.table_prefix, table_name)
d = db.query(sql)
if not d or len(d) == 0:
ret.append('-- table is empty.')
else:
fields_count = len(fields)
for i in range(len(d)):
x = []
for j in range(fields_count):
x.append(d[i][j].__str__())
val = "','".join(x).replace('\n', '\\n')
sql = "INSERT INTO `{}` VALUES ('{}');".format(table_name, val)
ret.append(sql)
return '\r\n'.join(ret)
def export_database(db):
ret = []
now = time.localtime(time.time())
ret.append('-- {:04d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d} '.format(now.tm_year, now.tm_mon, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec))
if db.db_type == db.DB_TYPE_SQLITE:
ret.append('-- export from SQLite Database')
elif db.db_type == db.DB_TYPE_MYSQL:
ret.append('-- export from MySQL Database')
else:
return 'Unknown Database Type'
_fields = ['account_id', 'account_type', 'account_name', 'account_pwd', 'account_status', 'account_lock', 'account_desc']
ret.append(_export_table(db, 'account', _fields))
_fields = ['auth_id', 'account_name', 'host_id', 'host_auth_id']
ret.append(_export_table(db, 'auth', _fields))
_fields = ['cert_id', 'cert_name', 'cert_pub', 'cert_pri', 'cert_desc']
ret.append(_export_table(db, 'key', _fields))
_fields = ['name', 'value']
ret.append(_export_table(db, 'config', _fields))
_fields = ['group_id', 'group_name']
ret.append(_export_table(db, 'group', _fields))
_fields = ['host_id', 'group_id', 'host_sys_type', 'host_ip', 'host_port', 'protocol', 'host_lock', 'host_desc']
ret.append(_export_table(db, 'host_info', _fields))
_fields = ['id', 'host_id', 'auth_mode', 'user_name', 'user_pswd', 'user_param', 'cert_id', 'encrypt', 'log_time']
ret.append(_export_table(db, 'auth_info', _fields))
_fields = ['id', 'session_id', 'account_name', 'host_ip', 'host_port', 'sys_type', 'auth_type', 'protocol', 'user_name', 'ret_code', 'begin_time', 'end_time', 'log_time']
ret.append(_export_table(db, 'log', _fields))
return '\r\n'.join(ret)
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 {},
`account_type` int(11) DEFAULT 0,
`account_name` 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, db.auto_increment))
_db_exec(db, step_begin, step_end, '创建表 auth', """CREATE TABLE `{}auth`(
`auth_id` INTEGER PRIMARY KEY {},
`account_name` varchar(255),
`host_id` INTEGER,
`host_auth_id` int(11) NOT NULL
);""".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 {},
`cert_name` varchar(255),
`cert_pub` varchar(2048) DEFAULT '',
`cert_pri` varchar(4096) DEFAULT '',
`cert_desc` varchar(255)
);
""".format(db.table_prefix, db.auto_increment))
_db_exec(db, step_begin, step_end, '创建表 config', """CREATE TABLE `{}config` (
`name` varchar(128) NOT NULL,
`value` varchar(255),
PRIMARY KEY (`name` ASC)
);""".format(db.table_prefix))
_db_exec(db, step_begin, step_end, '创建表 group', """CREATE TABLE `{}group` (
`group_id` integer PRIMARY KEY {},
`group_name` varchar(255) DEFAULT''
);""".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 {},
`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` varchar(255) 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 {},
`host_id` INTEGER,
`auth_mode` INTEGER,
`user_name` varchar(255),
`user_pswd` varchar(255),
`user_param` varchar(255),
`cert_id` INTEGER,
`encrypt` INTEGER,
`log_time` varchar(60)
);""".format(db.table_prefix, db.auto_increment))
_db_exec(db, step_begin, step_end, '创建表 key', """CREATE TABLE `{}log` (
`id` INTEGER PRIMARY KEY {},
`session_id` varchar(32),
`account_name` varchar(64),
`host_ip` varchar(32),
`host_port` INTEGER,
`sys_type` INTEGER DEFAULT 0,
`auth_type` INTEGER,
`protocol` INTEGER,
`user_name` varchar(64),
`ret_code` INTEGER,
`begin_time` INTEGER,
`end_time` INTEGER,
`log_time` varchar(64)
);""".format(db.table_prefix, db.auto_increment))
_admin_sec_password = sec_generate_password('admin')
_db_exec(db, step_begin, step_end,
'建立管理员账号',
'INSERT INTO `{}account` VALUES (1, 100, "admin", "{}", 0, 0, "超级管理员");'.format(db.table_prefix, _admin_sec_password)
)
_db_exec(db, step_begin, step_end,
'设定数据库版本',
'INSERT INTO `{}config` VALUES ("db_ver", "{}");'.format(db.table_prefix, db.DB_VERSION)
)
return True
except:
log.e('ERROR\n')
return False

View File

@ -12,6 +12,7 @@ from eom_common.eomcore import utils
from eom_common.eomcore.logger import log from eom_common.eomcore.logger import log
from .database.create import create_and_init from .database.create import create_and_init
from .database.upgrade import DatabaseUpgrade from .database.upgrade import DatabaseUpgrade
from .database.export import export_database
__all__ = ['get_db', 'DbItem'] __all__ = ['get_db', 'DbItem']
@ -304,10 +305,8 @@ class TPDatabase:
def export_to_sql(self): def export_to_sql(self):
# TODO: not implement. # TODO: not implement.
ret = []
ret.append('{}'.format(self.db_type)) return export_database(self)
ret.append('export to sql not implement.')
return '\n'.join(ret)
class TPDatabasePool: class TPDatabasePool:
@ -385,6 +384,7 @@ class TPSqlitePool(TPDatabasePool):
# return None # return None
except Exception as e: except Exception as e:
log.e('[sqlite] _do_query() failed: {}\n'.format(e.__str__())) log.e('[sqlite] _do_query() failed: {}\n'.format(e.__str__()))
log.e('[sqlite] SQL={}'.format(sql))
finally: finally:
cursor.close() cursor.close()
@ -397,6 +397,7 @@ class TPSqlitePool(TPDatabasePool):
# except sqlite3.OperationalError as e: # except sqlite3.OperationalError as e:
except Exception as e: except Exception as e:
log.e('[sqlite] _do_exec() failed: {}\n'.format(e.__str__())) log.e('[sqlite] _do_exec() failed: {}\n'.format(e.__str__()))
log.e('[sqlite] SQL={}'.format(sql))
return False return False
finally: finally:
cursor.close() cursor.close()
@ -444,6 +445,7 @@ class TPMysqlPool(TPDatabasePool):
conn.commit() conn.commit()
return db_ret return db_ret
except Exception as e: except Exception as e:
log.v('[mysql] SQL={}\n'.format(sql))
log.e('[mysql] _do_query() failed: {}\n'.format(e.__str__())) log.e('[mysql] _do_query() failed: {}\n'.format(e.__str__()))
return None return None
finally: finally:
@ -457,6 +459,7 @@ class TPMysqlPool(TPDatabasePool):
return True return True
except Exception as e: except Exception as e:
log.e('[mysql] _do_exec() failed: {}\n'.format(e.__str__())) log.e('[mysql] _do_exec() failed: {}\n'.format(e.__str__()))
log.e('[mysql] SQL={}'.format(sql))
return None return None
finally: finally:
cursor.close() cursor.close()

View File

@ -57,8 +57,11 @@ class IndexHandler(TPBaseAdminAuthHandler):
class ExportDatabaseHandler(TPBaseAdminAuthHandler): class ExportDatabaseHandler(TPBaseAdminAuthHandler):
def get(self): def get(self):
now = time.localtime(time.time())
dt = '{:04d}{:02d}{:02d}-{:02d}{:02d}{:02d}'.format(now.tm_year, now.tm_mon, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec)
self.set_header('Content-Type', 'application/octet-stream') self.set_header('Content-Type', 'application/octet-stream')
self.set_header('Content-Disposition', 'attachment; filename=teleport-database-export.sql') self.set_header('Content-Disposition', 'attachment; filename=teleport-database-export-{}.sql'.format(dt))
sql = get_db().export_to_sql() sql = get_db().export_to_sql()
@ -112,10 +115,39 @@ class ImportDatabaseHandler(TPBaseAdminAuthHandler):
return self.write(json.dumps(ret).encode('utf8')) return self.write(json.dumps(ret).encode('utf8'))
with open(sql_filename, encoding=file_encode) as f: with open(sql_filename, encoding=file_encode) as f:
db = get_db()
sql = []
lines = f.readlines() lines = f.readlines()
for line in lines: for line in lines:
print(line) line = line.strip('\r\n')
pass if line .startswith('TRUNCATE TABLE '):
x = line.split(' ', 2)
_table_name = '`{}{}`'.format(get_db().table_prefix, x[2][1:-2])
if db.db_type == db.DB_TYPE_MYSQL:
x[2] = _table_name
line = ' '.join(x)
line += ';'
sql.append(line)
elif db.db_type == db.DB_TYPE_SQLITE:
#delete from TableName; //清空数据
# update sqlite_sequence SET seq = 0 where name ='TableName';//自增长ID为0
sql.append('DELETE FROM {};'.format(_table_name))
sql.append('UPDATE `sqlite_sequence` SET `seq`=0 WHERE `name`="{}";'.format(_table_name[1:-1]))
if line.startswith('INSERT INTO '):
x = line.split(' ', 3)
_table_name = '`{}{}`'.format(db.table_prefix, x[2][1:-1])
x[2] = _table_name
line = ' '.join(x)
# print(line)
sql.append(line)
for line in sql:
db_ret = get_db().exec(line)
if not db_ret:
ret['code'] = -1
ret['message'] = 'SQL语句执行出错: {}'.format(line)
return self.write(json.dumps(ret).encode('utf8'))
ret['code'] = 0 ret['code'] = 0
return self.write(json.dumps(ret).encode('utf8')) return self.write(json.dumps(ret).encode('utf8'))

View File

@ -70,12 +70,9 @@ ywl.on_init = function (cb_stack, cb_args) {
// //
dom.btn_db_export.click(function () { dom.btn_db_export.click(function () {
alert('not implement.');
window.location.href = '/config/export-database' window.location.href = '/config/export-database'
}); });
dom.btn_db_import.click(function () { dom.btn_db_import.click(function () {
alert('not implement.');
var _fn_sure = function (cb_stack, cb_args) { var _fn_sure = function (cb_stack, cb_args) {
var html = '<input id="upload-file" type="file" name="sqlfile" class="hidden" value="" style="display: none;"/>'; var html = '<input id="upload-file" type="file" name="sqlfile" class="hidden" value="" style="display: none;"/>';
dom.btn_db_import.after($(html)); dom.btn_db_import.after($(html));