import copy
import json
import yaml
+import re
from osdf.utils.data_conversion import text_to_symbol
from osdf.utils.programming_utils import dot_notation
for policy in optimization_policy:
content = policy['content']
parameter_list = []
+ parameters = ["cloud_version", "hpa_score"]
for attr in content['objectiveParameter']['parameterAttributes']:
- parameter = attr['parameter'] if attr['parameter'] == "cloud_version" else attr['parameter']+"_between"
+ parameter = attr['parameter'] if attr['parameter'] in parameters else attr['parameter']+"_between"
vnfs = get_matching_vnfs(attr['resources'], vnf_list)
for vnf in vnfs:
- value = [vnf] if attr['parameter'] == "cloud_version" else [attr['customerLocationInfo'], vnf]
+ value = [vnf] if attr['parameter'] in parameters else [attr['customerLocationInfo'], vnf]
parameter_list.append({
attr['operator']: [attr['weight'], {parameter: value}]
})
:param match_type: "intersection" or "all" or "any" (any => send all_vnfs if there is any intersection)
:return: List of matching VNFs
"""
+ resources_lcase = [x.lower() for x in resources]
if match_type == "all": # don't bother with any comparisons
- return resources if set(resources) <= set(vnf_list) else None
- common_vnfs = set(vnf_list) & set(resources)
+ return resources if set(resources_lcase) <= set(vnf_list) else None
+ common_vnfs = set(vnf_list) & set(resources_lcase)
+ common_resources = [x for x in resources if x.lower() in common_vnfs]
if match_type == "intersection": # specifically requested intersection
- return list(common_vnfs)
+ return list(common_resources)
return resources if common_vnfs else None # "any" match => all resources to be returned
for k, v in policy_config_mapping['candidates'].items():
if k not in demand:
continue
- res[v] = [{'inventory_type': x['candidateType'], 'candidate_id': x['candidates']} for x in demand[k]]
+ res[v] = [{'inventory_type': x['identifierType'], 'candidate_id': x['identifiers']} for x in demand[k]]
return res
def get_policy_properties(demand, policies):
"""Get policy_properties for cases where there is a match with the demand"""
for policy in policies:
- if demand['resourceModuleName'] not in set(policy['content'].get('resources', [])):
+ policy_demands = set([x.lower() for x in policy['content'].get('resources', [])])
+ if demand['resourceModuleName'].lower() not in policy_demands:
continue # no match for this policy
for policy_property in policy['content']['vnfProperties']:
yield policy_property
for policy_property in get_policy_properties(demand, policies):
prop = dict(inventory_provider=policy_property['inventoryProvider'],
inventory_type=policy_property['inventoryType'],
- service_type=demand['serviceResourceId'])
- attributes = policy_config_mapping['attributes']
- prop['attributes'] = {
- 'global-customer-id': policy_property['customerId'],
- 'orchestration-status': "",
- 'model-invariant-id': demand['resourceModelInfo']['modelInvariantId'],
- 'model-version-id': demand['resourceModelInfo']['modelVersionId'],
- 'service-type': demand['serviceResourceId'],
- 'equipment-role': policy_property['equipmentRole']
- }
- # if 'attributes' in policy_property:
- # prop['attributes'] = get_augmented_policy_attributes(policy_property, demand)
- # for k1, v1, k2, v2 in policy_config_mapping['extra_fields']:
- # if k1 == v1:
- # prop[k2] = v2
- prop.update(get_candidates_demands(demand)) # for excluded and partial-rehoming cases
+ service_type=demand['serviceResourceId'],
+ service_resource_id=demand['serviceResourceId'])
+
+ prop.update({'unique': demand['unique']} if demand.get('unique') else {})
+ prop['attributes'] = dict()
+ prop['attributes'].update({'global-customer-id': policy_property['customerId']}
+ if policy_property['customerId'] else {})
+ prop['attributes'].update({'model-invariant-id': demand['resourceModelInfo']['modelInvariantId']}
+ if demand['resourceModelInfo']['modelInvariantId'] else {})
+ prop['attributes'].update({'model-version-id': demand['resourceModelInfo']['modelVersionId']}
+ if demand['resourceModelInfo']['modelVersionId'] else {})
+ prop['attributes'].update({'equipment-role': policy_property['equipmentRole']}
+ if policy_property['equipmentRole'] else {})
+
+ if policy_property.get('attributes'):
+ for attr_key, attr_val in policy_property['attributes'].items():
+ update_converted_attribute(attr_key, attr_val, prop)
+
+ prop.update(get_candidates_demands(demand))
demand_properties.append(prop)
return demand_properties
+def update_converted_attribute(attr_key, attr_val, properties):
+ """
+ Updates dictonary of attributes with one specified in the arguments.
+ Automatically translates key namr from camelCase to hyphens
+ :param attr_key: key of the attribute
+ :param attr_val: value of the attribute
+ :param properties: dictionary with attributes to update
+ :return:
+ """
+ if attr_val:
+ remapping = policy_config_mapping['attributes']
+ if remapping.get(attr_key):
+ key_value = remapping.get(attr_key)
+ else:
+ key_value = re.sub('(.)([A-Z][a-z]+)', r'\1-\2', attr_key)
+ key_value = re.sub('([a-z0-9])([A-Z])', r'\1-\2', key_value).lower()
+ properties['attributes'].update({key_value: attr_val})
+
+
def gen_demands(req_json, vnf_policies):
"""Generate list of demands based on request and VNF policies
:param req_json: Request object from the client (e.g. MSO)
"""
demand_dictionary = {}
for demand in req_json['placementInfo']['placementDemands']:
- demand_dictionary.update(
- {demand['resourceModuleName']: get_demand_properties(demand, vnf_policies)})
+ prop = get_demand_properties(demand, vnf_policies)
+ if len(prop) > 0:
+ demand_dictionary.update({demand['resourceModuleName']: prop})
return demand_dictionary