From 14afccee59b0e835b5b03a014e6c435a64ef190f Mon Sep 17 00:00:00 2001 From: "aleem.raja@t-systems.com" Date: Mon, 27 Feb 2023 20:44:17 +0530 Subject: Add support to process NSST Selection for HAS Issue-ID: OPTFRA-1123 Signed-off-by: Aleem Raja Change-Id: Ib025bfe49948180a1808b5525dc1647ba04c3e0d --- conductor/conductor/controller/translator_utils.py | 2 +- .../data/plugins/inventory_provider/aai.py | 46 +++++++++++++++++++++- .../candidates/nsst_candidate.py | 29 ++++++++++++++ .../data/plugins/inventory_provider/sdc.py | 40 +++++++++++++++++++ .../plugins/inventory_provider/utils/aai_utils.py | 10 ++++- .../data/plugins/inventory_provider/utils/csar.py | 24 +++++++++-- conductor/conductor/data/service.py | 2 + conductor/conductor/solver/service.py | 2 +- 8 files changed, 147 insertions(+), 8 deletions(-) create mode 100644 conductor/conductor/data/plugins/inventory_provider/candidates/nsst_candidate.py diff --git a/conductor/conductor/controller/translator_utils.py b/conductor/conductor/controller/translator_utils.py index e4aa4e1..0f6f4a0 100644 --- a/conductor/conductor/controller/translator_utils.py +++ b/conductor/conductor/controller/translator_utils.py @@ -21,7 +21,7 @@ VERSIONS = {'BASE': ["2016-11-01", "2017-10-10", "2018-02-01"], 'GENERIC': ["2020-08-13"]} LOCATION_KEYS = ['latitude', 'longitude', 'host_name', 'clli_code'] INVENTORY_PROVIDERS = ['aai', 'generator', 'sdc'] -INVENTORY_TYPES = ['cloud', 'service', 'transport', 'vfmodule', 'nssi', 'nsi', 'slice_profiles', 'nst'] +INVENTORY_TYPES = ['cloud', 'service', 'transport', 'vfmodule', 'nssi', 'nsi', 'slice_profiles', 'nst', 'nsst'] DEFAULT_INVENTORY_PROVIDER = INVENTORY_PROVIDERS[0] CANDIDATE_KEYS = ['candidate_id', 'cost', 'inventory_type', 'location_id', 'location_type'] diff --git a/conductor/conductor/data/plugins/inventory_provider/aai.py b/conductor/conductor/data/plugins/inventory_provider/aai.py index 7bbbe68..999c0ae 100644 --- a/conductor/conductor/data/plugins/inventory_provider/aai.py +++ b/conductor/conductor/data/plugins/inventory_provider/aai.py @@ -27,7 +27,6 @@ import uuid from oslo_config import cfg from oslo_log import log - from conductor.common import rest from conductor.data.plugins import constants from conductor.data.plugins.inventory_provider import base @@ -765,7 +764,7 @@ class AAI(base.InventoryProviderBase): if match_type == 'any': if attribute_key not in inventory_attributes or \ (len(attribute_values) > 0 and inventory_attributes[attribute_key] and - inventory_attributes[attribute_key] not in attribute_values): + inventory_attributes[attribute_key] not in attribute_values): return False elif match_type == 'not': # drop the candidate when @@ -1677,6 +1676,17 @@ class AAI(base.InventoryProviderBase): inventory_type) resolved_demands[name].extend(SDC().update_candidates(sdc_candidates_list)) + elif inventory_type == 'nsst': + if filtering_attributes: + second_level_match = aai_utils.get_first_level_and_second_level_filter(filtering_attributes, + "Nsst") + aai_response = self.get_nsst_response(filtering_attributes) + + sdc_candidates_list = self.get_nsst_candidates(aai_response, second_level_match, + default_attributes, candidate_uniqueness, + inventory_type) + resolved_demands[name].extend(SDC().update_candidates_nsst(sdc_candidates_list)) + else: LOG.error("Unknown inventory_type " " {}".format(inventory_type)) @@ -1950,6 +1960,17 @@ class AAI(base.InventoryProviderBase): if aai_response.json(): return aai_response.json() + def get_nsst_response(self, filtering_attributes): + raw_path = 'service-design-and-creation/models' + aai_utils.add_query_params_and_depth(filtering_attributes, + "2") + path = self._aai_versioned_path(raw_path) + aai_response = self._request('get', path, data=None) + + if aai_response is None or aai_response.status_code != 200: + return None + if aai_response.json(): + return aai_response.json() + def get_nst_candidates(self, response_body, filtering_attributes, default_attributes, candidate_uniqueness, type): candidates = list() @@ -1970,3 +1991,24 @@ class AAI(base.InventoryProviderBase): profile_info=None) candidates.append(nst_candidate) return candidates + + def get_nsst_candidates(self, response_body, filtering_attributes, default_attributes, candidate_uniqueness, + type): + candidates = list() + if response_body is not None: + nsst_metadatas = response_body.get("model", []) + + for nsst_metadata in nsst_metadatas: + nsst_info = aai_utils.get_nsst_info(nsst_metadata) + model_vers = nsst_metadata.get('model-vers').get('model-ver') + for model_ver in model_vers: + model_version_id = model_ver.get('model-version-id') + cost = self.conf.data.nsst_candidate_cost + info = Candidate.build_candidate_info('aai', type, cost, candidate_uniqueness, model_version_id) + model_version_obj = aai_utils.get_model_ver_info(model_ver) + model_ver_info = aai_utils.convert_hyphen_to_under_score(model_version_obj) + nst_candidate = NST(model_info=nsst_info, model_ver=model_ver_info, info=info, + default_fields=aai_utils.convert_hyphen_to_under_score(default_attributes), + profile_info=None) + candidates.append(nst_candidate) + return candidates diff --git a/conductor/conductor/data/plugins/inventory_provider/candidates/nsst_candidate.py b/conductor/conductor/data/plugins/inventory_provider/candidates/nsst_candidate.py new file mode 100644 index 0000000..56eb0ca --- /dev/null +++ b/conductor/conductor/data/plugins/inventory_provider/candidates/nsst_candidate.py @@ -0,0 +1,29 @@ +# +# ------------------------------------------------------------------------- +# Copyright (C) 2020 Wipro Limited. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ------------------------------------------------------------------------- +# + +from conductor.data.plugins.inventory_provider.candidates.candidate import Candidate + + +class NSST(Candidate): + def __init__(self, **kwargs): + super().__init__(kwargs['info']) + self.nsst_info = kwargs['model_info'] + self.model_ver_info = kwargs['model_ver'] + self.profile_info = kwargs['profile_info'] + self.other = kwargs['default_fields'] diff --git a/conductor/conductor/data/plugins/inventory_provider/sdc.py b/conductor/conductor/data/plugins/inventory_provider/sdc.py index c69d7b0..f7fc1d6 100644 --- a/conductor/conductor/data/plugins/inventory_provider/sdc.py +++ b/conductor/conductor/data/plugins/inventory_provider/sdc.py @@ -172,6 +172,28 @@ class SDC(object): candidateslist.append(finalcandidate) return candidateslist + def update_candidates_nsst(self, candidates): + absfilepath = self.conf.sdc.temp_path + candidateslist = [] + for candidate in candidates: + model_ver_obj = candidate.model_ver_info + model_name = model_ver_obj['model_name'] + self.model_version_id = candidate.candidate_id + response = self.get_nsst_template(self.model_version_id) + filepath = os.path.join(absfilepath, "{}.csar".format(self.model_version_id)) + if not os.path.exists(absfilepath): + os.makedirs(absfilepath) + f = open(filepath, "wb") + file_res = response.content + f.write(file_res) + obj = csar.SDCCSAR(filepath, model_name) + nsst_temp_prop = obj.validate() + nsst_properties = self.get_nsst_prop_dict(nsst_temp_prop) + candidate.profile_info = nsst_properties + finalcandidate = candidate.convert_nested_dict_to_dict() + candidateslist.append(finalcandidate) + return candidateslist + def get_nst_prop_dict(self, nst_properties): properties_dict = dict() for key in list(nst_properties): @@ -181,6 +203,15 @@ class SDC(object): properties_dict[key] = temp_dict[temp_key] return properties_dict + def get_nsst_prop_dict(self, nsst_properties): + properties_dict = dict() + for key in list(nsst_properties): + temp_dict = nsst_properties[key] + for temp_key in list(temp_dict): + if "default" in temp_key: + properties_dict[key] = temp_dict[temp_key] + return properties_dict + def get_nst_template(self, ver_id): raw_path = "/catalog/services/{}/toscaModel".format(ver_id) path = self._sdc_versioned_path(raw_path) @@ -189,3 +220,12 @@ class SDC(object): return None if sdc_response: return sdc_response + + def get_nsst_template(self, ver_id): + raw_path = "/catalog/services/{}/toscaModel".format(ver_id) + path = self._sdc_versioned_path(raw_path) + sdc_response = self._request('get', path, data=None) + if sdc_response is None or sdc_response.status_code != 200: + return None + if sdc_response: + return sdc_response diff --git a/conductor/conductor/data/plugins/inventory_provider/utils/aai_utils.py b/conductor/conductor/data/plugins/inventory_provider/utils/aai_utils.py index c88b459..5191c91 100644 --- a/conductor/conductor/data/plugins/inventory_provider/utils/aai_utils.py +++ b/conductor/conductor/data/plugins/inventory_provider/utils/aai_utils.py @@ -20,7 +20,7 @@ QUERY_PARAMS = {'service_instance': ["service-instance-id", "service-instance-name", "environment-context", "workload-context", "model-invariant-id", "model-version-id", "widget-model-id", "widget-model-version", "service-instance-location-id", "orchestration-status"], - 'nst': ["model-role"] + 'nst': ["model-role"], 'Nsst': ["model-role"] } @@ -90,6 +90,14 @@ def get_nst_info(nst_instance): return nst_dict +def get_nsst_info(nsst_instance): + nsst_dict = {} + nsst_dict['model_invariant_id'] = nsst_instance.get('model-invariant-id') + nsst_dict['model_type'] = nsst_instance.get('model-type') + nsst_dict['model_role'] = nsst_instance.get('model-role') + return nsst_dict + + def get_model_ver_info(model_version): for key in list(model_version): if "model-elements" in key: diff --git a/conductor/conductor/data/plugins/inventory_provider/utils/csar.py b/conductor/conductor/data/plugins/inventory_provider/utils/csar.py index 0caccac..dc0977c 100644 --- a/conductor/conductor/data/plugins/inventory_provider/utils/csar.py +++ b/conductor/conductor/data/plugins/inventory_provider/utils/csar.py @@ -1,5 +1,3 @@ - - # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at @@ -22,7 +20,6 @@ from toscaparser.utils.urlutils import UrlUtils from toscaparser.utils import yamlparser import zipfile - try: # Python 2.x from BytesIO import BytesIO except ImportError: # Python 3.x @@ -82,6 +79,12 @@ class SDCCSAR(CSAR): print("nst properties", nst_properies_res) return nst_properies_res + if is_validated: + main_tpl = self._read_template_yaml(self.main_template_file_name) + nsst_properies_res = self.get_nsst_properties(main_tpl) + print("nsst properties", nsst_properies_res) + return nsst_properies_res + def get_nst_properties(self, main_tpl): importsarr = main_tpl.get('imports') for imports in importsarr: @@ -96,3 +99,18 @@ class SDCCSAR(CSAR): nodedata = node_types[key] nst_properties = nodedata.get("properties") return nst_properties + + def get_nsst_properties(self, main_tpl): + importsarr = main_tpl.get('imports') + for imports in importsarr: + for key in imports: + if "service-{}-interface".format(self.model_name) in key: + val = imports[key] + filename = val.get("file") + datanew = self._read_template_yaml("Definitions/" + filename) + node_types = datanew.get("node_types") + for key in list(node_types): + if "org.openecomp" in key: + nodedata = node_types[key] + nsst_properties = nodedata.get("properties") + return nsst_properties diff --git a/conductor/conductor/data/service.py b/conductor/conductor/data/service.py index 69f6945..3f0ec13 100644 --- a/conductor/conductor/data/service.py +++ b/conductor/conductor/data/service.py @@ -68,6 +68,8 @@ DATA_OPTS = [ default=1.0), cfg.FloatOpt('nst_candidate_cost', default=1.0), + cfg.FloatOpt('nsst_candidate_cost', + default=1.0), ] CONF.register_opts(DATA_OPTS, group='data') diff --git a/conductor/conductor/solver/service.py b/conductor/conductor/solver/service.py index f0bb14b..a6fa2a0 100644 --- a/conductor/conductor/solver/service.py +++ b/conductor/conductor/solver/service.py @@ -486,7 +486,7 @@ class SolverService(cotyledon.Service): 'aic_version': resource.get("cloud_region_version")}, } - if rec["candidate"]["inventory_type"] in ["nssi", "nsi", "slice_profiles", "nst"]: + if rec["candidate"]["inventory_type"] in ["nssi", "nsi", "slice_profiles", "nst", "nsst"]: rec["candidate"] = resource if resource.get('vim-id'): -- cgit 1.2.3-korg