コード例 #1
0
 def _create_schema(self, session, database, schema, auths, options,
                    **kwargs):
     """create new schema intance on database_id"""
     req = kwargs.pop('req')
     try:
         local_ip, port = self._get_entity(req, int(database.reflection_id))
         if local_ip == 'unkonwn' or port == 0:
             raise exceptions.AcceptableDbError('Database not online')
         connection = connformater % dict(user=database.user,
                                          passwd=database.passwd,
                                          host=local_ip,
                                          port=port,
                                          schema=schema)
         engine = create_engine(connection,
                                thread_checkin=False,
                                poolclass=NullPool)
         utils.create_schema(engine,
                             auths=auths,
                             character_set=options.get('character_set'),
                             collation_type=options.get('collation_type'),
                             connection_timeout=3)
         yield local_ip, port
     except Exception:
         if LOG.isEnabledFor(logging.DEBUG):
             LOG.exception('Create schema fail')
         raise
コード例 #2
0
ファイル: __init__.py プロジェクト: lolizeppelin/gopdb
    def unbond(self, cfgfile, postrun, timeout,
               **kwargs):
        """slave unbond master database"""
        conf = CONF[common.DB]
        master = kwargs.pop('master')
        schemas = master.get('schemas')
        ready = master.get('ready')
        force = kwargs.pop('force', False)
        config = self.config_cls.load(cfgfile)
        sockfile = config.get('socket')

        master_name = 'masterdb-%(database_id)s' % master

        with self._lower_conn(sockfile, conf.localroot, conf.localpass,
                              schema=None, raise_on_warnings=False) as conn:
            LOG.info('Login mysql from unix sock success, try stop salve and unbond')
            # check schemas
            if (set(schemas) - set(self._schemas(conn))) and not force:
                raise exceptions.AcceptableDbError('Slave schemas not same as master %(database_id)s' % master)
            slaves = self._slave_status(conn)
            for slave_status in slaves:
                if slave_status.get('Connection_name') == master_name:
                    if LOG.isEnabledFor(logging.DEBUG):
                        for key in slave_status.keys():
                            LOG.debug('UNBOND SLAVE %s STATUS ------ %s : %s'
                                      % (master_name, key, slave_status[key]))
                    running = False
                    if slave_status.get('Slave_IO_Running').lower() == 'yes' \
                            or slave_status.get('Slave_SQL_Running').lower() == 'yes':
                        running = True

                    if running:
                        if ready and not force:
                            raise exceptions.AcceptableDbError('Slave thread is running')

                        cursor = conn.cursor()
                        cursor.execute("STOP SLAVE '%s'" % master_name)
                        cursor.close()

                    cursor = conn.cursor()
                    cursor.execute("RESET SLAVE '%s' ALL" % master_name)
                    cursor.close()
                    break
        if postrun:
            postrun()
コード例 #3
0
ファイル: __init__.py プロジェクト: lolizeppelin/gopdb
 def start_database(self, database_id, **kwargs):
     session = endpoint_session(readonly=True)
     query = model_query(session,
                         GopDatabase,
                         filter=GopDatabase.database_id == database_id)
     _database = query.one()
     if _database.status != common.OK:
         raise exceptions.AcceptableDbError('Database is not OK now')
     return self._start_database(_database, **kwargs)
コード例 #4
0
 def _delete_schema(self, session, database, schema, **kwargs):
     """delete schema intance on reflection_id"""
     req = kwargs.pop('req')
     local_ip, port = self._get_entity(req, int(database.reflection_id))
     if port <= 0:
         raise exceptions.AcceptableDbError(
             'Can not find Database port, not init finished')
     if not local_ip:
         raise exceptions.AcceptableDbError('Database agent is offline now')
     conn = connformater % dict(user=database.user,
                                passwd=database.passwd,
                                schema=schema.schema,
                                host=local_ip,
                                port=port)
     engine = create_engine(conn, thread_checkin=False, poolclass=NullPool)
     dropauths = None
     if schema.user != database.user:
         dropauths = privilegeutils.mysql_privileges(schema)
     utils.drop_schema(engine, dropauths)
     yield local_ip, port
コード例 #5
0
ファイル: __init__.py プロジェクト: lolizeppelin/gopdb
    def show_schema(self, database_id, schema, **kwargs):
        """show schema info"""
        session = endpoint_session()
        query = model_query(session,
                            GopSchema,
                            filter=and_(GopSchema.database_id == database_id,
                                        GopSchema.schema == schema))
        secret = kwargs.pop('secret', False)
        show_quotes = kwargs.pop('quotes', False)
        if show_quotes:
            query = query.options(joinedload(GopSchema.quotes,
                                             innerjoin=False))
        _schema = query.one_or_none()
        if not _schema:
            raise exceptions.AcceptableSchemaError(
                'Schema not not be found in %d' % database_id)

        _database = _schema.database
        if _database.slave:
            raise exceptions.AcceptableDbError(
                'Database is slave, can not get schema')

        _result = dict(database_id=database_id,
                       impl=_database.impl,
                       dbtype=_database.dbtype,
                       dbversion=_database.dbversion,
                       schema=_schema.schema,
                       schema_id=_schema.schema_id,
                       desc=_schema.desc)

        if show_quotes:
            _result.setdefault('quotes', [
                dict(quote_id=_quote.quote_id, desc=_quote.desc)
                for _quote in _schema.quotes
            ])

        if secret:
            _result.update({
                'user': _schema.user,
                'passwd': _schema.passwd,
                'ro_user': _schema.ro_user,
                'ro_passwd': _schema.ro_passwd
            })
        with self._show_schema(session, _database, _schema,
                               **kwargs) as address:
            host = address[0]
            port = address[1]
            _result.setdefault('host', host)
            _result.setdefault('port', port)
        return _result
コード例 #6
0
ファイル: __init__.py プロジェクト: lolizeppelin/gopdb
    def bondslave(self, cfgfile, postrun, timeout, dbinfo,
                  **kwargs):
        """master bond salve"""
        conf = CONF[common.DB]
        replication = kwargs.pop('replication')
        schemas = kwargs.pop('schemas')
        cf = self.config_cls.load(cfgfile)
        sockfile = cf.get('socket')
        if not cf.get('log-bin'):
            if schemas:
                raise exceptions.AcceptableDbError('Databaes bin log is off in config file')
            LOG.warning('Database log-bin not open, try open it')
            cf.binlog()
            with self._lower_conn(sockfile, conf.localroot, conf.localpass,
                                  schema=None, raise_on_warnings=False) as conn:
                if self._binlog_on(conn):
                    LOG.error('Config file %s value error on log bin' % cfgfile)
                    raise exceptions.UnAcceptableDbError('Log bin is on in mysql process but off in config')
                if self._master_status(conn):
                    raise exceptions.UnAcceptableDbError('Bin log has been opened but now closed')
            cf.save(cfgfile)
            LOG.info('log bin opened in config file, try restart mysql')
            self.stop(cfgfile, timeout=3)
            self.start(cfgfile)
            if not os.path.exists(sockfile):
                eventlet.sleep(1)

        sqls = []
        sqls.append("grant %(privileges)s on *.* to '%(user)s'@'%(source)s' IDENTIFIED by '%(passwd)s'"
                    % replication)
        sqls.append("FLUSH PRIVILEGES")
        if not schemas:
            sqls.append("RESET MASTER")
        with self._lower_conn(sockfile, conf.localroot, conf.localpass) as conn:
            LOG.info('Login mysql from unix sock %s success, try bond slave' % sockfile)
            if not self._binlog_on(conn):
                raise exceptions.AcceptableDbError('Database binlog is off')
            if set(schemas) != set(self._schemas(conn)):
                raise exceptions.UnAcceptableDbError('Master schemas record not the same with schemas in entity')
            if schemas:
                if not kwargs.get('file') or not kwargs.get('position'):
                    raise exceptions.AcceptableSchemaError('Database got schemas, need file and position')
                LOG.warning('Database add slave with schemas already exist')
            for sql in sqls:
                LOG.debug(sql)
                cursor = conn.cursor()
                cursor.execute(sql)
                cursor.close()
            if schemas:
                binlog = dict(File=kwargs.get('file'), Position=kwargs.get('position'))
            else:
                binlog = self._master_status(conn)
        LOG.info('Grant privileges for replication user success')
        if postrun:
            try:
                postrun(binlog, schemas)
            except Exception as e:
                LOG.error('Bond slave fail with exception %s' % e.__class__.__name__)
                sqls = []
                if not replication.get('schema'):
                    replication['schema'] = '*'
                sqls.append("REVOKE %(privileges)s ON %(schema)s.* FROM '%(user)s'@'%(source)s'" % replication)
                sqls.append("DROP USER '%(user)s'@'%(source)s'" % replication)
                sqls.append("FLUSH PRIVILEGES")
                try:
                    with self._lower_conn(sockfile, conf.localroot, conf.localpass) as conn:
                        for sql in sqls:
                            LOG.debug(sql)
                            cursor = conn.cursor()
                            cursor.execute(sql)
                            cursor.close()
                # TODO change Exception type
                except Exception:
                    LOG.error('Drop user fail')
                LOG.info('Bond fail, revoke user privilege success')
                raise e
コード例 #7
0
ファイル: __init__.py プロジェクト: lolizeppelin/gopdb
    def bond(self, cfgfile, postrun, timeout, dbinfo,
             **kwargs):
        """slave bond to master database"""
        conf = CONF[common.DB]
        master = kwargs.pop('master')
        schemas = set(master.pop('schemas'))
        force = kwargs.pop('force', False)
        config = self.config_cls.load(cfgfile)
        sockfile = config.get('socket')

        auth = privilegeutils.mysql_slave_replprivileges(slave_id=dbinfo.get('database_id'), **master)
        master_name = 'masterdb-%(database_id)s' % auth
        sql = "CHANGE MASTER 'masterdb-%(database_id)s' TO MASTER_HOST='%(host)s', MASTER_PORT=%(port)d," \
              "MASTER_USER='******',MASTER_PASSWORD='******'," \
              "MASTER_LOG_FILE='%(file)s',MASTER_LOG_POS=%(position)s" % auth
        LOG.info('Replication connect sql %s' % sql)

        with self._lower_conn(sockfile, conf.localroot, conf.localpass) as conn:
            LOG.info('Login mysql from unix sock %s success, try bond master' % sockfile)

            if schemas & set(self._schemas(conn)):
                raise exceptions.AcceptableSchemaError('Schema with same name exist')
            LOG.info('Slave channel name %s' % master_name)
            slaves = self._slave_status(conn)
            for slave_status in slaves:
                channel = slave_status.get('Connection_name')
                host = slave_status.get('Master_Host')
                port = slave_status.get('Master_Port')
                iothread = slave_status.get('Slave_IO_Running').lower()
                epos = slave_status.get('Exec_Master_Log_Pos')
                rpos = slave_status.get('Read_Master_Log_Pos')
                bsecond = slave_status.get('Seconds_Behind_Master')
                if channel != master_name and (host == auth.get('host') and port == auth.get('port')):
                    LOG.info('Bond slave find same host and port with different channel name %s' % channel)
                    if iothread == 'yes':
                        raise exceptions.AcceptableDbError('Slave with channel name %s '
                                                           'is running in same host:port' % channel)
                    if epos != 0 or rpos != 0 or bsecond != 0:
                        if not force:
                            raise exceptions.AcceptableDbError('Channel %s pos not zero, need force' %
                                                               channel)
                    LOG.warning('Reset slave channel %s' % channel)
                    if LOG.isEnabledFor(logging.DEBUG):
                        for key in slave_status.keys():
                            LOG.debug('BOND FIND OLD SLAVE %s STATUS ------ %s : %s'
                                      % (channel, key, slave_status[key]))
                    cursor = conn.cursor()
                    cursor.execute("RESET SLAVE '%s' ALL" % channel)
                    cursor.close()
                    break
                elif channel == master_name:
                    LOG.info('Bond slave find same channel')
                    if host != auth.get('host') or port != auth.get('port'):
                        if iothread == 'yes':
                            raise exceptions.AcceptableDbError('Channel %s is running but '
                                                               'connection is not the same' % channel)
                    if epos != 0 or rpos != 0 or bsecond != 0:
                        if not force:
                            raise exceptions.AcceptableDbError('Channel %s pos not zero, need force' %
                                                               channel)
                    if LOG.isEnabledFor(logging.DEBUG):
                        for key in slave_status.keys():
                            LOG.debug('BOND FIND OLD SLAVE %s STATUS ------ %s : %s'
                                      % (channel, key, slave_status[key]))
                    if iothread == 'yes':
                        cursor = conn.cursor()
                        cursor.execute("STOP SLAVE '%s'" % channel)
                        cursor.close()
                    cursor = conn.cursor()
                    cursor.execute("RESET SLAVE '%s' ALL" % channel)
                    cursor.close()
                    break

            cursor = conn.cursor()
            cursor.execute(sql)
            cursor.close()

            LOG.info('Connect to master success, try start slave')
            # master have no schemas auto start slave
            if not schemas:
                cursor = conn.cursor()
                cursor.execute("START SLAVE '%s'" % master_name)
                cursor.close()
                LOG.info('START SLAVE %s success' % master_name)

        if postrun:
            postrun()
コード例 #8
0
ファイル: __init__.py プロジェクト: lolizeppelin/gopdb
 def delete_schema(self, database_id, schema, **kwargs):
     """delete schema intance on reflection_id"""
     unquotes = set(kwargs.get('unquotes', []))
     ignores = set(kwargs.get('ignores', []))
     force = kwargs.get('force', False)
     session = endpoint_session()
     query = model_query(session,
                         GopDatabase,
                         filter=GopDatabase.database_id == database_id)
     query = query.options(joinedload(GopDatabase.schemas, innerjoin=False))
     with session.begin():
         _database = query.one()
         _result = dict(database_id=_database.database_id,
                        impl=_database.impl,
                        dbtype=_database.dbtype,
                        dbversion=_database.dbversion)
         if _database.slave:
             raise exceptions.AcceptableDbError(
                 'can not delete schema from slave database')
         squery = model_query(session,
                              GopSchema,
                              filter=and_(
                                  GopSchema.schema == schema,
                                  GopSchema.database_id == database_id))
         squery = squery.options(
             joinedload(GopSchema.quotes, innerjoin=False))
         _schema = squery.one()
         _result.setdefault('schema_id', _schema.schema_id)
         _slaves = [_slave.slave_id for _slave in _database.slaves]
         _slaves_q_query = model_query(
             session,
             SchemaQuote,
             filter=and_(SchemaQuote.schema_id == _schema.schema_id,
                         SchemaQuote.qdatabase_id.in_(_slaves)))
         quotes = {}
         # quote of slave
         slave_quotes = _slaves_q_query.all()
         for _quotes_list in (slave_quotes, _schema.quotes):
             if _quotes_list:
                 for _quote in _quotes_list:
                     quotes[_quote.quote_id] = _quote.desc
         # check quotes
         for quote_id, desc in quotes.items():
             if quote_id in unquotes:
                 quotes.pop(quote_id, None)
             if desc in ignores:
                 quotes.pop(quote_id, None)
         if quotes:
             if force:
                 for quote_id, desc in quotes.items():
                     LOG.warning('Quote %d: [%s] force delete' %
                                 (quote_id, desc))
             else:
                 raise exceptions.AcceptableSchemaError(
                     'Schema in quote, can not be delete')
         with self._delete_schema(session, _database, _schema,
                                  **kwargs) as address:
             host = address[0]
             port = address[1]
             _result.setdefault('host', host)
             _result.setdefault('port', port)
             _result.setdefault('schema', schema)
             squery.delete()
     return _result
コード例 #9
0
ファイル: __init__.py プロジェクト: lolizeppelin/gopdb
 def copy_schema(self, src_database_id, src_schema, dst_database_id,
                 dst_schema, auth, **kwargs):
     """create a schema"""
     auths = privilegeutils.mysql_privileges(auth)
     session = endpoint_session()
     query = model_query(session,
                         GopDatabase,
                         filter=GopDatabase.database_id.in_(
                             [src_database_id, dst_database_id]))
     query = query.options(joinedload(GopDatabase.schemas, innerjoin=False))
     src_database, dst_database = None, None
     for _database in query.all():
         if _database.database_id == src_database_id:
             if _database.slave:
                 raise exceptions.AcceptableDbError(
                     'Source database is not master')
             if not _database.passwd:
                 raise exceptions.AcceptableDbError(
                     'Source database has no passwd, can not copy')
             schemas = [_schema.name for _schema in _database.schemas]
             if src_schema not in schemas:
                 raise exceptions.AcceptableSchemaError(
                     'Source schemas %s not exist' % src_schema)
             src_database = _database
         elif _database.database_id == dst_database_id:
             if _database.slave:
                 raise exceptions.AcceptableDbError(
                     'Destination database is not master')
             if not _database.passwd:
                 raise exceptions.AcceptableDbError(
                     'Destination database has no passwd, can not copy')
             schemas = [_schema.name for _schema in _database.schemas]
             if dst_schema in schemas:
                 raise exceptions.AcceptableSchemaError(
                     'Destination schemas %s alreday exist' % dst_schema)
             dst_database = _database
     if not src_database or not dst_database:
         raise
     _result = dict(database_id=dst_database.database_id,
                    impl=dst_database.impl,
                    dbtype=dst_database.dbtype,
                    dbversion=dst_database.dbversion)
     with session.begin():
         with self._copy_schema(session, src_database, src_schema,
                                dst_database, dst_schema, auths,
                                **kwargs) as options:
             character_set = options[0] or 'utf8'
             collation_type = options[1]
             gop_schema = GopSchema(schema=dst_schema,
                                    database_id=dst_database.database_id,
                                    user=auth.get('user'),
                                    passwd=auth.get('passwd'),
                                    ro_user=auth.get('ro_user'),
                                    ro_passwd=auth.get('ro_passwd'),
                                    source=auth.get('source'),
                                    character_set=character_set,
                                    collation=collation_type)
             session.add(gop_schema)
             session.flush()
             _result.setdefault('schema_id', gop_schema.schema_id)
             _result.setdefault('schema', gop_schema.schema)
     return _result
コード例 #10
0
ファイル: __init__.py プロジェクト: lolizeppelin/gopdb
 def create_schema(self, database_id, schema, auth, options, **kwargs):
     """create new schema intance on reflection_id"""
     auths = privilegeutils.mysql_privileges(auth)
     bond = kwargs.get('bond')
     affinity = kwargs.get('affinity', None)
     session = endpoint_session()
     query = model_query(session,
                         GopDatabase,
                         filter=GopDatabase.database_id == database_id)
     query = query.options(joinedload(GopDatabase.schemas, innerjoin=False))
     quote_id = 0
     with session.begin():
         _database = query.one()
         _result = dict(database_id=database_id,
                        impl=_database.impl,
                        dbtype=_database.dbtype,
                        dbversion=_database.dbversion)
         if _database.slave:
             raise exceptions.AcceptableDbError(
                 'Database is slave, can not create schema')
         if _database.status != common.OK:
             raise exceptions.AcceptableDbError('Database is not OK now')
         if affinity is not None and (_database.affinity & affinity) == 0:
             raise exceptions.AcceptableDbError(
                 'Database affinity not match')
         schemas = [_schema.schema for _schema in _database.schemas]
         if schema in schemas:
             raise exceptions.AcceptableDbError('Duplicate schema name %s' %
                                                schema)
         options = options or {'character_set': 'utf8'}
         with self._create_schema(session, _database, schema, auths,
                                  options, **kwargs) as address:
             gop_schema = GopSchema(
                 schema=schema,
                 database_id=_database.database_id,
                 user=auth.get('user'),
                 passwd=auth.get('passwd'),
                 ro_user=auth.get('ro_user'),
                 ro_passwd=auth.get('ro_passwd'),
                 source=auth.get('source') or '%',
                 rosource=auth.get('rosource') or '%',
                 character_set=options.get('character_set'),
                 collation_type=options.get('collation_type'))
             session.add(gop_schema)
             session.flush()
             if bond:
                 _quote = SchemaQuote(schema_id=gop_schema.schema_id,
                                      qdatabase_id=_database.database_id,
                                      entity=bond.get('entity'),
                                      endpoint=bond.get('endpoint'),
                                      desc=bond.get('desc'))
                 session.add(_quote)
                 session.flush()
                 quote_id = _quote.quote_id
             host = address[0]
             port = address[1]
             _result.setdefault('host', host)
             _result.setdefault('port', port)
             _result.setdefault('character_set',
                                options.get('character_set'))
             _result.setdefault('collation_type',
                                options.get('collation_type'))
             _result.setdefault('schema_id', gop_schema.schema_id)
             _result.setdefault('schema', gop_schema.schema)
             _result.setdefault('quote_id', quote_id)
     return _result
コード例 #11
0
ファイル: __init__.py プロジェクト: lolizeppelin/gopdb
    def delete_database(self, database_id, master, **kwargs):
        """delete master database intance"""
        session = endpoint_session()
        query = model_query(session,
                            GopDatabase,
                            filter=GopDatabase.database_id == database_id)
        if master:
            query = query.options(
                joinedload(GopDatabase.schemas, innerjoin=False))
        else:
            query = query.options(
                joinedload(GopDatabase.quotes, innerjoin=False))

        with session.begin():
            _database = query.one()
            _result = dict(database_id=_database.database_id,
                           slave=_database.slave,
                           impl=_database.impl,
                           dbtype=_database.dbtype,
                           dbversion=_database.dbversion)
            # 删除主库
            if master:
                if _database.slave:
                    raise exceptions.AcceptableDbError(
                        'Target database is a salve database')
                if _database.schemas or _database.slaves:
                    raise exceptions.AcceptableDbError(
                        'can not delete master database, slaves or schemas exist'
                    )
                if model_count_with_key(session,
                                        SchemaQuote.qdatabase_id,
                                        filter=SchemaQuote.qdatabase_id ==
                                        _database.database_id):
                    raise exceptions.AcceptableDbError(
                        'Database in schema quote list')
                with self._delete_database(session, _database,
                                           **kwargs) as address:
                    host = address[0]
                    port = address[1]
                    _result.setdefault('host', host)
                    _result.setdefault('port', port)
                    query.delete()
            # 删除从库
            else:
                if not _database.slave:
                    raise exceptions.AcceptableDbError(
                        'Target database is not a slave database')
                if _database.quotes:
                    raise exceptions.AcceptableDbError(
                        'Target slave database in schema quote list')
                _masters = [
                    m[0] for m in model_query(session,
                                              GopSalveRelation.master_id,
                                              filter=GopSalveRelation.slave_id
                                              == database_id).all()
                ]
                if _masters:
                    masters = model_query(
                        session,
                        GopDatabase,
                        filter=and_(GopDatabase.database_id.in_(_masters),
                                    GopDatabase.slave == 0))
                    if len(_masters) != len(masters):
                        raise exceptions.UnAcceptableDbError(
                            'Target slave database master missed')
                    raise exceptions.AcceptableDbError(
                        'Slave is bond to masters, unbond before delete')

                with self._delete_database(session, _database,
                                           **kwargs) as address:
                    query.delete()
                    host = address[0]
                    port = address[1]
                    _result.setdefault('host', host)
                    _result.setdefault('port', port)
        return _result
コード例 #12
0
 def bond(self, req, database_id, schema, body=None):
     """schema quote"""
     body = body or {}
     database_id = int(database_id)
     slave = body.get('slave', True)
     slave_id = body.get('slave_id')
     desc = body.get('desc')
     esure = body.get('esure', True)
     quote_id = body.get('quote_id')
     entity = body.pop('entity', None)
     entity = int(entity) if entity is not None else None
     endpoint = body.pop(common.ENDPOINTKEY, None)
     if esure:
         if not endpoint or not entity:
             raise InvalidArgument(
                 'No endpoint info or entity, esure should be flase')
         # TODO log entity info
         entity_info = entity_controller.show(req=req,
                                              endpoint=endpoint,
                                              entity=entity)['data'][0]
     session = endpoint_session()
     query = model_query(session,
                         GopDatabase,
                         filter=and_(GopDatabase.database_id == database_id,
                                     GopDatabase.slave == 0))
     query = query.options(joinedload(GopDatabase.schemas, innerjoin=False))
     _database = query.one()
     _schema = None
     for __schema in _database.schemas:
         if __schema.schema == schema:
             _schema = __schema
             break
     if not _schema:
         raise exceptions.AcceptableSchemaError('Schema %s not found' %
                                                schema)
     quote_database_id = _database.database_id
     user = _schema.user
     passwd = _schema.passwd
     # glock = get_global().lock('entitys')
     # with glock(common.DB, [entity, ]):
     if slave:
         slaves = [
             _slave.slave_id for _slave in _database.slaves if _slave.ready
         ]
         if slave_id:
             if slave_id not in slaves:
                 raise exceptions.AcceptableDbError(
                     'Slave %d not found or not ready' % slave)
             quote_database_id = slave_id
         else:
             if slaves:
                 quote_database_id = slaves[0]
             else:
                 LOG.warning(
                     'Not slave database, use master database as slave')
         user = _schema.ro_user
         passwd = _schema.ro_passwd
     address = _address([
         quote_database_id,
     ]).get(quote_database_id)
     with session.begin():
         schema_quote = SchemaQuote(quote_id=quote_id,
                                    schema_id=_schema.schema_id,
                                    qdatabase_id=quote_database_id,
                                    entity=entity,
                                    endpoint=endpoint,
                                    desc=desc)
         session.add(schema_quote)
         session.flush()
     port = address.get('port')
     host = address.get('host')
     return resultutils.results(
         result='quote to %s.%d success' %
         (schema_quote.qdatabase_id, schema_quote.schema_id),
         data=[
             dict(schema_id=schema_quote.schema_id,
                  quote_id=schema_quote.quote_id,
                  qdatabase_id=quote_database_id,
                  host=host,
                  port=port,
                  user=user,
                  passwd=passwd,
                  schema=schema)
         ])