Loading src/pathcomp/frontend/service/algorithms/KDisjointPathAlgorithm.py +53 −33 Original line number Diff line number Diff line Loading @@ -13,7 +13,8 @@ # limitations under the License. import copy from typing import Optional from typing import Dict, List, Optional, Set, Tuple from common.proto.context_pb2 import Link from common.proto.pathcomp_pb2 import Algorithm_KDisjointPath, Algorithm_KShortestPath, PathCompReply from ._Algorithm import _Algorithm from .KShortestPathAlgorithm import KShortestPathAlgorithm Loading @@ -23,6 +24,36 @@ class KDisjointPathAlgorithm(_Algorithm): super().__init__('KDP', False, class_name=class_name) self.num_disjoint = algorithm.num_disjoint def get_link_from_endpoint(self, endpoint : Dict) -> Tuple[Dict, Link]: device_uuid = endpoint['device_id'] endpoint_uuid = endpoint['endpoint_uuid'] item = self.endpoint_to_link_dict.get((device_uuid, endpoint_uuid)) if item is None: MSG = 'Link for Endpoint({:s}, {:s}) not found' self.logger.warning(MSG.format(device_uuid, endpoint_uuid)) return None return item def path_to_links(self, path_endpoints : List[Dict]) -> Tuple[List[Dict], Set[str]]: path_links = list() path_link_ids = set() for endpoint in path_endpoints: link_tuple = self.get_link_from_endpoint(endpoint) if link_tuple is None: continue json_link,_ = link_tuple json_link_id = json_link['link_Id'] if len(path_links) == 0 or path_links[-1]['link_Id'] != json_link_id: path_links.append(json_link) path_link_ids.add(json_link_id) return path_links, path_link_ids def remove_traversed_links(self, link_list : List[Dict], path_endpoints : List[Dict]): _, path_link_ids = self.path_to_links(path_endpoints) new_link_list = list(filter(lambda l: l['link_Id'] not in path_link_ids, link_list)) self.logger.info('cur_link_list = {:s}'.format(str(link_list))) self.logger.info('new_link_list = {:s}'.format(str(new_link_list))) return new_link_list def execute(self, dump_request_filename: Optional[str] = None, dump_reply_filename: Optional[str] = None) -> None: algorithm = KShortestPathAlgorithm(Algorithm_KShortestPath(k_inspection=0, k_return=1)) algorithm.sync_paths = True Loading @@ -35,49 +66,38 @@ class KDisjointPathAlgorithm(_Algorithm): algorithm.service_list = self.service_list algorithm.service_dict = self.service_dict disjoint_paths = dict() Path = List[Dict] Path_NoPath = Optional[Path] # None = no path, list = path self.json_reply : Dict[Tuple[str, str], List[Path_NoPath]] = dict() for num_path in range(self.num_disjoint): algorithm.execute('ksp-{:d}-request.json'.format(num_path), 'ksp-{:d}-reply.txt'.format(num_path)) #dump_request_filename = 'ksp-{:d}-request.json'.format(num_path) #dump_reply_filename = 'ksp-{:d}-reply.txt'.format(num_path) #algorithm.execute(dump_request_filename, dump_reply_filename) algorithm.execute() response_list = algorithm.json_reply.get('response-list', []) for response in response_list: service_id = response['serviceId'] service_key = (service_id['contextId'], service_id['service_uuid']) disjoint_paths_service = disjoint_paths.setdefault(service_key, list()) json_reply_service = self.json_reply.setdefault(service_key, list()) no_path_issue = response.get('noPath', {}).get('issue') if no_path_issue is not None: disjoint_paths_service.append(None) json_reply_service.append(None) continue path_endpoints = response['path'][0]['devices'] path_links = list() path_link_ids = set() for endpoint in path_endpoints: device_uuid = endpoint['device_id'] endpoint_uuid = endpoint['endpoint_uuid'] item = algorithm.endpoint_to_link_dict.get((device_uuid, endpoint_uuid)) if item is None: MSG = 'Link for Endpoint({:s}, {:s}) not found' self.logger.warning(MSG.format(device_uuid, endpoint_uuid)) continue json_link,_ = item json_link_id = json_link['link_Id'] if len(path_links) == 0 or path_links[-1]['link_Id'] != json_link_id: path_links.append(json_link) path_link_ids.add(json_link_id) self.logger.info('path_links = {:s}'.format(str(path_links))) disjoint_paths_service.append(path_links) new_link_list = list(filter(lambda l: l['link_Id'] not in path_link_ids, algorithm.link_list)) self.logger.info('algorithm.link_list = {:s}'.format(str(algorithm.link_list))) self.logger.info('new_link_list = {:s}'.format(str(new_link_list))) algorithm.link_list = new_link_list # TODO: find used links and remove them from algorithm.link_list # TODO: compose disjoint path found json_reply_service.append(path_endpoints) algorithm.link_list = self.remove_traversed_links(algorithm.link_list, path_endpoints) self.logger.info('self.json_reply = {:s}'.format(str(self.json_reply))) self.logger.info('disjoint_paths = {:s}'.format(str(disjoint_paths))) self.json_reply = {} def get_reply(self) -> PathCompReply: reply = PathCompReply() for service_key,paths in self.json_reply.items(): grpc_service = self.add_service_to_reply(reply, service_key[0], service_key[1]) for path_endpoints in paths: if path_endpoints is None: continue grpc_connection = self.add_connection_to_reply(reply, grpc_service) self.add_path_to_connection(grpc_connection, path_endpoints) return reply src/pathcomp/frontend/service/algorithms/_Algorithm.py +36 −27 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ import json, logging, requests, uuid from typing import Dict, List, Optional, Tuple from common.proto.context_pb2 import Device, DeviceList, EndPointId, Link, LinkList, Service from common.proto.context_pb2 import Connection, Device, DeviceList, EndPointId, Link, LinkList, Service from common.proto.pathcomp_pb2 import PathCompReply, PathCompRequest from common.tools.grpc.Tools import grpc_message_to_json_string from pathcomp.frontend.Config import BACKEND_URL Loading @@ -32,13 +32,13 @@ class _Algorithm: self.algorithm_id = algorithm_id self.sync_paths = sync_paths self.device_list : List[Device] = list() self.device_list : List[Dict] = list() self.device_dict : Dict[str, Tuple[Dict, Device]] = dict() self.endpoint_dict : Dict[str, Dict[str, Tuple[Dict, EndPointId]]] = dict() self.link_list : List[Link] = list() self.link_list : List[Dict] = list() self.link_dict : Dict[str, Tuple[Dict, Link]] = dict() self.endpoint_to_link_dict : Dict[Tuple[str, str], Tuple[Dict, Link]] = dict() self.service_list : List[Service] = list() self.service_list : List[Dict] = list() self.service_dict : Dict[Tuple[str, str], Tuple[Dict, Service]] = dict() def add_devices(self, grpc_devices : DeviceList) -> None: Loading Loading @@ -105,15 +105,24 @@ class _Algorithm: self.json_reply = reply.json() def get_reply(self) -> PathCompReply: response_list = self.json_reply.get('response-list', []) reply = PathCompReply() for response in response_list: service_id = response['serviceId'] service_key = (service_id['contextId'], service_id['service_uuid']) def add_path_to_connection(self, connection : Connection, path_endpoints : List[Dict]) -> None: for endpoint in path_endpoints: device_uuid = endpoint['device_id'] endpoint_uuid = endpoint['endpoint_uuid'] endpoint_id = connection.path_hops_endpoint_ids.add() endpoint_id.CopyFrom(self.endpoint_dict[device_uuid][endpoint_uuid][1]) def add_connection_to_reply(self, reply : PathCompReply, service : Service) -> Connection: connection = reply.connections.add() connection.connection_id.connection_uuid.uuid = str(uuid.uuid4()) connection.service_id.CopyFrom(service.service_id) return connection def add_service_to_reply(self, reply : PathCompReply, context_uuid : str, service_uuid : str) -> Service: service_key = (context_uuid, service_uuid) tuple_service = self.service_dict.get(service_key) if tuple_service is None: raise Exception('ServiceKey({:s}) not found'.format(str(service_key))) json_service, grpc_service = tuple_service _, grpc_service = tuple_service # TODO: implement support for multi-point services service_endpoint_ids = grpc_service.service_endpoint_ids Loading @@ -122,9 +131,14 @@ class _Algorithm: service = reply.services.add() service.CopyFrom(grpc_service) connection = reply.connections.add() connection.connection_id.connection_uuid.uuid = str(uuid.uuid4()) connection.service_id.CopyFrom(service.service_id) return grpc_service def get_reply(self) -> PathCompReply: response_list = self.json_reply.get('response-list', []) reply = PathCompReply() for response in response_list: service_id = response['serviceId'] grpc_service = self.add_service_to_reply(reply, service_id['contextId'], service_id['service_uuid']) no_path_issue = response.get('noPath', {}).get('issue') if no_path_issue is not None: Loading @@ -132,9 +146,10 @@ class _Algorithm: # no_path_issue == 1 => no path due to a constraint continue service_paths = response['path'] for service_path in response['path']: grpc_connection = self.add_connection_to_reply(reply, grpc_service) self.add_path_to_connection(grpc_connection, service_path['devices']) for service_path in service_paths: # ... "path-capacity": {"total-size": {"value": 200, "unit": 0}}, # ... "path-latency": {"fixed-latency-characteristic": "10.000000"}, # ... "path-cost": {"cost-name": "", "cost-value": "5.000000", "cost-algorithm": "0.000000"}, Loading @@ -147,10 +162,4 @@ class _Algorithm: #path_cost_value = path_cost['cost-value'] #path_cost_algorithm = path_cost['cost-algorithm'] path_endpoints = service_path['devices'] for endpoint in path_endpoints: device_uuid = endpoint['device_id'] endpoint_uuid = endpoint['endpoint_uuid'] endpoint_id = connection.path_hops_endpoint_ids.add() endpoint_id.CopyFrom(self.endpoint_dict[device_uuid][endpoint_uuid][1]) return reply src/pathcomp/misc/example-results-kdisjointpaths.json 0 → 100644 +73 −0 Original line number Diff line number Diff line { "connections": [ { "connection_id": {"connection_uuid": {"uuid": "d8cb463a-77c4-4149-80fc-32c4842a191d"}}, "path_hops_endpoint_ids": [ {"device_id": {"device_uuid": {"uuid": "DC1-GW"}}, "endpoint_uuid": {"uuid": "int"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "DC1"}}}, {"device_id": {"device_uuid": {"uuid": "DC1-GW"}}, "endpoint_uuid": {"uuid": "eth1"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "DC1"}}}, {"device_id": {"device_uuid": {"uuid": "CS1-GW1"}}, "endpoint_uuid": {"uuid": "200"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "CS1"}}}, {"device_id": {"device_uuid": {"uuid": "TN-R2"}}, "endpoint_uuid": {"uuid": "1"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "TN"}}}, {"device_id": {"device_uuid": {"uuid": "TN-R3"}}, "endpoint_uuid": {"uuid": "100"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "TN"}}}, {"device_id": {"device_uuid": {"uuid": "CS2-GW1"}}, "endpoint_uuid": {"uuid": "1000"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "CS2"}}}, {"device_id": {"device_uuid": {"uuid": "DC2-GW"}}, "endpoint_uuid": {"uuid": "int"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "DC2"}}} ], "service_id": { "context_id": {"context_uuid": {"uuid": "admin"}}, "service_uuid": {"uuid": "svc:DC1-GW/int==DC2-GW/int"} }, "sub_service_ids": [] }, { "connection_id": {"connection_uuid": {"uuid": "9f7c5075-0736-4d2a-8435-b8e8c37fa6ea"}}, "path_hops_endpoint_ids": [ {"device_id": {"device_uuid": {"uuid": "DC1-GW"}}, "endpoint_uuid": {"uuid": "int"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "DC1"}}}, {"device_id": {"device_uuid": {"uuid": "DC1-GW"}}, "endpoint_uuid": {"uuid": "eth2"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "DC1"}}}, {"device_id": {"device_uuid": {"uuid": "CS1-GW2"}}, "endpoint_uuid": {"uuid": "200"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "CS1"}}}, {"device_id": {"device_uuid": {"uuid": "TN-R1"}}, "endpoint_uuid": {"uuid": "3"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "TN"}}}, {"device_id": {"device_uuid": {"uuid": "TN-R3"}}, "endpoint_uuid": {"uuid": "200"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "TN"}}}, {"device_id": {"device_uuid": {"uuid": "CS2-GW2"}}, "endpoint_uuid": {"uuid": "1000"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "CS2"}}}, {"device_id": {"device_uuid": {"uuid": "DC2-GW"}}, "endpoint_uuid": {"uuid": "int"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "DC2"}}} ], "service_id": { "context_id": {"context_uuid": {"uuid": "admin"}}, "service_uuid": {"uuid": "svc:DC1-GW/int==DC2-GW/int"} }, "sub_service_ids": [] } ], "services": [ { "service_id": { "context_id": {"context_uuid": {"uuid": "admin"}}, "service_uuid": {"uuid": "svc:DC1-GW/int==DC2-GW/int"} }, "service_type": "SERVICETYPE_L3NM", "service_endpoint_ids": [ {"device_id": {"device_uuid": {"uuid": "DC1-GW"}}, "endpoint_uuid": {"uuid": "int"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "DC1"}}}, {"device_id": {"device_uuid": {"uuid": "DC2-GW"}}, "endpoint_uuid": {"uuid": "int"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "DC2"}}} ], "service_status": {"service_status": "SERVICESTATUS_PLANNED"}, "service_constraints": [ {"custom": {"constraint_type": "bandwidth[gbps]", "constraint_value": "10.0"}}, {"custom": {"constraint_type": "latency[ms]", "constraint_value": "12.0"}} ], "service_config": {"config_rules": []} } ] } No newline at end of file src/pathcomp/test-commands.sh→src/pathcomp/misc/test-commands.sh +2 −0 Original line number Diff line number Diff line Loading @@ -29,3 +29,5 @@ docker network rm teraflowbridge docker images --filter="dangling=true" --quiet | xargs -r docker rmi docker exec -i pathcomp bash -c "pytest --log-level=INFO --verbose pathcomp/tests/test_unitary.py" ./scripts/run_tests_locally-pathcomp-frontend.sh Loading
src/pathcomp/frontend/service/algorithms/KDisjointPathAlgorithm.py +53 −33 Original line number Diff line number Diff line Loading @@ -13,7 +13,8 @@ # limitations under the License. import copy from typing import Optional from typing import Dict, List, Optional, Set, Tuple from common.proto.context_pb2 import Link from common.proto.pathcomp_pb2 import Algorithm_KDisjointPath, Algorithm_KShortestPath, PathCompReply from ._Algorithm import _Algorithm from .KShortestPathAlgorithm import KShortestPathAlgorithm Loading @@ -23,6 +24,36 @@ class KDisjointPathAlgorithm(_Algorithm): super().__init__('KDP', False, class_name=class_name) self.num_disjoint = algorithm.num_disjoint def get_link_from_endpoint(self, endpoint : Dict) -> Tuple[Dict, Link]: device_uuid = endpoint['device_id'] endpoint_uuid = endpoint['endpoint_uuid'] item = self.endpoint_to_link_dict.get((device_uuid, endpoint_uuid)) if item is None: MSG = 'Link for Endpoint({:s}, {:s}) not found' self.logger.warning(MSG.format(device_uuid, endpoint_uuid)) return None return item def path_to_links(self, path_endpoints : List[Dict]) -> Tuple[List[Dict], Set[str]]: path_links = list() path_link_ids = set() for endpoint in path_endpoints: link_tuple = self.get_link_from_endpoint(endpoint) if link_tuple is None: continue json_link,_ = link_tuple json_link_id = json_link['link_Id'] if len(path_links) == 0 or path_links[-1]['link_Id'] != json_link_id: path_links.append(json_link) path_link_ids.add(json_link_id) return path_links, path_link_ids def remove_traversed_links(self, link_list : List[Dict], path_endpoints : List[Dict]): _, path_link_ids = self.path_to_links(path_endpoints) new_link_list = list(filter(lambda l: l['link_Id'] not in path_link_ids, link_list)) self.logger.info('cur_link_list = {:s}'.format(str(link_list))) self.logger.info('new_link_list = {:s}'.format(str(new_link_list))) return new_link_list def execute(self, dump_request_filename: Optional[str] = None, dump_reply_filename: Optional[str] = None) -> None: algorithm = KShortestPathAlgorithm(Algorithm_KShortestPath(k_inspection=0, k_return=1)) algorithm.sync_paths = True Loading @@ -35,49 +66,38 @@ class KDisjointPathAlgorithm(_Algorithm): algorithm.service_list = self.service_list algorithm.service_dict = self.service_dict disjoint_paths = dict() Path = List[Dict] Path_NoPath = Optional[Path] # None = no path, list = path self.json_reply : Dict[Tuple[str, str], List[Path_NoPath]] = dict() for num_path in range(self.num_disjoint): algorithm.execute('ksp-{:d}-request.json'.format(num_path), 'ksp-{:d}-reply.txt'.format(num_path)) #dump_request_filename = 'ksp-{:d}-request.json'.format(num_path) #dump_reply_filename = 'ksp-{:d}-reply.txt'.format(num_path) #algorithm.execute(dump_request_filename, dump_reply_filename) algorithm.execute() response_list = algorithm.json_reply.get('response-list', []) for response in response_list: service_id = response['serviceId'] service_key = (service_id['contextId'], service_id['service_uuid']) disjoint_paths_service = disjoint_paths.setdefault(service_key, list()) json_reply_service = self.json_reply.setdefault(service_key, list()) no_path_issue = response.get('noPath', {}).get('issue') if no_path_issue is not None: disjoint_paths_service.append(None) json_reply_service.append(None) continue path_endpoints = response['path'][0]['devices'] path_links = list() path_link_ids = set() for endpoint in path_endpoints: device_uuid = endpoint['device_id'] endpoint_uuid = endpoint['endpoint_uuid'] item = algorithm.endpoint_to_link_dict.get((device_uuid, endpoint_uuid)) if item is None: MSG = 'Link for Endpoint({:s}, {:s}) not found' self.logger.warning(MSG.format(device_uuid, endpoint_uuid)) continue json_link,_ = item json_link_id = json_link['link_Id'] if len(path_links) == 0 or path_links[-1]['link_Id'] != json_link_id: path_links.append(json_link) path_link_ids.add(json_link_id) self.logger.info('path_links = {:s}'.format(str(path_links))) disjoint_paths_service.append(path_links) new_link_list = list(filter(lambda l: l['link_Id'] not in path_link_ids, algorithm.link_list)) self.logger.info('algorithm.link_list = {:s}'.format(str(algorithm.link_list))) self.logger.info('new_link_list = {:s}'.format(str(new_link_list))) algorithm.link_list = new_link_list # TODO: find used links and remove them from algorithm.link_list # TODO: compose disjoint path found json_reply_service.append(path_endpoints) algorithm.link_list = self.remove_traversed_links(algorithm.link_list, path_endpoints) self.logger.info('self.json_reply = {:s}'.format(str(self.json_reply))) self.logger.info('disjoint_paths = {:s}'.format(str(disjoint_paths))) self.json_reply = {} def get_reply(self) -> PathCompReply: reply = PathCompReply() for service_key,paths in self.json_reply.items(): grpc_service = self.add_service_to_reply(reply, service_key[0], service_key[1]) for path_endpoints in paths: if path_endpoints is None: continue grpc_connection = self.add_connection_to_reply(reply, grpc_service) self.add_path_to_connection(grpc_connection, path_endpoints) return reply
src/pathcomp/frontend/service/algorithms/_Algorithm.py +36 −27 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ import json, logging, requests, uuid from typing import Dict, List, Optional, Tuple from common.proto.context_pb2 import Device, DeviceList, EndPointId, Link, LinkList, Service from common.proto.context_pb2 import Connection, Device, DeviceList, EndPointId, Link, LinkList, Service from common.proto.pathcomp_pb2 import PathCompReply, PathCompRequest from common.tools.grpc.Tools import grpc_message_to_json_string from pathcomp.frontend.Config import BACKEND_URL Loading @@ -32,13 +32,13 @@ class _Algorithm: self.algorithm_id = algorithm_id self.sync_paths = sync_paths self.device_list : List[Device] = list() self.device_list : List[Dict] = list() self.device_dict : Dict[str, Tuple[Dict, Device]] = dict() self.endpoint_dict : Dict[str, Dict[str, Tuple[Dict, EndPointId]]] = dict() self.link_list : List[Link] = list() self.link_list : List[Dict] = list() self.link_dict : Dict[str, Tuple[Dict, Link]] = dict() self.endpoint_to_link_dict : Dict[Tuple[str, str], Tuple[Dict, Link]] = dict() self.service_list : List[Service] = list() self.service_list : List[Dict] = list() self.service_dict : Dict[Tuple[str, str], Tuple[Dict, Service]] = dict() def add_devices(self, grpc_devices : DeviceList) -> None: Loading Loading @@ -105,15 +105,24 @@ class _Algorithm: self.json_reply = reply.json() def get_reply(self) -> PathCompReply: response_list = self.json_reply.get('response-list', []) reply = PathCompReply() for response in response_list: service_id = response['serviceId'] service_key = (service_id['contextId'], service_id['service_uuid']) def add_path_to_connection(self, connection : Connection, path_endpoints : List[Dict]) -> None: for endpoint in path_endpoints: device_uuid = endpoint['device_id'] endpoint_uuid = endpoint['endpoint_uuid'] endpoint_id = connection.path_hops_endpoint_ids.add() endpoint_id.CopyFrom(self.endpoint_dict[device_uuid][endpoint_uuid][1]) def add_connection_to_reply(self, reply : PathCompReply, service : Service) -> Connection: connection = reply.connections.add() connection.connection_id.connection_uuid.uuid = str(uuid.uuid4()) connection.service_id.CopyFrom(service.service_id) return connection def add_service_to_reply(self, reply : PathCompReply, context_uuid : str, service_uuid : str) -> Service: service_key = (context_uuid, service_uuid) tuple_service = self.service_dict.get(service_key) if tuple_service is None: raise Exception('ServiceKey({:s}) not found'.format(str(service_key))) json_service, grpc_service = tuple_service _, grpc_service = tuple_service # TODO: implement support for multi-point services service_endpoint_ids = grpc_service.service_endpoint_ids Loading @@ -122,9 +131,14 @@ class _Algorithm: service = reply.services.add() service.CopyFrom(grpc_service) connection = reply.connections.add() connection.connection_id.connection_uuid.uuid = str(uuid.uuid4()) connection.service_id.CopyFrom(service.service_id) return grpc_service def get_reply(self) -> PathCompReply: response_list = self.json_reply.get('response-list', []) reply = PathCompReply() for response in response_list: service_id = response['serviceId'] grpc_service = self.add_service_to_reply(reply, service_id['contextId'], service_id['service_uuid']) no_path_issue = response.get('noPath', {}).get('issue') if no_path_issue is not None: Loading @@ -132,9 +146,10 @@ class _Algorithm: # no_path_issue == 1 => no path due to a constraint continue service_paths = response['path'] for service_path in response['path']: grpc_connection = self.add_connection_to_reply(reply, grpc_service) self.add_path_to_connection(grpc_connection, service_path['devices']) for service_path in service_paths: # ... "path-capacity": {"total-size": {"value": 200, "unit": 0}}, # ... "path-latency": {"fixed-latency-characteristic": "10.000000"}, # ... "path-cost": {"cost-name": "", "cost-value": "5.000000", "cost-algorithm": "0.000000"}, Loading @@ -147,10 +162,4 @@ class _Algorithm: #path_cost_value = path_cost['cost-value'] #path_cost_algorithm = path_cost['cost-algorithm'] path_endpoints = service_path['devices'] for endpoint in path_endpoints: device_uuid = endpoint['device_id'] endpoint_uuid = endpoint['endpoint_uuid'] endpoint_id = connection.path_hops_endpoint_ids.add() endpoint_id.CopyFrom(self.endpoint_dict[device_uuid][endpoint_uuid][1]) return reply
src/pathcomp/misc/example-results-kdisjointpaths.json 0 → 100644 +73 −0 Original line number Diff line number Diff line { "connections": [ { "connection_id": {"connection_uuid": {"uuid": "d8cb463a-77c4-4149-80fc-32c4842a191d"}}, "path_hops_endpoint_ids": [ {"device_id": {"device_uuid": {"uuid": "DC1-GW"}}, "endpoint_uuid": {"uuid": "int"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "DC1"}}}, {"device_id": {"device_uuid": {"uuid": "DC1-GW"}}, "endpoint_uuid": {"uuid": "eth1"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "DC1"}}}, {"device_id": {"device_uuid": {"uuid": "CS1-GW1"}}, "endpoint_uuid": {"uuid": "200"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "CS1"}}}, {"device_id": {"device_uuid": {"uuid": "TN-R2"}}, "endpoint_uuid": {"uuid": "1"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "TN"}}}, {"device_id": {"device_uuid": {"uuid": "TN-R3"}}, "endpoint_uuid": {"uuid": "100"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "TN"}}}, {"device_id": {"device_uuid": {"uuid": "CS2-GW1"}}, "endpoint_uuid": {"uuid": "1000"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "CS2"}}}, {"device_id": {"device_uuid": {"uuid": "DC2-GW"}}, "endpoint_uuid": {"uuid": "int"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "DC2"}}} ], "service_id": { "context_id": {"context_uuid": {"uuid": "admin"}}, "service_uuid": {"uuid": "svc:DC1-GW/int==DC2-GW/int"} }, "sub_service_ids": [] }, { "connection_id": {"connection_uuid": {"uuid": "9f7c5075-0736-4d2a-8435-b8e8c37fa6ea"}}, "path_hops_endpoint_ids": [ {"device_id": {"device_uuid": {"uuid": "DC1-GW"}}, "endpoint_uuid": {"uuid": "int"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "DC1"}}}, {"device_id": {"device_uuid": {"uuid": "DC1-GW"}}, "endpoint_uuid": {"uuid": "eth2"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "DC1"}}}, {"device_id": {"device_uuid": {"uuid": "CS1-GW2"}}, "endpoint_uuid": {"uuid": "200"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "CS1"}}}, {"device_id": {"device_uuid": {"uuid": "TN-R1"}}, "endpoint_uuid": {"uuid": "3"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "TN"}}}, {"device_id": {"device_uuid": {"uuid": "TN-R3"}}, "endpoint_uuid": {"uuid": "200"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "TN"}}}, {"device_id": {"device_uuid": {"uuid": "CS2-GW2"}}, "endpoint_uuid": {"uuid": "1000"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "CS2"}}}, {"device_id": {"device_uuid": {"uuid": "DC2-GW"}}, "endpoint_uuid": {"uuid": "int"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "DC2"}}} ], "service_id": { "context_id": {"context_uuid": {"uuid": "admin"}}, "service_uuid": {"uuid": "svc:DC1-GW/int==DC2-GW/int"} }, "sub_service_ids": [] } ], "services": [ { "service_id": { "context_id": {"context_uuid": {"uuid": "admin"}}, "service_uuid": {"uuid": "svc:DC1-GW/int==DC2-GW/int"} }, "service_type": "SERVICETYPE_L3NM", "service_endpoint_ids": [ {"device_id": {"device_uuid": {"uuid": "DC1-GW"}}, "endpoint_uuid": {"uuid": "int"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "DC1"}}}, {"device_id": {"device_uuid": {"uuid": "DC2-GW"}}, "endpoint_uuid": {"uuid": "int"}, "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "DC2"}}} ], "service_status": {"service_status": "SERVICESTATUS_PLANNED"}, "service_constraints": [ {"custom": {"constraint_type": "bandwidth[gbps]", "constraint_value": "10.0"}}, {"custom": {"constraint_type": "latency[ms]", "constraint_value": "12.0"}} ], "service_config": {"config_rules": []} } ] } No newline at end of file
src/pathcomp/test-commands.sh→src/pathcomp/misc/test-commands.sh +2 −0 Original line number Diff line number Diff line Loading @@ -29,3 +29,5 @@ docker network rm teraflowbridge docker images --filter="dangling=true" --quiet | xargs -r docker rmi docker exec -i pathcomp bash -c "pytest --log-level=INFO --verbose pathcomp/tests/test_unitary.py" ./scripts/run_tests_locally-pathcomp-frontend.sh