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)) session = endpoint_session(readonly=True) columns = [ Group.group_id, Group.name, Group.platfrom_id, Group.warsvr, Group.desc, Group.areas ] results = resultutils.bulk_results(session, model=Group, columns=columns, counter=Group.group_id, order=order, desc=desc, option=joinedload(Group.areas, innerjoin=False), page_num=page_num) for column in results['data']: areas = column.get('areas', []) column['areas'] = [] for area in areas: column['areas'].append( dict(area_id=area.area_id, areaname=area.areaname, show_id=area.show_id)) return results
def entitys(self, req, body=None): """批量查询entitys信息接口,内部接口agent启动的时调用,一般由agent端调用""" entitys = body.get('entitys') if not entitys: return resultutils.results(result='not any app entitys found') entitys = argutils.map_to_int(entitys) session = endpoint_session(readonly=True) query = model_query(session, AppEntity, filter=AppEntity.entity.in_(entitys)) query = query.options(joinedload(AppEntity.areas, innerjoin=False)) return resultutils.results(result='get app entitys success', data=[ dict(entity=_entity.entity, group_id=_entity.group_id, status=_entity.status, opentime=_entity.opentime, areas=[ dict(area_id=area.area_id, show_id=area.show_id, areaname=area.areaname) for area in _entity.areas ], objtype=_entity.objtype) for _entity in query ])
def unquote_version(self, req, group_id, objtype, entity, body=None): """区服包引用指定资源引用删除""" body = body or {} if objtype != common.GAMESERVER: raise InvalidArgument('Version unquote just for %s' % common.GAMESERVER) package_id = int(body.get('package_id')) group_id = int(group_id) entity = int(entity) session = endpoint_session() query = model_query(session, AppEntity, filter=AppEntity.entity == entity) quote = None with session.begin(): _entity = query.one() if _entity.objtype != objtype: raise InvalidArgument('Objtype not match') if _entity.group_id != group_id: raise InvalidArgument('Group id not match') versions = jsonutils.loads_as_bytes( _entity.versions) if _entity.versions else {} str_key = str(package_id) if str_key in versions: quote = versions.pop(str_key) cdnquote_controller.delete(req, quote.get('quote_id')) _entity.versions = jsonutils.dumps( versions) if versions else None session.flush() return resultutils.results( result='%s entity version unquote success' % objtype, data=[ dict(version=quote.get('version') if quote else None, quote_id=quote.get('quote_id') if quote else None) ])
def show(self, req, group_id, objtype, entity, body=None): body = body or {} group_id = int(group_id) entity = int(entity) session = endpoint_session(readonly=True) _format = body.get('format') or 'list' 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)) metadata, ports = self._entityinfo(req, entity) if _format == 'list': databases = [] else: databases = {} for database in _entity.databases: dbinfo = dict(quote_id=database.quote_id, database_id=database.database_id, host=database.host, port=database.port, ro_user=database.ro_user, ro_passwd=database.ro_passwd, subtype=database.subtype, schema='%s_%s_%s_%d' % (common.NAME, objtype, database.subtype, entity)) if _format == 'list': databases.append(dbinfo) else: databases[database.subtype] = dbinfo return resultutils.results( result='show %s areas success' % objtype, data=[ dict(entity=_entity.entity, agent_id=_entity.agent_id, objtype=objtype, group_id=_entity.group_id, opentime=_entity.opentime, platform=_entity.platform, status=_entity.status, versions=jsonutils.loads_as_bytes(_entity.versions) if _entity.versions else None, areas=[ dict( area_id=area.area_id, gid=0, show_id=area.show_id, areaname=area.areaname.encode('utf-8'), ) for area in _entity.areas ], databases=databases, metadata=metadata, ports=ports) ])
def bondto(self, req, entity, body=None): """本地记录数据库绑定信息,用于数据绑定失败后重新绑定""" body = body or {} entity = int(entity) databases = body.pop('databases') session = endpoint_session() with session.begin(): self._bondto(session, entity, databases) return resultutils.results(result='bond entity %d database success' % entity)
def delete(self, req, group_id, body=None): body = body or {} group_id = int(group_id) session = endpoint_session() query = model_query(session, Group, filter=Group.group_id == group_id) query = query.options(joinedload(Group.entitys, innerjoin=False)) _group = query.one() deleted = dict(group_id=_group.group_id, name=_group.name) if _group.entitys: raise InvalidArgument('Group has entitys, can not be delete') session.delete(_group) session.flush() return resultutils.results(result='delete group success', data=[deleted])
def migrate(self, req, group_id, objtype, entity, body=None): """Entity变更agent""" body = body or {} entity = int(entity) group_id = int(group_id) jsonutils.schema_validate(body, self.MIGRATE) new = body.pop('new') new = int(new) body.update({'databases': True, 'chiefs': True}) session = endpoint_session(autocommit=False) query = model_query(session, AppEntity, filter=AppEntity.entity == entity) query = query.options(joinedload(AppEntity.areas, innerjoin=False)) _entity = query.one() if _entity.objtype != objtype: raise InvalidArgument('Entity is not %s' % objtype) if not self._check_file(_entity.agent_id, objtype, body.get(common.APPFILE)): return resultutils.results( result='migrate entity %d not run, check appfile fail') LOG.debug('Check appfile success, migrate start') areas = [ dict(area_id=area.area_id, areaname=area.areaname, show_id=area.show_id) for area in _entity.areas ] with entity_controller.migrate_with_out_data( common.NAME, entity, new, dict(token=uuidutils.generate_uuid()), drop_ports=True): _entity.agent_id = new session.commit() LOG.info( 'Migrate finish, now call post create entity and reset entity on new agent' ) entity_controller.post_create_entity(entity, common.NAME, objtype=objtype, status=_entity.status, opentime=_entity.opentime, group_id=group_id, areas=areas, migrate=True) LOG.info('Notify create entity in new agent success') return self.reset(req, group_id, objtype, entity, body)
def databases(self, req, group_id, body=None): body = body or {} objtype = body.get('objtype', common.GAMESERVER) group_id = int(group_id) session = endpoint_session(readonly=True) _format = body.get('format') or 'list' query = model_query(session, AppEntity, filter=and_(AppEntity.group_id == group_id, AppEntity.objtype == objtype)) query = query.options(joinedload(AppEntity.databases, innerjoin=False)) entitys = query.all() slaves_map = database_controller.slaves_address([ database.database_id for entity in entitys for database in entity.databases ]) data = [] for entity in entitys: databases = {} for database in entity.databases: try: slaves = slaves_map[database.database_id] except KeyError: slaves = [] dbinfo = dict( database_id=database.database_id, host=database.host, port=database.port, ro_user=database.ro_user, ro_passwd=database.ro_passwd, subtype=database.subtype, schema='%s_%s_%s_%d' % (common.NAME, objtype, database.subtype, entity.entity), slaves=slaves, ) databases[database.subtype] = dbinfo data.append({ 'entity': entity.entity, 'group_id': group_id, 'objtype': objtype, 'databases': databases }) return resultutils.results(result='list group entity database success', data=data)
def packages(self, req, group_id, body=None): body = body or {} group_id = int(group_id) session = endpoint_session(readonly=True) query = model_query(session, Group, filter=Group.group_id == group_id) query = query.options(joinedload(Group.packages, innerjoin=False)) _group = query.one() return resultutils.results(result='list group packages success', data=[ dict( package_id=package.package_id, package_name=package.package_name, mark=package.mark, status=package.status, resource_id=package.resource_id, ) for package in _group.packages ])
def opentime(self, req, group_id, objtype, entity, body=None): """修改开服时间接口""" body = body or {} group_id = int(group_id) entity = int(entity) if objtype != common.GAMESERVER: raise InvalidArgument('Api just for %s' % common.GAMESERVER) opentime = int(body.pop('opentime')) if opentime < 0 or opentime >= int(time.time()) + 86400 * 15: raise InvalidArgument('opentime value error') session = endpoint_session() with session.begin(): query = model_query(session, AppEntity, filter=AppEntity.entity == entity) _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)) metadata, ports = self._entityinfo(req=req, entity=entity) target = targetutils.target_agent_by_string( metadata.get('agent_type'), metadata.get('host')) target.namespace = common.NAME rpc = get_client() finishtime, timeout = rpcfinishtime() # with session.begin(): rpc_ret = rpc.call(target, ctxt={'finishtime': finishtime}, msg={ 'method': 'opentime_entity', 'args': dict(entity=entity, opentime=opentime) }, timeout=timeout) query.update({'opentime': opentime}) if not rpc_ret: raise RpcResultError('change entity opentime result is None') if rpc_ret.get('resultcode') != manager_common.RESULT_SUCCESS: raise RpcResultError('change entity opentime fail %s' % rpc_ret.get('result')) return resultutils.results(result='change entity %d opentime success' % entity)
def continues(self, req, uuid, body=None): """中途失败的合服任务再次运行""" session = endpoint_session() query = model_query(session, MergeTask, filter=MergeTask.uuid == uuid) query = query.options(joinedload(MergeTask.entitys, innerjoin=False)) etask = query.one() if etask.status == common.MERGEFINISH: raise InvalidArgument('Merge task has all ready finished') _query = model_query(session, AppEntity, filter=AppEntity.entity == etask.entity) _query = _query.options( joinedload(AppEntity.databases, innerjoin=False)) appentity = _query.one_or_none() if not appentity or not appentity.databases or appentity.objtype != common.GAMESERVER: LOG.error('Etask entity can not be found or type/database error') raise exceptions.MergeException( 'Etask entity can not be found or type/database error') databases = self._database_to_dict(appentity) rpc = get_client() metadata, ports = self._entityinfo(req=req, entity=appentity.entity) target = targetutils.target_agent_by_string(metadata.get('agent_type'), metadata.get('host')) target.namespace = common.NAME rpc_ret = rpc.call(target, ctxt={'agents': [ appentity.agent_id, ]}, msg={ 'method': 'continue_merge', 'args': dict(entity=etask.entity, uuid=uuid, databases=databases) }) if not rpc_ret: raise RpcResultError('continue entity result is None') if rpc_ret.get('resultcode') != manager_common.RESULT_SUCCESS: raise RpcResultError('continue entity fail %s' % rpc_ret.get('result')) return resultutils.results( result='continue merge task command has been send', data=[dict(uuid=etask.uuid, entity=etask.entity)])
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 finish(self, req, uuid, body=None): """合服完毕接口""" session = endpoint_session() query = model_query(session, MergeTask, filter=MergeTask.uuid == uuid) query = query.options(joinedload(MergeTask.entitys, innerjoin=False)) etask = query.one() if etask.status == common.MERGEFINISH: return resultutils.results( result='swallowed finished', data=[dict(uuid=etask.uuid, entity=etask.entity)]) for _entity in etask.entitys: if _entity.status != common.MERGEED: raise InvalidArgument('Entity %d status is not mergeed' % _entity.entity) etask.status = common.MERGEFINISH session.flush() return resultutils.results( result='swallowed finished', data=[dict(uuid=etask.uuid, entity=etask.entity)])
def areas_map(group_id): session = endpoint_session(readonly=True) query = model_query(session, GameArea, filter=GameArea.group_id == group_id) maps = {} for _area in query: try: maps[_area.entity].append( dict(area_id=_area.area_id, areaname=_area.areaname, show_id=_area.show_id)) except KeyError: maps[_area.entity] = [ dict(area_id=_area.area_id, areaname=_area.areaname, show_id=_area.show_id), ] session.close() return maps
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 gmurl(req, group_id, interface): session = endpoint_session(readonly=True) query = model_query(session, AppEntity, filter=and_(AppEntity.objtype == common.GMSERVER, AppEntity.group_id == group_id)) gm = query.one_or_none() if not gm or gm.status != common.OK: raise exceptions.GmSvrHttpError('GM is none or not active' % common.GMSERVER) entityinfo = entity_controller.show(req=req, entity=gm.entity, endpoint=common.NAME, body={'ports': True})['data'][0] port = entityinfo.get('ports')[0] metadata = entityinfo.get('metadata') if not metadata: raise exceptions.GmSvrHttpError( '%s.%d is off line, can not stop by %s' % (gm.objtype, gm.entity, gm.objtype)) ipaddr = metadata.get('local_ip') url = 'http://%s:%d/%s' % (ipaddr, port, interface) return url
def swallow(self, req, entity, body=None): """合服内部接口,一般由agent调用 用于新实体吞噬旧实体的区服和数据库""" body = body or {} entity = int(entity) uuid = body.get('uuid') if not uuid: raise InvalidArgument('Merger uuid is None') session = endpoint_session() query = model_query(session, MergeTask, filter=MergeTask.uuid == uuid) query = query.options(joinedload(MergeTask.entitys, innerjoin=False)) glock = get_gamelock() rpc = get_client() with session.begin(): etask = query.one_or_none() if not etask: raise InvalidArgument('Not task exit with %s' % uuid) # 新实体不匹配 if etask.entity != body.get('entity'): raise InvalidArgument('New entity not %d' % etask.entity) # 找到目标实体 appentity = None for _entity in etask.entitys: if _entity.entity == entity: if _entity.status != common.MERGEING: if _entity.status != common.SWALLOWING: raise InvalidArgument( 'Swallow entity find status error') if not _entity.databases or not _entity.areas: raise InvalidArgument( 'Entity is swallowing but database or ares is None' ) LOG.warning('Entit is swallowing, return saved data') return resultutils.results( result='swallow entity is success', data=[ dict(databases=jsonutils.loads_as_bytes( _entity.databases), areas=jsonutils.loads_as_bytes( _entity.areas)) ]) _query = model_query(session, AppEntity, filter=AppEntity.entity == entity) _query = _query.options( joinedload(AppEntity.databases, innerjoin=False)) appentity = _query.one_or_none() break if not appentity: raise InvalidArgument('Can not find app entity?') if appentity.objtype != common.GAMESERVER: raise InvalidArgument('objtype error, entity not %s' % common.GAMESERVER) if appentity.status != common.MERGEING: raise InvalidArgument('find status error, when swallowing') databases = self._database_to_dict(appentity) areas = [area.to_dict() for area in appentity.areas] if not databases or not areas: LOG.error('Entity no areas or databases record') return resultutils.results( result='swallow entity fail, ' 'target entity can not found database or areas', resultcode=manager_common.RESULT_ERROR) with glock.grouplock(group=appentity.group_id): # 发送吞噬命令到目标区服agent metadata, ports = self._entityinfo(req=req, entity=entity) target = targetutils.target_agent_by_string( metadata.get('agent_type'), metadata.get('host')) target.namespace = common.NAME rpc_ret = rpc.call(target, ctxt={'agents': [ appentity.agent_id, ]}, msg={ 'method': 'swallow_entity', 'args': dict(entity=entity) }) if not rpc_ret: raise RpcResultError('swallow entity result is None') if rpc_ret.get('resultcode') != manager_common.RESULT_SUCCESS: raise RpcResultError('swallow entity fail %s' % rpc_ret.get('result')) # 修改实体在合服任务中的状态,存储areas以及databases appentity.status = common.SWALLOWING _entity.status = common.SWALLOWING _entity.areas = jsonutils.dumps(areas) _entity.databases = jsonutils.dumps(databases) session.flush() return resultutils.results( result='swallow entity is success', data=[dict(databases=databases, areas=areas)])
def swallowed(self, req, entity, body=None): """ 合服内部接口,一般由agent调用 用于新实体吞噬旧实体的区服完成后调用 调用后将设置appentity为deleted状态 """ body = body or {} entity = int(entity) uuid = body.get('uuid') if not uuid: raise InvalidArgument('Merger uuid is None') session = endpoint_session() query = model_query(session, MergeTask, filter=MergeTask.uuid == uuid) query = query.options(joinedload(MergeTask.entitys, innerjoin=False)) glock = get_gamelock() rpc = get_client() appentity = None with session.begin(): etask = query.one_or_none() if not etask: raise InvalidArgument('Not task exit with %s' % uuid) # 新实体不匹配 if etask.entity != body.get('entity'): raise InvalidArgument('New entity not %d' % etask.entity) for _entity in etask.entitys: if _entity.entity == entity: if _entity.status != common.SWALLOWING: raise InvalidArgument( 'Swallowed entity find status error') _query = model_query(session, AppEntity, filter=AppEntity.entity == entity) _query = _query.options( joinedload(AppEntity.databases, innerjoin=False)) appentity = _query.one_or_none() break if not appentity: raise InvalidArgument('Can not find app entity?') if appentity.objtype != common.GAMESERVER: raise InvalidArgument('objtype error, entity not %s' % common.GAMESERVER) if appentity.status != common.SWALLOWING: raise InvalidArgument('find status error, when swallowed') with glock.grouplock(group=appentity.group_id): # 发送吞噬完成命令到目标区服agent metadata, ports = self._entityinfo(req=req, entity=entity) target = targetutils.target_agent_by_string( metadata.get('agent_type'), metadata.get('host')) target.namespace = common.NAME rpc_ret = rpc.call(target, ctxt={'agents': [ appentity.agent_id, ]}, msg={ 'method': 'swallowed_entity', 'args': dict(entity=entity) }) if not rpc_ret: raise RpcResultError('swallowed entity result is None') if rpc_ret.get('resultcode') != manager_common.RESULT_SUCCESS: raise RpcResultError('swallowed entity fail %s' % rpc_ret.get('result')) # appentity状态修改为deleted appentity.status = common.DELETED # 修改实体在合服任务中的状态 _entity.status = common.MERGEED session.flush() # area绑定新实体 _query = model_query(session, GameArea, filter=GameArea.entity == entity) _query.update({'entity': etask.entity}) session.flush() def _unquote(): LOG.info('Swallowed %d finish, try unquote database' % appentity.entity) for database in appentity.databases: try: schema_controller.unquote(req, quote_id=database.quote_id) except Exception: LOG.error('Delete database quote fail') eventlet.spawn_n(_unquote) return resultutils.results( result='swallowed entity is success', data=[ dict(databases=jsonutils.loads_as_bytes(_entity.databases), areas=jsonutils.loads_as_bytes(_entity.areas)) ])
def entitys(objtypes=None, group_ids=None, need_ok=False, packages=False): filters = [ AppEntity.objtype.in_(objtypes), AppEntity.status > common.DELETED ] if group_ids: filters.append( AppEntity.group_id.in_(argutils.map_to_int(group_ids))) session = endpoint_session(readonly=True) query = model_query(session, AppEntity, filter=and_(*filters)) query = query.options(joinedload(AppEntity.areas)) appentitys = query.all() entitys = set() for entity in appentitys: entitys.add(entity.entity) if not entitys: return [], [] # 反查渠道 if packages and common.GAMESERVER in objtypes: pmaps = {} pquery = model_query(session, Package) pquery = pquery.options(joinedload(Package.areas, innerjoin=False)) if group_ids: pquery = pquery.filter( Package.group_id.in_(argutils.map_to_int(group_ids))) def _pmaps(): for package in pquery: for parea in package.areas: try: pmaps[parea.area_id].append(package.package_name) except KeyError: pmaps[parea.area_id] = [ package.package_name, ] th = eventlet.spawn(_pmaps) emaps = entity_controller.shows(common.NAME, entitys, ports=True, metadata=True) if packages and common.GAMESERVER in objtypes: th.wait() chiefs = [] areas = [] for entity in appentitys: if need_ok and entity.status != common.OK: continue entityinfo = emaps.get(entity.entity) ports = entityinfo.get('ports') metadata = entityinfo.get('metadata') if not metadata: raise ValueError('Can not get agent metadata for %d' % entity.entity) if entity.objtype == common.GAMESERVER: for area in entity.areas: info = dict( area_id=area.area_id, show_id=area.show_id, areaname=area.areaname, entity=entity.entity, group_id=entity.group_id, opentime=entity.opentime, platform=entity.platform, status=entity.status, versions=jsonutils.loads_as_bytes(entity.versions) if entity.versions else None, external_ips=metadata.get('external_ips'), dnsnames=metadata.get('dnsnames'), port=ports[0]) if packages: info.setdefault('packagenames', pmaps.get(area.area_id, [])) areas.append(info) else: chiefs.append( dict(entity=entity.entity, objtype=entity.objtype, group_id=entity.group_id, ports=ports, local_ip=metadata.get('local_ip'), dnsnames=metadata.get('dnsnames'), external_ips=metadata.get('external_ips'))) return chiefs, areas
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 _async_bluck_rpc(self, action, group_id, objtype, entity, body=None, context=None): caller = inspect.stack()[0][3] body = body or {} group_id = int(group_id) context = context or empty_context if entity == 'all': entitys = 'all' else: entitys = argutils.map_to_int(entity) asyncrequest = self.create_asyncrequest(body) target = targetutils.target_endpoint(common.NAME) session = endpoint_session(readonly=True) query = model_query(session, AppEntity, filter=and_(AppEntity.group_id == group_id, AppEntity.objtype == objtype)) emaps = dict() for _entity in query: if _entity.status <= common.DELETED: continue if _entity.status != common.OK and action != 'stop': continue emaps.setdefault(_entity.entity, _entity.agent_id) if entitys == 'all': entitys = emaps.keys() agents = set(emaps.values()) else: if entitys - set(emaps.keys()): raise InvalidArgument( 'Some entitys not found or status is not active') agents = set() for entity in emaps: if entity in entitys: agents.add(emaps[entity]) with context(asyncrequest.request_id, entitys, agents): 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_ctxt = {} rpc_ctxt.setdefault('agents', agents) rpc_method = '%s_entitys' % action rpc_args = dict(entitys=list(entitys)) rpc_args.update(body) 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='gogamechen3 %s entitys %s spawning' % (objtype, caller), data=[asyncrequest.to_dict()])
def index(self, req, group_id, objtype, body=None): body = body or {} group_id = int(group_id) order = body.pop('order', None) desc = body.pop('desc', False) detail = body.pop('detail', False) packages = body.pop('packages', False) page_num = int(body.pop('page_num', 0)) session = endpoint_session(readonly=True) columns = [ AppEntity.entity, AppEntity.group_id, AppEntity.agent_id, AppEntity.opentime, AppEntity.platform, AppEntity.versions, AppEntity.status, AppEntity.objtype ] joins = None if objtype == common.GAMESERVER: columns.append(AppEntity.areas) joins = joinedload(AppEntity.areas, innerjoin=False) if packages: joins = joins.joinedload(GameArea.packages, innerjoin=False) def _databases(): _maps = {} if objtype != common.GAMESERVER: return _maps query = model_query(session, AreaDatabase) for _db in query: dbinfo = dict( quote_id=_db.quote_id, subtype=_db.subtype, host=_db.host, port=_db.port, ) try: _maps[_db.entity].append(dbinfo) except KeyError: _maps[_db.entity] = [ dbinfo, ] return _maps if detail: dth = eventlet.spawn(_databases) results = resultutils.bulk_results(session, model=AppEntity, columns=columns, counter=AppEntity.entity, order=order, desc=desc, option=joins, filter=and_( AppEntity.group_id == group_id, AppEntity.objtype == objtype), page_num=page_num) if detail: dbmaps = dth.wait() if not results['data']: return results emaps = entity_controller.shows( endpoint=common.NAME, entitys=[column.get('entity') for column in results['data']]) for column in results['data']: entity = column.get('entity') entityinfo = emaps.get(entity) if detail: try: column['databases'] = dbmaps[entity] except KeyError: LOG.error('Entity %d lose database' % entity) if column['agent_id'] != entityinfo.get('agent_id'): raise RuntimeError( 'Entity agent id %d not the same as %d' % (column['agent_id'], entityinfo.get('agent_id'))) areas = column.pop('areas', []) if objtype == common.GAMESERVER: _areas = [] for area in areas: _area = dict(area_id=area.area_id, show_id=area.show_id, gid=0, areaname=area.areaname) if packages: _area.setdefault( 'packages', [parea.package_id for parea in area.packages]) _areas.append(_area) areas = _areas column['areas'] = areas column['ports'] = entityinfo.get('ports') metadata = entityinfo.get('metadata') if metadata: local_ip = metadata.get('local_ip') external_ips = metadata.get('external_ips') else: local_ip = external_ips = None column['local_ip'] = local_ip column['external_ips'] = external_ips versions = column.get('versions') if versions: column['versions'] = jsonutils.loads_as_bytes(versions) return results
def flushconfig(self, req, group_id, objtype, entity, body=None): body = body or {} group_id = int(group_id) jsonutils.schema_validate(body, self.FLUSH) if objtype == common.GAMESERVER: gm = body.pop(common.GMSERVER, 0) cross = body.pop(common.CROSSSERVER, 0) entitys = [] if gm: entitys.append(gm) if cross: entitys.append(cross) entitys = list(set(entitys)) if entitys: chiefs = {} session = endpoint_session() query = model_query(session, AppEntity, filter=and_(AppEntity.group_id == group_id, AppEntity.entity.in_(entitys))) gmsvr = crosssvr = None for appserver in query: if appserver.group_id != group_id: raise InvalidArgument('Entity group value error') if appserver.objtype == common.GMSERVER: if appserver.entity != gm: raise InvalidArgument('Find %s but entity is %d' % (common.GMSERVER, gm)) gmsvr = appserver elif appserver.objtype == common.CROSSSERVER: if appserver.entity != cross: raise InvalidArgument('Find %s but entity is %d' % (common.CROSSSERVER, cross)) crosssvr = appserver if gm and not gmsvr: raise InvalidArgument('%s.%d can not be found' % (common.GMSERVER, gm)) if cross and not crosssvr: raise InvalidArgument('%s.%d can not be found' % (common.CROSSSERVER, cross)) # 获取实体相关服务器信息(端口/ip) maps = entity_controller.shows(endpoint=common.NAME, entitys=entitys) if gmsvr: chiefs.setdefault( common.GMSERVER, dict( entity=gmsvr.entity, ports=maps.get(gmsvr.entity).get('ports'), local_ip=maps.get( gmsvr.entity).get('metadata').get('local_ip'))) if crosssvr: chiefs.setdefault( common.CROSSSERVER, dict(entity=crosssvr.entity, ports=maps.get(crosssvr.entity).get('ports'), local_ip=maps.get(crosssvr.entity).get( 'metadata').get('local_ip'))) body.update({'chiefs': chiefs}) return self._async_bluck_rpc('flushconfig', group_id, objtype, entity, body)
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) ])
group_id = 97 platform = 'ios' a = 'C:\\Users\\loliz_000\\Desktop\\etc\\goperation\\goperation.conf' b = 'C:\\Users\\loliz_000\\Desktop\\etc\\goperation\\gcenter.conf' c = 'C:\\Users\\loliz_000\\Desktop\\etc\\goperation\\endpoints\gogamechen3.server.conf' from goperation.manager import common as manager_common from goperation import config as goperation_config # create a new project and group named gcenter name = manager_common.SERVER # init goperation config main_group = goperation_config.configure(name, [a, b, c]) from simpleservice.ormdb.config import database_opts endpoint_group = cfg.OptGroup(common.NAME, title='endpopint of %s' % common.NAME) CONF.register_group(endpoint_group) CONF.register_opts(database_opts, endpoint_group) session = endpoint_session(readonly=True) query = session.query(func.max(GameArea.show_id)).select_from(AppEntity) query = query.join(AppEntity.areas, isouter=True) query = query.filter( and_(AppEntity.group_id == group_id, AppEntity.platform == platform)) last_show_id = query.scalar() or 0 print last_show_id
def create(self, req, group_id, objtype, body=None): body = body or {} group_id = int(group_id) jsonutils.schema_validate(body, self.CREATEAPPENTITY) if body.get('packages'): raise InvalidArgument('Package parameter is removed') # 找cross服务, gameserver专用 cross_id = body.pop('cross_id', None) # 开服时间, gameserver专用 opentime = body.pop('opentime', None) # 区服显示id, gameserver专用 show_id = body.pop('show_id', None) # 区服显示民称, gameserver专用 areaname = body.pop('areaname', None) # 平台类型 platform = body.get('platform') include = set(body.pop('include', [])) exclude = set(body.pop('exclude', [])) if include and exclude: raise InvalidArgument('Both packages and exclude is forbidden') packages = [] session = endpoint_session() if objtype == common.GAMESERVER: platform = common.PlatformTypeMap.get(platform) if not areaname or not opentime or not platform or not show_id: raise InvalidArgument( '%s need opentime and areaname and platform and show_id' % objtype) # 安装文件信息 appfile = body.pop(common.APPFILE) LOG.debug('Try find agent and database for entity') # 选择实例运行服务器 agent_id = body.get('agent_id') or self._agentselect( req, objtype, **body) # 选择实例运行数据库 databases = self._dbselect(req, objtype, **body) # 校验数据库信息 if not self._validate_databases(objtype, databases): raise InvalidArgument('Miss some database') LOG.info( 'Find agent and database for entity success, to agent %d, to databse %s' % (agent_id, str(databases))) query = model_query(session, Group, filter=Group.group_id == group_id) joins = joinedload(Group.entitys, innerjoin=False) joins = joins.joinedload(AppEntity.databases, innerjoin=False) query = query.options(joins) _group = query.one() glock = get_gamelock() with glock.grouplock(group_id): if objtype == common.GAMESERVER: _pquery = model_query(session, Package, filter=Package.group_id == group_id) _packages = set([ p.package_id for p in _pquery.all() if p.platform & platform ]) if (include - _packages) or (exclude - _packages): raise InvalidArgument( 'Package can not be found in include or exclude') if exclude: packages = _packages - exclude elif include: packages = include else: packages = _packages typemap = {} for _entity in _group.entitys: # 跳过未激活的实体 if _entity.status != common.OK: continue try: typemap[_entity.objtype].append(_entity) except KeyError: typemap[_entity.objtype] = [ _entity, ] # 前置实体 chiefs = None # 相同类型的实例列表 same_type_entitys = typemap.get(objtype, []) if objtype == common.GMSERVER: # GM服务不允许相同实例,必须clean掉所有同组GM服务器 for _entity in _group.entitys: if _entity.objtype == common.GMSERVER: return resultutils.results( result='create entity fail, %s duplicate in group' % objtype, resultcode=manager_common.RESULT_ERROR) else: # 非gm实体添加需要先找到同组的gm try: gm = typemap[common.GMSERVER][0] if gm.status <= common.DELETED: return resultutils.results( result='Create entity fail, gm mark deleted', resultcode=manager_common.RESULT_ERROR) except KeyError as e: return resultutils.results( result='Create entity fail, can not find GMSERVER: %s' % e.message, resultcode=manager_common.RESULT_ERROR) if objtype == common.GAMESERVER: if model_count_with_key( session, GameArea, filter=and_(GameArea.group_id == group_id, GameArea.areaname == areaname)): return resultutils.results( result='Create entity fail, name exist', resultcode=manager_common.RESULT_ERROR) cross = None # 游戏服务器需要在同组中找到cross实例 try: crossservers = typemap[common.CROSSSERVER] except KeyError as e: return resultutils.results( result= 'create entity fail, can not find my chief: %s' % e.message, resultcode=manager_common.RESULT_ERROR) # 如果指定了cross实例id if cross_id: # 判断cross实例id是否在当前组中 for _cross in crossservers: if cross_id == _cross.entity: cross = _cross break else: # 游戏服没有相同实例,直接使用第一个cross实例 if not same_type_entitys: cross = crossservers[0] else: # 统计所有cross实例的引用次数 counted = set() counter = dict() for _cross in crossservers: counter.setdefault(_cross.entity, 0) # 查询当前组内所有entity对应的cross_id for _entity in _group.entitys: if _entity.objtype != common.GAMESERVER: continue if _entity.cross_id in counted: continue counter[_entity.cross_id] += 1 # 选取引用次数最少的cross_id cross_id = sorted( zip(counter.itervalues(), counter.iterkeys()))[0][1] for _cross in crossservers: if cross_id == _cross.entity: cross = _cross break if not cross: raise InvalidArgument( 'cross server can not be found or not active') # 获取实体相关服务器信息(端口/ip) maps = entity_controller.shows( endpoint=common.NAME, entitys=[gm.entity, cross.entity]) for v in six.itervalues(maps): if v is None: raise InvalidArgument( 'Get chiefs info error, agent not online?') chiefs = dict() # 战场与GM服务器信息 for chief in (cross, gm): chiefmetadata = maps.get(chief.entity).get('metadata') ports = maps.get(chief.entity).get('ports') if not chiefmetadata: raise InvalidArgument( '%s.%d is offline' % (chief.objtype, chief.entity)) need = common.POSTS_COUNT[chief.objtype] if need and len(ports) != need: raise InvalidArgument('%s.%d port count error, ' 'find %d, need %d' % (chief.objtype, chief.entity, len(ports), need)) chiefs.setdefault( chief.objtype, dict(entity=chief.entity, ports=ports, local_ip=chiefmetadata.get('local_ip'))) cross_id = cross.entity # 完整的rpc数据包 create_body = dict(objtype=objtype, appfile=appfile, databases=databases, chiefs=chiefs, entity=int(body.get('entity', 0))) with session.begin(): body.setdefault('finishtime', rpcfinishtime()[0] + 5) try: create_result = entity_controller.create( req=req, agent_id=agent_id, endpoint=common.NAME, body=create_body)['data'][0] except RpcResultError as e: LOG.error('Create entity rpc call fail: %s' % e.message) raise InvalidArgument(e.message) entity = create_result.get('entity') rpc_result = create_result.get('notify') LOG.info('Create new entity %d' % entity) LOG.debug('Entity controller create rpc result %s', str(rpc_result)) # 插入实体信息 appentity = AppEntity(entity=entity, agent_id=agent_id, group_id=group_id, objtype=objtype, cross_id=cross_id, opentime=opentime, platform=platform) session.add(appentity) session.flush() if objtype == common.GAMESERVER: areaname = areaname.decode('utf-8') if isinstance( areaname, six.binary_type) else areaname gamearea = GameArea(group_id=_group.group_id, show_id=show_id, areaname=areaname, gid=None, entity=appentity.entity) session.add(gamearea) session.flush() # area id插入渠道包包含列表中,批量操作 if packages: for package_id in packages: session.add( PackageArea(package_id=package_id, area_id=gamearea.area_id)) session.flush() # 插入数据库绑定信息 if rpc_result.get('databases'): self._bondto(session, entity, rpc_result.get('databases')) else: LOG.error('New entity database miss') _result = dict(entity=entity, objtype=objtype, agent_id=agent_id, connection=rpc_result.get('connection'), ports=rpc_result.get('ports'), databases=rpc_result.get('databases')) areas = [] if objtype == common.GAMESERVER: areas = [ dict(area_id=gamearea.area_id, gid=0, areaname=areaname, show_id=show_id) ] _result.setdefault('areas', areas) _result.setdefault('cross_id', cross_id) _result.setdefault('opentime', opentime) _result.setdefault('platform', platform) _result.setdefault('packages', sorted(packages)) # 添加端口 # threadpool.add_thread(port_controller.unsafe_create, # agent_id, common.NAME, entity, rpc_result.get('ports')) port_controller.unsafe_create(agent_id, common.NAME, entity, rpc_result.get('ports')) # agent 后续通知 threadpool.add_thread(entity_controller.post_create_entity, entity, common.NAME, objtype=objtype, status=common.UNACTIVE, opentime=opentime, group_id=group_id, areas=areas) return resultutils.results(result='create %s entity success' % objtype, data=[ _result, ])
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)
def update(self, req, group_id, objtype, entity, body=None): body = body or {} group_id = int(group_id) entity = int(entity) status = body.get('status', common.OK) if status not in (common.UNACTIVE, common.OK): raise InvalidArgument('Status not in 0, 1, 2') session = endpoint_session() glock = get_gamelock() query = model_query(session, AppEntity, filter=AppEntity.entity == entity) if objtype == common.GAMESERVER: query = query.options(joinedload(AppEntity.areas, innerjoin=False)) _entity = query.one() if status == _entity.status: return resultutils.results(result='%s entity status in same' % objtype) if _entity.status not in (common.OK, common.UNACTIVE): return resultutils.results( resultcode=manager_common.RESULT_ERROR, result='%s entity is not ok or unactive' % objtype) if _entity.objtype != objtype: raise InvalidArgument('Objtype not match') if _entity.group_id != group_id: raise InvalidArgument('Group id not match') 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') rpc = get_client() target = targetutils.target_agent_by_string(metadata.get('agent_type'), metadata.get('host')) target.namespace = common.NAME if objtype == common.GAMESERVER: lock = functools.partial( glock.arealock, group=group_id, areas=[area.area_id for area in _entity.areas]) else: lock = functools.partial(glock.grouplock, group=group_id) with lock(): with session.begin(): _entity.status = status session.flush() finishtime, timeout = rpcfinishtime() rpc_ret = rpc.call(target, ctxt={ 'finishtime': finishtime, 'agents': [ agent_id, ] }, msg={ 'method': 'change_status', 'args': dict(entity=entity, status=status) }, timeout=timeout) if not rpc_ret: raise RpcResultError('change entity sttus result is None') if rpc_ret.get('resultcode') != manager_common.RESULT_SUCCESS: raise RpcResultError('change entity status fail %s' % rpc_ret.get('result')) return resultutils.results(result='%s entity update success' % objtype)
def delete(self, req, group_id, objtype, entity, body=None): """标记删除entity""" body = body or {} force = body.get('force', False) 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) if objtype == common.GAMESERVER: query = query.options(joinedload(AppEntity.areas, innerjoin=False)) _entity = query.one() if _entity.status == common.DELETED: return resultutils.results(result='mark %s entity delete success' % objtype, data=[ dict(entity=entity, objtype=objtype, ports=ports, metadata=metadata) ]) if _entity.objtype != objtype: raise InvalidArgument('Objtype not match') if _entity.group_id != group_id: raise InvalidArgument('Group id not match') target = targetutils.target_agent_by_string(metadata.get('agent_type'), metadata.get('host')) target.namespace = common.NAME rpc = get_client() with glock.grouplock(group=group_id): if objtype == common.GMSERVER: if model_count_with_key( session, AppEntity, filter=AppEntity.group_id == group_id) > 1: raise InvalidArgument( 'You must delete other objtype entity before delete gm' ) if model_count_with_key( session, Package, filter=Package.group_id == group_id) > 1: raise InvalidArgument( 'You must delete other Package before delete gm') elif objtype == common.CROSSSERVER: if model_count_with_key( session, AppEntity, filter=AppEntity.cross_id == _entity.entity): raise InvalidArgument('Cross server are reflected') with session.begin(): # 确认实体没有运行 rpc_ret = rpc.call(target, ctxt={'agents': [ _entity.agent_id, ]}, msg={ 'method': 'stoped', 'args': dict(entity=entity) }) if not rpc_ret: raise RpcResultError('check entity stoped result is None') if rpc_ret.get('resultcode') != manager_common.RESULT_SUCCESS: raise RpcResultError('check entity fail %s' % rpc_ret.get('result')) _entity.status = common.DELETED session.flush() if objtype == common.GAMESERVER: # 删除所有资源版本引用 if _entity.versions: for quote in six.itervalues( jsonutils.loads_as_bytes(_entity.versions)): threadpool.add_thread(cdnquote_controller.delete, req, quote.get('quote_id')) _entity.versions = None session.flush() if _entity.areas: if len(_entity.areas) > 1: raise InvalidArgument('%s areas more then one' % objtype) area = _entity.areas[0] if not force: if _entity.entity != model_max_with_key( session, AppEntity.entity, filter=and_( AppEntity.objtype == common.GAMESERVER, AppEntity.group_id == group_id)): raise InvalidArgument( 'entity %d is not the last gamesvr entity in group' % entity) session.flush() session.delete(area) session.flush() _query = model_query( session, PackageArea, filter=PackageArea.area_id == area.area_id) _query.delete() session.flush() rpc.cast(target, ctxt={'agents': [ _entity.agent_id, ]}, msg={ 'method': 'change_status', 'args': dict(entity=entity, status=common.DELETED) }) return resultutils.results(result='mark %s entity delete success' % objtype, data=[ dict(entity=entity, objtype=objtype, ports=ports, metadata=metadata) ])
def quote_version(self, req, group_id, objtype, entity, body=None): """区服包引用指定资源版本""" body = body or {} if objtype != common.GAMESERVER: raise InvalidArgument('Version quote just for %s' % common.GAMESERVER) package_id = int(body.get('package_id')) rversion = body.get('rversion') group_id = int(group_id) entity = int(entity) session = endpoint_session() query = model_query(session, Group, filter=Group.group_id == group_id) query = query.options(joinedload(Group.packages, innerjoin=False)) group = query.one() resource_id = None for package in group.packages: if package.package_id == package_id: resource_id = package.resource_id if not resource_id: raise InvalidArgument( 'Entity can not find package or package resource is None') query = model_query(session, AppEntity, filter=AppEntity.entity == entity) query = query.options(joinedload(AppEntity.areas, innerjoin=False)) with session.begin(): _entity = query.one() if _entity.objtype != objtype: raise InvalidArgument('Objtype not match') if _entity.group_id != group_id: raise InvalidArgument('Group id not match') if not model_count_with_key( session, PackageArea.package_id, filter=and_( PackageArea.package_id == package_id, PackageArea.area_id.in_( [area.area_id for area in _entity.areas]))): raise InvalidArgument('Entity area not in package areas') versions = jsonutils.loads_as_bytes( _entity.versions) if _entity.versions else {} str_key = str(package_id) if str_key in versions: quote = versions.get(str_key) if quote.get('version') != rversion: body = {'version': rversion} quote.update(body) cdnquote_controller.update(req, quote.get('quote_id'), body=body) else: qresult = cdnresource_controller.vquote( req, resource_id, body={ 'version': rversion, 'desc': '%s.%d' % (common.NAME, entity) }) quote = qresult['data'][0] quote = dict(version=rversion, quote_id=quote.get('quote_id')) versions.setdefault(str_key, quote) _entity.versions = jsonutils.dumps(versions) session.flush() return resultutils.results(result='set entity version quote success', data=[ dict(resource_id=resource_id, version=rversion, quote_id=quote.get('quote_id')) ])