diff --git a/src/tests/eucnc24/.gitlab-ci.yml b/src/tests/eucnc24/.gitlab-ci.yml index 4ed3574a88e5900a209e96933b3906d873cd4e0e..6a9acaffd8a56f897972f7ab17058a98d027232e 100644 --- a/src/tests/eucnc24/.gitlab-ci.yml +++ b/src/tests/eucnc24/.gitlab-ci.yml @@ -112,12 +112,61 @@ end2end_test eucnc24: # done - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server - # Run end-to-end tests + # Run end-to-end test: onboard scenario - > docker run -t --name ${TEST_NAME} --network=host --volume "$PWD/tfs_runtime_env_vars.sh:/var/teraflow/tfs_runtime_env_vars.sh" --volume "$PWD/src/tests/${TEST_NAME}:/opt/results" - $CI_REGISTRY_IMAGE/${TEST_NAME}:latest + $CI_REGISTRY_IMAGE/${TEST_NAME}:latest ./run_onboarding.sh + + # Run end-to-end test: configure service TFS + - > + docker run -t --name ${TEST_NAME} --network=host + --volume "$PWD/tfs_runtime_env_vars.sh:/var/teraflow/tfs_runtime_env_vars.sh" + --volume "$PWD/src/tests/${TEST_NAME}:/opt/results" + $CI_REGISTRY_IMAGE/${TEST_NAME}:latest ./run_tfs_service_create.sh + + # Run end-to-end test: test connectivity with ping + - sudo containerlab exec --name eucnc24 --label clab-node-name=dc1 --cmd 'ping -n -c3 192.168.1.10' + - sudo containerlab exec --name eucnc24 --label clab-node-name=dc1 --cmd 'ping -n -c3 192.168.1.1' + - sudo containerlab exec --name eucnc24 --label clab-node-name=dc1 --cmd 'ping -n -c3 192.168.2.1' + - sudo containerlab exec --name eucnc24 --label clab-node-name=dc1 --cmd 'ping -n -c3 192.168.2.10' + - sudo containerlab exec --name eucnc24 --label clab-node-name=dc1 --cmd 'ping -n -c3 192.168.3.10' + + # Run end-to-end test: deconfigure service TFS + - > + docker run -t --name ${TEST_NAME} --network=host + --volume "$PWD/tfs_runtime_env_vars.sh:/var/teraflow/tfs_runtime_env_vars.sh" + --volume "$PWD/src/tests/${TEST_NAME}:/opt/results" + $CI_REGISTRY_IMAGE/${TEST_NAME}:latest ./run_tfs_service_remove.sh + + # Run end-to-end test: configure service IETF + - > + docker run -t --name ${TEST_NAME} --network=host + --volume "$PWD/tfs_runtime_env_vars.sh:/var/teraflow/tfs_runtime_env_vars.sh" + --volume "$PWD/src/tests/${TEST_NAME}:/opt/results" + $CI_REGISTRY_IMAGE/${TEST_NAME}:latest ./run_ietf_service_create.sh + + # Run end-to-end test: test connectivity with ping + - sudo containerlab exec --name eucnc24 --label clab-node-name=dc1 --cmd 'ping -n -c3 192.168.1.10' + - sudo containerlab exec --name eucnc24 --label clab-node-name=dc1 --cmd 'ping -n -c3 192.168.1.1' + - sudo containerlab exec --name eucnc24 --label clab-node-name=dc1 --cmd 'ping -n -c3 192.168.2.1' + - sudo containerlab exec --name eucnc24 --label clab-node-name=dc1 --cmd 'ping -n -c3 192.168.2.10' + - sudo containerlab exec --name eucnc24 --label clab-node-name=dc1 --cmd 'ping -n -c3 192.168.3.10' + + # Run end-to-end test: deconfigure service IETF + - > + docker run -t --name ${TEST_NAME} --network=host + --volume "$PWD/tfs_runtime_env_vars.sh:/var/teraflow/tfs_runtime_env_vars.sh" + --volume "$PWD/src/tests/${TEST_NAME}:/opt/results" + $CI_REGISTRY_IMAGE/${TEST_NAME}:latest ./run_ietf_service_remove.sh + + # Run end-to-end test: cleanup scenario + - > + docker run -t --name ${TEST_NAME} --network=host + --volume "$PWD/tfs_runtime_env_vars.sh:/var/teraflow/tfs_runtime_env_vars.sh" + --volume "$PWD/src/tests/${TEST_NAME}:/opt/results" + $CI_REGISTRY_IMAGE/${TEST_NAME}:latest ./run_cleanup.sh after_script: # Dump TeraFlowSDN component logs diff --git a/src/tests/eucnc24/Dockerfile b/src/tests/eucnc24/Dockerfile index c46100fff94ad0c08ea6da44f4efcddc997ba832..06c463ac6d2ade010c371921fe1bdc4bf172c0fc 100644 --- a/src/tests/eucnc24/Dockerfile +++ b/src/tests/eucnc24/Dockerfile @@ -75,17 +75,4 @@ COPY src/tests/*.py ./tests/ COPY src/tests/eucnc24/__init__.py ./tests/eucnc24/__init__.py COPY src/tests/eucnc24/data/. ./tests/eucnc24/data/ COPY src/tests/eucnc24/tests/. ./tests/eucnc24/tests/ - -RUN tee ./run_tests.sh <<EOF -#!/bin/bash -source /var/teraflow/tfs_runtime_env_vars.sh -export PYTHONPATH=/var/teraflow -pytest --verbose --log-level=INFO /var/teraflow/tests/eucnc24/tests/test_functional_bootstrap.py --junitxml=/opt/results/report_bootstrap.xml -pytest --verbose --log-level=INFO /var/teraflow/tests/eucnc24/tests/test_functional_service_tfs.py --junitxml=/opt/results/report_service_tfs.xml -pytest --verbose --log-level=INFO /var/teraflow/tests/eucnc24/tests/test_functional_service_ietf.py --junitxml=/opt/results/report_service_ietf.xml -pytest --verbose --log-level=INFO /var/teraflow/tests/eucnc24/tests/test_functional_cleanup.py --junitxml=/opt/results/report_cleanup.xml -EOF -RUN chmod ug+x ./run_tests.sh - -# Run the tests -ENTRYPOINT ["./run_tests.sh"] +COPY src/tests/eucnc24/scripts/. ./ diff --git a/src/tests/eucnc24/scripts/clab-cli-dc1.sh b/src/tests/eucnc24/deploy-scripts/clab-cli-dc1.sh similarity index 100% rename from src/tests/eucnc24/scripts/clab-cli-dc1.sh rename to src/tests/eucnc24/deploy-scripts/clab-cli-dc1.sh diff --git a/src/tests/eucnc24/scripts/clab-cli-dc2.sh b/src/tests/eucnc24/deploy-scripts/clab-cli-dc2.sh similarity index 100% rename from src/tests/eucnc24/scripts/clab-cli-dc2.sh rename to src/tests/eucnc24/deploy-scripts/clab-cli-dc2.sh diff --git a/src/tests/eucnc24/scripts/clab-cli-r1.sh b/src/tests/eucnc24/deploy-scripts/clab-cli-r1.sh similarity index 100% rename from src/tests/eucnc24/scripts/clab-cli-r1.sh rename to src/tests/eucnc24/deploy-scripts/clab-cli-r1.sh diff --git a/src/tests/eucnc24/scripts/clab-cli-r2.sh b/src/tests/eucnc24/deploy-scripts/clab-cli-r2.sh similarity index 100% rename from src/tests/eucnc24/scripts/clab-cli-r2.sh rename to src/tests/eucnc24/deploy-scripts/clab-cli-r2.sh diff --git a/src/tests/eucnc24/scripts/clab-cli-r3.sh b/src/tests/eucnc24/deploy-scripts/clab-cli-r3.sh similarity index 100% rename from src/tests/eucnc24/scripts/clab-cli-r3.sh rename to src/tests/eucnc24/deploy-scripts/clab-cli-r3.sh diff --git a/src/tests/eucnc24/scripts/clab-deploy.sh b/src/tests/eucnc24/deploy-scripts/clab-deploy.sh similarity index 100% rename from src/tests/eucnc24/scripts/clab-deploy.sh rename to src/tests/eucnc24/deploy-scripts/clab-deploy.sh diff --git a/src/tests/eucnc24/scripts/clab-destroy.sh b/src/tests/eucnc24/deploy-scripts/clab-destroy.sh similarity index 100% rename from src/tests/eucnc24/scripts/clab-destroy.sh rename to src/tests/eucnc24/deploy-scripts/clab-destroy.sh diff --git a/src/tests/eucnc24/scripts/clab-inspect.sh b/src/tests/eucnc24/deploy-scripts/clab-inspect.sh similarity index 100% rename from src/tests/eucnc24/scripts/clab-inspect.sh rename to src/tests/eucnc24/deploy-scripts/clab-inspect.sh diff --git a/src/tests/eucnc24/scripts/run-cleanup.sh b/src/tests/eucnc24/scripts/run-cleanup.sh new file mode 100644 index 0000000000000000000000000000000000000000..c4b5867b37e472ed1828598fc980c6467283cb73 --- /dev/null +++ b/src/tests/eucnc24/scripts/run-cleanup.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# +# 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. + +source /var/teraflow/tfs_runtime_env_vars.sh +export PYTHONPATH=/var/teraflow +pytest --verbose --log-level=INFO \ + --junitxml=/opt/results/report_cleanup.xml \ + /var/teraflow/tests/eucnc24/tests/test_functional_cleanup.py diff --git a/src/tests/eucnc24/scripts/run-onboarding.sh b/src/tests/eucnc24/scripts/run-onboarding.sh new file mode 100644 index 0000000000000000000000000000000000000000..b94ab6f79f3f60f1ce3567d3a0188c014f94d213 --- /dev/null +++ b/src/tests/eucnc24/scripts/run-onboarding.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# +# 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. + +source /var/teraflow/tfs_runtime_env_vars.sh +export PYTHONPATH=/var/teraflow +pytest --verbose --log-level=INFO \ + --junitxml=/opt/results/report_onboarding.xml \ + /var/teraflow/tests/eucnc24/tests/test_functional_onboarding.py diff --git a/src/tests/eucnc24/scripts/run-service-ietf-create.sh b/src/tests/eucnc24/scripts/run-service-ietf-create.sh new file mode 100644 index 0000000000000000000000000000000000000000..d2ec9eef51a1dbe311ddbc052d305ef0d8c92085 --- /dev/null +++ b/src/tests/eucnc24/scripts/run-service-ietf-create.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# +# 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. + +source /var/teraflow/tfs_runtime_env_vars.sh +export PYTHONPATH=/var/teraflow +pytest --verbose --log-level=INFO \ + --junitxml=/opt/results/report_service_ietf_create.xml \ + /var/teraflow/tests/eucnc24/tests/test_service_ietf_create.py diff --git a/src/tests/eucnc24/scripts/run-service-ietf-remove.sh b/src/tests/eucnc24/scripts/run-service-ietf-remove.sh new file mode 100644 index 0000000000000000000000000000000000000000..8c52636001fb8163b3a94fa0b229c7ab1264ab13 --- /dev/null +++ b/src/tests/eucnc24/scripts/run-service-ietf-remove.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# +# 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. + +source /var/teraflow/tfs_runtime_env_vars.sh +export PYTHONPATH=/var/teraflow +pytest --verbose --log-level=INFO \ + --junitxml=/opt/results/report_service_ietf_remove.xml \ + /var/teraflow/tests/eucnc24/tests/test_service_ietf_remove.py diff --git a/src/tests/eucnc24/scripts/run-service-tfs-create.sh b/src/tests/eucnc24/scripts/run-service-tfs-create.sh new file mode 100644 index 0000000000000000000000000000000000000000..5395f38b3ab82a11361a066f2d80b750e636b010 --- /dev/null +++ b/src/tests/eucnc24/scripts/run-service-tfs-create.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# +# 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. + +source /var/teraflow/tfs_runtime_env_vars.sh +export PYTHONPATH=/var/teraflow +pytest --verbose --log-level=INFO \ + --junitxml=/opt/results/report_service_tfs_create.xml \ + /var/teraflow/tests/eucnc24/tests/test_service_tfs_create.py diff --git a/src/tests/eucnc24/scripts/run-service-tfs-remove.sh b/src/tests/eucnc24/scripts/run-service-tfs-remove.sh new file mode 100644 index 0000000000000000000000000000000000000000..d82d6d7738c24039fc4b8e878f48bb3c0c90f3fe --- /dev/null +++ b/src/tests/eucnc24/scripts/run-service-tfs-remove.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# +# 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. + +source /var/teraflow/tfs_runtime_env_vars.sh +export PYTHONPATH=/var/teraflow +pytest --verbose --log-level=INFO \ + --junitxml=/opt/results/report_service_tfs_remove.xml \ + /var/teraflow/tests/eucnc24/tests/test_service_tfs_remove.py diff --git a/src/tests/eucnc24/tests/Fixtures.py b/src/tests/eucnc24/tests/Fixtures.py index a9d2ceb24488dbd5b3775c958358df419dec4172..9eae2e2acda193157d0b5ed2fc8cde71cbcb2102 100644 --- a/src/tests/eucnc24/tests/Fixtures.py +++ b/src/tests/eucnc24/tests/Fixtures.py @@ -13,6 +13,7 @@ # limitations under the License. import pytest +from typing import Dict from context.client.ContextClient import ContextClient from device.client.DeviceClient import DeviceClient from monitoring.client.MonitoringClient import MonitoringClient @@ -41,3 +42,7 @@ def service_client(): _client = ServiceClient() yield _client _client.close() + +@pytest.fixture(scope='session') +def storage() -> Dict: + yield dict() diff --git a/src/tests/eucnc24/tests/test_functional_cleanup.py b/src/tests/eucnc24/tests/test_cleanup.py similarity index 100% rename from src/tests/eucnc24/tests/test_functional_cleanup.py rename to src/tests/eucnc24/tests/test_cleanup.py diff --git a/src/tests/eucnc24/tests/test_functional_service_ietf.py b/src/tests/eucnc24/tests/test_functional_service_ietf.py deleted file mode 100644 index 1abdb466b3c7cbb1da7b8bb676bdca0dee839652..0000000000000000000000000000000000000000 --- a/src/tests/eucnc24/tests/test_functional_service_ietf.py +++ /dev/null @@ -1,147 +0,0 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import json, logging, os, pytest -from typing import Dict -from common.Constants import DEFAULT_CONTEXT_NAME -from common.proto.context_pb2 import ContextId, ServiceStatusEnum, ServiceTypeEnum -from common.tools.grpc.Tools import grpc_message_to_json_string -from common.tools.object_factory.Context import json_context_id -from context.client.ContextClient import ContextClient -from .Fixtures import context_client # pylint: disable=unused-import -from .Tools import do_rest_delete_request, do_rest_get_request, do_rest_post_request - - -LOGGER = logging.getLogger(__name__) -LOGGER.setLevel(logging.DEBUG) - -REQUEST_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'data', 'ietf-l3vpn-service.json') -ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME)) - -@pytest.fixture(scope='session') -def storage() -> Dict: - yield dict() - -# pylint: disable=redefined-outer-name, unused-argument -def test_service_ietf_creation( - context_client : ContextClient, - storage : Dict -): - # Issue service creation request - with open(REQUEST_FILE, 'r', encoding='UTF-8') as f: - svc1_data = json.load(f) - URL = '/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services' - do_rest_post_request(URL, body=svc1_data, logger=LOGGER, expected_status_codes={201}) - vpn_id = svc1_data['ietf-l3vpn-svc:l3vpn-svc']['vpn-services']['vpn-service'][0]['vpn-id'] - - URL = '/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services/vpn-service={:s}/'.format(vpn_id) - service_data = do_rest_get_request(URL, logger=LOGGER, expected_status_codes={200}) - service_uuid = service_data['service-id'] - storage['svc-uuid'] = service_uuid - - # Verify service was created - response = context_client.GetContext(ADMIN_CONTEXT_ID) - assert len(response.service_ids) == 1 - assert len(response.slice_ids) == 0 - - # Check there is 1 service - response = context_client.ListServices(ADMIN_CONTEXT_ID) - LOGGER.warning('Services[{:d}] = {:s}'.format( - len(response.services), grpc_message_to_json_string(response) - )) - assert len(response.services) == 1 - - for service in response.services: - service_id = service.service_id - assert service_id.service_uuid.uuid == service_uuid - assert service.service_status.service_status == ServiceStatusEnum.SERVICESTATUS_ACTIVE - assert service.service_type == ServiceTypeEnum.SERVICETYPE_L3NM - - response = context_client.ListConnections(service_id) - LOGGER.warning(' ServiceId[{:s}] => Connections[{:d}] = {:s}'.format( - grpc_message_to_json_string(service_id), len(response.connections), - grpc_message_to_json_string(response) - )) - assert len(response.connections) == 1 - - -# pylint: disable=redefined-outer-name, unused-argument -def test_service_ietf_retrieval( - context_client : ContextClient, # pylint: disable=redefined-outer-name - storage : Dict -): - # Verify the scenario has 1 service and 0 slices - response = context_client.GetContext(ADMIN_CONTEXT_ID) - assert len(response.service_ids) == 1 - assert len(response.slice_ids) == 0 - - # Check there are no slices - response = context_client.ListSlices(ADMIN_CONTEXT_ID) - LOGGER.warning('Slices[{:d}] = {:s}'.format(len(response.slices), grpc_message_to_json_string(response))) - assert len(response.slices) == 0 - - # Check there is 1 service - response = context_client.ListServices(ADMIN_CONTEXT_ID) - LOGGER.warning('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response))) - assert len(response.services) == 1 - - assert 'svc-uuid' in storage - service_uuid = storage['svc-uuid'] - URL = '/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services/vpn-service={:s}/'.format(service_uuid) - do_rest_get_request(URL, logger=LOGGER, expected_status_codes={200}) - - -# pylint: disable=redefined-outer-name, unused-argument -def test_service_ietf_removal( - context_client : ContextClient, # pylint: disable=redefined-outer-name - storage : Dict -): - # Verify the scenario has 1 service and 0 slices - response = context_client.GetContext(ADMIN_CONTEXT_ID) - assert len(response.service_ids) == 1 - assert len(response.slice_ids) == 0 - - # Check there are no slices - response = context_client.ListSlices(ADMIN_CONTEXT_ID) - LOGGER.warning('Slices[{:d}] = {:s}'.format(len(response.slices), grpc_message_to_json_string(response))) - assert len(response.slices) == 0 - - # Check there is 1 service - response = context_client.ListServices(ADMIN_CONTEXT_ID) - LOGGER.warning('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response))) - assert len(response.services) == 1 - - assert 'svc-uuid' in storage - service_uuid = storage['svc-uuid'] - - for service in response.services: - service_id = service.service_id - assert service_id.service_uuid.uuid == service_uuid - assert service.service_status.service_status == ServiceStatusEnum.SERVICESTATUS_ACTIVE - assert service.service_type == ServiceTypeEnum.SERVICETYPE_L3NM - - response = context_client.ListConnections(service_id) - LOGGER.warning(' ServiceId[{:s}] => Connections[{:d}] = {:s}'.format( - grpc_message_to_json_string(service_id), len(response.connections), - grpc_message_to_json_string(response) - )) - assert len(response.connections) == 1 - - URL = '/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services/vpn-service={:s}/'.format(service_uuid) - do_rest_delete_request(URL, logger=LOGGER, expected_status_codes={204}) - - # Verify the scenario has no services/slices - response = context_client.GetContext(ADMIN_CONTEXT_ID) - assert len(response.service_ids) == 0 - assert len(response.slice_ids) == 0 diff --git a/src/tests/eucnc24/tests/test_functional_bootstrap.py b/src/tests/eucnc24/tests/test_onboarding.py similarity index 99% rename from src/tests/eucnc24/tests/test_functional_bootstrap.py rename to src/tests/eucnc24/tests/test_onboarding.py index 5222a4c871997410c874b884ff70a215d090c1a9..93f040877a4d0c40e2a9d832872e78c75688cffb 100644 --- a/src/tests/eucnc24/tests/test_functional_bootstrap.py +++ b/src/tests/eucnc24/tests/test_onboarding.py @@ -27,7 +27,7 @@ LOGGER.setLevel(logging.DEBUG) DESCRIPTOR_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'data', 'tfs-topology.json') ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME)) -def test_scenario_bootstrap( +def test_scenario_onboarding( context_client : ContextClient, # pylint: disable=redefined-outer-name device_client : DeviceClient, # pylint: disable=redefined-outer-name ) -> None: diff --git a/src/tests/eucnc24/tests/test_service_ietf_create.py b/src/tests/eucnc24/tests/test_service_ietf_create.py new file mode 100644 index 0000000000000000000000000000000000000000..5f713d45be7e24e3fcaf9e5c3f6f338a4db73950 --- /dev/null +++ b/src/tests/eucnc24/tests/test_service_ietf_create.py @@ -0,0 +1,73 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json, logging, os +from typing import Dict +from common.Constants import DEFAULT_CONTEXT_NAME +from common.proto.context_pb2 import ContextId, ServiceStatusEnum, ServiceTypeEnum +from common.tools.grpc.Tools import grpc_message_to_json_string +from common.tools.object_factory.Context import json_context_id +from context.client.ContextClient import ContextClient +from .Fixtures import context_client, storage # pylint: disable=unused-import +from .Tools import do_rest_get_request, do_rest_post_request + + +LOGGER = logging.getLogger(__name__) +LOGGER.setLevel(logging.DEBUG) + +REQUEST_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'data', 'ietf-l3vpn-service.json') +ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME)) + + +# pylint: disable=redefined-outer-name, unused-argument +def test_service_ietf_creation( + context_client : ContextClient, + storage : Dict +): + # Issue service creation request + with open(REQUEST_FILE, 'r', encoding='UTF-8') as f: + svc1_data = json.load(f) + URL = '/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services' + do_rest_post_request(URL, body=svc1_data, logger=LOGGER, expected_status_codes={201}) + vpn_id = svc1_data['ietf-l3vpn-svc:l3vpn-svc']['vpn-services']['vpn-service'][0]['vpn-id'] + + URL = '/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services/vpn-service={:s}/'.format(vpn_id) + service_data = do_rest_get_request(URL, logger=LOGGER, expected_status_codes={200}) + service_uuid = service_data['service-id'] + storage['svc-uuid'] = service_uuid + + # Verify service was created + response = context_client.GetContext(ADMIN_CONTEXT_ID) + assert len(response.service_ids) == 1 + assert len(response.slice_ids) == 0 + + # Check there is 1 service + response = context_client.ListServices(ADMIN_CONTEXT_ID) + LOGGER.warning('Services[{:d}] = {:s}'.format( + len(response.services), grpc_message_to_json_string(response) + )) + assert len(response.services) == 1 + + for service in response.services: + service_id = service.service_id + assert service_id.service_uuid.uuid == service_uuid + assert service.service_status.service_status == ServiceStatusEnum.SERVICESTATUS_ACTIVE + assert service.service_type == ServiceTypeEnum.SERVICETYPE_L3NM + + response = context_client.ListConnections(service_id) + LOGGER.warning(' ServiceId[{:s}] => Connections[{:d}] = {:s}'.format( + grpc_message_to_json_string(service_id), len(response.connections), + grpc_message_to_json_string(response) + )) + assert len(response.connections) == 1 diff --git a/src/tests/eucnc24/tests/test_service_ietf_remove.py b/src/tests/eucnc24/tests/test_service_ietf_remove.py new file mode 100644 index 0000000000000000000000000000000000000000..fe4210a57b264805184f130e7dab8e0c6d9c5c07 --- /dev/null +++ b/src/tests/eucnc24/tests/test_service_ietf_remove.py @@ -0,0 +1,75 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import logging, os +from typing import Dict +from common.Constants import DEFAULT_CONTEXT_NAME +from common.proto.context_pb2 import ContextId, ServiceStatusEnum, ServiceTypeEnum +from common.tools.grpc.Tools import grpc_message_to_json_string +from common.tools.object_factory.Context import json_context_id +from context.client.ContextClient import ContextClient +from .Fixtures import context_client, storage # pylint: disable=unused-import +from .Tools import do_rest_delete_request + + +LOGGER = logging.getLogger(__name__) +LOGGER.setLevel(logging.DEBUG) + +REQUEST_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'data', 'ietf-l3vpn-service.json') +ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME)) + + +# pylint: disable=redefined-outer-name, unused-argument +def test_service_ietf_removal( + context_client : ContextClient, # pylint: disable=redefined-outer-name + storage : Dict +): + # Verify the scenario has 1 service and 0 slices + response = context_client.GetContext(ADMIN_CONTEXT_ID) + assert len(response.service_ids) == 1 + assert len(response.slice_ids) == 0 + + # Check there are no slices + response = context_client.ListSlices(ADMIN_CONTEXT_ID) + LOGGER.warning('Slices[{:d}] = {:s}'.format(len(response.slices), grpc_message_to_json_string(response))) + assert len(response.slices) == 0 + + # Check there is 1 service + response = context_client.ListServices(ADMIN_CONTEXT_ID) + LOGGER.warning('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response))) + assert len(response.services) == 1 + + assert 'svc-uuid' in storage + service_uuid = storage['svc-uuid'] + + for service in response.services: + service_id = service.service_id + assert service_id.service_uuid.uuid == service_uuid + assert service.service_status.service_status == ServiceStatusEnum.SERVICESTATUS_ACTIVE + assert service.service_type == ServiceTypeEnum.SERVICETYPE_L3NM + + response = context_client.ListConnections(service_id) + LOGGER.warning(' ServiceId[{:s}] => Connections[{:d}] = {:s}'.format( + grpc_message_to_json_string(service_id), len(response.connections), + grpc_message_to_json_string(response) + )) + assert len(response.connections) == 1 + + URL = '/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services/vpn-service={:s}/'.format(service_uuid) + do_rest_delete_request(URL, logger=LOGGER, expected_status_codes={204}) + + # Verify the scenario has no services/slices + response = context_client.GetContext(ADMIN_CONTEXT_ID) + assert len(response.service_ids) == 0 + assert len(response.slice_ids) == 0 diff --git a/src/tests/eucnc24/tests/test_service_tfs_create.py b/src/tests/eucnc24/tests/test_service_tfs_create.py new file mode 100644 index 0000000000000000000000000000000000000000..6e0492f86f21b02c7f047d84c2db49d342710ac7 --- /dev/null +++ b/src/tests/eucnc24/tests/test_service_tfs_create.py @@ -0,0 +1,76 @@ +# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import logging, os +from common.Constants import DEFAULT_CONTEXT_NAME +from common.proto.context_pb2 import ContextId, ServiceStatusEnum, ServiceTypeEnum +from common.tools.descriptor.Loader import DescriptorLoader, check_descriptor_load_results +from common.tools.grpc.Tools import grpc_message_to_json_string +from common.tools.object_factory.Context import json_context_id +from context.client.ContextClient import ContextClient +from device.client.DeviceClient import DeviceClient +from service.client.ServiceClient import ServiceClient +from .Fixtures import context_client, device_client, service_client # pylint: disable=unused-import + + +LOGGER = logging.getLogger(__name__) +LOGGER.setLevel(logging.DEBUG) + +DESCRIPTOR_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'data', 'tfs-service.json') +ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME)) + + +def test_service_tfs_creation( + context_client : ContextClient, # pylint: disable=redefined-outer-name + device_client : DeviceClient, # pylint: disable=redefined-outer-name + service_client : ServiceClient, # pylint: disable=redefined-outer-name +): + # Load descriptors and validate the base scenario + descriptor_loader = DescriptorLoader( + descriptors_file=DESCRIPTOR_FILE, context_client=context_client, + device_client=device_client, service_client=service_client + ) + results = descriptor_loader.process() + check_descriptor_load_results(results, descriptor_loader) + + # Verify the scenario has 1 service and 0 slices + response = context_client.GetContext(ADMIN_CONTEXT_ID) + assert len(response.service_ids) == 1 + assert len(response.slice_ids) == 0 + + # Check there are no slices + response = context_client.ListSlices(ADMIN_CONTEXT_ID) + LOGGER.warning('Slices[{:d}] = {:s}'.format( + len(response.slices), grpc_message_to_json_string(response) + )) + assert len(response.slices) == 0 + + # Check there is 1 service + response = context_client.ListServices(ADMIN_CONTEXT_ID) + LOGGER.warning('Services[{:d}] = {:s}'.format( + len(response.services), grpc_message_to_json_string(response) + )) + assert len(response.services) == 1 + + for service in response.services: + service_id = service.service_id + assert service.service_status.service_status == ServiceStatusEnum.SERVICESTATUS_ACTIVE + assert service.service_type == ServiceTypeEnum.SERVICETYPE_L3NM + + response = context_client.ListConnections(service_id) + LOGGER.warning(' ServiceId[{:s}] => Connections[{:d}] = {:s}'.format( + grpc_message_to_json_string(service_id), len(response.connections), + grpc_message_to_json_string(response) + )) + assert len(response.connections) == 1 diff --git a/src/tests/eucnc24/tests/test_functional_service_tfs.py b/src/tests/eucnc24/tests/test_service_tfs_remove.py similarity index 62% rename from src/tests/eucnc24/tests/test_functional_service_tfs.py rename to src/tests/eucnc24/tests/test_service_tfs_remove.py index 84385843b5a982219ac3b6d5d473e7371153db2a..76fdf0fc7407ce86bbd87806932eb1a4a45c40d1 100644 --- a/src/tests/eucnc24/tests/test_functional_service_tfs.py +++ b/src/tests/eucnc24/tests/test_service_tfs_remove.py @@ -16,14 +16,13 @@ import logging, os from typing import Set, Tuple from common.Constants import DEFAULT_CONTEXT_NAME from common.proto.context_pb2 import ContextId, ServiceId, ServiceStatusEnum, ServiceTypeEnum -from common.tools.descriptor.Loader import DescriptorLoader, check_descriptor_load_results from common.tools.grpc.Tools import grpc_message_to_json_string from common.tools.object_factory.Context import json_context_id from common.tools.object_factory.Service import json_service_id from context.client.ContextClient import ContextClient -from device.client.DeviceClient import DeviceClient from service.client.ServiceClient import ServiceClient -from .Fixtures import context_client, device_client, service_client # pylint: disable=unused-import +from .Fixtures import context_client, service_client # pylint: disable=unused-import + LOGGER = logging.getLogger(__name__) LOGGER.setLevel(logging.DEBUG) @@ -31,49 +30,6 @@ LOGGER.setLevel(logging.DEBUG) DESCRIPTOR_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'data', 'tfs-service.json') ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME)) -def test_service_tfs_creation( - context_client : ContextClient, # pylint: disable=redefined-outer-name - device_client : DeviceClient, # pylint: disable=redefined-outer-name - service_client : ServiceClient, # pylint: disable=redefined-outer-name -): - # Load descriptors and validate the base scenario - descriptor_loader = DescriptorLoader( - descriptors_file=DESCRIPTOR_FILE, context_client=context_client, - device_client=device_client, service_client=service_client - ) - results = descriptor_loader.process() - check_descriptor_load_results(results, descriptor_loader) - - # Verify the scenario has 1 service and 0 slices - response = context_client.GetContext(ADMIN_CONTEXT_ID) - assert len(response.service_ids) == 1 - assert len(response.slice_ids) == 0 - - # Check there are no slices - response = context_client.ListSlices(ADMIN_CONTEXT_ID) - LOGGER.warning('Slices[{:d}] = {:s}'.format( - len(response.slices), grpc_message_to_json_string(response) - )) - assert len(response.slices) == 0 - - # Check there is 1 service - response = context_client.ListServices(ADMIN_CONTEXT_ID) - LOGGER.warning('Services[{:d}] = {:s}'.format( - len(response.services), grpc_message_to_json_string(response) - )) - assert len(response.services) == 1 - - for service in response.services: - service_id = service.service_id - assert service.service_status.service_status == ServiceStatusEnum.SERVICESTATUS_ACTIVE - assert service.service_type == ServiceTypeEnum.SERVICETYPE_L3NM - - response = context_client.ListConnections(service_id) - LOGGER.warning(' ServiceId[{:s}] => Connections[{:d}] = {:s}'.format( - grpc_message_to_json_string(service_id), len(response.connections), - grpc_message_to_json_string(response) - )) - assert len(response.connections) == 1 def test_service_tfs_removal( context_client : ContextClient, # pylint: disable=redefined-outer-name