def test_app_without_pool(self): data = { "pools": [{ "apps": [1], "cbm": 0xf0, "cores": [1], "id": 1, "name": "pool 1" }, { "cbm": 0xf0, "cores": [2], "id": 2, "name": "pool 2" }], "apps": [{ "cores": [1], "id": 1, "name": "app 1", "pids": [1] }, { "cores": [1], "id": 2, "name": "app 2", "pids": [2] }] } with pytest.raises(ValueError, match="not assigned to any pool"): ConfigStore.validate(data)
def test_app_invalid_core(self): def check_core(core): return core != 3 data = { "auth": { "password": "******", "username": "******" }, "pools": [{ "apps": [1], "cbm": 0xf0, "cores": [1], "id": 1, "name": "pool 1" }], "apps": [{ "cores": [3], "id": 1, "name": "app 1", "pids": [1] }] } with mock.patch('common.PQOS_API.check_core', new=check_core): with pytest.raises(ValueError, match="Invalid core 3"): ConfigStore.validate(data)
def test_app_core_does_not_match_pool(self): data = { "auth": { "password": "******", "username": "******" }, "pools": [{ "apps": [1], "cbm": 0xf0, "cores": [1], "id": 1, "name": "pool 1" }], "apps": [{ "cores": [3, 4, 5], "id": 1, "name": "app 1", "pids": [1] }] } with pytest.raises( ValueError, match="App 1, cores {3, 4, 5} does not match Pool 1"): ConfigStore.validate(data)
def test_pool_mba_mba_bw_enabled(self): data = { "rdt_iface": { "interface": "os" }, "mba_ctrl": { "enabled": True }, "pools": [{ "cbm": 0xf, "mba": 50, "cores": [1, 3], "id": 1, "name": "pool 1" }, { "cbm": 0xf, "mba": 70, "cores": [2], "id": 2, "name": "pool 2" }] } with pytest.raises( ValueError, match="MBA % is not enabled. Disable MBA BW and try again"): ConfigStore.validate(data)
def test_app_same_ids(self): data = { "auth": { "password": "******", "username": "******" }, "pools": [ { "apps": [1], "cbm": 0xf0, "cores": [1], "id": 1, "name": "pool 1" }, ], "apps": [{ "cores": [1], "id": 1, "name": "app 1", "pids": [1] }, { "cores": [1], "id": 1, "name": "app 2", "pids": [1] }] } with pytest.raises(ValueError, match="App 1, multiple apps with same id"): ConfigStore.validate(data)
def test_app_without_pool(self): data = { "auth": { "password": "******", "username": "******" }, "pools": [{ "apps": [1], "cbm": 0xf0, "cores": [1], "id": 1, "name": "pool 1" }, { "apps": [1, 2], "cbm": 0xf0, "cores": [2], "id": 2, "name": "pool 2" }], "apps": [{ "cores": [1], "id": 1, "name": "app 1", "pids": [1] }, { "cores": [2], "id": 2, "name": "app 2", "pids": [2] }] } with pytest.raises(ValueError, match="App 1, Assigned to more than one pool"): ConfigStore.validate(data)
def test_app_invalid_pid(self): data = { "auth": { "password": "******", "username": "******" }, "pools": [ { "apps": [1, 2], "cbm": 0xf0, "cores": [1], "id": 1, "name": "pool 1" }, ], "apps": [{ "cores": [1], "id": 1, "name": "app 1", "pids": [1] }, { "cores": [1], "id": 2, "name": "app 2", "pids": [99999] }] } with pytest.raises(ValueError, match="App 2, PID 99999 is not valid"): ConfigStore.validate(data)
def test_app_same_pid(self): data = { "auth": { "password": "******", "username": "******" }, "pools": [ { "apps": [1, 2], "cbm": 0xf0, "cores": [1], "id": 1, "name": "pool 1" }, ], "apps": [{ "cores": [1], "id": 1, "name": "app 1", "pids": [1] }, { "cores": [1], "id": 2, "name": "app 2", "pids": [1] }] } with pytest.raises( ValueError, match=r"App 2, PIDs \{1} already assigned to another App."): ConfigStore.validate(data)
def run(self): while True: vehicle = API_Engine().get_vehicle() vehicle["vid"] = ConfigStore().get_vid() vehicle["did"] = ConfigStore().get_did() ConfigStore().set_vehicle(vehicle) time.sleep(60)
def main(): app = FleetMonitorApp() parser = argparse.ArgumentParser() parser.add_argument("-s", "--serverUri", dest="serverUri", type=str, help="the server URI to send requests to") parser.add_argument("-d", "--driverID", dest="driverID", default=0, type=int, help="the ID of the driver using the vehicle") parser.add_argument("-v", "--vehicleID", dest="vehicleID", default=0, type=int, help="the ID of this vehicle") parser.add_argument("-l", "--log", help="output API calls", action="store_true") args = parser.parse_args() if args.serverUri: server = {"uri": args.serverUri} API_Engine().set_send(True) ConfigStore().set_server(server) else: API_Engine().set_send(False) API_Engine().set_logging(True) if args.log: API_Engine().set_logging(True) API_Engine().start() if args.vehicleID and args.driverID: vehicle = {"vid": args.vehicleID} vehicle["did"] = args.driverID vehicle["pids"] = [] ConfigStore().set_vehicle(vehicle) if app.startup(): app.start() time.sleep(5) print("Starting hardware") app.run_hardware()
def test_rdt_iface_invalid(self): data = { "auth": { "password": "******", "username": "******" }, "pools": [], "apps": [], "rdt_iface": "os" } with pytest.raises(jsonschema.exceptions.ValidationError, match="'os' is not of type 'object'"): ConfigStore.validate(data) data['rdt_iface'] = {} with pytest.raises(jsonschema.exceptions.ValidationError, match="'interface' is a required property"): ConfigStore.validate(data) data['rdt_iface']['interface'] = None with pytest.raises(jsonschema.exceptions.ValidationError, match="None is not of type 'string'"): ConfigStore.validate(data) data['rdt_iface']['interface'] = 2 with pytest.raises(jsonschema.exceptions.ValidationError, match="2 is not of type 'string'"): ConfigStore.validate(data) data['rdt_iface']['interface'] = "test_string" with pytest.raises( jsonschema.exceptions.ValidationError, match="'test_string' is not one of \\['msr', 'os'\\]"): ConfigStore.validate(data)
def test_get_global_attr_power_profiles_verify(mock_get_config, cfg, default, result): mock_get_config.return_value = cfg config_store = ConfigStore() assert config_store.get_global_attr('power_profiles_verify', default) == result
def __init__(self, hatari): userconfdir = ".hatari" ConfigStore.__init__(self, userconfdir) conffilename = "hatari.cfg" self.load(self.get_filepath(conffilename)) self._hatari = hatari self._lock_updates = False self._options = []
def __init__(self, previous): userconfdir = ".previous" ConfigStore.__init__(self, userconfdir) conffilename = "previous.cfg" self.load(self.get_filepath(conffilename)) self._previous = previous self._lock_updates = False self._options = []
def test_config_remove_default_pool(): config = deepcopy(CONFIG_POOLS) # default pool in config assert ConfigStore.is_default_pool_defined(config) == True # FUT ConfigStore.remove_default_pool(config) # no default pool in config assert not ConfigStore.is_default_pool_defined(config)
def test_pool_mba_not_supported(self): data = { "pools": [{ "mba": 50, "cores": [1, 3], "id": 1, "name": "pool 1" }] } with pytest.raises(ValueError, match="MBA is not supported"): ConfigStore.validate(data)
def test_pool_cat_not_supported(self): data = { "pools": [{ "apps": [], "cbm": 0x4, "cores": [1, 3], "id": 1, "name": "pool 1" }] } with pytest.raises(ValueError, match="CAT is not supported"): ConfigStore.validate(data)
def test_pool_mba_bw_not_supported_cat(self): data = { "pools": [{ "cbm": 0xf, "mba_bw": 5000, "cores": [1, 3], "id": 1, "name": "pool 1" }] } with pytest.raises(ValueError, match="MBA BW is not enabled/supported"): ConfigStore.validate(data)
def test_config_is_default_pool_defined(): config = deepcopy(CONFIG_POOLS) # FUT, default pool in config assert ConfigStore.is_default_pool_defined(config) == True # remove default pool from config for pool in config['pools'][:]: if pool['id'] == 0: config['pools'].remove(pool) break # FUT, no default pool in config assert not ConfigStore.is_default_pool_defined(config)
def test_config_recreate_default_pool(def_pool_def): config_store = ConfigStore() with mock.patch('config.ConfigStore.is_default_pool_defined', mock.MagicMock(return_value=def_pool_def)) as mock_is_def_pool_def,\ mock.patch('config.ConfigStore.remove_default_pool') as mock_rm_def_pool,\ mock.patch('config.ConfigStore.add_default_pool') as mock_add_def_pool: config_store.recreate_default_pool() if def_pool_def: mock_rm_def_pool.assert_called_once() else: mock_rm_def_pool.assert_not_called() mock_add_def_pool.assert_called_once()
def __init__(self): def startup(self): result = True vehicle = API_Engine().get_vehicle() vehicle["did"] = ConfigStore().get_did() ConfigStore().set_vehicle(vehicle) # Check for PiCAN connection try: self.can = can_interface.CanHandler() if not self.can.startup(): return False except: return False # Check for GPS connection try: self.gps = gps_interface.GPSHandler() if not self.gps.setup(): return False except: return False API_Engine().start()
def put(): """ Handles PUT /caps/rdt_iface request. Raises BadRequest, InternalError Returns: response, status code """ json_data = request.get_json() # validate request try: schema, resolver = ConfigStore.load_json_schema('modify_rdt_iface.json') jsonschema.validate(json_data, schema, resolver=resolver) except (jsonschema.ValidationError, OverflowError) as error: raise BadRequest("Request validation failed - %s" % (str(error))) if not json_data['interface'] in common.PQOS_API.supported_iface(): raise BadRequest("RDT interface '%s' not supported!" % (json_data['interface'])) if common.CONFIG_STORE.is_any_pool_defined(): return {'message': "Please remove all Pools first!"}, 409 data = deepcopy(common.CONFIG_STORE.get_config()) if 'rdt_iface' not in data: data['rdt_iface'] = {} data['rdt_iface']['interface'] = json_data['interface'] CapsMbaCtrl.set_mba_ctrl_enabled(data, False) common.CONFIG_STORE.set_config(data) res = {'message': "RDT Interface modified"} return res, 200
def make_refresh(self, tp, set_timestamp=False, save=True, send_notify=True): club_level = get_club_property(self.server_id, self.char_id, 'level') goods = ConfigStore.refresh(tp, club_level) try: tp_doc = self.doc['tp'][str(tp)] except KeyError: tp_doc = MongoStore.document_tp() if set_timestamp: tp_doc['refresh_at'] = arrow.utcnow().timestamp tp_doc['goods'] = { str(_id): { 'index': _index, 'times': 0 } for _id, _index in goods } self.doc['tp'][str(tp)] = tp_doc if save: MongoStore.db(self.server_id).update_one( {'_id': self.char_id}, {'$set': { 'tp.{0}'.format(tp): tp_doc }}) if send_notify: self.send_notify(tp=tp)
def send_notify(self, tp=None): if tp: act = ACT_UPDATE tps = [tp] else: act = ACT_INIT tps = ConfigStoreType.INSTANCES.keys() notify = StoreNotify() notify.act = act for _t in tps: ri = RefreshInfo(self.server_id, self.char_id, _t) notify_type = notify.store_types.add() notify_type.tp = _t notify_type.auto_refresh_at = self.next_auto_refresh_timestamp(_t) notify_type.remained_refresh_times = ri.remained_refresh_times notify_type.refresh_cost = ri.refresh_cost for _g in self.doc['tp'][str(_t)]['goods'].keys(): _g_data = self.doc['tp'][str(_t)]['goods'][str(_g)] notify_type_goods = notify_type.goods.add() notify_type_goods.id = int(_g) notify_type_goods.content_index = _g_data['index'] notify_type_goods.remained_times = ConfigStore.get( int(_g)).times_limit - _g_data['times'] MessagePipe(self.char_id).put(msg=notify)
def send_notify(self, tp=None): if tp: act = ACT_UPDATE tps = [tp] else: act = ACT_INIT tps = ConfigStoreType.INSTANCES.keys() notify = StoreNotify() notify.act = act for _t in tps: ri = RefreshInfo(self.server_id, self.char_id, _t) notify_type = notify.store_types.add() notify_type.tp = _t notify_type.auto_refresh_at = self.next_auto_refresh_timestamp(_t) notify_type.remained_refresh_times = ri.remained_refresh_times notify_type.refresh_cost = ri.refresh_cost for _g in self.doc['tp'][str(_t)]['goods'].keys(): _g_data = self.doc['tp'][str(_t)]['goods'][str(_g)] notify_type_goods = notify_type.goods.add() notify_type_goods.id = int(_g) notify_type_goods.content_index = _g_data['index'] notify_type_goods.remained_times = ConfigStore.get(int(_g)).times_limit - _g_data['times'] MessagePipe(self.char_id).put(msg=notify)
def put(): """ Handles HTTP PUT /caps/sstbf request. Raises BadRequest, InternalError Returns: response, status code """ json_data = request.get_json() # validate app schema try: schema, resolver = ConfigStore.load_json_schema('modify_sstbf.json') jsonschema.validate(json_data, schema, resolver=resolver) except (jsonschema.ValidationError, OverflowError) as error: raise BadRequest("Request validation failed - %s" % (str(error))) if not sstbf.configure_sstbf(json_data['configured']) == 0: raise InternalError("Failed to change SST-BF configured state.") # update power profile configuration power.configure_power() res = {'message': "SST-BF caps modified"} return res, 200
def startup(self): result = True vehicle = API_Engine().get_vehicle() vehicle["did"] = ConfigStore().get_did() ConfigStore().set_vehicle(vehicle) # Check for PiCAN connection self.can = can_interface.CANHandler() self.can.startup() # Check for GPS connection self.gps = gps_interface.GPSHandler() self.gps.startup() return True
def __init__(self, hatari): confdirs = [".config/hatari", ".hatari"] ConfigStore.__init__(self, confdirs) conffilename = "hatari.cfg" self.load(self.get_filepath(conffilename)) self._hatari = hatari self._lock_updates = False self._desktop_w = 0 self._desktop_h = 0 self._options = [] self._winuae = hatari.is_winuae() # initialize has_* attribs for things that may not be anymore # valid on Hatari config file and/or command line self.get_machine() self.get_desktop_st()
def put(): """ Handles PUT /caps/mba_ctrl request. Raises BadRequest, InternalError Returns: response, status code """ json_data = request.get_json() # validate request try: schema, resolver = ConfigStore.load_json_schema( 'modify_mba_ctrl.json') jsonschema.validate(json_data, schema, resolver=resolver) except jsonschema.ValidationError as error: raise BadRequest("Request validation failed - %s" % (str(error))) if not caps.mba_bw_supported(): return {'message': "MBA CTRL not supported!"}, 409 if common.CONFIG_STORE.is_any_pool_defined(): return {'message': "Please remove all Pools first!"}, 409 data = deepcopy(common.CONFIG_STORE.get_config()) CapsMbaCtrl.set_mba_ctrl_enabled(data, json_data['enabled']) common.CONFIG_STORE.set_config(data) return {'message': "MBA CTRL status changed."}, 200
def make_refresh(self, tp, set_timestamp=False, save=True, send_notify=True): club_level = get_club_property(self.server_id, self.char_id, 'level') goods = ConfigStore.refresh(tp, club_level) try: tp_doc = self.doc['tp'][str(tp)] except KeyError: tp_doc = MongoStore.document_tp() if set_timestamp: tp_doc['refresh_at'] = arrow.utcnow().timestamp tp_doc['goods'] = {str(_id): {'index': _index, 'times': 0} for _id, _index in goods} self.doc['tp'][str(tp)] = tp_doc if save: MongoStore.db(self.server_id).update_one( {'_id': self.char_id}, {'$set': { 'tp.{0}'.format(tp): tp_doc }} ) if send_notify: self.send_notify(tp=tp)
def __init__(self, hatari): confdirs = [".config/hatari", ".hatari"] ConfigStore.__init__(self, confdirs) conffilename = "hatari.cfg" confpath = self.get_filepath(conffilename) print("confpath: %s" % confpath) error = self.load(confpath) if error: print("WARNING: %s %s!" % (confpath, error)) else: print("loaded config: %s" % confpath) self._hatari = hatari self._lock_updates = False self._desktop_w = 0 self._desktop_h = 0 self._options = [] self._winuae = hatari.is_winuae()
def write_requests(self): while True: for pid in ConfigStore().get_pids(): message = get_request_message(pid) self.bus.send(message) time.sleep(0.05) time.sleep(2)
def test_pool_mba_not_supported_cat(self): data = { "auth": { "password": "******", "username": "******" }, "pools": [{ "cbm": 0xf, "mba": 50, "cores": [1, 3], "id": 1, "name": "pool 1" }] } with pytest.raises(ValueError, match="MBA is not supported"): ConfigStore.validate(data)
def buy(self, tp, goods_id): if tp not in ALL_TYPES: raise GameException(ConfigErrorMessage.get_error_id("INVALID_OPERATE")) config = ConfigStore.get(goods_id) if not config: raise GameException(ConfigErrorMessage.get_error_id("STORE_GOODS_NOT_EXIST")) try: data = self.doc['tp'][str(tp)]['goods'][str(goods_id)] except KeyError: raise GameException(ConfigErrorMessage.get_error_id("INVALID_OPERATE")) if data['times'] >= config.times_limit: raise GameException(ConfigErrorMessage.get_error_id("STORE_GOODS_NO_TIMES")) if config.condition_id == 1: # VIP 等级 VIP(self.server_id, self.char_id).check(config.condition_value) elif config.condition_id == 2: # 爬塔历史最高星 Tower(self.server_id, self.char_id).check_history_max_star(config.condition_value) elif config.condition_id == 3: # 竞技场当前排名 Arena(self.server_id, self.char_id).check_current_rank(config.condition_value) elif config.condition_id == 4: # 当前公会等级 Union(self.server_id, self.char_id).check_level(config.condition_value) item_id, item_amount, need_id, need_amount = config.content[data['index']] resource_classify = ResourceClassification.classify([(need_id, need_amount)]) resource_classify.check_exist(self.server_id, self.char_id) resource_classify.remove(self.server_id, self.char_id, message="Store.buy:{0}".format(goods_id)) resource_classify = ResourceClassification.classify([(item_id, item_amount)]) resource_classify.add(self.server_id, self.char_id, message="Store.buy:{0}".format(goods_id)) data['times'] += 1 MongoStore.db(self.server_id).update_one( {'_id': self.char_id}, {'$set': { 'tp.{0}.goods.{1}.times'.format(tp, goods_id): data['times'] }} ) self.send_notify(tp=tp) return resource_classify
def post(): """ Handles HTTP POST /pools request. Add a new Pool Raises NotFound, BadRequest, InternalError Returns: response, status code """ json_data = request.get_json() # validate pool schema try: schema, resolver = ConfigStore.load_json_schema('add_pool.json') jsonschema.validate(json_data, schema, resolver=resolver) except jsonschema.ValidationError as error: raise BadRequest("Request validation failed - %s" % (str(error))) post_data = json_data.copy() post_data['id'] = common.CONFIG_STORE.get_new_pool_id(post_data) if post_data['id'] is None: raise InternalError("New POOL not added, maximum number of POOLS"\ " reached for requested allocation combination") # convert cbm from string to int if 'cbm' in post_data: cbm = post_data['cbm'] if not isinstance(cbm, int): cbm = int(cbm, 16) post_data['cbm'] = cbm data = common.CONFIG_STORE.get_config().copy() data['pools'].append(post_data) try: common.CONFIG_STORE.validate(data) except Exception as ex: raise BadRequest("New POOL not added, " + str(ex)) else: common.CONFIG_STORE.set_config(data) res = {'id': post_data['id']} return res, 201
def load_options(self): # TODO: move config to MemoryAddress class? # (depends on how monitoring of addresses should work) lines = self.address.get_lines() follow_pc = self.address.get_follow_pc() miss_is_error = False # needed for adding windows defaults = { "[General]": { "nLines": lines, "bFollowPC": follow_pc } } userconfdir = ".hatari" config = ConfigStore(userconfdir, defaults, miss_is_error) configpath = config.get_filepath("debugui.cfg") config.load(configpath) # set defaults try: self.address.set_lines(config.get("[General]", "nLines")) self.address.set_follow_pc(config.get("[General]", "bFollowPC")) except (KeyError, AttributeError): ErrorDialog(None).run("Debug UI configuration mismatch!\nTry again after removing: '%s'." % configpath) self.config = config
def put(pool_id): # pylint: disable=too-many-branches """ Handles HTTP PUT /pools/<pool_id> request. Modifies a Pool Raises NotFound, BadRequest, InternalError Parameters: pool_id: Id of pool Returns: response, status code """ def check_alloc_tech(pool_id, json_data): alloc_tech = [] if 'cbm' in json_data: alloc_tech.append(common.CAT_CAP) if 'mba' in json_data: alloc_tech.append(common.MBA_CAP) if not alloc_tech: return True return pool_id <= common.PQOS_API.get_max_cos_id(alloc_tech) json_data = request.get_json() # validate app schema try: schema, resolver = ConfigStore.load_json_schema('modify_pool.json') jsonschema.validate(json_data, schema, resolver=resolver) except jsonschema.ValidationError as error: raise BadRequest("Request validation failed - %s" % (str(error))) data = common.CONFIG_STORE.get_config().copy() if 'pools' not in data: raise NotFound("No pools in config file") for pool in data['pools']: if pool['id'] != int(pool_id): continue if not check_alloc_tech(int(pool_id), json_data): raise BadRequest("Pool {} does not support requested technologies!"\ .format(pool_id)) # set new cbm if 'cbm' in json_data: cbm = json_data['cbm'] if not isinstance(cbm, int): cbm = int(cbm, 16) pool['cbm'] = cbm # set new mba if 'mba' in json_data: pool['mba'] = json_data['mba'] # set new cores if 'cores' in json_data: pool['cores'] = json_data['cores'] if 'apps' in pool and pool['apps']: for app_id in pool['apps']: for app in data['apps']: if app['id'] != app_id or 'cores' not in app: continue if not set(app['cores']).issubset(pool['cores']): app.pop('cores') # set new name if 'name' in json_data: pool['name'] = json_data['name'] try: common.CONFIG_STORE.validate(data) except Exception as ex: raise BadRequest("POOL " + str(pool_id) + " not updated, " + str(ex)) else: common.CONFIG_STORE.set_config(data) return "POOL " + str(pool_id) + " updated", 200 raise NotFound("POOL " + str(pool_id) + " not found in config")
def post(): # pylint: disable=too-many-branches """ Handles HTTP POST /apps request. Add a new App Raises NotFound, BadRequest, InternalError Returns: response, status code """ def get_app_id(): """ Get ID for new App Returns: ID for new App """ # put all ids into list app_ids = [] for app in data['apps']: app_ids.append(app['id']) app_ids = sorted(app_ids) # no app found in config if not app_ids: return 1 # add new app to apps # find an id new_ids = list(set(range(1, app_ids[-1])) - set(app_ids)) if new_ids: return new_ids[0] return app_ids[-1] + 1 json_data = request.get_json() # validate app schema try: schema, resolver = ConfigStore.load_json_schema('add_app.json') jsonschema.validate(json_data, schema, resolver=resolver) except jsonschema.ValidationError as error: raise BadRequest("Request validation failed - %s" % (str(error))) data = deepcopy(common.CONFIG_STORE.get_config()) if 'pools' not in data: raise NotFound("No pools in config file") json_data['id'] = get_app_id() if 'pids' in json_data: # validate pids for pid in json_data['pids']: valid = pid_ops.is_pid_valid(pid) if not valid: raise BadRequest("New APP not added, please provide valid pid's") # if pool_id not provided on app creation if 'pool_id' not in json_data or not json_data['pool_id']: json_data['pool_id'] = None # if apps cores list is a subset of existing pool cores list, # make existing pool a destination pool for app if 'cores' in json_data and json_data['cores']: for pool in data['pools']: if set(json_data['cores']).issubset(pool['cores']): json_data['pool_id'] = pool['id'] break # if it is not, make default pool a destination pool if json_data['pool_id'] is None: json_data['pool_id'] = 0 if 'cores' in json_data: json_data.pop('cores') # update pool configuration to include new app for pool in data['pools']: if pool['id'] == json_data['pool_id']: if not 'apps' in pool: pool['apps'] = [] pool['apps'].append(json_data['id']) break json_data.pop('pool_id') data['apps'].append(json_data) try: common.CONFIG_STORE.validate(data) except Exception as ex: raise BadRequest("New APP not added, " + str(ex)) else: common.CONFIG_STORE.set_config(data) res = {'id': json_data['id']} return res, 201
def put(app_id): """ Handles HTTP PUT /apps/<app_id> request. Modifies an App (e.g.: moves to different pool) Raises NotFound, InternalError Parameters: app_id: Id of app to modify Returns: response, status code """ json_data = request.get_json() # validate app schema try: schema, resolver = ConfigStore.load_json_schema('move_app.json') jsonschema.validate(json_data, schema, resolver=resolver) except jsonschema.ValidationError as error: raise BadRequest("Request validation failed - %s" % (str(error))) pool_id = json_data["pool_id"] data = deepcopy(common.CONFIG_STORE.get_config()) if 'apps' not in data or 'pools' not in data: raise NotFound("No apps or pools in config file") for app in data['apps']: if app['id'] != int(app_id): continue # remove app id from pool for pool in data['pools']: if 'apps' in pool: if app['id'] in pool['apps']: pool['apps'].remove(app['id']) break # add app id to new pool for pool in data['pools']: if pool['id'] == int(pool_id): if 'apps' in pool: pool['apps'].append(app['id']) break else: pool['apps'] = [app['id']] break # set new cores if 'cores' in json_data: app['cores'] = json_data['cores'] elif 'cores' in app: app.pop('cores') try: common.CONFIG_STORE.validate(data) except Exception as ex: raise BadRequest("APP not updated, " + str(ex)) else: common.CONFIG_STORE.set_config(data) common.STATS_STORE.general_stats_inc_apps_moves() return "APP " + str(app_id) + " moved to new pool", 200 raise NotFound("APP " + str(app_id) + " not found in config")