From a9b3dfd5cbd2b93bf738874e5b4258744544172f Mon Sep 17 00:00:00 2001 From: krishnaa96 Date: Tue, 16 Feb 2021 15:39:08 +0530 Subject: [PATCH] Update AAI plugin to fetch service profile From the latest modeling update, service profile will be attached to NSI as an allotted resource Issue-ID: OPTFRA-907 Signed-off-by: krishnaa96 Change-Id: I1816b271e978017d6ff215961905fc2202e53771 --- .../data/plugins/inventory_provider/aai.py | 19 +++- .../plugins/inventory_provider/utils/aai_utils.py | 5 + .../plugins/inventory_provider/nsi_response.json | 105 ++++++++++----------- .../inventory_provider/nsi_service_profile.json | 74 +++++++++++++++ .../plugins/inventory_provider/nssi_response.json | 102 ++++++++++---------- .../inventory_provider/nssi_slice_profile.json | 74 +++++++++++++++ .../data/plugins/inventory_provider/test_aai.py | 36 +++++++ 7 files changed, 309 insertions(+), 106 deletions(-) create mode 100644 conductor/conductor/tests/unit/data/plugins/inventory_provider/nsi_service_profile.json create mode 100644 conductor/conductor/tests/unit/data/plugins/inventory_provider/nssi_slice_profile.json diff --git a/conductor/conductor/data/plugins/inventory_provider/aai.py b/conductor/conductor/data/plugins/inventory_provider/aai.py index 6ec15da..fd5ca3f 100644 --- a/conductor/conductor/data/plugins/inventory_provider/aai.py +++ b/conductor/conductor/data/plugins/inventory_provider/aai.py @@ -1899,11 +1899,12 @@ class AAI(base.InventoryProviderBase): if not filtering_attributes or \ self.match_inventory_attributes(filtering_attributes, inventory_attributes, nxi_instance.get('service-instance-id')): + profile_instances = self.get_profile_instances(nxi_instance) if type == 'nssi': - profiles = nxi_instance.get('slice-profiles').get('slice-profile') + profiles = aai_utils.get_profiles(profile_instances, "slice-profile") cost = self.conf.data.nssi_candidate_cost elif type == 'nsi': - profiles = nxi_instance.get('service-profiles').get('service-profile') + profiles = aai_utils.get_profiles(profile_instances, "service-profile") cost = self.conf.data.nsi_candidate_cost for profile in profiles: profile_id = profile.get('profile-id') @@ -1915,6 +1916,20 @@ class AAI(base.InventoryProviderBase): candidates.append(candidate) return candidates + def get_profile_instances(self, nxi_instance): + related_nodes = self._get_aai_rel_link_data(nxi_instance, "allotted-resource", + "service-instance.service-instance-id") + profile_instances = [] + for node in related_nodes: + profile_instance_id = node["d_value"] + raw_path = f'nodes/service-instances/service-instance/{profile_instance_id}?depth=2' + path = self._aai_versioned_path(raw_path) + aai_response = self._request('get', path, data=None) + if aai_response.status_code == 200 and aai_response.json(): + profile_instances.append(aai_response.json()) + + return profile_instances + def get_nst_response(self, filtering_attributes): raw_path = 'service-design-and-creation/models' + aai_utils.add_query_params_and_depth(filtering_attributes, "2") 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 4c76645..4c6accc 100644 --- a/conductor/conductor/data/plugins/inventory_provider/utils/aai_utils.py +++ b/conductor/conductor/data/plugins/inventory_provider/utils/aai_utils.py @@ -95,3 +95,8 @@ def get_model_ver_info(model_version): if "model-elements" in key: del model_version["model-elements"] return model_version + + +def get_profiles(profile_instances, profile_type): + profile_type_plural = profile_type + 's' + return [x[profile_type_plural][profile_type][0] for x in profile_instances] diff --git a/conductor/conductor/tests/unit/data/plugins/inventory_provider/nsi_response.json b/conductor/conductor/tests/unit/data/plugins/inventory_provider/nsi_response.json index f24409e..1a869ec 100644 --- a/conductor/conductor/tests/unit/data/plugins/inventory_provider/nsi_response.json +++ b/conductor/conductor/tests/unit/data/plugins/inventory_provider/nsi_response.json @@ -11,56 +11,55 @@ "resource-version": "1581418601616", "orchestration-status": "active", "relationship-list": { - "relationship": [ - { - "related-to": "service-instance", - "relationship-label": "org.onap.relationships.inventory.ComposedOf", - "related-link": "/aai/v16/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/1a636c4d-5e76-427e-bfd6-241a947224b0", - "relationship-data": [ - { - "relationship-key": "customer.global-customer-id", - "relationship-value": "5GCustomer" - }, - { - "relationship-key": "service-subscription.service-type", - "relationship-value": "5G" - }, - { - "relationship-key": "service-instance.service-instance-id", - "relationship-value": "1a636c4d-5e76-427e-bfd6-241a947224b0" - } - ], - "related-to-property": [ - { - "property-key": "service-instance.service-instance-name", - "property-value": "nssi_test_0211" - } - ] - } - ] - }, - "service-profiles": { - "service-profile": [ - { - "profile-id": "89ad9f49-4201-4e3a-aac1-b0f27902c299", - "latency": 20, - "max-number-of-UEs": 10, - "coverage-area-TA-list": "[{\"province\":\"??\",\"city\":\"???\",\"county\":\"???\",\"street\":\"?????\"}]", - "ue-mobility-level": "stationary", - "resource-sharing-level": "0", - "exp-data-rate-UL": 100, - "exp-data-rate-DL": 100, - "activity-factor": 0, - "e2e-latency": 20, - "jitter": 1, - "survival-time": 0, - "exp-data-rate": 100, - "payload-size": 0, - "traffic-density": 0, - "conn-density": 100, - "resource-version": "1581418602494" - } - ] - } -} - ]} + "relationship": [{ + "related-to": "network-route", + "relationship-label": "org.onap.relationships.inventory.ComposedOf", + "related-link": "/aai/v21/network/network-routes/network-route/c0c55aa0-1a03-4851-8b1d-7a01bc5a1e76", + "relationship-data": [{ + "relationship-key": "network-route.route-id", + "relationship-value": "c0c55aa0-1a03-4851-8b1d-7a01bc5a1e76" + }] + }, { + "related-to": "service-instance", + "relationship-label": "org.onap.relationships.inventory.ComposedOf", + "related-link": "/aai/v21/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/aa5f4179-e42a-47d4-8f83-9fa1766ad51a", + "relationship-data": [{ + "relationship-key": "customer.global-customer-id", + "relationship-value": "5GCustomer" + }, { + "relationship-key": "service-subscription.service-type", + "relationship-value": "5G" + }, { + "relationship-key": "service-instance.service-instance-id", + "relationship-value": "aa5f4179-e42a-47d4-8f83-9fa1766ad51a" + }], + "related-to-property": [{ + "property-key": "service-instance.service-instance-name", + "property-value": "ns_smf_nsst_0302_b49301c0-0964-420c-99ee-acc47a93da70" + }] + }, { + "related-to": "allotted-resource", + "relationship-label": "org.onap.relationships.inventory.Uses", + "related-link": "/aai/v21/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/1c7046f2-a5a3-4d7f-9da8-388ee641a795/allotted-resources/allotted-resource/462e46c2-cd84-45e4-a6c1-77f4ef88328d", + "relationship-data": [{ + "relationship-key": "customer.global-customer-id", + "relationship-value": "5GCustomer" + }, { + "relationship-key": "service-subscription.service-type", + "relationship-value": "5G" + }, { + "relationship-key": "service-instance.service-instance-id", + "relationship-value": "1c7046f2-a5a3-4d7f-9da8-388ee641a795" + }, { + "relationship-key": "allotted-resource.id", + "relationship-value": "462e46c2-cd84-45e4-a6c1-77f4ef88328d" + }], + "related-to-property": [{ + "property-key": "allotted-resource.description" + }, { + "property-key": "allotted-resource.allotted-resource-name", + "property-value": "serviceProfile_ar_1812" + }] + }] + } +}]} diff --git a/conductor/conductor/tests/unit/data/plugins/inventory_provider/nsi_service_profile.json b/conductor/conductor/tests/unit/data/plugins/inventory_provider/nsi_service_profile.json new file mode 100644 index 0000000..53465dd --- /dev/null +++ b/conductor/conductor/tests/unit/data/plugins/inventory_provider/nsi_service_profile.json @@ -0,0 +1,74 @@ +{ + "allotted-resources": { + "allotted-resource": [ + { + "allotted-resource-name": "serviceProfile_ar_1812", + "id": "462e46c2-cd84-45e4-a6c1-77f4ef88328d", + "model-invariant-id": "3a3ec7f8-425f-4801-bed5-4df697fd9c67", + "model-version-id": "2c8e2fda-8103-4467-b820-6952bb95ed5c", + "relationship-list": { + "relationship": [ + { + "related-link": "/aai/v21/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/b49301c0-0964-420c-99ee-acc47a93da70", + "related-to": "service-instance", + "related-to-property": [ + { + "property-key": "service-instance.service-instance-name", + "property-value": "nssi_embb_nsst_1812" + } + ], + "relationship-data": [ + { + "relationship-key": "customer.global-customer-id", + "relationship-value": "5GCustomer" + }, + { + "relationship-key": "service-subscription.service-type", + "relationship-value": "5G" + }, + { + "relationship-key": "service-instance.service-instance-id", + "relationship-value": "b49301c0-0964-420c-99ee-acc47a93da70" + } + ], + "relationship-label": "org.onap.relationships.inventory.Uses" + } + ] + }, + "resource-version": "1612348253454", + "type": "Allotted Resource" + } + ] + }, + "environment-context": "01-5B179BD4", + "model-invariant-id": "96db48e6-7d62-4007-a0dd-b7e5322032a0", + "model-version-id": "7fca6ef0-5eea-4d4b-9312-75770de5a3a5", + "orchestration-status": "activated", + "resource-version": "1608296844317", + "service-instance-id": "1c7046f2-a5a3-4d7f-9da8-388ee641a795", + "service-instance-name": "embb_serviceProfile_1812", + "service-role": "e2eserviceprofile-service", + "service-profiles": { + "service-profile": [ + { + "profile-id": "89ad9f49-4201-4e3a-aac1-b0f27902c299", + "latency": 20, + "max-number-of-UEs": 10, + "coverage-area-TA-list": "[{\"province\":\"??\",\"city\":\"???\",\"county\":\"???\",\"street\":\"?????\"}]", + "ue-mobility-level": "stationary", + "resource-sharing-level": "0", + "exp-data-rate-UL": 100, + "exp-data-rate-DL": 100, + "activity-factor": 0, + "e2e-latency": 20, + "jitter": 1, + "survival-time": 0, + "exp-data-rate": 100, + "payload-size": 0, + "traffic-density": 0, + "conn-density": 100, + "resource-version": "1581418602494" + } + ] + } +} diff --git a/conductor/conductor/tests/unit/data/plugins/inventory_provider/nssi_response.json b/conductor/conductor/tests/unit/data/plugins/inventory_provider/nssi_response.json index 8165408..5b914f6 100644 --- a/conductor/conductor/tests/unit/data/plugins/inventory_provider/nssi_response.json +++ b/conductor/conductor/tests/unit/data/plugins/inventory_provider/nssi_response.json @@ -10,55 +10,55 @@ "resource-version": "1581418601616", "orchestration-status": "active", "relationship-list": { - "relationship": [ - { - "related-to": "service-instance", - "relationship-label": "org.onap.relationships.inventory.ComposedOf", - "related-link": "/aai/v16/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/4115d3c8-dd59-45d6-b09d-e756dee9b518", - "relationship-data": [ - { - "relationship-key": "customer.global-customer-id", - "relationship-value": "5GCustomer" - }, - { - "relationship-key": "service-subscription.service-type", - "relationship-value": "5G" - }, - { - "relationship-key": "service-instance.service-instance-id", - "relationship-value": "4115d3c8-dd59-45d6-b09d-e756dee9b518" - } - ], - "related-to-property": [ - { - "property-key": "service-instance.service-instance-name", - "property-value": "nsi_test_0211" - } - ] - } - ] - }, - "slice-profiles": { - "slice-profile": [ - { - "profile-id": "cdad9f49-4201-4e3a-aac1-b0f27902c299", - "latency": 20, - "max-number-of-UEs": 0, - "coverage-area-TA-list": "[{\"province\":\"??\",\"city\":\"???\",\"county\":\"???\",\"street\":\"?????\"}]", - "ue-mobility-level": "stationary", - "resource-sharing-level": "0", - "exp-data-rate-UL": 100, - "exp-data-rate-DL": 100, - "activity-factor": 0, - "e2e-latency": 0, - "jitter": 0, - "survival-time": 0, - "exp-data-rate": 0, - "payload-size": 0, - "traffic-density": 0, - "conn-density": 0, - "resource-version": "1581418602494" - } - ] - } + "relationship": [{ + "related-to": "network-route", + "relationship-label": "org.onap.relationships.inventory.ComposedOf", + "related-link": "/aai/v21/network/network-routes/network-route/c0c55aa0-1a03-4851-8b1d-7a01bc5a1e76", + "relationship-data": [{ + "relationship-key": "network-route.route-id", + "relationship-value": "c0c55aa0-1a03-4851-8b1d-7a01bc5a1e76" + }] + }, { + "related-to": "service-instance", + "relationship-label": "org.onap.relationships.inventory.ComposedOf", + "related-link": "/aai/v21/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/aa5f4179-e42a-47d4-8f83-9fa1766ad51a", + "relationship-data": [{ + "relationship-key": "customer.global-customer-id", + "relationship-value": "5GCustomer" + }, { + "relationship-key": "service-subscription.service-type", + "relationship-value": "5G" + }, { + "relationship-key": "service-instance.service-instance-id", + "relationship-value": "aa5f4179-e42a-47d4-8f83-9fa1766ad51a" + }], + "related-to-property": [{ + "property-key": "service-instance.service-instance-name", + "property-value": "ns_smf_nsst_0302_b49301c0-0964-420c-99ee-acc47a93da70" + }] + }, { + "related-to": "allotted-resource", + "relationship-label": "org.onap.relationships.inventory.Uses", + "related-link": "/aai/v21/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/1c7046f2-a5a3-4d7f-9da8-388ee641a795/allotted-resources/allotted-resource/462e46c2-cd84-45e4-a6c1-77f4ef88328d", + "relationship-data": [{ + "relationship-key": "customer.global-customer-id", + "relationship-value": "5GCustomer" + }, { + "relationship-key": "service-subscription.service-type", + "relationship-value": "5G" + }, { + "relationship-key": "service-instance.service-instance-id", + "relationship-value": "1c7046f2-a5a3-4d7f-9da8-388ee641a795" + }, { + "relationship-key": "allotted-resource.id", + "relationship-value": "462e46c2-cd84-45e4-a6c1-77f4ef88328d" + }], + "related-to-property": [{ + "property-key": "allotted-resource.description" + }, { + "property-key": "allotted-resource.allotted-resource-name", + "property-value": "sliceProfile_ar_1812" + }] + }] + } }]} diff --git a/conductor/conductor/tests/unit/data/plugins/inventory_provider/nssi_slice_profile.json b/conductor/conductor/tests/unit/data/plugins/inventory_provider/nssi_slice_profile.json new file mode 100644 index 0000000..fdba84f --- /dev/null +++ b/conductor/conductor/tests/unit/data/plugins/inventory_provider/nssi_slice_profile.json @@ -0,0 +1,74 @@ +{ + "allotted-resources": { + "allotted-resource": [ + { + "allotted-resource-name": "sliceProfile_ar_1812", + "id": "462e46c2-cd84-45e4-a6c1-77f4ef88328d", + "model-invariant-id": "3a3ec7f8-425f-4801-bed5-4df697fd9c67", + "model-version-id": "2c8e2fda-8103-4467-b820-6952bb95ed5c", + "relationship-list": { + "relationship": [ + { + "related-link": "/aai/v21/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/b49301c0-0964-420c-99ee-acc47a93da70", + "related-to": "service-instance", + "related-to-property": [ + { + "property-key": "service-instance.service-instance-name", + "property-value": "nssi_embb_nsst_1812" + } + ], + "relationship-data": [ + { + "relationship-key": "customer.global-customer-id", + "relationship-value": "5GCustomer" + }, + { + "relationship-key": "service-subscription.service-type", + "relationship-value": "5G" + }, + { + "relationship-key": "service-instance.service-instance-id", + "relationship-value": "b49301c0-0964-420c-99ee-acc47a93da70" + } + ], + "relationship-label": "org.onap.relationships.inventory.Uses" + } + ] + }, + "resource-version": "1612348253454", + "type": "Allotted Resource" + } + ] + }, + "environment-context": "01-5B179BD4", + "model-invariant-id": "96db48e6-7d62-4007-a0dd-b7e5322032a0", + "model-version-id": "7fca6ef0-5eea-4d4b-9312-75770de5a3a5", + "orchestration-status": "activated", + "resource-version": "1608296844317", + "service-instance-id": "1c7046f2-a5a3-4d7f-9da8-388ee641a795", + "service-instance-name": "embb_sliceProfile_1812", + "service-role": "e2esliceprofile-service", + "slice-profiles": { + "slice-profile": [ + { + "profile-id": "cdad9f49-4201-4e3a-aac1-b0f27902c299", + "latency": 20, + "max-number-of-UEs": 0, + "coverage-area-TA-list": "[{\"province\":\"??\",\"city\":\"???\",\"county\":\"???\",\"street\":\"?????\"}]", + "ue-mobility-level": "stationary", + "resource-sharing-level": "0", + "exp-data-rate-UL": 100, + "exp-data-rate-DL": 100, + "activity-factor": 0, + "e2e-latency": 0, + "jitter": 0, + "survival-time": 0, + "exp-data-rate": 0, + "payload-size": 0, + "traffic-density": 0, + "conn-density": 0, + "resource-version": "1581418602494" + } + ] + } +} diff --git a/conductor/conductor/tests/unit/data/plugins/inventory_provider/test_aai.py b/conductor/conductor/tests/unit/data/plugins/inventory_provider/test_aai.py index 54789f2..7261cee 100644 --- a/conductor/conductor/tests/unit/data/plugins/inventory_provider/test_aai.py +++ b/conductor/conductor/tests/unit/data/plugins/inventory_provider/test_aai.py @@ -731,9 +731,14 @@ tenant/3c6c471ada7747fe8ff7f28e100b61e8/vservers/vserver/00bddefc-126e-4e4f-a18d def test_filter_nssi_candidates(self): nssi_response_file = './conductor/tests/unit/data/plugins/inventory_provider/nssi_response.json' nssi_response = json.loads(open(nssi_response_file).read()) + slice_profile_file = './conductor/tests/unit/data/plugins/inventory_provider/nssi_slice_profile.json' + slice_profile = json.loads(open(slice_profile_file).read()) nssi_candidates_file = './conductor/tests/unit/data/plugins/inventory_provider/nssi_candidate.json' nssi_candidates = json.loads(open(nssi_candidates_file).read()) + self.mock_get_profiles = mock.patch.object(AAI, 'get_profile_instances', return_value=[slice_profile]) + self.mock_get_profiles.start() + service_role = 'nssi' second_level_filter = dict() second_level_filter['service-role'] = service_role @@ -774,6 +779,8 @@ tenant/3c6c471ada7747fe8ff7f28e100b61e8/vservers/vserver/00bddefc-126e-4e4f-a18d nssi_response_file = './conductor/tests/unit/data/plugins/inventory_provider/nssi_response.json' nssi_response = json.loads(open(nssi_response_file).read()) + slice_profile_file = './conductor/tests/unit/data/plugins/inventory_provider/nssi_slice_profile.json' + slice_profile = json.loads(open(slice_profile_file).read()) nssi_candidates_file = './conductor/tests/unit/data/plugins/inventory_provider/nssi_candidate.json' nssi_candidates = json.loads(open(nssi_candidates_file).read()) result = dict() @@ -783,6 +790,9 @@ tenant/3c6c471ada7747fe8ff7f28e100b61e8/vservers/vserver/00bddefc-126e-4e4f-a18d return_value=nssi_response) self.mock_get_nxi_candidates.start() + self.mock_get_profiles = mock.patch.object(AAI, 'get_profile_instances', return_value=[slice_profile]) + self.mock_get_profiles.start() + self.assertEqual(result, self.aai_ep.resolve_demands(demands_list, plan_info=plan_info, triage_translator_data=triage_translator_data)) @@ -791,6 +801,11 @@ tenant/3c6c471ada7747fe8ff7f28e100b61e8/vservers/vserver/00bddefc-126e-4e4f-a18d nsi_response = json.loads(open(nsi_response_file).read()) nsi_candidates_file = './conductor/tests/unit/data/plugins/inventory_provider/nsi_candidate.json' nsi_candidates = json.loads(open(nsi_candidates_file).read()) + service_profile_file = './conductor/tests/unit/data/plugins/inventory_provider/nsi_service_profile.json' + service_profile = json.loads(open(service_profile_file).read()) + + self.mock_get_profiles = mock.patch.object(AAI, 'get_profile_instances', return_value=[service_profile]) + self.mock_get_profiles.start() service_role = 'nsi' second_level_filter = dict() @@ -826,6 +841,12 @@ tenant/3c6c471ada7747fe8ff7f28e100b61e8/vservers/vserver/00bddefc-126e-4e4f-a18d result = dict() result['embb_nst'] = nsi_candidates + service_profile_file = './conductor/tests/unit/data/plugins/inventory_provider/nsi_service_profile.json' + service_profile = json.loads(open(service_profile_file).read()) + + self.mock_get_profiles = mock.patch.object(AAI, 'get_profile_instances', return_value=[service_profile]) + self.mock_get_profiles.start() + self.mock_get_nxi_candidates = mock.patch.object(AAI, 'get_nxi_candidates', return_value=nsi_response) self.mock_get_nxi_candidates.start() @@ -890,3 +911,18 @@ tenant/3c6c471ada7747fe8ff7f28e100b61e8/vservers/vserver/00bddefc-126e-4e4f-a18d self.mock_get_request.start() filtering_attr={"model-role":"NST"} self.assertEquals(nst_response, self.aai_ep.get_nst_response(filtering_attr)) + + def test_get_profile_instances(self): + nsi_response_file = './conductor/tests/unit/data/plugins/inventory_provider/nsi_response.json' + nsi_response = json.loads(open(nsi_response_file).read()) + service_profile_file = './conductor/tests/unit/data/plugins/inventory_provider/nsi_service_profile.json' + service_profile = json.loads(open(service_profile_file).read()) + + response = mock.MagicMock() + response.status_code = 200 + response.ok = True + response.json.return_value = service_profile + self.mock_get_profiles = mock.patch.object(AAI, '_request', return_value=response) + self.mock_get_profiles.start() + + self.assertEquals([service_profile], self.aai_ep.get_profile_instances(nsi_response["service-instance"][0])) -- 2.16.6