def create(self, req, body=None): body = body or {} session = endpoint_session() name = utils.validate_string(body.get('name')) desc = body.get('desc') _group = Group(name=name, desc=desc, platfrom_id=0, warsvr=False) session.add(_group) try: session.flush() except DBDuplicateEntry: raise InvalidArgument('Group name duplicate') return resultutils.results(result='create group success', data=[ dict(group_id=_group.group_id, name=_group.name, platfrom_id=_group.platfrom_id, warsvr=_group.warsvr, desc=_group.desc) ])
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 create(self, req, database_id, body=None): """create schema in database with database_id """ body = body or {} database_id = int(database_id) jsonutils.schema_validate(body, self.CREATESCHEMA) auth = body.pop('auth', None) options = body.pop('options', None) schema = body.pop('schema', None) self._validate_schema(schema) kwargs = dict(req=req) kwargs.update(body) dbmanager = _impl(database_id) dbresult = dbmanager.create_schema(database_id, schema, auth, options, **kwargs) return resultutils.results(result='create empty schema success', data=[ dbresult, ])
def loginout(self, req, mid, body=None): body = body or {} mid = int(mid) session = endpoint_session(readonly=True) query = model_query(session, Manager, filter=Manager.mid == mid) manager = query.one() if TokenProvider.is_fernet(req): raise InvalidArgument('Manager use uuid token') token_id = TokenProvider.getid(req) if not token_id: raise InvalidArgument('Not token find, not login?') def checker(token): if token.get('mid') != mid: raise InvalidArgument('Mnager id not the same') TokenProvider.delete(req, token_id, checker) return resultutils.results( result='manager loginout success', data=[dict(name=manager.name, mid=manager.mid)])
def readlog(self, req, agent_id, body=None): """call by agent""" body = body or {} lines = body.get('lines', 10) rpc = get_client() metadata = BaseContorller.agent_metadata(agent_id) if metadata is None: raise RpcPrepareError('Can not get log from offline agent: %d' % agent_id) session = get_session() query = model_query(session, Agent, filter=Agent.agent_id == agent_id) agent = query.one() rpc_ret = rpc.call(targetutils.target_agent(agent), ctxt={'finishtime': rpcfinishtime()[0]}, msg={'method': 'readlog', 'args': {'lines': lines}}) if not rpc_ret: raise RpcResultError('Get log agent rpc result is None') if rpc_ret.get('resultcode') != manager_common.RESULT_SUCCESS: raise RpcResultError('Get log agent rpc result: ' + rpc_ret.get('result')) return resultutils.results(result=rpc_ret.get('result'), data=[rpc_ret.get('uri')])
def edit(self, req, agent_id, body=None): """call by agent""" # TODO check data in body body = body or {} ports_range = body.pop('ports_range', []) if ports_range: body.setdefault('ports_range', jsonutils.dumps_as_bytes(ports_range)) session = get_session() glock = get_global().lock('agents') with glock([agent_id, ]): data = body if not data: raise InvalidInput('Not data exist') with session.begin(): query = model_query(session, Agent, Agent.agent_id == agent_id) query.update(data) result = resultutils.results(pagenum=0, result='Update agent success', data=[body, ]) return result
def login(self, req, mid, body=None): """管理员登录""" body = body or {} passwd = body.get('passwd') session = endpoint_session(readonly=True) query = model_query(session, Manager, filter=Manager.name == mid) manager = query.one() if not passwd: raise InvalidArgument('Need passwd') if manager.passwd != digestutils.strmd5( manager.salt.encode('utf-8') + passwd): raise InvalidArgument('Password error') if TokenProvider.is_fernet(req): raise InvalidArgument('Manager use uuid token') token = TokenProvider.create(req, dict(mid=manager.mid, name=manager.name), 3600) return resultutils.results( result='manager login success', data=[dict(token=token, name=manager.name, mid=manager.mid)])
def readlog(self, req, endpoint, entity, body=None): body = body or {} path = body.get('path') lines = body.get('lines', 10) if not path or '..' in path: raise InvalidArgument('Path value error') endpoint = validateutils.validate_endpoint(endpoint) entity = int(entity) session = get_session(readonly=True) query = model_query(session, AgentEntity, filter=and_(AgentEntity.endpoint == endpoint, AgentEntity.entity == entity)) _entity = query.one_or_none() if not _entity: raise InvalidArgument('no entity found for %s' % endpoint) metadata = BaseContorller.agent_metadata(_entity.agent_id) if not metadata: raise InvalidArgument('Can not get log from off line agent') target = targetutils.target_agent_by_string(manager_common.APPLICATION, metadata.get('host')) target.namespace = endpoint rpc = get_client() rpc_ret = rpc.call(target, ctxt={'finishtime': rpcfinishtime()[0]}, msg={ 'method': 'readlog', 'args': { 'entity': entity, 'path': path, 'lines': lines } }) if not rpc_ret: raise RpcResultError('Get %s.%d log rpc result is None' % (endpoint, entity)) if rpc_ret.get('resultcode') != manager_common.RESULT_SUCCESS: raise InvalidArgument(('Get %s.%d log agent rpc result: ' % (endpoint, entity)) + rpc_ret.get('result')) return resultutils.results(result=rpc_ret.get('result'), data=[rpc_ret.get('uri')])
def index(self, req, agent_id, endpoint, body=None): body = body or {} show_ports = body.get('ports') endpoint = validateutils.validate_endpoint(endpoint) session = get_session(readonly=True) query = model_query(session, AgentEntity, filter=and_(AgentEntity.endpoint == endpoint, AgentEntity.agent_id == agent_id)) if show_ports: query = query.options( joinedload(AgentEntity.ports, innerjoin=False)) entitys = query.all() return resultutils.results( result='show endpoint entitys success', data=[ dict(entity=entity.entity, ports=[port.port for port in entity.ports] if show_ports else []) for entity in entitys ])
def send(self, req, agent_id, md5, body=None): """call by client, and asyncrequest send file to agents """ body = body or {} asyncrequest = self.create_asyncrequest(body) target = targetutils.target_all(fanout=True) async_ctxt = dict(pre_run=body.pop('pre_run', None), after_run=body.pop('after_run', None), post_run=body.pop('post_run', None)) rpc_method = 'getfile' rpc_args = {'md5': md5, 'timeout': asyncrequest.deadline - 1} rpc_ctxt = {} if agent_id != 'all': rpc_ctxt.setdefault('agents', self.agents_id_check(agent_id)) def wapper(): self.send_asyncrequest(asyncrequest, target, rpc_ctxt, rpc_method, rpc_args, async_ctxt) threadpool.add_thread(safe_func_wrapper, wapper, LOG) return resultutils.results(result='Send file to agents thread spawning', data=[asyncrequest.to_dict()])
def status(self, req, agent_id, body=None): """get status from agent, not from database do not need Idsformater, check it in send_asyncrequest """ body = body or {} body.setdefault('expire', 180) asyncrequest = self.create_asyncrequest(body) target = targetutils.target_all(fanout=True) rpc_ctxt = {} if agent_id != 'all': rpc_ctxt.setdefault('agents', self.agents_id_check(agent_id)) rpc_method = 'status_agent' rpc_args = body def wapper(): self.send_asyncrequest(asyncrequest, target, rpc_ctxt, rpc_method, rpc_args) threadpool.add_thread(safe_func_wrapper, wapper, LOG) return resultutils.results(result='Status agent async request thread spawning', data=[asyncrequest.to_dict()])
def show(self, req, cid, body=None): """显示漫画详细, 自动确认用户登陆登陆信息""" cid = int(cid) session = endpoint_session(readonly=True) query = model_query(session, Comic, filter=Comic.cid == cid) comic = query.one() if comic.status < 0: raise exceptions.ComicError('Comic status error') chapter = 0 point = comic.point uid, mid = online(req) # 管理员 if mid: point = common.MAXCHAPTERS # 已登陆,token经过校验 elif uid: query = model_query(session, UserOwn.chapter, filter=and_(UserOwn.uid == uid, UserOwn.cid == cid)) owns = query.one_or_none() if owns: chapter = owns.chapter elif comic.status == common.HIDE: raise exceptions.ComicError('Comic status error') return resultutils.results(result='show comic success', data=[ dict(cid=comic.cid, name=comic.name, author=comic.author, type=comic.type, region=comic.region, point=comic.point, last=comic.last, lastup=comic.lastup, ext=comic.ext, chapters=format_chapters( point, comic.chapters, chapter)) ])
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 paylogs(self, req, uid, body=None): """用户支付列表""" body = body or {} uid = int(uid) desc = body.get('desc', True) session = endpoint_session(readonly=True) query = model_query(session, UserPayLog, filter=UserPayLog.uid == uid) query = query.order_by( UserPayLog.time.desc() if desc else UserPayLog.time) return resultutils.results(result='list users paylogs success', data=[ dict(cid=paylog.cid, chapter=paylog.chapter, value=paylog.value, offer=paylog.offer, coin=paylog.coin, gift=paylog.gift, coins=paylog.coins, gifts=paylog.gifts, time=paylog.time) for paylog in query ])
def mark(self, req, cid, uid, body=None): """收藏漫画""" cid = int(cid) uid = int(uid) session = endpoint_session() if model_count_with_key(session, UserBook, filter=UserBook.uid == uid) >= common.MAXBOOKS: raise InvalidArgument('Mark over 50') query = model_query(session, Comic.name, filter=Comic.cid == cid) comic = query.one() try: session.add( UserBook(uid=uid, cid=cid, ext=comic.ext, name=comic.name, time=int(time.time()))) session.flush() except DBDuplicateEntry: LOG.warning('User alreday mark comic') return resultutils.results(result='mark book success', data=[dict(cid=comic.cid, name=comic.name)])
def notify(self, req, oid, body=None): body = body or {} if not isinstance(body, dict): raise InvalidArgument( 'Http body not json or content type is not application/json') oid = int(oid) now = int(time.time() * 1000) otime = uuidutils.Gprimarykey.timeformat(oid) if (now - otime) > 600000 or otime > now: raise InvalidArgument('Order id error or more the 600s') jsonutils.schema_validate(body, ESUREPAY) paypal = body.get('paypal') uid = body.get('uid') session = endpoint_session() query = model_query(session, Order, filter=Order.oid == oid) order = query.one() if order.uid != uid: raise InvalidArgument('User id not the same') if order.serial != paypal.get('paymentID'): raise InvalidArgument('paymentID not the same') try: self.record(session, order, None, None) except DBError: LOG.error('Ipay save order %d to database fail' % order.oid) raise return resultutils.results(result='notify orde success', data=[ dict(paypal=dict( paymentID=paypal.get('paymentID'), payerID=paypal.get('payerID')), oid=oid, coins=order.gift + order.coin, money=order.money) ])
def show(self, req, group_id, body=None): body = body or {} group_id = int(group_id) detail = body.get('detail', False) session = endpoint_session(readonly=True) query = model_query(session, Group, filter=Group.group_id == group_id) joins = joinedload(Group.entitys, innerjoin=False) if detail: joins = joins.joinedload(AppEntity.areas, innerjoin=False) query = query.options(joins) _group = query.one() group_info = dict(group_id=_group.group_id, name=_group.name, platfrom_id=_group.platfrom_id, warsvr=_group.warsvr, desc=_group.desc) if detail: _entitys = {} for entity in _group.entitys: objtype = entity.objtype entityinfo = dict(entity=entity.entity, status=entity.status) if objtype == common.GAMESERVER: entityinfo.setdefault('areas', [ dict(area_id=area.area_id, areaname=area.areaname, show_id=area.show_id) for area in entity.areas ]) try: _entitys[objtype].append(entityinfo) except KeyError: _entitys[objtype] = [ entityinfo, ] group_info.setdefault('entitys', _entitys) return resultutils.results(result='show group success', data=[ group_info, ])
def active(self, req, agent_id, body=None): """call buy client""" body = body or {} status = body.get('status', manager_common.ACTIVE) if status not in (manager_common.ACTIVE, manager_common.UNACTIVE): raise InvalidArgument('Argument status not right') rpc = get_client() session = get_session() query = model_query(session, Agent, filter=and_(Agent.agent_id == agent_id, Agent.status > manager_common.DELETED)) agent = query.one() # make sure agent is online metadata = BaseContorller.agent_metadata(agent.agent_id) if metadata is None: raise RpcPrepareError('Can not active or unactive a offline agent: %d' % agent_id) agent_ipaddr = metadata.get('local_ip') with session.begin(): agent.update({'status': status}) active_agent = rpc.call(targetutils.target_agent(agent), ctxt={'finishtime': rpcfinishtime()[0]}, msg={'method': 'active_agent', 'args': {'agent_id': agent_id, 'agent_ipaddr': agent_ipaddr, 'status': status} }) if not active_agent: raise RpcResultError('Active agent rpc result is None') if active_agent.pop('resultcode') != manager_common.RESULT_SUCCESS: raise RpcResultError('Call agent active or unactive fail: ' + active_agent.get('result')) result = resultutils.results(result=active_agent.pop('result'), data=[dict(agent_id=agent.agent_id, host=agent.host, agent_type=agent.agent_type, metadata=metadata, status=agent.status) ]) return result
def new(self, req, body=None): """发起订单""" body = body or {} if not isinstance(body, dict): raise InvalidArgument( 'Http body not json or content type is not application/json') jsonutils.schema_validate(body, NEWPAYMENT) money = body.get('money') uid = body.get('uid') cid = body.get('cid') chapter = body.get('chapter') start_time = int(time.time()) oid = uuidutils.Gkey() prepay_id, sign, random_str = weiXinApi.payment( money, oid, start_time, req) session = endpoint_session() coins = self.order(session, weiXinApi, None, uid, oid, money, cid, chapter, ext={'prepay_id': prepay_id}, order_time=start_time) return resultutils.results(result='create paypal payment success', data=[ dict(oid=oid, coins=coins, money=money, weixin=dict(prepay_id, time=start_time, sign=sign, random=random_str)) ])
def post_create_entity(self, entity, endpoint, **kwargs): entity = int(entity) endpoint = validateutils.validate_endpoint(endpoint) session = get_session(readonly=True) query = model_query(session, AgentEntity, filter=and_(AgentEntity.endpoint == endpoint, AgentEntity.entity == entity)) _entity = query.one() metadata = BaseContorller.agent_metadata(_entity.agent_id) if not metadata: raise RpcPrepareError('Agent not online, can not sen post create') target = targetutils.target_agent_by_string( metadata.get('agent_type'), metadata.get('host'), ) target.namespace = endpoint body = dict(entity=entity) body.update(kwargs) rpc = get_client() rpc.cast(target, ctxt={ 'finishtime': body.pop('finishtime', rpcfinishtime()[0]), 'entitys': [ entity, ] }, msg={ 'method': 'post_create_entity', 'args': body }) return resultutils.results(result='notify post create success', data=[ dict(entity=entity, agent_id=_entity.agent_id, endpoint=endpoint) ])
def agents(self, req, endpoint): session = get_session(readonly=True) endpoint = validateutils.validate_endpoint(endpoint) query = model_query(session, AgentEndpoint, filter=AgentEndpoint.endpoint == endpoint) agents = set() for endpoint in query.all(): agents.add(endpoint.agent_id) if not agents: raise InvalidArgument('No agent found for %s' % endpoint) query = model_query(session, Agent, filter=and_(Agent.status > manager_common.DELETED, Agent.agent_id.in_(agents))) return resultutils.results( result='get agent for %s success' % endpoint, data=[ dict(agent_id=agent.agent_id, agent_host=agent.host, cpu=agent.cpu, memory=agent.memory) for agent in query.all() ])
def login(self, req, username, body=None): body = body or {} password = body.get('password') if not password: raise InvalidArgument('Need password') _name_check(username) session = get_session(readonly=True) query = model_query(session, User, filter=User.username == username) userinfo = query.one() if userinfo.password != digestutils.strmd5( userinfo.salt.encode('utf-8') + password): raise InvalidArgument('Password error') token = dict(ip=req.client_addr, user=userinfo.username) token.update({service_common.ADMINAPI: True}) token_id = TokenProvider.create(req, token, 3600) LOG.debug('Auth login success') return resultutils.results(result='Login success', data=[ dict(username=username, id=userinfo.id, token=token_id, email=userinfo.email) ])
def create(self, req, body=None): body = body or {} jsonutils.schema_validate(body, self.CREATEDATABASE) impl = body.pop('impl') dbtype = body.pop('dbtype') user = body.pop('user') passwd = body.pop('passwd') dbversion = body.pop('dbversion', None) affinity = body.pop('affinity', 0) if body.get('slave'): if body.get('bond'): raise InvalidArgument( 'Slave database can not bond to another database ') affinity = 0 kwargs = dict(req=req) kwargs.update(body) dbmanager = utils.impl_cls('wsgi', impl) dbresult = dbmanager.create_database(user, passwd, dbtype, dbversion, affinity, **kwargs) return resultutils.results(result='create database success', data=[ dbresult, ])
def delete(self, req, agent_id, endpoint, entity, ports, body=None): body = body or {} ports = argutils.map_with(ports, validators['type:port']) strict = body.get('strict', True) if not ports: raise InvalidArgument('Ports is None for delete ports') for port in ports: if not isinstance(port, (int, long)): raise InvalidArgument( 'Port in ports not int, can not edit ports') if not (0 <= port <= 65535): raise InvalidArgument( 'Port in ports over range, can not edit ports') session = get_session() glock = get_global().lock('agents') with glock([ agent_id, ]): with session.begin(subtransactions=True): query = model_query(session, AllocatedPort, filter=and_( AllocatedPort.agent_id == agent_id, AllocatedPort.endpoint == endpoint, AllocatedPort.entity == entity, AllocatedPort.port.in_(ports))) delete_count = query.delete() need_to_delete = len(ports) if delete_count != len(ports): LOG.warning('Delete %d ports, but expect count is %d' % (delete_count, need_to_delete)) if strict: raise InvalidArgument( 'Submit %d ports, but only %d ports found' % (len(ports), need_to_delete)) return resultutils.results(result='edit ports success')
def new(self, req, body=None): """发起订单""" body = body or {} if not isinstance(body, dict): raise InvalidArgument( 'Http body not json or content type is not application/json') jsonutils.schema_validate(body, NEWPAYMENT) money = body.get('money') uid = body.get('uid') cid = body.get('cid') chapter = body.get('chapter') # h5 = bool(body.get('h5')) start_time = int(time.time()) oid = uuidutils.Gkey() transid, url, url_r, url_h = iPayApi.payment(money, oid, req) session = endpoint_session() coins = self.order(session, iPayApi, transid, uid, oid, money, cid, chapter, order_time=start_time) return resultutils.results(result='create ipay payment success', data=[ dict(ipay=dict(transid=transid, url=url, url_r=url_r, url_h=url_h), oid=oid, coins=coins, money=money) ])
def login(self, req, uid, body=None): """用户登录""" body = body or {} passwd = body.get('passwd') session = endpoint_session(readonly=True) query = model_query(session, User, filter=User.name == uid) user = query.one() if not passwd: raise InvalidArgument('Need passwd') if user.passwd != digestutils.strmd5(user.salt + passwd): raise InvalidArgument('Password error') if not TokenProvider.is_fernet(req): raise InvalidArgument('Not supported for uuid token') token = TokenProvider.create(req, dict(uid=user.uid, name=user.name), 3600) return resultutils.results(result='login success', data=[ dict(token=token, name=user.name, uid=user.uid, coins=(user.coins + user.gifts), platforms=Platforms, one=max(0, CF.one - user.offer)) ])
def create(self, req, body=None): """创建新漫画""" body = body or {} jsonutils.schema_validate(body, NEWCOMIC) name = body.get('name') type = body.get('type') region = body.get('region') author = body.get('author') ext = body.get('ext', 'webp') session = endpoint_session() comic = Comic(name=name, type=type, author=author, region=region, ext=ext) with _prepare_comic_path() as prepare: with session.begin(): session.add(comic) session.flush() prepare.ok(comic.cid) LOG.info('Create comic success') return resultutils.results(result='create comic success', data=[dict(cid=comic.cid, name=comic.name)])
def area(self, req, group_id, body=None): """change entity area""" body = body or {} try: group_id = int(group_id) except (TypeError, ValueError): raise InvalidArgument('Group id value error') area_id = body.get('area_id') areaname = body.get('areaname') show_id = body.get('show_id') if not areaname and not show_id: raise InvalidArgument('No value change') rpc = get_client() session = endpoint_session() query = model_query(session, GameArea, filter=GameArea.area_id == area_id) with session.begin(): area = query.one_or_none() if not area: raise InvalidArgument('No area found') if area.group_id != group_id: raise InvalidArgument('Area group not %d' % group_id) entityinfo = entity_controller.show(req=req, entity=area.entity, endpoint=common.NAME, body={'ports': False})['data'][0] agent_id = entityinfo['agent_id'] metadata = entityinfo['metadata'] if not metadata: raise InvalidArgument( 'Agent is off line, can not reset entity') if areaname: if model_count_with_key(session, GameArea, filter=and_( GameArea.group_id == group_id, GameArea.areaname == areaname)): raise InvalidArgument('Area name duplicate in group %d' % group_id) area.areaname = areaname if show_id: area.show_id = show_id target = targetutils.target_agent_by_string( metadata.get('agent_type'), metadata.get('host')) target.namespace = common.NAME finishtime, timeout = rpcfinishtime() rpc_ret = rpc.call(target, ctxt={ 'finishtime': finishtime, 'agents': [ agent_id, ] }, msg={ 'method': 'change_entity_area', 'args': dict(entity=area.entity, area_id=area.area_id, show_id=area.show_id, areaname=area.areaname) }, timeout=timeout) if not rpc_ret: raise RpcResultError('change entity area result is None') if rpc_ret.get('resultcode') != manager_common.RESULT_SUCCESS: raise RpcResultError('change entity area fail %s' % rpc_ret.get('result')) session.flush() return resultutils.results(result='change group areas success')
def clean(self, req, group_id, objtype, entity, body=None): """彻底删除entity""" body = body or {} action = body.pop('clean', 'unquote') force = False ignores = body.pop('ignores', []) if action not in ('delete', 'unquote', 'force'): raise InvalidArgument('clean option value error') if action == 'force': action = 'delete' force = True group_id = int(group_id) entity = int(entity) session = endpoint_session() glock = get_gamelock() metadata, ports = self._entityinfo(req=req, entity=entity) if not metadata: raise InvalidArgument('Agent offline, can not delete entity') query = model_query(session, AppEntity, filter=AppEntity.entity == entity) query = query.options(joinedload(AppEntity.databases, innerjoin=False)) _entity = query.one() rollbacks = [] def _rollback(): for back in rollbacks: __database_id = back.get('database_id') __schema = back.get('schema') __quote_id = back.get('quote_id') rbody = dict(quote_id=__quote_id, entity=entity) rbody.setdefault(dbcommon.ENDPOINTKEY, common.NAME) try: schema_controller.bond(req, database_id=__database_id, schema=__schema, body=rbody) except Exception: LOG.error('rollback entity %d quote %d.%s.%d fail' % (entity, __database_id, schema, __quote_id)) with glock.grouplock(group=group_id): target = targetutils.target_agent_by_string(metadata.get('agent_type'), metadata.get('host')) target.namespace = common.NAME rpc = get_client() finishtime, timeout = rpcfinishtime() LOG.warning('Clean entity %s.%d with action %s' % (objtype, entity, action)) with session.begin(): rpc_ret = rpc.call(target, ctxt={'finishtime': finishtime}, msg={'method': 'stoped', 'args': dict(entity=entity)}) if not rpc_ret: raise RpcResultError('check entity is stoped result is None') if rpc_ret.get('resultcode') != manager_common.RESULT_SUCCESS: raise RpcResultError('check entity is stoped fail, running') with session.begin(): if _entity.status != common.DELETED: raise InvalidArgument('Entity status is not DELETED, ' 'mark status to DELETED before delete it') if _entity.objtype != objtype: raise InvalidArgument('Objtype not match') if _entity.group_id != group_id: raise InvalidArgument('Group id not match') # esure database delete if action == 'delete': LOG.warning('Clean option is delete, can not rollback when fail') if not force: for _database in _entity.databases: schema = '%s_%s_%s_%d' % (common.NAME, objtype, _database.subtype, entity) schema_info = schema_controller.show(req=req, database_id=_database.database_id, schema=schema, body={'quotes': True})['data'][0] quotes = {} for _quote in schema_info['quotes']: quotes[_quote.get('quote_id')] = _quote.get('desc') if _database.quote_id not in quotes.keys(): # if set(quotes) != set([_database.quote_id]): result = 'delete %s:%d fail' % (objtype, entity) reason = ': database [%d].%s quote: %s' % (_database.database_id, schema, str(quotes)) return resultutils.results(result=(result + reason), resultcode=manager_common.RESULT_ERROR) quotes.pop(_database.quote_id) for quote_id in quotes.keys(): if quotes[quote_id] in ignores: quotes.pop(quote_id, None) if quotes: if LOG.isEnabledFor(logging.DEBUG): LOG.debug('quotes not match for %d: %s' % (schema_info['schema_id'], schema)) for quote_id in quotes.keys(): LOG.debug('quote %d: %s exist' % (quote_id, quotes[quote_id])) LOG.debug('Can not delete schema before delete quotes') return resultutils.results(result='Quotes not match', resultcode=manager_common.RESULT_ERROR) LOG.info('Databae quotes check success for %s' % schema) # clean database for _database in _entity.databases: schema = '%s_%s_%s_%d' % (common.NAME, objtype, _database.subtype, entity) if action == 'delete': LOG.warning('Delete schema %s from %d' % (schema, _database.database_id)) try: schema_controller.delete(req=req, database_id=_database.database_id, schema=schema, body={'unquotes': [_database.quote_id], 'ignores': ignores, 'force': force}) except GopdbError as e: LOG.error('Delete schema:%s from %d fail, %s' % (schema, _database.database_id, e.message)) if not force: raise e except Exception: LOG.exception('Delete schema:%s from %d fail' % (schema, _database.database_id)) if not force: raise elif action == 'unquote': LOG.info('Try unquote %d' % _database.quote_id) try: quote = schema_controller.unquote(req=req, quote_id=_database.quote_id)['data'][0] if quote.get('database_id') != _database.database_id: LOG.critical('quote %d with database %d, not %d' % (_database.quote_id, quote.get('database_id'), _database.database_id)) raise RuntimeError('Data error, quote database not the same') rollbacks.append(dict(database_id=_database.database_id, quote_id=_database.quote_id, schema=schema)) except Exception as e: LOG.error('Unquote %d fail, try rollback' % _database.quote_id) if not force: threadpool.add_thread(_rollback) raise e token = uuidutils.generate_uuid() LOG.info('Send delete command with token %s' % token) session.delete(_entity) session.flush() try: entity_controller.delete(req, common.NAME, entity=entity, body=dict(token=token)) except Exception as e: # roll back unquote threadpool.add_thread(_rollback) raise e return resultutils.results(result='delete %s:%d success' % (objtype, entity), data=[dict(entity=entity, objtype=objtype, ports=ports, metadata=metadata)])
def reset(self, req, group_id, objtype, entity, body=None): """重置Entity程序以及配置""" body = body or {} group_id = int(group_id) entity = int(entity) # 重置程序文件,为空表示不需要重置程序文件 appfile = body.pop(common.APPFILE, None) # 重置数据库信息 databases = body.pop('databases', False) # 重置主服务器信息(gameserver专用) chiefs = body.pop('chiefs', False) # 查询entity信息 session = endpoint_session() query = model_query(session, AppEntity, filter=AppEntity.entity == entity) query = query.options(joinedload(AppEntity.databases, innerjoin=False)) _entity = query.one() if _entity.objtype != objtype: raise InvalidArgument('Entity is not %s' % objtype) if _entity.group_id != group_id: raise InvalidArgument('Entity group %d not match %d' % (_entity.group_id, group_id)) entityinfo = entity_controller.show(req=req, entity=entity, endpoint=common.NAME, body={'ports': False})['data'][0] agent_id = entityinfo['agent_id'] metadata = entityinfo['metadata'] if not metadata: raise InvalidArgument('Agent is off line, can not reset entity') # 需要更新数据库 if databases: miss = [] databases = {} # 从本地查询数据库信息 for database in _entity.databases: subtype = database.subtype schema = '%s_%s_%s_%d' % (common.NAME, objtype, subtype, entity) databases[subtype] = dict(host=database.host, port=database.port, user=database.user, passwd=database.passwd, schema=schema, character_set=database.character_set) # 必要数据库信息 NEEDED = common.DBAFFINITYS[objtype].keys() # 数据库信息不匹配,从gopdb接口反查数据库信息 if set(NEEDED) != set(databases.keys()): LOG.warning('Database not match, try find schema info from gopdb') quotes = schema_controller.quotes(req, body=dict(entitys=[entity, ], endpoint=common.NAME))['data'] for subtype in NEEDED: if subtype not in databases: # 从gopdb接口查询引用信息 schema = '%s_%s_%s_%d' % (common.NAME, objtype, subtype, entity) for quote_detail in quotes: # 确认引用不是从库且结构名称相等 if quote_detail['qdatabase_id'] == quote_detail['database_id'] \ and quote_detail['schema'] == schema: databases.setdefault(subtype, dict(host=quote_detail['host'], port=quote_detail['port'], user=quote_detail['user'], passwd=quote_detail['passwd'], schema=schema, character_set=quote_detail['character_set'])) miss.append(AreaDatabase(quote_id=quote_detail['quote_id'], database_id=quote_detail['qdatabase_id'], entity=entity, subtype=subtype, host=quote_detail['host'], port=quote_detail['port'], user=quote_detail['user'], passwd=quote_detail['passwd'], ro_user=quote_detail['ro_user'], ro_passwd=quote_detail['ro_passwd'], character_set=quote_detail['character_set']) ) quotes.remove(quote_detail) break if subtype not in databases: LOG.critical('Miss database of %s' % schema) # 数据库信息无法从gopdb中反查到 raise ValueError('Not %s.%s database found for %d' % (objtype, subtype, entity)) self._validate_databases(objtype, databases) # 有数据库信息遗漏 if miss: with session.begin(): for obj in miss: session.add(obj) session.flush() if objtype == common.GAMESERVER and chiefs: chiefs = {} cross_id = _entity.cross_id if cross_id is None: raise ValueError('%s.%d cross_id is None' % (objtype, entity)) query = model_query(session, AppEntity, filter=and_(AppEntity.group_id == group_id, or_(AppEntity.entity == cross_id, AppEntity.objtype == common.GMSERVER))) _chiefs = query.all() if len(_chiefs) != 2: raise ValueError('Try find %s.%d chiefs from local database error' % (objtype, entity)) for chief in _chiefs: for _objtype in (common.GMSERVER, common.CROSSSERVER): _metadata, ports = self._entityinfo(req, chief.entity) if not _metadata: raise InvalidArgument('Metadata of %s.%d is none' % (_objtype, chief.entity)) if chief.objtype == _objtype: chiefs[_objtype] = dict(entity=chief.entity, ports=ports, local_ip=_metadata.get('local_ip')) if len(chiefs) != 2: raise ValueError('%s.%d chiefs error' % (objtype, entity)) target = targetutils.target_agent_by_string(metadata.get('agent_type'), metadata.get('host')) target.namespace = common.NAME rpc = get_client() finishtime, timeout = rpcfinishtime() if appfile: finishtime += 30 timeout += 35 rpc_ret = rpc.call(target, ctxt={'finishtime': finishtime, 'agents': [agent_id, ]}, msg={'method': 'reset_entity', 'args': dict(entity=entity, appfile=appfile, opentime=_entity.opentime, databases=databases, chiefs=chiefs)}, timeout=timeout) if not rpc_ret: raise RpcResultError('reset entity result is None') if rpc_ret.get('resultcode') != manager_common.RESULT_SUCCESS: raise RpcResultError('reset entity fail %s' % rpc_ret.get('result')) return resultutils.results(result='reset entity %d success' % entity)