支持全量的数据库导入导出(仅数据,不含表结构)。
							parent
							
								
									10090648ff
								
							
						
					
					
						commit
						22900ebf9f
					
				| 
						 | 
				
			
			@ -866,7 +866,7 @@ int SshSession::_on_client_shell_request(ssh_session session, ssh_channel channe
 | 
			
		|||
// 			);
 | 
			
		||||
// 		ssh_channel_write(channel, buf, strlen(buf));
 | 
			
		||||
// 
 | 
			
		||||
		return SSH_ERROR;
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
	if (NULL == srv_info || NULL == srv_info->channel) {
 | 
			
		||||
		EXLOGE("[ssh] when client request shell, not found server channel.\n");
 | 
			
		||||
		return SSH_ERROR;
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
	srv_info->type = TS_SSH_CHANNEL_TYPE_SHELL;
 | 
			
		||||
 | 
			
		||||
	TS_SSH_CHANNEL_INFO *cli_info = _this->_get_cli_channel(srv_info->channel);
 | 
			
		||||
	if (NULL == cli_info || NULL == cli_info->channel) {
 | 
			
		||||
		EXLOGE("[ssh] when client request shell, not found client channel.\n");
 | 
			
		||||
		return SSH_ERROR;
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
	cli_info->type = TS_SSH_CHANNEL_TYPE_SHELL;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,33 +8,28 @@ 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);
 | 
			
		||||
 | 
			
		||||
	ExIniSection* ps = args->cfg->GetSection(L"protocol-ssh");
 | 
			
		||||
	if (NULL == ps)
 | 
			
		||||
	{
 | 
			
		||||
	if (NULL == ps) {
 | 
			
		||||
		EXLOGE("[ssh] invalid config(2).\n");
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ex_wstr tmp;
 | 
			
		||||
	if (!ps->GetStr(L"bind-ip", tmp))
 | 
			
		||||
	{
 | 
			
		||||
	if (!ps->GetStr(L"bind-ip", tmp)) {
 | 
			
		||||
		bind_ip = TS_SSH_PROXY_HOST;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
	else {
 | 
			
		||||
		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;
 | 
			
		||||
	}
 | 
			
		||||
	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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -12,6 +12,7 @@ from eom_common.eomcore import utils
 | 
			
		|||
from eom_common.eomcore.logger import log
 | 
			
		||||
from .database.create import create_and_init
 | 
			
		||||
from .database.upgrade import DatabaseUpgrade
 | 
			
		||||
from .database.export import export_database
 | 
			
		||||
 | 
			
		||||
__all__ = ['get_db', 'DbItem']
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -304,10 +305,8 @@ class TPDatabase:
 | 
			
		|||
 | 
			
		||||
    def export_to_sql(self):
 | 
			
		||||
        # TODO: not implement.
 | 
			
		||||
        ret = []
 | 
			
		||||
        ret.append('{}'.format(self.db_type))
 | 
			
		||||
        ret.append('export to sql not implement.')
 | 
			
		||||
        return '\n'.join(ret)
 | 
			
		||||
 | 
			
		||||
        return export_database(self)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TPDatabasePool:
 | 
			
		||||
| 
						 | 
				
			
			@ -385,6 +384,7 @@ class TPSqlitePool(TPDatabasePool):
 | 
			
		|||
        #     return None
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            log.e('[sqlite] _do_query() failed: {}\n'.format(e.__str__()))
 | 
			
		||||
            log.e('[sqlite] SQL={}'.format(sql))
 | 
			
		||||
        finally:
 | 
			
		||||
            cursor.close()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -397,6 +397,7 @@ class TPSqlitePool(TPDatabasePool):
 | 
			
		|||
        # except sqlite3.OperationalError as e:
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            log.e('[sqlite] _do_exec() failed: {}\n'.format(e.__str__()))
 | 
			
		||||
            log.e('[sqlite] SQL={}'.format(sql))
 | 
			
		||||
            return False
 | 
			
		||||
        finally:
 | 
			
		||||
            cursor.close()
 | 
			
		||||
| 
						 | 
				
			
			@ -444,6 +445,7 @@ class TPMysqlPool(TPDatabasePool):
 | 
			
		|||
            conn.commit()
 | 
			
		||||
            return db_ret
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            log.v('[mysql] SQL={}\n'.format(sql))
 | 
			
		||||
            log.e('[mysql] _do_query() failed: {}\n'.format(e.__str__()))
 | 
			
		||||
            return None
 | 
			
		||||
        finally:
 | 
			
		||||
| 
						 | 
				
			
			@ -457,6 +459,7 @@ class TPMysqlPool(TPDatabasePool):
 | 
			
		|||
            return True
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            log.e('[mysql] _do_exec() failed: {}\n'.format(e.__str__()))
 | 
			
		||||
            log.e('[mysql] SQL={}'.format(sql))
 | 
			
		||||
            return None
 | 
			
		||||
        finally:
 | 
			
		||||
            cursor.close()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -57,8 +57,11 @@ class IndexHandler(TPBaseAdminAuthHandler):
 | 
			
		|||
 | 
			
		||||
class ExportDatabaseHandler(TPBaseAdminAuthHandler):
 | 
			
		||||
    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-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()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -112,10 +115,39 @@ class ImportDatabaseHandler(TPBaseAdminAuthHandler):
 | 
			
		|||
                return self.write(json.dumps(ret).encode('utf8'))
 | 
			
		||||
 | 
			
		||||
            with open(sql_filename, encoding=file_encode) as f:
 | 
			
		||||
                db = get_db()
 | 
			
		||||
                sql = []
 | 
			
		||||
                lines = f.readlines()
 | 
			
		||||
                for line in lines:
 | 
			
		||||
                    print(line)
 | 
			
		||||
                pass
 | 
			
		||||
                    line = line.strip('\r\n')
 | 
			
		||||
                    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
 | 
			
		||||
            return self.write(json.dumps(ret).encode('utf8'))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -70,12 +70,9 @@ ywl.on_init = function (cb_stack, cb_args) {
 | 
			
		|||
//
 | 
			
		||||
 | 
			
		||||
    dom.btn_db_export.click(function () {
 | 
			
		||||
        alert('not implement.');
 | 
			
		||||
        window.location.href = '/config/export-database'
 | 
			
		||||
    });
 | 
			
		||||
    dom.btn_db_import.click(function () {
 | 
			
		||||
        alert('not implement.');
 | 
			
		||||
 | 
			
		||||
        var _fn_sure = function (cb_stack, cb_args) {
 | 
			
		||||
            var html = '<input id="upload-file" type="file" name="sqlfile" class="hidden" value="" style="display: none;"/>';
 | 
			
		||||
            dom.btn_db_import.after($(html));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue