Exemplo n.º 1
0
 def is_table_exists(self, table_name):
     """
     判断指定的表是否存在
     @param table_name: string
     @return: None or Boolean
     """
     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
         if len(ret) == 0:
             return False
         if ret[0][0] == 0:
             return False
         return True
     elif self.db_type == self.DB_TYPE_MYSQL:
         ret = self.query(
             'SELECT TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA="{}" and TABLE_NAME="{}";'
             .format(self.mysql_db, table_name))
         if ret is None:
             return None
         if len(ret) == 0:
             return False
         else:
             return True
     else:
         log.e('Unknown database type.\n')
         return None
Exemplo n.º 2
0
def read_record_info(record_id, file_id):
    record_path = os.path.join(app_cfg().core.replay_path, 'ssh',
                               '{:06d}'.format(int(record_id)))
    file_info = os.path.join(record_path, 'tp-ssh.{:03d}'.format(int(file_id)))
    file = None
    try:
        file = open(file_info, 'rb')
        data = file.read()
        total_size = len(data)

        offset = 0
        data_size, = struct.unpack_from('I', data, offset)
        offset += 4

        data_list = list()
        while True:
            action, = struct.unpack_from('B', data, offset)
            offset += 1

            _size, = struct.unpack_from('I', data, offset)
            offset += 4

            _time, = struct.unpack_from('I', data, offset)
            offset += 4

            # skip reserved 3 bytes.
            offset += 3

            _format = '{}s'.format(_size)
            _data, = struct.unpack_from(_format, data, offset)
            offset += _size

            temp = dict()
            temp['a'] = action
            temp['t'] = _time
            if action == 1:
                # this is window size changed.
                w, h = struct.unpack_from('HH', _data)
                temp['w'] = w
                temp['h'] = h
            elif action == 2:
                _data = _data.decode()
                # this is ssh data.
                temp['d'] = _data
            else:
                return None

            data_list.append(temp)
            if offset == total_size:
                break

    except Exception as e:
        log.e('failed to read record file: {}\n'.format(file_info))
        return None
    finally:
        if file is not None:
            file.close()
    return data_list
Exemplo n.º 3
0
 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
Exemplo n.º 4
0
    def alter_table(self, table_names, field_names=None):
        """
        修改表名称及字段名称
        table_name: 如果是string,则指定要操作的表,如果是list,则第一个元素是要操作的表,第二个元素是此表改名的目标名称
        fields_names: 如果为None,则不修改字段名,否则应该是一个list,其中每个元素是包含两个str的list,表示将此list第一个指定的字段改名为第二个指定的名称
        @return: None or Boolean
        """
        # TODO: 此函数尚未完成
        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

            if isinstance(table_names, str):
                old_table_name = table_names
                new_table_name = table_names
            elif isinstance(table_names, list) and len(table_names) == 2:
                old_table_name = table_names[0]
                new_table_name = table_names[1]
            else:
                log.w('invalid param.\n')
                return False

            if isinstance(field_names, list):
                for i in field_names:
                    if not isinstance(i, list) or 2 != len(i):
                        log.w('invalid param.\n')
                        return False

            if field_names is None:
                # 仅数据表改名
                return self.exec('ALTER TABLE `{}` RENAME TO `{}`;'.format(
                    old_table_name, new_table_name))
            else:
                # sqlite不支持字段改名,所以需要通过临时表中转一下

                # 先获取数据表的字段名列表
                ret = self.query(
                    'SELECT * FROM `sqlite_master` WHERE `type`="table" AND `name`="{}";'
                    .format(old_table_name))
                log.w('-----\n')
                log.w(ret[0][4])
                log.w('\n')

                # 先将数据表改名,成为一个临时表
                # tmp_table_name = '{}_sqlite_tmp'.format(old_table_name)
                # ret = self.exec('ALTER TABLE `{}` RENAME TO `{}`;'.format(old_table_name, tmp_table_name))
                # if ret is None or not ret:
                #     return ret

            pass
        elif self.db_type == self.DB_TYPE_MYSQL:
            log.e('mysql not supported yet.\n')
            return False
        else:
            log.e('Unknown database type.\n')
            return False
Exemplo n.º 5
0
 def _do_exec(self, conn, sql):
     try:
         with conn:
             conn.execute(sql)
         return True
     except Exception as e:
         log.e('[sqlite] _do_exec() failed: {}\n'.format(e.__str__()))
         log.e('[sqlite] SQL={}'.format(sql))
         return False
Exemplo n.º 6
0
 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('[sqlite] _do_query() failed: {}\n'.format(e.__str__()))
         log.e('[sqlite] SQL={}'.format(sql))
     finally:
         cursor.close()
Exemplo n.º 7
0
    def _do_connect(self):
        if not os.path.exists(self._db_file):
            log.e('[sqlite] can not connect, database file not exists.\n')
            return None

        try:
            return sqlite3.connect(self._db_file)
        except:
            log.e(
                '[sqlite] can not connect, does the database file correct?\n')
            return None
Exemplo n.º 8
0
 def _do_transaction(self, conn, sql_list):
     try:
         # 使用context manager,发生异常时会自动rollback,正常执行完毕后会自动commit
         with conn:
             for sql in sql_list:
                 conn.execute(sql)
         return True
     except Exception as e:
         log.e('[sqlite] _do_transaction() failed: {}\n'.format(
             e.__str__()))
         return False
Exemplo n.º 9
0
 def _do_exec(self, conn, sql):
     cursor = conn.cursor()
     try:
         cursor.execute(sql)
         conn.commit()
         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()
Exemplo n.º 10
0
 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()
Exemplo n.º 11
0
 def _last_insert_id(self, conn):
     cursor = conn.cursor()
     try:
         cursor.execute('SELECT LAST_INSERT_ID();')
         db_ret = cursor.fetchall()
         conn.commit()
         return db_ret[0][0]
     except Exception as e:
         log.e('[mysql] _last_insert_id() failed: {}\n'.format(e.__str__()))
         return -1
     finally:
         cursor.close()
Exemplo n.º 12
0
    def _upgrade_to_v5(self):
        _step = self.step_begin('检查数据库版本v5...')

        # 服务端升级到版本2.1.0.1时,为解决将来数据库升级的问题,在 ts_config 表中加入 db_ver 指明当前数据结构版本
        try:
            # 判断依据:
            # 如果 config 表中不存在名为db_ver的数据,说明是旧版本,需要升级

            if not self.db.is_table_exists('{}config'.format(
                    self.db.table_prefix)):
                if not self.db.exec("""CREATE TABLE `{}config` (
    `name`  varchar(256) NOT NULL,
    `value`  varchar(256),
    PRIMARY KEY (`name` ASC)
);""".format(self.db.table_prefix)):
                    self.step_end(_step, -1, 'config表不存在且无法创建')
                    return False

            db_ret = self.db.query(
                'SELECT `value` FROM `{}config` WHERE `name`="db_ver";'.format(
                    self.db.table_prefix))
            if db_ret is None:
                self.step_end(_step, -1)
                return False
            if len(db_ret) > 0 and int(db_ret[0][0]) >= self.db.DB_VERSION:
                self.step_end(_step, 0, '跳过 v4 到 v5 的升级操作')
                return True
            self.step_end(_step, 0, '需要升级到v5')

            _step = self.step_begin(' - 调整数据表字段名与表名')
            if not self.db.exec(
                    'ALTER TABLE `{}cert` RENAME TO `{}key`;'.format(
                        self.db.table_prefix, 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(
                    'INSERT INTO `{}config` VALUES ("db_ver", "{}");'.format(
                        self.db.table_prefix, self.db.DB_VERSION)):
                self.step_end(_step, -1)
                return False
            else:
                self.step_end(_step, 0)
                return True

        except:
            log.e('failed.\n')
            self.step_end(_step, -1)
            return False
Exemplo n.º 13
0
    def _do_exec(self, conn, sql):
        for retry in range(2):
            cursor = conn.cursor()
            try:
                cursor.execute(sql)
                conn.commit()
                return True
            except pymysql.err.OperationalError as e:
                errno, _ = e.args
                if retry == 1 or errno not in [2006, 2013]:
                    log.v('[mysql] SQL={}\n'.format(sql))
                    log.e('[mysql] _do_exec() failed: {}\n'.format(
                        e.__str__()))
                    return None

                log.w('[mysql] lost connection, reconnect.\n')
                with self._locker:
                    thread_id = threading.get_ident()
                    if thread_id not in self._connections:
                        log.e('[mysql] database pool internal error.\n')
                        return None
                    _conn = self._do_connect()
                    if _conn is not None:
                        self._connections[thread_id] = _conn
                        conn = _conn
                    else:
                        return None

            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()
Exemplo n.º 14
0
 def _do_connect(self):
     try:
         return pymysql.connect(host=self._host,
                                user=self._user,
                                passwd=self._password,
                                db=self._db_name,
                                port=self._port,
                                autocommit=False,
                                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
Exemplo n.º 15
0
 def _do_transaction(self, conn, sql_list):
     cursor = conn.cursor()
     try:
         conn.begin()
         for sql in sql_list:
             cursor.execute(sql)
         conn.commit()
         return True
     except Exception as e:
         conn.rollback()
         log.e('[mysql] _do_transaction() failed: {}\n'.format(e.__str__()))
         return False
     finally:
         cursor.close()
Exemplo n.º 16
0
    def update_core(self, conf_data):
        # log.d('update core server config info.\n')
        self['core'] = AttrDict()

        if conf_data is None:
            log.w('core server config info is empty.\n')
            self['core']['detected'] = False
            return True

        try:
            self['core']['ssh'] = AttrDict()
            self['core']['ssh']['enable'] = False
            self['core']['ssh']['port'] = 52189
            if 'ssh' in conf_data:
                self['core']['ssh']['enable'] = conf_data['ssh']['enable']
                self['core']['ssh']['port'] = conf_data['ssh']['port']

            self['core']['rdp'] = AttrDict()
            self['core']['rdp']['enable'] = False
            self['core']['rdp']['port'] = 52089
            if 'rdp' in conf_data:
                self['core']['rdp']['enable'] = conf_data['rdp']['enable']
                self['core']['rdp']['port'] = conf_data['rdp']['port']

            self['core']['telnet'] = AttrDict()
            self['core']['telnet']['enable'] = False
            self['core']['telnet']['port'] = 52389
            if 'telnet' in conf_data:
                self['core']['telnet']['enable'] = conf_data['telnet'][
                    'enable']
                self['core']['telnet']['port'] = conf_data['telnet']['port']

            if 'replay-path' in conf_data:
                self['core']['replay_path'] = conf_data['replay-path']

            if 'web-server-rpc' in conf_data:
                self['core']['web_server_rpc'] = conf_data['web-server-rpc']
            if 'version' in conf_data:
                self['core']['version'] = conf_data['version']

            self['core']['detected'] = True

        except IndexError:
            log.e('invalid core config.\n')
            return False

        return True
Exemplo n.º 17
0
    def load(self, cfg_file):
        if not os.path.exists(cfg_file):
            log.e(
                'configuration file does not exists: [{}]\n'.format(cfg_file))
            return False
        try:
            _cfg = configparser.ConfigParser()
            _cfg.read(cfg_file)
        except:
            log.e('can not load configuration file: [{}]\n'.format(cfg_file))
            return False

        if not self._on_load(_cfg):
            return False

        self['_cfg_file'] = cfg_file
        return True
Exemplo n.º 18
0
    def run(self):

        settings = {
            #
            'cookie_secret': '8946svdABGD345fg98uhIaefEBePIfegOIakjFH43oETzK',

            'login_url': '/auth/login',

            # 指定静态文件的路径,页面模板中可以用 {{ static_url('css/main.css') }} 的方式调用
            'static_path': cfg.static_path,

            # 指定模板文件的路径
            'template_path': cfg.template_path,

            # 防止跨站伪造请求,参见 http://old.sebug.net/paper/books/tornado/#_7
            'xsrf_cookies': False,

            'autoescape': 'xhtml_escape',

            # 'ui_modules': ui_modules,
            'debug': False,

            # 不开启模板和静态文件的缓存,这样一旦模板文件和静态文件变化,刷新浏览器即可看到更新。
            'compiled_template_cache': False,
            'static_hash_cache': False,
        }

        from eom_app.controller import controllers
        web_app = tornado.web.Application(controllers, **settings)

        server = tornado.httpserver.HTTPServer(web_app)
        try:
            server.listen(cfg.server_port)
            log.i('works on [http://127.0.0.1:{}]\n'.format(cfg.server_port))
        except:
            log.e('Can not listen on port {}, maybe it been used by another application.\n'.format(cfg.server_port))
            return 0

        # 启动session超时管理
        web_session().start()

        tornado.ioloop.IOLoop.instance().start()

        web_session().stop()

        return 0
Exemplo n.º 19
0
    def update_core(self, conf_data):
        self.core = AttrDict()
        self.core.detected = False

        if conf_data is None:
            log.w('core server config info is empty.\n')
            return True

        try:
            self.core.ssh = AttrDict()
            self.core.ssh.enable = False
            self.core.ssh.port = 52189
            if 'ssh' in conf_data:
                self.core.ssh.enable = conf_data['ssh']['enable']
                self.core.ssh.port = conf_data['ssh']['port']

            self.core.rdp = AttrDict()
            self.core.rdp.enable = False
            self.core.rdp.port = 52089
            if 'rdp' in conf_data:
                self.core.rdp.enable = conf_data['rdp']['enable']
                self.core.rdp.port = conf_data['rdp']['port']

            self.core.telnet = AttrDict()
            self.core.telnet.enable = False
            self.core.telnet.port = 52389
            if 'telnet' in conf_data:
                self.core.telnet.enable = conf_data['telnet']['enable']
                self.core.telnet.port = conf_data['telnet']['port']

            if 'replay-path' in conf_data:
                self.core.replay_path = conf_data['replay-path']

            if 'web-server-rpc' in conf_data:
                self.core.web_server_rpc = conf_data['web-server-rpc']
            if 'version' in conf_data:
                self.core.version = conf_data['version']

            self.core.detected = True

        except IndexError:
            log.e('invalid core config.\n')
            return False

        return True
Exemplo n.º 20
0
    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, 'db', '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
        else:
            log.e('unknown database type `{}`, support sqlite/mysql now.\n'.
                  format(cfg.database.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
Exemplo n.º 21
0
    def init(self, options):
        log.initialize()

        cfg.app_path = os.path.abspath(options['app_path'])
        cfg.static_path = os.path.abspath(options['static_path'])
        cfg.data_path = os.path.abspath(options['data_path'])
        cfg.template_path = os.path.abspath(options['template_path'])
        cfg.res_path = os.path.abspath(options['res_path'])
        cfg.cfg_path = os.path.abspath(options['cfg_path'])

        _cfg_file = os.path.join(cfg.cfg_path, 'web.ini')
        if not cfg.load(_cfg_file):
            return False

        cfg.log_path = os.path.abspath(options['log_path'])
        cfg.log_file = os.path.join(cfg.log_path, 'tpweb.log')

        if not os.path.exists(cfg.log_path):
            utils.make_dir(cfg.log_path)
            if not os.path.exists(cfg.log_path):
                log.e('Can not create log path:{}\n'.format(cfg.log_path))
                return False

        log.set_attribute(min_level=cfg.log_level, filename=cfg.log_file)
        if cfg.debug:
            log.set_attribute(trace_error=log.TRACE_ERROR_FULL)

        # 尝试通过CORE-JSON-RPC获取core服务的配置(主要是ssh/rdp/telnet的端口)
        self._get_core_server_config()

        if not web_session().init():
            return False

        # 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

        return True
Exemplo n.º 22
0
    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
Exemplo n.º 23
0
    def create_and_init(self, step_begin, step_end):
        log.v('start database create and initialization process.\n')

        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.sqlite_file):
                try:
                    with open(self.sqlite_file, 'w') as f:
                        pass
                except:
                    log.e('can not create db file `{}`.\n'.format(
                        self.sqlite_file))
                    return False

        if create_and_init(self, step_begin, step_end):
            log.v('database created.\n')
            self.need_create = False
            return True
        else:
            log.e('database create and initialize failed.\n')
            return False
Exemplo n.º 24
0
 def is_field_exists(self, table_name, field_name):
     if self.db_type == self.DB_TYPE_SQLITE:
         ret = self.query('PRAGMA table_info(`{}`);'.format(table_name))
         print(ret)
         if ret is None:
             return None
         if len(ret) == 0:
             return False
         else:
             return True
     elif self.db_type == self.DB_TYPE_MYSQL:
         ret = self.query('DESC `{}` `{}`;'.format(table_name, field_name))
         print(ret)
         if ret is None:
             return None
         if len(ret) == 0:
             return False
         else:
             return True
     else:
         log.e('Unknown database type.\n')
         return None
Exemplo n.º 25
0
 def is_table_exists(self, table_name):
     """
     判断指定的表是否存在
     @param table_name: string
     @return: None or Boolean
     """
     if self.db_source['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
         if len(ret) == 0:
             return False
         if ret[0][0] == 0:
             return False
         return True
     elif self.db_source['type'] == self.DB_TYPE_MYSQL:
         return None
     else:
         log.e('Unknown database type.\n')
         return None
Exemplo n.º 26
0
    def _upgrade_to_v6(self):
        _step = self.step_begin('检查数据库版本v6...')

        # 服务端升级到版本2.2.9时,为增加双因子认证,为account表增加oath_secret字段
        db_ret = self.db.is_field_exists(
            '{}account'.format(self.db.table_prefix), 'oath_secret')
        if db_ret is None:
            self.step_end(_step, -1, '无法连接到数据库')
            return False
        if db_ret:
            self.step_end(_step, 0, '跳过 v5 到 v6 的升级操作')
            return True

        self.step_end(_step, 0, '需要升级到v6')

        try:

            _step = self.step_begin(' - 在account表中加入oath_secret字段')
            if not self.db.exec(
                    'ALTER TABLE {}account ADD oath_secret VARCHAR(64) DEFAULT ""'
                    .format(self.db.table_prefix)):
                self.step_end(_step, -1, '失败')
                return False

            _step = self.step_begin(' - 更新数据库版本号')
            if not self.db.exec(
                    'UPDATE `{}config` SET `value`="6" WHERE `name`="db_ver";'.
                    format(self.db.table_prefix)):
                self.step_end(_step, -1, '无法更新数据库版本号')
                return False
            else:
                self.step_end(_step, 0)
                return True

        except:
            log.e('failed.\n')
            self.step_end(_step, -1)
            return False
Exemplo n.º 27
0
    def load(self, cfg_file):
        if not os.path.exists(cfg_file):
            log.e(
                'configuration file does not exists: [{}]\n'.format(cfg_file))
            return False
        try:
            _cfg = configparser.ConfigParser()
            _cfg.read(cfg_file)
        except:
            log.e('can not load configuration file: [{}]\n'.format(cfg_file))
            return False

        if 'common' not in _cfg:
            log.e('invalid configuration file: [{}]\n'.format(cfg_file))
            return False

        _comm = _cfg['common']
        self['server_port'] = _comm.getint('port', 7190)
        self['log_file'] = _comm.get('log-file', None)
        if self['log_file'] is not None:
            self['log_path'] = os.path.dirname(self['log_file'])

        self['log_level'] = log.LOG_INFO
        _level = _comm.getint('log-level', 2)
        if _level == 0:
            self['log_level'] = log.LOG_DEBUG
        elif _level == 1:
            self['log_level'] = log.LOG_VERBOSE
        elif _level == 2:
            self['log_level'] = log.LOG_INFO
        elif _level == 3:
            self['log_level'] = log.LOG_WARN
        elif _level == 4:
            self['log_level'] = log.LOG_ERROR
        else:
            self['log_level'] = log.LOG_VERBOSE

        # log.set_attribute(min_level=self['log_level'])

        self['debug'] = False
        _debug = _comm.getint('debug', 0)
        if _debug == 1:
            self['log_level'] = log.LOG_DEBUG
            self['debug'] = True

        self['core_server_rpc'] = _comm.get('core-server-rpc',
                                            'http://127.0.0.1:52080/rpc')

        return True
Exemplo n.º 28
0
    def _upgrade_to_v2(self):
        # 服务端升级到版本1.2.102.3时,管理员后台和普通用户后台合并了,数据库略有调整

        _step = self.step_begin('检查数据库版本v2...')

        try:
            # 判断依据:
            # 如果存在名为 ${prefix}sys_user 的表,说明是旧版本,需要升级

            ret = self.db.is_table_exists('{}sys_user'.format(
                self.db.table_prefix))
            if ret is None:
                self.step_end(_step, -1, '无法连接到数据库')
                return False
            elif not ret:
                self.step_end(_step, 0, '跳过 v1 到 v2 的升级操作')
                return True
            self.step_end(_step, 0, '需要升级到v2')

            if self.db.db_source['type'] == self.db.DB_TYPE_SQLITE:
                _step = self.step_begin(' - 备份数据库文件')
                _bak_file = '{}.before-v1-to-v2'.format(
                    self.db.db_source['file'])
                if not os.path.exists(_bak_file):
                    shutil.copy(self.db.db_source['file'], _bak_file)
                self.step_end(_step, 0)

            # 将原来的普通用户的account_type从 0 改为 1
            _step = self.step_begin(' - 调整用户账号类型...')
            if not self.db.exec(
                    'UPDATE `{}account` SET `account_type`=1 WHERE `account_type`=0;'
                    .format(self.db.table_prefix)):
                self.step_end(_step, -1)
                return False
            else:
                self.step_end(_step, 0)

            # 将原来的管理员合并到用户账号表中
            _step = self.step_begin(' - 合并管理员和普通用户账号...')
            db_ret = self.db.query('SELECT * FROM `{}sys_user`;'.format(
                self.db.table_prefix))
            if db_ret is None:
                self.step_end(_step, 0)
                return True

            for i in range(len(db_ret)):
                user_name = db_ret[i][1]
                user_pwd = db_ret[i][2]

                if not self.db.exec("""INSERT INTO `{}account`
    (`account_type`, `account_name`, `account_pwd`, `account_status`, `account_lock`, `account_desc`)
    VALUES (100,"{}","{}",0,0,"{}");""".format(self.db.table_prefix, user_name,
                                               user_pwd, '超级管理员')):
                    self.step_end(_step, -1)
                    return False

            # 移除旧的表(暂时改名而不是真的删除)
            _step = self.step_begin(' - 移除不再使用的数据表...')
            if not self.db.exec(
                    'ALTER TABLE `{}sys_user` RENAME TO `_bak_ts_sys_user`;'.
                    format(self.db.table_prefix)):
                self.step_end(_step, 0)
                return False
            else:
                self.step_end(_step, -1)

            return True

        except:
            log.e('failed.\n')
            self.step_end(_step, -1)
            return False
Exemplo n.º 29
0
    def _upgrade_to_v4(self):
        _step = self.step_begin('检查数据库版本v4...')

        # 服务端升级到版本1.6.224.3时,加入telnet支持,数据库有调整
        try:
            # 判断依据:
            # 如果ts_host_info表中还有pro_port字段,说明是旧版本,需要升级

            db_ret = self.db.query(
                'SELECT `pro_port` FROM `{}host_info` LIMIT 0;'.format(
                    self.db.table_prefix))
            if db_ret is None:
                self.step_end(_step, 0, '跳过 v3 到 v4 的升级操作')
                return True
            self.step_end(_step, 0, '需要升级到v4')

            if self.db.db_source['type'] == self.db.DB_TYPE_SQLITE:
                _step = self.step_begin(' - 备份数据库文件')
                _bak_file = '{}.before-v3-to-v4'.format(
                    self.db.db_source['file'])
                if not os.path.exists(_bak_file):
                    shutil.copy(self.db.db_source['file'], _bak_file)
                self.step_end(_step, 0)

            _step = self.step_begin(' - 为telnet增加默认配置')
            # 如果ts_config表中没有ts_server_telnet_port项,则增加默认值52389
            db_ret = self.db.query(
                'SELECT * FROM `{}config` WHERE `name`="ts_server_telnet_port";'
                .format(self.db.table_prefix))
            if len(db_ret) == 0:
                if not self.db.exec(
                        'INSERT INTO `{}config` (`name`, `value`) VALUES ("ts_server_telnet_port", "52389");'
                        .format(self.db.table_prefix)):
                    self.step_end(_step, -1)
                    return False
            self.step_end(_step, 0)

            _step = self.step_begin(' - 调整认证数据表数据...')
            auth_info_ret = self.db.query(
                'SELECT `id`, `host_id`, `pro_type`, `auth_mode`, `user_name`, `user_pswd`, `cert_id`, `encrypt`, `log_time` FROM `{}auth_info`;'
                .format(self.db.table_prefix))
            auth_ret = self.db.query(
                'SELECT `auth_id`, `account_name`, `host_id`, `host_auth_id` FROM `{}auth`;'
                .format(self.db.table_prefix))

            max_host_id = 0
            new_host_info = []
            new_auth_info = []
            new_auth = []

            # 从原来的表中查询数据
            host_info_ret = self.db.query(
                'SELECT `host_id`, `group_id`, `host_sys_type`, `host_ip`, `pro_port`, `host_lock`, `host_desc` FROM {}host_info;'
                .format(self.db.table_prefix))
            if host_info_ret is None:
                self.step_end(_step, 0, '尚无认证数据,跳过处理')
                return True

            # 先找出最大的host_id,这样如果要拆分一个host,就知道新的host_id应该是多少了
            for i in range(len(host_info_ret)):
                if host_info_ret[i][0] > max_host_id:
                    max_host_id = host_info_ret[i][0]
            max_host_id += 1

            # 然后构建新的host列表
            for i in range(len(host_info_ret)):
                host_info = {}
                host_info_alt = None

                protocol = json.loads(host_info_ret[i][4])
                host_info['host_id'] = host_info_ret[i][0]
                host_info['group_id'] = host_info_ret[i][1]
                host_info['host_sys_type'] = host_info_ret[i][2]
                host_info['host_ip'] = host_info_ret[i][3]
                host_info['host_lock'] = host_info_ret[i][5]
                host_info['host_desc'] = host_info_ret[i][6]
                host_info['_old_host_id'] = host_info_ret[i][0]
                host_info['host_port'] = 0
                host_info['protocol'] = 0

                have_rdp = False
                have_ssh = False
                if auth_info_ret is not None:
                    for j in range(len(auth_info_ret)):
                        if auth_info_ret[j][1] == host_info['host_id']:
                            if auth_info_ret[j][2] == 1:  # 用到了此主机的RDP
                                have_rdp = True
                            elif auth_info_ret[j][2] == 2:  # 用到了此主机的SSH
                                have_ssh = True

                if have_rdp and have_ssh:
                    # 需要拆分
                    host_info['protocol'] = 1
                    host_info['host_port'] = protocol['rdp']['port']

                    host_info_alt = {}
                    host_info_alt['host_id'] = max_host_id
                    max_host_id += 1
                    host_info_alt['group_id'] = host_info_ret[i][1]
                    host_info_alt['host_sys_type'] = host_info_ret[i][2]
                    host_info_alt['host_ip'] = host_info_ret[i][3]
                    host_info_alt['host_lock'] = host_info_ret[i][5]
                    host_info_alt['host_desc'] = host_info_ret[i][6]
                    host_info_alt['_old_host_id'] = host_info_ret[i][0]
                    host_info_alt['host_port'] = protocol['ssh']['port']
                    host_info_alt['protocol'] = 2
                elif have_rdp:
                    host_info['protocol'] = 1
                    host_info['host_port'] = protocol['rdp']['port']
                elif have_ssh:
                    host_info['host_port'] = protocol['ssh']['port']
                    host_info['protocol'] = 2

                new_host_info.append(host_info)
                if host_info_alt is not None:
                    new_host_info.append(host_info_alt)

            # 现在有了新的ts_host_info表,重构ts_auth_info表
            if auth_info_ret is not None:
                for i in range(len(auth_info_ret)):
                    auth_info = {}
                    auth_info['id'] = auth_info_ret[i][0]
                    auth_info['auth_mode'] = auth_info_ret[i][3]
                    auth_info['user_name'] = auth_info_ret[i][4]
                    auth_info['user_pswd'] = auth_info_ret[i][5]
                    auth_info['cert_id'] = auth_info_ret[i][6]
                    auth_info['encrypt'] = auth_info_ret[i][7]
                    auth_info['log_time'] = auth_info_ret[i][8]
                    auth_info['user_param'] = 'ogin:\nassword:'
                    found = False
                    for j in range(len(new_host_info)):
                        if auth_info_ret[i][1] == new_host_info[j][
                                '_old_host_id'] and auth_info_ret[i][
                                    2] == new_host_info[j]['protocol']:
                            found = True
                            auth_info['host_id'] = new_host_info[j]['host_id']
                            auth_info['_old_host_id'] = new_host_info[j][
                                '_old_host_id']
                            break
                    if found:
                        new_auth_info.append(auth_info)

            # 最后重构ts_auth表
            if auth_ret is not None:
                for i in range(len(auth_ret)):
                    auth = {}
                    auth['auth_id'] = auth_ret[i][0]
                    auth['account_name'] = auth_ret[i][1]
                    found = False
                    for j in range(len(new_auth_info)):
                        if auth_ret[i][2] == new_auth_info[j][
                                '_old_host_id'] and auth_ret[i][
                                    3] == new_auth_info[j]['id']:
                            found = True
                            auth['host_id'] = new_auth_info[j]['host_id']
                            auth['host_auth_id'] = new_auth_info[j]['id']
                            break
                    if found:
                        new_auth.append(auth)

            self.step_end(_step, 0)
            _step = self.step_begin(' - 重新整理认证数据表结构及数据...')

            # 将整理好的数据写入新的临时表
            # 先创建三个临时表
            if not self.db.exec("""CREATE TABLE `{}auth_tmp` (
    `auth_id`  INTEGER PRIMARY KEY AUTOINCREMENT,
    `account_name`  varchar(256),
    `host_id`  INTEGER,
    `host_auth_id`  int(11) NOT NULL
    );""".format(self.db.table_prefix)):
                self.step_end(_step, -1, '无法创建认证数据临时表')
                return False

            if not self.db.exec("""CREATE TABLE `{}host_info_tmp` (
    `host_id`  integer PRIMARY KEY AUTOINCREMENT,
    `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(self.db.table_prefix)):
                self.step_end(_step, -1, '无法创建主机信息数据临时表')
                return False

            if not self.db.exec("""CREATE TABLE `{}auth_info_tmp` (
    `id`  INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
    `host_id`  INTEGER,
    `auth_mode`  INTEGER,
    `user_name`  varchar(256),
    `user_pswd`  varchar(256),
    `user_param` varchar(256),
    `cert_id`  INTEGER,
    `encrypt`  INTEGER,
    `log_time`  varchar(60)
    );""".format(self.db.table_prefix)):
                self.step_end(_step, -1, '无法创建认证信息数据临时表')
                return False

            for i in range(len(new_host_info)):
                sql = 'INSERT INTO `{}host_info_tmp` (`host_id`, `group_id`, `host_sys_type`, `host_ip`, `host_port`, `protocol`, `host_lock`, `host_desc`) ' \
                      'VALUES ({}, {}, {}, \'{}\', {}, {}, {}, "{}");'.format(
                    self.db.table_prefix,
                    new_host_info[i]['host_id'], new_host_info[i]['group_id'], new_host_info[i]['host_sys_type'],
                    new_host_info[i]['host_ip'], new_host_info[i]['host_port'], new_host_info[i]['protocol'],
                    new_host_info[i]['host_lock'], new_host_info[i]['host_desc']
                )
                if not self.db.exec(sql):
                    self.step_end(_step, -1, '无法调整数据(1)')
                    return False

            for i in range(len(new_auth_info)):
                sql = 'INSERT INTO `{}auth_info_tmp` (`id`, `host_id`, `auth_mode`, `user_name`, `user_pswd`, `user_param`, `cert_id`, `encrypt`, `log_time`) ' \
                      'VALUES ({}, {}, {}, "{}", "{}", "{}", {}, {}, "{}");'.format(
                    self.db.table_prefix,
                    new_auth_info[i]['id'], new_auth_info[i]['host_id'], new_auth_info[i]['auth_mode'],
                    new_auth_info[i]['user_name'], new_auth_info[i]['user_pswd'], new_auth_info[i]['user_param'],
                    new_auth_info[i]['cert_id'], new_auth_info[i]['encrypt'], '1'
                )
                if not self.db.exec(sql):
                    self.step_end(_step, -1, '无法调整数据(2)')
                    return False

            for i in range(len(new_auth)):
                sql = 'INSERT INTO `{}auth_tmp` (`auth_id`, `account_name`, `host_id`, `host_auth_id`) ' \
                      'VALUES ({}, \'{}\', {}, {});'.format(
                    self.db.table_prefix,
                    new_auth[i]['auth_id'], new_auth[i]['account_name'], new_auth[i]['host_id'], new_auth[i]['host_auth_id']
                )
                if not self.db.exec(sql):
                    self.step_end(_step, -1, '无法调整数据(3)')
                    return False

            # 表改名
            if not self.db.exec(
                    'ALTER TABLE `{}auth` RENAME TO `__bak_{}auth`;'.format(
                        self.db.table_prefix, self.db.table_prefix)):
                self.step_end(_step, -1, '无法处理临时表(1)')
                return False

            if not self.db.exec(
                    'ALTER TABLE `{}auth_info` RENAME TO `__bak_{}auth_info`;'.
                    format(self.db.table_prefix, self.db.table_prefix)):
                self.step_end(_step, -1, '无法处理临时表(2)')
                return False

            if not self.db.exec(
                    'ALTER TABLE `{}host_info` RENAME TO `__bak_{}host_info`;'.
                    format(self.db.table_prefix, self.db.table_prefix)):
                self.step_end(_step, -1, '无法处理临时表(3)')
                return False

            if not self.db.exec(
                    'ALTER TABLE `{}auth_tmp` RENAME TO `{}auth`;'.format(
                        self.db.table_prefix, self.db.table_prefix)):
                self.step_end(_step, -1, '无法处理临时表(4)')
                return False

            if not self.db.exec(
                    'ALTER TABLE `{}auth_info_tmp` RENAME TO `{}auth_info`;'.
                    format(self.db.table_prefix, self.db.table_prefix)):
                self.step_end(_step, -1, '无法处理临时表(5)')
                return False

            if not self.db.exec(
                    'ALTER TABLE `{}host_info_tmp` RENAME TO `{}host_info`;'.
                    format(self.db.table_prefix, self.db.table_prefix)):
                self.step_end(_step, -1, '无法处理临时表(6)')
                return False

            self.step_end(_step, 0)
            return True

        except:
            log.e('failed.\n')
            self.step_end(_step, -1)
            return False
Exemplo n.º 30
0
    def _upgrade_to_v3(self):
        # 服务端升级到版本1.5.217.9时,为了支持一机多用户多协议,数据库结构有较大程度改动

        _step = self.step_begin('检查数据库版本v3...')

        try:
            # 判断依据:
            # 如果不存在名为 ts_host_info 的表,说明是旧版本,需要升级

            ret = self.db.is_table_exists('{}host_info'.format(
                self.db.table_prefix))
            if ret is None:
                self.step_end(_step, -1)
                return False
            elif ret:
                self.step_end(_step, 0, '跳过 v2 到 v3 的升级操作')
                return True
            self.step_end(_step, 0, '需要升级到v3')

            if self.db.db_source['type'] == self.db.DB_TYPE_SQLITE:
                _step = self.step_begin(' - 备份数据库文件')
                _bak_file = '{}.before-v2-to-v3'.format(
                    self.db.db_source['file'])
                if not os.path.exists(_bak_file):
                    shutil.copy(self.db.db_source['file'], _bak_file)
                self.step_end(_step, 0)

            _step = self.step_begin(' - 调整数据表...')
            if not self.db.exec(
                    'ALTER TABLE `{}auth` ADD `host_auth_id` INTEGER;'.format(
                        self.db.table_prefix)):
                self.step_end(_step, -1, '无法在auth表中加入host_auth_id字段')
                return False

            if not self.db.exec(
                    'UPDATE `{}auth` SET `host_auth_id`=`host_id`;'.format(
                        self.db.table_prefix)):
                self.step_end(_step, -1,
                              '无法将auth表中host_auth_id字段的值均调整为host_id字段的值')
                return False

            if not self.db.exec(
                    'ALTER TABLE `{}log` ADD `protocol` INTEGER;'.format(
                        self.db.table_prefix)):
                self.step_end(_step, -1, '无法在log表中加入protocol字段')
                return False

            if not self.db.exec(
                    'UPDATE `{}log` SET `protocol`=1 WHERE `sys_type`=1;'.
                    format(self.db.table_prefix)):
                self.step_end(_step, -1, '无法修正log表中的protocol字段数据(1)')
                return False

            if not self.db.exec(
                    'UPDATE `{}log` SET `protocol`=2 WHERE `sys_type`=2;'.
                    format(self.db.table_prefix)):
                self.step_end(_step, -1, '无法修正log表中的protocol字段数据(2)')
                return False

            if not self.db.exec(
                    'UPDATE `{}log` SET `ret_code`=9999 WHERE `ret_code`=0;'.
                    format(self.db.table_prefix)):
                self.step_end(_step, -1, '无法修正log表中的ret_code字段数据')
                return False

            self.step_end(_step, 0)
            _step = self.step_begin(' - 拆分数据表...')

            # 新建两个表,用于拆分原来的 ts_host 表
            if not self.db.exec("""CREATE TABLE `{}host_info` (
    `host_id` integer PRIMARY KEY AUTOINCREMENT,
    `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)):
                self.step_end(_step, -1)
                return False

            if not self.db.exec("""CREATE TABLE `{}auth_info` (
    `id`  INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
    `host_id`  INTEGER,
    `pro_type`  INTEGER,
    `auth_mode`  INTEGER,
    `user_name`  varchar(256),
    `user_pswd`  varchar(256),
    `cert_id`  INTEGER,
    `encrypt`  INTEGER,
    `log_time`  varchar(60)
    );""".format(self.db.table_prefix)):
                self.step_end(_step, -1)
                return False

            # 将原来的 ts_host 表改名
            if not self.db.exec(
                    'ALTER TABLE `{}host` RENAME TO `_bak_{}host;`'.format(
                        self.db.table_prefix, self.db.table_prefix)):
                self.step_end(_step, -1)
                return False

            self.step_end(_step, 0)
            _step = self.step_begin(' - 调整数据内容...')

            # 从原来 ts_host 表中查询出所有数据
            db_ret = self.db.query('SELECT * FROM `_bak_{}host;`'.format(
                self.db.table_prefix))
            if db_ret is not None:
                for i in range(len(db_ret)):
                    host_id = db_ret[i][0]
                    group_id = db_ret[i][1]
                    host_sys_type = db_ret[i][2]
                    host_ip = db_ret[i][3]
                    host_pro_port = db_ret[i][4]
                    host_user_name = db_ret[i][5]
                    host_user_pwd = db_ret[i][6]
                    host_pro_type = db_ret[i][7]
                    cert_id = db_ret[i][8]
                    host_lock = db_ret[i][9]
                    host_encrypt = db_ret[i][10]
                    host_auth_mode = db_ret[i][11]
                    host_desc = db_ret[i][12]

                    _pro_port = {}
                    _pro_port['ssh'] = {}
                    _pro_port['ssh']['enable'] = 0
                    _pro_port['ssh']['port'] = 22
                    _pro_port['rdp'] = {}
                    _pro_port['rdp']['enable'] = 0
                    _pro_port['rdp']['port'] = 3389

                    if host_pro_type == 1:
                        _pro_port['rdp']['enable'] = 1
                        _pro_port['rdp']['port'] = host_pro_port
                    elif host_pro_type == 2:
                        _pro_port['ssh']['enable'] = 1
                        _pro_port['ssh']['port'] = host_pro_port
                    pro_port = json.dumps(_pro_port)

                    sql = 'INSERT INTO `{}host_info` (`host_id`, `group_id`, `host_sys_type`, `host_ip`, `pro_port`, `host_lock`, `host_desc`) ' \
                          'VALUES ({}, {}, {}, "{}", "{}", {}, "{}");'.format(self.db.table_prefix, host_id, group_id, host_sys_type, host_ip, pro_port, host_lock, host_desc)
                    if not self.db.exec(sql):
                        self.step_end(_step, -1)
                        return False

                    sql = 'INSERT INTO `{}auth_info` (`host_id`, `pro_type`, `auth_mode`, `user_name`, `user_pswd`, `cert_id`, `encrypt`, `log_time`) ' \
                          'VALUES ({}, {}, {}, "{}", "{}", {}, {}, "{}");'.format(self.db.table_prefix, host_id, host_pro_type, host_auth_mode, host_user_name, host_user_pwd, cert_id, host_encrypt, '1')
                    if not self.db.exec(sql):
                        self.step_end(_step, -1)
                        return False

            self.step_end(_step, 0)
            return True

        except:
            log.e('failed.\n')
            self.step_end(_step, -1)
            return False