From a79d2cdd881bbafaf672b20ec540ee1c34ddfb3a Mon Sep 17 00:00:00 2001 From: Ankitkumar Patel Date: Tue, 27 Mar 2018 17:19:26 -0400 Subject: SO response build module updated SO response build module is updated based on the HAS API. Issue-ID: OPTFRA-208 Change-Id: I57ed198967d2dc9a58f1221eb57fda56fcb5fd2d Signed-off-by: Ankitkumar Patel --- .../optimizers/placementopt/conductor/conductor.py | 28 ++++++---- test/placement-tests/conductor_response.json | 64 ++++++++++++++++++++++ test/test_so_response_gen.py | 39 +++++++++++++ 3 files changed, 120 insertions(+), 11 deletions(-) create mode 100644 test/placement-tests/conductor_response.json create mode 100644 test/test_so_response_gen.py diff --git a/osdf/optimizers/placementopt/conductor/conductor.py b/osdf/optimizers/placementopt/conductor/conductor.py index dc67517..8f286ec 100644 --- a/osdf/optimizers/placementopt/conductor/conductor.py +++ b/osdf/optimizers/placementopt/conductor/conductor.py @@ -126,27 +126,32 @@ def conductor_response_processor(conductor_response, raw_response, req_id): """ composite_solutions = [] name_map = {"physical-location-id": "cloudClli", "host_id": "vnfHostName", - "cloud_version": "cloudVersion", "cloud_owner": "cloudOwner"} + "cloud_version": "cloudVersion", "cloud_owner": "cloudOwner", + "cloud": "cloudRegionId", "service": "serviceInstanceId", "is_rehome": "isRehome", + "location_id": "locationId", "location_type": "locationType"} for reco in conductor_response['plans'][0]['recommendations']: for resource in reco.keys(): c = reco[resource]['candidate'] solution = { 'resourceModuleName': resource, - 'serviceResourceId': reco[resource]['service_resource_id'], - 'inventoryType': c['inventory_type'], - 'serviceInstanceId': c['candidate_id'] if c['inventory_type'] == "service" else "", - 'cloudRegionId': c['location_id'], + 'serviceResourceId': reco[resource].get('service_resource_id', ""), + 'solution': {"identifier": c['inventory_type'], + 'identifiers': [c['candidate_id']], + 'cloudOwner': c.get('cloud_owner', "")}, 'assignmentInfo': [] } + for key, value in c.items(): + if key in ["location_id", "location_type", "is_rehome", "host_id"]: + try: + solution['assignmentInfo'].append({"key": name_map.get(key, key), "value": value}) + except KeyError: + debug_log.debug("The key[{}] is not mapped and will not be returned in assignment info".format(key)) for key, value in reco[resource]['attributes'].items(): try: - solution['assignmentInfo'].append({"variableName": name_map[key], "variableValue": value}) + solution['assignmentInfo'].append({"key": name_map.get(key, key), "value": value}) except KeyError: debug_log.debug("The key[{}] is not mapped and will not be returned in assignment info".format(key)) - - if c.get('host_id'): - solution['assignmentInfo'].append({'variableName': name_map['host_id'], 'variableValue': c['host_id']}) composite_solutions.append(solution) request_state = conductor_response['plans'][0]['status'] @@ -155,14 +160,15 @@ def conductor_response_processor(conductor_response, raw_response, req_id): solution_info = {} if composite_solutions: - solution_info['placementInfo'] = composite_solutions + solution_info.setdefault('placementSolutions', []) + solution_info['placementSolutions'].append(composite_solutions) resp = { "transactionId": transaction_id, "requestId": req_id, "requestState": request_state, "statusMessage": status_message, - "solutionInfo": solution_info + "solutions": solution_info } return resp diff --git a/test/placement-tests/conductor_response.json b/test/placement-tests/conductor_response.json new file mode 100644 index 0000000..e7037c2 --- /dev/null +++ b/test/placement-tests/conductor_response.json @@ -0,0 +1,64 @@ +{ + "plans": [ + { + "status": "done", + "id": "plan_id", + "name": "Plan Name 1", + "links": [ + [ + { + "href": "http://conductor:8091/v1/plans/plan_id", + "rel": "self" + } + ] + ], + "recommendations": [ + { + "vG": { + "inventory_provider": "aai", + "candidate": { + "candidate_id": "DLLSTX1A", + "cloud_owner": "CloudOwner1", + "inventory_type": "cloud", + "location_id": "DLLSTX1A", + "location_type": "openstack-cloud" + }, + "attributes": { + "flavors": { + "flavor_label_1": "vim_flavor_X", + "flavor_label_2": "vim_flavor_Y" + }, + "cloud_owner": "CloudOwner1", + "physical-location-id": "DLLSTX1A", + "cloud_version": "3.0", + "vim-id": "CloudOwner1_DLLSTX1A" + } + } + }, + { + "vGMuxInfra": { + "attributes": { + "host_id": "vgmux_host_name", + "cloud_owner": "CloudOwner1", + "physical-location-id": "DLLSTX1A", + "service_instance_id": "21d5f3e8-e714-4383-8f99-cc480144505a", + "cloud_version": "3.0", + "vim-id": "CloudOwner1_DLLSTX1A" + }, + "inventory_provider": "aai", + "service_resource_id": "12345", + "candidate": { + "is_rehome": "false", + "location_id": "DLLSTX1A", + "inventory_type": "service", + "candidate_id": "21d5f3e8-e714-4383-8f99-cc480144505a", + "host_id": "vgmux_host_name", + "cloud_owner": "CloudOwner1", + "location_type": "openstack-cloud" + } + } + } + ] + } + ] +} \ No newline at end of file diff --git a/test/test_so_response_gen.py b/test/test_so_response_gen.py new file mode 100644 index 0000000..ab73ef6 --- /dev/null +++ b/test/test_so_response_gen.py @@ -0,0 +1,39 @@ +# ------------------------------------------------------------------------- +# Copyright (c) 2017-2018 AT&T Intellectual Property +# +# 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. +# +# ------------------------------------------------------------------------- +# +import unittest +import json +import yaml +from osdf.utils.interfaces import json_from_file +from osdf.optimizers.placementopt.conductor.conductor import conductor_response_processor +from osdf.utils.interfaces import RestClient + + +class TestSoResponseGen(unittest.TestCase): + def setUp(self): + main_dir = "" + conductor_response_file = main_dir + "test/placement-tests/conductor_response.json" + self.conductor_res = json_from_file(conductor_response_file) + self.rc = RestClient() + + def test_so_response_gen(self): + res = conductor_response_processor(self.conductor_res, self.rc, "test") + self.assertEqual(len(res['solutions']['placementSolutions'][0]), 2) + + +if __name__ == "__main__": + unittest.main() \ No newline at end of file -- cgit 1.2.3-korg