diff --git a/src/tests/ofc25/.gitignore b/src/tests/ofc25/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..24a4b233365e23a9462f4b64e8b60fef6a62bee4 --- /dev/null +++ b/src/tests/ofc25/.gitignore @@ -0,0 +1,5 @@ +clab-*/ +images/ +*.clab.yml.bak +*.tar +*.tar.gz diff --git a/src/tests/ofc25/.gitlab-ci.yml b/src/tests/ofc25/.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..7bc42ce7b55066eef8f3bb8e600c221d505ca5ea --- /dev/null +++ b/src/tests/ofc25/.gitlab-ci.yml @@ -0,0 +1,121 @@ +# Copyright 2022-2025 ETSI 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. + +# Build, tag, and push the Docker images to the GitLab Docker registry +build ofc25: + variables: + TEST_NAME: 'ofc25' + NCE_NAME: 'nce' + AGG_NET_NAME: 'agg_net' + NCE_PORT: '9090' + AGG_NET_PORT: '9091' + stage: build + before_script: + - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY + script: + - HOST_IP=$(kubectl get nodes -o json | jq -r '.items[].status.addresses[] | select(.type=="InternalIP") | .address') + - sed -i "s/AGG_NET_IP/${HOST_IP}/g" src/tests/${TEST_NAME}/data/camara-e2e-topology.json + - sed -i "s/NCE_IP/${HOST_IP}/g" src/tests/${TEST_NAME}/data/camara-e2e-topology.json + - sed -i "s/AGG_NET_PORT/${AGG_NET_PORT}/g" src/tests/${TEST_NAME}/data/camara-e2e-topology.json + - sed -i "s/NCE_PORT/${NCE_PORT}/g" src/tests/${TEST_NAME}/data/camara-e2e-topology.json + - docker buildx build -t "${TEST_NAME}:latest" -f ./src/tests/${TEST_NAME}/Dockerfile . + - docker tag "${TEST_NAME}:latest" "$CI_REGISTRY_IMAGE/${TEST_NAME}:latest" + - docker push "$CI_REGISTRY_IMAGE/${TEST_NAME}:latest" + - docker buildx build -t "${NCE_NAME}:latest" -f ./src/tests/tools/mock_nce_ctrl/Dockerfile . + - docker tag "${NCE_NAME}:latest" "$CI_REGISTRY_IMAGE/${NCE_NAME}:latest" + - docker push "$CI_REGISTRY_IMAGE/${NCE_NAME}:latest" + - docker buildx build -t "${AGG_NET_NAME}:latest" -f ./src/tests/tools/mock_ietf_network_slice_sdn_ctrl/Dockerfile . + - docker tag "${AGG_NET_NAME}:latest" "$CI_REGISTRY_IMAGE/${AGG_NET_NAME}:latest" + - docker push "$CI_REGISTRY_IMAGE/${AGG_NET_NAME}:latest" + 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: + - src/common/**/*.py + - proto/*.proto + - src/tests/${TEST_NAME}/**/*.{py,in,sh,yml} + - src/tests/${TEST_NAME}/Dockerfile + - .gitlab-ci.yml + +# Deploy TeraFlowSDN and Execute end-2-end test +end2end_test ofc25: + variables: + TEST_NAME: 'ofc25' + NCE_NAME: 'nce' + AGG_NET_NAME: 'agg_net' + NCE_PORT: '9090' + AGG_NET_PORT: '9091' + stage: end2end_test + # Disable to force running it after all other tasks + before_script: + - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY + - docker rm -f ${TEST_NAME} || true + - docker pull "${CI_REGISTRY_IMAGE}/${NCE_NAME}:latest" + - docker run -d --name ${NCE_NAME} -p ${NCE_PORT}:8443 $CI_REGISTRY_IMAGE/${NCE_NAME}:latest + - docker pull "${CI_REGISTRY_IMAGE}/${AGG_NET_NAME}:latest" + - docker run -d --name ${AGG_NET_NAME} -p ${AGG_NET_PORT}:8443 $CI_REGISTRY_IMAGE/${AGG_NET_NAME}:latest + + script: + # Download Docker image to run the test + - docker pull "${CI_REGISTRY_IMAGE}/${TEST_NAME}:latest" + + # Check MicroK8s is ready + - microk8s status --wait-ready + - kubectl get pods --all-namespaces + + - source src/tests/${TEST_NAME}/deploy_specs.sh + + # Deploy TeraFlowSDN + - ./deploy/crdb.sh + - ./deploy/nats.sh + - ./deploy/qdb.sh + - ./deploy/kafka.sh + - ./deploy/tfs.sh + - ./deploy/show.sh + + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server + + # Run end-to-end test: onboard scenario + - > + docker run -t --rm --name ${TEST_NAME} --network=host + $CI_REGISTRY_IMAGE/${TEST_NAME}:latest /var/teraflow/run-onboarding.sh + + # Run end-to-end test: configure service TFS + - > + docker run -t --rm --name ${TEST_NAME} --network=host + $CI_REGISTRY_IMAGE/${TEST_NAME}:latest /var/teraflow/run-e2e-ietf-slice-operations.sh + + after_script: + - kubectl --namespace tfs logs deployment/contextservice -c server + - kubectl --namespace tfs logs deployment/deviceservice -c server + - kubectl --namespace tfs logs deployment/pathcompservice -c frontend + - kubectl --namespace tfs logs deployment/serviceservice -c server + - kubectl --namespace tfs logs deployment/nbiservice -c server + + # Destroy Scenario + - kubectl delete namespaces tfs || true + + # Clean old docker images + - docker images --filter="dangling=true" --quiet | xargs -r docker rmi + + #coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/' + 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"' + artifacts: + when: always + reports: + junit: ./src/tests/${TEST_NAME}/report_*.xml diff --git a/src/tests/ofc25/Dockerfile b/src/tests/ofc25/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..b2ce8157aea2f2167b468bc5d1104f369907566c --- /dev/null +++ b/src/tests/ofc25/Dockerfile @@ -0,0 +1,71 @@ +# Copyright 2022-2024 ETSI 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. + +FROM python:3.9-slim + +# Install dependencies +RUN apt-get --yes --quiet --quiet update && \ + apt-get --yes --quiet --quiet install wget g++ git && \ + rm -rf /var/lib/apt/lists/* + +# Set Python to show logs as they occur +ENV PYTHONUNBUFFERED=0 + +# Get generic Python packages +RUN python3 -m pip install --upgrade pip +RUN python3 -m pip install --upgrade setuptools wheel +RUN python3 -m pip install --upgrade pip-tools + +# Get common Python packages +# Note: this step enables sharing the previous Docker build steps among all the Python components +WORKDIR /var/teraflow +COPY common_requirements.in common_requirements.in +RUN pip-compile --quiet --output-file=common_requirements.txt common_requirements.in +RUN python3 -m pip install -r common_requirements.txt + +# Add common files into working directory +WORKDIR /var/teraflow/common +COPY src/common/. ./ +RUN rm -rf proto + +# Create proto sub-folder, copy .proto files, and generate Python code +RUN mkdir -p /var/teraflow/common/proto +WORKDIR /var/teraflow/common/proto +RUN touch __init__.py +COPY proto/*.proto ./ +RUN python3 -m grpc_tools.protoc -I=. --python_out=. --grpc_python_out=. *.proto +RUN rm *.proto +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/tests/ofc25 +WORKDIR /var/teraflow/tests/ofc25 +COPY src/tests/ofc25/requirements.in requirements.in +RUN pip-compile --quiet --output-file=requirements.txt requirements.in +RUN python3 -m pip install -r requirements.txt + +# Add component files into working directory +WORKDIR /var/teraflow +COPY src/__init__.py ./__init__.py +COPY src/tests/*.py ./tests/ +COPY src/tests/ofc25/__init__.py ./tests/ofc25/__init__.py +COPY src/tests/ofc25/data/. ./tests/ofc25/data/ +COPY src/tests/ofc25/tests/. ./tests/ofc25/tests/ +COPY src/tests/ofc25/scripts/. ./ + +RUN apt-get --yes --quiet --quiet update && \ + apt-get --yes --quiet --quiet install tree && \ + rm -rf /var/lib/apt/lists/* + +RUN tree -la /var/teraflow diff --git a/src/tests/ofc25/README.md b/src/tests/ofc25/README.md new file mode 100644 index 0000000000000000000000000000000000000000..23522ad6f8537f34df4be65c6ed325546385bd61 --- /dev/null +++ b/src/tests/ofc25/README.md @@ -0,0 +1,97 @@ +# DataPlane-in-a-Box - Control an Emulated DataPlane through TeraFlowSDN + +## Emulated DataPlane Deployment +- Scenario +- Descriptor + +## TeraFlowSDN Deployment +```bash +cd ~/tfs-ctrl +source ~/tfs-ctrl/src/tests/ofc25/deploy_specs.sh +./deploy/all.sh +``` + +## Deploy scenario +```bash +cd ~/tfs-ctrl/src/tests/ofc25/ +sudo containerlab deploy --topo eucnc24.clab.yml +``` + +## Inspect scenario +```bash +cd ~/tfs-ctrl/src/tests/eucnc24/ +sudo containerlab inspect --topo eucnc24.clab.yml +``` + +## Destroy scenario +```bash +cd ~/tfs-ctrl/src/tests/eucnc24/ +sudo containerlab destroy --topo eucnc24.clab.yml +sudo rm -rf clab-eucnc24/ .eucnc24.clab.yml.bak +``` + +## Access cEOS Bash/CLI +```bash +docker exec -it clab-eucnc24-r1 bash +docker exec -it clab-eucnc24-r2 bash +docker exec -it clab-eucnc24-r3 bash +docker exec -it clab-eucnc24-r1 Cli +docker exec -it clab-eucnc24-r2 Cli +docker exec -it clab-eucnc24-r3 Cli +``` + +## Configure ContainerLab clients +```bash +docker exec -it clab-eucnc24-dc1 bash + ip address add 172.16.1.10/24 dev eth1 + ip route add 172.16.2.0/24 via 172.16.1.1 + ping 172.16.2.10 + +docker exec -it clab-eucnc24-dc2 bash + ip address add 172.16.2.10/24 dev eth1 + ip route add 172.16.1.0/24 via 172.16.2.1 + ping 172.16.1.10 +``` + +## Install gNMIc +```bash +sudo bash -c "$(curl -sL https://get-gnmic.kmrd.dev)" +``` + +## gNMI Capabilities request +```bash +gnmic --address clab-eucnc24-r1 --port 6030 --username admin --password admin --insecure capabilities +``` + +## gNMI Get request +```bash +gnmic --address clab-eucnc24-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf get --path / > r1.json +gnmic --address clab-eucnc24-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf get --path /interfaces/interface > r1-ifaces.json +``` + +## gNMI Set request +```bash +gnmic --address clab-eucnc24-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf set --update-path /system/config/hostname --update-value srl11 +gnmic --address clab-eucnc24-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf get --path /system/config/hostname +``` + +## Subscribe request +```bash +gnmic --address clab-eucnc24-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf subscribe --path /interfaces/interface[name=Management0]/state/ + +# In another terminal, you can generate traffic opening SSH connection +ssh admin@clab-eucnc24-r1 +``` + +# Check configurations done: +```bash +gnmic --address clab-eucnc24-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf get --path '/network-instances' > r1-nis.json +gnmic --address clab-eucnc24-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf get --path '/interfaces' > r1-ifs.json +``` + +# Delete elements: +```bash +--address clab-eucnc24-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf set --delete '/network-instances/network-instance[name=b19229e8]' +--address clab-eucnc24-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf set --delete '/interfaces/interface[name=ethernet-1/1]/subinterfaces/subinterface[index=0]' +--address clab-eucnc24-r1 --port 6030 --username admin --password admin --insecure --encoding json_ietf set --delete '/interfaces/interface[name=ethernet-1/2]/subinterfaces/subinterface[index=0]' +``` diff --git a/src/tests/ofc25/__init__.py b/src/tests/ofc25/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..3ccc21c7db78aac26daa1f8c5ff8e1ffd3f35460 --- /dev/null +++ b/src/tests/ofc25/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2022-2025 ETSI 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. + diff --git a/src/tests/ofc25/data/camara-e2e-topology.json b/src/tests/ofc25/data/camara-e2e-topology.json new file mode 100644 index 0000000000000000000000000000000000000000..7ae2da79c0fe54f883c4c08b98fa0d05c7e74ee0 --- /dev/null +++ b/src/tests/ofc25/data/camara-e2e-topology.json @@ -0,0 +1,1642 @@ +{ + "contexts": [ + { + "context_id": { + "context_uuid": { + "uuid": "admin" + } + } + } + ], + "topologies": [ + { + "topology_id": { + "context_id": { + "context_uuid": { + "uuid": "admin" + } + }, + "topology_uuid": { + "uuid": "admin" + } + } + } + ], + "devices": [ + { + "device_id": { + "device_uuid": { + "uuid": "agg-net-controller" + } + }, + "name": "agg-net-controller", + "device_type": "ietf-slice", + "device_operational_status": 1, + "device_drivers": [ + 14 + ], + "device_config": { + "config_rules": [ + { + "action": 1, + "custom": { + "resource_key": "_connect/address", + "resource_value": "AGG_NET_IP" + } + }, + { + "action": 1, + "custom": { + "resource_key": "_connect/port", + "resource_value": "AGG_NET_PORT" + } + }, + { + "action": 1, + "custom": { + "resource_key": "_connect/settings", + "resource_value": { + "endpoints": [ + { + "uuid": "mgmt", + "name": "mgmt", + "type": "mgmt" + } + ], + "scheme": "http", + "username": "admin", + "password": "admin", + "base_url": "/restconf/v2/data", + "timeout": 120, + "verify": false + } + } + } + ] + }, + "device_endpoints": [] + }, + { + "device_id": { + "device_uuid": { + "uuid": "nce-controller" + } + }, + "name": "nce-controller", + "device_type": "nce", + "device_operational_status": 1, + "device_drivers": [ + 15 + ], + "device_config": { + "config_rules": [ + { + "action": 1, + "custom": { + "resource_key": "_connect/address", + "resource_value": "NCE_IP" + } + }, + { + "action": 1, + "custom": { + "resource_key": "_connect/port", + "resource_value": "NCE_PORT" + } + }, + { + "action": 1, + "custom": { + "resource_key": "_connect/settings", + "resource_value": { + "endpoints": [ + { + "uuid": "mgmt", + "name": "mgmt", + "type": "mgmt" + } + ], + "scheme": "http", + "username": "admin", + "password": "admin", + "base_url": "/restconf/v2/data", + "timeout": 120, + "verify": false + } + } + } + ] + }, + "device_endpoints": [] + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.182.25" + } + }, + "name": "172.16.182.25", + "device_type": "emu-packet-router", + "controller_id": { + "device_uuid": { + "uuid": "agg-net-controller" + } + }, + "device_operational_status": 1, + "device_drivers": [ + 0, + 14 + ], + "device_config": { + "config_rules": [ + { + "action": 1, + "custom": { + "resource_key": "_connect/address", + "resource_value": "127.0.0.1" + } + }, + { + "action": 1, + "custom": { + "resource_key": "_connect/port", + "resource_value": "0" + } + }, + { + "action": 1, + "custom": { + "resource_key": "_connect/settings", + "resource_value": { + "endpoints": [ + { + "uuid": "mgmt", + "name": "mgmt", + "type": "mgmt" + }, + { + "uuid": "200", + "name": "200", + "type": "optical", + "address_ip": "128.32.33.254", + "address_prefix": "24", + "site_location": "access", + "mtu": "1500" + }, + { + "uuid": "500", + "name": "500", + "type": "optical" + }, + { + "uuid": "501", + "name": "501", + "type": "optical" + } + ] + } + } + } + ] + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.185.31" + } + }, + "name": "172.16.185.31", + "device_type": "emu-packet-router", + "controller_id": { + "device_uuid": { + "uuid": "agg-net-controller" + } + }, + "device_operational_status": 1, + "device_drivers": [ + 0, + 14 + ], + "device_config": { + "config_rules": [ + { + "action": 1, + "custom": { + "resource_key": "_connect/address", + "resource_value": "127.0.0.1" + } + }, + { + "action": 1, + "custom": { + "resource_key": "_connect/port", + "resource_value": "0" + } + }, + { + "action": 1, + "custom": { + "resource_key": "_connect/settings", + "resource_value": { + "endpoints": [ + { + "uuid": "mgmt", + "name": "mgmt", + "type": "mgmt" + }, + { + "uuid": "500", + "name": "500", + "type": "optical" + }, + { + "uuid": "501", + "name": "501", + "type": "optical" + } + ] + } + } + } + ] + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.185.33" + } + }, + "name": "172.16.185.33", + "device_type": "emu-packet-router", + "controller_id": { + "device_uuid": { + "uuid": "agg-net-controller" + } + }, + "device_operational_status": 1, + "device_drivers": [ + 0, + 14 + ], + "device_config": { + "config_rules": [ + { + "action": 1, + "custom": { + "resource_key": "_connect/address", + "resource_value": "127.0.0.1" + } + }, + { + "action": 1, + "custom": { + "resource_key": "_connect/port", + "resource_value": "0" + } + }, + { + "action": 1, + "custom": { + "resource_key": "_connect/settings", + "resource_value": { + "endpoints": [ + { + "uuid": "mgmt", + "name": "mgmt", + "type": "mgmt" + }, + { + "uuid": "500", + "name": "500", + "type": "optical" + }, + { + "uuid": "501", + "name": "501", + "type": "optical" + } + ] + } + } + } + ] + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.185.32" + } + }, + "name": "172.16.185.32", + "device_type": "emu-packet-router", + "controller_id": { + "device_uuid": { + "uuid": "agg-net-controller" + } + }, + "device_operational_status": 1, + "device_drivers": [ + 0, + 14 + ], + "device_config": { + "config_rules": [ + { + "action": 1, + "custom": { + "resource_key": "_connect/address", + "resource_value": "127.0.0.1" + } + }, + { + "action": 1, + "custom": { + "resource_key": "_connect/port", + "resource_value": "0" + } + }, + { + "action": 1, + "custom": { + "resource_key": "_connect/settings", + "resource_value": { + "endpoints": [ + { + "uuid": "mgmt", + "name": "mgmt", + "type": "mgmt" + }, + { + "uuid": "200", + "name": "200", + "type": "optical", + "ce-ip": "172.10.33.2", + "address_ip": "172.10.33.254", + "address_prefix": "24", + "site_location": "cloud", + "mtu": "1500" + }, + { + "uuid": "500", + "name": "500", + "type": "optical" + }, + { + "uuid": "501", + "name": "501", + "type": "optical" + } + ] + } + } + } + ] + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.58.10" + } + }, + "name": "172.16.58.10", + "device_type": "emu-packet-router", + "controller_id": { + "device_uuid": { + "uuid": "nce-controller" + } + }, + "device_operational_status": 1, + "device_drivers": [ + 15 + ], + "device_config": { + "config_rules": [ + { + "action": 1, + "custom": { + "resource_key": "_connect/address", + "resource_value": "127.0.0.1" + } + }, + { + "action": 1, + "custom": { + "resource_key": "_connect/port", + "resource_value": "0" + } + }, + { + "action": 1, + "custom": { + "resource_key": "_connect/settings", + "resource_value": { + "endpoints": [ + { + "uuid": "mgmt", + "name": "mgmt", + "type": "mgmt" + }, + { + "uuid": "200", + "name": "200", + "type": "optical", + "address_ip": "0.0.0.0", + "address_prefix": "24" + }, + { + "uuid": "201", + "name": "201", + "type": "optical", + "address_ip": "0.0.0.0", + "address_prefix": "24" + }, + { + "uuid": "500", + "name": "500", + "type": "optical", + "address_ip": "128.32.33.2", + "address_prefix": "24" + } + ] + } + } + } + ] + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.61.10" + } + }, + "name": "172.16.61.10", + "device_type": "emu-packet-router", + "controller_id": { + "device_uuid": { + "uuid": "nce-controller" + } + }, + "device_operational_status": 1, + "device_drivers": [ + 15 + ], + "device_config": { + "config_rules": [ + { + "action": 1, + "custom": { + "resource_key": "_connect/address", + "resource_value": "127.0.0.1" + } + }, + { + "action": 1, + "custom": { + "resource_key": "_connect/port", + "resource_value": "0" + } + }, + { + "action": 1, + "custom": { + "resource_key": "_connect/settings", + "resource_value": { + "endpoints": [ + { + "uuid": "mgmt", + "name": "mgmt", + "type": "mgmt" + }, + { + "uuid": "200", + "name": "200", + "type": "optical", + "address_ip": "0.0.0.0", + "address_prefix": "24" + }, + { + "uuid": "500", + "name": "500", + "type": "optical", + "address_ip": "128.32.33.2", + "address_prefix": "24" + } + ] + } + } + } + ] + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.61.11" + } + }, + "name": "172.16.61.11", + "device_type": "emu-packet-router", + "controller_id": { + "device_uuid": { + "uuid": "nce-controller" + } + }, + "device_operational_status": 1, + "device_drivers": [ + 15 + ], + "device_config": { + "config_rules": [ + { + "action": 1, + "custom": { + "resource_key": "_connect/address", + "resource_value": "127.0.0.1" + } + }, + { + "action": 1, + "custom": { + "resource_key": "_connect/port", + "resource_value": "0" + } + }, + { + "action": 1, + "custom": { + "resource_key": "_connect/settings", + "resource_value": { + "endpoints": [ + { + "uuid": "mgmt", + "name": "mgmt", + "type": "mgmt" + }, + { + "uuid": "200", + "name": "200", + "type": "optical", + "address_ip": "0.0.0.0", + "address_prefix": "24" + }, + { + "uuid": "500", + "name": "500", + "type": "optical", + "address_ip": "128.32.33.2", + "address_prefix": "24" + } + ] + } + } + } + ] + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.104.221" + } + }, + "device_type": "emu-datacenter", + "device_drivers": [ + 0 + ], + "device_endpoints": [], + "device_operational_status": 1, + "device_config": { + "config_rules": [ + { + "action": 1, + "custom": { + "resource_key": "_connect/address", + "resource_value": "127.0.0.1" + } + }, + { + "action": 1, + "custom": { + "resource_key": "_connect/port", + "resource_value": "0" + } + }, + { + "action": 1, + "custom": { + "resource_key": "_connect/settings", + "resource_value": { + "endpoints": [ + { + "sample_types": [], + "type": "copper", + "uuid": "eth0" + } + ] + } + } + } + ] + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.104.222" + } + }, + "device_type": "emu-datacenter", + "device_drivers": [ + 0 + ], + "device_endpoints": [], + "device_operational_status": 1, + "device_config": { + "config_rules": [ + { + "action": 1, + "custom": { + "resource_key": "_connect/address", + "resource_value": "127.0.0.1" + } + }, + { + "action": 1, + "custom": { + "resource_key": "_connect/port", + "resource_value": "0" + } + }, + { + "action": 1, + "custom": { + "resource_key": "_connect/settings", + "resource_value": { + "endpoints": [ + { + "sample_types": [], + "type": "copper", + "uuid": "eth0" + } + ] + } + } + } + ] + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.204.220" + } + }, + "device_type": "emu-datacenter", + "device_drivers": [ + 0 + ], + "device_endpoints": [], + "device_operational_status": 1, + "device_config": { + "config_rules": [ + { + "action": 1, + "custom": { + "resource_key": "_connect/address", + "resource_value": "127.0.0.1" + } + }, + { + "action": 1, + "custom": { + "resource_key": "_connect/port", + "resource_value": "0" + } + }, + { + "action": 1, + "custom": { + "resource_key": "_connect/settings", + "resource_value": { + "endpoints": [ + { + "sample_types": [], + "type": "optical", + "uuid": "500" + }, + { + "sample_types": [], + "type": "optical", + "uuid": "200" + }, + { + "sample_types": [], + "type": "optical", + "uuid": "201" + } + ] + } + } + } + ] + } + } + ], + "links": [ + { + "link_id": { + "link_uuid": { + "uuid": "nce-controller/mgmt==172.16.61.11/mgmt" + } + }, + "name": "nce-controller/mgmt==172.16.61.11/mgmt", + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "nce-controller" + } + }, + "endpoint_uuid": { + "uuid": "mgmt" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.61.11" + } + }, + "endpoint_uuid": { + "uuid": "mgmt" + } + } + ] + }, + { + "link_id": { + "link_uuid": { + "uuid": "nce-controller/mgmt==172.16.61.10/mgmt" + } + }, + "name": "nce-controller/mgmt==172.16.61.10/mgmt", + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "nce-controller" + } + }, + "endpoint_uuid": { + "uuid": "mgmt" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.61.10" + } + }, + "endpoint_uuid": { + "uuid": "mgmt" + } + } + ] + }, + { + "link_id": { + "link_uuid": { + "uuid": "nce-controller/mgmt==172.16.58.10/mgmt" + } + }, + "name": "nce-controller/mgmt==172.16.58.10/mgmt", + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "nce-controller" + } + }, + "endpoint_uuid": { + "uuid": "mgmt" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.58.10" + } + }, + "endpoint_uuid": { + "uuid": "mgmt" + } + } + ] + }, + { + "link_id": { + "link_uuid": { + "uuid": "agg-net-controller/mgmt==172.16.185.33/mgmt" + } + }, + "name": "agg-net-controller/mgmt==172.16.185.33/mgmt", + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "agg-net-controller" + } + }, + "endpoint_uuid": { + "uuid": "mgmt" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.185.33" + } + }, + "endpoint_uuid": { + "uuid": "mgmt" + } + } + ] + }, + { + "link_id": { + "link_uuid": { + "uuid": "agg-net-controller/mgmt==172.16.185.31/mgmt" + } + }, + "name": "agg-net-controller/mgmt==172.16.185.31/mgmt", + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "agg-net-controller" + } + }, + "endpoint_uuid": { + "uuid": "mgmt" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.185.31" + } + }, + "endpoint_uuid": { + "uuid": "mgmt" + } + } + ] + }, + { + "link_id": { + "link_uuid": { + "uuid": "agg-net-controller/mgmt==172.16.182.25/mgmt" + } + }, + "name": "agg-net-controller/mgmt==172.16.182.25/mgmt", + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "agg-net-controller" + } + }, + "endpoint_uuid": { + "uuid": "mgmt" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.182.25" + } + }, + "endpoint_uuid": { + "uuid": "mgmt" + } + } + ] + }, + { + "link_id": { + "link_uuid": { + "uuid": "agg-net-controller/mgmt==172.16.182.25/mgmt" + } + }, + "name": "agg-net-controller/mgmt==172.16.182.25/mgmt", + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "agg-net-controller" + } + }, + "endpoint_uuid": { + "uuid": "mgmt" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.182.25" + } + }, + "endpoint_uuid": { + "uuid": "mgmt" + } + } + ] + }, + { + "link_id": { + "link_uuid": { + "uuid": "172.16.182.25-500" + } + }, + "name": "172.16.182.25-500", + "attributes": { + "total_capacity_gbps": 10, + "used_capacity_gbps": 0 + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "172.16.182.25" + } + }, + "endpoint_uuid": { + "uuid": "500" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.185.33" + } + }, + "endpoint_uuid": { + "uuid": "500" + } + } + ] + }, + { + "link_id": { + "link_uuid": { + "uuid": "172.16.185.33-500" + } + }, + "name": "172.16.185.33-500", + "attributes": { + "total_capacity_gbps": 10, + "used_capacity_gbps": 0 + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "172.16.185.33" + } + }, + "endpoint_uuid": { + "uuid": "500" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.182.25" + } + }, + "endpoint_uuid": { + "uuid": "500" + } + } + ] + }, + { + "link_id": { + "link_uuid": { + "uuid": "172.16.182.25-501" + } + }, + "name": "172.16.182.25-501", + "attributes": { + "total_capacity_gbps": 10, + "used_capacity_gbps": 0 + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "172.16.182.25" + } + }, + "endpoint_uuid": { + "uuid": "501" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.185.31" + } + }, + "endpoint_uuid": { + "uuid": "501" + } + } + ] + }, + { + "link_id": { + "link_uuid": { + "uuid": "172.16.185.31-501" + } + }, + "name": "172.16.185.31-501", + "attributes": { + "total_capacity_gbps": 10, + "used_capacity_gbps": 0 + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "172.16.185.31" + } + }, + "endpoint_uuid": { + "uuid": "501" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.182.25" + } + }, + "endpoint_uuid": { + "uuid": "501" + } + } + ] + }, + { + "link_id": { + "link_uuid": { + "uuid": "172.16.185.31-500" + } + }, + "name": "172.16.185.31-500", + "attributes": { + "total_capacity_gbps": 10, + "used_capacity_gbps": 0 + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "172.16.185.31" + } + }, + "endpoint_uuid": { + "uuid": "500" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.185.32" + } + }, + "endpoint_uuid": { + "uuid": "500" + } + } + ] + }, + { + "link_id": { + "link_uuid": { + "uuid": "172.16.185.32-500" + } + }, + "name": "172.16.185.32-500", + "attributes": { + "total_capacity_gbps": 10, + "used_capacity_gbps": 0 + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "172.16.185.32" + } + }, + "endpoint_uuid": { + "uuid": "500" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.185.31" + } + }, + "endpoint_uuid": { + "uuid": "500" + } + } + ] + }, + { + "link_id": { + "link_uuid": { + "uuid": "172.16.185.33-501" + } + }, + "name": "172.16.185.33-501", + "attributes": { + "total_capacity_gbps": 10, + "used_capacity_gbps": 0 + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "172.16.185.33" + } + }, + "endpoint_uuid": { + "uuid": "501" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.185.32" + } + }, + "endpoint_uuid": { + "uuid": "501" + } + } + ] + }, + { + "link_id": { + "link_uuid": { + "uuid": "172.16.185.32-501" + } + }, + "name": "172.16.185.32-501", + "attributes": { + "total_capacity_gbps": 10, + "used_capacity_gbps": 0 + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "172.16.185.32" + } + }, + "endpoint_uuid": { + "uuid": "501" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.185.33" + } + }, + "endpoint_uuid": { + "uuid": "501" + } + } + ] + }, + { + "link_id": { + "link_uuid": { + "uuid": "172.16.185.32-200" + } + }, + "name": "172.16.185.32-200", + "attributes": { + "total_capacity_gbps": 10, + "used_capacity_gbps": 0 + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "172.16.185.32" + } + }, + "endpoint_uuid": { + "uuid": "200" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.204.220" + } + }, + "endpoint_uuid": { + "uuid": "500" + } + } + ] + }, + { + "link_id": { + "link_uuid": { + "uuid": "172.16.204.220-500" + } + }, + "name": "172.16.204.220-500", + "attributes": { + "total_capacity_gbps": 10, + "used_capacity_gbps": 0 + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "172.16.204.220" + } + }, + "endpoint_uuid": { + "uuid": "500" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.185.32" + } + }, + "endpoint_uuid": { + "uuid": "200" + } + } + ] + }, + { + "link_id": { + "link_uuid": { + "uuid": "172.16.182.25-200" + } + }, + "name": "172.16.182.25-200", + "attributes": { + "total_capacity_gbps": 10, + "used_capacity_gbps": 0 + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "172.16.182.25" + } + }, + "endpoint_uuid": { + "uuid": "200" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.58.10" + } + }, + "endpoint_uuid": { + "uuid": "500" + } + } + ] + }, + { + "link_id": { + "link_uuid": { + "uuid": "172.16.58.10-500" + } + }, + "name": "172.16.58.10-500", + "attributes": { + "total_capacity_gbps": 10, + "used_capacity_gbps": 0 + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "172.16.58.10" + } + }, + "endpoint_uuid": { + "uuid": "500" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.182.25" + } + }, + "endpoint_uuid": { + "uuid": "200" + } + } + ] + }, + { + "link_id": { + "link_uuid": { + "uuid": "172.16.58.10-200" + } + }, + "name": "172.16.58.10-200", + "attributes": { + "total_capacity_gbps": 10, + "used_capacity_gbps": 0 + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "172.16.58.10" + } + }, + "endpoint_uuid": { + "uuid": "200" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.61.10" + } + }, + "endpoint_uuid": { + "uuid": "500" + } + } + ] + }, + { + "link_id": { + "link_uuid": { + "uuid": "172.16.61.10-500" + } + }, + "name": "172.16.61.10-500", + "attributes": { + "total_capacity_gbps": 10, + "used_capacity_gbps": 0 + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "172.16.61.10" + } + }, + "endpoint_uuid": { + "uuid": "500" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.58.10" + } + }, + "endpoint_uuid": { + "uuid": "200" + } + } + ] + }, + { + "link_id": { + "link_uuid": { + "uuid": "172.16.58.10-201" + } + }, + "name": "172.16.58.10-201", + "attributes": { + "total_capacity_gbps": 10, + "used_capacity_gbps": 0 + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "172.16.58.10" + } + }, + "endpoint_uuid": { + "uuid": "201" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.61.11" + } + }, + "endpoint_uuid": { + "uuid": "500" + } + } + ] + }, + { + "link_id": { + "link_uuid": { + "uuid": "172.16.61.11-500" + } + }, + "name": "172.16.61.11-500", + "attributes": { + "total_capacity_gbps": 10, + "used_capacity_gbps": 0 + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "172.16.61.11" + } + }, + "endpoint_uuid": { + "uuid": "500" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.58.10" + } + }, + "endpoint_uuid": { + "uuid": "201" + } + } + ] + }, + { + "link_id": { + "link_uuid": { + "uuid": "172.16.61.10-200" + } + }, + "name": "172.16.61.10-200", + "attributes": { + "total_capacity_gbps": 10, + "used_capacity_gbps": 0 + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "172.16.61.10" + } + }, + "endpoint_uuid": { + "uuid": "200" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.104.221" + } + }, + "endpoint_uuid": { + "uuid": "eth0" + } + } + ] + }, + { + "link_id": { + "link_uuid": { + "uuid": "172.16.104.221-eth0" + } + }, + "name": "172.16.104.221-eth0", + "attributes": { + "total_capacity_gbps": 10, + "used_capacity_gbps": 0 + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "172.16.104.221" + } + }, + "endpoint_uuid": { + "uuid": "eth0" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.61.10" + } + }, + "endpoint_uuid": { + "uuid": "200" + } + } + ] + }, + { + "link_id": { + "link_uuid": { + "uuid": "172.16.61.11-200" + } + }, + "name": "172.16.61.11-200", + "attributes": { + "total_capacity_gbps": 10, + "used_capacity_gbps": 0 + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "172.16.61.11" + } + }, + "endpoint_uuid": { + "uuid": "200" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.104.222" + } + }, + "endpoint_uuid": { + "uuid": "eth0" + } + } + ] + }, + { + "link_id": { + "link_uuid": { + "uuid": "172.16.104.222-eth0" + } + }, + "name": "172.16.104.222-eth0", + "attributes": { + "total_capacity_gbps": 10, + "used_capacity_gbps": 0 + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "172.16.104.222" + } + }, + "endpoint_uuid": { + "uuid": "eth0" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.61.11" + } + }, + "endpoint_uuid": { + "uuid": "200" + } + } + ] + } + ] +} diff --git a/src/tests/ofc25/data/slice/post_connection_group_to_network_slice1.json b/src/tests/ofc25/data/slice/post_connection_group_to_network_slice1.json new file mode 100644 index 0000000000000000000000000000000000000000..d39a837bd8c3719463e8ecfd3fbfc2d25111afef --- /dev/null +++ b/src/tests/ofc25/data/slice/post_connection_group_to_network_slice1.json @@ -0,0 +1,62 @@ +{ + "connection-group": [ + { + "id": "line2", + "connectivity-type": "point-to-point", + "connectivity-construct": [ + { + "id": 1, + "p2p-sender-sdp": "1", + "p2p-receiver-sdp": "3", + "service-slo-sle-policy": { + "slo-policy": { + "metric-bound": [ + { + "metric-type": "ietf-network-slice-service:one-way-delay-maximum", + "metric-unit": "milliseconds", + "bound": "10" + }, + { + "metric-type": "ietf-network-slice-service:one-way-bandwidth", + "metric-unit": "Mbps", + "bound": "5000" + }, + { + "metric-type": "ietf-network-slice-service:two-way-packet-loss", + "metric-unit": "percentage", + "percentile-value": "0.001" + } + ] + } + } + }, + { + "id": 2, + "p2p-sender-sdp": "3", + "p2p-receiver-sdp": "1", + "service-slo-sle-policy": { + "slo-policy": { + "metric-bound": [ + { + "metric-type": "ietf-network-slice-service:one-way-delay-maximum", + "metric-unit": "milliseconds", + "bound": "20" + }, + { + "metric-type": "ietf-network-slice-service:one-way-bandwidth", + "metric-unit": "Mbps", + "bound": "1000" + }, + { + "metric-type": "ietf-network-slice-service:two-way-packet-loss", + "metric-unit": "percentage", + "percentile-value": "0.001" + } + ] + } + } + } + ] + } + ] +} \ No newline at end of file diff --git a/src/tests/ofc25/data/slice/post_connection_group_to_network_slice2.json b/src/tests/ofc25/data/slice/post_connection_group_to_network_slice2.json new file mode 100644 index 0000000000000000000000000000000000000000..d39a837bd8c3719463e8ecfd3fbfc2d25111afef --- /dev/null +++ b/src/tests/ofc25/data/slice/post_connection_group_to_network_slice2.json @@ -0,0 +1,62 @@ +{ + "connection-group": [ + { + "id": "line2", + "connectivity-type": "point-to-point", + "connectivity-construct": [ + { + "id": 1, + "p2p-sender-sdp": "1", + "p2p-receiver-sdp": "3", + "service-slo-sle-policy": { + "slo-policy": { + "metric-bound": [ + { + "metric-type": "ietf-network-slice-service:one-way-delay-maximum", + "metric-unit": "milliseconds", + "bound": "10" + }, + { + "metric-type": "ietf-network-slice-service:one-way-bandwidth", + "metric-unit": "Mbps", + "bound": "5000" + }, + { + "metric-type": "ietf-network-slice-service:two-way-packet-loss", + "metric-unit": "percentage", + "percentile-value": "0.001" + } + ] + } + } + }, + { + "id": 2, + "p2p-sender-sdp": "3", + "p2p-receiver-sdp": "1", + "service-slo-sle-policy": { + "slo-policy": { + "metric-bound": [ + { + "metric-type": "ietf-network-slice-service:one-way-delay-maximum", + "metric-unit": "milliseconds", + "bound": "20" + }, + { + "metric-type": "ietf-network-slice-service:one-way-bandwidth", + "metric-unit": "Mbps", + "bound": "1000" + }, + { + "metric-type": "ietf-network-slice-service:two-way-packet-loss", + "metric-unit": "percentage", + "percentile-value": "0.001" + } + ] + } + } + } + ] + } + ] +} \ No newline at end of file diff --git a/src/tests/ofc25/data/slice/post_match_criteria_to_sdp1_in_slice1.json b/src/tests/ofc25/data/slice/post_match_criteria_to_sdp1_in_slice1.json new file mode 100644 index 0000000000000000000000000000000000000000..16a36d45b86230b27eafa45a612b95c248a7b3ac --- /dev/null +++ b/src/tests/ofc25/data/slice/post_match_criteria_to_sdp1_in_slice1.json @@ -0,0 +1,40 @@ +{ + "match-criterion": [ + { + "index": 2, + "match-type": [ + { + "type": "ietf-network-slice-service:vlan", + "value": [ + "101" + ] + }, + { + "type": "ietf-network-slice-service:source-ip-prefix", + "value": [ + "172.1.101.22/24" + ] + }, + { + "type": "ietf-network-slice-service:source-tcp-port", + "value": [ + "10200" + ] + }, + { + "type": "ietf-network-slice-service:destination-ip-prefix", + "value": [ + "172.16.104.222/24" + ] + }, + { + "type": "ietf-network-slice-service:destination-tcp-port", + "value": [ + "10500" + ] + } + ], + "target-connection-group-id": "line2" + } + ] +} \ No newline at end of file diff --git a/src/tests/ofc25/data/slice/post_match_criteria_to_sdp1_in_slice2.json b/src/tests/ofc25/data/slice/post_match_criteria_to_sdp1_in_slice2.json new file mode 100644 index 0000000000000000000000000000000000000000..8ceefdc2f2471af225143e5a1def2d7ba71e2ab1 --- /dev/null +++ b/src/tests/ofc25/data/slice/post_match_criteria_to_sdp1_in_slice2.json @@ -0,0 +1,40 @@ +{ + "match-criterion": [ + { + "index": 2, + "match-type": [ + { + "type": "ietf-network-slice-service:vlan", + "value": [ + "201" + ] + }, + { + "type": "ietf-network-slice-service:source-ip-prefix", + "value": [ + "172.1.201.22/24" + ] + }, + { + "type": "ietf-network-slice-service:source-tcp-port", + "value": [ + "10200" + ] + }, + { + "type": "ietf-network-slice-service:destination-ip-prefix", + "value": [ + "172.16.104.222/24" + ] + }, + { + "type": "ietf-network-slice-service:destination-tcp-port", + "value": [ + "10500" + ] + } + ], + "target-connection-group-id": "line2" + } + ] +} \ No newline at end of file diff --git a/src/tests/ofc25/data/slice/post_network_slice1.json b/src/tests/ofc25/data/slice/post_network_slice1.json new file mode 100644 index 0000000000000000000000000000000000000000..e6e0ee90a25ff12f73c8f8896f9c2c74ab6b4019 --- /dev/null +++ b/src/tests/ofc25/data/slice/post_network_slice1.json @@ -0,0 +1,188 @@ +{ + "slice-service": [ + { + "id": "slice1", + "description": "network slice 1, connect to VM1", + "sdps": { + "sdp": [ + { + "id": "1", + "node-id": "172.16.204.220", + "sdp-ip-address": [ + "172.16.204.220" + ], + "service-match-criteria": { + "match-criterion": [ + { + "index": 1, + "match-type": [ + { + "type": "ietf-network-slice-service:vlan", + "value": [ + "101" + ] + }, + { + "type": "ietf-network-slice-service:destination-ip-prefix", + "value": [ + "172.16.104.221/24" + ] + }, + { + "type": "ietf-network-slice-service:destination-tcp-port", + "value": [ + "10500" + ] + }, + { + "type": "ietf-network-slice-service:source-ip-prefix", + "value": [ + "172.1.101.22/24" + ] + }, + { + "type": "ietf-network-slice-service:source-tcp-port", + "value": [ + "10200" + ] + } + ], + "target-connection-group-id": "line1" + } + ] + }, + "attachment-circuits": { + "attachment-circuit": [ + { + "id": "AC POP to VM1", + "description": "AC VM1 connected to POP", + "ac-node-id": "172.16.204.220", + "ac-tp-id": "200" + } + ] + } + }, + { + "id": "2", + "node-id": "172.16.61.10", + "sdp-ip-address": [ + "172.16.61.10" + ], + "service-match-criteria": { + "match-criterion": [ + { + "index": 1, + "match-type": [ + { + "type": "ietf-network-slice-service:vlan", + "value": [ + "21" + ] + }, + { + "type": "ietf-network-slice-service:source-ip-prefix", + "value": [ + "172.16.104.221/24" + ] + }, + { + "type": "ietf-network-slice-service:source-tcp-port", + "value": [ + "10500" + ] + }, + { + "type": "ietf-network-slice-service:destination-ip-prefix", + "value": [ + "172.1.101.22/24" + ] + }, + { + "type": "ietf-network-slice-service:destination-tcp-port", + "value": [ + "10200" + ] + } + ], + "target-connection-group-id": "line1" + } + ] + }, + "attachment-circuits": { + "attachment-circuit": [ + { + "id": "AC ONT", + "description": "AC connected to PC1", + "ac-node-id": "172.16.61.10", + "ac-tp-id": "200" + } + ] + } + } + ] + }, + "connection-groups": { + "connection-group": [ + { + "id": "line1", + "connectivity-type": "point-to-point", + "connectivity-construct": [ + { + "id": 1, + "p2p-sender-sdp": "1", + "p2p-receiver-sdp": "2", + "service-slo-sle-policy": { + "slo-policy": { + "metric-bound": [ + { + "metric-type": "ietf-network-slice-service:one-way-delay-maximum", + "metric-unit": "milliseconds", + "bound": "10" + }, + { + "metric-type": "ietf-network-slice-service:one-way-bandwidth", + "metric-unit": "Mbps", + "bound": "5000" + }, + { + "metric-type": "ietf-network-slice-service:two-way-packet-loss", + "metric-unit": "percentage", + "percentile-value": "0.001" + } + ] + } + } + }, + { + "id": 2, + "p2p-sender-sdp": "2", + "p2p-receiver-sdp": "1", + "service-slo-sle-policy": { + "slo-policy": { + "metric-bound": [ + { + "metric-type": "ietf-network-slice-service:one-way-delay-maximum", + "metric-unit": "milliseconds", + "bound": "20" + }, + { + "metric-type": "ietf-network-slice-service:one-way-bandwidth", + "metric-unit": "Mbps", + "bound": "1000" + }, + { + "metric-type": "ietf-network-slice-service:two-way-packet-loss", + "metric-unit": "percentage", + "percentile-value": "0.001" + } + ] + } + } + } + ] + } + ] + } + } + ] +} \ No newline at end of file diff --git a/src/tests/ofc25/data/slice/post_network_slice2.json b/src/tests/ofc25/data/slice/post_network_slice2.json new file mode 100644 index 0000000000000000000000000000000000000000..97e6ade27449be0a3816085aa31b707ffbb6f813 --- /dev/null +++ b/src/tests/ofc25/data/slice/post_network_slice2.json @@ -0,0 +1,189 @@ +{ + "slice-service": [ + { + "id": "slice2", + "description": "network slice 2, connect to VM2", + "sdps": { + "sdp": [ + { + "id": "1", + "node-id": "172.16.204.220", + "sdp-ip-address": [ + "172.16.204.220" + ], + "service-match-criteria": { + "match-criterion": [ + { + "index": 1, + "match-type": [ + { + "type": "ietf-network-slice-service:vlan", + "value": [ + "201" + ] + }, + { + "type": "ietf-network-slice-service:destination-ip-prefix", + "value": [ + "172.16.104.221/24" + ] + }, + { + "type": "ietf-network-slice-service:destination-tcp-port", + "value": [ + "10500" + ] + }, + { + "type": "ietf-network-slice-service:source-ip-prefix", + "value": [ + "172.1.201.22/24" + ] + }, + { + "type": "ietf-network-slice-service:source-tcp-port", + "value": [ + "10200" + ] + } + ], + "target-connection-group-id": "line1" + } + ] + }, + "attachment-circuits": { + "attachment-circuit": [ + { + "id": "AC POP to VM2", + "description": "AC VM2 connected to POP", + "ac-node-id": "172.16.204.220", + "ac-tp-id": "201" + } + ] + } + }, + { + "id": "2", + "node-id": "172.16.61.10", + "sdp-ip-address": [ + "172.16.61.10" + ], + "service-match-criteria": { + "match-criterion": [ + { + "index": 1, + "match-type": [ + { + "type": "ietf-network-slice-service:vlan", + "value": [ + "31" + ] + }, + { + "type": "ietf-network-slice-service:source-ip-prefix", + "value": [ + "172.16.104.221/24" + ] + }, + { + "type": "ietf-network-slice-service:source-tcp-port", + "value": [ + "10500" + ] + }, + { + "type": "ietf-network-slice-service:destination-ip-prefix", + "value": [ + "172.1.201.22/24" + ] + }, + { + "type": "ietf-network-slice-service:destination-tcp-port", + "value": [ + "10200" + ] + } + ], + "target-connection-group-id": "line1" + } + ] + }, + "attachment-circuits": { + "attachment-circuit": [ + { + "id": "AC ONT", + "description": "AC connected to PC", + "ac-node-id": "172.16.61.10", + "ac-tp-id": "200", + "ac-ipv4-address": "172.16.61.10" + } + ] + } + } + ] + }, + "connection-groups": { + "connection-group": [ + { + "id": "line1", + "connectivity-type": "point-to-point", + "connectivity-construct": [ + { + "id": 1, + "p2p-sender-sdp": "1", + "p2p-receiver-sdp": "2", + "service-slo-sle-policy": { + "slo-policy": { + "metric-bound": [ + { + "metric-type": "ietf-network-slice-service:one-way-delay-maximum", + "metric-unit": "milliseconds", + "bound": "10" + }, + { + "metric-type": "ietf-network-slice-service:one-way-bandwidth", + "metric-unit": "Mbps", + "bound": "5000" + }, + { + "metric-type": "ietf-network-slice-service:two-way-packet-loss", + "metric-unit": "percentage", + "percentile-value": "0.001" + } + ] + } + } + }, + { + "id": 2, + "p2p-sender-sdp": "2", + "p2p-receiver-sdp": "1", + "service-slo-sle-policy": { + "slo-policy": { + "metric-bound": [ + { + "metric-type": "ietf-network-slice-service:one-way-delay-maximum", + "metric-unit": "milliseconds", + "bound": "20" + }, + { + "metric-type": "ietf-network-slice-service:one-way-bandwidth", + "metric-unit": "Mbps", + "bound": "1000" + }, + { + "metric-type": "ietf-network-slice-service:two-way-packet-loss", + "metric-unit": "percentage", + "percentile-value": "0.001" + } + ] + } + } + } + ] + } + ] + } + } + ] +} diff --git a/src/tests/ofc25/data/slice/post_sdp_to_network_slice1.json b/src/tests/ofc25/data/slice/post_sdp_to_network_slice1.json new file mode 100644 index 0000000000000000000000000000000000000000..bd3895fc4ae5a9a0b2059be3f6b31a05451abd22 --- /dev/null +++ b/src/tests/ofc25/data/slice/post_sdp_to_network_slice1.json @@ -0,0 +1,61 @@ +{ + "sdp": [ + { + "id": "3", + "node-id": "172.16.61.11", + "sdp-ip-address": [ + "172.16.61.11" + ], + "service-match-criteria": { + "match-criterion": [ + { + "index": 1, + "match-type": [ + { + "type": "ietf-network-slice-service:vlan", + "value": [ + "21" + ] + }, + { + "type": "ietf-network-slice-service:source-ip-prefix", + "value": [ + "172.16.104.222/24" + ] + }, + { + "type": "ietf-network-slice-service:source-tcp-port", + "value": [ + "10500" + ] + }, + { + "type": "ietf-network-slice-service:destination-ip-prefix", + "value": [ + "172.1.101.22/24" + ] + }, + { + "type": "ietf-network-slice-service:destination-tcp-port", + "value": [ + "10200" + ] + } + ], + "target-connection-group-id": "line2" + } + ] + }, + "attachment-circuits": { + "attachment-circuit": [ + { + "id": "AC ONT", + "description": "AC connected to PC2", + "ac-node-id": "172.16.61.11", + "ac-tp-id": "200" + } + ] + } + } + ] +} \ No newline at end of file diff --git a/src/tests/ofc25/data/slice/post_sdp_to_network_slice2.json b/src/tests/ofc25/data/slice/post_sdp_to_network_slice2.json new file mode 100644 index 0000000000000000000000000000000000000000..0b147125bd7eb3efc84c87bebab919639782f760 --- /dev/null +++ b/src/tests/ofc25/data/slice/post_sdp_to_network_slice2.json @@ -0,0 +1,62 @@ +{ + "sdp": [ + { + "id": "3", + "node-id": "172.16.61.11", + "sdp-ip-address": [ + "172.16.61.11" + ], + "service-match-criteria": { + "match-criterion": [ + { + "index": 1, + "match-type": [ + { + "type": "ietf-network-slice-service:vlan", + "value": [ + "31" + ] + }, + { + "type": "ietf-network-slice-service:source-ip-prefix", + "value": [ + "172.16.104.222/24" + ] + }, + { + "type": "ietf-network-slice-service:source-tcp-port", + "value": [ + "10500" + ] + }, + { + "type": "ietf-network-slice-service:destination-ip-prefix", + "value": [ + "172.1.201.22/24" + ] + }, + { + "type": "ietf-network-slice-service:destination-tcp-port", + "value": [ + "10200" + ] + } + ], + "target-connection-group-id": "line2" + } + ] + }, + "attachment-circuits": { + "attachment-circuit": [ + { + "id": "AC ONT", + "description": "AC connected to PC2", + "ac-node-id": "172.16.61.11", + "ac-tp-id": "200", + "ac-ipv4-address": "172.16.61.11" + } + ] + } + } + ] +} \ No newline at end of file diff --git a/src/tests/ofc25/data/slice/target-full-ietf-slice.json b/src/tests/ofc25/data/slice/target-full-ietf-slice.json new file mode 100644 index 0000000000000000000000000000000000000000..c99876ad9e00e2f94ce44d17b2376f61282e60d7 --- /dev/null +++ b/src/tests/ofc25/data/slice/target-full-ietf-slice.json @@ -0,0 +1,678 @@ +{ + "network-slice-services": { + "slice-service": [ + { + "connection-groups": { + "connection-group": [ + { + "connectivity-construct": [ + { + "id": 1, + "p2p-receiver-sdp": "2", + "p2p-sender-sdp": "1", + "service-slo-sle-policy": { + "slo-policy": { + "metric-bound": [ + { + "bound": "10", + "metric-type": "ietf-network-slice-service:one-way-delay-maximum", + "metric-unit": "milliseconds" + }, + { + "bound": "5000", + "metric-type": "ietf-network-slice-service:one-way-bandwidth", + "metric-unit": "Mbps" + }, + { + "metric-type": "ietf-network-slice-service:two-way-packet-loss", + "metric-unit": "percentage", + "percentile-value": "0.001" + } + ] + } + } + }, + { + "id": 2, + "p2p-receiver-sdp": "1", + "p2p-sender-sdp": "2", + "service-slo-sle-policy": { + "slo-policy": { + "metric-bound": [ + { + "bound": "20", + "metric-type": "ietf-network-slice-service:one-way-delay-maximum", + "metric-unit": "milliseconds" + }, + { + "bound": "1000", + "metric-type": "ietf-network-slice-service:one-way-bandwidth", + "metric-unit": "Mbps" + }, + { + "metric-type": "ietf-network-slice-service:two-way-packet-loss", + "metric-unit": "percentage", + "percentile-value": "0.001" + } + ] + } + } + } + ], + "connectivity-type": "point-to-point", + "id": "line1" + }, + { + "connectivity-construct": [ + { + "id": 1, + "p2p-receiver-sdp": "3", + "p2p-sender-sdp": "1", + "service-slo-sle-policy": { + "slo-policy": { + "metric-bound": [ + { + "bound": "10", + "metric-type": "ietf-network-slice-service:one-way-delay-maximum", + "metric-unit": "milliseconds" + }, + { + "bound": "5000", + "metric-type": "ietf-network-slice-service:one-way-bandwidth", + "metric-unit": "Mbps" + }, + { + "metric-type": "ietf-network-slice-service:two-way-packet-loss", + "metric-unit": "percentage", + "percentile-value": "0.001" + } + ] + } + } + }, + { + "id": 2, + "p2p-receiver-sdp": "1", + "p2p-sender-sdp": "3", + "service-slo-sle-policy": { + "slo-policy": { + "metric-bound": [ + { + "bound": "20", + "metric-type": "ietf-network-slice-service:one-way-delay-maximum", + "metric-unit": "milliseconds" + }, + { + "bound": "1000", + "metric-type": "ietf-network-slice-service:one-way-bandwidth", + "metric-unit": "Mbps" + }, + { + "metric-type": "ietf-network-slice-service:two-way-packet-loss", + "metric-unit": "percentage", + "percentile-value": "0.001" + } + ] + } + } + } + ], + "connectivity-type": "point-to-point", + "id": "line2" + } + ] + }, + "description": "network slice 2, connect to VM2", + "id": "slice2", + "sdps": { + "sdp": [ + { + "attachment-circuits": { + "attachment-circuit": [ + { + "ac-node-id": "172.16.204.220", + "ac-tp-id": "201", + "description": "AC VM2 connected to POP", + "id": "AC POP to VM2" + } + ] + }, + "id": "1", + "node-id": "172.16.204.220", + "sdp-ip-address": [ + "172.16.204.220" + ], + "service-match-criteria": { + "match-criterion": [ + { + "index": 1, + "match-type": [ + { + "type": "ietf-network-slice-service:vlan", + "value": [ + "201" + ] + }, + { + "type": "ietf-network-slice-service:destination-ip-prefix", + "value": [ + "172.16.104.221/24" + ] + }, + { + "type": "ietf-network-slice-service:destination-tcp-port", + "value": [ + "10500" + ] + }, + { + "type": "ietf-network-slice-service:source-ip-prefix", + "value": [ + "172.1.201.22/24" + ] + }, + { + "type": "ietf-network-slice-service:source-tcp-port", + "value": [ + "10200" + ] + } + ], + "target-connection-group-id": "line1" + }, + { + "index": 2, + "match-type": [ + { + "type": "ietf-network-slice-service:vlan", + "value": [ + "201" + ] + }, + { + "type": "ietf-network-slice-service:source-ip-prefix", + "value": [ + "172.1.201.22/24" + ] + }, + { + "type": "ietf-network-slice-service:source-tcp-port", + "value": [ + "10200" + ] + }, + { + "type": "ietf-network-slice-service:destination-ip-prefix", + "value": [ + "172.16.104.222/24" + ] + }, + { + "type": "ietf-network-slice-service:destination-tcp-port", + "value": [ + "10500" + ] + } + ], + "target-connection-group-id": "line2" + } + ] + } + }, + { + "attachment-circuits": { + "attachment-circuit": [ + { + "ac-ipv4-address": "172.16.61.10", + "ac-node-id": "172.16.61.10", + "ac-tp-id": "200", + "description": "AC connected to PC", + "id": "AC ONT" + } + ] + }, + "id": "2", + "node-id": "172.16.61.10", + "sdp-ip-address": [ + "172.16.61.10" + ], + "service-match-criteria": { + "match-criterion": [ + { + "index": 1, + "match-type": [ + { + "type": "ietf-network-slice-service:vlan", + "value": [ + "31" + ] + }, + { + "type": "ietf-network-slice-service:source-ip-prefix", + "value": [ + "172.16.104.221/24" + ] + }, + { + "type": "ietf-network-slice-service:source-tcp-port", + "value": [ + "10500" + ] + }, + { + "type": "ietf-network-slice-service:destination-ip-prefix", + "value": [ + "172.1.201.22/24" + ] + }, + { + "type": "ietf-network-slice-service:destination-tcp-port", + "value": [ + "10200" + ] + } + ], + "target-connection-group-id": "line1" + } + ] + } + }, + { + "attachment-circuits": { + "attachment-circuit": [ + { + "ac-ipv4-address": "172.16.61.11", + "ac-node-id": "172.16.61.11", + "ac-tp-id": "200", + "description": "AC connected to PC2", + "id": "AC ONT" + } + ] + }, + "id": "3", + "node-id": "172.16.61.11", + "sdp-ip-address": [ + "172.16.61.11" + ], + "service-match-criteria": { + "match-criterion": [ + { + "index": 1, + "match-type": [ + { + "type": "ietf-network-slice-service:vlan", + "value": [ + "31" + ] + }, + { + "type": "ietf-network-slice-service:source-ip-prefix", + "value": [ + "172.16.104.222/24" + ] + }, + { + "type": "ietf-network-slice-service:source-tcp-port", + "value": [ + "10500" + ] + }, + { + "type": "ietf-network-slice-service:destination-ip-prefix", + "value": [ + "172.1.201.22/24" + ] + }, + { + "type": "ietf-network-slice-service:destination-tcp-port", + "value": [ + "10200" + ] + } + ], + "target-connection-group-id": "line2" + } + ] + } + } + ] + } + }, + { + "connection-groups": { + "connection-group": [ + { + "connectivity-construct": [ + { + "id": 1, + "p2p-receiver-sdp": "2", + "p2p-sender-sdp": "1", + "service-slo-sle-policy": { + "slo-policy": { + "metric-bound": [ + { + "bound": "10", + "metric-type": "ietf-network-slice-service:one-way-delay-maximum", + "metric-unit": "milliseconds" + }, + { + "bound": "5000", + "metric-type": "ietf-network-slice-service:one-way-bandwidth", + "metric-unit": "Mbps" + }, + { + "metric-type": "ietf-network-slice-service:two-way-packet-loss", + "metric-unit": "percentage", + "percentile-value": "0.001" + } + ] + } + } + }, + { + "id": 2, + "p2p-receiver-sdp": "1", + "p2p-sender-sdp": "2", + "service-slo-sle-policy": { + "slo-policy": { + "metric-bound": [ + { + "bound": "20", + "metric-type": "ietf-network-slice-service:one-way-delay-maximum", + "metric-unit": "milliseconds" + }, + { + "bound": "1000", + "metric-type": "ietf-network-slice-service:one-way-bandwidth", + "metric-unit": "Mbps" + }, + { + "metric-type": "ietf-network-slice-service:two-way-packet-loss", + "metric-unit": "percentage", + "percentile-value": "0.001" + } + ] + } + } + } + ], + "connectivity-type": "point-to-point", + "id": "line1" + }, + { + "connectivity-construct": [ + { + "id": 1, + "p2p-receiver-sdp": "3", + "p2p-sender-sdp": "1", + "service-slo-sle-policy": { + "slo-policy": { + "metric-bound": [ + { + "bound": "10", + "metric-type": "ietf-network-slice-service:one-way-delay-maximum", + "metric-unit": "milliseconds" + }, + { + "bound": "5000", + "metric-type": "ietf-network-slice-service:one-way-bandwidth", + "metric-unit": "Mbps" + }, + { + "metric-type": "ietf-network-slice-service:two-way-packet-loss", + "metric-unit": "percentage", + "percentile-value": "0.001" + } + ] + } + } + }, + { + "id": 2, + "p2p-receiver-sdp": "1", + "p2p-sender-sdp": "3", + "service-slo-sle-policy": { + "slo-policy": { + "metric-bound": [ + { + "bound": "20", + "metric-type": "ietf-network-slice-service:one-way-delay-maximum", + "metric-unit": "milliseconds" + }, + { + "bound": "1000", + "metric-type": "ietf-network-slice-service:one-way-bandwidth", + "metric-unit": "Mbps" + }, + { + "metric-type": "ietf-network-slice-service:two-way-packet-loss", + "metric-unit": "percentage", + "percentile-value": "0.001" + } + ] + } + } + } + ], + "connectivity-type": "point-to-point", + "id": "line2" + } + ] + }, + "description": "network slice 1, connect to VM1", + "id": "slice1", + "sdps": { + "sdp": [ + { + "attachment-circuits": { + "attachment-circuit": [ + { + "ac-node-id": "172.16.204.220", + "ac-tp-id": "200", + "description": "AC VM1 connected to POP", + "id": "AC POP to VM1" + } + ] + }, + "id": "1", + "node-id": "172.16.204.220", + "sdp-ip-address": [ + "172.16.204.220" + ], + "service-match-criteria": { + "match-criterion": [ + { + "index": 1, + "match-type": [ + { + "type": "ietf-network-slice-service:vlan", + "value": [ + "101" + ] + }, + { + "type": "ietf-network-slice-service:destination-ip-prefix", + "value": [ + "172.16.104.221/24" + ] + }, + { + "type": "ietf-network-slice-service:destination-tcp-port", + "value": [ + "10500" + ] + }, + { + "type": "ietf-network-slice-service:source-ip-prefix", + "value": [ + "172.1.101.22/24" + ] + }, + { + "type": "ietf-network-slice-service:source-tcp-port", + "value": [ + "10200" + ] + } + ], + "target-connection-group-id": "line1" + }, + { + "index": 2, + "match-type": [ + { + "type": "ietf-network-slice-service:vlan", + "value": [ + "101" + ] + }, + { + "type": "ietf-network-slice-service:source-ip-prefix", + "value": [ + "172.1.101.22/24" + ] + }, + { + "type": "ietf-network-slice-service:source-tcp-port", + "value": [ + "10200" + ] + }, + { + "type": "ietf-network-slice-service:destination-ip-prefix", + "value": [ + "172.16.104.222/24" + ] + }, + { + "type": "ietf-network-slice-service:destination-tcp-port", + "value": [ + "10500" + ] + } + ], + "target-connection-group-id": "line2" + } + ] + } + }, + { + "attachment-circuits": { + "attachment-circuit": [ + { + "ac-node-id": "172.16.61.10", + "ac-tp-id": "200", + "description": "AC connected to PC1", + "id": "AC ONT" + } + ] + }, + "id": "2", + "node-id": "172.16.61.10", + "sdp-ip-address": [ + "172.16.61.10" + ], + "service-match-criteria": { + "match-criterion": [ + { + "index": 1, + "match-type": [ + { + "type": "ietf-network-slice-service:vlan", + "value": [ + "21" + ] + }, + { + "type": "ietf-network-slice-service:source-ip-prefix", + "value": [ + "172.16.104.221/24" + ] + }, + { + "type": "ietf-network-slice-service:source-tcp-port", + "value": [ + "10500" + ] + }, + { + "type": "ietf-network-slice-service:destination-ip-prefix", + "value": [ + "172.1.101.22/24" + ] + }, + { + "type": "ietf-network-slice-service:destination-tcp-port", + "value": [ + "10200" + ] + } + ], + "target-connection-group-id": "line1" + } + ] + } + }, + { + "attachment-circuits": { + "attachment-circuit": [ + { + "ac-node-id": "172.16.61.11", + "ac-tp-id": "200", + "description": "AC connected to PC2", + "id": "AC ONT" + } + ] + }, + "id": "3", + "node-id": "172.16.61.11", + "sdp-ip-address": [ + "172.16.61.11" + ], + "service-match-criteria": { + "match-criterion": [ + { + "index": 1, + "match-type": [ + { + "type": "ietf-network-slice-service:vlan", + "value": [ + "21" + ] + }, + { + "type": "ietf-network-slice-service:source-ip-prefix", + "value": [ + "172.16.104.222/24" + ] + }, + { + "type": "ietf-network-slice-service:source-tcp-port", + "value": [ + "10500" + ] + }, + { + "type": "ietf-network-slice-service:destination-ip-prefix", + "value": [ + "172.1.101.22/24" + ] + }, + { + "type": "ietf-network-slice-service:destination-tcp-port", + "value": [ + "10200" + ] + } + ], + "target-connection-group-id": "line2" + } + ] + } + } + ] + } + } + ] + } +} diff --git a/src/tests/ofc25/data/target-ietf-slice-posted-slices.json b/src/tests/ofc25/data/target-ietf-slice-posted-slices.json new file mode 100644 index 0000000000000000000000000000000000000000..004d3cafff0decf4cbe550f555e99b2229702b07 --- /dev/null +++ b/src/tests/ofc25/data/target-ietf-slice-posted-slices.json @@ -0,0 +1,382 @@ +[ + { + "network-slice-services": { + "slice-service": [ + { + "connection-groups": { + "connection-group": [ + { + "connectivity-construct": [ + { + "id": 1, + "p2p-receiver-sdp": "2", + "p2p-sender-sdp": "1", + "service-slo-sle-policy": { + "slo-policy": { + "metric-bound": [ + { + "bound": 10, + "metric-type": "ietf-network-slice-service:one-way-delay-maximum", + "metric-unit": "milliseconds" + }, + { + "bound": 5000, + "metric-type": "ietf-network-slice-service:one-way-bandwidth", + "metric-unit": "Mbps" + }, + { + "metric-type": "ietf-network-slice-service:two-way-packet-loss", + "metric-unit": "percentage", + "percentile-value": 0.001 + } + ] + } + } + }, + { + "id": 2, + "p2p-receiver-sdp": "1", + "p2p-sender-sdp": "2", + "service-slo-sle-policy": { + "slo-policy": { + "metric-bound": [ + { + "bound": 20, + "metric-type": "ietf-network-slice-service:one-way-delay-maximum", + "metric-unit": "milliseconds" + }, + { + "bound": 1000, + "metric-type": "ietf-network-slice-service:one-way-bandwidth", + "metric-unit": "Mbps" + }, + { + "metric-type": "ietf-network-slice-service:two-way-packet-loss", + "metric-unit": "percentage", + "percentile-value": 0.001 + } + ] + } + } + } + ], + "connectivity-type": "point-to-point", + "id": "line1" + } + ] + }, + "description": "dsc", + "id": "slice1", + "sdps": { + "sdp": [ + { + "attachment-circuits": { + "attachment-circuit": [ + { + "ac-node-id": "172.16.185.32", + "ac-tp-id": "200", + "description": "dsc", + "id": "0" + } + ] + }, + "id": "1", + "node-id": "172.16.185.32", + "sdp-ip-address": [ + "172.16.185.32" + ], + "service-match-criteria": { + "match-criterion": [ + { + "index": 1, + "match-type": [ + { + "type": "ietf-network-slice-service:vlan", + "value": [ + "101" + ] + }, + { + "type": "ietf-network-slice-service:source-ip-prefix", + "value": [ + "172.1.101.22/24" + ] + }, + { + "type": "ietf-network-slice-service:source-tcp-port", + "value": [ + "10200" + ] + }, + { + "type": "ietf-network-slice-service:destination-ip-prefix", + "value": [ + "172.16.104.221/24" + ] + }, + { + "type": "ietf-network-slice-service:destination-tcp-port", + "value": [ + "10500" + ] + } + ], + "target-connection-group-id": "line1" + } + ] + } + }, + { + "attachment-circuits": { + "attachment-circuit": [ + { + "ac-node-id": "172.16.182.25", + "ac-tp-id": "200", + "description": "dsc", + "id": "0" + } + ] + }, + "id": "2", + "node-id": "172.16.182.25", + "sdp-ip-address": [ + "172.16.182.25" + ], + "service-match-criteria": { + "match-criterion": [ + { + "index": 1, + "match-type": [ + { + "type": "ietf-network-slice-service:vlan", + "value": [ + "21" + ] + }, + { + "type": "ietf-network-slice-service:source-ip-prefix", + "value": [ + "172.16.104.221/24" + ] + }, + { + "type": "ietf-network-slice-service:source-tcp-port", + "value": [ + "10500" + ] + }, + { + "type": "ietf-network-slice-service:destination-ip-prefix", + "value": [ + "172.1.101.22/24" + ] + }, + { + "type": "ietf-network-slice-service:destination-tcp-port", + "value": [ + "10200" + ] + } + ], + "target-connection-group-id": "line1" + } + ] + } + } + ] + } + } + ] + } + }, + { + "network-slice-services": { + "slice-service": [ + { + "connection-groups": { + "connection-group": [ + { + "connectivity-construct": [ + { + "id": 1, + "p2p-receiver-sdp": "2", + "p2p-sender-sdp": "1", + "service-slo-sle-policy": { + "slo-policy": { + "metric-bound": [ + { + "bound": 10, + "metric-type": "ietf-network-slice-service:one-way-delay-maximum", + "metric-unit": "milliseconds" + }, + { + "bound": 5000, + "metric-type": "ietf-network-slice-service:one-way-bandwidth", + "metric-unit": "Mbps" + }, + { + "metric-type": "ietf-network-slice-service:two-way-packet-loss", + "metric-unit": "percentage", + "percentile-value": 0.001 + } + ] + } + } + }, + { + "id": 2, + "p2p-receiver-sdp": "1", + "p2p-sender-sdp": "2", + "service-slo-sle-policy": { + "slo-policy": { + "metric-bound": [ + { + "bound": 20, + "metric-type": "ietf-network-slice-service:one-way-delay-maximum", + "metric-unit": "milliseconds" + }, + { + "bound": 1000, + "metric-type": "ietf-network-slice-service:one-way-bandwidth", + "metric-unit": "Mbps" + }, + { + "metric-type": "ietf-network-slice-service:two-way-packet-loss", + "metric-unit": "percentage", + "percentile-value": 0.001 + } + ] + } + } + } + ], + "connectivity-type": "point-to-point", + "id": "line1" + } + ] + }, + "description": "dsc", + "id": "slice2", + "sdps": { + "sdp": [ + { + "attachment-circuits": { + "attachment-circuit": [ + { + "ac-node-id": "172.16.185.32", + "ac-tp-id": "200", + "description": "dsc", + "id": "0" + } + ] + }, + "id": "1", + "node-id": "172.16.185.32", + "sdp-ip-address": [ + "172.16.185.32" + ], + "service-match-criteria": { + "match-criterion": [ + { + "index": 1, + "match-type": [ + { + "type": "ietf-network-slice-service:vlan", + "value": [ + "201" + ] + }, + { + "type": "ietf-network-slice-service:source-ip-prefix", + "value": [ + "172.1.201.22/24" + ] + }, + { + "type": "ietf-network-slice-service:source-tcp-port", + "value": [ + "10200" + ] + }, + { + "type": "ietf-network-slice-service:destination-ip-prefix", + "value": [ + "172.16.104.221/24" + ] + }, + { + "type": "ietf-network-slice-service:destination-tcp-port", + "value": [ + "10500" + ] + } + ], + "target-connection-group-id": "line1" + } + ] + } + }, + { + "attachment-circuits": { + "attachment-circuit": [ + { + "ac-node-id": "172.16.182.25", + "ac-tp-id": "200", + "description": "dsc", + "id": "0" + } + ] + }, + "id": "2", + "node-id": "172.16.182.25", + "sdp-ip-address": [ + "172.16.182.25" + ], + "service-match-criteria": { + "match-criterion": [ + { + "index": 1, + "match-type": [ + { + "type": "ietf-network-slice-service:vlan", + "value": [ + "31" + ] + }, + { + "type": "ietf-network-slice-service:source-ip-prefix", + "value": [ + "172.16.104.221/24" + ] + }, + { + "type": "ietf-network-slice-service:source-tcp-port", + "value": [ + "10500" + ] + }, + { + "type": "ietf-network-slice-service:destination-ip-prefix", + "value": [ + "172.1.201.22/24" + ] + }, + { + "type": "ietf-network-slice-service:destination-tcp-port", + "value": [ + "10200" + ] + } + ], + "target-connection-group-id": "line1" + } + ] + } + } + ] + } + } + ] + } + } +] diff --git a/src/tests/ofc25/data/target-ietf-slice-put-connection-groups.json b/src/tests/ofc25/data/target-ietf-slice-put-connection-groups.json new file mode 100644 index 0000000000000000000000000000000000000000..7526ebd8b92a2eab7f30d94a035ba63f0a503c2d --- /dev/null +++ b/src/tests/ofc25/data/target-ietf-slice-put-connection-groups.json @@ -0,0 +1,234 @@ +[ + { + "connectivity-construct": [ + { + "id": 1, + "p2p-receiver-sdp": "2", + "p2p-sender-sdp": "1", + "service-slo-sle-policy": { + "slo-policy": { + "metric-bound": [ + { + "bound": 10, + "metric-type": "ietf-network-slice-service:one-way-delay-maximum", + "metric-unit": "milliseconds" + }, + { + "bound": 10000, + "metric-type": "ietf-network-slice-service:one-way-bandwidth", + "metric-unit": "Mbps" + }, + { + "metric-type": "ietf-network-slice-service:two-way-packet-loss", + "metric-unit": "percentage", + "percentile-value": 0.001 + } + ] + } + } + }, + { + "id": 2, + "p2p-receiver-sdp": "1", + "p2p-sender-sdp": "2", + "service-slo-sle-policy": { + "slo-policy": { + "metric-bound": [ + { + "bound": 20, + "metric-type": "ietf-network-slice-service:one-way-delay-maximum", + "metric-unit": "milliseconds" + }, + { + "bound": 2000, + "metric-type": "ietf-network-slice-service:one-way-bandwidth", + "metric-unit": "Mbps" + }, + { + "metric-type": "ietf-network-slice-service:two-way-packet-loss", + "metric-unit": "percentage", + "percentile-value": 0.001 + } + ] + } + } + } + ], + "connectivity-type": "point-to-point", + "id": "line1" + }, + { + "connectivity-construct": [ + { + "id": 1, + "p2p-receiver-sdp": "2", + "p2p-sender-sdp": "1", + "service-slo-sle-policy": { + "slo-policy": { + "metric-bound": [ + { + "bound": 10, + "metric-type": "ietf-network-slice-service:one-way-delay-maximum", + "metric-unit": "milliseconds" + }, + { + "bound": 10000, + "metric-type": "ietf-network-slice-service:one-way-bandwidth", + "metric-unit": "Mbps" + }, + { + "metric-type": "ietf-network-slice-service:two-way-packet-loss", + "metric-unit": "percentage", + "percentile-value": 0.001 + } + ] + } + } + }, + { + "id": 2, + "p2p-receiver-sdp": "1", + "p2p-sender-sdp": "2", + "service-slo-sle-policy": { + "slo-policy": { + "metric-bound": [ + { + "bound": 20, + "metric-type": "ietf-network-slice-service:one-way-delay-maximum", + "metric-unit": "milliseconds" + }, + { + "bound": 2000, + "metric-type": "ietf-network-slice-service:one-way-bandwidth", + "metric-unit": "Mbps" + }, + { + "metric-type": "ietf-network-slice-service:two-way-packet-loss", + "metric-unit": "percentage", + "percentile-value": 0.001 + } + ] + } + } + } + ], + "connectivity-type": "point-to-point", + "id": "line1" + }, + { + "connectivity-construct": [ + { + "id": 1, + "p2p-receiver-sdp": "2", + "p2p-sender-sdp": "1", + "service-slo-sle-policy": { + "slo-policy": { + "metric-bound": [ + { + "bound": 10, + "metric-type": "ietf-network-slice-service:one-way-delay-maximum", + "metric-unit": "milliseconds" + }, + { + "bound": 5000, + "metric-type": "ietf-network-slice-service:one-way-bandwidth", + "metric-unit": "Mbps" + }, + { + "metric-type": "ietf-network-slice-service:two-way-packet-loss", + "metric-unit": "percentage", + "percentile-value": 0.001 + } + ] + } + } + }, + { + "id": 2, + "p2p-receiver-sdp": "1", + "p2p-sender-sdp": "2", + "service-slo-sle-policy": { + "slo-policy": { + "metric-bound": [ + { + "bound": 20, + "metric-type": "ietf-network-slice-service:one-way-delay-maximum", + "metric-unit": "milliseconds" + }, + { + "bound": 1000, + "metric-type": "ietf-network-slice-service:one-way-bandwidth", + "metric-unit": "Mbps" + }, + { + "metric-type": "ietf-network-slice-service:two-way-packet-loss", + "metric-unit": "percentage", + "percentile-value": 0.001 + } + ] + } + } + } + ], + "connectivity-type": "point-to-point", + "id": "line1" + }, + { + "connectivity-construct": [ + { + "id": 1, + "p2p-receiver-sdp": "2", + "p2p-sender-sdp": "1", + "service-slo-sle-policy": { + "slo-policy": { + "metric-bound": [ + { + "bound": 10, + "metric-type": "ietf-network-slice-service:one-way-delay-maximum", + "metric-unit": "milliseconds" + }, + { + "bound": 5000, + "metric-type": "ietf-network-slice-service:one-way-bandwidth", + "metric-unit": "Mbps" + }, + { + "metric-type": "ietf-network-slice-service:two-way-packet-loss", + "metric-unit": "percentage", + "percentile-value": 0.001 + } + ] + } + } + }, + { + "id": 2, + "p2p-receiver-sdp": "1", + "p2p-sender-sdp": "2", + "service-slo-sle-policy": { + "slo-policy": { + "metric-bound": [ + { + "bound": 20, + "metric-type": "ietf-network-slice-service:one-way-delay-maximum", + "metric-unit": "milliseconds" + }, + { + "bound": 1000, + "metric-type": "ietf-network-slice-service:one-way-bandwidth", + "metric-unit": "Mbps" + }, + { + "metric-type": "ietf-network-slice-service:two-way-packet-loss", + "metric-unit": "percentage", + "percentile-value": 0.001 + } + ] + } + } + } + ], + "connectivity-type": "point-to-point", + "id": "line1" + } +] diff --git a/src/tests/ofc25/data/target-nce-app-flows.json b/src/tests/ofc25/data/target-nce-app-flows.json new file mode 100644 index 0000000000000000000000000000000000000000..66f7ed2543f7f5472e50ccda9755dd965bc73452 --- /dev/null +++ b/src/tests/ofc25/data/target-nce-app-flows.json @@ -0,0 +1,58 @@ +{ + "App_Flow_2_1_slice1": { + "app-flow": [ + { + "app-name": "App_Flow_2_1_slice1", + "duration": 9999, + "max-online-users": 1, + "name": "App_Flow_2_1_slice1", + "qos-profile": "AR_VR_Gaming", + "service-profile": "service_2_1_slice1", + "stas": "00:3D:E1:18:82:9E", + "user-id": "a8b5b840-1548-46c9-892e-5c18f9ec8d99" + } + ] + }, + "App_Flow_3_1_slice1": { + "app-flow": [ + { + "app-name": "App_Flow_3_1_slice1", + "duration": 9999, + "max-online-users": 1, + "name": "App_Flow_3_1_slice1", + "qos-profile": "AR_VR_Gaming", + "service-profile": "service_3_1_slice1", + "stas": "00:3D:E1:18:82:9E", + "user-id": "28a1c47b-0179-4ab8-85da-632e6f946491" + } + ] + }, + "App_Flow_2_1_slice2": { + "app-flow": [ + { + "app-name": "App_Flow_2_1_slice2", + "duration": 9999, + "max-online-users": 1, + "name": "App_Flow_2_1_slice2", + "qos-profile": "AR_VR_Gaming", + "service-profile": "service_2_1_slice2", + "stas": "00:3D:E1:18:82:9E", + "user-id": "9df7b98a-d5c0-43d4-bd0e-8d81ee4485f0" + } + ] + }, + "App_Flow_3_1_slice2": { + "app-flow": [ + { + "app-name": "App_Flow_3_1_slice2", + "duration": 9999, + "max-online-users": 1, + "name": "App_Flow_3_1_slice2", + "qos-profile": "AR_VR_Gaming", + "service-profile": "service_3_1_slice2", + "stas": "00:3D:E1:18:82:9E", + "user-id": "79b2becb-8500-42cc-b6be-c27c2ea60b22" + } + ] + } +} diff --git a/src/tests/ofc25/data/target-nce-apps.json b/src/tests/ofc25/data/target-nce-apps.json new file mode 100644 index 0000000000000000000000000000000000000000..11a25897910cbbfd7fb666ddd86babc1972e7052 --- /dev/null +++ b/src/tests/ofc25/data/target-nce-apps.json @@ -0,0 +1,82 @@ +{ + "App_Flow_2_1_slice1": { + "application": [ + { + "app-features": { + "app-feature": [ + { + "dest-ip": "172.1.101.22", + "dest-port": "10200", + "id": "feature_2_1_slice1", + "protocol": "tcp", + "src-ip": "172.16.104.221", + "src-port": "10500" + } + ] + }, + "app-id": "app_2_1_slice1", + "name": "App_Flow_2_1_slice1" + } + ] + }, + "App_Flow_3_1_slice1": { + "application": [ + { + "app-features": { + "app-feature": [ + { + "dest-ip": "172.1.101.22", + "dest-port": "10200", + "id": "feature_3_1_slice1", + "protocol": "tcp", + "src-ip": "172.16.104.222", + "src-port": "10500" + } + ] + }, + "app-id": "app_3_1_slice1", + "name": "App_Flow_3_1_slice1" + } + ] + }, + "App_Flow_2_1_slice2": { + "application": [ + { + "app-features": { + "app-feature": [ + { + "dest-ip": "172.1.201.22", + "dest-port": "10200", + "id": "feature_2_1_slice2", + "protocol": "tcp", + "src-ip": "172.16.104.221", + "src-port": "10500" + } + ] + }, + "app-id": "app_2_1_slice2", + "name": "App_Flow_2_1_slice2" + } + ] + }, + "App_Flow_3_1_slice2": { + "application": [ + { + "app-features": { + "app-feature": [ + { + "dest-ip": "172.1.201.22", + "dest-port": "10200", + "id": "feature_3_1_slice2", + "protocol": "tcp", + "src-ip": "172.16.104.222", + "src-port": "10500" + } + ] + }, + "app-id": "app_3_1_slice2", + "name": "App_Flow_3_1_slice2" + } + ] + } +} diff --git a/src/tests/ofc25/deploy_specs.sh b/src/tests/ofc25/deploy_specs.sh new file mode 100755 index 0000000000000000000000000000000000000000..72cd25b58a02f442838bab866cc969680c073ebc --- /dev/null +++ b/src/tests/ofc25/deploy_specs.sh @@ -0,0 +1,208 @@ +#!/bin/bash +# Copyright 2022-2025 ETSI 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. + + +# ----- TeraFlowSDN ------------------------------------------------------------ + +# Set the URL of the internal MicroK8s Docker registry where the images will be uploaded to. +export TFS_REGISTRY_IMAGES="http://localhost:32000/tfs/" + +# Set the list of components, separated by spaces, you want to build images for, and deploy. +#export TFS_COMPONENTS="context device pathcomp service slice nbi webui load_generator" +export TFS_COMPONENTS="context device pathcomp service nbi" + +# Uncomment to activate Monitoring (old) +#export TFS_COMPONENTS="${TFS_COMPONENTS} monitoring" + +# Uncomment to activate Monitoring Framework (new) +#export TFS_COMPONENTS="${TFS_COMPONENTS} kpi_manager kpi_value_writer kpi_value_api telemetry analytics automation" + +# Uncomment to activate QoS Profiles +#export TFS_COMPONENTS="${TFS_COMPONENTS} qos_profile" + +# Uncomment to activate BGP-LS Speaker +#export TFS_COMPONENTS="${TFS_COMPONENTS} bgpls_speaker" + +# Uncomment to activate Optical Controller +# To manage optical connections, "service" requires "opticalcontroller" to be deployed +# before "service", thus we "hack" the TFS_COMPONENTS environment variable prepending the +# "opticalcontroller" only if "service" is already in TFS_COMPONENTS, and re-export it. +#if [[ "$TFS_COMPONENTS" == *"service"* ]]; then +# BEFORE="${TFS_COMPONENTS% service*}" +# AFTER="${TFS_COMPONENTS#* service}" +# export TFS_COMPONENTS="${BEFORE} opticalcontroller service ${AFTER}" +#fi + +# Uncomment to activate ZTP +#export TFS_COMPONENTS="${TFS_COMPONENTS} ztp" + +# Uncomment to activate Policy Manager +#export TFS_COMPONENTS="${TFS_COMPONENTS} policy" + +# Uncomment to activate Optical CyberSecurity +#export TFS_COMPONENTS="${TFS_COMPONENTS} dbscanserving opticalattackmitigator opticalattackdetector opticalattackmanager" + +# Uncomment to activate L3 CyberSecurity +#export TFS_COMPONENTS="${TFS_COMPONENTS} l3_attackmitigator l3_centralizedattackdetector" + +# Uncomment to activate TE +#export TFS_COMPONENTS="${TFS_COMPONENTS} te" + +# Uncomment to activate Forecaster +#export TFS_COMPONENTS="${TFS_COMPONENTS} forecaster" + +# Uncomment to activate E2E Orchestrator +#export TFS_COMPONENTS="${TFS_COMPONENTS} e2e_orchestrator" + +# Uncomment to activate DLT and Interdomain +#export TFS_COMPONENTS="${TFS_COMPONENTS} interdomain dlt" +#if [[ "$TFS_COMPONENTS" == *"dlt"* ]]; then +# export KEY_DIRECTORY_PATH="src/dlt/gateway/keys/priv_sk" +# export CERT_DIRECTORY_PATH="src/dlt/gateway/keys/cert.pem" +# export TLS_CERT_PATH="src/dlt/gateway/keys/ca.crt" +#fi + +# Uncomment to activate QKD App +# To manage QKD Apps, "service" requires "qkd_app" to be deployed +# before "service", thus we "hack" the TFS_COMPONENTS environment variable prepending the +# "qkd_app" only if "service" is already in TFS_COMPONENTS, and re-export it. +#if [[ "$TFS_COMPONENTS" == *"service"* ]]; then +# BEFORE="${TFS_COMPONENTS% service*}" +# AFTER="${TFS_COMPONENTS#* service}" +# export TFS_COMPONENTS="${BEFORE} qkd_app service ${AFTER}" +#fi + + +# Set the tag you want to use for your images. +export TFS_IMAGE_TAG="dev" + +# Set the name of the Kubernetes namespace to deploy TFS to. +export TFS_K8S_NAMESPACE="tfs" + +# Set additional manifest files to be applied after the deployment +export TFS_EXTRA_MANIFESTS="manifests/nginx_ingress_http.yaml" + +# Uncomment to monitor performance of components +#export TFS_EXTRA_MANIFESTS="${TFS_EXTRA_MANIFESTS} manifests/servicemonitors.yaml" + +# Uncomment when deploying Optical CyberSecurity +#export TFS_EXTRA_MANIFESTS="${TFS_EXTRA_MANIFESTS} manifests/cachingservice.yaml" + +# Set the new Grafana admin password +export TFS_GRAFANA_PASSWORD="admin123+" + +# Disable skip-build flag to rebuild the Docker images. +export TFS_SKIP_BUILD="" + + +# ----- CockroachDB ------------------------------------------------------------ + +# Set the namespace where CockroackDB will be deployed. +export CRDB_NAMESPACE="crdb" + +# Set the external port CockroackDB Postgre SQL interface will be exposed to. +export CRDB_EXT_PORT_SQL="26257" + +# Set the external port CockroackDB HTTP Mgmt GUI interface will be exposed to. +export CRDB_EXT_PORT_HTTP="8081" + +# Set the database username to be used by Context. +export CRDB_USERNAME="tfs" + +# Set the database user's password to be used by Context. +export CRDB_PASSWORD="tfs123" + +# Set CockroachDB installation mode to 'single'. This option is convenient for development and testing. +# See ./deploy/all.sh or ./deploy/crdb.sh for additional details +export CRDB_DEPLOY_MODE="single" + +# Disable flag for dropping database, if it exists. +export CRDB_DROP_DATABASE_IF_EXISTS="YES" + +# Disable flag for re-deploying CockroachDB from scratch. +export CRDB_REDEPLOY="" + + +# ----- NATS ------------------------------------------------------------------- + +# Set the namespace where NATS will be deployed. +export NATS_NAMESPACE="nats" + +# Set the external port NATS Client interface will be exposed to. +export NATS_EXT_PORT_CLIENT="4222" + +# Set the external port NATS HTTP Mgmt GUI interface will be exposed to. +export NATS_EXT_PORT_HTTP="8222" + +# Set NATS installation mode to 'single'. This option is convenient for development and testing. +# See ./deploy/all.sh or ./deploy/nats.sh for additional details +export NATS_DEPLOY_MODE="single" + +# Disable flag for re-deploying NATS from scratch. +export NATS_REDEPLOY="" + + +# ----- QuestDB ---------------------------------------------------------------- + +# Set the namespace where QuestDB will be deployed. +export QDB_NAMESPACE="qdb" + +# Set the external port QuestDB Postgre SQL interface will be exposed to. +export QDB_EXT_PORT_SQL="8812" + +# Set the external port QuestDB Influx Line Protocol interface will be exposed to. +export QDB_EXT_PORT_ILP="9009" + +# Set the external port QuestDB HTTP Mgmt GUI interface will be exposed to. +export QDB_EXT_PORT_HTTP="9000" + +# Set the database username to be used for QuestDB. +export QDB_USERNAME="admin" + +# Set the database user's password to be used for QuestDB. +export QDB_PASSWORD="quest" + +# Set the table name to be used by Monitoring for KPIs. +export QDB_TABLE_MONITORING_KPIS="tfs_monitoring_kpis" + +# Set the table name to be used by Slice for plotting groups. +export QDB_TABLE_SLICE_GROUPS="tfs_slice_groups" + +# Disable flag for dropping tables if they exist. +export QDB_DROP_TABLES_IF_EXIST="YES" + +# Disable flag for re-deploying QuestDB from scratch. +export QDB_REDEPLOY="" + + +# ----- K8s Observability ------------------------------------------------------ + +# Set the external port Prometheus Mgmt HTTP GUI interface will be exposed to. +export PROM_EXT_PORT_HTTP="9090" + +# Set the external port Grafana HTTP Dashboards will be exposed to. +export GRAF_EXT_PORT_HTTP="3000" + + +# ----- Apache Kafka ----------------------------------------------------------- + +# Set the namespace where Apache Kafka will be deployed. +export KFK_NAMESPACE="kafka" + +# Set the port Apache Kafka server will be exposed to. +export KFK_SERVER_PORT="9092" + +# Set the flag to YES for redeploying of Apache Kafka +export KFK_REDEPLOY="" diff --git a/src/tests/ofc25/redeploy-tfs.sh b/src/tests/ofc25/redeploy-tfs.sh new file mode 100755 index 0000000000000000000000000000000000000000..a82dcbf258e0e7aeb05ce7a1bb711512c7b682ad --- /dev/null +++ b/src/tests/ofc25/redeploy-tfs.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# Copyright 2022-2025 ETSI 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 ~/tfs-ctrl/src/tests/ofc25/deploy_specs.sh +./deploy/all.sh diff --git a/src/tests/ofc25/requirements.in b/src/tests/ofc25/requirements.in new file mode 100644 index 0000000000000000000000000000000000000000..6210ec8172e17efbb23e0e14d30a91d7b61d4abe --- /dev/null +++ b/src/tests/ofc25/requirements.in @@ -0,0 +1,16 @@ +# Copyright 2022-2025 ETSI 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. + +deepdiff==6.7.* +requests==2.27.* diff --git a/src/tests/ofc25/scripts/run-e2e-ietf-slice-operations.sh b/src/tests/ofc25/scripts/run-e2e-ietf-slice-operations.sh new file mode 100755 index 0000000000000000000000000000000000000000..8996bfecd03bd1db584420bbed95992fb740c6b2 --- /dev/null +++ b/src/tests/ofc25/scripts/run-e2e-ietf-slice-operations.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# Copyright 2022-2025 ETSI 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_e2e_ietf_slice_operations.xml \ + /var/teraflow/tests/ofc25/tests/test_e2e_ietf_slice_operations.py diff --git a/src/tests/ofc25/scripts/run-onboarding.sh b/src/tests/ofc25/scripts/run-onboarding.sh new file mode 100755 index 0000000000000000000000000000000000000000..689de9c5a4079b9ce2b612ee596d3a7c770dc10c --- /dev/null +++ b/src/tests/ofc25/scripts/run-onboarding.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# Copyright 2022-2025 ETSI 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/ofc25/tests/test_onboarding.py diff --git a/src/tests/ofc25/tests/Tools.py b/src/tests/ofc25/tests/Tools.py new file mode 100644 index 0000000000000000000000000000000000000000..cd2add49edd23f4c169b5fdc3c5123b2b31daa8d --- /dev/null +++ b/src/tests/ofc25/tests/Tools.py @@ -0,0 +1,109 @@ +# Copyright 2022-2024 ETSI 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 enum, logging, requests +from typing import Any, Dict, List, Optional, Set, Union +from common.Constants import ServiceNameEnum +from common.Settings import get_service_host, get_service_port_http + +NBI_ADDRESS = get_service_host(ServiceNameEnum.NBI) +NBI_PORT = get_service_port_http(ServiceNameEnum.NBI) +NBI_USERNAME = 'admin' +NBI_PASSWORD = 'admin' +NBI_BASE_URL = '' + +class RestRequestMethod(enum.Enum): + GET = 'get' + POST = 'post' + PUT = 'put' + PATCH = 'patch' + DELETE = 'delete' + +EXPECTED_STATUS_CODES : Set[int] = { + requests.codes['OK' ], + requests.codes['CREATED' ], + requests.codes['ACCEPTED' ], + requests.codes['NO_CONTENT'], +} + +def do_rest_request( + method : RestRequestMethod, url : str, body : Optional[Any] = None, timeout : int = 10, + allow_redirects : bool = True, expected_status_codes : Set[int] = EXPECTED_STATUS_CODES, + logger : Optional[logging.Logger] = None +) -> Optional[Union[Dict, List]]: + request_url = 'http://{:s}:{:s}@{:s}:{:d}{:s}{:s}'.format( + NBI_USERNAME, NBI_PASSWORD, NBI_ADDRESS, NBI_PORT, str(NBI_BASE_URL), url + ) + + if logger is not None: + msg = 'Request: {:s} {:s}'.format(str(method.value).upper(), str(request_url)) + if body is not None: msg += ' body={:s}'.format(str(body)) + logger.warning(msg) + reply = requests.request(method.value, request_url, headers={'Content-Type': 'application/json'}, timeout=timeout, json=body, allow_redirects=allow_redirects) + if logger is not None: + logger.warning('Reply: {:s}'.format(str(reply.text))) + assert reply.status_code in expected_status_codes, 'Reply failed with status code {:d}'.format(reply.status_code) + + if reply.content and len(reply.content) > 0: return reply.json() + return None + +def do_rest_get_request( + url : str, body : Optional[Any] = None, timeout : int = 10, + allow_redirects : bool = True, expected_status_codes : Set[int] = EXPECTED_STATUS_CODES, + logger : Optional[logging.Logger] = None +) -> Optional[Union[Dict, List]]: + return do_rest_request( + RestRequestMethod.GET, url, body=body, timeout=timeout, allow_redirects=allow_redirects, + expected_status_codes=expected_status_codes, logger=logger + ) + +def do_rest_post_request( + url : str, body : Optional[Any] = None, timeout : int = 10, + allow_redirects : bool = True, expected_status_codes : Set[int] = EXPECTED_STATUS_CODES, + logger : Optional[logging.Logger] = None +) -> Optional[Union[Dict, List]]: + return do_rest_request( + RestRequestMethod.POST, url, body=body, timeout=timeout, allow_redirects=allow_redirects, + expected_status_codes=expected_status_codes, logger=logger + ) + +def do_rest_put_request( + url : str, body : Optional[Any] = None, timeout : int = 10, + allow_redirects : bool = True, expected_status_codes : Set[int] = EXPECTED_STATUS_CODES, + logger : Optional[logging.Logger] = None +) -> Optional[Union[Dict, List]]: + return do_rest_request( + RestRequestMethod.PUT, url, body=body, timeout=timeout, allow_redirects=allow_redirects, + expected_status_codes=expected_status_codes, logger=logger + ) + +def do_rest_patch_request( + url : str, body : Optional[Any] = None, timeout : int = 10, + allow_redirects : bool = True, expected_status_codes : Set[int] = EXPECTED_STATUS_CODES, + logger : Optional[logging.Logger] = None +) -> Optional[Union[Dict, List]]: + return do_rest_request( + RestRequestMethod.PATCH, url, body=body, timeout=timeout, allow_redirects=allow_redirects, + expected_status_codes=expected_status_codes, logger=logger + ) + +def do_rest_delete_request( + url : str, body : Optional[Any] = None, timeout : int = 10, + allow_redirects : bool = True, expected_status_codes : Set[int] = EXPECTED_STATUS_CODES, + logger : Optional[logging.Logger] = None +) -> Optional[Union[Dict, List]]: + return do_rest_request( + RestRequestMethod.DELETE, url, body=body, timeout=timeout, allow_redirects=allow_redirects, + expected_status_codes=expected_status_codes, logger=logger + ) diff --git a/src/tests/ofc25/tests/__init__.py b/src/tests/ofc25/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..3ccc21c7db78aac26daa1f8c5ff8e1ffd3f35460 --- /dev/null +++ b/src/tests/ofc25/tests/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2022-2025 ETSI 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. + diff --git a/src/tests/ofc25/tests/test_e2e_ietf_slice_operations.py b/src/tests/ofc25/tests/test_e2e_ietf_slice_operations.py new file mode 100644 index 0000000000000000000000000000000000000000..d6207d675db6b1d72b717f648dd684a00565a093 --- /dev/null +++ b/src/tests/ofc25/tests/test_e2e_ietf_slice_operations.py @@ -0,0 +1,481 @@ +# Copyright 2022-2025 ETSI 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 +import requests +from deepdiff import DeepDiff + + +LOGGER = logging.getLogger(__name__) +LOGGER.setLevel(logging.DEBUG) + +HEADERS = {"Content-Type": "application/json"} + +POST_NETWORK_SLICE1 = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "..", + "data", + "slice", + "post_network_slice1.json", +) +POST_NETWORK_SLICE2 = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "..", + "data", + "slice", + "post_network_slice2.json", +) +POST_CONNECTION_GROUP_TO_NETWORK_SLICE1 = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "..", + "data", + "slice", + "post_connection_group_to_network_slice1.json", +) +POST_CONNECTION_GROUP_TO_NETWORK_SLICE2 = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "..", + "data", + "slice", + "post_connection_group_to_network_slice2.json", +) +POST_MATCH_CRITERIA_TO_SDP1_IN_SLICE1 = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "..", + "data", + "slice", + "post_match_criteria_to_sdp1_in_slice1.json", +) +POST_MATCH_CRITERIA_TO_SDP1_IN_SLICE2 = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "..", + "data", + "slice", + "post_match_criteria_to_sdp1_in_slice2.json", +) +POST_SDP_TO_NETWORK_SLICE1 = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "..", + "data", + "slice", + "post_sdp_to_network_slice1.json", +) +POST_SDP_TO_NETWORK_SLICE2 = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "..", + "data", + "slice", + "post_sdp_to_network_slice2.json", +) +TARGET_NCE_APP_FLOWS = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "..", + "data", + "slice", + "target-nce-app-flows.json", +) +TARGET_NCE_APPS = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "..", + "data", + "slice", + "target-nce-apps.json", +) +TARGET_FULL_IETF_SLICE = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "..", + "data", + "slice", + "target-full-ietf-slice.json", +) +TARGET_FULL_IETF_SLICE = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "..", + "data", + "slice", + "target-full-ietf-slice.json", +) +TARGET_IETF_SLICE_POSTED_SLICES = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "..", + "data", + "target-ietf-slice-posted-slices.json", +) +TARGET_IETF_SLICE_PUT_CONNECTION_GROUPS = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "..", + "data", + "target-ietf-slice-put-connection-groups.json", +) + +NBI_ADDRESS = "localhost" +NBI_PORT = "80" +NBI_USERNAME = "admin" +NBI_PASSWORD = "admin" + +NCE_ADDRESS = "localhost" +NCE_PORT = 9090 + +AGG_TFS_ADDRESS = "localhost" +AGG_TFS_PORT = 9091 + +BASE_IETF_SLICE_URL = f"http://{NBI_ADDRESS}:{NBI_PORT}/restconf/data/ietf-network-slice-service:network-slice-services" +NCE_APP_DATA_URL = f"http://{NCE_ADDRESS}:{NCE_PORT}/restconf/v1/data/app-flows/apps" +NCE_APP_FLOW_DATA_URL = f"http://{NCE_ADDRESS}:{NCE_PORT}/restconf/v1/data/app-flows" +AGG_TFS_IETF_SLICE_URL = f"http://{AGG_TFS_ADDRESS}:{AGG_TFS_PORT}/restconf/data/ietf-network-slice-service:network-slice-services" + + +# pylint: disable=redefined-outer-name, unused-argument +def test_ietf_slice_creation_removal(): + # Issue service creation request + with open(POST_NETWORK_SLICE1, "r", encoding="UTF-8") as f: + post_network_slice1 = json.load(f) + with open(POST_NETWORK_SLICE2, "r", encoding="UTF-8") as f: + post_network_slice2 = json.load(f) + with open(POST_CONNECTION_GROUP_TO_NETWORK_SLICE1, "r", encoding="UTF-8") as f: + post_connection_group_to_network_slice1 = json.load(f) + with open(POST_CONNECTION_GROUP_TO_NETWORK_SLICE2, "r", encoding="UTF-8") as f: + post_connection_group_to_network_slice2 = json.load(f) + with open(POST_MATCH_CRITERIA_TO_SDP1_IN_SLICE1, "r", encoding="UTF-8") as f: + post_match_criteria_to_sdp1_in_slice1 = json.load(f) + with open(POST_MATCH_CRITERIA_TO_SDP1_IN_SLICE2, "r", encoding="UTF-8") as f: + post_match_criteria_to_sdp1_in_slice2 = json.load(f) + with open(POST_SDP_TO_NETWORK_SLICE1, "r", encoding="UTF-8") as f: + post_sdp_to_network_slice1 = json.load(f) + with open(POST_SDP_TO_NETWORK_SLICE2, "r", encoding="UTF-8") as f: + post_sdp_to_network_slice2 = json.load(f) + with open(TARGET_NCE_APPS, "r", encoding="UTF-8") as f: + target_nce_apps = json.load(f) + with open(TARGET_NCE_APP_FLOWS, "r", encoding="UTF-8") as f: + target_nce_app_flows = json.load(f) + with open(TARGET_FULL_IETF_SLICE, "r", encoding="UTF-8") as f: + target_full_ietf_slice = json.load(f) + with open(TARGET_IETF_SLICE_POSTED_SLICES, "r", encoding="UTF-8") as f: + target_ietf_slice_posted_slices = json.load(f) + with open(TARGET_IETF_SLICE_PUT_CONNECTION_GROUPS, "r", encoding="UTF-8") as f: + target_ietf_slice_put_connection_groups = json.load(f) + + # op 1 + URL = BASE_IETF_SLICE_URL + requests.post(URL, headers=HEADERS, json=post_network_slice1) + + URL = NCE_APP_DATA_URL + apps_response = requests.get(URL) + URL = NCE_APP_FLOW_DATA_URL + app_flows_response = requests.get(URL) + URL = AGG_TFS_IETF_SLICE_URL + ietf_slice_services = requests.get(URL) + URL = ( + AGG_TFS_IETF_SLICE_URL + + "/slice-service=dummy/connection-groups/connection-group=dummy" + ) + ietf_slice_connection_groups = requests.get(URL) + + app_name = apps_response["application"][0]["name"] + apps_diff = DeepDiff(apps_response[app_name], target_nce_apps[app_name]) + app_flows_diff = DeepDiff( + app_flows_response[app_name], + target_nce_app_flows[app_name], + exclude_regex_paths=r"root\['app-flow'\]\[\d+\]\['user-id'\]", + ) + assert not apps_diff + assert not app_flows_diff + assert len(apps_response) == 1 and len(app_flows_response) == 1 + + assert len(ietf_slice_connection_groups) == 0 + assert len(ietf_slice_services) == 1 + slice_diff = DeepDiff( + ietf_slice_services["slice1"], target_ietf_slice_posted_slices[0] + ) + assert not slice_diff + + # op 2 + URL = BASE_IETF_SLICE_URL + "/slice-service=slice1/sdps" + requests.post(URL, headers=HEADERS, json=post_sdp_to_network_slice1) + URL = BASE_IETF_SLICE_URL + "/slice-service=slice1/connection-groups" + requests.post(URL, headers=HEADERS, json=post_connection_group_to_network_slice1) + URL = ( + BASE_IETF_SLICE_URL + "/slice-service=slice1/sdps/sdp=1/service-match-criteria" + ) + requests.post(URL, headers=HEADERS, json=post_match_criteria_to_sdp1_in_slice1) + + URL = NCE_APP_DATA_URL + apps_response = requests.get(URL) + URL = NCE_APP_FLOW_DATA_URL + app_flows_response = requests.get(URL) + URL = AGG_TFS_IETF_SLICE_URL + ietf_slice_services = requests.get(URL) + URL = ( + AGG_TFS_IETF_SLICE_URL + + "/slice-service=dummy/connection-groups/connection-group=dummy" + ) + ietf_slice_connection_groups = requests.get(URL) + + app_name = apps_response["application"][0]["name"] + apps_diff = DeepDiff(apps_response[app_name], target_nce_apps[app_name]) + app_flows_diff = DeepDiff( + app_flows_response[app_name], + target_nce_app_flows[app_name], + exclude_regex_paths=r"root\['app-flow'\]\[\d+\]\['user-id'\]", + ) + assert not apps_diff + assert not app_flows_diff + assert len(apps_response) == 2 and len(app_flows_response) == 2 + + assert len(ietf_slice_connection_groups) == 1 + assert len(ietf_slice_services) == 1 + connection_group_diff = DeepDiff( + ietf_slice_connection_groups[0], target_ietf_slice_put_connection_groups[0] + ) + assert not connection_group_diff + + # op 3 + URL = BASE_IETF_SLICE_URL + requests.post(URL, headers=HEADERS, json=post_network_slice2) + + URL = NCE_APP_DATA_URL + apps_response = requests.get(URL) + URL = NCE_APP_FLOW_DATA_URL + app_flows_response = requests.get(URL) + URL = AGG_TFS_IETF_SLICE_URL + ietf_slice_services = requests.get(URL) + URL = ( + AGG_TFS_IETF_SLICE_URL + + "/slice-service=dummy/connection-groups/connection-group=dummy" + ) + ietf_slice_connection_groups = requests.get(URL) + + app_name = apps_response["application"][0]["name"] + apps_diff = DeepDiff(apps_response[app_name], target_nce_apps[app_name]) + app_flows_diff = DeepDiff( + app_flows_response[app_name], + target_nce_app_flows[app_name], + exclude_regex_paths=r"root\['app-flow'\]\[\d+\]\['user-id'\]", + ) + assert not apps_diff + assert not app_flows_diff + assert len(apps_response) == 3 and len(app_flows_response) == 3 + + assert len(ietf_slice_connection_groups) == 0 + assert len(ietf_slice_services) == 2 + slice_diff = DeepDiff( + ietf_slice_services["slice2"], target_ietf_slice_posted_slices[1] + ) + assert not slice_diff + + # op 4 + URL = BASE_IETF_SLICE_URL + "/slice-service=slice2/sdps" + requests.post(URL, headers=HEADERS, json=post_sdp_to_network_slice2) + URL = BASE_IETF_SLICE_URL + "/slice-service=slice2/connection-groups" + requests.post(URL, headers=HEADERS, json=post_connection_group_to_network_slice2) + URL = ( + BASE_IETF_SLICE_URL + "/slice-service=slice2/sdps/sdp=1/service-match-criteria" + ) + requests.post(URL, headers=HEADERS, json=post_match_criteria_to_sdp1_in_slice2) + + URL = NCE_APP_DATA_URL + apps_response = requests.get(URL) + URL = NCE_APP_FLOW_DATA_URL + app_flows_response = requests.get(URL) + URL = AGG_TFS_IETF_SLICE_URL + ietf_slice_services = requests.get(URL) + URL = ( + AGG_TFS_IETF_SLICE_URL + + "/slice-service=dummy/connection-groups/connection-group=dummy" + ) + ietf_slice_connection_groups = requests.get(URL) + + app_name = apps_response["application"][0]["name"] + apps_diff = DeepDiff(apps_response[app_name], target_nce_apps[app_name]) + app_flows_diff = DeepDiff( + app_flows_response[app_name], + target_nce_app_flows[app_name], + exclude_regex_paths=r"root\['app-flow'\]\[\d+\]\['user-id'\]", + ) + assert not apps_diff + assert not app_flows_diff + assert len(apps_response) == 4 and len(app_flows_response) == 4 + + assert len(ietf_slice_connection_groups) == 2 + assert len(ietf_slice_services) == 2 + connection_group_diff = DeepDiff( + ietf_slice_connection_groups[1], target_ietf_slice_put_connection_groups[1] + ) + assert not connection_group_diff + + # op 5 + ietf_slices_full_retrieved = requests.get(BASE_IETF_SLICE_URL) + ietf_slice_data = DeepDiff(ietf_slices_full_retrieved, target_full_ietf_slice) + assert not ietf_slice_data + + # op 6 + URL = BASE_IETF_SLICE_URL + "/slice-service=slice1/sdps/sdp=2" + requests.delete(URL) + URL = ( + BASE_IETF_SLICE_URL + + "/slice-service=slice1/sdps/sdp=1/service-match-criteria/match-criterion=1" + ) + requests.delete(URL) + URL = ( + BASE_IETF_SLICE_URL + + "/slice-service=slice1/connection-groups/connection-group=line1" + ) + requests.delete(URL) + + URL = NCE_APP_DATA_URL + apps_response = requests.get(URL) + URL = NCE_APP_FLOW_DATA_URL + app_flows_response = requests.get(URL) + URL = AGG_TFS_IETF_SLICE_URL + ietf_slice_services = requests.get(URL) + URL = ( + AGG_TFS_IETF_SLICE_URL + + "/slice-service=dummy/connection-groups/connection-group=dummy" + ) + ietf_slice_connection_groups = requests.get(URL) + + app_name = "App_Flow_2_1_slice1" + assert app_name not in apps_response + assert app_name not in app_flows_response + assert len(apps_response) == 3 and len(app_flows_response) == 3 + + assert len(ietf_slice_connection_groups) == 3 + assert len(ietf_slice_services) == 2 + connection_group_diff = DeepDiff( + ietf_slice_connection_groups[2], target_ietf_slice_put_connection_groups[2] + ) + assert not connection_group_diff + + # op 7 + URL = BASE_IETF_SLICE_URL + "/slice-service=slice1/sdps/sdp=3" + requests.delete(URL) + URL = ( + BASE_IETF_SLICE_URL + + "/slice-service=slice1/sdps/sdp=1/service-match-criteria/match-criterion=2" + ) + requests.delete(URL) + URL = ( + BASE_IETF_SLICE_URL + + "/slice-service=slice1/connection-groups/connection-group=line2" + ) + requests.delete(URL) + URL = BASE_IETF_SLICE_URL + "/slice-service=slice1/sdps/sdp=1" + + URL = NCE_APP_DATA_URL + apps_response = requests.get(URL) + URL = NCE_APP_FLOW_DATA_URL + app_flows_response = requests.get(URL) + URL = AGG_TFS_IETF_SLICE_URL + ietf_slice_services = requests.get(URL) + URL = ( + AGG_TFS_IETF_SLICE_URL + + "/slice-service=dummy/connection-groups/connection-group=dummy" + ) + ietf_slice_connection_groups = requests.get(URL) + + requests.delete(URL) + URL = BASE_IETF_SLICE_URL + "/slice-service=slice1" + requests.delete(URL) + + app_name = "App_Flow_3_1_slice1" + assert app_name not in apps_response + assert app_name not in app_flows_response + assert len(apps_response) == 2 and len(app_flows_response) == 2 + + assert len(ietf_slice_connection_groups) == 3 + assert len(ietf_slice_services) == 1 + assert "slice1" not in ietf_slice_services + + # op 8 + URL = BASE_IETF_SLICE_URL + "/slice-service=slice2/sdps/sdp=2" + requests.delete(URL) + URL = ( + BASE_IETF_SLICE_URL + + "/slice-service=slice2/sdps/sdp=1/service-match-criteria/match-criterion=1" + ) + requests.delete(URL) + URL = ( + BASE_IETF_SLICE_URL + + "/slice-service=slice2/connection-groups/connection-group=line1" + ) + requests.delete(URL) + + URL = NCE_APP_DATA_URL + apps_response = requests.get(URL) + URL = NCE_APP_FLOW_DATA_URL + app_flows_response = requests.get(URL) + URL = AGG_TFS_IETF_SLICE_URL + ietf_slice_services = requests.get(URL) + URL = ( + AGG_TFS_IETF_SLICE_URL + + "/slice-service=dummy/connection-groups/connection-group=dummy" + ) + ietf_slice_connection_groups = requests.get(URL) + + app_name = "App_Flow_2_1_slice2" + assert app_name not in apps_response + assert app_name not in app_flows_response + assert len(apps_response) == 1 and len(app_flows_response) == 1 + + assert len(ietf_slice_connection_groups) == 4 + assert len(ietf_slice_services) == 1 + connection_group_diff = DeepDiff( + ietf_slice_connection_groups[3], target_ietf_slice_put_connection_groups[3] + ) + assert not connection_group_diff + + # op 9 + URL = BASE_IETF_SLICE_URL + "/slice-service=slice2/sdps/sdp=3" + requests.delete(URL) + URL = ( + BASE_IETF_SLICE_URL + + "/slice-service=slice2/sdps/sdp=1/service-match-criteria/match-criterion=2" + ) + requests.delete(URL) + URL = ( + BASE_IETF_SLICE_URL + + "/slice-service=slice2/connection-groups/connection-group=line2" + ) + requests.delete(URL) + + URL = NCE_APP_DATA_URL + apps_response = requests.get(URL) + URL = NCE_APP_FLOW_DATA_URL + app_flows_response = requests.get(URL) + URL = AGG_TFS_IETF_SLICE_URL + ietf_slice_services = requests.get(URL) + URL = ( + AGG_TFS_IETF_SLICE_URL + + "/slice-service=dummy/connection-groups/connection-group=dummy" + ) + ietf_slice_connection_groups = requests.get(URL) + + URL = BASE_IETF_SLICE_URL + "/slice-service=slice2/sdps/sdp=1" + requests.delete(URL) + URL = BASE_IETF_SLICE_URL + "/slice-service=slice2" + requests.delete(URL) + + app_name = "App_Flow_3_1_slice2" + assert app_name not in apps_response + assert app_name not in app_flows_response + assert len(apps_response) == 0 and len(app_flows_response) == 0 + + assert len(ietf_slice_connection_groups) == 4 + assert len(ietf_slice_services) == 0 + + # op 10 + ietf_slices_full_retrieved = requests.get(BASE_IETF_SLICE_URL) + empty_ietf_slices = {"network-slice-services": {"slice-service": []}} + ietf_slice_data = DeepDiff(ietf_slices_full_retrieved, empty_ietf_slices) + assert not ietf_slice_data diff --git a/src/tests/ofc25/tests/test_onboarding.py b/src/tests/ofc25/tests/test_onboarding.py new file mode 100644 index 0000000000000000000000000000000000000000..b58cb38219c36caa77998af1e66eb80d0888301f --- /dev/null +++ b/src/tests/ofc25/tests/test_onboarding.py @@ -0,0 +1,67 @@ +# Copyright 2022-2024 ETSI 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, time +from common.Constants import DEFAULT_CONTEXT_NAME +from common.proto.context_pb2 import ContextId, DeviceOperationalStatusEnum, Empty +from common.tools.descriptor.Loader import DescriptorLoader, check_descriptor_load_results, validate_empty_scenario +from common.tools.object_factory.Context import json_context_id +from context.client.ContextClient import ContextClient +from device.client.DeviceClient import DeviceClient +from .Fixtures import context_client, device_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', 'camara-e2e-topology.json') +ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME)) + +def test_scenario_onboarding( + context_client : ContextClient, # pylint: disable=redefined-outer-name + device_client : DeviceClient, # pylint: disable=redefined-outer-name +) -> None: + validate_empty_scenario(context_client) + + descriptor_loader = DescriptorLoader( + descriptors_file=DESCRIPTOR_FILE, context_client=context_client, device_client=device_client) + results = descriptor_loader.process() + check_descriptor_load_results(results, descriptor_loader) + descriptor_loader.validate() + + # 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 + +def test_scenario_devices_enabled( + context_client : ContextClient, # pylint: disable=redefined-outer-name +) -> None: + """ + This test validates that the devices are enabled. + """ + DEVICE_OP_STATUS_ENABLED = DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_ENABLED + + num_devices = -1 + num_devices_enabled, num_retry = 0, 0 + while (num_devices != num_devices_enabled) and (num_retry < 10): + time.sleep(1.0) + response = context_client.ListDevices(Empty()) + num_devices = len(response.devices) + num_devices_enabled = 0 + for device in response.devices: + if device.device_operational_status != DEVICE_OP_STATUS_ENABLED: continue + num_devices_enabled += 1 + LOGGER.info('Num Devices enabled: {:d}/{:d}'.format(num_devices_enabled, num_devices)) + num_retry += 1 + assert num_devices_enabled == num_devices