def status_database(self, database_id, **kwargs): session = endpoint_session(readonly=True) query = model_query(session, GopDatabase, filter=GopDatabase.database_id == database_id) _database = query.one() return self._status_database(_database, **kwargs)
def ready_relation(self, database_id, **kwargs): slave_id = kwargs.pop('slave') force = kwargs.pop('force') session = endpoint_session() query = model_query(session, GopSalveRelation, filter=and_( GopSalveRelation.master_id == database_id, GopSalveRelation.slave_id == slave_id)) with session.begin(subtransactions=True): relation = query.one_or_none() if not relation: raise InvalidArgument( 'Can not find relation of master %d slave %d' % (database_id, slave_id)) if relation.ready: return None if force: relation.ready = True return None query = model_query(session, GopDatabase, filter=GopDatabase.database_id.in_( [database_id, slave_id])) query = query.options( joinedload(GopDatabase.schemas, innerjoin=False)) for database in query: if database.database_id == database_id: master = database elif database.database_id == slave_id: slave = database return self._ready_relation(session, master, slave, relation, **kwargs)
def _address(database_ids): IMPLMAP = {} NOT_CACHED = [] for database_id in database_ids: if database_id in MANAGERCACHE: try: IMPLMAP[MANAGERCACHE[database_id]].append(database_id) except KeyError: IMPLMAP[MANAGERCACHE[database_id]] = [ database_id, ] else: NOT_CACHED.append(database_id) if NOT_CACHED: session = endpoint_session(readonly=True) query = model_query(session, (GopDatabase.database_id, GopDatabase.impl), filter=GopDatabase.database_id.in_(NOT_CACHED)) for r in query: dbmanager = utils.impl_cls('wsgi', r[1]) try: IMPLMAP[dbmanager].append(r[0]) except KeyError: IMPLMAP[dbmanager] = [ r[0], ] session.close() maps = dict() for dbmanager in IMPLMAP: maps.update(dbmanager.address(IMPLMAP[dbmanager])) return maps
def quote(self, req, quote_id, body=None): """show schema quote info""" body = body or {} session = endpoint_session(readonly=True) query = model_query(session, SchemaQuote, filter=SchemaQuote.quote_id == quote_id) schema_quote = query.one() data = dict( quote_id=quote_id, schema_id=schema_quote.schema_id, qdatabase_id=schema_quote.qdatabase_id, entity=schema_quote.entity, endpoint=schema_quote.endpoint, ) if body.get('schema', False): schema = schema_quote.schema data.setdefault( 'schema', dict(schema=schema.schema, character_set=schema.character_set, collation_type=schema.collation_type)) if body.get('database', False): database = schema_quote.database data.setdefault( 'database', dict(impl=database.impl, reflection_id=database.reflection_id, slave=database.slave, dbtype=database.dbtype, dbversion=database.dbversion)) return resultutils.results(result='get quote success', data=[ data, ])
def index(self, req, database_id, body=None): body = body or {} database_id = int(database_id) order = body.pop('order', None) desc = body.pop('desc', False) page_num = int(body.pop('page_num', 0)) session = endpoint_session(readonly=True) results = resultutils.bulk_results( session, model=GopSchema, columns=[ GopSchema.schema_id, GopSchema.schema, GopSchema.database_id, GopSchema.schema, GopSchema.character_set, GopSchema.collation_type, ], counter=GopSchema.schema_id, order=order, desc=desc, filter=GopSchema.database_id == database_id, page_num=page_num) return results
def create_database(self, user, passwd, dbtype, dbversion, affinity, **kwargs): """create new database intance""" session = endpoint_session() with session.begin(): bond = kwargs.pop('bond', None) if bond: query = model_query(session, GopDatabase, filter=GopDatabase.database_id == bond) bond = query.one_or_none() if not bond: raise InvalidArgument( 'Target slave databse can not be found, can not bond to slave databases' ) if not bond.slave: raise InvalidArgument( 'Target database is not salve database') if bond.status != common.OK: raise InvalidArgument('Targe slave database is not active') count = model_count_with_key( session, GopSalveRelation, filter=GopSalveRelation.slave_id == bond.database_id) if count >= bond.slave: raise InvalidArgument('Target slave database is full') else: bond = None _database = GopDatabase(user=user, passwd=passwd, slave=kwargs.pop('slave'), dbtype=dbtype, dbversion=dbversion, affinity=affinity, desc=kwargs.pop('desc', None)) _result = dict(dbversion=_database.dbversion, slave=_database.slave, dbtype=_database.dbtype) with self._create_database(session, _database, bond, **kwargs) as address: host = address[0] port = address[1] _result.setdefault('host', host) _result.setdefault('port', port) _result.setdefault('affinity', affinity) session.add(_database) session.flush() if bond: LOG.info('Add GopSalveRelation for database') relation = GopSalveRelation( master_id=_database.database_id, slave_id=bond.database_id) session.add(relation) session.flush() self._esure_create(_database, **kwargs) _result.setdefault('database_id', _database.database_id) return _result
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)
def address(self, databases): session = endpoint_session(readonly=True) query = model_query(session, GopDatabase, filter=GopDatabase.database_id.in_(databases)) databases = query.all() maps = dict() for database in databases: maps[database.reflection_id] = database.database_id return self._address(session, maps)
def slave_database(self, database_id, **kwargs): slave_id = kwargs.pop('slave') file = kwargs.get('file') position = kwargs.get('position') master = None slave = None session = endpoint_session() query = model_query(session, GopDatabase, filter=GopDatabase.database_id.in_( [database_id, slave_id])) query = query.options(joinedload(GopDatabase.slaves, innerjoin=False)) with session.begin(subtransactions=True): for database in query: if database.database_id == database_id: master = database elif database.database_id == slave_id: slave = database # 校验主从 if slave is None or slave.slave <= 0: raise InvalidArgument( 'slave database with id %d can not be found' % slave_id) if slave.status != common.OK: raise InvalidArgument('Slave database is not active') if master is None or master.slave > 0: raise InvalidArgument( 'Master database with id %d can not be found' % database_id) if master.impl != slave.impl or master.dbtype != slave.dbtype: raise InvalidArgument( 'Master and slave not the same type or impl') schemas = [schema.schema for schema in master.schemas] # master中有schemas if schemas: if not file or not position: raise InvalidArgument( 'Can not bond slave without file and position') for _relation in master.slaves: # 找到绑定关系 if _relation.slave_id == slave_id: raise InvalidArgument('Slave already in master slave list') # 没有绑定关系, 确认从库上限 count = model_count_with_key( session, GopSalveRelation, filter=GopSalveRelation.slave_id == slave_id) if count >= slave.slave: raise InvalidArgument('Target slave database is full') kwargs['schemas'] = schemas return self._slave_database(session, master, slave, **kwargs)
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
def _impl(database_id): try: return MANAGERCACHE[database_id] except KeyError: session = endpoint_session(readonly=True) try: database = model_query( session, GopDatabase, GopDatabase.database_id == database_id).one() if database_id not in MANAGERCACHE: dbmanager = utils.impl_cls('wsgi', database.impl) MANAGERCACHE.setdefault(database_id, dbmanager) return MANAGERCACHE[database_id] finally: session.close()
def reflect_database(self, **kwargs): session = endpoint_session(readonly=True) _result = [] with self._reflect_database(session, **kwargs) as filters: key = filters[0] _filter = filters[1] if _filter is None: return _result query = model_query(session, GopDatabase, filter=_filter) for _database in query: dbinfo = dict(database_id=_database.database_id, dbtype=_database.dbtype, slave=_database.slave) dbinfo.setdefault(key, _database.reflection_id) _result.append(dbinfo) return _result
def quotes(self, req, body=None): body = body or {} session = endpoint_session(readonly=True) endpoint = body.pop('endpoint') entitys = argutils.map_to_int(body.pop('entitys')) if len(entitys) > 5: raise InvalidArgument('This api can not get entitys more then 5') query = session.query( SchemaQuote.quote_id, SchemaQuote.schema_id, SchemaQuote.qdatabase_id, SchemaQuote.entity, SchemaQuote.endpoint, GopSchema.database_id, GopSchema.schema, GopSchema.user, GopSchema.passwd, GopSchema.ro_user, GopSchema.ro_passwd, GopSchema.character_set, GopSchema.collation_type, ).join(GopSchema, and_(GopSchema.schema_id == SchemaQuote.schema_id)) query = query.filter( and_(SchemaQuote.endpoint == endpoint, SchemaQuote.entity.in_(entitys))) quotes = [] database_ids = set() for quote in query: database_ids.add(quote.qdatabase_id) quotes.append( dict(quote_id=quote.quote_id, schema_id=quote.schema_id, qdatabase_id=quote.qdatabase_id, database_id=quote.database_id, schema=quote.schema, user=quote.user, passwd=quote.passwd, ro_user=quote.ro_user, ro_passwd=quote.ro_passwd, character_set=quote.character_set, collation_type=quote.collation_type)) # get all address alladdress = _address(database_ids) for quote in quotes: quote.update(alladdress[quote.get('qdatabase_id')]) return resultutils.results(result='list quotes success', data=quotes)
def index(self, req, body=None): body = body or {} order = body.pop('order', None) desc = body.pop('desc', False) page_num = int(body.pop('page_num', 0)) slaves = body.pop('slaves', False) # schemas = body.pop('schemas', False) # quotes = body.pop('quotes', False) impl = body.get('impl', None) session = endpoint_session(readonly=True) _filter = None if impl: _filter = GopDatabase.impl == impl columns = [ GopDatabase.database_id, GopDatabase.slave, GopDatabase.impl, GopDatabase.dbtype, GopDatabase.dbversion, GopDatabase.reflection_id, GopDatabase.status, GopDatabase.affinity, GopDatabase.desc ] option = None if slaves: columns.append(GopDatabase.slaves) option = joinedload(GopDatabase.slaves, innerjoin=False) results = resultutils.bulk_results(session, model=GopDatabase, columns=columns, counter=GopDatabase.database_id, order=order, desc=desc, option=option, filter=_filter, page_num=page_num) for column in results['data']: slaves = column.get('slaves', []) column['slaves'] = [] for slave in slaves: column['slaves'].append( dict(slave_id=slave.slave_id, master_id=column.get('database_id'), readonly=slave.readonly, ready=slave.ready)) return results
def phpadmin(self, req, database_id, schema, body=None): body = body or {} slave = body.get('slave', True) name = body.get('name') or ('unkonwn %s' % 'slave' if slave else 'master') session = endpoint_session(readonly=True) 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 InvalidArgument('Schema %s not found' % schema) target = _database.database_id user = _schema.user passwd = _schema.passwd if slave: slaves = [ _slave.slave_id for _slave in _database.slaves if _slave.ready ] if slaves: target = slaves[0] else: LOG.warning('Not slave database, use master database as slave') user = _schema.ro_user passwd = _schema.ro_passwd address = _address([ target, ]).get(target) port = address.get('port') host = address.get('host') return cache_controller.create(req, body=dict(host=host, port=port, user=user, passwd=passwd, schema=schema, client=req.client_addr, name=name))
def unbond_database(self, database_id, **kwargs): master_id = kwargs.pop('master') force = kwargs.get('force') master = None slave = None relation = None session = endpoint_session() query = model_query(session, GopDatabase, filter=GopDatabase.database_id.in_( [database_id, master_id])) query = query.options(joinedload(GopDatabase.slaves, innerjoin=False)) with session.begin(subtransactions=True): for database in query: if database.database_id == database_id: slave = database elif database.database_id == master_id: master = database # 校验主从 if slave is None or slave.slave <= 0: raise InvalidArgument( 'slave database with id %d can not be found' % database_id) if slave.status != common.OK: raise InvalidArgument('Slave database is not active') if master is None or master.slave > 0: raise InvalidArgument( 'Master database with id %d can not be found' % master_id) if master.impl != slave.impl or master.dbtype != slave.dbtype: raise InvalidArgument( 'Master and slave not the same type or impl') for _relation in master.slaves: if _relation.slave_id == database_id: # 找到绑定关系 relation = _relation break if not relation: raise InvalidArgument( 'Target slave database no relation with %d' % master.database_id) if master.schemas and not force: raise InvalidArgument( 'Schemas in master database, can not unbond without argv force' ) return self._unbond_database(session, master, slave, relation, **kwargs)
def update(self, req, database_id, body=None): body = body or {} status = body.get('status', common.UNACTIVE) if status not in (common.UNACTIVE, common.OK): raise InvalidArgument('Status value error') database_id = int(database_id) session = endpoint_session() query = model_query(session, GopDatabase, filter=GopDatabase.database_id == database_id) with session.begin(): updata = {'status': status} if body.get('dbversion'): updata.setdefault('dbversion', body.get('dbversion')) count = query.update(updata) if not count: LOG.warning('Update not match, no database has been updated') return resultutils.results(result='Update %s database success' % database_id)
def unquote(self, req, quote_id, body=None): """schema unquote""" body = body or {} session = endpoint_session() query = model_query(session, SchemaQuote, filter=SchemaQuote.quote_id == quote_id) with session.begin(): schema_quote = query.one() query.delete() return resultutils.results( result='unquote from %s.%d success' % ( schema_quote.qdatabase_id, schema_quote.schema_id, ), data=[ dict(quote_id=schema_quote.quote_id, schema_id=schema_quote.schema_id, qdatabase_id=schema_quote.qdatabase_id, entity=schema_quote.entity, endpoint=schema_quote.endpoint) ])
def slaves_address(self, databases): """get slve database connect info""" databases = set(databases) session = endpoint_session(readonly=True) query = model_query(session, GopDatabase, filter=GopDatabase.database_id.in_(databases)) databases = query.all() slaves = set([ slave.slave_id for database in databases for slave in database.slaves ]) address_maps = self.address(slaves) results = {} for database in databases: results[database.database_id] = [] for slave in database.slaves: results[database.database_id].append({ 'database_id': slave.slave_id, 'address': address_maps[slave.slave_id] }) return results
def select_database(self, **kwargs): dbtype = kwargs.pop('dbtype', 'mysql') filters = [ GopDatabase.status == common.OK, GopDatabase.dbtype == dbtype ] affinitys = kwargs.get('affinitys') if affinitys: affinitys = argutils.map_with(affinitys, int) ors = [] # 通过位运算匹配亲和性 for affinity in affinitys: ors.append(GopDatabase.affinity.op('&')(affinity) > 0) if len(ors) > 1: filters.append(or_(*ors)) else: filters.append(ors[0]) session = endpoint_session(readonly=True) query = model_query(session, GopDatabase, filter=and_(*filters)) query = query.options(joinedload(GopDatabase.schemas, innerjoin=False)) results = self._select_database(session, query, dbtype, **kwargs) # 结果按照亲和性从小到大排序 # 亲和性数值越大,匹配范围越广 results.sort(key=lambda x: x['affinity']) return results
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
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
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
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) ])
def bond_database(self, database_id, **kwargs): master_id = kwargs.pop('master') file = kwargs.get('file') position = kwargs.get('position') schemas = kwargs.get('schemas') if not file or not position: raise InvalidArgument( 'Can not bond slave without file and position') master = None slave = None relation = None session = endpoint_session() query = model_query(session, GopDatabase, filter=GopDatabase.database_id.in_( [database_id, master_id])) query = query.options(joinedload(GopDatabase.slaves, innerjoin=False)) with session.begin(subtransactions=True): for database in query: if database.database_id == database_id: slave = database elif database.database_id == master_id: master = database # 校验主从 if slave is None or slave.slave <= 0: raise InvalidArgument( 'slave database with id %d can not be found' % database_id) if slave.status != common.OK: raise InvalidArgument('Slave database is not active') if master is None or master.slave > 0: raise InvalidArgument( 'Master database with id %d can not be found' % master_id) if master.impl != slave.impl or master.dbtype != slave.dbtype: raise InvalidArgument( 'Master and slave not the same type or impl') _schemas = set([schema.schema for schema in master.schemas]) # 校验master中的schemas是否正确 if set(_schemas) != set(schemas): raise ValueError('Master schemas info error') for _relation in master.slaves: if _relation.slave_id == database_id: # 找到绑定关系 if _relation.ready: raise InvalidArgument( 'Slave already in master slave list') relation = _relation break # 没有绑定关系, 确认从库上限 if not relation: count = model_count_with_key( session, GopSalveRelation, filter=GopSalveRelation.slave_id == database_id) if count >= slave.slave: raise InvalidArgument('Target slave database is full') relation = GopSalveRelation(master_id=master.database_id, slave_id=slave.database_id) session.add(relation) session.flush() return self._bond_database(session, master, slave, relation, **kwargs)
def show_database(self, database_id, **kwargs): """show database info""" session = endpoint_session(readonly=True) quotes = kwargs.pop('quotes', False) query = model_query(session, GopDatabase, filter=GopDatabase.database_id == database_id) _database = query.one() if _database.slave: schemas = [] # slave will find masters schemas to show master_ids = model_query( session, GopSalveRelation.master_id, filter=GopSalveRelation.slave_id == database_id).all() if master_ids: query = model_query(session, GopDatabase, filter=and_( GopDatabase.database_id.in_( [m[0] for m in master_ids]), GopDatabase.slave == 0)) query = query.options( joinedload(GopDatabase.schemas, innerjoin=False)) for m_database in query.all(): schemas.extend(m_database.schemas) else: schemas = _database.schemas if quotes: quotes = [ dict(entity=quote.entity, endpoint=quote.endpoint, quote_id=quote.quote_id, schema_id=quote.schema_id) for quote in _database.quotes ] else: quotes = [] _result = dict(database_id=database_id, impl=_database.impl, dbtype=_database.dbtype, dbversion=_database.dbversion, status=_database.status, reflection_id=_database.reflection_id, slave=_database.slave, affinity=_database.affinity, schemas=[ dict(schema=schema.schema, schema_id=schema.schema_id) for schema in schemas ], quotes=quotes) if _database.slave: _result.setdefault('masters', master_ids) else: # show master database slaves _result.setdefault('slaves', _database.slaves) with self._show_database(session, _database, **kwargs) as address: host = address[0] port = address[1] _result.setdefault('host', host) _result.setdefault('port', port) return _result
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