From 592bae2703b02af111f7a96e71f56f3888f76aed Mon Sep 17 00:00:00 2001 From: krishnaa96 Date: Thu, 23 Apr 2020 20:58:53 +0530 Subject: Add generator plugin for candidate generation Issue-ID: OPTFRA-744 Signed-off-by: krishnaa96 Change-Id: I047572609573ca8ab2fa91e087e9f37232eb0371 --- conductor/conductor/controller/translator.py | 2 +- .../data/plugins/inventory_provider/generator.py | 94 +++++++ .../inventory_provider/generated_candidates.json | 302 +++++++++++++++++++++ .../plugins/inventory_provider/test_generator.py | 65 +++++ 4 files changed, 462 insertions(+), 1 deletion(-) create mode 100644 conductor/conductor/data/plugins/inventory_provider/generator.py create mode 100644 conductor/conductor/tests/unit/data/plugins/inventory_provider/generated_candidates.json create mode 100644 conductor/conductor/tests/unit/data/plugins/inventory_provider/test_generator.py diff --git a/conductor/conductor/controller/translator.py b/conductor/conductor/controller/translator.py index 9fa5b6b..1c28889 100644 --- a/conductor/conductor/controller/translator.py +++ b/conductor/conductor/controller/translator.py @@ -43,7 +43,7 @@ CONF = cfg.CONF VERSIONS = ["2016-11-01", "2017-10-10", "2018-02-01"] LOCATION_KEYS = ['latitude', 'longitude', 'host_name', 'clli_code'] -INVENTORY_PROVIDERS = ['aai'] +INVENTORY_PROVIDERS = ['aai', 'generator'] INVENTORY_TYPES = ['cloud', 'service', 'transport', 'vfmodule', 'nssi'] DEFAULT_INVENTORY_PROVIDER = INVENTORY_PROVIDERS[0] CANDIDATE_KEYS = ['candidate_id', 'cost', 'inventory_type', 'location_id', diff --git a/conductor/conductor/data/plugins/inventory_provider/generator.py b/conductor/conductor/data/plugins/inventory_provider/generator.py new file mode 100644 index 0000000..c9cf67f --- /dev/null +++ b/conductor/conductor/data/plugins/inventory_provider/generator.py @@ -0,0 +1,94 @@ +# +# ------------------------------------------------------------------------- +# 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. +# +# ------------------------------------------------------------------------- +# + +import itertools +import uuid + +from oslo_log import log + +from conductor.data.plugins.inventory_provider import base + +LOG = log.getLogger(__name__) + + +class Generator(base.InventoryProviderBase): + + def __init__(self): + """Initialize variables""" + pass + + def name(self): + """Return human-readable name.""" + return "Generator" + + def resolve_demands(self, demands, plan_info, triage_translator_data): + """Resolve demands into candidate list""" + resolved_demands = dict() + for name, requirements in demands.items(): + resolved_demands[name] = list() + for requirement in requirements: + inventory_type = requirement.get('inventory_type').lower() + candidate_uniqueness = requirement.get('unique', 'true') + filtering_attributes = requirement.get('filtering_attributes') + + resolved_demands[name].append(self.generate_candidates(inventory_type, + filtering_attributes, + candidate_uniqueness)) + + return resolved_demands + + def generate_candidates(self, inventory_type, filtering_attributes, candidate_uniqueness): + candidate_list = list() + + if inventory_type == "nssi": + attribute_names, attribute_combinations = \ + self.generate_combinations(filtering_attributes) + for combination in attribute_combinations: + candidate = dict() + + for (name, value) in zip(attribute_names, combination): + candidate[name] = value + + candidate['candidate_id'] = str(uuid.uuid4()) + candidate['cost'] = 1.0 + candidate['inventory_type'] = inventory_type + candidate['inventory_provider'] = 'generator' + candidate['uniqueness'] = candidate_uniqueness + candidate['candidate_type'] = 'nssi' + + candidate_list.append(candidate) + else: + LOG.debug("No functionality implemented for \ + generating candidates for inventory_type {}".format(inventory_type)) + + return candidate_list + + def generate_combinations(self, attributes): + """Generates all combination of the given attribute values.""" + attr = dict() + for attribute, attr_params in attributes.items(): + values = attr_params.get('values') + if not values: + values = range(attr_params.get('min', 1), attr_params.get('max'), + attr_params.get('steps', 1)) + attr[attribute] = values + + attribute_names = list(attr.keys()) + attribute_combinations = list(itertools.product(*attr.values())) + return attribute_names, attribute_combinations diff --git a/conductor/conductor/tests/unit/data/plugins/inventory_provider/generated_candidates.json b/conductor/conductor/tests/unit/data/plugins/inventory_provider/generated_candidates.json new file mode 100644 index 0000000..14d89c4 --- /dev/null +++ b/conductor/conductor/tests/unit/data/plugins/inventory_provider/generated_candidates.json @@ -0,0 +1,302 @@ +[ + { + "candidate_id": "c5bff81d-e0de-45df-9a5c-72dd8696a901", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 5, + "reliability": 99.99, + "uniqueness": "true" + }, + { + "candidate_id": "8c92180c-26e3-47c7-8df3-fcf12c248606", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 5, + "reliability": 99.999, + "uniqueness": "true" + }, + { + "candidate_id": "d13ead23-e768-4bd1-886d-e0d8de014931", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 6, + "reliability": 99.99, + "uniqueness": "true" + }, + { + "candidate_id": "47c84e0a-7f7e-41f1-bdc2-38856de96a1c", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 6, + "reliability": 99.999, + "uniqueness": "true" + }, + { + "candidate_id": "cc3dd37f-2f0f-4733-9657-b864fcc327c0", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 7, + "reliability": 99.99, + "uniqueness": "true" + }, + { + "candidate_id": "3d95ebf5-ad71-4898-b011-80943d6d67f3", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 7, + "reliability": 99.999, + "uniqueness": "true" + }, + { + "candidate_id": "fae0f131-cc17-4c80-84d1-b4ec90ea216a", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 8, + "reliability": 99.99, + "uniqueness": "true" + }, + { + "candidate_id": "aa39b3ed-8fd7-4013-ae6a-4b7b32201664", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 8, + "reliability": 99.999, + "uniqueness": "true" + }, + { + "candidate_id": "7beb2493-feb1-478f-850a-81d49fcc6e09", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 9, + "reliability": 99.99, + "uniqueness": "true" + }, + { + "candidate_id": "3bff4bee-9ba3-41be-8ed2-001b25bc2d56", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 9, + "reliability": 99.999, + "uniqueness": "true" + }, + { + "candidate_id": "350baccf-072f-4371-a7be-5b19a6dfd31b", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 10, + "reliability": 99.99, + "uniqueness": "true" + }, + { + "candidate_id": "d43f8590-a2d5-4c33-ae6f-ce8817c11878", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 10, + "reliability": 99.999, + "uniqueness": "true" + }, + { + "candidate_id": "b37943fa-bfea-4149-8254-8fd80d22bd4e", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 11, + "reliability": 99.99, + "uniqueness": "true" + }, + { + "candidate_id": "b21ce156-8b0a-4af6-a0a3-f0093000e040", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 11, + "reliability": 99.999, + "uniqueness": "true" + }, + { + "candidate_id": "1e54453a-3d40-405a-821f-b57ea33f9bb0", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 12, + "reliability": 99.99, + "uniqueness": "true" + }, + { + "candidate_id": "f26946a3-db3d-48d5-8bbd-0620f459904b", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 12, + "reliability": 99.999, + "uniqueness": "true" + }, + { + "candidate_id": "583d6ddf-fbbc-4b47-9655-c205c30a625a", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 13, + "reliability": 99.99, + "uniqueness": "true" + }, + { + "candidate_id": "a4aedbb8-b9cb-4476-a6ef-6f51e16ab352", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 13, + "reliability": 99.999, + "uniqueness": "true" + }, + { + "candidate_id": "7a48a511-4303-43be-a758-b35b1de92106", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 14, + "reliability": 99.99, + "uniqueness": "true" + }, + { + "candidate_id": "3fcf9c64-d816-4cf6-b216-926b5a9023bd", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 14, + "reliability": 99.999, + "uniqueness": "true" + }, + { + "candidate_id": "17c46498-b622-4fc5-8254-2261318347fc", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 15, + "reliability": 99.99, + "uniqueness": "true" + }, + { + "candidate_id": "8005dd52-5d6c-4f7d-b992-7f5650e1a235", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 15, + "reliability": 99.999, + "uniqueness": "true" + }, + { + "candidate_id": "203802d4-44c8-4251-9977-401880992ac0", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 16, + "reliability": 99.99, + "uniqueness": "true" + }, + { + "candidate_id": "728343ef-e41e-405e-b626-f3dcffe02e65", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 16, + "reliability": 99.999, + "uniqueness": "true" + }, + { + "candidate_id": "77ac7fea-8452-4c83-9bdc-c1f4ce5c7314", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 17, + "reliability": 99.99, + "uniqueness": "true" + }, + { + "candidate_id": "971ef4bf-fa71-4e9c-9b1b-dbfa6b28bb39", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 17, + "reliability": 99.999, + "uniqueness": "true" + }, + { + "candidate_id": "9925d2b3-24a8-40e6-844d-f7d7b4cb5437", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 18, + "reliability": 99.99, + "uniqueness": "true" + }, + { + "candidate_id": "b862a417-6e59-4946-995e-b562420199f0", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 18, + "reliability": 99.999, + "uniqueness": "true" + }, + { + "candidate_id": "719b0a26-7a6e-4fab-9547-f4194620ed4a", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 19, + "reliability": 99.99, + "uniqueness": "true" + }, + { + "candidate_id": "0f00caf7-a985-4256-b160-5d98894dae1b", + "candidate_type": "nssi", + "cost": 1.0, + "inventory_provider": "generator", + "inventory_type": "nssi", + "latency": 19, + "reliability": 99.999, + "uniqueness": "true" + } +] diff --git a/conductor/conductor/tests/unit/data/plugins/inventory_provider/test_generator.py b/conductor/conductor/tests/unit/data/plugins/inventory_provider/test_generator.py new file mode 100644 index 0000000..c6249ce --- /dev/null +++ b/conductor/conductor/tests/unit/data/plugins/inventory_provider/test_generator.py @@ -0,0 +1,65 @@ +# +# ------------------------------------------------------------------------- +# 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. +# +# ------------------------------------------------------------------------- +# + +import unittest +import json +from mock import patch + +from conductor.data.plugins.inventory_provider.generator import Generator + + +class TestGenerator(unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + patch.stopall() + + def test_generate_candidate(self): + + candidates_file = './conductor/tests/unit/data/plugins/inventory_provider/generated_candidates.json' + expected_candidates = json.loads(open(candidates_file).read()) + + #uuids = [candidate['candidate_id'] for candidate in expected_candidates] + + #self.patcher = patch('uuid.uuid4', side_effect=uuids) + #self.patcher.start() + + generator = Generator() + + filtering_attributes = {'latency': {'min': 5, 'max': 20, 'steps': 1}, + 'reliability': {'values': [99.99, 99.999]}} + + generated_candidates = generator.generate_candidates('nssi', filtering_attributes, + candidate_uniqueness='true') + #with open('/home/krishna/actual_candidates.json', 'w') as f: + # f.write(json.dumps(generated_candidates)) + + for candidate in generated_candidates: + self.assertIsNotNone(candidate['candidate_id']) + del candidate['candidate_id'] + + for candidate in expected_candidates: + del candidate['candidate_id'] + + self.assertCountEqual(expected_candidates, generated_candidates) + + self.assertEqual([], generator.generate_candidates('cloud', filtering_attributes, + candidate_uniqueness='true')) -- cgit 1.2.3-korg