1 # -------------------------------------------------------------------------
2 # Copyright (c) 2020 Fujitsu Limited Intellectual Property
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
16 # -------------------------------------------------------------------------
23 from requests.auth import HTTPBasicAuth
26 from osdf.logging.osdf_logging import audit_log
28 from sklearn import preprocessing
30 BASE_DIR = os.path.dirname(__file__)
31 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
34 class InterDomainRouteOpt:
37 This values will need to deleted..
38 only added for the debug purpose
41 "X-TransactionId": "9999",
43 "Accept": "application/json",
44 "Content-Type": "application/json",
48 def get_route(self, request, osdf_config):
50 This method processes the mdons route request
51 and returns an optimised path for the given
56 route_info = request["routeInfo"]["routeRequest"]
57 src_controller_id = route_info["srcDetails"]["controllerId"]
58 src_port_id = route_info["srcDetails"]["interfaceId"]
59 dst_controller_id = route_info["dstDetails"]["controllerId"]
60 dst_port_id = route_info["dstDetails"]["interfaceId"]
61 service_rate = route_info["serviceRate"]
62 dzn_data, mapping_table = self.build_dzn_data(osdf_config, src_controller_id,
63 dst_controller_id, service_rate)
64 audit_log.info("Dzn data")
65 audit_log.info(dzn_data)
66 mzn_model = os.path.join(BASE_DIR, 'route_opt.mzn')
67 links_list = self.find_suitable_path(mzn_model, dzn_data, mapping_table)
68 ordered_list = self.get_ordered_route_list(links_list,
69 src_controller_id, dst_controller_id)
70 solution = self.get_solution_object(ordered_list, src_port_id, dst_port_id)
72 "requestId": request["requestInfo"]["requestId"],
73 "transactionId": request["requestInfo"]["transactionId"],
74 "statusMessage": "SUCCESS",
75 "requestStatus": "accepted",
78 except Exception as err:
82 def get_solution_object(self, ordered_list, src_port_id, dst_port_id):
84 :param ordered_list: service_route list
85 :param src_port_id: source port id of route
86 :param dst_port_id: destination port id of route
87 :return: solution object of the route respone
89 service_route_list = []
91 for value in ordered_list:
92 service_route_object = {}
93 service_route_object["srcInterfaceId"] = src_port_id
94 service_route_object["dstInterfaceId"] = value["srcPortId"]
95 service_route_object["controllerId"] = value["srcControllerId"]
96 service_route_list.append(service_route_object)
97 link_list.append(value["linkName"])
98 src_port_id = value["dstPortId"]
99 dst_controller_id = value["dstControllerId"]
100 service_route_object = {}
101 service_route_object["srcInterfaceId"] = src_port_id
102 service_route_object["dstInterfaceId"] = dst_port_id
103 service_route_object["controllerId"] = dst_controller_id
104 service_route_list.append(service_route_object)
105 route_info_object = {
106 "serviceRoute" : service_route_list,
107 "linkList" : link_list
110 "routeInfo" : route_info_object
115 def get_ordered_route_list(self, link_list, src_controller_id, dst_controller_id):
117 :param link_list: link list from the minizinc response
118 :param src_controller_id: source port id of route
119 :param dst_controller_id: destination port id of route
120 :return: route list in order
122 ordered_link_list = []
125 for item in link_list:
126 if item["srcControllerId"] == src_controller_id:
127 ordered_link_list.append(item)
128 src_controller_id = item["dstControllerId"]
129 if src_controller_id == dst_controller_id:
131 return ordered_link_list
134 def find_suitable_path(self, mzn_model, dzn_data, mapping_table):
136 :param mzn_model: minizinc model details
137 :param dzn_data: minizinc data
138 :param mapping_table: list that maintains AAI link details
139 :return: list of link from after running minizinc
141 minizinc_solution = self.solve(mzn_model, dzn_data)
142 audit_log.info("Minizinc Solution ==========>")
143 routes = list(minizinc_solution)
144 audit_log.info(routes)
147 except Exception as err:
148 audit_log.info("No minizinc solutions found")
151 for i in range(0, len(routes[0]['x'])):
153 links_list.append(mapping_table[i])
157 def process_inter_domain_link(self, logical_link, osdf_config):
159 :param logical_link: logical links from AAI
160 :param osdf_config: OSDF config details
161 :return: list of link object with src and dst controller details
164 link_details["linkName"] = logical_link["link-name"]
165 relationship = logical_link["relationship-list"]["relationship"]
168 for value in relationship:
169 if value["related-to"] == "p-interface" and flag == 1:
170 src_port_id = value["relationship-data"][1]["relationship-value"]
171 src_controller_id = self.get_controller_for_interface(osdf_config, src_port_id)
172 link_details["srcPortId"] = src_port_id
173 link_details["srcControllerId"] = src_controller_id
175 elif value["related-to"] == "p-interface" and flag == 2:
176 dest_port_id = value["relationship-data"][1]["relationship-value"]
177 dest_controller_id = self.get_controller_for_interface(osdf_config, dest_port_id)
178 link_details["dstPortId"] = dest_port_id
179 link_details["dstControllerId"] = dest_controller_id
183 def prepare_map_table(self, osdf_config, logical_links):
185 :param logical_links: logical links from AAI
186 :param osdf_config: OSDF config details
187 :return: list of link object with src and dst controller details
189 results = map(self.process_inter_domain_link, logical_links,
190 itertools.repeat(osdf_config, len(logical_links)))
191 new_results = list(results)
194 new_list += new_results
195 for i in new_results:
197 link_details["linkName"] = i["linkName"]
198 link_details["srcPortId"] = i["dstPortId"]
199 link_details["srcControllerId"] = i["dstControllerId"]
200 link_details["dstPortId"] = i["srcPortId"]
201 link_details["dstControllerId"] = i["srcControllerId"]
202 new_list.append(link_details)
206 def solve(self, mzn_model, dzn_data):
208 :param mzn_model: minizinc template
209 :param dzn_data: minizinc data model
210 :return: minizinc response
212 return pymzn.minizinc(mzn=mzn_model, data=dzn_data)
215 def get_links_based_on_bandwidth_attributes(self, logical_links_list,
216 osdf_config, service_rate):
218 This method filters the logical links based on the
219 bandwidth attribute availability of the interfaces
221 :return: filtered_list[]
224 for logical_link in logical_links_list:
225 relationship = logical_link["relationship-list"]["relationship"]
227 for value in relationship:
228 if value["related-to"] == "p-interface":
229 interface_url = value["related-link"]
230 if self.get_available_bandwidth_aai(interface_url, osdf_config, service_rate):
233 filtered_list.append(logical_link)
238 def build_dzn_data(self, osdf_config, src_controller_id, dst_controller_id, service_rate):
240 :param osdf_config: OSDF config details
241 :param src_controller_id: controller Id of the source port
242 :param dst_controller_id: controller id of the destination port
243 :param service_rate: service rate
244 :return: mapping atble which maintains link details from AAI
245 and minizinc data model to be used by template
247 logical_links = self.get_inter_domain_links(osdf_config)
248 logical_links_list = logical_links["logical-link"]
249 mapping_table = self.prepare_map_table(osdf_config,
250 self.get_links_based_on_bandwidth_attributes(logical_links_list, osdf_config, service_rate))
254 for item in mapping_table:
255 edge_start.append(item["srcControllerId"])
256 edge_end.append(item["dstControllerId"])
258 for k in range(0, len(edge_start)):
260 list_controllers = self.get_controllers_from_aai(osdf_config)
261 le = preprocessing.LabelEncoder()
262 le.fit(list_controllers)
264 start_edge = le.transform(edge_start)
265 end_edge = le.transform(edge_end)
266 source = le.transform([src_controller_id])
267 destination = le.transform([dst_controller_id])
269 final_dzn_start_arr = []
271 final_dzn_start_arr.append(i)
273 final_dzn_end_arr = []
275 final_dzn_end_arr.append(j)
277 contollers_length = len(list_controllers)
278 no_of_edges = len(final_dzn_start_arr)
280 'N': contollers_length,
282 'Edge_Start': final_dzn_start_arr,
283 'Edge_End': final_dzn_end_arr,
286 'End' : destination[0]
288 return dzn_data, mapping_table
291 def get_inter_domain_links(self, osdf_config):
293 This method returns list of all cross ONAP links
294 from /aai/v19/network/logical-links?link-type=inter-domain&operational-status="Up"
295 :return: logical-links[]
298 config = osdf_config.deployment
299 aai_url = config["aaiUrl"]
300 aai_req_url = aai_url + config["aaiGetInterDomainLinksUrl"]
301 response = requests.get(aai_req_url, headers=self.aai_headers,
302 auth=HTTPBasicAuth("AAI", "AAI"), verify=False)
303 if response.status_code == 200:
304 return response.json()
307 def get_controller_for_interface(self, osdf_config, port_id):
309 This method returns returns the controller id
310 given a p-interface from the below query
311 :return: controller_id
314 "start": ["external-system"],
315 "query": "query/getDomainController?portid="
317 query = data.get("query") + port_id
318 data.update(query=query)
319 config = osdf_config.deployment
320 aai_url = config["aaiUrl"]
321 aai_req_url = aai_url + config["controllerQueryUrl"]
322 response = requests.put(aai_req_url, data=json.dumps(data),
323 headers=self.aai_headers,
324 auth=HTTPBasicAuth("AAI", "AAI"),
326 if response.status_code == 200:
327 response_body = response.json()
328 return response_body["results"][0]["esr-thirdparty-sdnc"]["thirdparty-sdnc-id"]
331 def get_controllers_from_aai(self, osdf_config):
333 This method returns returns the list of
334 controller names in AAI
335 :return: controllers_list[]
337 controllers_list = []
338 config = osdf_config.deployment
339 aai_url = config["aaiUrl"]
340 aai_req_url = aai_url + config["aaiGetControllersUrl"]
341 response = requests.get(aai_req_url,
342 headers=self.aai_headers,
343 auth=HTTPBasicAuth("AAI", "AAI"),
345 if response.status_code == 200:
346 response_body = response.json()
347 esr_thirdparty_list = response_body["esr-thirdparty-sdnc"]
349 for item in esr_thirdparty_list:
350 controllers_list.append(item["thirdparty-sdnc-id"])
351 return controllers_list
354 def get_available_bandwidth_aai(self, interface_url, osdf_config, service_rate):
356 Checks if the given interface has the required bandwidth
357 :return: boolean flag
359 config = osdf_config.deployment
360 aai_url = config["aaiUrl"]
361 aai_req_url = aai_url + interface_url + "?depth=all"
362 response = requests.get(aai_req_url,
363 headers=self.aai_headers,
364 auth=HTTPBasicAuth("AAI", "AAI"), verify=False)
365 if response.status_code == 200:
366 response_body = response.json()
367 available_bandwidth = response_body["bandwidth-attributes"]["bandwidth-attribute"][0]["available-bandwidth-map"]["available-bandwidth"]
368 for i in available_bandwidth:
369 if i["odu-type"] == service_rate and i["number"] > 0: