diff --git a/scripts/run_tests_locally-pathcomp.sh b/scripts/run_tests_locally-pathcomp-frontend.sh similarity index 95% rename from scripts/run_tests_locally-pathcomp.sh rename to scripts/run_tests_locally-pathcomp-frontend.sh index f56f47a8b592939243a2ec5d9fd95d89046582d1..1bcf5e7f3792622622f9e59978fddbf11c54e492 100755 --- a/scripts/run_tests_locally-pathcomp.sh +++ b/scripts/run_tests_locally-pathcomp-frontend.sh @@ -25,4 +25,4 @@ RCFILE=$PROJECTDIR/coverage/.coveragerc #-o log_cli=true -o log_file=service.log -o log_file_level=DEBUG coverage run --rcfile=$RCFILE --append -m pytest --log-level=INFO --verbose \ - pathcomp/tests/test_unitary.py + pathcomp/frontend/tests/test_unitary.py diff --git a/src/pathcomp/.gitlab-ci.yml b/src/pathcomp/.gitlab-ci.yml index 671e1dc035bf8d5ebe497dfef7db0f995eaa5f84..2ef7ebf054a39964b18dfd3af1c066623235c30e 100644 --- a/src/pathcomp/.gitlab-ci.yml +++ b/src/pathcomp/.gitlab-ci.yml @@ -13,15 +13,15 @@ # limitations under the License. # Build, tag and push the Docker image to the GitLab registry -build pathcomp: +build pathcomp_frontend: variables: - IMAGE_NAME: 'pathcomp' # name of the microservice + IMAGE_NAME: 'pathcomp_frontend' # name of the microservice IMAGE_TAG: 'latest' # tag of the container image (production, development, etc) stage: build before_script: - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . + - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/frontend/Dockerfile . - docker tag "$IMAGE_NAME:$IMAGE_TAG" "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG" - docker push "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG" after_script: @@ -32,9 +32,34 @@ build pathcomp: - changes: - src/common/**/*.py - proto/*.proto - - src/$IMAGE_NAME/**/*.{py,in,yml} - - src/$IMAGE_NAME/Dockerfile - - src/$IMAGE_NAME/tests/*.py + - src/$IMAGE_NAME/frontend/**/*.{py,in,yml} + - src/$IMAGE_NAME/frontend/Dockerfile + - src/$IMAGE_NAME/frontend/tests/*.py + - manifests/${IMAGE_NAME}service.yaml + - .gitlab-ci.yml + +build pathcomp_backend: + variables: + IMAGE_NAME: 'pathcomp_backend' # name of the microservice + IMAGE_TAG: 'latest' # tag of the container image (production, development, etc) + stage: build + before_script: + - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY + script: + - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/backend/Dockerfile . + - docker tag "$IMAGE_NAME:$IMAGE_TAG" "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG" + - docker push "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG" + after_script: + - docker images --filter="dangling=true" --quiet | xargs -r docker rmi + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)' + - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"' + - changes: + - proto/*.proto + - src/$IMAGE_NAME/.gitlab-ci.yml + - src/$IMAGE_NAME/backend/**/*.{c,h,conf} + - src/$IMAGE_NAME/backend/Makefile + - src/$IMAGE_NAME/backend/Dockerfile - manifests/${IMAGE_NAME}service.yaml - .gitlab-ci.yml diff --git a/src/pathcomp/backend/Dockerfile-gdb b/src/pathcomp/backend/Dockerfile-gdb new file mode 100644 index 0000000000000000000000000000000000000000..13af33006504095204878b465bdee7f84f549d20 --- /dev/null +++ b/src/pathcomp/backend/Dockerfile-gdb @@ -0,0 +1,37 @@ +# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/) +# +# 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. + +# Multi-stage Docker image build + +# Stage 1 +FROM ubuntu:20.04 AS builder +ARG DEBIAN_FRONTEND=noninteractive + +# Install build software +RUN apt-get update -y && apt-get install build-essential libglib2.0-dev -y +RUN apt-get install gdb gdbserver -y + +# mkdir +RUN mkdir -p /var/teraflow + +# Define working directory +WORKDIR /var/teraflow + +# Copy every file in working directory +COPY src/pathcomp/backend/. ./ +RUN make + +EXPOSE 8081 + +ENTRYPOINT [ "gdb", "--args", "./pathComp", "config/pathcomp.conf", "pathcomp.log" ] diff --git a/src/pathcomp/frontend/Config.py b/src/pathcomp/frontend/Config.py index 9953c820575d42fa88351cc8de022d880ba96e6a..af7c277c553157a6d058815d7e6cb11cba5d169d 100644 --- a/src/pathcomp/frontend/Config.py +++ b/src/pathcomp/frontend/Config.py @@ -11,3 +11,7 @@ # 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. + +BACKEND_URL = 'http://{:s}:{:d}/pathComp/api/v1/compRoute' +BACKEND_HOST = '172.28.0.2' +BACKEND_PORT = 8081 diff --git a/src/pathcomp/frontend/Dockerfile b/src/pathcomp/frontend/Dockerfile index ec1ebbf06616233fb96acb4e54d3de24b8a016a4..0af022f128406f2a697ce01cefc48842cb7b134e 100644 --- a/src/pathcomp/frontend/Dockerfile +++ b/src/pathcomp/frontend/Dockerfile @@ -56,7 +56,7 @@ RUN find . -type f -exec sed -i -E 's/(import\ .*)_pb2/from . \1_pb2/g' {} \; # Create component sub-folders, get specific Python packages RUN mkdir -p /var/teraflow/pathcomp WORKDIR /var/teraflow/pathcomp -COPY src/pathcomp/requirements.in requirements.in +COPY src/pathcomp/frontend/requirements.in requirements.in RUN pip-compile --quiet --output-file=requirements.txt requirements.in RUN python3 -m pip install -r requirements.txt @@ -66,4 +66,4 @@ COPY src/context/. context/ COPY src/pathcomp/. pathcomp/ # Start the service -ENTRYPOINT ["python", "-m", "pathcomp.service"] +ENTRYPOINT ["python", "-m", "pathcomp.frontend.service"] diff --git a/src/pathcomp/frontend/example/command.txt b/src/pathcomp/frontend/example/command.txt new file mode 100644 index 0000000000000000000000000000000000000000..59002337f8efe1db607ebd724bb89287142e9d94 --- /dev/null +++ b/src/pathcomp/frontend/example/command.txt @@ -0,0 +1,4 @@ +curl -0 -v -X POST \ + -H "Expect:" -H "Content-Type: application/json" \ + http://172.17.0.2:8081/pathComp/api/v1/compRoute \ + -d @src/pathcomp/backend/test/inter_domain_test.txt diff --git a/src/pathcomp/frontend/example/reply.json b/src/pathcomp/frontend/example/reply.json new file mode 100644 index 0000000000000000000000000000000000000000..6bb4bef233d7eda6215a06d83a03f97901d8ad83 --- /dev/null +++ b/src/pathcomp/frontend/example/reply.json @@ -0,0 +1,92 @@ +{ + "response-list": [ + { + "serviceId": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "service_uuid": "651550d8-46a0-4f36-9fb9-21b8e4f1b8d2" + }, + "service_endpoints_ids": [ + { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa11", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa111" + }, + { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc33", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc331" + } + ], + "path": [ + { + "path-capacity": { + "total-size": { + "value": 200, + "unit": 0 + } + }, + "path-latency": { + "fixed-latency-characteristic": "8.000000" + }, + "path-cost": { + "cost-name": "", + "cost-value": "4.000000", + "cost-algorithm": "0.000000" + }, + "link": [ + { + "link_Id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaa1112", + "topology": [ + { + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + { + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + } + ] + }, + { + "link_Id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaa1214", + "topology": [ + { + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + { + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + } + ] + }, + { + "link_Id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaa1431", + "topology": [ + { + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + { + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + } + ] + }, + { + "link_Id": "cccccccc-cccc-cccc-cccc-cccccccc3133", + "topology": [ + { + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + { + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + } + ] + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/pathcomp/frontend/example/request.json b/src/pathcomp/frontend/example/request.json new file mode 100644 index 0000000000000000000000000000000000000000..a13f20f12fd9d181d0a21ffc737979cae23bf457 --- /dev/null +++ b/src/pathcomp/frontend/example/request.json @@ -0,0 +1,2474 @@ +{ + "serviceList": [ + { + "algId": "KSP", + "syncPaths": false, + "serviceId": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "service_uuid": "651550d8-46a0-4f36-9fb9-21b8e4f1b8d2" + }, + "serviceType": 1, + "service_endpoints_ids": [ + { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa11", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa111" + }, + { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc33", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc331" + } + ], + "service_constraints": [ + { + "constraint_type": "bandwidth", + "constraint_value": "100" + }, + { + "constraint_type": "latency", + "constraint_value": "20" + } + ], + "kPaths": 3 + } + ], + "deviceList": [ + { + "device_Id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa11", + "device_type": "L3", + "device_endpoints": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa11", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa111" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 4, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa11", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa112" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa11", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa113" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + } + } + ] + }, + { + "device_Id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa13", + "device_type": "L3", + "device_endpoints": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa13", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa132" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa13", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa133" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa13", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa134" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + } + } + ] + }, + { + "device_Id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa12", + "device_type": "L3", + "device_endpoints": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa12", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa122" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa12", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa123" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa12", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa124" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + } + } + ] + }, + { + "device_Id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa14", + "device_type": "L3", + "device_endpoints": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa14", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa142" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa14", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa143" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa14", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa141" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "inter-domain-plug-in": { + "plug-id-inter-domain-local-id": "a2", + "plug-id-inter-domain-remote-id": "c1" + } + } + ] + }, + { + "device_Id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa15", + "device_type": "L3", + "device_endpoints": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa15", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa151" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "inter-domain-plug-in": { + "plug-id-inter-domain-local-id": "a1", + "plug-id-inter-domain-remote-id": "b1" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa15", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa152" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa15", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa153" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + } + } + ] + }, + { + "device_Id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb21", + "device_type": "L3", + "device_endpoints": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + }, + "device_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb21", + "endpoint_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbb211" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "inter-domain-plug-in": { + "plug-id-inter-domain-local-id": "b1", + "plug-id-inter-domain-remote-id": "a1" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + }, + "device_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb21", + "endpoint_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbb212" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + }, + "device_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb21", + "endpoint_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbb213" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + } + } + ] + }, + { + "device_Id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb23", + "device_type": "L3", + "device_endpoints": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + }, + "device_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb23", + "endpoint_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbb231" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "inter-domain-plug-in": { + "plug-id-inter-domain-local-id": "b2", + "plug-id-inter-domain-remote-id": "c2" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + }, + "device_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb23", + "endpoint_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbb232" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + }, + "device_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb23", + "endpoint_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbb233" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + } + } + ] + }, + { + "device_Id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb24", + "device_type": "L3", + "device_endpoints": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + }, + "device_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb24", + "endpoint_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbb241" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "inter-domain-plug-in": { + "plug-id-inter-domain-local-id": "b4", + "plug-id-inter-domain-remote-id": "c3" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + }, + "device_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb24", + "endpoint_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbb242" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + }, + "device_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb24", + "endpoint_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbb243" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + } + } + ] + }, + { + "device_Id": "cccccccc-cccc-cccc-cccc-cccccccccc31", + "device_type": "L3", + "device_endpoints": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc31", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc311" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "inter-domain-plug-in": { + "plug-id-inter-domain-local-id": "c1", + "plug-id-inter-domain-remote-id": "a2" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc31", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc312" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc31", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc313" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + } + } + ] + }, + { + "device_Id": "cccccccc-cccc-cccc-cccc-cccccccccc32", + "device_type": "L3", + "device_endpoints": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc32", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc321" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "inter-domain-plug-in": { + "plug-id-inter-domain-local-id": "c2", + "plug-id-inter-domain-remote-id": "b2" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc32", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc322" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc32", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc323" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + } + } + ] + }, + { + "device_Id": "cccccccc-cccc-cccc-cccc-cccccccccc33", + "device_type": "L3", + "device_endpoints": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc33", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc331" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "inter-domain-plug-in": { + "plug-id-inter-domain-local-id": "c3", + "plug-id-inter-domain-remote-id": "b4" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc33", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc332" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc33", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc333" + }, + "endpoint_type": "termination", + "link_port_direction": 0, + "termination-direction": 0, + "termination-state": 0, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + } + } + ] + } + ], + "linkList": [ + { + "link_Id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaa1112", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa11", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa113" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa12", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa122" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaa1211", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa12", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa122" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa11", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa113" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaa1113", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa11", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa112" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa13", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa132" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaa1311", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa13", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa132" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa11", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa112" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaa1312", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa13", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa133" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa12", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa123" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaa1213", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa12", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa123" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa13", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa133" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaa1214", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa12", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa124" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa14", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa142" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaa1412", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa14", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa142" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa12", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa124" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaa1315", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa13", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa134" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa15", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa152" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaa1513", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa15", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa152" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa13", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa134" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaa1415", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa14", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa143" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa15", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa153" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaa1514", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa15", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa153" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa14", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa143" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaa1521", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa15", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa151" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + }, + "device_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb21", + "endpoint_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbb211" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbb2115", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + }, + "device_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb21", + "endpoint_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbb211" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa15", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa151" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaa1431", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa14", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa141" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc31", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc311" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "cccccccc-cccc-cccc-cccc-cccccccc3114", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc31", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc311" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + }, + "device_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaa14", + "endpoint_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaa141" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbb2124", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + }, + "device_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb21", + "endpoint_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbb212" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + }, + "device_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb24", + "endpoint_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbb242" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbb2421", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + }, + "device_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb24", + "endpoint_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbb242" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + }, + "device_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb21", + "endpoint_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbb212" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbb2123", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + }, + "device_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb21", + "endpoint_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbb213" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + }, + "device_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb23", + "endpoint_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbb233" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbb2321", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + }, + "device_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb23", + "endpoint_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbb233" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + }, + "device_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb21", + "endpoint_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbb213" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbb2324", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + }, + "device_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb23", + "endpoint_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbb232" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + }, + "device_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb24", + "endpoint_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbb243" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbb2424", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + }, + "device_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb24", + "endpoint_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbb243" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + }, + "device_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb23", + "endpoint_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbb232" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbb2332", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + }, + "device_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb23", + "endpoint_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbb231" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc32", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc321" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "cccccccc-cccc-cccc-cccc-cccccccc3223", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc32", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc321" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + }, + "device_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb23", + "endpoint_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbb231" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbb2433", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + }, + "device_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb24", + "endpoint_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbb241" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc34", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc331" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "cccccccc-cccc-cccc-cccc-cccccccc3324", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc33", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc331" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" + }, + "device_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbb24", + "endpoint_uuid": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbb241" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "cccccccc-cccc-cccc-cccc-cccccccc3132", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc31", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc312" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc32", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc323" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "cccccccc-cccc-cccc-cccc-cccccccc3231", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc32", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc323" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc31", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc312" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "cccccccc-cccc-cccc-cccc-cccccccc3133", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc31", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc313" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc33", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc333" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "cccccccc-cccc-cccc-cccc-cccccccc3331", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc33", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc333" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc31", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc313" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "cccccccc-cccc-cccc-cccc-cccccccc3233", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc32", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc322" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc33", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc332" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + }, + { + "link_Id": "cccccccc-cccc-cccc-cccc-cccccccc3332", + "link_endpoint_ids": [ + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc33", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc332" + } + }, + { + "endpoint_id": { + "topology_id": { + "contextId": "b55a05a5-ae2d-4ff3-85ca-97fac0c56f91", + "topology_uuid": "cccccccc-cccc-cccc-cccc-cccccccccccc" + }, + "device_id": "cccccccc-cccc-cccc-cccc-cccccccccc32", + "endpoint_uuid": "cccccccc-cccc-cccc-cccc-ccccccccc322" + } + } + ], + "forwarding_direction": 1, + "total-potential-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "available-capacity": { + "total-size": { + "value": 200, + "unit": 5 + } + }, + "cost-characteristics": { + "cost-name": "linkcost", + "cost-value": "1", + "cost-algorithm": "0" + }, + "latency-characteristics": { + "fixed-latency-characteristic": "2" + } + } + ] +} diff --git a/src/pathcomp/frontend/service/PathCompService.py b/src/pathcomp/frontend/service/PathCompService.py index 7fd9eab3ba8de53ddc5fdee018519126c44361f0..88dc5134754cc1b198a505ca9d1cd1f98f2ace22 100644 --- a/src/pathcomp/frontend/service/PathCompService.py +++ b/src/pathcomp/frontend/service/PathCompService.py @@ -15,7 +15,7 @@ from common.Constants import ServiceNameEnum from common.Settings import get_service_port_grpc from common.tools.service.GenericGrpcService import GenericGrpcService -from pathcomp.proto.pathcomp_pb2_grpc import add_PathCompServiceServicer_to_server +from common.proto.pathcomp_pb2_grpc import add_PathCompServiceServicer_to_server from .PathCompServiceServicerImpl import PathCompServiceServicerImpl class PathCompService(GenericGrpcService): diff --git a/src/pathcomp/frontend/service/PathCompServiceServicerImpl.py b/src/pathcomp/frontend/service/PathCompServiceServicerImpl.py index 239ab6ab5bbe8b6051115a8200cc1f6f304e75b5..2ec045c2755bd6d2079a4ee8ee96d4c3ad4cef36 100644 --- a/src/pathcomp/frontend/service/PathCompServiceServicerImpl.py +++ b/src/pathcomp/frontend/service/PathCompServiceServicerImpl.py @@ -12,14 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. +import grpc, json, logging, requests, uuid from typing import List -import grpc, logging, uuid from common.proto.context_pb2 import Connection, Empty, EndPointId from common.proto.pathcomp_pb2 import PathCompReply, PathCompRequest from common.proto.pathcomp_pb2_grpc import PathCompServiceServicer from common.rpc_method_wrapper.Decorator import create_metrics, safe_and_metered_rpc_method from common.tools.grpc.Tools import grpc_message_to_json, grpc_message_to_json_string from context.client.ContextClient import ContextClient +from pathcomp.frontend.Config import BACKEND_HOST, BACKEND_PORT, BACKEND_URL +from pathcomp.frontend.service.tools.ComposeRequest import compose_device, compose_link, compose_service LOGGER = logging.getLogger(__name__) @@ -36,28 +38,66 @@ class PathCompServiceServicerImpl(PathCompServiceServicer): def Compute(self, request : PathCompRequest, context : grpc.ServicerContext) -> PathCompReply: LOGGER.info('[Compute] begin ; request = {:s}'.format(grpc_message_to_json_string(request))) + algorithm = request.WhichOneof('algorithm') + if algorithm == 'shortest_path': + # no attributes + pass + elif algorithm == 'k_shortest_path': + k_inspection = request.k_shortest_path.k_inspection + k_return = request.k_shortest_path.k_return + else: + raise NotImplementedError('Unsupported Algorithm: {:s}'.format(str(algorithm))) + context_client = ContextClient() + algorithm = {'id': 'KSP', 'sync': False, 'k_paths': k_return} + service_list = [ + compose_service(grpc_service, algorithm) + for grpc_service in request.services + ] + # TODO: consider filtering resources - grpc_contexts = context_client.ListContexts(Empty()) + #grpc_contexts = context_client.ListContexts(Empty()) + #for grpc_context in grpc_contexts.contexts: + # # TODO: add context to request + # grpc_topologies = context_client.ListTopologies(grpc_context.context_id) + # for grpc_topology in grpc_topologies.topologies: #pylint: disable=unused-variable + # # TODO: add topology to request + # pass + grpc_devices = context_client.ListDevices(Empty()) + device_list = [ + compose_device(grpc_device) + for grpc_device in grpc_devices.devices + ] + grpc_links = context_client.ListLinks(Empty()) - for grpc_context in grpc_contexts.contexts: - # TODO: add context to request - grpc_topologies = context_client.ListTopologies(grpc_context.context_id) - for grpc_topology in grpc_topologies.topologies: #pylint: disable=unused-variable - # TODO: add topology to request - pass - for grpc_device in grpc_devices.devices: #pylint: disable=unused-variable - # TODO: add device to request - pass - for grpc_link in grpc_links.links: #pylint: disable=unused-variable - # TODO: add link to request - pass + link_list = [ + compose_link(grpc_link) + for grpc_link in grpc_links.links + ] + + request = { + 'serviceList': service_list, + 'deviceList' : device_list, + 'linkList' : link_list, + } + + #with open('pc-req.json', 'w', encoding='UTF-8') as f: + # f.write(json.dumps(request, sort_keys=True, indent=4)) + + backend_url = BACKEND_URL.format(BACKEND_HOST, BACKEND_PORT) + reply = requests.post(backend_url, json=request) + if reply.status_code not in {requests.codes.ok}: + raise Exception('Backend error({:s}) for request({:s})'.format( + str(reply.content.decode('UTF-8')), json.dumps(request, sort_keys=True))) + LOGGER.info('status_code={:s} reply={:s}'.format( + str(reply.status_code), str(reply.content.decode('UTF-8')))) + + reply = PathCompReply() - # TODO: issue path computation request # TODO: compose reply populating reply.services and reply.connections for service in request.services: diff --git a/src/pathcomp/frontend/service/tools/ComposeRequest.py b/src/pathcomp/frontend/service/tools/ComposeRequest.py new file mode 100644 index 0000000000000000000000000000000000000000..2cd4185f05abaa2221a20b8c2e61b96763ae49a5 --- /dev/null +++ b/src/pathcomp/frontend/service/tools/ComposeRequest.py @@ -0,0 +1,175 @@ +# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/) +# +# 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. + +from enum import IntEnum +from typing import Dict +from common.proto.context_pb2 import Constraint, Device, EndPointId, Link, Service, ServiceId, TopologyId +from common.tools.grpc.Tools import grpc_message_to_json_string + +class CapacityUnit(IntEnum): + TB = 0 + TBPS = 1 + GB = 2 + GBPS = 3 + MB = 4 + MBPS = 5 + KB = 6 + KBPS = 7 + GHZ = 8 + MHZ = 9 + +class LinkPortDirection(IntEnum): + BIDIRECTIONAL = 0 + INPUT = 1 + OUTPUT = 2 + UNKNOWN = 3 + +class TerminationDirection(IntEnum): + BIDIRECTIONAL = 0 + SINK = 1 + SOURCE = 2 + UNKNOWN = 3 + +class TerminationState(IntEnum): + CAN_NEVER_TERMINATE = 0 + NOT_TERMINATED = 1 + TERMINATED_SERVER_TO_CLIENT = 2 + TERMINATED_CLIENT_TO_SERVER = 3 + TERMINATED_BIDIRECTIONAL = 4 + PERMENANTLY_TERMINATED = 5 + TERMINATION_STATE_UNKNOWN = 6 + +class LinkForwardingDirection(IntEnum): + BIDIRECTIONAL = 0 + UNIDIRECTIONAL = 1 + UNKNOWN = 2 + +def compose_topology_id(topology_id : TopologyId) -> Dict: + context_uuid = topology_id.context_id.context_uuid.uuid + topology_uuid = topology_id.topology_uuid.uuid + return {'contextId': context_uuid, 'topology_uuid': topology_uuid} + +def compose_service_id(service_id : ServiceId) -> Dict: + context_uuid = service_id.context_id.context_uuid.uuid + service_uuid = service_id.service_uuid.uuid + return {'contextId': context_uuid, 'service_uuid': service_uuid} + +def compose_endpoint_id(endpoint_id : EndPointId) -> Dict: + topology_id = compose_topology_id(endpoint_id.topology_id) + device_uuid = endpoint_id.device_id.device_uuid.uuid + endpoint_uuid = endpoint_id.endpoint_uuid.uuid + return {'topology_id': topology_id, 'device_id': device_uuid, 'endpoint_uuid': endpoint_uuid} + +def compose_capacity(value : str, unit : str) -> Dict: + return {'total-size': {'value': value, 'unit': unit}} + +def compose_endpoint( + endpoint_id : Dict, endpoint_type : str, link_port_direction : int, termination_direction : int, + termination_state : int, total_potential_capacity : Dict, available_capacity : Dict +) -> Dict: + return { + 'endpoint_id': endpoint_id, 'endpoint_type': endpoint_type, 'link_port_direction': link_port_direction, + 'termination-direction': termination_direction, 'termination-state': termination_state, + 'total-potential-capacity': total_potential_capacity, 'available-capacity': available_capacity, + } + +def compose_cost_characteristics(cost_name : str, cost_value : str, cost_algorithm : str) -> Dict: + return {'cost-name': cost_name, 'cost-value': cost_value, 'cost-algorithm': cost_algorithm} + +def compose_latency_characteristics(fixed_latency_characteristic : str) -> Dict: + return {'fixed-latency-characteristic': fixed_latency_characteristic} + +def compose_constraint(constraint : Constraint) -> Dict: + if constraint.WhichOneof('constraint') != 'custom': + MSG = 'Constraint({:s}) not supported' + str_constraint = grpc_message_to_json_string(constraint) + raise NotImplementedError(MSG.format(str_constraint)) + constraint_type = constraint.custom.constraint_type + constraint_value = constraint.custom.constraint_value + return {'constraint_type': constraint_type, 'constraint_value': constraint_value} + +def compose_device(grpc_device : Device) -> Dict: + device_uuid = grpc_device.device_id.device_uuid.uuid + device_type = grpc_device.device_type + + endpoints = [] + for device_endpoint in grpc_device.device_endpoints: + endpoint_id = compose_endpoint_id(device_endpoint.endpoint_id) + endpoint_type = device_endpoint.endpoint_type + link_port_direction = LinkPortDirection.BIDIRECTIONAL.value + termination_direction = TerminationDirection.BIDIRECTIONAL.value + termination_state = TerminationState.TERMINATED_BIDIRECTIONAL.value + total_potential_capacity = compose_capacity(200, CapacityUnit.MBPS.value) + available_capacity = compose_capacity(200, CapacityUnit.MBPS.value) + endpoint = compose_endpoint( + endpoint_id, endpoint_type, link_port_direction, termination_direction, + termination_state, total_potential_capacity, available_capacity) + endpoints.append(endpoint) + + return {'device_Id': device_uuid, 'device_type': device_type, 'device_endpoints': endpoints} + +def compose_link(grpc_link : Link) -> Dict: + link_uuid = grpc_link.link_id.link_uuid.uuid + + endpoint_ids = [ + {'endpoint_id' : compose_endpoint_id(link_endpoint_id)} + for link_endpoint_id in grpc_link.link_endpoint_ids + ] + + forwarding_direction = LinkForwardingDirection.UNIDIRECTIONAL.value + total_potential_capacity = compose_capacity(200, CapacityUnit.MBPS.value) + available_capacity = compose_capacity(200, CapacityUnit.MBPS.value) + cost_characteristics = compose_cost_characteristics('linkcost', '1', '0') + latency_characteristics = compose_latency_characteristics('2') + + return { + 'link_Id': link_uuid, 'link_endpoint_ids': endpoint_ids, 'forwarding_direction': forwarding_direction, + 'total-potential-capacity': total_potential_capacity, 'available-capacity': available_capacity, + 'cost-characteristics': cost_characteristics, 'latency-characteristics': latency_characteristics, + } + +def compose_service(grpc_service : Service, algorithm : Dict) -> Dict: + service_id = compose_service_id(grpc_service.service_id) + service_type = grpc_service.service_type + + endpoint_ids = [ + compose_endpoint_id(service_endpoint_id) + for service_endpoint_id in grpc_service.service_endpoint_ids + ] + + constraints = [ + compose_constraint(service_constraint) + for service_constraint in grpc_service.service_constraints + ] + + # algorithm to be executed + algorithm_id = algorithm.get('id', 'SP') + + # if multiple services included in the request, prevent contention + # If true, services are computed one after the other and resources + # assigned to service i, are considered as used by services i+1..n + sync_paths = algorithm.get('sync', False) + + k_paths = algorithm.get('k_paths', 1) + + return { + 'serviceId': service_id, + 'serviceType': service_type, + 'service_endpoints_ids': endpoint_ids, + 'service_constraints': constraints, + + 'algId': algorithm_id, + 'syncPaths': sync_paths, + 'kPaths': k_paths, + } diff --git a/src/pathcomp/frontend/service/tools/__init__.py b/src/pathcomp/frontend/service/tools/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..70a33251242c51f49140e596b8208a19dd5245f7 --- /dev/null +++ b/src/pathcomp/frontend/service/tools/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/) +# +# 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. + diff --git a/src/pathcomp/frontend/tests/PrepareTestScenario.py b/src/pathcomp/frontend/tests/PrepareTestScenario.py index a4efcbdbfc0d311dfb120ab8124a9d2268660daf..9fb57e41b51f99b52bf71f7c6fc4d02d98ea100e 100644 --- a/src/pathcomp/frontend/tests/PrepareTestScenario.py +++ b/src/pathcomp/frontend/tests/PrepareTestScenario.py @@ -18,9 +18,9 @@ from common.Settings import ( ENVVAR_SUFIX_SERVICE_HOST, ENVVAR_SUFIX_SERVICE_PORT_GRPC, get_env_var_name, get_service_port_grpc) from context.client.ContextClient import ContextClient from device.client.DeviceClient import DeviceClient -from pathcomp.client.PathCompClient import PathCompClient -from pathcomp.service.PathCompService import PathCompService -from pathcomp.tests.MockService_Dependencies import MockService_Dependencies +from pathcomp.frontend.client.PathCompClient import PathCompClient +from pathcomp.frontend.service.PathCompService import PathCompService +from pathcomp.frontend.tests.MockService_Dependencies import MockService_Dependencies LOCAL_HOST = '127.0.0.1' MOCKSERVICE_PORT = 10000 diff --git a/src/pathcomp/frontend/tests/test_unitary.py b/src/pathcomp/frontend/tests/test_unitary.py index 23e574e0e1b512b7a69b69847ef5ef034bd2ca41..90d31bf0ab1f4fb41ddcfede5c4c308a88223c6d 100644 --- a/src/pathcomp/frontend/tests/test_unitary.py +++ b/src/pathcomp/frontend/tests/test_unitary.py @@ -18,7 +18,7 @@ from common.proto.pathcomp_pb2 import PathCompRequest from common.tools.grpc.Tools import grpc_message_to_json from context.client.ContextClient import ContextClient from device.client.DeviceClient import DeviceClient -from pathcomp.client.PathCompClient import PathCompClient +from pathcomp.frontend.client.PathCompClient import PathCompClient from .Objects import CONTEXTS, DEVICES, LINKS, SERVICES, TOPOLOGIES from .PrepareTestScenario import ( # pylint: disable=unused-import # be careful, order of symbols is important here! @@ -43,7 +43,11 @@ def test_request_service( request_services = SERVICES pathcomp_request = PathCompRequest(services=request_services) + pathcomp_request.k_shortest_path.k_inspection = 2 #pylint: disable=no-member + pathcomp_request.k_shortest_path.k_return = 2 #pylint: disable=no-member + pathcomp_reply = pathcomp_client.Compute(pathcomp_request) + pathcomp_reply = grpc_message_to_json(pathcomp_reply) reply_services = pathcomp_reply['services'] reply_connections = pathcomp_reply['connections'] diff --git a/src/pathcomp/test-deploy.sh b/src/pathcomp/test-deploy.sh new file mode 100644 index 0000000000000000000000000000000000000000..9414fabf79f0a9c6250599633bea8b5e039b8cde --- /dev/null +++ b/src/pathcomp/test-deploy.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/) +# +# 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. + +docker build -t "pathcomp-frontend:latest" -f ./src/pathcomp/frontend/Dockerfile . +docker build -t "pathcomp-backend:latest" -f ./src/pathcomp/backend/Dockerfile . +docker build -t "pathcomp-backend:gdb" -f ./src/pathcomp/backend/Dockerfile-gdb . + +docker network create --driver=bridge --subnet=172.28.0.0/24 --gateway=172.28.0.254 tfbr + +docker run --name pathcomp-frontend -d --network=tfbr --ip 172.28.0.1 pathcomp-frontend:latest +docker run --name pathcomp-backend -d --network=tfbr --ip 172.28.0.2 pathcomp-backend:latest + +docker rm -f pathcomp-frontend pathcomp-backend +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" diff --git a/src/pathcomp/test-run.sh b/src/pathcomp/test-run.sh new file mode 100644 index 0000000000000000000000000000000000000000..2c14511db83823a50a83f751d50fc3d3a4f4abab --- /dev/null +++ b/src/pathcomp/test-run.sh @@ -0,0 +1,29 @@ +#!/bin/bash +# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/) +# +# 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. + +docker build -t "pathcomp-frontend:latest" -f ./src/pathcomp/frontend/Dockerfile . +docker build -t "pathcomp-backend:latest" -f ./src/pathcomp/backend/Dockerfile . + +docker network create --driver=bridge --subnet=172.28.0.0/24 --gateway=172.28.0.254 tfbr + +docker run --name pathcomp-frontend -d --network=tfbr --ip 172.28.0.1 pathcomp-frontend:latest +docker run --name pathcomp-backend -d --network=tfbr --ip 172.28.0.2 pathcomp-backend:latest + +docker rm -f pathcomp-frontend pathcomp-backend +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"