aboutsummaryrefslogtreecommitdiffstats
path: root/apps/slice_selection/optimizers/conductor/response_processor.py
diff options
context:
space:
mode:
Diffstat (limited to 'apps/slice_selection/optimizers/conductor/response_processor.py')
-rw-r--r--apps/slice_selection/optimizers/conductor/response_processor.py227
1 files changed, 86 insertions, 141 deletions
diff --git a/apps/slice_selection/optimizers/conductor/response_processor.py b/apps/slice_selection/optimizers/conductor/response_processor.py
index a9bdad0..71a350f 100644
--- a/apps/slice_selection/optimizers/conductor/response_processor.py
+++ b/apps/slice_selection/optimizers/conductor/response_processor.py
@@ -20,144 +20,89 @@
Module for processing response from conductor for slice selection
"""
-from osdf.logging.osdf_logging import debug_log
-
-
-SLICE_PROFILE_FIELDS = {"latency":"latency", "max_number_of_ues":"maxNumberOfUEs", "coverage_area_ta_list": "coverageAreaTAList",
- "ue_mobility_level":"uEMobilityLevel", "resource_sharing_level":"resourceSharingLevel", "exp_data_rate_ul": "expDataRateUL",
- "exp_data_rate_dl":"expDataRateDL", "area_traffic_cap_ul":"areaTrafficCapUL", "area_traffic_cap_dl": "areaTrafficCapDL",
- "activity_factor":"activityFactor", "e2e_latency":"e2eLatency", "jitter":"jitter", "survival_time": "survivalTime",
- "exp_data_rate":"expDataRate", "payload_size":"payloadSize", "traffic_density":"trafficDensity", "conn_density":"connDensity",
- "reliability":"reliability", "service_area_dimension":"serviceAreaDimension", "cs_availability": "csAvailability"}
-
-
-def conductor_response_processor(overall_recommendations, nst_info_map, request_info, service_profile):
- """Process conductor response to form the response for the API request
- :param overall_recommendations: recommendations from conductor
- :param nst_info_map: NST info from the request
- :param request_info: request info
- :return: response json as a dictionary
- """
- shared_nsi_solutions = list()
- new_nsi_solutions = list()
- for nst_name, recommendations in overall_recommendations.items():
- if not (recommendations):
- new_nsi_solution = solution_with_only_slice_profile(service_profile, nst_info_map.get(nst_name))
- new_nsi_solutions.append(new_nsi_solution)
- continue
-
- for recommendation in recommendations:
- nsi_set = set(values['candidate']['nsi_id'] for key, values in recommendation.items())
- if len(nsi_set) == 1:
- nsi_id = nsi_set.pop()
- candidate = list(recommendation.values())[0]['candidate']
- debug_log.debug("The NSSIs in the solution belongs to the same NSI {}"
- .format(nsi_id))
- shared_nsi_solution = dict()
- shared_nsi_solution["NSIId"] = nsi_id
- shared_nsi_solution["NSIName"] = candidate.get('nsi_name')
- shared_nsi_solution["UUID"] = candidate.get('nsi_model_version_id')
- shared_nsi_solution["invariantUUID"] = candidate.get('nsi_model_invariant_id')
-
- nssi_info_list = get_nssi_solutions(recommendation)
- nssis = list()
- for nssi_info in nssi_info_list:
- nssi = dict()
- nssi["NSSIId"] = nssi_info.get("NSSISolution").get("NSSIId")
- nssi["NSSIName"] = nssi_info.get("NSSISolution").get("NSSIName")
- nssi["UUID"] = ""
- nssi["invariantUUID"] = ""
- nssi_info.get("sliceProfile").update({"domainType":"cn"})
- nssi["sliceProfile"] = [nssi_info.get("sliceProfile")]
- nssis.append(nssi)
-
- shared_nsi_solution["NSSIs"] = nssis
- shared_nsi_solutions.append(shared_nsi_solution)
- else:
- nssi_solutions = get_nssi_solutions(recommendation)
- new_nsi_solution = dict()
- new_nsi_solution['matchLevel'] = ""
- new_nsi_solution['NSTInfo'] = nst_info_map.get(nst_name)
- new_nsi_solution['NSSISolutions'] = nssi_solutions
- new_nsi_solutions.append(new_nsi_solution)
-
- solutions = dict()
- solutions['sharedNSISolutions'] = shared_nsi_solutions
- solutions['newNSISolutions'] = new_nsi_solutions
- return get_nsi_selection_response(request_info, solutions)
-
-
-def solution_with_only_slice_profile(service_profile, nst_info):
- nssi_solutions = get_slice_profile_from_service_profile(service_profile)
- new_nsi_solution = dict()
- new_nsi_solution['matchLevel'] = ""
- new_nsi_solution['NSTInfo'] = nst_info
- new_nsi_solution['NSSISolutions'] = nssi_solutions
- return new_nsi_solution
-
-def conductor_error_response_processor(request_info, error_message):
- """Form response message from the error message
- :param request_info: request info
- :param error_message: error message while processing the request
- :return: response json as dictionary
- """
- return {'requestId': request_info['requestId'],
- 'transactionId': request_info['transactionId'],
- 'requestStatus': 'error',
- 'statusMessage': error_message}
-
-
-def get_slice_profile_from_service_profile(service_profile):
- nssi_solutions = list()
- service_profile["domainType"] = "cn"
- nssi_solution = {"sliceProfile": service_profile}
- nssi_solutions.append(nssi_solution)
- return nssi_solutions
-
-
-def get_nssi_solutions(recommendation):
- """Get nssi solutions from recommendation
- :param recommendation: recommendation from conductor
- :return: new nssi solutions list
- """
- nssi_solutions = list()
-
- for nsst_name, nsst_rec in recommendation.items():
- candidate = nsst_rec['candidate']
- nssi_info, slice_profile = get_solution_from_candidate(candidate)
- nsst_info = {"NSSTName": nsst_name}
- nssi_solution = {"sliceProfile": slice_profile,
- "NSSTInfo": nsst_info,
- "NSSISolution": nssi_info}
- nssi_solutions.append(nssi_solution)
- return nssi_solutions
-
-
-def get_solution_from_candidate(candidate):
- """Get nssi info from candidate
- :param candidate: Candidate from the recommendation
- :return: nssi_info and slice profile derived from candidate
- """
- slice_profile = dict()
- nssi_info = {"NSSIName": candidate['instance_name'],
- "NSSIId": candidate['candidate_id']}
-
- for field in SLICE_PROFILE_FIELDS:
- if candidate[field]:
- slice_profile[SLICE_PROFILE_FIELDS[field]] = candidate[field]
-
- return nssi_info, slice_profile
-
-
-def get_nsi_selection_response(request_info, solutions):
- """Get NSI selection response from final solution
- :param request_info: request info
- :param solutions: final solutions
- :return: NSI selection response to send back as dictionary
- """
- return {'requestId': request_info['requestId'],
- 'transactionId': request_info['transactionId'],
- 'requestStatus': 'completed',
- 'statusMessage': '',
- 'solutions': solutions}
-
+import re
+
+
+class ResponseProcessor(object):
+ def __init__(self, request_info, slice_config):
+ self.request_info = request_info
+ self.slice_config = slice_config
+
+ def process_response(self, recommendations, model_info, subnets):
+ """Process conductor response to form the response for the API request
+
+ :param recommendations: recommendations from conductor
+ :param model_info: model info from the request
+ :param subnets: list of subnets
+ :return: response json as a dictionary
+ """
+ if not recommendations:
+ return self.get_slice_selection_response([])
+ model_name = model_info['name']
+ solutions = [self.get_solution_from_candidate(rec[model_name]['candidate'], model_info, subnets)
+ for rec in recommendations]
+ return self.get_slice_selection_response(solutions)
+
+ def get_solution_from_candidate(self, candidate, model_info, subnets):
+ if candidate['inventory_type'] == 'nssi':
+ return {
+ 'UUID': model_info['UUID'],
+ 'invariantUUID': model_info['invariantUUID'],
+ 'NSSIName': candidate['instance_name'],
+ 'NSSIId': candidate['instance_id']
+ }
+
+ elif candidate['inventory_type'] == 'nsi':
+ return {
+ 'existingNSI': True,
+ 'sharedNSISolution': {
+ 'UUID': model_info['UUID'],
+ 'invariantUUID': model_info['invariantUUID'],
+ 'NSIName': candidate['instance_name'],
+ 'NSIId': candidate['instance_id']
+ }
+ }
+
+ elif candidate['inventory_type'] == 'slice_profiles':
+ return {
+ 'existingNSI': False,
+ 'newNSISolution': {
+ 'slice_profiles': self.get_slice_profiles_from_candidate(candidate, subnets)
+ }
+ }
+
+ def get_slice_profiles_from_candidate(self, candidate, subnets):
+ slice_profiles = []
+ for subnet in subnets:
+ slice_profile = {self.get_profile_attribute(k, subnet): v for k, v in candidate.items()
+ if k.startswith(subnet)}
+ slice_profile['domainType'] = subnet
+ slice_profiles.append(slice_profile)
+ return slice_profiles
+
+ def get_profile_attribute(self, attribute, subnet):
+ snake_to_camel = self.slice_config['attribute_mapping']['snake_to_camel']
+ return snake_to_camel[re.sub(f'^{subnet}_', '', attribute)]
+
+ def process_error_response(self, error_message):
+ """Form response message from the error message
+
+ :param error_message: error message while processing the request
+ :return: response json as dictionary
+ """
+ return {'requestId': self.request_info['requestId'],
+ 'transactionId': self.request_info['transactionId'],
+ 'requestStatus': 'error',
+ 'statusMessage': error_message}
+
+ def get_slice_selection_response(self, solutions):
+ """Get NSI selection response from final solution
+
+ :param solutions: final solutions
+ :return: NSI selection response to send back as dictionary
+ """
+ return {'requestId': self.request_info['requestId'],
+ 'transactionId': self.request_info['transactionId'],
+ 'requestStatus': 'completed',
+ 'statusMessage': '',
+ 'solutions': solutions}