aboutsummaryrefslogtreecommitdiffstats
path: root/osdf/adapters
diff options
context:
space:
mode:
authorkrishnaa96 <krishna.moorthy6@wipro.com>2020-03-23 13:11:07 +0530
committerkrishnaa96 <krishna.moorthy6@wipro.com>2020-03-23 13:16:31 +0530
commitfcb37e97e37137d3111924e993e75fdb83c2a0a0 (patch)
treeb907cf4f4fb01b8961747f50caf9b9937e0b54fe /osdf/adapters
parentf0f912e2e8cb23952099c3df83167181a50ab2f8 (diff)
Add functionality to support NSI selection
Issue-ID: OPTFRA-677 Signed-off-by: krishnaa96 <krishna.moorthy6@wipro.com> Change-Id: Ibc51e15fce4692a445df400053060d3a6977b4ce
Diffstat (limited to 'osdf/adapters')
-rw-r--r--osdf/adapters/conductor/api_builder.py21
-rw-r--r--osdf/adapters/conductor/conductor.py30
-rwxr-xr-xosdf/adapters/conductor/templates/conductor_interface.json2
-rw-r--r--osdf/adapters/conductor/translation.py58
4 files changed, 66 insertions, 45 deletions
diff --git a/osdf/adapters/conductor/api_builder.py b/osdf/adapters/conductor/api_builder.py
index 17057d8..c99c5eb 100644
--- a/osdf/adapters/conductor/api_builder.py
+++ b/osdf/adapters/conductor/api_builder.py
@@ -33,7 +33,8 @@ def _build_parameters(group_policies, service_info, request_parameters):
:param request_parameters: request parameters
:return:
"""
- initial_params = tr.get_opt_query_data(request_parameters, group_policies['onap.policies.optimization.QueryPolicy'])
+ initial_params = tr.get_opt_query_data(request_parameters,
+ group_policies['onap.policies.optimization.QueryPolicy'])
params = dict()
params.update({"REQUIRED_MEM": initial_params.pop("requiredMemory", "")})
params.update({"REQUIRED_DISK": initial_params.pop("requiredDisk", "")})
@@ -49,16 +50,19 @@ def _build_parameters(group_policies, service_info, request_parameters):
return params
-def conductor_api_builder(req_info, demands, request_parameters, service_info, flat_policies: list, local_config,
+def conductor_api_builder(req_info, demands, request_parameters, service_info,
+ location_enabled, flat_policies: list, local_config,
template="osdf/adapters/conductor/templates/conductor_interface.json"):
"""Build an OSDF southbound API call for HAS-Conductor/Placement optimization
:param req_info: parameter data received from a client
:param demands: list of demands
:param request_parameters: request parameters
:param service_info: service info object
+ :param location_enabled: boolean to check location to be sent in the request
:param flat_policies: policy data received from the policy platform (flat policies)
:param template: template to generate southbound API call to conductor
- :param local_config: local configuration file with pointers for the service specific information
+ :param local_config: local configuration file with pointers for
+ the service specific information
:return: json to be sent to Conductor/placement optimization
"""
@@ -88,10 +92,14 @@ def conductor_api_builder(req_info, demands, request_parameters, service_info, f
demand_name_list, gp['onap.policies.optimization.Vim_fit'])
hpa_policy_list = tr.gen_hpa_policy(
demand_name_list, gp['onap.policies.optimization.HpaPolicy'])
+ threshold_policy_list = tr.gen_threshold_policy(demand_name_list,
+ gp['onap.policies.optimization.'
+ 'ThresholdPolicy'])
req_params_dict = _build_parameters(gp, service_info, request_parameters)
- conductor_policies = [attribute_policy_list, distance_to_location_policy_list, inventory_policy_list,
- resource_instance_policy_list, resource_region_policy_list, zone_policy_list,
- reservation_policy_list, capacity_policy_list, hpa_policy_list]
+ conductor_policies = [attribute_policy_list, distance_to_location_policy_list,
+ inventory_policy_list, resource_instance_policy_list,
+ resource_region_policy_list, zone_policy_list, reservation_policy_list,
+ capacity_policy_list, hpa_policy_list, threshold_policy_list]
filtered_policies = [x for x in conductor_policies if len(x) > 0]
policy_groups = list_flatten(filtered_policies)
request_type = req_info.get('requestType', None)
@@ -104,6 +112,7 @@ def conductor_api_builder(req_info, demands, request_parameters, service_info, f
timeout=req_info['timeout'],
limit=req_info['numSolutions'],
request_params=req_params_dict,
+ location_enabled=location_enabled,
json=json)
json_payload = json.dumps(json.loads(rendered_req)) # need this because template's JSON is ugly!
return json_payload
diff --git a/osdf/adapters/conductor/conductor.py b/osdf/adapters/conductor/conductor.py
index 00069a4..155d4d5 100644
--- a/osdf/adapters/conductor/conductor.py
+++ b/osdf/adapters/conductor/conductor.py
@@ -28,7 +28,8 @@ from osdf.utils.interfaces import RestClient
from osdf.operation.exceptions import BusinessException
-def request(req_info, demands, request_parameters, service_info, osdf_config, flat_policies):
+def request(req_info, demands, request_parameters, service_info, location_enabled,
+ osdf_config, flat_policies):
config = osdf_config.deployment
local_config = osdf_config.core
uid, passwd = config['conductorUsername'], config['conductorPassword']
@@ -43,13 +44,16 @@ def request(req_info, demands, request_parameters, service_info, osdf_config, fl
if cond_minor_version is not None:
x_minor_version = str(cond_minor_version)
headers.update({'X-MinorVersion': x_minor_version})
- debug_log.debug("Versions set in HTTP header to conductor: X-MinorVersion: {} ".format(x_minor_version))
+ debug_log.debug("Versions set in HTTP header to "
+ "conductor: X-MinorVersion: {} ".format(x_minor_version))
max_retries = config.get('conductorMaxRetries', 30)
ping_wait_time = config.get('conductorPingWaitTime', 60)
- rc = RestClient(userid=uid, passwd=passwd, method="GET", log_func=debug_log.debug, headers=headers)
- conductor_req_json_str = conductor_api_builder(req_info, demands, request_parameters, service_info, flat_policies,
+ rc = RestClient(userid=uid, passwd=passwd, method="GET", log_func=debug_log.debug,
+ headers=headers)
+ conductor_req_json_str = conductor_api_builder(req_info, demands, request_parameters,
+ service_info, location_enabled, flat_policies,
local_config)
conductor_req_json = json.loads(conductor_req_json_str)
@@ -77,14 +81,16 @@ def request(req_info, demands, request_parameters, service_info, osdf_config, fl
"this transaction is timing out".format(max_timeout))
time.sleep(ping_wait_time)
ctr += 1
- debug_log.debug("Attempt number {} url {}; prior status={}".format(ctr, new_url, resp['plans'][0]['status']))
+ debug_log.debug("Attempt number {} url {}; prior status={}"
+ .format(ctr, new_url, resp['plans'][0]['status']))
total_time += ping_wait_time
try:
raw_resp = rc.request(new_url, raw_response=True)
resp = raw_resp.json()
except RequestException as e:
- debug_log.debug("Conductor attempt {} for request_id {} has failed because {}".format(ctr, req_id, str(e)))
+ debug_log.debug("Conductor attempt {} for request_id {} has failed because {}"
+ .format(ctr, req_id, str(e)))
def initial_request_to_conductor(rc, conductor_url, conductor_req_json):
@@ -92,17 +98,21 @@ def initial_request_to_conductor(rc, conductor_url, conductor_req_json):
:param rc: REST client object for calling conductor
:param conductor_url: conductor's base URL to submit a placement request
:param conductor_req_json: request json object to send to Conductor
- :return: URL to check for follow up (similar to redirects); we keep checking these till we get a result/error
+ :return: URL to check for follow up (similar to redirects);
+ we keep checking these till we get a result/error
"""
debug_log.debug("Payload to Conductor: {}".format(json.dumps(conductor_req_json)))
- raw_resp = rc.request(url=conductor_url, raw_response=True, method="POST", json=conductor_req_json)
+ raw_resp = rc.request(url=conductor_url, raw_response=True, method="POST",
+ json=conductor_req_json)
resp = raw_resp.json()
if resp["status"] != "template":
raise RequestException(response=raw_resp, request=raw_resp.request)
time.sleep(10) # 10 seconds wait time to avoid being too quick!
plan_url = resp["links"][0][0]["href"]
- debug_log.debug("Attempting to read the plan from the conductor provided url {}".format(plan_url))
- raw_resp = rc.request(raw_response=True, url=plan_url) # TODO: check why a list of lists for links
+ debug_log.debug("Attempting to read the plan from "
+ "the conductor provided url {}".format(plan_url))
+ raw_resp = rc.request(raw_response=True,
+ url=plan_url) # TODO: check why a list of lists for links
resp = raw_resp.json()
if resp["plans"][0]["status"] in ["error"]:
diff --git a/osdf/adapters/conductor/templates/conductor_interface.json b/osdf/adapters/conductor/templates/conductor_interface.json
index 030d6a0..d4a9a0e 100755
--- a/osdf/adapters/conductor/templates/conductor_interface.json
+++ b/osdf/adapters/conductor/templates/conductor_interface.json
@@ -11,12 +11,14 @@
"{{key}}": {{ json.dumps(value) }}
{% endfor %}
},
+ {% if location_enabled %}
"locations": {
"customer_loc": {
"latitude": { "get_param": "customer_lat" },
"longitude": { "get_param": "customer_long" }
}
},
+ {% endif %}
"demands": {{ json.dumps(demand_list) }},
{% set comma_main = joiner(",") %}
"constraints": {
diff --git a/osdf/adapters/conductor/translation.py b/osdf/adapters/conductor/translation.py
index 12dfc88..002af88 100644
--- a/osdf/adapters/conductor/translation.py
+++ b/osdf/adapters/conductor/translation.py
@@ -26,6 +26,19 @@ from osdf.utils.programming_utils import dot_notation
policy_config_mapping = yaml.safe_load(open('config/has_config.yaml')).get('policy_config_mapping')
+CONSTRAINT_TYPE_MAP = {"onap.policies.optimization.AttributePolicy": "attribute",
+ "onap.policies.optimization.DistancePolicy": "distance_to_location",
+ "onap.policies.optimization.InventoryGroupPolicy": "inventory_group",
+ "onap.policies.optimization.ResourceInstancePolicy": "instance_fit",
+ "onap.policies.optimization.ResourceRegionPolicy": "region_fit",
+ "onap.policies.optimization.AffinityPolicy": "zone",
+ "onap.policies.optimization.InstanceReservationPolicy":
+ "instance_reservation",
+ "onap.policies.optimization.Vim_fit": "vim_fit",
+ "onap.policies.optimization.HpaPolicy": "hpa",
+ "onap.policies.optimization.ThresholdPolicy": "threshold"
+ }
+
def get_opt_query_data(request_parameters, policies):
"""
@@ -44,6 +57,7 @@ def get_opt_query_data(request_parameters, policies):
req_param_dict.update({queryProp['attribute']: attr_val})
return req_param_dict
+
def gen_optimization_policy(vnf_list, optimization_policy):
"""Generate optimization policy details to pass to Conductor
:param vnf_list: List of vnf's to used in placement request
@@ -105,7 +119,7 @@ def gen_policy_instance(vnf_list, resource_policy, match_type="intersection", rt
for policy in resource_policy:
pc = policy[list(policy.keys())[0]]
default, demands = get_matching_vnfs(pc['properties']['resources'], vnf_list, match_type=match_type)
- resource = {pc['properties']['identity']: {'type': map_constraint_type(pc['type']), 'demands': demands}}
+ resource = {pc['properties']['identity']: {'type': CONSTRAINT_TYPE_MAP.get(pc['type']), 'demands': demands}}
if rtype:
resource[pc['properties']['identity']]['properties'] = {'controller': pc[rtype]['controller'],
@@ -115,13 +129,13 @@ def gen_policy_instance(vnf_list, resource_policy, match_type="intersection", rt
if default:
for d in demands:
resource_repeated = True \
- if {pc['properties']['identity']: {'type': map_constraint_type(pc['type']), 'demands': d}} \
+ if {pc['properties']['identity']: {'type': CONSTRAINT_TYPE_MAP.get(pc['type']), 'demands': d}} \
in resource_policy_list else False
if resource_repeated:
continue
else:
resource_policy_list.append(
- {pc['properties']['identity']: {'type': map_constraint_type(pc['type']), 'demands': d }})
+ {pc['properties']['identity']: {'type': CONSTRAINT_TYPE_MAP.get(pc['type']), 'demands': d }})
policy[list(policy.keys())[0]]['properties']['resources'] = d
related_policies.append(policy)
# Need to override the default policies, here delete the outdated policy stored in the db
@@ -216,6 +230,14 @@ def gen_hpa_policy(vnf_list, hpa_policy):
return cur_policies
+def gen_threshold_policy(vnf_list, threshold_policy):
+ cur_policies, related_policies = gen_policy_instance(vnf_list, threshold_policy, rtype=None)
+ for p_new, p_main in zip(cur_policies, related_policies):
+ pmz = p_main[list(p_main.keys())[0]]['properties']['thresholdProperty']
+ p_new[p_main[list(p_main.keys())[0]]['properties']['identity']]['properties'] = pmz
+ return cur_policies
+
+
def get_augmented_policy_attributes(policy_property, demand):
"""Get policy attributes and augment them using policy_config_mapping and demand information"""
attributes = copy.copy(policy_property['attributes'])
@@ -260,13 +282,13 @@ def get_demand_properties(demand, policies):
policy_property['unique'] else {})
prop['filtering_attributes'] = dict()
prop['filtering_attributes'].update({'global-customer-id': policy_property['customerId']}
- if policy_property['customerId'] else {})
+ if 'customerId' in policy_property and policy_property['customerId'] else {})
prop['filtering_attributes'].update({'model-invariant-id': demand['resourceModelInfo']['modelInvariantId']}
if demand['resourceModelInfo']['modelInvariantId'] else {})
prop['filtering_attributes'].update({'model-version-id': demand['resourceModelInfo']['modelVersionId']}
if demand['resourceModelInfo']['modelVersionId'] else {})
prop['filtering_attributes'].update({'equipment-role': policy_property['equipmentRole']}
- if policy_property['equipmentRole'] else {})
+ if 'equipmentRole' in policy_property and policy_property['equipmentRole'] else {})
if policy_property.get('attributes'):
for attr_key, attr_val in policy_property['attributes'].items():
@@ -304,7 +326,8 @@ def update_converted_attribute(attr_key, attr_val, properties, attribute_type):
def gen_demands(demands, vnf_policies):
"""Generate list of demands based on request and VNF policies
:param demands: A List of demands
- :param vnf_policies: Policies associated with demand resources (e.g. from grouped_policies['vnfPolicy'])
+ :param vnf_policies: Policies associated with demand resources
+ (e.g. from grouped_policies['vnfPolicy'])
:return: list of demand parameters to populate the Conductor API call
"""
demand_dictionary = {}
@@ -315,29 +338,6 @@ def gen_demands(demands, vnf_policies):
return demand_dictionary
-def map_constraint_type(policy_type):
- if "onap.policies.optimization.AttributePolicy" == policy_type:
- return "attribute"
- if "onap.policies.optimization.DistancePolicy" == policy_type:
- return "distance_to_location"
- if "onap.policies.optimization.InventoryGroupPolicy" == policy_type:
- return "inventory_group"
- if "onap.policies.optimization.ResourceInstancePolicy" == policy_type:
- return "instance_fit"
- if "onap.policies.optimization.ResourceRegionPolicy" == policy_type:
- return "region_fit"
- if "onap.policies.optimization.AffinityPolicy" == policy_type:
- return "zone"
- if "onap.policies.optimization.InstanceReservationPolicy" == policy_type:
- return "instance_reservation"
- if "onap.policies.optimization.Vim_fit" == policy_type:
- return "vim_fit"
- if "onap.policies.optimization.HpaPolicy" == policy_type:
- return "hpa"
-
- return policy_type
-
-
def gen_cloud_region(property):
prop = {"cloud_region_attributes": dict()}
if 'cloudRegion' in property: