diff options
author | 2018-01-12 04:45:58 +0000 | |
---|---|---|
committer | 2018-01-12 04:45:58 +0000 | |
commit | e3e5575a06e3c02c8adecbeeb153d4a6a7f2fda4 (patch) | |
tree | 2e7b15f927bc112377cf73ff7879dfb564ae6b8f /optimizers/placementopt/conductor/api_builder.py | |
parent | e91ad0d899121fb190391865422ea6424ffc29ca (diff) | |
parent | 524573f21dfc3d88b1512850d52da7e5b545cf9d (diff) |
Merge "Seed code for OSDF placement adapter"
Diffstat (limited to 'optimizers/placementopt/conductor/api_builder.py')
-rw-r--r-- | optimizers/placementopt/conductor/api_builder.py | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/optimizers/placementopt/conductor/api_builder.py b/optimizers/placementopt/conductor/api_builder.py new file mode 100644 index 0000000..c0281fe --- /dev/null +++ b/optimizers/placementopt/conductor/api_builder.py @@ -0,0 +1,121 @@ +# ------------------------------------------------------------------------- +# Copyright (c) 2015-2017 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 copy +import json +from osdf.utils import data_mapping +from jinja2 import Template +from osdf.utils.programming_utils import list_flatten, dot_notation +import osdf.optimizers.placementopt.conductor.translation as tr +from osdf.adapters.policy.utils import group_policies + + +def conductor_api_builder(request_json, flat_policies: list, local_config, prov_status, + template="templates/conductor_interface.json"): + """Build a SNIRO southbound API call for Conductor/Placement optimization + :param request_json: parameter data received from a client + :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 prov_status: provStatus retrieved from Subscriber policy + :return: json to be sent to Conductor/placement optimization + """ + templ = Template(open(template).read()) + gp = group_policies(flat_policies) + demand_vnf_name_list = [] + + for placementDemand in request_json['placementInfo']['demandInfo']['placementDemand']: + demand_vnf_name_list.append(placementDemand['resourceModuleName']) + + demand_list = tr.gen_demands(request_json['placementInfo']['demandInfo'], gp['vnfPolicy']) + attribute_policy_list = tr.gen_attribute_policy(demand_vnf_name_list, gp['attribute']) + distance_to_location_policy_list = tr.gen_distance_to_location_policy( + demand_vnf_name_list, gp['distance_to_location']) + inventory_policy_list = tr.gen_inventory_group_policy(demand_vnf_name_list, gp['inventory_group']) + resource_instance_policy_list = tr.gen_resource_instance_policy( + demand_vnf_name_list, gp['instance_fit']) + resource_region_policy_list = tr.gen_resource_region_policy(demand_vnf_name_list, gp['region_fit']) + zone_policy_list = tr.gen_zone_policy(demand_vnf_name_list, gp['zone']) + optimization_policy_list = tr.gen_optimization_policy(demand_vnf_name_list, gp['placementOptimization']) + reservation_policy_list = tr.gen_reservation_policy(demand_vnf_name_list, gp['instance_reservation']) + conductor_policies = [attribute_policy_list, distance_to_location_policy_list, inventory_policy_list, + resource_instance_policy_list, resource_region_policy_list, zone_policy_list] + filtered_policies = [x for x in conductor_policies if len(x) > 0] + policy_groups = list_flatten(filtered_policies) + reservation_policies = [x for x in reservation_policy_list if len(x) > 0] + reservation_groups = list_flatten(reservation_policies) + req_info = request_json['requestInfo'] + model_name = request_json['placementInfo']['serviceModelInfo']['modelName'] + service_type = data_mapping.get_service_type(model_name) + service_info = local_config.get('service_info', {}).get(service_type, {}) + if 'orderInfo' in request_json["placementInfo"]: + order_info = json.loads(request_json["placementInfo"]["orderInfo"]) + request_type = req_info.get('requestType', None) + subs_com_site_id = "" + if 'subscriberInfo' in request_json['placementInfo']: + subs_com_site_id = request_json['placementInfo']['subscriberInfo'].get('subscriberCommonSiteId', "") + if service_type == 'vCPE': + data_mapping.normalize_user_params(order_info) + rendered_req = templ.render( + requestType=request_type, + chosenComplex=subs_com_site_id, + demand_list=demand_list, + policy_groups=policy_groups, + optimization_policies=optimization_policy_list, + name=req_info['requestId'], + timeout=req_info['timeout'], + limit=req_info['numSolutions'], + serviceType=service_type, + serviceInstance=request_json['placementInfo']['serviceInstanceId'], + provStatus = prov_status, + chosenRegion=order_info['requestParameters']['lcpCloudRegionId'], + json=json) + elif service_type == 'UNKNOWN': + rendered_req = templ.render( + requestType=request_type, + chosenComplex=subs_com_site_id, + demand_list=demand_list, + policy_groups=policy_groups, + reservation_groups=reservation_groups, + optimization_policies=optimization_policy_list, + name=req_info['requestId'], + timeout=req_info['timeout'], + limit=req_info['numSolutions'], + serviceType=service_type, + serviceInstance=request_json['placementInfo']['serviceInstanceId'], + provStatus = prov_status, + # process order data + bandwidth=dot_notation(order_info, service_info['bandwidth']), + bandwidth_unit=dot_notation(order_info, service_info['bandwidth_units']), + json=json) + json_payload = json.dumps(json.loads(rendered_req)) # need this because template's JSON is ugly! + return json_payload + + +def retrieve_node(req_json, reference): + """ + Get the child node(s) from the dot-notation [reference] and parent [req_json]. + For placement and other requests, there are encoded JSONs inside the request or policy, + so we need to expand it and then do a search over the parent plus expanded JSON. + """ + req_json_copy = copy.deepcopy(req_json) # since we expand the JSON in place, we work on a copy + if 'orderInfo' in req_json_copy['placementInfo']: + req_json_copy['placementInfo']['orderInfo'] = json.loads(req_json_copy['placementInfo']['orderInfo']) + info = dot_notation(req_json_copy, reference) + return list_flatten(info) if isinstance(info, list) else info + |