summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukasz Rajewski <lukasz.rajewski@orange.com>2019-11-13 22:21:55 +0100
committerLukasz Rajewski <lukasz.rajewski@orange.com>2019-11-19 10:25:10 +0100
commit75a0b893128d2fe9645f3131e0d41e7460422e68 (patch)
treef50d2cbc0756fbe7080e3ffb61dfc7f07656d8d3
parent79bef7f1ca027a1aad11ebdbf8975a216d817b97 (diff)
Add passthrough attributes
Added passthrough attributes in placement request. Current attributes HAS request section changed to filtering_attributes and new passthrough attributes added in HAS request - this one is read from vnf policy passthroughAttributes section. Issue-ID: OPTFRA-610 Signed-off-by: Lukasz Rajewski <lukasz.rajewski@orange.com> Change-Id: Ie2719fdd94bb0b42ef7cf2cbf47f5f182a4e7347
-rw-r--r--conductor/conductor/controller/translator.py12
-rw-r--r--conductor/conductor/data/plugins/inventory_provider/aai.py41
-rw-r--r--conductor/conductor/solver/service.py8
-rw-r--r--conductor/conductor/tests/unit/controller/test_translator.py6
-rw-r--r--conductor/conductor/tests/unit/data/plugins/inventory_provider/demand_list.json2
-rw-r--r--conductor/conductor/tests/unit/data/plugins/inventory_provider/service_demand_list.json2
-rw-r--r--conductor/conductor/tests/unit/data/plugins/inventory_provider/test_aai.py20
-rw-r--r--conductor/conductor/tests/unit/data/plugins/inventory_provider/vfmodule_candidates.json3
-rw-r--r--conductor/conductor/tests/unit/data/plugins/inventory_provider/vfmodule_demand_list.json5
9 files changed, 72 insertions, 27 deletions
diff --git a/conductor/conductor/controller/translator.py b/conductor/conductor/controller/translator.py
index 85f63af..45e0ee2 100644
--- a/conductor/conductor/controller/translator.py
+++ b/conductor/conductor/controller/translator.py
@@ -47,7 +47,7 @@ INVENTORY_TYPES = ['cloud', 'service', 'transport', 'vfmodule']
DEFAULT_INVENTORY_PROVIDER = INVENTORY_PROVIDERS[0]
CANDIDATE_KEYS = ['candidate_id', 'cost', 'inventory_type', 'location_id',
'location_type']
-DEMAND_KEYS = ['attributes', 'candidates', 'complex', 'conflict_identifier',
+DEMAND_KEYS = ['filtering_attributes', 'passthrough_attributes', 'candidates', 'complex', 'conflict_identifier',
'customer_id', 'default_cost', 'excluded_candidates',
'existing_placement', 'flavor', 'inventory_provider',
'inventory_type', 'port_key', 'region', 'required_candidates',
@@ -448,11 +448,11 @@ class Translator(object):
# For service and vfmodule inventories, customer_id and
# service_type MUST be specified
if inventory_type == 'service' or inventory_type == 'vfmodule':
- attributes = requirement.get('attributes')
+ filtering_attributes = requirement.get('filtering_attributes')
- if attributes:
- customer_id = attributes.get('customer-id')
- global_customer_id = attributes.get('global-customer-id')
+ if filtering_attributes:
+ customer_id = filtering_attributes.get('customer-id')
+ global_customer_id = filtering_attributes.get('global-customer-id')
if global_customer_id:
customer_id = global_customer_id
else:
@@ -465,7 +465,7 @@ class Translator(object):
"Customer ID not specified for "
"demand {}".format(name)
)
- if not attributes and not service_type:
+ if not filtering_attributes and not service_type:
raise TranslatorException(
"Service Type not specified for "
"demand {}".format(name)
diff --git a/conductor/conductor/data/plugins/inventory_provider/aai.py b/conductor/conductor/data/plugins/inventory_provider/aai.py
index b69655c..26b390a 100644
--- a/conductor/conductor/data/plugins/inventory_provider/aai.py
+++ b/conductor/conductor/data/plugins/inventory_provider/aai.py
@@ -1187,26 +1187,27 @@ class AAI(base.InventoryProviderBase):
inventory_type = requirement.get('inventory_type').lower()
service_subscription = requirement.get('service_subscription')
candidate_uniqueness = requirement.get('unique', 'true')
- attributes = requirement.get('attributes')
+ filtering_attributes = requirement.get('filtering_attributes')
+ passthrough_attributes = requirement.get('passthrough_attributes')
#TODO: may need to support multiple service_type and customer_id in the futrue
#TODO: make it consistent for dash and underscore
- if attributes:
+ if filtering_attributes:
# catch equipment-role and service-type from template
- equipment_role = attributes.get('equipment-role')
- service_type = attributes.get('service-type')
+ equipment_role = filtering_attributes.get('equipment-role')
+ service_type = filtering_attributes.get('service-type')
if equipment_role:
service_type = equipment_role
# catch global-customer-id and customer-id from template
- global_customer_id = attributes.get('global-customer-id')
- customer_id = attributes.get('customer-id')
+ global_customer_id = filtering_attributes.get('global-customer-id')
+ customer_id = filtering_attributes.get('customer-id')
if global_customer_id:
customer_id = global_customer_id
- model_invariant_id = attributes.get('model-invariant-id')
- model_version_id = attributes.get('model-version-id')
- service_role = attributes.get('service-role')
+ model_invariant_id = filtering_attributes.get('model-invariant-id')
+ model_version_id = filtering_attributes.get('model-version-id')
+ service_role = filtering_attributes.get('service-role')
# For earlier
else:
service_type = equipment_role = requirement.get('service_type')
@@ -1306,7 +1307,7 @@ class AAI(base.InventoryProviderBase):
cloud_region_attr['complex-name'] = region['complex_name']
cloud_region_attr['physical-location-id'] = region['physical_location_id']
- if attributes and (not self.match_inventory_attributes(attributes, cloud_region_attr, candidate['candidate_id'])):
+ if filtering_attributes and (not self.match_inventory_attributes(filtering_attributes, cloud_region_attr, candidate['candidate_id'])):
self.triage_translator.collectDroppedCandiate(candidate['candidate_id'], candidate['location_id'], name, triage_translator_data,
reason='attributes and match invetory attributes')
continue
@@ -1330,6 +1331,7 @@ class AAI(base.InventoryProviderBase):
if required_candidates and not self.match_candidate_by_list(candidate, required_candidates, False, name, triage_translator_data):
continue
+ self.add_passthrough_attributes(candidate, passthrough_attributes, name, triage_translator_data)
# add candidate to demand candidates
resolved_demands[name].append(candidate)
LOG.debug(">>>>>>> Candidate <<<<<<<")
@@ -1340,7 +1342,7 @@ class AAI(base.InventoryProviderBase):
# First level query to get the list of generic vnfs
vnf_by_model_invariant = list()
- if attributes and model_invariant_id:
+ if filtering_attributes and model_invariant_id:
raw_path = '/network/generic-vnfs/' \
'?model-invariant-id={}&depth=0'.format(model_invariant_id)
@@ -1477,7 +1479,7 @@ class AAI(base.InventoryProviderBase):
vnf['cloud-region-id'] = cloud_region_id
vnf['physical-location-id'] = candidate.get('physical_location_id')
- if attributes and not self.match_inventory_attributes(attributes, vnf, candidate['candidate_id']):
+ if filtering_attributes and not self.match_inventory_attributes(filtering_attributes, vnf, candidate['candidate_id']):
self.triage_translator.collectDroppedCandiate(candidate['candidate_id'], candidate['location_id'], name, triage_translator_data,
reason="attibute check error")
continue
@@ -1502,6 +1504,7 @@ class AAI(base.InventoryProviderBase):
triage_translator_data):
continue
else:
+ self.add_passthrough_attributes(candidate, passthrough_attributes, name, triage_translator_data)
resolved_demands[name].append(candidate)
LOG.debug(">>>>>>> Candidate <<<<<<<")
LOG.debug(json.dumps(candidate, indent=4))
@@ -1511,7 +1514,7 @@ class AAI(base.InventoryProviderBase):
# First level query to get the list of generic vnfs
vnf_by_model_invariant = list()
- if attributes and model_invariant_id:
+ if filtering_attributes and model_invariant_id:
raw_path = '/network/generic-vnfs/' \
'?model-invariant-id={}&depth=0'.format(model_invariant_id)
@@ -1715,7 +1718,7 @@ class AAI(base.InventoryProviderBase):
vnf_vf_module_inventory['physical-location-id'] = candidate.get('physical_location_id')
vnf_vf_module_inventory['service_instance_id'] = vs_service_instance_id
- if attributes and not self.match_inventory_attributes(attributes, vnf_vf_module_inventory,
+ if filtering_attributes and not self.match_inventory_attributes(filtering_attributes, vnf_vf_module_inventory,
candidate['candidate_id']):
self.triage_translator.collectDroppedCandiate(candidate['candidate_id'],
candidate['location_id'], name,
@@ -1744,6 +1747,7 @@ class AAI(base.InventoryProviderBase):
triage_translator_data):
continue
else:
+ self.add_passthrough_attributes(candidate, passthrough_attributes, name, triage_translator_data)
resolved_demands[name].append(candidate)
LOG.debug(">>>>>>> Candidate <<<<<<<")
LOG.debug(json.dumps(candidate, indent=4))
@@ -1870,6 +1874,7 @@ class AAI(base.InventoryProviderBase):
candidate['region'] = \
complex_info.get('region')
+ self.add_passthrough_attributes(candidate, passthrough_attributes, name, triage_translator_data)
# add candidate to demand candidates
resolved_demands[name].append(candidate)
@@ -1878,6 +1883,14 @@ class AAI(base.InventoryProviderBase):
" {}".format(inventory_type))
return resolved_demands
+ def add_passthrough_attributes(self, candidate, passthrough_attributes, demand_name, triage_translator_data):
+ if passthrough_attributes is None:
+ return
+ if len(passthrough_attributes.items()) > 0:
+ candidate['passthrough_attributes'] = dict()
+ for key, value in passthrough_attributes.items():
+ candidate['passthrough_attributes'][key] = value
+
def match_region(self, candidate, restricted_region_id, restricted_complex_id, demand_name, triage_translator_data):
if self.match_candidate_attribute(
candidate,
diff --git a/conductor/conductor/solver/service.py b/conductor/conductor/solver/service.py
index 978f735..fb7b2f0 100644
--- a/conductor/conductor/solver/service.py
+++ b/conductor/conductor/solver/service.py
@@ -556,7 +556,13 @@ class SolverService(cotyledon.Service):
if resource.get('conflict_id'):
rec["candidate"]["conflict_id"] = resource.get("conflict_id")
-
+ if resource.get('passthrough_attributes'):
+ for key, value in resource.get('passthrough_attributes').items():
+ if key in rec["attributes"]:
+ LOG.error('Passthrough attribute {} in demand {} already exist for candidate {}'.
+ format(key, demand_name, rec['candidate_id']))
+ else:
+ rec["attributes"][key] = value
# TODO(snarayanan): Add total value to recommendations?
# msg = "--- total value of decision = {}"
# LOG.debug(msg.format(_best_path.total_value))
diff --git a/conductor/conductor/tests/unit/controller/test_translator.py b/conductor/conductor/tests/unit/controller/test_translator.py
index 0d4048a..c30d937 100644
--- a/conductor/conductor/tests/unit/controller/test_translator.py
+++ b/conductor/conductor/tests/unit/controller/test_translator.py
@@ -180,7 +180,7 @@ class TestNoExceptionTranslator(unittest.TestCase):
"candidate_id": ["e765d576-8755-4145-8536-0bb6d9b1dc9a"],
"inventory_type": "vfmodule"
}],
- "attributes": {
+ "filtering_attributes": {
"prov-status": "ACTIVE",
"global-customer-id": "Demonstration",
"model-version-id": "763731df-84fd-494b-b824-01fc59a5ff2d",
@@ -209,7 +209,7 @@ class TestNoExceptionTranslator(unittest.TestCase):
"candidate_id": ["e765d576-8755-4145-8536-0bb6d9b1dc9a"],
"inventory_type": "vfmodule"
}],
- "attributes": {
+ "filtering_attributes": {
"prov-status": "ACTIVE",
"global-customer-id": "Demonstration",
"model-version-id": "763731df-84fd-494b-b824-01fc59a5ff2d",
@@ -236,7 +236,7 @@ class TestNoExceptionTranslator(unittest.TestCase):
"service_resource_id": "vFW-SINK-XX",
"vlan_key": "vlan_key",
"service_type": "vFW-SINK-XX",
- "attributes": {
+ "filtering_attributes": {
"cloud-region-id": {
"get_param": "chosen_region"
},
diff --git a/conductor/conductor/tests/unit/data/plugins/inventory_provider/demand_list.json b/conductor/conductor/tests/unit/data/plugins/inventory_provider/demand_list.json
index c817fbb..8a54a25 100644
--- a/conductor/conductor/tests/unit/data/plugins/inventory_provider/demand_list.json
+++ b/conductor/conductor/tests/unit/data/plugins/inventory_provider/demand_list.json
@@ -1,7 +1,7 @@
{
"demand_name": [
{
- "attributes": {
+ "filtering_attributes": {
"global-customer-id": "customer-123",
"equipment-role": "TEST",
"service-type": "TEST"
diff --git a/conductor/conductor/tests/unit/data/plugins/inventory_provider/service_demand_list.json b/conductor/conductor/tests/unit/data/plugins/inventory_provider/service_demand_list.json
index fb1059a..cffba57 100644
--- a/conductor/conductor/tests/unit/data/plugins/inventory_provider/service_demand_list.json
+++ b/conductor/conductor/tests/unit/data/plugins/inventory_provider/service_demand_list.json
@@ -5,7 +5,7 @@
"inventory_type": "service",
"port_key": "vlan_port",
"vlan_key": "vlan_key",
- "attributes": {
+ "filtering_attributes": {
"global-customer-id": "Demonstration",
"model-version-id": "e02a7e5c-9d27-4360-ab7c-73bb83b07e3b",
"model-invariant-id": "762472ef-5284-4daa-ab32-3e7bee2ec355"
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 d77b644..9d1245d 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
@@ -610,6 +610,26 @@ tenant/3c6c471ada7747fe8ff7f28e100b61e8/vservers/vserver/00bddefc-126e-4e4f-a18d
self.assertIsNone(self.aai_ep.resolve_service_instance_id_for_vnf(candidate, bad_vnf, customer_id, service_type,
demand_name, triage_translator_data))
+ def test_add_passthrough_parameters(self):
+ triage_translator_data = None
+
+ candidate = dict()
+ candidate['candidate_id'] = 'some_id'
+ candidate['location_id'] = 'some_location_id'
+ candidate['inventory_type'] = 'service'
+
+ parameters = dict()
+ parameters['param_one'] = "value"
+ parameters['param_two'] = "value"
+
+ candidate_info = copy.deepcopy(candidate)
+ candidate_info['passthrough_attributes'] = dict()
+ candidate_info['passthrough_attributes']['param_one'] = "value"
+ candidate_info['passthrough_attributes']['param_two'] = "value"
+
+ self.aai_ep.add_passthrough_attributes(candidate, parameters, 'demand', None)
+ self.assertDictEqual(candidate, candidate_info)
+
def test_match_candidate_by_list(self):
TraigeTranslator.collectDroppedCandiate = mock.MagicMock(return_value=None)
triage_translator_data = None
diff --git a/conductor/conductor/tests/unit/data/plugins/inventory_provider/vfmodule_candidates.json b/conductor/conductor/tests/unit/data/plugins/inventory_provider/vfmodule_candidates.json
index 7343f34..e7b398e 100644
--- a/conductor/conductor/tests/unit/data/plugins/inventory_provider/vfmodule_candidates.json
+++ b/conductor/conductor/tests/unit/data/plugins/inventory_provider/vfmodule_candidates.json
@@ -51,6 +51,9 @@
"cloud_owner": "CloudOwner",
"vnf-type": "5G_EVE_Demo/5G_EVE_PKG 0",
"nf-name": "vFW-PKG-MC",
+ "passthrough_attributes": {
+ "td-role": "anchor"
+ },
"inventory_type": "vfmodule",
"sriov_automation": "false",
"uniqueness": "false",
diff --git a/conductor/conductor/tests/unit/data/plugins/inventory_provider/vfmodule_demand_list.json b/conductor/conductor/tests/unit/data/plugins/inventory_provider/vfmodule_demand_list.json
index 8069e0f..c6d34aa 100644
--- a/conductor/conductor/tests/unit/data/plugins/inventory_provider/vfmodule_demand_list.json
+++ b/conductor/conductor/tests/unit/data/plugins/inventory_provider/vfmodule_demand_list.json
@@ -6,7 +6,7 @@
"port_key": "vlan_port",
"vlan_key": "vlan_key",
"unique": "false",
- "attributes": {
+ "filtering_attributes": {
"prov-status": "ACTIVE",
"global-customer-id": "Demonstration",
"model-version-id": "e02a7e5c-9d27-4360-ab7c-73bb83b07e3b",
@@ -15,6 +15,9 @@
"cloud-region-id": "RegionOne",
"service_instance_id": "3e8d118c-10ca-4b4b-b3db-089b5e9e6a1c"
},
+ "passthrough_attributes": {
+ "td-role": "anchor"
+ },
"service_type": "vPGN-XX",
"excluded_candidates": [{
"inventory_type": "vfmodule",