From d9a9520bd7efe2f022c0ad3de37b0c4ada4789df Mon Sep 17 00:00:00 2001 From: MD IRSHAD SHEIKH Date: Thu, 18 Feb 2021 18:31:25 +0530 Subject: Add support to process NST Selection for HAS Issue-ID: OPTFRA-911 Signed-off-by: MD IRSHAD SHEIKH Change-Id: I809857348b00fe415d416954b1cfbedd404bdffc --- apps/nst/optimizers/nst_select_processor.py | 90 +++++++++++++++------- config/common_config.yaml | 23 ++++++ osdf/adapters/conductor/translation.py | 1 - osdfapp.py | 2 + .../nst-selection-files/attribute_policy_nst.json | 42 ++++++++++ .../optimization_policy_nst.json | 37 +++++++++ .../nst-selection-files/query_policy_nst.json | 31 ++++++++ .../nst-selection-files/vnf_policy_nst.json | 34 ++++++++ 8 files changed, 231 insertions(+), 29 deletions(-) create mode 100644 test/policy-local-files/nst-selection-files/attribute_policy_nst.json create mode 100644 test/policy-local-files/nst-selection-files/optimization_policy_nst.json create mode 100644 test/policy-local-files/nst-selection-files/query_policy_nst.json create mode 100644 test/policy-local-files/nst-selection-files/vnf_policy_nst.json diff --git a/apps/nst/optimizers/nst_select_processor.py b/apps/nst/optimizers/nst_select_processor.py index faab999..5b31f73 100644 --- a/apps/nst/optimizers/nst_select_processor.py +++ b/apps/nst/optimizers/nst_select_processor.py @@ -18,8 +18,10 @@ """ This application generates NST SELECTION API calls using the information received from SO """ -import json import os +from osdf.adapters.conductor import conductor +from osdf.adapters.policy.interface import get_policies +from osdf.logging.osdf_logging import debug_log from osdf.logging.osdf_logging import error_log from osdf.utils.interfaces import get_rest_client from requests import RequestException @@ -38,6 +40,7 @@ class NstSelection(Thread): self.osdf_config = osdf_config self.request_json = request_json self.request_info = self.request_json['requestInfo'] + self.request_info['numSolutions'] = 1 def run(self): self.process_nst_selection() @@ -52,7 +55,6 @@ class NstSelection(Thread): try: rest_client = get_rest_client(self.request_json, service='so') solution = self.get_nst_solution() - solution = self.get_nst_selection_response(solution) except Exception as err: error_log.error("Error for {} {}".format(self.request_info.get('requestId'), traceback.format_exc())) @@ -70,32 +72,12 @@ class NstSelection(Thread): integrated there... """ - - config_input_json = os.path.join(BASE_DIR, 'conf/configIinputs.json') - with open(config_input_json, 'r') as openfile: - service_profile = self.request_json["serviceProfile"] - nst_solution_list = [] - resource_name = "NST" - nst_object = json.load(openfile) - for nst in nst_object[resource_name]: - [(nst_name, nst_list)] = nst.items() - individual_nst = dict() - matchall = False - for constraint_name in service_profile: - constraint_value = nst_list.get(constraint_name) - if not constraint_value: - matchall = False - break - else: - matchall = True - if matchall: - individual_nst["NSTName"] = nst_list.get("name") - individual_nst["UUID"] = nst_list.get("modeluuid") - individual_nst["invariantUUID"] = nst_list.get("modelinvariantuuid") - individual_nst["individual_nst"] = 1 - nst_solution_list.append(individual_nst) - - return nst_solution_list + req_info = self.request_json['requestInfo'] + requirements = self.request_json['serviceProfile'] + model_name = "nst" + policies = self.get_app_policies(model_name, "nst_selection") + conductor_response = self.get_conductor(req_info, requirements, policies, model_name) + return conductor_response def get_nst_selection_response(self, solutions): """Get NST selection response from final solution @@ -119,3 +101,55 @@ class NstSelection(Thread): 'transactionId': self.request_info['transactionId'], 'requestStatus': 'error', 'statusMessage': error_message} + + def get_app_policies(self, model_name, app_name): + policy_request_json = self.request_json.copy() + policy_request_json['serviceInfo'] = {'serviceName': model_name} + debug_log.debug("policy_request_json {}".format(str(policy_request_json))) + return get_policies(policy_request_json, app_name) # app_name: nst_selection + + def get_conductor(self, req_info, request_parameters, policies, model_name): + demands = [ + { + "resourceModuleName": model_name, + "resourceModelInfo": {} + } + ] + + try: + template_fields = { + 'location_enabled': False, + 'version': '2020-08-13' + } + resp = conductor.request(req_info, demands, request_parameters, {}, template_fields, + self.osdf_config, policies) + except RequestException as e: + resp = e.response.json() + error = resp['plans'][0]['message'] + if "Unable to find any" in error: + return self.get_nst_selection_response([]) + error_log.error('Error from conductor {}'.format(error)) + return self.error_response(error) + debug_log.debug("Response from conductor in get_conductor method {}".format(str(resp))) + recommendations = resp["plans"][0].get("recommendations") + return self.process_response(recommendations, model_name) + + def process_response(self, recommendations, model_name): + """Process conductor response to form the response for the API request + + :param recommendations: recommendations from conductor + :return: response json as a dictionary + """ + if not recommendations: + return self.get_nst_selection_response([]) + solutions = [self.get_solution_from_candidate(rec[model_name]['candidate']) + for rec in recommendations] + return self.get_nst_selection_response(solutions) + + def get_solution_from_candidate(self, candidate): + if candidate['inventory_type'] == 'nst': + return { + 'UUID': candidate['model_version_id'], + 'invariantUUID': candidate['model_invariant_id'], + 'NSTName': candidate['name'], + } diff --git a/config/common_config.yaml b/config/common_config.yaml index d720fb2..d4d205e 100644 --- a/config/common_config.yaml +++ b/config/common_config.yaml @@ -12,6 +12,7 @@ osdf_temp: # special configuration required for "workarounds" or testing global_disabled: True local_placement_policies_enabled: True local_slice_selection_policies_enabled: True + local_nst_selection_policies_enabled: True placement_policy_dir_vcpe: "./test/policy-local-files/" placement_policy_files_vcpe: # workaroud for policy platform glitches (or "work-arounds" for other components) - Affinity_vCPE_1.json @@ -45,6 +46,17 @@ osdf_temp: # special configuration required for "workarounds" or testing - query_policy_nsi.json - threshold_policy_nsi.json - vnf_policy_nsi_shared_case.json + nst_selection_policy_dir_embb-nst: "./test/policy-local-files/nst-selection-files/" + nst_selection_policy_files_embb-nst: + - query_policy_nst.json + - attribute_policy_nst.json + - vnf_policy_nst.json + nst_selection_policy_dir_nst: "./test/policy-local-files/nst-selection-files/" + nst_selection_policy_files_nst: + - query_policy_nst.json + - attribute_policy_nst.json + - vnf_policy_nst.json + - optimization_policy_nst.json service_info: vCPE: @@ -89,6 +101,17 @@ policy_info: resources: - get_param: service_name + nst_selection: + policy_fetch: by_scope + policy_scope: + - + scope: + - OSDF_GUILIN + services: + - nst + resources: + - nst + subnet_selection: policy_fetch: by_scope policy_scope: diff --git a/osdf/adapters/conductor/translation.py b/osdf/adapters/conductor/translation.py index 238428a..f44f27f 100644 --- a/osdf/adapters/conductor/translation.py +++ b/osdf/adapters/conductor/translation.py @@ -320,7 +320,6 @@ def get_demand_properties(demand, policies): prop['filtering_attributes'].update({'equipment-role': policy_property['equipmentRole']} if 'equipmentRole' in policy_property and policy_property['equipmentRole'] else {}) - prop.update(get_candidates_demands(demand)) demand_properties.append(prop) return demand_properties diff --git a/osdfapp.py b/osdfapp.py index df85343..28f9376 100755 --- a/osdfapp.py +++ b/osdfapp.py @@ -126,7 +126,9 @@ def do_mdons_route_calc(): def do_nst_selection(): request_json = request.get_json() req_id = request_json['requestInfo']['requestId'] + audit_log.info(MH.received_request(request.url, request.remote_addr, json.dumps(request_json))) NSTSelectionAPI(request_json).validate() + audit_log.info(MH.new_worker_thread(req_id, "[for NST selection]")) nst_selection = NstSelection(osdf_config, request_json) nst_selection.start() return req_accept(request_id=req_id, diff --git a/test/policy-local-files/nst-selection-files/attribute_policy_nst.json b/test/policy-local-files/nst-selection-files/attribute_policy_nst.json new file mode 100644 index 0000000..0989927 --- /dev/null +++ b/test/policy-local-files/nst-selection-files/attribute_policy_nst.json @@ -0,0 +1,42 @@ +{ + "Threshold_nst": { + "metadata": { + "policy-id": "Threshold_nst", + "policy-version": 1 + }, + "properties": { + "geography": [], + "identity": "nst_Threshold", + "resources": [ + "nst" + ], + "scope": [ + "OSDF_GUILIN" + ], + "services": [ + "nst" + ], + "thresholdProperties": [ + { + "attribute": "latency", + "operator": "lte", + "threshold": { + "get_param": "latency" + }, + "unit": "ms" + }, + { + "attribute": "reliability", + "operator": "gte", + "threshold": { + "get_param": "reliability" + }, + "unit": "" + } + ] + }, + "type": "onap.policies.optimization.resource.ThresholdPolicy", + "type_version": "1.0.0", + "version": "1.0.0" + } +} \ No newline at end of file diff --git a/test/policy-local-files/nst-selection-files/optimization_policy_nst.json b/test/policy-local-files/nst-selection-files/optimization_policy_nst.json new file mode 100644 index 0000000..27c1f7c --- /dev/null +++ b/test/policy-local-files/nst-selection-files/optimization_policy_nst.json @@ -0,0 +1,37 @@ +{ + "nst_minimize_latency": { + "metadata": { + "policy-id": "nst_minimize_latency", + "policy-version": 1 + }, + "properties": { + "geography": [], + "identity": "optimization", + "goal": "minimize", + "operation_function": { + "operator": "sum", + "operands": [ + { + "function": "attribute", + "params": { + "attribute": "latency", + "demand": "nst" + } + } + ] + }, + "resources": [ + "nst" + ], + "scope": [ + "OSDF_GUILIN" + ], + "services": [ + "nst" + ] + }, + "type": "onap.policies.optimization.resource.OptimizationPolicy", + "type_version": "2.0.0", + "version": "1.0.0" + } +} \ No newline at end of file diff --git a/test/policy-local-files/nst-selection-files/query_policy_nst.json b/test/policy-local-files/nst-selection-files/query_policy_nst.json new file mode 100644 index 0000000..1955e7b --- /dev/null +++ b/test/policy-local-files/nst-selection-files/query_policy_nst.json @@ -0,0 +1,31 @@ +{ + "queryPolicy_nst": { + "type": "onap.policies.optimization.service.QueryPolicy", + "version": "1.0.0", + "type_version": "1.0.0", + "metadata": { + "policy-id": "queryPolicy_nst", + "policy-version": 1 + }, + "properties": { + "scope": [ + "OSDF_GUILIN" + ], + "services": [ + "nst" + ], + "geography": [], + "identity": "queryPolicy_nst", + "queryProperties": [ + { + "attribute": "latency", + "attribute_location": "latency" + }, + { + "attribute": "reliability", + "attribute_location": "reliability" + } + ] + } + } +} \ No newline at end of file diff --git a/test/policy-local-files/nst-selection-files/vnf_policy_nst.json b/test/policy-local-files/nst-selection-files/vnf_policy_nst.json new file mode 100644 index 0000000..14906df --- /dev/null +++ b/test/policy-local-files/nst-selection-files/vnf_policy_nst.json @@ -0,0 +1,34 @@ +{ + "vnfPolicy_nst": { + "type": "onap.policies.optimization.resource.VnfPolicy", + "version": "1.0.0", + "type_version": "1.0.0", + "metadata": { + "policy-id": "vnfPolicy_nst", + "policy-version": 1 + }, + "properties": { + "scope": [ + "OSDF_GUILIN" + ], + "resources": [ + "nst" + ], + "services": [ + "nst" + ], + "identity": "vnf_nst", + "applicableResources": "any", + "vnfProperties": [ + { + "inventoryProvider": "aai", + "inventoryType": "nst", + "unique": "true", + "attributes": { + "model-role": "nst" + } + } + ] + } + } +} \ No newline at end of file -- cgit 1.2.3-korg