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/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/service/PathCompServiceServicerImpl.py b/src/pathcomp/frontend/service/PathCompServiceServicerImpl.py index a86405195d0b0890c8558301516f7742e25aa6fc..2ec045c2755bd6d2079a4ee8ee96d4c3ad4cef36 100644 --- a/src/pathcomp/frontend/service/PathCompServiceServicerImpl.py +++ b/src/pathcomp/frontend/service/PathCompServiceServicerImpl.py @@ -84,6 +84,9 @@ class PathCompServiceServicerImpl(PathCompServiceServicer): '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}: diff --git a/src/pathcomp/frontend/service/tools/ComposeRequest.py b/src/pathcomp/frontend/service/tools/ComposeRequest.py index 0b8e5e13c0a68c7ffd1b1a0572dd8681aeb72b0b..2cd4185f05abaa2221a20b8c2e61b96763ae49a5 100644 --- a/src/pathcomp/frontend/service/tools/ComposeRequest.py +++ b/src/pathcomp/frontend/service/tools/ComposeRequest.py @@ -14,7 +14,7 @@ from enum import IntEnum from typing import Dict -from common.proto.context_pb2 import Device, Link, Service +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): @@ -55,13 +55,20 @@ class LinkForwardingDirection(IntEnum): UNIDIRECTIONAL = 1 UNKNOWN = 2 -def compose_topology_id(context_uuid : str, topology_uuid : str) -> Dict: +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(context_uuid : str, service_uuid : str) -> Dict: +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(topology_id : Dict, device_uuid : str, endpoint_uuid : str) -> Dict: +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: @@ -83,7 +90,13 @@ def compose_cost_characteristics(cost_name : str, cost_value : str, cost_algorit def compose_latency_characteristics(fixed_latency_characteristic : str) -> Dict: return {'fixed-latency-characteristic': fixed_latency_characteristic} -def compose_constraint(constraint_type : str, constraint_value : str) -> Dict: +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: @@ -92,14 +105,8 @@ def compose_device(grpc_device : Device) -> Dict: endpoints = [] for device_endpoint in grpc_device.device_endpoints: - context_uuid = device_endpoint.endpoint_id.topology_id.context_id.context_uuid.uuid - topology_uuid = device_endpoint.endpoint_id.topology_id.topology_uuid.uuid - endpoint_uuid = device_endpoint.endpoint_id.endpoint_uuid.uuid + endpoint_id = compose_endpoint_id(device_endpoint.endpoint_id) endpoint_type = device_endpoint.endpoint_type - - topology_id = compose_topology_id(context_uuid, topology_uuid) - endpoint_id = compose_endpoint_id(topology_id, device_uuid, endpoint_uuid) - link_port_direction = LinkPortDirection.BIDIRECTIONAL.value termination_direction = TerminationDirection.BIDIRECTIONAL.value termination_state = TerminationState.TERMINATED_BIDIRECTIONAL.value @@ -115,15 +122,10 @@ def compose_device(grpc_device : Device) -> Dict: def compose_link(grpc_link : Link) -> Dict: link_uuid = grpc_link.link_id.link_uuid.uuid - endpoint_ids = [] - for link_endpoint_id in grpc_link.link_endpoint_ids: - context_uuid = link_endpoint_id.topology_id.context_id.context_uuid.uuid - topology_uuid = link_endpoint_id.topology_id.topology_uuid.uuid - device_uuid = link_endpoint_id.device_id.device_uuid.uuid - endpoint_uuid = link_endpoint_id.endpoint_uuid.uuid - topology_id = compose_topology_id(context_uuid, topology_uuid) - endpoint_id = compose_endpoint_id(topology_id, device_uuid, endpoint_uuid) - endpoint_ids.append({'endpoint_id' : endpoint_id}) + 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) @@ -138,31 +140,18 @@ def compose_link(grpc_link : Link) -> Dict: } def compose_service(grpc_service : Service, algorithm : Dict) -> Dict: - context_uuid = grpc_service.service_id.service_id.context_id.context_uuid.uuid - service_uuid = grpc_service.service_id.service_id.service_uuid.uuid - - service_id = compose_service_id(context_uuid, service_uuid) + service_id = compose_service_id(grpc_service.service_id) service_type = grpc_service.service_type - endpoint_ids = [] - for service_endpoint_id in grpc_service.service_endpoint_ids: - context_uuid = service_endpoint_id.topology_id.context_id.context_uuid.uuid - topology_uuid = service_endpoint_id.topology_id.topology_uuid.uuid - device_uuid = service_endpoint_id.device_id.device_uuid.uuid - endpoint_uuid = service_endpoint_id.endpoint_uuid.uuid - topology_id = compose_topology_id(context_uuid, topology_uuid) - endpoint_id = compose_endpoint_id(topology_id, device_uuid, endpoint_uuid) - endpoint_ids.append(endpoint_id) - - constraints = [] - for service_constraint in grpc_service.service_constraints: - if service_constraint.WhichOneof('constraint') != 'custom': - MSG = 'Constraint({:s}) not supported' - str_constraint = grpc_message_to_json_string(service_constraint) - raise NotImplementedError(MSG.format(str_constraint)) - constraint_type = service_constraint.custom.constraint_type - constraint_value = service_constraint.custom.constraint_value - constraints.append(compose_constraint(constraint_type, constraint_value)) + 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') 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 43a4a577dbf0488dc400464175e0cc197d0e606a..90d31bf0ab1f4fb41ddcfede5c4c308a88223c6d 100644 --- a/src/pathcomp/frontend/tests/test_unitary.py +++ b/src/pathcomp/frontend/tests/test_unitary.py @@ -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 index 2c14511db83823a50a83f751d50fc3d3a4f4abab..9414fabf79f0a9c6250599633bea8b5e039b8cde 100644 --- a/src/pathcomp/test-deploy.sh +++ b/src/pathcomp/test-deploy.sh @@ -15,6 +15,7 @@ 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 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"