def delete(pool_id): """ Handles HTTP DELETE /pool/<pull_id> request. Deletes single Pool Raises NotFound, BadRequest Parameters: pool_id: Id of pool to delete Returns: response, status code """ data = deepcopy(common.CONFIG_STORE.get_config()) if 'pools' not in data: raise NotFound("No pools in config file") if int(pool_id) == 0: raise BadRequest("POOL " + str(pool_id) + " is Default, cannot delete") for pool in data['pools']: if pool['id'] != int(pool_id): continue if 'apps' in pool and pool['apps']: raise BadRequest("POOL " + str(pool_id) + " is not empty") # remove app data['pools'].remove(pool) common.CONFIG_STORE.set_config(data) res = {'message': "POOL " + str(pool_id) + " deleted"} return res, 200 raise NotFound("POOL " + str(pool_id) + " not found in config")
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 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))) admission_control_check = json_data.pop('verify', True) and\ ('cores' in json_data or 'power_profile' in json_data) 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 # ignore 'power_profile' if SST-BF is enabled if sstbf.is_sstbf_configured(): post_data.pop('power_profile', None) data = deepcopy(common.CONFIG_STORE.get_config()) data['pools'].append(post_data) try: common.CONFIG_STORE.validate(data, admission_control_check) except Exception as ex: raise BadRequest("New POOL not added, " + str(ex)) common.CONFIG_STORE.set_config(data) res = { 'id': post_data['id'], 'message': "New POOL {} added".format(post_data['id']) } return res, 201
def check_alloc_tech(pool_id, json_data): if 'cbm' in json_data: if not caps.cat_supported(): raise BadRequest("System does not support CAT!") if pool_id > common.PQOS_API.get_max_cos_id([common.CAT_CAP]): raise BadRequest("Pool {} does not support CAT".format(pool_id)) if 'mba' in json_data: if not caps.mba_supported(): raise BadRequest("System does not support MBA!") if pool_id > common.PQOS_API.get_max_cos_id([common.MBA_CAP]): raise BadRequest("Pool {} does not support MBA".format(pool_id))
def put(profile_id): # pylint: disable=too-many-branches """ Handles HTTP PUT /power_profiles/<profile_id> request. Modifies a Power Profile Raises NotFound, BadRequest Parameters: profile_id: Id of pool Returns: response, status code """ json_data = request.get_json() # validate app schema try: schema, resolver = common.CONFIG_STORE.load_json_schema( 'modify_power.json') jsonschema.validate(json_data, schema, resolver=resolver) except jsonschema.ValidationError as error: raise BadRequest("Request validation failed - %s" % (str(error))) admission_control_check = json_data.pop('verify', True) data = deepcopy(common.CONFIG_STORE.get_config()) if 'power_profiles' not in data: raise NotFound("No Power Profiles in config file") for profile in data['power_profiles']: if profile['id'] != int(profile_id): continue # set new values profile.update(json_data) try: common.CONFIG_STORE.validate(data, admission_control_check) except Exception as ex: raise BadRequest("POWER PROFILE " + str(profile_id) + " not updated, " + str(ex)) common.CONFIG_STORE.set_config(data) res = {'message': "POWER PROFILE " + str(profile_id) + " updated"} return res, 200 raise NotFound("POWER PROFILE" + str(profile_id) + " not found in config")
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 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 post(): """ Handles HTTP POST /power_profiles request. Add a new Power Profile Raises BadRequest Returns: response, status code """ # validate power profile schema json_data = request.get_json() try: schema, resolver = common.CONFIG_STORE.load_json_schema( 'add_power.json') jsonschema.validate(json_data, schema, resolver=resolver) except jsonschema.ValidationError as error: raise BadRequest("Request validation failed - %s" % (str(error))) json_data['id'] = common.CONFIG_STORE.get_new_power_profile_id() data = deepcopy(common.CONFIG_STORE.get_config()) if 'power_profiles' not in data: data['power_profiles'] = [] data['power_profiles'].append(json_data) try: common.CONFIG_STORE.validate(data, False) except Exception as ex: raise BadRequest("New POWER PROFILE not added, " + str(ex)) common.CONFIG_STORE.set_config(data) res = { 'id': json_data['id'], 'message': "New POWER PROFILE {} added".format(json_data['id']) } return res, 201
def delete(profile_id): """ Handles HTTP DELETE /power_profiles/<profile_id> request. Deletes single Power Profile Raises NotFound, BadRequest Parameters: profile_id: Id of power_profile to delete Returns: response, status code """ data = deepcopy(common.CONFIG_STORE.get_config()) if 'power_profiles' not in data: raise NotFound("No Power Profiles in config file") for profile in data['power_profiles']: if profile['id'] != int(profile_id): continue for pool in data['pools']: if 'power_profile' not in pool: continue if pool['power_profile'] == int(profile_id): raise BadRequest("POWER PROFILE {} is in use.".format( str(profile_id))) # remove profile data['power_profiles'].remove(profile) common.CONFIG_STORE.set_config(data) res = {'message': "POWER PROFILE " + str(profile_id) + " deleted"} return res, 200 raise NotFound("POWER PROFILE " + str(profile_id) + " not found in config")
def check_alloc_tech(pool_id, json_data): if 'cbm' in json_data: if not caps.cat_l3_supported(): raise BadRequest("System does not support CAT!") if pool_id > common.PQOS_API.get_max_cos_id([common.CAT_L3_CAP]): raise BadRequest("Pool {} does not support CAT".format(pool_id)) if 'mba' in json_data or 'mba_bw' in json_data: if not caps.mba_supported(): raise BadRequest("System does not support MBA!") if pool_id > common.PQOS_API.get_max_cos_id([common.MBA_CAP]): raise BadRequest("Pool {} does not support MBA".format(pool_id)) if 'mba_bw' in json_data and not caps.mba_bw_enabled(): raise BadRequest("MBA CTRL is not {}!"\ .format("enabled" if caps.mba_bw_supported() else "supported")) if 'mba' in json_data and caps.mba_bw_enabled(): raise BadRequest("MBA RATE is disabled! Disable MBA CTRL and try again.")
def post(): # pylint: disable=too-many-branches """ Handles HTTP POST /apps request. Add a new App Raises NotFound, BadRequest Returns: response, status code """ 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'] = common.CONFIG_STORE.get_new_app_id() if 'pids' in json_data: # validate pids for pid in json_data['pids']: if not pid_ops.is_pid_valid(pid): raise BadRequest("New APP not added, invalid PID: " + str(pid)) # 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 core in json_data['cores']: if not common.PQOS_API.check_core(core): raise BadRequest("New APP not added, invalid core: " + str(core)) 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') try: pool = common.CONFIG_STORE.get_pool(data, json_data['pool_id']) except Exception as ex: raise BadRequest("New APP not added, " + str(ex)) # update pool configuration to include new app if not 'apps' in pool: pool['apps'] = [] pool['apps'].append(json_data['id']) json_data.pop('pool_id') data['apps'].append(json_data) try: common.CONFIG_STORE.validate(data) except AdmissionControlError: pass except Exception as ex: raise BadRequest("New APP not added, " + str(ex)) common.CONFIG_STORE.set_config(data) res = { 'id': json_data['id'], 'message': "New APP added to pool {}".format(str(pool['id'])) } return res, 201
def put(app_id): # pylint: disable=too-many-branches """ Handles HTTP PUT /apps/<app_id> request. Modifies an App (e.g.: moves to different pool) Raises NotFound, BadRequest 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('modify_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 'apps' not in data or 'pools' not in data: raise NotFound("No apps or pools in config file") # move to another pool for app in data['apps']: if app['id'] != int(app_id): continue if 'pool_id' in json_data: pool_id = json_data['pool_id'] # 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 not 'apps' in pool: pool['apps'] = [] pool['apps'].append(app['id']) break # set new cores if 'cores' in json_data: app['cores'] = json_data['cores'] # set new name if 'name' in json_data: app['name'] = json_data['name'] # set new PIDs if 'pids' in json_data: app['pids'] = json_data['pids'] try: common.CONFIG_STORE.validate(data) except AdmissionControlError: pass except Exception as ex: raise BadRequest("APP " + str(app_id) + " not updated, " + str(ex)) common.CONFIG_STORE.set_config(data) if 'pool_id' in json_data: common.STATS_STORE.general_stats_inc_apps_moves() res = {'message': "APP " + str(app_id) + " updated"} return res, 200 raise NotFound("APP " + str(app_id) + " not found in config")
def put(pool_id): # pylint: disable=too-many-branches """ Handles HTTP PUT /pools/<pool_id> request. Modifies a Pool Raises NotFound, BadRequest Parameters: pool_id: Id of pool Returns: response, status code """ def check_alloc_tech(pool_id, json_data): if 'cbm' in json_data: if not caps.cat_supported(): raise BadRequest("System does not support CAT!") if pool_id > common.PQOS_API.get_max_cos_id([common.CAT_CAP]): raise BadRequest( "Pool {} does not support CAT".format(pool_id)) if 'mba' in json_data: if not caps.mba_supported(): raise BadRequest("System does not support MBA!") if pool_id > common.PQOS_API.get_max_cos_id([common.MBA_CAP]): raise BadRequest( "Pool {} does not support MBA".format(pool_id)) 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))) admission_control_check = json_data.pop('verify', True) and\ ('cores' in json_data or 'power_profile' in json_data) data = deepcopy(common.CONFIG_STORE.get_config()) if 'pools' not in data: raise NotFound("No pools in config file") for pool in data['pools']: if pool['id'] != int(pool_id): continue check_alloc_tech(int(pool_id), json_data) # 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'] # set new power profile # ignore 'power_profile' if SST-BF is enabled if 'power_profile' in json_data and not sstbf.is_sstbf_configured( ): pool['power_profile'] = json_data['power_profile'] try: common.CONFIG_STORE.validate(data, admission_control_check) except Exception as ex: raise BadRequest("POOL " + str(pool_id) + " not updated, " + str(ex)) common.CONFIG_STORE.set_config(data) res = {'message': "POOL " + str(pool_id) + " updated"} return res, 200 raise NotFound("POOL " + str(pool_id) + " not found in config")