diff --git a/.gitignore b/.gitignore index 20b98c30c5b3edb0983578b0a5f74fb1c1f3025e..db47387c8c8ff9900a59107642221960134aa1f1 100644 --- a/.gitignore +++ b/.gitignore @@ -25,12 +25,14 @@ share/python-wheels/ .installed.cfg *.egg MANIFEST +.my_venv/ # requirements.txt # removed to enable tracking versions of packages over time # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest +.manifest/ *.spec # Installer logs @@ -176,3 +178,6 @@ libyang/ # Other logs **/logs/*.log.* + +# PySpark checkpoints +src/analytics/.spark/* diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e2d653e0360b694891adc966d6d0b1124ed72ac4..2fe4057332cb87e4014d2a9dd2fef04c9c118c9b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -34,6 +34,7 @@ include: - local: '/src/opticalcontroller/.gitlab-ci.yml' - local: '/src/ztp/.gitlab-ci.yml' - local: '/src/policy/.gitlab-ci.yml' + - local: '/src/automation/.gitlab-ci.yml' - local: '/src/forecaster/.gitlab-ci.yml' #- local: '/src/webui/.gitlab-ci.yml' #- local: '/src/l3_distributedattackdetector/.gitlab-ci.yml' @@ -45,6 +46,14 @@ include: #- local: '/src/dlt/.gitlab-ci.yml' - local: '/src/load_generator/.gitlab-ci.yml' - local: '/src/bgpls_speaker/.gitlab-ci.yml' + - local: '/src/kpi_manager/.gitlab-ci.yml' + - local: '/src/kpi_value_api/.gitlab-ci.yml' + - local: '/src/kpi_value_writer/.gitlab-ci.yml' + - local: '/src/telemetry/.gitlab-ci.yml' + - local: '/src/analytics/.gitlab-ci.yml' + - local: '/src/qos_profile/.gitlab-ci.yml' + - local: '/src/vnt_manager/.gitlab-ci.yml' + - local: '/src/e2e_orchestrator/.gitlab-ci.yml' # This should be last one: end-to-end integration tests - local: '/src/tests/.gitlab-ci.yml' diff --git a/clean_testing_environment.sh b/clean_testing_environment.sh index f037a2a39309abb192c36943c014c4a3b893dd98..8384549f5f201da0d8592c522d8ed79555154dbe 100755 --- a/clean_testing_environment.sh +++ b/clean_testing_environment.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/common_requirements.in b/common_requirements.in index 3aa30e174f43d6f8758f49b3104a20cc8580a7ff..e1bcad78bfc23217633fb28ef28a2d70d070644a 100644 --- a/common_requirements.in +++ b/common_requirements.in @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/coverage/.coveragerc.template b/coverage/.coveragerc.template index 3d8065acabefc65daad28fd4bd2e166b84d11d8b..ba25f55db56a42bf7590e26207243677a425b207 100644 --- a/coverage/.coveragerc.template +++ b/coverage/.coveragerc.template @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/data/perf/old/MW/generate.sh b/data/perf/old/MW/generate.sh index ccef4e113b3216bc4e4dddcd4be793c2bba32501..ca87cfcf962a77eac0181ed2cdff897a5f758827 100755 --- a/data/perf/old/MW/generate.sh +++ b/data/perf/old/MW/generate.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/data/perf/old/MW/generate_plot.py b/data/perf/old/MW/generate_plot.py index 22befef305bf33b4aa150bf60fbd39fac3c61402..2386a74231b935017cf400fee7f0998c8c3c4995 100644 --- a/data/perf/old/MW/generate_plot.py +++ b/data/perf/old/MW/generate_plot.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/data/perf/old/OpenConfig/generate.sh b/data/perf/old/OpenConfig/generate.sh index 5147d49626143919814a6184e02cbabdaf32b5cf..2d3819deb455e32a62f09079f8bd637cee6d5e53 100755 --- a/data/perf/old/OpenConfig/generate.sh +++ b/data/perf/old/OpenConfig/generate.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/data/perf/old/OpenConfig/generate_plot.py b/data/perf/old/OpenConfig/generate_plot.py index 8d50ab81fd41d5dc8963aa3a9dc317bd3487fd54..40b43ce071056d4c4969b1037eaa2bca6ec0c535 100644 --- a/data/perf/old/OpenConfig/generate_plot.py +++ b/data/perf/old/OpenConfig/generate_plot.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/data/perf/old/TE/te-cdf.py b/data/perf/old/TE/te-cdf.py index a3e7cc53006f5b1f513ee2b3b23938d33cb93fcd..e1e4975a690f8e7b91820ade172d5315051b7f9a 100644 --- a/data/perf/old/TE/te-cdf.py +++ b/data/perf/old/TE/te-cdf.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/data/perf/old/XR/generate.sh b/data/perf/old/XR/generate.sh index d5b70476331f3a3e6ffcaa77cd3f2ef68008bc67..7c99afce876133bae8ad315e02a27955ce4c4756 100755 --- a/data/perf/old/XR/generate.sh +++ b/data/perf/old/XR/generate.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/data/perf/old/XR/generate_plot.py b/data/perf/old/XR/generate_plot.py index f27c37e53a287d90c209620282a25d5f92152f1e..7acbc5d829e910e3e2f25ebd5f1f59c0fb4a0e73 100644 --- a/data/perf/old/XR/generate_plot.py +++ b/data/perf/old/XR/generate_plot.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/data/perf/old/emulated/generate.sh b/data/perf/old/emulated/generate.sh index 7b978c1fd4f2962693926f9cf443a6d03ee17161..c239eb7131e9d78754faf5afff7beb95e97beeac 100755 --- a/data/perf/old/emulated/generate.sh +++ b/data/perf/old/emulated/generate.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/data/perf/old/emulated/generate_plot.py b/data/perf/old/emulated/generate_plot.py index d049386c3cf010ae53e8f2a91a8354bdd54f910b..456e28d5b06070929545cabe15d20942b937deca 100644 --- a/data/perf/old/emulated/generate_plot.py +++ b/data/perf/old/emulated/generate_plot.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/deploy/all.sh b/deploy/all.sh index c169bc92c0d9a6dea87de919ad20b4cf3afc1199..97f4db37d53f4a7fcca850c51a5bfe6cc7653cb4 100755 --- a/deploy/all.sh +++ b/deploy/all.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -27,7 +27,47 @@ export TFS_REGISTRY_IMAGES=${TFS_REGISTRY_IMAGES:-"http://localhost:32000/tfs/"} # If not already set, set the list of components, separated by spaces, you want to build images for, and deploy. # By default, only basic components are deployed -export TFS_COMPONENTS=${TFS_COMPONENTS:-"context device ztp monitoring pathcomp service slice nbi webui load_generator"} +export TFS_COMPONENTS=${TFS_COMPONENTS:-"context device pathcomp service slice nbi webui load_generator"} + +# 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" + +# 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" # If not already set, set the tag you want to use for your images. export TFS_IMAGE_TAG=${TFS_IMAGE_TAG:-"dev"} @@ -63,12 +103,7 @@ export CRDB_USERNAME=${CRDB_USERNAME:-"tfs"} # If not already set, set the database user's password to be used by Context. export CRDB_PASSWORD=${CRDB_PASSWORD:-"tfs123"} -# If not already set, set the database name to be used by Context. -export CRDB_DATABASE=${CRDB_DATABASE:-"tfs"} - # If not already set, set CockroachDB installation mode. Accepted values are: 'single' and 'cluster'. -# "YES", the database pointed by variable CRDB_NAMESPACE will be dropped while -# checking/deploying CockroachDB. # - If CRDB_DEPLOY_MODE is "single", CockroachDB is deployed in single node mode. It is convenient for # development and testing purposes and should fit in a VM. IT SHOULD NOT BE USED IN PRODUCTION ENVIRONMENTS. # - If CRDB_DEPLOY_MODE is "cluster", CockroachDB is deployed in cluster mode, and an entire CockroachDB cluster @@ -80,7 +115,7 @@ export CRDB_DEPLOY_MODE=${CRDB_DEPLOY_MODE:-"single"} # If not already set, disable flag for dropping database, if it exists. # WARNING: ACTIVATING THIS FLAG IMPLIES LOOSING THE DATABASE INFORMATION! -# If CRDB_DROP_DATABASE_IF_EXISTS is "YES", the database pointed by variable CRDB_NAMESPACE will be dropped while +# If CRDB_DROP_DATABASE_IF_EXISTS is "YES", the databases starting with "tfs_" will be dropped while # checking/deploying CockroachDB. export CRDB_DROP_DATABASE_IF_EXISTS=${CRDB_DROP_DATABASE_IF_EXISTS:-""} @@ -102,6 +137,14 @@ export NATS_EXT_PORT_CLIENT=${NATS_EXT_PORT_CLIENT:-"4222"} # If not already set, set the external port NATS HTTP Mgmt GUI interface will be exposed to. export NATS_EXT_PORT_HTTP=${NATS_EXT_PORT_HTTP:-"8222"} +# If not already set, set NATS installation mode. Accepted values are: 'single' and 'cluster'. +# - If NATS_DEPLOY_MODE is "single", NATS is deployed in single node mode. It is convenient for +# development and testing purposes and should fit in a VM. IT SHOULD NOT BE USED IN PRODUCTION ENVIRONMENTS. +# - If NATS_DEPLOY_MODE is "cluster", NATS is deployed in cluster mode, and an entire NATS cluster +# with 3 replicas (set by default) will be deployed. It is convenient for production and +# provides scalability features. +export NATS_DEPLOY_MODE=${NATS_DEPLOY_MODE:-"single"} + # If not already set, disable flag for re-deploying NATS from scratch. # WARNING: ACTIVATING THIS FLAG IMPLIES LOOSING THE MESSAGE BROKER INFORMATION! # If NATS_REDEPLOY is "YES", the message broker will be dropped while checking/deploying NATS. @@ -137,7 +180,7 @@ export QDB_TABLE_SLICE_GROUPS=${QDB_TABLE_SLICE_GROUPS:-"tfs_slice_groups"} # If not already set, disable flag for dropping tables if they exist. # WARNING: ACTIVATING THIS FLAG IMPLIES LOOSING THE TABLE INFORMATION! # If QDB_DROP_TABLES_IF_EXIST is "YES", the tables pointed by variables -# QDB_TABLE_MONITORING_KPIS and QDB_TABLE_SLICE_GROUPS will be dropped while +# QDB_TABLE_MONITORING_KPIS and QDB_TABLE_SLICE_GROUPS will be dropped while # checking/deploying QuestDB. export QDB_DROP_TABLES_IF_EXIST=${QDB_DROP_TABLES_IF_EXIST:-""} @@ -169,6 +212,9 @@ export GRAF_EXT_PORT_HTTP=${GRAF_EXT_PORT_HTTP:-"3000"} # Deploy QuestDB ./deploy/qdb.sh +# Deploy Apache Kafka +./deploy/kafka.sh + # Expose Dashboard ./deploy/expose_dashboard.sh diff --git a/deploy/component.sh b/deploy/component.sh index 89d2383d7c62393753de27abf9d0a15f67066c76..74aca0c4ef40a2abcd88a233325ccc0c0a73ba67 100755 --- a/deploy/component.sh +++ b/deploy/component.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/deploy/crdb.sh b/deploy/crdb.sh index c979ad4f2c18861c6a93b6b04e5d8e3e71aae41e..ad0bdd30b6d01c8c70ad454220ee7d19f23468b8 100755 --- a/deploy/crdb.sh +++ b/deploy/crdb.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -33,12 +33,7 @@ export CRDB_USERNAME=${CRDB_USERNAME:-"tfs"} # If not already set, set the database user's password to be used by Context. export CRDB_PASSWORD=${CRDB_PASSWORD:-"tfs123"} -# If not already set, set the database name to be used by Context. -export CRDB_DATABASE=${CRDB_DATABASE:-"tfs"} - # If not already set, set CockroachDB installation mode. Accepted values are: 'single' and 'cluster'. -# "YES", the database pointed by variable CRDB_NAMESPACE will be dropped while -# checking/deploying CockroachDB. # - If CRDB_DEPLOY_MODE is "single", CockroachDB is deployed in single node mode. It is convenient for # development and testing purposes and should fit in a VM. IT SHOULD NOT BE USED IN PRODUCTION ENVIRONMENTS. # - If CRDB_DEPLOY_MODE is "cluster", CockroachDB is deployed in cluster mode, and an entire CockroachDB cluster @@ -48,9 +43,9 @@ export CRDB_DATABASE=${CRDB_DATABASE:-"tfs"} # Ref: https://www.cockroachlabs.com/docs/stable/recommended-production-settings.html export CRDB_DEPLOY_MODE=${CRDB_DEPLOY_MODE:-"single"} -# If not already set, disable flag for dropping database if exists. +# If not already set, disable flag for dropping database, if it exists. # WARNING: ACTIVATING THIS FLAG IMPLIES LOOSING THE DATABASE INFORMATION! -# If CRDB_DROP_DATABASE_IF_EXISTS is "YES", the database pointed by variable CRDB_DATABASE will be dropped while +# If CRDB_DROP_DATABASE_IF_EXISTS is "YES", the databases starting with "tfs_" will be dropped while # checking/deploying CockroachDB. export CRDB_DROP_DATABASE_IF_EXISTS=${CRDB_DROP_DATABASE_IF_EXISTS:-""} @@ -79,14 +74,13 @@ function crdb_deploy_single() { kubectl create namespace ${CRDB_NAMESPACE} echo - echo "CockroachDB (single-node)" + echo "CockroachDB (single-mode)" echo ">>> Checking if CockroachDB is deployed..." if kubectl get --namespace ${CRDB_NAMESPACE} statefulset/cockroachdb &> /dev/null; then echo ">>> CockroachDB is present; skipping step." else echo ">>> Deploy CockroachDB" cp "${CRDB_MANIFESTS_PATH}/single-node.yaml" "${TMP_MANIFESTS_FOLDER}/crdb_single_node.yaml" - sed -i "s/%CRDB_DATABASE%/${CRDB_DATABASE}/g" "${TMP_MANIFESTS_FOLDER}/crdb_single_node.yaml" sed -i "s/%CRDB_USERNAME%/${CRDB_USERNAME}/g" "${TMP_MANIFESTS_FOLDER}/crdb_single_node.yaml" sed -i "s/%CRDB_PASSWORD%/${CRDB_PASSWORD}/g" "${TMP_MANIFESTS_FOLDER}/crdb_single_node.yaml" kubectl apply --namespace ${CRDB_NAMESPACE} -f "${TMP_MANIFESTS_FOLDER}/crdb_single_node.yaml" @@ -139,7 +133,7 @@ function crdb_deploy_single() { } function crdb_undeploy_single() { - echo "CockroachDB" + echo "CockroachDB (single-mode)" echo ">>> Checking if CockroachDB is deployed..." if kubectl get --namespace ${CRDB_NAMESPACE} statefulset/cockroachdb &> /dev/null; then echo ">>> Undeploy CockroachDB" @@ -156,23 +150,27 @@ function crdb_undeploy_single() { echo } -function crdb_drop_database_single() { - echo "Drop database if exists" - - if [[ -z "${GITLAB_CI}" ]]; then - #kubectl --namespace ${CRDB_NAMESPACE} get service cockroachdb-public -o yaml - CRDB_HOST=$(kubectl --namespace ${CRDB_NAMESPACE} get service cockroachdb-public -o 'jsonpath={.spec.clusterIP}') - CRDB_PORT=$(kubectl --namespace ${CRDB_NAMESPACE} get service cockroachdb-public -o 'jsonpath={.spec.ports[?(@.name=="sql")].port}') - else - CRDB_HOST="127.0.0.1" - CRDB_PORT=${CRDB_EXT_PORT_SQL} - fi +function crdb_drop_databases_single() { + echo "Drop TFS databases, if exist" - CRDB_CLIENT_URL="postgresql://${CRDB_USERNAME}:${CRDB_PASSWORD}@${CRDB_HOST}:${CRDB_PORT}/defaultdb?sslmode=require" + CRDB_PORT=$(kubectl --namespace ${CRDB_NAMESPACE} get service cockroachdb-public -o 'jsonpath={.spec.ports[?(@.name=="sql")].port}') + CRDB_CLIENT_URL="postgresql://${CRDB_USERNAME}:${CRDB_PASSWORD}@cockroachdb-0:${CRDB_PORT}/defaultdb?sslmode=require" echo "CRDB_CLIENT_URL=${CRDB_CLIENT_URL}" - kubectl exec -i --namespace ${CRDB_NAMESPACE} cockroachdb-0 -- \ - ./cockroach sql --certs-dir=/cockroach/cockroach-certs --url=${CRDB_CLIENT_URL} \ - --execute "DROP DATABASE IF EXISTS ${CRDB_DATABASE};" + + DATABASES=$( + kubectl exec -i --namespace ${CRDB_NAMESPACE} cockroachdb-0 -- \ + ./cockroach sql --certs-dir=/cockroach/cockroach-certs --url=${CRDB_CLIENT_URL} \ + --execute "SHOW DATABASES;" --format=tsv | awk '{print $1}' | grep "^tfs" + ) + echo "Found TFS databases: ${DATABASES}" | tr '\n' ' ' + echo + + for DB_NAME in $DATABASES; do + echo "Dropping TFS database: $DB_NAME" + kubectl exec -i --namespace ${CRDB_NAMESPACE} cockroachdb-0 -- \ + ./cockroach sql --certs-dir=/cockroach/cockroach-certs --url=${CRDB_CLIENT_URL} \ + --execute="DROP DATABASE IF EXISTS $DB_NAME CASCADE;" + done echo } @@ -223,7 +221,7 @@ function crdb_deploy_cluster() { kubectl create namespace ${CRDB_NAMESPACE} echo - echo "CockroachDB" + echo "CockroachDB (cluster-mode)" echo ">>> Checking if CockroachDB is deployed..." if kubectl get --namespace ${CRDB_NAMESPACE} statefulset/cockroachdb &> /dev/null; then echo ">>> CockroachDB is present; skipping step." @@ -319,7 +317,7 @@ function crdb_undeploy_cluster() { fi echo - echo "CockroachDB" + echo "CockroachDB (cluster-mode)" echo ">>> Checking if CockroachDB is deployed..." if kubectl get --namespace ${CRDB_NAMESPACE} statefulset/cockroachdb &> /dev/null; then echo ">>> Undeploy CockroachDB" @@ -351,11 +349,23 @@ function crdb_undeploy_cluster() { echo } -function crdb_drop_database_cluster() { - echo "Drop database if exists" - kubectl exec -i --namespace ${CRDB_NAMESPACE} cockroachdb-client-secure -- \ - ./cockroach sql --certs-dir=/cockroach/cockroach-certs --host=cockroachdb-public --execute \ - "DROP DATABASE IF EXISTS ${CRDB_DATABASE};" +function crdb_drop_databases_cluster() { + echo "Drop TFS databases, if exist" + + DATABASES=$( + kubectl exec -i --namespace ${CRDB_NAMESPACE} cockroachdb-client-secure -- \ + ./cockroach sql --certs-dir=/cockroach/cockroach-certs --host=cockroachdb-public \ + --execute "SHOW DATABASES;" --format=tsv | awk '{print $1}' | grep "^tfs" + ) + echo "Found TFS databases: ${DATABASES}" | tr '\n' ' ' + echo + + for DB_NAME in $DATABASES; do + echo "Dropping TFS database: $DB_NAME" + kubectl exec -i --namespace ${CRDB_NAMESPACE} cockroachdb-client-secure -- \ + ./cockroach sql --certs-dir=/cockroach/cockroach-certs --host=cockroachdb-public \ + --execute="DROP DATABASE IF EXISTS $DB_NAME CASCADE;" + done echo } @@ -365,9 +375,10 @@ if [ "$CRDB_DEPLOY_MODE" == "single" ]; then fi crdb_deploy_single + sleep 3 if [ "$CRDB_DROP_DATABASE_IF_EXISTS" == "YES" ]; then - crdb_drop_database_single + crdb_drop_databases_single fi elif [ "$CRDB_DEPLOY_MODE" == "cluster" ]; then if [ "$CRDB_REDEPLOY" == "YES" ]; then @@ -375,9 +386,10 @@ elif [ "$CRDB_DEPLOY_MODE" == "cluster" ]; then fi crdb_deploy_cluster + sleep 3 if [ "$CRDB_DROP_DATABASE_IF_EXISTS" == "YES" ]; then - crdb_drop_database_cluster + crdb_drop_databases_cluster fi else echo "Unsupported value: CRDB_DEPLOY_MODE=$CRDB_DEPLOY_MODE" diff --git a/deploy/expose_dashboard.sh b/deploy/expose_dashboard.sh index f2391ab5d5b028bed11f23a2f95c06054d1f0cbc..296014ee3c3764a0e3f8af36af665a10365ef54f 100755 --- a/deploy/expose_dashboard.sh +++ b/deploy/expose_dashboard.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/deploy/kafka.sh b/deploy/kafka.sh new file mode 100755 index 0000000000000000000000000000000000000000..e426069034364d2d7a745b0633d531c7db811176 --- /dev/null +++ b/deploy/kafka.sh @@ -0,0 +1,90 @@ +#!/bin/bash +# 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. + +######################################################################################################################## +# Read deployment settings +######################################################################################################################## + +# If not already set, set the namespace where Apache Kafka will be deployed. +export KFK_NAMESPACE=${KFK_NAMESPACE:-"kafka"} + +# If not already set, set the port Apache Kafka server will be exposed to. +export KFK_SERVER_PORT=${KFK_SERVER_PORT:-"9092"} + +# If not already set, if flag is YES, Apache Kafka will be redeployed and all topics will be lost. +export KFK_REDEPLOY=${KFK_REDEPLOY:-""} + + +######################################################################################################################## +# Automated steps start here +######################################################################################################################## + + # Constants + TMP_FOLDER="./tmp" + KFK_MANIFESTS_PATH="manifests/kafka" + KFK_ZOOKEEPER_MANIFEST="01-zookeeper.yaml" + KFK_MANIFEST="02-kafka.yaml" + + # Create a tmp folder for files modified during the deployment + TMP_MANIFESTS_FOLDER="${TMP_FOLDER}/${KFK_NAMESPACE}/manifests" + mkdir -p ${TMP_MANIFESTS_FOLDER} + +function kafka_deploy() { + # copy zookeeper and kafka manifest files to temporary manifest location + cp "${KFK_MANIFESTS_PATH}/${KFK_ZOOKEEPER_MANIFEST}" "${TMP_MANIFESTS_FOLDER}/${KFK_ZOOKEEPER_MANIFEST}" + cp "${KFK_MANIFESTS_PATH}/${KFK_MANIFEST}" "${TMP_MANIFESTS_FOLDER}/${KFK_MANIFEST}" + + # echo "Apache Kafka Namespace" + echo "Delete Apache Kafka Namespace" + kubectl delete namespace ${KFK_NAMESPACE} --ignore-not-found + + echo "Create Apache Kafka Namespace" + kubectl create namespace ${KFK_NAMESPACE} + + # echo ">>> Deplying Apache Kafka Zookeeper" + # Kafka zookeeper service should be deployed before the kafka service + kubectl --namespace ${KFK_NAMESPACE} apply -f "${TMP_MANIFESTS_FOLDER}/${KFK_ZOOKEEPER_MANIFEST}" + + KFK_ZOOKEEPER_SERVICE="zookeeper-service" # this command may be replaced with command to extract service name automatically + KFK_ZOOKEEPER_IP=$(kubectl --namespace ${KFK_NAMESPACE} get service ${KFK_ZOOKEEPER_SERVICE} -o 'jsonpath={.spec.clusterIP}') + + # Kafka service should be deployed after the zookeeper service + sed -i "s//${KFK_ZOOKEEPER_IP}/" "${TMP_MANIFESTS_FOLDER}/$KFK_MANIFEST" + + # echo ">>> Deploying Apache Kafka Broker" + kubectl --namespace ${KFK_NAMESPACE} apply -f "${TMP_MANIFESTS_FOLDER}/$KFK_MANIFEST" + + # echo ">>> Verifing Apache Kafka deployment" + sleep 5 + # KFK_PODS_STATUS=$(kubectl --namespace ${KFK_NAMESPACE} get pods) + # if echo "$KFK_PODS_STATUS" | grep -qEv 'STATUS|Running'; then + # echo "Deployment Error: \n $KFK_PODS_STATUS" + # else + # echo "$KFK_PODS_STATUS" + # fi +} + +echo ">>> Apache Kafka" +echo "Checking if Apache Kafka is deployed ... " +if [ "$KFK_REDEPLOY" == "YES" ]; then + echo "Redeploying kafka namespace" + kafka_deploy +elif kubectl get namespace "${KFK_NAMESPACE}" &> /dev/null; then + echo "Apache Kafka already present; skipping step." +else + echo "Kafka namespace doesn't exists. Deploying kafka namespace" + kafka_deploy +fi +echo diff --git a/deploy/mock_blockchain.sh b/deploy/mock_blockchain.sh index fafa435b10f7c027e088435997ec01ebf1858d0f..7ba4b6de285859863683ce5c27c6bcfc140d9749 100755 --- a/deploy/mock_blockchain.sh +++ b/deploy/mock_blockchain.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/deploy/nats.sh b/deploy/nats.sh index 366270a6915a1eef969846446ecc9152c3fa9531..cb3dd23183d0f3004e8ffb3c82b3cc91414bf704 100755 --- a/deploy/nats.sh +++ b/deploy/nats.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -27,6 +27,14 @@ export NATS_EXT_PORT_CLIENT=${NATS_EXT_PORT_CLIENT:-"4222"} # If not already set, set the external port NATS HTTP Mgmt GUI interface will be exposed to. export NATS_EXT_PORT_HTTP=${NATS_EXT_PORT_HTTP:-"8222"} +# If not already set, set NATS installation mode. Accepted values are: 'single' and 'cluster'. +# - If NATS_DEPLOY_MODE is "single", NATS is deployed in single node mode. It is convenient for +# development and testing purposes and should fit in a VM. IT SHOULD NOT BE USED IN PRODUCTION ENVIRONMENTS. +# - If NATS_DEPLOY_MODE is "cluster", NATS is deployed in cluster mode, and an entire NATS cluster +# with 3 replicas (set by default) will be deployed. It is convenient for production and +# provides scalability features. +export NATS_DEPLOY_MODE=${NATS_DEPLOY_MODE:-"single"} + # If not already set, disable flag for re-deploying NATS from scratch. # WARNING: ACTIVATING THIS FLAG IMPLIES LOOSING THE MESSAGE BROKER INFORMATION! # If NATS_REDEPLOY is "YES", the message broker will be dropped while checking/deploying NATS. @@ -37,6 +45,14 @@ export NATS_REDEPLOY=${NATS_REDEPLOY:-""} # Automated steps start here ######################################################################################################################## +# Constants +TMP_FOLDER="./tmp" +NATS_MANIFESTS_PATH="manifests/nats" + +# Create a tmp folder for files modified during the deployment +TMP_MANIFESTS_FOLDER="${TMP_FOLDER}/${NATS_NAMESPACE}/manifests" +mkdir -p $TMP_MANIFESTS_FOLDER + function nats_deploy_single() { echo "NATS Namespace" echo ">>> Create NATS Namespace (if missing)" @@ -47,18 +63,86 @@ function nats_deploy_single() { helm3 repo add nats https://nats-io.github.io/k8s/helm/charts/ echo + echo "Install NATS (single-mode)" + echo ">>> Checking if NATS is deployed..." + if kubectl get --namespace ${NATS_NAMESPACE} statefulset/${NATS_NAMESPACE} &> /dev/null; then + echo ">>> NATS is present; skipping step." + else + echo ">>> Deploy NATS" + helm3 install ${NATS_NAMESPACE} nats/nats --namespace ${NATS_NAMESPACE} --set nats.image=nats:2.9-alpine --set config.cluster.enabled=true --set config.cluster.tls.enabled=true + + + echo ">>> Waiting NATS statefulset to be created..." + while ! kubectl get --namespace ${NATS_NAMESPACE} statefulset/${NATS_NAMESPACE} &> /dev/null; do + printf "%c" "." + sleep 1 + done + + # Wait for statefulset condition "Available=True" does not work + # Wait for statefulset condition "jsonpath='{.status.readyReplicas}'=3" throws error: + # "error: readyReplicas is not found" + # Workaround: Check the pods are ready + #echo ">>> NATS statefulset created. Waiting for readiness condition..." + #kubectl wait --namespace ${NATS_NAMESPACE} --for=condition=Available=True --timeout=300s statefulset/nats + #kubectl wait --namespace ${NATS_NAMESPACE} --for=jsonpath='{.status.readyReplicas}'=3 --timeout=300s \ + # statefulset/nats + echo ">>> NATS statefulset created. Waiting NATS pods to be created..." + while ! kubectl get --namespace ${NATS_NAMESPACE} pod/${NATS_NAMESPACE}-0 &> /dev/null; do + printf "%c" "." + sleep 1 + done + kubectl wait --namespace ${NATS_NAMESPACE} --for=condition=Ready --timeout=300s pod/${NATS_NAMESPACE}-0 + fi + echo + + echo "NATS Port Mapping" + echo ">>> Expose NATS Client port (4222->${NATS_EXT_PORT_CLIENT})" + NATS_PORT_CLIENT=$(kubectl --namespace ${NATS_NAMESPACE} get service ${NATS_NAMESPACE} -o 'jsonpath={.spec.ports[?(@.name=="client")].port}') + PATCH='{"data": {"'${NATS_EXT_PORT_CLIENT}'": "'${NATS_NAMESPACE}'/'${NATS_NAMESPACE}':'${NATS_PORT_CLIENT}'"}}' + kubectl patch configmap nginx-ingress-tcp-microk8s-conf --namespace ingress --patch "${PATCH}" + + PORT_MAP='{"containerPort": '${NATS_EXT_PORT_CLIENT}', "hostPort": '${NATS_EXT_PORT_CLIENT}'}' + CONTAINER='{"name": "nginx-ingress-microk8s", "ports": ['${PORT_MAP}']}' + PATCH='{"spec": {"template": {"spec": {"containers": ['${CONTAINER}']}}}}' + kubectl patch daemonset nginx-ingress-microk8s-controller --namespace ingress --patch "${PATCH}" + echo + + echo ">>> Expose NATS HTTP Mgmt GUI port (8222->${NATS_EXT_PORT_HTTP})" + NATS_PORT_HTTP=$(kubectl --namespace ${NATS_NAMESPACE} get service ${NATS_NAMESPACE} -o 'jsonpath={.spec.ports[?(@.name=="monitor")].port}') + PATCH='{"data": {"'${NATS_EXT_PORT_HTTP}'": "'${NATS_NAMESPACE}'/'${NATS_NAMESPACE}':'${NATS_PORT_HTTP}'"}}' + kubectl patch configmap nginx-ingress-tcp-microk8s-conf --namespace ingress --patch "${PATCH}" + + PORT_MAP='{"containerPort": '${NATS_EXT_PORT_HTTP}', "hostPort": '${NATS_EXT_PORT_HTTP}'}' + CONTAINER='{"name": "nginx-ingress-microk8s", "ports": ['${PORT_MAP}']}' + PATCH='{"spec": {"template": {"spec": {"containers": ['${CONTAINER}']}}}}' + kubectl patch daemonset nginx-ingress-microk8s-controller --namespace ingress --patch "${PATCH}" + echo +} + + +function nats_deploy_cluster() { + echo "NATS Namespace" + echo ">>> Create NATS Namespace (if missing)" + kubectl create namespace ${NATS_NAMESPACE} + echo + + echo "Add NATS Helm Chart" + helm3 repo add nats https://nats-io.github.io/k8s/helm/charts/ + echo + echo "Upgrade NATS Helm Chart" helm3 repo update nats echo - echo "Install NATS (single-node)" + echo "Install NATS (cluster-mode)" echo ">>> Checking if NATS is deployed..." if kubectl get --namespace ${NATS_NAMESPACE} statefulset/${NATS_NAMESPACE} &> /dev/null; then echo ">>> NATS is present; skipping step." else echo ">>> Deploy NATS" - helm3 install ${NATS_NAMESPACE} nats/nats --namespace ${NATS_NAMESPACE} --set nats.image=nats:2.9-alpine - + cp "${NATS_MANIFESTS_PATH}/cluster.yaml" "${TMP_MANIFESTS_FOLDER}/nats_cluster.yaml" + helm3 install ${NATS_NAMESPACE} nats/nats --namespace ${NATS_NAMESPACE} -f "${TMP_MANIFESTS_FOLDER}/nats_cluster.yaml" + echo ">>> Waiting NATS statefulset to be created..." while ! kubectl get --namespace ${NATS_NAMESPACE} statefulset/${NATS_NAMESPACE} &> /dev/null; do printf "%c" "." @@ -78,7 +162,17 @@ function nats_deploy_single() { printf "%c" "." sleep 1 done + while ! kubectl get --namespace ${NATS_NAMESPACE} pod/${NATS_NAMESPACE}-1 &> /dev/null; do + printf "%c" "." + sleep 1 + done + while ! kubectl get --namespace ${NATS_NAMESPACE} pod/${NATS_NAMESPACE}-2 &> /dev/null; do + printf "%c" "." + sleep 1 + done kubectl wait --namespace ${NATS_NAMESPACE} --for=condition=Ready --timeout=300s pod/${NATS_NAMESPACE}-0 + kubectl wait --namespace ${NATS_NAMESPACE} --for=condition=Ready --timeout=300s pod/${NATS_NAMESPACE}-1 + kubectl wait --namespace ${NATS_NAMESPACE} --for=condition=Ready --timeout=300s pod/${NATS_NAMESPACE}-2 fi echo @@ -110,7 +204,7 @@ function nats_deploy_single() { echo } -function nats_undeploy_single() { +function nats_undeploy() { echo "NATS" echo ">>> Checking if NATS is deployed..." if kubectl get --namespace ${NATS_NAMESPACE} statefulset/${NATS_NAMESPACE} &> /dev/null; then @@ -128,7 +222,13 @@ function nats_undeploy_single() { } if [ "$NATS_REDEPLOY" == "YES" ]; then - nats_undeploy_single + nats_undeploy fi -nats_deploy_single +if [ "$NATS_DEPLOY_MODE" == "single" ]; then + nats_deploy_single +elif [ "$NATS_DEPLOY_MODE" == "cluster" ]; then + nats_deploy_cluster +else + echo "Unsupported value: NATS_DEPLOY_MODE=$NATS_DEPLOY_MODE" +fi \ No newline at end of file diff --git a/deploy/qdb.sh b/deploy/qdb.sh index acbcfd4f96ccbd2b09d5d82f66a1bf801a710780..4fac6a3ce254a766b06b0081e45427b3fa0e318b 100755 --- a/deploy/qdb.sh +++ b/deploy/qdb.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -44,7 +44,7 @@ export QDB_TABLE_SLICE_GROUPS=${QDB_TABLE_SLICE_GROUPS:-"tfs_slice_groups"} # If not already set, disable flag for dropping tables if they exist. # WARNING: ACTIVATING THIS FLAG IMPLIES LOOSING THE TABLE INFORMATION! -# If QDB_DROP_TABLES_IF_EXIST is "YES", the table pointed by variables +# If QDB_DROP_TABLES_IF_EXIST is "YES", the tables pointed by variables # QDB_TABLE_MONITORING_KPIS and QDB_TABLE_SLICE_GROUPS will be dropped # while checking/deploying QuestDB. export QDB_DROP_TABLES_IF_EXIST=${QDB_DROP_TABLES_IF_EXIST:-""} diff --git a/deploy/show.sh b/deploy/show.sh index 4fa1ce3a6dac5194e967ccbe0826a6ed9a64e3f8..1bd7d5bf98def0d4a0675883fa05cd1937974eba 100755 --- a/deploy/show.sh +++ b/deploy/show.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/deploy/tfs.sh b/deploy/tfs.sh index 3fdbe77fb502c42aaf7dd507ab239f6b3bb20056..f396094080c8ec4a33b016b88bc0137a3a32e65c 100755 --- a/deploy/tfs.sh +++ b/deploy/tfs.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -27,7 +27,7 @@ export TFS_REGISTRY_IMAGES=${TFS_REGISTRY_IMAGES:-"http://localhost:32000/tfs/"} # If not already set, set the list of components, separated by spaces, you want to build images for, and deploy. # By default, only basic components are deployed -export TFS_COMPONENTS=${TFS_COMPONENTS:-"context device ztp monitoring pathcomp service slice nbi webui load_generator"} +export TFS_COMPONENTS=${TFS_COMPONENTS:-"context device pathcomp service slice nbi webui load_generator"} # If not already set, set the tag you want to use for your images. export TFS_IMAGE_TAG=${TFS_IMAGE_TAG:-"dev"} @@ -63,9 +63,6 @@ export CRDB_USERNAME=${CRDB_USERNAME:-"tfs"} # If not already set, set the database user's password to be used by Context. export CRDB_PASSWORD=${CRDB_PASSWORD:-"tfs123"} -# If not already set, set the database name to be used by Context. -export CRDB_DATABASE=${CRDB_DATABASE:-"tfs"} - # ----- NATS ------------------------------------------------------------------- @@ -115,6 +112,17 @@ export PROM_EXT_PORT_HTTP=${PROM_EXT_PORT_HTTP:-"9090"} export GRAF_EXT_PORT_HTTP=${GRAF_EXT_PORT_HTTP:-"3000"} +# ----- Apache Kafka ------------------------------------------------------ + +# If not already set, set the namespace where Apache Kafka will be deployed. +export KFK_NAMESPACE=${KFK_NAMESPACE:-"kafka"} + +# If not already set, set the port Apache Kafka server will be exposed to. +export KFK_SERVER_PORT=${KFK_SERVER_PORT:-"9092"} + +# If not already set, if flag is YES, Apache Kafka will be redeployed and topic will be lost. +export KFK_REDEPLOY=${KFK_REDEPLOY:-""} + ######################################################################################################################## # Automated steps start here ######################################################################################################################## @@ -135,17 +143,23 @@ kubectl create namespace $TFS_K8S_NAMESPACE sleep 2 printf "\n" -echo "Create secret with CockroachDB data" +echo ">>> Create Secret with CockroachDB data..." CRDB_SQL_PORT=$(kubectl --namespace ${CRDB_NAMESPACE} get service cockroachdb-public -o 'jsonpath={.spec.ports[?(@.name=="sql")].port}') kubectl create secret generic crdb-data --namespace ${TFS_K8S_NAMESPACE} --type='Opaque' \ --from-literal=CRDB_NAMESPACE=${CRDB_NAMESPACE} \ --from-literal=CRDB_SQL_PORT=${CRDB_SQL_PORT} \ - --from-literal=CRDB_DATABASE=${CRDB_DATABASE} \ --from-literal=CRDB_USERNAME=${CRDB_USERNAME} \ --from-literal=CRDB_PASSWORD=${CRDB_PASSWORD} \ --from-literal=CRDB_SSLMODE=require printf "\n" +echo ">>> Create Secret with Apache Kakfa..." +KFK_SERVER_PORT=$(kubectl --namespace ${KFK_NAMESPACE} get service kafka-service -o 'jsonpath={.spec.ports[0].port}') +kubectl create secret generic kfk-kpi-data --namespace ${TFS_K8S_NAMESPACE} --type='Opaque' \ + --from-literal=KFK_NAMESPACE=${KFK_NAMESPACE} \ + --from-literal=KFK_SERVER_PORT=${KFK_SERVER_PORT} +printf "\n" + echo "Create secret with NATS data" NATS_CLIENT_PORT=$(kubectl --namespace ${NATS_NAMESPACE} get service ${NATS_NAMESPACE} -o 'jsonpath={.spec.ports[?(@.name=="client")].port}') if [ -z "$NATS_CLIENT_PORT" ]; then @@ -174,6 +188,21 @@ kubectl create secret generic qdb-data --namespace ${TFS_K8S_NAMESPACE} --type=' --from-literal=METRICSDB_PASSWORD=${QDB_PASSWORD} printf "\n" +# Check if "dlt" is in the list of components +if [[ " ${TFS_COMPONENTS[@]} " =~ " dlt " ]]; then + echo "Create secret for HLF keystore" + kubectl create secret generic dlt-keystone --namespace ${TFS_K8S_NAMESPACE} --from-file=keystore=${KEY_DIRECTORY_PATH} + printf "\n" + + echo "Create secret for HLF signcerts" + kubectl create secret generic dlt-signcerts --namespace ${TFS_K8S_NAMESPACE} --from-file=signcerts.pem=${CERT_DIRECTORY_PATH} + printf "\n" + + echo "Create secret for HLF ca.crt" + kubectl create secret generic dlt-ca-crt --namespace ${TFS_K8S_NAMESPACE} --from-file=ca.crt=${TLS_CERT_PATH} + printf "\n" +fi + echo "Deploying components and collecting environment variables..." ENV_VARS_SCRIPT=tfs_runtime_env_vars.sh echo "# Environment variables for TeraFlowSDN deployment" > $ENV_VARS_SCRIPT @@ -204,6 +233,14 @@ if [[ $DOCKER_MAJOR_VERSION -ge 23 ]]; then DOCKER_BUILD="docker buildx build" fi +LINKERD_STATUS="$(microk8s status -a linkerd)" +if [[ $linkerd_status =~ "enabled" ]]; then + echo "LinkerD installed: workloads will be injected" +else + echo "LinkerD not installed" +fi +printf "\n" + for COMPONENT in $TFS_COMPONENTS; do echo "Processing '$COMPONENT' component..." @@ -213,15 +250,17 @@ for COMPONENT in $TFS_COMPONENTS; do if [ "$COMPONENT" == "ztp" ] || [ "$COMPONENT" == "policy" ]; then $DOCKER_BUILD -t "$COMPONENT:$TFS_IMAGE_TAG" -f ./src/"$COMPONENT"/Dockerfile ./src/"$COMPONENT"/ > "$BUILD_LOG" - elif [ "$COMPONENT" == "pathcomp" ]; then + elif [ "$COMPONENT" == "pathcomp" ] || [ "$COMPONENT" == "telemetry" ] || [ "$COMPONENT" == "analytics" ]; then BUILD_LOG="$TMP_LOGS_FOLDER/build_${COMPONENT}-frontend.log" $DOCKER_BUILD -t "$COMPONENT-frontend:$TFS_IMAGE_TAG" -f ./src/"$COMPONENT"/frontend/Dockerfile . > "$BUILD_LOG" BUILD_LOG="$TMP_LOGS_FOLDER/build_${COMPONENT}-backend.log" $DOCKER_BUILD -t "$COMPONENT-backend:$TFS_IMAGE_TAG" -f ./src/"$COMPONENT"/backend/Dockerfile . > "$BUILD_LOG" - # next command is redundant, but helpful to keep cache updated between rebuilds - IMAGE_NAME="$COMPONENT-backend:$TFS_IMAGE_TAG-builder" - $DOCKER_BUILD -t "$IMAGE_NAME" --target builder -f ./src/"$COMPONENT"/backend/Dockerfile . >> "$BUILD_LOG" + if [ "$COMPONENT" == "pathcomp" ]; then + # next command is redundant, but helpful to keep cache updated between rebuilds + IMAGE_NAME="$COMPONENT-backend:$TFS_IMAGE_TAG-builder" + $DOCKER_BUILD -t "$IMAGE_NAME" --target builder -f ./src/"$COMPONENT"/backend/Dockerfile . >> "$BUILD_LOG" + fi elif [ "$COMPONENT" == "dlt" ]; then BUILD_LOG="$TMP_LOGS_FOLDER/build_${COMPONENT}-connector.log" $DOCKER_BUILD -t "$COMPONENT-connector:$TFS_IMAGE_TAG" -f ./src/"$COMPONENT"/connector/Dockerfile . > "$BUILD_LOG" @@ -234,7 +273,7 @@ for COMPONENT in $TFS_COMPONENTS; do echo " Pushing Docker image to '$TFS_REGISTRY_IMAGES'..." - if [ "$COMPONENT" == "pathcomp" ]; then + if [ "$COMPONENT" == "pathcomp" ] || [ "$COMPONENT" == "telemetry" ] || [ "$COMPONENT" == "analytics" ] ; then IMAGE_URL=$(echo "$TFS_REGISTRY_IMAGES/$COMPONENT-frontend:$TFS_IMAGE_TAG" | sed 's,//,/,g' | sed 's,http:/,,g') TAG_LOG="$TMP_LOGS_FOLDER/tag_${COMPONENT}-frontend.log" @@ -279,10 +318,13 @@ for COMPONENT in $TFS_COMPONENTS; do echo " Adapting '$COMPONENT' manifest file..." MANIFEST="$TMP_MANIFESTS_FOLDER/${COMPONENT}service.yaml" - # cp ./manifests/"${COMPONENT}"service.yaml "$MANIFEST" - cat ./manifests/"${COMPONENT}"service.yaml | linkerd inject - --proxy-cpu-request "10m" --proxy-cpu-limit "1" --proxy-memory-request "64Mi" --proxy-memory-limit "256Mi" > "$MANIFEST" + if [[ $linkerd_status =~ "enabled" ]]; then + cat ./manifests/"${COMPONENT}"service.yaml | linkerd inject - --proxy-cpu-request "10m" --proxy-cpu-limit "1" --proxy-memory-request "64Mi" --proxy-memory-limit "256Mi" > "$MANIFEST" + else + cp ./manifests/"${COMPONENT}"service.yaml "$MANIFEST" + fi - if [ "$COMPONENT" == "pathcomp" ]; then + if [ "$COMPONENT" == "pathcomp" ] || [ "$COMPONENT" == "telemetry" ] || [ "$COMPONENT" == "analytics" ]; then IMAGE_URL=$(echo "$TFS_REGISTRY_IMAGES/$COMPONENT-frontend:$TFS_IMAGE_TAG" | sed 's,//,/,g' | sed 's,http:/,,g') VERSION=$(grep -i "${GITLAB_REPO_URL}/${COMPONENT}-frontend:" "$MANIFEST" | cut -d ":" -f4) sed -E -i "s#image: $GITLAB_REPO_URL/$COMPONENT-frontend:${VERSION}#image: $IMAGE_URL#g" "$MANIFEST" @@ -299,11 +341,10 @@ for COMPONENT in $TFS_COMPONENTS; do VERSION=$(grep -i "${GITLAB_REPO_URL}/${COMPONENT}-gateway:" "$MANIFEST" | cut -d ":" -f4) sed -E -i "s#image: $GITLAB_REPO_URL/$COMPONENT-gateway:${VERSION}#image: $IMAGE_URL#g" "$MANIFEST" else + VERSION=$(grep -i "${GITLAB_REPO_URL}/${COMPONENT}:" "$MANIFEST" | cut -d ":" -f4) if [ "$TFS_SKIP_BUILD" != "YES" ]; then IMAGE_URL=$(echo "$TFS_REGISTRY_IMAGES/$COMPONENT:$TFS_IMAGE_TAG" | sed 's,//,/,g' | sed 's,http:/,,g') - VERSION=$(grep -i "${GITLAB_REPO_URL}/${COMPONENT}:" "$MANIFEST" | cut -d ":" -f4) else - VERSION=$(grep -i "${GITLAB_REPO_URL}/${COMPONENT}:" "$MANIFEST" | cut -d ":" -f4) IMAGE_URL=$(echo "$TFS_REGISTRY_IMAGES/$COMPONENT:$VERSION" | sed 's,//,/,g' | sed 's,http:/,,g') fi sed -E -i "s#image: $GITLAB_REPO_URL/$COMPONENT:${VERSION}#image: $IMAGE_URL#g" "$MANIFEST" @@ -316,7 +357,7 @@ for COMPONENT in $TFS_COMPONENTS; do echo " Deploying '$COMPONENT' component to Kubernetes..." DEPLOY_LOG="$TMP_LOGS_FOLDER/deploy_${COMPONENT}.log" kubectl --namespace $TFS_K8S_NAMESPACE apply -f "$MANIFEST" > "$DEPLOY_LOG" - COMPONENT_OBJNAME=$(echo "${COMPONENT}" | sed "s/\_/-/") + COMPONENT_OBJNAME=$(echo "${COMPONENT}" | sed "s/\_/-/g") #kubectl --namespace $TFS_K8S_NAMESPACE scale deployment --replicas=0 ${COMPONENT_OBJNAME}service >> "$DEPLOY_LOG" #kubectl --namespace $TFS_K8S_NAMESPACE scale deployment --replicas=1 ${COMPONENT_OBJNAME}service >> "$DEPLOY_LOG" @@ -367,7 +408,7 @@ printf "\n" for COMPONENT in $TFS_COMPONENTS; do echo "Waiting for '$COMPONENT' component..." - COMPONENT_OBJNAME=$(echo "${COMPONENT}" | sed "s/\_/-/") + COMPONENT_OBJNAME=$(echo "${COMPONENT}" | sed "s/\_/-/g") kubectl wait --namespace $TFS_K8S_NAMESPACE \ --for='condition=available' --timeout=90s deployment/${COMPONENT_OBJNAME}service WAIT_EXIT_CODE=$? @@ -474,7 +515,7 @@ if [[ "$TFS_COMPONENTS" == *"monitoring"* ]] && [[ "$TFS_COMPONENTS" == *"webui" "type" : "postgres", "name" : "cockroachdb", "url" : "'cockroachdb-public.${CRDB_NAMESPACE}.svc.cluster.local:${CRDB_SQL_PORT}'", - "database" : "'${CRDB_DATABASE}'", + "database" : "tfs_context", "user" : "'${CRDB_USERNAME}'", "basicAuth": false, "isDefault": false, @@ -586,6 +627,10 @@ if [[ "$TFS_COMPONENTS" == *"monitoring"* ]] && [[ "$TFS_COMPONENTS" == *"webui" printf "\n\n" fi +echo "Pruning Docker Images..." +docker image prune --force +printf "\n\n" + if [ "$DOCKER_BUILD" == "docker buildx build" ]; then echo "Pruning Docker Buildx Cache..." docker buildx prune --force diff --git a/ecoc24 b/ecoc24 new file mode 120000 index 0000000000000000000000000000000000000000..37c97d3a77727ec098303cc9a5e04d711a30fcec --- /dev/null +++ b/ecoc24 @@ -0,0 +1 @@ +src/tests/ecoc24/ \ No newline at end of file diff --git a/hackfest/containerlab/README.md b/hackfest/containerlab/README.md new file mode 100644 index 0000000000000000000000000000000000000000..e08e944e991d8cb8599e89fab63f4b8b664ed73c --- /dev/null +++ b/hackfest/containerlab/README.md @@ -0,0 +1,35 @@ +# ContainerLab + +The setup consists of a management network for configuring and managing nodes. +srl1 and srl2 are interconnected. +client1 is connected to srl1 and client2 to srl2. +Routing between client1 and client2 is set up via the Nokia SR Linux nodes. + +## Management Network +Name: mgmt-net +Subnet: 172.100.100.0/24 + +## Node Kinds +Nokia SR Linux: Image ghcr.io/nokia/srlinux:23.10.3 +Linux: Image ghcr.io/hellt/network-multitool + +## Nodes + +### Nokia SR Linux +- Type: ixr6 +- CPU: 0.5 +- Memory: 2GB +- Management IP: 172.100.100.101 + +The provided SR Linux CLI commands in the _srl.cli_ enables system management and configures the GNMI server with OpenConfig models. + +### Linux + +Assigns IP 172.16.1.10/24 to eth1 and adds route to 172.16.2.0/24 via 172.16.1.1 + +In this topology file, the clients are pre-configured with the respectivly IP addresses in their interfaces and routes in their IP tables. + +### Links +- Connect srl1:e1-1 to srl2:e1-1 +- Connect client1:eth1 to srl1:e1-2 +- Connect client2:eth1 to srl2:e1-2 \ No newline at end of file diff --git a/hackfest/containerlab/commands.txt b/hackfest/containerlab/commands.txt index df5fbc0ce0163f4ce06b862e90e29854dbae204a..ac91d4b08b913209151e4024eb04b31384ed641a 100644 --- a/hackfest/containerlab/commands.txt +++ b/hackfest/containerlab/commands.txt @@ -83,19 +83,19 @@ $ssh admin@clab-tfs-scenario-srl1 # Check configurations done: -gnmic -a 172.100.100.101 -u admin -p NokiaSrl1! --skip-verify -e json_ietf get --path '/network-instances' > srl1-nis.json -gnmic -a 172.100.100.101 -u admin -p NokiaSrl1! --skip-verify -e json_ietf get --path '/interfaces' > srl1-ifs.json -gnmic -a 172.100.100.102 -u admin -p NokiaSrl1! --skip-verify -e json_ietf get --path '/network-instances' > srl2-nis.json -gnmic -a 172.100.100.102 -u admin -p NokiaSrl1! --skip-verify -e json_ietf get --path '/interfaces' > srl2-ifs.json +gnmic -a clab-tfs-scenario-srl1 -u admin -p NokiaSrl1! --skip-verify -e json_ietf get --path '/network-instances' > srl1-nis.json +gnmic -a clab-tfs-scenario-srl1 -u admin -p NokiaSrl1! --skip-verify -e json_ietf get --path '/interfaces' > srl1-ifs.json +gnmic -a clab-tfs-scenario-srl2 -u admin -p NokiaSrl1! --skip-verify -e json_ietf get --path '/network-instances' > srl2-nis.json +gnmic -a clab-tfs-scenario-srl2 -u admin -p NokiaSrl1! --skip-verify -e json_ietf get --path '/interfaces' > srl2-ifs.json # Delete elements: -gnmic -a 172.100.100.101 -u admin -p NokiaSrl1! --skip-verify -e json_ietf set --delete '/network-instances/network-instance[name=b19229e8]' -gnmic -a 172.100.100.101 -u admin -p NokiaSrl1! --skip-verify -e json_ietf set --delete '/interfaces/interface[name=ethernet-1/1]/subinterfaces/subinterface[index=0]' -gnmic -a 172.100.100.101 -u admin -p NokiaSrl1! --skip-verify -e json_ietf set --delete '/interfaces/interface[name=ethernet-1/2]/subinterfaces/subinterface[index=0]' -gnmic -a 172.100.100.102 -u admin -p NokiaSrl1! --skip-verify -e json_ietf set --delete '/network-instances/network-instance[name=b19229e8]' -gnmic -a 172.100.100.102 -u admin -p NokiaSrl1! --skip-verify -e json_ietf set --delete '/interfaces/interface[name=ethernet-1/1]/subinterfaces/subinterface[index=0]' -gnmic -a 172.100.100.102 -u admin -p NokiaSrl1! --skip-verify -e json_ietf set --delete '/interfaces/interface[name=ethernet-1/2]/subinterfaces/subinterface[index=0]' +gnmic -a clab-tfs-scenario-srl1 -u admin -p NokiaSrl1! --skip-verify -e json_ietf set --delete '/network-instances/network-instance[name=b19229e8]' +gnmic -a clab-tfs-scenario-srl1 -u admin -p NokiaSrl1! --skip-verify -e json_ietf set --delete '/interfaces/interface[name=ethernet-1/1]/subinterfaces/subinterface[index=0]' +gnmic -a clab-tfs-scenario-srl1 -u admin -p NokiaSrl1! --skip-verify -e json_ietf set --delete '/interfaces/interface[name=ethernet-1/2]/subinterfaces/subinterface[index=0]' +gnmic -a clab-tfs-scenario-srl2 -u admin -p NokiaSrl1! --skip-verify -e json_ietf set --delete '/network-instances/network-instance[name=b19229e8]' +gnmic -a clab-tfs-scenario-srl2 -u admin -p NokiaSrl1! --skip-verify -e json_ietf set --delete '/interfaces/interface[name=ethernet-1/1]/subinterfaces/subinterface[index=0]' +gnmic -a clab-tfs-scenario-srl2 -u admin -p NokiaSrl1! --skip-verify -e json_ietf set --delete '/interfaces/interface[name=ethernet-1/2]/subinterfaces/subinterface[index=0]' # Run gNMI Driver in standalone mode (advanced) PYTHONPATH=./src python -m src.device.tests.test_gnmi diff --git a/hackfest/containerlab/srl.cli b/hackfest/containerlab/srl.cli new file mode 100644 index 0000000000000000000000000000000000000000..7d4987e22795ddd4667e030abddbc11827b9dc66 --- /dev/null +++ b/hackfest/containerlab/srl.cli @@ -0,0 +1,2 @@ +set / system management openconfig admin-state enable +set / system gnmi-server network-instance mgmt yang-models openconfig diff --git a/hackfest/containerlab/tfs-scenario.clab.yml b/hackfest/containerlab/tfs-scenario.clab.yml index f79378757827ff706be849b03277b947ee85f7fb..5bb7b973f3e39b95b9099d4b2160ce9198cdf170 100644 --- a/hackfest/containerlab/tfs-scenario.clab.yml +++ b/hackfest/containerlab/tfs-scenario.clab.yml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -23,35 +23,41 @@ mgmt: topology: kinds: - srl: - image: ghcr.io/nokia/srlinux:23.3.1 + nokia_srlinux: + image: ghcr.io/nokia/srlinux:23.10.3 linux: image: ghcr.io/hellt/network-multitool nodes: srl1: - kind: srl + kind: nokia_srlinux type: ixr6 cpu: 0.5 - memory: 1GB + memory: 2GB mgmt-ipv4: 172.100.100.101 - #startup-config: srl1.cli + startup-config: srl.cli srl2: - kind: srl + kind: nokia_srlinux type: ixr6 cpu: 0.5 - memory: 1GB + memory: 2GB mgmt-ipv4: 172.100.100.102 - #startup-config: srl2.cli + startup-config: srl.cli client1: kind: linux cpu: 0.1 memory: 100MB mgmt-ipv4: 172.100.100.201 + exec: + - ip address add 172.16.1.10/24 dev eth1 + - ip route add 172.16.2.0/24 via 172.16.1.1 client2: kind: linux cpu: 0.1 memory: 100MB mgmt-ipv4: 172.100.100.202 + exec: + - ip address add 172.16.2.10/24 dev eth1 + - ip route add 172.16.1.0/24 via 172.16.2.1 links: - endpoints: ["srl1:e1-1", "srl2:e1-1"] diff --git a/hackfest/gnmi/srlinux.clab.yml b/hackfest/gnmi/srlinux.clab.yml index 6cfeb6108cd88cb52bd5925a374ea8c6724f4c69..84c23c64ae36988c3bf0230e02a89d73fc36101e 100644 --- a/hackfest/gnmi/srlinux.clab.yml +++ b/hackfest/gnmi/srlinux.clab.yml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/hackfest/grpc/connection.proto b/hackfest/grpc/connection.proto index 0da1059f3d65357f520b5123cc29d4c6230e8388..d9d04f8ef95a9153560011f2556e799618b9b7cf 100644 --- a/hackfest/grpc/connection.proto +++ b/hackfest/grpc/connection.proto @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/hackfest/grpc/connection/create.py b/hackfest/grpc/connection/create.py index 9e32dd8d4e3c89555c039d417b5aab2f6d9ef321..f286ac903e33e0809f55850001687300decf4a79 100644 --- a/hackfest/grpc/connection/create.py +++ b/hackfest/grpc/connection/create.py @@ -1,5 +1,5 @@ #! /usr/bin/env python3 -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/hackfest/grpc/connection/list.py b/hackfest/grpc/connection/list.py index e852b69b7cee16e02ca2021db83bbc11cd9c7538..41e5b4958dfb3a90f779d1d25b10701c47bde44b 100644 --- a/hackfest/grpc/connection/list.py +++ b/hackfest/grpc/connection/list.py @@ -1,5 +1,5 @@ #! /usr/bin/env python3 -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/hackfest/grpc/connectionService.proto b/hackfest/grpc/connectionService.proto index 0a80f2c1a49056ce76766e720b427283fd63969d..681150addab6ee817c209d653e24c20ca715b1cf 100644 --- a/hackfest/grpc/connectionService.proto +++ b/hackfest/grpc/connectionService.proto @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/hackfest/grpc/connectionService/connectionService_client.py b/hackfest/grpc/connectionService/connectionService_client.py index 2ed97ae97c4ef50c036635f8d5fb5812ad92c5b5..1d28689285fefb36ea50d0fcdb320c9583b5e5ab 100644 --- a/hackfest/grpc/connectionService/connectionService_client.py +++ b/hackfest/grpc/connectionService/connectionService_client.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/hackfest/grpc/connectionService/connectionService_server.py b/hackfest/grpc/connectionService/connectionService_server.py index ff991f44c16ac12ec7042f922dc9558ec08fcfbe..322da23754f657cfeecfac24d6898accdbec8a85 100644 --- a/hackfest/grpc/connectionService/connectionService_server.py +++ b/hackfest/grpc/connectionService/connectionService_server.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/hackfest/grpc/connectionServiceWithNotif.proto b/hackfest/grpc/connectionServiceWithNotif.proto index 778203e2619aa938194107d855ea4949fdf550da..e864bdb990eff2cf038ca94e3238bf51108d9ddf 100644 --- a/hackfest/grpc/connectionServiceWithNotif.proto +++ b/hackfest/grpc/connectionServiceWithNotif.proto @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/hackfest/grpc/connectionServiceWithNotif/connectionServiceWithNotif_client.py b/hackfest/grpc/connectionServiceWithNotif/connectionServiceWithNotif_client.py index 2503f424f4dd3445d91c82daa235f4677e6f910a..d7c669639bc9d85612dd6d5982c3e3b4bdd8a997 100644 --- a/hackfest/grpc/connectionServiceWithNotif/connectionServiceWithNotif_client.py +++ b/hackfest/grpc/connectionServiceWithNotif/connectionServiceWithNotif_client.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/hackfest/grpc/connectionServiceWithNotif/connectionServiceWithNotif_server.py b/hackfest/grpc/connectionServiceWithNotif/connectionServiceWithNotif_server.py index d5c413064968c9ef30e015cf818e66066d45ceb9..b67070efd1693ec34f5e1726b7385b2979dec807 100644 --- a/hackfest/grpc/connectionServiceWithNotif/connectionServiceWithNotif_server.py +++ b/hackfest/grpc/connectionServiceWithNotif/connectionServiceWithNotif_server.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/hackfest/grpc/topologyService.proto b/hackfest/grpc/topologyService.proto index 6a38bf9c7dd1762743eda91b01c639f9bc5ae3ab..b9e5763a400257faba15e06811b775ccfd31918e 100644 --- a/hackfest/grpc/topologyService.proto +++ b/hackfest/grpc/topologyService.proto @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/hackfest/grpc/topologyService/topologyService_client.py b/hackfest/grpc/topologyService/topologyService_client.py index aa1ffc2bf6269ebd7495c9f01438cfc73315c687..a2372426ab416389685db026a911359cdf337ca3 100644 --- a/hackfest/grpc/topologyService/topologyService_client.py +++ b/hackfest/grpc/topologyService/topologyService_client.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/hackfest/grpc/topologyService/topologyService_server.py b/hackfest/grpc/topologyService/topologyService_server.py index dfd62aa13adf189c10477840c747fb34b610d5fc..4654a9a325bc77fd503a7da43b4deecd5f21fdf4 100644 --- a/hackfest/grpc/topologyService/topologyService_server.py +++ b/hackfest/grpc/topologyService/topologyService_server.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/hackfest/kafka/pub.py b/hackfest/kafka/pub.py index 77564dfcb710677ecbd8fa9b2cbe8e6145c5baac..1b6b4c8e6a5c0fa0511ce51bd08c7a11b84bfe86 100644 --- a/hackfest/kafka/pub.py +++ b/hackfest/kafka/pub.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/hackfest/kafka/sub.py b/hackfest/kafka/sub.py index 2253c64674ce421d288344315649fbee64058432..170803af5d77a49829167f39e25760e775607290 100644 --- a/hackfest/kafka/sub.py +++ b/hackfest/kafka/sub.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/hackfest/mock_osm/MockOSM.py b/hackfest/mock_osm/MockOSM.py index 7ced57d3efa64038d09f5cea21fb7098b8ceb2ba..54a123dc40d235f047c99845c00707c82ed0928f 100644 --- a/hackfest/mock_osm/MockOSM.py +++ b/hackfest/mock_osm/MockOSM.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/hackfest/mock_osm/__init__.py b/hackfest/mock_osm/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/hackfest/mock_osm/__init__.py +++ b/hackfest/mock_osm/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/hackfest/mock_osm/__main__.py b/hackfest/mock_osm/__main__.py index 48866fb2db7ac92c37f57561abc58c2d45df810a..81f2345024d6efb47fd123c94a69f57d0886f64c 100644 --- a/hackfest/mock_osm/__main__.py +++ b/hackfest/mock_osm/__main__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/hackfest/netconf-oc/device_definition.py b/hackfest/netconf-oc/device_definition.py index ecd3dd6ce5a7091d5223153ddd0f6e3cca7fc39d..2c0088523908b21de5b9df19fe1a92f276b31b82 100644 --- a/hackfest/netconf-oc/device_definition.py +++ b/hackfest/netconf-oc/device_definition.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/hackfest/netconf-oc/interfaces.xml b/hackfest/netconf-oc/interfaces.xml index f04504bd408a7735ccdaa55c63c85ba25a7bde2d..c94118095ad08651375b6dfbcf3633a82041bc85 100644 --- a/hackfest/netconf-oc/interfaces.xml +++ b/hackfest/netconf-oc/interfaces.xml @@ -1,6 +1,6 @@ Calling StartResponseListener... ') + class_obj = AnalyticsFrontendServiceServicerImpl() + response = class_obj.StartResponseListener(added_analyzer_id.analyzer_id.uuid) + LOGGER.debug(response) + LOGGER.info("waiting for timer to comlete ...") + time.sleep(3) + LOGGER.info('--> StopAnalyzer') + response = analyticsFrontend_client.StopAnalyzer(added_analyzer_id) + LOGGER.debug(str(response)) + +# def test_SelectAnalytics(analyticsFrontend_client): +# LOGGER.info(' >>> test_SelectAnalytics START: <<< ') +# response = analyticsFrontend_client.SelectAnalyzers(create_analyzer_filter()) +# LOGGER.debug(str(response)) +# assert isinstance(response, AnalyzerList) + +# def test_StopAnalytic(analyticsFrontend_client): +# LOGGER.info(' >>> test_StopAnalytic START: <<< ') +# response = analyticsFrontend_client.StopAnalyzer(create_analyzer_id()) +# LOGGER.debug(str(response)) +# assert isinstance(response, Empty) + +# def test_ResponseListener(): +# LOGGER.info(' >>> test_ResponseListener START <<< ') +# analyzer_id = create_analyzer_id() +# LOGGER.debug("Starting Response Listener for Analyzer ID: {:}".format(analyzer_id.analyzer_id.uuid)) +# class_obj = AnalyticsFrontendServiceServicerImpl() +# for response in class_obj.StartResponseListener(analyzer_id.analyzer_id.uuid): +# LOGGER.debug(response) +# assert isinstance(response, tuple) diff --git a/src/analytics/requirements.in b/src/analytics/requirements.in new file mode 100644 index 0000000000000000000000000000000000000000..5ca81a10fbe1c0137ee8e83848371a4dbccd4271 --- /dev/null +++ b/src/analytics/requirements.in @@ -0,0 +1,19 @@ +# 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. + +confluent-kafka==2.3.* +psycopg2-binary==2.9.* +SQLAlchemy==1.4.* +sqlalchemy-cockroachdb==1.4.* +SQLAlchemy-Utils==0.38.* diff --git a/src/analytics/tests/__init__.py b/src/analytics/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..53d5157f750bfb085125cbd33faff1cec5924e14 --- /dev/null +++ b/src/analytics/tests/__init__.py @@ -0,0 +1,14 @@ +# 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. + diff --git a/src/analytics/tests/test_analytics_db.py b/src/analytics/tests/test_analytics_db.py new file mode 100644 index 0000000000000000000000000000000000000000..44fef9b4163a074a4357051b10d1dfa9b7e42d1c --- /dev/null +++ b/src/analytics/tests/test_analytics_db.py @@ -0,0 +1,29 @@ +# 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 +from analytics.database.Analyzer_DB import AnalyzerDB +from analytics.database.AnalyzerModel import Analyzer + +LOGGER = logging.getLogger(__name__) + +def test_verify_databases_and_tables(): + LOGGER.info('>>> test_verify_databases_and_tables : START <<< ') + AnalyzerDBobj = AnalyzerDB(Analyzer) + # AnalyzerDBobj.drop_database() + # AnalyzerDBobj.verify_tables() + AnalyzerDBobj.create_database() + AnalyzerDBobj.create_tables() + AnalyzerDBobj.verify_tables() diff --git a/src/automation/.gitlab-ci.yml b/src/automation/.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..c5f803df4b2d91667d8b6a3de2a38914519d09b6 --- /dev/null +++ b/src/automation/.gitlab-ci.yml @@ -0,0 +1,117 @@ +# 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. + +# Build, tag, and push the Docker image to the GitLab Docker registry +build automation: + variables: + IMAGE_NAME: 'automation' # name of the microservice + IMAGE_TAG: 'latest' # tag of the container image (production, development, etc) + stage: build + before_script: + - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY + script: + - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . + - docker tag "$IMAGE_NAME:$IMAGE_TAG" "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG" + - docker push "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG" + after_script: + - docker images --filter="dangling=true" --quiet | xargs -r docker rmi + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)' + - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"' + - changes: + - src/common/**/*.py + - proto/*.proto + - src/$IMAGE_NAME/**/*.{py,in,yml} + - src/$IMAGE_NAME/Dockerfile + - src/$IMAGE_NAME/tests/*.py + - manifests/${IMAGE_NAME}service.yaml + - .gitlab-ci.yml + +# Apply unit test to the component +unit_test automation: + variables: + IMAGE_NAME: 'automation' # name of the microservice + IMAGE_TAG: 'latest' # tag of the container image (production, development, etc) + stage: unit_test + needs: + - build automation + before_script: + - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY + - > + if docker network list | grep teraflowbridge; then + echo "teraflowbridge is already created"; + else + docker network create -d bridge teraflowbridge; + fi + - > + if docker container ls | grep $IMAGE_NAME; then + docker rm -f $IMAGE_NAME; + else + echo "$IMAGE_NAME image is not in the system"; + fi + script: + - docker pull "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG" + - docker run --name $IMAGE_NAME -d -p 2020:2020 -v "$PWD/src/$IMAGE_NAME/tests:/opt/results" --network=teraflowbridge $CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG + - sleep 5 + - docker ps -a + - docker logs $IMAGE_NAME + - docker exec -i $IMAGE_NAME bash -c "coverage run --append -m pytest --log-level=INFO --verbose $IMAGE_NAME/tests/test_unitary_emulated.py --junitxml=/opt/results/${IMAGE_NAME}_report_emulated.xml" + - docker exec -i $IMAGE_NAME bash -c "coverage run --append -m pytest --log-level=INFO --verbose $IMAGE_NAME/tests/test_unitary_ietf_actn.py --junitxml=/opt/results/${IMAGE_NAME}_report_ietf_actn.xml" + - docker exec -i $IMAGE_NAME bash -c "coverage report --include='${IMAGE_NAME}/*' --show-missing" + coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/' + after_script: + - docker rm -f $IMAGE_NAME + - docker network rm teraflowbridge + 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/$IMAGE_NAME/**/*.{py,in,yml} + - src/$IMAGE_NAME/Dockerfile + - src/$IMAGE_NAME/tests/*.py + - src/$IMAGE_NAME/tests/Dockerfile + - manifests/${IMAGE_NAME}service.yaml + - .gitlab-ci.yml + artifacts: + when: always + reports: + junit: src/$IMAGE_NAME/tests/${IMAGE_NAME}_report_*.xml + +## Deployment of the service in Kubernetes Cluster +#deploy automation: +# variables: +# IMAGE_NAME: 'automation' # name of the microservice +# IMAGE_TAG: 'latest' # tag of the container image (production, development, etc) +# stage: deploy +# needs: +# - unit test automation +# # - integ_test execute +# script: +# - 'sed -i "s/$IMAGE_NAME:.*/$IMAGE_NAME:$IMAGE_TAG/" manifests/${IMAGE_NAME}service.yaml' +# - kubectl version +# - kubectl get all +# - kubectl apply -f "manifests/${IMAGE_NAME}service.yaml" +# - kubectl get all +# # environment: +# # name: test +# # url: https://example.com +# # kubernetes: +# # namespace: test +# rules: +# - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)' +# when: manual +# - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"' +# when: manual diff --git a/src/automation/Config.py b/src/automation/Config.py new file mode 100644 index 0000000000000000000000000000000000000000..3aa410c134b0aebb3117ca3220e823f7433b180c --- /dev/null +++ b/src/automation/Config.py @@ -0,0 +1,14 @@ +# 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. + diff --git a/src/automation/Dockerfile b/src/automation/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..1818284c9553faa1c6ae962e59ea102ea1bc56b7 --- /dev/null +++ b/src/automation/Dockerfile @@ -0,0 +1,78 @@ +# 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 + +# Download the gRPC health probe +RUN GRPC_HEALTH_PROBE_VERSION=v0.2.0 && \ + wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \ + chmod +x /bin/grpc_health_probe + +# 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/automation +WORKDIR /var/teraflow/automation +COPY src/automation/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/context/__init__.py context/__init__.py +COPY src/context/client/. context/client/ +COPY src/kpi_manager/__init__.py kpi_manager/__init__.py +COPY src/kpi_manager/client/. kpi_manager/client/ +COPY src/telemetry/__init__.py telemetry/__init__.py +COPY src/telemetry/frontend/__init__.py telemetry/frontend/__init__.py +COPY src/telemetry/frontend/client/. telemetry/frontend/client/ +COPY src/analytics/__init__.py analytics/__init__.py +COPY src/analytics/frontend/__init__.py analytics/frontend/__init__.py +COPY src/analytics/frontend/client/. analytics/frontend/client/ +COPY src/automation/. automation/ + +# Start the service +ENTRYPOINT ["python", "-m", "automation.service"] diff --git a/src/automation/__init__.py b/src/automation/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..3aa410c134b0aebb3117ca3220e823f7433b180c --- /dev/null +++ b/src/automation/__init__.py @@ -0,0 +1,14 @@ +# 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. + diff --git a/src/automation/client/PolicyClient.py b/src/automation/client/PolicyClient.py new file mode 100644 index 0000000000000000000000000000000000000000..5c0224b464fa3ada2579da8ca465cb6575c166b3 --- /dev/null +++ b/src/automation/client/PolicyClient.py @@ -0,0 +1,54 @@ +# 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 grpc, logging +from common.Constants import ServiceNameEnum +from common.Settings import get_service_host, get_service_port_grpc +from common.proto.policy_pb2 import PolicyRuleService, PolicyRuleState +from common.proto.policy_pb2_grpc import PolicyServiceStub +from common.tools.client.RetryDecorator import retry, delay_exponential +from common.tools.grpc.Tools import grpc_message_to_json_string + +LOGGER = logging.getLogger(__name__) +MAX_RETRIES = 15 +DELAY_FUNCTION = delay_exponential(initial=0.01, increment=2.0, maximum=5.0) +RETRY_DECORATOR = retry(max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect') + +class PolicyClient: + def __init__(self, host=None, port=None): + if not host: host = get_service_host(ServiceNameEnum.POLICY) + if not port: port = get_service_port_grpc(ServiceNameEnum.POLICY) + self.endpoint = '{:s}:{:s}'.format(str(host), str(port)) + LOGGER.info('Creating channel to {:s}...'.format(str(self.endpoint))) + self.channel = None + self.stub = None + self.openconfig_stub=None + self.connect() + LOGGER.info('Channel created') + + def connect(self): + self.channel = grpc.insecure_channel(self.endpoint) + self.stub = PolicyServiceStub(self.channel) + + def close(self): + if self.channel is not None: self.channel.close() + self.channel = None + self.stub = None + + @RETRY_DECORATOR + def PolicyAddService(self, request : PolicyRuleService) -> PolicyRuleState: + LOGGER.debug('AddPolicy request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.PolicyAddService(request) + LOGGER.debug('AddPolicy result: {:s}'.format(grpc_message_to_json_string(response))) + return response diff --git a/src/automation/client/__init__.py b/src/automation/client/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..3aa410c134b0aebb3117ca3220e823f7433b180c --- /dev/null +++ b/src/automation/client/__init__.py @@ -0,0 +1,14 @@ +# 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. + diff --git a/src/automation/requirements.in b/src/automation/requirements.in new file mode 100644 index 0000000000000000000000000000000000000000..0f291eca8b84f4965c6832b9c4b691380dfcb75e --- /dev/null +++ b/src/automation/requirements.in @@ -0,0 +1,20 @@ +# 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. + +apscheduler==3.10.4 +confluent-kafka==2.3.* +psycopg2-binary==2.9.* +SQLAlchemy==1.4.* +sqlalchemy-cockroachdb==1.4.* +SQLAlchemy-Utils==0.38.* diff --git a/src/automation/service/AutomationService.py b/src/automation/service/AutomationService.py new file mode 100644 index 0000000000000000000000000000000000000000..52eca553f9eed9f8134d8a8c1a0a27a924c49c97 --- /dev/null +++ b/src/automation/service/AutomationService.py @@ -0,0 +1,28 @@ +# 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 common.Constants import ServiceNameEnum +from common.Settings import get_service_port_grpc +from common.proto.automation_pb2_grpc import add_AutomationServiceServicer_to_server +from common.tools.service.GenericGrpcService import GenericGrpcService +from automation.service.AutomationServiceServicerImpl import AutomationServiceServicerImpl + +class AutomationService(GenericGrpcService): + def __init__(self, cls_name: str = __name__) -> None: + port = get_service_port_grpc(ServiceNameEnum.AUTOMATION) + super().__init__(port, cls_name=cls_name) + self.automation_servicer = AutomationServiceServicerImpl() + + def install_servicers(self): + add_AutomationServiceServicer_to_server(self.automation_servicer, self.server) diff --git a/src/automation/service/AutomationServiceServicerImpl.py b/src/automation/service/AutomationServiceServicerImpl.py new file mode 100644 index 0000000000000000000000000000000000000000..521b07ce0d8734c2016b222420e45b910d314ded --- /dev/null +++ b/src/automation/service/AutomationServiceServicerImpl.py @@ -0,0 +1,224 @@ +# 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 grpc, json, logging +from uuid import uuid4 +from common.method_wrappers.Decorator import MetricsPool, safe_and_metered_rpc_method +from common.method_wrappers.ServiceExceptions import InvalidArgumentException +from common.proto.analytics_frontend_pb2 import Analyzer, AnalyzerId +from common.proto.automation_pb2 import ZSMCreateRequest, ZSMService, ZSMServiceID, ZSMServiceState, ZSMCreateUpdate +from common.proto.automation_pb2_grpc import AutomationServiceServicer +from common.proto.context_pb2 import Service, ServiceId +from common.proto.kpi_manager_pb2 import KpiId, KpiDescriptor +from common.proto.policy_pb2 import PolicyRuleService, PolicyRuleState +from common.proto.policy_action_pb2 import PolicyRuleAction, PolicyRuleActionConfig +from common.proto.policy_condition_pb2 import PolicyRuleCondition +from common.proto.telemetry_frontend_pb2 import Collector, CollectorId + +from analytics.frontend.client.AnalyticsFrontendClient import AnalyticsFrontendClient +from automation.client.PolicyClient import PolicyClient +from context.client.ContextClient import ContextClient +from kpi_manager.client.KpiManagerClient import KpiManagerClient +from telemetry.frontend.client.TelemetryFrontendClient import TelemetryFrontendClient + +LOGGER = logging.getLogger(__name__) +METRICS_POOL = MetricsPool('Automation', 'RPC') + +class AutomationServiceServicerImpl(AutomationServiceServicer): + def __init__(self): + LOGGER.info('Init AutomationService') + + @safe_and_metered_rpc_method(METRICS_POOL,LOGGER) + def ZSMCreate(self, request : ZSMCreateRequest, context : grpc.ServicerContext) -> ZSMService: + + # check that service does not exist + context_client = ContextClient() + kpi_manager_client = KpiManagerClient() + policy_client = PolicyClient() + telemetry_frontend_client = TelemetryFrontendClient() + analytics_frontend_client = AnalyticsFrontendClient() + + try: + + # TODO: Remove static variables(get them from ZSMCreateRequest) + # TODO: Refactor policy component (remove unnecessary variables) + + ####### GET Context ####################### + LOGGER.info('Get the service from Context: ') + service: Service = context_client.GetService(request.serviceId) + LOGGER.info('Service ({:s}) :'.format(str(service))) + ########################################### + + ####### SET Kpi Descriptor LAT ################ + LOGGER.info('Set Kpi Descriptor LAT: ') + + if(len(service.service_constraints) == 0): + raise InvalidArgumentException("service_constraints" , "empty", []); + + if(len(service.service_constraints) > 1): + raise InvalidArgumentException("service_constraints" , ">1", []); + + if(service.service_constraints[0].sla_latency is None ): + raise InvalidArgumentException("sla_latency", "empty", []); + + ## Static Implementation Applied only in case of SLA Latency Constraint ## + + # KPI Descriptor + kpi_descriptor_lat = KpiDescriptor() + kpi_descriptor_lat.kpi_sample_type = 701 #'KPISAMPLETYPE_SERVICE_LATENCY_MS' #static service.service_constraints[].sla_latency.e2e_latency_ms + kpi_descriptor_lat.service_id.service_uuid.uuid = request.serviceId.service_uuid.uuid + kpi_descriptor_lat.kpi_id.kpi_id.uuid = str(uuid4()) + + kpi_id_lat: KpiId = kpi_manager_client.SetKpiDescriptor(kpi_descriptor_lat) + LOGGER.info('The kpi_id_lat({:s})'.format(str(kpi_id_lat))) + ########################################### + + ####### SET Kpi Descriptor TX ################ + LOGGER.info('Set Kpi Descriptor TX: ') + + kpi_descriptor_tx = KpiDescriptor() + kpi_descriptor_tx.kpi_sample_type = 101 # static KPISAMPLETYPE_PACKETS_TRANSMITTED + kpi_descriptor_tx.service_id.service_uuid.uuid = request.serviceId.service_uuid.uuid + kpi_descriptor_tx.kpi_id.kpi_id.uuid = str(uuid4()) + + kpi_id_tx: KpiId = kpi_manager_client.SetKpiDescriptor(kpi_descriptor_tx) + LOGGER.info('The kpi_id_tx({:s})'.format(str(kpi_id_tx))) + ########################################### + + ####### SET Kpi Descriptor RX ################ + LOGGER.info('Set Kpi Descriptor RX: ') + + kpi_descriptor_rx = KpiDescriptor() + kpi_descriptor_rx.kpi_sample_type = 102 # static KPISAMPLETYPE_PACKETS_RECEIVED + kpi_descriptor_rx.service_id.service_uuid.uuid = request.serviceId.service_uuid.uuid + kpi_descriptor_rx.kpi_id.kpi_id.uuid = str(uuid4()) + + kpi_id_rx: KpiId = kpi_manager_client.SetKpiDescriptor(kpi_descriptor_rx) + LOGGER.info('kpi_id_rx({:s})'.format(str(kpi_id_rx))) + ########################################### + + + + ####### START Collector TX ################# + collect_tx = Collector() + collect_tx.collector_id.collector_id.uuid = str(uuid4()) + collect_tx.kpi_id.kpi_id.uuid = kpi_id_tx.kpi_id.uuid + collect_tx.duration_s = 20000 # static + collect_tx.interval_s = 1 # static + LOGGER.info('Start Collector TX'.format(str(collect_tx))) + + collect_id_tx: CollectorId = telemetry_frontend_client.StartCollector(collect_tx) + LOGGER.info('collect_id_tx({:s})'.format(str(collect_id_tx))) + ############################################# + + ####### START Collector RX ################## + collect_rx = Collector() + collect_rx.collector_id.collector_id.uuid = str(uuid4()) + collect_rx.kpi_id.kpi_id.uuid = kpi_id_rx.kpi_id.uuid + collect_rx.duration_s = 20000 # static + collect_rx.interval_s = 1 # static + LOGGER.info('Start Collector RX'.format(str(collect_rx))) + + collect_id_rx: CollectorId = telemetry_frontend_client.StartCollector(collect_rx) + LOGGER.info('collect_id_tx({:s})'.format(str(collect_id_rx))) + ############################################### + + ####### START Analyzer LAT ################ + analyzer = Analyzer() + analyzer.analyzer_id.analyzer_id.uuid = str(uuid4()) + analyzer.algorithm_name = 'Test_Aggregate_and_Threshold' # static + analyzer.operation_mode = 2 + analyzer.input_kpi_ids.append(kpi_id_rx) + analyzer.input_kpi_ids.append(kpi_id_tx) + analyzer.output_kpi_ids.append(kpi_id_lat) + + thresholdStr = service.service_constraints[0].custom.constraint_type + + _threshold_dict = {thresholdStr: (0, int(service.service_constraints[0].custom.constraint_value))} + analyzer.parameters['thresholds'] = json.dumps(_threshold_dict) + analyzer.parameters['window_size'] = "60s" + analyzer.parameters['window_slider'] = "30s" + + analyzer_id_lat: AnalyzerId = analytics_frontend_client.StartAnalyzer(analyzer) + LOGGER.info('analyzer_id_lat({:s})'.format(str(analyzer_id_lat))) + ########################################################### + + ####### SET Policy LAT ################ + policy_lat = PolicyRuleService() + policy_lat.serviceId.service_uuid.uuid = request.serviceId.service_uuid.uuid + policy_lat.serviceId.context_id.context_uuid.uuid = request.serviceId.context_id.context_uuid.uuid + + # PolicyRuleBasic + policy_lat.policyRuleBasic.priority = 0 + policy_lat.policyRuleBasic.policyRuleId.uuid.uuid = str(uuid4()) + policy_lat.policyRuleBasic.booleanOperator = 2 + + # PolicyRuleAction + policyRuleActionConfig = PolicyRuleActionConfig() + policyRuleActionConfig.action_key = "" + policyRuleActionConfig.action_value = "" + + policyRuleAction = PolicyRuleAction() + policyRuleAction.action = 5 + policyRuleAction.action_config.append(policyRuleActionConfig) + policy_lat.policyRuleBasic.actionList.append(policyRuleAction) + + # for constraint in service.service_constraints: + + # PolicyRuleCondition + policyRuleCondition = PolicyRuleCondition() + policyRuleCondition.kpiId.kpi_id.uuid = kpi_id_lat.kpi_id.uuid + policyRuleCondition.numericalOperator = 5 + policyRuleCondition.kpiValue.floatVal = 300 + + policy_lat.policyRuleBasic.conditionList.append(policyRuleCondition) + + policy_rule_state: PolicyRuleState = policy_client.PolicyAddService(policy_lat) + LOGGER.info('policy_rule_state({:s})'.format(str(policy_rule_state))) + + except grpc.RpcError as e: + if e.code() != grpc.StatusCode.NOT_FOUND: raise # pylint: disable=no-member + LOGGER.exception('Unable to get Service({:s})'.format(str(request))) + context_client.close() + kpi_manager_client.close() + policy_client.close() + telemetry_frontend_client.close() + return None + + context_client.close() + kpi_manager_client.close() + policy_client.close() + telemetry_frontend_client.close() + return ZSMService() + + @safe_and_metered_rpc_method(METRICS_POOL,LOGGER) + def ZSMUpdate(self, request : ZSMCreateUpdate, context : grpc.ServicerContext) -> ZSMService: + LOGGER.info('NOT IMPLEMENTED ZSMUpdate') + return ZSMService() + + @safe_and_metered_rpc_method(METRICS_POOL,LOGGER) + def ZSMDelete(self, request : ZSMServiceID, context : grpc.ServicerContext) -> ZSMServiceState: + LOGGER.info('NOT IMPLEMENTED ZSMDelete') + return ZSMServiceState() + + @safe_and_metered_rpc_method(METRICS_POOL,LOGGER) + def ZSMGetById(self, request : ZSMServiceID, context : grpc.ServicerContext) -> ZSMService: + LOGGER.info('NOT IMPLEMENTED ZSMGetById') + return ZSMService() + + + @safe_and_metered_rpc_method(METRICS_POOL,LOGGER) + def ZSMGetByService(self, request : ServiceId, context : grpc.ServicerContext) -> ZSMService: + LOGGER.info('NOT IMPLEMENTED ZSMGetByService') + return ZSMService() diff --git a/src/automation/service/EventEngine.py b/src/automation/service/EventEngine.py new file mode 100644 index 0000000000000000000000000000000000000000..b9666db9ea9b5b659cf271025a58fd8b7982d60f --- /dev/null +++ b/src/automation/service/EventEngine.py @@ -0,0 +1,169 @@ +# 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 json, logging, queue, threading +from typing import Dict, Optional +from automation.service.Tools import create_kpi_descriptor, start_collector +from common.proto.context_pb2 import ( + ConfigActionEnum, DeviceEvent, DeviceOperationalStatusEnum, Empty, ServiceEvent +) +from common.proto.kpi_sample_types_pb2 import KpiSampleType +from common.tools.grpc.BaseEventCollector import BaseEventCollector +from common.tools.grpc.BaseEventDispatcher import BaseEventDispatcher +from common.tools.grpc.Tools import grpc_message_to_json_string +from context.client.ContextClient import ContextClient +from kpi_manager.client.KpiManagerClient import KpiManagerClient +from telemetry.frontend.client.TelemetryFrontendClient import TelemetryFrontendClient + +LOGGER = logging.getLogger(__name__) + +DEVICE_OP_STATUS_UNDEFINED = DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_UNDEFINED +DEVICE_OP_STATUS_DISABLED = DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_DISABLED +DEVICE_OP_STATUS_ENABLED = DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_ENABLED +DEVICE_OP_STATUS_NOT_ENABLED = {DEVICE_OP_STATUS_UNDEFINED, DEVICE_OP_STATUS_DISABLED} + +KPISAMPLETYPE_UNKNOWN = KpiSampleType.KPISAMPLETYPE_UNKNOWN + +class EventCollector(BaseEventCollector): + pass + +class EventDispatcher(BaseEventDispatcher): + def __init__( + self, events_queue : queue.PriorityQueue, + terminate : Optional[threading.Event] = None + ) -> None: + super().__init__(events_queue, terminate) + self._context_client = ContextClient() + self._kpi_manager_client = KpiManagerClient() + self._telemetry_client = TelemetryFrontendClient() + self._device_endpoint_monitored : Dict[str, Dict[str, bool]] = dict() + + def dispatch_device_create(self, device_event : DeviceEvent) -> None: + MSG = 'Processing Device Create: {:s}' + LOGGER.info(MSG.format(grpc_message_to_json_string(device_event))) + self._device_activate_monitoring(device_event) + + def dispatch_device_update(self, device_event : DeviceEvent) -> None: + MSG = 'Processing Device Update: {:s}' + LOGGER.info(MSG.format(grpc_message_to_json_string(device_event))) + self._device_activate_monitoring(device_event) + + def dispatch_device_remove(self, device_event : DeviceEvent) -> None: + MSG = 'Processing Device Remove: {:s}' + LOGGER.info(MSG.format(grpc_message_to_json_string(device_event))) + + def dispatch_service_create(self, service_event : ServiceEvent) -> None: + MSG = 'Processing Service Create: {:s}' + LOGGER.info(MSG.format(grpc_message_to_json_string(service_event))) + + def dispatch_service_update(self, service_event : ServiceEvent) -> None: + MSG = 'Processing Service Update: {:s}' + LOGGER.info(MSG.format(grpc_message_to_json_string(service_event))) + + def dispatch_service_remove(self, service_event : ServiceEvent) -> None: + MSG = 'Processing Service Remove: {:s}' + LOGGER.info(MSG.format(grpc_message_to_json_string(service_event))) + + def _device_activate_monitoring(self, device_event : DeviceEvent) -> None: + device_id = device_event.device_id + device_uuid = device_id.device_uuid.uuid + device = self._context_client.GetDevice(device_id) + + device_op_status = device.device_operational_status + if device_op_status != DEVICE_OP_STATUS_ENABLED: + LOGGER.debug('Ignoring Device not enabled: {:s}'.format(grpc_message_to_json_string(device))) + return + + enabled_endpoint_names = set() + for config_rule in device.device_config.config_rules: + if config_rule.action != ConfigActionEnum.CONFIGACTION_SET: continue + if config_rule.WhichOneof('config_rule') != 'custom': continue + str_resource_key = str(config_rule.custom.resource_key) + if not str_resource_key.startswith('/interface['): continue + json_resource_value = json.loads(config_rule.custom.resource_value) + if 'name' not in json_resource_value: continue + if 'enabled' not in json_resource_value: continue + if not json_resource_value['enabled']: continue + enabled_endpoint_names.add(json_resource_value['name']) + + endpoints_monitored = self._device_endpoint_monitored.setdefault(device_uuid, dict()) + for endpoint in device.device_endpoints: + endpoint_uuid = endpoint.endpoint_id.endpoint_uuid.uuid + endpoint_name_or_uuid = endpoint.name + if endpoint_name_or_uuid is None or len(endpoint_name_or_uuid) == 0: + endpoint_name_or_uuid = endpoint_uuid + + endpoint_was_monitored = endpoints_monitored.get(endpoint_uuid, False) + endpoint_is_enabled = (endpoint_name_or_uuid in enabled_endpoint_names) + + if not endpoint_was_monitored and endpoint_is_enabled: + # activate + for kpi_sample_type in endpoint.kpi_sample_types: + if kpi_sample_type == KPISAMPLETYPE_UNKNOWN: continue + + kpi_id = create_kpi_descriptor( + self._kpi_manager_client, kpi_sample_type, + device_id=device.device_id, + endpoint_id=endpoint.endpoint_id, + ) + + duration_seconds = 86400 + interval_seconds = 10 + collector_id = start_collector( + self._telemetry_client, kpi_id, + duration_seconds, interval_seconds + ) + + endpoints_monitored[endpoint_uuid] = True + else: + MSG = 'Not implemented condition: event={:s} device={:s} endpoint={:s}' + \ + ' endpoint_was_monitored={:s} endpoint_is_enabled={:s}' + LOGGER.warning(MSG.format( + grpc_message_to_json_string(device_event), grpc_message_to_json_string(device), + grpc_message_to_json_string(endpoint), str(endpoint_was_monitored), + str(endpoint_is_enabled) + )) + +class EventEngine: + def __init__( + self, terminate : Optional[threading.Event] = None + ) -> None: + self._terminate = threading.Event() if terminate is None else terminate + + self._context_client = ContextClient() + self._event_collector = EventCollector(terminate=self._terminate) + self._event_collector.install_collector( + self._context_client.GetDeviceEvents, Empty(), + log_events_received=True + ) + self._event_collector.install_collector( + self._context_client.GetServiceEvents, Empty(), + log_events_received=True + ) + + self._event_dispatcher = EventDispatcher( + self._event_collector.get_events_queue(), + terminate=self._terminate + ) + + def start(self) -> None: + self._context_client.connect() + self._event_collector.start() + self._event_dispatcher.start() + + def stop(self) -> None: + self._terminate.set() + self._event_dispatcher.stop() + self._event_collector.stop() + self._context_client.close() diff --git a/src/automation/service/Tools.py b/src/automation/service/Tools.py new file mode 100644 index 0000000000000000000000000000000000000000..2f5f6e8568c8d2bfcda566109b2c90a652d0544b --- /dev/null +++ b/src/automation/service/Tools.py @@ -0,0 +1,64 @@ +# 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, uuid +from typing import Optional +from common.proto.context_pb2 import ConnectionId, DeviceId, EndPointId, LinkId, ServiceId, SliceId +from common.proto.kpi_manager_pb2 import KpiDescriptor, KpiId +from common.proto.kpi_sample_types_pb2 import KpiSampleType +from common.proto.telemetry_frontend_pb2 import Collector, CollectorId +from kpi_manager.client.KpiManagerClient import KpiManagerClient +from telemetry.frontend.client.TelemetryFrontendClient import TelemetryFrontendClient + +LOGGER = logging.getLogger(__name__) + +def create_kpi_descriptor( + kpi_manager_client : KpiManagerClient, + kpi_sample_type : KpiSampleType, + device_id : Optional[DeviceId ] = None, + endpoint_id : Optional[EndPointId ] = None, + service_id : Optional[ServiceId ] = None, + slice_id : Optional[SliceId ] = None, + connection_id : Optional[ConnectionId] = None, + link_id : Optional[LinkId ] = None, +) -> KpiId: + kpi_descriptor = KpiDescriptor() + kpi_descriptor.kpi_id.kpi_id.uuid = str(uuid.uuid4()) + kpi_descriptor.kpi_description = '' + kpi_descriptor.kpi_sample_type = kpi_sample_type + + if device_id is not None: kpi_descriptor.device_id .CopyFrom(device_id ) + if endpoint_id is not None: kpi_descriptor.endpoint_id .CopyFrom(endpoint_id ) + if service_id is not None: kpi_descriptor.service_id .CopyFrom(service_id ) + if slice_id is not None: kpi_descriptor.slice_id .CopyFrom(slice_id ) + if connection_id is not None: kpi_descriptor.connection_id.CopyFrom(connection_id) + if link_id is not None: kpi_descriptor.link_id .CopyFrom(link_id ) + + kpi_id : KpiId = kpi_manager_client.SetKpiDescriptor(kpi_descriptor) + return kpi_id + +def start_collector( + telemetry_client : TelemetryFrontendClient, + kpi_id : KpiId, + duration_seconds : float, + interval_seconds : float +) -> CollectorId: + collector = Collector() + collector.collector_id.collector_id.uuid = str(uuid.uuid4()) + collector.kpi_id.CopyFrom(kpi_id) + collector.duration_s = duration_seconds + collector.interval_s = interval_seconds + collector_id : CollectorId = telemetry_client.StartCollector(collector) + return collector_id diff --git a/src/automation/service/__init__.py b/src/automation/service/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..3aa410c134b0aebb3117ca3220e823f7433b180c --- /dev/null +++ b/src/automation/service/__init__.py @@ -0,0 +1,14 @@ +# 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. + diff --git a/src/automation/service/__main__.py b/src/automation/service/__main__.py new file mode 100644 index 0000000000000000000000000000000000000000..22113f975eacf70a4ef76362d58eae1890796061 --- /dev/null +++ b/src/automation/service/__main__.py @@ -0,0 +1,80 @@ +# 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, signal, sys, threading +from prometheus_client import start_http_server +from automation.service.EventEngine import EventEngine +from common.Constants import ServiceNameEnum +from common.Settings import ( + ENVVAR_SUFIX_SERVICE_HOST, ENVVAR_SUFIX_SERVICE_PORT_GRPC, + get_env_var_name, get_log_level, get_metrics_port, + wait_for_environment_variables +) +from .AutomationService import AutomationService + +LOG_LEVEL = get_log_level() +logging.basicConfig(level=LOG_LEVEL, format="[%(asctime)s] %(levelname)s:%(name)s:%(message)s") +LOGGER = logging.getLogger(__name__) + +terminate = threading.Event() + +def signal_handler(signal, frame): # pylint: disable=redefined-outer-name,unused-argument + LOGGER.warning('Terminate signal received') + terminate.set() + +def main(): + LOGGER.info('Starting...') + + wait_for_environment_variables([ + get_env_var_name(ServiceNameEnum.CONTEXT, ENVVAR_SUFIX_SERVICE_HOST ), + get_env_var_name(ServiceNameEnum.CONTEXT, ENVVAR_SUFIX_SERVICE_PORT_GRPC), + get_env_var_name(ServiceNameEnum.DEVICE, ENVVAR_SUFIX_SERVICE_HOST ), + get_env_var_name(ServiceNameEnum.DEVICE, ENVVAR_SUFIX_SERVICE_PORT_GRPC), + get_env_var_name(ServiceNameEnum.KPIMANAGER, ENVVAR_SUFIX_SERVICE_HOST ), + get_env_var_name(ServiceNameEnum.KPIMANAGER, ENVVAR_SUFIX_SERVICE_PORT_GRPC), + get_env_var_name(ServiceNameEnum.TELEMETRY, ENVVAR_SUFIX_SERVICE_HOST ), + get_env_var_name(ServiceNameEnum.TELEMETRY, ENVVAR_SUFIX_SERVICE_PORT_GRPC), + get_env_var_name(ServiceNameEnum.ANALYTICS, ENVVAR_SUFIX_SERVICE_HOST ), + get_env_var_name(ServiceNameEnum.ANALYTICS, ENVVAR_SUFIX_SERVICE_PORT_GRPC), + get_env_var_name(ServiceNameEnum.POLICY, ENVVAR_SUFIX_SERVICE_HOST ), + get_env_var_name(ServiceNameEnum.POLICY, ENVVAR_SUFIX_SERVICE_PORT_GRPC), + ]) + + signal.signal(signal.SIGINT, signal_handler) + signal.signal(signal.SIGTERM, signal_handler) + + # Start metrics server + metrics_port = get_metrics_port() + start_http_server(metrics_port) + + # Start Event Collection+Dispatching Engine + event_engine = EventEngine(terminate=terminate) + event_engine.start() + + # Starting Automation service + grpc_service = AutomationService() + grpc_service.start() + + # Wait for Ctrl+C or termination signal + while not terminate.wait(timeout=1.0): pass + + LOGGER.info('Terminating...') + grpc_service.stop() + event_engine.stop() + + LOGGER.info('Bye') + return 0 + +if __name__ == '__main__': + sys.exit(main()) diff --git a/src/automation/tests/__init__.py b/src/automation/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..3aa410c134b0aebb3117ca3220e823f7433b180c --- /dev/null +++ b/src/automation/tests/__init__.py @@ -0,0 +1,14 @@ +# 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. + diff --git a/src/automation/tests/test_unitary_emulated.py b/src/automation/tests/test_unitary_emulated.py new file mode 100644 index 0000000000000000000000000000000000000000..696327731dda35823e762a209929fe5605452be4 --- /dev/null +++ b/src/automation/tests/test_unitary_emulated.py @@ -0,0 +1,22 @@ +# 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 + +LOGGER = logging.getLogger(__name__) + +def test_device_emulated_add_error_cases(): + LOGGER.info("Start Tests") + LOGGER.info("Second log Tests") + assert True diff --git a/src/automation/tests/test_unitary_ietf_actn.py b/src/automation/tests/test_unitary_ietf_actn.py new file mode 100644 index 0000000000000000000000000000000000000000..5f1b4eef86482472312b2506d816007e5bd79906 --- /dev/null +++ b/src/automation/tests/test_unitary_ietf_actn.py @@ -0,0 +1,21 @@ +# 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 + +LOGGER = logging.getLogger(__name__) + +def test_device_emulated_add_error_cases(): + LOGGER.info("Start Tests") + assert True diff --git a/src/bgpls_speaker/.gitlab-ci.yml b/src/bgpls_speaker/.gitlab-ci.yml index b1e3c1ae1a7006667ab78d4b31f15d4877503097..927454042998269468d4b7b850d831b604eef239 100644 --- a/src/bgpls_speaker/.gitlab-ci.yml +++ b/src/bgpls_speaker/.gitlab-ci.yml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/bgpls_speaker/Config.py b/src/bgpls_speaker/Config.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/bgpls_speaker/Config.py +++ b/src/bgpls_speaker/Config.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/bgpls_speaker/Dockerfile b/src/bgpls_speaker/Dockerfile index 32743ae48061d87a2a1c9305dee8ece037648482..eefeb9a1dc9e21658319046b955a286cbb78c68e 100644 --- a/src/bgpls_speaker/Dockerfile +++ b/src/bgpls_speaker/Dockerfile @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/bgpls_speaker/__init__.py b/src/bgpls_speaker/__init__.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/bgpls_speaker/__init__.py +++ b/src/bgpls_speaker/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/bgpls_speaker/client/BgplsClient.py b/src/bgpls_speaker/client/BgplsClient.py index 2fb17c5724c95a54efd429bfc5586bf61ed04905..6f3c6e0f997835598605a010ff91ced061e9b7a7 100644 --- a/src/bgpls_speaker/client/BgplsClient.py +++ b/src/bgpls_speaker/client/BgplsClient.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/bgpls_speaker/client/__init__.py b/src/bgpls_speaker/client/__init__.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/bgpls_speaker/client/__init__.py +++ b/src/bgpls_speaker/client/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/bgpls_speaker/quick_deploy.sh b/src/bgpls_speaker/quick_deploy.sh index ab76c2ff6e8a640ee3591de6b19ed9dec38547ec..544ff5ee9e2339e658d52a4b262b05419f1f4303 100644 --- a/src/bgpls_speaker/quick_deploy.sh +++ b/src/bgpls_speaker/quick_deploy.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -60,9 +60,6 @@ export CRDB_USERNAME=${CRDB_USERNAME:-"tfs"} # If not already set, set the database user's password to be used by Context. export CRDB_PASSWORD=${CRDB_PASSWORD:-"tfs123"} -# If not already set, set the database name to be used by Context. -export CRDB_DATABASE=${CRDB_DATABASE:-"tfs"} - # ----- NATS ------------------------------------------------------------------- @@ -112,7 +109,6 @@ CRDB_SQL_PORT=$(kubectl --namespace ${CRDB_NAMESPACE} get service cockroachdb-pu kubectl create secret generic crdb-data --namespace ${TFS_K8S_NAMESPACE} --type='Opaque' \ --from-literal=CRDB_NAMESPACE=${CRDB_NAMESPACE} \ --from-literal=CRDB_SQL_PORT=${CRDB_SQL_PORT} \ - --from-literal=CRDB_DATABASE=${CRDB_DATABASE} \ --from-literal=CRDB_USERNAME=${CRDB_USERNAME} \ --from-literal=CRDB_PASSWORD=${CRDB_PASSWORD} \ --from-literal=CRDB_SSLMODE=require diff --git a/src/bgpls_speaker/requirements.in b/src/bgpls_speaker/requirements.in index 9ec39a9e026bfdbd03e2d1950df476860dca0a5b..5fbf034d5b7349880620abcb693c732153328fee 100644 --- a/src/bgpls_speaker/requirements.in +++ b/src/bgpls_speaker/requirements.in @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/bgpls_speaker/service/BgplsService.py b/src/bgpls_speaker/service/BgplsService.py index f2f77d08b6e3430ecc5fbaba6c10d20d19a4d373..e2acb9a6edd72fe7eeebce9ffea7c8215cda089f 100644 --- a/src/bgpls_speaker/service/BgplsService.py +++ b/src/bgpls_speaker/service/BgplsService.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/bgpls_speaker/service/BgplsServiceServicerImpl.py b/src/bgpls_speaker/service/BgplsServiceServicerImpl.py index 5e661c6aad19f82f943b9e9a7707b3354edf580f..eee42f7ff274d8bf80d6edf1f816f91448d2a091 100644 --- a/src/bgpls_speaker/service/BgplsServiceServicerImpl.py +++ b/src/bgpls_speaker/service/BgplsServiceServicerImpl.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/bgpls_speaker/service/__init__.py b/src/bgpls_speaker/service/__init__.py index 839e45e3b646bc60de7edd81fcfb91b7b38feadf..d1eba8e41fdc0b7257b50bf411869c7b2baa2e00 100644 --- a/src/bgpls_speaker/service/__init__.py +++ b/src/bgpls_speaker/service/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/bgpls_speaker/service/__main__.py b/src/bgpls_speaker/service/__main__.py index 564711b3b2766ddd79f555679d9eea94e718a85a..79f52f838b40e8a9fb1d4dc7a8de4ca15092c65f 100644 --- a/src/bgpls_speaker/service/__main__.py +++ b/src/bgpls_speaker/service/__main__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/bgpls_speaker/service/java/BGP4Parameters_3.xml b/src/bgpls_speaker/service/java/BGP4Parameters_3.xml index b945caa8307e89447a8ec1230d440e9dab6a43c4..1b5c674cf0ada4082ad3eaa50c991ff3855e4bfa 100644 --- a/src/bgpls_speaker/service/java/BGP4Parameters_3.xml +++ b/src/bgpls_speaker/service/java/BGP4Parameters_3.xml @@ -1,4 +1,4 @@ - + diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4PeerInitiatedSession.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4PeerInitiatedSession.java index 9651d78761d267fdb10bcb1994aa0a90d9c17cf8..f3d35e03abeee62dd6c66f3ae985af6781790d15 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4PeerInitiatedSession.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4PeerInitiatedSession.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4Session.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4Session.java index 0c1a656c4b2f74c63ffc09143ec93a274116d5f1..e5f26de90199af5008105158d01851ccfc945d60 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4Session.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4Session.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4SessionClient.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4SessionClient.java index b96359b6cb00fae27e50ac08b7e3fe07772275eb..130a055a2b75030555e0f1ab28a22383c873933e 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4SessionClient.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4SessionClient.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4SessionExistsException.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4SessionExistsException.java index 4f6f4af856ad4293d5c999cc2cc8cde6203b60f0..c4968a4e7fabd3ee785feeb9b3c098ada4e88058 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4SessionExistsException.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4SessionExistsException.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4SessionsInformation.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4SessionsInformation.java index 963406700f327ec47eb213ec943f29476714f76c..cdca5a4ed8bed12481575918a411e1b2daa4f925 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4SessionsInformation.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4SessionsInformation.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4StateSession.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4StateSession.java index 5a1a5119a6fc213c0c923673dd6dbdaa108b755c..aa526197d08c70d56a43c16a271fd998be08f955 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4StateSession.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4StateSession.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/ConnectRetryTimer.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/ConnectRetryTimer.java index 0eba7b30963ec9254ba8b892a057b6d4996513a5..b4f618b998077f97c5abaa1aecf453405e024d34 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/ConnectRetryTimer.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/ConnectRetryTimer.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/DeadTimerThread.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/DeadTimerThread.java index ee9dd662320914cec0afb7fff9ebed74a4f06756..ffcee3274639352cca335fda288c934bcc03095e 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/DeadTimerThread.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/DeadTimerThread.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/GenericBGP4Session.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/GenericBGP4Session.java index c42423affbb415a40e6697a56285e9f77f55c59c..4f9903f0c5ab4e15d9126b2826cc656b8d9b1ba8 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/GenericBGP4Session.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/GenericBGP4Session.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/KeepAliveThread.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/KeepAliveThread.java index 32112e01bd99bb5371e4cc966255ad7ff8b425ba..9533b74e954096ef16b41e34bb1f5efbcaba471c 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/KeepAliveThread.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/KeepAliveThread.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/KeepWaitTimerTask.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/KeepWaitTimerTask.java index 94e39fb19c927c4dd6c4c89f222dbbab9e4e48a4..30a76680673dd34d8b8b4e5ff95890e0e2a8f165 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/KeepWaitTimerTask.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/KeepWaitTimerTask.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/OpenWaitTimerTask.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/OpenWaitTimerTask.java index fbb9aca1adb8448c837ce0e437684f4b4e1999a9..fe7dd53264a3a01a7d29b43ff0527bc0ff72cbf1 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/OpenWaitTimerTask.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/OpenWaitTimerTask.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/grpc/grpcApp.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/grpc/grpcApp.java index 02cfbaf91bc0e6652ab8f558f48c68e707f15a3b..c92c10aa1fa1c6a73575dbe768328fafbd631ad0 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/grpc/grpcApp.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/grpc/grpcApp.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/grpc/grpcClient.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/grpc/grpcClient.java index ca9b13007bc3ed427bf89fd1f1847d511b7af0d7..55490689d3d308a9d8390453ebd734a5283a7a50 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/grpc/grpcClient.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/grpc/grpcClient.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/grpc/updateServiceImpl.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/grpc/updateServiceImpl.java index e9dff709fabd84fe14426e52057542e70e496e1d..2f4381650ecf97b223914725b6feb274ffe4edcc 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/grpc/updateServiceImpl.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/grpc/updateServiceImpl.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/json/bgpMarshal.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/json/bgpMarshal.java index f4bdcc587d7f56c8d690a2e69ba5944c670e2b91..15dec092076d3466f913f7806dd3dc6a5b8baee4 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/json/bgpMarshal.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/json/bgpMarshal.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/management/BGP4ManagementServer.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/management/BGP4ManagementServer.java index 3a813e93678f6e92002543cf92b3092957c23a42..0bbc3c9f602b32e88d25ff87bd3f209a3fbb8bb3 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/management/BGP4ManagementServer.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/management/BGP4ManagementServer.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/management/BGP4ManagementSession.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/management/BGP4ManagementSession.java index 476628728a45176791e364c42469086fed7a03e6..41ebdf1bb4d96520efff91226a1ed52cca18a840 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/management/BGP4ManagementSession.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/management/BGP4ManagementSession.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/LinkNLRIMsg.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/LinkNLRIMsg.java index fb9a08d7e9be664cd712d148c1edda69661ddf2f..f361ac3efb0cdefe159f2c7a0ea7fe19e67aaa2b 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/LinkNLRIMsg.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/LinkNLRIMsg.java @@ -1,5 +1,5 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/NodeNLRIMsg.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/NodeNLRIMsg.java index d206cf7e234fb8bcd936a192a5dd68f05dc062c0..f847aedaec05b537415159f7aa357567d1ce0ef4 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/NodeNLRIMsg.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/NodeNLRIMsg.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/PathAttributeMsg.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/PathAttributeMsg.java index 4f036b8a1ec89b1dd14f07d194d6af6f84dbcab1..d8252a76349c4e0ccb15f42700607c61a4735315 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/PathAttributeMsg.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/PathAttributeMsg.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/UpdateMsg.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/UpdateMsg.java index aba3dcef54c813bce1e0093c5f1289ad42902101..ec0acafe2fa326455689f8bada4dc8edd7258035 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/UpdateMsg.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/UpdateMsg.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/UpdateMsgList.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/UpdateMsgList.java index e274a87aaaf31c4eeff4592ea71f4408d6dfde43..acc84cdf810c4cbd59c09a7edabff1ca0f76c7d8 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/UpdateMsgList.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/UpdateMsgList.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4Exception.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4Exception.java index 6bd951501bb09d3de40cfc5e7c3bc43cf259cfee..def0bc5244a78a4b4ea2ac1bfd3802cb88f375c8 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4Exception.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4Exception.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4LSPeerInfo.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4LSPeerInfo.java index d751622ee03bb80099e1ab88914945fe4f04c29b..d03f07f55bca56e2e161400ee548683fb540f7ad 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4LSPeerInfo.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4LSPeerInfo.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4Parameters.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4Parameters.java index 3c83a9a776f88a85e165f70fc23bb3aa62c0f33b..a1746cea2c2575173303c5460e36e1ae9b90ee04 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4Parameters.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4Parameters.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4SessionClientManager.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4SessionClientManager.java index 9e54e64c1cbda7fb77ffec543d2f1977cb635fa6..d37d1c21c9e6f3576ebc3f2ee3684c0d188f3fe9 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4SessionClientManager.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4SessionClientManager.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4SessionServerManager.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4SessionServerManager.java index 0d337bb6140841bd27e37fcbd3c238445c0797d2..12c313737e89267eab5d62da223d9ff99395cec9 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4SessionServerManager.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4SessionServerManager.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGPPeer.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGPPeer.java index 9894a89663bcc7b64df18e10083d2fe560a2bcca..b29b52082f0d754e7d1873516b58dc4d000f4b43 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGPPeer.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGPPeer.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGPPeerMain.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGPPeerMain.java index aa2a5cc6a0b371eb29615a200f5a1c71505f2a75..405964c3321aa6681d308497a31cec38fc015a1f 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGPPeerMain.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGPPeerMain.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/SaveTopologyinDB.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/SaveTopologyinDB.java index d66f2485d4f7f04d92f6d61e17c7fa49836ea25e..8a67375d577e7bc1bc2dd9b41f34c3dca7a9db74 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/SaveTopologyinDB.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/SaveTopologyinDB.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/SendTopology.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/SendTopology.java index 5bfeae8e2764151671034754682c6082b98b62ca..cfd11fc5433c749913de6d885122269486def72e 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/SendTopology.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/SendTopology.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/tedb/BGP4DomainTEDB.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/tedb/BGP4DomainTEDB.java index cbea17cc524ee98088573cf133004087519ad064..ab5edde7cbbf634aa8658da248d18c19ec07e327 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/tedb/BGP4DomainTEDB.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/tedb/BGP4DomainTEDB.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/tedb/BGP4IntradomainTEDB.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/tedb/BGP4IntradomainTEDB.java index 19aad7115d5fab5d14824a3e26df01996c3458e5..35f17165552c6d1c3b1b812f4541652357be5158 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/tedb/BGP4IntradomainTEDB.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/tedb/BGP4IntradomainTEDB.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/tedb/IntraTEDBS.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/tedb/IntraTEDBS.java index 22319122a7a154fe048b47ea6457ef8dd63d2264..ddb7fb40faeb8d93cfaf2d3b20bd4ab6e068c07a 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/tedb/IntraTEDBS.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/tedb/IntraTEDBS.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdateDispatcher.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdateDispatcher.java index 0da582030271a0ca0beed213d5c03d29086927b9..f8efa971f5631af7be78f9d2844e549cfd9d4a89 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdateDispatcher.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdateDispatcher.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdateLink.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdateLink.java index bf7a0b84a31c80f694c1dfeaf7fad44fc85882ff..fc140335669faefc1f3f2a137bc9a4d3a082b0c8 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdateLink.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdateLink.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdateProccesorThread.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdateProccesorThread.java index 26d876c17fe01de9bfc474ea6d3367119354ae37..ad386cf3db956f2b12967bc86b716b59f56d55eb 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdateProccesorThread.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdateProccesorThread.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdaterThreadRedisTED.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdaterThreadRedisTED.java index 4c0fd13800b30f3b6b77407b95acda5fc71f5618..b4bb4f3f55215cde835908d8535f9d908dea746e 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdaterThreadRedisTED.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdaterThreadRedisTED.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/DatabaseControlSimplifiedLSA.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/DatabaseControlSimplifiedLSA.java index 436263a47ca453b6f7454d08e14976d13dc03cb8..b0eb267dcef6ac2c8d869353c744bf730539f443 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/DatabaseControlSimplifiedLSA.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/DatabaseControlSimplifiedLSA.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/DomainTEDB.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/DomainTEDB.java index 44d2973b2ae3463031d3bba42bbe9f754e193c90..393d7ab6a20f82237ae4f4e7750b58e50bea7ec4 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/DomainTEDB.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/DomainTEDB.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/EdgeUtils.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/EdgeUtils.java index 79ad7f82c5159c6f18e21afaba493ee2a0b31357..30cefeedbe6306cfa5eca9d4e2d515913b6a2a54 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/EdgeUtils.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/EdgeUtils.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/FileTEDBUpdater.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/FileTEDBUpdater.java index 16ba2de9b5ddc43de899adb996abad2541cb4020..603d9791c34a29eeb4c64ff26c674beb8b56771e 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/FileTEDBUpdater.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/FileTEDBUpdater.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/IT_Resources.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/IT_Resources.java index dac19068fa67be60b200262e0bbc7396238943c5..040a83562361dbd3d5d508fcdc8831d903c8572c 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/IT_Resources.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/IT_Resources.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/InterDomainEdge.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/InterDomainEdge.java index 187b212051c5b229d0c5b7e5b413f263c8ceef0b..11071c517d2468729b143a76290d0ad655919a0f 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/InterDomainEdge.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/InterDomainEdge.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/IntraDomainEdge.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/IntraDomainEdge.java index 09eeedd497433d6b3f7efa71e777c57f36613a31..023ec305376510a2d05020dc2efa2b2168882355 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/IntraDomainEdge.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/IntraDomainEdge.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/IntraDomainWeightEdge.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/IntraDomainWeightEdge.java index 63052028b4a510ff84dbf4803d015f50d530f6f1..1f7d49e026c3d80807d7d7a7e9d0c3eb9aee59ca 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/IntraDomainWeightEdge.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/IntraDomainWeightEdge.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/Layer.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/Layer.java index 96d0c0c2e3464a8b792216c4cccbfd9a3e2aa4a9..b87deed6b17094fe3c4b014a740f9f60a89b761e 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/Layer.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/Layer.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/MDTEDB.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/MDTEDB.java index b8e671de21ac6f8324eb4fbd8f2530e12da84baf..13b7cd9ffe47d3848018a06ee1d74446460e651c 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/MDTEDB.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/MDTEDB.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/MultiDomainTEDB.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/MultiDomainTEDB.java index 746338df2e4b02787e56f0ce88f338c3a0dcfaa8..36e3d2632463d8adaa0292509762b0d3bb03c0b7 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/MultiDomainTEDB.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/MultiDomainTEDB.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/MultiLayerTEDB.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/MultiLayerTEDB.java index bed570fedf5cca39a8a580521d7918f76b773cc8..31f9c17b1aaef9629d029e9372ad46b0d5394a2d 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/MultiLayerTEDB.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/MultiLayerTEDB.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/Node_Info.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/Node_Info.java index b0f3bb3acaba9f1d5c915cf64e9f44241f8456a8..f9b73e6354c289b4c1031d8b7618fbb2305f42ba 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/Node_Info.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/Node_Info.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/ReachabilityEntry.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/ReachabilityEntry.java index e65a0ec3f0a27d27640e3437d144044374775a20..beb8187e7a0d4b5e148f0dca3fe495327a436dad 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/ReachabilityEntry.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/ReachabilityEntry.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/ReachabilityManager.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/ReachabilityManager.java index 161d27f1f8b87c0e20c3f2425c060362dea37eb6..5f2dd6d30fe3b2043e6f6ee2337231fb2893d34a 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/ReachabilityManager.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/ReachabilityManager.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/SSONInformation.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/SSONInformation.java index 78a234ee1320a463b7fd7cbea4d3c3d591fde159..6cdda3757352670073114587b9319d9837f0ba1c 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/SSONInformation.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/SSONInformation.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/SSONListener.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/SSONListener.java index 22b91b98614f9256a7b829a6196c43e3e161a996..d771931e3ffbe02135be5bc0130bb69216a9db55 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/SSONListener.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/SSONListener.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/SimpleTEDB.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/SimpleTEDB.java index 4e74e445b04ba27e04bfbe2ecdab8d2672bcb468..3181e48ba38028effa6016400dc3cd00b7af516b 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/SimpleTEDB.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/SimpleTEDB.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TEDB.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TEDB.java index ca937a5aa603aefdd796c0165a33bdb419f0a6f6..45064f2811fcbe1da80b0a500ba5ad748496ba92 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TEDB.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TEDB.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TEDBUpdater.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TEDBUpdater.java index 6b0aa6176e733704993686629d2bb5c7563957e7..168c7ff56da1be5eda43d308b3de8a41d2b34d70 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TEDBUpdater.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TEDBUpdater.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TEDListener.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TEDListener.java index ec1b2e650c56de37ed1289aa864c643a58134da2..3cb52fbe0e7fef435aa6e19b66341e9e3be7b899 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TEDListener.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TEDListener.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TE_Information.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TE_Information.java index f1842a6ced8f8788e6242c0e4d15805be48718eb..dfb890d74e9f2dce611e9c628068b21ae42e95d8 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TE_Information.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TE_Information.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/WSONInformation.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/WSONInformation.java index 2b344a342c320101bba2b21c3dc4a7b828022600..767fdf55c52ee7764dd74426b2310c4c40599e4c 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/WSONInformation.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/WSONInformation.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/WSONListener.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/WSONListener.java index a802fae9e029c34f91000d6d37866e81026f5a16..b0e21c1869e04cc5c430eaf67d5cf51f0d79457f 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/WSONListener.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/WSONListener.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterController.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterController.java index 853aa217e264924c395b37439e53e528241f10a5..83ac7a7111b30497453ed742585ecdecc71a8512 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterController.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterController.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterFloodlight.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterFloodlight.java index 401e4bc9ca25017f1ceb3d8a32332965cbc60121..574ca12dfd931e9fbd7a313ab45486796fa32464 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterFloodlight.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterFloodlight.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterNOX.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterNOX.java index 5b8e65f0c3dc751b6513a8248f6a445a721a78ce..21a32d2234ff03ca2e72b0f69c5c8ac8f1c06eb2 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterNOX.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterNOX.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterODL.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterODL.java index 1bdbc624d06482763638af631e906ce483d9fc3d..f50d845c56eafb24a170d02c85709b2540a57bf3 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterODL.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterODL.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterRYU.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterRYU.java index 74b0a1f4e6b9e3dda9d7163c739e2df820b7332e..11766f0bff75060eeb593faf2d45382cf2d5319d 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterRYU.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterRYU.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterTREMA.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterTREMA.java index ac11500b7c3c34655996a07e67a49633a35e678a..3815582320e3e0f2c62118cbe2fc953f12b108f6 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterTREMA.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterTREMA.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/AuthInfo.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/AuthInfo.java index 223c1940efbed133f7633ec3aca75815f8b4d38e..e784a9c0b9696dfc734f217562318b96b2967fff 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/AuthInfo.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/AuthInfo.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Bandwidth.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Bandwidth.java index fd5f7aa882effab93ab24dd598260447822ff0e6..ddb0d5c1768226fad7b7912ed361fdf260e8e5bb 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Bandwidth.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Bandwidth.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/BgpParams.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/BgpParams.java index 37fab22972d14c23739c910b8d23d2fc29a2f22b..10e1329d1781a76cca152d9c499561e538100325 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/BgpParams.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/BgpParams.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/EndPoint.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/EndPoint.java index 845bcf416f0977bd3e619768fe6cb02159b9301d..c602ddc48f1bf920cae98747908cb707f615a1b6 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/EndPoint.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/EndPoint.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/IPNodeParams.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/IPNodeParams.java index 0c56d240c3560885782ea00c5ed621c91de290df..b8ef307f1e010d6bca10830c34ae294d9b2430dd 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/IPNodeParams.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/IPNodeParams.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Intf.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Intf.java index 57010b9997870f1aaadc1e389eaad1fbf0c6c656..7a7f9e46a4e1fdfba887aff0982a58d0bf65cc1f 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Intf.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Intf.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/IsisParams.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/IsisParams.java index 1daaf21242dcaea9b656c2d9a7cbdab11b64b844..423f7d65f00cf0848df8dee77fdebf0c9fbc9070 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/IsisParams.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/IsisParams.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Link.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Link.java index 35b3e9c22398f554f96903f4b1b7262128ed3329..27270d28a013bb3ba84a38e8b4d3c4eada5e3796 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Link.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Link.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Location.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Location.java index 311387bc3ca6fe3ca9de665854c840097663f645..ce7b3ab0ae35bdc184fee96a37c92b173680e2c2 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Location.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Location.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Node.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Node.java index 596dedb9ae27a6b0e20c1275f65071f630cd6a39..a18a75e1c53069b70bfdedf220b36b475558a489 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Node.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Node.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/OspfParams.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/OspfParams.java index 4b06f38680f5289620a22aaa49c82c98a4fe13c2..23f55da5a884c1fa3db634a8326d2ce1384b111d 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/OspfParams.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/OspfParams.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Path.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Path.java index d77a7039774239d55c07d5a3b1dfff7a7f4b9d39..42aafb1dc9f3b198a85b521fc18c76e909001438 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Path.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Path.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/PhyLinkParams.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/PhyLinkParams.java index 739508b41f44ddbf122354b33fb05e6830eebdf8..ae234a64773cde44a2826a00bfde7c53deb50836 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/PhyLinkParams.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/PhyLinkParams.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/RouterDesc.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/RouterDesc.java index 71cd098a5d0e12ea9f9117805f4162846475c555..2c4ca43e8ddf697dda3f11d5c8e139882d85d959 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/RouterDesc.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/RouterDesc.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/RouterInfoPM.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/RouterInfoPM.java index 037e6a1eb8eba8a43f8c9ef38dd574f74a4c5379..e3624685c6aebdd38440118ecb875c7f24f62468 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/RouterInfoPM.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/RouterInfoPM.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Service.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Service.java index a60bb60ffca8f5e1f39492365e1dfe179e41d61d..01e54c9733fcc9a375964e82a6e49a6c2c3b2154 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Service.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Service.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/StaticRoutingParams.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/StaticRoutingParams.java index efae987626a62cc01bb6c07105d8d9e2fa70723f..e01bdfe55430241cb170645ef8c4a8f77ef0fd1c 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/StaticRoutingParams.java +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/StaticRoutingParams.java @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/proto/grpcService.proto b/src/bgpls_speaker/service/java/netphony-topology/src/main/proto/grpcService.proto index 89ab745e1fe6eb32b2038ef2ed89d3ee70c14aee..7c994427b8bcde3402470e945db8eed22518bb2d 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/proto/grpcService.proto +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/proto/grpcService.proto @@ -1,4 +1,4 @@ -// Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +// 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. diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/TM_COP_example1/TMConfCOP.xml b/src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/TM_COP_example1/TMConfCOP.xml index c83d4ec1a146d5742b7a422c0fd4b7658dea4f32..c1d9ab31c877fbd5b99f27701843dfbad944be1c 100644 --- a/src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/TM_COP_example1/TMConfCOP.xml +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/TM_COP_example1/TMConfCOP.xml @@ -1,4 +1,4 @@ - + +module chaincode + +go 1.17 + +require github.com/hyperledger/fabric-contract-api-go v1.2.1 + +require ( + github.com/go-openapi/jsonpointer v0.19.5 // indirect + github.com/go-openapi/jsonreference v0.20.0 // indirect + github.com/go-openapi/spec v0.20.8 // indirect + github.com/go-openapi/swag v0.21.1 // indirect + github.com/gobuffalo/envy v1.10.1 // indirect + github.com/gobuffalo/packd v1.0.1 // indirect + github.com/gobuffalo/packr v1.30.1 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/hyperledger/fabric-chaincode-go v0.0.0-20230228194215-b84622ba6a7a // indirect + github.com/hyperledger/fabric-protos-go v0.3.0 // indirect + github.com/joho/godotenv v1.4.0 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/rogpeppe/go-internal v1.8.1 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect + github.com/xeipuuv/gojsonschema v1.2.0 // indirect + golang.org/x/net v0.7.0 // indirect + golang.org/x/sys v0.5.0 // indirect + golang.org/x/text v0.7.0 // indirect + google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect + google.golang.org/grpc v1.53.0 // indirect + google.golang.org/protobuf v1.28.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect +) diff --git a/src/dlt/gateway/chaincode/go.sum b/src/dlt/gateway/chaincode/go.sum new file mode 100644 index 0000000000000000000000000000000000000000..8bb9581b596c7f9dd4528d14f5051aa03132421f --- /dev/null +++ b/src/dlt/gateway/chaincode/go.sum @@ -0,0 +1,1240 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U= +cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= +cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= +cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= +cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= +cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= +cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= +cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= +cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= +cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o= +cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE= +cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= +cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= +cloud.google.com/go/aiplatform v1.27.0/go.mod h1:Bvxqtl40l0WImSb04d0hXFU7gDOiq9jQmorivIiWcKg= +cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= +cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= +cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk= +cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc= +cloud.google.com/go/apigeeconnect v1.3.0/go.mod h1:G/AwXFAKo0gIXkPTVfZDd2qA1TxBXJ3MgMRBQkIi9jc= +cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn/pkS3QlHp0Ni04= +cloud.google.com/go/appengine v1.4.0/go.mod h1:CS2NhuBuDXM9f+qscZ6V86m1MIIqPj3WC/UoEuR1Sno= +cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodCWatWI9Dmak= +cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4= +cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= +cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ= +cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= +cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0= +cloud.google.com/go/artifactregistry v1.9.0/go.mod h1:2K2RqvA2CYvAeARHRkLDhMDJ3OXy26h3XW+3/Jh2uYc= +cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= +cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s= +cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= +cloud.google.com/go/asset v1.9.0/go.mod h1:83MOE6jEJBMqFKadM9NLRcs80Gdw76qGuHn8m3h8oHQ= +cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAtZiIb0wY= +cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY= +cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw= +cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= +cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo= +cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= +cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= +cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= +cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8= +cloud.google.com/go/automl v1.8.0/go.mod h1:xWx7G/aPEe/NP+qzYXktoBSDfjO+vnKMGgsApGJJquM= +cloud.google.com/go/baremetalsolution v0.3.0/go.mod h1:XOrocE+pvK1xFfleEnShBlNAXf+j5blPPxrhjKgnIFc= +cloud.google.com/go/baremetalsolution v0.4.0/go.mod h1:BymplhAadOO/eBa7KewQ0Ppg4A4Wplbn+PsFKRLo0uI= +cloud.google.com/go/batch v0.3.0/go.mod h1:TR18ZoAekj1GuirsUsR1ZTKN3FC/4UDnScjT8NXImFE= +cloud.google.com/go/batch v0.4.0/go.mod h1:WZkHnP43R/QCGQsZ+0JyG4i79ranE2u8xvjq/9+STPE= +cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckmnSFS+xwTfm4= +cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= +cloud.google.com/go/bigquery v1.43.0/go.mod h1:ZMQcXHsl+xmU1z36G2jNGZmKp9zNY5BUua5wDgmNCfw= +cloud.google.com/go/bigquery v1.44.0/go.mod h1:0Y33VqXTEsbamHJvJHdFmtqHvMIY28aK1+dFsvaChGc= +cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= +cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= +cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI= +cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y= +cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= +cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= +cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0= +cloud.google.com/go/binaryauthorization v1.4.0/go.mod h1:tsSPQrBd77VLplV70GUhBf/Zm3FsKmgSqgm4UmiDItk= +cloud.google.com/go/certificatemanager v1.3.0/go.mod h1:n6twGDvcUBFu9uBgt4eYvvf3sQ6My8jADcOVwHmzadg= +cloud.google.com/go/certificatemanager v1.4.0/go.mod h1:vowpercVFyqs8ABSmrdV+GiFf2H/ch3KyudYQEMM590= +cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk= +cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk= +cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U= +cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA= +cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM= +cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk= +cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY= +cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI= +cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4= +cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI= +cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= +cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= +cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= +cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= +cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= +cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= +cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= +cloud.google.com/go/compute v1.12.0/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= +cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= +cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= +cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= +cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= +cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= +cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= +cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= +cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg= +cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo= +cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= +cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= +cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= +cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs= +cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= +cloud.google.com/go/datacatalog v1.7.0/go.mod h1:9mEl4AuDYWw81UGc41HonIHH7/sn52H0/tc8f8ZbZIE= +cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOXxZoKYF5wdISM= +cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM= +cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= +cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo= +cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= +cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0= +cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38= +cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w= +cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I= +cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ= +cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA= +cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A= +cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s= +cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI= +cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo= +cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/datastore v1.10.0/go.mod h1:PC5UzAmDEkAmkfaknstTYbNpgE49HAgW2J1gcgUfmdM= +cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo= +cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= +cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g= +cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4= +cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c= +cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s= +cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4= +cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0= +cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= +cloud.google.com/go/dialogflow v1.18.0/go.mod h1:trO7Zu5YdyEuR+BhSNOqJezyFQ3aUzz0njv7sMx/iek= +cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFMoosgy+6Gn0s0= +cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM= +cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q= +cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU= +cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU= +cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k= +cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4= +cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y= +cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= +cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= +cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= +cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= +cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI= +cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8= +cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc= +cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw= +cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w= +cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI= +cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= +cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= +cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= +cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY= +cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5UwtlpzoyquQ08= +cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= +cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= +cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w= +cloud.google.com/go/gaming v1.8.0/go.mod h1:xAqjS8b7jAVW0KFYeRUxngo9My3f33kFmua++Pi+ggM= +cloud.google.com/go/gkebackup v0.2.0/go.mod h1:XKvv/4LfG829/B8B7xRkk8zRrOEbKtEam6yNfuQNH60= +cloud.google.com/go/gkebackup v0.3.0/go.mod h1:n/E671i1aOQvUxT541aTkCwExO/bTer2HDlj4TsBRAo= +cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o= +cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A= +cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0= +cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= +cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA= +cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI= +cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= +cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2rg9bN8SXOa0bgM= +cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o= +cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c= +cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= +cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= +cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc= +cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= +cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= +cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= +cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= +cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM= +cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY= +cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs= +cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g= +cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= +cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg= +cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0= +cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= +cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= +cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE= +cloud.google.com/go/language v1.8.0/go.mod h1:qYPVHf7SPoNNiCL2Dr0FfEFNil1qi3pQEyygwpgVKB8= +cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= +cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= +cloud.google.com/go/logging v1.6.1/go.mod h1:5ZO0mHHbvm8gEmeEUHrmDlTDSu5imF6MUP9OfilNXBw= +cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE= +cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= +cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE= +cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM= +cloud.google.com/go/maps v0.1.0/go.mod h1:BQM97WGyfw9FWEmQMpZ5T6cpovXXSd1cGmFma94eubI= +cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= +cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= +cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= +cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM= +cloud.google.com/go/memcache v1.6.0/go.mod h1:XS5xB0eQZdHtTuTF9Hf8eJkKtR3pVRCcvJwtm68T3rA= +cloud.google.com/go/memcache v1.7.0/go.mod h1:ywMKfjWhNtkQTxrWxCkCFkoPjLHPW6A7WOTVI8xy3LY= +cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY= +cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s= +cloud.google.com/go/metastore v1.7.0/go.mod h1:s45D0B4IlsINu87/AsWiEVYbLaIMeUSoxlKKDqBGFS8= +cloud.google.com/go/metastore v1.8.0/go.mod h1:zHiMc4ZUpBiM7twCIFQmJ9JMEkDSyZS9U12uf7wHqSI= +cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk= +cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4= +cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= +cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= +cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM= +cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8= +cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8= +cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4= +cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ= +cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= +cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY= +cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= +cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA= +cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0= +cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4= +cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs= +cloud.google.com/go/orchestration v1.3.0/go.mod h1:Sj5tq/JpWiB//X/q3Ngwdl5K7B7Y0KZ7bfv0wL6fqVA= +cloud.google.com/go/orchestration v1.4.0/go.mod h1:6W5NLFWs2TlniBphAViZEVhrXRSMgUGDfW7vrWKvsBk= +cloud.google.com/go/orgpolicy v1.4.0/go.mod h1:xrSLIV4RePWmP9P3tBl8S93lTmlAxjm06NSm2UTmKvE= +cloud.google.com/go/orgpolicy v1.5.0/go.mod h1:hZEc5q3wzwXJaKrsx5+Ewg0u1LxJ51nNFlext7Tanwc= +cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs= +cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg= +cloud.google.com/go/osconfig v1.9.0/go.mod h1:Yx+IeIZJ3bdWmzbQU4fxNl8xsZ4amB+dygAwFPlvnNo= +cloud.google.com/go/osconfig v1.10.0/go.mod h1:uMhCzqC5I8zfD9zDEAfvgVhDS8oIjySWh+l4WK6GnWw= +cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E= +cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU= +cloud.google.com/go/oslogin v1.6.0/go.mod h1:zOJ1O3+dTU8WPlGEkFSh7qeHPPSoxrcMbbK1Nm2iX70= +cloud.google.com/go/oslogin v1.7.0/go.mod h1:e04SN0xO1UNJ1M5GP0vzVBFicIe4O53FOfcixIqTyXo= +cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0= +cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA= +cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg= +cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE= +cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0= +cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/pubsub v1.26.0/go.mod h1:QgBH3U/jdJy/ftjPhTkyXNj543Tin1pRYcdcPRnFIRI= +cloud.google.com/go/pubsub v1.27.1/go.mod h1:hQN39ymbV9geqBnfQq6Xf63yNhUAhv9CZhzp5O6qsW0= +cloud.google.com/go/pubsublite v1.5.0/go.mod h1:xapqNQ1CuLfGi23Yda/9l4bBCKz/wC3KIJ5gKcxveZg= +cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= +cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= +cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= +cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo= +cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI5sbwx9LBg3te2N6hGvHn2mE= +cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U= +cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg= +cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= +cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg= +cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c= +cloud.google.com/go/recommender v1.7.0/go.mod h1:XLHs/W+T8olwlGOgfQenXBTbIseGclClff6lhFVe9Bs= +cloud.google.com/go/recommender v1.8.0/go.mod h1:PkjXrTT05BFKwxaUxQmtIlrtj0kph108r02ZZQ5FE70= +cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y= +cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A= +cloud.google.com/go/redis v1.9.0/go.mod h1:HMYQuajvb2D0LvMgZmLDZW8V5aOC/WxstZHiy4g8OiA= +cloud.google.com/go/redis v1.10.0/go.mod h1:ThJf3mMBQtW18JzGgh41/Wld6vnDDc/F/F35UolRZPM= +cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA= +cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0= +cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU= +cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg= +cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4= +cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY= +cloud.google.com/go/retail v1.10.0/go.mod h1:2gDk9HsL4HMS4oZwz6daui2/jmKvqShXKQuB2RZ+cCc= +cloud.google.com/go/retail v1.11.0/go.mod h1:MBLk1NaWPmh6iVFSz9MeKG/Psyd7TAgm6y/9L2B4x9Y= +cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do= +cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo= +cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s= +cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI= +cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRrYB5ZtT+KOk= +cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44= +cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA= +cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4= +cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4= +cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4= +cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0= +cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU= +cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq/t9dzI+2Q= +cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA= +cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU= +cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= +cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk= +cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk= +cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU= +cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s= +cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs= +cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= +cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPjsRs1RlmJ4pqiNjVL4= +cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U= +cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco= +cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo= +cloud.google.com/go/serviceusage v1.3.0/go.mod h1:Hya1cozXM4SeSKTAgGXgj97GlqUvF5JaoXacR1JTP/E= +cloud.google.com/go/serviceusage v1.4.0/go.mod h1:SB4yxXSaYVuUBYUml6qklyONXNLt83U0Rb+CXyhjEeU= +cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4= +cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw= +cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= +cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= +cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= +cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= +cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= +cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= +cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= +cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= +cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= +cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= +cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= +cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= +cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM= +cloud.google.com/go/talent v1.4.0/go.mod h1:ezFtAgVuRf8jRsvyE6EwmbTK5LKciD4KVnHuDEFmOOA= +cloud.google.com/go/texttospeech v1.4.0/go.mod h1:FX8HQHA6sEpJ7rCMSfXuzBcysDAuWusNNNvN9FELDd8= +cloud.google.com/go/texttospeech v1.5.0/go.mod h1:oKPLhR4n4ZdQqWKURdwxMy0uiTS1xU161C8W57Wkea4= +cloud.google.com/go/tpu v1.3.0/go.mod h1:aJIManG0o20tfDQlRIej44FcwGGl/cD0oiRyMKG19IQ= +cloud.google.com/go/tpu v1.4.0/go.mod h1:mjZaX8p0VBgllCzF6wcU2ovUXN9TONFLd7iz227X2Xg= +cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28= +cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y= +cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs= +cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg= +cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk= +cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw= +cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= +cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= +cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M= +cloud.google.com/go/videointelligence v1.9.0/go.mod h1:29lVRMPDYHikk3v8EdPSaL8Ku+eMzDljjuvRs105XoU= +cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0= +cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo= +cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo= +cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb+MhPqRbPsY= +cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E= +cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE= +cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g= +cloud.google.com/go/vmwareengine v0.1.0/go.mod h1:RsdNEf/8UDvKllXhMz5J40XxDrNJNN4sagiox+OI208= +cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w= +cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8= +cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE= +cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= +cloud.google.com/go/webrisk v1.6.0/go.mod h1:65sW9V9rOosnc9ZY7A7jsy1zoHS5W9IAXv6dGqhMQMc= +cloud.google.com/go/webrisk v1.7.0/go.mod h1:mVMHgEYH0r337nmt1JyLthzMr6YxwN1aAIEc2fTcq7A= +cloud.google.com/go/websecurityscanner v1.3.0/go.mod h1:uImdKm2wyeXQevQJXeh8Uun/Ym1VqworNDlBXQevGMo= +cloud.google.com/go/websecurityscanner v1.4.0/go.mod h1:ebit/Fp0a+FWu5j4JOmJEV8S8CzdTkAS77oDsiSqYWQ= +cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= +cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= +cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M= +cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cucumber/gherkin-go/v19 v19.0.3/go.mod h1:jY/NP6jUtRSArQQJ5h1FXOUgk5fZK24qtE7vKi776Vw= +github.com/cucumber/godog v0.12.6/go.mod h1:Y02TTpimPXDb70PnG6M3zpODXm1+bjCsuZzcW76xAww= +github.com/cucumber/messages-go/v16 v16.0.0/go.mod h1:EJcyR5Mm5ZuDsKJnT2N9KRnBK30BGjtYotDKpwQ0v6g= +github.com/cucumber/messages-go/v16 v16.0.1/go.mod h1:EJcyR5Mm5ZuDsKJnT2N9KRnBK30BGjtYotDKpwQ0v6g= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= +github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= +github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= +github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= +github.com/go-openapi/spec v0.20.8 h1:ubHmXNY3FCIOinT8RNrrPfGc9t7I1qhPtdOGoG2AxRU= +github.com/go-openapi/spec v0.20.8/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/swag v0.21.1 h1:wm0rhTb5z7qpJRHBdPOMuY4QjVUMbF6/kwoYeRAOrKU= +github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/envy v1.10.1 h1:ppDLoXv2feQ5nus4IcgtyMdHQkKng2lhJCIm33cblM0= +github.com/gobuffalo/envy v1.10.1/go.mod h1:AWx4++KnNOW3JOeEvhSaq+mvgAvnMYOY1XSIin4Mago= +github.com/gobuffalo/logger v1.0.0/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs= +github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q= +github.com/gobuffalo/packd v1.0.1 h1:U2wXfRr4E9DH8IdsDLlRFwTZTK7hLfq9qT/QHXGVe/0= +github.com/gobuffalo/packd v1.0.1/go.mod h1:PP2POP3p3RXGz7Jh6eYEf93S7vA2za6xM7QT85L4+VY= +github.com/gobuffalo/packr v1.30.1 h1:hu1fuVR3fXEZR7rXNW3h8rqSML8EVAf6KNm0NKO/wKg= +github.com/gobuffalo/packr v1.30.1/go.mod h1:ljMyFO2EcrnzsHsN99cvbq055Y9OhRrIaviy289eRuk= +github.com/gobuffalo/packr/v2 v2.5.1/go.mod h1:8f9c96ITobJlPzI44jj+4tHnEKNt0xXWSVlXRN9X1Iw= +github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= +github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= +github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= +github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= +github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= +github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= +github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= +github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= +github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= +github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= +github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-memdb v1.3.2/go.mod h1:Mluclgwib3R93Hk5fxEfiRhB+6Dar64wWh71LpNSe3g= +github.com/hashicorp/go-memdb v1.3.3/go.mod h1:uBTr1oQbtuMgd1SSGoR8YV27eT3sBHbYiNm53bMpgSg= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hyperledger/fabric-chaincode-go v0.0.0-20230228194215-b84622ba6a7a h1:HwSCxEeiBthwcazcAykGATQ36oG9M+HEQvGLvB7aLvA= +github.com/hyperledger/fabric-chaincode-go v0.0.0-20230228194215-b84622ba6a7a/go.mod h1:TDSu9gxURldEnaGSFbH1eMlfSQBWQcMQfnDBcpQv5lU= +github.com/hyperledger/fabric-contract-api-go v1.2.1 h1:Ww9cKH/qHl5s6WqF+Ts5ju5eaBxC/awB/BJE+rOsEkM= +github.com/hyperledger/fabric-contract-api-go v1.2.1/go.mod h1:BhWve0gz1iH+Xc+cO3rmeIZI7YaTWOQodka9CgeUOgo= +github.com/hyperledger/fabric-protos-go v0.3.0 h1:MXxy44WTMENOh5TI8+PCK2x6pMj47Go2vFRKDHB2PZs= +github.com/hyperledger/fabric-protos-go v0.3.0/go.mod h1:WWnyWP40P2roPmmvxsUXSvVI/CF6vwY1K1UFidnKBys= +github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= +github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/karrick/godirwalk v1.10.12/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= +github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= +google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= +google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= +google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= +google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= +google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= +google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= +google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= +google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g= +google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= +google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= +google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI= +google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91A08= +google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= +google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= +google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20220329172620-7be39ac1afc7/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE= +google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= +google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220817144833-d7fd3f11b9b1/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220829144015-23454907ede3/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220829175752-36a9c930ecbf/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220913154956-18f8339a66a5/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220914142337-ca0e39ece12f/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw= +google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= +google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= +google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U= +google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= +google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= +google.golang.org/genproto v0.0.0-20221024153911-1573dae28c9c/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= +google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= +google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo= +google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221117204609-8f9c96812029/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= +google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= +google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= +google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/src/dlt/gateway/dltApp/package-lock.json b/src/dlt/gateway/dltApp/package-lock.json new file mode 100644 index 0000000000000000000000000000000000000000..6fb245621a1e38f84d6806aae2f94fc83394b05a --- /dev/null +++ b/src/dlt/gateway/dltApp/package-lock.json @@ -0,0 +1,2420 @@ +{ + "name": "dlt_gateway", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "dlt_gateway", + "version": "1.0.0", + "license": "Apache-2.0", + "dependencies": { + "@grpc/grpc-js": "^1.10.8", + "@grpc/proto-loader": "^0.7.13", + "@hyperledger/fabric-gateway": "~1.4.0", + "dotenv": "^16.4.5", + "grpc-tools": "^1.12.4", + "protobufjs": "^7.3.0", + "uuid": "^9.0.1" + }, + "devDependencies": { + "@tsconfig/node18": "^18.2.2", + "@types/node": "^18.18.6", + "@typescript-eslint/eslint-plugin": "^6.9.0", + "@typescript-eslint/parser": "^6.9.0", + "eslint": "^8.52.0", + "typescript": "~5.2.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@grpc/grpc-js": { + "version": "1.10.8", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.10.8.tgz", + "integrity": "sha512-vYVqYzHicDqyKB+NQhAc54I1QWCBLCrYG6unqOIcBTHx+7x8C9lcoLj3KVJXs2VB4lUbpWY+Kk9NipcbXYWmvg==", + "dependencies": { + "@grpc/proto-loader": "^0.7.13", + "@js-sdsl/ordered-map": "^4.4.2" + }, + "engines": { + "node": ">=12.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.7.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", + "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.5", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "dev": true + }, + "node_modules/@hyperledger/fabric-gateway": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@hyperledger/fabric-gateway/-/fabric-gateway-1.4.0.tgz", + "integrity": "sha512-dJ0eJdGBo8wtZ/oR5mADHnllp+pSuVOI7uq5fRFf0NTVk1SzlX42Q3kt4j53bJQaxd21TMvofgXNO+BCgJcB/A==", + "dependencies": { + "@grpc/grpc-js": "^1.9.0", + "@hyperledger/fabric-protos": "^0.2.0", + "asn1.js": "^5.4.1", + "bn.js": "^5.2.1", + "elliptic": "^6.5.4", + "google-protobuf": "^3.21.0" + }, + "engines": { + "node": ">=18.12.0" + }, + "optionalDependencies": { + "pkcs11js": "^1.3.0" + } + }, + "node_modules/@hyperledger/fabric-protos": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@hyperledger/fabric-protos/-/fabric-protos-0.2.1.tgz", + "integrity": "sha512-qjm0vIQIfCall804tWDeA8p/mUfu14sl5Sj+PbOn2yDKJq+7ThoIhNsLAqf+BCxUfqsoqQq6AojhqQeTFyOOqg==", + "dependencies": { + "@grpc/grpc-js": "^1.9.0", + "google-protobuf": "^3.21.0" + }, + "engines": { + "node": ">=14.15.0" + } + }, + "node_modules/@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, + "node_modules/@tsconfig/node18": { + "version": "18.2.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node18/-/node18-18.2.4.tgz", + "integrity": "sha512-5xxU8vVs9/FNcvm3gE07fPbn9tl6tqGGWA9tSlwsUEkBxtRnTsNmwrV8gasZ9F/EobaSv9+nu8AxUKccw77JpQ==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "18.19.33", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.33.tgz", + "integrity": "sha512-NR9+KrpSajr2qBVp/Yt5TU/rp+b5Mayi3+OlMlcg2cVCfRmcG5PWZ7S4+MG9PZ5gWBoc9Pd0BKSRViuBCRPu0A==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/semver": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "deprecated": "This package is no longer supported.", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/elliptic": { + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.5.tgz", + "integrity": "sha512-7EjbcmUm17NQFu4Pmgmq2olYMj8nwMnpcddByChSUjArp8F5DQWcIcpriwO4ZToLNAJig0yiyjswfyGNje/ixw==", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "deprecated": "This package is no longer supported.", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/google-protobuf": { + "version": "3.21.2", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.2.tgz", + "integrity": "sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/grpc-tools": { + "version": "1.12.4", + "resolved": "https://registry.npmjs.org/grpc-tools/-/grpc-tools-1.12.4.tgz", + "integrity": "sha512-5+mLAJJma3BjnW/KQp6JBjUMgvu7Mu3dBvBPd1dcbNIb+qiR0817zDpgPjS7gRb+l/8EVNIa3cB02xI9JLToKg==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.5" + }, + "bin": { + "grpc_tools_node_protoc": "bin/protoc.js", + "grpc_tools_node_protoc_plugin": "bin/protoc_plugin.js" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" + }, + "node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.19.0.tgz", + "integrity": "sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==", + "optional": true + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "deprecated": "This package is no longer supported.", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkcs11js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkcs11js/-/pkcs11js-1.3.1.tgz", + "integrity": "sha512-eo7fTeQwYGzX1pFmRaf4ji/WcDW2XKpwqylOwzutsjNWECv6G9PzDHj3Yj5dX9EW/fydMnJG8xvWj/btnQT9TA==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "nan": "^2.15.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/PeculiarVentures" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/protobufjs": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.3.0.tgz", + "integrity": "sha512-YWD03n3shzV9ImZRX3ccbjqLxj7NokGN0V/ESiBV5xWqrommYHYiihuIyavq03pWSGqlyvYUFmfoMKd+1rPA/g==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.1.tgz", + "integrity": "sha512-f/vbBsu+fOiYt+lmwZV0rVwJScl46HppnOA1ZvIuBWKOTlllpyJ3bfVax76/OrhCH38dyxoDIA8K7uB963IYgA==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/src/dlt/gateway/dltApp/package.json b/src/dlt/gateway/dltApp/package.json new file mode 100644 index 0000000000000000000000000000000000000000..9d29b5287e1d3085c1cede9ab73b23189f3228d3 --- /dev/null +++ b/src/dlt/gateway/dltApp/package.json @@ -0,0 +1,38 @@ +{ + "name": "dlt_gateway", + "version": "1.0.0", + "description": "A DLT application that record and manages network related data as JSON, implemented in typeScript using HLF fabric-gateway", + "main": "dist/index.js", + "typings": "dist/index.d.ts", + "engines": { + "node": ">=18" + }, + "scripts": { + "build": "tsc", + "build:watch": "tsc -w", + "lint": "eslint . --ext .ts", + "prepare": "npm run build", + "pretest": "npm run lint", + "start": "node dist/dlt_gateway.js" + }, + "engineStrict": true, + "author": "Javier Jose Diaz (CTTC)", + "license": "Apache-2.0", + "dependencies": { + "@grpc/grpc-js": "^1.10.8", + "@grpc/proto-loader": "^0.7.13", + "@hyperledger/fabric-gateway": "~1.4.0", + "dotenv": "^16.4.5", + "grpc-tools": "^1.12.4", + "protobufjs": "^7.3.0", + "uuid": "^9.0.1" + }, + "devDependencies": { + "@tsconfig/node18": "^18.2.2", + "@types/node": "^18.18.6", + "@typescript-eslint/eslint-plugin": "^6.9.0", + "@typescript-eslint/parser": "^6.9.0", + "eslint": "^8.52.0", + "typescript": "~5.2.2" + } +} diff --git a/src/dlt/gateway/dltApp/src/dltGateway.js b/src/dlt/gateway/dltApp/src/dltGateway.js new file mode 100644 index 0000000000000000000000000000000000000000..3949a6c5bded5fb462e8d57110e4714c725b8b22 --- /dev/null +++ b/src/dlt/gateway/dltApp/src/dltGateway.js @@ -0,0 +1,262 @@ +// 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. + + +const grpc = require('@grpc/grpc-js'); +const protoLoader = require('@grpc/proto-loader'); +const path = require('path'); +const { connectToNetwork } = require('../dist/fabricConnect'); +const utf8Decoder = new TextDecoder(); + +// Load the protocol buffer definitions +const PROTO_PATH = path.resolve(__dirname, '../proto/dlt_gateway.proto'); +const packageDefinition = protoLoader.loadSync(PROTO_PATH, { + keepCase: true, + longs: String, + enums: String, + defaults: true, + oneofs: true, +}); +const dltProto = grpc.loadPackageDefinition(packageDefinition).dlt; + +// Create a gRPC server instance +const server = new grpc.Server(); +let contractInstance = null; +let closeConnection = null; +let events = null; // To store the events iterable + +const clients = new Set(); // Set to keep track of active client streams + + + +// Initialize connection to the chaincode + +async function initChaincodeConnection() { + try { + const networkResources = await connectToNetwork(); + contractInstance = networkResources.contract; + events = networkResources.events; // Initiate event listening + closeConnection = networkResources.close; + + //console.log("DEBUG", events) + console.log("Chaincode connection established successfully."); + } catch (error) { + console.error('Failed to establish chaincode connection:', error); + process.exit(1); // Exit if the connection cannot be established + } +} + +// gRPC method to handle recording data to the DLT +async function recordToDlt(call, callback) { + if (!contractInstance) { + callback({ + code: grpc.status.UNAVAILABLE, + details: "Chaincode connection is not established." + }); + return; + } + const { record_id, operation, data_json } = call.request; + try { + + + console.log(`Operation requested: ${operation}`); + + switch (operation) { + case 'DLTRECORDOPERATION_ADD': + await contractInstance.submitTransaction('StoreRecord', JSON.stringify(record_id), data_json); + break; + case 'DLTRECORDOPERATION_UPDATE': + await contractInstance.submitTransaction('UpdateRecord', JSON.stringify(record_id), data_json); + break; + case 'DLTRECORDOPERATION_DELETE': + await contractInstance.submitTransaction('DeleteRecord', JSON.stringify(record_id)); + break; + default: + throw new Error('Invalid operation'); + } + // Send success response + callback(null, { record_id, status: 'DLTRECORDSTATUS_SUCCEEDED' }); + } catch (error) { + // Send failure response with error message + console.log("ERRROR", error) + callback(null, { record_id, status: 'DLTRECORDSTATUS_FAILED', error_message: error.message }); + } +} + +// gRPC method to fetch data from the DLT +async function getFromDlt(call, callback) { + + if (!contractInstance) { + callback({ + code: grpc.status.UNAVAILABLE, + details: "Chaincode connection is not established." + }); + return; + } + + try { + + console.log("RECEIVED CALL REQUEST:", call.request); + //const { record_id, operation, data_json } = call.request; + const resultBytes = await contractInstance.evaluateTransaction('RetrieveRecord', JSON.stringify(call.request)); + // Decode and parse the result + const resultJson = utf8Decoder.decode(resultBytes); + const result = JSON.parse(resultJson); + + // Send the response with the formatted JSON data + callback(null, { record_id: call.request, operation: result.operation, data_json: result.data_json }); + } catch (error) { + if (error.message.includes("data not found for key")) { + // Return an empty response when no record is found + console.log("REQUEST ERROR:", error); + const emptyRecordId = { + domain_uuid: { uuid: "" }, + type: 'DLTRECORDTYPE_UNDEFINED', + record_uuid: { uuid: "" } + }; + callback(null, { record_id: emptyRecordId, data_json: "" }); + } else { + // Send failure response with error message + callback({ + code: grpc.status.UNKNOWN, + details: error.message + }); + } + } +} + +// Implement subscription to DLT events + +const eventNameToEventTypeEnum = { + 'StoreRecord': 'EVENTTYPE_CREATE', + 'UpdateRecord': 'EVENTTYPE_UPDATE', + 'DeleteRecord': 'EVENTTYPE_REMOVE' +}; + +function subscribeToDlt(call) { + if (!events) { + call.emit('error', { + code: grpc.status.UNAVAILABLE, + details: "Event listener is not established." + }); + return; + } + + // Add the client to the set of active clients + clients.add(call); + console.log(`Client connected. Total clients: ${clients.size}`); + + // Clean up when the client disconnects + call.on('cancelled', () => { + clients.delete(call); + console.log(`Client disconnected (cancelled). Total clients: ${clients.size}`); + + }); + call.on('error', (err) => { + clients.delete(call); + console.log(`Client disconnected (error: ${err.message}). Total clients: ${clients.size}`); + + }); + call.on('end', () => { + clients.delete(call); + console.log(`Client disconnected (end). Total clients: ${clients.size}`); + + }); + + (async () => { + try { + for await (const event of events) { + const eventPayload = event.payload; + //console.log("Raw event payload:", eventPayload); + const resultJson = utf8Decoder.decode(eventPayload); + const eventJson = JSON.parse(resultJson); + + console.log("Writing event to stream:", eventJson.record_id); + + const eventType = eventNameToEventTypeEnum[event.eventName] || 'EVENTTYPE_UNDEFINED'; + + for (const client of clients) { + const writeSuccessful = client.write({ + event: { + timestamp: { timestamp: Math.floor(Date.now() / 1000) }, + event_type: eventType // Set appropriate event type + }, + record_id: { + domain_uuid: { uuid: eventJson.record_id.domain_uuid.uuid }, + type: eventJson.record_id.type || 'DLTRECORDTYPE_UNDEFINED', + record_uuid: { uuid: eventJson.record_id.record_uuid.uuid } + } + }); + + // Check if the internal buffer is full + if (!writeSuccessful) { + // Wait for the 'drain' event before continuing + await new Promise((resolve) => client.once('drain', resolve)); + } + } + } + + //call.end(); + + } catch (error) { + for (const client of clients) { + client.emit('error', { + code: grpc.status.UNKNOWN, + details: `Error processing event: ${error.message}` + }); + + } + } + })(); +} + +// Placeholder +function getDltStatus(call, callback) { + // Implement status fetching logic here + // Not implemented for simplicity +} + +// Placeholder +function getDltPeers(call, callback) { + // Implement peers fetching logic here + // Not implemented for simplicity +} + +// Add the service to the server +server.addService(dltProto.DltGatewayService.service, { + RecordToDlt: recordToDlt, + GetFromDlt: getFromDlt, + SubscribeToDlt: subscribeToDlt, + GetDltStatus: getDltStatus, + GetDltPeers: getDltPeers, +}); + +// Start the server +const PORT = process.env.GRPC_PORT || '50051'; +server.bindAsync(`0.0.0.0:${PORT}`, grpc.ServerCredentials.createInsecure(), async (error) => { + if (error) { + console.error('Failed to bind server:', error); + return; + } + console.log(`gRPC server running at http://0.0.0.0:${PORT}`); + await initChaincodeConnection(); //Connects to the chaincode and + server; +}); + +// Handle shutdown gracefully +process.on('SIGINT', async () => { + console.log('Shutting down...'); + await closeConnection(); + server.forceShutdown(); +}); \ No newline at end of file diff --git a/src/dlt/gateway/dltApp/src/fabricConnect.ts b/src/dlt/gateway/dltApp/src/fabricConnect.ts new file mode 100644 index 0000000000000000000000000000000000000000..8d9f4146eac3122db34cb9e1d2d40359d9685115 --- /dev/null +++ b/src/dlt/gateway/dltApp/src/fabricConnect.ts @@ -0,0 +1,209 @@ +// 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 * as grpc from '@grpc/grpc-js'; +import { connect, Contract, Identity, Signer, signers, Network, CloseableAsyncIterable, ChaincodeEvent, GatewayError } from '@hyperledger/fabric-gateway'; +import * as crypto from 'crypto'; +import { promises as fs } from 'fs'; +import * as path from 'path'; +import { TextDecoder } from 'util'; +import * as dotenv from 'dotenv'; + +dotenv.config({ path: path.resolve(__dirname, '..', '.env') }); +const channelName = getEnvVar('CHANNEL_NAME'); +const chaincodeName = getEnvVar('CHAINCODE_NAME'); +const mspId = getEnvVar('MSP_ID'); + + +// Path to user private key directory. +const keyDirectoryPath = getEnvVar('KEY_DIRECTORY_PATH'); + +// Path to user certificate directory. +const certDirectoryPath = getEnvVar('CERT_DIRECTORY_PATH'); + +// Path to peer tls certificate. +const tlsCertPath = getEnvVar('TLS_CERT_PATH'); + +// Gateway peer endpoint. +const peerEndpoint = getEnvVar('PEER_ENDPOINT'); + +// Gateway peer SSL host name override. +const peerHostAlias = getEnvVar('PEER_HOST_ALIAS'); + +const utf8Decoder = new TextDecoder(); +const assetId = `asset${Date.now()}`; + +export async function connectToNetwork(): Promise<{ contract: Contract, events: CloseableAsyncIterable, close: () => Promise }> { + + await displayInputParameters(); + + // The gRPC client connection should be shared by all Gateway connections to this endpoint. + + const client = await newGrpcConnection(); + + const gateway = connect({ + client, + identity: await newIdentity(), + signer: await newSigner(), + // Default timeouts for different gRPC calls + evaluateOptions: () => { + return { deadline: Date.now() + 5000 }; // 5 seconds + }, + endorseOptions: () => { + return { deadline: Date.now() + 15000 }; // 15 seconds + }, + submitOptions: () => { + return { deadline: Date.now() + 5000 }; // 5 seconds + }, + commitStatusOptions: () => { + return { deadline: Date.now() + 60000 }; // 1 minute + }, + }); + + let events: CloseableAsyncIterable | undefined; + + + // Get a network instance representing the channel where the smart contract is deployed. + const network = gateway.getNetwork(channelName); + + // Get the smart contract from the network. + const contract = network.getContract(chaincodeName); + + //Listen for events emitted by transactions + //events = await startEventListening(network); + events = await network.getChaincodeEvents(chaincodeName); + + // Initialize the ledger. + await initLedger(contract); + + console.log(Date.now()) + + return { + contract: contract, + events: events, + close: async function () { + if (events) events.close(); + gateway.close(); + client.close(); + } + }; + + +} + +async function newGrpcConnection(): Promise { + const tlsRootCert = await fs.readFile(tlsCertPath); + const tlsCredentials = grpc.credentials.createSsl(tlsRootCert); + return new grpc.Client(peerEndpoint, tlsCredentials, { + 'grpc.ssl_target_name_override': peerHostAlias, + }); +} + +async function newIdentity(): Promise { + //const certPath = await getFirstDirFileName(certDirectoryPath); + //console.log("DEBUG", certDirectoryPath); + const credentials = await fs.readFile(certDirectoryPath); + return { mspId, credentials }; +} + + +async function newSigner(): Promise { + //const keyPath = await getFirstDirFileName(keyDirectoryPath); + //console.log("DEBUG2", keyDirectoryPath); + const privateKeyPem = await fs.readFile(keyDirectoryPath); + const privateKey = crypto.createPrivateKey(privateKeyPem); + return signers.newPrivateKeySigner(privateKey); +} + +/** + * This type of transaction would typically only be run once by an application the first time it was started after its + * initial deployment. A new version of the chaincode deployed later would likely not need to run an "init" function. + */ +async function initLedger(contract: Contract): Promise { + try { + console.log('\n--> Submit Transaction: InitLedger, function activates the chaincode'); + + await contract.submitTransaction('InitLedger'); + + console.log('*** Transaction committed successfully'); + } catch (error) { + console.error('Failed to submit InitLedger transaction:', error); + throw error; + } +} + + + +/** + * getEnvVar() will return the value of an environment variable. + */ +function getEnvVar(varName: string): string { + const value = process.env[varName]; + if (!value) { + throw new Error(`Environment variable ${varName} is not set`); + } + return value; +} + +/** + * displayInputParameters() will print the global scope parameters used by the main driver routine. + */ +async function displayInputParameters(): Promise { + console.log(`channelName: ${channelName}`); + console.log(`chaincodeName: ${chaincodeName}`); + console.log(`mspId: ${mspId}`); + console.log(`keyDirectoryPath: ${keyDirectoryPath}`); + console.log(`certDirectoryPath: ${certDirectoryPath}`); + console.log(`tlsCertPath: ${tlsCertPath}`); + console.log(`peerEndpoint: ${peerEndpoint}`); + console.log(`peerHostAlias: ${peerHostAlias}`); +} + +/** + * startEventListening() will initiate the event listener for chaincode events. + */ +async function startEventListening(network: Network): Promise> { + console.log('\n*** Start chaincode event listening'); + + const events = await network.getChaincodeEvents(chaincodeName); + + void readEvents(events); // Don't await - run asynchronously + return events; +} + +/** + * readEvents() format and display the events as a JSON. + */ +async function readEvents(events: CloseableAsyncIterable): Promise { + try { + for await (const event of events) { + const payload = parseJson(event.payload); + console.log(`\n<-- Chaincode event received: ${event.eventName} -`, payload); + } + } catch (error: unknown) { + // Ignore the read error when events.close() is called explicitly + if (!(error instanceof GatewayError) || error.code !== grpc.status.CANCELLED.valueOf()) { + throw error; + } + } +} + +/** + * parseJson() formats a JSON. + */ +function parseJson(jsonBytes: Uint8Array): unknown { + const json = utf8Decoder.decode(jsonBytes); + return JSON.parse(json); +} + diff --git a/src/dlt/gateway/dltApp/tsconfig.json b/src/dlt/gateway/dltApp/tsconfig.json new file mode 100644 index 0000000000000000000000000000000000000000..34eddef69221adeca4861399d574047a8c9ae6f1 --- /dev/null +++ b/src/dlt/gateway/dltApp/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends":"@tsconfig/node18/tsconfig.json", + "compilerOptions": { + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "outDir": "dist", + "declaration": true, + "sourceMap": true, + "noImplicitAny": true + }, + "include": [ + "./src/**/*" ], + "exclude": [ + "./src/**/*.spec.ts" + ] + } + \ No newline at end of file diff --git a/src/dlt/gateway/keys/.gitignore b/src/dlt/gateway/keys/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..b54a37fc5e1fa51616f1de2ef20651cb28504040 --- /dev/null +++ b/src/dlt/gateway/keys/.gitignore @@ -0,0 +1,3 @@ +ca.crt +cert.pem +priv_sk diff --git a/src/dlt/gateway/keys/place_hls_keys_in_this_folder b/src/dlt/gateway/keys/place_hls_keys_in_this_folder new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/dlt/gateway/samples/sampleTopo.json b/src/dlt/gateway/samples/sampleTopo.json new file mode 100644 index 0000000000000000000000000000000000000000..67115d4be322ed8567688c51a68a95c2b0800138 --- /dev/null +++ b/src/dlt/gateway/samples/sampleTopo.json @@ -0,0 +1,30 @@ +{ + "name": "Network A", + "nodes": [ + { + "id": "node1", + "type": "switch", + "status": "active", + "connections": [ + "node2", + "node3" + ] + }, + { + "id": "node2", + "type": "router", + "status": "inactive", + "connections": [ + "node1" + ] + }, + { + "id": "node3", + "type": "server", + "status": "active", + "connections": [ + "node1" + ] + } + ] +} diff --git a/src/dlt/gateway/samples/topo1.json b/src/dlt/gateway/samples/topo1.json new file mode 100644 index 0000000000000000000000000000000000000000..e4a49981f99339d77538af814365703e463d3db5 --- /dev/null +++ b/src/dlt/gateway/samples/topo1.json @@ -0,0 +1,96 @@ +{ + "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": "DC1"}}, "device_type": "emu-datacenter", "device_drivers": [0], + "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": "eth1", "type": "copper"}, {"uuid": "eth2", "type": "copper"}, {"uuid": "int", "type": "copper"} + ]}}} + ]} + }, + { + "device_id": {"device_uuid": {"uuid": "DC2"}}, "device_type": "emu-datacenter", "device_drivers": [0], + "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": "eth1", "type": "copper"}, {"uuid": "eth2", "type": "copper"}, {"uuid": "int", "type": "copper"} + ]}}} + ]} + }, + { + "device_id": {"device_uuid": {"uuid": "SRL1"}}, "device_type": "packet-router", "device_drivers": [8], + "device_config": {"config_rules": [ + {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "172.100.100.101"}}, + {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "57400"}}, + {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": { + "username": "admin", "password": "NokiaSrl1!", "use_tls": true + }}} + ]} + }, + { + "device_id": {"device_uuid": {"uuid": "SRL2"}}, "device_type": "packet-router", "device_drivers": [8], + "device_config": {"config_rules": [ + {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "172.100.100.102"}}, + {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "57400"}}, + {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": { + "username": "admin", "password": "NokiaSrl1!", "use_tls": true + }}} + ]} + } + ], + "links": [ + { + "link_id": {"link_uuid": {"uuid": "DC1/eth1==SRL1/ethernet-1/2"}}, + "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "DC1"}}, "endpoint_uuid": {"uuid": "eth1"}}, + {"device_id": {"device_uuid": {"uuid": "SRL1"}}, "endpoint_uuid": {"uuid": "ethernet-1/2"}} + ] + }, + { + "link_id": {"link_uuid": {"uuid": "SRL1/ethernet-1/2==DC1/eth1"}}, + "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "SRL1"}}, "endpoint_uuid": {"uuid": "ethernet-1/2"}}, + {"device_id": {"device_uuid": {"uuid": "DC1"}}, "endpoint_uuid": {"uuid": "eth1"}} + ] + }, + + { + "link_id": {"link_uuid": {"uuid": "SRL1/ethernet-1/1==SRL2/ethernet-1/1"}}, + "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "SRL1"}}, "endpoint_uuid": {"uuid": "ethernet-1/1"}}, + {"device_id": {"device_uuid": {"uuid": "SRL2"}}, "endpoint_uuid": {"uuid": "ethernet-1/1"}} + ] + }, + { + "link_id": {"link_uuid": {"uuid": "SRL2/ethernet-1/1==SRL1/ethernet-1/1"}}, + "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "SRL2"}}, "endpoint_uuid": {"uuid": "ethernet-1/1"}}, + {"device_id": {"device_uuid": {"uuid": "SRL1"}}, "endpoint_uuid": {"uuid": "ethernet-1/1"}} + ] + }, + + { + "link_id": {"link_uuid": {"uuid": "DC2/eth1==SRL2/ethernet-1/2"}}, + "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "DC2"}}, "endpoint_uuid": {"uuid": "eth1"}}, + {"device_id": {"device_uuid": {"uuid": "SRL2"}}, "endpoint_uuid": {"uuid": "ethernet-1/2"}} + ] + }, + { + "link_id": {"link_uuid": {"uuid": "SRL2/ethernet-1/2==DC2/eth1"}}, + "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "SRL2"}}, "endpoint_uuid": {"uuid": "ethernet-1/2"}}, + {"device_id": {"device_uuid": {"uuid": "DC2"}}, "endpoint_uuid": {"uuid": "eth1"}} + ] + } + ] +} diff --git a/src/dlt/gateway/samples/topo2.json b/src/dlt/gateway/samples/topo2.json new file mode 100644 index 0000000000000000000000000000000000000000..6885c7d9082bfcb17447252636ea4efb0f500283 --- /dev/null +++ b/src/dlt/gateway/samples/topo2.json @@ -0,0 +1,210 @@ +{ + "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": "R1"}}, "device_type": "emu-packet-router", "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": [101, 102, 201, 202], "type": "copper", "uuid": "1/1"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/2"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/3"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/4"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/5"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/6"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "2/1"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "2/2"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "2/3"} + ]}}} + ]} + }, + { + "device_id": {"device_uuid": {"uuid": "R2"}}, "device_type": "emu-packet-router", "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": [101, 102, 201, 202], "type": "copper", "uuid": "1/1"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/2"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/3"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/4"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/5"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/6"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "2/1"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "2/2"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "2/3"} + ]}}} + ]} + }, + { + "device_id": {"device_uuid": {"uuid": "R3"}}, "device_type": "emu-packet-router", "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": [101, 102, 201, 202], "type": "copper", "uuid": "1/1"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/2"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/3"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/4"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/5"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/6"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "2/1"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "2/2"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "2/3"} + ]}}} + ]} + }, + { + "device_id": {"device_uuid": {"uuid": "R4"}}, "device_type": "emu-packet-router", "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": [101, 102, 201, 202], "type": "copper", "uuid": "1/1"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/2"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/3"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/4"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/5"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/6"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "2/1"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "2/2"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "2/3"} + ]}}} + ]} + }, + { + "device_id": {"device_uuid": {"uuid": "R5"}}, "device_type": "emu-packet-router", "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": [101, 102, 201, 202], "type": "copper", "uuid": "1/1"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/2"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/3"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/4"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/5"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/6"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "2/1"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "2/2"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "2/3"} + ]}}} + ]} + }, + { + "device_id": {"device_uuid": {"uuid": "R6"}}, "device_type": "emu-packet-router", "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": [101, 102, 201, 202], "type": "copper", "uuid": "1/1"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/2"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/3"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/4"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/5"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/6"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "2/1"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "2/2"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "2/3"} + ]}}} + ]} + }, + { + "device_id": {"device_uuid": {"uuid": "R7"}}, "device_type": "emu-packet-router", "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": [101, 102, 201, 202], "type": "copper", "uuid": "1/1"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/2"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "1/3"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "2/1"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "2/2"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "2/3"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "2/4"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "2/5"}, + {"sample_types": [101, 102, 201, 202], "type": "copper", "uuid": "2/6"} + ]}}} + ]} + } + ], + "links": [ + {"link_id": {"link_uuid": {"uuid": "R1==R2"}}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "R1"}}, "endpoint_uuid": {"uuid": "2/1"}}, + {"device_id": {"device_uuid": {"uuid": "R2"}}, "endpoint_uuid": {"uuid": "2/2"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "R1==R6"}}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "R1"}}, "endpoint_uuid": {"uuid": "2/2"}}, + {"device_id": {"device_uuid": {"uuid": "R6"}}, "endpoint_uuid": {"uuid": "2/1"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "R1==R7"}}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "R1"}}, "endpoint_uuid": {"uuid": "2/3"}}, + {"device_id": {"device_uuid": {"uuid": "R7"}}, "endpoint_uuid": {"uuid": "2/1"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "R2==R1"}}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "R2"}}, "endpoint_uuid": {"uuid": "2/2"}}, + {"device_id": {"device_uuid": {"uuid": "R1"}}, "endpoint_uuid": {"uuid": "2/1"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "R2==R3"}}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "R2"}}, "endpoint_uuid": {"uuid": "2/1"}}, + {"device_id": {"device_uuid": {"uuid": "R3"}}, "endpoint_uuid": {"uuid": "2/2"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "R3==R2"}}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "R3"}}, "endpoint_uuid": {"uuid": "2/2"}}, + {"device_id": {"device_uuid": {"uuid": "R2"}}, "endpoint_uuid": {"uuid": "2/1"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "R3==R4"}}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "R3"}}, "endpoint_uuid": {"uuid": "2/1"}}, + {"device_id": {"device_uuid": {"uuid": "R4"}}, "endpoint_uuid": {"uuid": "2/2"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "R3==R7"}}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "R3"}}, "endpoint_uuid": {"uuid": "2/3"}}, + {"device_id": {"device_uuid": {"uuid": "R7"}}, "endpoint_uuid": {"uuid": "2/3"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "R4==R3"}}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "R4"}}, "endpoint_uuid": {"uuid": "2/2"}}, + {"device_id": {"device_uuid": {"uuid": "R3"}}, "endpoint_uuid": {"uuid": "2/1"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "R4==R5"}}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "R4"}}, "endpoint_uuid": {"uuid": "2/1"}}, + {"device_id": {"device_uuid": {"uuid": "R5"}}, "endpoint_uuid": {"uuid": "2/2"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "R5==R4"}}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "R5"}}, "endpoint_uuid": {"uuid": "2/2"}}, + {"device_id": {"device_uuid": {"uuid": "R4"}}, "endpoint_uuid": {"uuid": "2/1"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "R5==R6"}}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "R5"}}, "endpoint_uuid": {"uuid": "2/1"}}, + {"device_id": {"device_uuid": {"uuid": "R6"}}, "endpoint_uuid": {"uuid": "2/2"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "R5==R7"}}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "R5"}}, "endpoint_uuid": {"uuid": "2/3"}}, + {"device_id": {"device_uuid": {"uuid": "R7"}}, "endpoint_uuid": {"uuid": "2/5"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "R6==R1"}}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "R6"}}, "endpoint_uuid": {"uuid": "2/1"}}, + {"device_id": {"device_uuid": {"uuid": "R1"}}, "endpoint_uuid": {"uuid": "2/2"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "R6==R5"}}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "R6"}}, "endpoint_uuid": {"uuid": "2/2"}}, + {"device_id": {"device_uuid": {"uuid": "R5"}}, "endpoint_uuid": {"uuid": "2/1"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "R7==R1"}}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "R7"}}, "endpoint_uuid": {"uuid": "2/1"}}, + {"device_id": {"device_uuid": {"uuid": "R1"}}, "endpoint_uuid": {"uuid": "2/3"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "R7==R3"}}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "R7"}}, "endpoint_uuid": {"uuid": "2/3"}}, + {"device_id": {"device_uuid": {"uuid": "R3"}}, "endpoint_uuid": {"uuid": "2/3"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "R7==R5"}}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "R7"}}, "endpoint_uuid": {"uuid": "2/5"}}, + {"device_id": {"device_uuid": {"uuid": "R5"}}, "endpoint_uuid": {"uuid": "2/3"}} + ]} + ] +} diff --git a/src/dlt/gateway/samples/topo3.json b/src/dlt/gateway/samples/topo3.json new file mode 100644 index 0000000000000000000000000000000000000000..f36fbd7d03a93db61a7233e084f60e7680a54606 --- /dev/null +++ b/src/dlt/gateway/samples/topo3.json @@ -0,0 +1,200 @@ +{ + "contexts": [ + {"context_id": {"context_uuid": {"uuid": "admin"}}, "name": "admin"} + ], + "topologies": [ + {"topology_id": {"topology_uuid": {"uuid": "admin"}, "context_id": {"context_uuid": {"uuid": "admin"}}}, "name": "admin"} + ], + "devices": [ + {"device_id": {"device_uuid": {"uuid": "fr1.fr"}}, "device_type": "emu-packet-router", "device_operational_status": 1, "device_drivers": [0], "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": "client:1", "type": "copper"}, {"uuid": "client:2", "type": "copper"}, {"uuid": "client:3", "type": "copper"}, + {"uuid": "be1.be", "type": "copper"}, {"uuid": "pt1.pt", "type": "copper"}, {"uuid": "uk1.uk", "type": "copper"}, + {"uuid": "es1.es", "type": "copper"}, {"uuid": "it1.it", "type": "copper"} + ]}}} + ]}}, + {"device_id": {"device_uuid": {"uuid": "be1.be"}}, "device_type": "emu-packet-router", "device_operational_status": 1, "device_drivers": [0], "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": "client:1", "type": "copper"}, {"uuid": "client:2", "type": "copper"}, {"uuid": "client:3", "type": "copper"}, + {"uuid": "de1.de", "type": "copper"}, {"uuid": "gr1.gr", "type": "copper"}, {"uuid": "uk1.uk", "type": "copper"}, + {"uuid": "fr1.fr", "type": "copper"}, {"uuid": "it1.it", "type": "copper"} + ]}}} + ]}}, + {"device_id": {"device_uuid": {"uuid": "uk1.uk"}}, "device_type": "emu-packet-router", "device_operational_status": 1, "device_drivers": [0], "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": "client:1", "type": "copper"}, {"uuid": "client:2", "type": "copper"}, {"uuid": "client:3", "type": "copper"}, + {"uuid": "de1.de", "type": "copper"}, {"uuid": "fr1.fr", "type": "copper"}, {"uuid": "be1.be", "type": "copper"}, + {"uuid": "pt1.pt", "type": "copper"} + ]}}} + ]}}, + {"device_id": {"device_uuid": {"uuid": "de1.de"}}, "device_type": "emu-packet-router", "device_operational_status": 1, "device_drivers": [0], "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": "client:1", "type": "copper"}, {"uuid": "client:2", "type": "copper"}, {"uuid": "client:3", "type": "copper"}, + {"uuid": "uk1.uk", "type": "copper"}, {"uuid": "be1.be", "type": "copper"}, {"uuid": "gr1.gr", "type": "copper"} + ]}}} + ]}}, + {"device_id": {"device_uuid": {"uuid": "pt1.pt"}}, "device_type": "emu-packet-router", "device_operational_status": 1, "device_drivers": [0], "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": "client:1", "type": "copper"}, {"uuid": "client:2", "type": "copper"}, {"uuid": "client:3", "type": "copper"}, + {"uuid": "uk1.uk", "type": "copper"}, {"uuid": "fr1.fr", "type": "copper"}, {"uuid": "es1.es", "type": "copper"} + ]}}} + ]}}, + {"device_id": {"device_uuid": {"uuid": "es1.es"}}, "device_type": "emu-packet-router", "device_operational_status": 1, "device_drivers": [0], "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": "client:1", "type": "copper"}, {"uuid": "client:2", "type": "copper"}, {"uuid": "client:3", "type": "copper"}, + {"uuid": "it1.it", "type": "copper"}, {"uuid": "fr1.fr", "type": "copper"}, {"uuid": "pt1.pt", "type": "copper"} + ]}}} + ]}}, + {"device_id": {"device_uuid": {"uuid": "it1.it"}}, "device_type": "emu-packet-router", "device_operational_status": 1, "device_drivers": [0], "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": "client:1", "type": "copper"}, {"uuid": "client:2", "type": "copper"}, {"uuid": "client:3", "type": "copper"}, + {"uuid": "es1.es", "type": "copper"}, {"uuid": "fr1.fr", "type": "copper"}, {"uuid": "be1.be", "type": "copper"}, + {"uuid": "gr1.gr", "type": "copper"} + ]}}} + ]}}, + {"device_id": {"device_uuid": {"uuid": "gr1.gr"}}, "device_type": "emu-packet-router", "device_operational_status": 1, "device_drivers": [0], "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": "client:1", "type": "copper"}, {"uuid": "client:2", "type": "copper"}, {"uuid": "client:3", "type": "copper"}, + {"uuid": "it1.it", "type": "copper"}, {"uuid": "de1.de", "type": "copper"}, {"uuid": "be1.be", "type": "copper"} + ]}}} + ]}} + ], + "links": [ + {"link_id": {"link_uuid": {"uuid": "fr1.fr_be1.be"}}, "attributes": {"total_capacity_gbps": 100, "used_capacity_gbps": 4.804849}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "fr1.fr"}}, "endpoint_uuid": {"uuid": "be1.be"}}, + {"device_id": {"device_uuid": {"uuid": "be1.be"}}, "endpoint_uuid": {"uuid": "fr1.fr"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "uk1.uk_fr1.fr"}}, "attributes": {"total_capacity_gbps": 300, "used_capacity_gbps": 55.182499}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "uk1.uk"}}, "endpoint_uuid": {"uuid": "fr1.fr"}}, + {"device_id": {"device_uuid": {"uuid": "fr1.fr"}}, "endpoint_uuid": {"uuid": "uk1.uk"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "uk1.uk_de1.de"}}, "attributes": {"total_capacity_gbps": 600, "used_capacity_gbps": 199.272255}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "uk1.uk"}}, "endpoint_uuid": {"uuid": "de1.de"}}, + {"device_id": {"device_uuid": {"uuid": "de1.de"}}, "endpoint_uuid": {"uuid": "uk1.uk"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "uk1.uk_be1.be"}}, "attributes": {"total_capacity_gbps": 100, "used_capacity_gbps": 14.334868}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "uk1.uk"}}, "endpoint_uuid": {"uuid": "be1.be"}}, + {"device_id": {"device_uuid": {"uuid": "be1.be"}}, "endpoint_uuid": {"uuid": "uk1.uk"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "pt1.pt_uk1.uk"}}, "attributes": {"total_capacity_gbps": 400, "used_capacity_gbps": 51.415678}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "pt1.pt"}}, "endpoint_uuid": {"uuid": "uk1.uk"}}, + {"device_id": {"device_uuid": {"uuid": "uk1.uk"}}, "endpoint_uuid": {"uuid": "pt1.pt"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "pt1.pt_fr1.fr"}}, "attributes": {"total_capacity_gbps": 100, "used_capacity_gbps": 3.733925}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "pt1.pt"}}, "endpoint_uuid": {"uuid": "fr1.fr"}}, + {"device_id": {"device_uuid": {"uuid": "fr1.fr"}}, "endpoint_uuid": {"uuid": "pt1.pt"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "pt1.pt_es1.es"}}, "attributes": {"total_capacity_gbps": 100, "used_capacity_gbps": 13.32428}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "pt1.pt"}}, "endpoint_uuid": {"uuid": "es1.es"}}, + {"device_id": {"device_uuid": {"uuid": "es1.es"}}, "endpoint_uuid": {"uuid": "pt1.pt"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "it1.it_gr1.gr"}}, "attributes": {"total_capacity_gbps": 800, "used_capacity_gbps": 1.593313}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "it1.it"}}, "endpoint_uuid": {"uuid": "gr1.gr"}}, + {"device_id": {"device_uuid": {"uuid": "gr1.gr"}}, "endpoint_uuid": {"uuid": "it1.it"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "it1.it_fr1.fr"}}, "attributes": {"total_capacity_gbps": 200, "used_capacity_gbps": 98.574706}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "it1.it"}}, "endpoint_uuid": {"uuid": "fr1.fr"}}, + {"device_id": {"device_uuid": {"uuid": "fr1.fr"}}, "endpoint_uuid": {"uuid": "it1.it"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "it1.it_es1.es"}}, "attributes": {"total_capacity_gbps": 300, "used_capacity_gbps": 18.97108}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "it1.it"}}, "endpoint_uuid": {"uuid": "es1.es"}}, + {"device_id": {"device_uuid": {"uuid": "es1.es"}}, "endpoint_uuid": {"uuid": "it1.it"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "it1.it_be1.be"}}, "attributes": {"total_capacity_gbps": 100, "used_capacity_gbps": 10.327772}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "it1.it"}}, "endpoint_uuid": {"uuid": "be1.be"}}, + {"device_id": {"device_uuid": {"uuid": "be1.be"}}, "endpoint_uuid": {"uuid": "it1.it"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "gr1.gr_it1.it"}}, "attributes": {"total_capacity_gbps": 100, "used_capacity_gbps": 7.983659}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "gr1.gr"}}, "endpoint_uuid": {"uuid": "it1.it"}}, + {"device_id": {"device_uuid": {"uuid": "it1.it"}}, "endpoint_uuid": {"uuid": "gr1.gr"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "gr1.gr_de1.de"}}, "attributes": {"total_capacity_gbps": 5000, "used_capacity_gbps": 4930.897339}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "gr1.gr"}}, "endpoint_uuid": {"uuid": "de1.de"}}, + {"device_id": {"device_uuid": {"uuid": "de1.de"}}, "endpoint_uuid": {"uuid": "gr1.gr"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "gr1.gr_be1.be"}}, "attributes": {"total_capacity_gbps": 100, "used_capacity_gbps": 0.895539}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "gr1.gr"}}, "endpoint_uuid": {"uuid": "be1.be"}}, + {"device_id": {"device_uuid": {"uuid": "be1.be"}}, "endpoint_uuid": {"uuid": "gr1.gr"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "fr1.fr_uk1.uk"}}, "attributes": {"total_capacity_gbps": 200, "used_capacity_gbps": 28.144199}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "fr1.fr"}}, "endpoint_uuid": {"uuid": "uk1.uk"}}, + {"device_id": {"device_uuid": {"uuid": "uk1.uk"}}, "endpoint_uuid": {"uuid": "fr1.fr"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "fr1.fr_pt1.pt"}}, "attributes": {"total_capacity_gbps": 100, "used_capacity_gbps": 1.916587}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "fr1.fr"}}, "endpoint_uuid": {"uuid": "pt1.pt"}}, + {"device_id": {"device_uuid": {"uuid": "pt1.pt"}}, "endpoint_uuid": {"uuid": "fr1.fr"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "fr1.fr_it1.it"}}, "attributes": {"total_capacity_gbps": 100, "used_capacity_gbps": 3.330747}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "fr1.fr"}}, "endpoint_uuid": {"uuid": "it1.it"}}, + {"device_id": {"device_uuid": {"uuid": "it1.it"}}, "endpoint_uuid": {"uuid": "fr1.fr"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "fr1.fr_es1.es"}}, "attributes": {"total_capacity_gbps": 100, "used_capacity_gbps": 96.682749}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "fr1.fr"}}, "endpoint_uuid": {"uuid": "es1.es"}}, + {"device_id": {"device_uuid": {"uuid": "es1.es"}}, "endpoint_uuid": {"uuid": "fr1.fr"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "es1.es_pt1.pt"}}, "attributes": {"total_capacity_gbps": 100, "used_capacity_gbps": 5.643483}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "es1.es"}}, "endpoint_uuid": {"uuid": "pt1.pt"}}, + {"device_id": {"device_uuid": {"uuid": "pt1.pt"}}, "endpoint_uuid": {"uuid": "es1.es"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "es1.es_it1.it"}}, "attributes": {"total_capacity_gbps": 100, "used_capacity_gbps": 15.353667}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "es1.es"}}, "endpoint_uuid": {"uuid": "it1.it"}}, + {"device_id": {"device_uuid": {"uuid": "it1.it"}}, "endpoint_uuid": {"uuid": "es1.es"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "es1.es_fr1.fr"}}, "attributes": {"total_capacity_gbps": 100, "used_capacity_gbps": 20.517778}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "es1.es"}}, "endpoint_uuid": {"uuid": "fr1.fr"}}, + {"device_id": {"device_uuid": {"uuid": "fr1.fr"}}, "endpoint_uuid": {"uuid": "es1.es"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "de1.de_uk1.uk"}}, "attributes": {"total_capacity_gbps": 600, "used_capacity_gbps": 239.446965}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "de1.de"}}, "endpoint_uuid": {"uuid": "uk1.uk"}}, + {"device_id": {"device_uuid": {"uuid": "uk1.uk"}}, "endpoint_uuid": {"uuid": "de1.de"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "de1.de_gr1.gr"}}, "attributes": {"total_capacity_gbps": 2100, "used_capacity_gbps": 110.602237}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "de1.de"}}, "endpoint_uuid": {"uuid": "gr1.gr"}}, + {"device_id": {"device_uuid": {"uuid": "gr1.gr"}}, "endpoint_uuid": {"uuid": "de1.de"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "de1.de_be1.be"}}, "attributes": {"total_capacity_gbps": 100, "used_capacity_gbps": 57.709307}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "de1.de"}}, "endpoint_uuid": {"uuid": "be1.be"}}, + {"device_id": {"device_uuid": {"uuid": "be1.be"}}, "endpoint_uuid": {"uuid": "de1.de"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "uk1.uk_pt1.pt"}}, "attributes": {"total_capacity_gbps": 800, "used_capacity_gbps": 652.70225}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "uk1.uk"}}, "endpoint_uuid": {"uuid": "pt1.pt"}}, + {"device_id": {"device_uuid": {"uuid": "pt1.pt"}}, "endpoint_uuid": {"uuid": "uk1.uk"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "be1.be_uk1.uk"}}, "attributes": {"total_capacity_gbps": 200, "used_capacity_gbps": 8.252107}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "be1.be"}}, "endpoint_uuid": {"uuid": "uk1.uk"}}, + {"device_id": {"device_uuid": {"uuid": "uk1.uk"}}, "endpoint_uuid": {"uuid": "be1.be"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "be1.be_it1.it"}}, "attributes": {"total_capacity_gbps": 100, "used_capacity_gbps": 0.357069}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "be1.be"}}, "endpoint_uuid": {"uuid": "it1.it"}}, + {"device_id": {"device_uuid": {"uuid": "it1.it"}}, "endpoint_uuid": {"uuid": "be1.be"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "be1.be_de1.de"}}, "attributes": {"total_capacity_gbps": 100, "used_capacity_gbps": 20.400142}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "be1.be"}}, "endpoint_uuid": {"uuid": "de1.de"}}, + {"device_id": {"device_uuid": {"uuid": "de1.de"}}, "endpoint_uuid": {"uuid": "be1.be"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "be1.be_fr1.fr"}}, "attributes": {"total_capacity_gbps": 100, "used_capacity_gbps": 31.346514}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "be1.be"}}, "endpoint_uuid": {"uuid": "fr1.fr"}}, + {"device_id": {"device_uuid": {"uuid": "fr1.fr"}}, "endpoint_uuid": {"uuid": "be1.be"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "be1.be_gr1.gr"}}, "attributes": {"total_capacity_gbps": 100, "used_capacity_gbps": 0.026822}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "be1.be"}}, "endpoint_uuid": {"uuid": "gr1.gr"}}, + {"device_id": {"device_uuid": {"uuid": "gr1.gr"}}, "endpoint_uuid": {"uuid": "be1.be"}} + ]} + ] +} diff --git a/src/dlt/gateway/samples/topo4.json b/src/dlt/gateway/samples/topo4.json new file mode 100644 index 0000000000000000000000000000000000000000..85bbad55eb8608d2d2a7abad7fffab8fffdae682 --- /dev/null +++ b/src/dlt/gateway/samples/topo4.json @@ -0,0 +1,150 @@ +{ + "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": "T1"}}, "device_type": "optical-transponder", "device_drivers": [11], + "device_operational_status": 1, + "device_endpoints": [ + {"endpoint_id": { + "device_id": {"device_uuid": {"uuid": "T1"}}, "endpoint_uuid": {"uuid": "1"}, + "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} + }} + ], + "device_config": {"config_rules": [ + {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "172.254.253.101"}}, + {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "2022"}}, + {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": { + "username": "admin", "password": "admin", "force_running": false, "hostkey_verify": false, + "look_for_keys": false, "allow_agent": false, "commit_per_rule": false, + "device_params": {"name": "default"}, "manager_params": {"timeout": 120}, + "endpoints": [{"uuid": "1", "type": "optical", "sample_types": [101, 102, 201, 202]}] + }}} + ]} + }, + { + "device_id": {"device_uuid": {"uuid": "T2"}}, "device_type": "optical-transponder", "device_drivers": [11], + "device_operational_status": 1, + "device_endpoints": [ + {"endpoint_id": { + "device_id": {"device_uuid": {"uuid": "T2"}}, "endpoint_uuid": {"uuid": "6"}, + "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} + }} + ], + "device_config": {"config_rules": [ + {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "172.254.253.102"}}, + {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "2022"}}, + {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": { + "username": "admin", "password": "admin", "force_running": false, "hostkey_verify": false, + "look_for_keys": false, "allow_agent": false, "commit_per_rule": false, + "device_params": {"name": "default"}, "manager_params": {"timeout": 120}, + "endpoints": [{"uuid": "6", "type": "optical", "sample_types": [101, 102, 201, 202]}] + }}} + ]} + }, + { + "device_id": {"device_uuid": {"uuid": "R1"}}, "device_type": "optical-roadm", "device_drivers": [11], + "device_operational_status": 1, + "device_endpoints": [ + {"endpoint_id": { + "device_id": {"device_uuid": {"uuid": "R1"}}, "endpoint_uuid": {"uuid": "2"}, + "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} + }}, + {"endpoint_id": { + "device_id": {"device_uuid": {"uuid": "R1"}}, "endpoint_uuid": {"uuid": "3"}, + "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} + }}, + {"endpoint_id": { + "device_id": {"device_uuid": {"uuid": "R1"}}, "endpoint_uuid": {"uuid": "12"}, + "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} + }}, + {"endpoint_id": { + "device_id": {"device_uuid": {"uuid": "R1"}}, "endpoint_uuid": {"uuid": "13"}, + "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} + }} + ], + "device_config": {"config_rules": [ + {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "172.254.253.201"}}, + {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "2022"}}, + {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": { + "username": "admin", "password": "admin", "force_running": false, "hostkey_verify": false, + "look_for_keys": false, "allow_agent": false, "commit_per_rule": false, + "device_params": {"name": "default"}, "manager_params": {"timeout": 120}, + "endpoints": [ + {"sample_types": [101, 102, 201, 202], "type": "optical", "uuid": "2"}, + {"sample_types": [101, 102, 201, 202], "type": "optical", "uuid": "3"}, + {"sample_types": [101, 102, 201, 202], "type": "optical", "uuid": "12"}, + {"sample_types": [101, 102, 201, 202], "type": "optical", "uuid": "13"} + ]} + }}] + } + }, + { + "device_id": {"device_uuid": {"uuid": "R2"}}, "device_type": "optical-roadm", "device_drivers": [11], + "device_operational_status": 1, + "device_endpoints": [ + {"endpoint_id": { + "device_id": {"device_uuid": {"uuid": "R2"}}, "endpoint_uuid": {"uuid": "4"}, + "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} + }}, + {"endpoint_id": { + "device_id": {"device_uuid": {"uuid": "R2"}}, "endpoint_uuid": {"uuid": "5"}, + "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} + }}, + {"endpoint_id": { + "device_id": {"device_uuid": {"uuid": "R2"}}, "endpoint_uuid": {"uuid": "14"}, + "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} + }}, + {"endpoint_id": { + "device_id": {"device_uuid": {"uuid": "R2"}}, "endpoint_uuid": {"uuid": "15"}, + "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} + }} + ], + "device_config": {"config_rules": [ + {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "172.254.253.202"}}, + {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "2022"}}, + {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": { + "username": "admin", "password": "admin", "force_running": false, "hostkey_verify": false, + "look_for_keys": false, "allow_agent": false, "commit_per_rule": false, + "device_params": {"name": "default"}, "manager_params": {"timeout": 120}, + "endpoints": [ + {"sample_types": [101, 102, 201, 202], "type": "optical", "uuid": "4"}, + {"sample_types": [101, 102, 201, 202], "type": "optical", "uuid": "5"}, + {"sample_types": [101, 102, 201, 202], "type": "optical", "uuid": "14"}, + {"sample_types": [101, 102, 201, 202], "type": "optical", "uuid": "15"} + ] + }}} + ]} + } + ], + "links": [ + {"link_id": {"link_uuid": {"uuid": "T1->R1"}}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "T1"}}, "endpoint_uuid": {"uuid": "1"}}, + {"device_id": {"device_uuid": {"uuid": "R1"}}, "endpoint_uuid": {"uuid": "12"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "R1->T1"}}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "R1"}}, "endpoint_uuid": {"uuid": "2"}}, + {"device_id": {"device_uuid": {"uuid": "T1"}}, "endpoint_uuid": {"uuid": "1"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "R1->R2"}}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "R1"}}, "endpoint_uuid": {"uuid": "3"}}, + {"device_id": {"device_uuid": {"uuid": "R2"}}, "endpoint_uuid": {"uuid": "14"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "R2->R1"}}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "R2"}}, "endpoint_uuid": {"uuid": "4"}}, + {"device_id": {"device_uuid": {"uuid": "R1"}}, "endpoint_uuid": {"uuid": "13"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "T2->R2"}}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "T2"}}, "endpoint_uuid": {"uuid": "6"}}, + {"device_id": {"device_uuid": {"uuid": "R2"}}, "endpoint_uuid": {"uuid": "15"}} + ]}, + {"link_id": {"link_uuid": {"uuid": "R2->T2"}}, "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "R2"}}, "endpoint_uuid": {"uuid": "5"}}, + {"device_id": {"device_uuid": {"uuid": "T2"}}, "endpoint_uuid": {"uuid": "6"}} + ]} + ] +} diff --git a/src/dlt/gateway/samples/updatedTopo.json b/src/dlt/gateway/samples/updatedTopo.json new file mode 100644 index 0000000000000000000000000000000000000000..74b084b9d9c48de89ddf6122f46316a74c1a4fca --- /dev/null +++ b/src/dlt/gateway/samples/updatedTopo.json @@ -0,0 +1,17 @@ +{ + "name": "Updated Network", + "nodes": [ + { + "id": "node1", + "type": "switch", + "status": "active", + "connections": ["node2"] + }, + { + "id": "node2", + "type": "router", + "status": "inactive", + "connections": ["node1"] + } + ] +} diff --git a/src/dlt/gateway/tests/perfTest.js b/src/dlt/gateway/tests/perfTest.js new file mode 100644 index 0000000000000000000000000000000000000000..579a8539f4ab86736debc310443e24e80a0bc728 --- /dev/null +++ b/src/dlt/gateway/tests/perfTest.js @@ -0,0 +1,119 @@ +// 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. + +const { connectToNetwork } = require('../dltApp/dist/fabricConnect'); +const fsp = require('fs').promises; +const fs = require('fs'); +const util = require('util'); + +const utf8Decoder = new TextDecoder(); +const topoDirectory = '../samples/'; +const topologies = ['topo1.json', 'topo2.json', 'topo3.json', 'topo4.json']; +//const topologies = ['topo4.json']; + +const iterations = 1000; + +async function main() { + try { + const { contract, close } = await connectToNetwork(); + for (const topoFile of topologies) { + const logFilePath = `./operation_times_${topoFile.split('.')[0]}.txt`; // Creates a separate logfile for each topology + const appendFile = util.promisify(fs.appendFile.bind(fs, logFilePath)); + + console.log(`Starting tests for ${topoFile}`); + for (let i = 0; i < iterations; i++) { + console.log(`Iteration ${i + 1} for ${topoFile}`); + await runBlockchainOperations(contract, topoFile, appendFile); + } + } + await close(); // Clean up the connection + } catch (error) { + console.error('An error occurred:', error); + } +} + +async function runBlockchainOperations(contract, topoFile, appendFile) { + const assetId = `asset${Date.now()}`; + const jsonData = await readJsonData(`${topoDirectory}${topoFile}`); + + // Define operations + const operations = [ + { type: 'STORE', jsonData }, + { type: 'UPDATE', jsonData }, + { type: 'FETCH', jsonData: null }, + { type: 'DELETE', jsonData: null }, + { type: 'FETCH_ALL', jsonData: null } + ]; + + for (let op of operations) { + await executeOperation(contract, op.type, assetId, op.jsonData, appendFile); + } +} + +async function readJsonData(filePath) { + try { + return await fsp.readFile(filePath, 'utf8'); + } catch (error) { + console.error(`Failed to read file: ${filePath}`, error); + return '{}'; + } +} + +async function executeOperation(contract, operationType, assetId, jsonData, appendFile) { + const startTime = process.hrtime.bigint(); + try { + let result; + switch (operationType) { + case 'STORE': + result = await contract.submitTransaction('StoreTopoData', assetId, jsonData); + break; + case 'UPDATE': + result = await contract.submitTransaction('UpdateTopoData', assetId, jsonData); + break; + case 'FETCH': + result = await contract.evaluateTransaction('RetrieveTopoData', assetId); + break; + case 'DELETE': + result = await contract.submitTransaction('DeleteTopo', assetId); + break; + case 'FETCH_ALL': + result = await contract.evaluateTransaction('GetAllInfo'); + break; + } + result = utf8Decoder.decode(result); + const operationTime = recordOperationTime(startTime); + await logOperationTime(operationTime, operationType, appendFile); + console.log(`${operationType} Result:`, result); + } catch (error) { + console.error(`Error during ${operationType}:`, error); + } +} + +function recordOperationTime(startTime) { + const endTime = process.hrtime.bigint(); + const operationTime = Number(endTime - startTime) / 1e6; + return operationTime; +} + +async function logOperationTime(operationTime, operationType, appendFile) { + const timestamp = Date.now(); + const logEntry = `${timestamp} - ${operationType} - Execution time: ${operationTime.toFixed(3)} ms\n`; + try { + await appendFile(logEntry); + } catch (error) { + console, error('Error writing to log file:', error); + } +} + +main(); diff --git a/src/dlt/gateway/tests/rateTest.js b/src/dlt/gateway/tests/rateTest.js new file mode 100644 index 0000000000000000000000000000000000000000..fb0477665794bc51f2550acc50cc1742770ec6a6 --- /dev/null +++ b/src/dlt/gateway/tests/rateTest.js @@ -0,0 +1,85 @@ +// 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. + +const { connectToNetwork } = require('../dltApp/dist/fabricConnect'); +const fs = require('fs'); +const util = require('util'); +const appendFile = util.promisify(fs.appendFile); +const logFilePath = './transaction_times_TPS_TOPO3.txt'; +const utf8Decoder = new TextDecoder(); +const topoDirectory = '../samples/'; + +async function main() { + const { contract, close } = await connectToNetwork(); + try { + const rates = [10, 50, 250, 500]; // Transactions per second + for (let i = 0; i < 1000; i++) { + for (let rate of rates) { + console.log(`Testing at ${rate} TPS`); + await performLoadTest(contract, 1000, rate); + } + } + } finally { + await close(); // Ensure to close the network connection + } +} + +async function performLoadTest(contract, totalTransactions, rate) { + const interval = 1000 / rate; // Calculate interval in milliseconds + let promises = []; + const startTime = Date.now(); + + for (let i = 0; i < totalTransactions; i++) { + // Queue a transaction promise + promises.push(sendTransaction(contract, `asset${Date.now() + i}`)); + + // Process in batches according to the rate + if ((i + 1) % rate === 0 || i === totalTransactions - 1) { + await Promise.all(promises); // Send a batch of transactions + promises = []; // Reset for the next batch + if (i < totalTransactions - 1) { + await new Promise(resolve => setTimeout(resolve, interval)); // Throttle the transaction sending + } + } + } + + const endTime = Date.now(); + const totalTime = endTime - startTime; + const actualRate = totalTransactions / (totalTime / 1000); + console.log(`Total time for ${totalTransactions} transactions at target ${rate} TPS: ${totalTime} ms`); + console.log(`Actual rate achieved: ${actualRate.toFixed(2)} TPS`); + await appendFile(logFilePath, `Target Rate: ${rate} TPS, Total Time: ${totalTime} ms, Actual Rate: ${actualRate.toFixed(2)} TPS\n`); +} + +async function sendTransaction(contract, assetId) { + try { + const jsonData = await readJsonData(`${topoDirectory}topo3.json`); + const result = await contract.submitTransaction('StoreTopoData', assetId, jsonData); + return utf8Decoder.decode(result); + } catch (error) { + console.error('Transaction failed:', error); + return null; + } +} + +async function readJsonData(filePath) { + try { + return await fs.promises.readFile(filePath, 'utf8'); + } catch (error) { + console.error(`Failed to read file: ${filePath}`, error); + return '{}'; + } +} + +main().catch(console.error); diff --git a/src/dlt/gateway/tests/simpleTest.js b/src/dlt/gateway/tests/simpleTest.js new file mode 100644 index 0000000000000000000000000000000000000000..d7605bd73d8dc66cd65139357533220b1695b60c --- /dev/null +++ b/src/dlt/gateway/tests/simpleTest.js @@ -0,0 +1,74 @@ +// 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. + +const { connectToNetwork } = require('../dltApp/dist/fabricConnect'); +const fs = require('fs'); +const util = require('util'); +const appendFile = util.promisify(fs.appendFile); +const logFilePath = './transaction_times_TPS2.txt'; +const utf8Decoder = new TextDecoder(); +const topoDirectory = '../samples/'; + +async function main() { + const { contract, close } = await connectToNetwork(); + try { + console.log('Testing with 8 consecutive transactions'); + await performLoadTest(contract); + } finally { + await close(); // Ensure to close the network connection + } +} + +async function performLoadTest(contract) { + const totalTransactions = 500; + const promises = []; + const startTime = Date.now(); + + for (let i = 0; i < totalTransactions; i++) { + // Queue a transaction promise + promises.push(sendTransaction(contract, `asset${startTime}_${i}`)); + } + + await Promise.all(promises); // Send all transactions + + const endTime = Date.now(); + const totalTime = endTime - startTime; + const actualRate = totalTransactions / (totalTime / 1000); + console.log(`Total time for ${totalTransactions} transactions: ${totalTime} ms`); + console.log(`Actual rate achieved: ${actualRate.toFixed(2)} TPS`); + await appendFile(logFilePath, `Total Transactions: ${totalTransactions}, Total Time: ${totalTime} ms, Actual Rate: ${actualRate.toFixed(2)} TPS\n`); +} + +async function sendTransaction(contract, assetId) { + try { + const jsonData = await readJsonData(`${topoDirectory}topo4.json`); + //const jsonData = JSON.stringify({ data: `Data for ${assetId}`}); + const result = await contract.submitTransaction('StoreTopoData', assetId, jsonData); + return utf8Decoder.decode(result); + } catch (error) { + console.error('Transaction failed:', error); + return null; + } +} + +async function readJsonData(filePath) { + try { + return await fs.promises.readFile(filePath, 'utf8'); + } catch (error) { + console.error(`Failed to read file: ${filePath}`, error); + return '{}'; + } +} + +main().catch(console.error); diff --git a/src/dlt/gateway/tests/testEvents.js b/src/dlt/gateway/tests/testEvents.js new file mode 100644 index 0000000000000000000000000000000000000000..3ef826ebef93b97d2bbd6237742a5f2801fbfe1c --- /dev/null +++ b/src/dlt/gateway/tests/testEvents.js @@ -0,0 +1,66 @@ +// 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. + + +const grpc = require('@grpc/grpc-js'); +const protoLoader = require('@grpc/proto-loader'); +const path = require('path'); + +const PROTO_PATH = path.resolve(__dirname, '../../../../proto/dlt_gateway.proto'); +const packageDefinition = protoLoader.loadSync(PROTO_PATH, { + keepCase: true, + longs: String, + enums: String, + defaults: true, + oneofs: true, +}); +const dltProto = grpc.loadPackageDefinition(packageDefinition).dlt; + +const client = new dltProto.DltGatewayService( + '127.0.0.1:32001', // Replace with TFS server IP_ADDRESS + grpc.credentials.createInsecure() +); + +function subscribeToDlt() { + const request = { + // Define any necessary subscription filters here if applicable + }; + + const call = client.SubscribeToDlt(request); + + call.on('data', (event) => { + console.log('Received event:', event); + }); + + call.on('error', (error) => { + console.error('Error:', error.message); + }); + + call.on('end', () => { + console.log('Stream ended.'); + }); + + // Optionally, you can cancel the subscription after a certain time or condition + setTimeout(() => { + console.log('Cancelling subscription...'); + call.cancel(); + }, 600000); // Cancel after 1 minute for demonstration purposes +} + +function runTests() { + console.log("Testing subscription to DLT events"); + subscribeToDlt(); +} + +runTests(); diff --git a/src/dlt/gateway/tests/testGateway.js b/src/dlt/gateway/tests/testGateway.js new file mode 100644 index 0000000000000000000000000000000000000000..5edfe82fced4115b447e0e9af14322fe4f33b3ae --- /dev/null +++ b/src/dlt/gateway/tests/testGateway.js @@ -0,0 +1,126 @@ +// 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. + + +const grpc = require('@grpc/grpc-js'); +const protoLoader = require('@grpc/proto-loader'); +const path = require('path'); +const fs = require('fs').promises; +const { v4: uuidv4 } = require('uuid'); // Import the UUID library + + +const PROTO_PATH = path.resolve(__dirname, '../../../../proto/dlt_gateway.proto'); +const packageDefinition = protoLoader.loadSync(PROTO_PATH, { + keepCase: true, + longs: String, + enums: String, + defaults: true, + oneofs: true, +}); +const dltProto = grpc.loadPackageDefinition(packageDefinition).dlt; + +const client = new dltProto.DltGatewayService( + '127.0.0.1:32001', // Replace with TFS server IP_ADDRESS + grpc.credentials.createInsecure() +); + +const assetId = `asset-${Date.now()}`; +const domainUuid = `domain-${uuidv4()}`; // Generate a pretty domain UUID + +async function getTopoData(filename) { + try { + const data = await fs.readFile(`../samples/${filename}`, 'utf8'); + return data; + } catch (error) { + console.error('Failed to read file:', filename, error); + return '{}'; // Empty JSON if error + } +} + +async function processTopoData(operation, assetId, jsonFilename) { + let jsonData = '{}'; + if (jsonFilename) { + jsonData = await getTopoData(jsonFilename); + } + + const request = { + record_id: { + domain_uuid: { uuid: domainUuid }, // Replace "domain-uuid" with actual domain UUID if needed + type: 'DLTRECORDTYPE_TOPOLOGY', // Use the appropriate type if needed + record_uuid: { uuid: assetId } + }, + operation, + data_json: jsonData + }; + + return new Promise((resolve, reject) => { + client.RecordToDlt(request, (error, response) => { + if (error) { + console.error('Error:', error.message); + reject(error); + } else { + console.log('Response:', response); + resolve(response); + } + }); + }); +} + +async function getDLTData(assetId) { + + const request = { + domain_uuid: { uuid: domainUuid }, // Replace "domain-uuid" with actual domain UUID if needed + type: 'DLTRECORDTYPE_TOPOLOGY', // Use the appropriate type if needed + record_uuid: { uuid: assetId } + }; + + return new Promise((resolve, reject) => { + client.GetFromDlt(request, (error, response) => { + if (error) { + console.error('Error:', error.message); + reject(error); + } else { + console.log('Response:', response); + resolve(response); + } + }); + }); +} + +async function runTests() { + console.log("Testing Store Operation"); + await processTopoData('DLTRECORDOPERATION_ADD', assetId, 'topo2.json'); + + console.log("Testing Update Operation"); + await processTopoData('DLTRECORDOPERATION_UPDATE', assetId, 'topo3.json'); + + console.log("Testing Fetch Operation"); + await getDLTData(assetId); + + + console.log("Testing Delete Operation"); + await processTopoData('DLTRECORDOPERATION_DELETE', assetId); + + console.log("Testing Fetch All Operation"); + // This part assumes you have a GetAllInfo method implemented in your chaincode and corresponding gRPC service. + // client.GetAllInfo({}, (error, response) => { + // if (error) { + // console.error('Error:', error.message); + // } else { + // console.log('All Data:', response); + // } + // }); +} + +runTests().catch(console.error); diff --git a/src/dlt/mock_blockchain/Dockerfile b/src/dlt/mock_blockchain/Dockerfile index 776904c5f0adf12d4328b8d660794af93f142c77..93bae2f87a0ee8c3a688589fec3745343322cbbc 100644 --- a/src/dlt/mock_blockchain/Dockerfile +++ b/src/dlt/mock_blockchain/Dockerfile @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/dlt/mock_blockchain/__init__.py b/src/dlt/mock_blockchain/__init__.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/dlt/mock_blockchain/__init__.py +++ b/src/dlt/mock_blockchain/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/dlt/mock_blockchain/requirements.in b/src/dlt/mock_blockchain/requirements.in index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/dlt/mock_blockchain/requirements.in +++ b/src/dlt/mock_blockchain/requirements.in @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/dlt/mock_blockchain/service/__init__.py b/src/dlt/mock_blockchain/service/__init__.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/dlt/mock_blockchain/service/__init__.py +++ b/src/dlt/mock_blockchain/service/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/dlt/mock_blockchain/service/__main__.py b/src/dlt/mock_blockchain/service/__main__.py index 8e2662571e6f8c49975687ee29b28c5eac6121c5..6d02d084c3d7017fd9f2c5de555536734227bb9f 100644 --- a/src/dlt/mock_blockchain/service/__main__.py +++ b/src/dlt/mock_blockchain/service/__main__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/dlt/performance/__init__.py b/src/dlt/performance/__init__.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/dlt/performance/__init__.py +++ b/src/dlt/performance/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/dlt/performance/__main__.py b/src/dlt/performance/__main__.py index 1d6c419651bd561b12325dbcb0dba44461f25195..fb57d575a538e7cb8c8d5d17ff78bb3265d30e3e 100644 --- a/src/dlt/performance/__main__.py +++ b/src/dlt/performance/__main__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/dlt/performance/play_ground/Dlt.py b/src/dlt/performance/play_ground/Dlt.py index b2c88954581987f5bb52d2458e4d711820d0d3b6..f0684d3a6ee9c15d40cb3daa1727519bb57cea56 100644 --- a/src/dlt/performance/play_ground/Dlt.py +++ b/src/dlt/performance/play_ground/Dlt.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/dlt/performance/play_ground/Enums.py b/src/dlt/performance/play_ground/Enums.py index 0bbd49403920a773fc4d9edc9e70a6478a4d9867..ad249d0ff87065c001da65dda56e73d2c61d12e2 100644 --- a/src/dlt/performance/play_ground/Enums.py +++ b/src/dlt/performance/play_ground/Enums.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/dlt/performance/play_ground/PerfData.py b/src/dlt/performance/play_ground/PerfData.py index 500e060b417d61b2d4356c221994142da03b5bf5..3221fa946fee25a2174e5430f2dbb9ed9e0b7b31 100644 --- a/src/dlt/performance/play_ground/PerfData.py +++ b/src/dlt/performance/play_ground/PerfData.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/dlt/performance/play_ground/PerfPoint.py b/src/dlt/performance/play_ground/PerfPoint.py index f557299b7cfc44fcc176b3431f3e3c20c7037aa5..2de88cc388f41f3e636c4b21ab5cea115ac36eaf 100644 --- a/src/dlt/performance/play_ground/PerfPoint.py +++ b/src/dlt/performance/play_ground/PerfPoint.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/dlt/performance/play_ground/Random.py b/src/dlt/performance/play_ground/Random.py index bea20f9ae74f3d8b1c01dda1b37cbb5cf5867ab6..64eac7dfef896513fb4a884a6f44e85c61b92ae4 100644 --- a/src/dlt/performance/play_ground/Random.py +++ b/src/dlt/performance/play_ground/Random.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/dlt/performance/play_ground/Settings.py b/src/dlt/performance/play_ground/Settings.py index 9944ebfaad01f7e0a494e462c4712c2f254953a9..a29655d1e9a161b5bddfc85812d4988465f5f780 100644 --- a/src/dlt/performance/play_ground/Settings.py +++ b/src/dlt/performance/play_ground/Settings.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/dlt/performance/play_ground/__init__.py b/src/dlt/performance/play_ground/__init__.py index 68ad14deebd57548815db01d38cec2605e3d2a7d..0ac3642b72a4cae72cd7b7846113dff79cbeb935 100644 --- a/src/dlt/performance/play_ground/__init__.py +++ b/src/dlt/performance/play_ground/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/dlt/performance/run_test.sh b/src/dlt/performance/run_test.sh index 7d23d4e65f570c5d26172c5618bef9a559422ec8..c744ea70353e928a6262806e0b9be1cd6224c52a 100755 --- a/src/dlt/performance/run_test.sh +++ b/src/dlt/performance/run_test.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/e2e_orchestrator/.gitlab-ci.yml b/src/e2e_orchestrator/.gitlab-ci.yml index ecc17f26119e40659d6191e88e26a4000c9d9ada..9e2ec38a1e13e511982ab2e30c3c0077064a0372 100644 --- a/src/e2e_orchestrator/.gitlab-ci.yml +++ b/src/e2e_orchestrator/.gitlab-ci.yml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -13,9 +13,9 @@ # limitations under the License. # build, tag and push the Docker image to the gitlab registry -build e2eorchestrator: +build e2e_orchestrator: variables: - IMAGE_NAME: 'e2eorchestrator' # name of the microservice + IMAGE_NAME: 'e2e_orchestrator' # name of the microservice IMAGE_TAG: 'latest' # tag of the container image (production, development, etc) stage: build before_script: diff --git a/src/e2e_orchestrator/Config.py b/src/e2e_orchestrator/Config.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/e2e_orchestrator/Config.py +++ b/src/e2e_orchestrator/Config.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/e2e_orchestrator/Dockerfile b/src/e2e_orchestrator/Dockerfile index 1ead42a2fd85316b8f8a45aded98f91d861e6b8d..f875663c1abbb8aeaadef6504c00fe6c8cbd28de 100644 --- a/src/e2e_orchestrator/Dockerfile +++ b/src/e2e_orchestrator/Dockerfile @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -77,8 +77,11 @@ RUN pip-compile --quiet --output-file=e2e_orchestrator/requirements.txt e2e_orch RUN python3 -m pip install -r e2e_orchestrator/requirements.txt # Add component files into working directory -COPY --chown=teraflow:teraflow ./src/context/. context -COPY --chown=teraflow:teraflow ./src/e2e_orchestrator/. e2e_orchestrator +COPY src/context/__init__.py context/__init__.py +COPY src/context/client/. context/client/ +COPY src/service/__init__.py service/__init__.py +COPY src/service/client/. service/client/ +COPY src/e2e_orchestrator/. e2e_orchestrator/ # Start the service ENTRYPOINT ["python", "-m", "e2e_orchestrator.service"] diff --git a/src/e2e_orchestrator/__init__.py b/src/e2e_orchestrator/__init__.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/e2e_orchestrator/__init__.py +++ b/src/e2e_orchestrator/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/e2e_orchestrator/client/E2EOrchestratorClient.py b/src/e2e_orchestrator/client/E2EOrchestratorClient.py index e532bb93eb80a3d1120d6de862e5ffb8021b606c..bc8ea8652db3afa82712f9f9ac8637590035a0aa 100644 --- a/src/e2e_orchestrator/client/E2EOrchestratorClient.py +++ b/src/e2e_orchestrator/client/E2EOrchestratorClient.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/e2e_orchestrator/client/__init__.py b/src/e2e_orchestrator/client/__init__.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/e2e_orchestrator/client/__init__.py +++ b/src/e2e_orchestrator/client/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/e2e_orchestrator/requirements.in b/src/e2e_orchestrator/requirements.in index 6553c5a41eb9bcf20b7841d8af1fb84be61a27fc..691d14abd1a75b3ea37ef0ee34103fd05a545310 100644 --- a/src/e2e_orchestrator/requirements.in +++ b/src/e2e_orchestrator/requirements.in @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -12,4 +12,5 @@ # See the License for the specific language governing permissions and # limitations under the License. -networkx \ No newline at end of file +networkx +websockets==12.0 diff --git a/src/e2e_orchestrator/service/E2EOrchestratorService.py b/src/e2e_orchestrator/service/E2EOrchestratorService.py index 2e12ea980da0f90352f2cfba1cf1f39af4594901..9fa7bf4bd82564c4158b5af77c0d69b0b9014289 100644 --- a/src/e2e_orchestrator/service/E2EOrchestratorService.py +++ b/src/e2e_orchestrator/service/E2EOrchestratorService.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/e2e_orchestrator/service/E2EOrchestratorServiceServicerImpl.py b/src/e2e_orchestrator/service/E2EOrchestratorServiceServicerImpl.py index 0ba2eba3390ab13f38ce80affd4faaeba61e1b87..945f3171fbc3949056255a79e366ce17c2fa5c88 100644 --- a/src/e2e_orchestrator/service/E2EOrchestratorServiceServicerImpl.py +++ b/src/e2e_orchestrator/service/E2EOrchestratorServiceServicerImpl.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -12,33 +12,181 @@ # See the License for the specific language governing permissions and # limitations under the License. -import logging - -import networkx as nx -import grpc import copy - -from common.Constants import ServiceNameEnum -from common.method_wrappers.Decorator import (MetricsPool, MetricTypeEnum, safe_and_metered_rpc_method) +from common.method_wrappers.Decorator import MetricsPool, safe_and_metered_rpc_method from common.proto.e2eorchestrator_pb2 import E2EOrchestratorRequest, E2EOrchestratorReply -from common.proto.context_pb2 import Empty, Connection, EndPointId +from common.proto.context_pb2 import ( + Empty, Connection, EndPointId, Link, LinkId, TopologyDetails, Topology, Context, Service, ServiceId, + ServiceTypeEnum, ServiceStatusEnum) from common.proto.e2eorchestrator_pb2_grpc import E2EOrchestratorServiceServicer +from common.Settings import get_setting from context.client.ContextClient import ContextClient +from service.client.ServiceClient import ServiceClient from context.service.database.uuids.EndPoint import endpoint_get_uuid +from context.service.database.uuids.Device import device_get_uuid +from common.proto.vnt_manager_pb2 import VNTSubscriptionRequest +from common.tools.grpc.Tools import grpc_message_to_json_string +import grpc +import json +import logging +import networkx as nx +from threading import Thread +from websockets.sync.client import connect +from websockets.sync.server import serve +from common.Constants import DEFAULT_CONTEXT_NAME LOGGER = logging.getLogger(__name__) +logging.getLogger("websockets").propagate = True METRICS_POOL = MetricsPool("E2EOrchestrator", "RPC") + context_client: ContextClient = ContextClient() +service_client: ServiceClient = ServiceClient() + +EXT_HOST = str(get_setting('WS_IP_HOST')) +EXT_PORT = str(get_setting('WS_IP_PORT')) + +OWN_HOST = str(get_setting('WS_E2E_HOST')) +OWN_PORT = str(get_setting('WS_E2E_PORT')) + + +ALL_HOSTS = "0.0.0.0" + +class SubscriptionServer(Thread): + def __init__(self): + Thread.__init__(self) + + def run(self): + url = "ws://" + EXT_HOST + ":" + EXT_PORT + request = VNTSubscriptionRequest() + request.host = OWN_HOST + request.port = OWN_PORT + try: + LOGGER.debug("Trying to connect to {}".format(url)) + websocket = connect(url) + except Exception as ex: + LOGGER.error('Error connecting to {}'.format(url)) + else: + with websocket: + LOGGER.debug("Connected to {}".format(url)) + send = grpc_message_to_json_string(request) + websocket.send(send) + LOGGER.debug("Sent: {}".format(send)) + try: + message = websocket.recv() + LOGGER.debug("Received message from WebSocket: {}".format(message)) + except Exception as ex: + LOGGER.error('Exception receiving from WebSocket: {}'.format(ex)) + + self._events_server() + + + def _events_server(self): + all_hosts = "0.0.0.0" + + try: + server = serve(self._event_received, all_hosts, int(OWN_PORT)) + except Exception as ex: + LOGGER.error('Error starting server on {}:{}'.format(all_hosts, OWN_PORT)) + LOGGER.error('Exception!: {}'.format(ex)) + else: + with server: + LOGGER.info("Running events server...: {}:{}".format(all_hosts, OWN_PORT)) + server.serve_forever() + + + def _event_received(self, connection): + LOGGER.info("EVENT received!") + for message in connection: + message_json = json.loads(message) + # LOGGER.info("message_json: {}".format(message_json)) + + # Link creation + if 'link_id' in message_json: + link = Link(**message_json) + + service = Service() + service.service_id.service_uuid.uuid = link.link_id.link_uuid.uuid + service.service_id.context_id.context_uuid.uuid = DEFAULT_CONTEXT_NAME + service.service_type = ServiceTypeEnum.SERVICETYPE_OPTICAL_CONNECTIVITY + service.service_status.service_status = ServiceStatusEnum.SERVICESTATUS_PLANNED + service_client.CreateService(service) + + links = context_client.ListLinks(Empty()).links + a_device_uuid = device_get_uuid(link.link_endpoint_ids[0].device_id) + a_endpoint_uuid = endpoint_get_uuid(link.link_endpoint_ids[0])[2] + z_device_uuid = device_get_uuid(link.link_endpoint_ids[1].device_id) + z_endpoint_uuid = endpoint_get_uuid(link.link_endpoint_ids[1])[2] + + for _link in links: + for _endpoint_id in _link.link_endpoint_ids: + if _endpoint_id.device_id.device_uuid.uuid == a_device_uuid and \ + _endpoint_id.endpoint_uuid.uuid == a_endpoint_uuid: + a_ep_id = _endpoint_id + elif _endpoint_id.device_id.device_uuid.uuid == z_device_uuid and \ + _endpoint_id.endpoint_uuid.uuid == z_endpoint_uuid: + z_ep_id = _endpoint_id + + if (not 'a_ep_id' in locals()) or (not 'z_ep_id' in locals()): + error_msg = 'Could not get VNT link endpoints' + LOGGER.error(error_msg) + connection.send(error_msg) + return + + service.service_endpoint_ids.append(copy.deepcopy(a_ep_id)) + service.service_endpoint_ids.append(copy.deepcopy(z_ep_id)) + + # service_client.UpdateService(service) + connection.send(grpc_message_to_json_string(link)) + # Link removal + elif 'link_uuid' in message_json: + LOGGER.info('REMOVING VIRTUAL LINK') + link_id = LinkId(**message_json) + + service_id = ServiceId() + service_id.service_uuid.uuid = link_id.link_uuid.uuid + service_id.context_id.context_uuid.uuid = DEFAULT_CONTEXT_NAME + # service_client.DeleteService(service_id) + connection.send(grpc_message_to_json_string(link_id)) + context_client.RemoveLink(link_id) + # Topology received + else: + LOGGER.info('TOPOLOGY') + topology_details = TopologyDetails(**message_json) + + context = Context() + context.context_id.context_uuid.uuid = topology_details.topology_id.context_id.context_uuid.uuid + context_client.SetContext(context) + + topology = Topology() + topology.topology_id.context_id.CopyFrom(context.context_id) + topology.topology_id.topology_uuid.uuid = topology_details.topology_id.topology_uuid.uuid + context_client.SetTopology(topology) + + for device in topology_details.devices: + context_client.SetDevice(device) + + for link in topology_details.links: + context_client.SetLink(link) + class E2EOrchestratorServiceServicerImpl(E2EOrchestratorServiceServicer): def __init__(self): LOGGER.debug("Creating Servicer...") - LOGGER.debug("Servicer Created") + try: + LOGGER.debug("Requesting subscription") + sub_server = SubscriptionServer() + sub_server.start() + LOGGER.debug("Servicer Created") + + except Exception as ex: + LOGGER.info("Exception!: {}".format(ex)) + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) def Compute(self, request: E2EOrchestratorRequest, context: grpc.ServicerContext) -> E2EOrchestratorReply: endpoints_ids = [] diff --git a/src/e2e_orchestrator/service/__init__.py b/src/e2e_orchestrator/service/__init__.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/e2e_orchestrator/service/__init__.py +++ b/src/e2e_orchestrator/service/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/e2e_orchestrator/service/__main__.py b/src/e2e_orchestrator/service/__main__.py index 5f20fd72f062127e12fc41352e7213fa320d4a94..0854aed2de9c748bab7c4d70f35dc6fd3e2ebfd3 100644 --- a/src/e2e_orchestrator/service/__main__.py +++ b/src/e2e_orchestrator/service/__main__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -43,13 +43,6 @@ def main(): logging.basicConfig(level=log_level) LOGGER = logging.getLogger(__name__) - wait_for_environment_variables( - [ - get_env_var_name(ServiceNameEnum.E2EORCHESTRATOR, ENVVAR_SUFIX_SERVICE_HOST), - get_env_var_name(ServiceNameEnum.E2EORCHESTRATOR, ENVVAR_SUFIX_SERVICE_PORT_GRPC), - ] - ) - signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) diff --git a/src/e2e_orchestrator/tests/__init__.py b/src/e2e_orchestrator/tests/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/e2e_orchestrator/tests/__init__.py +++ b/src/e2e_orchestrator/tests/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/e2e_orchestrator/tests/deploy_specs.sh b/src/e2e_orchestrator/tests/deploy_specs.sh index 9ce234c326b0036986bc685e7abb6a1235e185bc..645c5d6723d927ba80264632e12feb5a6a593470 100755 --- a/src/e2e_orchestrator/tests/deploy_specs.sh +++ b/src/e2e_orchestrator/tests/deploy_specs.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -83,9 +83,6 @@ export CRDB_USERNAME="tfs" # Set the database user's password to be used by Context. export CRDB_PASSWORD="tfs123" -# Set the database name to be used by Context. -export CRDB_DATABASE="tfs" - # 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" diff --git a/src/e2e_orchestrator/tests/functional_tests/Fixtures.py b/src/e2e_orchestrator/tests/functional_tests/Fixtures.py index 7fe3093d082e6400f118ce38a273496036ac6d41..0d6b15aa9724b4abfe81ecec25c20856dbbe3f8e 100644 --- a/src/e2e_orchestrator/tests/functional_tests/Fixtures.py +++ b/src/e2e_orchestrator/tests/functional_tests/Fixtures.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/e2e_orchestrator/tests/functional_tests/Objects.py b/src/e2e_orchestrator/tests/functional_tests/Objects.py index 4cf8334962562e14193fc60654cb4d4c93b221b3..d1bb13089ed0155bbdccf2247a60796016d6cc10 100644 --- a/src/e2e_orchestrator/tests/functional_tests/Objects.py +++ b/src/e2e_orchestrator/tests/functional_tests/Objects.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/e2e_orchestrator/tests/functional_tests/__init__.py b/src/e2e_orchestrator/tests/functional_tests/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/e2e_orchestrator/tests/functional_tests/__init__.py +++ b/src/e2e_orchestrator/tests/functional_tests/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/e2e_orchestrator/tests/functional_tests/test_functional_bootstrap.py b/src/e2e_orchestrator/tests/functional_tests/test_functional_bootstrap.py index 1103977dab86e4145590377f6f57fb56d1c92b84..005b775c5df191304b671c57812935243fee5f0c 100644 --- a/src/e2e_orchestrator/tests/functional_tests/test_functional_bootstrap.py +++ b/src/e2e_orchestrator/tests/functional_tests/test_functional_bootstrap.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/e2e_orchestrator/tests/functional_tests/test_functional_cleanup.py b/src/e2e_orchestrator/tests/functional_tests/test_functional_cleanup.py index 0d4cf66723e1f3dff6168b32ca1d1d5670316f74..970b654a46f7cbd435422c95667d464dbf3df72e 100644 --- a/src/e2e_orchestrator/tests/functional_tests/test_functional_cleanup.py +++ b/src/e2e_orchestrator/tests/functional_tests/test_functional_cleanup.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/e2e_orchestrator/tests/functional_tests/test_functional_compute_path.py b/src/e2e_orchestrator/tests/functional_tests/test_functional_compute_path.py index a4bbb0c06cd6a5bd33727022722166b1fd21de79..2b37784c30fe15178d837b0cb7ea9788a3aea323 100644 --- a/src/e2e_orchestrator/tests/functional_tests/test_functional_compute_path.py +++ b/src/e2e_orchestrator/tests/functional_tests/test_functional_compute_path.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/e2e_orchestrator/tests/redeploy.sh b/src/e2e_orchestrator/tests/redeploy.sh index 830feca00a4f36d1c9264ae315fd9c4854d629c5..1a544b62695a2d2e199617a28d2ec58d051c9fac 100755 --- a/src/e2e_orchestrator/tests/redeploy.sh +++ b/src/e2e_orchestrator/tests/redeploy.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/e2e_orchestrator/tests/run_test_01_bootstrap.sh b/src/e2e_orchestrator/tests/run_test_01_bootstrap.sh index 657acb5c04844a3030bcafa56d5d309d3beb005a..e2a7bbd9381490101e1c44e1ac1a9e6565cc6324 100755 --- a/src/e2e_orchestrator/tests/run_test_01_bootstrap.sh +++ b/src/e2e_orchestrator/tests/run_test_01_bootstrap.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/e2e_orchestrator/tests/run_test_02_compute_path.sh b/src/e2e_orchestrator/tests/run_test_02_compute_path.sh index c6d20bad0da14bd191f607a8abf38241d98d8879..b94c77600892a1ac0cde75e1f4cf1840733ca09b 100755 --- a/src/e2e_orchestrator/tests/run_test_02_compute_path.sh +++ b/src/e2e_orchestrator/tests/run_test_02_compute_path.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/e2e_orchestrator/tests/run_test_03_cleanup.sh b/src/e2e_orchestrator/tests/run_test_03_cleanup.sh index 6ddacf5bdd82bfae66ae1e5558359ea800c7c11b..4aa2ec1aa05276d8297ca4b2753db7a163e8f966 100755 --- a/src/e2e_orchestrator/tests/run_test_03_cleanup.sh +++ b/src/e2e_orchestrator/tests/run_test_03_cleanup.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/e2e_orchestrator/tests/run_tests.sh b/src/e2e_orchestrator/tests/run_tests.sh index 70b5668ffe9517bf653ea49198c212f257a51b3a..a9f4c6d7fab93bf56a5f25643e4083eeffa0afbb 100755 --- a/src/e2e_orchestrator/tests/run_tests.sh +++ b/src/e2e_orchestrator/tests/run_tests.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/forecaster/.gitlab-ci.yml b/src/forecaster/.gitlab-ci.yml index 65ce9467b4ad6b13db0dc0a795eeafe94e6e49b9..74d7f6a1fb71b11cb609213f30259897ee10ffdc 100644 --- a/src/forecaster/.gitlab-ci.yml +++ b/src/forecaster/.gitlab-ci.yml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/forecaster/Config.py b/src/forecaster/Config.py index 84c82dd1513f3a0d16912b2bdec9d149c6da3f68..2319e6ba5f500e294b2e354b4438b6ba6b375835 100644 --- a/src/forecaster/Config.py +++ b/src/forecaster/Config.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/forecaster/Dockerfile b/src/forecaster/Dockerfile index 62c905a15085537da6c8abf01d522405c544ba15..f521eab4028f749465eec231a44cb0ce5322a4e7 100644 --- a/src/forecaster/Dockerfile +++ b/src/forecaster/Dockerfile @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/forecaster/__init__.py b/src/forecaster/__init__.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/forecaster/__init__.py +++ b/src/forecaster/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/forecaster/client/ForecasterClient.py b/src/forecaster/client/ForecasterClient.py index d3ba72778807e584f175e735c3c2c9fef8ac3f54..9bffffc6215b895f47cc138555975a9673555c27 100644 --- a/src/forecaster/client/ForecasterClient.py +++ b/src/forecaster/client/ForecasterClient.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/forecaster/client/__init__.py b/src/forecaster/client/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/forecaster/client/__init__.py +++ b/src/forecaster/client/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/forecaster/requirements.in b/src/forecaster/requirements.in index 6caa5d616f7b7efc525eb5d79a607b4005d0c4ac..08672672a01e3d405ac3bff4d3aa0441e3106ec6 100644 --- a/src/forecaster/requirements.in +++ b/src/forecaster/requirements.in @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -#numpy==1.23.* +numpy<2.0.0 pandas==1.5.* #prophet==1.1.* scikit-learn==1.1.* diff --git a/src/forecaster/service/Forecaster.py b/src/forecaster/service/Forecaster.py index 148bc8bf81e03ef41ec65cff8353f2edcc51c52a..e7930679d6922e315df06a1bcbb519dbf209bc4d 100644 --- a/src/forecaster/service/Forecaster.py +++ b/src/forecaster/service/Forecaster.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/forecaster/service/ForecasterService.py b/src/forecaster/service/ForecasterService.py index c44e2e163bcb1b00f0953a2d9e048347521a0f4a..5f540cdc5bc628ae1a35e5f5ebf47ead276a413c 100644 --- a/src/forecaster/service/ForecasterService.py +++ b/src/forecaster/service/ForecasterService.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/forecaster/service/ForecasterServiceServicerImpl.py b/src/forecaster/service/ForecasterServiceServicerImpl.py index de99054a436aecfd03b5ac3d7dcb7e9ca16d01e3..df592b4df481ddad53cdaaa848d7e020ebd160e5 100644 --- a/src/forecaster/service/ForecasterServiceServicerImpl.py +++ b/src/forecaster/service/ForecasterServiceServicerImpl.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/forecaster/service/KpiManager.py b/src/forecaster/service/KpiManager.py index b9b6618d0950e134410c648601732ed99d8697de..48bc920c775fb29afb5f88543795ee5ad1bb6d31 100644 --- a/src/forecaster/service/KpiManager.py +++ b/src/forecaster/service/KpiManager.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/forecaster/service/__init__.py b/src/forecaster/service/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/forecaster/service/__init__.py +++ b/src/forecaster/service/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/forecaster/service/__main__.py b/src/forecaster/service/__main__.py index 61f9083eaecd6ed4eb24d6e863f41e80194cac76..cf5e881109529560d47d5e1b0ac30333d760e32f 100644 --- a/src/forecaster/service/__main__.py +++ b/src/forecaster/service/__main__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/forecaster/tests/MockService_Dependencies.py b/src/forecaster/tests/MockService_Dependencies.py index 55a28e39405ee2f99806f69cb2cc8f792fd97482..56ef052bdb02caee2e33019d87578e84fe1ff66d 100644 --- a/src/forecaster/tests/MockService_Dependencies.py +++ b/src/forecaster/tests/MockService_Dependencies.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/forecaster/tests/PrepareTestScenario.py b/src/forecaster/tests/PrepareTestScenario.py index 74f6ffed7861b37c4ebf3994d0dba82bff30a02c..71bfa37dbf8bd57b3e2d6945d74eba07aea4cf21 100644 --- a/src/forecaster/tests/PrepareTestScenario.py +++ b/src/forecaster/tests/PrepareTestScenario.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/forecaster/tests/Tools.py b/src/forecaster/tests/Tools.py index ff686750710fe47adbf03adfad91040fb0fb980b..246132140574df581a6011e9e5beca41624db853 100644 --- a/src/forecaster/tests/Tools.py +++ b/src/forecaster/tests/Tools.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/forecaster/tests/__init__.py b/src/forecaster/tests/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/forecaster/tests/__init__.py +++ b/src/forecaster/tests/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/forecaster/tests/data/inject_samples.py b/src/forecaster/tests/data/inject_samples.py index fdc6606c22c6d6e2b9c2720a50be0713527c56e4..06029d095d14d9333128d657875952f6d76d12b6 100644 --- a/src/forecaster/tests/data/inject_samples.py +++ b/src/forecaster/tests/data/inject_samples.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/forecaster/tests/test_unitary.py b/src/forecaster/tests/test_unitary.py index 02a7c3202f3293183680fa1396f1aee3f90fbf42..cf5200cc8c5610988c9464628c74685b5d263a73 100644 --- a/src/forecaster/tests/test_unitary.py +++ b/src/forecaster/tests/test_unitary.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/gitlab-ci.yml_generator.py b/src/gitlab-ci.yml_generator.py index e3d81b7739bbe8bdf39da3dc446beea0bbb69f69..8d8b4fc24f769cb7c76526c31d18b51d61e7acd1 100644 --- a/src/gitlab-ci.yml_generator.py +++ b/src/gitlab-ci.yml_generator.py @@ -1,5 +1,5 @@ #!/usr/bin/python -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/interdomain/.gitlab-ci.yml b/src/interdomain/.gitlab-ci.yml index 775df616f781912909a13a65f8b6a74b6d8e5942..00bf83739ef2dda31dc7cd6abdbce30b39cc49e3 100644 --- a/src/interdomain/.gitlab-ci.yml +++ b/src/interdomain/.gitlab-ci.yml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/interdomain/Config.py b/src/interdomain/Config.py index 918f60d79d51ee8f9fe3875b630de2c373c01a5a..fff1c96a5dc38dfc01dd85218eda7f9ba00da393 100644 --- a/src/interdomain/Config.py +++ b/src/interdomain/Config.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -15,6 +15,7 @@ from common.Settings import get_setting SETTING_NAME_TOPOLOGY_ABSTRACTOR = 'TOPOLOGY_ABSTRACTOR' +SETTING_NAME_DLT_INTEGRATION = 'DLT_INTEGRATION' TRUE_VALUES = {'Y', 'YES', 'TRUE', 'T', 'E', 'ENABLE', 'ENABLED'} def is_topology_abstractor_enabled() -> bool: @@ -22,3 +23,9 @@ def is_topology_abstractor_enabled() -> bool: if is_enabled is None: return False str_is_enabled = str(is_enabled).upper() return str_is_enabled in TRUE_VALUES + +def is_dlt_enabled() -> bool: + is_enabled = get_setting(SETTING_NAME_DLT_INTEGRATION, default=None) + if is_enabled is None: return False + str_is_enabled = str(is_enabled).upper() + return str_is_enabled in TRUE_VALUES diff --git a/src/interdomain/Dockerfile b/src/interdomain/Dockerfile index 39a68987cc288f8547e3f8d944718a0b9cbf19c2..57f55007aac4aa62d86b3c7317b142a531f58fd0 100644 --- a/src/interdomain/Dockerfile +++ b/src/interdomain/Dockerfile @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/interdomain/__init__.py b/src/interdomain/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/interdomain/__init__.py +++ b/src/interdomain/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/interdomain/client/InterdomainClient.py b/src/interdomain/client/InterdomainClient.py index a829c293ebbe035ef59c8f09369b8d1c0b850e38..ae78c2078a9bcf025ea90e87495ed48541e0c604 100644 --- a/src/interdomain/client/InterdomainClient.py +++ b/src/interdomain/client/InterdomainClient.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/interdomain/client/__init__.py b/src/interdomain/client/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/interdomain/client/__init__.py +++ b/src/interdomain/client/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/interdomain/requirements.in b/src/interdomain/requirements.in index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/interdomain/requirements.in +++ b/src/interdomain/requirements.in @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/interdomain/service/InterdomainService.py b/src/interdomain/service/InterdomainService.py index 12d651e2f0e76d05e0683be74f48808d71993bdb..f71a8e422a1f239bfdb9752dd9fff3857d0f17b3 100644 --- a/src/interdomain/service/InterdomainService.py +++ b/src/interdomain/service/InterdomainService.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/interdomain/service/InterdomainServiceServicerImpl.py b/src/interdomain/service/InterdomainServiceServicerImpl.py index 54878be2ed70fa834692b85ce27337d61160948b..3aafdc4d1b12cbe7246bc0e452db451ee808c24e 100644 --- a/src/interdomain/service/InterdomainServiceServicerImpl.py +++ b/src/interdomain/service/InterdomainServiceServicerImpl.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -34,7 +34,7 @@ from common.tools.object_factory.Device import json_device_id from common.tools.object_factory.EndPoint import json_endpoint_id from common.tools.object_factory.Topology import json_topology_id from context.client.ContextClient import ContextClient -from dlt.connector.client.DltConnectorClient import DltConnectorClient +from dlt.connector.client.DltConnectorClientAsync import DltConnectorClientAsync from pathcomp.frontend.client.PathCompClient import PathCompClient from service.client.ServiceClient import ServiceClient from slice.client.SliceClient import SliceClient @@ -88,7 +88,7 @@ class InterdomainServiceServicerImpl(InterdomainServiceServicer): ]) if len(env_vars) == 2: # DLT available - dlt_connector_client = DltConnectorClient() + dlt_connector_client = DltConnectorClientAsync() dlt_connector_client.connect() else: dlt_connector_client = None diff --git a/src/interdomain/service/RemoteDomainClients.py b/src/interdomain/service/RemoteDomainClients.py index b69b9f545869d2b9d8721ca109cb0cbe4ad1f8ea..93fd1bb25184a12be5f1291961d299df0084a658 100644 --- a/src/interdomain/service/RemoteDomainClients.py +++ b/src/interdomain/service/RemoteDomainClients.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/interdomain/service/Tools.py b/src/interdomain/service/Tools.py index a43279236d9e5f7ac5c9985c8c93fb2e421fff69..9e4e7b67c6182786cd89e0f5698273bd6d66bdf3 100644 --- a/src/interdomain/service/Tools.py +++ b/src/interdomain/service/Tools.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/interdomain/service/__init__.py b/src/interdomain/service/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/interdomain/service/__init__.py +++ b/src/interdomain/service/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/interdomain/service/__main__.py b/src/interdomain/service/__main__.py index c0497bd2902080f8b967ba50ce370a4c9b711689..39cd2cbc74d60394d4e7967a97a149ed9470a8dd 100644 --- a/src/interdomain/service/__main__.py +++ b/src/interdomain/service/__main__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -18,8 +18,9 @@ from common.Constants import ServiceNameEnum from common.Settings import ( ENVVAR_SUFIX_SERVICE_HOST, ENVVAR_SUFIX_SERVICE_PORT_GRPC, get_env_var_name, get_log_level, get_metrics_port, wait_for_environment_variables) -from interdomain.Config import is_topology_abstractor_enabled +from interdomain.Config import is_dlt_enabled, is_topology_abstractor_enabled from .topology_abstractor.TopologyAbstractor import TopologyAbstractor +from .topology_abstractor.DltRecorder import DLTRecorder from .InterdomainService import InterdomainService from .RemoteDomainClients import RemoteDomainClients @@ -69,12 +70,21 @@ def main(): topology_abstractor = TopologyAbstractor() topology_abstractor.start() + # Subscribe to Context Events + dlt_enabled = is_dlt_enabled() + if dlt_enabled: + LOGGER.info('Starting DLT functionality...') + dlt_recorder = DLTRecorder() + dlt_recorder.start() + # Wait for Ctrl+C or termination signal while not terminate.wait(timeout=1.0): pass LOGGER.info('Terminating...') if topology_abstractor_enabled: topology_abstractor.stop() + if dlt_enabled: + dlt_recorder.stop() grpc_service.stop() remote_domain_clients.stop() diff --git a/src/interdomain/service/_old_code/InterdomainServiceServicerImpl.py b/src/interdomain/service/_old_code/InterdomainServiceServicerImpl.py index 6b0fe9468497bb11818bbf4a5451e74c53b9b6d5..004d00de5c054c6353465e74800eeb104dbed8cb 100644 --- a/src/interdomain/service/_old_code/InterdomainServiceServicerImpl.py +++ b/src/interdomain/service/_old_code/InterdomainServiceServicerImpl.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/interdomain/service/topology_abstractor/AbstractDevice.py b/src/interdomain/service/topology_abstractor/AbstractDevice.py index 38523130cba2c657a2d3b0b61897269f6b7f5cb1..e5768911e0ab1033d32dc2a1dcfbeaa4e8f761dd 100644 --- a/src/interdomain/service/topology_abstractor/AbstractDevice.py +++ b/src/interdomain/service/topology_abstractor/AbstractDevice.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/interdomain/service/topology_abstractor/AbstractLink.py b/src/interdomain/service/topology_abstractor/AbstractLink.py index f336d0ad90cc531c1d6b50efb33036088f63f190..25c0d537dea8e523be3736e534d1c40e5a5e1af1 100644 --- a/src/interdomain/service/topology_abstractor/AbstractLink.py +++ b/src/interdomain/service/topology_abstractor/AbstractLink.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/interdomain/service/topology_abstractor/DltRecordSender.py b/src/interdomain/service/topology_abstractor/DltRecordSender.py index a504fe01b4e5755b880b76114c60d28f186f3f6f..f2a8b0a489837da9261d7c8aa9436a260f7994dd 100644 --- a/src/interdomain/service/topology_abstractor/DltRecordSender.py +++ b/src/interdomain/service/topology_abstractor/DltRecordSender.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -12,24 +12,28 @@ # See the License for the specific language governing permissions and # limitations under the License. -import logging -from typing import Dict, List, Optional, Tuple +import asyncio, logging +from typing import Dict, List, Tuple from common.proto.context_pb2 import Device, Link, Service, Slice, TopologyId from common.proto.dlt_connector_pb2 import DltDeviceId, DltLinkId, DltServiceId, DltSliceId from context.client.ContextClient import ContextClient -from dlt.connector.client.DltConnectorClient import DltConnectorClient -from .Types import DltRecordTypes +from dlt.connector.client.DltConnectorClientAsync import DltConnectorClientAsync LOGGER = logging.getLogger(__name__) class DltRecordSender: - def __init__(self, context_client : ContextClient, dlt_connector_client : Optional[DltConnectorClient]) -> None: + def __init__(self, context_client : ContextClient) -> None: self.context_client = context_client - self.dlt_connector_client = dlt_connector_client + LOGGER.debug('Creating Servicer...') + self.dlt_connector_client = DltConnectorClientAsync() + LOGGER.debug('Servicer Created') self.dlt_record_uuids : List[str] = list() - self.dlt_record_uuid_to_data : Dict[str, Tuple[TopologyId, DltRecordTypes]] = dict() + self.dlt_record_uuid_to_data : Dict[str, Tuple[TopologyId, object]] = dict() - def _add_record(self, record_uuid : str, data : Tuple[TopologyId, DltRecordTypes]) -> None: + async def initialize(self): + await self.dlt_connector_client.connect() + + def _add_record(self, record_uuid : str, data : Tuple[TopologyId, object]) -> None: if record_uuid in self.dlt_record_uuid_to_data: return self.dlt_record_uuid_to_data[record_uuid] = data self.dlt_record_uuids.append(record_uuid) @@ -60,36 +64,45 @@ class DltRecordSender: record_uuid = '{:s}:slice:{:s}/{:s}'.format(topology_uuid, context_uuid, slice_uuid) self._add_record(record_uuid, (topology_id, slice_)) - def commit(self) -> None: + async def commit(self) -> None: + if not self.dlt_connector_client: + LOGGER.error('DLT Connector Client is None, cannot commit records.') + return + + tasks = [] # List to hold all the async tasks + for dlt_record_uuid in self.dlt_record_uuids: - topology_id,dlt_record = self.dlt_record_uuid_to_data[dlt_record_uuid] + topology_id, dlt_record = self.dlt_record_uuid_to_data[dlt_record_uuid] if isinstance(dlt_record, Device): - device_id = self.context_client.SetDevice(dlt_record) + device_id = dlt_record.device_id if self.dlt_connector_client is None: continue dlt_device_id = DltDeviceId() dlt_device_id.topology_id.CopyFrom(topology_id) # pylint: disable=no-member dlt_device_id.device_id.CopyFrom(device_id) # pylint: disable=no-member - self.dlt_connector_client.RecordDevice(dlt_device_id) + tasks.append(self.dlt_connector_client.RecordDevice(dlt_device_id)) elif isinstance(dlt_record, Link): - link_id = self.context_client.SetLink(dlt_record) + link_id = dlt_record.link_id if self.dlt_connector_client is None: continue dlt_link_id = DltLinkId() dlt_link_id.topology_id.CopyFrom(topology_id) # pylint: disable=no-member dlt_link_id.link_id.CopyFrom(link_id) # pylint: disable=no-member - self.dlt_connector_client.RecordLink(dlt_link_id) + tasks.append(self.dlt_connector_client.RecordLink(dlt_link_id)) elif isinstance(dlt_record, Service): - service_id = self.context_client.SetService(dlt_record) + service_id = dlt_record.service_id if self.dlt_connector_client is None: continue dlt_service_id = DltServiceId() dlt_service_id.topology_id.CopyFrom(topology_id) # pylint: disable=no-member dlt_service_id.service_id.CopyFrom(service_id) # pylint: disable=no-member - self.dlt_connector_client.RecordService(dlt_service_id) + tasks.append(self.dlt_connector_client.RecordService(dlt_service_id)) elif isinstance(dlt_record, Slice): - slice_id = self.context_client.SetSlice(dlt_record) + slice_id = dlt_record.slice_id if self.dlt_connector_client is None: continue dlt_slice_id = DltSliceId() dlt_slice_id.topology_id.CopyFrom(topology_id) # pylint: disable=no-member dlt_slice_id.slice_id.CopyFrom(slice_id) # pylint: disable=no-member - self.dlt_connector_client.RecordSlice(dlt_slice_id) + tasks.append(self.dlt_connector_client.RecordSlice(dlt_slice_id)) else: - LOGGER.error('Unsupported Record({:s})'.format(str(dlt_record))) + LOGGER.error(f'Unsupported Record({str(dlt_record)})') + + if tasks: + await asyncio.gather(*tasks) # Run all the tasks concurrently diff --git a/src/interdomain/service/topology_abstractor/DltRecorder.py b/src/interdomain/service/topology_abstractor/DltRecorder.py new file mode 100644 index 0000000000000000000000000000000000000000..6f89a447da9a4e8c949c9c50e9f7c8956c60cbd5 --- /dev/null +++ b/src/interdomain/service/topology_abstractor/DltRecorder.py @@ -0,0 +1,206 @@ +# 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, threading, asyncio, time +from typing import Dict, Optional +from common.Constants import DEFAULT_CONTEXT_NAME, DEFAULT_TOPOLOGY_NAME, INTERDOMAIN_TOPOLOGY_NAME +from common.proto.context_pb2 import ( + ContextEvent, ContextId, DeviceEvent, DeviceId, LinkId, LinkEvent, TopologyId, TopologyEvent +) +from common.tools.context_queries.Context import create_context +from common.tools.grpc.Tools import grpc_message_to_json_string +from common.tools.object_factory.Context import json_context_id +from common.tools.object_factory.Topology import json_topology_id +from context.client.ContextClient import ContextClient +from context.client.EventsCollector import EventsCollector +from .DltRecordSender import DltRecordSender +from .Types import EventTypes + +LOGGER = logging.getLogger(__name__) + +ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME)) +INTERDOMAIN_TOPOLOGY_ID = TopologyId(**json_topology_id(INTERDOMAIN_TOPOLOGY_NAME, context_id=ADMIN_CONTEXT_ID)) + + +class DLTRecorder(threading.Thread): + def __init__(self) -> None: + super().__init__(daemon=True) + self.terminate = threading.Event() + self.context_client = ContextClient() + self.context_event_collector = EventsCollector(self.context_client) + self.topology_cache: Dict[str, TopologyId] = {} + + # Queues for each event type + self.create_event_queue = asyncio.Queue() + self.update_event_queue = asyncio.Queue() + self.remove_event_queue = asyncio.Queue() + + def stop(self): + self.terminate.set() + + def run(self) -> None: + asyncio.run(self._run()) + + async def _run(self) -> None: + self.context_client.connect() + create_context(self.context_client, DEFAULT_CONTEXT_NAME) + #self.create_topologies() + self.context_event_collector.start() + + batch_timeout = 1 # Time in seconds to wait before processing whatever tasks are available + last_task_time = time.time() + + while not self.terminate.is_set(): + event = self.context_event_collector.get_event(timeout=0.1) + if event: + LOGGER.info('Received Event({:s})...'.format(grpc_message_to_json_string(event))) + + # Prioritize the event based on its type + if event.event.event_type == 1: # CREATE + await self.create_event_queue.put(event) + elif event.event.event_type == 2: # UPDATE + await self.update_event_queue.put(event) + elif event.event.event_type == 3: # REMOVE + await self.remove_event_queue.put(event) + + # Check if it's time to process the tasks or if we have enough tasks + current_time = time.time() + if current_time - last_task_time >= batch_timeout: + await self.process_events() + last_task_time = current_time # Reset the timer after processing + + self.context_event_collector.stop() + self.context_client.close() + + async def process_events(self): + # Process CREATE events first + await self.process_queue(self.create_event_queue) + # Then process UPDATE events + await self.process_queue(self.update_event_queue) + # Finally, process REMOVE events + await self.process_queue(self.remove_event_queue) + + async def process_queue(self, queue : asyncio.Queue): + tasks = [] + while not queue.empty(): + event = await queue.get() + LOGGER.info('Processing Event({:s}) from queue...'.format(grpc_message_to_json_string(event))) + task = asyncio.create_task(self.update_record(event)) + tasks.append(task) + + # Execute tasks concurrently + if tasks: + try: + await asyncio.gather(*tasks) + except Exception as e: + LOGGER.error(f"Error while processing tasks: {e}") + + async def update_record(self, event : EventTypes) -> None: + dlt_record_sender = DltRecordSender(self.context_client) + await dlt_record_sender.initialize() # Ensure DltRecordSender is initialized asynchronously + LOGGER.debug('STARTING processing event: {:s}'.format(grpc_message_to_json_string(event))) + + if isinstance(event, ContextEvent): + LOGGER.debug('Processing ContextEvent({:s})'.format(grpc_message_to_json_string(event))) + LOGGER.warning('Ignoring ContextEvent({:s})'.format(grpc_message_to_json_string(event))) + + elif isinstance(event, TopologyEvent): + LOGGER.debug('Processing TopologyEvent({:s})'.format(grpc_message_to_json_string(event))) + self.process_topology_event(event, dlt_record_sender) + + elif isinstance(event, DeviceEvent): + LOGGER.debug('Processing DeviceEvent ASYNC({:s})'.format(grpc_message_to_json_string(event))) + self.process_device_event(event, dlt_record_sender) + + elif isinstance(event, LinkEvent): + LOGGER.debug('Processing LinkEvent({:s})'.format(grpc_message_to_json_string(event))) + self.process_link_event(event, dlt_record_sender) + + else: + LOGGER.warning('Unsupported Event({:s})'.format(grpc_message_to_json_string(event))) + + await dlt_record_sender.commit() + #await asyncio.sleep(2) # Simulates processing time + LOGGER.debug('Finished processing event: {:s}'.format(grpc_message_to_json_string(event))) + + + def process_topology_event(self, event : TopologyEvent, dlt_record_sender : DltRecordSender) -> None: + topology_id = event.topology_id + topology_uuid = topology_id.topology_uuid.uuid + context_id = topology_id.context_id + context_uuid = context_id.context_uuid.uuid + topology_uuids = {DEFAULT_TOPOLOGY_NAME, INTERDOMAIN_TOPOLOGY_NAME} + + context = self.context_client.GetContext(context_id) + context_name = context.name + + topology_details = self.context_client.GetTopologyDetails(topology_id) + topology_name = topology_details.name + + self.topology_cache[topology_uuid] = topology_id + + LOGGER.debug('TOPOLOGY Details({:s})'.format(grpc_message_to_json_string(topology_details))) + + if ((context_uuid == DEFAULT_CONTEXT_NAME) or (context_name == DEFAULT_CONTEXT_NAME)) and \ + (topology_uuid not in topology_uuids) and (topology_name not in topology_uuids): + LOGGER.debug('DEVICES({:s})'.format(grpc_message_to_json_string(topology_details.devices))) + for device in topology_details.devices: + LOGGER.debug('DEVICE_INFO_TOPO({:s})'.format(grpc_message_to_json_string(device))) + dlt_record_sender.add_device(topology_id, device) + + for link in topology_details.links: + dlt_record_sender.add_link(topology_id, link) + + else: + MSG = 'Ignoring ({:s}/{:s})({:s}/{:s}) TopologyEvent({:s})' + args = context_uuid, context_name, topology_uuid, topology_name, grpc_message_to_json_string(event) + LOGGER.warning(MSG.format(*args)) + + def find_topology_for_device(self, device_id : DeviceId) -> Optional[TopologyId]: + for topology_uuid, topology_id in self.topology_cache.items(): + details = self.context_client.GetTopologyDetails(topology_id) + for device in details.devices: + if device.device_id == device_id: + return topology_id + return None + + def find_topology_for_link(self, link_id : LinkId) -> Optional[TopologyId]: + for topology_uuid, topology_id in self.topology_cache.items(): + details = self.context_client.GetTopologyDetails(topology_id) + for link in details.links: + if link.link_id == link_id: + return topology_id + return None + + def process_device_event(self, event : DeviceEvent, dlt_record_sender : DltRecordSender) -> None: + device_id = event.device_id + device = self.context_client.GetDevice(device_id) + topology_id = self.find_topology_for_device(device_id) + if topology_id: + LOGGER.debug('DEVICE_INFO({:s}), DEVICE_ID ({:s})'.format( + str(device.device_id.device_uuid.uuid), + grpc_message_to_json_string(device_id) + )) + dlt_record_sender.add_device(topology_id, device) + else: + LOGGER.warning("Topology not found for device {:s}".format(str(device_id.device_uuid.uuid))) + + def process_link_event(self, event: LinkEvent, dlt_record_sender: DltRecordSender) -> None: + link_id = event.link_id + link = self.context_client.GetLink(link_id) + topology_id = self.find_topology_for_link(link_id) + if topology_id: + dlt_record_sender.add_link(topology_id, link) + else: + LOGGER.warning("Topology not found for link {:s}".format(str(link_id.link_uuid.uuid))) diff --git a/src/interdomain/service/topology_abstractor/TopologyAbstractor.py b/src/interdomain/service/topology_abstractor/TopologyAbstractor.py index 2a6ef5e32ca5a973ab833e7e5d0429f65df9812b..68cd52cab01745dfe90f832ff5195b57271edba5 100644 --- a/src/interdomain/service/topology_abstractor/TopologyAbstractor.py +++ b/src/interdomain/service/topology_abstractor/TopologyAbstractor.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/interdomain/service/topology_abstractor/Types.py b/src/interdomain/service/topology_abstractor/Types.py index 5cb3220eb2d6c0204b1271b6881676b8563904fd..8e2132a8c55361c718e0a26e6f47797e9ec4ff69 100644 --- a/src/interdomain/service/topology_abstractor/Types.py +++ b/src/interdomain/service/topology_abstractor/Types.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/interdomain/service/topology_abstractor/__init__.py b/src/interdomain/service/topology_abstractor/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/interdomain/service/topology_abstractor/__init__.py +++ b/src/interdomain/service/topology_abstractor/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/interdomain/tests/__init__.py b/src/interdomain/tests/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/interdomain/tests/__init__.py +++ b/src/interdomain/tests/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/interdomain/tests/old_tests.py b/src/interdomain/tests/old_tests.py index d5bb962629e5456320e18136976423531fa1d9da..3eb3b09e1c75294a104cab3065f89e92ddb5cb71 100644 --- a/src/interdomain/tests/old_tests.py +++ b/src/interdomain/tests/old_tests.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/interdomain/tests/test_compute_domains.py b/src/interdomain/tests/test_compute_domains.py index 81cc2b6708c7f0f91de48e064f6fde833f55f797..8455881dab3d7c5c3909e9853c01d0fe7bc51e78 100644 --- a/src/interdomain/tests/test_compute_domains.py +++ b/src/interdomain/tests/test_compute_domains.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/interdomain/tests/test_topology_abstractor.py b/src/interdomain/tests/test_topology_abstractor.py index 43f470a38e12f7eefaad5346504eb9c0b67d1201..b325f7a8eccee6cca2cd105f9c9282b590462568 100644 --- a/src/interdomain/tests/test_topology_abstractor.py +++ b/src/interdomain/tests/test_topology_abstractor.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/kpi_manager/.gitlab-ci.yml b/src/kpi_manager/.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..fb917601ab27cb4dda491b27572be80426d6c3de --- /dev/null +++ b/src/kpi_manager/.gitlab-ci.yml @@ -0,0 +1,132 @@ +# 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. + +# Build, tag, and push the Docker image to the GitLab Docker registry +build kpi-manager: + variables: + IMAGE_NAME: 'kpi_manager' # name of the microservice + IMAGE_TAG: 'latest' # tag of the container image (production, development, etc) + stage: build + before_script: + - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY + script: + - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . + - docker tag "$IMAGE_NAME:$IMAGE_TAG" "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG" + - docker push "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG" + after_script: + - docker images --filter="dangling=true" --quiet | xargs -r docker rmi + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)' + - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"' + - changes: + - src/common/**/*.py + - proto/*.proto + - src/$IMAGE_NAME/**/*.{py,in,yml} + - src/$IMAGE_NAME/Dockerfile + - src/$IMAGE_NAME/tests/*.py + - manifests/${IMAGE_NAME}service.yaml + - .gitlab-ci.yml + +# Apply unit test to the component +unit_test kpi-manager: + variables: + IMAGE_NAME: 'kpi_manager' # name of the microservice + IMAGE_TAG: 'latest' # tag of the container image (production, development, etc) + stage: unit_test + needs: + - build kpi-manager + before_script: + - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY + - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create -d bridge teraflowbridge; fi + - if docker container ls | grep crdb; then docker rm -f crdb; else echo "CockroachDB container is not in the system"; fi + - if docker volume ls | grep crdb; then docker volume rm -f crdb; else echo "CockroachDB volume is not in the system"; fi + - if docker container ls | grep $IMAGE_NAME; then docker rm -f $IMAGE_NAME; else echo "$IMAGE_NAME container is not in the system"; fi + - docker container prune -f + script: + - docker pull "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG" + - docker pull "cockroachdb/cockroach:latest-v22.2" + - docker volume create crdb + - > + docker run --name crdb -d --network=teraflowbridge -p 26257:26257 -p 8080:8080 + --env COCKROACH_DATABASE=tfs_test --env COCKROACH_USER=tfs --env COCKROACH_PASSWORD=tfs123 + --volume "crdb:/cockroach/cockroach-data" + cockroachdb/cockroach:latest-v22.2 start-single-node + - echo "Waiting for initialization..." + - while ! docker logs crdb 2>&1 | grep -q 'finished creating default user \"tfs\"'; do sleep 1; done + - docker logs crdb + - docker ps -a + - CRDB_ADDRESS=$(docker inspect crdb --format "{{.NetworkSettings.Networks.teraflowbridge.IPAddress}}") + - echo $CRDB_ADDRESS + - > + docker run --name $IMAGE_NAME -d -p 30010:30010 + --env "CRDB_URI=cockroachdb://tfs:tfs123@${CRDB_ADDRESS}:26257/tfs_test?sslmode=require" + --volume "$PWD/src/$IMAGE_NAME/tests:/opt/results" + --network=teraflowbridge + $CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG + - docker ps -a + - sleep 5 + - docker logs $IMAGE_NAME + - > + docker exec -i $IMAGE_NAME bash -c + "coverage run -m pytest --log-level=INFO --verbose --junitxml=/opt/results/${IMAGE_NAME}_report.xml $IMAGE_NAME/tests/test_*.py" + - docker exec -i $IMAGE_NAME bash -c "coverage report --include='${IMAGE_NAME}/*' --show-missing" + coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/' + after_script: + - docker rm -f $IMAGE_NAME crdb + - docker volume rm -f crdb + - docker network rm teraflowbridge + - docker volume prune --force + - docker image prune --force + 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/$IMAGE_NAME/**/*.{py,in,yml} + - src/$IMAGE_NAME/Dockerfile + - src/$IMAGE_NAME/tests/*.py + - src/$IMAGE_NAME/tests/Dockerfile + - manifests/${IMAGE_NAME}service.yaml + - .gitlab-ci.yml + artifacts: + when: always + reports: + junit: src/$IMAGE_NAME/tests/${IMAGE_NAME}_report.xml + +## Deployment of the service in Kubernetes Cluster +#deploy context: +# variables: +# IMAGE_NAME: 'context' # name of the microservice +# IMAGE_TAG: 'latest' # tag of the container image (production, development, etc) +# stage: deploy +# needs: +# - unit test context +# # - integ_test execute +# script: +# - 'sed -i "s/$IMAGE_NAME:.*/$IMAGE_NAME:$IMAGE_TAG/" manifests/${IMAGE_NAME}service.yaml' +# - kubectl version +# - kubectl get all +# - kubectl apply -f "manifests/${IMAGE_NAME}service.yaml" +# - kubectl get all +# # environment: +# # name: test +# # url: https://example.com +# # kubernetes: +# # namespace: test +# rules: +# - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)' +# when: manual +# - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"' +# when: manual diff --git a/src/kpi_manager/Dockerfile b/src/kpi_manager/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..12455e4c96d8cf343b33decc9ccd5bac4e01ed7a --- /dev/null +++ b/src/kpi_manager/Dockerfile @@ -0,0 +1,68 @@ +# 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 + +# Download the gRPC health probe +RUN GRPC_HEALTH_PROBE_VERSION=v0.2.0 && \ + wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \ + chmod +x /bin/grpc_health_probe + +# 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/kpi_manager +WORKDIR /var/teraflow/kpi_manager +COPY src/kpi_manager/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/kpi_manager/. kpi_manager/ + +# Start the service +ENTRYPOINT ["python", "-m", "kpi_manager.service"] diff --git a/src/kpi_manager/README.md b/src/kpi_manager/README.md new file mode 100644 index 0000000000000000000000000000000000000000..0496f0945047950e9fbd4e5caf78a79a15051cf6 --- /dev/null +++ b/src/kpi_manager/README.md @@ -0,0 +1,18 @@ +# How to locally run and test KPI manager micro-service + +### Pre-requisets +Ensure the following requirements are met before executing the KPI management service: + +1. A virtual enviornment exist with all the required packages listed in ["requirements.in"](https://labs.etsi.org/rep/tfs/controller/-/blob/develop/src/kpi_manager/requirements.in) sucessfully installed. +2. Verify the creation of required database and table. The +[KPI DB test](https://labs.etsi.org/rep/tfs/controller/-/blob/develop/src/kpi_manager/tests/test_kpi_db.py) python file lists the functions to create tables and the database. + +### Messages format templates +The ["messages"](https://labs.etsi.org/rep/tfs/controller/-/blob/develop/src/kpi_manager/tests/test_messages.py) python file contains templates for creating gRPC messages. + +### Flow of execution (Kpi Manager Service functions) +1. Call the gRPC method `SetKpiDescriptor(KpiDescriptor)->KpiId` to add the KpiDescriptor to the `Kpi` DB. `KpiDescriptor` and `KpiId` are both pre-defined gRPC message types. + +2. Call `GetKpiDescriptor(KpiId)->KpiDescriptor` to read the `KpiDescriptor` from the DB and `DeleteKpiDescriptor(KpiId)` to delete the `KpiDescriptor` from the DB. + +3. Call `SelectKpiDescriptor(KpiDescriptorFilter)->KpiDescriptorList` to get all `KpiDescriptor` objects that matches filter criteria. `KpiDescriptorFilter` and `KpiDescriptorList` are pre-defined gRPC message types. diff --git a/src/kpi_manager/__init__.py b/src/kpi_manager/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..53d5157f750bfb085125cbd33faff1cec5924e14 --- /dev/null +++ b/src/kpi_manager/__init__.py @@ -0,0 +1,14 @@ +# 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. + diff --git a/src/kpi_manager/client/KpiManagerClient.py b/src/kpi_manager/client/KpiManagerClient.py new file mode 100755 index 0000000000000000000000000000000000000000..b0a6ec1f577b84fc30568f4f9384b4c6cdc13741 --- /dev/null +++ b/src/kpi_manager/client/KpiManagerClient.py @@ -0,0 +1,77 @@ +# 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 grpc, logging +from common.Constants import ServiceNameEnum +from common.Settings import get_service_host, get_service_port_grpc + +from common.proto.context_pb2 import Empty +from common.tools.grpc.Tools import grpc_message_to_json_string +from common.tools.client.RetryDecorator import retry, delay_exponential +from common.proto.kpi_manager_pb2_grpc import KpiManagerServiceStub +from common.proto.kpi_manager_pb2 import KpiId, KpiDescriptor, KpiDescriptorFilter, KpiDescriptorList + +LOGGER = logging.getLogger(__name__) +MAX_RETRIES = 10 +DELAY_FUNCTION = delay_exponential(initial=0.01, increment=2.0, maximum=5.0) +RETRY_DECORATOR = retry(max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect') + +class KpiManagerClient: + def __init__(self, host=None, port=None): + if not host: host = get_service_host(ServiceNameEnum.KPIMANAGER) + if not port: port = get_service_port_grpc(ServiceNameEnum.KPIMANAGER) + self.endpoint = '{:s}:{:s}'.format(str(host), str(port)) + LOGGER.debug('Creating channel to {:s}...'.format(str(self.endpoint))) + + self.channel = None + self.stub = None + self.connect() + LOGGER.debug('Channel created') + + def connect(self): + self.channel = grpc.insecure_channel(self.endpoint) + self.stub = KpiManagerServiceStub(self.channel) + + def close(self): + if self.channel is not None: self.channel.close() + self.channel = None + self.stub = None + + @RETRY_DECORATOR + def SetKpiDescriptor(self, request : KpiDescriptor) -> KpiId: + LOGGER.debug('SetKpiDescriptor: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.SetKpiDescriptor(request) + LOGGER.debug('SetKpiDescriptor result: {:s}'.format(grpc_message_to_json_string(response))) + return response + + @RETRY_DECORATOR + def DeleteKpiDescriptor(self,request : KpiId) -> Empty: + LOGGER.debug('DeleteKpiDescriptor: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.DeleteKpiDescriptor(request) + LOGGER.debug('DeleteKpiDescriptor result: {:s}'.format(grpc_message_to_json_string(response))) + return response + + @RETRY_DECORATOR + def GetKpiDescriptor(self, request : KpiId) -> KpiDescriptor: + LOGGER.debug('GetKpiDescriptor: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.GetKpiDescriptor(request) + LOGGER.debug('GetKpiDescriptor result: {:s}'.format(grpc_message_to_json_string(response))) + return response + + @RETRY_DECORATOR + def SelectKpiDescriptor(self, filter : KpiDescriptorFilter) -> KpiDescriptorList: + LOGGER.debug('SelectKpiDescriptor: {:s}'.format(grpc_message_to_json_string(filter))) + response = self.stub.SelectKpiDescriptor(filter) + LOGGER.debug('SelectKpiDescriptor result: {:s}'.format(grpc_message_to_json_string(response))) + return response diff --git a/src/kpi_manager/client/__init__.py b/src/kpi_manager/client/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..130d6c80b35b1551a38d67bdd32f74de026f4c9a --- /dev/null +++ b/src/kpi_manager/client/__init__.py @@ -0,0 +1,14 @@ +# 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. + diff --git a/src/kpi_manager/database/KpiDB.py b/src/kpi_manager/database/KpiDB.py new file mode 100644 index 0000000000000000000000000000000000000000..75b52798a93700d724000b0db8ef445a4eed2ffc --- /dev/null +++ b/src/kpi_manager/database/KpiDB.py @@ -0,0 +1,66 @@ +# 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 +from common.method_wrappers.Decorator import MetricsPool +from common.tools.database.GenericDatabase import Database +from common.method_wrappers.ServiceExceptions import OperationFailedException + +LOGGER = logging.getLogger(__name__) +METRICS_POOL = MetricsPool('KpiManager', 'Database') + +class KpiDB(Database): + def __init__(self, model) -> None: + LOGGER.info('Init KpiManagerService') + super().__init__(model) + + def select_with_filter(self, model, filter_object): + """ + Generic method to create filters dynamically based on filter_object attributes. + params: model: SQLAlchemy model class to query. + filter_object: Object that contains filtering criteria as attributes. + return: SQLAlchemy session, query and Model + """ + session = self.Session() + try: + query = session.query(model) + # Apply filters based on the filter_object + if filter_object.kpi_id: + query = query.filter(model.kpi_id.in_([k.kpi_id.uuid for k in filter_object.kpi_id])) + + if filter_object.kpi_sample_type: + query = query.filter(model.kpi_sample_type.in_(filter_object.kpi_sample_type)) + + if filter_object.device_id: + query = query.filter(model.device_id.in_([d.device_uuid.uuid for d in filter_object.device_id])) + + if filter_object.endpoint_id: + query = query.filter(model.endpoint_id.in_([e.endpoint_uuid.uuid for e in filter_object.endpoint_id])) + + if filter_object.service_id: + query = query.filter(model.service_id.in_([s.service_uuid.uuid for s in filter_object.service_id])) + + if filter_object.slice_id: + query = query.filter(model.slice_id.in_([s.slice_uuid.uuid for s in filter_object.slice_id])) + + if filter_object.connection_id: + query = query.filter(model.connection_id.in_([c.connection_uuid.uuid for c in filter_object.connection_id])) + + if filter_object.link_id: + query = query.filter(model.link_id.in_([l.link_uuid.uuid for l in filter_object.link_id])) + except Exception as e: + LOGGER.error(f"Error creating filter of {model.__name__} table. ERROR: {e}") + raise OperationFailedException ("CreateKpiDescriptorFilter", extra_details=["unable to create the filter {:}".format(e)]) + + return super().select_with_filter(query, session, model) diff --git a/src/kpi_manager/database/KpiModel.py b/src/kpi_manager/database/KpiModel.py new file mode 100644 index 0000000000000000000000000000000000000000..0e3161baadbd37a32b01d2508fb318a06c26cc7b --- /dev/null +++ b/src/kpi_manager/database/KpiModel.py @@ -0,0 +1,84 @@ +# 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 +from sqlalchemy.dialects.postgresql import UUID +from sqlalchemy import Column, Integer, String, Text +from sqlalchemy.orm import registry +from common.proto.kpi_manager_pb2 import KpiDescriptor + +logging.basicConfig(level=logging.INFO) +LOGGER = logging.getLogger(__name__) + +# Create a base class for declarative models +Base = registry().generate_base() + +class Kpi(Base): + __tablename__ = 'kpi' + + kpi_id = Column(UUID(as_uuid=False), primary_key=True) + kpi_description = Column(Text , nullable=False) + kpi_sample_type = Column(Integer , nullable=False) + device_id = Column(String , nullable=False) + endpoint_id = Column(String , nullable=False) + service_id = Column(String , nullable=False) + slice_id = Column(String , nullable=False) + connection_id = Column(String , nullable=False) + link_id = Column(String , nullable=False) + + # helps in logging the information + def __repr__(self): + return (f"") + + @classmethod + def convert_KpiDescriptor_to_row(cls, request): + """ + Create an instance of Kpi from a request object. + Args: request: The request object containing the data. + Returns: An instance of Kpi initialized with data from the request. + """ + return cls( + kpi_id = request.kpi_id.kpi_id.uuid, + kpi_description = request.kpi_description, + kpi_sample_type = request.kpi_sample_type, + device_id = request.device_id.device_uuid.uuid, + endpoint_id = request.endpoint_id.endpoint_uuid.uuid, + service_id = request.service_id.service_uuid.uuid, + slice_id = request.slice_id.slice_uuid.uuid, + connection_id = request.connection_id.connection_uuid.uuid, + link_id = request.link_id.link_uuid.uuid + ) + + @classmethod + def convert_row_to_KpiDescriptor(cls, row): + """ + Create and return a dictionary representation of a Kpi instance. + Args: row: The Kpi instance (row) containing the data. + Returns: KpiDescriptor object + """ + response = KpiDescriptor() + response.kpi_id.kpi_id.uuid = row.kpi_id + response.kpi_description = row.kpi_description + response.kpi_sample_type = row.kpi_sample_type + response.service_id.service_uuid.uuid = row.service_id + response.device_id.device_uuid.uuid = row.device_id + response.slice_id.slice_uuid.uuid = row.slice_id + response.endpoint_id.endpoint_uuid.uuid = row.endpoint_id + response.connection_id.connection_uuid.uuid = row.connection_id + response.link_id.link_uuid.uuid = row.link_id + return response diff --git a/src/kpi_manager/database/__init__.py b/src/kpi_manager/database/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..53d5157f750bfb085125cbd33faff1cec5924e14 --- /dev/null +++ b/src/kpi_manager/database/__init__.py @@ -0,0 +1,14 @@ +# 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. + diff --git a/src/kpi_manager/requirements.in b/src/kpi_manager/requirements.in new file mode 100644 index 0000000000000000000000000000000000000000..264e08853708a78c5321b8e85377a595eca1078a --- /dev/null +++ b/src/kpi_manager/requirements.in @@ -0,0 +1,18 @@ +# 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. + +psycopg2-binary==2.9.* +SQLAlchemy==1.4.* +sqlalchemy-cockroachdb==1.4.* +SQLAlchemy-Utils==0.38.* diff --git a/src/kpi_manager/service/KpiManagerService.py b/src/kpi_manager/service/KpiManagerService.py new file mode 100755 index 0000000000000000000000000000000000000000..6da00ab5e61876461ffef5675e211c9359d71c71 --- /dev/null +++ b/src/kpi_manager/service/KpiManagerService.py @@ -0,0 +1,29 @@ +# 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 common.Constants import ServiceNameEnum +from common.Settings import get_service_port_grpc +from common.tools.service.GenericGrpcService import GenericGrpcService +from common.proto.kpi_manager_pb2_grpc import add_KpiManagerServiceServicer_to_server +from kpi_manager.service.KpiManagerServiceServicerImpl import KpiManagerServiceServicerImpl + + +class KpiManagerService(GenericGrpcService): + def __init__(self, cls_name: str = __name__) -> None: + port = get_service_port_grpc(ServiceNameEnum.KPIMANAGER) + super().__init__(port, cls_name=cls_name) + self.kpiManagerService_servicer = KpiManagerServiceServicerImpl() + + def install_servicers(self): + add_KpiManagerServiceServicer_to_server(self.kpiManagerService_servicer, self.server) diff --git a/src/kpi_manager/service/KpiManagerServiceServicerImpl.py b/src/kpi_manager/service/KpiManagerServiceServicerImpl.py new file mode 100644 index 0000000000000000000000000000000000000000..1dd214506339ccb257830c28fc43d0d80cdee9e7 --- /dev/null +++ b/src/kpi_manager/service/KpiManagerServiceServicerImpl.py @@ -0,0 +1,95 @@ +# 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, grpc +from common.method_wrappers.Decorator import MetricsPool, safe_and_metered_rpc_method +from common.proto.context_pb2 import Empty +from common.proto.kpi_manager_pb2_grpc import KpiManagerServiceServicer +from common.proto.kpi_manager_pb2 import KpiId, KpiDescriptor, KpiDescriptorFilter, KpiDescriptorList +# from kpi_manager.database.Kpi_DB import KpiDB +from kpi_manager.database.KpiDB import KpiDB +from kpi_manager.database.KpiModel import Kpi as KpiModel + +LOGGER = logging.getLogger(__name__) +METRICS_POOL = MetricsPool('KpiManager', 'NBIgRPC') + +class KpiManagerServiceServicerImpl(KpiManagerServiceServicer): + def __init__(self): + LOGGER.info('Init KpiManagerService') + self.kpi_db_obj = KpiDB(KpiModel) + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def SetKpiDescriptor(self, request: KpiDescriptor, grpc_context: grpc.ServicerContext # type: ignore + ) -> KpiId: # type: ignore + response = KpiId() + LOGGER.info("Received gRPC message object: {:}".format(request)) + try: + kpi_to_insert = KpiModel.convert_KpiDescriptor_to_row(request) + if(self.kpi_db_obj.add_row_to_db(kpi_to_insert)): + response.kpi_id.uuid = request.kpi_id.kpi_id.uuid + # LOGGER.info("Added Row: {:}".format(response)) + return response + except Exception as e: + LOGGER.info("Unable to create KpiModel class object. {:}".format(e)) + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def GetKpiDescriptor(self, request: KpiId, grpc_context: grpc.ServicerContext # type: ignore + ) -> KpiDescriptor: # type: ignore + response = KpiDescriptor() + print("--> Received gRPC message object: {:}".format(request)) + LOGGER.info("Received gRPC message object: {:}".format(request)) + try: + kpi_id_to_search = request.kpi_id.uuid + row = self.kpi_db_obj.search_db_row_by_id(KpiModel, 'kpi_id', kpi_id_to_search) + if row is None: + print ('No matching row found for kpi id: {:}'.format(kpi_id_to_search)) + LOGGER.info('No matching row found kpi id: {:}'.format(kpi_id_to_search)) + return Empty() + else: + response = KpiModel.convert_row_to_KpiDescriptor(row) + return response + except Exception as e: + print ('Unable to search kpi id. {:}'.format(e)) + LOGGER.info('Unable to search kpi id. {:}'.format(e)) + raise e + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def DeleteKpiDescriptor(self, request: KpiId, grpc_context: grpc.ServicerContext # type: ignore + ) -> Empty: # type: ignore + LOGGER.info("Received gRPC message object: {:}".format(request)) + try: + kpi_id_to_search = request.kpi_id.uuid + self.kpi_db_obj.delete_db_row_by_id(KpiModel, 'kpi_id', kpi_id_to_search) + except Exception as e: + LOGGER.info('Unable to search kpi id. {:}'.format(e)) + finally: + return Empty() + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def SelectKpiDescriptor(self, filter: KpiDescriptorFilter, grpc_context: grpc.ServicerContext # type: ignore + ) -> KpiDescriptorList: # type: ignore + LOGGER.info("Received gRPC message object: {:}".format(filter)) + response = KpiDescriptorList() + try: + rows = self.kpi_db_obj.select_with_filter(KpiModel, filter) + except Exception as e: + LOGGER.info('Unable to apply filter on kpi descriptor. {:}'.format(e)) + try: + for row in rows: + kpiDescriptor_obj = KpiModel.convert_row_to_KpiDescriptor(row) + response.kpi_descriptor_list.append(kpiDescriptor_obj) + return response + except Exception as e: + LOGGER.info('Unable to process filter response {:}'.format(e)) diff --git a/src/kpi_manager/service/__init__.py b/src/kpi_manager/service/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..53d5157f750bfb085125cbd33faff1cec5924e14 --- /dev/null +++ b/src/kpi_manager/service/__init__.py @@ -0,0 +1,14 @@ +# 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. + diff --git a/src/kpi_manager/service/__main__.py b/src/kpi_manager/service/__main__.py new file mode 100644 index 0000000000000000000000000000000000000000..7da2a77916995dca7c5d137085eeaaabcaa50cc6 --- /dev/null +++ b/src/kpi_manager/service/__main__.py @@ -0,0 +1,59 @@ +# 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, signal, sys, threading +from common.Settings import get_log_level +from .KpiManagerService import KpiManagerService + +from kpi_manager.database.KpiModel import Kpi as Model +from common.tools.database.GenericDatabase import Database + +terminate = threading.Event() +LOGGER = None + +def signal_handler(signal, frame): # pylint: disable=redefined-outer-name + LOGGER.warning('Terminate signal received') + terminate.set() + +def main(): + global LOGGER # pylint: disable=global-statement + + log_level = get_log_level() + logging.basicConfig(level=log_level) + LOGGER = logging.getLogger(__name__) + + signal.signal(signal.SIGINT, signal_handler) + signal.signal(signal.SIGTERM, signal_handler) + + LOGGER.debug('Starting...') + + # To create DB + kpiDBobj = Database(Model) + kpiDBobj.create_database() + kpiDBobj.create_tables() + + grpc_service = KpiManagerService() + grpc_service.start() + + # Wait for Ctrl+C or termination signal + while not terminate.wait(timeout=1.0): pass + + LOGGER.debug('Terminating...') + grpc_service.stop() + + LOGGER.debug('Bye') + return 0 + +if __name__ == '__main__': + sys.exit(main()) diff --git a/src/kpi_manager/tests/__init__.py b/src/kpi_manager/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..53d5157f750bfb085125cbd33faff1cec5924e14 --- /dev/null +++ b/src/kpi_manager/tests/__init__.py @@ -0,0 +1,14 @@ +# 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. + diff --git a/src/kpi_manager/tests/test_kpi_db.py b/src/kpi_manager/tests/test_kpi_db.py new file mode 100644 index 0000000000000000000000000000000000000000..be1feab088ff685e8d5f933fc3546c5934c09d9b --- /dev/null +++ b/src/kpi_manager/tests/test_kpi_db.py @@ -0,0 +1,29 @@ +# 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 +from kpi_manager.database.KpiDB import KpiDB +from kpi_manager.database.KpiModel import Kpi as KpiModel + +LOGGER = logging.getLogger(__name__) + +def test_verify_databases_and_Tables(): + LOGGER.info('>>> test_verify_Tables : START <<< ') + kpiDBobj = KpiDB(KpiModel) + # kpiDBobj.drop_database() + # kpiDBobj.verify_tables() + kpiDBobj.create_database() + kpiDBobj.create_tables() + kpiDBobj.verify_tables() diff --git a/src/kpi_manager/tests/test_kpi_manager.py b/src/kpi_manager/tests/test_kpi_manager.py new file mode 100755 index 0000000000000000000000000000000000000000..fedc3f94cee5be08301cd6241779966f3111f9c1 --- /dev/null +++ b/src/kpi_manager/tests/test_kpi_manager.py @@ -0,0 +1,140 @@ +# 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 os, pytest +import logging +from typing import Union + +from common.proto.context_pb2 import Empty +from common.Constants import ServiceNameEnum +from common.Settings import ( + ENVVAR_SUFIX_SERVICE_HOST, ENVVAR_SUFIX_SERVICE_PORT_GRPC, get_env_var_name, get_service_port_grpc) +from common.tests.MockServicerImpl_Context import MockServicerImpl_Context +from common.proto.context_pb2_grpc import add_ContextServiceServicer_to_server + +from common.proto.kpi_manager_pb2 import KpiId, KpiDescriptor, KpiDescriptorFilter, KpiDescriptorList +from common.tools.service.GenericGrpcService import GenericGrpcService + +from kpi_manager.tests.test_messages import create_kpi_descriptor_request, create_kpi_filter_request, create_kpi_descriptor_request_a +from kpi_manager.service.KpiManagerService import KpiManagerService +from kpi_manager.client.KpiManagerClient import KpiManagerClient +from kpi_manager.tests.test_messages import create_kpi_descriptor_request +from kpi_manager.tests.test_messages import create_kpi_id_request + +########################### +# Tests Setup +########################### + +LOCAL_HOST = '127.0.0.1' + +KPIMANAGER_SERVICE_PORT = get_service_port_grpc(ServiceNameEnum.KPIMANAGER) # type: ignore +os.environ[get_env_var_name(ServiceNameEnum.KPIMANAGER, ENVVAR_SUFIX_SERVICE_HOST )] = str(LOCAL_HOST) +os.environ[get_env_var_name(ServiceNameEnum.KPIMANAGER, ENVVAR_SUFIX_SERVICE_PORT_GRPC)] = str(KPIMANAGER_SERVICE_PORT) + +LOGGER = logging.getLogger(__name__) + +class MockContextService(GenericGrpcService): + # Mock Service implementing Context to simplify unitary tests of Monitoring + + def __init__(self, bind_port: Union[str, int]) -> None: + super().__init__(bind_port, LOCAL_HOST, enable_health_servicer=False, cls_name='MockService') + + # pylint: disable=attribute-defined-outside-init + def install_servicers(self): + self.context_servicer = MockServicerImpl_Context() + add_ContextServiceServicer_to_server(self.context_servicer, self.server) + +# This fixture will be requested by test cases and last during testing session +@pytest.fixture(scope='session') +def kpi_manager_service(): + LOGGER.info('Initializing KpiManagerService...') + _service = KpiManagerService() + _service.start() + + # yield the server, when test finishes, execution will resume to stop it + LOGGER.info('Yielding KpiManagerService...') + yield _service + + LOGGER.info('Terminating KpiManagerService...') + _service.stop() + + LOGGER.info('Terminated KpiManagerService...') + +# This fixture will be requested by test cases and last during testing session. +# The client requires the server, so client fixture has the server as dependency. +# def monitoring_client(monitoring_service : MonitoringService): (Add for better understanding) +@pytest.fixture(scope='session') +def kpi_manager_client(kpi_manager_service : KpiManagerService): # pylint: disable=redefined-outer-name,unused-argument + LOGGER.info('Initializing KpiManagerClient...') + _client = KpiManagerClient() + + # yield the server, when test finishes, execution will resume to stop it + LOGGER.info('Yielding KpiManagerClient...') + yield _client + + LOGGER.info('Closing KpiManagerClient...') + _client.close() + + LOGGER.info('Closed KpiManagerClient...') + +################################################## +# Prepare Environment, should be the first test +################################################## + + +########################### +# Tests Implementation of Kpi Manager +########################### + +# ---------- 3rd Iteration Tests ---------------- +def test_SetKpiDescriptor(kpi_manager_client): + LOGGER.info(" >>> test_SetKpiDescriptor: START <<< ") + response = kpi_manager_client.SetKpiDescriptor(create_kpi_descriptor_request()) + LOGGER.info("Response gRPC message object: {:}".format(response)) + assert isinstance(response, KpiId) + +def test_DeleteKpiDescriptor(kpi_manager_client): + LOGGER.info(" >>> test_DeleteKpiDescriptor: START <<< ") + # adding KPI + response_id = kpi_manager_client.SetKpiDescriptor(create_kpi_descriptor_request()) + # deleting KPI + del_response = kpi_manager_client.DeleteKpiDescriptor(response_id) + # select KPI + kpi_manager_client.GetKpiDescriptor(response_id) + LOGGER.info("Response of delete method gRPC message object: {:}".format(del_response)) + assert isinstance(del_response, Empty) + +def test_GetKpiDescriptor(kpi_manager_client): + LOGGER.info(" >>> test_GetKpiDescriptor: START <<< ") + # adding KPI + response_id = kpi_manager_client.SetKpiDescriptor(create_kpi_descriptor_request()) + # get KPI + response = kpi_manager_client.GetKpiDescriptor(response_id) + LOGGER.info("Response gRPC message object: {:}".format(response)) + + LOGGER.info(" >>> calling GetKpiDescriptor with random ID") + rand_response = kpi_manager_client.GetKpiDescriptor(create_kpi_id_request()) + LOGGER.info("Response gRPC message object: {:}".format(rand_response)) + + assert isinstance(response, KpiDescriptor) + +def test_SelectKpiDescriptor(kpi_manager_client): + LOGGER.info(" >>> test_SelectKpiDescriptor: START <<< ") + # adding KPI + kpi_manager_client.SetKpiDescriptor(create_kpi_descriptor_request()) + # select KPI(s) + response = kpi_manager_client.SelectKpiDescriptor(create_kpi_filter_request()) + LOGGER.info("Response gRPC message object: {:}".format(response)) + assert isinstance(response, KpiDescriptorList) diff --git a/src/kpi_manager/tests/test_messages.py b/src/kpi_manager/tests/test_messages.py new file mode 100644 index 0000000000000000000000000000000000000000..5f55c2cfcfd3c5c65aa317d02376dd6971fba384 --- /dev/null +++ b/src/kpi_manager/tests/test_messages.py @@ -0,0 +1,80 @@ +# 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 uuid +from common.proto import kpi_manager_pb2 +from common.proto.kpi_sample_types_pb2 import KpiSampleType +from common.proto.context_pb2 import DeviceId, LinkId, ServiceId, SliceId,\ + ConnectionId, EndPointId + + +def create_kpi_id_request(): + _create_kpi_id = kpi_manager_pb2.KpiId() + _create_kpi_id.kpi_id.uuid = str(uuid.uuid4()) + return _create_kpi_id + +def create_kpi_descriptor_request(descriptor_name: str = "Test_name"): + _create_kpi_request = kpi_manager_pb2.KpiDescriptor() + _create_kpi_request.kpi_id.kpi_id.uuid = str(uuid.uuid4()) + # _create_kpi_request.kpi_id.kpi_id.uuid = "6e22f180-ba28-4641-b190-2287bf448888" + # _create_kpi_request.kpi_id.kpi_id.uuid = "1e22f180-ba28-4641-b190-2287bf446666" + _create_kpi_request.kpi_description = descriptor_name + _create_kpi_request.kpi_sample_type = KpiSampleType.KPISAMPLETYPE_PACKETS_RECEIVED + _create_kpi_request.device_id.device_uuid.uuid = 'DEV2' + _create_kpi_request.service_id.service_uuid.uuid = 'SERV2' + _create_kpi_request.slice_id.slice_uuid.uuid = 'SLC1' + _create_kpi_request.endpoint_id.endpoint_uuid.uuid = 'END1' + _create_kpi_request.connection_id.connection_uuid.uuid = 'CON1' + _create_kpi_request.link_id.link_uuid.uuid = 'LNK1' + return _create_kpi_request + +def create_kpi_descriptor_request_a(description: str = "Test Description"): + _create_kpi_request = kpi_manager_pb2.KpiDescriptor() + _create_kpi_request.kpi_id.kpi_id.uuid = str(uuid.uuid4()) + _create_kpi_request.kpi_description = description + _create_kpi_request.kpi_sample_type = KpiSampleType.KPISAMPLETYPE_PACKETS_RECEIVED + _create_kpi_request.device_id.device_uuid.uuid = 'DEV4' + _create_kpi_request.service_id.service_uuid.uuid = 'SERV3' + _create_kpi_request.slice_id.slice_uuid.uuid = 'SLC3' + _create_kpi_request.endpoint_id.endpoint_uuid.uuid = 'END2' + _create_kpi_request.connection_id.connection_uuid.uuid = 'CON2' + _create_kpi_request.link_id.link_uuid.uuid = 'LNK2' + return _create_kpi_request + +def create_kpi_filter_request(): + _create_kpi_filter_request = kpi_manager_pb2.KpiDescriptorFilter() + _create_kpi_filter_request.kpi_sample_type.append(KpiSampleType.KPISAMPLETYPE_PACKETS_RECEIVED) + + device_id_obj = DeviceId() + service_id_obj = ServiceId() + slice_id_obj = SliceId() + endpoint_id_obj = EndPointId() + connection_id_obj = ConnectionId() + link_id_obj = LinkId() + + device_id_obj.device_uuid.uuid = "DEV2" + service_id_obj.service_uuid.uuid = "SERV2" + slice_id_obj.slice_uuid.uuid = "SLC1" + endpoint_id_obj.endpoint_uuid.uuid = "END1" + connection_id_obj.connection_uuid.uuid = "CON1" + link_id_obj.link_uuid.uuid = "LNK1" + + _create_kpi_filter_request.device_id.append(device_id_obj) + _create_kpi_filter_request.service_id.append(service_id_obj) + _create_kpi_filter_request.slice_id.append(slice_id_obj) + _create_kpi_filter_request.endpoint_id.append(endpoint_id_obj) + _create_kpi_filter_request.connection_id.append(connection_id_obj) + _create_kpi_filter_request.link_id.append(link_id_obj) + + return _create_kpi_filter_request \ No newline at end of file diff --git a/src/kpi_value_api/.gitlab-ci.yml b/src/kpi_value_api/.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..cbbaab22cae5f920d1aa1918dae74afa7e3fd91e --- /dev/null +++ b/src/kpi_value_api/.gitlab-ci.yml @@ -0,0 +1,133 @@ +# 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. + +# Build, tag, and push the Docker image to the GitLab Docker registry +build kpi-value-api: + variables: + IMAGE_NAME: 'kpi_value_api' # name of the microservice + IMAGE_TAG: 'latest' # tag of the container image (production, development, etc) + stage: build + before_script: + - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY + script: + - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . + - docker tag "$IMAGE_NAME:$IMAGE_TAG" "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG" + - docker push "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG" + after_script: + - docker images --filter="dangling=true" --quiet | xargs -r docker rmi + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)' + - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"' + - changes: + - src/common/**/*.py + - proto/*.proto + - src/$IMAGE_NAME/**/*.{py,in,yml} + - src/$IMAGE_NAME/Dockerfile + - src/$IMAGE_NAME/tests/*.py + - manifests/${IMAGE_NAME}service.yaml + - .gitlab-ci.yml + +# Apply unit test to the component +unit_test kpi-value-api: + variables: + IMAGE_NAME: 'kpi_value_api' # name of the microservice + IMAGE_TAG: 'latest' # tag of the container image (production, development, etc) + stage: unit_test + needs: + - build kpi-value-api + before_script: + - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY + - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create -d bridge teraflowbridge; fi + - if docker container ls | grep $IMAGE_NAME; then docker rm -f $IMAGE_NAME; else echo "$IMAGE_NAME container is not in the system"; fi + - if docker container ls | grep kafka; then docker rm -f kafka; else echo "Kafka container is not in the system"; fi + - if docker container ls | grep zookeeper; then docker rm -f zookeeper; else echo "Zookeeper container is not in the system"; fi + - docker container prune -f + script: + - docker pull "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG" + - docker pull "bitnami/zookeeper:latest" + - docker pull "bitnami/kafka:latest" + - > + docker run --name zookeeper -d --network=teraflowbridge -p 2181:2181 + --env ALLOW_ANONYMOUS_LOGIN=yes + bitnami/zookeeper:latest + - sleep 10 # Wait for Zookeeper to start + - > + docker run --name kafka -d --network=teraflowbridge -p 9092:9092 + --env KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181 + --env ALLOW_PLAINTEXT_LISTENER=yes + bitnami/kafka:latest + - sleep 20 # Wait for Kafka to start + - KAFKA_IP=$(docker inspect kafka --format "{{.NetworkSettings.Networks.teraflowbridge.IPAddress}}") + - echo $KAFKA_IP + - > + docker run --name $IMAGE_NAME -d -p 30020:30020 + --env "KFK_SERVER_ADDRESS=${KAFKA_IP}:9092" + --volume "$PWD/src/$IMAGE_NAME/tests:/opt/results" + --network=teraflowbridge + $CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG + - sleep 5 + - docker ps -a + - docker logs $IMAGE_NAME + - > + docker exec -i $IMAGE_NAME bash -c + "coverage run -m pytest --log-level=INFO --verbose --junitxml=/opt/results/${IMAGE_NAME}_report.xml $IMAGE_NAME/tests/test_*.py" + - docker exec -i $IMAGE_NAME bash -c "coverage report --include='${IMAGE_NAME}/*' --show-missing" + coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/' + after_script: + - docker rm -f $IMAGE_NAME + - docker rm -f kafka + - docker rm -f zookeeper + - docker network rm teraflowbridge + 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/$IMAGE_NAME/**/*.{py,in,yml} + - src/$IMAGE_NAME/Dockerfile + - src/$IMAGE_NAME/tests/*.py + # - src/$IMAGE_NAME/tests/Dockerfile # mayne not needed + - manifests/${IMAGE_NAME}service.yaml + - .gitlab-ci.yml + artifacts: + when: always + reports: + junit: src/$IMAGE_NAME/tests/${IMAGE_NAME}_report.xml + +## Deployment of the service in Kubernetes Cluster +#deploy context: +# variables: +# IMAGE_NAME: 'context' # name of the microservice +# IMAGE_TAG: 'latest' # tag of the container image (production, development, etc) +# stage: deploy +# needs: +# - unit test context +# # - integ_test execute +# script: +# - 'sed -i "s/$IMAGE_NAME:.*/$IMAGE_NAME:$IMAGE_TAG/" manifests/${IMAGE_NAME}service.yaml' +# - kubectl version +# - kubectl get all +# - kubectl apply -f "manifests/${IMAGE_NAME}service.yaml" +# - kubectl get all +# # environment: +# # name: test +# # url: https://example.com +# # kubernetes: +# # namespace: test +# rules: +# - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)' +# when: manual +# - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"' +# when: manual diff --git a/src/kpi_value_api/Dockerfile b/src/kpi_value_api/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..91e1690066162339b63bb7fe9b1f889621cf04ca --- /dev/null +++ b/src/kpi_value_api/Dockerfile @@ -0,0 +1,70 @@ +# 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 + +# Download the gRPC health probe +RUN GRPC_HEALTH_PROBE_VERSION=v0.2.0 && \ + wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \ + chmod +x /bin/grpc_health_probe + +# 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/kpi_value_api +WORKDIR /var/teraflow/kpi_value_api +COPY src/kpi_value_api/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/kpi_value_api/. kpi_value_api/ +COPY src/kpi_manager/__init__.py kpi_manager/__init__.py +COPY src/kpi_manager/client/. kpi_manager/client/ + +# Start the service +ENTRYPOINT ["python", "-m", "kpi_value_api.service"] diff --git a/src/kpi_value_api/README.md b/src/kpi_value_api/README.md new file mode 100644 index 0000000000000000000000000000000000000000..f946360633ccb62a49e44b2f4b77227dcda9d21f --- /dev/null +++ b/src/kpi_value_api/README.md @@ -0,0 +1,22 @@ +# How to locally run and test KPI Value API + +### Pre-requisets +Ensure the following requirements are met before executing the KPI Value API service. + +1. The KPI Manger service is running and Apache Kafka is running. + +2. A virtual enviornment exist with all the required packages listed in ["requirements.in"](https://labs.etsi.org/rep/tfs/controller/-/blob/develop/src/kpi_value_api/requirements.in) file sucessfully installed. + + +### Messages format templates +The ["messages"](https://labs.etsi.org/rep/tfs/controller/-/blob/develop/src/kpi_value_api/tests/messages.py) python file contains templates for creating gRPC messages. + +### Unit test file +The ["KPI Value API test"](https://labs.etsi.org/rep/tfs/controller/-/blob/develop/src/kpi_value_api/tests/test_kpi_value_api.py) python file enlist various tests conducted to validate functionality. + +### Flow of execution (Kpi Value Api Service functions) +1. Call `StoreKpiValues(KpiValueList)` to produce `Kpi Value` on a Kafka Topic. (The `KpiValueWriter` microservice will consume and process this `Kpi Value`) + +2. Call `SelectKpiValues(KpiValueFilter) -> KpiValueList` to read metric from the Prometheus DB. + +3. Call `GetKpiAlarms(KpiId) -> KpiAlarms` to read alrams from the Kafka. diff --git a/src/kpi_value_api/__init__.py b/src/kpi_value_api/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..53d5157f750bfb085125cbd33faff1cec5924e14 --- /dev/null +++ b/src/kpi_value_api/__init__.py @@ -0,0 +1,14 @@ +# 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. + diff --git a/src/kpi_value_api/client/KpiValueApiClient.py b/src/kpi_value_api/client/KpiValueApiClient.py new file mode 100644 index 0000000000000000000000000000000000000000..b1bc32f902d0b62f2fbd81cbdd9cac7a8ae53ea8 --- /dev/null +++ b/src/kpi_value_api/client/KpiValueApiClient.py @@ -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. + +import grpc, logging + +from common.Constants import ServiceNameEnum +from common.Settings import get_service_host, get_service_port_grpc + +from common.tools.client.RetryDecorator import retry, delay_exponential +from common.tools.grpc.Tools import grpc_message_to_json_string +from common.proto.context_pb2 import Empty +from common.proto.kpi_manager_pb2 import KpiId +from common.proto.kpi_value_api_pb2 import KpiValueList, KpiValueFilter, KpiAlarms +from common.proto.kpi_value_api_pb2_grpc import KpiValueAPIServiceStub + +LOGGER = logging.getLogger(__name__) +MAX_RETRIES = 10 +DELAY_FUNCTION = delay_exponential(initial=0.01, increment=2.0, maximum=5.0) +RETRY_DECORATOR = retry(max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect') + +class KpiValueApiClient: + def __init__(self, host=None, port=None): + if not host: host = get_service_host(ServiceNameEnum.KPIVALUEAPI) + if not port: port = get_service_port_grpc(ServiceNameEnum.KPIVALUEAPI) + self.endpoint = '{:s}:{:s}'.format(str(host), str(port)) + LOGGER.debug('Creating channel to {:s}...'.format(str(self.endpoint))) + self.channel = None + self.stub = None + self.connect() + LOGGER.debug('Channel created') + + def connect(self): + self.channel = grpc.insecure_channel(self.endpoint) + self.stub = KpiValueAPIServiceStub(self.channel) + + def close(self): + if self.channel is not None: self.channel.close() + self.channel = None + self.stub = None + + @RETRY_DECORATOR + def StoreKpiValues(self, request: KpiValueList) -> Empty: # type: ignore + LOGGER.debug('StoreKpiValues: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.StoreKpiValues(request) + LOGGER.debug('StoreKpiValues result: {:s}'.format(grpc_message_to_json_string(response))) + return response + + @RETRY_DECORATOR + def SelectKpiValues(self, request: KpiValueFilter) -> KpiValueList: # type: ignore + LOGGER.debug('SelectKpiValues: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.SelectKpiValues(request) + LOGGER.debug('SelectKpiValues result: {:s}'.format(grpc_message_to_json_string(response))) + return response + + @RETRY_DECORATOR + def GetKpiAlarms(self, request: KpiId) -> KpiAlarms: # type: ignore + LOGGER.debug('GetKpiAlarms: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.GetKpiAlarms(request) + LOGGER.debug('GetKpiAlarms result: {:s}'.format(grpc_message_to_json_string(response))) + return response diff --git a/src/kpi_value_api/client/__init__.py b/src/kpi_value_api/client/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..53d5157f750bfb085125cbd33faff1cec5924e14 --- /dev/null +++ b/src/kpi_value_api/client/__init__.py @@ -0,0 +1,14 @@ +# 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. + diff --git a/src/kpi_value_api/requirements.in b/src/kpi_value_api/requirements.in new file mode 100644 index 0000000000000000000000000000000000000000..6addbfdfd961ee238b2ca44e78de87f735379673 --- /dev/null +++ b/src/kpi_value_api/requirements.in @@ -0,0 +1,18 @@ +# 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. + +confluent-kafka==2.3.* +requests==2.27.* +prometheus-api-client==0.5.3 +apscheduler==3.10.1 diff --git a/src/kpi_value_api/service/KpiValueApiService.py b/src/kpi_value_api/service/KpiValueApiService.py new file mode 100644 index 0000000000000000000000000000000000000000..ea79792912524db69064d8369bb9339621e00664 --- /dev/null +++ b/src/kpi_value_api/service/KpiValueApiService.py @@ -0,0 +1,30 @@ +# 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 common.Constants import ServiceNameEnum +from common.Settings import get_service_port_grpc +from common.tools.service.GenericGrpcService import GenericGrpcService +from .KpiValueApiServiceServicerImpl import KpiValueApiServiceServicerImpl +from common.proto.kpi_value_api_pb2_grpc import add_KpiValueAPIServiceServicer_to_server + + +class KpiValueApiService(GenericGrpcService): + def __init__(self, cls_name : str = __name__ ) -> None: + port = get_service_port_grpc(ServiceNameEnum.KPIVALUEAPI) + super().__init__(port, cls_name=cls_name) + self.kpiValueApiService_servicer = KpiValueApiServiceServicerImpl() + + def install_servicers(self): + add_KpiValueAPIServiceServicer_to_server(self.kpiValueApiService_servicer, self.server) diff --git a/src/kpi_value_api/service/KpiValueApiServiceServicerImpl.py b/src/kpi_value_api/service/KpiValueApiServiceServicerImpl.py new file mode 100644 index 0000000000000000000000000000000000000000..ecba7a063f3636409303ecdad7c18543bc833a19 --- /dev/null +++ b/src/kpi_value_api/service/KpiValueApiServiceServicerImpl.py @@ -0,0 +1,231 @@ +# 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 datetime import datetime +import logging, grpc, json, queue +from typing import Dict +from common.method_wrappers.Decorator import MetricsPool, safe_and_metered_rpc_method +from common.tools.kafka.Variables import KafkaConfig, KafkaTopic +from confluent_kafka import KafkaError + +from common.proto.context_pb2 import Empty +from common.proto.kpi_sample_types_pb2 import KpiSampleType +from common.proto.kpi_manager_pb2 import KpiDescriptor, KpiId +from common.proto.kpi_value_api_pb2_grpc import KpiValueAPIServiceServicer +from common.proto.kpi_value_api_pb2 import KpiAlarms, KpiValueList, KpiValueFilter, KpiValue, KpiValueType +from apscheduler.schedulers.background import BackgroundScheduler +from apscheduler.triggers.interval import IntervalTrigger +from confluent_kafka import Producer as KafkaProducer +from confluent_kafka import Consumer as KafkaConsumer + +from prometheus_api_client import PrometheusConnect +from prometheus_api_client.utils import parse_datetime + +from kpi_manager.client.KpiManagerClient import KpiManagerClient + +LOGGER = logging.getLogger(__name__) +METRICS_POOL = MetricsPool('KpiValueAPI', 'NBIgRPC') +PROM_URL = "http://prometheus-k8s.monitoring.svc.cluster.local:9090" # TODO: updated with the env variables + +class KpiValueApiServiceServicerImpl(KpiValueAPIServiceServicer): + def __init__(self): + LOGGER.debug('Init KpiValueApiService') + self.listener_topic = KafkaTopic.ALARMS.value + self.result_queue = queue.Queue() + self.scheduler = BackgroundScheduler() + self.kafka_producer = KafkaProducer({'bootstrap.servers' : KafkaConfig.get_kafka_address()}) + self.kafka_consumer = KafkaConsumer({'bootstrap.servers' : KafkaConfig.get_kafka_address(), + 'group.id' : 'kpi-value-api-frontend', + 'auto.offset.reset' : 'latest'}) + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def StoreKpiValues(self, request: KpiValueList, grpc_context: grpc.ServicerContext + ) -> Empty: + LOGGER.debug('StoreKpiValues: Received gRPC message object: {:}'.format(request)) + + producer = self.kafka_producer + for kpi_value in request.kpi_value_list: + kpi_value_to_produce : Dict = { + "kpi_uuid" : kpi_value.kpi_id.kpi_id.uuid, + "timestamp" : kpi_value.timestamp.timestamp, + "kpi_value_type" : self.ExtractKpiValueByType(kpi_value.kpi_value_type) + } + LOGGER.debug('KPI to produce is {:}'.format(kpi_value_to_produce)) + msg_key = "gRPC-kpivalueapi" # str(__class__.__name__) can be used + + producer.produce( + KafkaTopic.VALUE.value, + key = msg_key, + value = json.dumps(kpi_value_to_produce), + callback = self.delivery_callback + ) + producer.flush() + return Empty() + + def ExtractKpiValueByType(self, value): + attributes = [ 'floatVal' , 'int32Val' , 'uint32Val','int64Val', + 'uint64Val', 'stringVal', 'boolVal'] + for attr in attributes: + try: + return getattr(value, attr) + except (ValueError, TypeError, AttributeError): + continue + return None + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def SelectKpiValues(self, request: KpiValueFilter, grpc_context: grpc.ServicerContext + ) -> KpiValueList: + LOGGER.debug('StoreKpiValues: Received gRPC message object: {:}'.format(request)) + response = KpiValueList() + + kpi_manager_client = KpiManagerClient() + prom_connect = PrometheusConnect(url=PROM_URL) + + metrics = [self.GetKpiSampleType(kpi, kpi_manager_client) for kpi in request.kpi_id] + start_timestamps = [parse_datetime(timestamp) for timestamp in request.start_timestamp] + end_timestamps = [parse_datetime(timestamp) for timestamp in request.end_timestamp] + + prom_response = [] + for start_time, end_time in zip(start_timestamps, end_timestamps): + for metric in metrics: + print(start_time, end_time, metric) + LOGGER.debug(">>> Query: {:}".format(metric)) + prom_response.append( + prom_connect.custom_query_range( + query = metric, # this is the metric name and label config + start_time = start_time, + end_time = end_time, + step = 30, # or any other step value (missing in gRPC Filter request) + ) + ) + + for single_resposne in prom_response: + # print ("{:}".format(single_resposne)) + for record in single_resposne: + # print("Record >>> kpi: {:} >>> time & values set: {:}".format(record['metric']['__name__'], record['values'])) + for value in record['values']: + # print("{:} - {:}".format(record['metric']['__name__'], value)) + kpi_value = KpiValue() + kpi_value.kpi_id.kpi_id = record['metric']['__name__'], + kpi_value.timestamp = value[0], + kpi_value.kpi_value_type.CopyFrom(self.ConverValueToKpiValueType(value['kpi_value'])) + response.kpi_value_list.append(kpi_value) + return response + + def GetKpiSampleType(self, kpi_value: str, kpi_manager_client): + kpi_id = KpiId() + kpi_id.kpi_id.uuid = kpi_value.kpi_id.kpi_id.uuid + # print("KpiId generated: {:}".format(kpi_id)) + try: + kpi_descriptor_object = KpiDescriptor() + kpi_descriptor_object = kpi_manager_client.GetKpiDescriptor(kpi_id) + # TODO: why kpi_descriptor_object recevies a KpiDescriptor type object not Empty type object??? + if kpi_descriptor_object.kpi_id.kpi_id.uuid == kpi_id.kpi_id.uuid: + LOGGER.info("Extracted KpiDescriptor: {:}".format(kpi_descriptor_object)) + print("Extracted KpiDescriptor: {:}".format(kpi_descriptor_object)) + return KpiSampleType.Name(kpi_descriptor_object.kpi_sample_type) # extract and return the name of KpiSampleType + else: + LOGGER.info("No KPI Descriptor found in DB for Kpi ID: {:}".format(kpi_id)) + print("No KPI Descriptor found in DB for Kpi ID: {:}".format(kpi_id)) + except Exception as e: + LOGGER.info("Unable to get KpiDescriptor. Error: {:}".format(e)) + print ("Unable to get KpiDescriptor. Error: {:}".format(e)) + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def GetKpiAlarms(self, request: KpiId, grpc_context: grpc.ServicerContext) -> KpiAlarms: # type: ignore + """ + Get Alarms from Kafka return Alrams periodically. + """ + LOGGER.debug('GetKpiAlarms: {:}'.format(request)) + response = KpiAlarms() + + for alarm_key, value in self.StartResponseListener(request.kpi_id.uuid): + response.start_timestamp.timestamp = datetime.strptime( + value["window_start"], "%Y-%m-%dT%H:%M:%S.%fZ").timestamp() + response.kpi_id.kpi_id.uuid = value['kpi_id'] + for key, threshold in value.items(): + if key not in ['kpi_id', 'window']: + response.alarms[key] = threshold + + yield response + + def StartResponseListener(self, filter_key=None): + """ + Start the Kafka response listener with APScheduler and return key-value pairs periodically. + """ + LOGGER.info("Starting StartResponseListener") + # Schedule the ResponseListener at fixed intervals + self.scheduler.add_job( + self.response_listener, + trigger=IntervalTrigger(seconds=5), + args=[filter_key], + id=f"response_listener_{self.listener_topic}", + replace_existing=True + ) + self.scheduler.start() + LOGGER.info(f"Started Kafka listener for topic {self.listener_topic}...") + try: + while True: + LOGGER.info("entering while...") + key, value = self.result_queue.get() # Wait until a result is available + LOGGER.info("In while true ...") + yield key, value # Yield the result to the calling function + except Exception as e: + LOGGER.warning("Listener stopped. Error: {:}".format(e)) + finally: + self.scheduler.shutdown() + + def response_listener(self, filter_key=None): + """ + Poll Kafka messages and put key-value pairs into the queue. + """ + LOGGER.info(f"Polling Kafka topic {self.listener_topic}...") + + consumer = self.kafka_consumer + consumer.subscribe([self.listener_topic]) + while True: + msg = consumer.poll(1.0) + if msg is None: + continue + elif msg.error(): + if msg.error().code() != KafkaError._PARTITION_EOF: + LOGGER.error(f"Kafka error: {msg.error()}") + break + try: + key = msg.key().decode('utf-8') if msg.key() else None + if filter_key is not None and key == filter_key: + value = json.loads(msg.value().decode('utf-8')) + LOGGER.info(f"Received key: {key}, value: {value}") + self.result_queue.put((key, value)) + else: + LOGGER.warning(f"Skipping message with unmatched key: {key} - {filter_key}") + except Exception as e: + LOGGER.error(f"Error processing Kafka message: {e}") + + def delivery_callback(self, err, msg): + if err: LOGGER.debug('Message delivery failed: {:}'.format(err)) + else: LOGGER.debug('Message delivered to topic {:}'.format(msg.topic())) + + def ConverValueToKpiValueType(self, value): + kpi_value_type = KpiValueType() + if isinstance(value, int): + kpi_value_type.int32Val = value + elif isinstance(value, float): + kpi_value_type.floatVal = value + elif isinstance(value, str): + kpi_value_type.stringVal = value + elif isinstance(value, bool): + kpi_value_type.boolVal = value + # Add other checks for different types as needed + return kpi_value_type diff --git a/src/kpi_value_api/service/__init__.py b/src/kpi_value_api/service/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..53d5157f750bfb085125cbd33faff1cec5924e14 --- /dev/null +++ b/src/kpi_value_api/service/__init__.py @@ -0,0 +1,14 @@ +# 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. + diff --git a/src/kpi_value_api/service/__main__.py b/src/kpi_value_api/service/__main__.py new file mode 100644 index 0000000000000000000000000000000000000000..6ac7e1cb23254ab2be7183b7a1bc42c40597d670 --- /dev/null +++ b/src/kpi_value_api/service/__main__.py @@ -0,0 +1,51 @@ +# 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, signal, sys, threading +from common.Settings import get_log_level +from .KpiValueApiService import KpiValueApiService + +terminate = threading.Event() +LOGGER = None + +def signal_handler(signal, frame): # pylint: disable=redefined-outer-name + LOGGER.warning('Terminate signal received') + terminate.set() + +def main(): + global LOGGER # pylint: disable=global-statement + + log_level = get_log_level() + logging.basicConfig(level=log_level) + LOGGER = logging.getLogger(__name__) + + signal.signal(signal.SIGINT, signal_handler) + signal.signal(signal.SIGTERM, signal_handler) + + LOGGER.debug('Starting...') + + grpc_service = KpiValueApiService() + grpc_service.start() + + # Wait for Ctrl+C or termination signal + while not terminate.wait(timeout=1.0): pass + + LOGGER.debug('Terminating...') + grpc_service.stop() + + LOGGER.debug('Bye') + return 0 + +if __name__ == '__main__': + sys.exit(main()) diff --git a/src/kpi_value_api/tests/messages.py b/src/kpi_value_api/tests/messages.py new file mode 100644 index 0000000000000000000000000000000000000000..8ded327dc8de410a83a69a24b654e1787d7070cf --- /dev/null +++ b/src/kpi_value_api/tests/messages.py @@ -0,0 +1,43 @@ +# 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 uuid, time +from common.proto import kpi_manager_pb2 +from common.proto.kpi_value_api_pb2 import KpiValue, KpiValueList + + +def create_kpi_id_request(): + _create_kpi_id = kpi_manager_pb2.KpiId() + _create_kpi_id.kpi_id.uuid = "6e22f180-ba28-4641-b190-2287bf448888" + # _create_kpi_id.kpi_id.uuid = str(uuid.uuid4()) + return _create_kpi_id + +def create_kpi_value_list(): + _create_kpi_value_list = KpiValueList() + # To run this experiment sucessfully, add an existing UUID of a KPI Descriptor from the KPI DB. + # This UUID is used to get the descriptor form the KPI DB. If the Kpi ID does not exists, + # some part of the code won't execute. + EXISTING_KPI_IDs = ["725ce3ad-ac67-4373-bd35-8cd9d6a86e09", + str(uuid.uuid4()), + str(uuid.uuid4())] + + for kpi_id_uuid in EXISTING_KPI_IDs: + kpi_value_object = KpiValue() + kpi_value_object.kpi_id.kpi_id.uuid = kpi_id_uuid + kpi_value_object.timestamp.timestamp = float(time.time()) + kpi_value_object.kpi_value_type.floatVal = 100 + + _create_kpi_value_list.kpi_value_list.append(kpi_value_object) + + return _create_kpi_value_list diff --git a/src/kpi_value_api/tests/test_kpi_value_api.py b/src/kpi_value_api/tests/test_kpi_value_api.py new file mode 100644 index 0000000000000000000000000000000000000000..bd9049e160536e9c85f0d40d1eeb138759ecf87b --- /dev/null +++ b/src/kpi_value_api/tests/test_kpi_value_api.py @@ -0,0 +1,91 @@ +# 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 os, logging, pytest +from common.proto.context_pb2 import Empty +from common.Constants import ServiceNameEnum +from common.tools.kafka.Variables import KafkaTopic +from common.Settings import ( + ENVVAR_SUFIX_SERVICE_HOST, ENVVAR_SUFIX_SERVICE_PORT_GRPC, get_env_var_name, get_service_port_grpc) +from kpi_value_api.service.KpiValueApiService import KpiValueApiService +from kpi_value_api.client.KpiValueApiClient import KpiValueApiClient +from kpi_value_api.tests.messages import create_kpi_value_list, create_kpi_id_request +from common.proto.kpi_value_api_pb2 import KpiAlarms + +LOCAL_HOST = '127.0.0.1' +KPIVALUEAPI_SERVICE_PORT = get_service_port_grpc(ServiceNameEnum.KPIVALUEAPI) # type: ignore +os.environ[get_env_var_name(ServiceNameEnum.KPIVALUEAPI, ENVVAR_SUFIX_SERVICE_HOST )] = str(LOCAL_HOST) +os.environ[get_env_var_name(ServiceNameEnum.KPIVALUEAPI, ENVVAR_SUFIX_SERVICE_PORT_GRPC)] = str(KPIVALUEAPI_SERVICE_PORT) +LOGGER = logging.getLogger(__name__) + +# This fixture will be requested by test cases and last during testing session +@pytest.fixture(scope='session') +def kpi_value_api_service(): + LOGGER.info('Initializing KpiValueApiService...') + # _service = MonitoringService(name_mapping) + _service = KpiValueApiService() + _service.start() + + # yield the server, when test finishes, execution will resume to stop it + LOGGER.info('Yielding KpiValueApiService...') + yield _service + + LOGGER.info('Terminating KpiValueApiService...') + _service.stop() + + LOGGER.info('Terminated KpiValueApiService...') + +# This fixture will be requested by test cases and last during testing session. +# The client requires the server, so client fixture has the server as dependency. +@pytest.fixture(scope='session') +def kpi_value_api_client(kpi_value_api_service : KpiValueApiService ): + LOGGER.info('Initializing KpiValueApiClient...') + _client = KpiValueApiClient() + + # yield the server, when test finishes, execution will resume to stop it + LOGGER.info('Yielding KpiValueApiClient...') + yield _client + + LOGGER.info('Closing KpiValueApiClient...') + _client.close() + + LOGGER.info('Closed KpiValueApiClient...') + +################################################## +# Prepare Environment, should be the first test +################################################## + +# To be added here + +########################### +# Tests Implementation of Kpi Value Api +########################### + +def test_validate_kafka_topics(): + LOGGER.debug(" >>> test_validate_kafka_topics: START <<< ") + response = KafkaTopic.create_all_topics() + assert isinstance(response, bool) + +# def test_GetKpiAlarms(kpi_value_api_client): +# LOGGER.debug(" >>> test_GetKpiAlarms") +# stream = kpi_value_api_client.GetKpiAlarms(create_kpi_id_request()) +# for response in stream: +# LOGGER.debug(str(response)) +# assert isinstance(response, KpiAlarms) + +# def test_store_kpi_values(kpi_value_api_client): +# LOGGER.debug(" >>> test_set_list_of_KPIs: START <<< ") +# response = kpi_value_api_client.StoreKpiValues(create_kpi_value_list()) +# assert isinstance(response, Empty) diff --git a/src/kpi_value_writer/.gitlab-ci.yml b/src/kpi_value_writer/.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..fccf1c9869205e46f6ee6da84a70f2fc5d3bf3c6 --- /dev/null +++ b/src/kpi_value_writer/.gitlab-ci.yml @@ -0,0 +1,135 @@ +# 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. + +# Build, tag, and push the Docker image to the GitLab Docker registry +build kpi-value-writer: + variables: + IMAGE_NAME: 'kpi_value_writer' # name of the microservice + IMAGE_TAG: 'latest' # tag of the container image (production, development, etc) + stage: build + before_script: + - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY + script: + - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . + - docker tag "$IMAGE_NAME:$IMAGE_TAG" "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG" + - docker push "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG" + after_script: + - docker images --filter="dangling=true" --quiet | xargs -r docker rmi + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)' + - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"' + - changes: + - src/common/**/*.py + - proto/*.proto + - src/$IMAGE_NAME/**/*.{py,in,yml} + - src/$IMAGE_NAME/Dockerfile + - src/$IMAGE_NAME/tests/*.py + - manifests/${IMAGE_NAME}service.yaml + - .gitlab-ci.yml + +# Apply unit test to the component +unit_test kpi-value-writer: + variables: + IMAGE_NAME: 'kpi_value_writer' # name of the microservice + IMAGE_TAG: 'latest' # tag of the container image (production, development, etc) + stage: unit_test + needs: + - build kpi-value-writer + before_script: + - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY + - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create -d bridge teraflowbridge; fi + - if docker container ls | grep $IMAGE_NAME; then docker rm -f $IMAGE_NAME; else echo "$IMAGE_NAME container is not in the system"; fi + - if docker container ls | grep kafka; then docker rm -f kafka; else echo "Kafka container is not in the system"; fi + - if docker container ls | grep zookeeper; then docker rm -f zookeeper; else echo "Zookeeper container is not in the system"; fi + - docker container prune -f + script: + - docker pull "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG" + - docker pull "bitnami/zookeeper:latest" + - docker pull "bitnami/kafka:latest" + - > + docker run --name zookeeper -d --network=teraflowbridge -p 2181:2181 + --env ALLOW_ANONYMOUS_LOGIN=yes + bitnami/zookeeper:latest + - sleep 10 # Wait for Zookeeper to start + - > + docker run --name kafka -d --network=teraflowbridge -p 9092:9092 + --env KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181 + --env ALLOW_PLAINTEXT_LISTENER=yes + bitnami/kafka:latest + - sleep 20 # Wait for Kafka to start + - KAFKA_IP=$(docker inspect kafka --format "{{.NetworkSettings.Networks.teraflowbridge.IPAddress}}") + - echo $KAFKA_IP + - > + docker run --name $IMAGE_NAME -d -p 30030:30030 + --env "KFK_SERVER_ADDRESS=${KAFKA_IP}:9092" + --volume "$PWD/src/$IMAGE_NAME/tests:/opt/results" + --network=teraflowbridge + $CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG + - sleep 5 + - docker ps -a + - docker logs zookeeper + - docker logs kafka + - docker logs $IMAGE_NAME + - > + docker exec -i $IMAGE_NAME bash -c + "coverage run -m pytest --log-level=INFO --verbose --junitxml=/opt/results/${IMAGE_NAME}_report.xml $IMAGE_NAME/tests/test_*.py" + - docker exec -i $IMAGE_NAME bash -c "coverage report --include='${IMAGE_NAME}/*' --show-missing" + coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/' + after_script: + - docker rm -f $IMAGE_NAME + - docker rm -f kafka + - docker rm -f zookeeper + - docker network rm teraflowbridge + 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/$IMAGE_NAME/**/*.{py,in,yml} + - src/$IMAGE_NAME/Dockerfile + - src/$IMAGE_NAME/tests/*.py + - src/$IMAGE_NAME/tests/Dockerfile + - manifests/${IMAGE_NAME}service.yaml + - .gitlab-ci.yml + artifacts: + when: always + reports: + junit: src/$IMAGE_NAME/tests/${IMAGE_NAME}_report.xml + +## Deployment of the service in Kubernetes Cluster +#deploy context: +# variables: +# IMAGE_NAME: 'context' # name of the microservice +# IMAGE_TAG: 'latest' # tag of the container image (production, development, etc) +# stage: deploy +# needs: +# - unit test context +# # - integ_test execute +# script: +# - 'sed -i "s/$IMAGE_NAME:.*/$IMAGE_NAME:$IMAGE_TAG/" manifests/${IMAGE_NAME}service.yaml' +# - kubectl version +# - kubectl get all +# - kubectl apply -f "manifests/${IMAGE_NAME}service.yaml" +# - kubectl get all +# # environment: +# # name: test +# # url: https://example.com +# # kubernetes: +# # namespace: test +# rules: +# - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)' +# when: manual +# - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"' +# when: manual diff --git a/src/kpi_value_writer/Dockerfile b/src/kpi_value_writer/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..f6f8b135230d187e503fe7c2a2b76fe616d05d61 --- /dev/null +++ b/src/kpi_value_writer/Dockerfile @@ -0,0 +1,70 @@ +# 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 + +# Download the gRPC health probe +RUN GRPC_HEALTH_PROBE_VERSION=v0.2.0 && \ + wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \ + chmod +x /bin/grpc_health_probe + +# 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/kpi_value_writer +WORKDIR /var/teraflow/kpi_value_writer +COPY src/kpi_value_writer/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/kpi_value_writer/. kpi_value_writer/ +COPY src/kpi_manager/__init__.py kpi_manager/__init__.py +COPY src/kpi_manager/client/. kpi_manager/client/ + +# Start the service +ENTRYPOINT ["python", "-m", "kpi_value_writer.service"] diff --git a/src/kpi_value_writer/README.md b/src/kpi_value_writer/README.md new file mode 100644 index 0000000000000000000000000000000000000000..703358728178f0ab703ae7b78096430eb5e0503b --- /dev/null +++ b/src/kpi_value_writer/README.md @@ -0,0 +1,15 @@ +# How to locally run and test the KPI Value Writer + +### Pre-requisets +Ensure the following requirements are meet before executing the KPI Value Writer service. + +1. The KPI Manger and KPI Value API services are running. + +2. A Virtual enviornment exist with all the required packages listed in the ["requirements.in"](https://labs.etsi.org/rep/tfs/controller/-/blob/develop/src/kpi_value_writer/requirements.in) file installed sucessfully. + +### Messages format templates +The ["messages"](https://labs.etsi.org/rep/tfs/controller/-/blob/develop/src/kpi_value_writer/tests/test_messages.py) python file contains the templates to create gRPC messages. + + +### Flow of execution +1. The service will be running, consuming KPI values from the Kafka topic, and pushing KPI metrics to Prometheus. diff --git a/src/kpi_value_writer/__init__.py b/src/kpi_value_writer/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..53d5157f750bfb085125cbd33faff1cec5924e14 --- /dev/null +++ b/src/kpi_value_writer/__init__.py @@ -0,0 +1,14 @@ +# 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. + diff --git a/src/kpi_value_writer/requirements.in b/src/kpi_value_writer/requirements.in new file mode 100644 index 0000000000000000000000000000000000000000..ac0c82cc3c638f17b777459dec1577b68ad2a0ba --- /dev/null +++ b/src/kpi_value_writer/requirements.in @@ -0,0 +1,16 @@ +# 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. + +confluent-kafka==2.3.* +requests==2.27.* diff --git a/src/kpi_value_writer/service/KpiValueWriter.py b/src/kpi_value_writer/service/KpiValueWriter.py new file mode 100644 index 0000000000000000000000000000000000000000..0bc95355e35e6deab8ba79eeeb87e278b1b2ecd2 --- /dev/null +++ b/src/kpi_value_writer/service/KpiValueWriter.py @@ -0,0 +1,98 @@ +# 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 json +import logging +import threading +from common.tools.kafka.Variables import KafkaConfig, KafkaTopic +from common.proto.kpi_value_api_pb2 import KpiValue +from common.proto.kpi_manager_pb2 import KpiDescriptor, KpiId +from common.Settings import get_service_port_grpc +from common.Constants import ServiceNameEnum +from common.tools.service.GenericGrpcService import GenericGrpcService + + +from confluent_kafka import KafkaError +from confluent_kafka import Consumer as KafkaConsumer + +from kpi_manager.client.KpiManagerClient import KpiManagerClient +# -- test import -- +# from kpi_value_writer.tests.test_messages import create_kpi_descriptor_request +from .MetricWriterToPrometheus import MetricWriterToPrometheus + + +LOGGER = logging.getLogger(__name__) +ACTIVE_CONSUMERS = [] + +class KpiValueWriter(GenericGrpcService): + def __init__(self, cls_name : str = __name__) -> None: + port = get_service_port_grpc(ServiceNameEnum.KPIVALUEWRITER) + super().__init__(port, cls_name=cls_name) + self.kafka_consumer = KafkaConsumer({'bootstrap.servers' : KafkaConfig.get_kafka_address(), + 'group.id' : 'KpiValueWriter', + 'auto.offset.reset' : 'latest'}) + + def RunKafkaConsumer(self): + thread = threading.Thread(target=self.KafkaKpiConsumer, args=()) + ACTIVE_CONSUMERS.append(thread) + thread.start() + + def KafkaKpiConsumer(self): + kpi_manager_client = KpiManagerClient() + metric_writer = MetricWriterToPrometheus() + + consumer = self.kafka_consumer + consumer.subscribe([KafkaTopic.VALUE.value]) + LOGGER.debug("Kafka Consumer start listenng on topic: {:}".format(KafkaTopic.VALUE.value)) + print("Kafka Consumer start listenng on topic: {:}".format(KafkaTopic.VALUE.value)) + while True: + raw_kpi = consumer.poll(1.0) + if raw_kpi is None: + continue + elif raw_kpi.error(): + if raw_kpi.error().code() == KafkaError._PARTITION_EOF: + continue + else: + print("Consumer error: {}".format(raw_kpi.error())) + continue + try: + kpi_value = json.loads(raw_kpi.value().decode('utf-8')) + LOGGER.info("Received KPI : {:}".format(kpi_value)) + print("Received KPI : {:}".format(kpi_value)) + self.get_kpi_descriptor(kpi_value, kpi_manager_client, metric_writer) + except Exception as e: + print("Error detail: {:}".format(e)) + continue + + def get_kpi_descriptor(self, kpi_value: str, kpi_manager_client, metric_writer): + print("--- START -----") + + kpi_id = KpiId() + kpi_id.kpi_id.uuid = kpi_value['kpi_uuid'] + print("KpiId generated: {:}".format(kpi_id)) + # print("Kpi manger client created: {:}".format(kpi_manager_client)) + try: + kpi_descriptor_object = KpiDescriptor() + kpi_descriptor_object = kpi_manager_client.GetKpiDescriptor(kpi_id) + # TODO: why kpi_descriptor_object recevies a KpiDescriptor type object not Empty type object??? + if kpi_descriptor_object.kpi_id.kpi_id.uuid == kpi_id.kpi_id.uuid: + LOGGER.info("Extracted KpiDescriptor: {:}".format(kpi_descriptor_object)) + print("Extracted KpiDescriptor: {:}".format(kpi_descriptor_object)) + metric_writer.create_and_expose_cooked_kpi(kpi_descriptor_object, kpi_value) + else: + LOGGER.info("No KPI Descriptor found in DB for Kpi ID: {:}".format(kpi_id)) + print("No KPI Descriptor found in DB for Kpi ID: {:}".format(kpi_id)) + except Exception as e: + LOGGER.info("Unable to get KpiDescriptor. Error: {:}".format(e)) + print ("Unable to get KpiDescriptor. Error: {:}".format(e)) diff --git a/src/kpi_value_writer/service/MetricWriterToPrometheus.py b/src/kpi_value_writer/service/MetricWriterToPrometheus.py new file mode 100644 index 0000000000000000000000000000000000000000..bfbb6e3bab9770719f2fc23b3fab00e2805b074a --- /dev/null +++ b/src/kpi_value_writer/service/MetricWriterToPrometheus.py @@ -0,0 +1,86 @@ +# 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. + +# read Kafka stream from Kafka topic + +import logging +from prometheus_client import Gauge +from common.proto.kpi_sample_types_pb2 import KpiSampleType + +from common.proto.kpi_value_api_pb2 import KpiValue +from common.proto.kpi_manager_pb2 import KpiDescriptor + +LOGGER = logging.getLogger(__name__) +PROM_METRICS = {} + +class MetricWriterToPrometheus: + ''' + This class exposes the *cooked KPI* on the endpoint to be scraped by the Prometheus server. + cooked KPI value = KpiDescriptor (gRPC message) + KpiValue (gRPC message) + ''' + def __init__(self): + pass + + def merge_kpi_descriptor_and_kpi_value(self, kpi_descriptor, kpi_value): + # Creating a dictionary from the kpi_descriptor's attributes + cooked_kpi = { + 'kpi_id' : kpi_descriptor.kpi_id.kpi_id.uuid, + 'kpi_description': kpi_descriptor.kpi_description, + 'kpi_sample_type': KpiSampleType.Name(kpi_descriptor.kpi_sample_type), + 'device_id' : kpi_descriptor.device_id.device_uuid.uuid, + 'endpoint_id' : kpi_descriptor.endpoint_id.endpoint_uuid.uuid, + 'service_id' : kpi_descriptor.service_id.service_uuid.uuid, + 'slice_id' : kpi_descriptor.slice_id.slice_uuid.uuid, + 'connection_id' : kpi_descriptor.connection_id.connection_uuid.uuid, + 'link_id' : kpi_descriptor.link_id.link_uuid.uuid, + 'time_stamp' : kpi_value.timestamp.timestamp, + 'kpi_value' : kpi_value.kpi_value_type.floatVal + } + LOGGER.debug("Cooked Kpi: {:}".format(cooked_kpi)) + return cooked_kpi + + def create_and_expose_cooked_kpi(self, kpi_descriptor: KpiDescriptor, kpi_value: KpiValue): + # merge both gRPC messages into single varible. + cooked_kpi = self.merge_kpi_descriptor_and_kpi_value(kpi_descriptor, kpi_value) + tags_to_exclude = {'kpi_description', 'kpi_sample_type', 'kpi_value'} + metric_tags = [tag for tag in cooked_kpi.keys() if tag not in tags_to_exclude] # These values will be used as metric tags + metric_name = cooked_kpi['kpi_sample_type'] + try: + if metric_name not in PROM_METRICS: # Only register the metric, when it doesn't exists + PROM_METRICS[metric_name] = Gauge ( + metric_name, + cooked_kpi['kpi_description'], + metric_tags + ) + LOGGER.debug("Metric is created with labels: {:}".format(metric_tags)) + PROM_METRICS[metric_name].labels( + kpi_id = cooked_kpi['kpi_id'], + device_id = cooked_kpi['device_id'], + endpoint_id = cooked_kpi['endpoint_id'], + service_id = cooked_kpi['service_id'], + slice_id = cooked_kpi['slice_id'], + connection_id = cooked_kpi['connection_id'], + link_id = cooked_kpi['link_id'], + time_stamp = cooked_kpi['time_stamp'], + ).set(float(cooked_kpi['kpi_value'])) + LOGGER.debug("Metric pushed to the endpoints: {:}".format(PROM_METRICS[metric_name])) + + except ValueError as e: + if 'Duplicated timeseries' in str(e): + LOGGER.debug("Metric {:} is already registered. Skipping.".format(metric_name)) + print("Metric {:} is already registered. Skipping.".format(metric_name)) + else: + LOGGER.error("Error while pushing metric: {}".format(e)) + raise + diff --git a/src/kpi_value_writer/service/__init__.py b/src/kpi_value_writer/service/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..53d5157f750bfb085125cbd33faff1cec5924e14 --- /dev/null +++ b/src/kpi_value_writer/service/__init__.py @@ -0,0 +1,14 @@ +# 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. + diff --git a/src/kpi_value_writer/service/__main__.py b/src/kpi_value_writer/service/__main__.py new file mode 100644 index 0000000000000000000000000000000000000000..28ba2ac90f1e9ed28dfeeeda6b6da17568a124e7 --- /dev/null +++ b/src/kpi_value_writer/service/__main__.py @@ -0,0 +1,54 @@ +# 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, signal, sys, threading +from prometheus_client import start_http_server +from kpi_value_writer.service.KpiValueWriter import KpiValueWriter +from common.Settings import get_log_level + +terminate = threading.Event() +LOGGER = None + +def signal_handler(signal, frame): # pylint: disable=redefined-outer-name + LOGGER.warning('Terminate signal received') + terminate.set() + +def main(): + global LOGGER # pylint: disable=global-statement + + log_level = get_log_level() + logging.basicConfig(level=log_level) + LOGGER = logging.getLogger(__name__) + + signal.signal(signal.SIGINT, signal_handler) + signal.signal(signal.SIGTERM, signal_handler) + + LOGGER.debug('Starting...') + + grpc_service = KpiValueWriter() + grpc_service.start() + + start_http_server(10808) + LOGGER.debug("Prometheus client is started on port 10808") + # Wait for Ctrl+C or termination signal + while not terminate.wait(timeout=1.0): pass + + LOGGER.debug('Terminating...') + grpc_service.stop() + + LOGGER.debug('Bye') + return 0 + +if __name__ == '__main__': + sys.exit(main()) diff --git a/src/kpi_value_writer/tests/test_kpi_value_writer.py b/src/kpi_value_writer/tests/test_kpi_value_writer.py new file mode 100755 index 0000000000000000000000000000000000000000..0d3f9e683db5430fe9214cbf4131dcc38912da85 --- /dev/null +++ b/src/kpi_value_writer/tests/test_kpi_value_writer.py @@ -0,0 +1,33 @@ +# 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 +from kpi_value_writer.service.KpiValueWriter import KpiValueWriter + +from common.tools.kafka.Variables import KafkaTopic + + + +LOGGER = logging.getLogger(__name__) + +# -------- Initial Test ---------------- +def test_validate_kafka_topics(): + LOGGER.debug(" >>> test_validate_kafka_topics: START <<< ") + response = KafkaTopic.create_all_topics() + assert isinstance(response, bool) + +def test_KafkaConsumer(): + LOGGER.debug(" --->>> test_kafka_consumer: START <<<--- ") + # kpi_value_writer = KpiValueWriter() + # kpi_value_writer.RunKafkaConsumer() diff --git a/src/kpi_value_writer/tests/test_messages.py b/src/kpi_value_writer/tests/test_messages.py new file mode 100755 index 0000000000000000000000000000000000000000..ffc6b398c4ff6405fe1ac8eec086553fa6fbe193 --- /dev/null +++ b/src/kpi_value_writer/tests/test_messages.py @@ -0,0 +1,44 @@ +# 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 uuid, time +import random +from common.proto import kpi_manager_pb2 +from common.proto.kpi_value_api_pb2 import KpiValue +from common.proto.kpi_sample_types_pb2 import KpiSampleType + +def create_kpi_id_request(): + _create_kpi_id = kpi_manager_pb2.KpiId() + _create_kpi_id.kpi_id.uuid = str(uuid.uuid4()) + return _create_kpi_id + +def create_kpi_descriptor_request(description: str = "Test Description"): + _create_kpi_request = kpi_manager_pb2.KpiDescriptor() + _create_kpi_request.kpi_id.kpi_id.uuid = str(uuid.uuid4()) + _create_kpi_request.kpi_description = description + _create_kpi_request.kpi_sample_type = KpiSampleType.KPISAMPLETYPE_PACKETS_RECEIVED + _create_kpi_request.device_id.device_uuid.uuid = 'DEV4' + _create_kpi_request.service_id.service_uuid.uuid = 'SERV3' + _create_kpi_request.slice_id.slice_uuid.uuid = 'SLC3' + _create_kpi_request.endpoint_id.endpoint_uuid.uuid = 'END2' + _create_kpi_request.connection_id.connection_uuid.uuid = 'CON2' + _create_kpi_request.link_id.link_uuid.uuid = 'LNK2' + return _create_kpi_request + +def create_kpi_value_request(): + _create_kpi_value_request = KpiValue() + _create_kpi_value_request.kpi_id.kpi_id.uuid = str(uuid.uuid4()) + _create_kpi_value_request.timestamp.timestamp = time.time() + _create_kpi_value_request.kpi_value_type.floatVal = random.randint(10, 10000) + return _create_kpi_value_request diff --git a/src/kpi_value_writer/tests/test_metric_writer_to_prom.py b/src/kpi_value_writer/tests/test_metric_writer_to_prom.py new file mode 100644 index 0000000000000000000000000000000000000000..e8f97c8a7650ece493eaaee345d6645a7c9625c6 --- /dev/null +++ b/src/kpi_value_writer/tests/test_metric_writer_to_prom.py @@ -0,0 +1,28 @@ +# 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 threading +import logging +from kpi_value_writer.service.MetricWriterToPrometheus import MetricWriterToPrometheus +from kpi_value_writer.tests.test_messages import create_kpi_descriptor_request, create_kpi_value_request + +LOGGER = logging.getLogger(__name__) + +def test_metric_writer_to_prometheus(): + LOGGER.info(' >>> test_metric_writer_to_prometheus START <<< ') + metric_writer_obj = MetricWriterToPrometheus() + metric_writer_obj.create_and_expose_cooked_kpi( + create_kpi_descriptor_request(), + create_kpi_value_request() + ) diff --git a/src/l3_attackmitigator/.gitlab-ci.yml b/src/l3_attackmitigator/.gitlab-ci.yml index afc3c32d629275e2bb6465f38df6ff0e41c18daf..a1d6a3de8461a1ac960ae82887db01bb6a55fe59 100644 --- a/src/l3_attackmitigator/.gitlab-ci.yml +++ b/src/l3_attackmitigator/.gitlab-ci.yml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_attackmitigator/Config.py b/src/l3_attackmitigator/Config.py index e82dc4f0dd4cb94713ababc71d34ea7274abc3c5..622336889539fbcc44ec3f95463aa82ac7fa69a8 100644 --- a/src/l3_attackmitigator/Config.py +++ b/src/l3_attackmitigator/Config.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_attackmitigator/Dockerfile b/src/l3_attackmitigator/Dockerfile index 4622f6f9b9a0cfb4d55f758612026f74d9de45e7..9d80570fa284cd63de2e55f5b61f79b9a6852616 100644 --- a/src/l3_attackmitigator/Dockerfile +++ b/src/l3_attackmitigator/Dockerfile @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_attackmitigator/__init__.py b/src/l3_attackmitigator/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/l3_attackmitigator/__init__.py +++ b/src/l3_attackmitigator/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_attackmitigator/client/__init__.py b/src/l3_attackmitigator/client/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/l3_attackmitigator/client/__init__.py +++ b/src/l3_attackmitigator/client/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_attackmitigator/client/l3_attackmitigatorClient.py b/src/l3_attackmitigator/client/l3_attackmitigatorClient.py index a2bcdae40e0d1d5c4e5315af06a9247ce7850cc6..02e56bcffd46c7bffa523c9ecfa0a3aa376deca9 100644 --- a/src/l3_attackmitigator/client/l3_attackmitigatorClient.py +++ b/src/l3_attackmitigator/client/l3_attackmitigatorClient.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_attackmitigator/requirements.in b/src/l3_attackmitigator/requirements.in index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/l3_attackmitigator/requirements.in +++ b/src/l3_attackmitigator/requirements.in @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_attackmitigator/service/__init__.py b/src/l3_attackmitigator/service/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/l3_attackmitigator/service/__init__.py +++ b/src/l3_attackmitigator/service/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_attackmitigator/service/__main__.py b/src/l3_attackmitigator/service/__main__.py index 3a0263e25a65073e1d7199c8cc978efd05cc493d..8a54ef66c2b32aefb1a37b21e8b8fdd01e1ca482 100644 --- a/src/l3_attackmitigator/service/__main__.py +++ b/src/l3_attackmitigator/service/__main__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_attackmitigator/service/l3_attackmitigatorService.py b/src/l3_attackmitigator/service/l3_attackmitigatorService.py index 7794041bd9f25666b2c4417834b8b41fa10a624f..560c04b9291e4a3f49af0e19fe01956e41aa202d 100644 --- a/src/l3_attackmitigator/service/l3_attackmitigatorService.py +++ b/src/l3_attackmitigator/service/l3_attackmitigatorService.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_attackmitigator/service/l3_attackmitigatorServiceServicerImpl.py b/src/l3_attackmitigator/service/l3_attackmitigatorServiceServicerImpl.py index 6b2a65c9822d749a86db9a18b51626d12c6ba173..70464d3169f84b9fb2603a1830e8f4a0fd407774 100644 --- a/src/l3_attackmitigator/service/l3_attackmitigatorServiceServicerImpl.py +++ b/src/l3_attackmitigator/service/l3_attackmitigatorServiceServicerImpl.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_attackmitigator/tests/__init__.py b/src/l3_attackmitigator/tests/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/l3_attackmitigator/tests/__init__.py +++ b/src/l3_attackmitigator/tests/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_attackmitigator/tests/test_unitary.py b/src/l3_attackmitigator/tests/test_unitary.py index 53d09a227350eb127ab684c210cea6d56bcb7ac1..650dae098b6020586619b434c1dda68a98e4ddc3 100644 --- a/src/l3_attackmitigator/tests/test_unitary.py +++ b/src/l3_attackmitigator/tests/test_unitary.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_centralizedattackdetector/.gitlab-ci.yml b/src/l3_centralizedattackdetector/.gitlab-ci.yml index 1b047aef8205e5852a4b30a7234ebfdad7686358..65c4b32a8c78a79441d23f085aa95b1bf46c7614 100644 --- a/src/l3_centralizedattackdetector/.gitlab-ci.yml +++ b/src/l3_centralizedattackdetector/.gitlab-ci.yml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_centralizedattackdetector/Config.py b/src/l3_centralizedattackdetector/Config.py index afff93eb5250214389aa082b0a0c16255482adcf..9ffe3f07109e26316029c0b888c8dcb2ef9fbe0d 100644 --- a/src/l3_centralizedattackdetector/Config.py +++ b/src/l3_centralizedattackdetector/Config.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_centralizedattackdetector/Dockerfile b/src/l3_centralizedattackdetector/Dockerfile index a294014ac02d8377db5bd848a5d7e07643658de6..718b4ff951dbcf10034f1cd1269220f9cc4efddd 100644 --- a/src/l3_centralizedattackdetector/Dockerfile +++ b/src/l3_centralizedattackdetector/Dockerfile @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_centralizedattackdetector/__init__.py b/src/l3_centralizedattackdetector/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/l3_centralizedattackdetector/__init__.py +++ b/src/l3_centralizedattackdetector/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_centralizedattackdetector/client/__init__.py b/src/l3_centralizedattackdetector/client/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/l3_centralizedattackdetector/client/__init__.py +++ b/src/l3_centralizedattackdetector/client/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_centralizedattackdetector/client/l3_centralizedattackdetectorClient.py b/src/l3_centralizedattackdetector/client/l3_centralizedattackdetectorClient.py index 02aed22b40831dee4ee5e0eeec36822e481220be..7204bf5dc87154d946a48108a299848ed44e6166 100644 --- a/src/l3_centralizedattackdetector/client/l3_centralizedattackdetectorClient.py +++ b/src/l3_centralizedattackdetector/client/l3_centralizedattackdetectorClient.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_centralizedattackdetector/requirements.in b/src/l3_centralizedattackdetector/requirements.in index 34513101381471027dbdbab4d3a615e057acd92e..fafb057a2e354c5055574fd35d129e026ced910c 100644 --- a/src/l3_centralizedattackdetector/requirements.in +++ b/src/l3_centralizedattackdetector/requirements.in @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -12,6 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -numpy==1.23.* +numpy<2.0.0 onnxruntime==1.12.* scikit-learn==1.1.* diff --git a/src/l3_centralizedattackdetector/service/__init__.py b/src/l3_centralizedattackdetector/service/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/l3_centralizedattackdetector/service/__init__.py +++ b/src/l3_centralizedattackdetector/service/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_centralizedattackdetector/service/__main__.py b/src/l3_centralizedattackdetector/service/__main__.py index c03f77f4287de25a407dfadcaa0a1730678d1a66..aedde01427cbc519d9787cc9611284a9844645fe 100644 --- a/src/l3_centralizedattackdetector/service/__main__.py +++ b/src/l3_centralizedattackdetector/service/__main__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_centralizedattackdetector/service/l3_centralizedattackdetectorService.py b/src/l3_centralizedattackdetector/service/l3_centralizedattackdetectorService.py index b9367a51153bcbf1d1ac13a5ab64491c3d20ab97..ef5182d2bfa675afbf9a574ba6de9b5ac245e7d5 100644 --- a/src/l3_centralizedattackdetector/service/l3_centralizedattackdetectorService.py +++ b/src/l3_centralizedattackdetector/service/l3_centralizedattackdetectorService.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_centralizedattackdetector/service/l3_centralizedattackdetectorServiceServicerImpl.py b/src/l3_centralizedattackdetector/service/l3_centralizedattackdetectorServiceServicerImpl.py index b03ee98f5c401445cf59f3c7b918a5af7fcd0318..16e88760086c0d3fd1ce7d2254201fbb9fe0ce18 100644 --- a/src/l3_centralizedattackdetector/service/l3_centralizedattackdetectorServiceServicerImpl.py +++ b/src/l3_centralizedattackdetector/service/l3_centralizedattackdetectorServiceServicerImpl.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_centralizedattackdetector/tests/__init__.py b/src/l3_centralizedattackdetector/tests/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/l3_centralizedattackdetector/tests/__init__.py +++ b/src/l3_centralizedattackdetector/tests/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_centralizedattackdetector/tests/test_unitary.py b/src/l3_centralizedattackdetector/tests/test_unitary.py index b11be4862295eb17afd7e4be7bd60964e485a8dc..36f70dd6161afaf386cb1db5cf72e661283b3f99 100644 --- a/src/l3_centralizedattackdetector/tests/test_unitary.py +++ b/src/l3_centralizedattackdetector/tests/test_unitary.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_distributedattackdetector/.gitlab-ci.yml b/src/l3_distributedattackdetector/.gitlab-ci.yml index 1ab68357354c13edb3722498501d6a2d2445d795..a833e3ac1aadc48843db71c80532395997a34ba5 100644 --- a/src/l3_distributedattackdetector/.gitlab-ci.yml +++ b/src/l3_distributedattackdetector/.gitlab-ci.yml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_distributedattackdetector/Config.py b/src/l3_distributedattackdetector/Config.py index bf344455f537c5b363d8fa4c737ccff57b145e08..8ee308efa202f0bf27e77a2a39fd500cb179d381 100644 --- a/src/l3_distributedattackdetector/Config.py +++ b/src/l3_distributedattackdetector/Config.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_distributedattackdetector/Dockerfile b/src/l3_distributedattackdetector/Dockerfile index fd1a38483d49e6debdbe981d547268374bb5fc7b..95914d22e5a1219fd0fd2d63b47c8f2e147dbeca 100644 --- a/src/l3_distributedattackdetector/Dockerfile +++ b/src/l3_distributedattackdetector/Dockerfile @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_distributedattackdetector/__init__.py b/src/l3_distributedattackdetector/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/l3_distributedattackdetector/__init__.py +++ b/src/l3_distributedattackdetector/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_distributedattackdetector/requirements.in b/src/l3_distributedattackdetector/requirements.in index 6deb8d906f733e25bfac07bbe82b536b4774f5bb..602570408f0005fcb1ec17419544045c901eb779 100644 --- a/src/l3_distributedattackdetector/requirements.in +++ b/src/l3_distributedattackdetector/requirements.in @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -12,5 +12,5 @@ # See the License for the specific language governing permissions and # limitations under the License. -numpy==1.23.* +numpy<2.0.0 asyncio==3.4.3 diff --git a/src/l3_distributedattackdetector/service/__init__.py b/src/l3_distributedattackdetector/service/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/l3_distributedattackdetector/service/__init__.py +++ b/src/l3_distributedattackdetector/service/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_distributedattackdetector/service/__main__.py b/src/l3_distributedattackdetector/service/__main__.py index a46177611453824d7fe80506539f129776041897..bc14e05210feb994cec50ae2b95413b8f9706431 100644 --- a/src/l3_distributedattackdetector/service/__main__.py +++ b/src/l3_distributedattackdetector/service/__main__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_distributedattackdetector/service/l3_distributedattackdetector.py b/src/l3_distributedattackdetector/service/l3_distributedattackdetector.py index c841b21b451168ec74660b5df5fd218ab1d66cba..517ef42d3464b070cbf9f0132e76132b44635cde 100644 --- a/src/l3_distributedattackdetector/service/l3_distributedattackdetector.py +++ b/src/l3_distributedattackdetector/service/l3_distributedattackdetector.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_distributedattackdetector/tests/__init__.py b/src/l3_distributedattackdetector/tests/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/l3_distributedattackdetector/tests/__init__.py +++ b/src/l3_distributedattackdetector/tests/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_distributedattackdetector/tests/data_generator.py b/src/l3_distributedattackdetector/tests/data_generator.py index 02efcdc321dce1adb932e91d51a65a1f87ca7ece..ba9e3df5c35b58fd95e05af7d5eba1f305c6540a 100644 --- a/src/l3_distributedattackdetector/tests/data_generator.py +++ b/src/l3_distributedattackdetector/tests/data_generator.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/l3_distributedattackdetector/tests/test_unitary.py b/src/l3_distributedattackdetector/tests/test_unitary.py index 3d54cb7d269617ae819353721f9a1b504e8e3d93..a60ab9f798bbb57252c96cf5483aed290c818715 100644 --- a/src/l3_distributedattackdetector/tests/test_unitary.py +++ b/src/l3_distributedattackdetector/tests/test_unitary.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/load_generator/.gitlab-ci.yml b/src/load_generator/.gitlab-ci.yml index 5664c4dc53c6b62f20fba45749e5911a2505a04e..28ac0fbd11d49e8e56483fca57ace23c8efb675e 100644 --- a/src/load_generator/.gitlab-ci.yml +++ b/src/load_generator/.gitlab-ci.yml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/load_generator/Config.py b/src/load_generator/Config.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/load_generator/Config.py +++ b/src/load_generator/Config.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/load_generator/Dockerfile b/src/load_generator/Dockerfile index 243b908d5c95f41f6afeb1f42b87d3257056a5ba..3ef1470f4696f96f0a6d69af99d2daabb2c8540c 100644 --- a/src/load_generator/Dockerfile +++ b/src/load_generator/Dockerfile @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/load_generator/__init__.py b/src/load_generator/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/load_generator/__init__.py +++ b/src/load_generator/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/load_generator/client/LoadGeneratorClient.py b/src/load_generator/client/LoadGeneratorClient.py index 688184b6d48058f7b7553fb0c0ac195bf789f9b6..7ef15c1ca084f4e13b31ddb04e831fc0972b6963 100644 --- a/src/load_generator/client/LoadGeneratorClient.py +++ b/src/load_generator/client/LoadGeneratorClient.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/load_generator/client/__init__.py b/src/load_generator/client/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/load_generator/client/__init__.py +++ b/src/load_generator/client/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/load_generator/command/__init__.py b/src/load_generator/command/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/load_generator/command/__init__.py +++ b/src/load_generator/command/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/load_generator/command/__main__.py b/src/load_generator/command/__main__.py index d47a8290bddc910fd34f80860962ca59dffe95a9..914758a8d252c8096696a0ce799a467339a92f9c 100644 --- a/src/load_generator/command/__main__.py +++ b/src/load_generator/command/__main__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/load_generator/load_gen/Constants.py b/src/load_generator/load_gen/Constants.py index e4f34d50a34c7673cd949cf321736f88a70ea64c..7f1612dc710c34694b983c70e6023d0964212fe8 100644 --- a/src/load_generator/load_gen/Constants.py +++ b/src/load_generator/load_gen/Constants.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/load_generator/load_gen/DltTools.py b/src/load_generator/load_gen/DltTools.py index 0ac7ab3f03d29480b0e57cc9993b71c4d8324d76..8f2078cdb42c681a88176d5f9d6d4321031dd76a 100644 --- a/src/load_generator/load_gen/DltTools.py +++ b/src/load_generator/load_gen/DltTools.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/load_generator/load_gen/Parameters.py b/src/load_generator/load_gen/Parameters.py index adc551cd23e72565b3cc40989f7e533b849bc3af..64f321d9a45abb38e3576cf63bbf13123a61f755 100644 --- a/src/load_generator/load_gen/Parameters.py +++ b/src/load_generator/load_gen/Parameters.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/load_generator/load_gen/RequestGenerator.py b/src/load_generator/load_gen/RequestGenerator.py index 2a3e89fe02bc2a8267d203d3134c65983cb985f2..45c88a66aedde3bd6a04196247de7045efd64ea5 100644 --- a/src/load_generator/load_gen/RequestGenerator.py +++ b/src/load_generator/load_gen/RequestGenerator.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/load_generator/load_gen/RequestScheduler.py b/src/load_generator/load_gen/RequestScheduler.py index 3bc9486dc67121f52961c5397859f1aec28b9fab..206c556548126368577ce4f8e4f47abf83697ed8 100644 --- a/src/load_generator/load_gen/RequestScheduler.py +++ b/src/load_generator/load_gen/RequestScheduler.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/load_generator/load_gen/__init__.py b/src/load_generator/load_gen/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/load_generator/load_gen/__init__.py +++ b/src/load_generator/load_gen/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/load_generator/requirements.in b/src/load_generator/requirements.in index 8a92ca4ea18ecde0c1f8e9ff74b932fcac3fb6a0..c7552cd3b310bf43da4b6888c552404e6695b906 100644 --- a/src/load_generator/requirements.in +++ b/src/load_generator/requirements.in @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/load_generator/run.sh b/src/load_generator/run.sh index 08572a31c18520ae46faab8c56daa59a13f22e61..3fa87d5dc584f3a1ccb7965f00a08d0c30d456b1 100755 --- a/src/load_generator/run.sh +++ b/src/load_generator/run.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/load_generator/service/Constants.py b/src/load_generator/service/Constants.py index 5053dc5fecf9a033a1de7dd14af3a95bd142b9c6..9835fec7e665288a9e38de67995b933ce8777188 100644 --- a/src/load_generator/service/Constants.py +++ b/src/load_generator/service/Constants.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/load_generator/service/LoadGeneratorService.py b/src/load_generator/service/LoadGeneratorService.py index 2c99d7da7776a0952ad0ae00455bc5e2f5e29ed0..ff4ab2295620116d1723589ca20450cdb55138e7 100644 --- a/src/load_generator/service/LoadGeneratorService.py +++ b/src/load_generator/service/LoadGeneratorService.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/load_generator/service/LoadGeneratorServiceServicerImpl.py b/src/load_generator/service/LoadGeneratorServiceServicerImpl.py index ff32f23a67e83fd3bda4a0acf166b2e1bb9abacb..29e0264290ad4cc9d13185b74651a850a3e5b657 100644 --- a/src/load_generator/service/LoadGeneratorServiceServicerImpl.py +++ b/src/load_generator/service/LoadGeneratorServiceServicerImpl.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/load_generator/service/__init__.py b/src/load_generator/service/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/load_generator/service/__init__.py +++ b/src/load_generator/service/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/load_generator/service/__main__.py b/src/load_generator/service/__main__.py index 933fdad31e3bd430aa5cd2e61026c90c1a51a33f..989f2fae99f72f16e5ecd82c830a7afae992d25e 100644 --- a/src/load_generator/service/__main__.py +++ b/src/load_generator/service/__main__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/load_generator/tests/__init__.py b/src/load_generator/tests/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/load_generator/tests/__init__.py +++ b/src/load_generator/tests/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/load_generator/tests/deploy_specs.sh b/src/load_generator/tests/deploy_specs.sh index 3a85d615bf61cd5ef88dcd3d2499592c5999e927..851e6a4354ea46733d0259c703744bb19fd8d852 100755 --- a/src/load_generator/tests/deploy_specs.sh +++ b/src/load_generator/tests/deploy_specs.sh @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/load_generator/tests/test_dlt_functional.py b/src/load_generator/tests/test_dlt_functional.py index f3dea3b4a83ed59cfb137eba03d312f4c87f0d45..5e9cdd7300850075a0f90eea80249022250c6447 100644 --- a/src/load_generator/tests/test_dlt_functional.py +++ b/src/load_generator/tests/test_dlt_functional.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/load_generator/tools/ListScalarRange.py b/src/load_generator/tools/ListScalarRange.py index a41ca22eb3ddccf5e420f7d46cd6d13a157b84a6..f62360dc798012a34ab1aae218196ce476306909 100644 --- a/src/load_generator/tools/ListScalarRange.py +++ b/src/load_generator/tools/ListScalarRange.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/load_generator/tools/__init__.py b/src/load_generator/tools/__init__.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/load_generator/tools/__init__.py +++ b/src/load_generator/tools/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/monitoring/.gitlab-ci.yml b/src/monitoring/.gitlab-ci.yml index 73365dfada1715e689f58fe94d7451cc9df9c155..3d1e7009aad7a5ca885d0a4470f30fe62d950336 100644 --- a/src/monitoring/.gitlab-ci.yml +++ b/src/monitoring/.gitlab-ci.yml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/monitoring/Dockerfile b/src/monitoring/Dockerfile index af308d06002a0461f51ea56366222a76e100dc69..1c7a03c534c653c55dc02fb78a5556bcfb285036 100644 --- a/src/monitoring/Dockerfile +++ b/src/monitoring/Dockerfile @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/monitoring/__init__.py b/src/monitoring/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/monitoring/__init__.py +++ b/src/monitoring/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/monitoring/client/MonitoringClient.py b/src/monitoring/client/MonitoringClient.py index 994cede8e2606a53606af1c5ed8d2b6544d473fb..13cc1a4a5c991340aeffc6e56bb89af79e27eb23 100644 --- a/src/monitoring/client/MonitoringClient.py +++ b/src/monitoring/client/MonitoringClient.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/monitoring/client/__init__.py b/src/monitoring/client/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/monitoring/client/__init__.py +++ b/src/monitoring/client/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/monitoring/requirements.in b/src/monitoring/requirements.in index 8684cb22350416818c20e881993a62d4f10a2e9e..b888a579f328e74ca7a4d1905b2b8dc1958a98d9 100644 --- a/src/monitoring/requirements.in +++ b/src/monitoring/requirements.in @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -18,7 +18,7 @@ APScheduler==3.10.1 #google-api-core #opencensus[stackdriver] #google-cloud-profiler -#numpy +numpy<2.0.0 #Jinja2==3.0.3 #ncclient==0.6.13 #p4runtime==1.3.0 diff --git a/src/monitoring/service/AlarmManager.py b/src/monitoring/service/AlarmManager.py index e71464c418567fdf1773ec913166ce3c1d3fe26e..3d1cf68cc056cee94dd064eb3a3d8e16b9f00c87 100644 --- a/src/monitoring/service/AlarmManager.py +++ b/src/monitoring/service/AlarmManager.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/monitoring/service/EventTools.py b/src/monitoring/service/EventTools.py index 7820f11c86e87f543087c88704572e1a169c6e7d..146092f032608826366ee91ef8e33031278b1cde 100644 --- a/src/monitoring/service/EventTools.py +++ b/src/monitoring/service/EventTools.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -108,12 +108,15 @@ class EventsDeviceCollector: if config_rule.action != ConfigActionEnum.CONFIGACTION_SET: continue if config_rule.WhichOneof('config_rule') != 'custom': continue str_resource_key = str(config_rule.custom.resource_key) - if not str_resource_key.startswith('/interface['): continue - json_resource_value = json.loads(config_rule.custom.resource_value) - if 'name' not in json_resource_value: continue - if 'enabled' not in json_resource_value: continue - if not json_resource_value['enabled']: continue - enabled_endpoint_names.add(json_resource_value['name']) + if str_resource_key.startswith('/interface[') or str_resource_key.startswith('/endpoints/endpoint['): + json_resource_value = json.loads(config_rule.custom.resource_value) + if 'name' not in json_resource_value: continue + if 'enabled' in json_resource_value: + if not json_resource_value['enabled']: continue + enabled_endpoint_names.add(json_resource_value['name']) + if 'oper-status' in json_resource_value: + if str(json_resource_value['oper-status']).upper() != 'UP': continue + enabled_endpoint_names.add(json_resource_value['name']) endpoints_monitored = self._device_endpoint_monitored.setdefault(device_uuid, dict()) for endpoint in device.device_endpoints: @@ -127,7 +130,10 @@ class EventsDeviceCollector: endpoint_was_monitored = endpoints_monitored.get(endpoint_uuid, False) endpoint_is_enabled = (endpoint_name_or_uuid in enabled_endpoint_names) - if not endpoint_was_monitored and endpoint_is_enabled: + if not endpoint_was_monitored and not endpoint_is_enabled: + # endpoint is idle, do nothing + pass + elif not endpoint_was_monitored and endpoint_is_enabled: # activate for value in endpoint.kpi_sample_types: if value == KPISAMPLETYPE_UNKNOWN: continue diff --git a/src/monitoring/service/InfluxTools.py b/src/monitoring/service/InfluxTools.py index 152114faf01314324bdab4d7e1d6980d2f728002..93de12a2aa0cfe8c3bda84e4da56ad89dee51536 100644 --- a/src/monitoring/service/InfluxTools.py +++ b/src/monitoring/service/InfluxTools.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/monitoring/service/ManagementDBTools.py b/src/monitoring/service/ManagementDBTools.py index eb249dad65fdb7298a37bb067b54d6e22533e9e3..cdff894709e897e990371e86cf623a82a04f98a9 100644 --- a/src/monitoring/service/ManagementDBTools.py +++ b/src/monitoring/service/ManagementDBTools.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/monitoring/service/MetricsDBTools.py b/src/monitoring/service/MetricsDBTools.py index 5f387dbb5471750439d99d4ee988f33f182e7d4f..f722a0a334b3d0e0ecfd4d6fde3d7008bc1ea4d4 100644 --- a/src/monitoring/service/MetricsDBTools.py +++ b/src/monitoring/service/MetricsDBTools.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/monitoring/service/MonitoringService.py b/src/monitoring/service/MonitoringService.py index 9e78b149ff7b4e55f63432765eb06a8ab6843ee3..7252f15ee1a0acefe2d6143501452ada19e00270 100644 --- a/src/monitoring/service/MonitoringService.py +++ b/src/monitoring/service/MonitoringService.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/monitoring/service/MonitoringServiceServicerImpl.py b/src/monitoring/service/MonitoringServiceServicerImpl.py index e7025969172482ebc7c964bbc94d698824ee6966..2ec1091c4e2b89272a1ae0662ed5337e93f9fe73 100644 --- a/src/monitoring/service/MonitoringServiceServicerImpl.py +++ b/src/monitoring/service/MonitoringServiceServicerImpl.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/monitoring/service/NameMapping.py b/src/monitoring/service/NameMapping.py index f98e367b17b4a2e4c7c6f3dcdb90dfb8ee24d3ad..60cc69c60366f2586db0f153ab2627bd468cd9e4 100644 --- a/src/monitoring/service/NameMapping.py +++ b/src/monitoring/service/NameMapping.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/monitoring/service/SubscriptionManager.py b/src/monitoring/service/SubscriptionManager.py index 9e775315573dd1f9bb84b4d7de6b0f99755b3a96..55a35c0b815bef0e7f4583323c51f1ce2217b892 100644 --- a/src/monitoring/service/SubscriptionManager.py +++ b/src/monitoring/service/SubscriptionManager.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/monitoring/service/__init__.py b/src/monitoring/service/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/monitoring/service/__init__.py +++ b/src/monitoring/service/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/monitoring/service/__main__.py b/src/monitoring/service/__main__.py index b3c4765beb4809dd66f71e60844abda5af43083f..751dc9990835733a0fdd3d863566961699433d96 100644 --- a/src/monitoring/service/__main__.py +++ b/src/monitoring/service/__main__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/monitoring/tests/Messages.py b/src/monitoring/tests/Messages.py index a6ea6f74a7a727e4d23ea54ad51fa032c736c271..da9219e04726ae96bef7f7f29c847d2d420e6045 100644 --- a/src/monitoring/tests/Messages.py +++ b/src/monitoring/tests/Messages.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/monitoring/tests/Objects.py b/src/monitoring/tests/Objects.py index 09354bd18b910d281f907deed9f218d6b21b5000..fa6ad43edb7b2de2d70ba7cdb2a129d6b5b1479b 100644 --- a/src/monitoring/tests/Objects.py +++ b/src/monitoring/tests/Objects.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/monitoring/tests/__init__.py b/src/monitoring/tests/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/monitoring/tests/__init__.py +++ b/src/monitoring/tests/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/monitoring/tests/test_unitary.py b/src/monitoring/tests/test_unitary.py index 6838d66f3102aaf43bca913c8bb3266e10b4a4e8..f3b8beebc62c975f47b643e9b14a0e6c81aa76d2 100644 --- a/src/monitoring/tests/test_unitary.py +++ b/src/monitoring/tests/test_unitary.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/.gitlab-ci.yml b/src/nbi/.gitlab-ci.yml index 5f4e45366fff439aee3afe29edae5b0b8356a053..71bf223ba9408e178e252d600c625dc2256dbe92 100644 --- a/src/nbi/.gitlab-ci.yml +++ b/src/nbi/.gitlab-ci.yml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/Config.py b/src/nbi/Config.py index d715ba5d71ee186c31b83f2c07b1dc1d2c9ce4be..83a35005855d60b714259c6b671c7210cf14331d 100644 --- a/src/nbi/Config.py +++ b/src/nbi/Config.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/Dockerfile b/src/nbi/Dockerfile index 1435e9757226e290e92f208ef48a7182eb106c55..a9be06d37c15757f51d6d849f395d683885e9508 100644 --- a/src/nbi/Dockerfile +++ b/src/nbi/Dockerfile @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -16,9 +16,24 @@ FROM python:3.9-slim # Install dependencies RUN apt-get --yes --quiet --quiet update && \ - apt-get --yes --quiet --quiet install wget g++ git && \ + apt-get --yes --quiet --quiet install wget g++ git build-essential cmake libpcre2-dev python3-dev python3-cffi && \ rm -rf /var/lib/apt/lists/* +# Download, build and install libyang. Note that APT package is outdated +# - Ref: https://github.com/CESNET/libyang +# - Ref: https://github.com/CESNET/libyang-python/ +RUN mkdir -p /var/libyang +RUN git clone https://github.com/CESNET/libyang.git /var/libyang +WORKDIR /var/libyang +RUN git fetch +RUN git checkout v2.1.148 +RUN mkdir -p /var/libyang/build +WORKDIR /var/libyang/build +RUN cmake -D CMAKE_BUILD_TYPE:String="Release" .. +RUN make +RUN make install +RUN ldconfig + # Set Python to show logs as they occur ENV PYTHONUNBUFFERED=0 @@ -53,24 +68,6 @@ 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' {} \; -# Download, build and install libyang. Note that APT package is outdated -# - Ref: https://github.com/CESNET/libyang -# - Ref: https://github.com/CESNET/libyang-python/ -RUN apt-get --yes --quiet --quiet update && \ - apt-get --yes --quiet --quiet install build-essential cmake libpcre2-dev python3-dev python3-cffi && \ - rm -rf /var/lib/apt/lists/* -RUN mkdir -p /var/libyang -RUN git clone https://github.com/CESNET/libyang.git /var/libyang -WORKDIR /var/libyang -RUN git fetch -RUN git checkout v2.1.148 -RUN mkdir -p /var/libyang/build -WORKDIR /var/libyang/build -RUN cmake -D CMAKE_BUILD_TYPE:String="Release" .. -RUN make -RUN make install -RUN ldconfig - # Create component sub-folders, get specific Python packages RUN mkdir -p /var/teraflow/nbi WORKDIR /var/teraflow/nbi @@ -89,6 +86,10 @@ COPY src/service/__init__.py service/__init__.py COPY src/service/client/. service/client/ COPY src/slice/__init__.py slice/__init__.py COPY src/slice/client/. slice/client/ +COPY src/qkd_app/__init__.py qkd_app/__init__.py +COPY src/qkd_app/client/. qkd_app/client/ +COPY src/vnt_manager/__init__.py vnt_manager/__init__.py +COPY src/vnt_manager/client/. vnt_manager/client/ RUN mkdir -p /var/teraflow/tests/tools COPY src/tests/tools/mock_osm/. tests/tools/mock_osm/ diff --git a/src/nbi/__init__.py b/src/nbi/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/nbi/__init__.py +++ b/src/nbi/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/client/NbiClient.py b/src/nbi/client/NbiClient.py index d7eb27486e70968b1dc66e8a6296103a2b8ca440..043035c5a4b0612652b1473ac6deeaa9e3cfce19 100644 --- a/src/nbi/client/NbiClient.py +++ b/src/nbi/client/NbiClient.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/client/__init__.py b/src/nbi/client/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/nbi/client/__init__.py +++ b/src/nbi/client/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/requirements.in b/src/nbi/requirements.in index 78d941974c62e32251373a805056068608b0bda2..0d780483626979cc993a984d3da709762c749d56 100644 --- a/src/nbi/requirements.in +++ b/src/nbi/requirements.in @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -22,5 +22,7 @@ libyang==2.8.0 netaddr==0.9.0 pyang==2.6.0 git+https://github.com/robshakir/pyangbind.git +pydantic==2.6.3 requests==2.27.1 werkzeug==2.3.7 +websockets==12.0 diff --git a/src/nbi/service/NbiService.py b/src/nbi/service/NbiService.py index d8886cf38e7bb6d6dd973fdfd5aa4f7e564c31ee..fe7bf2e7b22271ea27746084ebee831257aa43d0 100644 --- a/src/nbi/service/NbiService.py +++ b/src/nbi/service/NbiService.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/NbiServiceServicerImpl.py b/src/nbi/service/NbiServiceServicerImpl.py index b1d62afb11709d9ee237bc1f840b803674923c00..5719b67e4bb7a151d1f668132c7a8dc7073d4948 100644 --- a/src/nbi/service/NbiServiceServicerImpl.py +++ b/src/nbi/service/NbiServiceServicerImpl.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -20,7 +20,7 @@ from common.proto.nbi_pb2_grpc import NbiServiceServicer LOGGER = logging.getLogger(__name__) -METRICS_POOL = MetricsPool('Compute', 'RPC') +METRICS_POOL = MetricsPool('NBI', 'RPC') class NbiServiceServicerImpl(NbiServiceServicer): def __init__(self): diff --git a/src/nbi/service/__init__.py b/src/nbi/service/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/nbi/service/__init__.py +++ b/src/nbi/service/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/__main__.py b/src/nbi/service/__main__.py index 362b0116d6f0bdbc4d1fa2025c09ac23c828617f..71df0517aa688c106d8d0fe544f5f6b1af5a58f3 100644 --- a/src/nbi/service/__main__.py +++ b/src/nbi/service/__main__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -16,16 +16,22 @@ import logging, signal, sys, threading from prometheus_client import start_http_server from common.Constants import ServiceNameEnum from common.Settings import ( - ENVVAR_SUFIX_SERVICE_HOST, ENVVAR_SUFIX_SERVICE_PORT_GRPC, get_env_var_name, get_log_level, get_metrics_port, - wait_for_environment_variables) + ENVVAR_SUFIX_SERVICE_HOST, ENVVAR_SUFIX_SERVICE_PORT_GRPC, + get_env_var_name, get_log_level, get_metrics_port, + wait_for_environment_variables +) from .NbiService import NbiService from .rest_server.RestServer import RestServer from .rest_server.nbi_plugins.etsi_bwm import register_etsi_bwm_api +from .rest_server.nbi_plugins.ietf_hardware import register_ietf_hardware from .rest_server.nbi_plugins.ietf_l2vpn import register_ietf_l2vpn from .rest_server.nbi_plugins.ietf_l3vpn import register_ietf_l3vpn from .rest_server.nbi_plugins.ietf_network import register_ietf_network from .rest_server.nbi_plugins.ietf_network_slice import register_ietf_nss +from .rest_server.nbi_plugins.ietf_acl import register_ietf_acl +from .rest_server.nbi_plugins.qkd_app import register_qkd_app from .rest_server.nbi_plugins.tfs_api import register_tfs_api +from .context_subscription import register_context_subscription terminate = threading.Event() LOGGER = None @@ -44,8 +50,10 @@ def main(): wait_for_environment_variables([ get_env_var_name(ServiceNameEnum.CONTEXT, ENVVAR_SUFIX_SERVICE_HOST ), get_env_var_name(ServiceNameEnum.CONTEXT, ENVVAR_SUFIX_SERVICE_PORT_GRPC), - get_env_var_name(ServiceNameEnum.SLICE, ENVVAR_SUFIX_SERVICE_HOST ), - get_env_var_name(ServiceNameEnum.SLICE, ENVVAR_SUFIX_SERVICE_PORT_GRPC), + get_env_var_name(ServiceNameEnum.DEVICE, ENVVAR_SUFIX_SERVICE_HOST ), + get_env_var_name(ServiceNameEnum.DEVICE, ENVVAR_SUFIX_SERVICE_PORT_GRPC), + get_env_var_name(ServiceNameEnum.SERVICE, ENVVAR_SUFIX_SERVICE_HOST ), + get_env_var_name(ServiceNameEnum.SERVICE, ENVVAR_SUFIX_SERVICE_PORT_GRPC), ]) signal.signal(signal.SIGINT, signal_handler) @@ -63,13 +71,26 @@ def main(): rest_server = RestServer() register_etsi_bwm_api(rest_server) + register_ietf_hardware(rest_server) register_ietf_l2vpn(rest_server) # Registering L2VPN entrypoint register_ietf_l3vpn(rest_server) # Registering L3VPN entrypoint register_ietf_network(rest_server) register_ietf_nss(rest_server) # Registering NSS entrypoint + register_ietf_acl(rest_server) + register_qkd_app(rest_server) register_tfs_api(rest_server) rest_server.start() + register_context_subscription() + + LOGGER.debug('Configured Resources:') + for resource in rest_server.api.resources: + LOGGER.debug(' - {:s}'.format(str(resource))) + + LOGGER.debug('Configured Rules:') + for rule in rest_server.app.url_map.iter_rules(): + LOGGER.debug(' - {:s}'.format(str(rule))) + # Wait for Ctrl+C or termination signal while not terminate.wait(timeout=1.0): pass diff --git a/src/nbi/service/context_subscription/__init__.py b/src/nbi/service/context_subscription/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..758f3d82c538fe364add40cc5119f745aea1dc34 --- /dev/null +++ b/src/nbi/service/context_subscription/__init__.py @@ -0,0 +1,64 @@ +# 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 + +from websockets.sync.server import serve +from common.proto.vnt_manager_pb2 import VNTSubscriptionRequest +from common.Settings import get_setting +from context.client.ContextClient import ContextClient +from common.Constants import DEFAULT_CONTEXT_NAME, DEFAULT_TOPOLOGY_NAME +from common.tools.object_factory.Topology import json_topology_id +from common.tools.object_factory.Context import json_context_id +from common.proto.context_pb2 import ContextId, TopologyId +import json +import os +from vnt_manager.client.VNTManagerClient import VNTManagerClient + +JSON_ADMIN_CONTEXT_ID = json_context_id(DEFAULT_CONTEXT_NAME) +ADMIN_CONTEXT_ID = ContextId(**JSON_ADMIN_CONTEXT_ID) +ADMIN_TOPOLOGY_ID = TopologyId(**json_topology_id(DEFAULT_TOPOLOGY_NAME, context_id=JSON_ADMIN_CONTEXT_ID)) + +vnt_manager_client: VNTManagerClient = VNTManagerClient() +context_client: ContextClient = ContextClient() + +ALL_HOSTS = "0.0.0.0" +WS_E2E_PORT = int(get_setting('WS_E2E_PORT', default='8762')) + +LOGGER = logging.getLogger(__name__) + + +def register_context_subscription(): + with serve(subcript_to_vnt_manager, ALL_HOSTS, WS_E2E_PORT, logger=LOGGER) as server: + LOGGER.info("Running subscription server...: {}:{}".format(ALL_HOSTS, str(WS_E2E_PORT))) + server.serve_forever() + LOGGER.info("Exiting subscription server...") + + +def subcript_to_vnt_manager(websocket): + for message in websocket: + LOGGER.debug("Message received: {}".format(message)) + message_json = json.loads(message) + request = VNTSubscriptionRequest() + request.host = message_json['host'] + request.port = message_json['port'] + LOGGER.debug("Received gRPC from ws: {}".format(request)) + + try: + vntm_reply = vnt_manager_client.VNTSubscript(request) + LOGGER.debug("Received gRPC from vntm: {}".format(vntm_reply)) + except Exception as e: + LOGGER.error('Could not subscript to VTNManager: {}'.format(e)) + + websocket.send(vntm_reply.subscription) diff --git a/src/nbi/service/rest_server/RestServer.py b/src/nbi/service/rest_server/RestServer.py index 42775036237eba32f6fb1cd5a47e41ff3e885deb..521de2735f4d8476c59a263651a67f42851084e2 100644 --- a/src/nbi/service/rest_server/RestServer.py +++ b/src/nbi/service/rest_server/RestServer.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/__init__.py b/src/nbi/service/rest_server/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/nbi/service/rest_server/__init__.py +++ b/src/nbi/service/rest_server/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/__init__.py b/src/nbi/service/rest_server/nbi_plugins/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/nbi/service/rest_server/nbi_plugins/__init__.py +++ b/src/nbi/service/rest_server/nbi_plugins/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Resources.py b/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Resources.py index 4c6ad47bc210316908ed3e3676abbda6757cf615..ba522fd9802372c2b7ab0c6a9cc6e57adb80ee48 100644 --- a/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Resources.py +++ b/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Resources.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -13,12 +13,15 @@ # limitations under the License. import copy, deepmerge, json, logging +from typing import Dict +from flask_restful import Resource, request +from werkzeug.exceptions import UnsupportedMediaType from common.Constants import DEFAULT_CONTEXT_NAME from context.client.ContextClient import ContextClient -from flask_restful import Resource, request from service.client.ServiceClient import ServiceClient from .Tools import ( - format_grpc_to_json, grpc_context_id, grpc_service_id, bwInfo_2_service, service_2_bwInfo) + format_grpc_to_json, grpc_context_id, grpc_service_id, bwInfo_2_service, service_2_bwInfo +) LOGGER = logging.getLogger(__name__) @@ -37,15 +40,20 @@ class BwInfo(_Resource): return bw_allocations def post(self): - bwinfo = request.get_json() - service = bwInfo_2_service(self.client, bwinfo) + if not request.is_json: + raise UnsupportedMediaType('JSON payload is required') + request_data: Dict = request.get_json() + service = bwInfo_2_service(self.client, request_data) stripped_service = copy.deepcopy(service) stripped_service.ClearField('service_endpoint_ids') stripped_service.ClearField('service_constraints') stripped_service.ClearField('service_config') - response = format_grpc_to_json(self.service_client.CreateService(stripped_service)) - response = format_grpc_to_json(self.service_client.UpdateService(service)) + try: + response = format_grpc_to_json(self.service_client.CreateService(stripped_service)) + response = format_grpc_to_json(self.service_client.UpdateService(service)) + except Exception as e: # pylint: disable=broad-except + return e return response diff --git a/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py b/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py index 59436708cca2fcf7ff0ff65aa4977e2ccfaeda95..b3ff6e2d17de7548ba4862212fbe6e31bc59d9a4 100644 --- a/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py +++ b/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -12,20 +12,39 @@ # See the License for the specific language governing permissions and # limitations under the License. -import json -import logging -import time +import json, logging, re, time from decimal import ROUND_HALF_EVEN, Decimal from flask.json import jsonify from common.proto.context_pb2 import ( - ContextId, Empty, EndPointId, ServiceId, ServiceTypeEnum, Service, Constraint, Constraint_SLA_Capacity, - ConfigRule, ConfigRule_Custom, ConfigActionEnum) + ContextId, Empty, EndPointId, ServiceId, ServiceStatusEnum, ServiceTypeEnum, + Service, Constraint, Constraint_SLA_Capacity, ConfigRule, ConfigRule_Custom, + ConfigActionEnum +) +from common.tools.grpc.ConfigRules import update_config_rule_custom from common.tools.grpc.Tools import grpc_message_to_json from common.tools.object_factory.Context import json_context_id from common.tools.object_factory.Service import json_service_id LOGGER = logging.getLogger(__name__) +ENDPOINT_SETTINGS_KEY = '/device[{:s}]/endpoint[{:s}]/vlan[{:d}]/settings' +DEVICE_SETTINGS_KEY = '/device[{:s}]/settings' +RE_CONFIG_RULE_IF_SUBIF = re.compile(r'^\/interface\[([^\]]+)\]\/subinterface\[([^\]]+)\]$') +MEC_CONSIDERED_FIELDS = ['requestType', 'sessionFilter', 'fixedAllocation', 'allocationDirection', 'fixedBWPriority'] +ALLOCATION_DIRECTION_DESCRIPTIONS = { + '00' : 'Downlink (towards the UE)', + '01' : 'Uplink (towards the application/session)', + '10' : 'Symmetrical'} +VLAN_TAG = 0 +PREFIX_LENGTH = 24 +BGP_AS = 65000 +POLICY_AZ = 'srv_{:d}_a'.format(VLAN_TAG) +POLICY_ZA = 'srv_{:d}_b'.format(VLAN_TAG) +BGP_NEIGHBOR_IP_A = '192.168.150.1' +BGP_NEIGHBOR_IP_Z = '192.168.150.2' +ROUTER_ID_A = '200.1.1.1' +ROUTER_ID_Z = '200.1.1.2' +ROUTE_DISTINGUISHER = '{:5d}:{:03d}'.format(BGP_AS, VLAN_TAG) def service_2_bwInfo(service: Service) -> dict: response = {} @@ -40,12 +59,19 @@ def service_2_bwInfo(service: Service) -> dict: break for config_rule in service.service_config.config_rules: + resource_value_json = json.loads(config_rule.custom.resource_value) + if config_rule.custom.resource_key != '/request': + continue for key in ['allocationDirection', 'fixedBWPriority', 'requestType', 'sourceIp', 'sourcePort', 'dstPort', 'protocol', 'sessionFilter']: - if config_rule.custom.resource_key == key: - if key != 'sessionFilter': - response[key] = config_rule.custom.resource_value - else: - response[key] = json.loads(config_rule.custom.resource_value) + if key not in resource_value_json: + continue + + if key == 'sessionFilter': + response[key] = [resource_value_json[key]] + elif key == 'requestType': + response[key] = str(resource_value_json[key]) + else: + response[key] = resource_value_json[key] unixtime = time.time() response['timeStamp'] = { # Time stamp to indicate when the corresponding information elements are sent @@ -55,47 +81,108 @@ def service_2_bwInfo(service: Service) -> dict: return response -def bwInfo_2_service(client, bwInfo: dict) -> Service: +def bwInfo_2_service(client, bw_info: dict) -> Service: + # add description to allocationDirection code + if 'sessionFilter' in bw_info: + bw_info['sessionFilter'] = bw_info['sessionFilter'][0] # Discard other items in sessionFilter field + service = Service() - for key in ['allocationDirection', 'fixedBWPriority', 'requestType', 'timeStamp', 'sessionFilter']: - if key not in bwInfo: - continue - config_rule = ConfigRule() - config_rule.action = ConfigActionEnum.CONFIGACTION_SET - config_rule_custom = ConfigRule_Custom() - config_rule_custom.resource_key = key - if key != 'sessionFilter': - config_rule_custom.resource_value = str(bwInfo[key]) - else: - config_rule_custom.resource_value = json.dumps(bwInfo[key]) - config_rule.custom.CopyFrom(config_rule_custom) - service.service_config.config_rules.append(config_rule) - - if 'sessionFilter' in bwInfo: - a_ip = bwInfo['sessionFilter'][0]['sourceIp'] - z_ip = bwInfo['sessionFilter'][0]['dstAddress'] + + service_config_rules = service.service_config.config_rules + + + request_cr_key = '/request' + request_cr_value = {k:bw_info[k] for k in MEC_CONSIDERED_FIELDS} + + config_rule = ConfigRule() + config_rule.action = ConfigActionEnum.CONFIGACTION_SET + config_rule_custom = ConfigRule_Custom() + config_rule_custom.resource_key = request_cr_key + config_rule_custom.resource_value = json.dumps(request_cr_value) + config_rule.custom.CopyFrom(config_rule_custom) + service_config_rules.append(config_rule) + + if 'sessionFilter' in bw_info: + a_ip = bw_info['sessionFilter']['sourceIp'] + z_ip = bw_info['sessionFilter']['dstAddress'] devices = client.ListDevices(Empty()).devices + ip_interface_name_dict = {} for device in devices: + device_endpoint_uuids = {ep.name:ep.endpoint_id.endpoint_uuid.uuid for ep in device.device_endpoints} + skip_device = True for cr in device.device_config.config_rules: - if cr.WhichOneof('config_rule') == 'custom' and cr.custom.resource_key == '_connect/settings': - for ep in json.loads(cr.custom.resource_value)['endpoints']: - if 'ip' in ep and (ep['ip'] == a_ip or ep['ip'] == z_ip): - ep_id = EndPointId() - ep_id.endpoint_uuid.uuid = ep['uuid'] - ep_id.device_id.device_uuid.uuid = device.device_id.device_uuid.uuid - service.service_endpoint_ids.append(ep_id) - + if cr.WhichOneof('config_rule') != 'custom': + continue + match_subif = RE_CONFIG_RULE_IF_SUBIF.match(cr.custom.resource_key) + if not match_subif: + continue + address_ip = json.loads(cr.custom.resource_value).get('address_ip') + short_port_name = match_subif.groups(0)[0] + ip_interface_name_dict[address_ip] = short_port_name + if address_ip not in [a_ip, z_ip]: + continue + port_name = 'PORT-' + short_port_name # `PORT-` added as prefix + ep_id = EndPointId() + ep_id.endpoint_uuid.uuid = device_endpoint_uuids[port_name] + ep_id.device_id.device_uuid.uuid = device.device_id.device_uuid.uuid + service.service_endpoint_ids.append(ep_id) + # add interface config rules + endpoint_settings_key = ENDPOINT_SETTINGS_KEY.format(device.name, port_name, VLAN_TAG) + if address_ip in a_ip: + router_id = ROUTER_ID_A + policy_az = POLICY_AZ + policy_za = POLICY_ZA + neighbor_bgp_interface_address_ip = BGP_NEIGHBOR_IP_Z + self_bgp_interface_address_ip = BGP_NEIGHBOR_IP_A + else: + router_id = ROUTER_ID_Z + policy_az = POLICY_ZA + policy_za = POLICY_AZ + neighbor_bgp_interface_address_ip= BGP_NEIGHBOR_IP_A + self_bgp_interface_address_ip = BGP_NEIGHBOR_IP_Z + endpoint_field_updates = { + 'address_ip': (address_ip, True), + 'address_prefix' : (PREFIX_LENGTH, True), + 'sub_interface_index': (0, True), + } + LOGGER.debug(f'BEFORE UPDATE -> device.device_config.config_rules: {service_config_rules}') + update_config_rule_custom(service_config_rules, endpoint_settings_key, endpoint_field_updates) + LOGGER.debug(f'AFTER UPDATE -> device.device_config.config_rules: {service_config_rules}') + skip_device = False + if skip_device: + continue + device_field_updates = { + 'bgp_as':(BGP_AS, True), + 'route_distinguisher': (ROUTE_DISTINGUISHER, True), + 'router_id': (router_id, True), + 'policy_AZ': (policy_az, True), + 'policy_ZA': (policy_za, True), + 'neighbor_bgp_interface_address_ip': (neighbor_bgp_interface_address_ip, True), + 'self_bgp_interface_name': (ip_interface_name_dict[self_bgp_interface_address_ip], True), + 'self_bgp_interface_address_ip': (self_bgp_interface_address_ip, True), + 'bgp_interface_address_prefix': (PREFIX_LENGTH, True) + } + device_settings_key = DEVICE_SETTINGS_KEY.format(device.name) + LOGGER.debug(f'BEFORE UPDATE -> device.device_config.config_rules: {service_config_rules}') + update_config_rule_custom(service_config_rules, device_settings_key, device_field_updates) + LOGGER.debug(f'AFTER UPDATE -> device.device_config.config_rules: {service_config_rules}') + + settings_cr_key = '/settings' + settings_cr_value = {} + update_config_rule_custom(service_config_rules, settings_cr_key, settings_cr_value) + + service.service_status.service_status = ServiceStatusEnum.SERVICESTATUS_PLANNED service.service_type = ServiceTypeEnum.SERVICETYPE_L3NM - if 'appInsId' in bwInfo: - service.service_id.service_uuid.uuid = bwInfo['appInsId'] + if 'appInsId' in bw_info: + service.service_id.service_uuid.uuid = bw_info['appInsId'] service.service_id.context_id.context_uuid.uuid = 'admin' - service.name = bwInfo['appInsId'] + service.name = bw_info['appInsId'] - if 'fixedAllocation' in bwInfo: + if 'fixedAllocation' in bw_info: capacity = Constraint_SLA_Capacity() - capacity.capacity_gbps = float(bwInfo['fixedAllocation']) / 1.e9 + capacity.capacity_gbps = float(bw_info['fixedAllocation']) / 1.e9 constraint = Constraint() constraint.sla_capacity.CopyFrom(capacity) service.service_constraints.append(constraint) diff --git a/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/__init__.py b/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/__init__.py index 33ce027421028d02b8cee5fb6882e0718f3d7414..718c4d6a3d1c0e7ecd1b628153d42885a51431fe 100644 --- a/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/__init__.py +++ b/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_acl/Acl.py b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/Acl.py new file mode 100644 index 0000000000000000000000000000000000000000..c0cbbcff74adb5c6be3df6f675ae586e86423f3b --- /dev/null +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/Acl.py @@ -0,0 +1,75 @@ +# 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 json, logging, re +from flask_restful import Resource +from werkzeug.exceptions import NotFound +from common.proto.context_pb2 import ConfigActionEnum, ConfigRule +from common.tools.context_queries.Device import get_device +from context.client.ContextClient import ContextClient +from device.client.DeviceClient import DeviceClient +from nbi.service.rest_server.nbi_plugins.tools.Authentication import HTTP_AUTH +from .ietf_acl_parser import ietf_acl_from_config_rule_resource_value + +LOGGER = logging.getLogger(__name__) + +ACL_CONIG_RULE_KEY = r'\/device\[.+\]\/endpoint\[(.+)\]/acl_ruleset\[{}\]' + +class Acl(Resource): + @HTTP_AUTH.login_required + def get(self, device_uuid : str, acl_name : str): + LOGGER.debug('GET device_uuid={:s}, acl_name={:s}'.format(str(device_uuid), str(acl_name))) + RE_ACL_CONIG_RULE_KEY = re.compile(ACL_CONIG_RULE_KEY.format(acl_name)) + + context_client = ContextClient() + device = get_device(context_client, device_uuid, rw_copy=False, include_config_rules=True) + if device is None: raise NotFound('Device({:s}) not found'.format(str(device_uuid))) + + for config_rule in device.device_config.config_rules: + if config_rule.WhichOneof('config_rule') != 'custom': continue + ep_uuid_match = RE_ACL_CONIG_RULE_KEY.match(config_rule.custom.resource_key) + if ep_uuid_match is None: continue + resource_value_dict = json.loads(config_rule.custom.resource_value) + return ietf_acl_from_config_rule_resource_value(resource_value_dict) + + raise NotFound('Acl({:s}) not found in Device({:s})'.format(str(acl_name), str(device_uuid))) + + @HTTP_AUTH.login_required + def delete(self, device_uuid : str, acl_name : str): + LOGGER.debug('DELETE device_uuid={:s}, acl_name={:s}'.format(str(device_uuid), str(acl_name))) + RE_ACL_CONIG_RULE_KEY = re.compile(ACL_CONIG_RULE_KEY.format(acl_name)) + + context_client = ContextClient() + device = get_device(context_client, device_uuid, rw_copy=True, include_config_rules=True) + if device is None: raise NotFound('Device({:s}) not found'.format(str(device_uuid))) + + delete_config_rules = list() + for config_rule in device.device_config.config_rules: + if config_rule.WhichOneof('config_rule') != 'custom': continue + ep_uuid_match = RE_ACL_CONIG_RULE_KEY.match(config_rule.custom.resource_key) + if ep_uuid_match is None: continue + + _config_rule = ConfigRule() + _config_rule.CopyFrom(config_rule) + _config_rule.action = ConfigActionEnum.CONFIGACTION_DELETE + delete_config_rules.append(_config_rule) + + if len(delete_config_rules) == 0: + raise NotFound('Acl({:s}) not found in Device({:s})'.format(str(acl_name), str(device_uuid))) + + device_client = DeviceClient() + del device.device_config.config_rules[:] + device.device_config.config_rules.extend(delete_config_rules) + device_client.ConfigureDevice(device) + return None diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_acl/Acls.py b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/Acls.py new file mode 100644 index 0000000000000000000000000000000000000000..816aba138beb7b1047043d93358642302345139a --- /dev/null +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/Acls.py @@ -0,0 +1,131 @@ +# 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 json, logging +from typing import Dict, List, Set +from flask import jsonify, request +from flask_restful import Resource +from werkzeug.exceptions import BadRequest, NotFound, UnsupportedMediaType +from common.proto.context_pb2 import ConfigRule +from common.tools.context_queries.Device import get_device +from common.tools.grpc.Tools import grpc_message_to_json_string +from context.client.ContextClient import ContextClient +from device.client.DeviceClient import DeviceClient +from nbi.service.rest_server.nbi_plugins.tools.Authentication import HTTP_AUTH +from .ietf_acl_parser import AclDirectionEnum, config_rule_from_ietf_acl +from .YangValidator import YangValidator + +LOGGER = logging.getLogger(__name__) + + +def compose_interface_direction_acl_rules( + device_name : str, interface_name : str, interface_data : Dict, + acl_direction : AclDirectionEnum, acl_name__to__acl_data : Dict[str, Dict] +) -> List[ConfigRule]: + acl_direction_name = acl_direction.value + acl_direction_title = str(acl_direction_name).title() + direction_data : Dict[str, Dict] = interface_data.get(acl_direction_name, {}) + acl_sets : Dict[str, Dict] = direction_data.get('acl-sets', {}) + acl_set_list : List[Dict] = acl_sets .get('acl-set', []) + acl_set_names : Set[str] = {acl_set['name'] for acl_set in acl_set_list} + + acl_config_rules : List[ConfigRule] = list() + for acl_set_name in acl_set_names: + acl_set = acl_name__to__acl_data.get(acl_set_name) + if acl_set is None: + MSG = 'Interface({:s})/{:s}/AclSet({:s}) not found' + raise NotFound(MSG.format( + str(interface_name), acl_direction_title, + str(acl_set_name) + )) + + acl_config_rule = config_rule_from_ietf_acl( + device_name, interface_name, acl_set + ) + MSG = 'Adding {:s} ACL Config Rule: {:s}' + LOGGER.info(MSG.format( + acl_direction_title, grpc_message_to_json_string(acl_config_rule) + )) + acl_config_rules.append(acl_config_rule) + + return acl_config_rules + +class Acls(Resource): + @HTTP_AUTH.login_required + def get(self): + return {} + + @HTTP_AUTH.login_required + def post(self, device_uuid : str): + if not request.is_json: + LOGGER.warning('POST device_uuid={:s}, body={:s}'.format(str(device_uuid), str(request.data))) + raise UnsupportedMediaType('JSON payload is required') + request_data : Dict = request.json + LOGGER.debug('POST device_uuid={:s}, body={:s}'.format(str(device_uuid), json.dumps(request_data))) + + context_client = ContextClient() + device = get_device( + context_client, device_uuid, rw_copy=True, include_config_rules=False, include_components=False + ) + if device is None: + raise NotFound('Device({:s}) not found'.format(str(device_uuid))) + + device_name = device.name + interface_names : Set[str] = set() + for endpoint in device.device_endpoints: + interface_names.add(endpoint.endpoint_id.endpoint_uuid.uuid) + interface_names.add(endpoint.name) + + yang_validator = YangValidator() + request_data = yang_validator.parse_to_dict(request_data, list(interface_names)) + yang_validator.destroy() + + acls : Dict = request_data.get('acls', {}) + acl_list : List = acls.get('acl', []) + acl_name__to__acl_data = { + acl['name'] : acl + for acl in acl_list + } + + if len(acl_name__to__acl_data) == 0: + raise BadRequest('No ACLs defined in the request') + + interface_list : List = acls.get('attachment-points', {}).get('interface', []) + interface_name__to__interface_data = { + interface['interface-id'] : interface + for interface in interface_list + } + + if len(interface_name__to__interface_data) == 0: + raise BadRequest('No interfaces defined in the request') + + for interface_name in interface_names: + interface_data = interface_name__to__interface_data.get(interface_name) + if interface_data is None: continue + + ingress_acl_config_rules = compose_interface_direction_acl_rules( + device_name, interface_name, interface_data, AclDirectionEnum.INGRESS, + acl_name__to__acl_data + ) + device.device_config.config_rules.extend(ingress_acl_config_rules) + + egress_acl_config_rules = compose_interface_direction_acl_rules( + device_name, interface_name, interface_data, AclDirectionEnum.EGRESS, + acl_name__to__acl_data + ) + device.device_config.config_rules.extend(egress_acl_config_rules) + + device_client = DeviceClient() + device_client.ConfigureDevice(device) + return jsonify({}) diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_acl/YangValidator.py b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/YangValidator.py new file mode 100644 index 0000000000000000000000000000000000000000..a55b7755e2bb510a893390275807c324dc1f03e4 --- /dev/null +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/YangValidator.py @@ -0,0 +1,111 @@ +# 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 copy, json, libyang, logging, os +from typing import Dict, List, Optional + +LOGGER = logging.getLogger(__name__) + +YANG_DIR = os.path.join(os.path.dirname(__file__), 'yang') +YANG_MODULES = [ + 'ietf-yang-types', + 'ietf-interfaces', + 'iana-if-type', + 'ietf-access-control-list', +] + +class YangValidator: + def __init__(self) -> None: + self._yang_context = libyang.Context(YANG_DIR) + for module_name in YANG_MODULES: + LOGGER.info('Loading module: {:s}'.format(str(module_name))) + yang_module = self._yang_context.load_module(module_name) + yang_module.feature_enable_all() + + def parse_to_dict(self, message : Dict, interface_names : List[str]) -> Dict: + LOGGER.debug('[parse_to_dict] message={:s}'.format(json.dumps(message))) + LOGGER.debug('[parse_to_dict] interface_names={:s}'.format(json.dumps(interface_names))) + + # Inject synthetic interfaces for validation purposes + interfaces = self._yang_context.create_data_path('/ietf-interfaces:interfaces') + for if_index,interface_name in enumerate(interface_names): + if_path = 'interface[name="{:s}"]'.format(str(interface_name)) + interface = interfaces.create_path(if_path) + interface.create_path('if-index', if_index + 1) + interface.create_path('type', 'iana-if-type:ethernetCsmacd') + interface.create_path('admin-status', 'up') + interface.create_path('oper-status', 'up') + statistics = interface.create_path('statistics') + statistics.create_path('discontinuity-time', '2024-07-11T10:00:00.000000Z') + + extended_message = copy.deepcopy(message) + extended_message['ietf-interfaces:interfaces'] = interfaces.print_dict()['interfaces'] + LOGGER.debug('[parse_to_dict] extended_message={:s}'.format(json.dumps(extended_message))) + + dnode : Optional[libyang.DNode] = self._yang_context.parse_data_mem( + json.dumps(extended_message), 'json', validate_present=True, strict=True + ) + if dnode is None: + LOGGER.error('[parse_to_dict] unable to parse message') + raise Exception('Unable to parse Message({:s})'.format(str(message))) + message_dict = dnode.print_dict() + LOGGER.debug('[parse_to_dict] message_dict={:s}'.format(json.dumps(message_dict))) + + dnode.free() + interfaces.free() + return message_dict + + def destroy(self) -> None: + self._yang_context.destroy() + self._yang_context = None + +def main() -> None: + import uuid # pylint: disable=import-outside-toplevel + logging.basicConfig(level=logging.DEBUG) + + interface_names = {'200', '500', str(uuid.uuid4()), str(uuid.uuid4())} + ACL_RULE = {"ietf-access-control-list:acls": { + "acl": [{ + "name": "sample-ipv4-acl", "type": "ipv4-acl-type", + "aces": {"ace": [{ + "name": "rule1", + "matches": { + "ipv4": { + "source-ipv4-network": "128.32.10.6/24", + "destination-ipv4-network": "172.10.33.0/24", + "dscp": 18 + }, + "tcp": { + "source-port": {"operator": "eq", "port": 1444}, + "destination-port": {"operator": "eq", "port": 1333}, + "flags": "syn" + } + }, + "actions": {"forwarding": "drop"} + }]} + }], + "attachment-points": {"interface": [{ + "interface-id": "200", + "ingress": {"acl-sets": {"acl-set": [{"name": "sample-ipv4-acl"}]}} + }] + }}} + + yang_validator = YangValidator() + request_data = yang_validator.parse_to_dict(ACL_RULE, list(interface_names)) + yang_validator.destroy() + + LOGGER.info('request_data = {:s}'.format(str(request_data))) + +if __name__ == '__main__': + main() diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_acl/__init__.py b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..da4fb182e539d1c1e1c9bafcfb81d153d4e11b4d --- /dev/null +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/__init__.py @@ -0,0 +1,38 @@ +# 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 flask_restful import Resource +from nbi.service.rest_server.RestServer import RestServer +from .Acl import Acl +from .Acls import Acls + +URL_PREFIX = '/restconf/data' + +def __add_resource(rest_server: RestServer, resource: Resource, *urls, **kwargs): + urls = [(URL_PREFIX + url) for url in urls] + rest_server.add_resource(resource, *urls, **kwargs) + +def register_ietf_acl(rest_server: RestServer): + __add_resource( + rest_server, + Acls, + '/device=/ietf-access-control-list:acls', + ) + + __add_resource( + rest_server, + Acl, + '/device=/ietf-access-control-list:acl=', + '/device=/ietf-access-control-list:acl=/', + ) diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_acl/ietf_acl_parser.py b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/ietf_acl_parser.py new file mode 100644 index 0000000000000000000000000000000000000000..493fb00cf9fb7a0013bfaabbb65d75dc1aba735e --- /dev/null +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/ietf_acl_parser.py @@ -0,0 +1,257 @@ +# 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 enum import Enum +from typing import List, Dict +from pydantic import BaseModel, Field +from werkzeug.exceptions import NotImplemented +from common.proto.acl_pb2 import AclForwardActionEnum, AclRuleTypeEnum, AclEntry +from common.proto.context_pb2 import ConfigActionEnum, ConfigRule + +class AclDirectionEnum(Enum): + INGRESS = 'ingress' + EGRESS = 'egress' + +class Ipv4(BaseModel): + dscp: int = 0 + source_ipv4_network: str = Field(serialization_alias="source-ipv4-network", default="") + destination_ipv4_network: str = Field(serialization_alias="destination-ipv4-network", default="") + +class Port(BaseModel): + port: int = 0 + operator: str = "eq" + +class Tcp(BaseModel): + flags: str = "" + source_port: Port = Field(serialization_alias="source-port", default_factory=lambda: Port()) + destination_port: Port = Field(serialization_alias="destination-port", default_factory=lambda: Port()) + +class Matches(BaseModel): + ipv4: Ipv4 = Ipv4() + tcp: Tcp = Tcp() + +class Action(BaseModel): + forwarding: str = "" + +class Ace(BaseModel): + name: str = "custom_rule" + matches: Matches = Matches() + actions: Action = Action() + +class Aces(BaseModel): + ace: List[Ace] = [Ace()] + +class Acl(BaseModel): + name: str = "" + type: str = "" + aces: Aces = Aces() + +class Name(BaseModel): + name: str = "" + +class AclSet(BaseModel): + acl_set: List[Name] = Field(serialization_alias="acl-set", default=[Name()]) + +class AclSets(BaseModel): + acl_sets: AclSet = Field(serialization_alias="acl-sets", default=AclSet()) + +class Ingress(BaseModel): + ingress : AclSets = AclSets() + +class Egress(BaseModel): + egress : AclSets = AclSets() + +class Interface(BaseModel): + interface_id: str = Field(serialization_alias="interface-id", default="") + ingress : Ingress = Ingress() + egress : Egress = Egress() + +class Interfaces(BaseModel): + interface: List[Interface] = [Interface()] + +class AttachmentPoints(BaseModel): + attachment_points: Interfaces = Field(serialization_alias="attachment-points", default=Interfaces()) + +class Acls(BaseModel): + acl: List[Acl] = [Acl()] + attachment_points: AttachmentPoints = Field(serialization_alias="attachment-points", default=AttachmentPoints()) + +class IETF_ACL(BaseModel): + acls: Acls = Acls() + + +IETF_TFS_RULE_TYPE_MAPPING = { + "ipv4-acl-type": "ACLRULETYPE_IPV4", + "ipv6-acl-type": "ACLRULETYPE_IPV6", +} + +IETF_TFS_FORWARDING_ACTION_MAPPING = { + "accept": "ACLFORWARDINGACTION_ACCEPT", + "drop" : "ACLFORWARDINGACTION_DROP", +} + +TFS_IETF_RULE_TYPE_MAPPING = { + "ACLRULETYPE_IPV4": "ipv4-acl-type", + "ACLRULETYPE_IPV6": "ipv6-acl-type", +} + +TFS_IETF_FORWARDING_ACTION_MAPPING = { + "ACLFORWARDINGACTION_ACCEPT": "accept", + "ACLFORWARDINGACTION_DROP" : "drop", +} + +def config_rule_from_ietf_acl( + device_name : str, endpoint_name : str, acl_set_data : Dict +) -> ConfigRule: + acl_config_rule = ConfigRule() + acl_config_rule.action = ConfigActionEnum.CONFIGACTION_SET + acl_endpoint_id = acl_config_rule.acl.endpoint_id + acl_endpoint_id.device_id.device_uuid.uuid = device_name + acl_endpoint_id.endpoint_uuid.uuid = endpoint_name + + acl_name = acl_set_data['name'] + acl_type = acl_set_data['type'] + if acl_type.startswith('ietf-access-control-list:'): + acl_type = acl_type.replace('ietf-access-control-list:', '') + acl_type = getattr(AclRuleTypeEnum, IETF_TFS_RULE_TYPE_MAPPING[acl_type]) + + acl_rule_set = acl_config_rule.acl.rule_set + acl_rule_set.name = acl_name + acl_rule_set.type = acl_type + #acl_rule_set.description = ... + + access_control_entry_list = acl_set_data.get('aces', {}).get('ace', []) + for sequence_id,ace in enumerate(access_control_entry_list): + ace_name = ace['name'] + ace_matches = ace.get('matches', {}) + ace_actions = ace.get('actions', {}) + + acl_entry = AclEntry() + acl_entry.sequence_id = sequence_id + 1 + #acl_entry.description = ... + + if 'ipv4' in ace_matches: + ipv4_data = ace_matches['ipv4'] + if 'source-ipv4-network' in ipv4_data: + acl_entry.match.src_address = ipv4_data['source-ipv4-network'] + if 'destination-ipv4-network' in ipv4_data: + acl_entry.match.dst_address = ipv4_data['destination-ipv4-network'] + if 'dscp' in ipv4_data: + acl_entry.match.dscp = ipv4_data['dscp'] + if 'protocol' in ipv4_data: + acl_entry.match.protocol = ipv4_data['protocol'] + + if 'tcp' in ace_matches: + # https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml + acl_entry.match.protocol = 6 + tcp_data = ace_matches['tcp'] + if 'source-port' in tcp_data: + tcp_src_port : Dict = tcp_data['source-port'] + tcp_src_port_op = tcp_src_port.get('operator', 'eq') + if tcp_src_port_op != 'eq': + MSG = 'Acl({:s})/Ace({:s})/Match/Tcp({:s}) operator not supported' + raise NotImplemented(MSG.format(acl_name, ace_name, str(tcp_data))) + acl_entry.match.src_port = tcp_src_port['port'] + if 'destination-port' in tcp_data: + tcp_dst_port : Dict = tcp_data['destination-port'] + tcp_dst_port_op = tcp_dst_port.get('operator', 'eq') + if tcp_dst_port_op != 'eq': + MSG = 'Acl({:s})/Ace({:s})/Match/Tcp({:s}) operator not supported' + raise NotImplemented(MSG.format(acl_name, ace_name, str(tcp_data))) + acl_entry.match.dst_port = tcp_dst_port['port'] + if 'flags' in tcp_data: + acl_entry.match.tcp_flags = tcp_data['flags'] + + if 'udp' in ace_matches: + # https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml + acl_entry.match.protocol = 17 + udp_data = ace_matches['udp'] + if 'source-port' in udp_data: + udp_src_port : Dict = udp_data['source-port'] + udp_src_port_op = udp_src_port.get('operator', 'eq') + if udp_src_port_op != 'eq': + MSG = 'Acl({:s})/Ace({:s})/Match/Udp({:s}) operator not supported' + raise NotImplemented(MSG.format(acl_name, ace_name, str(udp_data))) + acl_entry.match.src_port = udp_src_port['port'] + if 'destination-port' in udp_data: + udp_dst_port : Dict = udp_data['destination-port'] + udp_dst_port_op = udp_dst_port.get('operator', 'eq') + if udp_dst_port_op != 'eq': + MSG = 'Acl({:s})/Ace({:s})/Match/Udp({:s}) operator not supported' + raise NotImplemented(MSG.format(acl_name, ace_name, str(udp_data))) + acl_entry.match.dst_port = udp_dst_port['port'] + + if 'forwarding' in ace_actions: + ace_forward_action = ace_actions['forwarding'] + if ace_forward_action.startswith('ietf-access-control-list:'): + ace_forward_action = ace_forward_action.replace('ietf-access-control-list:', '') + ace_forward_action = IETF_TFS_FORWARDING_ACTION_MAPPING[ace_forward_action] + acl_entry.action.forward_action = getattr(AclForwardActionEnum, ace_forward_action) + + acl_rule_set.entries.append(acl_entry) + + return acl_config_rule + +def ietf_acl_from_config_rule_resource_value(config_rule_rv: Dict) -> Dict: + rule_set = config_rule_rv['rule_set'] + acl_entry = rule_set['entries'][0] + match_ = acl_entry['match'] + + ipv4 = Ipv4( + dscp=match_["dscp"], + source_ipv4_network=match_["src_address"], + destination_ipv4_network=match_["dst_address"] + ) + tcp = Tcp( + flags=match_["tcp_flags"], + source_port=Port(port=match_["src_port"]), + destination_port=Port(port=match_["dst_port"]) + ) + matches = Matches(ipvr=ipv4, tcp=tcp) + aces = Aces(ace=[ + Ace( + matches=matches, + actions=Action( + forwarding=TFS_IETF_FORWARDING_ACTION_MAPPING[acl_entry["action"]["forward_action"]] + ) + ) + ]) + acl = Acl( + name=rule_set["name"], + type=TFS_IETF_RULE_TYPE_MAPPING[rule_set["type"]], + aces=aces + ) + acl_sets = AclSets( + acl_sets=AclSet( + acl_set=[ + Name(name=rule_set["name"]) + ] + ) + ) + ingress = Ingress(ingress=acl_sets) + interfaces = Interfaces(interface=[ + Interface( + interface_id=config_rule_rv["interface"], + ingress=ingress + ) + ]) + acls = Acls( + acl=[acl], + attachment_points=AttachmentPoints( + attachment_points=interfaces + ) + ) + ietf_acl = IETF_ACL(acls=acls) + + return ietf_acl.model_dump(by_alias=True) diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_acl/yang/iana-if-type@2014-05-08.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/yang/iana-if-type@2014-05-08.yang new file mode 100644 index 0000000000000000000000000000000000000000..8d52d16f505074ed5c147b22f248bb2ceb89352a --- /dev/null +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/yang/iana-if-type@2014-05-08.yang @@ -0,0 +1,1508 @@ +module iana-if-type { + namespace "urn:ietf:params:xml:ns:yang:iana-if-type"; + prefix ianaift; + + import ietf-interfaces { + prefix if; + } + + organization "IANA"; + contact + " Internet Assigned Numbers Authority + + Postal: ICANN + 4676 Admiralty Way, Suite 330 + Marina del Rey, CA 90292 + + Tel: +1 310 823 9358 + "; + + description + "This YANG module defines YANG identities for IANA-registered + interface types. + + This YANG module is maintained by IANA and reflects the + 'ifType definitions' registry. + + The latest revision of this YANG module can be obtained from + the IANA web site. + + Requests for new values should be made to IANA via + email (iana@iana.org). + + Copyright (c) 2014 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (http://trustee.ietf.org/license-info). + + The initial version of this YANG module is part of RFC 7224; + see the RFC itself for full legal notices."; + reference + "IANA 'ifType definitions' registry. + "; + + revision 2014-05-08 { + description + "Initial revision."; + reference + "RFC 7224: IANA Interface Type YANG Module"; + } + + identity iana-interface-type { + base if:interface-type; + description + "This identity is used as a base for all interface types + defined in the 'ifType definitions' registry."; + } + + identity other { + base iana-interface-type; + } + identity regular1822 { + base iana-interface-type; + } + identity hdh1822 { + base iana-interface-type; + } + identity ddnX25 { + base iana-interface-type; + } + identity rfc877x25 { + base iana-interface-type; + reference + "RFC 1382 - SNMP MIB Extension for the X.25 Packet Layer"; + } + identity ethernetCsmacd { + base iana-interface-type; + description + "For all Ethernet-like interfaces, regardless of speed, + as per RFC 3635."; + reference + "RFC 3635 - Definitions of Managed Objects for the + Ethernet-like Interface Types"; + } + identity iso88023Csmacd { + base iana-interface-type; + status deprecated; + description + "Deprecated via RFC 3635. + Use ethernetCsmacd(6) instead."; + reference + "RFC 3635 - Definitions of Managed Objects for the + Ethernet-like Interface Types"; + } + identity iso88024TokenBus { + base iana-interface-type; + } + identity iso88025TokenRing { + base iana-interface-type; + } + identity iso88026Man { + base iana-interface-type; + } + identity starLan { + base iana-interface-type; + status deprecated; + description + "Deprecated via RFC 3635. + Use ethernetCsmacd(6) instead."; + reference + "RFC 3635 - Definitions of Managed Objects for the + Ethernet-like Interface Types"; + } + identity proteon10Mbit { + base iana-interface-type; + } + identity proteon80Mbit { + base iana-interface-type; + } + identity hyperchannel { + base iana-interface-type; + } + identity fddi { + base iana-interface-type; + reference + "RFC 1512 - FDDI Management Information Base"; + } + identity lapb { + base iana-interface-type; + reference + "RFC 1381 - SNMP MIB Extension for X.25 LAPB"; + } + identity sdlc { + base iana-interface-type; + } + identity ds1 { + base iana-interface-type; + description + "DS1-MIB."; + reference + "RFC 4805 - Definitions of Managed Objects for the + DS1, J1, E1, DS2, and E2 Interface Types"; + } + identity e1 { + base iana-interface-type; + status obsolete; + description + "Obsolete; see DS1-MIB."; + reference + "RFC 4805 - Definitions of Managed Objects for the + DS1, J1, E1, DS2, and E2 Interface Types"; + } + identity basicISDN { + base iana-interface-type; + description + "No longer used. See also RFC 2127."; + } + identity primaryISDN { + base iana-interface-type; + description + "No longer used. See also RFC 2127."; + } + identity propPointToPointSerial { + base iana-interface-type; + description + "Proprietary serial."; + } + identity ppp { + base iana-interface-type; + } + identity softwareLoopback { + base iana-interface-type; + } + identity eon { + base iana-interface-type; + description + "CLNP over IP."; + } + identity ethernet3Mbit { + base iana-interface-type; + } + identity nsip { + base iana-interface-type; + description + "XNS over IP."; + } + identity slip { + base iana-interface-type; + description + "Generic SLIP."; + } + identity ultra { + base iana-interface-type; + description + "Ultra Technologies."; + } + identity ds3 { + base iana-interface-type; + description + "DS3-MIB."; + reference + "RFC 3896 - Definitions of Managed Objects for the + DS3/E3 Interface Type"; + } + identity sip { + base iana-interface-type; + description + "SMDS, coffee."; + reference + "RFC 1694 - Definitions of Managed Objects for SMDS + Interfaces using SMIv2"; + } + identity frameRelay { + base iana-interface-type; + description + "DTE only."; + reference + "RFC 2115 - Management Information Base for Frame Relay + DTEs Using SMIv2"; + } + identity rs232 { + base iana-interface-type; + reference + "RFC 1659 - Definitions of Managed Objects for RS-232-like + Hardware Devices using SMIv2"; + } + identity para { + base iana-interface-type; + description + "Parallel-port."; + reference + "RFC 1660 - Definitions of Managed Objects for + Parallel-printer-like Hardware Devices using + SMIv2"; + } + identity arcnet { + base iana-interface-type; + description + "ARCnet."; + } + identity arcnetPlus { + base iana-interface-type; + description + "ARCnet Plus."; + } + identity atm { + base iana-interface-type; + description + "ATM cells."; + } + identity miox25 { + base iana-interface-type; + reference + "RFC 1461 - SNMP MIB extension for Multiprotocol + Interconnect over X.25"; + } + identity sonet { + base iana-interface-type; + description + "SONET or SDH."; + } + identity x25ple { + base iana-interface-type; + reference + "RFC 2127 - ISDN Management Information Base using SMIv2"; + } + identity iso88022llc { + base iana-interface-type; + } + identity localTalk { + base iana-interface-type; + } + identity smdsDxi { + base iana-interface-type; + } + identity frameRelayService { + base iana-interface-type; + description + "FRNETSERV-MIB."; + reference + "RFC 2954 - Definitions of Managed Objects for Frame + Relay Service"; + } + identity v35 { + base iana-interface-type; + } + identity hssi { + base iana-interface-type; + } + identity hippi { + base iana-interface-type; + } + identity modem { + base iana-interface-type; + description + "Generic modem."; + } + identity aal5 { + base iana-interface-type; + description + "AAL5 over ATM."; + } + identity sonetPath { + base iana-interface-type; + } + identity sonetVT { + base iana-interface-type; + } + identity smdsIcip { + base iana-interface-type; + description + "SMDS InterCarrier Interface."; + } + identity propVirtual { + base iana-interface-type; + description + "Proprietary virtual/internal."; + reference + "RFC 2863 - The Interfaces Group MIB"; + } + identity propMultiplexor { + base iana-interface-type; + description + "Proprietary multiplexing."; + reference + "RFC 2863 - The Interfaces Group MIB"; + } + identity ieee80212 { + base iana-interface-type; + description + "100BaseVG."; + } + identity fibreChannel { + base iana-interface-type; + description + "Fibre Channel."; + } + identity hippiInterface { + base iana-interface-type; + description + "HIPPI interfaces."; + } + identity frameRelayInterconnect { + base iana-interface-type; + status obsolete; + description + "Obsolete; use either + frameRelay(32) or frameRelayService(44)."; + } + identity aflane8023 { + base iana-interface-type; + description + "ATM Emulated LAN for 802.3."; + } + identity aflane8025 { + base iana-interface-type; + description + "ATM Emulated LAN for 802.5."; + } + identity cctEmul { + base iana-interface-type; + description + "ATM Emulated circuit."; + } + identity fastEther { + base iana-interface-type; + status deprecated; + description + "Obsoleted via RFC 3635. + ethernetCsmacd(6) should be used instead."; + reference + "RFC 3635 - Definitions of Managed Objects for the + Ethernet-like Interface Types"; + } + identity isdn { + base iana-interface-type; + description + "ISDN and X.25."; + reference + "RFC 1356 - Multiprotocol Interconnect on X.25 and ISDN + in the Packet Mode"; + } + identity v11 { + base iana-interface-type; + description + "CCITT V.11/X.21."; + } + identity v36 { + base iana-interface-type; + description + "CCITT V.36."; + } + identity g703at64k { + base iana-interface-type; + description + "CCITT G703 at 64Kbps."; + } + identity g703at2mb { + base iana-interface-type; + status obsolete; + description + "Obsolete; see DS1-MIB."; + } + identity qllc { + base iana-interface-type; + description + "SNA QLLC."; + } + identity fastEtherFX { + base iana-interface-type; + status deprecated; + description + "Obsoleted via RFC 3635. + ethernetCsmacd(6) should be used instead."; + reference + "RFC 3635 - Definitions of Managed Objects for the + Ethernet-like Interface Types"; + } + identity channel { + base iana-interface-type; + description + "Channel."; + } + identity ieee80211 { + base iana-interface-type; + description + "Radio spread spectrum."; + } + identity ibm370parChan { + base iana-interface-type; + description + "IBM System 360/370 OEMI Channel."; + } + identity escon { + base iana-interface-type; + description + "IBM Enterprise Systems Connection."; + } + identity dlsw { + base iana-interface-type; + description + "Data Link Switching."; + } + identity isdns { + base iana-interface-type; + description + "ISDN S/T interface."; + } + identity isdnu { + base iana-interface-type; + description + "ISDN U interface."; + } + identity lapd { + base iana-interface-type; + description + "Link Access Protocol D."; + } + identity ipSwitch { + base iana-interface-type; + description + "IP Switching Objects."; + } + identity rsrb { + base iana-interface-type; + description + "Remote Source Route Bridging."; + } + identity atmLogical { + base iana-interface-type; + description + "ATM Logical Port."; + reference + "RFC 3606 - Definitions of Supplemental Managed Objects + for ATM Interface"; + } + identity ds0 { + base iana-interface-type; + description + "Digital Signal Level 0."; + reference + "RFC 2494 - Definitions of Managed Objects for the DS0 + and DS0 Bundle Interface Type"; + } + identity ds0Bundle { + base iana-interface-type; + description + "Group of ds0s on the same ds1."; + reference + "RFC 2494 - Definitions of Managed Objects for the DS0 + and DS0 Bundle Interface Type"; + } + identity bsc { + base iana-interface-type; + description + "Bisynchronous Protocol."; + } + identity async { + base iana-interface-type; + description + "Asynchronous Protocol."; + } + identity cnr { + base iana-interface-type; + description + "Combat Net Radio."; + } + identity iso88025Dtr { + base iana-interface-type; + description + "ISO 802.5r DTR."; + } + identity eplrs { + base iana-interface-type; + description + "Ext Pos Loc Report Sys."; + } + identity arap { + base iana-interface-type; + description + "Appletalk Remote Access Protocol."; + } + identity propCnls { + base iana-interface-type; + description + "Proprietary Connectionless Protocol."; + } + identity hostPad { + base iana-interface-type; + description + "CCITT-ITU X.29 PAD Protocol."; + } + identity termPad { + base iana-interface-type; + description + "CCITT-ITU X.3 PAD Facility."; + } + identity frameRelayMPI { + base iana-interface-type; + description + "Multiproto Interconnect over FR."; + } + identity x213 { + base iana-interface-type; + description + "CCITT-ITU X213."; + } + identity adsl { + base iana-interface-type; + description + "Asymmetric Digital Subscriber Loop."; + } + identity radsl { + base iana-interface-type; + description + "Rate-Adapt. Digital Subscriber Loop."; + } + identity sdsl { + base iana-interface-type; + description + "Symmetric Digital Subscriber Loop."; + } + identity vdsl { + base iana-interface-type; + description + "Very H-Speed Digital Subscrib. Loop."; + } + identity iso88025CRFPInt { + base iana-interface-type; + description + "ISO 802.5 CRFP."; + } + identity myrinet { + base iana-interface-type; + description + "Myricom Myrinet."; + } + identity voiceEM { + base iana-interface-type; + description + "Voice recEive and transMit."; + } + identity voiceFXO { + base iana-interface-type; + description + "Voice Foreign Exchange Office."; + } + identity voiceFXS { + base iana-interface-type; + description + "Voice Foreign Exchange Station."; + } + identity voiceEncap { + base iana-interface-type; + description + "Voice encapsulation."; + } + identity voiceOverIp { + base iana-interface-type; + description + "Voice over IP encapsulation."; + } + identity atmDxi { + base iana-interface-type; + description + "ATM DXI."; + } + identity atmFuni { + base iana-interface-type; + description + "ATM FUNI."; + } + identity atmIma { + base iana-interface-type; + description + "ATM IMA."; + } + identity pppMultilinkBundle { + base iana-interface-type; + description + "PPP Multilink Bundle."; + } + identity ipOverCdlc { + base iana-interface-type; + description + "IBM ipOverCdlc."; + } + identity ipOverClaw { + base iana-interface-type; + description + "IBM Common Link Access to Workstn."; + } + identity stackToStack { + base iana-interface-type; + description + "IBM stackToStack."; + } + identity virtualIpAddress { + base iana-interface-type; + description + "IBM VIPA."; + } + identity mpc { + base iana-interface-type; + description + "IBM multi-protocol channel support."; + } + identity ipOverAtm { + base iana-interface-type; + description + "IBM ipOverAtm."; + reference + "RFC 2320 - Definitions of Managed Objects for Classical IP + and ARP Over ATM Using SMIv2 (IPOA-MIB)"; + } + identity iso88025Fiber { + base iana-interface-type; + description + "ISO 802.5j Fiber Token Ring."; + } + identity tdlc { + base iana-interface-type; + description + "IBM twinaxial data link control."; + } + identity gigabitEthernet { + base iana-interface-type; + status deprecated; + description + "Obsoleted via RFC 3635. + ethernetCsmacd(6) should be used instead."; + reference + "RFC 3635 - Definitions of Managed Objects for the + Ethernet-like Interface Types"; + } + identity hdlc { + base iana-interface-type; + description + "HDLC."; + } + identity lapf { + base iana-interface-type; + description + "LAP F."; + } + identity v37 { + base iana-interface-type; + description + "V.37."; + } + identity x25mlp { + base iana-interface-type; + description + "Multi-Link Protocol."; + } + identity x25huntGroup { + base iana-interface-type; + description + "X25 Hunt Group."; + } + identity transpHdlc { + base iana-interface-type; + description + "Transp HDLC."; + } + identity interleave { + base iana-interface-type; + description + "Interleave channel."; + } + identity fast { + base iana-interface-type; + description + "Fast channel."; + } + identity ip { + base iana-interface-type; + description + "IP (for APPN HPR in IP networks)."; + } + identity docsCableMaclayer { + base iana-interface-type; + description + "CATV Mac Layer."; + } + identity docsCableDownstream { + base iana-interface-type; + description + "CATV Downstream interface."; + } + identity docsCableUpstream { + base iana-interface-type; + description + "CATV Upstream interface."; + } + identity a12MppSwitch { + base iana-interface-type; + description + "Avalon Parallel Processor."; + } + identity tunnel { + base iana-interface-type; + description + "Encapsulation interface."; + } + identity coffee { + base iana-interface-type; + description + "Coffee pot."; + reference + "RFC 2325 - Coffee MIB"; + } + identity ces { + base iana-interface-type; + description + "Circuit Emulation Service."; + } + identity atmSubInterface { + base iana-interface-type; + description + "ATM Sub Interface."; + } + identity l2vlan { + base iana-interface-type; + description + "Layer 2 Virtual LAN using 802.1Q."; + } + identity l3ipvlan { + base iana-interface-type; + description + "Layer 3 Virtual LAN using IP."; + } + identity l3ipxvlan { + base iana-interface-type; + description + "Layer 3 Virtual LAN using IPX."; + } + identity digitalPowerline { + base iana-interface-type; + description + "IP over Power Lines."; + } + identity mediaMailOverIp { + base iana-interface-type; + description + "Multimedia Mail over IP."; + } + identity dtm { + base iana-interface-type; + description + "Dynamic synchronous Transfer Mode."; + } + identity dcn { + base iana-interface-type; + description + "Data Communications Network."; + } + identity ipForward { + base iana-interface-type; + description + "IP Forwarding Interface."; + } + identity msdsl { + base iana-interface-type; + description + "Multi-rate Symmetric DSL."; + } + identity ieee1394 { + base iana-interface-type; + description + "IEEE1394 High Performance Serial Bus."; + } + identity if-gsn { + base iana-interface-type; + description + "HIPPI-6400."; + } + identity dvbRccMacLayer { + base iana-interface-type; + description + "DVB-RCC MAC Layer."; + } + identity dvbRccDownstream { + base iana-interface-type; + description + "DVB-RCC Downstream Channel."; + } + identity dvbRccUpstream { + base iana-interface-type; + description + "DVB-RCC Upstream Channel."; + } + identity atmVirtual { + base iana-interface-type; + description + "ATM Virtual Interface."; + } + identity mplsTunnel { + base iana-interface-type; + description + "MPLS Tunnel Virtual Interface."; + } + identity srp { + base iana-interface-type; + description + "Spatial Reuse Protocol."; + } + identity voiceOverAtm { + base iana-interface-type; + description + "Voice over ATM."; + } + identity voiceOverFrameRelay { + base iana-interface-type; + description + "Voice Over Frame Relay."; + } + identity idsl { + base iana-interface-type; + description + "Digital Subscriber Loop over ISDN."; + } + identity compositeLink { + base iana-interface-type; + description + "Avici Composite Link Interface."; + } + identity ss7SigLink { + base iana-interface-type; + description + "SS7 Signaling Link."; + } + identity propWirelessP2P { + base iana-interface-type; + description + "Prop. P2P wireless interface."; + } + identity frForward { + base iana-interface-type; + description + "Frame Forward Interface."; + } + identity rfc1483 { + base iana-interface-type; + description + "Multiprotocol over ATM AAL5."; + reference + "RFC 1483 - Multiprotocol Encapsulation over ATM + Adaptation Layer 5"; + } + identity usb { + base iana-interface-type; + description + "USB Interface."; + } + identity ieee8023adLag { + base iana-interface-type; + description + "IEEE 802.3ad Link Aggregate."; + } + identity bgppolicyaccounting { + base iana-interface-type; + description + "BGP Policy Accounting."; + } + identity frf16MfrBundle { + base iana-interface-type; + description + "FRF.16 Multilink Frame Relay."; + } + identity h323Gatekeeper { + base iana-interface-type; + description + "H323 Gatekeeper."; + } + identity h323Proxy { + base iana-interface-type; + description + "H323 Voice and Video Proxy."; + } + identity mpls { + base iana-interface-type; + description + "MPLS."; + } + identity mfSigLink { + base iana-interface-type; + description + "Multi-frequency signaling link."; + } + identity hdsl2 { + base iana-interface-type; + description + "High Bit-Rate DSL - 2nd generation."; + } + identity shdsl { + base iana-interface-type; + description + "Multirate HDSL2."; + } + identity ds1FDL { + base iana-interface-type; + description + "Facility Data Link (4Kbps) on a DS1."; + } + identity pos { + base iana-interface-type; + description + "Packet over SONET/SDH Interface."; + } + identity dvbAsiIn { + base iana-interface-type; + description + "DVB-ASI Input."; + } + identity dvbAsiOut { + base iana-interface-type; + description + "DVB-ASI Output."; + } + identity plc { + base iana-interface-type; + description + "Power Line Communications."; + } + identity nfas { + base iana-interface-type; + description + "Non-Facility Associated Signaling."; + } + identity tr008 { + base iana-interface-type; + description + "TR008."; + } + identity gr303RDT { + base iana-interface-type; + description + "Remote Digital Terminal."; + } + identity gr303IDT { + base iana-interface-type; + description + "Integrated Digital Terminal."; + } + identity isup { + base iana-interface-type; + description + "ISUP."; + } + identity propDocsWirelessMaclayer { + base iana-interface-type; + description + "Cisco proprietary Maclayer."; + } + identity propDocsWirelessDownstream { + base iana-interface-type; + description + "Cisco proprietary Downstream."; + } + identity propDocsWirelessUpstream { + base iana-interface-type; + description + "Cisco proprietary Upstream."; + } + identity hiperlan2 { + base iana-interface-type; + description + "HIPERLAN Type 2 Radio Interface."; + } + identity propBWAp2Mp { + base iana-interface-type; + description + "PropBroadbandWirelessAccesspt2Multipt (use of this value + for IEEE 802.16 WMAN interfaces as per IEEE Std 802.16f + is deprecated, and ieee80216WMAN(237) should be used + instead)."; + } + identity sonetOverheadChannel { + base iana-interface-type; + description + "SONET Overhead Channel."; + } + identity digitalWrapperOverheadChannel { + base iana-interface-type; + description + "Digital Wrapper."; + } + identity aal2 { + base iana-interface-type; + description + "ATM adaptation layer 2."; + } + identity radioMAC { + base iana-interface-type; + description + "MAC layer over radio links."; + } + identity atmRadio { + base iana-interface-type; + description + "ATM over radio links."; + } + identity imt { + base iana-interface-type; + description + "Inter-Machine Trunks."; + } + identity mvl { + base iana-interface-type; + description + "Multiple Virtual Lines DSL."; + } + identity reachDSL { + base iana-interface-type; + description + "Long Reach DSL."; + } + identity frDlciEndPt { + base iana-interface-type; + description + "Frame Relay DLCI End Point."; + } + identity atmVciEndPt { + base iana-interface-type; + description + "ATM VCI End Point."; + } + identity opticalChannel { + base iana-interface-type; + description + "Optical Channel."; + } + identity opticalTransport { + base iana-interface-type; + description + "Optical Transport."; + } + identity propAtm { + base iana-interface-type; + description + "Proprietary ATM."; + } + identity voiceOverCable { + base iana-interface-type; + description + "Voice Over Cable Interface."; + } + identity infiniband { + base iana-interface-type; + description + "Infiniband."; + } + identity teLink { + base iana-interface-type; + description + "TE Link."; + } + identity q2931 { + base iana-interface-type; + description + "Q.2931."; + } + identity virtualTg { + base iana-interface-type; + description + "Virtual Trunk Group."; + } + identity sipTg { + base iana-interface-type; + description + "SIP Trunk Group."; + } + identity sipSig { + base iana-interface-type; + description + "SIP Signaling."; + } + identity docsCableUpstreamChannel { + base iana-interface-type; + description + "CATV Upstream Channel."; + } + identity econet { + base iana-interface-type; + description + "Acorn Econet."; + } + identity pon155 { + base iana-interface-type; + description + "FSAN 155Mb Symetrical PON interface."; + } + identity pon622 { + base iana-interface-type; + description + "FSAN 622Mb Symetrical PON interface."; + } + identity bridge { + base iana-interface-type; + description + "Transparent bridge interface."; + } + identity linegroup { + base iana-interface-type; + description + "Interface common to multiple lines."; + } + identity voiceEMFGD { + base iana-interface-type; + description + "Voice E&M Feature Group D."; + } + identity voiceFGDEANA { + base iana-interface-type; + description + "Voice FGD Exchange Access North American."; + } + identity voiceDID { + base iana-interface-type; + description + "Voice Direct Inward Dialing."; + } + identity mpegTransport { + base iana-interface-type; + description + "MPEG transport interface."; + } + identity sixToFour { + base iana-interface-type; + status deprecated; + description + "6to4 interface (DEPRECATED)."; + reference + "RFC 4087 - IP Tunnel MIB"; + } + identity gtp { + base iana-interface-type; + description + "GTP (GPRS Tunneling Protocol)."; + } + identity pdnEtherLoop1 { + base iana-interface-type; + description + "Paradyne EtherLoop 1."; + } + identity pdnEtherLoop2 { + base iana-interface-type; + description + "Paradyne EtherLoop 2."; + } + identity opticalChannelGroup { + base iana-interface-type; + description + "Optical Channel Group."; + } + identity homepna { + base iana-interface-type; + description + "HomePNA ITU-T G.989."; + } + identity gfp { + base iana-interface-type; + description + "Generic Framing Procedure (GFP)."; + } + identity ciscoISLvlan { + base iana-interface-type; + description + "Layer 2 Virtual LAN using Cisco ISL."; + } + identity actelisMetaLOOP { + base iana-interface-type; + description + "Acteleis proprietary MetaLOOP High Speed Link."; + } + identity fcipLink { + base iana-interface-type; + description + "FCIP Link."; + } + identity rpr { + base iana-interface-type; + description + "Resilient Packet Ring Interface Type."; + } + identity qam { + base iana-interface-type; + description + "RF Qam Interface."; + } + identity lmp { + base iana-interface-type; + description + "Link Management Protocol."; + reference + "RFC 4327 - Link Management Protocol (LMP) Management + Information Base (MIB)"; + } + identity cblVectaStar { + base iana-interface-type; + description + "Cambridge Broadband Networks Limited VectaStar."; + } + identity docsCableMCmtsDownstream { + base iana-interface-type; + description + "CATV Modular CMTS Downstream Interface."; + } + identity adsl2 { + base iana-interface-type; + status deprecated; + description + "Asymmetric Digital Subscriber Loop Version 2 + (DEPRECATED/OBSOLETED - please use adsl2plus(238) + instead)."; + reference + "RFC 4706 - Definitions of Managed Objects for Asymmetric + Digital Subscriber Line 2 (ADSL2)"; + } + identity macSecControlledIF { + base iana-interface-type; + description + "MACSecControlled."; + } + identity macSecUncontrolledIF { + base iana-interface-type; + description + "MACSecUncontrolled."; + } + identity aviciOpticalEther { + base iana-interface-type; + description + "Avici Optical Ethernet Aggregate."; + } + identity atmbond { + base iana-interface-type; + description + "atmbond."; + } + identity voiceFGDOS { + base iana-interface-type; + description + "Voice FGD Operator Services."; + } + identity mocaVersion1 { + base iana-interface-type; + description + "MultiMedia over Coax Alliance (MoCA) Interface + as documented in information provided privately to IANA."; + } + identity ieee80216WMAN { + base iana-interface-type; + description + "IEEE 802.16 WMAN interface."; + } + identity adsl2plus { + base iana-interface-type; + description + "Asymmetric Digital Subscriber Loop Version 2 - + Version 2 Plus and all variants."; + } + identity dvbRcsMacLayer { + base iana-interface-type; + description + "DVB-RCS MAC Layer."; + reference + "RFC 5728 - The SatLabs Group DVB-RCS MIB"; + } + identity dvbTdm { + base iana-interface-type; + description + "DVB Satellite TDM."; + reference + "RFC 5728 - The SatLabs Group DVB-RCS MIB"; + } + identity dvbRcsTdma { + base iana-interface-type; + description + "DVB-RCS TDMA."; + reference + "RFC 5728 - The SatLabs Group DVB-RCS MIB"; + } + identity x86Laps { + base iana-interface-type; + description + "LAPS based on ITU-T X.86/Y.1323."; + } + identity wwanPP { + base iana-interface-type; + description + "3GPP WWAN."; + } + identity wwanPP2 { + base iana-interface-type; + description + "3GPP2 WWAN."; + } + identity voiceEBS { + base iana-interface-type; + description + "Voice P-phone EBS physical interface."; + } + identity ifPwType { + base iana-interface-type; + description + "Pseudowire interface type."; + reference + "RFC 5601 - Pseudowire (PW) Management Information Base (MIB)"; + } + identity ilan { + base iana-interface-type; + description + "Internal LAN on a bridge per IEEE 802.1ap."; + } + identity pip { + base iana-interface-type; + description + "Provider Instance Port on a bridge per IEEE 802.1ah PBB."; + } + identity aluELP { + base iana-interface-type; + description + "Alcatel-Lucent Ethernet Link Protection."; + } + identity gpon { + base iana-interface-type; + description + "Gigabit-capable passive optical networks (G-PON) as per + ITU-T G.948."; + } + identity vdsl2 { + base iana-interface-type; + description + "Very high speed digital subscriber line Version 2 + (as per ITU-T Recommendation G.993.2)."; + reference + "RFC 5650 - Definitions of Managed Objects for Very High + Speed Digital Subscriber Line 2 (VDSL2)"; + } + identity capwapDot11Profile { + base iana-interface-type; + description + "WLAN Profile Interface."; + reference + "RFC 5834 - Control and Provisioning of Wireless Access + Points (CAPWAP) Protocol Binding MIB for + IEEE 802.11"; + } + identity capwapDot11Bss { + base iana-interface-type; + description + "WLAN BSS Interface."; + reference + "RFC 5834 - Control and Provisioning of Wireless Access + Points (CAPWAP) Protocol Binding MIB for + IEEE 802.11"; + } + identity capwapWtpVirtualRadio { + base iana-interface-type; + description + "WTP Virtual Radio Interface."; + reference + "RFC 5833 - Control and Provisioning of Wireless Access + Points (CAPWAP) Protocol Base MIB"; + } + identity bits { + base iana-interface-type; + description + "bitsport."; + } + identity docsCableUpstreamRfPort { + base iana-interface-type; + description + "DOCSIS CATV Upstream RF Port."; + } + identity cableDownstreamRfPort { + base iana-interface-type; + description + "CATV downstream RF Port."; + } + identity vmwareVirtualNic { + base iana-interface-type; + description + "VMware Virtual Network Interface."; + } + identity ieee802154 { + base iana-interface-type; + description + "IEEE 802.15.4 WPAN interface."; + reference + "IEEE 802.15.4-2006"; + } + identity otnOdu { + base iana-interface-type; + description + "OTN Optical Data Unit."; + } + identity otnOtu { + base iana-interface-type; + description + "OTN Optical channel Transport Unit."; + } + identity ifVfiType { + base iana-interface-type; + description + "VPLS Forwarding Instance Interface Type."; + } + identity g9981 { + base iana-interface-type; + description + "G.998.1 bonded interface."; + } + identity g9982 { + base iana-interface-type; + description + "G.998.2 bonded interface."; + } + identity g9983 { + base iana-interface-type; + description + "G.998.3 bonded interface."; + } + identity aluEpon { + base iana-interface-type; + description + "Ethernet Passive Optical Networks (E-PON)."; + } + identity aluEponOnu { + base iana-interface-type; + description + "EPON Optical Network Unit."; + } + identity aluEponPhysicalUni { + base iana-interface-type; + description + "EPON physical User to Network interface."; + } + identity aluEponLogicalLink { + base iana-interface-type; + description + "The emulation of a point-to-point link over the EPON + layer."; + } + identity aluGponOnu { + base iana-interface-type; + description + "GPON Optical Network Unit."; + reference + "ITU-T G.984.2"; + } + identity aluGponPhysicalUni { + base iana-interface-type; + description + "GPON physical User to Network interface."; + reference + "ITU-T G.984.2"; + } + identity vmwareNicTeam { + base iana-interface-type; + description + "VMware NIC Team."; + } +} diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_acl/yang/ietf-access-control-list@2019-03-04.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/yang/ietf-access-control-list@2019-03-04.yang new file mode 100644 index 0000000000000000000000000000000000000000..00ae58ee6a63d385c583231f0b84bcdd1bdc41bf --- /dev/null +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/yang/ietf-access-control-list@2019-03-04.yang @@ -0,0 +1,674 @@ +module ietf-access-control-list { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-access-control-list"; + prefix acl; + + import ietf-yang-types { + prefix yang; + reference + "RFC 6991 - Common YANG Data Types."; + } + + import ietf-packet-fields { + prefix pf; + reference + "RFC 8519 - YANG Data Model for Network Access Control + Lists (ACLs)."; + } + + import ietf-interfaces { + prefix if; + reference + "RFC 8343 - A YANG Data Model for Interface Management."; + } + + organization + "IETF NETMOD (Network Modeling) Working Group."; + + contact + "WG Web: + WG List: netmod@ietf.org + + Editor: Mahesh Jethanandani + mjethanandani@gmail.com + Editor: Lisa Huang + huangyi_99@yahoo.com + Editor: Sonal Agarwal + sagarwal12@gmail.com + Editor: Dana Blair + dana@blairhome.com"; + + description + "This YANG module defines a component that describes the + configuration and monitoring of Access Control Lists (ACLs). + + The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', + 'SHALL NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', + 'NOT RECOMMENDED', 'MAY', and 'OPTIONAL' in this document + are to be interpreted as described in BCP 14 (RFC 2119) + (RFC 8174) when, and only when, they appear in all + capitals, as shown here. + + Copyright (c) 2019 IETF Trust and the persons identified as + the document authors. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD + License set forth in Section 4.c of the IETF Trust's Legal + Provisions Relating to IETF Documents + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 8519; see + the RFC itself for full legal notices."; + + revision 2019-03-04 { + description + "Initial version."; + reference + "RFC 8519: YANG Data Model for Network Access Control + Lists (ACLs)."; + } + + /* + * Identities + */ + /* + * Forwarding actions for a packet + */ + + identity forwarding-action { + description + "Base identity for actions in the forwarding category."; + } + + identity accept { + base forwarding-action; + description + "Accept the packet."; + } + + identity drop { + base forwarding-action; + description + "Drop packet without sending any ICMP error message."; + } + + identity reject { + base forwarding-action; + description + "Drop the packet and send an ICMP error message to the source."; + } + + /* + * Logging actions for a packet + */ + + identity log-action { + description + "Base identity for defining the destination for logging + actions."; + } + + identity log-syslog { + base log-action; + description + "System log (syslog) the information for the packet."; + } + + identity log-none { + base log-action; + description + "No logging for the packet."; + } + + /* + * ACL type identities + */ + + identity acl-base { + description + "Base Access Control List type for all Access Control List type + identifiers."; + } + + identity ipv4-acl-type { + base acl:acl-base; + if-feature "ipv4"; + description + "An ACL that matches on fields from the IPv4 header + (e.g., IPv4 destination address) and Layer 4 headers (e.g., TCP + destination port). An ACL of type ipv4 does not contain + matches on fields in the Ethernet header or the IPv6 header."; + } + + identity ipv6-acl-type { + base acl:acl-base; + if-feature "ipv6"; + description + "An ACL that matches on fields from the IPv6 header + (e.g., IPv6 destination address) and Layer 4 headers (e.g., TCP + destination port). An ACL of type ipv6 does not contain + matches on fields in the Ethernet header or the IPv4 header."; + } + + identity eth-acl-type { + base acl:acl-base; + if-feature "eth"; + description + "An ACL that matches on fields in the Ethernet header, + like 10/100/1000baseT or a Wi-Fi Access Control List. An ACL + of type ethernet does not contain matches on fields in the + IPv4 header, the IPv6 header, or Layer 4 headers."; + } + + identity mixed-eth-ipv4-acl-type { + base acl:eth-acl-type; + base acl:ipv4-acl-type; + if-feature "mixed-eth-ipv4"; + description + "An ACL that contains a mix of entries that match + on fields in Ethernet headers and in IPv4 headers. + Matching on Layer 4 header fields may also exist in the + list."; + } + + identity mixed-eth-ipv6-acl-type { + base acl:eth-acl-type; + base acl:ipv6-acl-type; + if-feature "mixed-eth-ipv6"; + description + "An ACL that contains a mix of entries that match on fields + in Ethernet headers and in IPv6 headers. Matching + on Layer 4 header fields may also exist in the list."; + } + + identity mixed-eth-ipv4-ipv6-acl-type { + base acl:eth-acl-type; + base acl:ipv4-acl-type; + base acl:ipv6-acl-type; + if-feature "mixed-eth-ipv4-ipv6"; + description + "An ACL that contains a mix of entries that + match on fields in Ethernet headers, IPv4 headers, and IPv6 + headers. Matching on Layer 4 header fields may also exist + in the list."; + } + + /* + * Features + */ + + /* + * Features supported by device + */ + feature match-on-eth { + description + "The device can support matching on Ethernet headers."; + } + + feature match-on-ipv4 { + description + "The device can support matching on IPv4 headers."; + } + + feature match-on-ipv6 { + description + "The device can support matching on IPv6 headers."; + } + + feature match-on-tcp { + description + "The device can support matching on TCP headers."; + } + + feature match-on-udp { + description + "The device can support matching on UDP headers."; + } + + feature match-on-icmp { + description + "The device can support matching on ICMP (v4 and v6) headers."; + } + + /* + * Header classifications combinations supported by + * device + */ + + feature eth { + if-feature "match-on-eth"; + description + "Plain Ethernet ACL supported."; + } + + feature ipv4 { + if-feature "match-on-ipv4"; + description + "Plain IPv4 ACL supported."; + } + + feature ipv6 { + if-feature "match-on-ipv6"; + description + "Plain IPv6 ACL supported."; + } + + feature mixed-eth-ipv4 { + if-feature "match-on-eth and match-on-ipv4"; + description + "Ethernet and IPv4 ACL combinations supported."; + } + + feature mixed-eth-ipv6 { + if-feature "match-on-eth and match-on-ipv6"; + description + "Ethernet and IPv6 ACL combinations supported."; + } + + feature mixed-eth-ipv4-ipv6 { + if-feature + "match-on-eth and match-on-ipv4 + and match-on-ipv6"; + description + "Ethernet, IPv4, and IPv6 ACL combinations supported."; + } + + /* + * Stats Features + */ + feature interface-stats { + description + "ACL counters are available and reported only per interface."; + } + + feature acl-aggregate-stats { + description + "ACL counters are aggregated over all interfaces and reported + only per ACL entry."; + } + + /* + * Attachment point features + */ + feature interface-attachment { + description + "ACLs are set on interfaces."; + } + + /* + * Typedefs + */ + typedef acl-type { + type identityref { + base acl-base; + } + description + "This type is used to refer to an ACL type."; + } + + /* + * Groupings + */ + grouping acl-counters { + description + "Common grouping for ACL counters."; + leaf matched-packets { + type yang:counter64; + config false; + description + "Count of the number of packets matching the current ACL + entry. + + An implementation should provide this counter on a + per-interface, per-ACL-entry basis if possible. + + If an implementation only supports ACL counters on a per- + entry basis (i.e., not broken out per interface), then the + value should be equal to the aggregate count across all + interfaces. + + An implementation that provides counters on a per-entry, per- + interface basis is not required to also provide an aggregate + count, e.g., per entry -- the user is expected to be able to + implement the required aggregation if such a count is + needed."; + } + + leaf matched-octets { + type yang:counter64; + config false; + description + "Count of the number of octets (bytes) matching the current + ACL entry. + + An implementation should provide this counter on a + per-interface, per-ACL-entry basis if possible. + + If an implementation only supports ACL counters per entry + (i.e., not broken out per interface), then the value + should be equal to the aggregate count across all interfaces. + + An implementation that provides counters per entry per + interface is not required to also provide an aggregate count, + e.g., per entry -- the user is expected to be able to + implement the required aggregation if such a count is needed."; + } + } + + /* + * Configuration and monitoring data nodes + */ + + container acls { + description + "This is a top-level container for Access Control Lists. + It can have one or more acl nodes."; + list acl { + key "name"; + description + "An ACL is an ordered list of ACEs. Each ACE has a + list of match criteria and a list of actions. + Since there are several kinds of ACLs implemented + with different attributes for different vendors, + this model accommodates customizing ACLs for + each kind and for each vendor."; + leaf name { + type string { + length "1..64"; + } + description + "The name of the access list. A device MAY further + restrict the length of this name; space and special + characters are not allowed."; + } + leaf type { + type acl-type; + description + "Type of ACL. Indicates the primary intended + type of match criteria (e.g., Ethernet, IPv4, IPv6, mixed, + etc.) used in the list instance."; + } + container aces { + description + "The aces container contains one or more ACE nodes."; + list ace { + key "name"; + ordered-by user; + description + "List of ACEs."; + leaf name { + type string { + length "1..64"; + } + description + "A unique name identifying this ACE."; + } + + container matches { + description + "The rules in this set determine what fields will be + matched upon before any action is taken on them. + The rules are selected based on the feature set + defined by the server and the acl-type defined. + If no matches are defined in a particular container, + then any packet will match that container. If no + matches are specified at all in an ACE, then any + packet will match the ACE."; + + choice l2 { + container eth { + when "derived-from-or-self(/acls/acl/type, " + + "'acl:eth-acl-type')"; + if-feature "match-on-eth"; + uses pf:acl-eth-header-fields; + description + "Rule set that matches Ethernet headers."; + } + description + "Match Layer 2 headers, for example, Ethernet + header fields."; + } + + choice l3 { + container ipv4 { + when "derived-from-or-self(/acls/acl/type, " + + "'acl:ipv4-acl-type')"; + if-feature "match-on-ipv4"; + uses pf:acl-ip-header-fields; + uses pf:acl-ipv4-header-fields; + description + "Rule set that matches IPv4 headers."; + } + + container ipv6 { + when "derived-from-or-self(/acls/acl/type, " + + "'acl:ipv6-acl-type')"; + if-feature "match-on-ipv6"; + uses pf:acl-ip-header-fields; + uses pf:acl-ipv6-header-fields; + description + "Rule set that matches IPv6 headers."; + } + description + "Choice of either IPv4 or IPv6 headers"; + } + + choice l4 { + container tcp { + if-feature "match-on-tcp"; + uses pf:acl-tcp-header-fields; + container source-port { + choice source-port { + case range-or-operator { + uses pf:port-range-or-operator; + description + "Source port definition from range or + operator."; + } + description + "Choice of source port definition using + range/operator or a choice to support future + 'case' statements, such as one enabling a + group of source ports to be referenced."; + } + description + "Source port definition."; + } + container destination-port { + choice destination-port { + case range-or-operator { + uses pf:port-range-or-operator; + description + "Destination port definition from range or + operator."; + } + description + "Choice of destination port definition using + range/operator or a choice to support future + 'case' statements, such as one enabling a + group of destination ports to be referenced."; + } + description + "Destination port definition."; + } + description + "Rule set that matches TCP headers."; + } + + container udp { + if-feature "match-on-udp"; + uses pf:acl-udp-header-fields; + container source-port { + choice source-port { + case range-or-operator { + uses pf:port-range-or-operator; + description + "Source port definition from range or + operator."; + } + description + "Choice of source port definition using + range/operator or a choice to support future + 'case' statements, such as one enabling a + group of source ports to be referenced."; + } + description + "Source port definition."; + } + container destination-port { + choice destination-port { + case range-or-operator { + uses pf:port-range-or-operator; + description + "Destination port definition from range or + operator."; + } + description + "Choice of destination port definition using + range/operator or a choice to support future + 'case' statements, such as one enabling a + group of destination ports to be referenced."; + } + description + "Destination port definition."; + } + description + "Rule set that matches UDP headers."; + } + + container icmp { + if-feature "match-on-icmp"; + uses pf:acl-icmp-header-fields; + description + "Rule set that matches ICMP headers."; + } + description + "Choice of TCP, UDP, or ICMP headers."; + } + + leaf egress-interface { + type if:interface-ref; + description + + "Egress interface. This should not be used if this ACL + is attached as an egress ACL (or the value should + equal the interface to which the ACL is attached)."; + } + + leaf ingress-interface { + type if:interface-ref; + description + "Ingress interface. This should not be used if this ACL + is attached as an ingress ACL (or the value should + equal the interface to which the ACL is attached)."; + } + } + + container actions { + description + "Definition of actions for this ace entry."; + leaf forwarding { + type identityref { + base forwarding-action; + } + mandatory true; + description + "Specifies the forwarding action per ace entry."; + } + + leaf logging { + type identityref { + base log-action; + } + default "log-none"; + description + "Specifies the log action and destination for + matched packets. Default value is not to log the + packet."; + } + } + container statistics { + if-feature "acl-aggregate-stats"; + config false; + description + "Statistics gathered across all attachment points for the + given ACL."; + uses acl-counters; + } + } + } + } + + container attachment-points { + description + "Enclosing container for the list of + attachment points on which ACLs are set."; + /* + * Groupings + */ + grouping interface-acl { + description + "Grouping for per-interface ingress ACL data."; + container acl-sets { + description + "Enclosing container for the list of ingress ACLs on the + interface."; + list acl-set { + key "name"; + ordered-by user; + description + "List of ingress ACLs on the interface."; + leaf name { + type leafref { + path "/acls/acl/name"; + } + description + "Reference to the ACL name applied on the ingress."; + } + list ace-statistics { + if-feature "interface-stats"; + key "name"; + config false; + description + "List of ACEs."; + leaf name { + type leafref { + path "/acls/acl/aces/ace/name"; + } + description + "Name of the ace entry."; + } + uses acl-counters; + } + } + } + } + + list interface { + if-feature "interface-attachment"; + key "interface-id"; + description + "List of interfaces on which ACLs are set."; + + leaf interface-id { + type if:interface-ref; + description + "Reference to the interface id list key."; + } + + container ingress { + uses interface-acl; + description + "The ACLs applied to the ingress interface."; + } + container egress { + uses interface-acl; + description + "The ACLs applied to the egress interface."; + } + } + } + } +} diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_acl/yang/ietf-ethertypes@2019-03-04.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/yang/ietf-ethertypes@2019-03-04.yang new file mode 100644 index 0000000000000000000000000000000000000000..115c05ce0644ccfab07a96f6b8e5bc31b954a5f6 --- /dev/null +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/yang/ietf-ethertypes@2019-03-04.yang @@ -0,0 +1,381 @@ +module ietf-ethertypes { + namespace "urn:ietf:params:xml:ns:yang:ietf-ethertypes"; + prefix ethertypes; + + organization + "IETF NETMOD (Network Modeling) Working Group."; + + contact + "WG Web: + WG List: + + Editor: Mahesh Jethanandani + "; + + description + "This module contains common definitions for the + Ethertype used by different modules. It is a + placeholder module, till such time that IEEE + starts a project to define these Ethertypes + and publishes a standard. + + At that time, this module can be deprecated. + + Copyright (c) 2019 IETF Trust and the persons identified as + the document authors. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD + License set forth in Section 4.c of the IETF Trust's Legal + Provisions Relating to IETF Documents + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 8519; see + the RFC itself for full legal notices."; + + revision 2019-03-04 { + description + "Initial revision."; + reference + "RFC 8519: YANG Data Model for Network Access Control + Lists (ACLs)."; + } + + typedef ethertype { + type union { + type uint16; + type enumeration { + enum ipv4 { + value 2048; + description + "Internet Protocol version 4 (IPv4) with a + hex value of 0x0800."; + reference + "RFC 791: Internet Protocol."; + } + enum arp { + value 2054; + description + "Address Resolution Protocol (ARP) with a + hex value of 0x0806."; + reference + "RFC 826: An Ethernet Address Resolution Protocol: Or + Converting Network Protocol Addresses to 48.bit + Ethernet Address for Transmission on Ethernet + Hardware."; + } + enum wlan { + value 2114; + description + "Wake-on-LAN. Hex value of 0x0842."; + } + enum trill { + value 8947; + description + "Transparent Interconnection of Lots of Links. + Hex value of 0x22F3."; + reference + "RFC 6325: Routing Bridges (RBridges): Base Protocol + Specification."; + } + enum srp { + value 8938; + description + "Stream Reservation Protocol. Hex value of + 0x22EA."; + reference + "IEEE 801.1Q-2011."; + } + enum decnet { + value 24579; + description + "DECnet Phase IV. Hex value of 0x6003."; + } + enum rarp { + value 32821; + description + "Reverse Address Resolution Protocol. + Hex value 0x8035."; + reference + "RFC 903: A Reverse Address Resolution Protocol."; + } + enum appletalk { + value 32923; + description + "Appletalk (Ethertalk). Hex value of 0x809B."; + } + enum aarp { + value 33011; + description + "Appletalk Address Resolution Protocol. Hex value + of 0x80F3."; + } + enum vlan { + value 33024; + description + "VLAN-tagged frame (IEEE 802.1Q) and Shortest Path + Bridging IEEE 802.1aq with Network-Network + Interface (NNI) compatibility. Hex value of + 0x8100."; + reference + "IEEE 802.1Q."; + } + enum ipx { + value 33079; + description + "Internetwork Packet Exchange (IPX). Hex value + of 0x8137."; + } + enum qnx { + value 33284; + description + "QNX Qnet. Hex value of 0x8204."; + } + enum ipv6 { + value 34525; + description + "Internet Protocol Version 6 (IPv6). Hex value + of 0x86DD."; + reference + "RFC 8200: Internet Protocol, Version 6 (IPv6) + Specification + RFC 8201: Path MTU Discovery for IP version 6."; + } + enum efc { + value 34824; + description + "Ethernet flow control using pause frames. + Hex value of 0x8808."; + reference + "IEEE 802.1Qbb."; + } + enum esp { + value 34825; + description + "Ethernet Slow Protocol. Hex value of 0x8809."; + reference + "IEEE 802.3-2015."; + } + enum cobranet { + value 34841; + description + "CobraNet. Hex value of 0x8819."; + } + enum mpls-unicast { + value 34887; + description + "Multiprotocol Label Switching (MPLS) unicast traffic. + Hex value of 0x8847."; + reference + "RFC 3031: Multiprotocol Label Switching Architecture."; + } + enum mpls-multicast { + value 34888; + description + "MPLS multicast traffic. Hex value of 0x8848."; + reference + "RFC 3031: Multiprotocol Label Switching Architecture."; + } + enum pppoe-discovery { + value 34915; + description + "Point-to-Point Protocol over Ethernet. Used during + the discovery process. Hex value of 0x8863."; + reference + "RFC 2516: A Method for Transmitting PPP Over Ethernet + (PPPoE)."; + } + enum pppoe-session { + value 34916; + description + "Point-to-Point Protocol over Ethernet. Used during + session stage. Hex value of 0x8864."; + reference + "RFC 2516: A Method for Transmitting PPP Over Ethernet + (PPPoE)."; + } + enum intel-ans { + value 34925; + description + "Intel Advanced Networking Services. Hex value of + 0x886D."; + } + enum jumbo-frames { + value 34928; + description + "Jumbo frames or Ethernet frames with more than + 1500 bytes of payload, up to 9000 bytes."; + } + enum homeplug { + value 34939; + description + "Family name for the various power line + communications. Hex value of 0x887B."; + } + enum eap { + value 34958; + description + "Ethernet Access Protocol (EAP) over LAN. Hex value + of 0x888E."; + reference + "IEEE 802.1X."; + } + enum profinet { + value 34962; + description + "PROcess FIeld Net (PROFINET). Hex value of 0x8892."; + } + enum hyperscsi { + value 34970; + description + "Small Computer System Interface (SCSI) over Ethernet. + Hex value of 0x889A."; + } + enum aoe { + value 34978; + description + "Advanced Technology Advancement (ATA) over Ethernet. + Hex value of 0x88A2."; + } + enum ethercat { + value 34980; + description + "Ethernet for Control Automation Technology (EtherCAT). + Hex value of 0x88A4."; + } + enum provider-bridging { + value 34984; + description + "Provider Bridging (802.1ad) and Shortest Path Bridging + (801.1aq). Hex value of 0x88A8."; + reference + "IEEE 802.1ad and IEEE 802.1aq)."; + } + enum ethernet-powerlink { + value 34987; + description + "Ethernet Powerlink. Hex value of 0x88AB."; + } + enum goose { + value 35000; + description + "Generic Object Oriented Substation Event (GOOSE). + Hex value of 0x88B8."; + reference + "IEC/ISO 8802-2 and 8802-3."; + } + enum gse { + value 35001; + description + "Generic Substation Events. Hex value of 88B9."; + reference + "IEC 61850."; + } + enum sv { + value 35002; + description + "Sampled Value Transmission. Hex value of 0x88BA."; + reference + "IEC 61850."; + } + enum lldp { + value 35020; + description + "Link Layer Discovery Protocol (LLDP). Hex value of + 0x88CC."; + reference + "IEEE 802.1AB."; + } + enum sercos { + value 35021; + description + "Sercos Interface. Hex value of 0x88CD."; + } + enum wsmp { + value 35036; + description + "WAVE Short Message Protocol (WSMP). Hex value of + 0x88DC."; + } + enum homeplug-av-mme { + value 35041; + description + "HomePlug AV Mobile Management Entity (MME). Hex value + of 88E1."; + } + enum mrp { + value 35043; + description + "Media Redundancy Protocol (MRP). Hex value of + 0x88E3."; + reference + "IEC 62439-2."; + } + enum macsec { + value 35045; + description + "MAC Security. Hex value of 0x88E5."; + reference + "IEEE 802.1AE."; + } + enum pbb { + value 35047; + description + "Provider Backbone Bridges (PBB). Hex value of + 0x88E7."; + reference + "IEEE 802.1ah."; + } + enum cfm { + value 35074; + description + "Connectivity Fault Management (CFM). Hex value of + 0x8902."; + reference + "IEEE 802.1ag."; + } + enum fcoe { + value 35078; + description + "Fiber Channel over Ethernet (FCoE). Hex value of + 0x8906."; + reference + "T11 FC-BB-5."; + } + enum fcoe-ip { + value 35092; + description + "FCoE Initialization Protocol. Hex value of 0x8914."; + } + enum roce { + value 35093; + description + "RDMA over Converged Ethernet (RoCE). Hex value of + 0x8915."; + } + enum tte { + value 35101; + description + "TTEthernet Protocol Control Frame (TTE). Hex value + of 0x891D."; + reference + "SAE AS6802."; + } + enum hsr { + value 35119; + description + "High-availability Seamless Redundancy (HSR). Hex + value of 0x892F."; + reference + "IEC 62439-3:2016."; + } + } + } + description + "The uint16 type placeholder is defined to enable + users to manage their own ethertypes not + covered by the module. Otherwise, the module contains + enum definitions for the more commonly used ethertypes."; + } +} diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_acl/yang/ietf-inet-types@2013-07-15.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/yang/ietf-inet-types@2013-07-15.yang new file mode 100644 index 0000000000000000000000000000000000000000..790bafc31dd7dc3582ef1c765fe104145b8a6016 --- /dev/null +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/yang/ietf-inet-types@2013-07-15.yang @@ -0,0 +1,459 @@ + module ietf-inet-types { + + namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types"; + prefix "inet"; + + organization + "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; + + contact + "WG Web: + WG List: + + WG Chair: David Kessens + + + WG Chair: Juergen Schoenwaelder + + + Editor: Juergen Schoenwaelder + "; + + description + "This module contains a collection of generally useful derived + YANG data types for Internet addresses and related things. + + Copyright (c) 2013 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 6991; see + the RFC itself for full legal notices."; + + revision 2013-07-15 { + description + "This revision adds the following new data types: + - ip-address-no-zone + - ipv4-address-no-zone + - ipv6-address-no-zone"; + reference + "RFC 6991: Common YANG Data Types"; + } + + revision 2010-09-24 { + description + "Initial revision."; + reference + "RFC 6021: Common YANG Data Types"; + } + + /*** collection of types related to protocol fields ***/ + + typedef ip-version { + type enumeration { + enum unknown { + value "0"; + description + "An unknown or unspecified version of the Internet + protocol."; + } + enum ipv4 { + value "1"; + description + "The IPv4 protocol as defined in RFC 791."; + } + enum ipv6 { + value "2"; + description + "The IPv6 protocol as defined in RFC 2460."; + } + } + description + "This value represents the version of the IP protocol. + + In the value set and its semantics, this type is equivalent + to the InetVersion textual convention of the SMIv2."; + reference + "RFC 791: Internet Protocol + RFC 2460: Internet Protocol, Version 6 (IPv6) Specification + RFC 4001: Textual Conventions for Internet Network Addresses"; + } + + typedef dscp { + type uint8 { + range "0..63"; + } + description + "The dscp type represents a Differentiated Services Code Point + that may be used for marking packets in a traffic stream. + + In the value set and its semantics, this type is equivalent + to the Dscp textual convention of the SMIv2."; + reference + "RFC 3289: Management Information Base for the Differentiated + Services Architecture + RFC 2474: Definition of the Differentiated Services Field + (DS Field) in the IPv4 and IPv6 Headers + RFC 2780: IANA Allocation Guidelines For Values In + the Internet Protocol and Related Headers"; + } + + typedef ipv6-flow-label { + type uint32 { + range "0..1048575"; + } + description + "The ipv6-flow-label type represents the flow identifier or Flow + Label in an IPv6 packet header that may be used to + discriminate traffic flows. + + In the value set and its semantics, this type is equivalent + to the IPv6FlowLabel textual convention of the SMIv2."; + reference + "RFC 3595: Textual Conventions for IPv6 Flow Label + RFC 2460: Internet Protocol, Version 6 (IPv6) Specification"; + } + + typedef port-number { + type uint16 { + range "0..65535"; + } + description + "The port-number type represents a 16-bit port number of an + Internet transport-layer protocol such as UDP, TCP, DCCP, or + SCTP. Port numbers are assigned by IANA. A current list of + all assignments is available from . + + Note that the port number value zero is reserved by IANA. In + situations where the value zero does not make sense, it can + be excluded by subtyping the port-number type. + In the value set and its semantics, this type is equivalent + to the InetPortNumber textual convention of the SMIv2."; + reference + "RFC 768: User Datagram Protocol + RFC 793: Transmission Control Protocol + RFC 4960: Stream Control Transmission Protocol + RFC 4340: Datagram Congestion Control Protocol (DCCP) + RFC 4001: Textual Conventions for Internet Network Addresses"; + } + + /*** collection of types related to autonomous systems ***/ + + typedef as-number { + type uint32; + description + "The as-number type represents autonomous system numbers + which identify an Autonomous System (AS). An AS is a set + of routers under a single technical administration, using + an interior gateway protocol and common metrics to route + packets within the AS, and using an exterior gateway + protocol to route packets to other ASes. IANA maintains + the AS number space and has delegated large parts to the + regional registries. + + Autonomous system numbers were originally limited to 16 + bits. BGP extensions have enlarged the autonomous system + number space to 32 bits. This type therefore uses an uint32 + base type without a range restriction in order to support + a larger autonomous system number space. + + In the value set and its semantics, this type is equivalent + to the InetAutonomousSystemNumber textual convention of + the SMIv2."; + reference + "RFC 1930: Guidelines for creation, selection, and registration + of an Autonomous System (AS) + RFC 4271: A Border Gateway Protocol 4 (BGP-4) + RFC 4001: Textual Conventions for Internet Network Addresses + RFC 6793: BGP Support for Four-Octet Autonomous System (AS) + Number Space"; + } + + /*** collection of types related to IP addresses and hostnames ***/ + + typedef ip-address { + type union { + type inet:ipv4-address; + type inet:ipv6-address; + } + description + "The ip-address type represents an IP address and is IP + version neutral. The format of the textual representation + implies the IP version. This type supports scoped addresses + by allowing zone identifiers in the address format."; + reference + "RFC 4007: IPv6 Scoped Address Architecture"; + } + + typedef ipv4-address { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' + + '(%[\p{N}\p{L}]+)?'; + } + description + "The ipv4-address type represents an IPv4 address in + dotted-quad notation. The IPv4 address may include a zone + index, separated by a % sign. + + The zone index is used to disambiguate identical address + values. For link-local addresses, the zone index will + typically be the interface index number or the name of an + interface. If the zone index is not present, the default + zone of the device will be used. + + The canonical format for the zone index is the numerical + format"; + } + + typedef ipv6-address { + type string { + pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' + + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' + + '(%[\p{N}\p{L}]+)?'; + pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' + + '(%.+)?'; + } + description + "The ipv6-address type represents an IPv6 address in full, + mixed, shortened, and shortened-mixed notation. The IPv6 + address may include a zone index, separated by a % sign. + + The zone index is used to disambiguate identical address + values. For link-local addresses, the zone index will + typically be the interface index number or the name of an + interface. If the zone index is not present, the default + zone of the device will be used. + + The canonical format of IPv6 addresses uses the textual + representation defined in Section 4 of RFC 5952. The + canonical format for the zone index is the numerical + format as described in Section 11.2 of RFC 4007."; + reference + "RFC 4291: IP Version 6 Addressing Architecture + RFC 4007: IPv6 Scoped Address Architecture + RFC 5952: A Recommendation for IPv6 Address Text + Representation"; + } + + typedef ip-address-no-zone { + type union { + type inet:ipv4-address-no-zone; + type inet:ipv6-address-no-zone; + } + description + "The ip-address-no-zone type represents an IP address and is + IP version neutral. The format of the textual representation + implies the IP version. This type does not support scoped + addresses since it does not allow zone identifiers in the + address format."; + reference + "RFC 4007: IPv6 Scoped Address Architecture"; + } + + typedef ipv4-address-no-zone { + type inet:ipv4-address { + pattern '[0-9\.]*'; + } + description + "An IPv4 address without a zone index. This type, derived from + ipv4-address, may be used in situations where the zone is + known from the context and hence no zone index is needed."; + } + + typedef ipv6-address-no-zone { + type inet:ipv6-address { + pattern '[0-9a-fA-F:\.]*'; + } + description + "An IPv6 address without a zone index. This type, derived from + ipv6-address, may be used in situations where the zone is + known from the context and hence no zone index is needed."; + reference + "RFC 4291: IP Version 6 Addressing Architecture + RFC 4007: IPv6 Scoped Address Architecture + RFC 5952: A Recommendation for IPv6 Address Text + Representation"; + } + + typedef ip-prefix { + type union { + type inet:ipv4-prefix; + type inet:ipv6-prefix; + } + description + "The ip-prefix type represents an IP prefix and is IP + version neutral. The format of the textual representations + implies the IP version."; + } + + typedef ipv4-prefix { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' + + '/(([0-9])|([1-2][0-9])|(3[0-2]))'; + } + description + "The ipv4-prefix type represents an IPv4 address prefix. + The prefix length is given by the number following the + slash character and must be less than or equal to 32. + + A prefix length value of n corresponds to an IP address + mask that has n contiguous 1-bits from the most + significant bit (MSB) and all other bits set to 0. + + The canonical format of an IPv4 prefix has all bits of + the IPv4 address set to zero that are not part of the + IPv4 prefix."; + } + + typedef ipv6-prefix { + type string { + pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' + + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' + + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'; + pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' + + '(/.+)'; + } + + description + "The ipv6-prefix type represents an IPv6 address prefix. + The prefix length is given by the number following the + slash character and must be less than or equal to 128. + + A prefix length value of n corresponds to an IP address + mask that has n contiguous 1-bits from the most + significant bit (MSB) and all other bits set to 0. + + The IPv6 address should have all bits that do not belong + to the prefix set to zero. + + The canonical format of an IPv6 prefix has all bits of + the IPv6 address set to zero that are not part of the + IPv6 prefix. Furthermore, the IPv6 address is represented + as defined in Section 4 of RFC 5952."; + reference + "RFC 5952: A Recommendation for IPv6 Address Text + Representation"; + } + + /*** collection of domain name and URI types ***/ + + typedef domain-name { + type string { + pattern + '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*' + + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)' + + '|\.'; + length "1..253"; + } + description + "The domain-name type represents a DNS domain name. The + name SHOULD be fully qualified whenever possible. + + Internet domain names are only loosely specified. Section + 3.5 of RFC 1034 recommends a syntax (modified in Section + 2.1 of RFC 1123). The pattern above is intended to allow + for current practice in domain name use, and some possible + future expansion. It is designed to hold various types of + domain names, including names used for A or AAAA records + (host names) and other records, such as SRV records. Note + that Internet host names have a stricter syntax (described + in RFC 952) than the DNS recommendations in RFCs 1034 and + 1123, and that systems that want to store host names in + schema nodes using the domain-name type are recommended to + adhere to this stricter standard to ensure interoperability. + + The encoding of DNS names in the DNS protocol is limited + to 255 characters. Since the encoding consists of labels + prefixed by a length bytes and there is a trailing NULL + byte, only 253 characters can appear in the textual dotted + notation. + + The description clause of schema nodes using the domain-name + type MUST describe when and how these names are resolved to + IP addresses. Note that the resolution of a domain-name value + may require to query multiple DNS records (e.g., A for IPv4 + and AAAA for IPv6). The order of the resolution process and + which DNS record takes precedence can either be defined + explicitly or may depend on the configuration of the + resolver. + + Domain-name values use the US-ASCII encoding. Their canonical + format uses lowercase US-ASCII characters. Internationalized + domain names MUST be A-labels as per RFC 5890."; + reference + "RFC 952: DoD Internet Host Table Specification + RFC 1034: Domain Names - Concepts and Facilities + RFC 1123: Requirements for Internet Hosts -- Application + and Support + RFC 2782: A DNS RR for specifying the location of services + (DNS SRV) + RFC 5890: Internationalized Domain Names in Applications + (IDNA): Definitions and Document Framework"; + } + + typedef host { + type union { + type inet:ip-address; + type inet:domain-name; + } + description + "The host type represents either an IP address or a DNS + domain name."; + } + + typedef uri { + type string; + description + "The uri type represents a Uniform Resource Identifier + (URI) as defined by STD 66. + + Objects using the uri type MUST be in US-ASCII encoding, + and MUST be normalized as described by RFC 3986 Sections + 6.2.1, 6.2.2.1, and 6.2.2.2. All unnecessary + percent-encoding is removed, and all case-insensitive + characters are set to lowercase except for hexadecimal + digits, which are normalized to uppercase as described in + Section 6.2.2.1. + + The purpose of this normalization is to help provide + unique URIs. Note that this normalization is not + sufficient to provide uniqueness. Two URIs that are + textually distinct after this normalization may still be + equivalent. + + Objects using the uri type may restrict the schemes that + they permit. For example, 'data:' and 'urn:' schemes + might not be appropriate. + + A zero-length URI is not a valid URI. This can be used to + express 'URI absent' where required. + + In the value set and its semantics, this type is equivalent + to the Uri SMIv2 textual convention defined in RFC 5017."; + reference + "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax + RFC 3305: Report from the Joint W3C/IETF URI Planning Interest + Group: Uniform Resource Identifiers (URIs), URLs, + and Uniform Resource Names (URNs): Clarifications + and Recommendations + RFC 5017: MIB Textual Conventions for Uniform Resource + Identifiers (URIs)"; + } + + } diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_acl/yang/ietf-interfaces@2018-02-20.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/yang/ietf-interfaces@2018-02-20.yang new file mode 100644 index 0000000000000000000000000000000000000000..e53675b9d3caab79e15e1d7453d118df8c177089 --- /dev/null +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/yang/ietf-interfaces@2018-02-20.yang @@ -0,0 +1,1123 @@ +module ietf-interfaces { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-interfaces"; + prefix if; + + import ietf-yang-types { + prefix yang; + } + + organization + "IETF NETMOD (Network Modeling) Working Group"; + + contact + "WG Web: + WG List: + + Editor: Martin Bjorklund + "; + + description + "This module contains a collection of YANG definitions for + managing network interfaces. + + Copyright (c) 2018 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (https://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 8343; see + the RFC itself for full legal notices."; + + revision 2018-02-20 { + description + "Updated to support NMDA."; + reference + "RFC 8343: A YANG Data Model for Interface Management"; + } + + revision 2014-05-08 { + description + "Initial revision."; + reference + "RFC 7223: A YANG Data Model for Interface Management"; + } + + /* + * Typedefs + */ + + typedef interface-ref { + type leafref { + path "/if:interfaces/if:interface/if:name"; + } + description + "This type is used by data models that need to reference + interfaces."; + } + + /* + * Identities + */ + + identity interface-type { + description + "Base identity from which specific interface types are + derived."; + } + + /* + * Features + */ + + feature arbitrary-names { + description + "This feature indicates that the device allows user-controlled + interfaces to be named arbitrarily."; + } + feature pre-provisioning { + description + "This feature indicates that the device supports + pre-provisioning of interface configuration, i.e., it is + possible to configure an interface whose physical interface + hardware is not present on the device."; + } + feature if-mib { + description + "This feature indicates that the device implements + the IF-MIB."; + reference + "RFC 2863: The Interfaces Group MIB"; + } + + /* + * Data nodes + */ + + container interfaces { + description + "Interface parameters."; + + list interface { + key "name"; + + description + "The list of interfaces on the device. + + The status of an interface is available in this list in the + operational state. If the configuration of a + system-controlled interface cannot be used by the system + (e.g., the interface hardware present does not match the + interface type), then the configuration is not applied to + the system-controlled interface shown in the operational + state. If the configuration of a user-controlled interface + cannot be used by the system, the configured interface is + not instantiated in the operational state. + + System-controlled interfaces created by the system are + always present in this list in the operational state, + whether or not they are configured."; + + leaf name { + type string; + description + "The name of the interface. + + A device MAY restrict the allowed values for this leaf, + possibly depending on the type of the interface. + For system-controlled interfaces, this leaf is the + device-specific name of the interface. + + If a client tries to create configuration for a + system-controlled interface that is not present in the + operational state, the server MAY reject the request if + the implementation does not support pre-provisioning of + interfaces or if the name refers to an interface that can + never exist in the system. A Network Configuration + Protocol (NETCONF) server MUST reply with an rpc-error + with the error-tag 'invalid-value' in this case. + + If the device supports pre-provisioning of interface + configuration, the 'pre-provisioning' feature is + advertised. + + If the device allows arbitrarily named user-controlled + interfaces, the 'arbitrary-names' feature is advertised. + + When a configured user-controlled interface is created by + the system, it is instantiated with the same name in the + operational state. + + A server implementation MAY map this leaf to the ifName + MIB object. Such an implementation needs to use some + mechanism to handle the differences in size and characters + allowed between this leaf and ifName. The definition of + such a mechanism is outside the scope of this document."; + reference + "RFC 2863: The Interfaces Group MIB - ifName"; + } + + leaf description { + type string; + description + "A textual description of the interface. + + A server implementation MAY map this leaf to the ifAlias + MIB object. Such an implementation needs to use some + mechanism to handle the differences in size and characters + allowed between this leaf and ifAlias. The definition of + such a mechanism is outside the scope of this document. + + Since ifAlias is defined to be stored in non-volatile + storage, the MIB implementation MUST map ifAlias to the + value of 'description' in the persistently stored + configuration."; + reference + "RFC 2863: The Interfaces Group MIB - ifAlias"; + } + + leaf type { + type identityref { + base interface-type; + } + mandatory true; + description + "The type of the interface. + + When an interface entry is created, a server MAY + initialize the type leaf with a valid value, e.g., if it + is possible to derive the type from the name of the + interface. + + If a client tries to set the type of an interface to a + value that can never be used by the system, e.g., if the + type is not supported or if the type does not match the + name of the interface, the server MUST reject the request. + A NETCONF server MUST reply with an rpc-error with the + error-tag 'invalid-value' in this case."; + reference + "RFC 2863: The Interfaces Group MIB - ifType"; + } + + leaf enabled { + type boolean; + default "true"; + description + "This leaf contains the configured, desired state of the + interface. + + Systems that implement the IF-MIB use the value of this + leaf in the intended configuration to set + IF-MIB.ifAdminStatus to 'up' or 'down' after an ifEntry + has been initialized, as described in RFC 2863. + + Changes in this leaf in the intended configuration are + reflected in ifAdminStatus."; + reference + "RFC 2863: The Interfaces Group MIB - ifAdminStatus"; + } + + leaf link-up-down-trap-enable { + if-feature if-mib; + type enumeration { + enum enabled { + value 1; + description + "The device will generate linkUp/linkDown SNMP + notifications for this interface."; + } + enum disabled { + value 2; + description + "The device will not generate linkUp/linkDown SNMP + notifications for this interface."; + } + } + description + "Controls whether linkUp/linkDown SNMP notifications + should be generated for this interface. + + If this node is not configured, the value 'enabled' is + operationally used by the server for interfaces that do + not operate on top of any other interface (i.e., there are + no 'lower-layer-if' entries), and 'disabled' otherwise."; + reference + "RFC 2863: The Interfaces Group MIB - + ifLinkUpDownTrapEnable"; + } + + leaf admin-status { + if-feature if-mib; + type enumeration { + enum up { + value 1; + description + "Ready to pass packets."; + } + enum down { + value 2; + description + "Not ready to pass packets and not in some test mode."; + } + enum testing { + value 3; + description + "In some test mode."; + } + } + config false; + mandatory true; + description + "The desired state of the interface. + + This leaf has the same read semantics as ifAdminStatus."; + reference + "RFC 2863: The Interfaces Group MIB - ifAdminStatus"; + } + + leaf oper-status { + type enumeration { + enum up { + value 1; + description + "Ready to pass packets."; + } + enum down { + value 2; + + description + "The interface does not pass any packets."; + } + enum testing { + value 3; + description + "In some test mode. No operational packets can + be passed."; + } + enum unknown { + value 4; + description + "Status cannot be determined for some reason."; + } + enum dormant { + value 5; + description + "Waiting for some external event."; + } + enum not-present { + value 6; + description + "Some component (typically hardware) is missing."; + } + enum lower-layer-down { + value 7; + description + "Down due to state of lower-layer interface(s)."; + } + } + config false; + mandatory true; + description + "The current operational state of the interface. + + This leaf has the same semantics as ifOperStatus."; + reference + "RFC 2863: The Interfaces Group MIB - ifOperStatus"; + } + + leaf last-change { + type yang:date-and-time; + config false; + description + "The time the interface entered its current operational + state. If the current state was entered prior to the + last re-initialization of the local network management + subsystem, then this node is not present."; + reference + "RFC 2863: The Interfaces Group MIB - ifLastChange"; + } + + leaf if-index { + if-feature if-mib; + type int32 { + range "1..2147483647"; + } + config false; + mandatory true; + description + "The ifIndex value for the ifEntry represented by this + interface."; + reference + "RFC 2863: The Interfaces Group MIB - ifIndex"; + } + + leaf phys-address { + type yang:phys-address; + config false; + description + "The interface's address at its protocol sub-layer. For + example, for an 802.x interface, this object normally + contains a Media Access Control (MAC) address. The + interface's media-specific modules must define the bit + and byte ordering and the format of the value of this + object. For interfaces that do not have such an address + (e.g., a serial line), this node is not present."; + reference + "RFC 2863: The Interfaces Group MIB - ifPhysAddress"; + } + + leaf-list higher-layer-if { + type interface-ref; + config false; + description + "A list of references to interfaces layered on top of this + interface."; + reference + "RFC 2863: The Interfaces Group MIB - ifStackTable"; + } + + leaf-list lower-layer-if { + type interface-ref; + config false; + + description + "A list of references to interfaces layered underneath this + interface."; + reference + "RFC 2863: The Interfaces Group MIB - ifStackTable"; + } + + leaf speed { + type yang:gauge64; + units "bits/second"; + config false; + description + "An estimate of the interface's current bandwidth in bits + per second. For interfaces that do not vary in + bandwidth or for those where no accurate estimation can + be made, this node should contain the nominal bandwidth. + For interfaces that have no concept of bandwidth, this + node is not present."; + reference + "RFC 2863: The Interfaces Group MIB - + ifSpeed, ifHighSpeed"; + } + + container statistics { + config false; + description + "A collection of interface-related statistics objects."; + + leaf discontinuity-time { + type yang:date-and-time; + mandatory true; + description + "The time on the most recent occasion at which any one or + more of this interface's counters suffered a + discontinuity. If no such discontinuities have occurred + since the last re-initialization of the local management + subsystem, then this node contains the time the local + management subsystem re-initialized itself."; + } + + leaf in-octets { + type yang:counter64; + description + "The total number of octets received on the interface, + including framing characters. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifHCInOctets"; + } + + leaf in-unicast-pkts { + type yang:counter64; + description + "The number of packets, delivered by this sub-layer to a + higher (sub-)layer, that were not addressed to a + multicast or broadcast address at this sub-layer. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifHCInUcastPkts"; + } + + leaf in-broadcast-pkts { + type yang:counter64; + description + "The number of packets, delivered by this sub-layer to a + higher (sub-)layer, that were addressed to a broadcast + address at this sub-layer. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - + ifHCInBroadcastPkts"; + } + + leaf in-multicast-pkts { + type yang:counter64; + description + "The number of packets, delivered by this sub-layer to a + higher (sub-)layer, that were addressed to a multicast + address at this sub-layer. For a MAC-layer protocol, + this includes both Group and Functional addresses. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - + ifHCInMulticastPkts"; + } + + leaf in-discards { + type yang:counter32; + description + "The number of inbound packets that were chosen to be + discarded even though no errors had been detected to + prevent their being deliverable to a higher-layer + protocol. One possible reason for discarding such a + packet could be to free up buffer space. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifInDiscards"; + } + + leaf in-errors { + type yang:counter32; + description + "For packet-oriented interfaces, the number of inbound + packets that contained errors preventing them from being + deliverable to a higher-layer protocol. For character- + oriented or fixed-length interfaces, the number of + inbound transmission units that contained errors + preventing them from being deliverable to a higher-layer + protocol. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifInErrors"; + } + + leaf in-unknown-protos { + type yang:counter32; + + description + "For packet-oriented interfaces, the number of packets + received via the interface that were discarded because + of an unknown or unsupported protocol. For + character-oriented or fixed-length interfaces that + support protocol multiplexing, the number of + transmission units received via the interface that were + discarded because of an unknown or unsupported protocol. + For any interface that does not support protocol + multiplexing, this counter is not present. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifInUnknownProtos"; + } + + leaf out-octets { + type yang:counter64; + description + "The total number of octets transmitted out of the + interface, including framing characters. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifHCOutOctets"; + } + + leaf out-unicast-pkts { + type yang:counter64; + description + "The total number of packets that higher-level protocols + requested be transmitted and that were not addressed + to a multicast or broadcast address at this sub-layer, + including those that were discarded or not sent. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifHCOutUcastPkts"; + } + + leaf out-broadcast-pkts { + type yang:counter64; + description + "The total number of packets that higher-level protocols + requested be transmitted and that were addressed to a + broadcast address at this sub-layer, including those + that were discarded or not sent. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - + ifHCOutBroadcastPkts"; + } + + leaf out-multicast-pkts { + type yang:counter64; + description + "The total number of packets that higher-level protocols + requested be transmitted and that were addressed to a + multicast address at this sub-layer, including those + that were discarded or not sent. For a MAC-layer + protocol, this includes both Group and Functional + addresses. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - + ifHCOutMulticastPkts"; + } + + leaf out-discards { + type yang:counter32; + description + "The number of outbound packets that were chosen to be + discarded even though no errors had been detected to + prevent their being transmitted. One possible reason + for discarding such a packet could be to free up buffer + space. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifOutDiscards"; + } + + leaf out-errors { + type yang:counter32; + description + "For packet-oriented interfaces, the number of outbound + packets that could not be transmitted because of errors. + For character-oriented or fixed-length interfaces, the + number of outbound transmission units that could not be + transmitted because of errors. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifOutErrors"; + } + } + + } + } + + /* + * Legacy typedefs + */ + + typedef interface-state-ref { + type leafref { + path "/if:interfaces-state/if:interface/if:name"; + } + status deprecated; + description + "This type is used by data models that need to reference + the operationally present interfaces."; + } + + /* + * Legacy operational state data nodes + */ + + container interfaces-state { + config false; + status deprecated; + description + "Data nodes for the operational state of interfaces."; + + list interface { + key "name"; + status deprecated; + + description + "The list of interfaces on the device. + + System-controlled interfaces created by the system are + always present in this list, whether or not they are + configured."; + + leaf name { + type string; + status deprecated; + description + "The name of the interface. + + A server implementation MAY map this leaf to the ifName + MIB object. Such an implementation needs to use some + mechanism to handle the differences in size and characters + allowed between this leaf and ifName. The definition of + such a mechanism is outside the scope of this document."; + reference + "RFC 2863: The Interfaces Group MIB - ifName"; + } + + leaf type { + type identityref { + base interface-type; + } + mandatory true; + status deprecated; + description + "The type of the interface."; + reference + "RFC 2863: The Interfaces Group MIB - ifType"; + } + + leaf admin-status { + if-feature if-mib; + type enumeration { + enum up { + value 1; + description + "Ready to pass packets."; + } + enum down { + value 2; + description + "Not ready to pass packets and not in some test mode."; + } + enum testing { + value 3; + description + "In some test mode."; + } + } + mandatory true; + status deprecated; + description + "The desired state of the interface. + + This leaf has the same read semantics as ifAdminStatus."; + reference + "RFC 2863: The Interfaces Group MIB - ifAdminStatus"; + } + + leaf oper-status { + type enumeration { + enum up { + value 1; + description + "Ready to pass packets."; + } + enum down { + value 2; + description + "The interface does not pass any packets."; + } + enum testing { + value 3; + description + "In some test mode. No operational packets can + be passed."; + } + enum unknown { + value 4; + description + "Status cannot be determined for some reason."; + } + enum dormant { + value 5; + description + "Waiting for some external event."; + } + enum not-present { + value 6; + description + "Some component (typically hardware) is missing."; + } + enum lower-layer-down { + value 7; + description + "Down due to state of lower-layer interface(s)."; + } + } + mandatory true; + status deprecated; + description + "The current operational state of the interface. + + This leaf has the same semantics as ifOperStatus."; + reference + "RFC 2863: The Interfaces Group MIB - ifOperStatus"; + } + + leaf last-change { + type yang:date-and-time; + status deprecated; + description + "The time the interface entered its current operational + state. If the current state was entered prior to the + last re-initialization of the local network management + subsystem, then this node is not present."; + reference + "RFC 2863: The Interfaces Group MIB - ifLastChange"; + } + + leaf if-index { + if-feature if-mib; + type int32 { + range "1..2147483647"; + } + mandatory true; + status deprecated; + description + "The ifIndex value for the ifEntry represented by this + interface."; + + reference + "RFC 2863: The Interfaces Group MIB - ifIndex"; + } + + leaf phys-address { + type yang:phys-address; + status deprecated; + description + "The interface's address at its protocol sub-layer. For + example, for an 802.x interface, this object normally + contains a Media Access Control (MAC) address. The + interface's media-specific modules must define the bit + and byte ordering and the format of the value of this + object. For interfaces that do not have such an address + (e.g., a serial line), this node is not present."; + reference + "RFC 2863: The Interfaces Group MIB - ifPhysAddress"; + } + + leaf-list higher-layer-if { + type interface-state-ref; + status deprecated; + description + "A list of references to interfaces layered on top of this + interface."; + reference + "RFC 2863: The Interfaces Group MIB - ifStackTable"; + } + + leaf-list lower-layer-if { + type interface-state-ref; + status deprecated; + description + "A list of references to interfaces layered underneath this + interface."; + reference + "RFC 2863: The Interfaces Group MIB - ifStackTable"; + } + + leaf speed { + type yang:gauge64; + units "bits/second"; + status deprecated; + description + "An estimate of the interface's current bandwidth in bits + per second. For interfaces that do not vary in + bandwidth or for those where no accurate estimation can + + be made, this node should contain the nominal bandwidth. + For interfaces that have no concept of bandwidth, this + node is not present."; + reference + "RFC 2863: The Interfaces Group MIB - + ifSpeed, ifHighSpeed"; + } + + container statistics { + status deprecated; + description + "A collection of interface-related statistics objects."; + + leaf discontinuity-time { + type yang:date-and-time; + mandatory true; + status deprecated; + description + "The time on the most recent occasion at which any one or + more of this interface's counters suffered a + discontinuity. If no such discontinuities have occurred + since the last re-initialization of the local management + subsystem, then this node contains the time the local + management subsystem re-initialized itself."; + } + + leaf in-octets { + type yang:counter64; + status deprecated; + description + "The total number of octets received on the interface, + including framing characters. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifHCInOctets"; + } + + leaf in-unicast-pkts { + type yang:counter64; + status deprecated; + description + "The number of packets, delivered by this sub-layer to a + higher (sub-)layer, that were not addressed to a + multicast or broadcast address at this sub-layer. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifHCInUcastPkts"; + } + + leaf in-broadcast-pkts { + type yang:counter64; + status deprecated; + description + "The number of packets, delivered by this sub-layer to a + higher (sub-)layer, that were addressed to a broadcast + address at this sub-layer. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - + ifHCInBroadcastPkts"; + } + + leaf in-multicast-pkts { + type yang:counter64; + status deprecated; + description + "The number of packets, delivered by this sub-layer to a + higher (sub-)layer, that were addressed to a multicast + address at this sub-layer. For a MAC-layer protocol, + this includes both Group and Functional addresses. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - + ifHCInMulticastPkts"; + } + + leaf in-discards { + type yang:counter32; + status deprecated; + + description + "The number of inbound packets that were chosen to be + discarded even though no errors had been detected to + prevent their being deliverable to a higher-layer + protocol. One possible reason for discarding such a + packet could be to free up buffer space. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifInDiscards"; + } + + leaf in-errors { + type yang:counter32; + status deprecated; + description + "For packet-oriented interfaces, the number of inbound + packets that contained errors preventing them from being + deliverable to a higher-layer protocol. For character- + oriented or fixed-length interfaces, the number of + inbound transmission units that contained errors + preventing them from being deliverable to a higher-layer + protocol. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifInErrors"; + } + + leaf in-unknown-protos { + type yang:counter32; + status deprecated; + description + "For packet-oriented interfaces, the number of packets + received via the interface that were discarded because + of an unknown or unsupported protocol. For + character-oriented or fixed-length interfaces that + support protocol multiplexing, the number of + transmission units received via the interface that were + discarded because of an unknown or unsupported protocol. + For any interface that does not support protocol + multiplexing, this counter is not present. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifInUnknownProtos"; + } + + leaf out-octets { + type yang:counter64; + status deprecated; + description + "The total number of octets transmitted out of the + interface, including framing characters. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifHCOutOctets"; + } + + leaf out-unicast-pkts { + type yang:counter64; + status deprecated; + description + "The total number of packets that higher-level protocols + requested be transmitted and that were not addressed + to a multicast or broadcast address at this sub-layer, + including those that were discarded or not sent. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifHCOutUcastPkts"; + } + + leaf out-broadcast-pkts { + type yang:counter64; + status deprecated; + + description + "The total number of packets that higher-level protocols + requested be transmitted and that were addressed to a + broadcast address at this sub-layer, including those + that were discarded or not sent. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - + ifHCOutBroadcastPkts"; + } + + leaf out-multicast-pkts { + type yang:counter64; + status deprecated; + description + "The total number of packets that higher-level protocols + requested be transmitted and that were addressed to a + multicast address at this sub-layer, including those + that were discarded or not sent. For a MAC-layer + protocol, this includes both Group and Functional + addresses. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - + ifHCOutMulticastPkts"; + } + + leaf out-discards { + type yang:counter32; + status deprecated; + description + "The number of outbound packets that were chosen to be + discarded even though no errors had been detected to + prevent their being transmitted. One possible reason + for discarding such a packet could be to free up buffer + space. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifOutDiscards"; + } + + leaf out-errors { + type yang:counter32; + status deprecated; + description + "For packet-oriented interfaces, the number of outbound + packets that could not be transmitted because of errors. + For character-oriented or fixed-length interfaces, the + number of outbound transmission units that could not be + transmitted because of errors. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifOutErrors"; + } + } + } + } +} diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_acl/yang/ietf-packet-fields@2019-03-04.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/yang/ietf-packet-fields@2019-03-04.yang new file mode 100644 index 0000000000000000000000000000000000000000..2fb797bd87bf4ed825f83ec788df707b94c5f68b --- /dev/null +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/yang/ietf-packet-fields@2019-03-04.yang @@ -0,0 +1,576 @@ +module ietf-packet-fields { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-packet-fields"; + prefix packet-fields; + + import ietf-inet-types { + prefix inet; + reference + "RFC 6991 - Common YANG Data Types."; + } + + import ietf-yang-types { + prefix yang; + reference + "RFC 6991 - Common YANG Data Types."; + } + + import ietf-ethertypes { + prefix eth; + reference + "RFC 8519 - YANG Data Model for Network Access Control + Lists (ACLs)."; + } + + organization + "IETF NETMOD (Network Modeling) Working Group."; + + contact + "WG Web: + WG List: netmod@ietf.org + + Editor: Mahesh Jethanandani + mjethanandani@gmail.com + Editor: Lisa Huang + huangyi_99@yahoo.com + Editor: Sonal Agarwal + sagarwal12@gmail.com + Editor: Dana Blair + dana@blairhome.com"; + + description + "This YANG module defines groupings that are used by + the ietf-access-control-list YANG module. Their usage + is not limited to ietf-access-control-list and can be + used anywhere as applicable. + + Copyright (c) 2019 IETF Trust and the persons identified as + the document authors. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD + License set forth in Section 4.c of the IETF Trust's Legal + Provisions Relating to IETF Documents + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 8519; see + the RFC itself for full legal notices."; + + revision 2019-03-04 { + description + "Initial version."; + reference + "RFC 8519: YANG Data Model for Network Access Control + Lists (ACLs)."; + } + + /* + * Typedefs + */ + typedef operator { + type enumeration { + enum lte { + description + "Less than or equal to."; + } + enum gte { + description + "Greater than or equal to."; + } + enum eq { + description + "Equal to."; + } + enum neq { + description + "Not equal to."; + } + } + description + "The source and destination port range definitions + can be further qualified using an operator. An + operator is needed only if the lower-port is specified + and the upper-port is not specified. The operator + therefore further qualifies the lower-port only."; + } + + /* + * Groupings + */ + grouping port-range-or-operator { + choice port-range-or-operator { + case range { + leaf lower-port { + type inet:port-number; + must '. <= ../upper-port' { + error-message + "The lower-port must be less than or equal to + the upper-port."; + } + mandatory true; + description + "Lower boundary for a port."; + } + leaf upper-port { + type inet:port-number; + mandatory true; + description + "Upper boundary for a port."; + } + } + case operator { + leaf operator { + type operator; + default "eq"; + description + "Operator to be applied on the port below."; + } + leaf port { + type inet:port-number; + mandatory true; + description + "Port number along with the operator on which to + match."; + } + } + description + "Choice of specifying a port range or a single + port along with an operator."; + } + description + "Grouping for port definitions in the form of a + choice statement."; + } + + grouping acl-ip-header-fields { + description + "IP header fields common to IPv4 and IPv6"; + reference + "RFC 791: Internet Protocol."; + + leaf dscp { + type inet:dscp; + description + "Differentiated Services Code Point."; + reference + "RFC 2474: Definition of the Differentiated Services + Field (DS Field) in the IPv4 and IPv6 + Headers."; + } + + leaf ecn { + type uint8 { + range "0..3"; + } + description + "Explicit Congestion Notification."; + reference + "RFC 3168: The Addition of Explicit Congestion + Notification (ECN) to IP."; + } + + leaf length { + type uint16; + description + "In the IPv4 header field, this field is known as the Total + Length. Total Length is the length of the datagram, measured + in octets, including internet header and data. + + In the IPv6 header field, this field is known as the Payload + Length, which is the length of the IPv6 payload, i.e., the rest + of the packet following the IPv6 header, in octets."; + reference + "RFC 791: Internet Protocol + RFC 8200: Internet Protocol, Version 6 (IPv6) Specification."; + } + leaf ttl { + type uint8; + description + "This field indicates the maximum time the datagram is allowed + to remain in the internet system. If this field contains the + value zero, then the datagram must be dropped. + + In IPv6, this field is known as the Hop Limit."; + reference + "RFC 791: Internet Protocol + RFC 8200: Internet Protocol, Version 6 (IPv6) Specification."; + } + leaf protocol { + type uint8; + description + "Internet Protocol number. Refers to the protocol of the + payload. In IPv6, this field is known as 'next-header', + and if extension headers are present, the protocol is + present in the 'upper-layer' header."; + reference + "RFC 791: Internet Protocol + RFC 8200: Internet Protocol, Version 6 (IPv6) Specification."; + } + } + + grouping acl-ipv4-header-fields { + description + "Fields in the IPv4 header."; + leaf ihl { + type uint8 { + range "5..60"; + } + description + "In an IPv4 header field, the Internet Header Length (IHL) is + the length of the internet header in 32-bit words and + thus points to the beginning of the data. Note that the + minimum value for a correct header is 5."; + } + leaf flags { + type bits { + bit reserved { + position 0; + description + "Reserved. Must be zero."; + } + bit fragment { + position 1; + description + "Setting the value to 0 indicates may fragment, while + setting the value to 1 indicates do not fragment."; + } + bit more { + position 2; + description + "Setting the value to 0 indicates this is the last fragment, + and setting the value to 1 indicates more fragments are + coming."; + } + } + description + "Bit definitions for the Flags field in the IPv4 header."; + } + leaf offset { + type uint16 { + range "20..65535"; + } + description + "The fragment offset is measured in units of 8 octets (64 bits). + The first fragment has offset zero. The length is 13 bits"; + } + leaf identification { + type uint16; + description + "An identifying value assigned by the sender to aid in + assembling the fragments of a datagram."; + } + + choice destination-network { + case destination-ipv4-network { + leaf destination-ipv4-network { + type inet:ipv4-prefix; + description + "Destination IPv4 address prefix."; + } + } + description + "Choice of specifying a destination IPv4 address or + referring to a group of IPv4 destination addresses."; + } + + choice source-network { + case source-ipv4-network { + leaf source-ipv4-network { + type inet:ipv4-prefix; + description + "Source IPv4 address prefix."; + } + } + description + "Choice of specifying a source IPv4 address or + referring to a group of IPv4 source addresses."; + } + } + + grouping acl-ipv6-header-fields { + description + "Fields in the IPv6 header."; + + choice destination-network { + case destination-ipv6-network { + leaf destination-ipv6-network { + type inet:ipv6-prefix; + description + "Destination IPv6 address prefix."; + } + } + description + "Choice of specifying a destination IPv6 address + or referring to a group of IPv6 destination + addresses."; + } + + choice source-network { + case source-ipv6-network { + leaf source-ipv6-network { + type inet:ipv6-prefix; + description + "Source IPv6 address prefix."; + } + } + description + "Choice of specifying a source IPv6 address or + referring to a group of IPv6 source addresses."; + } + + leaf flow-label { + type inet:ipv6-flow-label; + description + "IPv6 Flow label."; + } + reference + "RFC 4291: IP Version 6 Addressing Architecture + RFC 4007: IPv6 Scoped Address Architecture + RFC 5952: A Recommendation for IPv6 Address Text + Representation."; + } + + grouping acl-eth-header-fields { + description + "Fields in the Ethernet header."; + leaf destination-mac-address { + type yang:mac-address; + description + "Destination IEEE 802 Media Access Control (MAC) + address."; + } + leaf destination-mac-address-mask { + type yang:mac-address; + description + "Destination IEEE 802 MAC address mask."; + } + leaf source-mac-address { + type yang:mac-address; + description + "Source IEEE 802 MAC address."; + } + leaf source-mac-address-mask { + type yang:mac-address; + description + "Source IEEE 802 MAC address mask."; + } + leaf ethertype { + type eth:ethertype; + description + "The Ethernet Type (or Length) value represented + in the canonical order defined by IEEE 802. + The canonical representation uses lowercase + characters."; + reference + "IEEE 802-2014, Clause 9.2."; + } + reference + "IEEE 802: IEEE Standard for Local and Metropolitan + Area Networks: Overview and Architecture."; + } + + grouping acl-tcp-header-fields { + description + "Collection of TCP header fields that can be used to + set up a match filter."; + leaf sequence-number { + type uint32; + description + "Sequence number that appears in the packet."; + } + leaf acknowledgement-number { + type uint32; + description + "The acknowledgement number that appears in the + packet."; + } + leaf data-offset { + type uint8 { + range "5..15"; + } + description + "Specifies the size of the TCP header in 32-bit + words. The minimum size header is 5 words and + the maximum is 15 words; thus, this gives a + minimum size of 20 bytes and a maximum of 60 + bytes, allowing for up to 40 bytes of options + in the header."; + } + leaf reserved { + type uint8; + description + "Reserved for future use."; + } + leaf flags { + type bits { + bit cwr { + position 1; + description + "The Congestion Window Reduced (CWR) flag is set + by the sending host to indicate that it received + a TCP segment with the ECN-Echo (ECE) flag set + and had responded in the congestion control + mechanism."; + reference + "RFC 3168: The Addition of Explicit Congestion + Notification (ECN) to IP."; + } + bit ece { + position 2; + description + "ECN-Echo has a dual role, depending on the value + of the SYN flag. It indicates the following: if + the SYN flag is set (1), the TCP peer is ECN + capable, and if the SYN flag is clear (0), a packet + with the Congestion Experienced flag set (ECN=11) + in the IP header was received during normal + transmission (added to the header by RFC 3168). + This serves as an indication of network congestion + (or impending congestion) to the TCP sender."; + reference + "RFC 3168: The Addition of Explicit Congestion + Notification (ECN) to IP."; + } + bit urg { + position 3; + description + "Indicates that the Urgent Pointer field is significant."; + } + bit ack { + position 4; + description + "Indicates that the Acknowledgement field is significant. + All packets after the initial SYN packet sent by the + client should have this flag set."; + } + bit psh { + position 5; + description + "Push function. Asks to push the buffered data to the + receiving application."; + } + bit rst { + position 6; + description + "Reset the connection."; + } + bit syn { + position 7; + description + "Synchronize sequence numbers. Only the first packet + sent from each end should have this flag set. Some + other flags and fields change meaning based on this + flag, and some are only valid for when it is set, + and others when it is clear."; + } + bit fin { + position 8; + description + "Last package from the sender."; + } + } + description + "Also known as Control Bits. Contains nine 1-bit flags."; + reference + "RFC 793: Transmission Control Protocol."; + } + leaf window-size { + type uint16; + units "bytes"; + description + "The size of the receive window, which specifies + the number of window size units beyond the segment + identified by the sequence number in the Acknowledgement + field that the sender of this segment is currently + willing to receive."; + } + leaf urgent-pointer { + type uint16; + description + "This field is an offset from the sequence number + indicating the last urgent data byte."; + } + leaf options { + type binary { + length "1..40"; + } + description + "The length of this field is determined by the + Data Offset field. Options have up to three + fields: Option-Kind (1 byte), Option-Length + (1 byte), and Option-Data (variable). The Option-Kind + field indicates the type of option and is the + only field that is not optional. Depending on + what kind of option we are dealing with, + the next two fields may be set: the Option-Length + field indicates the total length of the option, + and the Option-Data field contains the value of + the option, if applicable."; + } + } + + grouping acl-udp-header-fields { + description + "Collection of UDP header fields that can be used + to set up a match filter."; + leaf length { + type uint16; + description + "A field that specifies the length in bytes of + the UDP header and UDP data. The minimum + length is 8 bytes because that is the length of + the header. The field size sets a theoretical + limit of 65,535 bytes (8-byte header plus 65,527 + bytes of data) for a UDP datagram. However, the + actual limit for the data length, which is + imposed by the underlying IPv4 protocol, is + 65,507 bytes (65,535 minus 8-byte UDP header + minus 20-byte IP header). + + In IPv6 jumbograms, it is possible to have + UDP packets of a size greater than 65,535 bytes. + RFC 2675 specifies that the Length field is set + to zero if the length of the UDP header plus + UDP data is greater than 65,535."; + } + } + + grouping acl-icmp-header-fields { + description + "Collection of ICMP header fields that can be + used to set up a match filter."; + leaf type { + type uint8; + description + "Also known as control messages."; + reference + "RFC 792: Internet Control Message Protocol + RFC 4443: Internet Control Message Protocol (ICMPv6) + for Internet Protocol Version 6 (IPv6) + Specification."; + } + leaf code { + type uint8; + description + "ICMP subtype. Also known as control messages."; + reference + "RFC 792: Internet Control Message Protocol + RFC 4443: Internet Control Message Protocol (ICMPv6) + for Internet Protocol Version 6 (IPv6) + Specification."; + } + leaf rest-of-header { + type binary; + description + "Unbounded in length, the contents vary based on the + ICMP type and code. Also referred to as 'Message Body' + in ICMPv6."; + reference + "RFC 792: Internet Control Message Protocol + RFC 4443: Internet Control Message Protocol (ICMPv6) + for Internet Protocol Version 6 (IPv6) + Specification."; + } + } +} diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_acl/yang/ietf-yang-types@2013-07-15.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/yang/ietf-yang-types@2013-07-15.yang new file mode 100644 index 0000000000000000000000000000000000000000..956562a7b342055127961732d8bde4be21c80d7d --- /dev/null +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_acl/yang/ietf-yang-types@2013-07-15.yang @@ -0,0 +1,475 @@ + module ietf-yang-types { + + namespace "urn:ietf:params:xml:ns:yang:ietf-yang-types"; + prefix "yang"; + + organization + "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; + + contact + "WG Web: + WG List: + + WG Chair: David Kessens + + + WG Chair: Juergen Schoenwaelder + + + Editor: Juergen Schoenwaelder + "; + + description + "This module contains a collection of generally useful derived + YANG data types. + + Copyright (c) 2013 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 6991; see + the RFC itself for full legal notices."; + + revision 2013-07-15 { + description + "This revision adds the following new data types: + - yang-identifier + - hex-string + - uuid + - dotted-quad"; + reference + "RFC 6991: Common YANG Data Types"; + } + + revision 2010-09-24 { + description + "Initial revision."; + reference + "RFC 6021: Common YANG Data Types"; + } + + /*** collection of counter and gauge types ***/ + + typedef counter32 { + type uint32; + description + "The counter32 type represents a non-negative integer + that monotonically increases until it reaches a + maximum value of 2^32-1 (4294967295 decimal), when it + wraps around and starts increasing again from zero. + + Counters have no defined 'initial' value, and thus, a + single value of a counter has (in general) no information + content. Discontinuities in the monotonically increasing + value normally occur at re-initialization of the + management system, and at other times as specified in the + description of a schema node using this type. If such + other times can occur, for example, the creation of + a schema node of type counter32 at times other than + re-initialization, then a corresponding schema node + should be defined, with an appropriate type, to indicate + the last discontinuity. + + The counter32 type should not be used for configuration + schema nodes. A default statement SHOULD NOT be used in + combination with the type counter32. + + In the value set and its semantics, this type is equivalent + to the Counter32 type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef zero-based-counter32 { + type yang:counter32; + default "0"; + description + "The zero-based-counter32 type represents a counter32 + that has the defined 'initial' value zero. + + A schema node of this type will be set to zero (0) on creation + and will thereafter increase monotonically until it reaches + a maximum value of 2^32-1 (4294967295 decimal), when it + wraps around and starts increasing again from zero. + + Provided that an application discovers a new schema node + of this type within the minimum time to wrap, it can use the + 'initial' value as a delta. It is important for a management + station to be aware of this minimum time and the actual time + between polls, and to discard data if the actual time is too + long or there is no defined minimum time. + + In the value set and its semantics, this type is equivalent + to the ZeroBasedCounter32 textual convention of the SMIv2."; + reference + "RFC 4502: Remote Network Monitoring Management Information + Base Version 2"; + } + + typedef counter64 { + type uint64; + description + "The counter64 type represents a non-negative integer + that monotonically increases until it reaches a + maximum value of 2^64-1 (18446744073709551615 decimal), + when it wraps around and starts increasing again from zero. + + Counters have no defined 'initial' value, and thus, a + single value of a counter has (in general) no information + content. Discontinuities in the monotonically increasing + value normally occur at re-initialization of the + management system, and at other times as specified in the + description of a schema node using this type. If such + other times can occur, for example, the creation of + a schema node of type counter64 at times other than + re-initialization, then a corresponding schema node + should be defined, with an appropriate type, to indicate + the last discontinuity. + + The counter64 type should not be used for configuration + schema nodes. A default statement SHOULD NOT be used in + combination with the type counter64. + + In the value set and its semantics, this type is equivalent + to the Counter64 type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef zero-based-counter64 { + type yang:counter64; + default "0"; + description + "The zero-based-counter64 type represents a counter64 that + has the defined 'initial' value zero. + + A schema node of this type will be set to zero (0) on creation + and will thereafter increase monotonically until it reaches + a maximum value of 2^64-1 (18446744073709551615 decimal), + when it wraps around and starts increasing again from zero. + + Provided that an application discovers a new schema node + of this type within the minimum time to wrap, it can use the + 'initial' value as a delta. It is important for a management + station to be aware of this minimum time and the actual time + between polls, and to discard data if the actual time is too + long or there is no defined minimum time. + + In the value set and its semantics, this type is equivalent + to the ZeroBasedCounter64 textual convention of the SMIv2."; + reference + "RFC 2856: Textual Conventions for Additional High Capacity + Data Types"; + } + + typedef gauge32 { + type uint32; + description + "The gauge32 type represents a non-negative integer, which + may increase or decrease, but shall never exceed a maximum + value, nor fall below a minimum value. The maximum value + cannot be greater than 2^32-1 (4294967295 decimal), and + the minimum value cannot be smaller than 0. The value of + a gauge32 has its maximum value whenever the information + being modeled is greater than or equal to its maximum + value, and has its minimum value whenever the information + being modeled is smaller than or equal to its minimum value. + If the information being modeled subsequently decreases + below (increases above) the maximum (minimum) value, the + gauge32 also decreases (increases). + + In the value set and its semantics, this type is equivalent + to the Gauge32 type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef gauge64 { + type uint64; + description + "The gauge64 type represents a non-negative integer, which + may increase or decrease, but shall never exceed a maximum + value, nor fall below a minimum value. The maximum value + cannot be greater than 2^64-1 (18446744073709551615), and + the minimum value cannot be smaller than 0. The value of + a gauge64 has its maximum value whenever the information + being modeled is greater than or equal to its maximum + value, and has its minimum value whenever the information + being modeled is smaller than or equal to its minimum value. + If the information being modeled subsequently decreases + below (increases above) the maximum (minimum) value, the + gauge64 also decreases (increases). + + In the value set and its semantics, this type is equivalent + to the CounterBasedGauge64 SMIv2 textual convention defined + in RFC 2856"; + reference + "RFC 2856: Textual Conventions for Additional High Capacity + Data Types"; + } + + /*** collection of identifier-related types ***/ + + typedef object-identifier { + type string { + pattern '(([0-1](\.[1-3]?[0-9]))|(2\.(0|([1-9]\d*))))' + + '(\.(0|([1-9]\d*)))*'; + } + description + "The object-identifier type represents administratively + assigned names in a registration-hierarchical-name tree. + + Values of this type are denoted as a sequence of numerical + non-negative sub-identifier values. Each sub-identifier + value MUST NOT exceed 2^32-1 (4294967295). Sub-identifiers + are separated by single dots and without any intermediate + whitespace. + + The ASN.1 standard restricts the value space of the first + sub-identifier to 0, 1, or 2. Furthermore, the value space + of the second sub-identifier is restricted to the range + 0 to 39 if the first sub-identifier is 0 or 1. Finally, + the ASN.1 standard requires that an object identifier + has always at least two sub-identifiers. The pattern + captures these restrictions. + + Although the number of sub-identifiers is not limited, + module designers should realize that there may be + implementations that stick with the SMIv2 limit of 128 + sub-identifiers. + + This type is a superset of the SMIv2 OBJECT IDENTIFIER type + since it is not restricted to 128 sub-identifiers. Hence, + this type SHOULD NOT be used to represent the SMIv2 OBJECT + IDENTIFIER type; the object-identifier-128 type SHOULD be + used instead."; + reference + "ISO9834-1: Information technology -- Open Systems + Interconnection -- Procedures for the operation of OSI + Registration Authorities: General procedures and top + arcs of the ASN.1 Object Identifier tree"; + } + + typedef object-identifier-128 { + type object-identifier { + pattern '\d*(\.\d*){1,127}'; + } + description + "This type represents object-identifiers restricted to 128 + sub-identifiers. + + In the value set and its semantics, this type is equivalent + to the OBJECT IDENTIFIER type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef yang-identifier { + type string { + length "1..max"; + pattern '[a-zA-Z_][a-zA-Z0-9\-_.]*'; + pattern '.|..|[^xX].*|.[^mM].*|..[^lL].*'; + } + description + "A YANG identifier string as defined by the 'identifier' + rule in Section 12 of RFC 6020. An identifier must + start with an alphabetic character or an underscore + followed by an arbitrary sequence of alphabetic or + numeric characters, underscores, hyphens, or dots. + + A YANG identifier MUST NOT start with any possible + combination of the lowercase or uppercase character + sequence 'xml'."; + reference + "RFC 6020: YANG - A Data Modeling Language for the Network + Configuration Protocol (NETCONF)"; + } + + /*** collection of types related to date and time***/ + + typedef date-and-time { + type string { + pattern '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?' + + '(Z|[\+\-]\d{2}:\d{2})'; + } + description + "The date-and-time type is a profile of the ISO 8601 + standard for representation of dates and times using the + Gregorian calendar. The profile is defined by the + date-time production in Section 5.6 of RFC 3339. + + The date-and-time type is compatible with the dateTime XML + schema type with the following notable exceptions: + + (a) The date-and-time type does not allow negative years. + + (b) The date-and-time time-offset -00:00 indicates an unknown + time zone (see RFC 3339) while -00:00 and +00:00 and Z + all represent the same time zone in dateTime. + + (c) The canonical format (see below) of data-and-time values + differs from the canonical format used by the dateTime XML + schema type, which requires all times to be in UTC using + the time-offset 'Z'. + + This type is not equivalent to the DateAndTime textual + convention of the SMIv2 since RFC 3339 uses a different + separator between full-date and full-time and provides + higher resolution of time-secfrac. + + The canonical format for date-and-time values with a known time + zone uses a numeric time zone offset that is calculated using + the device's configured known offset to UTC time. A change of + the device's offset to UTC time will cause date-and-time values + to change accordingly. Such changes might happen periodically + in case a server follows automatically daylight saving time + (DST) time zone offset changes. The canonical format for + date-and-time values with an unknown time zone (usually + referring to the notion of local time) uses the time-offset + -00:00."; + reference + "RFC 3339: Date and Time on the Internet: Timestamps + RFC 2579: Textual Conventions for SMIv2 + XSD-TYPES: XML Schema Part 2: Datatypes Second Edition"; + } + + typedef timeticks { + type uint32; + description + "The timeticks type represents a non-negative integer that + represents the time, modulo 2^32 (4294967296 decimal), in + hundredths of a second between two epochs. When a schema + node is defined that uses this type, the description of + the schema node identifies both of the reference epochs. + + In the value set and its semantics, this type is equivalent + to the TimeTicks type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef timestamp { + type yang:timeticks; + description + "The timestamp type represents the value of an associated + timeticks schema node at which a specific occurrence + happened. The specific occurrence must be defined in the + description of any schema node defined using this type. When + the specific occurrence occurred prior to the last time the + associated timeticks attribute was zero, then the timestamp + value is zero. Note that this requires all timestamp values + to be reset to zero when the value of the associated timeticks + attribute reaches 497+ days and wraps around to zero. + + The associated timeticks schema node must be specified + in the description of any schema node using this type. + + In the value set and its semantics, this type is equivalent + to the TimeStamp textual convention of the SMIv2."; + reference + "RFC 2579: Textual Conventions for SMIv2"; + } + + /*** collection of generic address types ***/ + + typedef phys-address { + type string { + pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?'; + } + + description + "Represents media- or physical-level addresses represented + as a sequence octets, each octet represented by two hexadecimal + numbers. Octets are separated by colons. The canonical + representation uses lowercase characters. + + In the value set and its semantics, this type is equivalent + to the PhysAddress textual convention of the SMIv2."; + reference + "RFC 2579: Textual Conventions for SMIv2"; + } + + typedef mac-address { + type string { + pattern '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'; + } + description + "The mac-address type represents an IEEE 802 MAC address. + The canonical representation uses lowercase characters. + + In the value set and its semantics, this type is equivalent + to the MacAddress textual convention of the SMIv2."; + reference + "IEEE 802: IEEE Standard for Local and Metropolitan Area + Networks: Overview and Architecture + RFC 2579: Textual Conventions for SMIv2"; + } + + /*** collection of XML-specific types ***/ + + typedef xpath1.0 { + type string; + description + "This type represents an XPATH 1.0 expression. + + When a schema node is defined that uses this type, the + description of the schema node MUST specify the XPath + context in which the XPath expression is evaluated."; + reference + "XPATH: XML Path Language (XPath) Version 1.0"; + } + + /*** collection of string types ***/ + + typedef hex-string { + type string { + pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?'; + } + + description + "A hexadecimal string with octets represented as hex digits + separated by colons. The canonical representation uses + lowercase characters."; + } + + typedef uuid { + type string { + pattern '[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-' + + '[0-9a-fA-F]{4}-[0-9a-fA-F]{12}'; + } + description + "A Universally Unique IDentifier in the string representation + defined in RFC 4122. The canonical representation uses + lowercase characters. + + The following is an example of a UUID in string representation: + f81d4fae-7dec-11d0-a765-00a0c91e6bf6 + "; + reference + "RFC 4122: A Universally Unique IDentifier (UUID) URN + Namespace"; + } + + typedef dotted-quad { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'; + } + description + "An unsigned 32-bit number expressed in the dotted-quad + notation, i.e., four octets written as decimal numbers + and separated with the '.' (full stop) character."; + } + } diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_hardware/Hardware.py b/src/nbi/service/rest_server/nbi_plugins/ietf_hardware/Hardware.py new file mode 100644 index 0000000000000000000000000000000000000000..bce1d6d14d0663dd42b05fe8664271fcc777713d --- /dev/null +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_hardware/Hardware.py @@ -0,0 +1,53 @@ +# 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 +from flask import request +from flask.json import jsonify +from flask_restful import Resource +from common.tools.context_queries.Device import get_device +from context.client.ContextClient import ContextClient +from ..tools.Authentication import HTTP_AUTH +from ..tools.HttpStatusCodes import HTTP_OK, HTTP_SERVERERROR +from .YangHandler import YangHandler + +LOGGER = logging.getLogger(__name__) + +class Hardware(Resource): + @HTTP_AUTH.login_required + def get(self, device_uuid : str): + LOGGER.debug('Device UUID: {:s}'.format(str(device_uuid))) + LOGGER.debug('Request: {:s}'.format(str(request))) + + try: + context_client = ContextClient() + device = get_device( + context_client, device_uuid, rw_copy=False, + include_endpoints=False, include_config_rules=False, include_components=True + ) + if device is None: + raise Exception('Device({:s}) not found in database'.format(str(device_uuid))) + + yang_handler = YangHandler() + hardware_reply = yang_handler.compose(device) + yang_handler.destroy() + + response = jsonify(hardware_reply) + response.status_code = HTTP_OK + except Exception as e: # pylint: disable=broad-except + MSG = 'Something went wrong Retrieving Hardware of Device({:s})' + LOGGER.exception(MSG.format(str(device_uuid))) + response = jsonify({'error': str(e)}) + response.status_code = HTTP_SERVERERROR + return response diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_hardware/HardwareMultipleDevices.py b/src/nbi/service/rest_server/nbi_plugins/ietf_hardware/HardwareMultipleDevices.py new file mode 100644 index 0000000000000000000000000000000000000000..2ac0bf40ebca17abeb7c85775ed6d26630f06d5d --- /dev/null +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_hardware/HardwareMultipleDevices.py @@ -0,0 +1,50 @@ +# 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 +from flask import request +from flask.json import jsonify +from flask_restful import Resource +from common.proto.context_pb2 import Empty +from context.client.ContextClient import ContextClient +from ..tools.Authentication import HTTP_AUTH +from ..tools.HttpStatusCodes import HTTP_OK, HTTP_SERVERERROR +from .YangHandler import YangHandler + +LOGGER = logging.getLogger(__name__) + +class HardwareMultipleDevices(Resource): + @HTTP_AUTH.login_required + def get(self): + + LOGGER.debug('Request: {:s}'.format(str(request))) + + try: + context_client = ContextClient() + list_devices = context_client.ListDevices(Empty()) + LOGGER.info('Request: {:s}'.format(str(list_devices))) + hardware_list_reply = [] + yang_handler = YangHandler() + for device in list_devices.devices: + hardware_reply = yang_handler.compose(device) + hardware_list_reply.append(hardware_reply) + + yang_handler.destroy() + response = jsonify(hardware_list_reply) + response.status_code = HTTP_OK + except Exception as e: # pylint: disable=broad-except + MSG = 'Something went wrong Retrieving Hardware of Devices({:s})' + response = jsonify({'error': str(e)}) + response.status_code = HTTP_SERVERERROR + return response diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_hardware/YangHandler.py b/src/nbi/service/rest_server/nbi_plugins/ietf_hardware/YangHandler.py new file mode 100644 index 0000000000000000000000000000000000000000..fe6494231023f438d1304d7a08a040898c83de8d --- /dev/null +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_hardware/YangHandler.py @@ -0,0 +1,131 @@ +# 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 common.proto.context_pb2 import Device +from typing import Dict, Optional +import datetime +import json +import logging +import libyang +import os +import re + +LOGGER = logging.getLogger(__name__) +YANG_DIR = os.path.join(os.path.dirname(__file__), 'yang') +YANG_MODULES = [ + 'iana-hardware', + 'ietf-hardware', + 'ietf-network-hardware-inventory' +] + +class YangHandler: + def __init__(self) -> None: + self._yang_context = libyang.Context(YANG_DIR) + for yang_module_name in YANG_MODULES: + LOGGER.info('Loading module: {:s}'.format(str(yang_module_name))) + self._yang_context.load_module(yang_module_name).feature_enable_all() + + def parse_to_dict(self, message : Dict) -> Dict: + yang_module = self._yang_context.get_module('ietf-network-hardware-inventory') + dnode : Optional[libyang.DNode] = yang_module.parse_data_dict( + message, validate_present=True, validate=True, strict=True + ) + if dnode is None: raise Exception('Unable to parse Message({:s})'.format(str(message))) + message = dnode.print_dict() + dnode.free() + return message + + @staticmethod + def convert_to_iso_date(date_str: str) -> Optional[str]: + date_str = date_str.strip('"') + pattern = r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[\+\-]\d{2}:\d{2})" + if re.match(pattern, date_str): + return date_str + else: + try: + datetime_obj = datetime.datetime.strptime(date_str, "%Y-%m-%d") + iso_date = datetime_obj.isoformat() + "Z" + return iso_date + except ValueError: + return None + + def compose(self, device : Device) -> Dict: + hardware = self._yang_context.create_data_path('/ietf-network-hardware-inventory:network-hardware-inventory') + network_elements = hardware.create_path('network-elements') + + network_element = network_elements.create_path('network-element[uuid="{:s}"]'.format(device.device_id.device_uuid.uuid)) + network_element.create_path('uuid', device.device_id.device_uuid.uuid) + network_element.create_path('name', device.name) + components = network_element.create_path('components') + physical_index = 1 + + for component in device.components: + attributes = component.attributes + component_new = components.create_path('component[uuid="{:s}"]'.format(component.component_uuid.uuid)) + component_new.create_path('name', component.name) + component_type = component.type + if component_type == "TRANSCEIVER" : + component_type = "module" + if component_type == "FRU" : + component_type = "slack" + + component_type = component_type.replace("_", "-").lower() + component_type = 'iana-hardware:' + component_type + component_new.create_path('class', component_type) + physical_index += 1 + component_new.create_path('description', attributes["description"].replace('/"',"")) + if "CHASSIS" not in component.type: + parent_component_references = component_new.create_path('parent-component-references') + parent = parent_component_references.create_path('component-reference[index="{:d}"]'.format(physical_index)) + for component_parent in device.components: + if component.parent == component_parent.name : + parent.create_path('uuid', component_parent.component_uuid.uuid) + break + if attributes["mfg-date"] != "": + mfg_date = self.convert_to_iso_date(attributes["mfg-date"]) + component_new.create_path('mfg-date', mfg_date) + + component_new.create_path('hardware-rev', attributes["hardware-rev"]) + component_new.create_path('software-rev', attributes["software-rev"]) + component_new.create_path('firmware-rev', attributes["firmware-version"]) + component_new.create_path('serial-num', attributes["serial-num"]) + component_new.create_path('mfg-name', attributes["mfg-name"]) + if attributes["removable"]: + removable = attributes["removable"].lower() + if 'true' in removable: + component_new.create_path('is-fru', True) + elif 'false' in removable: + component_new.create_path('is-fru', False) + + if attributes["id"]: + try: + if "CHASSIS" in component.type : + component_new.create_path('parent-rel-pos', 0) + else: + parent_rel_pos = int(attributes["id"].replace("\"", "")) + component_new.create_path('parent-rel-pos', parent_rel_pos) + except ValueError: + LOGGER.info('ERROR:{:s} '.format(component.name )) + continue + + component_new.create_path('uri', component.name) + component_new.create_path('uuid', component.component_uuid.uuid) + for child in device.components: + if component.name == child.parent : + component_new.create_path('contained-child', child.component_uuid.uuid) + + return json.loads(hardware.print_mem('json')) + + def destroy(self) -> None: + self._yang_context.destroy() diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_hardware/__init__.py b/src/nbi/service/rest_server/nbi_plugins/ietf_hardware/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..fe9418b7be811cac2eccb8f566c97e98c97b6000 --- /dev/null +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_hardware/__init__.py @@ -0,0 +1,24 @@ +# 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 nbi.service.rest_server.nbi_plugins.ietf_hardware.Hardware import Hardware +from nbi.service.rest_server.nbi_plugins.ietf_hardware.HardwareMultipleDevices import HardwareMultipleDevices +from nbi.service.rest_server.RestServer import RestServer + +URL_PREFIX_DEVICE = "/restconf/data/device=/ietf-network-hardware-inventory:network-hardware-inventory" +URL_PREFIX_HARDWARE = "/restconf/data/ietf-network-hardware-inventory:network-hardware-inventory" + +def register_ietf_hardware(rest_server: RestServer): + rest_server.add_resource(Hardware, URL_PREFIX_DEVICE) + rest_server.add_resource(HardwareMultipleDevices, URL_PREFIX_HARDWARE) diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_hardware/yang/iana-hardware@2018-03-13.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_hardware/yang/iana-hardware@2018-03-13.yang new file mode 100644 index 0000000000000000000000000000000000000000..5cd52648ff9b676dc04a98b5b85bd180f88f8a6e --- /dev/null +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_hardware/yang/iana-hardware@2018-03-13.yang @@ -0,0 +1,189 @@ +module iana-hardware { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:iana-hardware"; + prefix ianahw; + + organization "IANA"; + contact + " Internet Assigned Numbers Authority + + Postal: ICANN + 12025 Waterfront Drive, Suite 300 + Los Angeles, CA 90094-2536 + United States of America + + Tel: +1 310 301 5800 + E-Mail: iana@iana.org>"; + + description + "IANA-defined identities for hardware class. + + The latest revision of this YANG module can be obtained from + the IANA website. + + Requests for new values should be made to IANA via + email (iana@iana.org). + + Copyright (c) 2018 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (https://trustee.ietf.org/license-info). + + The initial version of this YANG module is part of RFC 8348; + see the RFC itself for full legal notices."; + reference + "https://www.iana.org/assignments/yang-parameters"; + + revision 2018-03-13 { + description + "Initial revision."; + reference + "RFC 8348: A YANG Data Model for Hardware Management"; + } + + /* + * Identities + */ + + identity hardware-class { + description + "This identity is the base for all hardware class + identifiers."; + } + + identity unknown { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is unknown + to the server."; + } + + identity chassis { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is an + overall container for networking equipment. Any class of + physical component, except a stack, may be contained within a + chassis; a chassis may only be contained within a stack."; + } + + identity backplane { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is some sort + of device for aggregating and forwarding networking traffic, + such as a shared backplane in a modular ethernet switch. Note + that an implementation may model a backplane as a single + physical component, which is actually implemented as multiple + discrete physical components (within a chassis or stack)."; + } + + identity container { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is capable + of containing one or more removable physical entities, + possibly of different types. For example, each (empty or + full) slot in a chassis will be modeled as a container. Note + that all removable physical components should be modeled + within a container component, such as field-replaceable + modules, fans, or power supplies. Note that all known + containers should be modeled by the agent, including empty + containers."; + } + + identity power-supply { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is a + power-supplying component."; + } + + identity fan { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is a fan or + other heat-reduction component."; + } + + identity sensor { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is some sort + of sensor, such as a temperature sensor within a router + chassis."; + } + + identity module { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is some sort + of self-contained sub-system. If a module component is + removable, then it should be modeled within a container + + component; otherwise, it should be modeled directly within + another physical component (e.g., a chassis or another + module)."; + } + + identity port { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is some sort + of networking port capable of receiving and/or transmitting + networking traffic."; + } + + identity stack { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is some sort + of super-container (possibly virtual) intended to group + together multiple chassis entities. A stack may be realized + by a virtual cable, a real interconnect cable attached to + multiple chassis, or multiple interconnect cables. A stack + should not be modeled within any other physical components, + but a stack may be contained within another stack. Only + chassis components should be contained within a stack."; + } + + identity cpu { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is some sort + of central processing unit."; + } + + identity energy-object { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is some sort + of energy object, i.e., it is a piece of equipment that is + part of or attached to a communications network that is + monitored, it is controlled, or it aids in the management of + another device for Energy Management."; + } + + identity battery { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is some sort + of battery."; + } + + identity storage-drive { + base ianahw:hardware-class; + description + "This identity is applicable if the hardware class is some sort + of component with data storage capability as its main + functionality, e.g., hard disk drive (HDD), solid-state device + (SSD), solid-state hybrid drive (SSHD), object storage device + (OSD), or other."; + } +} diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_hardware/yang/ietf-hardware@2018-03-13.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_hardware/yang/ietf-hardware@2018-03-13.yang new file mode 100644 index 0000000000000000000000000000000000000000..4f984b616a61bb169f5ac132c3002ae1033aae7e --- /dev/null +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_hardware/yang/ietf-hardware@2018-03-13.yang @@ -0,0 +1,1194 @@ +module ietf-hardware { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-hardware"; + prefix hw; + + import ietf-inet-types { + prefix inet; + } + import ietf-yang-types { + prefix yang; + } + import iana-hardware { + prefix ianahw; + } + + organization + "IETF NETMOD (Network Modeling) Working Group"; + + contact + "WG Web: + WG List: + + Editor: Andy Bierman + + + Editor: Martin Bjorklund + + + Editor: Jie Dong + + + Editor: Dan Romascanu + "; + + description + "This module contains a collection of YANG definitions for + managing hardware. + + This data model is designed for the Network Management Datastore + Architecture (NMDA) defined in RFC 8342. + Copyright (c) 2018 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (https://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 8348; see + the RFC itself for full legal notices."; + + revision 2018-03-13 { + description + "Initial revision."; + reference + "RFC 8348: A YANG Data Model for Hardware Management"; + } + + /* + * Features + */ + + feature entity-mib { + description + "This feature indicates that the device implements + the ENTITY-MIB."; + reference + "RFC 6933: Entity MIB (Version 4)"; + } + + feature hardware-state { + description + "Indicates that ENTITY-STATE-MIB objects are supported"; + reference + "RFC 4268: Entity State MIB"; + } + + feature hardware-sensor { + description + "Indicates that ENTITY-SENSOR-MIB objects are supported"; + reference + "RFC 3433: Entity Sensor Management Information Base"; + } + + /* + * Typedefs + */ + + typedef admin-state { + type enumeration { + enum unknown { + value 1; + description + "The resource is unable to report administrative state."; + } + enum locked { + value 2; + description + "The resource is administratively prohibited from use."; + } + enum shutting-down { + value 3; + description + "The resource usage is administratively limited to current + instances of use."; + } + enum unlocked { + value 4; + description + "The resource is not administratively prohibited from + use."; + } + } + description + "Represents the various possible administrative states."; + reference + "RFC 4268: Entity State MIB - EntityAdminState"; + } + + typedef oper-state { + type enumeration { + enum unknown { + value 1; + description + "The resource is unable to report its operational state."; + } + enum disabled { + value 2; + description + "The resource is totally inoperable."; + } + enum enabled { + value 3; + + description + "The resource is partially or fully operable."; + } + enum testing { + value 4; + description + "The resource is currently being tested and cannot + therefore report whether or not it is operational."; + } + } + description + "Represents the possible values of operational states."; + reference + "RFC 4268: Entity State MIB - EntityOperState"; + } + + typedef usage-state { + type enumeration { + enum unknown { + value 1; + description + "The resource is unable to report usage state."; + } + enum idle { + value 2; + description + "The resource is servicing no users."; + } + enum active { + value 3; + description + "The resource is currently in use, and it has sufficient + spare capacity to provide for additional users."; + } + enum busy { + value 4; + description + "The resource is currently in use, but it currently has no + spare capacity to provide for additional users."; + } + } + description + "Represents the possible values of usage states."; + reference + "RFC 4268: Entity State MIB - EntityUsageState"; + } + + typedef alarm-state { + type bits { + bit unknown { + position 0; + description + "The resource is unable to report alarm state."; + } + bit under-repair { + position 1; + description + "The resource is currently being repaired, which, depending + on the implementation, may make the other values in this + bit string not meaningful."; + } + bit critical { + position 2; + description + "One or more critical alarms are active against the + resource."; + } + bit major { + position 3; + description + "One or more major alarms are active against the + resource."; + } + bit minor { + position 4; + description + "One or more minor alarms are active against the + resource."; + } + bit warning { + position 5; + description + "One or more warning alarms are active against the + resource."; + } + bit indeterminate { + position 6; + description + "One or more alarms of whose perceived severity cannot be + determined are active against this resource."; + } + } + description + "Represents the possible values of alarm states. An alarm is a + persistent indication of an error or warning condition. + + When no bits of this attribute are set, then no active alarms + are known against this component and it is not under repair."; + reference + "RFC 4268: Entity State MIB - EntityAlarmStatus"; + } + + typedef standby-state { + type enumeration { + enum unknown { + value 1; + description + "The resource is unable to report standby state."; + } + enum hot-standby { + value 2; + description + "The resource is not providing service, but it will be + immediately able to take over the role of the resource to + be backed up, without the need for initialization + activity, and will contain the same information as the + resource to be backed up."; + } + enum cold-standby { + value 3; + description + "The resource is to back up another resource, but it will + not be immediately able to take over the role of a + resource to be backed up and will require some + initialization activity."; + } + enum providing-service { + value 4; + description + "The resource is providing service."; + } + } + description + "Represents the possible values of standby states."; + reference + "RFC 4268: Entity State MIB - EntityStandbyStatus"; + } + + typedef sensor-value-type { + type enumeration { + enum other { + value 1; + description + "A measure other than those listed below."; + } + enum unknown { + value 2; + description + "An unknown measurement or arbitrary, relative numbers"; + } + enum volts-AC { + value 3; + description + "A measure of electric potential (alternating current)."; + } + enum volts-DC { + value 4; + description + "A measure of electric potential (direct current)."; + } + enum amperes { + value 5; + description + "A measure of electric current."; + } + enum watts { + value 6; + description + "A measure of power."; + } + enum hertz { + value 7; + description + "A measure of frequency."; + } + enum celsius { + value 8; + description + "A measure of temperature."; + } + enum percent-RH { + value 9; + description + "A measure of percent relative humidity."; + } + enum rpm { + value 10; + description + "A measure of shaft revolutions per minute."; + } + enum cmm { + value 11; + description + "A measure of cubic meters per minute (airflow)."; + } + enum truth-value { + value 12; + description + "Value is one of 1 (true) or 2 (false)"; + } + } + description + "A node using this data type represents the sensor measurement + data type associated with a physical sensor value. The actual + data units are determined by examining a node of this type + together with the associated sensor-value-scale node. + + A node of this type SHOULD be defined together with nodes of + type sensor-value-scale and type sensor-value-precision. + These three types are used to identify the semantics of a node + of type sensor-value."; + reference + "RFC 3433: Entity Sensor Management Information Base - + EntitySensorDataType"; + } + + typedef sensor-value-scale { + type enumeration { + enum yocto { + value 1; + description + "Data scaling factor of 10^-24."; + } + enum zepto { + value 2; + description + "Data scaling factor of 10^-21."; + } + enum atto { + value 3; + description + "Data scaling factor of 10^-18."; + } + enum femto { + value 4; + description + "Data scaling factor of 10^-15."; + } + enum pico { + value 5; + description + "Data scaling factor of 10^-12."; + } + enum nano { + value 6; + description + "Data scaling factor of 10^-9."; + } + enum micro { + value 7; + description + "Data scaling factor of 10^-6."; + } + enum milli { + value 8; + description + "Data scaling factor of 10^-3."; + } + enum units { + value 9; + description + "Data scaling factor of 10^0."; + } + enum kilo { + value 10; + description + "Data scaling factor of 10^3."; + } + enum mega { + value 11; + description + "Data scaling factor of 10^6."; + } + enum giga { + value 12; + description + "Data scaling factor of 10^9."; + } + enum tera { + value 13; + description + "Data scaling factor of 10^12."; + } + enum peta { + value 14; + description + "Data scaling factor of 10^15."; + } + enum exa { + value 15; + description + "Data scaling factor of 10^18."; + } + enum zetta { + value 16; + description + "Data scaling factor of 10^21."; + } + enum yotta { + value 17; + description + "Data scaling factor of 10^24."; + } + } + description + "A node using this data type represents a data scaling factor, + represented with an International System of Units (SI) prefix. + The actual data units are determined by examining a node of + this type together with the associated sensor-value-type. + + A node of this type SHOULD be defined together with nodes of + type sensor-value-type and type sensor-value-precision. + Together, associated nodes of these three types are used to + identify the semantics of a node of type sensor-value."; + reference + "RFC 3433: Entity Sensor Management Information Base - + EntitySensorDataScale"; + } + + typedef sensor-value-precision { + type int8 { + range "-8 .. 9"; + } + description + "A node using this data type represents a sensor value + precision range. + + A node of this type SHOULD be defined together with nodes of + type sensor-value-type and type sensor-value-scale. Together, + associated nodes of these three types are used to identify the + semantics of a node of type sensor-value. + + If a node of this type contains a value in the range 1 to 9, + it represents the number of decimal places in the fractional + part of an associated sensor-value fixed-point number. + + If a node of this type contains a value in the range -8 to -1, + it represents the number of accurate digits in the associated + sensor-value fixed-point number. + + The value zero indicates the associated sensor-value node is + not a fixed-point number. + + Server implementers must choose a value for the associated + sensor-value-precision node so that the precision and accuracy + of the associated sensor-value node is correctly indicated. + + For example, a component representing a temperature sensor + that can measure 0 to 100 degrees C in 0.1 degree + increments, +/- 0.05 degrees, would have a + sensor-value-precision value of '1', a sensor-value-scale + value of 'units', and a sensor-value ranging from '0' to + '1000'. The sensor-value would be interpreted as + 'degrees C * 10'."; + reference + "RFC 3433: Entity Sensor Management Information Base - + EntitySensorPrecision"; + } + + typedef sensor-value { + type int32 { + range "-1000000000 .. 1000000000"; + } + description + "A node using this data type represents a sensor value. + + A node of this type SHOULD be defined together with nodes of + type sensor-value-type, type sensor-value-scale, and + type sensor-value-precision. Together, associated nodes of + those three types are used to identify the semantics of a node + of this data type. + + The semantics of a node using this data type are determined by + the value of the associated sensor-value-type node. + + If the associated sensor-value-type node is equal to 'voltsAC', + 'voltsDC', 'amperes', 'watts', 'hertz', 'celsius', or 'cmm', + then a node of this type MUST contain a fixed-point number + ranging from -999,999,999 to +999,999,999. The value + -1000000000 indicates an underflow error. The value + +1000000000 indicates an overflow error. The + sensor-value-precision indicates how many fractional digits + are represented in the associated sensor-value node. + + If the associated sensor-value-type node is equal to + 'percentRH', then a node of this type MUST contain a number + ranging from 0 to 100. + + If the associated sensor-value-type node is equal to 'rpm', + then a node of this type MUST contain a number ranging from + -999,999,999 to +999,999,999. + + If the associated sensor-value-type node is equal to + 'truth-value', then a node of this type MUST contain either the + value 1 (true) or the value 2 (false). + + If the associated sensor-value-type node is equal to 'other' or + 'unknown', then a node of this type MUST contain a number + ranging from -1000000000 to 1000000000."; + reference + "RFC 3433: Entity Sensor Management Information Base - + EntitySensorValue"; + } + + typedef sensor-status { + type enumeration { + enum ok { + value 1; + description + "Indicates that the server can obtain the sensor value."; + } + enum unavailable { + value 2; + description + "Indicates that the server presently cannot obtain the + sensor value."; + } + enum nonoperational { + value 3; + description + "Indicates that the server believes the sensor is broken. + The sensor could have a hard failure (disconnected wire) + or a soft failure such as out-of-range, jittery, or wildly + fluctuating readings."; + } + } + description + "A node using this data type represents the operational status + of a physical sensor."; + reference + "RFC 3433: Entity Sensor Management Information Base - + EntitySensorStatus"; + } + + /* + * Data nodes + */ + + container hardware { + description + "Data nodes representing components. + + If the server supports configuration of hardware components, + then this data model is instantiated in the configuration + datastores supported by the server. The leaf-list 'datastore' + for the module 'ietf-hardware' in the YANG library provides + this information."; + + leaf last-change { + type yang:date-and-time; + config false; + description + "The time the '/hardware/component' list changed in the + operational state."; + } + + list component { + key name; + description + "List of components. + + When the server detects a new hardware component, it + initializes a list entry in the operational state. + + If the server does not support configuration of hardware + components, list entries in the operational state are + initialized with values for all nodes as detected by the + implementation. + + Otherwise, this procedure is followed: + + 1. If there is an entry in the '/hardware/component' list + in the intended configuration with values for the nodes + 'class', 'parent', and 'parent-rel-pos' that are equal + to the detected values, then the list entry in the + operational state is initialized with the configured + values, including the 'name'. + + 2. Otherwise (i.e., there is no matching configuration + entry), the list entry in the operational state is + initialized with values for all nodes as detected by + the implementation. + + If the '/hardware/component' list in the intended + configuration is modified, then the system MUST behave as if + it re-initializes itself and follow the procedure in (1)."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalEntry"; + + leaf name { + type string; + description + "The name assigned to this component. + + This name is not required to be the same as + entPhysicalName."; + } + + leaf class { + type identityref { + base ianahw:hardware-class; + } + mandatory true; + description + "An indication of the general hardware type of the + component."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalClass"; + } + + leaf physical-index { + if-feature entity-mib; + type int32 { + range "1..2147483647"; + } + config false; + description + "The entPhysicalIndex for the entPhysicalEntry represented + by this list entry."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalIndex"; + } + + leaf description { + type string; + config false; + description + "A textual description of the component. This node should + contain a string that identifies the manufacturer's name + for the component and should be set to a distinct value + for each version or model of the component."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalDescr"; + } + + leaf parent { + type leafref { + path "../../component/name"; + require-instance false; + } + description + "The name of the component that physically contains this + component. + + If this leaf is not instantiated, it indicates that this + component is not contained in any other component. + + In the event that a physical component is contained by + more than one physical component (e.g., double-wide + modules), this node contains the name of one of these + components. An implementation MUST use the same name + every time this node is instantiated."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalContainedIn"; + } + + leaf parent-rel-pos { + type int32 { + range "0 .. 2147483647"; + } + description + "An indication of the relative position of this child + component among all its sibling components. Sibling + components are defined as components that: + + o share the same value of the 'parent' node and + + o share a common base identity for the 'class' node. + + Note that the last rule gives implementations flexibility + in how components are numbered. For example, some + implementations might have a single number series for all + components derived from 'ianahw:port', while some others + might have different number series for different + components with identities derived from 'ianahw:port' (for + example, one for registered jack 45 (RJ45) and one for + small form-factor pluggable (SFP))."; + + reference + "RFC 6933: Entity MIB (Version 4) - + entPhysicalParentRelPos"; + } + + leaf-list contains-child { + type leafref { + path "../../component/name"; + } + config false; + description + "The name of the contained component."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalChildIndex"; + } + + leaf hardware-rev { + type string; + config false; + description + "The vendor-specific hardware revision string for the + component. The preferred value is the hardware revision + identifier actually printed on the component itself (if + present)."; + reference + "RFC 6933: Entity MIB (Version 4) - + entPhysicalHardwareRev"; + } + + leaf firmware-rev { + type string; + config false; + description + "The vendor-specific firmware revision string for the + component."; + reference + "RFC 6933: Entity MIB (Version 4) - + entPhysicalFirmwareRev"; + } + + leaf software-rev { + type string; + config false; + + description + "The vendor-specific software revision string for the + component."; + reference + "RFC 6933: Entity MIB (Version 4) - + entPhysicalSoftwareRev"; + } + + leaf serial-num { + type string; + config false; + description + "The vendor-specific serial number string for the + component. The preferred value is the serial number + string actually printed on the component itself (if + present)."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalSerialNum"; + } + + leaf mfg-name { + type string; + config false; + description + "The name of the manufacturer of this physical component. + The preferred value is the manufacturer name string + actually printed on the component itself (if present). + + Note that comparisons between instances of the + 'model-name', 'firmware-rev', 'software-rev', and + 'serial-num' nodes are only meaningful amongst components + with the same value of 'mfg-name'. + + If the manufacturer name string associated with the + physical component is unknown to the server, then this + node is not instantiated."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalMfgName"; + } + + leaf model-name { + type string; + config false; + description + "The vendor-specific model name identifier string + associated with this physical component. The preferred + value is the customer-visible part number, which may be + printed on the component itself. + If the model name string associated with the physical + component is unknown to the server, then this node is not + instantiated."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalModelName"; + } + + leaf alias { + type string; + description + "An 'alias' name for the component, as specified by a + network manager, that provides a non-volatile 'handle' for + the component. + + If no configured value exists, the server MAY set the + value of this node to a locally unique value in the + operational state. + + A server implementation MAY map this leaf to the + entPhysicalAlias MIB object. Such an implementation needs + to use some mechanism to handle the differences in size + and characters allowed between this leaf and + entPhysicalAlias. The definition of such a mechanism is + outside the scope of this document."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalAlias"; + } + + leaf asset-id { + type string; + description + "This node is a user-assigned asset tracking identifier for + the component. + + A server implementation MAY map this leaf to the + entPhysicalAssetID MIB object. Such an implementation + needs to use some mechanism to handle the differences in + size and characters allowed between this leaf and + entPhysicalAssetID. The definition of such a mechanism is + outside the scope of this document."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalAssetID"; + } + + leaf is-fru { + type boolean; + config false; + + description + "This node indicates whether or not this component is + considered a 'field-replaceable unit' by the vendor. If + this node contains the value 'true', then this component + identifies a field-replaceable unit. For all components + that are permanently contained within a field-replaceable + unit, the value 'false' should be returned for this + node."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalIsFRU"; + } + + leaf mfg-date { + type yang:date-and-time; + config false; + description + "The date of manufacturing of the managed component."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalMfgDate"; + } + + leaf-list uri { + type inet:uri; + description + "This node contains identification information about the + component."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalUris"; + } + + leaf uuid { + type yang:uuid; + config false; + description + "A Universally Unique Identifier of the component."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalUUID"; + } + + container state { + if-feature hardware-state; + description + "State-related nodes"; + reference + "RFC 4268: Entity State MIB"; + + leaf state-last-changed { + type yang:date-and-time; + config false; + description + "The date and time when the value of any of the + admin-state, oper-state, usage-state, alarm-state, or + standby-state changed for this component. + + If there has been no change since the last + re-initialization of the local system, this node + contains the date and time of local system + initialization. If there has been no change since the + component was added to the local system, this node + contains the date and time of the insertion."; + reference + "RFC 4268: Entity State MIB - entStateLastChanged"; + } + + leaf admin-state { + type admin-state; + description + "The administrative state for this component. + + This node refers to a component's administrative + permission to service both other components within its + containment hierarchy as well other users of its + services defined by means outside the scope of this + module. + + Some components exhibit only a subset of the remaining + administrative state values. Some components cannot be + locked; hence, this node exhibits only the 'unlocked' + state. Other components cannot be shut down gracefully; + hence, this node does not exhibit the 'shutting-down' + state."; + reference + "RFC 4268: Entity State MIB - entStateAdmin"; + } + + leaf oper-state { + type oper-state; + config false; + description + "The operational state for this component. + + Note that this node does not follow the administrative + state. An administrative state of 'down' does not + predict an operational state of 'disabled'. + + Note that some implementations may not be able to + accurately report oper-state while the admin-state node + has a value other than 'unlocked'. In these cases, this + node MUST have a value of 'unknown'."; + reference + "RFC 4268: Entity State MIB - entStateOper"; + } + + leaf usage-state { + type usage-state; + config false; + description + "The usage state for this component. + + This node refers to a component's ability to service + more components in a containment hierarchy. + + Some components will exhibit only a subset of the usage + state values. Components that are unable to ever + service any components within a containment hierarchy + will always have a usage state of 'busy'. In some + cases, a component will be able to support only one + other component within its containment hierarchy and + will therefore only exhibit values of 'idle' and + 'busy'."; + reference + "RFC 4268: Entity State MIB - entStateUsage"; + } + + leaf alarm-state { + type alarm-state; + config false; + description + "The alarm state for this component. It does not + include the alarms raised on child components within its + containment hierarchy."; + reference + "RFC 4268: Entity State MIB - entStateAlarm"; + } + + leaf standby-state { + type standby-state; + config false; + description + "The standby state for this component. + + Some components will exhibit only a subset of the + remaining standby state values. If this component + cannot operate in a standby role, the value of this node + will always be 'providing-service'."; + reference + "RFC 4268: Entity State MIB - entStateStandby"; + } + } + + container sensor-data { + when 'derived-from-or-self(../class, + "ianahw:sensor")' { + description + "Sensor data nodes present for any component of type + 'sensor'"; + } + if-feature hardware-sensor; + config false; + + description + "Sensor-related nodes."; + reference + "RFC 3433: Entity Sensor Management Information Base"; + + leaf value { + type sensor-value; + description + "The most recent measurement obtained by the server + for this sensor. + + A client that periodically fetches this node should also + fetch the nodes 'value-type', 'value-scale', and + 'value-precision', since they may change when the value + is changed."; + reference + "RFC 3433: Entity Sensor Management Information Base - + entPhySensorValue"; + } + + leaf value-type { + type sensor-value-type; + description + "The type of data units associated with the + sensor value"; + reference + "RFC 3433: Entity Sensor Management Information Base - + entPhySensorType"; + } + leaf value-scale { + type sensor-value-scale; + description + "The (power of 10) scaling factor associated + with the sensor value"; + reference + "RFC 3433: Entity Sensor Management Information Base - + entPhySensorScale"; + } + + leaf value-precision { + type sensor-value-precision; + description + "The number of decimal places of precision + associated with the sensor value"; + reference + "RFC 3433: Entity Sensor Management Information Base - + entPhySensorPrecision"; + } + + leaf oper-status { + type sensor-status; + description + "The operational status of the sensor."; + reference + "RFC 3433: Entity Sensor Management Information Base - + entPhySensorOperStatus"; + } + + leaf units-display { + type string; + description + "A textual description of the data units that should be + used in the display of the sensor value."; + reference + "RFC 3433: Entity Sensor Management Information Base - + entPhySensorUnitsDisplay"; + } + + leaf value-timestamp { + type yang:date-and-time; + description + "The time the status and/or value of this sensor was last + obtained by the server."; + reference + "RFC 3433: Entity Sensor Management Information Base - + entPhySensorValueTimeStamp"; + } + leaf value-update-rate { + type uint32; + units "milliseconds"; + description + "An indication of the frequency that the server updates + the associated 'value' node, represented in + milliseconds. The value zero indicates: + + - the sensor value is updated on demand (e.g., + when polled by the server for a get-request), + + - the sensor value is updated when the sensor + value changes (event-driven), or + + - the server does not know the update rate."; + reference + "RFC 3433: Entity Sensor Management Information Base - + entPhySensorValueUpdateRate"; + } + } + } + } + + /* + * Notifications + */ + + notification hardware-state-change { + description + "A hardware-state-change notification is generated when the + value of /hardware/last-change changes in the operational + state."; + reference + "RFC 6933: Entity MIB (Version 4) - entConfigChange"; + } + + notification hardware-state-oper-enabled { + if-feature hardware-state; + description + "A hardware-state-oper-enabled notification signifies that a + component has transitioned into the 'enabled' state."; + + leaf name { + type leafref { + path "/hardware/component/name"; + } + + description + "The name of the component that has transitioned into the + 'enabled' state."; + } + leaf admin-state { + type leafref { + path "/hardware/component/state/admin-state"; + } + description + "The administrative state for the component."; + } + leaf alarm-state { + type leafref { + path "/hardware/component/state/alarm-state"; + } + description + "The alarm state for the component."; + } + reference + "RFC 4268: Entity State MIB - entStateOperEnabled"; + } + + notification hardware-state-oper-disabled { + if-feature hardware-state; + description + "A hardware-state-oper-disabled notification signifies that a + component has transitioned into the 'disabled' state."; + + leaf name { + type leafref { + path "/hardware/component/name"; + } + description + "The name of the component that has transitioned into the + 'disabled' state."; + } + leaf admin-state { + type leafref { + path "/hardware/component/state/admin-state"; + } + description + "The administrative state for the component."; + } + leaf alarm-state { + type leafref { + path "/hardware/component/state/alarm-state"; + } + + description + "The alarm state for the component."; + } + reference + "RFC 4268: Entity State MIB - entStateOperDisabled"; + } + +} diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_hardware/yang/ietf-inet-types@2013-07-15.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_hardware/yang/ietf-inet-types@2013-07-15.yang new file mode 100644 index 0000000000000000000000000000000000000000..eacefb6363de1beb543567a0fa705571b7dc57a2 --- /dev/null +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_hardware/yang/ietf-inet-types@2013-07-15.yang @@ -0,0 +1,458 @@ +module ietf-inet-types { + + namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types"; + prefix "inet"; + + organization + "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; + + contact + "WG Web: + WG List: + + WG Chair: David Kessens + + + WG Chair: Juergen Schoenwaelder + + + Editor: Juergen Schoenwaelder + "; + + description + "This module contains a collection of generally useful derived + YANG data types for Internet addresses and related things. + + Copyright (c) 2013 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 6991; see + the RFC itself for full legal notices."; + + revision 2013-07-15 { + description + "This revision adds the following new data types: + - ip-address-no-zone + - ipv4-address-no-zone + - ipv6-address-no-zone"; + reference + "RFC 6991: Common YANG Data Types"; + } + + revision 2010-09-24 { + description + "Initial revision."; + reference + "RFC 6021: Common YANG Data Types"; + } + + /*** collection of types related to protocol fields ***/ + + typedef ip-version { + type enumeration { + enum unknown { + value "0"; + description + "An unknown or unspecified version of the Internet + protocol."; + } + enum ipv4 { + value "1"; + description + "The IPv4 protocol as defined in RFC 791."; + } + enum ipv6 { + value "2"; + description + "The IPv6 protocol as defined in RFC 2460."; + } + } + description + "This value represents the version of the IP protocol. + + In the value set and its semantics, this type is equivalent + to the InetVersion textual convention of the SMIv2."; + reference + "RFC 791: Internet Protocol + RFC 2460: Internet Protocol, Version 6 (IPv6) Specification + RFC 4001: Textual Conventions for Internet Network Addresses"; + } + + typedef dscp { + type uint8 { + range "0..63"; + } + description + "The dscp type represents a Differentiated Services Code Point + that may be used for marking packets in a traffic stream. + In the value set and its semantics, this type is equivalent + to the Dscp textual convention of the SMIv2."; + reference + "RFC 3289: Management Information Base for the Differentiated + Services Architecture + RFC 2474: Definition of the Differentiated Services Field + (DS Field) in the IPv4 and IPv6 Headers + RFC 2780: IANA Allocation Guidelines For Values In + the Internet Protocol and Related Headers"; + } + + typedef ipv6-flow-label { + type uint32 { + range "0..1048575"; + } + description + "The ipv6-flow-label type represents the flow identifier or Flow + Label in an IPv6 packet header that may be used to + discriminate traffic flows. + + In the value set and its semantics, this type is equivalent + to the IPv6FlowLabel textual convention of the SMIv2."; + reference + "RFC 3595: Textual Conventions for IPv6 Flow Label + RFC 2460: Internet Protocol, Version 6 (IPv6) Specification"; + } + + typedef port-number { + type uint16 { + range "0..65535"; + } + description + "The port-number type represents a 16-bit port number of an + Internet transport-layer protocol such as UDP, TCP, DCCP, or + SCTP. Port numbers are assigned by IANA. A current list of + all assignments is available from . + + Note that the port number value zero is reserved by IANA. In + situations where the value zero does not make sense, it can + be excluded by subtyping the port-number type. + In the value set and its semantics, this type is equivalent + to the InetPortNumber textual convention of the SMIv2."; + reference + "RFC 768: User Datagram Protocol + RFC 793: Transmission Control Protocol + RFC 4960: Stream Control Transmission Protocol + RFC 4340: Datagram Congestion Control Protocol (DCCP) + RFC 4001: Textual Conventions for Internet Network Addresses"; + } + + /*** collection of types related to autonomous systems ***/ + + typedef as-number { + type uint32; + description + "The as-number type represents autonomous system numbers + which identify an Autonomous System (AS). An AS is a set + of routers under a single technical administration, using + an interior gateway protocol and common metrics to route + packets within the AS, and using an exterior gateway + protocol to route packets to other ASes. IANA maintains + the AS number space and has delegated large parts to the + regional registries. + + Autonomous system numbers were originally limited to 16 + bits. BGP extensions have enlarged the autonomous system + number space to 32 bits. This type therefore uses an uint32 + base type without a range restriction in order to support + a larger autonomous system number space. + + In the value set and its semantics, this type is equivalent + to the InetAutonomousSystemNumber textual convention of + the SMIv2."; + reference + "RFC 1930: Guidelines for creation, selection, and registration + of an Autonomous System (AS) + RFC 4271: A Border Gateway Protocol 4 (BGP-4) + RFC 4001: Textual Conventions for Internet Network Addresses + RFC 6793: BGP Support for Four-Octet Autonomous System (AS) + Number Space"; + } + + /*** collection of types related to IP addresses and hostnames ***/ + + typedef ip-address { + type union { + type inet:ipv4-address; + type inet:ipv6-address; + } + description + "The ip-address type represents an IP address and is IP + version neutral. The format of the textual representation + implies the IP version. This type supports scoped addresses + by allowing zone identifiers in the address format."; + reference + "RFC 4007: IPv6 Scoped Address Architecture"; + } + + typedef ipv4-address { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' + + '(%[\p{N}\p{L}]+)?'; + } + description + "The ipv4-address type represents an IPv4 address in + dotted-quad notation. The IPv4 address may include a zone + index, separated by a % sign. + + The zone index is used to disambiguate identical address + values. For link-local addresses, the zone index will + typically be the interface index number or the name of an + interface. If the zone index is not present, the default + zone of the device will be used. + + The canonical format for the zone index is the numerical + format"; + } + + typedef ipv6-address { + type string { + pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' + + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' + + '(%[\p{N}\p{L}]+)?'; + pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' + + '(%.+)?'; + } + description + "The ipv6-address type represents an IPv6 address in full, + mixed, shortened, and shortened-mixed notation. The IPv6 + address may include a zone index, separated by a % sign. + + The zone index is used to disambiguate identical address + values. For link-local addresses, the zone index will + typically be the interface index number or the name of an + interface. If the zone index is not present, the default + zone of the device will be used. + + The canonical format of IPv6 addresses uses the textual + representation defined in Section 4 of RFC 5952. The + canonical format for the zone index is the numerical + format as described in Section 11.2 of RFC 4007."; + reference + "RFC 4291: IP Version 6 Addressing Architecture + RFC 4007: IPv6 Scoped Address Architecture + RFC 5952: A Recommendation for IPv6 Address Text + Representation"; + } + + typedef ip-address-no-zone { + type union { + type inet:ipv4-address-no-zone; + type inet:ipv6-address-no-zone; + } + description + "The ip-address-no-zone type represents an IP address and is + IP version neutral. The format of the textual representation + implies the IP version. This type does not support scoped + addresses since it does not allow zone identifiers in the + address format."; + reference + "RFC 4007: IPv6 Scoped Address Architecture"; + } + + typedef ipv4-address-no-zone { + type inet:ipv4-address { + pattern '[0-9\.]*'; + } + description + "An IPv4 address without a zone index. This type, derived from + ipv4-address, may be used in situations where the zone is + known from the context and hence no zone index is needed."; + } + + typedef ipv6-address-no-zone { + type inet:ipv6-address { + pattern '[0-9a-fA-F:\.]*'; + } + description + "An IPv6 address without a zone index. This type, derived from + ipv6-address, may be used in situations where the zone is + known from the context and hence no zone index is needed."; + reference + "RFC 4291: IP Version 6 Addressing Architecture + RFC 4007: IPv6 Scoped Address Architecture + RFC 5952: A Recommendation for IPv6 Address Text + Representation"; + } + + typedef ip-prefix { + type union { + type inet:ipv4-prefix; + type inet:ipv6-prefix; + } + description + "The ip-prefix type represents an IP prefix and is IP + version neutral. The format of the textual representations + implies the IP version."; + } + + typedef ipv4-prefix { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' + + '/(([0-9])|([1-2][0-9])|(3[0-2]))'; + } + description + "The ipv4-prefix type represents an IPv4 address prefix. + The prefix length is given by the number following the + slash character and must be less than or equal to 32. + + A prefix length value of n corresponds to an IP address + mask that has n contiguous 1-bits from the most + significant bit (MSB) and all other bits set to 0. + + The canonical format of an IPv4 prefix has all bits of + the IPv4 address set to zero that are not part of the + IPv4 prefix."; + } + + typedef ipv6-prefix { + type string { + pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' + + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' + + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'; + pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' + + '(/.+)'; + } + + description + "The ipv6-prefix type represents an IPv6 address prefix. + The prefix length is given by the number following the + slash character and must be less than or equal to 128. + + A prefix length value of n corresponds to an IP address + mask that has n contiguous 1-bits from the most + significant bit (MSB) and all other bits set to 0. + + The IPv6 address should have all bits that do not belong + to the prefix set to zero. + + The canonical format of an IPv6 prefix has all bits of + the IPv6 address set to zero that are not part of the + IPv6 prefix. Furthermore, the IPv6 address is represented + as defined in Section 4 of RFC 5952."; + reference + "RFC 5952: A Recommendation for IPv6 Address Text + Representation"; + } + + /*** collection of domain name and URI types ***/ + + typedef domain-name { + type string { + pattern + '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*' + + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)' + + '|\.'; + length "1..253"; + } + description + "The domain-name type represents a DNS domain name. The + name SHOULD be fully qualified whenever possible. + + Internet domain names are only loosely specified. Section + 3.5 of RFC 1034 recommends a syntax (modified in Section + 2.1 of RFC 1123). The pattern above is intended to allow + for current practice in domain name use, and some possible + future expansion. It is designed to hold various types of + domain names, including names used for A or AAAA records + (host names) and other records, such as SRV records. Note + that Internet host names have a stricter syntax (described + in RFC 952) than the DNS recommendations in RFCs 1034 and + 1123, and that systems that want to store host names in + schema nodes using the domain-name type are recommended to + adhere to this stricter standard to ensure interoperability. + + The encoding of DNS names in the DNS protocol is limited + to 255 characters. Since the encoding consists of labels + prefixed by a length bytes and there is a trailing NULL + byte, only 253 characters can appear in the textual dotted + notation. + + The description clause of schema nodes using the domain-name + type MUST describe when and how these names are resolved to + IP addresses. Note that the resolution of a domain-name value + may require to query multiple DNS records (e.g., A for IPv4 + and AAAA for IPv6). The order of the resolution process and + which DNS record takes precedence can either be defined + explicitly or may depend on the configuration of the + resolver. + + Domain-name values use the US-ASCII encoding. Their canonical + format uses lowercase US-ASCII characters. Internationalized + domain names MUST be A-labels as per RFC 5890."; + reference + "RFC 952: DoD Internet Host Table Specification + RFC 1034: Domain Names - Concepts and Facilities + RFC 1123: Requirements for Internet Hosts -- Application + and Support + RFC 2782: A DNS RR for specifying the location of services + (DNS SRV) + RFC 5890: Internationalized Domain Names in Applications + (IDNA): Definitions and Document Framework"; + } + + typedef host { + type union { + type inet:ip-address; + type inet:domain-name; + } + description + "The host type represents either an IP address or a DNS + domain name."; + } + + typedef uri { + type string; + description + "The uri type represents a Uniform Resource Identifier + (URI) as defined by STD 66. + + Objects using the uri type MUST be in US-ASCII encoding, + and MUST be normalized as described by RFC 3986 Sections + 6.2.1, 6.2.2.1, and 6.2.2.2. All unnecessary + percent-encoding is removed, and all case-insensitive + characters are set to lowercase except for hexadecimal + digits, which are normalized to uppercase as described in + Section 6.2.2.1. + + The purpose of this normalization is to help provide + unique URIs. Note that this normalization is not + sufficient to provide uniqueness. Two URIs that are + textually distinct after this normalization may still be + equivalent. + + Objects using the uri type may restrict the schemes that + they permit. For example, 'data:' and 'urn:' schemes + might not be appropriate. + + A zero-length URI is not a valid URI. This can be used to + express 'URI absent' where required. + + In the value set and its semantics, this type is equivalent + to the Uri SMIv2 textual convention defined in RFC 5017."; + reference + "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax + RFC 3305: Report from the Joint W3C/IETF URI Planning Interest + Group: Uniform Resource Identifiers (URIs), URLs, + and Uniform Resource Names (URNs): Clarifications + and Recommendations + RFC 5017: MIB Textual Conventions for Uniform Resource + Identifiers (URIs)"; + } + +} diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_hardware/yang/ietf-network-hardware-inventory@2023-03-09.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_hardware/yang/ietf-network-hardware-inventory@2023-03-09.yang new file mode 100644 index 0000000000000000000000000000000000000000..e074e3005e97f9657f7ef23a39741d3ce4b912b8 --- /dev/null +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_hardware/yang/ietf-network-hardware-inventory@2023-03-09.yang @@ -0,0 +1,604 @@ +module ietf-network-hardware-inventory { + yang-version 1.1; + namespace + "urn:ietf:params:xml:ns:yang:ietf-network-hardware-inventory"; + prefix nhi; + + import ietf-yang-types { + prefix yang; + reference + "RFC6991: Common YANG Data Types."; + } + + import iana-hardware { + prefix ianahw; + reference + "https://www.iana.org/assignments/yang-parameters"; + } + + import ietf-inet-types { + prefix inet; + reference + "RFC6991: Common YANG Data Types."; + } + + organization + "IETF CCAMP Working Group"; + contact + "WG Web: + WG List: + + Editor: Chaode Yu + + + Editor: Italo Busi + + + Editor: Aihua Guo + + + Editor: Sergio Belotti + + + Editor: Jean-Francois Bouquier + + + Editor: Fabio Peruzzini + "; + + description + "This module defines a model for retrieving network hardware + inventory. + + The model fully conforms to the Network Management + Datastore Architecture (NMDA). + Copyright (c) 2022 IETF Trust and the persons + identified as authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Revised BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (https://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC XXXX; see + the RFC itself for full legal notices. + + The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL + NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', 'NOT RECOMMENDED', + 'MAY', and 'OPTIONAL' in this document are to be interpreted as + described in BCP 14 (RFC 2119) (RFC 8174) when, and only when, + they appear in all capitals, as shown here."; + + // RFC Ed.: replace XXXX with actual RFC number and remove this + // note. + // RFC Ed.: update the date below with the date of RFC publication + // and remove this note. + + revision 2023-03-09 { + description + "Initial version"; + reference + "RFC XXXX: A YANG Data Model for Network Hardware Inventory."; + //RFC Editor: replace XXXX with actual RFC number, update date + //information and remove this note + } + + container network-hardware-inventory { + config false; + description + "The top-level container for the network inventory + information."; + uses equipment-rooms-grouping; + uses network-elements-grouping; + } + + grouping common-entity-attributes { + description + "A set of attributes which are common to all the entities + (e.g., component, equipment room) defined in this module."; + leaf uuid { + type yang:uuid; + description + "Uniquely identifies an entity (e.g., component)."; + } + leaf name { + type string; + description + "A name for an entity (e.g., component), as specified by + a network manager, that provides a non-volatile 'handle' + for the entity and that can be modified anytime during the + entity lifetime. + + If no configured value exists, the server MAY set the value + of this node to a locally unique value in the operational + state."; + } + leaf description { + type string; + description "a textual description of inventory object"; + } + leaf alias { + type string; + description + "a alias name of inventory objects. This alias name can be + specified by network manager."; + } + } + + grouping network-elements-grouping { + description + "The attributes of the network elements."; + container network-elements { + description + "The container for the list of network elements."; + list network-element { + key uuid; + description + "The list of network elements within the network."; + uses common-entity-attributes; + container ne-location { + description + "The location information of this network element."; + leaf-list equipment-room-name { + type leafref { + path "/nhi:network-hardware-inventory/" + + "nhi:equipment-rooms/nhi:equipment-room/nhi:name"; + } + description + "Names of equipment rooms where the NE is located. + Please note that a NE could be located in several + equipment rooms."; + } + } + uses ne-specific-info-grouping; + uses components-grouping; + } + } + } + + grouping ne-specific-info-grouping { + description + "Attributes applicable to network elements."; + leaf hardware-rev { + type string; + description + "The vendor-specific hardware revision string for the NE."; + } + leaf software-rev { + type string; + description + "The vendor-specific software revision string for the NE."; + } + leaf mfg-name { + type string; + description "The name of the manufacturer of this NE"; + } + leaf mfg-date { + type yang:date-and-time; + description "The date of manufacturing of the NE."; + } + leaf part-number { + type string; + description + "The vendor-specific model name identifier string associated + with this NE. The preferred value is the customer-visible + part number, which may be printed on the NE itself."; + } + leaf serial-number { + type string; + description + "The vendor-specific serial number string for the NE"; + } + leaf product-name { + type string; + description + "indicates the vendor-spefic device type infomation."; + } + } + + grouping equipment-rooms-grouping { + description + "The attributes of the equipment rooms."; + container equipment-rooms { + description + "The container for the list of equipment rooms."; + list equipment-room { + key uuid; + description + "The list of equipment rooms within the network."; + uses common-entity-attributes; + leaf location { + type string; + description + "compared with the location information of the other + inventory objects, a GIS address is preferred for + equipment room"; + } + container racks { + description + "Top level container for the list of racks."; + list rack { + key uuid; + description + "The list of racks within an equipment room."; + uses common-entity-attributes; + uses rack-specific-info-grouping; + list contained-chassis { + key "ne-ref component-ref"; + description + "The list of chassis within a rack."; + leaf ne-ref { + type leafref { + path "/nhi:network-hardware-inventory" + + "/nhi:network-elements/nhi:network-element" + + "/nhi:uuid"; + } + description + "The reference to the network element containing + the chassis component."; + } + leaf component-ref { + type leafref { + path "/nhi:network-hardware-inventory" + + "/nhi:network-elements/nhi:network-element" + + "[nhi:uuid=current()/../ne-ref]/nhi:components" + + "/nhi:component/nhi:uuid"; + } + description + "The reference to the chassis component within + the network element and contained by the rack."; + } + leaf relative-position { + type uint8; + description "A relative position of chassis within + the rack"; + } + } + } + } + } + } + } + + grouping rack-specific-info-grouping { + description + "Attributes applicable to racks only."; + container rack-location { + description + "The location information of the rack, which comprises the + name of the equipment room, row number, and column number."; + leaf equipment-room-name { + type leafref { + path "/nhi:network-hardware-inventory/nhi:equipment-rooms" + + "/nhi:equipment-room/nhi:name"; + } + description + "Name of equipment room where this rack is located."; + } + leaf row-number { + type uint32; + description + "Identifies the row within the equipment room where + the rack is located."; + } + leaf column-number { + type uint32; + description + "Identifies the physical location of the rack within + the column."; + } + } + leaf height { + type uint16; + units millimeter; + description + "Rack height."; + } + leaf width { + type uint16; + units millimeter; + description + "Rack width."; + } + leaf depth { + type uint16; + units millimeter; + description + "Rack depth."; + } + leaf max-voltage { + type uint16; + units volt; + description + "The maximum voltage could be supported by the rack."; + } + } + + grouping components-grouping { + description + "The attributes of the hardware components."; + container components { + description + "The container for the list of components."; + list component { + key uuid; + description + "The list of components within a network element."; + uses common-entity-attributes; + leaf location { + type string; + description + "A relative location information of this component. + In optical transport network, the location string is + using the following pattern: + '/ne=[/r=][/sh= + [/s_sh= ...]][[/sl= + [/s_sl= ...]][/p= …]]' + "; + } + leaf class { + type identityref { + base ianahw:hardware-class; + } + description + "An indication of the general hardware type of the + component."; + reference + "RFC 8348: A YANG Data Model for Hardware Management."; + } + leaf-list contained-child { + type leafref { + path "../nhi:uuid"; + } + description + "The list of the identifiers of the child components + physically contained within this component."; + } + leaf parent-rel-pos { + type int32 { + range "0 .. 2147483647"; + } + description + "The relative position with respect to the parent + component among all the sibling components."; + reference + "RFC 6933: Entity MIB (Version 4) - + entPhysicalParentRelPos"; + } + + container parent-component-references { + description + "The top level container for the list of the + identifiers of the parents of this component in a + hierarchy."; + list component-reference { + key index; + description + "The list of the identifiers of the parents of this + component in a hierarchy. + + The index parameter defines the hierarchy: the topmost + parent has an index of 0."; + leaf index { + type uint8; + description + "The index of the parent with respect to the + hierarchy."; + } + leaf class { + type leafref { + path "../../../nhi:class"; + } + description + "Class of the hierarchial parent component."; + } + leaf uuid { + type leafref { + path "../../../nhi:uuid"; + } + description + "The identifier of the parent's component in the + hierarchy."; + } + } + } + + leaf hardware-rev { + type string; + description + "The vendor-specific hardware revision string for the + component. The preferred value is the hardware revision + identifier actually printed on the component itself (if + present)."; + reference + "RFC 6933: Entity MIB (Version 4) - + entPhysicalHardwareRev"; + } + leaf firmware-rev { + type string; + description + "The vendor-specific firmware revision string for the + component."; + reference + "RFC 6933: Entity MIB (Version 4) - + entPhysicalFirmwareRev"; + } + leaf software-rev { + type string; + description + "The vendor-specific software revision string for the + component."; + reference + "RFC 6933: Entity MIB (Version 4) - + entPhysicalSoftwareRev"; + } + leaf serial-num { + type string; + description + "The vendor-specific serial number string for the + component. The preferred value is the serial number + string actually printed on the component itself (if + present)."; + reference + "RFC 6933: Entity MIB (Version 4) - + entPhysicalSerialNum"; + } + leaf mfg-name { + type string; + description + "The name of the manufacturer of this physical component. + The preferred value is the manufacturer name string + actually printed on the component itself (if present). + + Note that comparisons between instances of the + 'model-name', 'firmware-rev', 'software-rev', and + 'serial-num' nodes are only meaningful amongst + components with the same value of 'mfg-name'. + + If the manufacturer name string associated with the + physical component is unknown to the server, then this + node is not instantiated."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalMfgName"; + } + leaf part-number { + type string; + description + "The vendor-specific model name identifier string + associated with this physical component. The preferred + value is the customer-visible part number, which may be + printed on the component itself. + + If the model name string associated with the physical + component is unknown to the server, then this node is + not instantiated."; + reference + "RFC 6933: Entity MIB (Version 4) - + entPhysicalModelName"; + } + leaf asset-id { + type string; + description + "This node is a user-assigned asset tracking identifier + for the component. + + A server implementation MAY map this leaf to the + entPhysicalAssetID MIB object. Such an implementation + needs to use some mechanism to handle the differences in + size and characters allowed between this leaf and + entPhysicalAssetID. The definition of such a mechanism + is outside the scope of this document."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalAssetID"; + } + leaf is-fru { + type boolean; + description + "This node indicates whether or not this component is + considered a 'field-replaceable unit' by the vendor. If + this node contains the value 'true', then this component + identifies a field-replaceable unit. For all components + that are permanently contained within a + field-replaceable unit, the value 'false' should be + returned for this node."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalIsFRU"; + } + leaf mfg-date { + type yang:date-and-time; + description + "The date of manufacturing of the managed component."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalMfgDate"; + } + leaf-list uri { + type inet:uri; + description + "This node contains identification information about the + component."; + reference + "RFC 6933: Entity MIB (Version 4) - entPhysicalUris"; + } + uses component-specific-info-grouping; + } + } + } + + grouping component-specific-info-grouping { + description + "In case if there are some missing attributes of component not + defined by RFC8348. These attributes could be + component-specific. + Here we provide a extension structure for all the components + we recognized. We will enrich these component specifc + containers in the future."; + choice component-class { + description + "This extension differs between different component + classes."; + case chassis { + when "./class = 'ianahw:chassis'"; + container chassis-specific-info { + description + "This container contains some attributes belong to + chassis only."; + uses chassis-specific-info-grouping; + } + } + case container { + when "./class = 'ianahw:container'"; + container slot-specific-info { + description + "This container contains some attributes belong to + slot or sub-slot only."; + uses slot-specific-info-grouping; + } + } + case module { + when "./nhi:class = 'ianahw:module'"; + container board-specific-info { + description + "This container contains some attributes belong to + board only."; + uses board-specific-info-grouping; + } + } + case port { + when "./nhi:class = 'ianahw:port'"; + container port-specific-info { + description + "This container contains some attributes belong to + port only."; + uses port-specific-info-grouping; + } + } + //TO BE ADDED: transceiver + } + } + + grouping chassis-specific-info-grouping { + //To be enriched in the future. + description + "Specific attributes applicable to chassis only."; + } + + grouping slot-specific-info-grouping { + //To be enriched in the future. + description + "Specific attributes applicable to slots only."; + } + + grouping board-specific-info-grouping { + //To be enriched in the future. + description + "Specific attributes applicable to boards only."; + } + + grouping port-specific-info-grouping { + //To be enriched in the future. + description + "Specific attributes applicable to ports only."; + } +} diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_hardware/yang/ietf-yang-types@2013-07-15.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_hardware/yang/ietf-yang-types@2013-07-15.yang new file mode 100644 index 0000000000000000000000000000000000000000..ee58fa3ab0042120d5607b8713d21fa0ba845895 --- /dev/null +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_hardware/yang/ietf-yang-types@2013-07-15.yang @@ -0,0 +1,474 @@ +module ietf-yang-types { + + namespace "urn:ietf:params:xml:ns:yang:ietf-yang-types"; + prefix "yang"; + + organization + "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; + + contact + "WG Web: + WG List: + + WG Chair: David Kessens + + + WG Chair: Juergen Schoenwaelder + + + Editor: Juergen Schoenwaelder + "; + + description + "This module contains a collection of generally useful derived + YANG data types. + + Copyright (c) 2013 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 6991; see + the RFC itself for full legal notices."; + + revision 2013-07-15 { + description + "This revision adds the following new data types: + - yang-identifier + - hex-string + - uuid + - dotted-quad"; + reference + "RFC 6991: Common YANG Data Types"; + } + + revision 2010-09-24 { + description + "Initial revision."; + reference + "RFC 6021: Common YANG Data Types"; + } + + /*** collection of counter and gauge types ***/ + + typedef counter32 { + type uint32; + description + "The counter32 type represents a non-negative integer + that monotonically increases until it reaches a + maximum value of 2^32-1 (4294967295 decimal), when it + wraps around and starts increasing again from zero. + + Counters have no defined 'initial' value, and thus, a + single value of a counter has (in general) no information + content. Discontinuities in the monotonically increasing + value normally occur at re-initialization of the + management system, and at other times as specified in the + description of a schema node using this type. If such + other times can occur, for example, the creation of + a schema node of type counter32 at times other than + re-initialization, then a corresponding schema node + should be defined, with an appropriate type, to indicate + the last discontinuity. + + The counter32 type should not be used for configuration + schema nodes. A default statement SHOULD NOT be used in + combination with the type counter32. + + In the value set and its semantics, this type is equivalent + to the Counter32 type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef zero-based-counter32 { + type yang:counter32; + default "0"; + description + "The zero-based-counter32 type represents a counter32 + that has the defined 'initial' value zero. + + A schema node of this type will be set to zero (0) on creation + and will thereafter increase monotonically until it reaches + a maximum value of 2^32-1 (4294967295 decimal), when it + wraps around and starts increasing again from zero. + + Provided that an application discovers a new schema node + of this type within the minimum time to wrap, it can use the + 'initial' value as a delta. It is important for a management + station to be aware of this minimum time and the actual time + between polls, and to discard data if the actual time is too + long or there is no defined minimum time. + + In the value set and its semantics, this type is equivalent + to the ZeroBasedCounter32 textual convention of the SMIv2."; + reference + "RFC 4502: Remote Network Monitoring Management Information + Base Version 2"; + } + + typedef counter64 { + type uint64; + description + "The counter64 type represents a non-negative integer + that monotonically increases until it reaches a + maximum value of 2^64-1 (18446744073709551615 decimal), + when it wraps around and starts increasing again from zero. + + Counters have no defined 'initial' value, and thus, a + single value of a counter has (in general) no information + content. Discontinuities in the monotonically increasing + value normally occur at re-initialization of the + management system, and at other times as specified in the + description of a schema node using this type. If such + other times can occur, for example, the creation of + a schema node of type counter64 at times other than + re-initialization, then a corresponding schema node + should be defined, with an appropriate type, to indicate + the last discontinuity. + + The counter64 type should not be used for configuration + schema nodes. A default statement SHOULD NOT be used in + combination with the type counter64. + + In the value set and its semantics, this type is equivalent + to the Counter64 type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef zero-based-counter64 { + type yang:counter64; + default "0"; + description + "The zero-based-counter64 type represents a counter64 that + has the defined 'initial' value zero. + + A schema node of this type will be set to zero (0) on creation + and will thereafter increase monotonically until it reaches + a maximum value of 2^64-1 (18446744073709551615 decimal), + when it wraps around and starts increasing again from zero. + + Provided that an application discovers a new schema node + of this type within the minimum time to wrap, it can use the + 'initial' value as a delta. It is important for a management + station to be aware of this minimum time and the actual time + between polls, and to discard data if the actual time is too + long or there is no defined minimum time. + + In the value set and its semantics, this type is equivalent + to the ZeroBasedCounter64 textual convention of the SMIv2."; + reference + "RFC 2856: Textual Conventions for Additional High Capacity + Data Types"; + } + + typedef gauge32 { + type uint32; + description + "The gauge32 type represents a non-negative integer, which + may increase or decrease, but shall never exceed a maximum + value, nor fall below a minimum value. The maximum value + cannot be greater than 2^32-1 (4294967295 decimal), and + the minimum value cannot be smaller than 0. The value of + a gauge32 has its maximum value whenever the information + being modeled is greater than or equal to its maximum + value, and has its minimum value whenever the information + being modeled is smaller than or equal to its minimum value. + If the information being modeled subsequently decreases + below (increases above) the maximum (minimum) value, the + gauge32 also decreases (increases). + + In the value set and its semantics, this type is equivalent + to the Gauge32 type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef gauge64 { + type uint64; + description + "The gauge64 type represents a non-negative integer, which + may increase or decrease, but shall never exceed a maximum + value, nor fall below a minimum value. The maximum value + cannot be greater than 2^64-1 (18446744073709551615), and + the minimum value cannot be smaller than 0. The value of + a gauge64 has its maximum value whenever the information + being modeled is greater than or equal to its maximum + value, and has its minimum value whenever the information + being modeled is smaller than or equal to its minimum value. + If the information being modeled subsequently decreases + below (increases above) the maximum (minimum) value, the + gauge64 also decreases (increases). + + In the value set and its semantics, this type is equivalent + to the CounterBasedGauge64 SMIv2 textual convention defined + in RFC 2856"; + reference + "RFC 2856: Textual Conventions for Additional High Capacity + Data Types"; + } + + /*** collection of identifier-related types ***/ + + typedef object-identifier { + type string { + pattern '(([0-1](\.[1-3]?[0-9]))|(2\.(0|([1-9]\d*))))' + + '(\.(0|([1-9]\d*)))*'; + } + description + "The object-identifier type represents administratively + assigned names in a registration-hierarchical-name tree. + + Values of this type are denoted as a sequence of numerical + non-negative sub-identifier values. Each sub-identifier + value MUST NOT exceed 2^32-1 (4294967295). Sub-identifiers + are separated by single dots and without any intermediate + whitespace. + + The ASN.1 standard restricts the value space of the first + sub-identifier to 0, 1, or 2. Furthermore, the value space + of the second sub-identifier is restricted to the range + 0 to 39 if the first sub-identifier is 0 or 1. Finally, + the ASN.1 standard requires that an object identifier + has always at least two sub-identifiers. The pattern + captures these restrictions. + + Although the number of sub-identifiers is not limited, + module designers should realize that there may be + implementations that stick with the SMIv2 limit of 128 + sub-identifiers. + + This type is a superset of the SMIv2 OBJECT IDENTIFIER type + since it is not restricted to 128 sub-identifiers. Hence, + this type SHOULD NOT be used to represent the SMIv2 OBJECT + IDENTIFIER type; the object-identifier-128 type SHOULD be + used instead."; + reference + "ISO9834-1: Information technology -- Open Systems + Interconnection -- Procedures for the operation of OSI + Registration Authorities: General procedures and top + arcs of the ASN.1 Object Identifier tree"; + } + + typedef object-identifier-128 { + type object-identifier { + pattern '\d*(\.\d*){1,127}'; + } + description + "This type represents object-identifiers restricted to 128 + sub-identifiers. + + In the value set and its semantics, this type is equivalent + to the OBJECT IDENTIFIER type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef yang-identifier { + type string { + length "1..max"; + pattern '[a-zA-Z_][a-zA-Z0-9\-_.]*'; + pattern '.|..|[^xX].*|.[^mM].*|..[^lL].*'; + } + description + "A YANG identifier string as defined by the 'identifier' + rule in Section 12 of RFC 6020. An identifier must + start with an alphabetic character or an underscore + followed by an arbitrary sequence of alphabetic or + numeric characters, underscores, hyphens, or dots. + + A YANG identifier MUST NOT start with any possible + combination of the lowercase or uppercase character + sequence 'xml'."; + reference + "RFC 6020: YANG - A Data Modeling Language for the Network + Configuration Protocol (NETCONF)"; + } + + /*** collection of types related to date and time***/ + + typedef date-and-time { + type string { + pattern '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?' + + '(Z|[\+\-]\d{2}:\d{2})'; + } + description + "The date-and-time type is a profile of the ISO 8601 + standard for representation of dates and times using the + Gregorian calendar. The profile is defined by the + date-time production in Section 5.6 of RFC 3339. + + The date-and-time type is compatible with the dateTime XML + schema type with the following notable exceptions: + + (a) The date-and-time type does not allow negative years. + + (b) The date-and-time time-offset -00:00 indicates an unknown + time zone (see RFC 3339) while -00:00 and +00:00 and Z + all represent the same time zone in dateTime. + + (c) The canonical format (see below) of data-and-time values + differs from the canonical format used by the dateTime XML + schema type, which requires all times to be in UTC using + the time-offset 'Z'. + + This type is not equivalent to the DateAndTime textual + convention of the SMIv2 since RFC 3339 uses a different + separator between full-date and full-time and provides + higher resolution of time-secfrac. + + The canonical format for date-and-time values with a known time + zone uses a numeric time zone offset that is calculated using + the device's configured known offset to UTC time. A change of + the device's offset to UTC time will cause date-and-time values + to change accordingly. Such changes might happen periodically + in case a server follows automatically daylight saving time + (DST) time zone offset changes. The canonical format for + date-and-time values with an unknown time zone (usually + referring to the notion of local time) uses the time-offset + -00:00."; + reference + "RFC 3339: Date and Time on the Internet: Timestamps + RFC 2579: Textual Conventions for SMIv2 + XSD-TYPES: XML Schema Part 2: Datatypes Second Edition"; + } + + typedef timeticks { + type uint32; + description + "The timeticks type represents a non-negative integer that + represents the time, modulo 2^32 (4294967296 decimal), in + hundredths of a second between two epochs. When a schema + node is defined that uses this type, the description of + the schema node identifies both of the reference epochs. + + In the value set and its semantics, this type is equivalent + to the TimeTicks type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef timestamp { + type yang:timeticks; + description + "The timestamp type represents the value of an associated + timeticks schema node at which a specific occurrence + happened. The specific occurrence must be defined in the + description of any schema node defined using this type. When + the specific occurrence occurred prior to the last time the + associated timeticks attribute was zero, then the timestamp + value is zero. Note that this requires all timestamp values + to be reset to zero when the value of the associated timeticks + attribute reaches 497+ days and wraps around to zero. + + The associated timeticks schema node must be specified + in the description of any schema node using this type. + + In the value set and its semantics, this type is equivalent + to the TimeStamp textual convention of the SMIv2."; + reference + "RFC 2579: Textual Conventions for SMIv2"; + } + + /*** collection of generic address types ***/ + + typedef phys-address { + type string { + pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?'; + } + + description + "Represents media- or physical-level addresses represented + as a sequence octets, each octet represented by two hexadecimal + numbers. Octets are separated by colons. The canonical + representation uses lowercase characters. + + In the value set and its semantics, this type is equivalent + to the PhysAddress textual convention of the SMIv2."; + reference + "RFC 2579: Textual Conventions for SMIv2"; + } + + typedef mac-address { + type string { + pattern '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'; + } + description + "The mac-address type represents an IEEE 802 MAC address. + The canonical representation uses lowercase characters. + + In the value set and its semantics, this type is equivalent + to the MacAddress textual convention of the SMIv2."; + reference + "IEEE 802: IEEE Standard for Local and Metropolitan Area + Networks: Overview and Architecture + RFC 2579: Textual Conventions for SMIv2"; + } + + /*** collection of XML-specific types ***/ + + typedef xpath1.0 { + type string; + description + "This type represents an XPATH 1.0 expression. + + When a schema node is defined that uses this type, the + description of the schema node MUST specify the XPath + context in which the XPath expression is evaluated."; + reference + "XPATH: XML Path Language (XPath) Version 1.0"; + } + + /*** collection of string types ***/ + + typedef hex-string { + type string { + pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?'; + } + description + "A hexadecimal string with octets represented as hex digits + separated by colons. The canonical representation uses + lowercase characters."; + } + + typedef uuid { + type string { + pattern '[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-' + + '[0-9a-fA-F]{4}-[0-9a-fA-F]{12}'; + } + description + "A Universally Unique IDentifier in the string representation + defined in RFC 4122. The canonical representation uses + lowercase characters. + + The following is an example of a UUID in string representation: + f81d4fae-7dec-11d0-a765-00a0c91e6bf6 + "; + reference + "RFC 4122: A Universally Unique IDentifier (UUID) URN + Namespace"; + } + + typedef dotted-quad { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'; + } + description + "An unsigned 32-bit number expressed in the dotted-quad + notation, i.e., four octets written as decimal numbers + and separated with the '.' (full stop) character."; + } +} diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/Constants.py b/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/Constants.py index 8ed148f1c29443ae8c39fb5652b531aa5f334567..d010259ff477d0155aca2f5f8dc02e37a1311642 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/Constants.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/Constants.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/L2VPN_Service.py b/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/L2VPN_Service.py index 5a2b1cc9775f737c75fc723c8a192d15e6d14780..288ed2d105d1ebc564fc5b609d03b9244defa966 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/L2VPN_Service.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/L2VPN_Service.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/L2VPN_Services.py b/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/L2VPN_Services.py index ba855c4a993d393302e4b699b5d90166b24f894e..c728b4073837d0a067ce13c69b471bf5c63b60c5 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/L2VPN_Services.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/L2VPN_Services.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/L2VPN_SiteNetworkAccesses.py b/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/L2VPN_SiteNetworkAccesses.py index 65c2123c805b384a002c84119b1269dd753346ec..2ae776c2047272de9b07f0e12c5537cea355d0b8 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/L2VPN_SiteNetworkAccesses.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/L2VPN_SiteNetworkAccesses.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/__init__.py b/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/__init__.py index 31217f078d2935ac228a7c8d1e75bcbcbc478d44..a391040d9a77cb006ba421ae7fe0c0427b3915b1 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/__init__.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/schemas/Common.py b/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/schemas/Common.py index b1d90c75e0823fd98ab7b9eea245d3c98648d2b3..7fc4e93088bc41f99eded5c3575d3441fb7b7234 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/schemas/Common.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/schemas/Common.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/schemas/__init__.py b/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/schemas/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/schemas/__init__.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/schemas/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/schemas/site_network_access.py b/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/schemas/site_network_access.py index 3d9c2f2b6c052f9aa59202cc2d51bca288d04a33..a873849091c120caab5ad6badef28fd97f593dba 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/schemas/site_network_access.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/schemas/site_network_access.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/schemas/vpn_service.py b/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/schemas/vpn_service.py index 1960ae8c8dfd7cd769f8356bfd273f848ef19ff2..85a0fe8bae5bf339ae03a1144ab02f114fd4e279 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/schemas/vpn_service.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_l2vpn/schemas/vpn_service.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/Handlers.py b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/Handlers.py index f7329cb35666f423e85f99510e5f89a82e89b7f8..0e8b8013ef5cba1305cdd040ea68efc653eefa5e 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/Handlers.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/Handlers.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -195,11 +195,17 @@ def process_site(site : Dict, errors : List[Dict]) -> None: # site_static_routing: (lan-range, lan-prefix-len, lan-tag) => next-hop site_static_routing : Dict[Tuple[str, str], str] = {} - for rt_proto in site['routing-protocols']['routing-protocol']: + site_routing_protocols : Dict = site.get('routing-protocols', dict()) + site_routing_protocol : List = site_routing_protocols.get('routing-protocol', list()) + for rt_proto in site_routing_protocol: if rt_proto['type'] != 'ietf-l3vpn-svc:static': MSG = 'Site Routing Protocol Type: {:s}' raise NotImplementedError(MSG.format(str(rt_proto['type']))) - for ipv4_rt in rt_proto['static']['cascaded-lan-prefixes']['ipv4-lan-prefixes']: + + rt_proto_static : Dict = rt_proto.get('static', dict()) + rt_proto_static_clps : Dict = rt_proto_static.get('cascaded-lan-prefixes', dict()) + rt_proto_static_clps_v4 = rt_proto_static_clps.get('ipv4-lan-prefixes', list()) + for ipv4_rt in rt_proto_static_clps_v4: lan_range, lan_prefix = ipv4_rt['lan'].split('/') lan_prefix = int(lan_prefix) lan_tag = int(ipv4_rt['lan-tag'].replace('vlan', '')) diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_Service.py b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_Service.py index a313677c12203c1621b920f3fcb7f6ff0c281bfb..97364dff8606f1af48bab362b94b968561792411 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_Service.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_Service.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -44,7 +44,7 @@ class L3VPN_Service(Resource): service_ready_status = ServiceStatusEnum.SERVICESTATUS_ACTIVE service_status = target.service_status.service_status # pylint: disable=no-member - response = jsonify({}) + response = jsonify({'service-id': target.service_id.service_uuid.uuid}) response.status_code = HTTP_OK if service_status == service_ready_status else HTTP_GATEWAYTIMEOUT except Exception as e: # pylint: disable=broad-except LOGGER.exception('Something went wrong Retrieving VPN({:s})'.format(str(vpn_id))) diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_Services.py b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_Services.py index 11f2d6dae2f42cb06543979dcdb4d44b4d21e8aa..98d950952702d5cf1df8aa29edc50683e56a296e 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_Services.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_Services.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_SiteNetworkAccesses.py b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_SiteNetworkAccesses.py index 9f4b43848ab94bd8db670715f0fba807ce794ccd..338c7d631f41e675f214a713d12acb3e7cea839f 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_SiteNetworkAccesses.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_SiteNetworkAccesses.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/YangValidator.py b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/YangValidator.py index 77071f7f7a72ad7d46e34f118a87dc2280a2a24c..171134c4bce42c03d2988ab050154d5ac612971d 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/YangValidator.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/YangValidator.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/__init__.py b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/__init__.py index 71c32acfcf1ec2b29ad437365cfd937c358672df..7d18c692948774741f2bf8dea993fe0e5778e9a1 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/__init__.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network/ComposeLink.py b/src/nbi/service/rest_server/nbi_plugins/ietf_network/ComposeLink.py index 8fec8798a508ba198c27fc355545ff2eba0be5e3..394b916c54c1c3df0206e6023bc6f9cf5adb9e8a 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_network/ComposeLink.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network/ComposeLink.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network/ComposeNetwork.py b/src/nbi/service/rest_server/nbi_plugins/ietf_network/ComposeNetwork.py index 9efbce8759142b594929156bbc29c1c13e095ee5..ef9e7f31e0c17f6cc71e41208880c73c7dfc7f3d 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_network/ComposeNetwork.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network/ComposeNetwork.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network/ComposeNode.py b/src/nbi/service/rest_server/nbi_plugins/ietf_network/ComposeNode.py index e2c690cd322e9da8b57d78be45d64e9505e9d33d..24da280e6a6ed0fc9dd76800dc62cd65a2270af2 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_network/ComposeNode.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network/ComposeNode.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network/ComposeTermPoint.py b/src/nbi/service/rest_server/nbi_plugins/ietf_network/ComposeTermPoint.py index 904742441e357cd1d257904d2a21816891effbb6..9922e0470d3774c633eda6c2d261328fc646790a 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_network/ComposeTermPoint.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network/ComposeTermPoint.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network/ManualFixes.py b/src/nbi/service/rest_server/nbi_plugins/ietf_network/ManualFixes.py index d0c378aad451533bf11e297f393dfa901d696d8e..803d2bd098807584c43d0f8d55de490a2ea8bd77 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_network/ManualFixes.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network/ManualFixes.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network/NameMapping.py b/src/nbi/service/rest_server/nbi_plugins/ietf_network/NameMapping.py index 0c10559115f4e4ba9e5b2468e36cf7f917c25f51..03d052afd36d2872c8151d9e260a72e42f8e1017 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_network/NameMapping.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network/NameMapping.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -19,7 +19,7 @@ class NameMappings: def __init__(self) -> None: self._device_uuid_to_name : Dict[str, str] = dict() self._endpoint_uuid_to_name : Dict[Tuple[str, str], str] = dict() - + def store_device_name(self, device : Device) -> None: device_uuid = device.device_id.device_uuid.uuid device_name = device.name diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network/NetworkTypeEnum.py b/src/nbi/service/rest_server/nbi_plugins/ietf_network/NetworkTypeEnum.py index 96fe4dff1452458479b4b04f98e12be63343e022..849252b99a8eaa4118a77debe6ce18ffadad11b4 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_network/NetworkTypeEnum.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network/NetworkTypeEnum.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network/Networks.py b/src/nbi/service/rest_server/nbi_plugins/ietf_network/Networks.py index 5d663b8b3071856bc9cd204ee911c61b368ebe97..e2ac05307f136d53fe9d7a5db348e1eb99a31368 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_network/Networks.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network/Networks.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -12,19 +12,23 @@ # See the License for the specific language governing permissions and # limitations under the License. -import json, logging +import enum, json, logging import pyangbind.lib.pybindJSON as pybindJSON from flask import request from flask.json import jsonify from flask_restful import Resource from common.Constants import DEFAULT_CONTEXT_NAME, DEFAULT_TOPOLOGY_NAME +from common.Settings import get_setting +from common.proto.context_pb2 import ContextId, Empty from common.tools.context_queries.Topology import get_topology_details +from common.tools.object_factory.Context import json_context_id from context.client.ContextClient import ContextClient from nbi.service.rest_server.nbi_plugins.tools.Authentication import HTTP_AUTH from nbi.service.rest_server.nbi_plugins.tools.HttpStatusCodes import HTTP_OK, HTTP_SERVERERROR from .bindings import ietf_network from .ComposeNetwork import compose_network from .ManualFixes import manual_fixes +from .YangHandler import YangHandler LOGGER = logging.getLogger(__name__) @@ -33,6 +37,14 @@ TE_TOPOLOGY_NAMES = [ 'providerId-10-clientId-0-topologyId-2' ] +class Renderer(enum.Enum): + LIBYANG = 'LIBYANG' + PYANGBIND = 'PYANGBIND' + +DEFAULT_RENDERER = Renderer.LIBYANG +USE_RENDERER = get_setting('IETF_NETWORK_RENDERER', default=DEFAULT_RENDERER.value) + + class Networks(Resource): @HTTP_AUTH.login_required def get(self): @@ -40,31 +52,59 @@ class Networks(Resource): topology_id = '' try: context_client = ContextClient() - #target = get_slice_by_uuid(context_client, vpn_id, rw_copy=True) - #if target is None: - # raise Exception('VPN({:s}) not found in database'.format(str(vpn_id))) - ietf_nets = ietf_network() + if USE_RENDERER == Renderer.PYANGBIND.value: + #target = get_slice_by_uuid(context_client, vpn_id, rw_copy=True) + #if target is None: + # raise Exception('VPN({:s}) not found in database'.format(str(vpn_id))) + + ietf_nets = ietf_network() + + topology_details = get_topology_details( + context_client, DEFAULT_TOPOLOGY_NAME, context_uuid=DEFAULT_CONTEXT_NAME, + #rw_copy=True + ) + if topology_details is None: + MSG = 'Topology({:s}/{:s}) not found' + raise Exception(MSG.format(DEFAULT_CONTEXT_NAME, DEFAULT_TOPOLOGY_NAME)) - topology_details = get_topology_details( - context_client, DEFAULT_TOPOLOGY_NAME, context_uuid=DEFAULT_CONTEXT_NAME, #rw_copy=True - ) - if topology_details is None: - MSG = 'Topology({:s}/{:s}) not found' - raise Exception(MSG.format(DEFAULT_CONTEXT_NAME, DEFAULT_TOPOLOGY_NAME)) + for te_topology_name in TE_TOPOLOGY_NAMES: + ietf_net = ietf_nets.networks.network.add(te_topology_name) + compose_network(ietf_net, te_topology_name, topology_details) - for te_topology_name in TE_TOPOLOGY_NAMES: - ietf_net = ietf_nets.networks.network.add(te_topology_name) - compose_network(ietf_net, te_topology_name, topology_details) + # TODO: improve these workarounds to enhance performance + json_response = json.loads(pybindJSON.dumps(ietf_nets, mode='ietf')) + + # Workaround; pyangbind does not allow to set otn_topology / eth-tran-topology + manual_fixes(json_response) + elif USE_RENDERER == Renderer.LIBYANG.value: + yang_handler = YangHandler() + json_response = [] - # TODO: improve these workarounds to enhance performance - json_response = json.loads(pybindJSON.dumps(ietf_nets, mode='ietf')) - - # Workaround; pyangbind does not allow to set otn_topology / eth-tran-topology - manual_fixes(json_response) + contexts = context_client.ListContexts(Empty()).contexts + context_names = [context.name for context in contexts] + LOGGER.info(f'Contexts detected: {context_names}') + + for context_name in context_names: + topologies = context_client.ListTopologies(ContextId(**json_context_id(context_name))).topologies + topology_names = [topology.name for topology in topologies] + LOGGER.info(f'Topologies detected for context {context_name}: {topology_names}') + + for topology_name in topology_names: + topology_details = get_topology_details(context_client, topology_name, context_name) + if topology_details is None: + raise Exception(f'Topology({context_name}/{topology_name}) not found') + + network_reply = yang_handler.compose_network(topology_name, topology_details) + json_response.append(network_reply) + + yang_handler.destroy() + else: + raise Exception('Unsupported Renderer: {:s}'.format(str(USE_RENDERER))) response = jsonify(json_response) response.status_code = HTTP_OK + except Exception as e: # pylint: disable=broad-except LOGGER.exception('Something went wrong Retrieving Topology({:s})'.format(str(topology_id))) response = jsonify({'error': str(e)}) diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network/YangHandler.py b/src/nbi/service/rest_server/nbi_plugins/ietf_network/YangHandler.py new file mode 100644 index 0000000000000000000000000000000000000000..413f48f823fcd5cb818683b68494d2172bad3e0b --- /dev/null +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network/YangHandler.py @@ -0,0 +1,117 @@ +# 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 json +import libyang, logging, os +from typing import Any +from common.proto.context_pb2 import TopologyDetails, Device, Link +from .NameMapping import NameMappings +from context.client.ContextClient import ContextClient +from common.tools.object_factory.Device import json_device_id +from common.proto.context_pb2 import DeviceId + +LOGGER = logging.getLogger(__name__) + +YANG_DIR = os.path.join(os.path.dirname(__file__), 'yang') +YANG_MODULES = ['ietf-network', 'ietf-network-topology', 'ietf-l3-unicast-topology'] + +class YangHandler: + def __init__(self) -> None: + self._yang_context = libyang.Context(YANG_DIR) + for yang_module_name in YANG_MODULES: + LOGGER.info('Loading module: {:s}'.format(str(yang_module_name))) + self._yang_context.load_module(yang_module_name).feature_enable_all() + + def compose_network(self, te_topology_name: str, topology_details: TopologyDetails) -> dict: + networks = self._yang_context.create_data_path('/ietf-network:networks') + network = networks.create_path(f'network[network-id="{te_topology_name}"]') + network.create_path('network-id', te_topology_name) + + network_types = network.create_path('network-types') + network_types.create_path('ietf-l3-unicast-topology:l3-unicast-topology') + + name_mappings = NameMappings() + + for device in topology_details.devices: + self.compose_node(device, name_mappings, network) + + for link in topology_details.links: + self.compose_link(link, name_mappings, network) + + return json.loads(networks.print_mem('json')) + + def compose_node(self, dev: Device, name_mappings: NameMappings, network: Any) -> None: + device_name = dev.name + name_mappings.store_device_name(dev) + + node = network.create_path(f'node[node-id="{device_name}"]') + node.create_path('node-id', device_name) + node_attributes = node.create_path('ietf-l3-unicast-topology:l3-node-attributes') + node_attributes.create_path('name', device_name) + + context_client = ContextClient() + device = context_client.GetDevice(DeviceId(**json_device_id(device_name))) + + for endpoint in device.device_endpoints: + name_mappings.store_endpoint_name(dev, endpoint) + + self._process_device_config(device, node) + + def _process_device_config(self, device: Device, node: Any) -> None: + for config in device.device_config.config_rules: + if config.WhichOneof('config_rule') != 'custom' or '/interface[' not in config.custom.resource_key: + continue + + for endpoint in device.device_endpoints: + endpoint_name = endpoint.name + if f'/interface[{endpoint_name}]' in config.custom.resource_key or f'/interface[{endpoint_name}.' in config.custom.resource_key: + interface_name = config.custom.resource_key.split('interface[')[1].split(']')[0] + self._create_termination_point(node, interface_name, endpoint_name, config.custom.resource_value) + + def _create_termination_point(self, node: Any, interface_name: str, endpoint_name: str, resource_value: str) -> None: + ip_addresses = self._extract_ip_addresses(json.loads(resource_value)) + if ip_addresses: + tp = node.create_path(f'ietf-network-topology:termination-point[tp-id="{interface_name}"]') + tp.create_path('tp-id', interface_name) + tp_attributes = tp.create_path('ietf-l3-unicast-topology:l3-termination-point-attributes') + + for ip in ip_addresses: + tp_attributes.create_path('ip-address', ip) + tp_attributes.create_path('interface-name', endpoint_name) + + @staticmethod + def _extract_ip_addresses(resource_value: dict) -> list: + ip_addresses = [] + if 'address_ip' in resource_value: + ip_addresses.append(resource_value['address_ip']) + if 'address_ipv6' in resource_value: + ip_addresses.append(resource_value['address_ipv6']) + return ip_addresses + + def compose_link(self, link_specs: Link, name_mappings: NameMappings, network: Any) -> None: + link_name = link_specs.name + links = network.create_path(f'ietf-network-topology:link[link-id="{link_name}"]') + links.create_path('link-id', link_name) + + self._create_link_endpoint(links, 'source', link_specs.link_endpoint_ids[0], name_mappings) + self._create_link_endpoint(links, 'destination', link_specs.link_endpoint_ids[-1], name_mappings) + + def _create_link_endpoint(self, links: Any, endpoint_type: str, endpoint_id: Any, name_mappings: NameMappings) -> None: + endpoint = links.create_path(endpoint_type) + if endpoint_type == 'destination': endpoint_type = 'dest' + endpoint.create_path(f'{endpoint_type}-node', name_mappings.get_device_name(endpoint_id.device_id)) + endpoint.create_path(f'{endpoint_type}-tp', name_mappings.get_endpoint_name(endpoint_id)) + + def destroy(self) -> None: + self._yang_context.destroy() diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network/__init__.py b/src/nbi/service/rest_server/nbi_plugins/ietf_network/__init__.py index 3f70c97d4ddbc273e50654182c8928807deb09e3..84f3a59baea6ea2fbca4dc6ba5bda81bddc29e24 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_network/__init__.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network/build-yang-bindings.sh b/src/nbi/service/rest_server/nbi_plugins/ietf_network/build-yang-bindings.sh index 8e5b182e73e4fe933a869a45918a1277b2cc3143..2775f80da62430997c15c9ae5d31b99354fe0ecb 100755 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_network/build-yang-bindings.sh +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network/build-yang-bindings.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network/yang/ietf-l3-unicast-topology@2018-02-26.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_network/yang/ietf-l3-unicast-topology@2018-02-26.yang new file mode 100644 index 0000000000000000000000000000000000000000..39fcebd767bf7ea687de523b0dd0ba731d3c80e7 --- /dev/null +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network/yang/ietf-l3-unicast-topology@2018-02-26.yang @@ -0,0 +1,359 @@ +module ietf-l3-unicast-topology { + yang-version 1.1; + namespace + "urn:ietf:params:xml:ns:yang:ietf-l3-unicast-topology"; + prefix "l3t"; + import ietf-network { + prefix "nw"; + } + import ietf-network-topology { + prefix "nt"; + } + import ietf-inet-types { + prefix "inet"; + } + import ietf-routing-types { + prefix "rt-types"; + } + organization + "IETF I2RS (Interface to the Routing System) Working Group"; + contact + "WG Web: + WG List: + Editor: Alexander Clemm + + Editor: Jan Medved + + Editor: Robert Varga + + Editor: Xufeng Liu + + Editor: Nitin Bahadur + + Editor: Hariharan Ananthakrishnan + "; + description + "This module defines a model for Layer 3 Unicast + topologies. + + Copyright (c) 2018 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (https://trustee.ietf.org/license-info). + + This version of this YANG module is part of + RFC 8346; see the RFC itself for full legal notices."; + revision "2018-02-26" { + description + "Initial revision."; + reference + "RFC 8346: A YANG Data Model for Layer 3 Topologies"; + } + + identity flag-identity { + description "Base type for flags"; + } + + typedef l3-event-type { + type enumeration { + enum "add" { + description + "A Layer 3 node, link, prefix, or termination point has + been added"; + } + enum "remove" { + description + "A Layer 3 node, link, prefix, or termination point has + been removed"; + } + enum "update" { + description + "A Layer 3 node, link, prefix, or termination point has + been updated"; + } + } + description "Layer 3 event type for notifications"; + } + + typedef prefix-flag-type { + type identityref { + base "flag-identity"; + } + description "Prefix flag attributes"; + } + + typedef node-flag-type { + type identityref { + base "flag-identity"; + } + description "Node flag attributes"; + } + + typedef link-flag-type { + type identityref { + base "flag-identity"; + } + description "Link flag attributes"; + } + + typedef l3-flag-type { + type identityref { + base "flag-identity"; + } + description "L3 flag attributes"; + } + + grouping l3-prefix-attributes { + description + "L3 prefix attributes"; + leaf prefix { + type inet:ip-prefix; + description + "IP prefix value"; + } + leaf metric { + type uint32; + description + "Prefix metric"; + } + leaf-list flag { + type prefix-flag-type; + description + "Prefix flags"; + } + } + grouping l3-unicast-topology-type { + description "Identifies the topology type to be L3 Unicast."; + container l3-unicast-topology { + presence "indicates L3 Unicast topology"; + description + "The presence of the container node indicates L3 Unicast + topology"; + } + } + grouping l3-topology-attributes { + description "Topology scope attributes"; + container l3-topology-attributes { + description "Contains topology attributes"; + leaf name { + type string; + description + "Name of the topology"; + } + leaf-list flag { + type l3-flag-type; + description + "Topology flags"; + } + } + } + grouping l3-node-attributes { + description "L3 node scope attributes"; + container l3-node-attributes { + description + "Contains node attributes"; + leaf name { + type inet:domain-name; + description + "Node name"; + } + leaf-list flag { + type node-flag-type; + description + "Node flags"; + } + leaf-list router-id { + type rt-types:router-id; + description + "Router-id for the node"; + } + list prefix { + key "prefix"; + description + "A list of prefixes along with their attributes"; + uses l3-prefix-attributes; + } + } + } + grouping l3-link-attributes { + description + "L3 link scope attributes"; + container l3-link-attributes { + description + "Contains link attributes"; + leaf name { + type string; + description + "Link Name"; + } + leaf-list flag { + type link-flag-type; + description + "Link flags"; + } + leaf metric1 { + type uint64; + description + "Link Metric 1"; + } + leaf metric2 { + type uint64; + description + "Link Metric 2"; + } + } + } + grouping l3-termination-point-attributes { + description "L3 termination point scope attributes"; + container l3-termination-point-attributes { + description + "Contains termination point attributes"; + choice termination-point-type { + description + "Indicates the termination point type"; + case ip { + leaf-list ip-address { + type inet:ip-address; + description + "IPv4 or IPv6 address."; + } + } + case unnumbered { + leaf unnumbered-id { + type uint32; + description + "Unnumbered interface identifier. + The identifier will correspond to the ifIndex value + of the interface, i.e., the ifIndex value of the + ifEntry that represents the interface in + implementations where the Interfaces Group MIB + (RFC 2863) is supported."; + reference + "RFC 2863: The Interfaces Group MIB"; + } + } + case interface-name { + leaf interface-name { + type string; + description + "Name of the interface. The name can (but does not + have to) correspond to an interface reference of a + containing node's interface, i.e., the path name of a + corresponding interface data node on the containing + node reminiscent of data type interface-ref defined + in RFC 8343. It should be noted that data type + interface-ref of RFC 8343 cannot be used directly, + + as this data type is used to reference an interface + in a datastore of a single node in the network, not + to uniquely reference interfaces across a network."; + reference + "RFC 8343: A YANG Data Model for Interface Management"; + } + } + } + } + } + augment "/nw:networks/nw:network/nw:network-types" { + description + "Introduces new network type for L3 Unicast topology"; + uses l3-unicast-topology-type; + } + augment "/nw:networks/nw:network" { + when "nw:network-types/l3t:l3-unicast-topology" { + description + "Augmentation parameters apply only for networks with + L3 Unicast topology"; + } + description + "L3 Unicast for the network as a whole"; + uses l3-topology-attributes; + } + augment "/nw:networks/nw:network/nw:node" { + when "../nw:network-types/l3t:l3-unicast-topology" { + description + "Augmentation parameters apply only for networks with + L3 Unicast topology"; + } + description + "L3 Unicast node-level attributes "; + uses l3-node-attributes; + } + augment "/nw:networks/nw:network/nt:link" { + when "../nw:network-types/l3t:l3-unicast-topology" { + description + "Augmentation parameters apply only for networks with + L3 Unicast topology"; + } + description + "Augments topology link attributes"; + uses l3-link-attributes; + } + augment "/nw:networks/nw:network/nw:node/" + +"nt:termination-point" { + when "../../nw:network-types/l3t:l3-unicast-topology" { + description + "Augmentation parameters apply only for networks with + L3 Unicast topology"; + } + description "Augments topology termination point configuration"; + uses l3-termination-point-attributes; + } + notification l3-node-event { + description + "Notification event for L3 node"; + leaf l3-event-type { + type l3-event-type; + description + "Event type"; + } + uses nw:node-ref; + uses l3-unicast-topology-type; + uses l3-node-attributes; + } + notification l3-link-event { + description + "Notification event for L3 link"; + leaf l3-event-type { + type l3-event-type; + description + "Event type"; + } + uses nt:link-ref; + uses l3-unicast-topology-type; + uses l3-link-attributes; + } + notification l3-prefix-event { + description + "Notification event for L3 prefix"; + leaf l3-event-type { + type l3-event-type; + description + "Event type"; + } + uses nw:node-ref; + uses l3-unicast-topology-type; + container prefix { + description + "Contains L3 prefix attributes"; + uses l3-prefix-attributes; + } + } + notification termination-point-event { + description + "Notification event for L3 termination point"; + leaf l3-event-type { + type l3-event-type; + description + "Event type"; + } + uses nt:tp-ref; + uses l3-unicast-topology-type; + uses l3-termination-point-attributes; + } +} diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Service.py b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Service.py index 7d2aa714a27a854291c55275b2f89bd01678fe1d..e25270d3601ffa1cfdffa68a98305e3646602001 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Service.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Service.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Services.py b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Services.py index ad2a2e0321d837bcad6b672e841aed0544c66d82..11a73141d6bd05db851d3019903e5a6db2f5c2d6 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Services.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Services.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/__init__.py b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/__init__.py index 5fcbe27e1c736531c53b0c9d3049fab023629b70..e900c27e96aafc248e5db1bec303cb25b5a0f2d7 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/__init__.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/ofc23_batch_slices.py b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/ofc23_batch_slices.py index 576033e9d30800bcc051a154ac193e519a94f369..70f1b0d816e4ee24bc88ad829fdcefc1d47b8578 100644 --- a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/ofc23_batch_slices.py +++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/ofc23_batch_slices.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/qkd_app/Resources.py b/src/nbi/service/rest_server/nbi_plugins/qkd_app/Resources.py new file mode 100644 index 0000000000000000000000000000000000000000..089f5f98af88de60895f6564fc6b8affc7b28836 --- /dev/null +++ b/src/nbi/service/rest_server/nbi_plugins/qkd_app/Resources.py @@ -0,0 +1,111 @@ +# 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 uuid +import json +from flask import request +from flask_restful import Resource +from common.proto.context_pb2 import Empty +from common.proto.qkd_app_pb2 import App, QKDAppTypesEnum +from common.Constants import DEFAULT_CONTEXT_NAME +from context.client.ContextClient import ContextClient +from qkd_app.client.QKDAppClient import QKDAppClient + +class _Resource(Resource): + def __init__(self) -> None: + super().__init__() + self.context_client = ContextClient() + self.qkd_app_client = QKDAppClient() + +class Index(_Resource): + def get(self): + return {'hello': 'world'} + +class ListDevices(_Resource): + def get(self): + """ + List devices and associate the apps with them. + """ + devices = self.context_client.ListDevices(Empty()).devices + for device in devices: + # Fetch apps associated with this device + device.apps = self.get_apps_for_device(device.device_id.device_uuid.uuid) + return {'devices': [self.format_device(device) for device in devices]} + + def get_apps_for_device(self, device_uuid): + """ + Fetch the apps associated with a given device UUID. + """ + try: + # Call the AppService to get the list of apps + apps_list = self.qkd_app_client.ListApps(Empty()) + + # Filter apps for this specific device + device_apps = [] + for app in apps_list.apps: + if app.local_device_id.device_uuid.uuid == device_uuid or \ + app.remote_device_id.device_uuid.uuid == device_uuid: + device_apps.append(app) + return device_apps + + except Exception as e: + print(f"Error fetching apps for device {device_uuid}: {e}") + return [] + + def format_device(self, device): + """ + Formats a device object to include the associated apps in the response. + """ + return { + 'device_uuid': device.device_id.device_uuid.uuid, + 'name': device.name, + 'type': device.device_type, + 'status': device.device_operational_status, + 'apps': [{'app_id': app.app_id.app_uuid.uuid, 'app_status': app.app_status, 'app_type': app.app_type} for app in device.apps] + } + +class CreateQKDApp(_Resource): + def post(self): + app = request.get_json()['app'] + devices = self.context_client.ListDevices(Empty()).devices + local_device = None + + # This for-loop won't be necessary if Device ID is guaranteed to be the same as QKDN Id + for device in devices: + for config_rule in device.device_config.config_rules: + if config_rule.custom.resource_key == '__node__': + value = json.loads(config_rule.custom.resource_value) + qkdn_id = value['qkdn_id'] + if app['local_qkdn_id'] == qkdn_id: + local_device = device + break + + if local_device is None: + return {"status": "fail"} + + external_app_src_dst = { + 'app_id': {'context_id': {'context_uuid': {'uuid': DEFAULT_CONTEXT_NAME}}, 'app_uuid': {'uuid': ''}}, + 'app_status': 'QKDAPPSTATUS_' + app['app_status'], + 'app_type': QKDAppTypesEnum.QKDAPPTYPES_CLIENT, + 'server_app_id': app['server_app_id'], + 'client_app_id': app['client_app_id'], + 'backing_qkdl_id': [{'qkdl_uuid': {'uuid': qkdl_id}} for qkdl_id in app['backing_qkdl_id']], + 'local_device_id': local_device.device_id, + 'remote_device_id': {'device_uuid': {'uuid': ''}}, + } + + self.qkd_app_client.RegisterApp(App(**external_app_src_dst)) + + return {"status": "success"} + diff --git a/src/nbi/service/rest_server/nbi_plugins/qkd_app/__init__.py b/src/nbi/service/rest_server/nbi_plugins/qkd_app/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..0c048f6625c0cdf749ed6cd84722008ddac9d228 --- /dev/null +++ b/src/nbi/service/rest_server/nbi_plugins/qkd_app/__init__.py @@ -0,0 +1,29 @@ +# 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 nbi.service.rest_server.RestServer import RestServer +from .Resources import CreateQKDApp, Index + +URL_PREFIX = '/qkd_app' + +# Use 'path' type since some identifiers might contain char '/' and Flask is unable to recognize them in 'string' type. +RESOURCES = [ + # (endpoint_name, resource_class, resource_url) + ('api.index', Index, '/'), + ('api.register_qkd_app', CreateQKDApp, '/create_qkd_app'), +] + +def register_qkd_app(rest_server : RestServer): + for endpoint_name, resource_class, resource_url in RESOURCES: + rest_server.add_resource(resource_class, URL_PREFIX + resource_url, endpoint=endpoint_name) diff --git a/src/nbi/service/rest_server/nbi_plugins/tfs_api/Resources.py b/src/nbi/service/rest_server/nbi_plugins/tfs_api/Resources.py index ce60bdea3a7ab08b8dc24dd2e7c2efe4ecf81ae0..eaa21352527a95591829e6bad87de8ecef1df521 100644 --- a/src/nbi/service/rest_server/nbi_plugins/tfs_api/Resources.py +++ b/src/nbi/service/rest_server/nbi_plugins/tfs_api/Resources.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -13,35 +13,80 @@ # limitations under the License. import json +import logging from flask.json import jsonify from flask_restful import Resource, request -from common.proto.context_pb2 import Empty +from werkzeug.exceptions import BadRequest +from common.proto.context_pb2 import Empty, LinkTypeEnum from common.tools.grpc.Tools import grpc_message_to_json from context.client.ContextClient import ContextClient +from device.client.DeviceClient import DeviceClient from service.client.ServiceClient import ServiceClient +from slice.client.SliceClient import SliceClient +from vnt_manager.client.VNTManagerClient import VNTManagerClient + from .Tools import ( - format_grpc_to_json, grpc_connection_id, grpc_context_id, grpc_device_id, grpc_link_id, grpc_policy_rule_id, - grpc_service_id, grpc_service, grpc_slice_id, grpc_topology_id) + format_grpc_to_json, grpc_connection_id, grpc_context, grpc_context_id, grpc_device, + grpc_device_id, grpc_link, grpc_link_id, grpc_policy_rule_id, + grpc_service_id, grpc_service, grpc_slice, grpc_slice_id, grpc_topology, grpc_topology_id +) + +LOGGER = logging.getLogger(__name__) + class _Resource(Resource): def __init__(self) -> None: super().__init__() - self.client = ContextClient() + self.context_client = ContextClient() + self.device_client = DeviceClient() self.service_client = ServiceClient() + self.vntmanager_client = VNTManagerClient() + self.slice_client = SliceClient() class ContextIds(_Resource): def get(self): - return format_grpc_to_json(self.client.ListContextIds(Empty())) + return format_grpc_to_json(self.context_client.ListContextIds(Empty())) class Contexts(_Resource): def get(self): - return format_grpc_to_json(self.client.ListContexts(Empty())) + return format_grpc_to_json(self.context_client.ListContexts(Empty())) + + def post(self): + json_requests = request.get_json() + if 'contexts' in json_requests: + json_requests = json_requests['contexts'] + return [ + format_grpc_to_json(self.context_client.SetContext(grpc_context(context))) + for context in json_requests + ] + +class Context(_Resource): + def get(self, context_uuid : str): + return format_grpc_to_json(self.context_client.GetContext(grpc_context_id(context_uuid))) + + def put(self, context_uuid : str): + context = request.get_json() + if context_uuid != context['context_id']['context_uuid']['uuid']: + raise BadRequest('Mismatching context_uuid') + return format_grpc_to_json(self.context_client.SetContext(grpc_context(context))) + + def delete(self, context_uuid : str): + return format_grpc_to_json(self.context_client.RemoveContext(grpc_context_id(context_uuid))) class DummyContexts(_Resource): def get(self): - contexts = grpc_message_to_json(self.client.ListContexts(Empty()), use_integers_for_enums=True)['contexts'] - devices = grpc_message_to_json(self.client.ListDevices(Empty()), use_integers_for_enums=True)['devices'] - links = grpc_message_to_json(self.client.ListLinks(Empty()), use_integers_for_enums=True)['links'] + contexts = grpc_message_to_json( + self.context_client.ListContexts(Empty()), + use_integers_for_enums=True + )['contexts'] + devices = grpc_message_to_json( + self.context_client.ListDevices(Empty()), + use_integers_for_enums=True + )['devices'] + links = grpc_message_to_json( + self.context_client.ListLinks(Empty()), + use_integers_for_enums=True + )['links'] topologies = list() slices = list() @@ -53,17 +98,17 @@ class DummyContexts(_Resource): context_id = grpc_context_id(context_uuid) topologies.extend(grpc_message_to_json( - self.client.ListTopologies(context_id), + self.context_client.ListTopologies(context_id), use_integers_for_enums=True )['topologies']) slices.extend(grpc_message_to_json( - self.client.ListSlices(context_id), + self.context_client.ListSlices(context_id), use_integers_for_enums=True )['slices']) context_services = grpc_message_to_json( - self.client.ListServices(context_id), + self.context_client.ListServices(context_id), use_integers_for_enums=True )['services'] services.extend(context_services) @@ -72,7 +117,7 @@ class DummyContexts(_Resource): service_uuid = service['service_id']['service_uuid']['uuid'] service_id = grpc_service_id(context_uuid, service_uuid) connections.extend(grpc_message_to_json( - self.client.ListConnections(service_id), + self.context_client.ListConnections(service_id), use_integers_for_enums=True )['connections']) @@ -97,115 +142,196 @@ class DummyContexts(_Resource): if len(connections) > 0: dummy_context['connections'] = connections return jsonify(dummy_context) -class Context(_Resource): - def get(self, context_uuid : str): - return format_grpc_to_json(self.client.GetContext(grpc_context_id(context_uuid))) - class TopologyIds(_Resource): def get(self, context_uuid : str): - return format_grpc_to_json(self.client.ListTopologyIds(grpc_context_id(context_uuid))) + return format_grpc_to_json(self.context_client.ListTopologyIds(grpc_context_id(context_uuid))) class Topologies(_Resource): def get(self, context_uuid : str): - return format_grpc_to_json(self.client.ListTopologies(grpc_context_id(context_uuid))) + return format_grpc_to_json(self.context_client.ListTopologies(grpc_context_id(context_uuid))) + + def post(self, context_uuid : str): + json_requests = request.get_json() + if 'topologies' in json_requests: + json_requests = json_requests['topologies'] + for topology in json_requests: + if context_uuid != topology['topology_id']['context_id']['context_uuid']['uuid']: + raise BadRequest('Mismatching context_uuid') + return [ + format_grpc_to_json(self.context_client.SetTopology(grpc_topology(**topology))) + for topology in json_requests + ] class Topology(_Resource): def get(self, context_uuid : str, topology_uuid : str): - return format_grpc_to_json(self.client.GetTopology(grpc_topology_id(context_uuid, topology_uuid))) + return format_grpc_to_json(self.context_client.GetTopology(grpc_topology_id(context_uuid, topology_uuid))) + + def put(self, context_uuid : str, topology_uuid : str): + topology = request.get_json() + if context_uuid != topology['topology_id']['context_id']['context_uuid']['uuid']: + raise BadRequest('Mismatching context_uuid') + if topology_uuid != topology['topology_id']['topology_uuid']['uuid']: + raise BadRequest('Mismatching topology_uuid') + return format_grpc_to_json(self.context_client.SetTopology(grpc_topology(topology))) + + def delete(self, context_uuid : str, topology_uuid : str): + return format_grpc_to_json(self.context_client.RemoveTopology(grpc_topology_id(context_uuid, topology_uuid))) class ServiceIds(_Resource): def get(self, context_uuid : str): - return format_grpc_to_json(self.client.ListServiceIds(grpc_context_id(context_uuid))) + return format_grpc_to_json(self.context_client.ListServiceIds(grpc_context_id(context_uuid))) class Services(_Resource): def get(self, context_uuid : str): - return format_grpc_to_json(self.client.ListServices(grpc_context_id(context_uuid))) + return format_grpc_to_json(self.context_client.ListServices(grpc_context_id(context_uuid))) + + def post(self, context_uuid : str): + json_requests = request.get_json() + if 'services' in json_requests: + json_requests = json_requests['services'] + for service in json_requests: + if context_uuid != service['service_id']['context_id']['context_uuid']['uuid']: + raise BadRequest('Mismatching context_uuid') + return [ + format_grpc_to_json(self.service_client.CreateService(grpc_service(**service))) + for service in json_requests + ] class Service(_Resource): def get(self, context_uuid : str, service_uuid : str): - return format_grpc_to_json(self.client.GetService(grpc_service_id(context_uuid, service_uuid))) - - def post(self, context_uuid : str, service_uuid : str): # pylint: disable=unused-argument - service = request.get_json()['services'][0] - return format_grpc_to_json(self.service_client.CreateService(grpc_service( - service_uuid = service['service_id']['service_uuid']['uuid'], - service_type = service['service_type'], - context_uuid = service['service_id']['context_id']['context_uuid']['uuid'], - ))) - - def put(self, context_uuid : str, service_uuid : str): # pylint: disable=unused-argument - service = request.get_json()['services'][0] - return format_grpc_to_json(self.service_client.UpdateService(grpc_service( - service_uuid = service['service_id']['service_uuid']['uuid'], - service_type = service['service_type'], - context_uuid = service['service_id']['context_id']['context_uuid']['uuid'], - status = service['service_status']['service_status'], - endpoint_ids = service['service_endpoint_ids'], - constraints = service['service_constraints'], - config_rules = service['service_config']['config_rules'] - ))) + return format_grpc_to_json(self.context_client.GetService(grpc_service_id(context_uuid, service_uuid))) + + def put(self, context_uuid : str, service_uuid : str): + service = request.get_json() + if context_uuid != service['service_id']['context_id']['context_uuid']['uuid']: + raise BadRequest('Mismatching context_uuid') + if service_uuid != service['service_id']['service_uuid']['uuid']: + raise BadRequest('Mismatching service_uuid') + return format_grpc_to_json(self.service_client.UpdateService(grpc_service(service))) def delete(self, context_uuid : str, service_uuid : str): - return format_grpc_to_json(self.service_client.DeleteService(grpc_service_id( - context_uuid, service_uuid, - ))) + return format_grpc_to_json(self.service_client.DeleteService(grpc_service_id(context_uuid, service_uuid))) class SliceIds(_Resource): def get(self, context_uuid : str): - return format_grpc_to_json(self.client.ListSliceIds(grpc_context_id(context_uuid))) + return format_grpc_to_json(self.context_client.ListSliceIds(grpc_context_id(context_uuid))) class Slices(_Resource): def get(self, context_uuid : str): - return format_grpc_to_json(self.client.ListSlices(grpc_context_id(context_uuid))) + return format_grpc_to_json(self.context_client.ListSlices(grpc_context_id(context_uuid))) + + def post(self, context_uuid : str): + json_requests = request.get_json() + if 'slices' in json_requests: + json_requests = json_requests['slices'] + for slice_ in json_requests: + if context_uuid != slice_['slice_id']['context_id']['context_uuid']['uuid']: + raise BadRequest('Mismatching context_uuid') + return [ + format_grpc_to_json(self.slice_client.CreateSlice(grpc_slice(**slice_))) + for slice_ in json_requests + ] class Slice(_Resource): def get(self, context_uuid : str, slice_uuid : str): - return format_grpc_to_json(self.client.GetSlice(grpc_slice_id(context_uuid, slice_uuid))) + return format_grpc_to_json(self.context_client.GetSlice(grpc_slice_id(context_uuid, slice_uuid))) + + def put(self, context_uuid : str, slice_uuid : str): + slice_ = request.get_json() + if context_uuid != slice_['slice_id']['context_id']['context_uuid']['uuid']: + raise BadRequest('Mismatching context_uuid') + if slice_uuid != slice_['slice_id']['slice_uuid']['uuid']: + raise BadRequest('Mismatching slice_uuid') + return format_grpc_to_json(self.slice_client.UpdateSlice(grpc_slice(slice_))) + + def delete(self, context_uuid : str, slice_uuid : str): + return format_grpc_to_json(self.slice_client.DeleteSlice(grpc_slice_id(context_uuid, slice_uuid))) class DeviceIds(_Resource): def get(self): - return format_grpc_to_json(self.client.ListDeviceIds(Empty())) + return format_grpc_to_json(self.context_client.ListDeviceIds(Empty())) class Devices(_Resource): def get(self): - return format_grpc_to_json(self.client.ListDevices(Empty())) + return format_grpc_to_json(self.context_client.ListDevices(Empty())) + + def post(self): + json_requests = request.get_json() + if 'devices' in json_requests: + json_requests = json_requests['devices'] + return [ + format_grpc_to_json(self.device_client.AddDevice(grpc_device(device))) + for device in json_requests + ] class Device(_Resource): def get(self, device_uuid : str): - return format_grpc_to_json(self.client.GetDevice(grpc_device_id(device_uuid))) + return format_grpc_to_json(self.context_client.GetDevice(grpc_device_id(device_uuid))) + + def put(self, device_uuid : str): + device = request.get_json() + if device_uuid != device['device_id']['device_uuid']['uuid']: + raise BadRequest('Mismatching device_uuid') + return format_grpc_to_json(self.device_client.ConfigureDevice(grpc_device(device))) + + def delete(self, device_uuid : str): + return format_grpc_to_json(self.device_client.DeleteDevice(grpc_device_id(device_uuid))) class LinkIds(_Resource): def get(self): - return format_grpc_to_json(self.client.ListLinkIds(Empty())) + return format_grpc_to_json(self.context_client.ListLinkIds(Empty())) class Links(_Resource): def get(self): - return format_grpc_to_json(self.client.ListLinks(Empty())) + return format_grpc_to_json(self.context_client.ListLinks(Empty())) + + def post(self): + json_requests = request.get_json() + if 'links' in json_requests: + json_requests = json_requests['links'] + return [ + format_grpc_to_json(self.context_client.SetLink(grpc_link(link))) + for link in json_requests + ] class Link(_Resource): def get(self, link_uuid : str): - return format_grpc_to_json(self.client.GetLink(grpc_link_id(link_uuid))) + return format_grpc_to_json(self.context_client.GetLink(grpc_link_id(link_uuid))) + + def put(self, link_uuid : str): + link_json = request.get_json() + link = grpc_link(link_json) + virtual_types = {LinkTypeEnum.LINKTYPE_VIRTUAL_COPPER, LinkTypeEnum.LINKTYPE_VIRTUAL_OPTICAL} + if link_uuid != link.link_id.link_uuid.uuid: + raise BadRequest('Mismatching link_uuid') + elif link.link_type in virtual_types: + link = grpc_link(link_json) + return format_grpc_to_json(self.vntmanager_client.SetVirtualLink(link)) + return format_grpc_to_json(self.context_client.SetLink(grpc_link(link))) + + def delete(self, link_uuid : str): + return format_grpc_to_json(self.context_client.RemoveLink(grpc_link_id(link_uuid))) class ConnectionIds(_Resource): def get(self, context_uuid : str, service_uuid : str): - return format_grpc_to_json(self.client.ListConnectionIds(grpc_service_id(context_uuid, service_uuid))) + return format_grpc_to_json(self.context_client.ListConnectionIds(grpc_service_id(context_uuid, service_uuid))) class Connections(_Resource): def get(self, context_uuid : str, service_uuid : str): - return format_grpc_to_json(self.client.ListConnections(grpc_service_id(context_uuid, service_uuid))) + return format_grpc_to_json(self.context_client.ListConnections(grpc_service_id(context_uuid, service_uuid))) class Connection(_Resource): def get(self, connection_uuid : str): - return format_grpc_to_json(self.client.GetConnection(grpc_connection_id(connection_uuid))) + return format_grpc_to_json(self.context_client.GetConnection(grpc_connection_id(connection_uuid))) class PolicyRuleIds(_Resource): def get(self): - return format_grpc_to_json(self.client.ListPolicyRuleIds(Empty())) + return format_grpc_to_json(self.context_client.ListPolicyRuleIds(Empty())) class PolicyRules(_Resource): def get(self): - return format_grpc_to_json(self.client.ListPolicyRules(Empty())) + return format_grpc_to_json(self.context_client.ListPolicyRules(Empty())) class PolicyRule(_Resource): def get(self, policy_rule_uuid : str): - return format_grpc_to_json(self.client.GetPolicyRule(grpc_policy_rule_id(policy_rule_uuid))) + return format_grpc_to_json(self.context_client.GetPolicyRule(grpc_policy_rule_id(policy_rule_uuid))) diff --git a/src/nbi/service/rest_server/nbi_plugins/tfs_api/Tools.py b/src/nbi/service/rest_server/nbi_plugins/tfs_api/Tools.py index 1f69ffffb8c97a83591ec626920b57f40d032783..0053d1590f2312e2735171b0fdc3cba48025315e 100644 --- a/src/nbi/service/rest_server/nbi_plugins/tfs_api/Tools.py +++ b/src/nbi/service/rest_server/nbi_plugins/tfs_api/Tools.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -12,21 +12,20 @@ # See the License for the specific language governing permissions and # limitations under the License. +from typing import Dict from flask.json import jsonify from common.proto.context_pb2 import ( - ConnectionId, ContextId, DeviceId, LinkId, ServiceId, SliceId, TopologyId, Service, ServiceStatusEnum + ConnectionId, Context, ContextId, Device, DeviceId, Link, LinkId, + ServiceId, Slice, SliceId, Topology, TopologyId, Service ) -from common.proto.policy_pb2 import PolicyRuleId +from common.proto.policy_pb2 import PolicyRule, PolicyRuleId from common.tools.grpc.Tools import grpc_message_to_json from common.tools.object_factory.Connection import json_connection_id from common.tools.object_factory.Context import json_context_id -from common.tools.object_factory.ConfigRule import json_config_rule -from common.tools.object_factory.Constraint import json_constraint_custom -from common.tools.object_factory.EndPoint import json_endpoint_id from common.tools.object_factory.Device import json_device_id from common.tools.object_factory.Link import json_link_id from common.tools.object_factory.PolicyRule import json_policyrule_id -from common.tools.object_factory.Service import json_service_id, json_service +from common.tools.object_factory.Service import json_service_id from common.tools.object_factory.Slice import json_slice_id from common.tools.object_factory.Topology import json_topology_id @@ -40,51 +39,41 @@ def grpc_connection_id(connection_uuid): def grpc_context_id(context_uuid): return ContextId(**json_context_id(context_uuid)) +def grpc_context(json_context : Dict): + return Context(**json_context) + def grpc_device_id(device_uuid): return DeviceId(**json_device_id(device_uuid)) +def grpc_device(json_device : Dict): + return Device(**json_device) + def grpc_link_id(link_uuid): return LinkId(**json_link_id(link_uuid)) +def grpc_link(json_link : Dict): + return Link(**json_link) + def grpc_service_id(context_uuid, service_uuid): return ServiceId(**json_service_id(service_uuid, context_id=json_context_id(context_uuid))) -def grpc_service( - service_uuid, service_type, context_uuid, status=None, endpoint_ids=None, constraints=None, config_rules=None -): - json_context = json_context_id(context_uuid) - json_status = status if status else ServiceStatusEnum.SERVICESTATUS_PLANNED - json_endpoints_ids = [ - json_endpoint_id( - json_device_id(endpoint_id['device_id']['device_uuid']['uuid']), - endpoint_id['endpoint_uuid']['uuid'] - ) - for endpoint_id in endpoint_ids - ] if endpoint_ids else [] - json_constraints = [ - json_constraint_custom( - constraint['custom']['constraint_type'], - constraint['custom']['constraint_value'] - ) - for constraint in constraints - ] if constraints else [] - json_config_rules = [ - json_config_rule( - config_rule['action'], - config_rule['custom']['resource_key'], - config_rule['custom']['resource_value'] - ) - for config_rule in config_rules - ] if config_rules else [] - return Service(**json_service( - service_uuid, service_type, json_context, json_status, - json_endpoints_ids, json_constraints, json_config_rules)) +def grpc_service(json_service : Dict): + return Service(**json_service) def grpc_slice_id(context_uuid, slice_uuid): return SliceId(**json_slice_id(slice_uuid, context_id=json_context_id(context_uuid))) - + +def grpc_slice(json_slice : Dict): + return Slice(**json_slice) + def grpc_topology_id(context_uuid, topology_uuid): return TopologyId(**json_topology_id(topology_uuid, context_id=json_context_id(context_uuid))) +def grpc_topology(json_topology : Dict): + return Topology(**json_topology) + def grpc_policy_rule_id(policy_rule_uuid): return PolicyRuleId(**json_policyrule_id(policy_rule_uuid)) + +def grpc_policy_rule(json_policy_rule : Dict): + return PolicyRule(**json_policy_rule) diff --git a/src/nbi/service/rest_server/nbi_plugins/tfs_api/__init__.py b/src/nbi/service/rest_server/nbi_plugins/tfs_api/__init__.py index 41e8ff1ea634869e69258c20f81f7c3db9767eb5..304a326481f4713f4b2e4f860fd2d42c25ae656b 100644 --- a/src/nbi/service/rest_server/nbi_plugins/tfs_api/__init__.py +++ b/src/nbi/service/rest_server/nbi_plugins/tfs_api/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/tools/Authentication.py b/src/nbi/service/rest_server/nbi_plugins/tools/Authentication.py index d3b7a56383f731972d3a7f07b2d0fee08e9c2eb7..112838cc43ca1a2466739fb1f84fcd906436ba95 100644 --- a/src/nbi/service/rest_server/nbi_plugins/tools/Authentication.py +++ b/src/nbi/service/rest_server/nbi_plugins/tools/Authentication.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/tools/HttpStatusCodes.py b/src/nbi/service/rest_server/nbi_plugins/tools/HttpStatusCodes.py index f228065724a2123e85edcc5383dce4194c29851d..56ea475c7657c80957f0d34ec5c8a3560d68d20a 100644 --- a/src/nbi/service/rest_server/nbi_plugins/tools/HttpStatusCodes.py +++ b/src/nbi/service/rest_server/nbi_plugins/tools/HttpStatusCodes.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/tools/Validator.py b/src/nbi/service/rest_server/nbi_plugins/tools/Validator.py index f955a5a06376defed8696a64d2eb9524250ce087..66b607c8bd6b115c83ff9173446646cebae11697 100644 --- a/src/nbi/service/rest_server/nbi_plugins/tools/Validator.py +++ b/src/nbi/service/rest_server/nbi_plugins/tools/Validator.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/service/rest_server/nbi_plugins/tools/__init__.py b/src/nbi/service/rest_server/nbi_plugins/tools/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/nbi/service/rest_server/nbi_plugins/tools/__init__.py +++ b/src/nbi/service/rest_server/nbi_plugins/tools/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/tests/Constants.py b/src/nbi/tests/Constants.py index b24c0b7ef69942a48a4307d4ced0afaf30197e09..886ddcafa4c3e1d798558f5dc285808ac7deecc6 100644 --- a/src/nbi/tests/Constants.py +++ b/src/nbi/tests/Constants.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/tests/MockService_Dependencies.py b/src/nbi/tests/MockService_Dependencies.py index 3c9ad5c5f80afbb62a7cb05aff87cede920bac7b..3224413670f02a3318e4f6af95b258993b2edd2d 100644 --- a/src/nbi/tests/MockService_Dependencies.py +++ b/src/nbi/tests/MockService_Dependencies.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/tests/PrepareTestScenario.py b/src/nbi/tests/PrepareTestScenario.py index e82c0166acff476924fbc2b873dbc30765fcce6a..a574f086b30cf0125d82f1b41a986e3dc0fd2366 100644 --- a/src/nbi/tests/PrepareTestScenario.py +++ b/src/nbi/tests/PrepareTestScenario.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/tests/__init__.py b/src/nbi/tests/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/nbi/tests/__init__.py +++ b/src/nbi/tests/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/tests/data/ietf_acl.json b/src/nbi/tests/data/ietf_acl.json new file mode 100644 index 0000000000000000000000000000000000000000..072df6d01513db8e47e50ffd42fc6719a6715f77 --- /dev/null +++ b/src/nbi/tests/data/ietf_acl.json @@ -0,0 +1,56 @@ +{ + "ietf-access-control-list": { + "acls": { + "acl": [ + { + "name": "sample-ipv4-acl", + "type": "ipv4-acl-type", + "aces": { + "ace": [ + { + "name": "rule1", + "matches": { + "ipv4": { + "dscp": 18, + "source-ipv4-network": "128.32.10.6/24", + "destination-ipv4-network": "172.10.33.0/24" + }, + "tcp": { + "flags": "syn", + "source-port": { + "port": 1444, + "operator": "eq" + }, + "destination-port": { + "port": 1333, + "operator": "eq" + } + } + }, + "actions": { + "forwarding": "drop" + } + } + ] + } + } + ], + "attachment-points": { + "interface": [ + { + "interface-id": "200", + "ingress": { + "acl-sets": { + "acl-set": [ + { + "name": "sample-ipv4-acl" + } + ] + } + } + } + ] + } + } + } +} diff --git a/src/nbi/tests/ietf_acl_client.py b/src/nbi/tests/ietf_acl_client.py new file mode 100644 index 0000000000000000000000000000000000000000..20887f1a8ac037d700e3df4a5c1da91f2ae58899 --- /dev/null +++ b/src/nbi/tests/ietf_acl_client.py @@ -0,0 +1,89 @@ +# 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 requests, time +from typing import Optional +from requests.auth import HTTPBasicAuth + +BASE_URL = '{:s}://{:s}:{:d}/restconf/data' +ACLS_URL = '{:s}/device={:s}/ietf-access-control-list:acls' +ACL_URL = '{:s}/device={:s}/ietf-access-control-list:acl={:s}' + +CSG1_DEVICE_UUID = '118295c8-318a-52ec-a394-529fc4b70f2f' # router: 128.32.10.1 +ACL_NAME = 'sample-ipv4-acl' +ACL_RULE = {"ietf-access-control-list:acls": { + "acl": [{ + "name": "sample-ipv4-acl", "type": "ipv4-acl-type", + "aces": {"ace": [{ + "name": "rule1", + "matches": { + "ipv4": { + "source-ipv4-network": "128.32.10.6/24", + "destination-ipv4-network": "172.10.33.0/24", + "dscp": 18 + }, + "tcp": { + "source-port": {"operator": "eq", "port": 1444}, + "destination-port": {"operator": "eq", "port": 1333}, + "flags": "syn" + } + }, + "actions": {"forwarding": "drop"} + }]} + }], + "attachment-points": {"interface": [{ + "interface-id": "200", + "ingress": {"acl-sets": {"acl-set": [{"name": "sample-ipv4-acl"}]}} + }] +}}} + +class TfsIetfAclClient: + def __init__( + self, host : str = 'localhost', port : int = 80, schema : str = 'http', + username : Optional[str] = 'admin', password : Optional[str] = 'admin', + timeout : int = 10, allow_redirects : bool = True, verify : bool = False + ) -> None: + self._base_url = BASE_URL.format(schema, host, port) + auth = HTTPBasicAuth(username, password) if username is not None and password is not None else None + self._settings = dict(auth=auth, timeout=timeout, allow_redirects=allow_redirects, verify=verify) + + def post(self, device_uuid : str, ietf_acl_data : dict) -> str: + request_url = ACLS_URL.format(self._base_url, device_uuid) + reply = requests.post(request_url, json=ietf_acl_data, **(self._settings)) + return reply.text + + def get(self, device_uuid : str, acl_name : str) -> str: + request_url = ACL_URL.format(self._base_url, device_uuid, acl_name) + reply = requests.get(request_url, **(self._settings)) + return reply.text + + def delete(self, device_uuid : str, acl_name : str) -> str: + request_url = ACL_URL.format(self._base_url, device_uuid, acl_name) + reply = requests.delete(request_url, **(self._settings)) + return reply.text + +def main(): + client = TfsIetfAclClient() + print(f'ACL rule: {ACL_RULE}') + post_response = client.post(CSG1_DEVICE_UUID, ACL_RULE) + print(f'post response: {post_response}') + time.sleep(.5) + get_response = client.get(CSG1_DEVICE_UUID, ACL_NAME) + print(f'get response: {get_response}') + time.sleep(.5) + delete_response = client.delete(CSG1_DEVICE_UUID, ACL_NAME) + print(f'delete response: {delete_response}') + +if __name__ == '__main__': + main() diff --git a/src/nbi/tests/test_etsi_bwm.py b/src/nbi/tests/test_etsi_bwm.py index e621e40726e92c21979eba5ba2c956aebd59e029..9400de00f95d7f1ec11c2fcf9af7e3b480c70ad2 100644 --- a/src/nbi/tests/test_etsi_bwm.py +++ b/src/nbi/tests/test_etsi_bwm.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/tests/test_ietf_l2vpn.py b/src/nbi/tests/test_ietf_l2vpn.py index 007d8d45e07da303ad846dc4ef256b9b16a9b499..7bed8ff5db57a59e90f39dce1ba1bc9e43dd005b 100644 --- a/src/nbi/tests/test_ietf_l2vpn.py +++ b/src/nbi/tests/test_ietf_l2vpn.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/tests/test_ietf_l3vpn.py b/src/nbi/tests/test_ietf_l3vpn.py index 5c77744a6024803157f210212ee071eba3a3fbf1..0f214661f4451317520db5dc0fc115459ce8e015 100644 --- a/src/nbi/tests/test_ietf_l3vpn.py +++ b/src/nbi/tests/test_ietf_l3vpn.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/tests/test_ietf_network.py b/src/nbi/tests/test_ietf_network.py index 9a25e1b3b5e0ee202a0af945e88794f8aa9b0ec4..68337d0a8b3cf4b4942f9cba7c4ca9a60b338268 100644 --- a/src/nbi/tests/test_ietf_network.py +++ b/src/nbi/tests/test_ietf_network.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -12,14 +12,20 @@ # See the License for the specific language governing permissions and # limitations under the License. -import deepdiff, json, logging, operator +import deepdiff, json, logging, operator, os from typing import Dict from common.Constants import DEFAULT_CONTEXT_NAME from common.proto.context_pb2 import ContextId -from common.tools.descriptor.Loader import DescriptorLoader, check_descriptor_load_results, validate_empty_scenario +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 nbi.service.rest_server import RestServer + +# Explicitly state NBI to use PyangBind Renderer for this test +os.environ['IETF_NETWORK_RENDERER'] = 'PYANGBIND' + from .PrepareTestScenario import ( # pylint: disable=unused-import # be careful, order of symbols is important here! do_rest_get_request, mock_service, nbi_service_rest, osm_wim, context_client diff --git a/src/nbi/tests/test_slice.py b/src/nbi/tests/test_slice.py index d382542fdbc5e51658531a1456bebf5d79d5f770..fe112e6fc70c94caa1f5fc3824e56758c2ec442c 100644 --- a/src/nbi/tests/test_slice.py +++ b/src/nbi/tests/test_slice.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/tests/test_tfs_api.py b/src/nbi/tests/test_tfs_api.py index f7d81aa56ef3274fbf17d20f5a067b3a7fa355a7..eab2f8d9ba6408491fb272cd59bc2f79a1c08a64 100644 --- a/src/nbi/tests/test_tfs_api.py +++ b/src/nbi/tests/test_tfs_api.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/nbi/tests/test_yang_acl.py b/src/nbi/tests/test_yang_acl.py new file mode 100644 index 0000000000000000000000000000000000000000..2f45c50bc4a140ca289aad03969f94148efa71d4 --- /dev/null +++ b/src/nbi/tests/test_yang_acl.py @@ -0,0 +1,104 @@ +# 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 copy, json, libyang, logging, os +from typing import Dict, List, Optional + +LOGGER = logging.getLogger(__name__) + +YANG_DIR = os.path.join(os.path.dirname(__file__), 'yang') +YANG_MODULES = [ + 'ietf-yang-types', + 'ietf-interfaces', + 'iana-if-type', + 'ietf-access-control-list', +] + +class YangValidator: + def __init__(self) -> None: + self._yang_context = libyang.Context(YANG_DIR) + for module_name in YANG_MODULES: + LOGGER.info('Loading module: {:s}'.format(str(module_name))) + yang_module = self._yang_context.load_module(module_name) + yang_module.feature_enable_all() + yang_module_prefix = yang_module.prefix() + LOGGER.info(' Prefix: {:s}'.format(str(yang_module_prefix))) + + def parse_to_dict(self, message : Dict, interface_names : List[str]) -> Dict: + interfaces = self._yang_context.create_data_path('/ietf-interfaces:interfaces') + for if_index,interface_name in enumerate(interface_names): + if_path = 'interface[name="{:s}"]'.format(str(interface_name)) + interface = interfaces.create_path(if_path) + interface.create_path('if-index', if_index + 1) + interface.create_path('type', 'iana-if-type:ethernetCsmacd') + interface.create_path('admin-status', 'up') + interface.create_path('oper-status', 'up') + statistics = interface.create_path('statistics') + statistics.create_path('discontinuity-time', '2024-07-11T10:00:00.000000Z') + + message = copy.deepcopy(message) + message['ietf-interfaces:interfaces'] = interfaces.print_dict()['interfaces'] + + dnode : Optional[libyang.DNode] = self._yang_context.parse_data_mem( + json.dumps(message), 'json', validate_present=True, strict=True + ) + if dnode is None: raise Exception('Unable to parse Message({:s})'.format(str(message))) + message = dnode.print_dict() + dnode.free() + interfaces.free() + return message + + def destroy(self) -> None: + self._yang_context.destroy() + self._yang_context = None + +def main() -> None: + import uuid # pylint: disable=import-outside-toplevel + logging.basicConfig(level=logging.DEBUG) + + interface_names = {'200', '500', str(uuid.uuid4()), str(uuid.uuid4())} + ACL_RULE = {"ietf-access-control-list:acls": { + "acl": [{ + "name": "sample-ipv4-acl", "type": "ipv4-acl-type", + "aces": {"ace": [{ + "name": "rule1", + "matches": { + "ipv4": { + "source-ipv4-network": "128.32.10.6/24", + "destination-ipv4-network": "172.10.33.0/24", + "dscp": 18 + }, + "tcp": { + "source-port": {"operator": "eq", "port": 1444}, + "destination-port": {"operator": "eq", "port": 1333}, + "flags": "syn" + } + }, + "actions": {"forwarding": "drop"} + }]} + }], + "attachment-points": {"interface": [{ + "interface-id": "200", + "ingress": {"acl-sets": {"acl-set": [{"name": "sample-ipv4-acl"}]}} + }] + }}} + + yang_validator = YangValidator() + request_data = yang_validator.parse_to_dict(ACL_RULE, list(interface_names)) + yang_validator.destroy() + + LOGGER.info('request_data = {:s}'.format(str(request_data))) + +if __name__ == '__main__': + main() diff --git a/src/opticalattackdetector/.gitlab-ci.yml b/src/opticalattackdetector/.gitlab-ci.yml index fb5715f755a2b11f10263b3093b3b59fbc62b72e..40cf3c397e93e231639ca8529829745274442c1b 100644 --- a/src/opticalattackdetector/.gitlab-ci.yml +++ b/src/opticalattackdetector/.gitlab-ci.yml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackdetector/Config.py b/src/opticalattackdetector/Config.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/opticalattackdetector/Config.py +++ b/src/opticalattackdetector/Config.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackdetector/Dockerfile b/src/opticalattackdetector/Dockerfile index 37d79582e754b4bbd2f0b82ad1fd63731c777ef8..60220dc63ce8ca157d56dcc76bbba05ab6aa6b7e 100644 --- a/src/opticalattackdetector/Dockerfile +++ b/src/opticalattackdetector/Dockerfile @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackdetector/__init__.py b/src/opticalattackdetector/__init__.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/opticalattackdetector/__init__.py +++ b/src/opticalattackdetector/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackdetector/client/OpticalAttackDetectorClient.py b/src/opticalattackdetector/client/OpticalAttackDetectorClient.py index 42a2b6c668a4e358daf6c6e24638084329fd5262..035d49fab2c2ec300ebe2aac042b8701734c8b7f 100644 --- a/src/opticalattackdetector/client/OpticalAttackDetectorClient.py +++ b/src/opticalattackdetector/client/OpticalAttackDetectorClient.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackdetector/client/__init__.py b/src/opticalattackdetector/client/__init__.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/opticalattackdetector/client/__init__.py +++ b/src/opticalattackdetector/client/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackdetector/requirements.in b/src/opticalattackdetector/requirements.in index 39982773b7bbd14a680aa3b26173e8fbcecd88fd..b1a4c5a9a983d39de44ce8108e77b22a9eda26d1 100644 --- a/src/opticalattackdetector/requirements.in +++ b/src/opticalattackdetector/requirements.in @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -12,5 +12,5 @@ # See the License for the specific language governing permissions and # limitations under the License. -numpy +numpy<2.0.0 redis diff --git a/src/opticalattackdetector/service/OpticalAttackDetectorService.py b/src/opticalattackdetector/service/OpticalAttackDetectorService.py index 8b8263d738066b412236ade0dfc5cd4ea806e0f5..637d268c8e5d110ba35b9755638cb81172b932c9 100644 --- a/src/opticalattackdetector/service/OpticalAttackDetectorService.py +++ b/src/opticalattackdetector/service/OpticalAttackDetectorService.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackdetector/service/OpticalAttackDetectorServiceServicerImpl.py b/src/opticalattackdetector/service/OpticalAttackDetectorServiceServicerImpl.py index d479f48e5b10c689b92aef64d13b2b3cb094826d..ee2b02f410444134eac92dfd9e3787ee71c37d58 100644 --- a/src/opticalattackdetector/service/OpticalAttackDetectorServiceServicerImpl.py +++ b/src/opticalattackdetector/service/OpticalAttackDetectorServiceServicerImpl.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackdetector/service/__init__.py b/src/opticalattackdetector/service/__init__.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/opticalattackdetector/service/__init__.py +++ b/src/opticalattackdetector/service/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackdetector/service/__main__.py b/src/opticalattackdetector/service/__main__.py index b9c7202cf1949b31c91cab37d0dea04c455ba037..d265de4d3ee399e5103c11dd944a4acc2c1c682a 100644 --- a/src/opticalattackdetector/service/__main__.py +++ b/src/opticalattackdetector/service/__main__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackdetector/tests/__init__.py b/src/opticalattackdetector/tests/__init__.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/opticalattackdetector/tests/__init__.py +++ b/src/opticalattackdetector/tests/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackdetector/tests/example_objects.py b/src/opticalattackdetector/tests/example_objects.py index 436b0ebaba4a5c3b7a172f87c2d0741c170932ed..8c9c8eef967702e5acac10c29849d18c7c142121 100644 --- a/src/opticalattackdetector/tests/example_objects.py +++ b/src/opticalattackdetector/tests/example_objects.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackdetector/tests/test_unitary.py b/src/opticalattackdetector/tests/test_unitary.py index a5ae8d59dbd271042575164276d746a705971a05..6b204b266f2e726ec8bd36dc64ebed210fb86e92 100644 --- a/src/opticalattackdetector/tests/test_unitary.py +++ b/src/opticalattackdetector/tests/test_unitary.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackmanager/.gitlab-ci.yml b/src/opticalattackmanager/.gitlab-ci.yml index fc10007775769d9c14bb984b7b0b62bd2edbe9a9..ccc5191a5fae0e40002396e519b1c4961ba9ae66 100644 --- a/src/opticalattackmanager/.gitlab-ci.yml +++ b/src/opticalattackmanager/.gitlab-ci.yml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackmanager/Config.py b/src/opticalattackmanager/Config.py index 9fd60386c3913bb7ee9b23c9688852b9743c881c..ba6d16bc00b208d932a19f1cc4eaa5c123bad7bd 100644 --- a/src/opticalattackmanager/Config.py +++ b/src/opticalattackmanager/Config.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackmanager/Dockerfile b/src/opticalattackmanager/Dockerfile index f9f5537a4c3249798d8022ddefd6d15e54fe9af4..2af1f282ae1389114fce5c83c71f9e38ef16e0ef 100644 --- a/src/opticalattackmanager/Dockerfile +++ b/src/opticalattackmanager/Dockerfile @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackmanager/__init__.py b/src/opticalattackmanager/__init__.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/opticalattackmanager/__init__.py +++ b/src/opticalattackmanager/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackmanager/requirements.in b/src/opticalattackmanager/requirements.in index 61bd9bd8b8d77bfa6f08c58ed64427c9058e2733..aed5638921626dd4cd200e22defcdf36c5ab1bbe 100644 --- a/src/opticalattackmanager/requirements.in +++ b/src/opticalattackmanager/requirements.in @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackmanager/service/__init__.py b/src/opticalattackmanager/service/__init__.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/opticalattackmanager/service/__init__.py +++ b/src/opticalattackmanager/service/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackmanager/service/__main__.py b/src/opticalattackmanager/service/__main__.py index 461756855b5fa5f1e55a8840019f92c7679c000c..31cccba055e92edf0e0ac9793d4bf423fbfdf458 100644 --- a/src/opticalattackmanager/service/__main__.py +++ b/src/opticalattackmanager/service/__main__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackmanager/tests/__init__.py b/src/opticalattackmanager/tests/__init__.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/opticalattackmanager/tests/__init__.py +++ b/src/opticalattackmanager/tests/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackmanager/tests/test_unitary.py b/src/opticalattackmanager/tests/test_unitary.py index 9530b288a664cbef4d7955f45bf86a54332cdf03..93baa46eacd658738379f86c419d260d7d46fdb7 100644 --- a/src/opticalattackmanager/tests/test_unitary.py +++ b/src/opticalattackmanager/tests/test_unitary.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackmanager/utils/__init__.py b/src/opticalattackmanager/utils/__init__.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/opticalattackmanager/utils/__init__.py +++ b/src/opticalattackmanager/utils/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackmanager/utils/monitor.py b/src/opticalattackmanager/utils/monitor.py index 39208245f08ad27bbae203c5c59c114d6d260eb8..76672ecf7a488746660b384f6af122cf914df508 100644 --- a/src/opticalattackmanager/utils/monitor.py +++ b/src/opticalattackmanager/utils/monitor.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackmitigator/.gitlab-ci.yml b/src/opticalattackmitigator/.gitlab-ci.yml index 4c3525f4aebb83caf22931ed2609d82246332e0f..501fcb7840200698df9ef9446c1fecea5eb1607c 100644 --- a/src/opticalattackmitigator/.gitlab-ci.yml +++ b/src/opticalattackmitigator/.gitlab-ci.yml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackmitigator/Config.py b/src/opticalattackmitigator/Config.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/opticalattackmitigator/Config.py +++ b/src/opticalattackmitigator/Config.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackmitigator/Dockerfile b/src/opticalattackmitigator/Dockerfile index 18c22861915317113b7eec4178385c7075d99365..f4c5a2b5ce1f7e69a35a05dcc59c1442569719e6 100644 --- a/src/opticalattackmitigator/Dockerfile +++ b/src/opticalattackmitigator/Dockerfile @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackmitigator/__init__.py b/src/opticalattackmitigator/__init__.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/opticalattackmitigator/__init__.py +++ b/src/opticalattackmitigator/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackmitigator/client/OpticalAttackMitigatorClient.py b/src/opticalattackmitigator/client/OpticalAttackMitigatorClient.py index 3498eae04eda8dedd3bd3766747c3ebf0d2980e1..7278144400d64d4bde3667252cf5e0b4046ec306 100644 --- a/src/opticalattackmitigator/client/OpticalAttackMitigatorClient.py +++ b/src/opticalattackmitigator/client/OpticalAttackMitigatorClient.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackmitigator/client/__init__.py b/src/opticalattackmitigator/client/__init__.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/opticalattackmitigator/client/__init__.py +++ b/src/opticalattackmitigator/client/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackmitigator/requirements.in b/src/opticalattackmitigator/requirements.in index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/opticalattackmitigator/requirements.in +++ b/src/opticalattackmitigator/requirements.in @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackmitigator/service/OpticalAttackMitigatorService.py b/src/opticalattackmitigator/service/OpticalAttackMitigatorService.py index 94b87485d524d971f3ab05cd4b78677de558c4d8..dfb2f7e3c2f6ec4d75f8c885e02f4cd3b4edd40f 100644 --- a/src/opticalattackmitigator/service/OpticalAttackMitigatorService.py +++ b/src/opticalattackmitigator/service/OpticalAttackMitigatorService.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackmitigator/service/OpticalAttackMitigatorServiceServicerImpl.py b/src/opticalattackmitigator/service/OpticalAttackMitigatorServiceServicerImpl.py index 96769f352ef3861719609d8adfba76721f4c318e..4437df98de19eb5e9d7d36da0d05e8a351f5b2e7 100644 --- a/src/opticalattackmitigator/service/OpticalAttackMitigatorServiceServicerImpl.py +++ b/src/opticalattackmitigator/service/OpticalAttackMitigatorServiceServicerImpl.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackmitigator/service/__init__.py b/src/opticalattackmitigator/service/__init__.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/opticalattackmitigator/service/__init__.py +++ b/src/opticalattackmitigator/service/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackmitigator/service/__main__.py b/src/opticalattackmitigator/service/__main__.py index 1e13e2ef0c0ac69ff2a0753247b1c7522fedda2a..135ad5bdd8d43a63d3af0bb2e63b4c907e1fed69 100644 --- a/src/opticalattackmitigator/service/__main__.py +++ b/src/opticalattackmitigator/service/__main__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackmitigator/tests/__init__.py b/src/opticalattackmitigator/tests/__init__.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/opticalattackmitigator/tests/__init__.py +++ b/src/opticalattackmitigator/tests/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalattackmitigator/tests/test_unitary.py b/src/opticalattackmitigator/tests/test_unitary.py index ba58c60709a4ead7653314bb885fe4e6a370b883..bf6927ff046d241e7daac32b402c8c93972b6edf 100644 --- a/src/opticalattackmitigator/tests/test_unitary.py +++ b/src/opticalattackmitigator/tests/test_unitary.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalcontroller/.gitlab-ci.yml b/src/opticalcontroller/.gitlab-ci.yml index 831a61186d0e56b0b359d47c551c555da8ade3ee..20125e178b79b0a0db05a23769038e6aea8b9e7e 100644 --- a/src/opticalcontroller/.gitlab-ci.yml +++ b/src/opticalcontroller/.gitlab-ci.yml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalcontroller/Dockerfile b/src/opticalcontroller/Dockerfile index faea3b2e056768ef9947db108df61928c8a177cb..3668646868f9d48faa6e3e9afa70ce4e3a1bc9df 100644 --- a/src/opticalcontroller/Dockerfile +++ b/src/opticalcontroller/Dockerfile @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -67,5 +67,4 @@ COPY src/context/client/. context/client/ COPY src/opticalcontroller/. opticalcontroller/ # Start the service -WORKDIR /var/teraflow/opticalcontroller -ENTRYPOINT ["python", "OpticalController.py"] +ENTRYPOINT ["python", "-m", "opticalcontroller.OpticalController"] diff --git a/src/opticalcontroller/OpticalController.py b/src/opticalcontroller/OpticalController.py index 0febb7b1f470bf86dc30754c1db2af262779a25d..74fd7882689d92a654a749ea5be0c2583841a31b 100644 --- a/src/opticalcontroller/OpticalController.py +++ b/src/opticalcontroller/OpticalController.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -12,19 +12,23 @@ # See the License for the specific language governing permissions and # limitations under the License. +import logging, time from flask import Flask from flask import render_template from flask_restplus import Resource, Api +from google.protobuf.json_format import MessageToDict +from common.proto.context_pb2 import TopologyId +from opticalcontroller.tools import * +from opticalcontroller.variables import * +from opticalcontroller.RSA import RSA -from tools import * -from variables import * -from RSA import RSA -import time -import logging - +logging.basicConfig(level=logging.INFO) +LOGGER = logging.getLogger(__name__) +global rsa +global links_dict rsa = None -LOGGER = logging.getLogger(__name__) + app = Flask(__name__) api = Api(app, version='1.0', title='Optical controller API', @@ -47,7 +51,7 @@ class AddLightpath(Resource): @staticmethod def put(src, dst, bitrate, bidir=1): - LOGGER.info("INFO: New Lightpath request from {} to {} with rate {} ".format(src, dst, bitrate)) + print("INFO: New Lightpath request from {} to {} with rate {} ".format(src, dst, bitrate)) t0 = time.time()*1000.0 if debug: rsa.g.printGraph() @@ -56,9 +60,9 @@ class AddLightpath(Resource): flow_id = rsa.rsa_computation(src, dst, bitrate, bidir) if rsa.db_flows[flow_id]["op-mode"] == 0: return 'No path found', 404 - t1 = time.time()*1000.0 + t1 = time.time() * 1000.0 elapsed = t1 - t0 - LOGGER.info("INFO: time elapsed = {} ms".format(elapsed)) + print("INFO: time elapsed = {} ms".format(elapsed)) return rsa.db_flows[flow_id], 200 else: return "Error", 404 @@ -74,18 +78,15 @@ class AddLightpath(Resource): @optical.response(404, 'Error, not found') class AddFlexLightpath(Resource): @staticmethod - def put(src, dst, bitrate,bidir=1, band=None): - + def put(src, dst, bitrate, bidir=1, band=None): + print("INFO: New FlexLightpath request from {} to {} with rate {} ".format(src, dst, bitrate)) - LOGGER.info("INFO: New FlexLightpath request from {} to {} with rate {} ".format(src, dst, bitrate)) t0 = time.time()*1000.0 if debug: rsa.g.printGraph() if rsa is not None: flow_id, optical_band_id = rsa.rsa_fs_computation(src, dst, bitrate, bidir, band) - print (f"flow_id {flow_id} and optical_band_id {optical_band_id} ") - LOGGER.debug('flow_id={:s} rsa.db_flows={:s}'.format(str(flow_id), str(rsa.db_flows))) if flow_id is not None: if rsa.db_flows[flow_id]["op-mode"] == 0: return 'No path found', 404 @@ -100,53 +101,118 @@ class AddFlexLightpath(Resource): else: t1 = time.time() * 1000.0 elapsed = t1 - t0 - LOGGER.info("INFO: time elapsed = {} ms".format(elapsed)) + print("INFO: time elapsed = {} ms".format(elapsed)) return rsa.optical_bands[optical_band_id], 200 else: return "Error", 404 -@optical.route('/DelFlexLightpath/////') + +# @optical.route('/DelFlexLightpath////') +@optical.route('/DelFlexLightpath////') +@optical.route('/DelFlexLightpath/////') @optical.response(200, 'Success') @optical.response(404, 'Error, not found') -class DelLightpath(Resource): +class DelFLightpath(Resource): @staticmethod - def delete(flow_id, src, dst, bitrate, o_band_id): - if flow_id in rsa.db_flows.keys(): - flow = rsa.db_flows[flow_id] - bidir = flow["bidir"] - match1 = flow["src"] == src and flow["dst"] == dst and flow["bitrate"] == bitrate - if bidir: - match2 = flow["src"] == dst and flow["dst"] == src and flow["bitrate"] == bitrate - if match1 or match2: + def delete( src, dst, bitrate, o_band_id, flow_id=None): + flow = None + match1 = False + ob_id = None + if flow_id is not None: + if flow_id in rsa.db_flows.keys(): + flow = rsa.db_flows[flow_id] + match1 = flow["src"] == src and flow["dst"] == dst and flow["bitrate"] == bitrate ob_id = flow["parent_opt_band"] - rsa.del_flow(flow, ob_id) - rsa.db_flows[flow_id]["is_active"] = False - rsa.optical_bands[ob_id]["served_lightpaths"].remove(flow_id) - if rsa.optical_bands[ob_id]["reverse_optical_band_id"] != 0: - rev_ob_id = rsa.optical_bands[ob_id]["reverse_optical_band_id"] - rsa.optical_bands[rev_ob_id]["served_lightpaths"].remove(flow_id) - - if debug: - LOGGER.info(links_dict) - return "flow {} deleted".format(flow_id), 200 + flow['is_active'] = False + + if flow is not None: + bidir = flow["bidir"] + if bidir: + match2 = flow["src"] == dst and flow["dst"] == src and flow["bitrate"] == bitrate + if match1 or match2: + ob_id = flow["parent_opt_band"] + rsa.del_flow(flow, ob_id) + rsa.db_flows[flow_id]["is_active"] = False + if flow_id in rsa.optical_bands[ob_id]["served_lightpaths"]: + rsa.optical_bands[ob_id]["served_lightpaths"].remove(flow_id) + #if rsa.optical_bands[ob_id]["reverse_optical_band_id"] != 0: + # rev_ob_id = rsa.optical_bands[ob_id]["reverse_optical_band_id"] + # rsa.optical_bands[rev_ob_id]["served_lightpaths"].remove(flow_id) + + if debug: + print(rsa.links_dict) + return "flow {} deleted".format(flow_id), 200 + else: + return "flow {} not matching".format(flow_id), 404 else: - return "flow {} not matching".format(flow_id), 404 + if match1: + # if delete_band !=0 and ob_id is not None: + # print(f"delete_lightpath {delete_band} and ob_id {ob_id}") + # if len( rsa.optical_bands[ob_id]["served_lightpaths"]) != 0: + # return "DELETE_NOT_ALLOWED" ,400 + rsa.del_flow(flow,flow_id,ob_id) + + if debug: + print(f"vor ob_id {ob_id} rsa.optical_bands {rsa.optical_bands[ob_id]}") + print(f"rsa.links_dict {rsa.links_dict}") + return "flow {} deleted".format(flow_id), 200 + else: + return "flow {} not matching".format(flow_id), 404 else: - if match1: - ob_id = flow["parent_opt_band"] - rsa.del_flow(flow, ob_id) - rsa.db_flows[flow_id]["is_active"] = False - rsa.optical_bands[ob_id]["served_lightpaths"].remove(flow_id) - if debug: - LOGGER.info(links_dict) - return "flow {} deleted".format(flow_id), 200 - else: - return "flow {} not matching".format(flow_id), 404 - else: - return "flow id {} does not exist".format(flow_id), 404 + return "flow id {} does not exist".format(flow_id), 404 +@optical.route('/DelOpticalBand///', methods=['DELETE']) +@optical.response(200, 'Success') +@optical.response(404, 'Error, not found') +class DelOpticalBand(Resource): + @staticmethod + def delete( src, dst, o_band_id): + flow = None + ob_id = None + if o_band_id is not None: + if o_band_id in rsa.optical_bands.keys(): + flow = rsa.optical_bands[o_band_id] + match1 = flow["src"] == src and flow["dst"] == dst and flow["bitrate"] + ob_id = o_band_id + + if flow is not None: + bidir = flow["bidir"] + if bidir: + match2 = flow["src"] == dst and flow["dst"] == src and flow["bitrate"] + if match1 or match2: + ob_id = flow["parent_opt_band"] + #rsa.del_flow(flow, ob_id) + rsa.optical_bands[ob_id]["is_active"] = False + # if flow_id in rsa.optical_bands[ob_id]["served_lightpaths"]: + # rsa.optical_bands[ob_id]["served_lightpaths"].remove(flow_id) + #if rsa.optical_bands[ob_id]["reverse_optical_band_id"] != 0: + # rev_ob_id = rsa.optical_bands[ob_id]["reverse_optical_band_id"] + # rsa.optical_bands[rev_ob_id]["served_lightpaths"].remove(flow_id) + + if debug: + print(rsa.links_dict) + return "ob_id {} deleted".format(ob_id), 200 + else: + return "ob_id {} not matching".format(ob_id), 404 + else: + if ob_id is not None: + + if len( rsa.optical_bands[ob_id]["served_lightpaths"]) != 0: + return "DELETE_NOT_ALLOWED" ,400 + + rsa.del_band(flow,ob_id) + if debug: + print(f"vor ob_id {ob_id} rsa.optical_bands {rsa.optical_bands[ob_id]}") + print(f"rsa.links_dict {rsa.links_dict}") + return "ob_id {} deleted".format(ob_id), 200 + + else : + return "flow for ob_id {} not found".format(ob_id),400 + else: + return "ob_id {} does not exist".format(ob_id), 404 + @optical.route('/DelLightpath////') @optical.response(200, 'Success') @@ -162,7 +228,7 @@ class DelLightpath(Resource): rsa.del_flow(flow) rsa.db_flows[flow_id]["is_active"] = False if debug: - LOGGER.info(links_dict) + print(rsa.links_dict) return "flow {} deleted".format(flow_id), 200 else: return "flow {} not matching".format(flow_id), 404 @@ -178,22 +244,21 @@ class GetFlows(Resource): def get(): try: if debug: - LOGGER.info(rsa.db_flows) + print(rsa.db_flows) return rsa.db_flows, 200 except: return "Error", 404 + @optical.route('/GetOpticalBands') @optical.response(200, 'Success') @optical.response(404, 'Error, not found') class GetBands(Resource): @staticmethod def get(): - print("Getting ") - LOGGER.info("Getting") try: if debug: - LOGGER.info(rsa.optical_bands) + print(rsa.optical_bands) return rsa.optical_bands, 200 except: return "Error", 404 @@ -208,7 +273,7 @@ class GetBand(Resource): for ob_idx in rsa.optical_bands.keys(): if str(ob_idx) == str(ob_id): if debug: - LOGGER.info(rsa.optical_bands[ob_id]) + print(rsa.optical_bands[ob_id]) return rsa.optical_bands[ob_idx], 200 return {}, 404 @@ -219,28 +284,74 @@ class GetBand(Resource): class GetFlows(Resource): @staticmethod def get(): - global links_dict + global rsa + #global links_dict + links = None + if rsa is not None : + links = rsa.links_dict try: if debug: - LOGGER.info(links_dict) - return links_dict, 200 + print(links) + return links, 200 except: return "Error", 404 -if __name__ == '__main__': +@optical.route('/GetTopology//',methods=['GET']) +@optical.response(200, 'Success') +@optical.response(404, 'Error, not found') +class GetTopology(Resource): + @staticmethod + def get(context_id:str,topology_id:str): + + global rsa + if (rsa is not None): + return "Opticalcontroller is synchronised" ,200 + topog_id = TopologyId() + topog_id.topology_uuid.uuid=topology_id + topog_id.context_id.context_uuid.uuid=context_id + + try: + links_dict = {"optical_links": []} + node_dict = {} + topo, nodes = readTopologyDataFromContext(topog_id) + + for link in topo: + link_dict_type = MessageToDict(link, preserving_proto_field_name=True) + + if "c_slots" in link_dict_type["optical_details"]: + link_dict_type["optical_details"]["c_slots"] = link_dict_type["optical_details"]["c_slots"] + + if "l_slots" in link_dict_type["optical_details"]: + link_dict_type["optical_details"]["l_slots"] = link_dict_type["optical_details"]["l_slots"] + + if "s_slots" in link_dict_type["optical_details"]: + link_dict_type["optical_details"]["s_slots"] = link_dict_type["optical_details"]["s_slots"] + + links_dict["optical_links"].append(link_dict_type) + + for device in nodes : + dev_dic = { + "id":device.device_id.device_uuid.uuid, + #"ip":f"10.30.2.{207+i}", + #"port":"50001", + "type":"OC-ROADM" if device.device_type =="optical-roadm" else "OC-TP", + "driver": "OpticalOC" + } + node_dict[device.name] = dev_dic + #i+=1 + #print(f"refresh_optical controller optical_links_dict= {links_dict}") + #print(f"refresh_optical controller node_dict {node_dict}") + + rsa = RSA(node_dict, links_dict) + if debug: + print(rsa.init_link_slots2()) + return "ok", 200 + except Exception as e: + LOGGER.exception('Error in GetTopology') + print(f"err {e}") + return "Error", 400 - # Start metrics server - - LOGGER.info('Starting...') - - - - nodes_dict, links_dict = readTopologyData(nodes_json, topology_json) - - #topologies, links = getTopology() - #print("topologies{} and devices {}".format(topologies,links)) - rsa = RSA(nodes_dict, links_dict) - - app.run(host='0.0.0.0', port=10060, debug=True) +if __name__ == '__main__': + app.run(host='0.0.0.0', port=10060) diff --git a/src/opticalcontroller/README.md b/src/opticalcontroller/README.md index 5fd94c59e51cbd78dd76a7db0f24aaaec4ebd9db..f121055cec91470646b9885bfe90db137027f472 100644 --- a/src/opticalcontroller/README.md +++ b/src/opticalcontroller/README.md @@ -1,17 +1,20 @@ -# optical-controller -This a framework to implement the optical controller for the RMSA algorithm. +# Optical Controller + +This is a framework to test the optical controller for the RMSA algorithm in an isolated manner. + +![Reference Architecture](images/topo.png) + +```bash #create a venv python -m venv venv -in linux +# in linux source venv/Scripts/activate -in windows +# in windows venv\Scripts\activate -pip install -r requirements_opt.txt +pip install -r requirements_optical_ctrl_test.txt python OpticalController.py -![Reference Architecture](images/topo.png) - - +``` diff --git a/src/opticalcontroller/RSA.py b/src/opticalcontroller/RSA.py index b15357c98242ad6b18d4068b6f0aa1cb08852d7a..da31187eb1d5c3f6f51cbbdc1c9641653b683e4b 100644 --- a/src/opticalcontroller/RSA.py +++ b/src/opticalcontroller/RSA.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -12,9 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -import dijsktra -from tools import * -from variables import * +from opticalcontroller.dijkstra import Graph, shortest_path +from opticalcontroller.tools import * +from opticalcontroller.variables import * class RSA(): @@ -26,15 +26,15 @@ class RSA(): self.flow_id = 0 self.opt_band_id = 0 self.db_flows = {} - self.initGraph() + self.initGraph2() self.c_slot_number = 0 self.l_slot_number = 0 self.s_slot_number = 0 self.optical_bands = {} - def init_link_slots(self, testing): - if not testing: - for l in self.links_dict["links"]: + def init_link_slots(self): + if full_links: + for l in self.links_dict["optical_links"]: for fib in l["optical_link"]["details"]["fibers"]: #fib = self.links_dict[l]["fibers"][f] if len(fib["c_slots"]) > 0: @@ -45,7 +45,7 @@ class RSA(): fib["s_slots"] = list(range(0, Ns)) if debug: print(fib) - for l1 in self.links_dict["links"]: + for l1 in self.links_dict["optical_links"]: for fib1 in l1["optical_link"]["details"]["fibers"]: #fib1 = self.links_dict[l1]["details"]["fibers"][f1] @@ -58,11 +58,35 @@ class RSA(): break return "{},{},{}".format(self.c_slot_number, self.l_slot_number, self.s_slot_number) + def init_link_slots2(self): + if full_links: + for l in self.links_dict["optical_links"]: + fib = l["optical_details"] + #fib = self.links_dict[l]["fibers"][f] + if len(fib["c_slots"]) > 0: + for c in range(0, Nc): + fib["c_slots"][c] = 1 + if len(fib["l_slots"]) > 0: + for c in range(0, Nl): + fib["l_slots"][c] = 1 + if len(fib["s_slots"]) > 0: + for c in range(0, Ns): + fib["s_slots"][c] = 1 + if debug: + print(fib) + for l1 in self.links_dict["optical_links"]: + fib1 = l1["optical_details"] + self.c_slot_number = len(fib1["c_slots"].keys()) + self.l_slot_number = len(fib1["l_slots"].keys()) + self.s_slot_number = len(fib1["s_slots"].keys()) + break + return "{},{},{}".format(self.c_slot_number, self.l_slot_number, self.s_slot_number) + def initGraph(self): - self.g = dijsktra.Graph() + self.g = Graph() for n in self.nodes_dict: self.g.add_vertex(n) - for l in self.links_dict["links"]: + for l in self.links_dict["optical_links"]: if debug: print(l) [s, d] = l["optical_link"]["name"].split('-') @@ -74,8 +98,26 @@ class RSA(): if debug: self.g.printGraph() + def initGraph2(self): + + self.g = Graph() + + for n in self.nodes_dict: + self.g.add_vertex(n) + for l in self.links_dict["optical_links"]: + if debug: + print(l) + [s, d] = l["name"].split('-') + ps = l["optical_details"]["src_port"] + pd = l["optical_details"]["dst_port"] + self.g.add_edge(s, d, ps, pd, 1) + + print("INFO: Graph initiated.2") + if debug: + self.g.printGraph() + def compute_path(self, src, dst): - path = dijsktra.shortest_path(self.g, self.g.get_vertex(src), self.g.get_vertex(dst)) + path = shortest_path(self.g, self.g.get_vertex(src), self.g.get_vertex(dst)) print("INFO: Path from {} to {} with distance: {}".format(src, dst, self.g.get_vertex(dst).get_distance())) if debug: print(path) @@ -95,7 +137,7 @@ class RSA(): self.g.reset_graph() return links, path - def get_slots(self, links, slots, optical_band_id = None): + def get_slots(self, links, slots, optical_band_id=None): if isinstance(slots, int): val_c = slots @@ -120,38 +162,40 @@ class RSA(): add = links[0] if self.nodes_dict[dst_2]["type"] == "OC-TP": drop = links[-1] - + found = 0 for l in links: c_slots[l] = [] l_slots[l] = [] s_slots[l] = [] - found = 0 - for link in self.links_dict["links"]: - if link["optical_link"]["name"] == l: - #for f in self.links_dict[l]['fibers'].keys(): - for fib in link["optical_link"]["details"]["fibers"]: - if l == add: - if 'used' in fib: - if fib["used"]: - #if debug: - print("WARNING!!!: link {}, fiber {} is already in use".format(l, fib["ID"])) - continue - if l == drop: - if 'used' in fib: - if fib["used"]: - #if debug: - print("WARNING!!!: link {}, fiber {} is already in use".format(l, fib["ID"])) - continue - if len(fib["c_slots"]) > 0: - c_slots[l] = combine(c_slots[l], consecutives(fib["c_slots"], val_c)) - if len(fib["l_slots"]) > 0: - l_slots[l] = combine(l_slots[l], consecutives(fib["l_slots"], val_l)) - if len(fib["s_slots"]) > 0: - s_slots[l] = combine(s_slots[l], consecutives(fib["s_slots"], val_s)) - if debug: - print(l, c_slots[l]) - found = 1 - if found == 0: + + link = self.get_link_by_name(l) + fib = link["optical_details"] + if l == add: + if 'used' in fib: + if fib["used"]: + #if debug: + print("WARNING!!!: link {}, is already in use".format(l)) + return [], [], [] + if l == drop: + if 'used' in fib: + if fib["used"]: + #if debug: + print("WARNING!!!: link {} is already in use".format(l)) + return [], [], [] + c_found = l_found = s_found = 0 + if len(fib["c_slots"].keys()) > 0: + #c_slots[l] = combine(c_slots[l], consecutives(fib["c_slots"], val_c)) + c_slots[l] = combine(c_slots[l], consecutives(fib["c_slots"], val_c)) + c_found = 1 + if len(fib["l_slots"].keys()) > 0: + l_slots[l] = combine(l_slots[l], consecutives(fib["l_slots"], val_l)) + l_found = 1 + if len(fib["s_slots"].keys()) > 0: + s_slots[l] = combine(s_slots[l], consecutives(fib["s_slots"], val_s)) + s_found = 1 + if debug: + print(l, c_slots[l]) + if c_found == 0 and l_found == 0 and s_found == 0: return [], [], [] keys = list(c_slots.keys()) @@ -185,60 +229,80 @@ class RSA(): c_sts = common_slots(a_c, b_c) l_sts = common_slots(a_l, b_l) s_sts = common_slots(a_s, b_s) + ''' + if len(fib["l_slots"]) > 0: + l_slots[l] = combine(l_slots[l], consecutives(fib["l_slots"], val_l)) + l_found = 1''' if optical_band_id is not None: if "c_slots" in self.optical_bands[optical_band_id].keys(): if len(self.optical_bands[optical_band_id]["c_slots"]) > 0: a_c = c_sts - b_c = self.optical_bands[optical_band_id]["c_slots"] + #MOD + b_c = consecutives(self.optical_bands[optical_band_id]["c_slots"], val_c) + #b_c = self.optical_bands[optical_band_id]["c_slots"] c_sts = common_slots(a_c, b_c) - else: - c_sts = [] else: c_sts = [] if "l_slots" in self.optical_bands[optical_band_id].keys(): if len(self.optical_bands[optical_band_id]["l_slots"]) > 0: a_l = l_sts - b_l = self.optical_bands[optical_band_id]["l_slots"] + b_l = consecutives(self.optical_bands[optical_band_id]["l_slots"], val_c) l_sts = common_slots(a_l, b_l) - else: - l_sts = [] else: l_sts = [] if "s_slots" in self.optical_bands[optical_band_id].keys(): if len(self.optical_bands[optical_band_id]["s_slots"]) > 0: a_s = s_sts - b_s = self.optical_bands[optical_band_id]["s_slots"] + b_s = consecutives(str_list_to_int(self.optical_bands[optical_band_id]["s_slots"].keys()), val_c) s_sts = common_slots(a_s, b_s) - else: - s_sts = [] else: s_sts = [] return c_sts, l_sts, s_sts def update_link(self, fib, slots, band): + #print(fib) for i in slots: - fib[band].remove(i) + fib[band][str(i)] = 0 if 'used' in fib: fib['used'] = True + print(f"fib updated {fib}") + #print(fib) def update_optical_band(self, optical_band_id, slots, band): for i in slots: - self.optical_bands[optical_band_id][band].remove(i) + self.optical_bands[optical_band_id][band][str(i)] = 0 + + def augment_optical_band(self, optical_band_id, slots, band): + for i in slots: + self.optical_bands[optical_band_id][band][str(i)] = 1 def restore_link(self, fib, slots, band): for i in slots: - fib[band].append(int(i)) + fib[band][str(i)] = 1 if 'used' in fib: fib['used'] = False - fib[band].sort() + #fib[band].sort() def restore_optical_band(self, optical_band_id, slots, band): for i in slots: - self.optical_bands[optical_band_id][band].append(int(i)) - self.optical_bands[optical_band_id][band].sort() + self.optical_bands[optical_band_id][band][str(i)] = 1 + #self.optical_bands[optical_band_id][band].append(int(i)) + #self.optical_bands[optical_band_id][band].sort() + + def restore_optical_band_2(self, optical_band_id, slots, band ,links): + print(f"example of band { band}") + print(f"example of slots {slots}") + print(f"example of self.optical_bands_before { self.optical_bands}") + for i in slots: + self.optical_bands[optical_band_id][band][str(i)] = 1 + print(f"example of self.optical_bands_after { self.optical_bands}") + + #link_name= self.optical_bands[optical_band_id]['links'][0] + #link = self.get_link_by_name(link_name) + #update_optical_band(optical_bands=self.optical_bands,optical_band_id=optical_band_id,band=band,link=link) - def del_flow(self, flow, o_b_id = None): + def del_flow(self, flow,flow_id, o_b_id = None): flows = flow["flows"] band = flow["band_type"] slots = flow["slots"] @@ -249,22 +313,123 @@ class RSA(): path = flow["path"] links = flow["links"] bidir = flow["bidir"] + flow_id = flow["flow_id"] - for l in fiber_f.keys(): + for l in links: if debug: print(l) - print(fiber_f[l]) #link = self.links_dict[l] #f = fiber_f[l] #fib = link['fibers'][f] - fib = self.get_fiber_details(l, fiber_f[l]) - if not list_in_list(slots, fib[band]): - self.restore_link(fib, slots, band) + fib = self.get_link_by_name(l)["optical_details"] + + self.restore_link(fib, slots, band) + if debug: + print(fib[band]) + + if o_b_id is not None: + if debug: + print("restoring OB") + print(f"invoking restore_optical_band o_b_id: {o_b_id} , slots {slots} , band {band} ") + self.restore_optical_band(o_b_id, slots, band) + if flow_id in self.optical_bands[o_b_id]["served_lightpaths"]: + if flow_id in self.optical_bands[o_b_id]["served_lightpaths"]: + self.optical_bands[o_b_id]["served_lightpaths"].remove(flow_id) + + #self.restore_optical_band_2(o_b_id, slots, band,links) + + if bidir: + for l in links: + r_l = reverse_link(l) + if debug: + print(r_l) + # link = self.links_dict[l] + # f = fiber_f[l] + # fib = link['fibers'][f] + fib = self.get_link_by_name(r_l)["optical_details"] + if list_in_list(slots, str_list_to_int(fib[band].keys())): + self.restore_link(fib, slots, band) + if debug: + print(fib[band]) + ''' + for rl in fiber_b.keys(): if debug: - print(fib[band]) + print(rl) + print(fiber_b[rl]) + #rlink = self.links_dict[rl] + #rf = fiber_b[rl] + #rfib = rlink['fibers'][rf] + rfib = self.get_fiber_details(rl, fiber_b[rl]) + if not list_in_list(slots, rfib[band]): + self.restore_link(rfib, slots, band) + if debug: + print(rfib[band]) + ''' + #changed according to TFS development + #if o_b_id is not None: + # rev_o_band_id = self.optical_bands[o_b_id]["reverse_optical_band_id"] + # self.restore_optical_band(rev_o_band_id, slots, band) + return True + + + def del_band(self, flow, o_b_id = None): + print(f"delete band {flow} ") + + flows = flow["flows"] + band = None + #slots = flow["slots"] + fiber_f = flow["fiber_forward"] + fiber_b = flow["fiber_backward"] + op = flow["op-mode"] + n_slots = 0 + path = flow["path"] + bidir = flow["bidir"] + links = [] + if o_b_id is not None: + links= self.optical_bands[o_b_id]["links"] + band = self.optical_bands[o_b_id]["band_type"] + n_slots =self.optical_bands[o_b_id]["n_slots"] + if n_slots > 0: + slots=[i+1 for i in range(n_slots)] + + for l in links: + if debug: + print(l) + #link = self.links_dict[l] + #f = fiber_f[l] + #fib = link['fibers'][f] + fib = self.get_link_by_name(l)["optical_details"] + print(f"del_flow_fib {fib } and band {band}") + print(f"del_flow { str_list_to_int(fib[band].keys())}") + + print(f"invoking restore_link fib: {fib} , slots {slots} , band {band} ") + self.restore_link(fib, slots, band) + self.optical_bands[o_b_id]["is_active"]=False + + if debug: + print(fib[band]) + if o_b_id is not None: + + if debug: + print("restoring OB") + print(f"invoking restore_optical_band o_b_id: {o_b_id} , slots {slots} , band {band} ") self.restore_optical_band(o_b_id, slots, band) + #self.restore_optical_band_2(o_b_id, slots, band,links) if bidir: + for l in links: + r_l = reverse_link(l) + if debug: + print(r_l) + # link = self.links_dict[l] + # f = fiber_f[l] + # fib = link['fibers'][f] + fib = self.get_link_by_name(r_l)["optical_details"] + if list_in_list(slots, str_list_to_int(fib[band].keys())): + self.restore_link(fib, slots, band) + if debug: + print(fib[band]) + ''' for rl in fiber_b.keys(): if debug: print(rl) @@ -277,17 +442,26 @@ class RSA(): self.restore_link(rfib, slots, band) if debug: print(rfib[band]) + ''' #changed according to TFS development #if o_b_id is not None: # rev_o_band_id = self.optical_bands[o_b_id]["reverse_optical_band_id"] # self.restore_optical_band(rev_o_band_id, slots, band) return True + def del_handler(self, flow,flow_id, o_b_id = None,delete_band=0): + print(f" del_handler flow {flow} flow_id {flow_id} o_b_id {o_b_id} delete_band {delete_band}") + if delete_band != 0: + print(f"delete band del_band") + self.del_band(flow,flow_id,o_b_id=o_b_id) + else : + self.del_flow(flow,flow_id=flow_id,o_b_id=o_b_id) + def get_fibers_forward(self, links, slots, band): fiber_list = {} add = links[0] drop = links[-1] - print(links) + #print(links) ''' for link in self.links_dict["links"]: if link["optical_link"]["name"] == l: @@ -296,85 +470,98 @@ class RSA(): ''' for l in links: - for link in self.links_dict["links"]: - if link["optical_link"]["name"] == l: - for fib in link["optical_link"]["details"]["fibers"]: - #for f in self.links_dict[l]['fibers'].keys(): - #for fib in l["optical_link"]["details"]["fibers"]: - #fib = self.links_dict[l]['fibers'][f] - if l == add: - if 'used' in fib: - if fib["used"]: - if debug: - print("link {}, fiber {} is already in use".format(l, fib["ID"])) - continue - if l == drop: - if 'used' in fib: - if fib["used"]: - if debug: - print("link {}, fiber {} is already in use".format(l, fib["ID"])) - continue - if list_in_list(slots, fib[band]): - fiber_list[l] = fib["ID"] - self.update_link(fib, slots, band) - break + for link in self.links_dict["optical_links"]: + print(f"tracking link info {link}") + if link["name"] == l: + fib = link["optical_details"] + #for f in self.links_dict[l]['fibers'].keys(): + #for fib in l["optical_link"]["details"]["fibers"]: + #fib = self.links_dict[l]['fibers'][f] + if l == add: + if 'used' in fib: + if fib["used"]: + if debug: + print("link {} is already in use".format(l)) + continue + if l == drop: + if 'used' in fib: + if fib["used"]: + if debug: + print("link {} is already in use".format(l)) + continue + if list_in_list(slots, str_list_to_int(fib[band].keys())): + #fiber_list[l] = fib["ID"] + self.update_link(fib, slots, band) + break print("INFO: Path forward computation completed") return fiber_list def get_link_by_name (self, key): - result = None - for link in self.links_dict["links"]: - if link["optical_link"]["name"] == key: + for link in self.links_dict["optical_links"]: + if link["name"] == key: if debug: print(link) - result = link break - return result + return link def get_fiber_details(self, link_key, fiber_id): - for link in self.links_dict["links"]: - if link["optical_link"]["name"] == link_key: + for link in self.links_dict["optical_links"]: + if link["name"] == link_key: if debug: print(link) - for fib in link["optical_link"]["details"]["fibers"]: + for fib in link["optical_details"]: if fib["ID"] == fiber_id: return fib return None - - def get_fibers_backward(self, links, fibers, slots, band): + def get_fibers_backward(self, links, slots, band): fiber_list = {} #r_drop = reverse_link(links[0]) #r_add = reverse_link(links[-1]) - for l in fibers.keys(): - fib = self.get_fiber_details(l, fibers[l]) + for l in links: + fib = self.get_link_by_name(l)["optical_details"] ''' link = self.get_link_by_name(l) #port = self.links_dict[l]["fibers"][fibers[l]]["src_port"] for fib in link["optical_link"]["details"]["fibers"]: if fib["ID"] == fibers[l]: ''' - port = fib["src_port"] + s_port = fib["src_port"] + d_port = fib["dst_port"] + + if debug: + print(l, s_port, d_port) + r_l = reverse_link(l) r_link = self.get_link_by_name(r_l) + if debug: + print(r_l) + #for f in r_link["fibers"].keys(): - for r_fib in r_link["optical_link"]["details"]["fibers"]: - if r_fib["remote_peer_port"] == port: - if list_in_list(slots, r_fib[band]): - fiber_list[r_l] = r_fib["ID"] - self.update_link(r_fib, slots, band) + r_fib = r_link["optical_details"] + if r_fib["remote_peer_port"] == s_port and r_fib["local_peer_port"] == d_port: + if list_in_list(slots, str_list_to_int(r_fib[band].keys())): + #fiber_list[r_l] = r_fib["ID"] + self.update_link(r_fib, slots, band) print("INFO: Path backward computation completed") return fiber_list + #function invoked for lightpaths and OB def select_slots_and_ports(self, links, n_slots, c, l, s, bidir): if debug: - print(self.links_dict) + print (links, n_slots, c, l, s, bidir, self.c_slot_number, self.l_slot_number, self.s_slot_number) band, slots = slot_selection(c, l, s, n_slots, self.c_slot_number, self.l_slot_number, self.s_slot_number) + if debug: + print (band, slots) if band is None: print("No slots available in the three bands") - return None, None, None - if debug: - print(band, slots) + #return None, None, None, {}, {} + return None, None, None, {}, {} + + self.get_fibers_forward(links, slots, band) + if bidir: + self.get_fibers_backward(links, slots, band) + ''' fibers_f = self.get_fibers_forward(links, slots, band) fibers_b = [] @@ -385,6 +572,7 @@ class RSA(): print(fibers_f) print("backward") print(fibers_b) + ''' add = links[0] drop = links[-1] inport = "0" @@ -394,18 +582,22 @@ class RSA(): t_flows = {} #if len(links) == 1: - for lx in fibers_f: - if lx == add: + for llx in links: + if llx == add: inport = "0" r_outport = "0" - if lx == drop: + if llx == drop: outport = "0" r_inport = "0" + ''' f = fibers_f[lx] - src, dst = lx.split("-") + fibx = self.get_fiber_details(lx, f) + ''' + src, dst = llx.split("-") #outport = self.links_dict[lx]['fibers'][f]["src_port"] - outport = fibx["src_port"] + lx = self.get_link_by_name(llx)["optical_details"] + outport = lx["src_port"] t_flows[src] = {} t_flows[src]["f"] = {} @@ -414,14 +606,14 @@ class RSA(): if bidir: #r_inport = self.links_dict[lx]['fibers'][f]["local_peer_port"] - r_inport = fibx["local_peer_port"] + r_inport = lx["local_peer_port"] t_flows[src]["b"] = {"in": r_inport, "out": r_outport} #inport = self.links_dict[lx]['fibers'][f]["dst_port"] - inport = fibx["dst_port"] + inport = lx["dst_port"] if bidir: #r_outport = self.links_dict[lx]['fibers'][f]["remote_peer_port"] - r_outport = fibx["remote_peer_port"] + r_outport = lx["remote_peer_port"] t_flows[dst] = {} t_flows[dst]["f"] = {} t_flows[dst]["b"] = {} @@ -436,8 +628,9 @@ class RSA(): print(t_flows) print("INFO: Flow matrix computed") - return t_flows, band, slots, fibers_f, fibers_b + return t_flows, band, slots, {}, {} + #function ivoked for fs lightpaths only def select_slots_and_ports_fs(self, links, n_slots, c, l, s, bidir, o_band_id): if debug: print(self.links_dict) @@ -447,22 +640,20 @@ class RSA(): return None, None, None, None, None if debug: print(band, slots) - fibers_f = self.get_fibers_forward(links, slots, band) - self.update_optical_band(o_band_id, slots, band) - fibers_b = [] + self.get_fibers_forward(links, slots, band) if bidir: - fibers_b = self.get_fibers_backward(links, fibers_f, slots, band) + self.get_fibers_backward(links, slots, band) + + #fibers_f = self.get_fibers_forward(links, slots, band) + self.update_optical_band(o_band_id, slots, band) + #fibers_b = [] + #if bidir: + # fibers_b = self.get_fibers_backward(links, fibers_f, slots, band) ''' rev_o_band_id = self.optical_bands[o_band_id]["reverse_optical_band_id"] self.update_optical_band(rev_o_band_id, slots, band) ''' - if debug: - print("forward") - print(fibers_f) - if bidir: - print("backward") - print(fibers_b) add = links[0] drop = links[-1] port_0 = "0" @@ -470,11 +661,10 @@ class RSA(): t_flows = {} #flows_add_side - f = fibers_f[add] src, dst = add.split("-") - fibx = self.get_fiber_details(add, f) + lx = self.get_link_by_name(add)["optical_details"] #outport = self.links_dict[add]['fibers'][f]["src_port"] - outport = fibx["src_port"] + outport = lx["src_port"] #T1 rules t_flows[src] = {} t_flows[src]["f"] = {} @@ -482,7 +672,7 @@ class RSA(): t_flows[src]["f"] = {"in": port_0, "out": outport} if bidir: #r_inport = self.links_dict[add]['fibers'][f]["local_peer_port"] - r_inport = fibx["local_peer_port"] + r_inport = lx["local_peer_port"] t_flows[src]["b"] = {"in": r_inport, "out": port_0} #R1 rules @@ -490,27 +680,26 @@ class RSA(): t_flows[dst]["f"] = {} t_flows[dst]["b"] = {} #inport = self.links_dict[add]['fibers'][f]["dst_port"] - inport = fibx["dst_port"] + inport = lx["dst_port"] opt_band_src_port = self.optical_bands[o_band_id]["src_port"] t_flows[dst]["f"] = {"in": inport, "out": opt_band_src_port} #to modify to peer ports if bidir: #r_inport = self.links_dict[add]['fibers'][f]["local_peer_port"] - r_inport = fibx["local_peer_port"] + r_inport = lx["local_peer_port"] t_flows[src]["b"] = {"in": r_inport, "out": port_0} if bidir: rev_opt_band_dst_port = self.optical_bands[o_band_id]["rev_dst_port"] #r_outport = self.links_dict[add]['fibers'][f]["remote_peer_port"] - r_outport = fibx["remote_peer_port"] + r_outport = lx["remote_peer_port"] t_flows[dst]["b"] = {"in": rev_opt_band_dst_port, "out": r_outport} #flows_drop_side # R2 rules - f = fibers_f[drop] + ly = self.get_link_by_name(drop)["optical_details"] src, dst = drop.split("-") - fiby = self.get_fiber_details(drop, f) #outport = self.links_dict[drop]['fibers'][f]["src_port"] - outport = fiby["src_port"] + outport = ly["src_port"] t_flows[src] = {} t_flows[src]["f"] = {} @@ -520,17 +709,17 @@ class RSA(): if bidir: rev_opt_band_src_port = self.optical_bands[o_band_id]["rev_src_port"] #r_inport = self.links_dict[drop]['fibers'][f]["local_peer_port"] - r_inport = fiby["local_peer_port"] + r_inport = ly["local_peer_port"] t_flows[src]["b"] = {"in": r_inport, "out": rev_opt_band_src_port} t_flows[dst] = {} t_flows[dst]["f"] = {} t_flows[dst]["b"] = {} #inport = self.links_dict[drop]['fibers'][f]["dst_port"] - inport = fiby["dst_port"] + inport = ly["dst_port"] t_flows[dst]["f"] = {"in": inport, "out": port_0} if bidir: #r_inport = self.links_dict[drop]['fibers'][f]["remote_peer_port"] - r_inport = fiby["remote_peer_port"] + r_inport = ly["remote_peer_port"] t_flows[dst]["b"] = {"in": port_0, "out": r_inport} if debug: @@ -540,7 +729,7 @@ class RSA(): print(t_flows) print("INFO: Flow matrix computed for Flex Lightpath") - return t_flows, band, slots, fibers_f, fibers_b + return t_flows, band, slots, {}, {} def rsa_computation(self, src, dst, rate, bidir): self.flow_id += 1 @@ -565,7 +754,7 @@ class RSA(): if len(c_slots) > 0 or len(l_slots) > 0 or len(s_slots) > 0: flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports(links, num_slots, c_slots, l_slots, s_slots, bidir) - f0, band = freqency_converter(band_range, slots) + f0, band = frequency_converter(band_range, slots) if debug: print(f0, band) print("INFO: RSA completed for normal wavelenght connection") @@ -675,50 +864,43 @@ class RSA(): print(s_slots) if len(c_slots) > 0 or len(l_slots) > 0 or len(s_slots) > 0: flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports(links, num_slots, c_slots, l_slots, s_slots, bidir) - f0, band = freqency_converter(band_range, slots) - print(flow_list, band_range, slots, fiber_f, fiber_b) - ''' - - flow_list_b = {} - rev_path = path.copy() - rev_path.reverse() - rev_links = reverse_links(links) - if bidir: - for dev_x in flow_list.keys(): - flow_list_b[dev_x] = {} - flow_list_b[dev_x]["f"] = flow_list[dev_x]["b"] - del flow_list[dev_x]["b"] - rev_path = path.copy() - ''' + if debug: + print(flow_list, band_range, slots, fiber_f, fiber_b) + f0, band = frequency_converter(band_range, slots) if debug: print(f0, band) print("INFO: RSA completed for optical band") if flow_list is None: self.null_values(self.flow_id) return self.flow_id, [] - slots_i = [] + #slots_i = [] + #for i in slots: + # slots_i.append(int(i)) + slots_i = {} for i in slots: - slots_i.append(int(i)) + slots_i[str(i)] = 1 # return links, path, flow_list, band_range, slots, fiber_f, fiber_b, op, num_slots, f0, band # links, path, flows, bx, slots, fiber_f, fiber_b, op, n_slots, f0, band + if debug: + print(links) if len(flow_list) > 0: src_port = flow_list[path[0]]['f']['out'] dst_port = flow_list[path[-1]]['f']['in'] - print(flow_list) - if len(fiber_f.keys()) == 1: - link_x = list(fiber_f.keys())[0] + if debug: + print(flow_list) + if len(links) == 1: #fib_x = fiber_f[link_x] #rev_dst_port = self.links_dict[link_x]['fibers'][fib_x]["local_peer_port"] #rev_src_port = self.links_dict[link_x]['fibers'][fib_x]["remote_peer_port"] - fibx = self.get_fiber_details(link_x, fiber_f[link_x]) + fibx = self.get_link_by_name(links[0])["optical_details"] rev_dst_port = fibx["local_peer_port"] rev_src_port = fibx["remote_peer_port"] else: - link_in = list(fiber_f.keys())[0] - link_out = list(fiber_f.keys())[-1] - fib_inx = self.get_fiber_details(link_in, fiber_f[link_in]) - fib_outx = self.get_fiber_details(link_out, fiber_f[link_out]) + link_in = links[0] + link_out = links[-1] + fib_inx = self.get_link_by_name(link_in)["optical_details"] + fib_outx = self.get_link_by_name(link_out)["optical_details"] rev_dst_port = fib_inx["local_peer_port"] rev_src_port = fib_outx["remote_peer_port"] @@ -790,6 +972,7 @@ class RSA(): return self.flow_id, [] optical_band_id, temp_links = self.create_optical_band(links, path, bidir, num_slots_ob) return None, optical_band_id + print("INFO: TP to TP connection") self.flow_id += 1 self.db_flows[self.flow_id] = {} self.db_flows[self.flow_id]["flow_id"] = self.flow_id @@ -797,7 +980,7 @@ class RSA(): self.db_flows[self.flow_id]["dst"] = dst self.db_flows[self.flow_id]["bitrate"] = rate self.db_flows[self.flow_id]["bidir"] = bidir - print("INFO: TP to TP connection") + if band is None: temp_links2 = [] temp_path = [] @@ -816,13 +999,16 @@ class RSA(): temp_path.append(roadm_dst) temp_path.append(t_dst) existing_ob = self.get_optical_bands(roadm_src, roadm_dst) - if len(existing_ob) > 0: print("INFO: Evaluating existing OB {}".format(existing_ob)) #first checking in existing OB ob_found = 0 for ob_id in existing_ob: + if "is_active" in self.optical_bands[ob_id].keys(): + is_active = self.optical_bands[ob_id]["is_active"] + if not is_active: + continue op, num_slots = map_rate_to_slot(rate) if debug: print(temp_links2) @@ -836,7 +1022,7 @@ class RSA(): c_slots, l_slots, s_slots, bidir, ob_id) - f0, band = freqency_converter(band_range, slots) + f0, band = frequency_converter(band_range, slots) if debug: print(f0, band) print("INFO: RSA completed for Flex Lightpath with OB already in place") @@ -871,6 +1057,75 @@ class RSA(): return self.flow_id, ob_id else: print("not enough slots") + print("trying to extend OB {}".format(ob_id)) + new_slots = self.extend_optical_band(ob_id, band=None) + + if len(new_slots) > 0: + band_type = self.optical_bands[ob_id]["band_type"] + c_slots = [] + l_slots = [] + s_slots = [] + if band_type == "c_slots": + c_slots = new_slots + elif band_type == "l_slots": + l_slots = new_slots + else: + s_slots = new_slots + op, num_slots = map_rate_to_slot(rate) + if debug: + print(temp_links2) + c_slots, l_slots, s_slots = self.get_slots(temp_links2, num_slots, ob_id) + if debug: + print(c_slots) + print(l_slots) + print(s_slots) + #print(c_slots) + #print(l_slots) + #print(s_slots) + if len(c_slots) >= num_slots or len(l_slots) >= num_slots or len(s_slots) >= num_slots: + flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports_fs( + temp_links2, num_slots, + c_slots, + l_slots, s_slots, bidir, + ob_id) + f0, band = frequency_converter(band_range, slots) + if debug: + print(f0, band) + print("INFO: RSA completed for Flex Lightpath with OB already in place") + if flow_list is None: + self.null_values(self.flow_id) + continue + slots_i = [] + for i in slots: + slots_i.append(int(i)) + # return links, path, flow_list, band_range, slots, fiber_f, fiber_b, op, num_slots, f0, band + # links, path, flows, bx, slots, fiber_f, fiber_b, op, n_slots, f0, band + self.db_flows[self.flow_id]["flows"] = flow_list + self.db_flows[self.flow_id]["band_type"] = band_range + self.db_flows[self.flow_id]["slots"] = slots_i + self.db_flows[self.flow_id]["fiber_forward"] = fiber_f + self.db_flows[self.flow_id]["fiber_backward"] = fiber_b + self.db_flows[self.flow_id]["op-mode"] = op + self.db_flows[self.flow_id]["n_slots"] = num_slots + self.db_flows[self.flow_id]["links"] = temp_links2 + self.db_flows[self.flow_id]["path"] = temp_path + self.db_flows[self.flow_id]["band"] = band + self.db_flows[self.flow_id]["freq"] = f0 + self.db_flows[self.flow_id]["is_active"] = True + self.db_flows[self.flow_id]["parent_opt_band"] = ob_id + self.db_flows[self.flow_id]["new_optical_band"] = 1 + #self.db_flows[self.flow_id]["new_optical_band"] = 2 + self.optical_bands[ob_id]["served_lightpaths"].append(self.flow_id) + ''' + if bidir: + rev_ob_id = self.optical_bands[ob_id]["reverse_optical_band_id"] + self.optical_bands[rev_ob_id]["served_lightpaths"].append(self.flow_id) + ''' + return self.flow_id, ob_id + else: + print("it is not possible to allocate connection in extended OB {}".format(ob_id)) + + if band is None: print("INFO: Not existing optical-band meeting the requirements") else: @@ -879,14 +1134,6 @@ class RSA(): links, path = self.compute_path(src, dst) optical_band_id, temp_links = self.create_optical_band(links, path, bidir, num_slots_ob) op, num_slots = map_rate_to_slot(rate) - # self.flow_id += 1 - # self.db_flows[self.flow_id] = {} - # self.db_flows[self.flow_id]["flow_id"] = self.flow_id - # self.db_flows[self.flow_id]["src"] = src - # self.db_flows[self.flow_id]["dst"] = dst - # self.db_flows[self.flow_id]["bitrate"] = rate - # self.db_flows[self.flow_id]["bidir"] = bidir - if debug: print(temp_links) c_slots, l_slots, s_slots = self.get_slots(temp_links, num_slots, optical_band_id) @@ -897,7 +1144,7 @@ class RSA(): if len(c_slots) > 0 or len(l_slots) > 0 or len(s_slots) > 0: flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports_fs(temp_links, num_slots, c_slots, l_slots, s_slots, bidir, optical_band_id) - f0, band = freqency_converter(band_range, slots) + f0, band = frequency_converter(band_range, slots) if debug: print(f0, band) print("INFO: RSA completed for FLex Lightpath with new OB") @@ -929,3 +1176,41 @@ class RSA(): self.optical_bands[rev_ob_id]["served_lightpaths"].append(self.flow_id) ''' return self.flow_id, optical_band_id + + def extend_optical_band(self, ob_id, band=None): + ob = self.optical_bands[ob_id] + links = ob["links"] + old_band = ob["band"] + band_type = ob["band_type"] + f0 = ob["freq"] + slots = ob[band_type] + if band is None: + num_slots_ob = map_band_to_slot(old_band/1000.0) + else: + num_slots_ob = map_band_to_slot(band) + new_slots = [] + for l in links: + link = self.get_link_by_name(l) + fib = link["optical_details"][band_type] + #s_slots = get_side_slots_on_link(link, band_type, num_slots_ob, slots) + s_slots, s_num = get_side_slots_on_link(fib, num_slots_ob, slots) + print("NEW SLOTS {}".format(s_slots)) + if len(new_slots) == 0: + new_slots = s_slots + else: + if len(new_slots) < s_num: + new_slots = list_in_list(new_slots, s_slots) + print("NEW SLOTS {}".format(new_slots)) + self.augment_optical_band(ob_id, new_slots, band_type) + new_band = int(len(new_slots)*12.5*1000) + print("{}, {},{},{} ".format(old_band, f0, len(new_slots), new_band)) + final_band = old_band + new_band + final_f0 = int(f0 + new_band/2) + print("{}, {}".format(final_band, final_f0)) + ob["band"] = final_band + ob["freq"] = final_f0 + for link_x in links: + link = self.get_link_by_name(link_x) + fib = link["optical_details"] + self.update_link(fib, new_slots, band_type) + return new_slots diff --git a/src/opticalcontroller/__init__.py b/src/opticalcontroller/__init__.py index bbfc943b68af13a11e562abbc8680ade71db8f02..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/opticalcontroller/__init__.py +++ b/src/opticalcontroller/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -11,3 +11,4 @@ # 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/opticalcontroller/dijsktra.py b/src/opticalcontroller/dijkstra.py similarity index 98% rename from src/opticalcontroller/dijsktra.py rename to src/opticalcontroller/dijkstra.py index 058d59e75cbc09c1b18ab4b406f08186e106609d..2657990cf7f111c25c08ded4e12d7eaf81fd5e12 100644 --- a/src/opticalcontroller/dijsktra.py +++ b/src/opticalcontroller/dijkstra.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/opticalcontroller/json_files/nodes.json b/src/opticalcontroller/json_files/nodes.json deleted file mode 100644 index 60f017c19d7c7a578c0ddfc2225cab742deb0026..0000000000000000000000000000000000000000 --- a/src/opticalcontroller/json_files/nodes.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "R1":{ - "id":0, - "ip":"10.30.2.207", - "port":"50001", - "type":"OC-ROADM", - "driver": "OpticalOC" - }, - - "R2":{ - "id":1, - "ip":"10.30.2.208", - "port":"50001", - "type":"OC-ROADM", - "driver": "OpticalOC" - }, - - "R3":{ - "id":2, - "ip":"10.30.2.209", - "port":"50001", - "type":"OC-ROADM", - "driver": "OpticalOC" - }, - "T1":{ - "id":3, - "ip":"10.30.2.210", - "port":"50001", - "type":"OC-TP", - "driver": "OpticalOC" - }, - "T2":{ - "id":4, - "ip":"10.30.2.211", - "port":"50001", - "type":"OC-TP", - "driver": "OpticalOC" - } -} diff --git a/src/opticalcontroller/json_files/optical_TFSworking.json b/src/opticalcontroller/json_files/optical_TFSworking.json deleted file mode 100644 index ff1841eeea9df1e73bcfb25d07f19d64554f11e1..0000000000000000000000000000000000000000 --- a/src/opticalcontroller/json_files/optical_TFSworking.json +++ /dev/null @@ -1,486 +0,0 @@ -{ - "R1-R2": { - "length": 80, - "source": "d1", - "target": "d1", - "fibers": { - "d1-1": { - "length": 80, - "src_port": "3", - "dst_port": "14", - "local_peer_port": "13", - "remote_peer_port": "4", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R2-R1": { - "length": 80, - "source": "d1", - "target": "d1", - "fibers": { - "d1-1": { - "length": 80, - "src_port": "4", - "dst_port": "13", - "local_peer_port": "14", - "remote_peer_port": "3", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "T1-R1": { - "length": 0, - "source": "muxT", - "target": "srgR", - "fibers": { - "M1": { - "length": 0, - "src_port": "1", - "dst_port": "12", - "local_peer_port": "1", - "remote_peer_port": "2", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R1-T1": { - "length": 0, - "source": "srgT", - "target": "muxR", - "fibers": { - "S1": { - "length": 0, - "src_port": "2", - "dst_port": "1", - "local_peer_port": "12", - "remote_peer_port": "1", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "T2-R2": { - "length": 0, - "source": "muxT", - "target": "srgR", - "fibers": { - "M1": { - "length": 0, - "src_port": "6", - "dst_port": "15", - "local_peer_port": "6", - "remote_peer_port": "5", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R2-T2": { - "length": 0, - "source": "srgT", - "target": "muxR", - "fibers": { - "S1": { - "length": 0, - "src_port": "5", - "dst_port": "6", - "local_peer_port": "15", - "remote_peer_port": "6", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - } -} diff --git a/src/opticalcontroller/json_files/optical_topoTFS.json b/src/opticalcontroller/json_files/optical_topoTFS.json deleted file mode 100644 index 7dea474cd676b7c699cffc1c180e14598b987473..0000000000000000000000000000000000000000 --- a/src/opticalcontroller/json_files/optical_topoTFS.json +++ /dev/null @@ -1,1836 +0,0 @@ -{ - "R1-R2": { - "length": 80, - "source": "d1", - "target": "d1", - "fibers": { - "d1-1": { - "length": 80, - "src_port": "101", - "dst_port": "201", - "local_peer_port": "201", - "remote_peer_port": "101", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "d1-2": { - "length": 80, - "src_port": "102", - "dst_port": "202", - "local_peer_port": "202", - "remote_peer_port": "102", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R2-R1": { - "length": 80, - "source": "d1", - "target": "d1", - "fibers": { - "d1-1": { - "length": 80, - "src_port": "101", - "dst_port": "201", - "local_peer_port": "201", - "remote_peer_port": "101", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "d1-2": { - "length": 80, - "src_port": "102", - "dst_port": "202", - "local_peer_port": "202", - "remote_peer_port": "102", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R1-R3": { - "length": 80, - "source": "d2", - "target": "d1", - "fibers": { - "d2-1": { - "length": 80, - "src_port": "103", - "dst_port": "201", - "local_peer_port": "203", - "remote_peer_port": "101", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "d2-2": { - "length": 80, - "src_port": "104", - "dst_port": "202", - "local_peer_port": "204", - "remote_peer_port": "102", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R3-R1": { - "length": 80, - "source": "d1", - "target": "d2", - "fibers": { - "d1-1": { - "length": 80, - "src_port": "101", - "dst_port": "203", - "local_peer_port": "201", - "remote_peer_port": "103", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "d1-2": { - "length": 80, - "src_port": "102", - "dst_port": "204", - "local_peer_port": "202", - "remote_peer_port": "104", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R2-R3": { - "length": 80, - "source": "d2", - "target": "d2", - "fibers": { - "d2-1": { - "length": 80, - "src_port": "103", - "dst_port": "203", - "local_peer_port": "203", - "remote_peer_port": "103", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "d2-2": { - "length": 80, - "src_port": "104", - "dst_port": "204", - "local_peer_port": "204", - "remote_peer_port": "104", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R3-R2": { - "length": 80, - "source": "d2", - "target": "d2", - "fibers": { - "d2-1": { - "length": 80, - "src_port": "103", - "dst_port": "203", - "local_peer_port": "203", - "remote_peer_port": "103", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "d2-2": { - "length": 80, - "src_port": "104", - "dst_port": "204", - "local_peer_port": "204", - "remote_peer_port": "104", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "T1-R1": { - "length": 0, - "source": "muxT", - "target": "srgR", - "fibers": { - "M1": { - "length": 0, - "src_port": "1", - "dst_port": "2001", - "local_peer_port": "1", - "remote_peer_port": "1001", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "M2": { - "length": 0, - "src_port": "2", - "dst_port": "2002", - "local_peer_port": "2", - "remote_peer_port": "1002", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "M3": { - "length": 0, - "src_port": "3", - "dst_port": "2003", - "local_peer_port": "3", - "remote_peer_port": "1003", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R1-T1": { - "length": 0, - "source": "srgT", - "target": "muxR", - "fibers": { - "S1": { - "length": 0, - "src_port": "1001", - "dst_port": "1", - "local_peer_port": "2001", - "remote_peer_port": "1", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "S2": { - "length": 0, - "src_port": "1002", - "dst_port": "2", - "local_peer_port": "2002", - "remote_peer_port": "2", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "S3": { - "length": 0, - "src_port": "1003", - "dst_port": "3", - "local_peer_port": "2003", - "remote_peer_port": "3", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "T2-R2": { - "length": 0, - "source": "muxT", - "target": "srgR", - "fibers": { - "M1": { - "length": 0, - "src_port": "1", - "dst_port": "2001", - "local_peer_port": "1", - "remote_peer_port": "1001", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "M2": { - "length": 0, - "src_port": "2", - "dst_port": "2002", - "local_peer_port": "2", - "remote_peer_port": "1002", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "M3": { - "length": 0, - "src_port": "3", - "dst_port": "2003", - "local_peer_port": "3", - "remote_peer_port": "1003", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R2-T2": { - "length": 0, - "source": "srgT", - "target": "muxR", - "fibers": { - "S1": { - "length": 0, - "src_port": "1001", - "dst_port": "1", - "local_peer_port": "2001", - "remote_peer_port": "1", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "S2": { - "length": 0, - "src_port": "1002", - "dst_port": "2", - "local_peer_port": "2002", - "remote_peer_port": "2", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "S3": { - "length": 0, - "src_port": "1003", - "dst_port": "3", - "local_peer_port": "2003", - "remote_peer_port": "3", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - } -} diff --git a/src/opticalcontroller/json_files/tfs.json b/src/opticalcontroller/json_files/tfs.json deleted file mode 100644 index 31803b893b5639e957be33465599573baa475ca2..0000000000000000000000000000000000000000 --- a/src/opticalcontroller/json_files/tfs.json +++ /dev/null @@ -1,686 +0,0 @@ -{ - "links": [ - { - "link_id": { - "link_uuid": { - "uuid": "T1->R1" - } - }, - "link_endpoint_ids": [ - { - "device_id": { - "device_uuid": { - "uuid": "T1" - } - }, - "endpoint_uuid": { - "uuid": "1" - } - }, - { - "device_id": { - "device_uuid": { - "uuid": "R1" - } - }, - "endpoint_uuid": { - "uuid": "12" - } - } - ], - "optical_link": { - "name": "T1-R1", - "details": { - "length": 0, - "source": "muxT", - "target": "srgR", - "fibers": [ - { - "ID": "M1", - "length": 0, - "src_port": "1", - "dst_port": "12", - "local_peer_port": "1", - "remote_peer_port": "2", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - ] - } - } - }, - { - "link_id": { - "link_uuid": { - "uuid": "R1->T1" - } - }, - "link_endpoint_ids": [ - { - "device_id": { - "device_uuid": { - "uuid": "R1" - } - }, - "endpoint_uuid": { - "uuid": "2" - } - }, - { - "device_id": { - "device_uuid": { - "uuid": "T1" - } - }, - "endpoint_uuid": { - "uuid": "1" - } - } - ], - "optical_link": { - "name": "R1-T1", - "details": { - "length": 0, - "source": "srgT", - "target": "muxT", - "fibers": [ - { - "ID": "M1", - "length": 0, - "src_port": "2", - "dst_port": "1", - "local_peer_port": "12", - "remote_peer_port": "1", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - ] - } - } - }, - { - "link_id": { - "link_uuid": { - "uuid": "R1->R2" - } - }, - "link_endpoint_ids": [ - { - "device_id": { - "device_uuid": { - "uuid": "R1" - } - }, - "endpoint_uuid": { - "uuid": "3" - } - }, - { - "device_id": { - "device_uuid": { - "uuid": "R2" - } - }, - "endpoint_uuid": { - "uuid": "14" - } - } - ], - "optical_link": { - "name": "R1-R2", - "details": { - "length": 0, - "source": "D1", - "target": "D1", - "fibers": [ - { - "ID": "D11", - "length": 0, - "src_port": "3", - "dst_port": "14", - "local_peer_port": "13", - "remote_peer_port": "4", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - ] - } - } - }, - { - "link_id": { - "link_uuid": { - "uuid": "R2->R1" - } - }, - "link_endpoint_ids": [ - { - "device_id": { - "device_uuid": { - "uuid": "R2" - } - }, - "endpoint_uuid": { - "uuid": "4" - } - }, - { - "device_id": { - "device_uuid": { - "uuid": "R1" - } - }, - "endpoint_uuid": { - "uuid": "13" - } - } - ], - "optical_link": { - "name": "R2-R1", - "details": { - "length": 0, - "source": "D1", - "target": "D1", - "fibers": [ - { - "ID": "D11", - "length": 0, - "src_port": "4", - "dst_port": "13", - "local_peer_port": "14", - "remote_peer_port": "3", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - ] - } - } - }, - { - "link_id": { - "link_uuid": { - "uuid": "T2->R2" - } - }, - "link_endpoint_ids": [ - { - "device_id": { - "device_uuid": { - "uuid": "T2" - } - }, - "endpoint_uuid": { - "uuid": "6" - } - }, - { - "device_id": { - "device_uuid": { - "uuid": "R2" - } - }, - "endpoint_uuid": { - "uuid": "15" - } - } - ], - "optical_link": { - "name": "T2-R2", - "details": { - "length": 0, - "source": "srgT", - "target": "muxT", - "fibers": [ - { - "ID": "M1", - "length": 0, - "src_port": "6", - "dst_port": "15", - "local_peer_port": "6", - "remote_peer_port": "5", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - ] - } - } - }, - { - "link_id": { - "link_uuid": { - "uuid": "R2->T2" - } - }, - "link_endpoint_ids": [ - { - "device_id": { - "device_uuid": { - "uuid": "R2" - } - }, - "endpoint_uuid": { - "uuid": "5" - } - }, - { - "device_id": { - "device_uuid": { - "uuid": "T2" - } - }, - "endpoint_uuid": { - "uuid": "6" - } - } - ], - "optical_link": { - "name": "R2-T2", - "details": { - "length": 0, - "source": "srgT", - "target": "muxT", - "fibers": [ - { - "ID": "M1", - "length": 0, - "src_port": "5", - "dst_port": "6", - "local_peer_port": "15", - "remote_peer_port": "6", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - ] - } - } - } - ] -} \ No newline at end of file diff --git a/src/opticalcontroller/json_files/topo_2_links.json b/src/opticalcontroller/json_files/topo_2_links.json deleted file mode 100644 index 02165938ce675071a4ff4c3424e3b53244d40810..0000000000000000000000000000000000000000 --- a/src/opticalcontroller/json_files/topo_2_links.json +++ /dev/null @@ -1,1530 +0,0 @@ -{ - "R1-R3": { - "length": 80, - "source": "d2", - "target": "d1", - "fibers": { - "d2-1": { - "length": 80, - "src_port": "103", - "dst_port": "201", - "local_peer_port": "203", - "remote_peer_port": "101", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "d2-2": { - "length": 80, - "src_port": "104", - "dst_port": "202", - "local_peer_port": "204", - "remote_peer_port": "102", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R3-R1": { - "length": 80, - "source": "d1", - "target": "d2", - "fibers": { - "d1-1": { - "length": 80, - "src_port": "101", - "dst_port": "203", - "local_peer_port": "201", - "remote_peer_port": "103", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "d1-2": { - "length": 80, - "src_port": "102", - "dst_port": "204", - "local_peer_port": "202", - "remote_peer_port": "104", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R2-R3": { - "length": 80, - "source": "d2", - "target": "d2", - "fibers": { - "d2-1": { - "length": 80, - "src_port": "103", - "dst_port": "203", - "local_peer_port": "203", - "remote_peer_port": "103", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "d2-2": { - "length": 80, - "src_port": "104", - "dst_port": "204", - "local_peer_port": "204", - "remote_peer_port": "104", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R3-R2": { - "length": 80, - "source": "d2", - "target": "d2", - "fibers": { - "d2-1": { - "length": 80, - "src_port": "103", - "dst_port": "203", - "local_peer_port": "203", - "remote_peer_port": "103", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "d2-2": { - "length": 80, - "src_port": "104", - "dst_port": "204", - "local_peer_port": "204", - "remote_peer_port": "104", - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "T1-R1": { - "length": 0, - "source": "muxT", - "target": "srgR", - "fibers": { - "M1": { - "length": 0, - "src_port": "1", - "dst_port": "2001", - "local_peer_port": "1", - "remote_peer_port": "1001", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "M2": { - "length": 0, - "src_port": "2", - "dst_port": "2002", - "local_peer_port": "2", - "remote_peer_port": "1002", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "M3": { - "length": 0, - "src_port": "3", - "dst_port": "2003", - "local_peer_port": "3", - "remote_peer_port": "1003", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R1-T1": { - "length": 0, - "source": "srgT", - "target": "muxR", - "fibers": { - "S1": { - "length": 0, - "src_port": "1001", - "dst_port": "1", - "local_peer_port": "2001", - "remote_peer_port": "1", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "S2": { - "length": 0, - "src_port": "1002", - "dst_port": "2", - "local_peer_port": "2002", - "remote_peer_port": "2", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "S3": { - "length": 0, - "src_port": "1003", - "dst_port": "3", - "local_peer_port": "2003", - "remote_peer_port": "3", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "T2-R2": { - "length": 0, - "source": "muxT", - "target": "srgR", - "fibers": { - "M1": { - "length": 0, - "src_port": "1", - "dst_port": "2001", - "local_peer_port": "1", - "remote_peer_port": "1001", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "M2": { - "length": 0, - "src_port": "2", - "dst_port": "2002", - "local_peer_port": "2", - "remote_peer_port": "1002", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "M3": { - "length": 0, - "src_port": "3", - "dst_port": "2003", - "local_peer_port": "3", - "remote_peer_port": "1003", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - }, - "R2-T2": { - "length": 0, - "source": "srgT", - "target": "muxR", - "fibers": { - "S1": { - "length": 0, - "src_port": "1001", - "dst_port": "1", - "local_peer_port": "2001", - "remote_peer_port": "1", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "S2": { - "length": 0, - "src_port": "1002", - "dst_port": "2", - "local_peer_port": "2002", - "remote_peer_port": "2", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - }, - "S3": { - "length": 0, - "src_port": "1003", - "dst_port": "3", - "local_peer_port": "2003", - "remote_peer_port": "3", - "used": false, - "c_slots": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20 - ], - "l_slots": [ - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120 - ], - "s_slots": [ - 501, - 502, - 503, - 504, - 505, - 506, - 507, - 508, - 509, - 510, - 511, - 512, - 513, - 514, - 515, - 516, - 517, - 518, - 519, - 520 - ] - } - } - } -} diff --git a/src/opticalcontroller/json_files/topology-optical.json b/src/opticalcontroller/json_files/topology-optical.json deleted file mode 100644 index e2453b654d53fc3200570ce9c2b17effc964bd25..0000000000000000000000000000000000000000 --- a/src/opticalcontroller/json_files/topology-optical.json +++ /dev/null @@ -1,252 +0,0 @@ -{ - "r1-r2": { - "length": 80, - "source" : "d1", - "target" : "d1", - "fibers" : { - "d1-1": { - "src_port": "1T", - "dst_port": "1R", - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - }, - "d1-2":{ - "src_port": "2T", - "dst_port": "2R", - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - } - } - }, - "r2-r1": { - "length": 80, - "source" : "d1", - "target" : "d1", - "fibers" : { - "d1-1" : { - "src_port": "1T", - "dst_port": "1R", - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - }, - "d1-2" : { - "src_port": "2T", - "dst_port": "2R", - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - } - } - }, - "r1-r3": { - "length": 80, - "source" : "d2", - "target" : "d1", - "fibers" : { - "d2-1":{ - "src_port": "3T", - "dst_port": "1R", - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - }, - "d2-2":{ - "src_port": "4T", - "dst_port": "2R", - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - } - } - }, - "r3-r1": { - "length": 80, - "source" : "d1", - "target" : "d2", - "fibers" : { - "d1-1": { - "src_port": "1T", - "dst_port": "3R", - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - }, - "d1-2": { - "src_port": "2T", - "dst_port": "4R", - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - } - } - }, - "r2-r3": { - "length": 80, - "source" : "d2", - "target" : "d2", - "fibers" : { - "d2-1": { - "src_port": "3T", - "dst_port": "3R", - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - }, - "d2-2": { - "src_port": "4T", - "dst_port": "4R", - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - } - } - }, - "r3-r2": { - "length": 80, - "source" : "d2", - "target" : "d2", - "fibers" : { - "d2-1": { - "src_port": "3T", - "dst_port": "3R", - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - }, - "d2-2":{ - "src_port": "4T", - "dst_port": "4R", - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - } - } - }, - "t1-r1": { - "length": 0, - "source" : "muxT", - "target" : "srgR", - "fibers" : { - "M1": { - "src_port": "1", - "dst_port": "101R", - "used": false, - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - }, - "M2": { - "src_port": "2", - "dst_port": "102R", - "used": false, - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - }, - "M3": { - "src_port": "3", - "dst_port": "103R", - "used": false, - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - } - } - }, - "r1-t1": { - "length": 0, - "source" : "srgT", - "target" : "muxR", - "fibers" : { - "S1": { - "src_port": "101T", - "dst_port": "1", - "used": false, - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - }, - "S2": { - "src_port": "102T", - "dst_port": "2", - "used": false, - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - }, - "S3": { - "src_port": "103T", - "dst_port": "3", - "used": false, - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - } - } - }, - "t2-r2": { - "length": 0, - "source" : "muxT", - "target" : "srgR", - "fibers" : { - "M1": { - "src_port": "1", - "dst_port": "101R", - "used": false, - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - }, - "M2": { - "src_port": "2", - "dst_port": "102R", - "used": false, - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - }, - "M3": { - "src_port": "3", - "dst_port": "103R", - "used": false, - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - } - } - }, - "r2-t2": { - "length": 0, - "source" : "srgT", - "target" : "muxR", - "fibers" : { - "S1": { - "src_port": "101T", - "dst_port": "1", - "used": false, - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - }, - "S2": { - "src_port": "102T", - "dst_port": "2", - "used": false, - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - }, - "S3": { - "src_port": "103T", - "dst_port": "3", - "used": false, - "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, - "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, - "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} - } - } - } -} diff --git a/src/opticalcontroller/json_files/topology-optical2.json b/src/opticalcontroller/json_files/topology-optical2.json deleted file mode 100644 index fe8e9866bcc64d52b2f49089ce03af47d72df9d0..0000000000000000000000000000000000000000 --- a/src/opticalcontroller/json_files/topology-optical2.json +++ /dev/null @@ -1,324 +0,0 @@ -{ - "r1-r2": { - "length": 80, - "source" : "d1", - "target" : "d1", - "fibers" : { - "d1-1": { - "length": 80, - "src_port": "1T", - "dst_port": "1R", - "local_peer_port": "1R", - "remote_peer_port": "1T", - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - }, - "d1-2":{ - "length": 80, - "src_port": "2T", - "dst_port": "2R", - "local_peer_port": "2R", - "remote_peer_port": "2T", - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - } - } - }, - "r2-r1": { - "length": 80, - "source" : "d1", - "target" : "d1", - "fibers" : { - "d1-1" : { - "length": 80, - "src_port": "1T", - "dst_port": "1R", - "local_peer_port": "1R", - "remote_peer_port": "1T", - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - }, - "d1-2" : { - "length": 80, - "src_port": "2T", - "dst_port": "2R", - "local_peer_port": "2R", - "remote_peer_port": "2T", - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - } - } - }, - "r1-r3": { - "length": 80, - "source" : "d2", - "target" : "d1", - "fibers" : { - "d2-1":{ - "length": 80, - "src_port": "3T", - "dst_port": "1R", - "local_peer_port": "3R", - "remote_peer_port": "1T", - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - }, - "d2-2":{ - "length": 80, - "src_port": "4T", - "dst_port": "2R", - "local_peer_port": "4R", - "remote_peer_port": "2T", - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - } - } - }, - "r3-r1": { - "length": 80, - "source" : "d1", - "target" : "d2", - "fibers" : { - "d1-1": { - "length": 80, - "src_port": "1T", - "dst_port": "3R", - "local_peer_port": "1R", - "remote_peer_port": "3T", - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - }, - "d1-2": { - "length": 80, - "src_port": "2T", - "dst_port": "4R", - "local_peer_port": "2R", - "remote_peer_port": "4T", - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - } - } - }, - "r2-r3": { - "length": 80, - "source" : "d2", - "target" : "d2", - "fibers" : { - "d2-1": { - "length": 80, - "src_port": "3T", - "dst_port": "3R", - "local_peer_port": "3R", - "remote_peer_port": "3T", - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - }, - "d2-2": { - "length": 80, - "src_port": "4T", - "dst_port": "4R", - "local_peer_port": "4R", - "remote_peer_port": "4T", - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - } - } - }, - "r3-r2": { - "length": 80, - "source" : "d2", - "target" : "d2", - "fibers" : { - "d2-1": { - "length": 80, - "src_port": "3T", - "dst_port": "3R", - "local_peer_port": "3R", - "remote_peer_port": "3T", - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - }, - "d2-2":{ - "length": 80, - "src_port": "4T", - "dst_port": "4R", - "local_peer_port": "4R", - "remote_peer_port": "4T", - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - } - } - }, - "t1-r1": { - "length": 0, - "source" : "muxT", - "target" : "srgR", - "fibers" : { - "M1": { - "length": 0, - "src_port": "1", - "dst_port": "101R", - "local_peer_port": "1", - "remote_peer_port": "101T", - "used": false, - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - }, - "M2": { - "length": 0, - "src_port": "2", - "dst_port": "102R", - "local_peer_port": "2", - "remote_peer_port": "102T", - "used": false, - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - }, - "M3": { - "length": 0, - "src_port": "3", - "dst_port": "103R", - "local_peer_port": "3", - "remote_peer_port": "103T", - "used": false, - "c_slots": [], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - } - } - }, - "r1-t1": { - "length": 0, - "source" : "srgT", - "target" : "muxR", - "fibers" : { - "S1": { - "length": 0, - "src_port": "101T", - "dst_port": "1", - "local_peer_port": "101R", - "remote_peer_port": "1", - "used": false, - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - }, - "S2": { - "length": 0, - "src_port": "102T", - "dst_port": "2", - "local_peer_port": "102T", - "remote_peer_port": "2", - "used": false, - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - }, - "S3": { - "length": 0, - "src_port": "103T", - "dst_port": "3", - "local_peer_port": "103R", - "remote_peer_port": "3", - "used": false, - "c_slots": [], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - } - } - }, - "t2-r2": { - "length": 0, - "source" : "muxT", - "target" : "srgR", - "fibers" : { - "M1": { - "length": 0, - "src_port": "1", - "dst_port": "101R", - "local_peer_port": "1", - "remote_peer_port": "101T", - "used": false, - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - }, - "M2": { - "length": 0, - "src_port": "2", - "dst_port": "102R", - "local_peer_port": "2", - "remote_peer_port": "102T", - "used": false, - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - }, - "M3": { - "length": 0, - "src_port": "3", - "dst_port": "103R", - "local_peer_port": "3", - "remote_peer_port": "103T", - "used": false, - "c_slots": [], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - } - } - }, - "r2-t2": { - "length": 0, - "source" : "srgT", - "target" : "muxR", - "fibers" : { - "S1": { - "length": 0, - "src_port": "101T", - "dst_port": "1", - "local_peer_port": "101R", - "remote_peer_port": "1", - "used": false, - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - }, - "S2": { - "length": 0, - "src_port": "102T", - "dst_port": "2", - "local_peer_port": "102R", - "remote_peer_port": "2", - "used": false, - "c_slots": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - }, - "S3": { - "length": 0, - "src_port": "103T", - "dst_port": "3", - "local_peer_port": "103R", - "remote_peer_port": "3", - "used": false, - "c_slots": [], - "l_slots": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 ,120], - "s_slots": [501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519 ,520] - } - } - } -} diff --git a/src/opticalcontroller/requirements.in b/src/opticalcontroller/requirements.in index 0b1947bee2c7f1e89491dff4f7589d3465d28c38..f77bc15970be2695bbfde4fc744c5b2e363a6bf0 100644 --- a/src/opticalcontroller/requirements.in +++ b/src/opticalcontroller/requirements.in @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -12,10 +12,25 @@ # See the License for the specific language governing permissions and # limitations under the License. +aniso8601==9.0.1 +attrs==23.1.0 +blinker==1.6.2 +click==8.1.7 +colorama==0.4.6 Flask==1.1.2 flask-restplus==0.13.0 +importlib-metadata==6.8.0 +importlib-resources==6.0.1 itsdangerous==1.1.0 Jinja2==2.11.3 +jsonschema==4.19.0 +jsonschema-specifications==2023.7.1 MarkupSafe==1.1.1 numpy==1.23.0 +pkgutil-resolve-name==1.3.10 +pytz==2023.3.post1 +referencing==0.30.2 +rpds-py==0.10.3 +six==1.16.0 Werkzeug==0.16.1 +zipp==3.16.2 diff --git a/src/opticalcontroller/requirements_optical_ctrl_test.txt b/src/opticalcontroller/requirements_optical_ctrl_test.txt new file mode 100644 index 0000000000000000000000000000000000000000..7e7443c2d693e199a34bfbd0e87b2569c26fd98f --- /dev/null +++ b/src/opticalcontroller/requirements_optical_ctrl_test.txt @@ -0,0 +1,21 @@ +# 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. + +Flask==1.1.2 +flask-restplus==0.13.0 +itsdangerous==1.1.0 +Jinja2==2.11.3 +MarkupSafe==1.1.1 +numpy==1.23.0 +Werkzeug==0.16.1 diff --git a/src/opticalcontroller/tools.py b/src/opticalcontroller/tools.py index a173856b8e7bd00a0e538cd3893e1c762edff8c8..cab1807604fe238c9686e5b9f07eae0ad6c9646e 100644 --- a/src/opticalcontroller/tools.py +++ b/src/opticalcontroller/tools.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -12,9 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -import numpy as np -from variables import * import json +import numpy as np +from common.proto.context_pb2 import TopologyId , LinkId , OpticalLink , OpticalLinkDetails +from common.tools.object_factory.OpticalLink import correct_slot +from context.client.ContextClient import ContextClient +from opticalcontroller.variables import * def common_slots(a, b): @@ -24,9 +27,11 @@ def common_slots(a, b): def map_modulation_to_op(mod): if mod == "DP-QPSK": return 1 - if mod == "DP-16QAM": - return 7 - if mod == "DP-64QAM": + elif mod == "DP-8QAM": + return 4 + elif mod == "DP-16QAM": + return 8 + elif mod == "DP-32QAM": return 10 @@ -40,13 +45,19 @@ def map_rate_to_slot(rate): slots = 4 op = map_modulation_to_op(mod) return op, slots - if rate == 400: + elif rate == 400: + mod = "DP-8QAM" + slots = 4 + op = map_modulation_to_op(mod) + return op, slots + elif rate == 800: mod = "DP-16QAM" - slots = 8 + #todo: check slot width + slots = 8#12 (150GHz) op = map_modulation_to_op(mod) return op, slots - if rate == 1000: - mod = "DP-64QAM" + elif rate == 1000: + mod = "DP-32QAM" slots = 18 op = map_modulation_to_op(mod) return op, slots @@ -54,21 +65,34 @@ def map_rate_to_slot(rate): return 2, 5 -def consecutives(x, val): +def consecutives(link, val): res = [] temp = [] + x1 = list(link.keys()) + x = str_list_to_int(x1) x.sort() - temp.append(x[0]) - y = 1 + y = 0 + if debug: + print("BLACK") + print(link) + print(x) + print(x[0]) + if link[str(x[0])] == 1: + temp.append(int(x[0])) + y = 1 for i in range(1, len(x)): - if x[i] == x[i - 1] + 1: + if (int(x[i]) == int(x[i - 1]) + 1) and link[str(x[i])] == 1: y += 1 - temp.append(x[i]) + temp.append(int(x[i])) else: if y >= val: res.extend(temp) - temp = [x[i]] - y = 1 + if link[str(x[i])] == 1: + temp = [int(x[i])] + y = 1 + else: + temp = [] + y = 0 if i == len(x) - 1 and y >= val: res.extend(temp) return res @@ -83,6 +107,14 @@ def combine(ls1, ls2): return temp +def str_list_to_int(str_list): + int_list = [] + for i in str_list: + int_list.append(int(i)) + int_list.sort() + return int_list + + def list_in_list(a, b): # convert list A to numpy array a_arr = np.array(a) @@ -112,7 +144,30 @@ def get_slot_frequency(b, n): return Fl + n * 12.5 -def freqency_converter(b, slots): +def get_side_slots_on_link(link, val, old_slots): + #link = l["optical_details"][band] + x = list(old_slots.keys()) + y = list(link.keys()) + keys = str_list_to_int(x) + keys.sort() + #print("AAAA") + #print(link, val, old_slots, keys) + #print(x) + starting_slot = keys[-1] + num = 0 + res = [] + #print(starting_slot) + for slot_id in range(starting_slot, len(y)): + if link[y[slot_id]] == 1: + num += 1 + res.append(int(y[slot_id])) + else: + return res, 0 + if num == val or slot_id == len(y) - 1: + return res, num + + +def frequency_converter(b, slots): l = len(slots) if debug: print(slots) @@ -135,14 +190,24 @@ def freqency_converter(b, slots): def readTopologyData(nodes, topology): - nodes_file = open(nodes, 'r') - topo_file = open(topology, 'r') - nodes = json.load(nodes_file) - topo = json.load(topo_file) - print(topo) - nodes_file.close() - topo_file.close() - return nodes, topo + nodes_file = open(nodes, 'r') + topo_file = open(topology, 'r') + nodes = json.load(nodes_file) + topo = json.load(topo_file) + #print(topo) + nodes_file.close() + topo_file.close() + return nodes, topo + + +def readTopologyDataFromContext(topology_id:TopologyId): + ctx_client = ContextClient() + ctx_client.connect() + topo_details = ctx_client.GetTopologyDetails(topology_id) + topo = topo_details.optical_links + nodes = topo_details.devices + ctx_client.close() + return topo , nodes def reverse_links(links): @@ -154,23 +219,26 @@ def reverse_links(links): result.append("{}-{}".format(b, a)) return result + def get_links_from_node(topology, node): result = {} - for link in topology["links"]: - if "{}-".format(node) in link["optical_link"]["name"]: - result[link["optical_link"]["name"]] = link + for link in topology["optical_links"]: + if "{}-".format(node) in link["name"]: + result[link["name"]] = link return result + def get_links_to_node(topology, node): result = {} - for link in topology["links"]: - if "-{}".format(node) in link["optical_link"]["name"]: - result[link["optical_link"]["name"]] = link + for link in topology["optical_links"]: + if "-{}".format(node) in link["name"]: + result[link["name"]] = link return result def slot_selection(c, l, s, n_slots, Nc, Nl, Ns): # First Fit + if isinstance(n_slots, int): slot_c = n_slots slot_l = n_slots @@ -183,7 +251,15 @@ def slot_selection(c, l, s, n_slots, Nc, Nl, Ns): return "c_slots", c[0: slot_c] elif len(l) >= slot_l: return "l_slots", l[0: slot_l] - elif len(l) >= slot_s: + elif len(s) >= slot_s: return "s_slots", s[0: slot_s] else: return None, None + +def handle_slot (slot_field, slot): + for key,value in slot.items() : + slot_field[key]=value + + + + diff --git a/src/opticalcontroller/variables.py b/src/opticalcontroller/variables.py index ca436736b20a525c866ea9745be14bc4db37dfcf..de9d6609a3931840cc30069979361bd00699b53c 100644 --- a/src/opticalcontroller/variables.py +++ b/src/opticalcontroller/variables.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -23,10 +23,4 @@ Nc = 320 #Nc = 10 Ns = 720 -nodes_json = 'json_files/nodes.json' -topology_json = 'json_files/tfs.json' #LAST -#topology_json = 'json_files/optical_TFSworking.json' #LAST -#topology_json = 'json_files/optical_topoTFS.json' -#topology_json = 'json_files/topo_2_links.json' - -testing = 1 +full_links = 0 diff --git a/src/pathcomp/.gitlab-ci.yml b/src/pathcomp/.gitlab-ci.yml index 24f6d42d37ec6b6f341616f0badf08e9ef55ffff..85aab06e266ac42d13ced84aa8f012329ca002d6 100644 --- a/src/pathcomp/.gitlab-ci.yml +++ b/src/pathcomp/.gitlab-ci.yml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/__init__.py b/src/pathcomp/__init__.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/pathcomp/__init__.py +++ b/src/pathcomp/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/backend/Dockerfile b/src/pathcomp/backend/Dockerfile index 0c992f8fbc59020f818def2852c93eeda25efcce..7b3da21a7274c6cab1148abe1153d86f6f403d88 100644 --- a/src/pathcomp/backend/Dockerfile +++ b/src/pathcomp/backend/Dockerfile @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/backend/Dockerfile-gdb b/src/pathcomp/backend/Dockerfile-gdb index a5f18e02bb8ce463b88c93b1e3325eb6eed370fb..65879dc1a46549f802a593858f49364cddc91785 100644 --- a/src/pathcomp/backend/Dockerfile-gdb +++ b/src/pathcomp/backend/Dockerfile-gdb @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/backend/Makefile b/src/pathcomp/backend/Makefile index 2ca6f42cbf49141d9db9138bb6481ec7a0d3c2a8..1b5ed67e1fa39e546dedefc087aa68ad08297723 100644 --- a/src/pathcomp/backend/Makefile +++ b/src/pathcomp/backend/Makefile @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/backend/pathComp.c b/src/pathcomp/backend/pathComp.c index 4961c55a391d2c48a64ae844adf0eccb351cd7cf..51c92bf428ea46d386827bb052ea0fbb25d90712 100644 --- a/src/pathcomp/backend/pathComp.c +++ b/src/pathcomp/backend/pathComp.c @@ -1,5 +1,5 @@ /* - * Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) + * 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. diff --git a/src/pathcomp/backend/pathComp.h b/src/pathcomp/backend/pathComp.h index ec2c91e88f4fe54c4f66e7df7e6dc8cfd2ee68b8..ac877e9caeddc3fc9673464cdb4764f749c562b3 100644 --- a/src/pathcomp/backend/pathComp.h +++ b/src/pathcomp/backend/pathComp.h @@ -1,5 +1,5 @@ /* - * Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) + * 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. diff --git a/src/pathcomp/backend/pathComp_RESTapi.c b/src/pathcomp/backend/pathComp_RESTapi.c index 093088aa8046d1aa4ac84408557ecbd11b7a7e4e..9fa92832a649bce9a28a94a71dd553a6ab43066a 100644 --- a/src/pathcomp/backend/pathComp_RESTapi.c +++ b/src/pathcomp/backend/pathComp_RESTapi.c @@ -1,5 +1,5 @@ /* - * Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) + * 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. diff --git a/src/pathcomp/backend/pathComp_RESTapi.h b/src/pathcomp/backend/pathComp_RESTapi.h index b3c7658d93f0f93f1dcdbaeacd5572cf03ad0e51..dcb1bd90e1f1c58959e8655799b94884a57ebe92 100644 --- a/src/pathcomp/backend/pathComp_RESTapi.h +++ b/src/pathcomp/backend/pathComp_RESTapi.h @@ -1,5 +1,5 @@ /* - * Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) + * 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. diff --git a/src/pathcomp/backend/pathComp_cjson.c b/src/pathcomp/backend/pathComp_cjson.c index b0721f3cd7d15a4c51a26d66d4dfaa48806164a4..f1e045ab337f83f6ee8cd6010f847c36011a11c4 100644 --- a/src/pathcomp/backend/pathComp_cjson.c +++ b/src/pathcomp/backend/pathComp_cjson.c @@ -1,5 +1,5 @@ /* - * Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) + * 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. diff --git a/src/pathcomp/backend/pathComp_cjson.h b/src/pathcomp/backend/pathComp_cjson.h index 9e54070a72368d47d617867d53714fe5e71af75a..af0d30b869321346ecbb201caf1bae958fec9db6 100644 --- a/src/pathcomp/backend/pathComp_cjson.h +++ b/src/pathcomp/backend/pathComp_cjson.h @@ -1,5 +1,5 @@ /* - * Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) + * 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. diff --git a/src/pathcomp/backend/pathComp_ear.c b/src/pathcomp/backend/pathComp_ear.c index 37be2833d358b359dffacf13e696340ceba0f549..82b362031cdda5e2377ac327ea44b3ced8e0b533 100644 --- a/src/pathcomp/backend/pathComp_ear.c +++ b/src/pathcomp/backend/pathComp_ear.c @@ -1,5 +1,5 @@ /* - * Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) + * 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. diff --git a/src/pathcomp/backend/pathComp_ear.h b/src/pathcomp/backend/pathComp_ear.h index afe95413a0665ea84edb96ab67828d7df12d1f07..31f4131ad93d5619ea31ca9ca580521976ecfc1a 100644 --- a/src/pathcomp/backend/pathComp_ear.h +++ b/src/pathcomp/backend/pathComp_ear.h @@ -1,5 +1,5 @@ /* - * Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) + * 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. diff --git a/src/pathcomp/backend/pathComp_ksp.c b/src/pathcomp/backend/pathComp_ksp.c index 13a00ca43a961abfb28579198f2694b89937d8d2..b778224a543157584fe6d8b6ba02b5b1522333d1 100644 --- a/src/pathcomp/backend/pathComp_ksp.c +++ b/src/pathcomp/backend/pathComp_ksp.c @@ -1,5 +1,5 @@ /* - * Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) + * 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. diff --git a/src/pathcomp/backend/pathComp_ksp.h b/src/pathcomp/backend/pathComp_ksp.h index f155a23d33019466c1ac3021da953f978e3ecf95..158188f14affda256bf2ca7ffefc943cc4333f8a 100644 --- a/src/pathcomp/backend/pathComp_ksp.h +++ b/src/pathcomp/backend/pathComp_ksp.h @@ -1,5 +1,5 @@ /* - * Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) + * 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. diff --git a/src/pathcomp/backend/pathComp_log.c b/src/pathcomp/backend/pathComp_log.c index 4d2b5cad2a6069834545cb02dcf4909fe37113ed..9e8c795c115ad09c42e76fd3f06de22f6ae634e5 100644 --- a/src/pathcomp/backend/pathComp_log.c +++ b/src/pathcomp/backend/pathComp_log.c @@ -1,5 +1,5 @@ /* - * Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) + * 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. diff --git a/src/pathcomp/backend/pathComp_log.h b/src/pathcomp/backend/pathComp_log.h index 559281a3f3b7dbf5d8a232f8073d62c1b9b0cf70..b42e043312e971f7d74598ab20f52474c878f752 100644 --- a/src/pathcomp/backend/pathComp_log.h +++ b/src/pathcomp/backend/pathComp_log.h @@ -1,5 +1,5 @@ /* - * Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) + * 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. diff --git a/src/pathcomp/backend/pathComp_sp.c b/src/pathcomp/backend/pathComp_sp.c index ac6577520e70314f88f0ba5aa18ea52035f797ad..913fabb60c14588fe26780fe0566385262a0c726 100644 --- a/src/pathcomp/backend/pathComp_sp.c +++ b/src/pathcomp/backend/pathComp_sp.c @@ -1,5 +1,5 @@ /* - * Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) + * 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. diff --git a/src/pathcomp/backend/pathComp_sp.h b/src/pathcomp/backend/pathComp_sp.h index ab684ffeeafc2a6ca1267583bad1f1b5e7afbe56..2a8b4553401793253768df4b38348d8c4fcabcee 100644 --- a/src/pathcomp/backend/pathComp_sp.h +++ b/src/pathcomp/backend/pathComp_sp.h @@ -1,5 +1,5 @@ /* - * Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) + * 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. diff --git a/src/pathcomp/backend/pathComp_tools.c b/src/pathcomp/backend/pathComp_tools.c index e573dce00f15a12cc2749fd6127da8adf56c9d70..df92594b3d8c73bc82e31bec263eb9eabb720bc3 100644 --- a/src/pathcomp/backend/pathComp_tools.c +++ b/src/pathcomp/backend/pathComp_tools.c @@ -1,5 +1,5 @@ /* - * Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) + * 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. diff --git a/src/pathcomp/backend/pathComp_tools.h b/src/pathcomp/backend/pathComp_tools.h index 85d1c62ead295642e6d3d297941ae72d532bdeed..546adad06641e3e5f4739fe1b2d37bbb52f2be45 100644 --- a/src/pathcomp/backend/pathComp_tools.h +++ b/src/pathcomp/backend/pathComp_tools.h @@ -1,5 +1,5 @@ /* - * Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) + * 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. diff --git a/src/pathcomp/backend/tests/run-test.sh b/src/pathcomp/backend/tests/run-test.sh index 4a1b1b4bd6d4e4e8fc0989f531021c87a958abd4..d021d593220f86d5fe20cd474076bd1116f23d3d 100755 --- a/src/pathcomp/backend/tests/run-test.sh +++ b/src/pathcomp/backend/tests/run-test.sh @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/Config.py b/src/pathcomp/frontend/Config.py index 08de81b47dd05ce19ac8335b5b31df8ef4ee461e..c67f62870f156516c953e69cf4c5ae7af64cc79e 100644 --- a/src/pathcomp/frontend/Config.py +++ b/src/pathcomp/frontend/Config.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -13,7 +13,7 @@ # limitations under the License. import os -from common.Settings import get_setting +from common.Settings import get_setting, is_deployed_forecaster DEFAULT_PATHCOMP_BACKEND_SCHEME = 'http' DEFAULT_PATHCOMP_BACKEND_HOST = '127.0.0.1' @@ -44,6 +44,7 @@ SETTING_NAME_ENABLE_FORECASTER = 'ENABLE_FORECASTER' TRUE_VALUES = {'Y', 'YES', 'TRUE', 'T', 'E', 'ENABLE', 'ENABLED'} def is_forecaster_enabled() -> bool: + if not is_deployed_forecaster(): return False is_enabled = get_setting(SETTING_NAME_ENABLE_FORECASTER, default=None) if is_enabled is None: return False str_is_enabled = str(is_enabled).upper() diff --git a/src/pathcomp/frontend/Dockerfile b/src/pathcomp/frontend/Dockerfile index 0c72a1f144da4766215add67c5252ccd939de817..c96db7293cb16cbe18e8ae2b8894590d16fb492c 100644 --- a/src/pathcomp/frontend/Dockerfile +++ b/src/pathcomp/frontend/Dockerfile @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/__init__.py b/src/pathcomp/frontend/__init__.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/pathcomp/frontend/__init__.py +++ b/src/pathcomp/frontend/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/client/PathCompClient.py b/src/pathcomp/frontend/client/PathCompClient.py index 14756ea6e2ec452a9c80d8ba09caff4c5435cfa3..0cbe1ef64e96124de4381c2b13ef62dfb392122b 100644 --- a/src/pathcomp/frontend/client/PathCompClient.py +++ b/src/pathcomp/frontend/client/PathCompClient.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/client/__init__.py b/src/pathcomp/frontend/client/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/pathcomp/frontend/client/__init__.py +++ b/src/pathcomp/frontend/client/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/requirements.in b/src/pathcomp/frontend/requirements.in index 0466b25dc1e326d72735c02aa9b581264dd02620..ea970224a21d8948ae846c4470d64eb78f13028a 100644 --- a/src/pathcomp/frontend/requirements.in +++ b/src/pathcomp/frontend/requirements.in @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -13,6 +13,7 @@ # limitations under the License. +numpy<2.0.0 pandas==1.5.* requests==2.27.1 scikit-learn==1.1.* diff --git a/src/pathcomp/frontend/service/PathCompService.py b/src/pathcomp/frontend/service/PathCompService.py index 76edef6cf8f34b757f3dd975d51a7e57c328b920..c19e59e77b9b5f75f66eec07990691a76cdc36b7 100644 --- a/src/pathcomp/frontend/service/PathCompService.py +++ b/src/pathcomp/frontend/service/PathCompService.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/service/PathCompServiceServicerImpl.py b/src/pathcomp/frontend/service/PathCompServiceServicerImpl.py index ffaa6c358811f567de0a38ba3f50d69b5e0e3ced..f5bc8074a8c67b832d9c8f5efbb480bc9deac94f 100644 --- a/src/pathcomp/frontend/service/PathCompServiceServicerImpl.py +++ b/src/pathcomp/frontend/service/PathCompServiceServicerImpl.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/service/TopologyTools.py b/src/pathcomp/frontend/service/TopologyTools.py index 0ae114b1a3dea31e2abd3399e43ba8d131f2b917..707130459aeb8416d14a4bc8a5511b951cb1f8c1 100644 --- a/src/pathcomp/frontend/service/TopologyTools.py +++ b/src/pathcomp/frontend/service/TopologyTools.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/service/__init__.py b/src/pathcomp/frontend/service/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/pathcomp/frontend/service/__init__.py +++ b/src/pathcomp/frontend/service/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/service/__main__.py b/src/pathcomp/frontend/service/__main__.py index 9c7b7fe202cde4edae2e9193b3a8a3aa4197e12f..58ad597bcc79e70b35f70ebf86f50b262980fc0a 100644 --- a/src/pathcomp/frontend/service/__main__.py +++ b/src/pathcomp/frontend/service/__main__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/service/algorithms/Factory.py b/src/pathcomp/frontend/service/algorithms/Factory.py index be18bc2bcce7e2037ed1c10a9dad70db2acc5217..1332dcf47a035d9832173e8a6ba46fa7669e8d67 100644 --- a/src/pathcomp/frontend/service/algorithms/Factory.py +++ b/src/pathcomp/frontend/service/algorithms/Factory.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/service/algorithms/KDisjointPathAlgorithm.py b/src/pathcomp/frontend/service/algorithms/KDisjointPathAlgorithm.py index e5dc2938124c6a668e6ddcf3296ebf273786cc2e..6f88f497c9a9bcb654de2bf96fd76dc119dbceee 100644 --- a/src/pathcomp/frontend/service/algorithms/KDisjointPathAlgorithm.py +++ b/src/pathcomp/frontend/service/algorithms/KDisjointPathAlgorithm.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/service/algorithms/KShortestPathAlgorithm.py b/src/pathcomp/frontend/service/algorithms/KShortestPathAlgorithm.py index 57ce43979f4aeb7671bf8be5a6dba5e58a50cd87..85775199b240ec652236bceda352a537fcf7e3f5 100644 --- a/src/pathcomp/frontend/service/algorithms/KShortestPathAlgorithm.py +++ b/src/pathcomp/frontend/service/algorithms/KShortestPathAlgorithm.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/service/algorithms/ShortestPathAlgorithm.py b/src/pathcomp/frontend/service/algorithms/ShortestPathAlgorithm.py index effe6c50b126abb818cbb8de170845ac519a6325..9e7030b9261cac225ca5a3163d5e94e502cc9905 100644 --- a/src/pathcomp/frontend/service/algorithms/ShortestPathAlgorithm.py +++ b/src/pathcomp/frontend/service/algorithms/ShortestPathAlgorithm.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/service/algorithms/_Algorithm.py b/src/pathcomp/frontend/service/algorithms/_Algorithm.py index 3ed2b13fb33ae06faeacc4286959a8016ca995d1..ea54f77978057af9ca99c700b5d1c7a46ed934ae 100644 --- a/src/pathcomp/frontend/service/algorithms/_Algorithm.py +++ b/src/pathcomp/frontend/service/algorithms/_Algorithm.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -14,6 +14,7 @@ import json, logging, requests, uuid from typing import Dict, List, Optional, Tuple, Union +from common.DeviceTypes import DeviceTypeEnum from common.proto.context_pb2 import ( ConfigRule, Connection, Device, DeviceList, EndPointId, Link, LinkList, Service, ServiceStatusEnum, ServiceTypeEnum ) @@ -251,21 +252,37 @@ class _Algorithm: ] self.logger.debug('path_hops = {:s}'.format(str(path_hops))) - try: - _device_dict = {k:v[0] for k,v in self.device_dict.items()} - self.logger.debug('self.device_dict = {:s}'.format(str(_device_dict))) - connections = convert_explicit_path_hops_to_connections( - path_hops, self.device_dict, main_service_uuid, main_service_type) - self.logger.debug('EXTRAPOLATED connections = {:s}'.format(str(connections))) - except: # pylint: disable=bare-except - MSG = ' '.join([ - 'Unable to Extrapolate sub-services and sub-connections.', - 'Assuming single-service and single-connection.', - ]) - self.logger.exception(MSG) + device_types = {v[0]['device_type'] for k,v in self.device_dict.items()} + DEVICES_BASIC_CONNECTION = { + DeviceTypeEnum.DATACENTER.value, DeviceTypeEnum.EMULATED_DATACENTER.value, + DeviceTypeEnum.CLIENT.value, DeviceTypeEnum.EMULATED_CLIENT.value, + DeviceTypeEnum.PACKET_ROUTER.value, DeviceTypeEnum.EMULATED_PACKET_ROUTER.value, + } + self.logger.debug('device_types = {:s}'.format(str(device_types))) + self.logger.debug('DEVICES_BASIC_CONNECTION = {:s}'.format(str(DEVICES_BASIC_CONNECTION))) + is_basic_connection = device_types.issubset(DEVICES_BASIC_CONNECTION) + self.logger.debug('is_basic_connection = {:s}'.format(str(is_basic_connection))) + if is_basic_connection: + self.logger.info('Assuming basic connections...') connections = convert_explicit_path_hops_to_plain_connection( path_hops, main_service_uuid, main_service_type) self.logger.debug('BASIC connections = {:s}'.format(str(connections))) + else: + try: + _device_dict = {k:v[0] for k,v in self.device_dict.items()} + self.logger.debug('self.device_dict = {:s}'.format(str(_device_dict))) + connections = convert_explicit_path_hops_to_connections( + path_hops, self.device_dict, main_service_uuid, main_service_type) + self.logger.debug('EXTRAPOLATED connections = {:s}'.format(str(connections))) + except: # pylint: disable=bare-except + MSG = ' '.join([ + 'Unable to Extrapolate sub-services and sub-connections.', + 'Assuming single-service and single-connection.', + ]) + self.logger.exception(MSG) + connections = convert_explicit_path_hops_to_plain_connection( + path_hops, main_service_uuid, main_service_type) + self.logger.debug('BASIC connections = {:s}'.format(str(connections))) for connection in connections: service_uuid,service_type,path_hops,_ = connection diff --git a/src/pathcomp/frontend/service/algorithms/__init__.py b/src/pathcomp/frontend/service/algorithms/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/pathcomp/frontend/service/algorithms/__init__.py +++ b/src/pathcomp/frontend/service/algorithms/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/service/algorithms/tools/ComposeConfigRules.py b/src/pathcomp/frontend/service/algorithms/tools/ComposeConfigRules.py index 0c98254729afd0b2089c84499a9c739e985b27f5..f0775371d0f3fea01411ce4049226377feebc27e 100644 --- a/src/pathcomp/frontend/service/algorithms/tools/ComposeConfigRules.py +++ b/src/pathcomp/frontend/service/algorithms/tools/ComposeConfigRules.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -184,6 +184,10 @@ def compose_device_config_rules( device_endpoint_keys = set(itertools.product(device_keys, endpoint_keys)) if len(device_endpoint_keys.intersection(endpoints_traversed)) == 0: continue + + # TODO: check if vlan needs to be removed from config_rule + #config_rule.custom.resource_key = re.sub('\/vlan\[[^\]]+\]', '', config_rule.custom.resource_key) + subservice_config_rules.append(config_rule) else: continue diff --git a/src/pathcomp/frontend/service/algorithms/tools/ComposeRequest.py b/src/pathcomp/frontend/service/algorithms/tools/ComposeRequest.py index c4141c47855140259309efa43edfad35138968c4..0554084f8e3c83504e3c225ecc5a3e7503ed9c53 100644 --- a/src/pathcomp/frontend/service/algorithms/tools/ComposeRequest.py +++ b/src/pathcomp/frontend/service/algorithms/tools/ComposeRequest.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/service/algorithms/tools/ComputeSubServices.py b/src/pathcomp/frontend/service/algorithms/tools/ComputeSubServices.py index a34798b137fed759837bad04a47212fa867e54dd..dfcd1156b78cebee7da84033cbc9943aaabdb14d 100644 --- a/src/pathcomp/frontend/service/algorithms/tools/ComputeSubServices.py +++ b/src/pathcomp/frontend/service/algorithms/tools/ComputeSubServices.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/service/algorithms/tools/ConstantsMappings.py b/src/pathcomp/frontend/service/algorithms/tools/ConstantsMappings.py index 9f596b4b324b2bf06c58cd9eb6d96c5753257ae4..d72127bdbeaa8457f1933a5c4669ead0a2106a9c 100644 --- a/src/pathcomp/frontend/service/algorithms/tools/ConstantsMappings.py +++ b/src/pathcomp/frontend/service/algorithms/tools/ConstantsMappings.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/service/algorithms/tools/EroPathToHops.py b/src/pathcomp/frontend/service/algorithms/tools/EroPathToHops.py index a33397bb4e21a50c247b74a1ef6c55c8768e0c7f..9ee17783045ea0ade2216d9f125e4f119b761c9c 100644 --- a/src/pathcomp/frontend/service/algorithms/tools/EroPathToHops.py +++ b/src/pathcomp/frontend/service/algorithms/tools/EroPathToHops.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/service/algorithms/tools/ResourceGroups.py b/src/pathcomp/frontend/service/algorithms/tools/ResourceGroups.py index 185b111657ce0a3964879bb322fe146b9b7811c2..42635bf4ad5cfd1a1a4cb174b73d26c51576af9a 100644 --- a/src/pathcomp/frontend/service/algorithms/tools/ResourceGroups.py +++ b/src/pathcomp/frontend/service/algorithms/tools/ResourceGroups.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/service/algorithms/tools/ServiceTypes.py b/src/pathcomp/frontend/service/algorithms/tools/ServiceTypes.py index 2792a86639fbd6852a41499e928de7a4131ed408..8230092c2decc0b2c988f63a2677f879f7ec944f 100644 --- a/src/pathcomp/frontend/service/algorithms/tools/ServiceTypes.py +++ b/src/pathcomp/frontend/service/algorithms/tools/ServiceTypes.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/service/algorithms/tools/__init__.py b/src/pathcomp/frontend/service/algorithms/tools/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/pathcomp/frontend/service/algorithms/tools/__init__.py +++ b/src/pathcomp/frontend/service/algorithms/tools/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/tests/MockService_Dependencies.py b/src/pathcomp/frontend/tests/MockService_Dependencies.py index 55a28e39405ee2f99806f69cb2cc8f792fd97482..56ef052bdb02caee2e33019d87578e84fe1ff66d 100644 --- a/src/pathcomp/frontend/tests/MockService_Dependencies.py +++ b/src/pathcomp/frontend/tests/MockService_Dependencies.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/tests/Objects_A_B_C.py b/src/pathcomp/frontend/tests/Objects_A_B_C.py index 1be130c7be1525f670e351ff979e2911b6e8f34f..bdcaef65b0981c9c7d7cc7e76a21c81b2ae950b5 100644 --- a/src/pathcomp/frontend/tests/Objects_A_B_C.py +++ b/src/pathcomp/frontend/tests/Objects_A_B_C.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/tests/Objects_DC_CSGW_TN.py b/src/pathcomp/frontend/tests/Objects_DC_CSGW_TN.py index 7c92179b05ebe3ae7a14f2b302451a86c3c65ea2..0dc10b669001ac7dc35644b96b7772d890870c58 100644 --- a/src/pathcomp/frontend/tests/Objects_DC_CSGW_TN.py +++ b/src/pathcomp/frontend/tests/Objects_DC_CSGW_TN.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/tests/Objects_DC_CSGW_TN_OLS.py b/src/pathcomp/frontend/tests/Objects_DC_CSGW_TN_OLS.py index 2b786119294e6badee097fc35a3a76bfaf301a26..359f45b3241444c26a1f780548f0822aebce1e15 100644 --- a/src/pathcomp/frontend/tests/Objects_DC_CSGW_TN_OLS.py +++ b/src/pathcomp/frontend/tests/Objects_DC_CSGW_TN_OLS.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/tests/PrepareTestScenario.py b/src/pathcomp/frontend/tests/PrepareTestScenario.py index 8b00fb3e81f64467a7c1fedf284a42ba7fa1ef64..9dd05cdf5a5c2357042423f1d36a96418040fe92 100644 --- a/src/pathcomp/frontend/tests/PrepareTestScenario.py +++ b/src/pathcomp/frontend/tests/PrepareTestScenario.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/tests/__init__.py b/src/pathcomp/frontend/tests/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/pathcomp/frontend/tests/__init__.py +++ b/src/pathcomp/frontend/tests/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/tests/test_ero_path.py b/src/pathcomp/frontend/tests/test_ero_path.py index 1b80ca83cc567be120ed07df8b4c228ac20052fa..af8877ae37c84eb56e734d50981a2343c9813eb0 100644 --- a/src/pathcomp/frontend/tests/test_ero_path.py +++ b/src/pathcomp/frontend/tests/test_ero_path.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/tests/test_pathcomp/__init__.py b/src/pathcomp/frontend/tests/test_pathcomp/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/pathcomp/frontend/tests/test_pathcomp/__init__.py +++ b/src/pathcomp/frontend/tests/test_pathcomp/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/tests/test_pathcomp/__main__.py b/src/pathcomp/frontend/tests/test_pathcomp/__main__.py index 687e9b96dfbdd543b49641f2dd8357c69485d102..108da5a7f411a397b91ecd70bdfd48e5bdbc4fae 100644 --- a/src/pathcomp/frontend/tests/test_pathcomp/__main__.py +++ b/src/pathcomp/frontend/tests/test_pathcomp/__main__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/tests/test_pathcomp/data.py b/src/pathcomp/frontend/tests/test_pathcomp/data.py index 3fc5c6fac2bf2c5739872ec4bc21621599ad7883..eac4d821bf850be49acdb082b78f26633b7b01b3 100644 --- a/src/pathcomp/frontend/tests/test_pathcomp/data.py +++ b/src/pathcomp/frontend/tests/test_pathcomp/data.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/tests/test_unitary.py b/src/pathcomp/frontend/tests/test_unitary.py index 902b84c63f60a8f47b5fe15ec18278f4392de8f2..4327ff1295ca732536c12ea8e1274ca5a1119966 100644 --- a/src/pathcomp/frontend/tests/test_unitary.py +++ b/src/pathcomp/frontend/tests/test_unitary.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/frontend/tests/test_unitary_pathcomp_forecaster.py b/src/pathcomp/frontend/tests/test_unitary_pathcomp_forecaster.py index 62750b52519c77e6c00d482f785fc7455b2f3dc2..0e41c18c9562b97f04bf3ed6043c2caf20817af3 100644 --- a/src/pathcomp/frontend/tests/test_unitary_pathcomp_forecaster.py +++ b/src/pathcomp/frontend/tests/test_unitary_pathcomp_forecaster.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/misc/my_deploy-tests.sh b/src/pathcomp/misc/my_deploy-tests.sh index 15ce64cfc31ee2ff42a697d2a3f51e2765d7c45b..b1e6ec14e26ce619e5358ebb8a6cc2bef19b36c1 100755 --- a/src/pathcomp/misc/my_deploy-tests.sh +++ b/src/pathcomp/misc/my_deploy-tests.sh @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/pathcomp/misc/test-commands.sh b/src/pathcomp/misc/test-commands.sh index f4aefabbb056bc874215f0aa626f826ad103864d..f1fd5ce21323eb241f137a959c087a450010a686 100755 --- a/src/pathcomp/misc/test-commands.sh +++ b/src/pathcomp/misc/test-commands.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/policy/.gitlab-ci.yml b/src/policy/.gitlab-ci.yml index 881da003e198a3bed3c498e2060c2d321a66e857..530913d3a82de09ca40db9986355b213594829e1 100644 --- a/src/policy/.gitlab-ci.yml +++ b/src/policy/.gitlab-ci.yml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/policy/pom.xml b/src/policy/pom.xml index 79294fba4020c091ee5234649c788d2ea7e88b56..5bf04013c3f604e9c3deac392a86d3aa721a7561 100644 --- a/src/policy/pom.xml +++ b/src/policy/pom.xml @@ -1,6 +1,6 @@ + + + + + device + + device + + + MellanoxSwitch + SSSA-CNIT + 1.0.0 + 1.0.0 + 1.0.0 + 610610 + typex:OPERATING_SYSTEM + + + + channel-1 + + channel-1 + + + channel-1 + typex:OPTICAL_CHANNEL + + + + 191600000 + 100 + 0 + transceiver-1 + + + 191600000 + 0 + 0 + transceiver-1 + 1 + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + + + + channel-2 + + channel-2 + + + channel-2 + typex:OPTICAL_CHANNEL + + + + 191600000 + 100 + 0 + transceiver-2 + + + 191600000 + 0 + 0 + transceiver-2 + 1 + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + + + + channel-3 + + channel-3 + + + channel-3 + typex:OPTICAL_CHANNEL + + + + 191600000 + 100 + 0 + transceiver-3 + + + 191600000 + 0 + 0 + transceiver-3 + 1 + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + + + + channel-4 + + channel-4 + + + channel-4 + typex:OPTICAL_CHANNEL + + + + 191600000 + 100 + 0 + transceiver-4 + + + 191600000 + 0 + 0 + transceiver-4 + 1 + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + + + + transceiver-1 + + transceiver-1 + + + transceiver-1 + typex:TRANSCEIVER + + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + Cisco + 400zr-QSFP-DD + 01 + 1567321 + + + + 1 + + 1 + channel-1 + + + + + + + transceiver-2 + + transceiver-2 + + + transceiver-2 + typex:TRANSCEIVER + + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + Cisco + 400zr-QSFP-DD + 01 + 1567321 + + + + 1 + + 1 + channel-2 + + + + + + + transceiver-3 + + transceiver-3 + + + transceiver-3 + typex:TRANSCEIVER + + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + Cisco + 400zr-QSFP-DD + 01 + 1567321 + + + + 1 + + 1 + channel-3 + + + + + + + + transceiver-4 + + transceiver-4 + + + transceiver-4 + typex:TRANSCEIVER + + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + Cisco + 400zr-QSFP-DD + 01 + 1567321 + + + + 1 + + 1 + channel-4 + + + + + + + port-1 + + port-1 + + + port-1 + typex:PORT + + + + channel-1 + + channel-1 + + + channel-1 + + + + + + onos-index + + onos-index + 1 + + + onos-index + 1 + + + + odtn-port-type + + odtn-port-type + line + + + odtn-port-type + line + + + + + + port-2 + + port-2 + + + port-2 + typex:PORT + + + + channel-2 + + channel-2 + + + channel-2 + + + + + + onos-index + + onos-index + 2 + + + onos-index + 2 + + + + odtn-port-type + + odtn-port-type + line + + + odtn-port-type + line + + + + + + port-3 + + port-3 + + + port-3 + typex:PORT + + + + channel-3 + + channel-3 + + + channel-3 + + + + + + onos-index + + onos-index + 3 + + + onos-index + 3 + + + + odtn-port-type + + odtn-port-type + line + + + odtn-port-type + line + + + + + + port-4 + + port-4 + + + port-4 + typex:PORT + + + + channel-4 + + channel-4 + + + channel-4 + + + + + + onos-index + + onos-index + 4 + + + onos-index + 4 + + + + odtn-port-type + + odtn-port-type + line + + + odtn-port-type + line + + + + + + + + + + + 1 + + 1 + Logical channel 1 + DISABLED + type:PROT_OTN + NONE + + + 1 + Logical channel 1 + DISABLED + type:PROT_OTN + NONE + UP + + + + transceiver-1 + + + transceiver-1 + + + + + test1 + test1 + + + test1 + test1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + + + + 1 + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-1 + + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-1 + + + + + + + + 2 + + 2 + Logical channel 2 + DISABLED + type:PROT_OTN + NONE + + + 2 + Logical channel 2 + DISABLED + type:PROT_OTN + NONE + UP + + + + transceiver-2 + + + transceiver-2 + + + + + test1 + test1 + + + test1 + test1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + + + + 1 + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-2 + + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-2 + + + + + + + + 3 + + 3 + Logical channel 3 + DISABLED + type:PROT_OTN + NONE + + + 3 + Logical channel 3 + DISABLED + type:PROT_OTN + NONE + UP + + + + transceiver-3 + + + transceiver-3 + + + + + test1 + test1 + + + test1 + test1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + + + + 1 + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-3 + + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-3 + + + + + + + + 4 + + 4 + Logical channel 4 + DISABLED + type:PROT_OTN + NONE + + + 4 + Logical channel 4 + DISABLED + type:PROT_OTN + NONE + UP + + + + transceiver-4 + + + transceiver-4 + + + + + test1 + test1 + + + test1 + test1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + + + + 1 + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-4 + + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-4 + + + + + + + + 1 + + 1 + FEC1 + Ericsson + + + + 2 + + 2 + FEC2 + Ericsson + + + + + + diff --git a/src/tests/ofc24/node-agents-config/transponders_x4_2.xml b/src/tests/ofc24/node-agents-config/transponders_x4_2.xml new file mode 100644 index 0000000000000000000000000000000000000000..3231dd95f7f7eb2cd0c3c93d6f13e5dfc9f57059 --- /dev/null +++ b/src/tests/ofc24/node-agents-config/transponders_x4_2.xml @@ -0,0 +1,1055 @@ + + + + + + device + + device + + + MellanoxSwitch + SSSA-CNIT + 1.0.0 + 1.0.0 + 1.0.0 + 610610 + typex:OPERATING_SYSTEM + + + + channel-5 + + channel-5 + + + channel-5 + typex:OPTICAL_CHANNEL + + + + 191600000 + 100 + 0 + transceiver-5 + + + 191600000 + 0 + 0 + transceiver-5 + 1 + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + + + + channel-6 + + channel-6 + + + channel-6 + typex:OPTICAL_CHANNEL + + + + 191600000 + 100 + 0 + transceiver-6 + + + 191600000 + 0 + 0 + transceiver-6 + 1 + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + + + + channel-7 + + channel-7 + + + channel-7 + typex:OPTICAL_CHANNEL + + + + 191600000 + 100 + 0 + transceiver-7 + + + 191600000 + 0 + 0 + transceiver-7 + 1 + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + + + + channel-8 + + channel-8 + + + channel-8 + typex:OPTICAL_CHANNEL + + + + 191600000 + 100 + 0 + transceiver-8 + + + 191600000 + 0 + 0 + transceiver-8 + 1 + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + + + + transceiver-5 + + transceiver-5 + + + transceiver-5 + typex:TRANSCEIVER + + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + Cisco + 400zr-QSFP-DD + 01 + 1567321 + + + + 1 + + 1 + channel-5 + + + + + + + transceiver-6 + + transceiver-6 + + + transceiver-6 + typex:TRANSCEIVER + + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + Cisco + 400zr-QSFP-DD + 01 + 1567321 + + + + 1 + + 1 + channel-6 + + + + + + + transceiver-7 + + transceiver-7 + + + transceiver-7 + typex:TRANSCEIVER + + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + Cisco + 400zr-QSFP-DD + 01 + 1567321 + + + + 1 + + 1 + channel-7 + + + + + + + + transceiver-8 + + transceiver-8 + + + transceiver-8 + typex:TRANSCEIVER + + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + Cisco + 400zr-QSFP-DD + 01 + 1567321 + + + + 1 + + 1 + channel-8 + + + + + + + port-5 + + port-5 + + + port-5 + typex:PORT + + + + channel-5 + + channel-5 + + + channel-5 + + + + + + onos-index + + onos-index + 5 + + + onos-index + 5 + + + + odtn-port-type + + odtn-port-type + line + + + odtn-port-type + line + + + + + + port-6 + + port-6 + + + port-6 + typex:PORT + + + + channel-6 + + channel-6 + + + channel-6 + + + + + + onos-index + + onos-index + 6 + + + onos-index + 6 + + + + odtn-port-type + + odtn-port-type + line + + + odtn-port-type + line + + + + + + port-7 + + port-7 + + + port-7 + typex:PORT + + + + channel-7 + + channel-7 + + + channel-7 + + + + + + onos-index + + onos-index + 7 + + + onos-index + 7 + + + + odtn-port-type + + odtn-port-type + line + + + odtn-port-type + line + + + + + + port-8 + + port-8 + + + port-8 + typex:PORT + + + + channel-8 + + channel-8 + + + channel-8 + + + + + + onos-index + + onos-index + 8 + + + onos-index + 8 + + + + odtn-port-type + + odtn-port-type + line + + + odtn-port-type + line + + + + + + + + + + + 5 + + 5 + Logical channel 5 + DISABLED + type:PROT_OTN + NONE + + + 5 + Logical channel 5 + DISABLED + type:PROT_OTN + NONE + UP + + + + transceiver-5 + + + transceiver-5 + + + + + test1 + test1 + + + test1 + test1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + + + + 1 + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-5 + + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-5 + + + + + + + + 6 + + 6 + Logical channel 6 + DISABLED + type:PROT_OTN + NONE + + + 6 + Logical channel 6 + DISABLED + type:PROT_OTN + NONE + UP + + + + transceiver-6 + + + transceiver-6 + + + + + test1 + test1 + + + test1 + test1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + + + + 1 + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-6 + + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-6 + + + + + + + + 7 + + 7 + Logical channel 7 + DISABLED + type:PROT_OTN + NONE + + + 7 + Logical channel 7 + DISABLED + type:PROT_OTN + NONE + UP + + + + transceiver-7 + + + transceiver-7 + + + + + test1 + test1 + + + test1 + test1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + + + + 1 + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-7 + + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-7 + + + + + + + + 8 + + 8 + Logical channel 8 + DISABLED + type:PROT_OTN + NONE + + + 8 + Logical channel 8 + DISABLED + type:PROT_OTN + NONE + UP + + + + transceiver-8 + + + transceiver-8 + + + + + test1 + test1 + + + test1 + test1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + + + + 1 + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-8 + + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-8 + + + + + + + + 1 + + 1 + FEC1 + Ericsson + + + + 2 + + 2 + FEC2 + Ericsson + + + + + + diff --git a/src/tests/ofc24/r_t.sh b/src/tests/ofc24/r_t.sh new file mode 100755 index 0000000000000000000000000000000000000000..f4ce3d22a83fe62a78534f445f587483ddd64bce --- /dev/null +++ b/src/tests/ofc24/r_t.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# 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 + + +docker stop -t 1 t1 +docker stop -t 1 na3 +docker stop -t 1 t2 +docker stop -t 1 na2 + +docker rm t1 +docker rm na3 + +docker rm t2 +docker rm na2 + +screen -dmS t1 -T xterm sh -c "docker run --name t1 -p 10.0.2.4:2023:2022 -v /home/tfs/tfs-ctrl/src/tests/ofc24/tempOC/files:/files -it asgamb1/oc23bgp.img:latest bash -c 'cp /files/transponders_x4.xml demoECOC21.xml ; ./startNetconfAgent.sh'" +screen -dmS t3 -T xterm sh -c "docker run --name na3 -p 10.0.2.4:2025:2022 -v /home/tfs/tfs-ctrl/src/tests/ofc24/tempOC/files:/files -it asgamb1/flexscale-node.img:latest bash -c 'cp /files/platform_r1.xml init_openconfig-platform.xml ; ./startNetconfAgent.sh'" +screen -dmS t2 -T xterm sh -c "docker run --name t2 -p 10.0.2.4:2024:2022 -v /home/tfs/tfs-ctrl/src/tests/ofc24/tempOC/files:/files -it asgamb1/oc23bgp.img:latest bash -c 'cp /files/transponders_x4_2.xml demoECOC21.xml ; ./startNetconfAgent.sh'" +screen -dmS t4 -T xterm sh -c "docker run --name na2 -p 10.0.2.4:2026:2022 -v /home/tfs/tfs-ctrl/src/tests/ofc24/tempOC/files:/files -it asgamb1/flexscale-node.img:latest bash -c 'cp /files/platform_r2.xml init_openconfig-platform.xml ; ./startNetconfAgent.sh'" diff --git a/src/tests/ofc24/requirements.in b/src/tests/ofc24/requirements.in index 468af1a17931d6e545647e3e7a057433d74826b3..d733b0adb03957eb23b685c8a901cdc4b3a6d8d6 100644 --- a/src/tests/ofc24/requirements.in +++ b/src/tests/ofc24/requirements.in @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/ofc24/roadms.sh b/src/tests/ofc24/roadms.sh new file mode 100644 index 0000000000000000000000000000000000000000..afa4f1c463b4ae179ebaed5eeec19b0afc09cfac --- /dev/null +++ b/src/tests/ofc24/roadms.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# 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. + + +docker stop -t 1 na3 +docker stop -t 1 na4 + +docker rm na3 +docker rm na4 + + + +screen -dmS t3 -T xterm sh -c "docker run --name na3 -p 10.0.2.4:2025:2022 -v /home/tfs/tfs-ctrl/src/tests/ofc24/tempOC/files:/files -it asgamb1/flexscale-node.img:latest bash -c 'cp /files/platform_r1.xml demoECOC21.xml ; ./startNetconfAgent.sh'" +screen -dmS t4 -T xterm sh -c "docker run --name na4 -p 10.0.2.4:2026:2022 -v /home/tfs/tfs-ctrl/src/tests/ofc24/tempOC/files:/files -it asgamb1/flexscale-node.img:latest bash -c 'cp /files/platform_r2.xml demoECOC21.xml ; ./startNetconfAgent.sh'" \ No newline at end of file diff --git a/src/tests/ofc24/run-tests-locally.sh b/src/tests/ofc24/run-tests-locally.sh index 3a273e70674e76f77067851c78fe6b05507611d1..ca442a4a244763952df50469fe0ab4a85dd85584 100755 --- a/src/tests/ofc24/run-tests-locally.sh +++ b/src/tests/ofc24/run-tests-locally.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/ofc24/run_test.sh b/src/tests/ofc24/run_test.sh new file mode 100644 index 0000000000000000000000000000000000000000..7f146cf7992e450d743e825dcf82b2b2ccc7e233 --- /dev/null +++ b/src/tests/ofc24/run_test.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# 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 + +docker stop na1 +docker rm na1 +screen -dmS t1 -T xterm sh -c "docker run -p 10.0.2.10:2023:2022 -v ~/tfs-ctrl/src/tests/ofc24/tempOC/files:/files --name na1 -it asgamb1/oc23bgp.img:latest" +sleep 2 +if [ "$( docker container inspect -f '{{.State.Running}}' na1)" = "true" ]; then + docker exec na1 sh -c " cp /files/platform_t1.xml demoECOC21.xml ; /confd/examples.confd/OC23/startNetconfAgent.sh; " +else + echo "your container is not running yet" +fi diff --git a/src/tests/ofc24/tempOC/files/platform_r1.xml b/src/tests/ofc24/tempOC/files/platform_r1.xml new file mode 100644 index 0000000000000000000000000000000000000000..92442a3a0f592dbc69f1e927421d2ec494da0493 --- /dev/null +++ b/src/tests/ofc24/tempOC/files/platform_r1.xml @@ -0,0 +1,253 @@ + + + + + + 2 + + 2 + + + + MG_ON_PORT_TYPE + + MG_ON_PORT_TYPE + MG_ON_OPTICAL_PORT_WAVEBAND + + + + MG_ON_PORT_DIRECTION + + MG_ON_PORT_DIRECTION + OUTPUT + + + + MG_ON_PORT_DEGREE + + MG_ON_PORT_DEGREE + D1 + + + + + + 12 + + 12 + + + + MG_ON_PORT_TYPE + + MG_ON_PORT_TYPE + MG_ON_OPTICAL_PORT_WAVEBAND + + + + MG_ON_PORT_DIRECTION + + MG_ON_PORT_DIRECTION + INPUT + + + + MG_ON_PORT_DEGREE + + MG_ON_PORT_DEGREE + D1 + + + + + + 3 + + 3 + + + + MG_ON_PORT_TYPE + + MG_ON_PORT_TYPE + MG_ON_OPTICAL_PORT_WAVEBAND + + + + MG_ON_PORT_DIRECTION + + MG_ON_PORT_DIRECTION + OUTPUT + + + + MG_ON_PORT_DEGREE + + MG_ON_PORT_DEGREE + D2 + + + + + + 13 + + 13 + + + + MG_ON_PORT_TYPE + + MG_ON_PORT_TYPE + MG_ON_OPTICAL_PORT_WAVEBAND + + + + MG_ON_PORT_DIRECTION + + MG_ON_PORT_DIRECTION + INPUT + + + + MG_ON_PORT_DEGREE + + MG_ON_PORT_DEGREE + D2 + + + + + + 4 + + 4 + + + + MG_ON_PORT_TYPE + + MG_ON_PORT_TYPE + MG_ON_OPTICAL_PORT_WAVEBAND + + + + MG_ON_PORT_DIRECTION + + MG_ON_PORT_DIRECTION + OUTPUT + + + + MG_ON_PORT_DEGREE + + MG_ON_PORT_DEGREE + D2 + + + + + + 14 + + 14 + + + + MG_ON_PORT_TYPE + + MG_ON_PORT_TYPE + MG_ON_OPTICAL_PORT_WAVEBAND + + + + MG_ON_PORT_DIRECTION + + MG_ON_PORT_DIRECTION + INPUT + + + + MG_ON_PORT_DEGREE + + MG_ON_PORT_DEGREE + D2 + + + + + + + 101 + + 101 + + + + MG_ON_PORT_TYPE + + MG_ON_PORT_TYPE + MG_ON_OPTICAL_PORT_WAVEBAND + + + + MG_ON_PORT_DIRECTION + + MG_ON_PORT_DIRECTION + OUTPUT + + + + MG_ON_PORT_DEGREE + + MG_ON_PORT_DEGREE + D2 + + + + + + 111 + + 111 + + + + MG_ON_PORT_TYPE + + MG_ON_PORT_TYPE + MG_ON_OPTICAL_PORT_WAVEBAND + + + + MG_ON_PORT_DIRECTION + + MG_ON_PORT_DIRECTION + INPUT + + + + MG_ON_PORT_DEGREE + + MG_ON_PORT_DEGREE + D2 + + + + + + \ No newline at end of file diff --git a/src/tests/ofc24/tempOC/files/platform_r2.xml b/src/tests/ofc24/tempOC/files/platform_r2.xml new file mode 100644 index 0000000000000000000000000000000000000000..66f9ecd85fa11a762febd2c99547cd3ecd44a7ca --- /dev/null +++ b/src/tests/ofc24/tempOC/files/platform_r2.xml @@ -0,0 +1,253 @@ + + + + + + 2 + + 2 + + + + MG_ON_PORT_TYPE + + MG_ON_PORT_TYPE + MG_ON_OPTICAL_PORT_WAVEBAND + + + + MG_ON_PORT_DIRECTION + + MG_ON_PORT_DIRECTION + OUTPUT + + + + MG_ON_PORT_DEGREE + + MG_ON_PORT_DEGREE + D1 + + + + + + 12 + + 12 + + + + MG_ON_PORT_TYPE + + MG_ON_PORT_TYPE + MG_ON_OPTICAL_PORT_WAVEBAND + + + + MG_ON_PORT_DIRECTION + + MG_ON_PORT_DIRECTION + INPUT + + + + MG_ON_PORT_DEGREE + + MG_ON_PORT_DEGREE + D1 + + + + + + 3 + + 3 + + + + MG_ON_PORT_TYPE + + MG_ON_PORT_TYPE + MG_ON_OPTICAL_PORT_WAVEBAND + + + + MG_ON_PORT_DIRECTION + + MG_ON_PORT_DIRECTION + OUTPUT + + + + MG_ON_PORT_DEGREE + + MG_ON_PORT_DEGREE + D2 + + + + + + 13 + + 13 + + + + MG_ON_PORT_TYPE + + MG_ON_PORT_TYPE + MG_ON_OPTICAL_PORT_WAVEBAND + + + + MG_ON_PORT_DIRECTION + + MG_ON_PORT_DIRECTION + INPUT + + + + MG_ON_PORT_DEGREE + + MG_ON_PORT_DEGREE + D2 + + + + + + 4 + + 4 + + + + MG_ON_PORT_TYPE + + MG_ON_PORT_TYPE + MG_ON_OPTICAL_PORT_WAVEBAND + + + + MG_ON_PORT_DIRECTION + + MG_ON_PORT_DIRECTION + OUTPUT + + + + MG_ON_PORT_DEGREE + + MG_ON_PORT_DEGREE + D2 + + + + + + 14 + + 14 + + + + MG_ON_PORT_TYPE + + MG_ON_PORT_TYPE + MG_ON_OPTICAL_PORT_WAVEBAND + + + + MG_ON_PORT_DIRECTION + + MG_ON_PORT_DIRECTION + INPUT + + + + MG_ON_PORT_DEGREE + + MG_ON_PORT_DEGREE + D2 + + + + + + + 101 + + 101 + + + + MG_ON_PORT_TYPE + + MG_ON_PORT_TYPE + MG_ON_OPTICAL_PORT_WAVEBAND + + + + MG_ON_PORT_DIRECTION + + MG_ON_PORT_DIRECTION + OUTPUT + + + + MG_ON_PORT_DEGREE + + MG_ON_PORT_DEGREE + D2 + + + + + + 111 + + 111 + + + + MG_ON_PORT_TYPE + + MG_ON_PORT_TYPE + MG_ON_OPTICAL_PORT_WAVEBAND + + + + MG_ON_PORT_DIRECTION + + MG_ON_PORT_DIRECTION + INPUT + + + + MG_ON_PORT_DEGREE + + MG_ON_PORT_DEGREE + D2 + + + + + + \ No newline at end of file diff --git a/src/tests/ofc24/tempOC/files/platform_t1.xml b/src/tests/ofc24/tempOC/files/platform_t1.xml new file mode 100644 index 0000000000000000000000000000000000000000..0fed3a0711da8a50235e3989565685eb88a957ac --- /dev/null +++ b/src/tests/ofc24/tempOC/files/platform_t1.xml @@ -0,0 +1,311 @@ + + + + + + device + + device + + + MellanoxSwitch + SSSA-CNIT + 1.0.0 + 1.0.0 + 1.0.0 + 610610 + typex:OPERATING_SYSTEM + + + + channel-1 + + channel-1 + + + channel-1 + typex:OPTICAL_CHANNEL + + + + 191600000 + 100 + 0 + transceiver-1 + + + 191600000 + 0 + 0 + transceiver-1 + 1 + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + + + + transceiver-1 + + transceiver-1 + + + transceiver-1 + typex:TRANSCEIVER + + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + Cisco + 400zr-QSFP-DD + 01 + 1567321 + + + + 1 + + 1 + channel-1 + + + + + + + + port-1 + + port-1 + + + port-1 + typex:PORT + + + + channel-1 + + channel-1 + + + channel-1 + + + + + + onos-index + + onos-index + 4 + + + onos-index + 4 + + + + odtn-port-type + + odtn-port-type + line + + + odtn-port-type + line + + + + + + + + + + + + 1 + + 1 + Logical channel 1 + DISABLED + type:PROT_OTN + NONE + + + 1 + Logical channel 1 + DISABLED + type:PROT_OTN + NONE + UP + + + + transceiver-1 + + + transceiver-1 + + + + + test1 + test1 + + + test1 + test1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + + + + 1 + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-1 + + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-1 + + + + + + + + 1 + + 1 + FEC1 + Ericsson + + + + 2 + + 2 + FEC2 + Ericsson + + + + + diff --git a/src/tests/ofc24/tempOC/files/platform_t2.xml b/src/tests/ofc24/tempOC/files/platform_t2.xml new file mode 100644 index 0000000000000000000000000000000000000000..55b7b047ec718660359966918beac6d0f584e469 --- /dev/null +++ b/src/tests/ofc24/tempOC/files/platform_t2.xml @@ -0,0 +1,311 @@ + + + + + + device + + device + + + MellanoxSwitch + SSSA-CNIT + 1.0.0 + 1.0.0 + 1.0.0 + 610610 + typex:OPERATING_SYSTEM + + + + channel-6 + + channel-6 + + + channel-6 + typex:OPTICAL_CHANNEL + + + + 191600000 + 100 + 0 + transceiver-6 + + + 191600000 + 0 + 0 + transceiver-6 + 1 + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + + + + transceiver-6 + + transceiver-6 + + + transceiver-6 + typex:TRANSCEIVER + + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + Cisco + 400zr-QSFP-DD + 01 + 1567321 + + + + 1 + + 1 + channel-6 + + + + + + + + port-6 + + port-6 + + + port-6 + typex:PORT + + + + channel-6 + + channel-6 + + + channel-6 + + + + + + onos-index + + onos-index + 4 + + + onos-index + 4 + + + + odtn-port-type + + odtn-port-type + line + + + odtn-port-type + line + + + + + + + + + + + + 4 + + 4 + Logical channel 4 + DISABLED + type:PROT_OTN + NONE + + + 4 + Logical channel 4 + DISABLED + type:PROT_OTN + NONE + UP + + + + transceiver-6 + + + transceiver-6 + + + + + test1 + test1 + + + test1 + test1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + + + + 1 + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-6 + + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-6 + + + + + + + + 1 + + 1 + FEC1 + Ericsson + + + + 2 + + 2 + FEC2 + Ericsson + + + + + diff --git a/src/tests/ofc24/tempOC/files/startNetconfAgent.sh b/src/tests/ofc24/tempOC/files/startNetconfAgent.sh new file mode 100644 index 0000000000000000000000000000000000000000..1a03290d097db6f09ad5e1efc7fa92f6d7bbcedf --- /dev/null +++ b/src/tests/ofc24/tempOC/files/startNetconfAgent.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# 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 + +make clean +make all +#make init +cp init_openconfig-platform.xml confd-cdb/ +#cp init_flex-scale-mg-on.xml confd-cdb/ +make start2 diff --git a/src/tests/ofc24/tempOC/files/transponders_x4.xml b/src/tests/ofc24/tempOC/files/transponders_x4.xml new file mode 100644 index 0000000000000000000000000000000000000000..b7fa5868e182b11195caff5601feaa54104fcb7f --- /dev/null +++ b/src/tests/ofc24/tempOC/files/transponders_x4.xml @@ -0,0 +1,1055 @@ + + + + + + device + + device + + + MellanoxSwitch + SSSA-CNIT + 1.0.0 + 1.0.0 + 1.0.0 + 610610 + typex:OPERATING_SYSTEM + + + + channel-1 + + channel-1 + + + channel-1 + typex:OPTICAL_CHANNEL + + + + 191600000 + 100 + 0 + transceiver-1 + + + 191600000 + 0 + 0 + transceiver-1 + 1 + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + + + + channel-2 + + channel-2 + + + channel-2 + typex:OPTICAL_CHANNEL + + + + 191600000 + 100 + 0 + transceiver-2 + + + 191600000 + 0 + 0 + transceiver-2 + 1 + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + + + + channel-3 + + channel-3 + + + channel-3 + typex:OPTICAL_CHANNEL + + + + 191600000 + 100 + 0 + transceiver-3 + + + 191600000 + 0 + 0 + transceiver-3 + 1 + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + + + + channel-4 + + channel-4 + + + channel-4 + typex:OPTICAL_CHANNEL + + + + 191600000 + 100 + 0 + transceiver-4 + + + 191600000 + 0 + 0 + transceiver-4 + 1 + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + + + + transceiver-1 + + transceiver-1 + + + transceiver-1 + typex:TRANSCEIVER + + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + Cisco + 400zr-QSFP-DD + 01 + 1567321 + + + + 1 + + 1 + channel-1 + + + + + + + transceiver-2 + + transceiver-2 + + + transceiver-2 + typex:TRANSCEIVER + + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + Cisco + 400zr-QSFP-DD + 01 + 1567321 + + + + 1 + + 1 + channel-2 + + + + + + + transceiver-3 + + transceiver-3 + + + transceiver-3 + typex:TRANSCEIVER + + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + Cisco + 400zr-QSFP-DD + 01 + 1567321 + + + + 1 + + 1 + channel-3 + + + + + + + + transceiver-4 + + transceiver-4 + + + transceiver-4 + typex:TRANSCEIVER + + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + Cisco + 400zr-QSFP-DD + 01 + 1567321 + + + + 1 + + 1 + channel-4 + + + + + + + port-1 + + port-1 + + + port-1 + typex:PORT + + + + channel-1 + + channel-1 + + + channel-1 + + + + + + onos-index + + onos-index + 1 + + + onos-index + 1 + + + + odtn-port-type + + odtn-port-type + line + + + odtn-port-type + line + + + + + + port-2 + + port-2 + + + port-2 + typex:PORT + + + + channel-2 + + channel-2 + + + channel-2 + + + + + + onos-index + + onos-index + 2 + + + onos-index + 2 + + + + odtn-port-type + + odtn-port-type + line + + + odtn-port-type + line + + + + + + port-3 + + port-3 + + + port-3 + typex:PORT + + + + channel-3 + + channel-3 + + + channel-3 + + + + + + onos-index + + onos-index + 3 + + + onos-index + 3 + + + + odtn-port-type + + odtn-port-type + line + + + odtn-port-type + line + + + + + + port-4 + + port-4 + + + port-4 + typex:PORT + + + + channel-4 + + channel-4 + + + channel-4 + + + + + + onos-index + + onos-index + 4 + + + onos-index + 4 + + + + odtn-port-type + + odtn-port-type + line + + + odtn-port-type + line + + + + + + + + + + + 1 + + 1 + Logical channel 1 + DISABLED + type:PROT_OTN + NONE + + + 1 + Logical channel 1 + DISABLED + type:PROT_OTN + NONE + UP + + + + transceiver-1 + + + transceiver-1 + + + + + test1 + test1 + + + test1 + test1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + + + + 1 + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-1 + + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-1 + + + + + + + + 2 + + 2 + Logical channel 2 + DISABLED + type:PROT_OTN + NONE + + + 2 + Logical channel 2 + DISABLED + type:PROT_OTN + NONE + UP + + + + transceiver-2 + + + transceiver-2 + + + + + test1 + test1 + + + test1 + test1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + + + + 1 + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-2 + + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-2 + + + + + + + + 3 + + 3 + Logical channel 3 + DISABLED + type:PROT_OTN + NONE + + + 3 + Logical channel 3 + DISABLED + type:PROT_OTN + NONE + UP + + + + transceiver-3 + + + transceiver-3 + + + + + test1 + test1 + + + test1 + test1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + + + + 1 + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-3 + + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-3 + + + + + + + + 4 + + 4 + Logical channel 4 + DISABLED + type:PROT_OTN + NONE + + + 4 + Logical channel 4 + DISABLED + type:PROT_OTN + NONE + UP + + + + transceiver-4 + + + transceiver-4 + + + + + test1 + test1 + + + test1 + test1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + + + + 1 + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-4 + + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-4 + + + + + + + + 1 + + 1 + FEC1 + Ericsson + + + + 2 + + 2 + FEC2 + Ericsson + + + + + + diff --git a/src/tests/ofc24/tempOC/files/transponders_x4_2.xml b/src/tests/ofc24/tempOC/files/transponders_x4_2.xml new file mode 100644 index 0000000000000000000000000000000000000000..3231dd95f7f7eb2cd0c3c93d6f13e5dfc9f57059 --- /dev/null +++ b/src/tests/ofc24/tempOC/files/transponders_x4_2.xml @@ -0,0 +1,1055 @@ + + + + + + device + + device + + + MellanoxSwitch + SSSA-CNIT + 1.0.0 + 1.0.0 + 1.0.0 + 610610 + typex:OPERATING_SYSTEM + + + + channel-5 + + channel-5 + + + channel-5 + typex:OPTICAL_CHANNEL + + + + 191600000 + 100 + 0 + transceiver-5 + + + 191600000 + 0 + 0 + transceiver-5 + 1 + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + + + + channel-6 + + channel-6 + + + channel-6 + typex:OPTICAL_CHANNEL + + + + 191600000 + 100 + 0 + transceiver-6 + + + 191600000 + 0 + 0 + transceiver-6 + 1 + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + + + + channel-7 + + channel-7 + + + channel-7 + typex:OPTICAL_CHANNEL + + + + 191600000 + 100 + 0 + transceiver-7 + + + 191600000 + 0 + 0 + transceiver-7 + 1 + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + + + + channel-8 + + channel-8 + + + channel-8 + typex:OPTICAL_CHANNEL + + + + 191600000 + 100 + 0 + transceiver-8 + + + 191600000 + 0 + 0 + transceiver-8 + 1 + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + 0 + 0 + 0 + + + + + + transceiver-5 + + transceiver-5 + + + transceiver-5 + typex:TRANSCEIVER + + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + Cisco + 400zr-QSFP-DD + 01 + 1567321 + + + + 1 + + 1 + channel-5 + + + + + + + transceiver-6 + + transceiver-6 + + + transceiver-6 + typex:TRANSCEIVER + + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + Cisco + 400zr-QSFP-DD + 01 + 1567321 + + + + 1 + + 1 + channel-6 + + + + + + + transceiver-7 + + transceiver-7 + + + transceiver-7 + typex:TRANSCEIVER + + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + Cisco + 400zr-QSFP-DD + 01 + 1567321 + + + + 1 + + 1 + channel-7 + + + + + + + + transceiver-8 + + transceiver-8 + + + transceiver-8 + typex:TRANSCEIVER + + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + + + true + typex:QSFP56_DD_TYPE1 + typex:ETH_400GBASE_ZR + typex:FEC_AUTO + typex:TYPE_DIGITAL_COHERENT_OPTIC + Cisco + 400zr-QSFP-DD + 01 + 1567321 + + + + 1 + + 1 + channel-8 + + + + + + + port-5 + + port-5 + + + port-5 + typex:PORT + + + + channel-5 + + channel-5 + + + channel-5 + + + + + + onos-index + + onos-index + 5 + + + onos-index + 5 + + + + odtn-port-type + + odtn-port-type + line + + + odtn-port-type + line + + + + + + port-6 + + port-6 + + + port-6 + typex:PORT + + + + channel-6 + + channel-6 + + + channel-6 + + + + + + onos-index + + onos-index + 6 + + + onos-index + 6 + + + + odtn-port-type + + odtn-port-type + line + + + odtn-port-type + line + + + + + + port-7 + + port-7 + + + port-7 + typex:PORT + + + + channel-7 + + channel-7 + + + channel-7 + + + + + + onos-index + + onos-index + 7 + + + onos-index + 7 + + + + odtn-port-type + + odtn-port-type + line + + + odtn-port-type + line + + + + + + port-8 + + port-8 + + + port-8 + typex:PORT + + + + channel-8 + + channel-8 + + + channel-8 + + + + + + onos-index + + onos-index + 8 + + + onos-index + 8 + + + + odtn-port-type + + odtn-port-type + line + + + odtn-port-type + line + + + + + + + + + + + 5 + + 5 + Logical channel 5 + DISABLED + type:PROT_OTN + NONE + + + 5 + Logical channel 5 + DISABLED + type:PROT_OTN + NONE + UP + + + + transceiver-5 + + + transceiver-5 + + + + + test1 + test1 + + + test1 + test1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + + + + 1 + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-5 + + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-5 + + + + + + + + 6 + + 6 + Logical channel 6 + DISABLED + type:PROT_OTN + NONE + + + 6 + Logical channel 6 + DISABLED + type:PROT_OTN + NONE + UP + + + + transceiver-6 + + + transceiver-6 + + + + + test1 + test1 + + + test1 + test1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + + + + 1 + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-6 + + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-6 + + + + + + + + 7 + + 7 + Logical channel 7 + DISABLED + type:PROT_OTN + NONE + + + 7 + Logical channel 7 + DISABLED + type:PROT_OTN + NONE + UP + + + + transceiver-7 + + + transceiver-7 + + + + + test1 + test1 + + + test1 + test1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + + + + 1 + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-7 + + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-7 + + + + + + + + 8 + + 8 + Logical channel 8 + DISABLED + type:PROT_OTN + NONE + + + 8 + Logical channel 8 + DISABLED + type:PROT_OTN + NONE + UP + + + + transceiver-8 + + + transceiver-8 + + + + + test1 + test1 + + + test1 + test1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + 0.0 + 0.0 + 0.0 + 0.0 + 0 + + + + + + 1 + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-8 + + + 1 + Optical channel assigned 100 + 100 + OPTICAL_CHANNEL + channel-8 + + + + + + + + 1 + + 1 + FEC1 + Ericsson + + + + 2 + + 2 + FEC2 + Ericsson + + + + + + diff --git a/src/tests/ofc24/tests/__init__.py b/src/tests/ofc24/tests/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/tests/ofc24/tests/__init__.py +++ b/src/tests/ofc24/tests/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/ofc24/tests/test_functional_bootstrap.py b/src/tests/ofc24/tests/test_functional_bootstrap.py index c82e751f9a956f92ff5892aaa4d7bb2deff7d8f3..274ab1c3fc9d1548a12366562a864c505784b0ba 100644 --- a/src/tests/ofc24/tests/test_functional_bootstrap.py +++ b/src/tests/ofc24/tests/test_functional_bootstrap.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -16,6 +16,7 @@ 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.grpc.Tools import grpc_message_to_json, grpc_message_to_json_string from common.tools.object_factory.Context import json_context_id from context.client.ContextClient import ContextClient from device.client.DeviceClient import DeviceClient @@ -59,9 +60,15 @@ def test_scenario_devices_enabled( response = context_client.ListDevices(Empty()) num_devices = len(response.devices) num_devices_enabled = 0 + disabled_devices = list() for device in response.devices: - if device.device_operational_status != DEVICE_OP_STATUS_ENABLED: continue - num_devices_enabled += 1 + if device.device_operational_status == DEVICE_OP_STATUS_ENABLED: + num_devices_enabled += 1 + else: + disabled_devices.append(grpc_message_to_json(device)) LOGGER.info('Num Devices enabled: {:d}/{:d}'.format(num_devices_enabled, num_devices)) num_retry += 1 + if num_devices_enabled != num_devices: + LOGGER.info('Disabled Devices: {:s}'.format(str(disabled_devices))) + LOGGER.info('Devices: {:s}'.format(grpc_message_to_json_string(response))) assert num_devices_enabled == num_devices diff --git a/src/tests/ofc24/tests/test_functional_cleanup.py b/src/tests/ofc24/tests/test_functional_cleanup.py index 3d08409b4e43b2de1f1265b4f78356fef5766aa0..a482c6e46559a97e3d194c6eb9dbc0a092cc39d4 100644 --- a/src/tests/ofc24/tests/test_functional_cleanup.py +++ b/src/tests/ofc24/tests/test_functional_cleanup.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/ofc24/tests/test_functional_create_service_bidir.py b/src/tests/ofc24/tests/test_functional_create_service_bidir.py index c81f423d45a356b76ac2aff1b7e80c576a58760e..83b20b7f7dc5de56813f4fc780264ebb9faf7430 100644 --- a/src/tests/ofc24/tests/test_functional_create_service_bidir.py +++ b/src/tests/ofc24/tests/test_functional_create_service_bidir.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/ofc24/tests/test_functional_create_service_unidir.py b/src/tests/ofc24/tests/test_functional_create_service_unidir.py index a52af6d1f94d42600fa6e6ac0d6dfa9314292f91..4982b5a328a6b0c157d890fabbdc4e2f34fc713c 100644 --- a/src/tests/ofc24/tests/test_functional_create_service_unidir.py +++ b/src/tests/ofc24/tests/test_functional_create_service_unidir.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/ofc24/tests/test_functional_delete_service_bidir.py b/src/tests/ofc24/tests/test_functional_delete_service_bidir.py index 3aa1926c08d654c17dc980bd99fc47df965211be..20848a00013e570854fefc242fcae240fcf342db 100644 --- a/src/tests/ofc24/tests/test_functional_delete_service_bidir.py +++ b/src/tests/ofc24/tests/test_functional_delete_service_bidir.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/ofc24/tests/test_functional_delete_service_unidir.py b/src/tests/ofc24/tests/test_functional_delete_service_unidir.py index fdfcdec29498b6c7ca92dff3505afec2c9089ec2..3d375201f22a533f44c4b1a03d98075b385633f0 100644 --- a/src/tests/ofc24/tests/test_functional_delete_service_unidir.py +++ b/src/tests/ofc24/tests/test_functional_delete_service_unidir.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -69,9 +69,30 @@ def test_service_removal_unidir( assert len(context_service_uuids) == 1 context_uuid, service_uuid = set(context_service_uuids).pop() - # Delete Service + # NOTE: For optical bands, the service needs to be removed twice, + # first time for the lightpath, second for the optical band. + + # Check there is exactly 1 service + response = context_client.ListServices(ADMIN_CONTEXT_ID) + LOGGER.warning('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response))) + assert len(response.services) == 1 + + # Delete Service (lightpath) + service_client.DeleteService(ServiceId(**json_service_id(service_uuid, json_context_id(context_uuid)))) + + # Check there is exactly 1 service + response = context_client.ListServices(ADMIN_CONTEXT_ID) + LOGGER.warning('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response))) + assert len(response.services) == 1 + + # Delete Service (optical band) service_client.DeleteService(ServiceId(**json_service_id(service_uuid, json_context_id(context_uuid)))) + # Check there are no services + response = context_client.ListServices(ADMIN_CONTEXT_ID) + LOGGER.warning('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response))) + assert len(response.services) == 0 + # Verify the scenario has no services/slices response = context_client.GetContext(ADMIN_CONTEXT_ID) assert len(response.service_ids) == 0 diff --git a/src/tests/ofc24/transponders.sh b/src/tests/ofc24/transponders.sh new file mode 100644 index 0000000000000000000000000000000000000000..6af230b58cba5ed9db11494f9121e33a3d6a41a6 --- /dev/null +++ b/src/tests/ofc24/transponders.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# 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. + + +docker stop -t 1 tna1 +docker stop -t 1 tna2 + +docker rm tna1 +docker rm tna2 + + + +screen -dmS tt1 -T xterm sh -c "docker run --name tna1 -p 10.0.2.4:2023:2022 -v /home/tfs/tfs-ctrl/src/tests/ofc24/tempOC/files:/files -it asgamb1/oc23bgp.img:latest bash -c 'cp /files/platform_t1.xml demoECOC21.xml ; ./startNetconfAgent.sh'" +screen -dmS tt2 -T xterm sh -c "docker run --name tna2 -p 10.0.2.4:2024:2022 -v /home/tfs/tfs-ctrl/src/tests/ofc24/tempOC/files:/files -it asgamb1/oc23bgp.img:latest bash -c 'cp /files/platform_t2.xml demoECOC21.xml ; ./startNetconfAgent.sh'" diff --git a/src/tests/p4-fwd-l1/README.md b/src/tests/p4-fwd-l1/README.md new file mode 100644 index 0000000000000000000000000000000000000000..b7da0fd88c6b54e4210d5f0d6664ae1ce219fafb --- /dev/null +++ b/src/tests/p4-fwd-l1/README.md @@ -0,0 +1,47 @@ +# Tests for P4 functionality of TeraFlowSDN + +This directory contains the necessary scripts and configurations to run tests for a simple port forwarding TFS program atop software-based P4 switches (using Mininet). + +## Prerequisites + +This test requires some custom monitoring services (latency monitoring and probe). +These services are implemented in Rust and can be found in the `./probe` directory. +To build these services on your target platform, follow the instructions in `./probe/probe-tfs/README.md`. + +## Basic scripts + +To run the experiments you should use the five scripts in the following order: + +```shell +setup.sh +run_test_01_bootstrap.sh +run_test_02_create_service.sh +run_test_03_delete_service.sh +run_test_04_cleanup.sh +``` + +The `setup` script copies the necessary artefacts to the SBI service pod. It should be run just once, after a fresh install of TFS. +The `bootstrap` script registers the context, topology, links, and devices to TFS. +The `create` service script establishes a service between two endpoints. +The `delete` service script deletes the aforementioned service. +The `cleanup` script deletes all the objects (context, topology, links, and devices) from TFS. + +## Objects file + +The above bash scripts make use of the corresponding python scripts found under `./tests/` directory. +More important is the `./tests/Objects.py` file, which contains the definition of the Context, Topology, Devices, Links, Services. **This is the file that needs changes in case of a new topology.** + +Check the `./tests/Objects.py` file before running the experiment to make sure that the switches' details are correct (ip address, port, etc.) + +## Mininet topologies + +In the `./mininet/` directory there are different mininet topology examples. The current `./tests/Objects.py` file corresponds to the `./mininet/8switch3path.py` topology. Additionally there is a backup file `./tests/topologies/6switchObjects.py` which corresponds to the `./mininet/6switch2path.py`. + +## P4 artefacts + +In the `./p4/` directory there are compiled p4 artefacts of the pipeline that will be pushed to the p4 switch, along with the p4-runtime definitions. +The `./setup.sh` script copies from this directory. So if you need to change p4 program, make sure to put the compiled artefacts there. + +## Latency probe + +In the `./probe/` directory there is a little program which calculates latency between two hosts in mininet and sends these measurements to the Monitoring component. For specific instructions, refer to the corresponding `./probe/README.md` file. diff --git a/src/tests/p4-fwd-l1/__init__.py b/src/tests/p4-fwd-l1/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..53d5157f750bfb085125cbd33faff1cec5924e14 --- /dev/null +++ b/src/tests/p4-fwd-l1/__init__.py @@ -0,0 +1,14 @@ +# 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. + diff --git a/src/tests/p4/deploy_specs.sh b/src/tests/p4-fwd-l1/deploy_specs.sh similarity index 94% rename from src/tests/p4/deploy_specs.sh rename to src/tests/p4-fwd-l1/deploy_specs.sh index 5a3097610d2ac386f80541b8628c841479c44226..8004973e6210c4cec00792d7d605a276443712ca 100755 --- a/src/tests/p4/deploy_specs.sh +++ b/src/tests/p4-fwd-l1/deploy_specs.sh @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/p4/mininet/1switch1path.py b/src/tests/p4-fwd-l1/mininet/1switch1path.py similarity index 100% rename from src/tests/p4/mininet/1switch1path.py rename to src/tests/p4-fwd-l1/mininet/1switch1path.py diff --git a/src/tests/p4/mininet/2switch1path.py b/src/tests/p4-fwd-l1/mininet/2switch1path.py similarity index 99% rename from src/tests/p4/mininet/2switch1path.py rename to src/tests/p4-fwd-l1/mininet/2switch1path.py index 91db70052a95dea9b53d24dabb25b0feaa9935cf..d782d1085babd2f47b2b23f538950d5e7189f45a 100644 --- a/src/tests/p4/mininet/2switch1path.py +++ b/src/tests/p4-fwd-l1/mininet/2switch1path.py @@ -73,12 +73,12 @@ class TutorialTopo(Topo): def main(): net = Mininet(topo=TutorialTopo(), controller=None) net.start() - + client = net.hosts[0] client.setARP('10.0.0.2', 'aa:bb:cc:dd:ee:22') server = net.hosts[1] server.setARP('10.0.0.1', 'aa:bb:cc:dd:ee:11') - + CLI(net) net.stop() print '#' * 80 diff --git a/src/tests/p4/mininet/4switch2path.py b/src/tests/p4-fwd-l1/mininet/4switch2path.py similarity index 99% rename from src/tests/p4/mininet/4switch2path.py rename to src/tests/p4-fwd-l1/mininet/4switch2path.py index d8ad04b0193a2b9b610a4d5f828891e575d8efe8..0c0fa578b470a059cb896c22429379fc59982a2a 100644 --- a/src/tests/p4/mininet/4switch2path.py +++ b/src/tests/p4-fwd-l1/mininet/4switch2path.py @@ -70,13 +70,13 @@ class TutorialTopo(Topo): ip='10.0.0.1/24', gw='10.0.0.100') server = self.addHost('server', cls=IPv4Host, mac="aa:bb:cc:dd:ee:22", ip='10.0.0.2/24', gw='10.0.0.100') - + # Switch links self.addLink(switch1, switch2) # Switch1:port 1, Switch2:port 1 self.addLink(switch1, switch3) # Switch1:port 2, Switch3:port 1 self.addLink(switch2, switch4) # Switch2:port 2, Switch4:port 1 self.addLink(switch3, switch4) # Switch3:port 2, Switch4:port 2 - + # Host links self.addLink(client, switch1) # Switch 1: port 3 self.addLink(server, switch4) # Switch 4: port 3 @@ -84,12 +84,12 @@ class TutorialTopo(Topo): def main(): net = Mininet(topo=TutorialTopo(), controller=None) net.start() - + client = net.hosts[0] client.setARP('10.0.0.2', 'aa:bb:cc:dd:ee:22') server = net.hosts[1] server.setARP('10.0.0.1', 'aa:bb:cc:dd:ee:11') - + CLI(net) net.stop() print '#' * 80 diff --git a/src/tests/p4/mininet/6switch2path.py b/src/tests/p4-fwd-l1/mininet/6switch2path.py similarity index 99% rename from src/tests/p4/mininet/6switch2path.py rename to src/tests/p4-fwd-l1/mininet/6switch2path.py index 8efb4b017f8c71e55884db8dd5f805820bb65fd6..b98c0e9608b7ebd346a264d5b2153e9ef099f4e1 100644 --- a/src/tests/p4/mininet/6switch2path.py +++ b/src/tests/p4-fwd-l1/mininet/6switch2path.py @@ -74,7 +74,7 @@ class TutorialTopo(Topo): ip='10.0.0.1/24', gw='10.0.0.100') server = self.addHost('server', cls=IPv4Host, mac="aa:bb:cc:dd:ee:22", ip='10.0.0.2/24', gw='10.0.0.100') - + # Switch links self.addLink(switch1, switch2) # Switch1:port 1, Switch2:port 1 self.addLink(switch1, switch3) # Switch1:port 2, Switch3:port 1 @@ -84,7 +84,7 @@ class TutorialTopo(Topo): self.addLink(switch4, switch6) # Switch4:port 2, Switch6:port 1 self.addLink(switch5, switch6) # Switch5:port 2, Switch6:port 2 - + # Host links self.addLink(client, switch1) # Switch1: port 3 self.addLink(server, switch6) # Switch6: port 3 @@ -92,12 +92,12 @@ class TutorialTopo(Topo): def main(): net = Mininet(topo=TutorialTopo(), controller=None) net.start() - + client = net.hosts[0] client.setARP('10.0.0.2', 'aa:bb:cc:dd:ee:22') server = net.hosts[1] server.setARP('10.0.0.1', 'aa:bb:cc:dd:ee:11') - + CLI(net) net.stop() print '#' * 80 diff --git a/src/tests/p4/mininet/8switch3path.py b/src/tests/p4-fwd-l1/mininet/8switch3path.py similarity index 97% rename from src/tests/p4/mininet/8switch3path.py rename to src/tests/p4-fwd-l1/mininet/8switch3path.py index 20322fac9ce364cd21ea6a8eb1d68ee736dcd524..d1ae15490de15abc43972140d7591791050819cf 100755 --- a/src/tests/p4/mininet/8switch3path.py +++ b/src/tests/p4-fwd-l1/mininet/8switch3path.py @@ -1,6 +1,6 @@ #!/usr/bin/python -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# Copyright 2022-2024 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) # Copyright 2019-present Open Networking Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -79,7 +79,7 @@ class TutorialTopo(Topo): ip='10.0.0.1/24', gw='10.0.0.100') server = self.addHost('server', cls=IPv4Host, mac="aa:bb:cc:dd:ee:22", ip='10.0.0.2/24', gw='10.0.0.100') - + # Switch links self.addLink(switch1, switch2) # Switch1:port 1, Switch2:port 1 self.addLink(switch1, switch4) # Switch1:port 2, Switch4:port 1 @@ -92,7 +92,7 @@ class TutorialTopo(Topo): self.addLink(switch3, switch8) # Switch3:port 2, Switch8:port 1 self.addLink(switch5, switch8) # Switch5:port 2, Switch8:port 2 self.addLink(switch7, switch8) # Switch7:port 2, Switch8:port 3 - + # Host links self.addLink(client, switch1) # Switch1: port 4 self.addLink(server, switch8) # Switch8: port 4 @@ -100,13 +100,13 @@ class TutorialTopo(Topo): def main(): net = Mininet(topo=TutorialTopo(), controller=None) net.start() - + #get hosts client = net.hosts[0] client.setARP('10.0.0.2', 'aa:bb:cc:dd:ee:22') server = net.hosts[1] server.setARP('10.0.0.1', 'aa:bb:cc:dd:ee:11') - + CLI(net) net.stop() print '#' * 80 diff --git a/src/tests/p4/p4/bmv2.json b/src/tests/p4-fwd-l1/p4/bmv2.json similarity index 100% rename from src/tests/p4/p4/bmv2.json rename to src/tests/p4-fwd-l1/p4/bmv2.json diff --git a/src/tests/p4/p4/main.p4 b/src/tests/p4-fwd-l1/p4/main.p4 similarity index 100% rename from src/tests/p4/p4/main.p4 rename to src/tests/p4-fwd-l1/p4/main.p4 diff --git a/src/tests/p4/p4/p4info.txt b/src/tests/p4-fwd-l1/p4/p4info.txt similarity index 100% rename from src/tests/p4/p4/p4info.txt rename to src/tests/p4-fwd-l1/p4/p4info.txt diff --git a/src/tests/p4/probe/README.md b/src/tests/p4-fwd-l1/probe/README.md similarity index 100% rename from src/tests/p4/probe/README.md rename to src/tests/p4-fwd-l1/probe/README.md diff --git a/src/tests/p4/probe/monitoring_kpis.ipynb b/src/tests/p4-fwd-l1/probe/monitoring_kpis.ipynb similarity index 100% rename from src/tests/p4/probe/monitoring_kpis.ipynb rename to src/tests/p4-fwd-l1/probe/monitoring_kpis.ipynb diff --git a/src/tests/p4/probe/monitoring_kpis.py b/src/tests/p4-fwd-l1/probe/monitoring_kpis.py similarity index 97% rename from src/tests/p4/probe/monitoring_kpis.py rename to src/tests/p4-fwd-l1/probe/monitoring_kpis.py index 25a1eab66bc4bc2b9567879a395d33ae3eea6689..dc3757718d5a973e1629de63f7e61a09998842c1 100644 --- a/src/tests/p4/probe/monitoring_kpis.py +++ b/src/tests/p4-fwd-l1/probe/monitoring_kpis.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/p4/probe/probe-tfs/.gitignore b/src/tests/p4-fwd-l1/probe/probe-tfs/.gitignore similarity index 100% rename from src/tests/p4/probe/probe-tfs/.gitignore rename to src/tests/p4-fwd-l1/probe/probe-tfs/.gitignore diff --git a/src/tests/p4/probe/probe-tfs/Cargo.toml b/src/tests/p4-fwd-l1/probe/probe-tfs/Cargo.toml similarity index 93% rename from src/tests/p4/probe/probe-tfs/Cargo.toml rename to src/tests/p4-fwd-l1/probe/probe-tfs/Cargo.toml index 5ee07d7844ea4a2b42970f9ff09c6dc5db22207c..da64d7a325d690666ca285fc9621ce3edaa52425 100644 --- a/src/tests/p4/probe/probe-tfs/Cargo.toml +++ b/src/tests/p4-fwd-l1/probe/probe-tfs/Cargo.toml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/p4/probe/probe-tfs/LICENSE b/src/tests/p4-fwd-l1/probe/probe-tfs/LICENSE similarity index 100% rename from src/tests/p4/probe/probe-tfs/LICENSE rename to src/tests/p4-fwd-l1/probe/probe-tfs/LICENSE diff --git a/src/tests/p4-fwd-l1/probe/probe-tfs/README.md b/src/tests/p4-fwd-l1/probe/probe-tfs/README.md new file mode 100644 index 0000000000000000000000000000000000000000..3cff11314ee92db79d7b56c03e38a8a7f2acadec --- /dev/null +++ b/src/tests/p4-fwd-l1/probe/probe-tfs/README.md @@ -0,0 +1,21 @@ +# Rust-tfs + +Client for TFS functionalities written in Rust. + +## Dependencies + +This project requires the cargo Rust compiler: + +```sh +sudo apt-get install protobuf-compiler cargo +``` + +## Build + +Build sources as follows: + +```sh +cargo build +``` + +After a successfuly build, two new executables will be generated in `target/`. diff --git a/src/tests/p4/probe/probe-tfs/build.rs b/src/tests/p4-fwd-l1/probe/probe-tfs/build.rs similarity index 93% rename from src/tests/p4/probe/probe-tfs/build.rs rename to src/tests/p4-fwd-l1/probe/probe-tfs/build.rs index 0d9af6c48a1017e99976948f4824041a2d54f25d..4da300f68f40ac7d6cb4eacfeab90d9003675cd4 100644 --- a/src/tests/p4/probe/probe-tfs/build.rs +++ b/src/tests/p4-fwd-l1/probe/probe-tfs/build.rs @@ -1,5 +1,5 @@ /** - * Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) + * 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. diff --git a/src/tests/p4/probe/probe-tfs/connect_to_mininet.sh b/src/tests/p4-fwd-l1/probe/probe-tfs/connect_to_mininet.sh similarity index 89% rename from src/tests/p4/probe/probe-tfs/connect_to_mininet.sh rename to src/tests/p4-fwd-l1/probe/probe-tfs/connect_to_mininet.sh index 2a71cbb151d4f4c2249d801773341289aedc32dc..86a823ed964482e08deba3aaa6f71c753f4ebb98 100755 --- a/src/tests/p4/probe/probe-tfs/connect_to_mininet.sh +++ b/src/tests/p4-fwd-l1/probe/probe-tfs/connect_to_mininet.sh @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/p4/probe/probe-tfs/deploy.sh b/src/tests/p4-fwd-l1/probe/probe-tfs/deploy.sh similarity index 95% rename from src/tests/p4/probe/probe-tfs/deploy.sh rename to src/tests/p4-fwd-l1/probe/probe-tfs/deploy.sh index c18e96559d8d90f9328fe7c77fa66c2ca374665f..d88549a12c1cad339455d161871245849c5f57a1 100755 --- a/src/tests/p4/probe/probe-tfs/deploy.sh +++ b/src/tests/p4-fwd-l1/probe/probe-tfs/deploy.sh @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/p4/probe/probe-tfs/proto b/src/tests/p4-fwd-l1/probe/probe-tfs/proto similarity index 100% rename from src/tests/p4/probe/probe-tfs/proto rename to src/tests/p4-fwd-l1/probe/probe-tfs/proto diff --git a/src/tests/p4/probe/probe-tfs/src/agent.rs b/src/tests/p4-fwd-l1/probe/probe-tfs/src/agent.rs similarity index 98% rename from src/tests/p4/probe/probe-tfs/src/agent.rs rename to src/tests/p4-fwd-l1/probe/probe-tfs/src/agent.rs index 749e42a6c81ce0523ae2cf52a29e9c90c43f48e7..a9b8e5a609f08622d45ef72e05421508807b505b 100644 --- a/src/tests/p4/probe/probe-tfs/src/agent.rs +++ b/src/tests/p4-fwd-l1/probe/probe-tfs/src/agent.rs @@ -1,5 +1,5 @@ /** - * Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) + * 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. @@ -195,6 +195,7 @@ async fn main() -> Result<(), Box> { endpoint_id: None, slice_id: None, connection_id: None, + link_id: None, kpi_description: format!( "Latency value for service {}", event_service.service_uuid.unwrap().uuid diff --git a/src/tests/p4/probe/probe-tfs/src/ping.rs b/src/tests/p4-fwd-l1/probe/probe-tfs/src/ping.rs similarity index 96% rename from src/tests/p4/probe/probe-tfs/src/ping.rs rename to src/tests/p4-fwd-l1/probe/probe-tfs/src/ping.rs index bec984b66cb24ee6e6f3dc707fe9cd392b5ebb28..cb192586bcb1555f6bda47f201346a8ee679cb7c 100644 --- a/src/tests/p4/probe/probe-tfs/src/ping.rs +++ b/src/tests/p4-fwd-l1/probe/probe-tfs/src/ping.rs @@ -1,5 +1,5 @@ /** - * Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) + * 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. diff --git a/src/tests/p4/run_test_01_bootstrap.sh b/src/tests/p4-fwd-l1/run_test_01_bootstrap.sh similarity index 81% rename from src/tests/p4/run_test_01_bootstrap.sh rename to src/tests/p4-fwd-l1/run_test_01_bootstrap.sh index 60bb20d0d64a41936b58df4e6726d051497216d6..e4b61937e9ab243d4309777b335e232933fae24a 100755 --- a/src/tests/p4/run_test_01_bootstrap.sh +++ b/src/tests/p4-fwd-l1/run_test_01_bootstrap.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -18,5 +18,4 @@ # - tfs_runtime_env_vars.sh source tfs_runtime_env_vars.sh -python -m pytest --verbose src/tests/p4/tests/test_functional_bootstrap.py - +python -m pytest --verbose src/tests/p4-fwd-l1/tests/test_functional_bootstrap.py diff --git a/src/tests/p4/run_test_02_create_service.sh b/src/tests/p4-fwd-l1/run_test_02_create_service.sh similarity index 78% rename from src/tests/p4/run_test_02_create_service.sh rename to src/tests/p4-fwd-l1/run_test_02_create_service.sh index 8246262340f3d2029d8e0a0f41ec9821518cd5bf..52335c299035f6dcd0b0951ecbc71ed69a1fec69 100755 --- a/src/tests/p4/run_test_02_create_service.sh +++ b/src/tests/p4-fwd-l1/run_test_02_create_service.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -14,4 +14,4 @@ # limitations under the License. source tfs_runtime_env_vars.sh -python -m pytest --verbose src/tests/p4/tests/test_functional_create_service.py +python -m pytest --verbose src/tests/p4-fwd-l1/tests/test_functional_create_service.py diff --git a/src/tests/p4/run_test_03_delete_service.sh b/src/tests/p4-fwd-l1/run_test_03_delete_service.sh similarity index 78% rename from src/tests/p4/run_test_03_delete_service.sh rename to src/tests/p4-fwd-l1/run_test_03_delete_service.sh index c4337daea207269586c5f1f698683c37ae98406e..5e11b04856401b9a734321141d59c3d1094e1384 100755 --- a/src/tests/p4/run_test_03_delete_service.sh +++ b/src/tests/p4-fwd-l1/run_test_03_delete_service.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -14,4 +14,4 @@ # limitations under the License. source tfs_runtime_env_vars.sh -python -m pytest --verbose src/tests/p4/tests/test_functional_delete_service.py +python -m pytest --verbose src/tests/p4-fwd-l1/tests/test_functional_delete_service.py diff --git a/src/tests/p4/run_test_04_cleanup.sh b/src/tests/p4-fwd-l1/run_test_04_cleanup.sh similarity index 79% rename from src/tests/p4/run_test_04_cleanup.sh rename to src/tests/p4-fwd-l1/run_test_04_cleanup.sh index f2ebec08b2dbead7fb27522456fb853845578ed8..894446c80cf1aff5c7b9fc45c6ff9aa2c94fc518 100755 --- a/src/tests/p4/run_test_04_cleanup.sh +++ b/src/tests/p4-fwd-l1/run_test_04_cleanup.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -14,4 +14,4 @@ # limitations under the License. source tfs_runtime_env_vars.sh -python -m pytest --verbose src/tests/p4/tests/test_functional_cleanup.py +python -m pytest --verbose src/tests/p4-fwd-l1/tests/test_functional_cleanup.py diff --git a/src/tests/p4/setup.sh b/src/tests/p4-fwd-l1/setup.sh similarity index 75% rename from src/tests/p4/setup.sh rename to src/tests/p4-fwd-l1/setup.sh index 1e6b63c544c5029613f8d9084b61e5fab9e83043..1370c01692a5d872f0334c0fc2986b53cafa8abd 100755 --- a/src/tests/p4/setup.sh +++ b/src/tests/p4-fwd-l1/setup.sh @@ -1,5 +1,5 @@ #! /bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -18,5 +18,5 @@ export POD_NAME=$(kubectl get pods -n=tfs | grep device | awk '{print $1}') kubectl exec ${POD_NAME} -n=tfs -c=server -- mkdir /root/p4 -kubectl cp src/tests/p4/p4/p4info.txt tfs/${POD_NAME}:/root/p4 -c=server -kubectl cp src/tests/p4/p4/bmv2.json tfs/${POD_NAME}:/root/p4 -c=server +kubectl cp src/tests/p4-fwd-l1/p4/p4info.txt tfs/${POD_NAME}:/root/p4 -c=server +kubectl cp src/tests/p4-fwd-l1/p4/bmv2.json tfs/${POD_NAME}:/root/p4 -c=server diff --git a/src/tests/p4/tests/.gitignore b/src/tests/p4-fwd-l1/tests/.gitignore similarity index 100% rename from src/tests/p4/tests/.gitignore rename to src/tests/p4-fwd-l1/tests/.gitignore diff --git a/src/tests/p4/tests/BuildDescriptors.py b/src/tests/p4-fwd-l1/tests/BuildDescriptors.py similarity index 93% rename from src/tests/p4/tests/BuildDescriptors.py rename to src/tests/p4-fwd-l1/tests/BuildDescriptors.py index cfd29eea0cb80306f402ef71530016599b570eb1..c0f01ee7537e88883704e3af36f6c51b672a607e 100644 --- a/src/tests/p4/tests/BuildDescriptors.py +++ b/src/tests/p4-fwd-l1/tests/BuildDescriptors.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/p4/tests/LoadDescriptors.py b/src/tests/p4-fwd-l1/tests/LoadDescriptors.py similarity index 95% rename from src/tests/p4/tests/LoadDescriptors.py rename to src/tests/p4-fwd-l1/tests/LoadDescriptors.py index 407d5b6dc6b46ba7dd920cb1f60be391f839bda7..c47bea18d43c3a71656169cbb3855bd1602240fd 100644 --- a/src/tests/p4/tests/LoadDescriptors.py +++ b/src/tests/p4-fwd-l1/tests/LoadDescriptors.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/p4/tests/Objects.py b/src/tests/p4-fwd-l1/tests/Objects.py similarity index 97% rename from src/tests/p4/tests/Objects.py rename to src/tests/p4-fwd-l1/tests/Objects.py index 6004ea413ec6af3412780bb7b49f03edb0481b7e..ba260e936805e57fb8f07761b1e5fc79cffbaf8f 100644 --- a/src/tests/p4/tests/Objects.py +++ b/src/tests/p4-fwd-l1/tests/Objects.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -60,7 +60,7 @@ DEVICE_SW1 = json_device_p4_disabled(DEVICE_SW1_UUID) DEVICE_SW1_DPID = 1 DEVICE_SW1_NAME = DEVICE_SW1_UUID -DEVICE_SW1_IP_ADDR = '192.168.6.38' +DEVICE_SW1_IP_ADDR = '192.168.5.131' DEVICE_SW1_PORT = '50001' DEVICE_SW1_VENDOR = 'Open Networking Foundation' DEVICE_SW1_HW_VER = 'BMv2 simple_switch' @@ -102,7 +102,7 @@ DEVICE_SW2 = json_device_p4_disabled(DEVICE_SW2_UUID) DEVICE_SW2_DPID = 1 DEVICE_SW2_NAME = DEVICE_SW2_UUID -DEVICE_SW2_IP_ADDR = '192.168.6.38' +DEVICE_SW2_IP_ADDR = '192.168.5.131' DEVICE_SW2_PORT = '50002' DEVICE_SW2_VENDOR = 'Open Networking Foundation' DEVICE_SW2_HW_VER = 'BMv2 simple_switch' @@ -140,7 +140,7 @@ DEVICE_SW3 = json_device_p4_disabled(DEVICE_SW3_UUID) DEVICE_SW3_DPID = 1 DEVICE_SW3_NAME = DEVICE_SW3_UUID -DEVICE_SW3_IP_ADDR = '192.168.6.38' +DEVICE_SW3_IP_ADDR = '192.168.5.131' DEVICE_SW3_PORT = '50003' DEVICE_SW3_VENDOR = 'Open Networking Foundation' DEVICE_SW3_HW_VER = 'BMv2 simple_switch' @@ -178,7 +178,7 @@ DEVICE_SW4 = json_device_p4_disabled(DEVICE_SW4_UUID) DEVICE_SW4_DPID = 1 DEVICE_SW4_NAME = DEVICE_SW4_UUID -DEVICE_SW4_IP_ADDR = '192.168.6.38' +DEVICE_SW4_IP_ADDR = '192.168.5.131' DEVICE_SW4_PORT = '50004' DEVICE_SW4_VENDOR = 'Open Networking Foundation' DEVICE_SW4_HW_VER = 'BMv2 simple_switch' @@ -216,7 +216,7 @@ DEVICE_SW5 = json_device_p4_disabled(DEVICE_SW5_UUID) DEVICE_SW5_DPID = 1 DEVICE_SW5_NAME = DEVICE_SW5_UUID -DEVICE_SW5_IP_ADDR = '192.168.6.38' +DEVICE_SW5_IP_ADDR = '192.168.5.131' DEVICE_SW5_PORT = '50005' DEVICE_SW5_VENDOR = 'Open Networking Foundation' DEVICE_SW5_HW_VER = 'BMv2 simple_switch' @@ -254,7 +254,7 @@ DEVICE_SW6 = json_device_p4_disabled(DEVICE_SW6_UUID) DEVICE_SW6_DPID = 1 DEVICE_SW6_NAME = DEVICE_SW6_UUID -DEVICE_SW6_IP_ADDR = '192.168.6.38' +DEVICE_SW6_IP_ADDR = '192.168.5.131' DEVICE_SW6_PORT = '50006' DEVICE_SW6_VENDOR = 'Open Networking Foundation' DEVICE_SW6_HW_VER = 'BMv2 simple_switch' @@ -292,7 +292,7 @@ DEVICE_SW7 = json_device_p4_disabled(DEVICE_SW7_UUID) DEVICE_SW7_DPID = 1 DEVICE_SW7_NAME = DEVICE_SW7_UUID -DEVICE_SW7_IP_ADDR = '192.168.6.38' +DEVICE_SW7_IP_ADDR = '192.168.5.131' DEVICE_SW7_PORT = '50007' DEVICE_SW7_VENDOR = 'Open Networking Foundation' DEVICE_SW7_HW_VER = 'BMv2 simple_switch' @@ -330,7 +330,7 @@ DEVICE_SW8 = json_device_p4_disabled(DEVICE_SW8_UUID) DEVICE_SW8_DPID = 1 DEVICE_SW8_NAME = DEVICE_SW8_UUID -DEVICE_SW8_IP_ADDR = '192.168.6.38' +DEVICE_SW8_IP_ADDR = '192.168.5.131' DEVICE_SW8_PORT = '50008' DEVICE_SW8_VENDOR = 'Open Networking Foundation' DEVICE_SW8_HW_VER = 'BMv2 simple_switch' @@ -506,7 +506,7 @@ LINKS = [ LINK_SW8_SW3, LINK_SW8_SW5, LINK_SW8_SW7, -] +] SERVICES = [ (SERVICE_SW1_SW8, SERVICE_SW1_SW8_ENDPOINT_IDS), diff --git a/src/tests/p4-fwd-l1/tests/__init__.py b/src/tests/p4-fwd-l1/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..53d5157f750bfb085125cbd33faff1cec5924e14 --- /dev/null +++ b/src/tests/p4-fwd-l1/tests/__init__.py @@ -0,0 +1,14 @@ +# 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. + diff --git a/src/tests/p4/tests/test_functional_bootstrap.py b/src/tests/p4-fwd-l1/tests/test_functional_bootstrap.py similarity index 98% rename from src/tests/p4/tests/test_functional_bootstrap.py rename to src/tests/p4-fwd-l1/tests/test_functional_bootstrap.py index 0f4ea07a370593bf38c8c602311296bc5fb4f2c6..fe622c908b44ed28a5c91ca8b35b8524511de388 100644 --- a/src/tests/p4/tests/test_functional_bootstrap.py +++ b/src/tests/p4-fwd-l1/tests/test_functional_bootstrap.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/p4/tests/test_functional_cleanup.py b/src/tests/p4-fwd-l1/tests/test_functional_cleanup.py similarity index 97% rename from src/tests/p4/tests/test_functional_cleanup.py rename to src/tests/p4-fwd-l1/tests/test_functional_cleanup.py index df279cc2a2736cbb47c5eeb330eccf4ada382c1b..67934ff8a78f79252ef4b6994c3b628a8275c503 100644 --- a/src/tests/p4/tests/test_functional_cleanup.py +++ b/src/tests/p4-fwd-l1/tests/test_functional_cleanup.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/p4/tests/test_functional_create_service.py b/src/tests/p4-fwd-l1/tests/test_functional_create_service.py similarity index 97% rename from src/tests/p4/tests/test_functional_create_service.py rename to src/tests/p4-fwd-l1/tests/test_functional_create_service.py index 516ed8b1c8b9cfb138353167841e0dd80503ca30..9f82da129e159f02d40ee57b890409b0a5685b75 100644 --- a/src/tests/p4/tests/test_functional_create_service.py +++ b/src/tests/p4-fwd-l1/tests/test_functional_create_service.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/p4/tests/test_functional_delete_service.py b/src/tests/p4-fwd-l1/tests/test_functional_delete_service.py similarity index 97% rename from src/tests/p4/tests/test_functional_delete_service.py rename to src/tests/p4-fwd-l1/tests/test_functional_delete_service.py index 8542e671a85511821835a79574d8431c2a3c109e..98b6a01c1be2a00003b3be267839a4513967d4f7 100644 --- a/src/tests/p4/tests/test_functional_delete_service.py +++ b/src/tests/p4-fwd-l1/tests/test_functional_delete_service.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/p4/tests/topologies/6switchObjects.py b/src/tests/p4-fwd-l1/tests/topologies/6switchObjects.py similarity index 99% rename from src/tests/p4/tests/topologies/6switchObjects.py rename to src/tests/p4-fwd-l1/tests/topologies/6switchObjects.py index 395fe58030e29a28029be241f87afa93f5c506cd..522066bb0c4c77fa4e949f68226ebea27d262bcb 100644 --- a/src/tests/p4/tests/topologies/6switchObjects.py +++ b/src/tests/p4-fwd-l1/tests/topologies/6switchObjects.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/p4/README.md b/src/tests/p4/README.md deleted file mode 100644 index 43920d14d5e99214bb2ad8418cc4babcae5be91c..0000000000000000000000000000000000000000 --- a/src/tests/p4/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# Tests for P4 functionality of TeraFlowSDN - -This directory contains the necessary scripts and configurations to run tests for the P4 functionality of TFS. - -## Basic scripts - -To run the experiments you should use the five scripts in the following order: -``` -setup.sh -run_test_01_bootstrap.sh -run_test_02_create_service.sh -run_test_03_delete_service.sh -run_test_04_cleanup.sh -``` - -The setup script copies the necessary artifacts to the SBI service pod. It should be run just once, after a fresh install of TFS. -The bootstrap script registers the context, topology, links and, devices to TFS. -The create service scripts establishes a service between two endpoints. -The delete service script delete the aforementioned service. -Cleanup script deletes all the objects (context, topology, links, devices) from TFS. - -## Objects file - -The above bash scripts make use of the corresponding python scripts found under `./tests/` directory. -More important is the `./tests/Objects.py` file, which contains the definition of the Context, Topology, Devices, Links, Services. **This is the file that need changes in case of a new topology.** - -Check the `./tests/Objects.py` file before running the experiment to make sure that the switches details are correct (ip address, port, etc.) - -## Mininet topologies - -In the `./mininet/` directory there are different mininet topology examples. The current `./tests/Objects.py` file corresponds to the `./mininet/8switch3path.py` topology. Additionally there is a backup file `./tests/topologies/6switchObjects.py` which corresponds to the `./mininet/6switch2path.py`. - -## P4 artifacts - -In the `./p4/` directory there are the compiled p4 artifacts that contain the pipeline that will be pushed to the p4 switch, along with the p4-runtime definitions. -The `./setup.sh` script copies from this directory. So if you need to change p4 program, make sure to put the compiled artifacts here. - -## Latency probe - -In the `./probe/` directory there is a little program which calculates latency between two hosts in mininet and sends them to the Monitoring component. For specific instructions, refer to the corresponding `./probe/README.md` file. - diff --git a/src/tests/p4/probe/probe-tfs/README.md b/src/tests/p4/probe/probe-tfs/README.md deleted file mode 100644 index f88d7c542dae22ad623797f43750e0589d2473cf..0000000000000000000000000000000000000000 --- a/src/tests/p4/probe/probe-tfs/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# rust-tfs -Client for TFS functionalities written in Rust. diff --git a/src/tests/p4/probe/probe-tfs/target/x86_64-unknown-linux-musl/release/tfsagent b/src/tests/p4/probe/probe-tfs/target/x86_64-unknown-linux-musl/release/tfsagent deleted file mode 100755 index b7cef11a433c6bf2eeb94638fa90d93f25acd3c8..0000000000000000000000000000000000000000 Binary files a/src/tests/p4/probe/probe-tfs/target/x86_64-unknown-linux-musl/release/tfsagent and /dev/null differ diff --git a/src/tests/p4/probe/probe-tfs/target/x86_64-unknown-linux-musl/release/tfsping b/src/tests/p4/probe/probe-tfs/target/x86_64-unknown-linux-musl/release/tfsping deleted file mode 100755 index 6e943d292dd6653e857bf5eea3258d38ad246026..0000000000000000000000000000000000000000 Binary files a/src/tests/p4/probe/probe-tfs/target/x86_64-unknown-linux-musl/release/tfsping and /dev/null differ diff --git a/src/tests/scenario2/__init__.py b/src/tests/scenario2/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/tests/scenario2/__init__.py +++ b/src/tests/scenario2/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/delete_all.sh b/src/tests/scenario2/delete_all.sh index a11d668c38f9ca8608170e220fa21555d01f20a0..266b92641597d2de4ef3ce59510a6b0ba070fa28 100755 --- a/src/tests/scenario2/delete_all.sh +++ b/src/tests/scenario2/delete_all.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/deploy_all.sh b/src/tests/scenario2/deploy_all.sh index 1c52068d3fb1aa1afd2cf040734fa381d4fb0207..05553f936e3453de1a0d897003ca7c4be3bc437c 100755 --- a/src/tests/scenario2/deploy_all.sh +++ b/src/tests/scenario2/deploy_all.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/deploy_specs_dom1.sh b/src/tests/scenario2/deploy_specs_dom1.sh index d7557a464608a4741393e6d2d65edaf23a1c0ff2..9eb778cba64d944a5ea2d70a1546c45110fc0200 100755 --- a/src/tests/scenario2/deploy_specs_dom1.sh +++ b/src/tests/scenario2/deploy_specs_dom1.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/deploy_specs_dom2.sh b/src/tests/scenario2/deploy_specs_dom2.sh index d601b2b9bf47274ebd1bc8d1693a67b0693d50b6..88c20171f57a13ba4e3ddd0eef4f8302c2bab382 100755 --- a/src/tests/scenario2/deploy_specs_dom2.sh +++ b/src/tests/scenario2/deploy_specs_dom2.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/deploy_specs_dom3.sh b/src/tests/scenario2/deploy_specs_dom3.sh index 869b4050a62e87315131875f44a947ad036fde03..35209be3b94f6e2574f7435c42e366fd3ad96f33 100755 --- a/src/tests/scenario2/deploy_specs_dom3.sh +++ b/src/tests/scenario2/deploy_specs_dom3.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/deploy_specs_dom4.sh b/src/tests/scenario2/deploy_specs_dom4.sh index 5e119c1a9fc9c632ed2ab74dff80e2f1ddd62d7c..71874b31a814b8401315aca4571f9fe03ec1d5ea 100755 --- a/src/tests/scenario2/deploy_specs_dom4.sh +++ b/src/tests/scenario2/deploy_specs_dom4.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/dump_logs.sh b/src/tests/scenario2/dump_logs.sh index 567617420037a0650b2f5b353a6cb5255a578352..98a4e334c8b64fdb95dd41ad63b7fe93173099f9 100755 --- a/src/tests/scenario2/dump_logs.sh +++ b/src/tests/scenario2/dump_logs.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/fast_redeploy.sh b/src/tests/scenario2/fast_redeploy.sh index 2e1e8a1926bdf8aaec308751d4bf61907210135c..4d57b070918842ccdbbb12dc6688723581ec2a12 100755 --- a/src/tests/scenario2/fast_redeploy.sh +++ b/src/tests/scenario2/fast_redeploy.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/nginx-ingress-controller-dom1.yaml b/src/tests/scenario2/nginx-ingress-controller-dom1.yaml index 70a0f45f4091a4e6ba94fe7e0fb2012bfe63528c..779a5fce8426b71e07a6c4f24e188c74e6df41c0 100644 --- a/src/tests/scenario2/nginx-ingress-controller-dom1.yaml +++ b/src/tests/scenario2/nginx-ingress-controller-dom1.yaml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/nginx-ingress-controller-dom2.yaml b/src/tests/scenario2/nginx-ingress-controller-dom2.yaml index 11e4ccf254d7cb938cd777ce35e77e05eefd604f..d80804508e578c57138ce7e0661b744afd89c52b 100644 --- a/src/tests/scenario2/nginx-ingress-controller-dom2.yaml +++ b/src/tests/scenario2/nginx-ingress-controller-dom2.yaml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/nginx-ingress-controller-dom3.yaml b/src/tests/scenario2/nginx-ingress-controller-dom3.yaml index d6ae8b1c287a59cf19ba4336aba1e02aefeb1ded..0f9ff89d5ecc50a2b7c36e2645d28c90edf9d840 100644 --- a/src/tests/scenario2/nginx-ingress-controller-dom3.yaml +++ b/src/tests/scenario2/nginx-ingress-controller-dom3.yaml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/nginx-ingress-controller-dom4.yaml b/src/tests/scenario2/nginx-ingress-controller-dom4.yaml index 6600d83c7c0be9ac58cec2ecf32155b4b804481f..c96c027fb7e2a05c31b82d0213a3d304eb90326b 100644 --- a/src/tests/scenario2/nginx-ingress-controller-dom4.yaml +++ b/src/tests/scenario2/nginx-ingress-controller-dom4.yaml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/old_tests/run_test_01_bootstrap.sh b/src/tests/scenario2/old_tests/run_test_01_bootstrap.sh index bdd93ca27b6f61adc131258cc9e52b9d2e10d23d..03bb6505829c678f063cc5263b7df164cee9be0a 100755 --- a/src/tests/scenario2/old_tests/run_test_01_bootstrap.sh +++ b/src/tests/scenario2/old_tests/run_test_01_bootstrap.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/old_tests/run_test_02_create_service.sh b/src/tests/scenario2/old_tests/run_test_02_create_service.sh index a9c5e7bd8167e27200545acd19397a44d3b6f911..c27004b5494c072b26886920903a5dfa5cd065ee 100755 --- a/src/tests/scenario2/old_tests/run_test_02_create_service.sh +++ b/src/tests/scenario2/old_tests/run_test_02_create_service.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/old_tests/run_test_03_delete_service.sh b/src/tests/scenario2/old_tests/run_test_03_delete_service.sh index 776c9050e74275d6a559338279c641901ecb4a6b..63c3fb3ee03244139da14231df7d5c14e2a5061c 100755 --- a/src/tests/scenario2/old_tests/run_test_03_delete_service.sh +++ b/src/tests/scenario2/old_tests/run_test_03_delete_service.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/old_tests/run_test_04_cleanup.sh b/src/tests/scenario2/old_tests/run_test_04_cleanup.sh index 5ab9f70d49effbe80d6a5df32cf4a703a3c8589a..f857a8adf69d480ec043e595cc7aad3b262351ce 100755 --- a/src/tests/scenario2/old_tests/run_test_04_cleanup.sh +++ b/src/tests/scenario2/old_tests/run_test_04_cleanup.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/old_tests/run_tests_and_coverage.sh b/src/tests/scenario2/old_tests/run_tests_and_coverage.sh index 6d7351bb5f8c6a8af67b9cc9c38a0b926c6a8fa0..2bcfb0b75805e859da0863daeef0ca715986d5ee 100755 --- a/src/tests/scenario2/old_tests/run_tests_and_coverage.sh +++ b/src/tests/scenario2/old_tests/run_tests_and_coverage.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/old_tests/tests/BuildDescriptors.py b/src/tests/scenario2/old_tests/tests/BuildDescriptors.py index cfd29eea0cb80306f402ef71530016599b570eb1..c0f01ee7537e88883704e3af36f6c51b672a607e 100644 --- a/src/tests/scenario2/old_tests/tests/BuildDescriptors.py +++ b/src/tests/scenario2/old_tests/tests/BuildDescriptors.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/old_tests/tests/Fixtures.py b/src/tests/scenario2/old_tests/tests/Fixtures.py index dceec235ab6d4fd757e14f2d5dd00c2f38bdc963..d23198d9e242b3fe13c8a4a1be76399fc384866f 100644 --- a/src/tests/scenario2/old_tests/tests/Fixtures.py +++ b/src/tests/scenario2/old_tests/tests/Fixtures.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/old_tests/tests/LoadDescriptors.py b/src/tests/scenario2/old_tests/tests/LoadDescriptors.py index 407d5b6dc6b46ba7dd920cb1f60be391f839bda7..c47bea18d43c3a71656169cbb3855bd1602240fd 100644 --- a/src/tests/scenario2/old_tests/tests/LoadDescriptors.py +++ b/src/tests/scenario2/old_tests/tests/LoadDescriptors.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/old_tests/tests/Objects.py b/src/tests/scenario2/old_tests/tests/Objects.py index 1ecb2eca1f0f43c6b9ddbfc949b533662ed37ba5..221a0633f4d73339b669bd3f61049345f0062e1c 100644 --- a/src/tests/scenario2/old_tests/tests/Objects.py +++ b/src/tests/scenario2/old_tests/tests/Objects.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/old_tests/tests/__init__.py b/src/tests/scenario2/old_tests/tests/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/tests/scenario2/old_tests/tests/__init__.py +++ b/src/tests/scenario2/old_tests/tests/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/old_tests/tests/test_functional_bootstrap.py b/src/tests/scenario2/old_tests/tests/test_functional_bootstrap.py index 2c4743f08eca82c88aaaf901b60f5894059e07f3..f56b511fba1ebc8e1908d548fd36b6360e8f499d 100644 --- a/src/tests/scenario2/old_tests/tests/test_functional_bootstrap.py +++ b/src/tests/scenario2/old_tests/tests/test_functional_bootstrap.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/old_tests/tests/test_functional_cleanup.py b/src/tests/scenario2/old_tests/tests/test_functional_cleanup.py index 259ce831498a8b8a566e53fafba72d109299832b..d1d5ccbe7ca3a78c8a1fa864d0bd5eca2e714c3e 100644 --- a/src/tests/scenario2/old_tests/tests/test_functional_cleanup.py +++ b/src/tests/scenario2/old_tests/tests/test_functional_cleanup.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/old_tests/tests/test_functional_create_service.py b/src/tests/scenario2/old_tests/tests/test_functional_create_service.py index a286c1e79056e14d5f397c99b62265ffa3f7b43e..ff97ef46f3e54da7aaaa58aa2eed94417b21ce38 100644 --- a/src/tests/scenario2/old_tests/tests/test_functional_create_service.py +++ b/src/tests/scenario2/old_tests/tests/test_functional_create_service.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/old_tests/tests/test_functional_delete_service.py b/src/tests/scenario2/old_tests/tests/test_functional_delete_service.py index b799e467ceba1e43c7dd0a443294168dd18f09a5..4c91291ee22a5e8cb4c885013ee86611a5283d66 100644 --- a/src/tests/scenario2/old_tests/tests/test_functional_delete_service.py +++ b/src/tests/scenario2/old_tests/tests/test_functional_delete_service.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/reset.sh b/src/tests/scenario2/reset.sh index 5b1d1ee0cd96edd5ee046b362c4d1541da841582..f84c984979af06f2ecb9432ffb5c6188c797894b 100755 --- a/src/tests/scenario2/reset.sh +++ b/src/tests/scenario2/reset.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/show_deploy.sh b/src/tests/scenario2/show_deploy.sh index dfceb6fee9ef5b819d02c8c1e752c4511c02ec1d..f9b5b9dcb1568e45b9d0d506b8be2c66716bd24e 100755 --- a/src/tests/scenario2/show_deploy.sh +++ b/src/tests/scenario2/show_deploy.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/tfs-ingress-dom1.yaml b/src/tests/scenario2/tfs-ingress-dom1.yaml index 39502bb20df16c4ceadeff0f3fe8fd219d81e640..3027dc21d902aeb3b54017643f3532e4b58d74cb 100644 --- a/src/tests/scenario2/tfs-ingress-dom1.yaml +++ b/src/tests/scenario2/tfs-ingress-dom1.yaml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/tfs-ingress-dom2.yaml b/src/tests/scenario2/tfs-ingress-dom2.yaml index 1c0ff6de94e1cdc208880823e70b7817c36fe97c..ceedd0d17512813eef676d4df47f1f6c8a741154 100644 --- a/src/tests/scenario2/tfs-ingress-dom2.yaml +++ b/src/tests/scenario2/tfs-ingress-dom2.yaml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/tfs-ingress-dom3.yaml b/src/tests/scenario2/tfs-ingress-dom3.yaml index 80957e657b8bdcbe50e2a9e00d8a2769b6f6c591..8847d63a66054490c33a8c7197d0f2c79dd85e1c 100644 --- a/src/tests/scenario2/tfs-ingress-dom3.yaml +++ b/src/tests/scenario2/tfs-ingress-dom3.yaml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario2/tfs-ingress-dom4.yaml b/src/tests/scenario2/tfs-ingress-dom4.yaml index 6b384eed7ddeff0b9f7c9ed94535479e8adb378c..15f1d37b25982b96937b67d5e0427a1b91239b91 100644 --- a/src/tests/scenario2/tfs-ingress-dom4.yaml +++ b/src/tests/scenario2/tfs-ingress-dom4.yaml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario3/l3/deploy.sh b/src/tests/scenario3/l3/deploy.sh index 97224bd2c86b999acaf734adb304af6aa76956cc..b84610f0ff3eb62a23a9e375e2faffd13864b4e0 100755 --- a/src/tests/scenario3/l3/deploy.sh +++ b/src/tests/scenario3/l3/deploy.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario3/l3/deploy_specs.sh b/src/tests/scenario3/l3/deploy_specs.sh index b3dd07b7ab025e5f325d0c26e75fff5271980316..802fb0e0962df4b46d097234d57599b2764ab64f 100644 --- a/src/tests/scenario3/l3/deploy_specs.sh +++ b/src/tests/scenario3/l3/deploy_specs.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -77,9 +77,6 @@ export CRDB_USERNAME="tfs" # Set the database user's password to be used by Context. export CRDB_PASSWORD="tfs123" -# Set the database name to be used by Context. -export CRDB_DATABASE="tfs" - # 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" diff --git a/src/tests/scenario3/l3/run.sh b/src/tests/scenario3/l3/run.sh index 109350ad07de38a40703ea095a7d47d1636ffea1..53d78751b3bcc41662a173543fc09df40c15416c 100644 --- a/src/tests/scenario3/l3/run.sh +++ b/src/tests/scenario3/l3/run.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario3/optical/deploy_specs.sh b/src/tests/scenario3/optical/deploy_specs.sh index b02e5f22a42614d0beb2a2c6a97babbf1fabd34a..5532708e89f38f19aa066610cacd11c1c1347bfc 100644 --- a/src/tests/scenario3/optical/deploy_specs.sh +++ b/src/tests/scenario3/optical/deploy_specs.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario3/optical/jocn/run_experiment.py b/src/tests/scenario3/optical/jocn/run_experiment.py index 6e7d0c1c1b1b0de42a48ff29d3d75f21fc23e3ff..d3afbbc380878c2e8917114277bce18086293721 100644 --- a/src/tests/scenario3/optical/jocn/run_experiment.py +++ b/src/tests/scenario3/optical/jocn/run_experiment.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/scenario3/optical/ofc23/run_experiment_demo.py b/src/tests/scenario3/optical/ofc23/run_experiment_demo.py index 4af9550db4fc168b47e9a31ebc4016583c8b6a72..f4a021c82431e76b239435e77ac3e15cc8bd1ba6 100644 --- a/src/tests/scenario3/optical/ofc23/run_experiment_demo.py +++ b/src/tests/scenario3/optical/ofc23/run_experiment_demo.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/sns4sns24/01-tfs-topology.json b/src/tests/sns4sns24/01-tfs-topology.json new file mode 100644 index 0000000000000000000000000000000000000000..c3b95a69b7a8e5138a0cc3889d218bfdfde4f11b --- /dev/null +++ b/src/tests/sns4sns24/01-tfs-topology.json @@ -0,0 +1,102 @@ +{ + "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": "core-net"}}, "device_type": "network", + "device_drivers": ["DEVICEDRIVER_UNDEFINED"], + "device_config": {"config_rules": [ + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}}, + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/port", "resource_value": "0"}}, + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [ + {"uuid": "int", "type": "copper"}, + {"uuid": "eth1", "type": "copper"} + ]}}} + ]} + }, + { + "device_id": {"device_uuid": {"uuid": "edge-net"}}, "device_type": "network", + "device_drivers": ["DEVICEDRIVER_UNDEFINED"], + "device_config": {"config_rules": [ + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}}, + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/port", "resource_value": "0"}}, + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [ + {"uuid": "int", "type": "copper"}, + {"uuid": "eth1", "type": "copper"} + ]}}} + ]} + }, + { + "device_id": {"device_uuid": {"uuid": "r1"}}, "device_type": "packet-router", + "device_drivers": ["DEVICEDRIVER_GNMI_OPENCONFIG"], + "device_config": {"config_rules": [ + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/address", "resource_value": "172.20.20.101"}}, + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/port", "resource_value": "6030"}}, + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/settings", "resource_value": { + "username": "admin", "password": "admin", "use_tls": false + }}} + ]} + }, + { + "device_id": {"device_uuid": {"uuid": "r2"}}, "device_type": "packet-router", + "device_drivers": ["DEVICEDRIVER_GNMI_OPENCONFIG"], + "device_config": {"config_rules": [ + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/address", "resource_value": "172.20.20.102"}}, + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/port", "resource_value": "6030"}}, + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/settings", "resource_value": { + "username": "admin", "password": "admin", "use_tls": false + }}} + ]} + } + ], + "links": [ + { + "link_id": {"link_uuid": {"uuid": "r1/Ethernet2==r2/Ethernet1"}}, + "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "r1"}}, "endpoint_uuid": {"uuid": "Ethernet2"}}, + {"device_id": {"device_uuid": {"uuid": "r2"}}, "endpoint_uuid": {"uuid": "Ethernet1"}} + ] + }, + { + "link_id": {"link_uuid": {"uuid": "r2/Ethernet1==r1/Ethernet2"}}, + "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "r2"}}, "endpoint_uuid": {"uuid": "Ethernet1"}}, + {"device_id": {"device_uuid": {"uuid": "r1"}}, "endpoint_uuid": {"uuid": "Ethernet2"}} + ] + }, + + { + "link_id": {"link_uuid": {"uuid": "r1/Ethernet10==core-net/eth1"}}, + "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "r1"}}, "endpoint_uuid": {"uuid": "Ethernet10"}}, + {"device_id": {"device_uuid": {"uuid": "core-net"}}, "endpoint_uuid": {"uuid": "eth1"}} + ] + }, + { + "link_id": {"link_uuid": {"uuid": "core-net/eth1==r1/Ethernet10"}}, + "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "core-net"}}, "endpoint_uuid": {"uuid": "eth1"}}, + {"device_id": {"device_uuid": {"uuid": "r1"}}, "endpoint_uuid": {"uuid": "Ethernet10"}} + ] + }, + + { + "link_id": {"link_uuid": {"uuid": "r2/Ethernet10==edge-net/eth1"}}, + "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "r2"}}, "endpoint_uuid": {"uuid": "Ethernet10"}}, + {"device_id": {"device_uuid": {"uuid": "edge-net"}}, "endpoint_uuid": {"uuid": "eth1"}} + ] + }, + { + "link_id": {"link_uuid": {"uuid": "edge-net/eth1==r2/Ethernet10"}}, + "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "edge-net"}}, "endpoint_uuid": {"uuid": "eth1"}}, + {"device_id": {"device_uuid": {"uuid": "r2"}}, "endpoint_uuid": {"uuid": "Ethernet10"}} + ] + } + ] +} diff --git a/src/tests/sns4sns24/02-ietf-l3vpn-nbi.json b/src/tests/sns4sns24/02-ietf-l3vpn-nbi.json new file mode 100644 index 0000000000000000000000000000000000000000..31d7e0a6d1636af4572b10dd07cecc9a2aedeb9d --- /dev/null +++ b/src/tests/sns4sns24/02-ietf-l3vpn-nbi.json @@ -0,0 +1,83 @@ +{ + "ietf-l3vpn-svc:l3vpn-svc": { + "vpn-services": {"vpn-service": [{"vpn-id": "ietf-l3vpn-edge-core"}]}, + "sites": { + "site": [ + { + "site-id": "site_core-net", + "management": {"type": "ietf-l3vpn-svc:provider-managed"}, + "locations": {"location": [{"location-id": "core-net"}]}, + "devices": {"device": [{"device-id": "core-net", "location": "core-net"}]}, + "site-network-accesses": { + "site-network-access": [ + { + "site-network-access-id": "int", + "site-network-access-type": "ietf-l3vpn-svc:multipoint", + "device-reference": "core-net", + "vpn-attachment": {"vpn-id": "ietf-l3vpn-edge-core", "site-role": "ietf-l3vpn-svc:spoke-role"}, + "ip-connection": { + "ipv4": { + "address-allocation-type": "ietf-l3vpn-svc:static-address", + "addresses": { + "provider-address": "10.10.10.229", + "customer-address": "10.10.10.0", + "prefix-length": 24 + } + } + }, + "service": { + "svc-mtu": 1500, + "svc-input-bandwidth": 1000000000, + "svc-output-bandwidth": 1000000000, + "qos": {"qos-profile": {"classes": {"class": [{ + "class-id": "qos-realtime", + "direction": "ietf-l3vpn-svc:both", + "latency": {"latency-boundary": 10}, + "bandwidth": {"guaranteed-bw-percent": 100} + }]}}} + } + } + ] + } + }, + { + "site-id": "site_edge-net", + "management": {"type": "ietf-l3vpn-svc:provider-managed"}, + "locations": {"location": [{"location-id": "edge-net"}]}, + "devices": {"device": [{"device-id": "edge-net", "location": "edge-net"}]}, + "site-network-accesses": { + "site-network-access": [ + { + "site-network-access-id": "int", + "site-network-access-type": "ietf-l3vpn-svc:multipoint", + "device-reference": "edge-net", + "vpn-attachment": {"vpn-id": "ietf-l3vpn-edge-core", "site-role": "ietf-l3vpn-svc:hub-role"}, + "ip-connection": { + "ipv4": { + "address-allocation-type": "ietf-l3vpn-svc:static-address", + "addresses": { + "provider-address": "10.158.72.229", + "customer-address": "10.158.72.0", + "prefix-length": 24 + } + } + }, + "service": { + "svc-mtu": 1500, + "svc-input-bandwidth": 1000000000, + "svc-output-bandwidth": 1000000000, + "qos": {"qos-profile": {"classes": {"class": [{ + "class-id": "qos-realtime", + "direction": "ietf-l3vpn-svc:both", + "latency": {"latency-boundary": 10}, + "bandwidth": {"guaranteed-bw-percent": 100} + }]}}} + } + } + ] + } + } + ] + } + } +} diff --git a/src/tests/sns4sns24/02-tfs-l3-service.json b/src/tests/sns4sns24/02-tfs-l3-service.json new file mode 100644 index 0000000000000000000000000000000000000000..1fcd0267b8279a218fea0cded4263323577fec1c --- /dev/null +++ b/src/tests/sns4sns24/02-tfs-l3-service.json @@ -0,0 +1,34 @@ +{ + "services": [ + { + "service_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, "service_uuid": {"uuid": "core-to-edge-l2svc"} + }, + "service_type": "SERVICETYPE_L3NM", + "service_status": {"service_status": "SERVICESTATUS_PLANNED"}, + "service_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "core-net"}}, "endpoint_uuid": {"uuid": "int"}}, + {"device_id": {"device_uuid": {"uuid": "edge-net"}}, "endpoint_uuid": {"uuid": "int"}} + ], + "service_constraints": [], + "service_config": {"config_rules": [ + {"action": "CONFIGACTION_SET", "custom": { + "resource_key": "/device[core-net]/endpoint[eth1]/settings", + "resource_value": {"address_ip": "10.10.10.0", "address_prefix": 24, "index": 0} + }}, + {"action": "CONFIGACTION_SET", "custom": { + "resource_key": "/device[r1]/endpoint[Ethernet10]/settings", + "resource_value": {"address_ip": "10.10.10.229", "address_prefix": 24, "index": 0} + }}, + {"action": "CONFIGACTION_SET", "custom": { + "resource_key": "/device[r2]/endpoint[Ethernet10]/settings", + "resource_value": {"address_ip": "10.158.72.229", "address_prefix": 24, "index": 0} + }}, + {"action": "CONFIGACTION_SET", "custom": { + "resource_key": "/device[edge-net]/endpoint[eth1]/settings", + "resource_value": {"address_ip": "10.158.72.0", "address_prefix": 24, "index": 0} + }} + ]} + } + ] +} diff --git a/src/tests/sns4sns24/clab-cli-r1.sh b/src/tests/sns4sns24/clab-cli-r1.sh new file mode 100755 index 0000000000000000000000000000000000000000..8e6084fe48fd6f3cf1f8b8b53dabd22e47ad6d68 --- /dev/null +++ b/src/tests/sns4sns24/clab-cli-r1.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# 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. + +docker exec -it clab-sns4sns-r1 Cli diff --git a/src/tests/sns4sns24/clab-cli-r2.sh b/src/tests/sns4sns24/clab-cli-r2.sh new file mode 100755 index 0000000000000000000000000000000000000000..8b0ed55d425bd0591fdff42a3590f0da5fd74ed9 --- /dev/null +++ b/src/tests/sns4sns24/clab-cli-r2.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# 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. + +docker exec -it clab-sns4sns-r2 Cli diff --git a/src/tests/sns4sns24/clab-deploy.sh b/src/tests/sns4sns24/clab-deploy.sh new file mode 100755 index 0000000000000000000000000000000000000000..ec4c674b7c5790c3e759e20b1443256189821be5 --- /dev/null +++ b/src/tests/sns4sns24/clab-deploy.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# 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. + +cd /home/$USER/tfs-ctrl/src/tests/sns4sns/ +sudo containerlab deploy --topo sns4sns.clab.yml diff --git a/src/tests/sns4sns24/clab-destroy.sh b/src/tests/sns4sns24/clab-destroy.sh new file mode 100755 index 0000000000000000000000000000000000000000..2c5c18fa398da094c3816ca990f60188e7ece8cc --- /dev/null +++ b/src/tests/sns4sns24/clab-destroy.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# 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. + +cd /home/$USER/tfs-ctrl/src/tests/sns4sns/ +sudo containerlab destroy --topo sns4sns.clab.yml +sudo rm -rf clab-sns4sns/ .sns4sns.clab.yml.bak diff --git a/src/tests/sns4sns24/clab-inspect.sh b/src/tests/sns4sns24/clab-inspect.sh new file mode 100755 index 0000000000000000000000000000000000000000..4badf729650880b30ff9c199eb36a2b36e1787d8 --- /dev/null +++ b/src/tests/sns4sns24/clab-inspect.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# 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. + +cd /home/$USER/tfs-ctrl/src/tests/sns4sns/ +sudo containerlab inspect --topo sns4sns.clab.yml diff --git a/src/tests/sns4sns24/deploy_specs.sh b/src/tests/sns4sns24/deploy_specs.sh new file mode 100755 index 0000000000000000000000000000000000000000..71bd0d72ca4fed0ad05e19e19befb1f354f0838f --- /dev/null +++ b/src/tests/sns4sns24/deploy_specs.sh @@ -0,0 +1,151 @@ +#!/bin/bash +# 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. + + +# ----- 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 slice nbi webui" + +# Uncomment to activate Monitoring +export TFS_COMPONENTS="${TFS_COMPONENTS} monitoring" + +# 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" + +# 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" + +# 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" diff --git a/src/tests/sns4sns24/ietf-create.sh b/src/tests/sns4sns24/ietf-create.sh new file mode 100755 index 0000000000000000000000000000000000000000..fa88228ceff99de44a95114ee71db33e36fb2510 --- /dev/null +++ b/src/tests/sns4sns24/ietf-create.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# 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. + + +curl -X POST \ + --header "Content-Type: application/json" \ + --data @02-ietf-l3vpn-nbi.json \ + --user "admin:admin" \ + http://10.10.10.41/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services diff --git a/src/tests/sns4sns24/ietf-delete.sh b/src/tests/sns4sns24/ietf-delete.sh new file mode 100755 index 0000000000000000000000000000000000000000..4e2c2af0404a3ab0b0e42b0991fd42da19c2270f --- /dev/null +++ b/src/tests/sns4sns24/ietf-delete.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# 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. + + +curl -X DELETE \ + --user "admin:admin" \ + http://10.10.10.41/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services/vpn-service=ietf-l3vpn-edge-core/ diff --git a/src/tests/sns4sns24/ietf-get.sh b/src/tests/sns4sns24/ietf-get.sh new file mode 100755 index 0000000000000000000000000000000000000000..b76ac2d32df00fd0059a40e38238918bd6277b65 --- /dev/null +++ b/src/tests/sns4sns24/ietf-get.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# 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. + + +curl --user "admin:admin" \ + http://10.10.10.41/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services/vpn-service=ietf-l3vpn-edge-core/ diff --git a/src/tests/sns4sns24/sns4sns.clab.yml b/src/tests/sns4sns24/sns4sns.clab.yml new file mode 100644 index 0000000000000000000000000000000000000000..6d017a84982946be8cad767bfb278d0c334fdb50 --- /dev/null +++ b/src/tests/sns4sns24/sns4sns.clab.yml @@ -0,0 +1,47 @@ +# 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. + +# Ref: https://containerlab.dev/manual/network/#macvlan-links +# Ref: https://containerlab.dev/manual/network/#host-links + + +# ETSI SNS4SNS OSL+TFS Integration (Static configuration) + +name: sns4sns-static + +mgmt: + network: mgmt-net + ipv4-subnet: 172.20.20.0/24 + mtu: 1400 + +topology: + kinds: + arista_ceos: + kind: arista_ceos + #image: ceos:4.30.4M + image: ceos:4.31.2F + + nodes: + r1: + kind: arista_ceos + mgmt-ipv4: 172.20.20.101 + + r2: + kind: arista_ceos + mgmt-ipv4: 172.20.20.102 + + links: + - endpoints: ["r1:eth2", "r2:eth1"] + - endpoints: ["r1:eth10", "macvlan:enp0s3"] # connect to core domain virtual network + - endpoints: ["r2:eth10", "macvlan:enp0s5"] # connect to shared virtual network with edge domain diff --git a/src/tests/sns4sns24/static_setup/r1-static.cfg b/src/tests/sns4sns24/static_setup/r1-static.cfg new file mode 100644 index 0000000000000000000000000000000000000000..f225a9c5c5273beb65844612e1975a7e516f46d1 --- /dev/null +++ b/src/tests/sns4sns24/static_setup/r1-static.cfg @@ -0,0 +1,45 @@ +! Startup-config last modified at Tue Oct 15 12:24:02 2024 by root +! device: r1 (cEOSLab, EOS-4.31.2F-35442176.4312F (engineering build)) +! +no aaa root +! +username admin privilege 15 role network-admin secret sha512 $6$WlffHUsmnrG2WVRf$cfZfWFJtrnv9wuGlkyMHRS66VQeA8bOjxM0jSXTB1deScpsqz0I3oVEcvrR6IMrqVOsXANKmoghcZvcDbC4Ry/ +! +transceiver qsfp default-mode 4x10G +! +service routing protocols model multi-agent +! +hostname r1 +! +spanning-tree mode mstp +! +system l1 + unsupported speed action error + unsupported error-correction action error +! +management api http-commands + no shutdown +! +management api gnmi + transport grpc default +! +management api netconf + transport ssh default +! +interface Ethernet2 + no switchport + ip address 10.254.254.1/30 +! +interface Ethernet10 + no switchport + ip address 10.10.10.229/24 +! +interface Management0 + ip address 172.20.20.101/24 +! +ip routing +! +ip route 0.0.0.0/0 172.20.20.1 +ip route 10.158.72.0/24 10.254.254.2 +! +end diff --git a/src/tests/sns4sns24/static_setup/r2-static.cfg b/src/tests/sns4sns24/static_setup/r2-static.cfg new file mode 100644 index 0000000000000000000000000000000000000000..2bbd8f80fbb2a6b083dd9b3862db93dd0d41a8f5 --- /dev/null +++ b/src/tests/sns4sns24/static_setup/r2-static.cfg @@ -0,0 +1,45 @@ +! Startup-config last modified at Tue Oct 15 12:23:41 2024 by root +! device: r2 (cEOSLab, EOS-4.31.2F-35442176.4312F (engineering build)) +! +no aaa root +! +username admin privilege 15 role network-admin secret sha512 $6$3nmPs7/wiY.aN139$BrgG79cp9R5bd.bQST4LnQB6wq6GLuIHKdbafZkcVH2R5D.v771gZNgeQSILN6ubz1.j29Wy5UmavY9Pavsoy0 +! +transceiver qsfp default-mode 4x10G +! +service routing protocols model multi-agent +! +hostname r2 +! +spanning-tree mode mstp +! +system l1 + unsupported speed action error + unsupported error-correction action error +! +management api http-commands + no shutdown +! +management api gnmi + transport grpc default +! +management api netconf + transport ssh default +! +interface Ethernet1 + no switchport + ip address 10.254.254.2/30 +! +interface Ethernet10 + no switchport + ip address 10.158.72.229/24 +! +interface Management0 + ip address 172.20.20.102/24 +! +ip routing +! +ip route 0.0.0.0/0 172.20.20.1 +ip route 10.10.10.0/24 10.254.254.1 +! +end diff --git a/src/tests/sns4sns24/static_setup/sns4sns.clab.yml b/src/tests/sns4sns24/static_setup/sns4sns.clab.yml new file mode 100644 index 0000000000000000000000000000000000000000..ac931773bed9868c825f964880b80b218b8397dc --- /dev/null +++ b/src/tests/sns4sns24/static_setup/sns4sns.clab.yml @@ -0,0 +1,49 @@ +# 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. + +# Ref: https://containerlab.dev/manual/network/#macvlan-links +# Ref: https://containerlab.dev/manual/network/#host-links + + +# ETSI SNS4SNS OSL+TFS Integration (Static configuration) + +name: sns4sns-static + +mgmt: + network: mgmt-net + ipv4-subnet: 172.20.20.0/24 + mtu: 1400 + +topology: + kinds: + arista_ceos: + kind: arista_ceos + #image: ceos:4.30.4M + image: ceos:4.31.2F + + nodes: + r1: + kind: arista_ceos + mgmt-ipv4: 172.20.20.101 + startup-config: r1-static.cfg + + r2: + kind: arista_ceos + mgmt-ipv4: 172.20.20.102 + startup-config: r2-static.cfg + + links: + - endpoints: ["r1:eth2", "r2:eth1"] + - endpoints: ["r1:eth10", "macvlan:enp0s3"] # connect to core domain virtual network + - endpoints: ["r2:eth10", "macvlan:enp0s5"] # connect to shared virtual network with edge domain diff --git a/src/tests/sns4sns24/static_setup/static-setup.txt b/src/tests/sns4sns24/static_setup/static-setup.txt new file mode 100644 index 0000000000000000000000000000000000000000..5cbd7d2cfb3b9000ce585983ac3c304317155439 --- /dev/null +++ b/src/tests/sns4sns24/static_setup/static-setup.txt @@ -0,0 +1,39 @@ + | 10.10.10.229/24 (eth10) ++--+--+ +| R1 | ++--+--+ + | .1 (eth2) + | + | 10.254.254.0/30 + | + | .2 (eth1) ++--+--+ +| R2 | ++--+--+ + | 10.158.72.11/24 (eth10) + + +r1(config)#show running-config +interface Ethernet2 + no switchport + ip address 10.254.254.1/30 + +interface Ethernet10 + no switchport + ip address 10.10.10.229/24 + +ip routing +ip route 10.158.72.0/24 10.254.254.2 + + +r2(config)#show running-config +interface Ethernet1 + no switchport + ip address 10.254.254.2/30 + +interface Ethernet10 + no switchport + ip address 10.158.72.11/24 + +ip routing +ip route 10.10.10.0/24 10.254.254.1 diff --git a/src/tests/tools/__init__.py b/src/tests/tools/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/tests/tools/__init__.py +++ b/src/tests/tools/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/load_scenario/__init__.py b/src/tests/tools/load_scenario/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/tests/tools/load_scenario/__init__.py +++ b/src/tests/tools/load_scenario/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/load_scenario/__main__.py b/src/tests/tools/load_scenario/__main__.py index 0e225cc46d104885d065addec867ce9f5841ee65..5c8f2987a931038024d147db2ea5a5651f2f3002 100644 --- a/src/tests/tools/load_scenario/__main__.py +++ b/src/tests/tools/load_scenario/__main__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/load_scenario/run.sh b/src/tests/tools/load_scenario/run.sh index b4c58bcb60b4ca5363d431a6ed800fe50a2d6af4..e3b49272bed443eb5e89216bef5f2bc3ce2840f6 100755 --- a/src/tests/tools/load_scenario/run.sh +++ b/src/tests/tools/load_scenario/run.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/mock_ietf_actn_sdn_ctrl/Dockerfile b/src/tests/tools/mock_ietf_actn_sdn_ctrl/Dockerfile index 02af91b62e5ff4110890fc7d19dae020fd5bdb39..8875154cf64b6b06ff0ee8fc08a9a44de6b9043a 100644 --- a/src/tests/tools/mock_ietf_actn_sdn_ctrl/Dockerfile +++ b/src/tests/tools/mock_ietf_actn_sdn_ctrl/Dockerfile @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/mock_ietf_actn_sdn_ctrl/MockIetfActnSdnCtrl.py b/src/tests/tools/mock_ietf_actn_sdn_ctrl/MockIetfActnSdnCtrl.py index 7bc79e55870d52667afc7d608a48a3df168cccf3..ba8497f80d912da434cc9a38f144be1579294413 100644 --- a/src/tests/tools/mock_ietf_actn_sdn_ctrl/MockIetfActnSdnCtrl.py +++ b/src/tests/tools/mock_ietf_actn_sdn_ctrl/MockIetfActnSdnCtrl.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/mock_ietf_actn_sdn_ctrl/ResourceEthServices.py b/src/tests/tools/mock_ietf_actn_sdn_ctrl/ResourceEthServices.py index 64e47b27317f673fc62e0803c3b6726798d10c61..f1d93a354a0ca0983a5f5e1e034c00280ebd070c 100644 --- a/src/tests/tools/mock_ietf_actn_sdn_ctrl/ResourceEthServices.py +++ b/src/tests/tools/mock_ietf_actn_sdn_ctrl/ResourceEthServices.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/mock_ietf_actn_sdn_ctrl/ResourceOsuTunnels.py b/src/tests/tools/mock_ietf_actn_sdn_ctrl/ResourceOsuTunnels.py index 85950dfe99e9380459ac9b1d8f5099cf5226b66b..6a5ec91e74ed813e8211aa59f0f0691f257e4e89 100644 --- a/src/tests/tools/mock_ietf_actn_sdn_ctrl/ResourceOsuTunnels.py +++ b/src/tests/tools/mock_ietf_actn_sdn_ctrl/ResourceOsuTunnels.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/mock_ietf_actn_sdn_ctrl/__init__.py b/src/tests/tools/mock_ietf_actn_sdn_ctrl/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/tests/tools/mock_ietf_actn_sdn_ctrl/__init__.py +++ b/src/tests/tools/mock_ietf_actn_sdn_ctrl/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/mock_ietf_actn_sdn_ctrl/build.sh b/src/tests/tools/mock_ietf_actn_sdn_ctrl/build.sh index 06184bed6b64e3d8fdde08a60b3bdafc01afcd06..3cfe04fde99eb0b5322b5ea0766eeadd6b160c04 100755 --- a/src/tests/tools/mock_ietf_actn_sdn_ctrl/build.sh +++ b/src/tests/tools/mock_ietf_actn_sdn_ctrl/build.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/mock_ietf_actn_sdn_ctrl/deploy.sh b/src/tests/tools/mock_ietf_actn_sdn_ctrl/deploy.sh index 02c32797105e4751fc614fb371f38c76ce4b79b5..c2fa7a7b6e2773aec10fc167a37ae1cde2776886 100755 --- a/src/tests/tools/mock_ietf_actn_sdn_ctrl/deploy.sh +++ b/src/tests/tools/mock_ietf_actn_sdn_ctrl/deploy.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/mock_ietf_actn_sdn_ctrl/mock-ietf-actn-sdn-ctrl.yaml b/src/tests/tools/mock_ietf_actn_sdn_ctrl/mock-ietf-actn-sdn-ctrl.yaml index f59249e8e4c38ce10bd0e3a4800f7f2dff33c601..c95b01d104d7d0f8eca4e70488a48d0932ea4d9c 100644 --- a/src/tests/tools/mock_ietf_actn_sdn_ctrl/mock-ietf-actn-sdn-ctrl.yaml +++ b/src/tests/tools/mock_ietf_actn_sdn_ctrl/mock-ietf-actn-sdn-ctrl.yaml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/mock_ietf_actn_sdn_ctrl/requirements.in b/src/tests/tools/mock_ietf_actn_sdn_ctrl/requirements.in index fc3bee8f04fe9dc21793e7d522d53c732fdd4b3f..9fb7bd0e1e8d662903d9d8e019abbc83db1eb6ca 100644 --- a/src/tests/tools/mock_ietf_actn_sdn_ctrl/requirements.in +++ b/src/tests/tools/mock_ietf_actn_sdn_ctrl/requirements.in @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/mock_ietf_actn_sdn_ctrl/run.sh b/src/tests/tools/mock_ietf_actn_sdn_ctrl/run.sh index f6edea6e7171fd14ae0dc35ce6eae1a7d0b9f50f..47ea5717a48542c42c67e546c10e4e5e94de21e7 100755 --- a/src/tests/tools/mock_ietf_actn_sdn_ctrl/run.sh +++ b/src/tests/tools/mock_ietf_actn_sdn_ctrl/run.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/mock_ipm_sdn_ctrl/MockIPMSdnCtrl.py b/src/tests/tools/mock_ipm_sdn_ctrl/MockIPMSdnCtrl.py index cf8deb1a82d122f4194cf8f2b7b1d9bb6f21b2c8..b7daf4053bb95c21e893d94e4fe795fdfa845751 100644 --- a/src/tests/tools/mock_ipm_sdn_ctrl/MockIPMSdnCtrl.py +++ b/src/tests/tools/mock_ipm_sdn_ctrl/MockIPMSdnCtrl.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/mock_ipm_sdn_ctrl/run.sh b/src/tests/tools/mock_ipm_sdn_ctrl/run.sh index f51a627be085d373c0381b1393180d6e36533373..2b42ab287bf437665851bdbbf4015edd79a701aa 100755 --- a/src/tests/tools/mock_ipm_sdn_ctrl/run.sh +++ b/src/tests/tools/mock_ipm_sdn_ctrl/run.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/mock_mw_sdn_ctrl/MockMWSdnCtrl.py b/src/tests/tools/mock_mw_sdn_ctrl/MockMWSdnCtrl.py index d67e65db49e507b15236d64b7ba276314b288928..ecf4b503c597b7f98dbd570b8be324142906d1eb 100644 --- a/src/tests/tools/mock_mw_sdn_ctrl/MockMWSdnCtrl.py +++ b/src/tests/tools/mock_mw_sdn_ctrl/MockMWSdnCtrl.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/mock_mw_sdn_ctrl/run.sh b/src/tests/tools/mock_mw_sdn_ctrl/run.sh index 632e481a9f5a570af0973ea1e3faa1dfaae71b02..d46bbef09462afc5e780ef0656c5b7b27a72dee5 100755 --- a/src/tests/tools/mock_mw_sdn_ctrl/run.sh +++ b/src/tests/tools/mock_mw_sdn_ctrl/run.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/mock_mw_sdn_ctrl/scenario/microwave_deploy.sh b/src/tests/tools/mock_mw_sdn_ctrl/scenario/microwave_deploy.sh index 5e6af0e77c89cb23f4c29097ca059bc68d131f7d..4c2662d63d3137e44d02a30e07579b7d915f645a 100755 --- a/src/tests/tools/mock_mw_sdn_ctrl/scenario/microwave_deploy.sh +++ b/src/tests/tools/mock_mw_sdn_ctrl/scenario/microwave_deploy.sh @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/mock_mw_sdn_ctrl/ssl_not_working/Dockerfile b/src/tests/tools/mock_mw_sdn_ctrl/ssl_not_working/Dockerfile index 097844a4148da5500c86de31c0f7e3adfa85ad6c..fc5bdf99a1905fe60be45e60abc09d50f7458958 100644 --- a/src/tests/tools/mock_mw_sdn_ctrl/ssl_not_working/Dockerfile +++ b/src/tests/tools/mock_mw_sdn_ctrl/ssl_not_working/Dockerfile @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/mock_mw_sdn_ctrl/ssl_not_working/build.sh b/src/tests/tools/mock_mw_sdn_ctrl/ssl_not_working/build.sh index bea3f9bdf69e2b5136db4c851b5844982299c159..e6fe0979a87f9f614f8a6091e0dbb5f68308d686 100755 --- a/src/tests/tools/mock_mw_sdn_ctrl/ssl_not_working/build.sh +++ b/src/tests/tools/mock_mw_sdn_ctrl/ssl_not_working/build.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/mock_mw_sdn_ctrl/ssl_not_working/deploy.sh b/src/tests/tools/mock_mw_sdn_ctrl/ssl_not_working/deploy.sh index e1d2168dfd9512f6f5ba6a56502dec87f1097861..4ec3d94302b5bf4b14fb5c080d63bb7a1f6165dc 100755 --- a/src/tests/tools/mock_mw_sdn_ctrl/ssl_not_working/deploy.sh +++ b/src/tests/tools/mock_mw_sdn_ctrl/ssl_not_working/deploy.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/mock_mw_sdn_ctrl/ssl_not_working/mock-mw-sdn-ctrl.yaml b/src/tests/tools/mock_mw_sdn_ctrl/ssl_not_working/mock-mw-sdn-ctrl.yaml index bccbfc987872b702c3a77f8d7b2e75ff97e5c6bd..ec89005224995a0143e6cb31e6c2f41fba6f12ea 100644 --- a/src/tests/tools/mock_mw_sdn_ctrl/ssl_not_working/mock-mw-sdn-ctrl.yaml +++ b/src/tests/tools/mock_mw_sdn_ctrl/ssl_not_working/mock-mw-sdn-ctrl.yaml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/mock_mw_sdn_ctrl/ssl_not_working/requirements.in b/src/tests/tools/mock_mw_sdn_ctrl/ssl_not_working/requirements.in index 74e09dfaa621c6d82875b19e5b737effae1c0545..2f736a2fa9feefb304f37ce2a8799a4f8a07dcce 100644 --- a/src/tests/tools/mock_mw_sdn_ctrl/ssl_not_working/requirements.in +++ b/src/tests/tools/mock_mw_sdn_ctrl/ssl_not_working/requirements.in @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/mock_mw_sdn_ctrl/test_mw.py b/src/tests/tools/mock_mw_sdn_ctrl/test_mw.py index 3165662b18996cf8c6ff486af40e8cf6e90d7d52..654c40fd6660b22d4f59c880b5c115f271115043 100644 --- a/src/tests/tools/mock_mw_sdn_ctrl/test_mw.py +++ b/src/tests/tools/mock_mw_sdn_ctrl/test_mw.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/mock_osm/Constants.py b/src/tests/tools/mock_osm/Constants.py index fb59ef2c7f42736572c175fb02eb08d877523b14..ff145cf388c609b73029834b495ff11af2209292 100644 --- a/src/tests/tools/mock_osm/Constants.py +++ b/src/tests/tools/mock_osm/Constants.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/mock_osm/MockOSM.py b/src/tests/tools/mock_osm/MockOSM.py index 7ced57d3efa64038d09f5cea21fb7098b8ceb2ba..54a123dc40d235f047c99845c00707c82ed0928f 100644 --- a/src/tests/tools/mock_osm/MockOSM.py +++ b/src/tests/tools/mock_osm/MockOSM.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/mock_osm/Tools.py b/src/tests/tools/mock_osm/Tools.py index 3b0ab84875486370d72b4156e19547f5407d2d1a..dc744e87720f3f0d1f5b2c315ea6c55c88ce3c5a 100644 --- a/src/tests/tools/mock_osm/Tools.py +++ b/src/tests/tools/mock_osm/Tools.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/mock_osm/__init__.py b/src/tests/tools/mock_osm/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/tests/tools/mock_osm/__init__.py +++ b/src/tests/tools/mock_osm/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/mock_qkd_nodes/YangValidator.py b/src/tests/tools/mock_qkd_nodes/YangValidator.py new file mode 100644 index 0000000000000000000000000000000000000000..b7d86a362b4910f5575857cc62e4fa6ca9b31490 --- /dev/null +++ b/src/tests/tools/mock_qkd_nodes/YangValidator.py @@ -0,0 +1,42 @@ +# 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 libyang, os +from typing import Dict, Optional + +YANG_DIR = os.path.join(os.path.dirname(__file__), 'yang') + +class YangValidator: + def __init__(self, main_module : str, dependency_modules : [str]) -> None: + self._yang_context = libyang.Context(YANG_DIR) + + self._yang_module = self._yang_context.load_module(main_module) + mods = [self._yang_context.load_module(mod) for mod in dependency_modules] + [self._yang_module] + + for mod in mods: + mod.feature_enable_all() + + + + def parse_to_dict(self, message : Dict) -> Dict: + dnode : Optional[libyang.DNode] = self._yang_module.parse_data_dict( + message, validate_present=True, validate=True, strict=True + ) + if dnode is None: raise Exception('Unable to parse Message({:s})'.format(str(message))) + message = dnode.print_dict() + dnode.free() + return message + + def destroy(self) -> None: + self._yang_context.destroy() diff --git a/src/tests/tools/mock_qkd_nodes/start.sh b/src/tests/tools/mock_qkd_nodes/start.sh new file mode 100755 index 0000000000000000000000000000000000000000..9f0a56edb6f1a7218c5204f8bcc2504c1996b557 --- /dev/null +++ b/src/tests/tools/mock_qkd_nodes/start.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# 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. + +#!/bin/bash +cd "$(dirname "$0")" + +# Function to kill all background processes +killbg() { + for p in "${pids[@]}" ; do + kill "$p"; + done +} + +trap killbg EXIT +pids=() + +# Set FLASK_APP and run the Flask instances on different ports +export FLASK_APP=wsgi +flask run --host 0.0.0.0 --port 11111 & +pids+=($!) + +flask run --host 0.0.0.0 --port 22222 & +pids+=($!) + +flask run --host 0.0.0.0 --port 33333 & +pids+=($!) + +# Wait for all background processes to finish +wait + diff --git a/src/tests/tools/mock_qkd_nodes/wsgi.py b/src/tests/tools/mock_qkd_nodes/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..627eb629fe876b5d931fad64142d4654d498a685 --- /dev/null +++ b/src/tests/tools/mock_qkd_nodes/wsgi.py @@ -0,0 +1,368 @@ +# 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 os +from flask import Flask, request +from YangValidator import YangValidator + +app = Flask(__name__) + + +yang_validator = YangValidator('etsi-qkd-sdn-node', ['etsi-qkd-node-types']) + + +nodes = { + '10.0.2.10:11111': {'node': { + 'qkdn_id': '00000001-0000-0000-0000-000000000000', + }, + 'qkdn_capabilities': { + }, + 'qkd_applications': { + 'qkd_app': [ + { + 'app_id': '00000001-0001-0000-0000-000000000000', + 'client_app_id': [], + 'app_statistics': { + 'statistics': [] + }, + 'app_qos': { + }, + 'backing_qkdl_id': [] + } + ] + }, + 'qkd_interfaces': { + 'qkd_interface': [ + { + 'qkdi_id': '100', + 'qkdi_att_point': { + }, + 'qkdi_capabilities': { + } + }, + { + 'qkdi_id': '101', + 'qkdi_att_point': { + 'device':'10.0.2.10', + 'port':'1001' + }, + 'qkdi_capabilities': { + } + } + ] + }, + 'qkd_links': { + 'qkd_link': [ + + ] + } + }, + + '10.0.2.10:22222': {'node': { + 'qkdn_id': '00000002-0000-0000-0000-000000000000', + }, + 'qkdn_capabilities': { + }, + 'qkd_applications': { + 'qkd_app': [ + { + 'app_id': '00000002-0001-0000-0000-000000000000', + 'client_app_id': [], + 'app_statistics': { + 'statistics': [] + }, + 'app_qos': { + }, + 'backing_qkdl_id': [] + } + ] + }, + 'qkd_interfaces': { + 'qkd_interface': [ + { + 'qkdi_id': '200', + 'qkdi_att_point': { + }, + 'qkdi_capabilities': { + } + }, + { + 'qkdi_id': '201', + 'qkdi_att_point': { + 'device':'10.0.2.10', + 'port':'2001' + }, + 'qkdi_capabilities': { + } + }, + { + 'qkdi_id': '202', + 'qkdi_att_point': { + 'device':'10.0.2.10', + 'port':'2002' + }, + 'qkdi_capabilities': { + } + } + ] + }, + 'qkd_links': { + 'qkd_link': [ + + ] + } + }, + + '10.0.2.10:33333': {'node': { + 'qkdn_id': '00000003-0000-0000-0000-000000000000', + }, + 'qkdn_capabilities': { + }, + 'qkd_applications': { + 'qkd_app': [ + { + 'app_id': '00000003-0001-0000-0000-000000000000', + 'client_app_id': [], + 'app_statistics': { + 'statistics': [] + }, + 'app_qos': { + }, + 'backing_qkdl_id': [] + } + ] + }, + 'qkd_interfaces': { + 'qkd_interface': [ + { + 'qkdi_id': '300', + 'qkdi_att_point': { + }, + 'qkdi_capabilities': { + } + }, + { + 'qkdi_id': '301', + 'qkdi_att_point': { + 'device':'10.0.2.10', + 'port':'3001' + }, + 'qkdi_capabilities': { + } + } + ] + }, + 'qkd_links': { + 'qkd_link': [ + + ] + } + } +} + + +def get_side_effect(url): + + steps = url.lstrip('https://').lstrip('http://').rstrip('/') + ip_port, _, _, header, *steps = steps.split('/') + + header_splitted = header.split(':') + + module = header_splitted[0] + assert(module == 'etsi-qkd-sdn-node') + + tree = {'qkd_node': nodes[ip_port]['node'].copy()} + + if len(header_splitted) == 1 or not header_splitted[1]: + value = nodes[ip_port].copy() + value.pop('node') + tree['qkd_node'].update(value) + + return tree, tree + + root = header_splitted[1] + assert(root == 'qkd_node') + + if not steps: + return tree, tree + + + endpoint, *steps = steps + + value = nodes[ip_port][endpoint] + + if not steps: + return_value = {endpoint:value} + tree['qkd_node'].update(return_value) + + return return_value, tree + + + + ''' + element, *steps = steps + + container, key = element.split('=') + + # value = value[container][key] + + if not steps: + return_value['qkd_node'][endpoint] = [value] + return return_value + + ''' + raise Exception('Url too long') + + + +def edit(from_dict, to_dict, create): + for key, value in from_dict.items(): + if isinstance(value, dict): + if key not in to_dict and create: + to_dict[key] = {} + edit(from_dict[key], to_dict[key], create) + elif isinstance(value, list): + to_dict[key].extend(value) + else: + to_dict[key] = value + + + +def edit_side_effect(url, json, create): + steps = url.lstrip('https://').lstrip('http://').rstrip('/') + ip_port, _, _, header, *steps = steps.split('/') + + module, root = header.split(':') + + assert(module == 'etsi-qkd-sdn-node') + assert(root == 'qkd_node') + + if not steps: + edit(json, nodes[ip_port]['node']) + return + + endpoint, *steps = steps + + if not steps: + edit(json[endpoint], nodes[ip_port][endpoint], create) + return + + + ''' + element, *steps = steps + + container, key = element.split('=') + + if not steps: + if key not in nodes[ip_port][endpoint][container] and create: + nodes[ip_port][endpoint][container][key] = {} + + edit(json, nodes[ip_port][endpoint][container][key], create) + return 0 + ''' + + raise Exception('Url too long') + + + + + + +@app.get('/', defaults={'path': ''}) +@app.get("/") +@app.get('/') +def get(path): + msg, msg_validate = get_side_effect(request.base_url) + print(msg_validate) + yang_validator.parse_to_dict(msg_validate) + return msg + + +@app.post('/', defaults={'path': ''}) +@app.post("/") +@app.post('/') +def post(path): + success = True + reason = '' + try: + edit_side_effect(request.base_url, request.json, True) + except Exception as e: + reason = str(e) + success = False + return {'success': success, 'reason': reason} + + + +@app.route('/', defaults={'path': ''}, methods=['PUT', 'PATCH']) +@app.route("/", methods=['PUT', 'PATCH']) +@app.route('/', methods=['PUT', 'PATCH']) +def patch(path): + success = True + reason = '' + try: + edit_side_effect(request.base_url, request.json, False) + except Exception as e: + reason = str(e) + success = False + return {'success': success, 'reason': reason} + + + + + +# import json +# from mock import requests +# import pyangbind.lib.pybindJSON as enc +# from pyangbind.lib.serialise import pybindJSONDecoder as dec +# from yang.sbi.qkd.templates.etsi_qkd_sdn_node import etsi_qkd_sdn_node + +# module = etsi_qkd_sdn_node() +# url = 'https://1.1.1.1/restconf/data/etsi-qkd-sdn-node:' + +# # Get node all info +# z = requests.get(url).json() +# var = dec.load_json(z, None, None, obj=module) +# print(enc.dumps(var)) + + +# Reset module variable because it is already filled +# module = etsi_qkd_sdn_node() + +# # Get node basic info +# node = module.qkd_node +# z = requests.get(url + 'qkd_node').json() +# var = dec.load_json(z, None, None, obj=node) +# print(enc.dumps(var)) + + +# # Get all apps +# apps = node.qkd_applications +# z = requests.get(url + 'qkd_node/qkd_applications').json() +# var = dec.load_json(z, None, None, obj=apps) +# print(enc.dumps(var)) + +# # Edit app 0 +# app = apps.qkd_app['00000000-0001-0000-0000-000000000000'] +# app.client_app_id = 'id_0' +# requests.put(url + 'qkd_node/qkd_applications/qkd_app=00000000-0001-0000-0000-000000000000', json=json.loads(enc.dumps(app))) + +# # Create app 1 +# app = apps.qkd_app.add('00000000-0001-0000-0000-000000000001') +# requests.post(url + 'qkd_node/qkd_applications/qkd_app=00000000-0001-0000-0000-000000000001', json=json.loads(enc.dumps(app))) + +# # Get all apps +# apps = node.qkd_applications +# z = requests.get(url + 'qkd_node/qkd_applications').json() +# var = dec.load_json(z, None, None, obj=apps) +# print(enc.dumps(var)) diff --git a/src/tests/tools/mock_qkd_nodes/yang/etsi-qkd-node-types.yang b/src/tests/tools/mock_qkd_nodes/yang/etsi-qkd-node-types.yang new file mode 100644 index 0000000000000000000000000000000000000000..04bbd8a875445a9bcf19266f21b792439bf9005c --- /dev/null +++ b/src/tests/tools/mock_qkd_nodes/yang/etsi-qkd-node-types.yang @@ -0,0 +1,326 @@ +/* Copyright 2022 ETSI +Licensed under the BSD-3 Clause (https://forge.etsi.org/legal-matters) */ + +module etsi-qkd-node-types { + + yang-version "1"; + + namespace "urn:etsi:qkd:yang:etsi-qkd-node-types"; + + prefix "etsi-qkdn-types"; + + organization "ETSI ISG QKD"; + + contact + "https://www.etsi.org/committee/qkd + vicente@fi.upm.es"; + + description + "This module contains the base types created for + the software-defined QKD node information models + specified in ETSI GS QKD 015 V2.1.1 + - QKD-TECHNOLOGY-TYPES + - QKDN-STATUS-TYPES + - QKD-LINK-TYPES + - QKD-ROLE-TYPES + - QKD-APP-TYPES + - Wavelength + "; + + revision "2022-01-30" { + description + "Refinement of the YANG model to make it compatible with the ETSI ISG QKD 018. Minor fixes."; + } + + revision "2020-09-30" { + description + "First definition based on initial requirement analysis."; + } + + identity QKD-TECHNOLOGY-TYPES { + description "Quantum Key Distribution System base technology types."; + } + + identity CV-QKD { + base QKD-TECHNOLOGY-TYPES; + description "Continuous Variable base technology."; + } + + identity DV-QKD { + base QKD-TECHNOLOGY-TYPES; + description "Discrete Variable base technology."; + } + + identity DV-QKD-COW { + base QKD-TECHNOLOGY-TYPES; + description "COW base technology."; + } + + identity DV-QKD-2Ws { + base QKD-TECHNOLOGY-TYPES; + description "2-Ways base technology."; + } + + typedef qkd-technology-types { + type identityref { + base QKD-TECHNOLOGY-TYPES; + } + description "This type represents the base technology types of the SD-QKD system."; + } + + identity QKDN-STATUS-TYPES { + description "Base identity used to identify the SD-QKD node status."; + } + + identity NEW { + base QKDN-STATUS-TYPES; + description "The QKD node is installed."; + } + + identity OPERATING { + base QKDN-STATUS-TYPES; + description "The QKD node is up."; + } + + identity DOWN { + base QKDN-STATUS-TYPES; + description "The QKD node is not working as expected."; + } + + identity FAILURE { + base QKDN-STATUS-TYPES; + description "The QKD node cannot be accessed by SDN controller with communication failure."; + } + + identity OUT { + base QKDN-STATUS-TYPES; + description "The QKD node is switched off and uninstalled."; + } + + typedef qkdn-status-types { + type identityref { + base QKDN-STATUS-TYPES; + } + description "This type represents the status of the SD-QKD node."; + } + + identity QKD-LINK-TYPES { + description "QKD key association link types."; + } + + identity VIRT { + base QKD-LINK-TYPES; + description "Virtual Link."; + } + + identity PHYS { + base QKD-LINK-TYPES; + description "Physical Link."; + } + + typedef qkd-link-types { + type identityref { + base QKD-LINK-TYPES; + } + description "This type represents the key association link type between two SD-QKD nodes."; + } + + identity QKD-ROLE-TYPES { + description "QKD Role Type."; + } + + identity TRANSMITTER { + base QKD-ROLE-TYPES; + description "QKD module working as transmitter."; + } + + identity RECEIVER { + base QKD-ROLE-TYPES; + description "QKD module working as receiver."; + } + + identity TRANSCEIVER { + base QKD-ROLE-TYPES; + description "QKD System that can work as a transmitter or receiver."; + } + + typedef qkd-role-types { + type identityref { + base QKD-ROLE-TYPES; + } + description "This type represents the working mode of a SD-QKD module."; + } + + identity QKD-APP-TYPES { + description "Application types."; + } + + identity CLIENT { + base QKD-APP-TYPES; + description "Application working as client."; + } + + identity INTERNAL { + base QKD-APP-TYPES; + description "Internal QKD node application."; + } + + typedef qkd-app-types { + type identityref { + base QKD-APP-TYPES; + } + description "This type represents the application class consuming key from SD-QKD nodes."; + } + + identity PHYS-PERF-TYPES { + description "Physical performance types."; + } + + identity QBER { + base PHYS-PERF-TYPES; + description "Quantum Bit Error Rate."; + } + + identity SNR { + base PHYS-PERF-TYPES; + description "Signal to Noise Ratio."; + } + + typedef phys-perf-types { + type identityref { + base PHYS-PERF-TYPES; + } + description "This type represents physical performance types."; + } + + identity LINK-STATUS-TYPES { + description "Status of the key association QKD link (physical and virtual)."; + } + + identity ACTIVE { + base LINK-STATUS-TYPES; + description "Link actively generating keys."; + } + + identity PASSIVE { + base LINK-STATUS-TYPES; + description "No key generation on key association QKD link but a pool of keys + are still available."; + } + + identity PENDING { + base LINK-STATUS-TYPES; + description "Waiting for activation and no keys are available."; + } + + identity OFF { + base LINK-STATUS-TYPES; + description "No key generation and no keys are available."; + } + + typedef link-status-types { + type identityref { + base LINK-STATUS-TYPES; + } + description "This type represents the status of a key association QKD link, both physical and virtual."; + } + + /// + + identity IFACE-STATUS-TYPES { + description "Interface Status."; + } + + identity ENABLED { + base IFACE-STATUS-TYPES; + description "The interfaces is up."; + } + + identity DISABLED { + base IFACE-STATUS-TYPES; + description "The interfaces is down."; + } + + identity FAILED { + base IFACE-STATUS-TYPES; + description "The interfaces has failed."; + } + + typedef iface-status-types { + type identityref { + base IFACE-STATUS-TYPES; + } + description "This type represents the status of a interface between a SD-QKD node and a SD-QKD module."; + } + + identity APP-STATUS-TYPES { + description "Application types."; + } + + identity ON { + base APP-STATUS-TYPES; + description "The application is on."; + } + + identity DISCONNECTED { + base APP-STATUS-TYPES; + description "The application is disconnected."; + } + + identity OUT-OF-TIME { + base APP-STATUS-TYPES; + description "The application is out of time."; + } + + identity ZOMBIE { + base APP-STATUS-TYPES; + description "The application is in a zombie state."; + } + + typedef app-status-types { + type identityref { + base APP-STATUS-TYPES; + } + description "This type represents the status of an application consuming key from SD-QKD nodes."; + } + + identity SEVERITY-TYPES { + description "Error/Failure severity levels."; + } + + identity MAJOR { + base SEVERITY-TYPES; + description "Major error/failure."; + } + + identity MINOR { + base SEVERITY-TYPES; + description "Minor error/failure."; + } + + typedef severity-types { + type identityref { + base SEVERITY-TYPES; + } + description "This type represents the Error/Failure severity levels."; + } + + typedef wavelength { + type string { + pattern "([1-9][0-9]{0,3})"; + } + description + "A WDM channel number (starting at 1). For example: 20"; + } + + //Pattern from "A Yang Data Model for WSON Optical Networks". + typedef wavelength-range-type { + type string { + pattern "([1-9][0-9]{0,3}(-[1-9][0-9]{0,3})?" + + "(,[1-9][0-9]{0,3}(-[1-9][0-9]{0,3})?)*)"; + } + description + "A list of WDM channel numbers (starting at 1) + in ascending order. For example: 1,12-20,40,50-80"; + } +} diff --git a/src/tests/tools/mock_qkd_nodes/yang/etsi-qkd-sdn-node.yang b/src/tests/tools/mock_qkd_nodes/yang/etsi-qkd-sdn-node.yang new file mode 100644 index 0000000000000000000000000000000000000000..d07004cdc5b558adc5a9c0b6acb32adac0d7cc11 --- /dev/null +++ b/src/tests/tools/mock_qkd_nodes/yang/etsi-qkd-sdn-node.yang @@ -0,0 +1,941 @@ +/* Copyright 2022 ETSI +Licensed under the BSD-3 Clause (https://forge.etsi.org/legal-matters) */ + +module etsi-qkd-sdn-node { + + yang-version "1"; + + namespace "urn:etsi:qkd:yang:etsi-qkd-node"; + + prefix "etsi-qkdn"; + + import ietf-yang-types { prefix "yang"; } + import ietf-inet-types { prefix "inet"; } + import etsi-qkd-node-types { prefix "etsi-qkdn-types"; } + + // meta + organization "ETSI ISG QKD"; + + contact + "https://www.etsi.org/committee/qkd + vicente@fi.upm.es"; + + description + "This module contains the groupings and containers composing + the software-defined QKD node information models + specified in ETSI GS QKD 015 V2.1.1"; + + revision "2022-01-30" { + description + "Refinement of the YANG model to make it compatible with the ETSI ISG QKD 018. Minor fixes."; + reference + "ETSI GS QKD 015 V2.1.1 (2022-01)"; + } + + revision "2020-09-30" { + description + "First definition based on initial requirement analysis."; + reference + "ETSI GS QKD 015 V1.1.1 (2021-03)"; + } + + grouping qkdn_id { + description "Grouping of qkdn_id leaf."; + + leaf qkdn_id { + type yang:uuid; + mandatory true; + description + "This value reflects the unique ID of the SD-QKD node."; + } + } + + grouping qkdn_version { + description "Grouping of qkdn_version leaf."; + + leaf qkdn_version { + type string; + description "Hardware or software version of the SD-QKD node."; + } + } + + grouping qkdn_location_id { + description "Grouping of qkdn_location_id leaf."; + + leaf qkdn_location_id { + type string; + default ""; + description + "This value enables the location of the secure + area that contains the SD-QKD node to be specified."; + } + } + + grouping qkdn_status { + description "Grouping of qkdn_status leaf."; + + leaf qkdn_status { + type etsi-qkdn-types:qkdn-status-types; + config false; + description "Status of the SD-QKD node."; + } + } + + grouping qkdn_capabilities { + description "Grouping of the capabilities of the SD-QKD node."; + + container qkdn_capabilities { + description "Capabilities of the SD-QKD node."; + + leaf link_stats_support { + type boolean; + default true; + description + "If true, this node exposes link-related statistics (secure key + generation rate-SKR, link consumption, status, QBER)."; + } + + leaf application_stats_support { + type boolean; + default true; + description "If true, this node exposes application related + statistics (application consumption, alerts)."; + } + + leaf key_relay_mode_enable { + type boolean; + default true; + description "If true, this node supports key relay (multi-hop) mode services."; + } + } + } + + grouping app_id { + description "Grouping of app_id leaf."; + + leaf app_id { + type yang:uuid; + description + "Unique ID that identifies a QKD application consisting of a set of entities + that are allowed to receive keys shared with each other from the SD-QKD nodes + they connect to. This value is similar to a key ID or key handle."; + } + } + + grouping app_basic { + description "Grouping of app's basic parameters."; + + uses app_id; + + leaf app_status { + type etsi-qkdn-types:app-status-types; + config false; + description "Status of the application."; + } + } + + grouping app_priority { + description "Grouping of app_priority leaf."; + + leaf app_priority { + type uint32; + default 0; + description "Priority of the association/application + might be defined by the user but usually + handled by a network administrator."; + } + } + + grouping app_details { + description "Grouping of app's details parameters."; + + leaf app_type { + type etsi-qkdn-types:qkd-app-types; + description "Type of the registered application. These + values, defined within the types module, can be client + (if an external applications requesting keys) + or internal (application is defined to maintain + the QKD - e.g. multi-hop, authentication or + other encryption operations)."; + } + + leaf server_app_id { + type inet:uri; + description "ID that identifies the entity that initiated the + creation of the QKD application to receive keys shared with one + or more specified target entity identified by client_app_id. + It is a client in the interface to the SD-QKD node and the name + server_app_id reflects that it requested the QKD application to + be initiated."; + } + + leaf-list client_app_id { + type inet:uri; + description "List of IDs that identifies the one or more + entities that are allowed to receive keys from SD-QKD + node(s) under the QKD application in addition to the + initiating entity identified by server_app_id."; + } + + uses app_priority; + } + + grouping local_qkdn_id { + description "Grouping of local_qkdn_id leaf."; + + leaf local_qkdn_id { + type yang:uuid; + description "Unique ID of the local SD-QKD node which + is providing QKD keys to the local application."; + } + } + + grouping app_time { + description "Grouping of app's time parameters."; + + leaf creation_time { + type yang:date-and-time; + config false; + description "Date and time of the service creation."; + } + + leaf expiration_time { + type yang:date-and-time; + description "Date and time of the service expiration."; + } + } + + grouping app_statistics { + description "Grouping of app's statistic parameters."; + + container app_statistics { + description "Statistical information relating to a specific statistic period of time."; + + list statistics { + key "end_time"; + config false; + description "List of statistics."; + + leaf end_time { + type yang:date-and-time; + config false; + description "End time for the statistic period."; + } + + leaf start_time { + type yang:date-and-time; + config false; + description "Start time for the statistic period."; + } + + leaf consumed_bits { + type uint32; + config false; + description "Consumed secret key amount (in bits) for a statistics collection period of time."; + } + } + } + } + + grouping app_qos { + description "Grouping of app's basic qos parameters."; + + container app_qos { + description "Requested Quality of Service."; + + leaf max_bandwidth { + type uint32; + description "Maximum bandwidth (in bits per second) allowed for + this specific application. Exceeding this value will raise an + error from the local key store to the appl. This value might + be internally configured (or by an admin) with a default value."; + } + + leaf min_bandwidth { + type uint32; + description "This value is an optional QoS parameter which + enables to require a minimum key rate (in bits per second) + for the application."; + } + + leaf jitter { + type uint32; + description "This value allows to specify the maximum jitter + (in msec) to be provided by the key delivery API for + applications requiring fast rekeying. This value can be + coordinated with the other QoS to provide a wide enough + QoS definition."; + } + + leaf ttl { + type uint32; + description "This value is used to specify the maximum time + (in seconds) that a key could be kept in the key store for + a given application without being used."; + } + } + } + + grouping augmented_app_qos { + description "Grouping of app's detailed qos parameters."; + + uses app_qos { + augment app_qos { + description "Augmentation of app's basic parameters with app's detailed qos parameters."; + + leaf clients_shared_path_enable { + type boolean; + default false; + description "If true, multiple clients for this + application might share keys to reduce service + impact (consumption)."; + } + + leaf clients_shared_keys_required { + type boolean; + default false; + description "If true, multiple clients for this application + might share keys to reduce service impact (consumption)."; + } + } + } + } + + grouping qkd_applications { + description "Grouping of the list of applications container."; + + container qkd_applications { + description "List of applications container."; + + list qkd_app { + key "app_id"; + description "List of applications that are currently registered + in the SD-QKD node. Any entity consuming QKD-derived keys (either + for internal or external purposes) is considered an application."; + + uses app_basic; + + uses app_details; + + uses app_time; + + uses app_statistics; + + uses augmented_app_qos; + + leaf-list backing_qkdl_id { + type yang:uuid; + description "Unique ID of the key association link which is + providing QKD keys to these applications."; + } + + uses local_qkdn_id; + + leaf remote_qkdn_id { + type yang:uuid; + description "Unique ID of the remote SD-QKD node which + is providing QKD keys to the remote application. + While unknown, the local SD-QKD will not be able to + provide keys to the local application."; + } + } + } + } + + grouping qkdi_status { + description "Grouping of qkdi_status leaf."; + + leaf qkdi_status { + type etsi-qkdn-types:iface-status-types; + config false; + description "Status of a QKD interface of the SD-QKD node."; + } + } + + grouping qkdi_model { + description "Grouping of qkdi_model leaf."; + + leaf qkdi_model { + type string; + description "Device model (vendor/device)."; + } + } + + grouping qkdi_type { + description "Grouping of qkdi_type leaf."; + + leaf qkdi_type { + type etsi-qkdn-types:qkd-technology-types; + description "Interface type (QKD technology)."; + } + } + + grouping qkdi_att_point { + description "Grouping of the interface attachment points to an optical switch."; + + container qkdi_att_point { + description "Interface attachment point to an optical switch."; + + leaf device { + type string; + description "Unique ID of the optical switch (or + passive component) to which the interface is connected."; + } + + leaf port { + type uint32; + description "Port ID of the device to which the interface + is connected."; + } + } + } + + grouping qkdi_id { + description "Grouping of qkdi_id leaf."; + + leaf qkdi_id { + type uint32; + description "Interface id. It is described as a locally unique number, + which is globally unique when combined with the SD-QKD node ID."; + } + } + + grouping qkd_interface_item { + description "Grouping of the interface parameters."; + + uses qkdi_id; + + uses qkdi_model; + + uses qkdi_type; + + uses qkdi_att_point; + + container qkdi_capabilities { + description "Capabilities of the QKD system (interface)."; + + leaf role_support { + type etsi-qkdn-types:qkd-role-types; + description "QKD node support for key relay mode services."; + } + + leaf wavelength_range { + type etsi-qkdn-types:wavelength-range-type; + description "Range of supported wavelengths (nm) (multiple + if it contains a tunable laser)."; + } + + leaf max_absorption { + type decimal64 { + fraction-digits 3; + } + description "Maximum absorption supported (in dB)."; + } + } + } + + grouping qkd_interfaces { + description "Grouping of the list of interfaces."; + + container qkd_interfaces { + description "List of interfaces container."; + + list qkd_interface { + key "qkdi_id"; + description "List of physical QKD modules in a secure location, + abstracted as interfaces of the SD-QKD node."; + + uses qkd_interface_item; + + uses qkdi_status; + + } + } + } + + grouping qkdl_id { + description "Grouping of qkdl_id leaf."; + + leaf qkdl_id { + type yang:uuid; + description "Unique ID of the QKD link (key association)."; + } + } + + grouping qkdl_status { + description "Grouping of qkdl_status leaf."; + + leaf qkdl_status { + type etsi-qkdn-types:link-status-types; + description "Status of the QKD key association link."; + } + } + + grouping common_performance { + description "Grouping of common performance parameters."; + + leaf expected_consumption { + type uint32; + config false; + description "Sum of all the application's bandwidth (in bits per + second) on this particular key association link."; + } + + leaf skr { + type uint32; + config false; + description "Secret key rate generation (in bits per second) + of the key association link."; + } + + leaf eskr { + type uint32; + config false; + description "Effective secret key rate (in bits per second) generation + of the key association link available after internal consumption."; + } + } + + grouping physical_link_perf { + description "Grouping of the list of physical performance parameters."; + + list phys_perf { + key "perf_type"; + config false; + description "List of physical performance parameters."; + + leaf perf_type { + type etsi-qkdn-types:phys-perf-types; + config false; + description "Type of the physical performance value to be + exposed to the controller."; + } + + leaf value { + type decimal64 { + fraction-digits 3; + } + config false; + description "Numerical value for the performance parameter + type specified above."; + } + } + } + + grouping virtual_link_spec { + description "Grouping of the virtual link's parameters."; + + leaf virt_prev_hop { + type yang:uuid; + description "Previous hop in a multi-hop/virtual key + association link config."; + } + + leaf-list virt_next_hop { + type yang:uuid; + description "Next hop(s) in a multihop/virtual key + association link config. Defined as a list for multicast + over shared sub-paths."; + } + + leaf virt_bandwidth { + type uint32; + description "Required bandwidth (in bits per second) for that key association link. + Used to reserve bandwidth from the physical QKD links to support the virtual key + association link as an internal application."; + } + } + + grouping physical_link_spec { + description "Grouping of the physical link's parameters."; + + leaf phys_channel_att { + type decimal64 { + fraction-digits 3; + } + description "Expected attenuation on the quantum channel (in dB) + between the Source/qkd_node and Destination/qkd_node."; + + } + + leaf phys_wavelength { + type etsi-qkdn-types:wavelength; + description "Wavelength (in nm) to be used for the quantum channel. + If the interface is not tunable, this configuration could be bypassed"; + } + + leaf phys_qkd_role { + type etsi-qkdn-types:qkd-role-types; + description "Transmitter/receiver mode for the QKD module. + If there is no multi-role support, this could be ignored."; + } + } + + grouping qkd_links { + description "Grouping of the list of links."; + + container qkd_links { + description "List of links container"; + + list qkd_link { + key "qkdl_id"; + description "List of (key association) links to other SD-QKD nodes in the network. + The links can be physical (direct quantum channel) or virtual multi-hop + connection doing key-relay through several nodes."; + + uses qkdl_id; + + uses qkdl_status; + + leaf qkdl_enable { + type boolean; + default true; + description "This value allows to enable of disable the key generation + process for a given link."; + + } + + container qkdl_local { + description "Source (local) node of the SD-QKD link."; + + leaf qkdn_id { + type yang:uuid; + description "Unique ID of the local SD-QKD node."; + } + + leaf qkdi_id { + type uint32; + description "Interface used to create the key association link."; + } + } + + container qkdl_remote { + description "Destination (remote) unique SD-QKD node."; + + leaf qkdn_id { + type yang:uuid; + description "Unique ID of the remote SD-QKD node. This value is + provided by the SDN controller when the key association link + request arrives."; + } + + leaf qkdi_id { + type uint32; + description "Interface used to create the link."; + } + } + + leaf qkdl_type { + type etsi-qkdn-types:qkd-link-types; + description "Key Association Link type: Virtual (multi-hop) or Direct."; + } + + leaf-list qkdl_applications { + type yang:uuid; + description "Applications which are consuming keys from + this key association link."; + } + + uses virtual_link_spec { + when "qkdl_type = 'etsi-qkd-node-types:VIRT'" { + description "Virtual key association link specific configuration."; + } + } + + uses physical_link_spec { + when "qkdl_type = 'etsi-qkd-node-types:PHYS'" { + description "Physical key association link specific configuration."; + } + } + + container qkdl_performance { + description "Container of link's performace parameters."; + + uses common_performance; + + uses physical_link_perf { + when "../qkdl_type = 'PHYS'" { + description "Performance of the specific physical link."; + } + } + } + } + } + } + + container qkd_node { + description + "Top module describing a software-defined QKD node (SD-QKD node)."; + + uses qkdn_id; + + uses qkdn_status; + + uses qkdn_version; + + uses qkdn_location_id; + + uses qkdn_capabilities; + + uses qkd_applications; + + uses qkd_interfaces; + + uses qkd_links; + } + + grouping message { + description "Grouping of message leaf."; + + leaf message { + type string; + description "Placeholder for the message."; + } + } + + grouping severity { + description "Grouping of severity leaf."; + + leaf severity { + type etsi-qkdn-types:severity-types; + description "Placeholder for the severity."; + } + } + + grouping reason { + description "Grouping of reason leaf."; + + leaf reason { + type string; + description "Auxiliary parameter to include additional + information about the reason for link failure."; + } + } + + notification sdqkdn_application_new { + description "Defined for the controller to detect new applications + requesting keys from a QKD node. This maps with the workflow shown + in clause 5.2 'QKD Application Registration'. Parameters such as + client and server app IDs, local QKD node identifier, priority and + QoS are sent in the notification."; + + container qkd_application { + description "'sdqkdn_application_new' notification's qkd_application parameters."; + + uses app_details; + + uses local_qkdn_id; + + uses augmented_app_qos; + + } + } + + notification sdqkdn_application_qos_update { + description "Notification that includes information about priority or + QoS changes on an existing and already registered application."; + + container qkd_application { + description "'sdqkdn_application_qos_update' notification's qkd_application parameters."; + + uses app_id; + + uses augmented_app_qos; + + uses app_priority; + + } + } + + notification sdqkdn_application_disconnected { + description "Includes the application identifier to inform that the + application is no longer registered and active in the QKD node."; + + container qkd_application { + description "'sdqkdn_application_disconnected' notification's qkd_application parameters."; + + uses app_id; + + } + } + + notification sdqkdn_interface_new { + description "Includes all the information about the new QKD system + installed in the secure location of a given QKD node."; + + container qkd_interface { + description "'sdqkdn_interface_new' notification's qkd_interface parameters."; + + uses qkd_interface_item; + + } + } + + notification sdqkdn_interface_down { + description "Identifies an interface within a QKD node which is not + working as expected, allowing additional information to be included + in a 'reason' string field."; + + container qkd_interface { + description "'sdqkdn_interface_down' notification's qkd_interface parameters."; + + uses qkdi_id; + + uses reason; + + } + } + + notification sdqkdn_interface_out { + description "Contains the ID of an interface which is switch off and + uninstall from a QKD node. This information can be gathered from this + notification or from regular polling from the controller's side."; + + container qkd_interface { + description "'sdqkdn_interface_out' notification's qkd_interface parameters."; + + uses qkdi_id; + + } + } + + notification sdqkdn_link_down { + description "As in the interface down event, this notification contains + the identifier of a given link which has gone down unexpectedly. + In addition, further information can be sent in the 'reason' field."; + + container qkd_link { + description "'sdqkdn_link_down' notification's qkd_link parameters."; + + uses qkdl_id; + + uses reason; + + } + } + + notification sdqkdn_link_perf_update { + description "This notification allows to inform of any mayor + modification in the performance of an active link. The identifier + of the link is sent together with the performance parameters of the link."; + + container qkd_link { + description "'sdqkdn_link_perf_update' notification's qkd_link parameters."; + + uses qkdl_id; + + container performance { + description "'sdqkdn_link_perf_update' notification's performance parameters."; + + uses common_performance; + + uses physical_link_perf; + + } + } + } + + notification sdqkdn_link_overloaded { + description "This notification is sent when the link cannot cope with the + demand. The link identifier is sent with the expected consumption and + general performance parameters."; + + container qkd_link { + description "'sdqkdn_link_overloaded' notification's qkd_link parameters."; + + uses qkdl_id; + + container performance { + description "'sdqkdn_link_overloaded' notification's performance parameters."; + + uses common_performance; + + } + } + } + + notification alarm { + description "'alarm' notification."; + + container link { + description "'alarm' notification's link parameters."; + + uses qkdl_id; + + uses qkdl_status; + + uses message; + + uses severity; + + } + + container interface { + description "'alarm' notification's interface parameters."; + + uses qkdi_id; + + uses qkdi_status; + + uses message; + + uses severity; + + } + + container application { + description "'alarm' notification's application parameters."; + + uses app_basic; + + uses message; + + uses severity; + + } + + } + + notification event { + description "'event' notification."; + + container link { + description "'alarm' notification's link parameters."; + + uses qkdl_id; + + uses qkdl_status; + + uses message; + + uses severity; + + } + + container interface { + description "'alarm' notification's interface parameters."; + + uses qkdi_id; + + uses qkdi_status; + + uses message; + + uses severity; + + } + + container application { + description "'alarm' notification's application parameters."; + + uses app_basic; + + uses message; + + uses severity; + + } + + } + +} diff --git a/src/tests/tools/mock_qkd_nodes/yang/ietf-inet-types.yang b/src/tests/tools/mock_qkd_nodes/yang/ietf-inet-types.yang new file mode 100644 index 0000000000000000000000000000000000000000..eacefb6363de1beb543567a0fa705571b7dc57a2 --- /dev/null +++ b/src/tests/tools/mock_qkd_nodes/yang/ietf-inet-types.yang @@ -0,0 +1,458 @@ +module ietf-inet-types { + + namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types"; + prefix "inet"; + + organization + "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; + + contact + "WG Web: + WG List: + + WG Chair: David Kessens + + + WG Chair: Juergen Schoenwaelder + + + Editor: Juergen Schoenwaelder + "; + + description + "This module contains a collection of generally useful derived + YANG data types for Internet addresses and related things. + + Copyright (c) 2013 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 6991; see + the RFC itself for full legal notices."; + + revision 2013-07-15 { + description + "This revision adds the following new data types: + - ip-address-no-zone + - ipv4-address-no-zone + - ipv6-address-no-zone"; + reference + "RFC 6991: Common YANG Data Types"; + } + + revision 2010-09-24 { + description + "Initial revision."; + reference + "RFC 6021: Common YANG Data Types"; + } + + /*** collection of types related to protocol fields ***/ + + typedef ip-version { + type enumeration { + enum unknown { + value "0"; + description + "An unknown or unspecified version of the Internet + protocol."; + } + enum ipv4 { + value "1"; + description + "The IPv4 protocol as defined in RFC 791."; + } + enum ipv6 { + value "2"; + description + "The IPv6 protocol as defined in RFC 2460."; + } + } + description + "This value represents the version of the IP protocol. + + In the value set and its semantics, this type is equivalent + to the InetVersion textual convention of the SMIv2."; + reference + "RFC 791: Internet Protocol + RFC 2460: Internet Protocol, Version 6 (IPv6) Specification + RFC 4001: Textual Conventions for Internet Network Addresses"; + } + + typedef dscp { + type uint8 { + range "0..63"; + } + description + "The dscp type represents a Differentiated Services Code Point + that may be used for marking packets in a traffic stream. + In the value set and its semantics, this type is equivalent + to the Dscp textual convention of the SMIv2."; + reference + "RFC 3289: Management Information Base for the Differentiated + Services Architecture + RFC 2474: Definition of the Differentiated Services Field + (DS Field) in the IPv4 and IPv6 Headers + RFC 2780: IANA Allocation Guidelines For Values In + the Internet Protocol and Related Headers"; + } + + typedef ipv6-flow-label { + type uint32 { + range "0..1048575"; + } + description + "The ipv6-flow-label type represents the flow identifier or Flow + Label in an IPv6 packet header that may be used to + discriminate traffic flows. + + In the value set and its semantics, this type is equivalent + to the IPv6FlowLabel textual convention of the SMIv2."; + reference + "RFC 3595: Textual Conventions for IPv6 Flow Label + RFC 2460: Internet Protocol, Version 6 (IPv6) Specification"; + } + + typedef port-number { + type uint16 { + range "0..65535"; + } + description + "The port-number type represents a 16-bit port number of an + Internet transport-layer protocol such as UDP, TCP, DCCP, or + SCTP. Port numbers are assigned by IANA. A current list of + all assignments is available from . + + Note that the port number value zero is reserved by IANA. In + situations where the value zero does not make sense, it can + be excluded by subtyping the port-number type. + In the value set and its semantics, this type is equivalent + to the InetPortNumber textual convention of the SMIv2."; + reference + "RFC 768: User Datagram Protocol + RFC 793: Transmission Control Protocol + RFC 4960: Stream Control Transmission Protocol + RFC 4340: Datagram Congestion Control Protocol (DCCP) + RFC 4001: Textual Conventions for Internet Network Addresses"; + } + + /*** collection of types related to autonomous systems ***/ + + typedef as-number { + type uint32; + description + "The as-number type represents autonomous system numbers + which identify an Autonomous System (AS). An AS is a set + of routers under a single technical administration, using + an interior gateway protocol and common metrics to route + packets within the AS, and using an exterior gateway + protocol to route packets to other ASes. IANA maintains + the AS number space and has delegated large parts to the + regional registries. + + Autonomous system numbers were originally limited to 16 + bits. BGP extensions have enlarged the autonomous system + number space to 32 bits. This type therefore uses an uint32 + base type without a range restriction in order to support + a larger autonomous system number space. + + In the value set and its semantics, this type is equivalent + to the InetAutonomousSystemNumber textual convention of + the SMIv2."; + reference + "RFC 1930: Guidelines for creation, selection, and registration + of an Autonomous System (AS) + RFC 4271: A Border Gateway Protocol 4 (BGP-4) + RFC 4001: Textual Conventions for Internet Network Addresses + RFC 6793: BGP Support for Four-Octet Autonomous System (AS) + Number Space"; + } + + /*** collection of types related to IP addresses and hostnames ***/ + + typedef ip-address { + type union { + type inet:ipv4-address; + type inet:ipv6-address; + } + description + "The ip-address type represents an IP address and is IP + version neutral. The format of the textual representation + implies the IP version. This type supports scoped addresses + by allowing zone identifiers in the address format."; + reference + "RFC 4007: IPv6 Scoped Address Architecture"; + } + + typedef ipv4-address { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' + + '(%[\p{N}\p{L}]+)?'; + } + description + "The ipv4-address type represents an IPv4 address in + dotted-quad notation. The IPv4 address may include a zone + index, separated by a % sign. + + The zone index is used to disambiguate identical address + values. For link-local addresses, the zone index will + typically be the interface index number or the name of an + interface. If the zone index is not present, the default + zone of the device will be used. + + The canonical format for the zone index is the numerical + format"; + } + + typedef ipv6-address { + type string { + pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' + + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' + + '(%[\p{N}\p{L}]+)?'; + pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' + + '(%.+)?'; + } + description + "The ipv6-address type represents an IPv6 address in full, + mixed, shortened, and shortened-mixed notation. The IPv6 + address may include a zone index, separated by a % sign. + + The zone index is used to disambiguate identical address + values. For link-local addresses, the zone index will + typically be the interface index number or the name of an + interface. If the zone index is not present, the default + zone of the device will be used. + + The canonical format of IPv6 addresses uses the textual + representation defined in Section 4 of RFC 5952. The + canonical format for the zone index is the numerical + format as described in Section 11.2 of RFC 4007."; + reference + "RFC 4291: IP Version 6 Addressing Architecture + RFC 4007: IPv6 Scoped Address Architecture + RFC 5952: A Recommendation for IPv6 Address Text + Representation"; + } + + typedef ip-address-no-zone { + type union { + type inet:ipv4-address-no-zone; + type inet:ipv6-address-no-zone; + } + description + "The ip-address-no-zone type represents an IP address and is + IP version neutral. The format of the textual representation + implies the IP version. This type does not support scoped + addresses since it does not allow zone identifiers in the + address format."; + reference + "RFC 4007: IPv6 Scoped Address Architecture"; + } + + typedef ipv4-address-no-zone { + type inet:ipv4-address { + pattern '[0-9\.]*'; + } + description + "An IPv4 address without a zone index. This type, derived from + ipv4-address, may be used in situations where the zone is + known from the context and hence no zone index is needed."; + } + + typedef ipv6-address-no-zone { + type inet:ipv6-address { + pattern '[0-9a-fA-F:\.]*'; + } + description + "An IPv6 address without a zone index. This type, derived from + ipv6-address, may be used in situations where the zone is + known from the context and hence no zone index is needed."; + reference + "RFC 4291: IP Version 6 Addressing Architecture + RFC 4007: IPv6 Scoped Address Architecture + RFC 5952: A Recommendation for IPv6 Address Text + Representation"; + } + + typedef ip-prefix { + type union { + type inet:ipv4-prefix; + type inet:ipv6-prefix; + } + description + "The ip-prefix type represents an IP prefix and is IP + version neutral. The format of the textual representations + implies the IP version."; + } + + typedef ipv4-prefix { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' + + '/(([0-9])|([1-2][0-9])|(3[0-2]))'; + } + description + "The ipv4-prefix type represents an IPv4 address prefix. + The prefix length is given by the number following the + slash character and must be less than or equal to 32. + + A prefix length value of n corresponds to an IP address + mask that has n contiguous 1-bits from the most + significant bit (MSB) and all other bits set to 0. + + The canonical format of an IPv4 prefix has all bits of + the IPv4 address set to zero that are not part of the + IPv4 prefix."; + } + + typedef ipv6-prefix { + type string { + pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' + + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' + + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'; + pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' + + '(/.+)'; + } + + description + "The ipv6-prefix type represents an IPv6 address prefix. + The prefix length is given by the number following the + slash character and must be less than or equal to 128. + + A prefix length value of n corresponds to an IP address + mask that has n contiguous 1-bits from the most + significant bit (MSB) and all other bits set to 0. + + The IPv6 address should have all bits that do not belong + to the prefix set to zero. + + The canonical format of an IPv6 prefix has all bits of + the IPv6 address set to zero that are not part of the + IPv6 prefix. Furthermore, the IPv6 address is represented + as defined in Section 4 of RFC 5952."; + reference + "RFC 5952: A Recommendation for IPv6 Address Text + Representation"; + } + + /*** collection of domain name and URI types ***/ + + typedef domain-name { + type string { + pattern + '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*' + + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)' + + '|\.'; + length "1..253"; + } + description + "The domain-name type represents a DNS domain name. The + name SHOULD be fully qualified whenever possible. + + Internet domain names are only loosely specified. Section + 3.5 of RFC 1034 recommends a syntax (modified in Section + 2.1 of RFC 1123). The pattern above is intended to allow + for current practice in domain name use, and some possible + future expansion. It is designed to hold various types of + domain names, including names used for A or AAAA records + (host names) and other records, such as SRV records. Note + that Internet host names have a stricter syntax (described + in RFC 952) than the DNS recommendations in RFCs 1034 and + 1123, and that systems that want to store host names in + schema nodes using the domain-name type are recommended to + adhere to this stricter standard to ensure interoperability. + + The encoding of DNS names in the DNS protocol is limited + to 255 characters. Since the encoding consists of labels + prefixed by a length bytes and there is a trailing NULL + byte, only 253 characters can appear in the textual dotted + notation. + + The description clause of schema nodes using the domain-name + type MUST describe when and how these names are resolved to + IP addresses. Note that the resolution of a domain-name value + may require to query multiple DNS records (e.g., A for IPv4 + and AAAA for IPv6). The order of the resolution process and + which DNS record takes precedence can either be defined + explicitly or may depend on the configuration of the + resolver. + + Domain-name values use the US-ASCII encoding. Their canonical + format uses lowercase US-ASCII characters. Internationalized + domain names MUST be A-labels as per RFC 5890."; + reference + "RFC 952: DoD Internet Host Table Specification + RFC 1034: Domain Names - Concepts and Facilities + RFC 1123: Requirements for Internet Hosts -- Application + and Support + RFC 2782: A DNS RR for specifying the location of services + (DNS SRV) + RFC 5890: Internationalized Domain Names in Applications + (IDNA): Definitions and Document Framework"; + } + + typedef host { + type union { + type inet:ip-address; + type inet:domain-name; + } + description + "The host type represents either an IP address or a DNS + domain name."; + } + + typedef uri { + type string; + description + "The uri type represents a Uniform Resource Identifier + (URI) as defined by STD 66. + + Objects using the uri type MUST be in US-ASCII encoding, + and MUST be normalized as described by RFC 3986 Sections + 6.2.1, 6.2.2.1, and 6.2.2.2. All unnecessary + percent-encoding is removed, and all case-insensitive + characters are set to lowercase except for hexadecimal + digits, which are normalized to uppercase as described in + Section 6.2.2.1. + + The purpose of this normalization is to help provide + unique URIs. Note that this normalization is not + sufficient to provide uniqueness. Two URIs that are + textually distinct after this normalization may still be + equivalent. + + Objects using the uri type may restrict the schemes that + they permit. For example, 'data:' and 'urn:' schemes + might not be appropriate. + + A zero-length URI is not a valid URI. This can be used to + express 'URI absent' where required. + + In the value set and its semantics, this type is equivalent + to the Uri SMIv2 textual convention defined in RFC 5017."; + reference + "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax + RFC 3305: Report from the Joint W3C/IETF URI Planning Interest + Group: Uniform Resource Identifiers (URIs), URLs, + and Uniform Resource Names (URNs): Clarifications + and Recommendations + RFC 5017: MIB Textual Conventions for Uniform Resource + Identifiers (URIs)"; + } + +} diff --git a/src/tests/tools/mock_qkd_nodes/yang/ietf-yang-types.yang b/src/tests/tools/mock_qkd_nodes/yang/ietf-yang-types.yang new file mode 100644 index 0000000000000000000000000000000000000000..ee58fa3ab0042120d5607b8713d21fa0ba845895 --- /dev/null +++ b/src/tests/tools/mock_qkd_nodes/yang/ietf-yang-types.yang @@ -0,0 +1,474 @@ +module ietf-yang-types { + + namespace "urn:ietf:params:xml:ns:yang:ietf-yang-types"; + prefix "yang"; + + organization + "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; + + contact + "WG Web: + WG List: + + WG Chair: David Kessens + + + WG Chair: Juergen Schoenwaelder + + + Editor: Juergen Schoenwaelder + "; + + description + "This module contains a collection of generally useful derived + YANG data types. + + Copyright (c) 2013 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 6991; see + the RFC itself for full legal notices."; + + revision 2013-07-15 { + description + "This revision adds the following new data types: + - yang-identifier + - hex-string + - uuid + - dotted-quad"; + reference + "RFC 6991: Common YANG Data Types"; + } + + revision 2010-09-24 { + description + "Initial revision."; + reference + "RFC 6021: Common YANG Data Types"; + } + + /*** collection of counter and gauge types ***/ + + typedef counter32 { + type uint32; + description + "The counter32 type represents a non-negative integer + that monotonically increases until it reaches a + maximum value of 2^32-1 (4294967295 decimal), when it + wraps around and starts increasing again from zero. + + Counters have no defined 'initial' value, and thus, a + single value of a counter has (in general) no information + content. Discontinuities in the monotonically increasing + value normally occur at re-initialization of the + management system, and at other times as specified in the + description of a schema node using this type. If such + other times can occur, for example, the creation of + a schema node of type counter32 at times other than + re-initialization, then a corresponding schema node + should be defined, with an appropriate type, to indicate + the last discontinuity. + + The counter32 type should not be used for configuration + schema nodes. A default statement SHOULD NOT be used in + combination with the type counter32. + + In the value set and its semantics, this type is equivalent + to the Counter32 type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef zero-based-counter32 { + type yang:counter32; + default "0"; + description + "The zero-based-counter32 type represents a counter32 + that has the defined 'initial' value zero. + + A schema node of this type will be set to zero (0) on creation + and will thereafter increase monotonically until it reaches + a maximum value of 2^32-1 (4294967295 decimal), when it + wraps around and starts increasing again from zero. + + Provided that an application discovers a new schema node + of this type within the minimum time to wrap, it can use the + 'initial' value as a delta. It is important for a management + station to be aware of this minimum time and the actual time + between polls, and to discard data if the actual time is too + long or there is no defined minimum time. + + In the value set and its semantics, this type is equivalent + to the ZeroBasedCounter32 textual convention of the SMIv2."; + reference + "RFC 4502: Remote Network Monitoring Management Information + Base Version 2"; + } + + typedef counter64 { + type uint64; + description + "The counter64 type represents a non-negative integer + that monotonically increases until it reaches a + maximum value of 2^64-1 (18446744073709551615 decimal), + when it wraps around and starts increasing again from zero. + + Counters have no defined 'initial' value, and thus, a + single value of a counter has (in general) no information + content. Discontinuities in the monotonically increasing + value normally occur at re-initialization of the + management system, and at other times as specified in the + description of a schema node using this type. If such + other times can occur, for example, the creation of + a schema node of type counter64 at times other than + re-initialization, then a corresponding schema node + should be defined, with an appropriate type, to indicate + the last discontinuity. + + The counter64 type should not be used for configuration + schema nodes. A default statement SHOULD NOT be used in + combination with the type counter64. + + In the value set and its semantics, this type is equivalent + to the Counter64 type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef zero-based-counter64 { + type yang:counter64; + default "0"; + description + "The zero-based-counter64 type represents a counter64 that + has the defined 'initial' value zero. + + A schema node of this type will be set to zero (0) on creation + and will thereafter increase monotonically until it reaches + a maximum value of 2^64-1 (18446744073709551615 decimal), + when it wraps around and starts increasing again from zero. + + Provided that an application discovers a new schema node + of this type within the minimum time to wrap, it can use the + 'initial' value as a delta. It is important for a management + station to be aware of this minimum time and the actual time + between polls, and to discard data if the actual time is too + long or there is no defined minimum time. + + In the value set and its semantics, this type is equivalent + to the ZeroBasedCounter64 textual convention of the SMIv2."; + reference + "RFC 2856: Textual Conventions for Additional High Capacity + Data Types"; + } + + typedef gauge32 { + type uint32; + description + "The gauge32 type represents a non-negative integer, which + may increase or decrease, but shall never exceed a maximum + value, nor fall below a minimum value. The maximum value + cannot be greater than 2^32-1 (4294967295 decimal), and + the minimum value cannot be smaller than 0. The value of + a gauge32 has its maximum value whenever the information + being modeled is greater than or equal to its maximum + value, and has its minimum value whenever the information + being modeled is smaller than or equal to its minimum value. + If the information being modeled subsequently decreases + below (increases above) the maximum (minimum) value, the + gauge32 also decreases (increases). + + In the value set and its semantics, this type is equivalent + to the Gauge32 type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef gauge64 { + type uint64; + description + "The gauge64 type represents a non-negative integer, which + may increase or decrease, but shall never exceed a maximum + value, nor fall below a minimum value. The maximum value + cannot be greater than 2^64-1 (18446744073709551615), and + the minimum value cannot be smaller than 0. The value of + a gauge64 has its maximum value whenever the information + being modeled is greater than or equal to its maximum + value, and has its minimum value whenever the information + being modeled is smaller than or equal to its minimum value. + If the information being modeled subsequently decreases + below (increases above) the maximum (minimum) value, the + gauge64 also decreases (increases). + + In the value set and its semantics, this type is equivalent + to the CounterBasedGauge64 SMIv2 textual convention defined + in RFC 2856"; + reference + "RFC 2856: Textual Conventions for Additional High Capacity + Data Types"; + } + + /*** collection of identifier-related types ***/ + + typedef object-identifier { + type string { + pattern '(([0-1](\.[1-3]?[0-9]))|(2\.(0|([1-9]\d*))))' + + '(\.(0|([1-9]\d*)))*'; + } + description + "The object-identifier type represents administratively + assigned names in a registration-hierarchical-name tree. + + Values of this type are denoted as a sequence of numerical + non-negative sub-identifier values. Each sub-identifier + value MUST NOT exceed 2^32-1 (4294967295). Sub-identifiers + are separated by single dots and without any intermediate + whitespace. + + The ASN.1 standard restricts the value space of the first + sub-identifier to 0, 1, or 2. Furthermore, the value space + of the second sub-identifier is restricted to the range + 0 to 39 if the first sub-identifier is 0 or 1. Finally, + the ASN.1 standard requires that an object identifier + has always at least two sub-identifiers. The pattern + captures these restrictions. + + Although the number of sub-identifiers is not limited, + module designers should realize that there may be + implementations that stick with the SMIv2 limit of 128 + sub-identifiers. + + This type is a superset of the SMIv2 OBJECT IDENTIFIER type + since it is not restricted to 128 sub-identifiers. Hence, + this type SHOULD NOT be used to represent the SMIv2 OBJECT + IDENTIFIER type; the object-identifier-128 type SHOULD be + used instead."; + reference + "ISO9834-1: Information technology -- Open Systems + Interconnection -- Procedures for the operation of OSI + Registration Authorities: General procedures and top + arcs of the ASN.1 Object Identifier tree"; + } + + typedef object-identifier-128 { + type object-identifier { + pattern '\d*(\.\d*){1,127}'; + } + description + "This type represents object-identifiers restricted to 128 + sub-identifiers. + + In the value set and its semantics, this type is equivalent + to the OBJECT IDENTIFIER type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef yang-identifier { + type string { + length "1..max"; + pattern '[a-zA-Z_][a-zA-Z0-9\-_.]*'; + pattern '.|..|[^xX].*|.[^mM].*|..[^lL].*'; + } + description + "A YANG identifier string as defined by the 'identifier' + rule in Section 12 of RFC 6020. An identifier must + start with an alphabetic character or an underscore + followed by an arbitrary sequence of alphabetic or + numeric characters, underscores, hyphens, or dots. + + A YANG identifier MUST NOT start with any possible + combination of the lowercase or uppercase character + sequence 'xml'."; + reference + "RFC 6020: YANG - A Data Modeling Language for the Network + Configuration Protocol (NETCONF)"; + } + + /*** collection of types related to date and time***/ + + typedef date-and-time { + type string { + pattern '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?' + + '(Z|[\+\-]\d{2}:\d{2})'; + } + description + "The date-and-time type is a profile of the ISO 8601 + standard for representation of dates and times using the + Gregorian calendar. The profile is defined by the + date-time production in Section 5.6 of RFC 3339. + + The date-and-time type is compatible with the dateTime XML + schema type with the following notable exceptions: + + (a) The date-and-time type does not allow negative years. + + (b) The date-and-time time-offset -00:00 indicates an unknown + time zone (see RFC 3339) while -00:00 and +00:00 and Z + all represent the same time zone in dateTime. + + (c) The canonical format (see below) of data-and-time values + differs from the canonical format used by the dateTime XML + schema type, which requires all times to be in UTC using + the time-offset 'Z'. + + This type is not equivalent to the DateAndTime textual + convention of the SMIv2 since RFC 3339 uses a different + separator between full-date and full-time and provides + higher resolution of time-secfrac. + + The canonical format for date-and-time values with a known time + zone uses a numeric time zone offset that is calculated using + the device's configured known offset to UTC time. A change of + the device's offset to UTC time will cause date-and-time values + to change accordingly. Such changes might happen periodically + in case a server follows automatically daylight saving time + (DST) time zone offset changes. The canonical format for + date-and-time values with an unknown time zone (usually + referring to the notion of local time) uses the time-offset + -00:00."; + reference + "RFC 3339: Date and Time on the Internet: Timestamps + RFC 2579: Textual Conventions for SMIv2 + XSD-TYPES: XML Schema Part 2: Datatypes Second Edition"; + } + + typedef timeticks { + type uint32; + description + "The timeticks type represents a non-negative integer that + represents the time, modulo 2^32 (4294967296 decimal), in + hundredths of a second between two epochs. When a schema + node is defined that uses this type, the description of + the schema node identifies both of the reference epochs. + + In the value set and its semantics, this type is equivalent + to the TimeTicks type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef timestamp { + type yang:timeticks; + description + "The timestamp type represents the value of an associated + timeticks schema node at which a specific occurrence + happened. The specific occurrence must be defined in the + description of any schema node defined using this type. When + the specific occurrence occurred prior to the last time the + associated timeticks attribute was zero, then the timestamp + value is zero. Note that this requires all timestamp values + to be reset to zero when the value of the associated timeticks + attribute reaches 497+ days and wraps around to zero. + + The associated timeticks schema node must be specified + in the description of any schema node using this type. + + In the value set and its semantics, this type is equivalent + to the TimeStamp textual convention of the SMIv2."; + reference + "RFC 2579: Textual Conventions for SMIv2"; + } + + /*** collection of generic address types ***/ + + typedef phys-address { + type string { + pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?'; + } + + description + "Represents media- or physical-level addresses represented + as a sequence octets, each octet represented by two hexadecimal + numbers. Octets are separated by colons. The canonical + representation uses lowercase characters. + + In the value set and its semantics, this type is equivalent + to the PhysAddress textual convention of the SMIv2."; + reference + "RFC 2579: Textual Conventions for SMIv2"; + } + + typedef mac-address { + type string { + pattern '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'; + } + description + "The mac-address type represents an IEEE 802 MAC address. + The canonical representation uses lowercase characters. + + In the value set and its semantics, this type is equivalent + to the MacAddress textual convention of the SMIv2."; + reference + "IEEE 802: IEEE Standard for Local and Metropolitan Area + Networks: Overview and Architecture + RFC 2579: Textual Conventions for SMIv2"; + } + + /*** collection of XML-specific types ***/ + + typedef xpath1.0 { + type string; + description + "This type represents an XPATH 1.0 expression. + + When a schema node is defined that uses this type, the + description of the schema node MUST specify the XPath + context in which the XPath expression is evaluated."; + reference + "XPATH: XML Path Language (XPath) Version 1.0"; + } + + /*** collection of string types ***/ + + typedef hex-string { + type string { + pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?'; + } + description + "A hexadecimal string with octets represented as hex digits + separated by colons. The canonical representation uses + lowercase characters."; + } + + typedef uuid { + type string { + pattern '[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-' + + '[0-9a-fA-F]{4}-[0-9a-fA-F]{12}'; + } + description + "A Universally Unique IDentifier in the string representation + defined in RFC 4122. The canonical representation uses + lowercase characters. + + The following is an example of a UUID in string representation: + f81d4fae-7dec-11d0-a765-00a0c91e6bf6 + "; + reference + "RFC 4122: A Universally Unique IDentifier (UUID) URN + Namespace"; + } + + typedef dotted-quad { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'; + } + description + "An unsigned 32-bit number expressed in the dotted-quad + notation, i.e., four octets written as decimal numbers + and separated with the '.' (full stop) character."; + } +} diff --git a/src/tests/tools/mock_tfs_optical_sdn_ctrl/MockTfsOpticalSdnCtrl.py b/src/tests/tools/mock_tfs_optical_sdn_ctrl/MockTfsOpticalSdnCtrl.py index 3316e6ad564f9037deb82f2a3c89a278f5aa7eda..188109350d23c22a926794bc6c21efc5865c1709 100644 --- a/src/tests/tools/mock_tfs_optical_sdn_ctrl/MockTfsOpticalSdnCtrl.py +++ b/src/tests/tools/mock_tfs_optical_sdn_ctrl/MockTfsOpticalSdnCtrl.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/mock_tfs_optical_sdn_ctrl/data.py b/src/tests/tools/mock_tfs_optical_sdn_ctrl/data.py index 91635e6e9682693e72b0d841a8a73f1dbd7d3cf1..96bbbf0e488b71eec77c479cb989ce7fb0d48d78 100644 --- a/src/tests/tools/mock_tfs_optical_sdn_ctrl/data.py +++ b/src/tests/tools/mock_tfs_optical_sdn_ctrl/data.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/mock_tfs_optical_sdn_ctrl/run.sh b/src/tests/tools/mock_tfs_optical_sdn_ctrl/run.sh index f89ecbf5c33cbc81893b5cd21b1d71680a50ca9f..f8b79e851086c42d89550b3e47c182c1a7077332 100755 --- a/src/tests/tools/mock_tfs_optical_sdn_ctrl/run.sh +++ b/src/tests/tools/mock_tfs_optical_sdn_ctrl/run.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/Component_RPC_Methods.py b/src/tests/tools/perf_plots/Component_RPC_Methods.py index fe94e5b8b19d188e1cf170bf1dbe74533c838c76..b5046388d89c225dbb3b07c913723b9f9a8a9752 100644 --- a/src/tests/tools/perf_plots/Component_RPC_Methods.py +++ b/src/tests/tools/perf_plots/Component_RPC_Methods.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/Device_Driver_Details.py b/src/tests/tools/perf_plots/Device_Driver_Details.py index 26a2d711e5a872c46ce39a308d46d7117f2c9cdd..4263252e2576c1f978fc3ac6067239e09af320f9 100644 --- a/src/tests/tools/perf_plots/Device_Driver_Details.py +++ b/src/tests/tools/perf_plots/Device_Driver_Details.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/Device_Driver_Methods.py b/src/tests/tools/perf_plots/Device_Driver_Methods.py index b4f70c4fd86d62e9b11abad4ce86e9facc0f8089..9ad6bd5e6edaf35340f532818711927c3de440d2 100644 --- a/src/tests/tools/perf_plots/Device_Driver_Methods.py +++ b/src/tests/tools/perf_plots/Device_Driver_Methods.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/LoadGen_Requests.py b/src/tests/tools/perf_plots/LoadGen_Requests.py index 3ed4861a8c8d3b5022c6b320b796c249ff75da63..f327d4b8bad1b1c0c946b3bcc455b3b353893165 100644 --- a/src/tests/tools/perf_plots/LoadGen_Requests.py +++ b/src/tests/tools/perf_plots/LoadGen_Requests.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/Service_Handler_Methods.py b/src/tests/tools/perf_plots/Service_Handler_Methods.py index 1e6c197f53c585469d19c760c3bf47c55b1e4b6f..d2f2eb058ff0be7431a33fcd78fa6ac5b5034e8f 100644 --- a/src/tests/tools/perf_plots/Service_Handler_Methods.py +++ b/src/tests/tools/perf_plots/Service_Handler_Methods.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/__init__.py b/src/tests/tools/perf_plots/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/tests/tools/perf_plots/__init__.py +++ b/src/tests/tools/perf_plots/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/collect.sh b/src/tests/tools/perf_plots/collect.sh index 6b8d16e59274b308f116bb381ddbcc034ffc8e5f..3bf12167ce62745d3dc5a866ac83b73a3156ff18 100755 --- a/src/tests/tools/perf_plots/collect.sh +++ b/src/tests/tools/perf_plots/collect.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/experiments/Experiment.py b/src/tests/tools/perf_plots/experiments/Experiment.py index 2fc03f89a58ee51a9c6954ac8d269d6f61b693dd..618142dd84d14fefe274068b8d6b8cb17e60e7a9 100644 --- a/src/tests/tools/perf_plots/experiments/Experiment.py +++ b/src/tests/tools/perf_plots/experiments/Experiment.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/experiments/__init__.py b/src/tests/tools/perf_plots/experiments/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/tests/tools/perf_plots/experiments/__init__.py +++ b/src/tests/tools/perf_plots/experiments/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/experiments/scenario_1/Emu_Onboard.py b/src/tests/tools/perf_plots/experiments/scenario_1/Emu_Onboard.py index d96c0c7d44c98005addc0b6c262625d351371708..107f21f71f738066ac141834b6aeb9f41a9e6add 100644 --- a/src/tests/tools/perf_plots/experiments/scenario_1/Emu_Onboard.py +++ b/src/tests/tools/perf_plots/experiments/scenario_1/Emu_Onboard.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/experiments/scenario_1/L2NM_EMU_Service.py b/src/tests/tools/perf_plots/experiments/scenario_1/L2NM_EMU_Service.py index f2fd2a69826eec1a59ddfcb365b98b42da7e97a6..4e32dee2545be75c01fc93797a033f792fe4fad3 100644 --- a/src/tests/tools/perf_plots/experiments/scenario_1/L2NM_EMU_Service.py +++ b/src/tests/tools/perf_plots/experiments/scenario_1/L2NM_EMU_Service.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/experiments/scenario_1/L3NM_EMU_Service.py b/src/tests/tools/perf_plots/experiments/scenario_1/L3NM_EMU_Service.py index 949f070964ffb7e56eb5d00c2d3b00abf109b52b..1a9a4e36b5a5bdc7c139cda87943f9ed9693e664 100644 --- a/src/tests/tools/perf_plots/experiments/scenario_1/L3NM_EMU_Service.py +++ b/src/tests/tools/perf_plots/experiments/scenario_1/L3NM_EMU_Service.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/experiments/scenario_1/__init__.py b/src/tests/tools/perf_plots/experiments/scenario_1/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/tests/tools/perf_plots/experiments/scenario_1/__init__.py +++ b/src/tests/tools/perf_plots/experiments/scenario_1/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/experiments/scenario_2/Scal_001tnt_005erl.py b/src/tests/tools/perf_plots/experiments/scenario_2/Scal_001tnt_005erl.py index e09c36c18c00aa3f99c2463933d112d5b71c2953..778b9ee5194da04fd1a9b3985c454f9ae6bf566e 100644 --- a/src/tests/tools/perf_plots/experiments/scenario_2/Scal_001tnt_005erl.py +++ b/src/tests/tools/perf_plots/experiments/scenario_2/Scal_001tnt_005erl.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/experiments/scenario_2/Scal_005tnt_025erl.py b/src/tests/tools/perf_plots/experiments/scenario_2/Scal_005tnt_025erl.py index fd9207b7f91f9c36dc844ff4e8a80064207d0d55..035967053a0e6c5e4cd390f74cce471f587ef269 100644 --- a/src/tests/tools/perf_plots/experiments/scenario_2/Scal_005tnt_025erl.py +++ b/src/tests/tools/perf_plots/experiments/scenario_2/Scal_005tnt_025erl.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/experiments/scenario_2/Scal_010tnt_050erl.py b/src/tests/tools/perf_plots/experiments/scenario_2/Scal_010tnt_050erl.py index 02df1a0dd6ceaa31849911732098e9fa83c9da4d..76d39d82aaa2bc4eec6eefd6dcc4f794283556d1 100644 --- a/src/tests/tools/perf_plots/experiments/scenario_2/Scal_010tnt_050erl.py +++ b/src/tests/tools/perf_plots/experiments/scenario_2/Scal_010tnt_050erl.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/experiments/scenario_2/Scal_020tnt_100erl.py b/src/tests/tools/perf_plots/experiments/scenario_2/Scal_020tnt_100erl.py index c69f4bb9ea6116cee562dc14bd71b004c550e845..01a75bd1b62e92eecd4e8f53665c509ced1183ff 100644 --- a/src/tests/tools/perf_plots/experiments/scenario_2/Scal_020tnt_100erl.py +++ b/src/tests/tools/perf_plots/experiments/scenario_2/Scal_020tnt_100erl.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/experiments/scenario_2/Scal_040tnt_200erl.py b/src/tests/tools/perf_plots/experiments/scenario_2/Scal_040tnt_200erl.py index 910752cf5680896f906792bd4b64fb611726a24b..3363446d55c54e593c569b501b2a5d314c57d700 100644 --- a/src/tests/tools/perf_plots/experiments/scenario_2/Scal_040tnt_200erl.py +++ b/src/tests/tools/perf_plots/experiments/scenario_2/Scal_040tnt_200erl.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/experiments/scenario_2/Scal_060tnt_300erl.py b/src/tests/tools/perf_plots/experiments/scenario_2/Scal_060tnt_300erl.py index a45ef712b27eadee053fb4a3f0861f50fe052eab..21c099ce2e9d190e921fa642d1d8a8d0f600000a 100644 --- a/src/tests/tools/perf_plots/experiments/scenario_2/Scal_060tnt_300erl.py +++ b/src/tests/tools/perf_plots/experiments/scenario_2/Scal_060tnt_300erl.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/experiments/scenario_2/Scal_080tnt_400erl.py b/src/tests/tools/perf_plots/experiments/scenario_2/Scal_080tnt_400erl.py index 75c567e258f23248fe1a389008a1cddc9ca212cc..4064a081b2230d0a5f1128ca9eb3254fc3af6065 100644 --- a/src/tests/tools/perf_plots/experiments/scenario_2/Scal_080tnt_400erl.py +++ b/src/tests/tools/perf_plots/experiments/scenario_2/Scal_080tnt_400erl.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/experiments/scenario_2/Scal_100tnt_500erl.py b/src/tests/tools/perf_plots/experiments/scenario_2/Scal_100tnt_500erl.py index 330c2e6c7e417b2d305353c3d27693c836202500..fcd4d989272aa13bbe67f62fbfee579e71cd8351 100644 --- a/src/tests/tools/perf_plots/experiments/scenario_2/Scal_100tnt_500erl.py +++ b/src/tests/tools/perf_plots/experiments/scenario_2/Scal_100tnt_500erl.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/experiments/scenario_2/Scal_120tnt_600erl.py b/src/tests/tools/perf_plots/experiments/scenario_2/Scal_120tnt_600erl.py index f28ec3fba00053fbc66da2f5a818094fc94af5c2..0b867cc091aaa591008af9ccd3195759c0f9e5d5 100644 --- a/src/tests/tools/perf_plots/experiments/scenario_2/Scal_120tnt_600erl.py +++ b/src/tests/tools/perf_plots/experiments/scenario_2/Scal_120tnt_600erl.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/experiments/scenario_2/__init__.py b/src/tests/tools/perf_plots/experiments/scenario_2/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/tests/tools/perf_plots/experiments/scenario_2/__init__.py +++ b/src/tests/tools/perf_plots/experiments/scenario_2/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/tools/FileSystem.py b/src/tests/tools/perf_plots/tools/FileSystem.py index 32493639acf861328fe710aca653c7a3912525f8..205d2d903cd9789998da78cb80a864c6a1b620ba 100644 --- a/src/tests/tools/perf_plots/tools/FileSystem.py +++ b/src/tests/tools/perf_plots/tools/FileSystem.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/tools/Histogram.py b/src/tests/tools/perf_plots/tools/Histogram.py index 811b48eaad0e6d6c48eb624e90b52e0026d6d951..483371364c2e6fd8044510484a328bc55b37a8d8 100644 --- a/src/tests/tools/perf_plots/tools/Histogram.py +++ b/src/tests/tools/perf_plots/tools/Histogram.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/tools/HistogramData.py b/src/tests/tools/perf_plots/tools/HistogramData.py index 73b5ccc460fd196840f9f6b2ab9bf5e649411748..528d1810a91793457af4d087630cb7864f7cb563 100644 --- a/src/tests/tools/perf_plots/tools/HistogramData.py +++ b/src/tests/tools/perf_plots/tools/HistogramData.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/tools/Plotter.py b/src/tests/tools/perf_plots/tools/Plotter.py index afb440d48b89dae3afc273c02bce48f37a2354be..ba92361471a2852d5c72b881f42eb9043363cbe4 100644 --- a/src/tests/tools/perf_plots/tools/Plotter.py +++ b/src/tests/tools/perf_plots/tools/Plotter.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/tools/Prometheus.py b/src/tests/tools/perf_plots/tools/Prometheus.py index f6702889d29f9b872263a9d68c66f15b6747abcf..a66d53a4bc5c2850eccf6af0e8b6f26aebb1d6d0 100644 --- a/src/tests/tools/perf_plots/tools/Prometheus.py +++ b/src/tests/tools/perf_plots/tools/Prometheus.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/tests/tools/perf_plots/tools/__init__.py b/src/tests/tools/perf_plots/tools/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/tests/tools/perf_plots/tools/__init__.py +++ b/src/tests/tools/perf_plots/tools/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/vnt_manager/.gitlab-ci.yml b/src/vnt_manager/.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..8199dabcc4a8620931757ce47c21877ea365b399 --- /dev/null +++ b/src/vnt_manager/.gitlab-ci.yml @@ -0,0 +1,38 @@ +# 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. + +# build, tag and push the Docker image to the gitlab registry +build vnt_manager: + variables: + IMAGE_NAME: 'vnt_manager' # name of the microservice + IMAGE_TAG: 'latest' # tag of the container image (production, development, etc) + stage: build + before_script: + - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY + script: + - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . + - docker tag "$IMAGE_NAME:$IMAGE_TAG" "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG" + - docker push "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG" + after_script: + - docker images --filter="dangling=true" --quiet | xargs -r docker rmi + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)' + - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"' + - changes: + - src/$IMAGE_NAME/**/*.{py,in,yml} + - src/$IMAGE_NAME/Dockerfile + - src/$IMAGE_NAME/tests/*.py + - src/$IMAGE_NAME/tests/Dockerfile + - manifests/${IMAGE_NAME}service.yaml + - .gitlab-ci.yml diff --git a/src/vnt_manager/Config.py b/src/vnt_manager/Config.py new file mode 100644 index 0000000000000000000000000000000000000000..023830645e0fcb60e3f8583674a954810af222f2 --- /dev/null +++ b/src/vnt_manager/Config.py @@ -0,0 +1,13 @@ +# 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. diff --git a/src/vnt_manager/Dockerfile b/src/vnt_manager/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..3ff0acf3ff250a2921a80b4dfd8bc278d6896f2e --- /dev/null +++ b/src/vnt_manager/Dockerfile @@ -0,0 +1,87 @@ +# 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++ && \ + rm -rf /var/lib/apt/lists/* + +# Set Python to show logs as they occur +ENV PYTHONUNBUFFERED=0 +ENV PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python + +# Download the gRPC health probe +RUN GRPC_HEALTH_PROBE_VERSION=v0.2.0 && \ + wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \ + chmod +x /bin/grpc_health_probe + +# Creating a user for security reasons +RUN groupadd -r teraflow && useradd -u 1001 --no-log-init -r -m -g teraflow teraflow +USER teraflow + +# set working directory +RUN mkdir -p /home/teraflow/controller/common/ +WORKDIR /home/teraflow/controller + +# Get Python packages per module +ENV VIRTUAL_ENV=/home/teraflow/venv +RUN python3 -m venv ${VIRTUAL_ENV} +ENV PATH="${VIRTUAL_ENV}/bin:${PATH}" + +# 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 +COPY --chown=teraflow:teraflow 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 /home/teraflow/controller/common +COPY --chown=teraflow:teraflow src/common/. ./ +RUN rm -rf proto + +# Create proto sub-folder, copy .proto files, and generate Python code +RUN mkdir -p /home/teraflow/controller/common/proto +WORKDIR /home/teraflow/controller/common/proto +RUN touch __init__.py +COPY --chown=teraflow:teraflow 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 module sub-folders +RUN mkdir -p /home/teraflow/controller/vnt_manager +WORKDIR /home/teraflow/controller + +# Get Python packages per module +COPY --chown=teraflow:teraflow ./src/vnt_manager/requirements.in vnt_manager/requirements.in +# consider common and specific requirements to avoid inconsistencies with dependencies +RUN pip-compile --quiet --output-file=vnt_manager/requirements.txt vnt_manager/requirements.in common_requirements.in +RUN python3 -m pip install -r vnt_manager/requirements.txt + +# Add component files into working directory +COPY src/context/__init__.py context/__init__.py +COPY src/context/client/. context/client/ +COPY src/device/__init__.py device/__init__.py +COPY src/device/client/. device/client/ +COPY src/vnt_manager/. vnt_manager/ + +# Start the service +ENTRYPOINT ["python", "-m", "vnt_manager.service"] diff --git a/src/vnt_manager/__init__.py b/src/vnt_manager/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..023830645e0fcb60e3f8583674a954810af222f2 --- /dev/null +++ b/src/vnt_manager/__init__.py @@ -0,0 +1,13 @@ +# 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. diff --git a/src/vnt_manager/client/VNTManagerClient.py b/src/vnt_manager/client/VNTManagerClient.py new file mode 100644 index 0000000000000000000000000000000000000000..b313a590f3c5d8db64a9ae1b7b9ac89a94595f2a --- /dev/null +++ b/src/vnt_manager/client/VNTManagerClient.py @@ -0,0 +1,104 @@ +# 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 + +import grpc + +from common.Constants import ServiceNameEnum +from common.proto.context_pb2 import Empty +from common.proto.vnt_manager_pb2 import VNTSubscriptionRequest, VNTSubscriptionReply +from common.proto.vnt_manager_pb2_grpc import VNTManagerServiceStub +from common.Settings import get_service_host, get_service_port_grpc +from common.tools.client.RetryDecorator import delay_exponential, retry +from common.tools.grpc.Tools import grpc_message_to_json +from common.proto.context_pb2 import ( + Link, LinkId, LinkIdList, LinkList, +) +from common.tools.grpc.Tools import grpc_message_to_json_string + +LOGGER = logging.getLogger(__name__) +MAX_RETRIES = 15 +DELAY_FUNCTION = delay_exponential(initial=0.01, increment=2.0, maximum=5.0) +RETRY_DECORATOR = retry( + max_retries=MAX_RETRIES, + delay_function=DELAY_FUNCTION, + prepare_method_name="connect", +) + + +class VNTManagerClient: + def __init__(self, host=None, port=None): + if not host: + host = get_service_host(ServiceNameEnum.VNTMANAGER) + if not port: + port = get_service_port_grpc(ServiceNameEnum.VNTMANAGER) + self.endpoint = "{:s}:{:s}".format(str(host), str(port)) + LOGGER.debug("Creating channel to {:s}...".format(str(self.endpoint))) + self.channel = None + self.stub = None + self.connect() + LOGGER.debug("Channel created") + + def connect(self): + self.channel = grpc.insecure_channel(self.endpoint) + self.stub = VNTManagerServiceStub(self.channel) + + def close(self): + if self.channel is not None: + self.channel.close() + self.channel = None + self.stub = None + + @RETRY_DECORATOR + def VNTSubscript(self, request: VNTSubscriptionRequest) -> VNTSubscriptionReply: + LOGGER.debug("Subscript request: {:s}".format(str(grpc_message_to_json(request)))) + response = self.stub.VNTSubscript(request) + LOGGER.debug("Subscript result: {:s}".format(str(grpc_message_to_json(response)))) + return response + + @RETRY_DECORATOR + def ListVirtualLinkIds(self, request: Empty) -> LinkIdList: + LOGGER.debug('ListVirtualLinkIds request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.ListVirtualLinkIds(request) + LOGGER.debug('ListVirtualLinkIds result: {:s}'.format(grpc_message_to_json_string(response))) + return response + + @RETRY_DECORATOR + def ListVirtualLinks(self, request: Empty) -> LinkList: + LOGGER.debug('ListVirtualLinks request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.ListVirtualLinks(request) + LOGGER.debug('ListVirtualLinks result: {:s}'.format(grpc_message_to_json_string(response))) + return response + + @RETRY_DECORATOR + def GetVirtualLink(self, request: LinkId) -> Link: + LOGGER.debug('GetVirtualLink request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.GetVirtualLink(request) + LOGGER.debug('GetVirtualLink result: {:s}'.format(grpc_message_to_json_string(response))) + return response + + @RETRY_DECORATOR + def SetVirtualLink(self, request: Link) -> LinkId: + LOGGER.debug('SetVirtualLink request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.SetVirtualLink(request) + LOGGER.debug('SetVirtualLink result: {:s}'.format(grpc_message_to_json_string(response))) + return response + + @RETRY_DECORATOR + def RemoveVirtualLink(self, request: LinkId) -> Empty: + LOGGER.debug('RemoveVirtualLink request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.RemoveVirtualLink(request) + LOGGER.debug('RemoveVirtualLink result: {:s}'.format(grpc_message_to_json_string(response))) + return response diff --git a/src/vnt_manager/client/__init__.py b/src/vnt_manager/client/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..023830645e0fcb60e3f8583674a954810af222f2 --- /dev/null +++ b/src/vnt_manager/client/__init__.py @@ -0,0 +1,13 @@ +# 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. diff --git a/src/vnt_manager/requirements.in b/src/vnt_manager/requirements.in new file mode 100644 index 0000000000000000000000000000000000000000..38764add745987ea115b9c8f2a9a169e6d0e3c39 --- /dev/null +++ b/src/vnt_manager/requirements.in @@ -0,0 +1,15 @@ +# 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. + +websockets==12.0 diff --git a/src/vnt_manager/service/VNTManagerService.py b/src/vnt_manager/service/VNTManagerService.py new file mode 100644 index 0000000000000000000000000000000000000000..b95ad089a454e9d73e99d9f14cbe525a6c9ca8cb --- /dev/null +++ b/src/vnt_manager/service/VNTManagerService.py @@ -0,0 +1,35 @@ +# 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 + +from common.Constants import ServiceNameEnum +from common.proto.vnt_manager_pb2_grpc import add_VNTManagerServiceServicer_to_server +from common.Settings import get_service_port_grpc +from common.tools.service.GenericGrpcService import GenericGrpcService +from .VNTManagerServiceServicerImpl import VNTManagerServiceServicerImpl + +LOGGER = logging.getLogger(__name__) + + +class VNTManagerService(GenericGrpcService): + def __init__(self, cls_name: str = __name__): + port = get_service_port_grpc(ServiceNameEnum.VNTMANAGER) + super().__init__(port, cls_name=cls_name) + self.vntmanager_servicer = VNTManagerServiceServicerImpl() + + def install_servicers(self): + add_VNTManagerServiceServicer_to_server( + self.vntmanager_servicer, self.server + ) diff --git a/src/vnt_manager/service/VNTManagerServiceServicerImpl.py b/src/vnt_manager/service/VNTManagerServiceServicerImpl.py new file mode 100644 index 0000000000000000000000000000000000000000..835b658fa946a19bd542b47c80c1c51587eb698d --- /dev/null +++ b/src/vnt_manager/service/VNTManagerServiceServicerImpl.py @@ -0,0 +1,183 @@ +# 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 grpc +import json +import logging +import threading +import time +from websockets.sync.client import connect +from common.Constants import DEFAULT_CONTEXT_NAME, DEFAULT_TOPOLOGY_NAME +from common.method_wrappers.Decorator import MetricsPool, safe_and_metered_rpc_method +from common.proto.context_pb2 import ContextId, Empty, Link, LinkId, LinkList, TopologyId +from common.proto.vnt_manager_pb2 import VNTSubscriptionRequest, VNTSubscriptionReply +from common.proto.vnt_manager_pb2_grpc import VNTManagerServiceServicer +from common.tools.grpc.Tools import grpc_message_to_json, grpc_message_to_json_string +from common.tools.object_factory.Context import json_context_id +from common.tools.object_factory.Topology import json_topology_id +from context.client.ContextClient import ContextClient +from context.client.EventsCollector import EventsCollector +from .vntm_config_device import configure, deconfigure + +LOGGER = logging.getLogger(__name__) + +METRICS_POOL = MetricsPool("VNTManager", "RPC") + +context_client: ContextClient = ContextClient() + +JSON_ADMIN_CONTEXT_ID = json_context_id(DEFAULT_CONTEXT_NAME) +ADMIN_CONTEXT_ID = ContextId(**JSON_ADMIN_CONTEXT_ID) +ADMIN_TOPOLOGY_ID = TopologyId(**json_topology_id(DEFAULT_TOPOLOGY_NAME, context_id=JSON_ADMIN_CONTEXT_ID)) + +GET_EVENT_TIMEOUT = 0.5 + + +class VNTMEventDispatcher(threading.Thread): + def __init__(self, host, port) -> None: + LOGGER.debug('Creating VTNM connector...') + self.host = host + self.port = port + super().__init__(name='VNTMEventDispatcher', daemon=True) + self._terminate = threading.Event() + LOGGER.debug('VNTM connector created') + + def start(self) -> None: + self._terminate.clear() + return super().start() + + def stop(self): + self._terminate.set() + + + def send_msg(self, msg): + try: + self.websocket.send(msg) + except Exception as e: + LOGGER.info(e) + + def recv_msg(self): + message = self.websocket.recv() + return message + + def run(self) -> None: + + time.sleep(5) + events_collector = EventsCollector( + context_client, log_events_received=True, + activate_context_collector = False, + activate_topology_collector = True, + activate_device_collector = False, + activate_link_collector = False, + activate_service_collector = False, + activate_slice_collector = False, + activate_connection_collector = False,) + events_collector.start() + + + url = "ws://" + str(self.host) + ":" + str(self.port) + LOGGER.debug('Connecting to {}'.format(url)) + + try: + LOGGER.info("Connecting to events server...: {}".format(url)) + self.websocket = connect(url) + except Exception as ex: + LOGGER.error('Error connecting to {}'.format(url)) + else: + LOGGER.info('Connected to {}'.format(url)) + context_id = json_context_id(DEFAULT_CONTEXT_NAME) + topology_id = json_topology_id(DEFAULT_TOPOLOGY_NAME, context_id) + + try: + topology_details = context_client.GetTopologyDetails(TopologyId(**topology_id)) + except Exception as ex: + LOGGER.warning('No topology found') + else: + self.send_msg(grpc_message_to_json_string(topology_details)) + + while not self._terminate.is_set(): + event = events_collector.get_event(block=True, timeout=GET_EVENT_TIMEOUT) + LOGGER.info('Event type: {}'.format(event)) + if event is None: continue + LOGGER.debug('Received event: {}'.format(event)) + topology_details = context_client.GetTopologyDetails(TopologyId(**topology_id)) + + to_send = grpc_message_to_json_string(topology_details) + + self.send_msg(to_send) + + LOGGER.info('Exiting') + events_collector.stop() + + +class VNTManagerServiceServicerImpl(VNTManagerServiceServicer): + def __init__(self): + LOGGER.debug("Creating Servicer...") + LOGGER.debug("Servicer Created") + self.links = [] + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def VNTSubscript(self, request: VNTSubscriptionRequest, context: grpc.ServicerContext) -> VNTSubscriptionReply: + LOGGER.info("Subscript request: {:s}".format(str(grpc_message_to_json(request)))) + reply = VNTSubscriptionReply() + reply.subscription = "OK" + + self.event_dispatcher = VNTMEventDispatcher(request.host, int(request.port)) + self.host = request.host + self.port = request.port + self.event_dispatcher.start() + return reply + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def ListVirtualLinks(self, request : Empty, context : grpc.ServicerContext) -> LinkList: + return [link for link in context_client.ListLinks(Empty()).links if link.virtual] + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def GetVirtualLink(self, request : LinkId, context : grpc.ServicerContext) -> Link: + link = context_client.GetLink(request) + return link if link.virtual else Empty() + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def SetVirtualLink(self, request : Link, context : grpc.ServicerContext) -> LinkId: + try: + LOGGER.info('SETTING virtual link') + self.event_dispatcher.send_msg(grpc_message_to_json_string(request)) + # configure('CSGW1', 'xe5', 'CSGW2', 'xe5', 'ecoc2024-1') + response = self.event_dispatcher.recv_msg() + message_json = json.loads(response) + link = Link(**message_json) + context_client.SetLink(link) + except Exception as e: + LOGGER.error('Exception setting virtual link={}\n\t{}'.format(request.link_id.link_uuid.uuid, e)) + return request.link_id + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def RemoveVirtualLink(self, request : LinkId, context : grpc.ServicerContext) -> Empty: + try: + self.event_dispatcher.send_msg(grpc_message_to_json_string(request)) + # deconfigure('CSGW1', 'xe5', 'CSGW2', 'xe5', 'ecoc2024-1') + response = self.event_dispatcher.recv_msg() + message_json = json.loads(response) + link_id = LinkId(**message_json) + context_client.RemoveLink(link_id) + + LOGGER.info('Removed') + except Exception as e: + msg_error = 'Exception removing virtual link={}\n\t{}'.format(request.link_uuid.uuid, e) + LOGGER.error(msg_error) + return msg_error + else: + context_client.RemoveLink(request) + LOGGER.info('Removed') + + return Empty() diff --git a/src/vnt_manager/service/__init__.py b/src/vnt_manager/service/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..023830645e0fcb60e3f8583674a954810af222f2 --- /dev/null +++ b/src/vnt_manager/service/__init__.py @@ -0,0 +1,13 @@ +# 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. diff --git a/src/vnt_manager/service/__main__.py b/src/vnt_manager/service/__main__.py new file mode 100644 index 0000000000000000000000000000000000000000..c36a0ae1fb7bfa568f79bae26e53cd5d734a4f2e --- /dev/null +++ b/src/vnt_manager/service/__main__.py @@ -0,0 +1,66 @@ +# 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, signal, sys, threading +from prometheus_client import start_http_server +from common.Constants import ServiceNameEnum +from common.Settings import ( + ENVVAR_SUFIX_SERVICE_HOST, ENVVAR_SUFIX_SERVICE_PORT_GRPC, + get_env_var_name, get_log_level, get_metrics_port, + wait_for_environment_variables +) +from .VNTManagerService import VNTManagerService + +LOG_LEVEL = get_log_level() +logging.basicConfig(level=LOG_LEVEL, format="[%(asctime)s] %(levelname)s:%(name)s:%(message)s") +LOGGER = logging.getLogger(__name__) + +terminate = threading.Event() + +def signal_handler(signal, frame): # pylint: disable=redefined-outer-name,unused-argument + LOGGER.warning("Terminate signal received") + terminate.set() + +def main(): + LOGGER.info("Starting...") + + wait_for_environment_variables([ + get_env_var_name(ServiceNameEnum.CONTEXT, ENVVAR_SUFIX_SERVICE_HOST ), + get_env_var_name(ServiceNameEnum.CONTEXT, ENVVAR_SUFIX_SERVICE_PORT_GRPC), + get_env_var_name(ServiceNameEnum.DEVICE, ENVVAR_SUFIX_SERVICE_HOST ), + get_env_var_name(ServiceNameEnum.DEVICE, ENVVAR_SUFIX_SERVICE_PORT_GRPC), + ]) + + signal.signal(signal.SIGINT, signal_handler) + signal.signal(signal.SIGTERM, signal_handler) + + # Start metrics server + metrics_port = get_metrics_port() + start_http_server(metrics_port) + + # Starting VNTManager service + grpc_service = VNTManagerService() + grpc_service.start() + + # Wait for Ctrl+C or termination signal + while not terminate.wait(timeout=1): pass + + LOGGER.info("Terminating...") + grpc_service.stop() + + LOGGER.info("Bye") + return 0 + +if __name__ == "__main__": + sys.exit(main()) diff --git a/src/vnt_manager/service/vntm_config_device.py b/src/vnt_manager/service/vntm_config_device.py new file mode 100644 index 0000000000000000000000000000000000000000..98fddcd954519c64b0a63a9c1e52c9402078d922 --- /dev/null +++ b/src/vnt_manager/service/vntm_config_device.py @@ -0,0 +1,184 @@ +# 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 typing import Dict +from common.proto.context_pb2 import ConfigRule +from common.tools.context_queries.Device import get_device +from common.tools.object_factory.ConfigRule import json_config_rule_set, json_config_rule_delete +from context.client.ContextClient import ContextClient +from device.client.DeviceClient import DeviceClient + +##### Config Rule Composers #################################################### + +def compose_config_rule(resource_key, resource_value, delete) -> Dict: + json_config_rule = json_config_rule_delete if delete else json_config_rule_set + return ConfigRule(**json_config_rule(resource_key, resource_value)) + +def network_instance(ni_name, ni_type, ni_router_id=None, ni_route_distinguisher=None, delete=False) -> Dict: + path = '/network_instance[{:s}]'.format(ni_name) + data = {'name': ni_name, 'type': ni_type} + if ni_router_id is not None: data['router_id'] = ni_router_id + if ni_route_distinguisher is not None: data['route_distinguisher'] = ni_route_distinguisher + return compose_config_rule(path, data, delete) + +def network_instance_add_protocol_bgp(ni_name, ni_type, ni_router_id, ni_bgp_as, neighbors=[], delete=False)-> Dict: + path = '/network_instance[{:s}]/protocols[BGP]'.format(ni_name) + data = { + 'name': ni_name, 'type': ni_type, 'router_id': ni_router_id, 'identifier': 'BGP', + 'protocol_name': ni_bgp_as, 'as': ni_bgp_as + } + if len(neighbors) > 0: + data['neighbors'] = [ + {'ip_address': neighbor_ip_address, 'remote_as': neighbor_remote_as} + for neighbor_ip_address, neighbor_remote_as in neighbors + ] + return compose_config_rule(path, data, delete) + +def network_instance_add_protocol_direct(ni_name, ni_type, delete=False) -> Dict: + path = '/network_instance[{:s}]/protocols[DIRECTLY_CONNECTED]'.format(ni_name) + data = { + 'name': ni_name, 'type': ni_type, 'identifier': 'DIRECTLY_CONNECTED', + 'protocol_name': 'DIRECTLY_CONNECTED' + } + return compose_config_rule(path, data, delete) + +def network_instance_add_protocol_static(ni_name, ni_type, delete=False) -> Dict: + path = '/network_instance[{:s}]/protocols[STATIC]'.format(ni_name) + data = { + 'name': ni_name, 'type': ni_type, 'identifier': 'STATIC', + 'protocol_name': 'STATIC' + } + return compose_config_rule(path, data, delete) + +def network_instance_add_table_connection( + ni_name, src_protocol, dst_protocol, address_family, default_import_policy, bgp_as=None, delete=False +) -> Dict: + path = '/network_instance[{:s}]/table_connections[{:s}][{:s}][{:s}]'.format( + ni_name, src_protocol, dst_protocol, address_family + ) + data = { + 'name': ni_name, 'src_protocol': src_protocol, 'dst_protocol': dst_protocol, + 'address_family': address_family, 'default_import_policy': default_import_policy, + } + if bgp_as is not None: data['as'] = bgp_as + return compose_config_rule(path, data, delete) + +def interface( + name, index, description=None, if_type=None, vlan_id=None, mtu=None, ipv4_address_prefix=None, + enabled=None, delete=False +) -> Dict: + path = '/interface[{:s}]/subinterface[{:d}]'.format(name, index) + data = {'name': name, 'index': index} + if description is not None: data['description'] = description + if if_type is not None: data['type' ] = if_type + if vlan_id is not None: data['vlan_id' ] = vlan_id + if mtu is not None: data['mtu' ] = mtu + if enabled is not None: data['enabled' ] = enabled + if ipv4_address_prefix is not None: + ipv4_address, ipv4_prefix = ipv4_address_prefix + data['address_ip' ] = ipv4_address + data['address_prefix'] = ipv4_prefix + return compose_config_rule(path, data, delete) + +def network_instance_interface(ni_name, ni_type, if_name, if_index, delete=False) -> Dict: + path = '/network_instance[{:s}]/interface[{:s}.{:d}]'.format(ni_name, if_name, if_index) + data = {'name': ni_name, 'type': ni_type, 'id': if_name, 'interface': if_name, 'subinterface': if_index} + return compose_config_rule(path, data, delete) + +# configure('CSGW1', 'xe5', 'CSGW2', 'xe5', 'ecoc2024-1') +# deconfigure('CSGW1', 'xe5', 'CSGW2', 'xe5', 'ecoc2024-1') + +def configure(router_a, port_a, router_b, port_b, ni_name): + context_client = ContextClient() + device_client = DeviceClient() + + client_if_name = 'ce1' + client_if_addr = {'CSGW1': ('192.168.10.1', 24), 'CSGW2': ('192.168.20.1', 24)} + bgp_router_addresses = {'CSGW1': '192.168.150.1', 'CSGW2': '192.168.150.2'} + + locations = [ + {'router': router_a, 'port': port_a, 'neighbor': router_b}, + {'router': router_b, 'port': port_b, 'neighbor': router_a}, + ] + for location in locations: + router = location['router'] + port = location['port'] + neighbor = location['neighbor'] + + client_ipv4_address_prefix = client_if_addr[router] + bgp_router_address = bgp_router_addresses[router] + bgp_neighbor_address = bgp_router_addresses[neighbor] + + config_rules = [ + network_instance(ni_name, 'L3VRF', bgp_router_address, '65001:1'), + network_instance_add_protocol_direct(ni_name, 'L3VRF'), + network_instance_add_protocol_static(ni_name, 'L3VRF'), + network_instance_add_protocol_bgp(ni_name, 'L3VRF', bgp_router_address, '65001', neighbors=[ + (bgp_neighbor_address, '65001') + ]), + network_instance_add_table_connection( + ni_name, 'DIRECTLY_CONNECTED', 'BGP', 'IPV4', 'ACCEPT_ROUTE', bgp_as='65001' + ), + network_instance_add_table_connection( + ni_name, 'STATIC', 'BGP', 'IPV4', 'ACCEPT_ROUTE', bgp_as='65001' + ), + + interface(client_if_name, 0, if_type='ethernetCsmacd', mtu=1500), + network_instance_interface(ni_name, 'L3VRF', client_if_name, 0), + interface(client_if_name, 0, if_type='ethernetCsmacd', mtu=1500, + ipv4_address_prefix=client_ipv4_address_prefix, enabled=True), + + interface(port, 0, if_type='ethernetCsmacd', mtu=1500), + network_instance_interface(ni_name, 'L3VRF', port, 0), + interface(port, 0, if_type='ethernetCsmacd', mtu=1500, + ipv4_address_prefix=(bgp_router_address, 24), enabled=True), + ] + + device = get_device( + context_client, router, rw_copy=True, include_endpoints=False, + include_config_rules=False, include_components=False + ) + device.device_config.config_rules.extend(config_rules) + device_client.ConfigureDevice(device) + + +def deconfigure(router_a, port_a, router_b, port_b, ni_name): + context_client = ContextClient() + device_client = DeviceClient() + + client_if_name = 'ce1' + + locations = [ + {'router': router_a, 'port': port_a, 'neighbor': router_b}, + {'router': router_b, 'port': port_b, 'neighbor': router_a}, + ] + for location in locations: + router = location['router'] + port = location['port'] + #neighbor = location['neighbor'] + + config_rules = [ + network_instance_interface(ni_name, 'L3VRF', client_if_name, 0, delete=True), + network_instance_interface(ni_name, 'L3VRF', port, 0, delete=True), + #interface(client_if_name, 0, delete=True), + #interface(port, 0, delete=True), + network_instance(ni_name, 'L3VRF', delete=True), + ] + + device = get_device( + context_client, router, rw_copy=True, include_endpoints=False, + include_config_rules=False, include_components=False + ) + device.device_config.config_rules.extend(config_rules) + device_client.ConfigureDevice(device) diff --git a/src/webui/.gitlab-ci.yml b/src/webui/.gitlab-ci.yml index 48f41744a706c05c97293245fa05c8c798cc005e..c1a445ffed9aa44e8357b73aee075b7827278f61 100644 --- a/src/webui/.gitlab-ci.yml +++ b/src/webui/.gitlab-ci.yml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/webui/Config.py b/src/webui/Config.py index fc7fa1e57290fb7c5fae2028bc1ab4b91f2029ff..ce491370717964f92d71008c7c4e8e48a921dc36 100644 --- a/src/webui/Config.py +++ b/src/webui/Config.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/webui/Dockerfile b/src/webui/Dockerfile index 55e67b670f36812a55cf60e411cf137bc5b8a2ee..0327b68ef712fbd4d89776ed348cbc00171153c9 100644 --- a/src/webui/Dockerfile +++ b/src/webui/Dockerfile @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -84,9 +84,11 @@ COPY --chown=webui:webui src/service/__init__.py service/__init__.py COPY --chown=webui:webui src/service/client/. service/client/ COPY --chown=webui:webui src/slice/__init__.py slice/__init__.py COPY --chown=webui:webui src/slice/client/. slice/client/ -COPY --chown=webui:webui src/webui/. webui/ +COPY --chown=webui:webui src/qkd_app/__init__.py qkd_app/__init__.py +COPY --chown=webui:webui src/qkd_app/client/. qkd_app/client/ COPY --chown=webui:webui src/bgpls_speaker/__init__.py bgpls_speaker/__init__.py COPY --chown=webui:webui src/bgpls_speaker/client/. bgpls_speaker/client/ +COPY --chown=webui:webui src/webui/. webui/ # Start the service ENTRYPOINT ["python", "-m", "webui.service"] diff --git a/src/webui/__init__.py b/src/webui/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/webui/__init__.py +++ b/src/webui/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/webui/requirements.in b/src/webui/requirements.in index ab512dedb16d95c21d8807732f4ef386475aa32e..f5bbee5bc954aa82392d86d653fda57725cda40b 100644 --- a/src/webui/requirements.in +++ b/src/webui/requirements.in @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/webui/service/__init__.py b/src/webui/service/__init__.py index 9b6950aeb0f3fda630db87d5d80ad2bf730fac3d..f64ecca3b6453baf193c683c11fbb2ca27629286 100644 --- a/src/webui/service/__init__.py +++ b/src/webui/service/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -14,11 +14,15 @@ import json from typing import List, Tuple, Union -from flask import Flask, request, session +from flask import Flask, session from flask_healthz import healthz, HealthError from common.tools.grpc.Tools import grpc_message_to_json from context.client.ContextClient import ContextClient from device.client.DeviceClient import DeviceClient +from common.Settings import ( + is_deployed_bgpls, is_deployed_load_gen, is_deployed_optical, + is_deployed_policy, is_deployed_qkd_app, is_deployed_slice +) def get_working_context() -> str: return session['context_uuid'] if 'context_uuid' in session else '---' @@ -49,7 +53,10 @@ def json_to_list(json_str : str) -> List[Union[str, Tuple[str, str]]]: if isinstance(data, dict): return [('kv', (key, value)) for key, value in data.items()] elif isinstance(data, list): - return [('item', ', '.join(data))] + if len(data) == 1 and isinstance(data[0], dict): + return [('kv', (key, value)) for key, value in data[0].items()] + else: + return [('item', ', '.join([str(d) for d in data]))] else: return [('item', str(data))] @@ -75,31 +82,43 @@ def create_app(use_config=None, web_app_root=None): app.register_blueprint(healthz, url_prefix='/healthz') - from webui.service.js.routes import js # pylint: disable=import-outside-toplevel + from webui.service.js.routes import js # pylint: disable=import-outside-toplevel app.register_blueprint(js) - from webui.service.main.routes import main # pylint: disable=import-outside-toplevel + from webui.service.main.routes import main # pylint: disable=import-outside-toplevel app.register_blueprint(main) - from webui.service.load_gen.routes import load_gen # pylint: disable=import-outside-toplevel + from webui.service.load_gen.routes import load_gen # pylint: disable=import-outside-toplevel app.register_blueprint(load_gen) - from webui.service.service.routes import service # pylint: disable=import-outside-toplevel + from webui.service.base_optical.route import base_optical # pylint: disable=import-outside-toplevel + app.register_blueprint(base_optical) + + from webui.service.opticalconfig.routes import opticalconfig # pylint: disable=import-outside-toplevel + app.register_blueprint(opticalconfig) + + from webui.service.optical_link.routes import optical_link # pylint: disable=import-outside-toplevel + app.register_blueprint(optical_link) + + from webui.service.service.routes import service # pylint: disable=import-outside-toplevel app.register_blueprint(service) - from webui.service.slice.routes import slice # pylint: disable=import-outside-toplevel,redefined-builtin + from webui.service.slice.routes import slice # pylint: disable=import-outside-toplevel,redefined-builtin app.register_blueprint(slice) - from webui.service.device.routes import device # pylint: disable=import-outside-toplevel + from webui.service.device.routes import device # pylint: disable=import-outside-toplevel app.register_blueprint(device) - from webui.service.bgpls.routes import bgpls # pylint: disable=import-outside-toplevel + from webui.service.bgpls.routes import bgpls # pylint: disable=import-outside-toplevel app.register_blueprint(bgpls) - from webui.service.link.routes import link # pylint: disable=import-outside-toplevel + from webui.service.link.routes import link # pylint: disable=import-outside-toplevel app.register_blueprint(link) - from webui.service.policy_rule.routes import policy_rule # pylint: disable=import-outside-toplevel + from webui.service.qkd_app.routes import qkd_app # pylint: disable=import-outside-toplevel + app.register_blueprint(qkd_app) + + from webui.service.policy_rule.routes import policy_rule # pylint: disable=import-outside-toplevel app.register_blueprint(policy_rule) app.jinja_env.globals.update({ # pylint: disable=no-member @@ -109,6 +128,13 @@ def create_app(use_config=None, web_app_root=None): 'round' : round, 'get_working_context' : get_working_context, 'get_working_topology': get_working_topology, + + 'is_deployed_bgpls' : is_deployed_bgpls, + 'is_deployed_load_gen': is_deployed_load_gen, + 'is_deployed_optical' : is_deployed_optical, + 'is_deployed_policy' : is_deployed_policy, + 'is_deployed_qkd_app' : is_deployed_qkd_app, + 'is_deployed_slice' : is_deployed_slice, }) if web_app_root is not None: diff --git a/src/webui/service/__main__.py b/src/webui/service/__main__.py index e9a906e8a431e287911547abc4065d9d9364ccb4..6f7954147677045da3db36e487f8ce85c1eac32d 100644 --- a/src/webui/service/__main__.py +++ b/src/webui/service/__main__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -33,6 +33,7 @@ def main(): logging.basicConfig(level=log_level) logger = logging.getLogger(__name__) + # DEPENDENCY QKD wait_for_environment_variables([ get_env_var_name(ServiceNameEnum.CONTEXT, ENVVAR_SUFIX_SERVICE_HOST ), get_env_var_name(ServiceNameEnum.CONTEXT, ENVVAR_SUFIX_SERVICE_PORT_GRPC), @@ -40,8 +41,6 @@ def main(): get_env_var_name(ServiceNameEnum.DEVICE, ENVVAR_SUFIX_SERVICE_PORT_GRPC), get_env_var_name(ServiceNameEnum.SERVICE, ENVVAR_SUFIX_SERVICE_HOST ), get_env_var_name(ServiceNameEnum.SERVICE, ENVVAR_SUFIX_SERVICE_PORT_GRPC), - get_env_var_name(ServiceNameEnum.SLICE, ENVVAR_SUFIX_SERVICE_HOST ), - get_env_var_name(ServiceNameEnum.SLICE, ENVVAR_SUFIX_SERVICE_PORT_GRPC), ]) logger.info('Starting...') diff --git a/src/webui/service/base_optical/__init__.py b/src/webui/service/base_optical/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..53d5157f750bfb085125cbd33faff1cec5924e14 --- /dev/null +++ b/src/webui/service/base_optical/__init__.py @@ -0,0 +1,14 @@ +# 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. + diff --git a/src/webui/service/base_optical/route.py b/src/webui/service/base_optical/route.py new file mode 100644 index 0000000000000000000000000000000000000000..1b443474a493675671943bdc2d7efb95e1b48f63 --- /dev/null +++ b/src/webui/service/base_optical/route.py @@ -0,0 +1,33 @@ +# 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 flask import render_template, Blueprint +#from common.proto.context_pb2 import Empty, OpticalConfigList +#from context.client.ContextClient import ContextClient +#from device.client.DeviceClient import DeviceClient + +base_optical = Blueprint('base_optical', __name__, url_prefix='/base_optical') +#device_client = DeviceClient() +#context_client = ContextClient() + +@base_optical.get('/') +def home(): + # context_client.connect() + # opticalConfig_list:OpticalConfigList = context_client.GetOpticalConfig(Empty()) + # context_client.close() + # device_client.connect() + # device_client.GetDeviceConfiguration(opticalConfig_list) + # device_client.close() + return render_template("base_optical/home.html") diff --git a/src/webui/service/bgpls/__init__.py b/src/webui/service/bgpls/__init__.py index bbfc943b68af13a11e562abbc8680ade71db8f02..023830645e0fcb60e3f8583674a954810af222f2 100644 --- a/src/webui/service/bgpls/__init__.py +++ b/src/webui/service/bgpls/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/webui/service/bgpls/forms.py b/src/webui/service/bgpls/forms.py index 46e89e748b1d2a77639acaf5231751a20e073106..6868520ce0d493b81373b511fc053cf2daf55483 100644 --- a/src/webui/service/bgpls/forms.py +++ b/src/webui/service/bgpls/forms.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/webui/service/bgpls/routes.py b/src/webui/service/bgpls/routes.py index 4148b1cd233e3b2b3dd6d91eb51d103bc8ea7c51..aa2ebc77d78de639f0ea147074a86eca1e2d14f7 100644 --- a/src/webui/service/bgpls/routes.py +++ b/src/webui/service/bgpls/routes.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/webui/service/context/__init__.py b/src/webui/service/context/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/webui/service/context/__init__.py +++ b/src/webui/service/context/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/webui/service/context/routes.py b/src/webui/service/context/routes.py index 7462126a9b4f0aac1592a9430894e2a04bfd594e..463d994c0db3fa15b8b5637459608b1a757bf2d4 100644 --- a/src/webui/service/context/routes.py +++ b/src/webui/service/context/routes.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/webui/service/device/__init__.py b/src/webui/service/device/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/webui/service/device/__init__.py +++ b/src/webui/service/device/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/webui/service/device/forms.py b/src/webui/service/device/forms.py index e4c71d92170dc9fe46996a1c93978647800aa300..4fa6829e760be6f24ba011a18664ce2ee4635595 100644 --- a/src/webui/service/device/forms.py +++ b/src/webui/service/device/forms.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -33,6 +33,7 @@ class AddDeviceForm(FlaskForm): device_drivers_gnmi_openconfig = BooleanField('GNMI OPENCONFIG') device_drivers_optical_tfs = BooleanField('OPTICAL TFS') device_drivers_ietf_actn = BooleanField('IETF ACTN') + device_drivers_qkd = BooleanField('QKD') device_config_address = StringField('connect/address',default='127.0.0.1',validators=[DataRequired(), Length(min=5)]) device_config_port = StringField('connect/port',default='0',validators=[DataRequired(), Length(min=1)]) @@ -57,3 +58,4 @@ class UpdateDeviceForm(FlaskForm): validators=[NumberRange(min=0)]) submit = SubmitField('Update') + diff --git a/src/webui/service/device/routes.py b/src/webui/service/device/routes.py index fb930024d9fc3ff0b70b77345041e33dcb0d28c2..f3896bdd8f80ddcbcc55f91707caa5e462801cab 100644 --- a/src/webui/service/device/routes.py +++ b/src/webui/service/device/routes.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -129,6 +129,8 @@ def add(): device_drivers.append(DeviceDriverEnum.DEVICEDRIVER_OPTICAL_TFS) if form.device_drivers_ietf_actn.data: device_drivers.append(DeviceDriverEnum.DEVICEDRIVER_IETF_ACTN) + if form.device_drivers_qkd.data: + device_drivers.append(DeviceDriverEnum.DEVICEDRIVER_QKD) device_obj.device_drivers.extend(device_drivers) # pylint: disable=no-member try: @@ -165,6 +167,16 @@ def inventory(device_uuid: str): context_client.close() return render_template('device/inventory.html', device=device_obj) +@device.route('logical/', methods=['GET', 'POST']) +def logical(device_uuid: str): + context_client.connect() + device_obj = get_device(context_client, device_uuid, rw_copy=False) + if device_obj is None: + flash('Device({:s}) not found'.format(str(device_uuid)), 'danger') + device_obj = Device() + context_client.close() + return render_template('device/logical.html', device=device_obj) + @device.get('/delete') def delete(device_uuid): try: diff --git a/src/webui/service/js/__init__.py b/src/webui/service/js/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/webui/service/js/__init__.py +++ b/src/webui/service/js/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/webui/service/js/routes.py b/src/webui/service/js/routes.py index a6180825f7e1294d5ca571e9672d3b4a4b6715d4..dfc965381ddf041b28e6705c5456b17c8ff4825c 100644 --- a/src/webui/service/js/routes.py +++ b/src/webui/service/js/routes.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/webui/service/link/__init__.py b/src/webui/service/link/__init__.py index 7c7568fdb6e3b1446aa9412ad32a0a5948ba949b..3aa410c134b0aebb3117ca3220e823f7433b180c 100644 --- a/src/webui/service/link/__init__.py +++ b/src/webui/service/link/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/webui/service/link/routes.py b/src/webui/service/link/routes.py index 973414fb35cde2bd667fcc74e4841f434824e038..dacf77534711c97237ca1afd54c3646fe9809a28 100644 --- a/src/webui/service/link/routes.py +++ b/src/webui/service/link/routes.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/webui/service/load_gen/__init__.py b/src/webui/service/load_gen/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/webui/service/load_gen/__init__.py +++ b/src/webui/service/load_gen/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/webui/service/load_gen/forms.py b/src/webui/service/load_gen/forms.py index ede779681eed4c7709d1c91620ce2302ea6981c0..d0454948a3f982b923d434d8cf1d4d42614dc48f 100644 --- a/src/webui/service/load_gen/forms.py +++ b/src/webui/service/load_gen/forms.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/webui/service/load_gen/routes.py b/src/webui/service/load_gen/routes.py index 24f2a078d2ed70f9ba9c86431336c7018f6d4d8d..fc1bb8f125eadbbc6d438fe26f799e2acb58b6e0 100644 --- a/src/webui/service/load_gen/routes.py +++ b/src/webui/service/load_gen/routes.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/webui/service/main/__init__.py b/src/webui/service/main/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/webui/service/main/__init__.py +++ b/src/webui/service/main/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/webui/service/main/forms.py b/src/webui/service/main/forms.py index dd55fb5640eb7003a0be16d11031460f92027ca0..bddf6d0d323e0742bda684e811cfb027c3dc31bf 100644 --- a/src/webui/service/main/forms.py +++ b/src/webui/service/main/forms.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/webui/service/main/routes.py b/src/webui/service/main/routes.py index 52944a31c439472055d65e9e75249465dcbca7f7..02e1d28ba4a2f2f334a4cf015368d0a8fb5bb8d2 100644 --- a/src/webui/service/main/routes.py +++ b/src/webui/service/main/routes.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -153,11 +153,24 @@ def topology(): 'source': link.link_endpoint_ids[0].device_id.device_uuid.uuid, 'target': link.link_endpoint_ids[1].device_id.device_uuid.uuid, }) - - return jsonify({'devices': devices, 'links': links}) + + optical_links = [] + for link in response.optical_links: + if len(link.link_endpoint_ids) != 2: + str_link = grpc_message_to_json_string(link) + LOGGER.warning('Unexpected link with len(endpoints) != 2: {:s}'.format(str_link)) + continue + optical_links.append({ + 'id': link.link_id.link_uuid.uuid, + 'name': link.name, + 'source': link.link_endpoint_ids[0].device_id.device_uuid.uuid, + 'target': link.link_endpoint_ids[1].device_id.device_uuid.uuid, + }) + + return jsonify({'devices': devices, 'links': links, 'optical_links': optical_links}) except: # pylint: disable=bare-except LOGGER.exception('Error retrieving topology') - return jsonify({'devices': [], 'links': []}) + return jsonify({'devices': [], 'links': [], 'optical_links': []}) finally: context_client.close() diff --git a/src/webui/service/optical_link/__init__.py b/src/webui/service/optical_link/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..3aa410c134b0aebb3117ca3220e823f7433b180c --- /dev/null +++ b/src/webui/service/optical_link/__init__.py @@ -0,0 +1,14 @@ +# 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. + diff --git a/src/webui/service/optical_link/routes.py b/src/webui/service/optical_link/routes.py new file mode 100644 index 0000000000000000000000000000000000000000..764d4c266948998b7389f276126f384bff7e7ba8 --- /dev/null +++ b/src/webui/service/optical_link/routes.py @@ -0,0 +1,108 @@ +# 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 flask import current_app, render_template, Blueprint, flash, session, redirect, url_for +from common.proto.context_pb2 import Empty, OpticalLink, LinkId, OpticalLinkList +from common.tools.context_queries.EndPoint import get_endpoint_names +from common.tools.context_queries.Topology import get_topology +from context.client.ContextClient import ContextClient + +optical_link = Blueprint('optical_link', __name__, url_prefix='/optical_link') +context_client = ContextClient() + +@optical_link.get('/') +def home(): + if 'context_uuid' not in session or 'topology_uuid' not in session: + flash("Please select a context!", "warning") + return redirect(url_for("main.home")) + + context_uuid = session['context_uuid'] + topology_uuid = session['topology_uuid'] + + links, endpoint_ids = list(), list() + device_names, endpoints_data = dict(), dict() + + context_client.connect() + grpc_topology = get_topology(context_client, topology_uuid, context_uuid=context_uuid, rw_copy=False) + if grpc_topology is None: + flash('Context({:s})/Topology({:s}) not found'.format(str(context_uuid), str(topology_uuid)), 'danger') + else: + grpc_links : OpticalLinkList = context_client.GetOpticalLinkList(Empty()) + for link_ in grpc_links.optical_links: + links.append(link_) + endpoint_ids.extend(link_.link_endpoint_ids) + device_names, endpoints_data = get_endpoint_names(context_client, endpoint_ids) + context_client.close() + + return render_template( + 'optical_link/home.html', links=links, device_names=device_names, + endpoints_data=endpoints_data + ) + + +@optical_link.route('detail/', methods=('GET', 'POST')) +def detail(link_uuid: str): + context_client.connect() + # pylint: disable=no-member + link_id = LinkId() + link_id.link_uuid.uuid = link_uuid + link_obj = context_client.GetOpticalLink(link_id) + c_slots=s_slots=l_slots=None + if link_obj is None: + flash('Optical Link({:s}) not found'.format(str(link_uuid)), 'danger') + link_obj = OpticalLink() + device_names, endpoints_data = dict(), dict() + else: + device_names, endpoints_data = get_endpoint_names(context_client, link_obj.link_endpoint_ids) + c_slots = link_obj.optical_details.c_slots + l_slots = link_obj.optical_details.l_slots + s_slots = link_obj.optical_details.s_slots + + context_client.close() + + return render_template( + 'optical_link/detail.html', link=link_obj, device_names=device_names, + endpoints_data=endpoints_data, c_slots=c_slots, l_slots=l_slots, s_slots=s_slots + ) + + +@optical_link.get('/delete') +def delete(link_uuid): + try: + request = LinkId() + request.link_uuid.uuid = link_uuid # pylint: disable=no-member + context_client.connect() + context_client.DeleteOpticalLink(request) + context_client.close() + + flash(f'Optical Link "{link_uuid}" deleted successfully!', 'success') + except Exception as e: # pylint: disable=broad-except + flash(f'Problem deleting link "{link_uuid}": {e.details()}', 'danger') + current_app.logger.exception(e) + return redirect(url_for('optical_link.home')) + + +@optical_link.get("delete_all") +def delete_all(): + try: + context_client.connect() + optical_link_list : OpticalLinkList = context_client.GetOpticalLinkList(Empty()) + for optical_link in optical_link_list.optical_links: + context_client.DeleteOpticalLink(optical_link.link_id) + context_client.close() + flash(f"All Optical Link Deleted Successfully",'success') + except Exception as e: + flash(f"Problem in delete all optical link => {e}",'danger') + return redirect(url_for('optical_link.home')) diff --git a/src/webui/service/opticalconfig/__init__.py b/src/webui/service/opticalconfig/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..53d5157f750bfb085125cbd33faff1cec5924e14 --- /dev/null +++ b/src/webui/service/opticalconfig/__init__.py @@ -0,0 +1,14 @@ +# 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. + diff --git a/src/webui/service/opticalconfig/forms.py b/src/webui/service/opticalconfig/forms.py new file mode 100644 index 0000000000000000000000000000000000000000..21bd1bc22d52e8da0933aa906fc09541c86ca9a3 --- /dev/null +++ b/src/webui/service/opticalconfig/forms.py @@ -0,0 +1,41 @@ +# 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 flask_wtf import FlaskForm +from wtforms import StringField, SelectField, SubmitField + +class UpdateDeviceForm(FlaskForm): + power = StringField('Power') + frequency = StringField("Frequency") + operational_mode = StringField("Operational Mode") + line_port = SelectField("Line Port") + submit = SubmitField('Update') + +class AddTrancseiver(FlaskForm): + transceiver = StringField("Transceiver") + submit = SubmitField('Add') + +class UpdateInterfaceForm(FlaskForm): + ip = StringField("IP Address") + prefix_length = StringField("Prefix Length") + +DEVICE_STATUS = [ + ('', 'Select...'), + ('DISABLED', 'DISABLED'), + ('ENABLED', 'ENABLED') +] + +class UpdateStatusForm(FlaskForm): + status = SelectField("Device Status", choices=DEVICE_STATUS) diff --git a/src/webui/service/opticalconfig/routes.py b/src/webui/service/opticalconfig/routes.py new file mode 100644 index 0000000000000000000000000000000000000000..298ef77a938d81f1a49572e8e90e822790c63ce8 --- /dev/null +++ b/src/webui/service/opticalconfig/routes.py @@ -0,0 +1,407 @@ +# 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 json, logging +from flask import ( + request, redirect, render_template, Blueprint, flash, session, url_for, + current_app, make_response +) +from common.proto.context_pb2 import ( + Empty, OpticalConfig, OpticalConfigId, OpticalConfigList +) +from common.tools.context_queries.OpticalConfig import opticalconfig_get_uuid +from common.DeviceTypes import DeviceTypeEnum +from context.client.ContextClient import ContextClient +from device.client.DeviceClient import DeviceClient +from service.client.ServiceClient import ServiceClient +from slice.client.SliceClient import SliceClient +from .forms import UpdateDeviceForm, AddTrancseiver, UpdateStatusForm + +opticalconfig = Blueprint('opticalconfig', __name__, url_prefix="/opticalconfig") + +context_client = ContextClient() +device_client = DeviceClient() +service_client = ServiceClient() +slice_client = SliceClient() + +LOGGER = logging.getLogger(__name__) + +DESCRIPTOR_LOADER_NUM_WORKERS = 10 + +@opticalconfig.get("/") +def home() : + list_config = [] + if 'context_uuid' not in session or 'topology_uuid' not in session: + flash("Please select a context!", "warning") + return redirect(url_for("main.home")) + context_uuid = session['context_uuid'] + topology_uuid = session['topology_uuid'] + + context_client.connect() + opticalConfig_list : OpticalConfigList = context_client.GetOpticalConfig(Empty()) + for configs in opticalConfig_list.opticalconfigs: + value = json.loads(configs.config) if type(configs.config)==str else configs.config + config_type = value["type"] + if config_type != DeviceTypeEnum.OPEN_ROADM._value_ : + if 'channels' in value: + value["channels_number"] = len(value['channels']) + else: + if 'interfaces' in value: + value["channels_number"] = len(value['interfaces']) + # value['operationalMode']=value['operational-mode'] + # value['targetOutputPower']=value['target-output-power'] + value['opticalconfig_id']=configs.opticalconfig_id + # value['line_port']=value["line-port"] + list_config.append(value) + + context_client.close() + return render_template('opticalconfig/home.html', config=list_config) + +@opticalconfig.route('/detail',methods=['GET']) +def show_details(config_uuid): + opticalconfigId = OpticalConfigId() + opticalconfigId.opticalconfig_uuid = config_uuid + device_details = [] + + context_client.connect() + response = context_client.SelectOpticalConfig(opticalconfigId) + context_client.close() + if (response and response.opticalconfig_id.opticalconfig_uuid !=''): + opticalConfig = OpticalConfig() + opticalConfig.CopyFrom(response) + + device_name = "" + config = json.loads(opticalConfig.config) + if "device_name" in config: + device_name = config["device_name"] + + config_type = config["type"] + if config_type == DeviceTypeEnum.OPTICAL_TRANSPONDER._value_: + LOGGER.info("config details from show detail %s",config) + if 'channels' in config: + for channel in config['channels'] : + new_config={} + new_config["name"]=channel['name'] + new_config['operationalMode']=channel['operational-mode'] if 'operational-mode' in channel else '' + new_config['targetOutputPower']=channel['target-output-power'] if 'target-output-power' in channel else '' + new_config["frequency"]=channel['frequency'] if 'frequency' in channel else '' + new_config['line_port']=channel["line-port"] if 'line-port' in channel else '' + new_config["status"] = channel['status'] if 'status' in channel else "" + device_details.append(new_config) + + if config_type == DeviceTypeEnum.OPTICAL_ROADM._value_: + LOGGER.info("config details from show detail %s",config) + if 'channels' in config: + for channel in config['channels'] : + new_config={} + new_config["band_name"]=channel['band_name'] if 'band_name' in channel else None + new_config['type']=channel['type'] if 'type' in channel else '' + new_config['src_port']=channel['src_port'] if 'src_port' in channel else '' + new_config['dest_port']=channel['dest_port'] if 'dest_port' in channel else '' + new_config["lower_frequency"]=channel['lower_frequency'] if 'lower_frequency' in channel else '' + new_config["upper_frequency"]=channel['upper_frequency'] if 'upper_frequency' in channel else '' + new_config["status"] = channel['status'] if 'status' in channel else "" + new_config['optical_band_parent']= channel['optical_band_parent'] if 'optical_band_parent' in channel else '' + new_config['channel_index']= channel['channel_index'] if 'channel_index' in channel else '' + device_details.append(new_config) + + if config_type == DeviceTypeEnum.OPEN_ROADM._value_: + if 'interfaces' in config : + for interface in config["interfaces"]: + new_config={} + new_config["name"]=interface["name"] if "name" in interface else '' + new_config["administrative_state"]=interface[ "administrative_state"] + new_config["circuit_pack_name"]=interface["circuit_pack_name"] + new_config["port"]=interface["port"] + new_config["interface_list"]=interface["interface_list"] + new_config["frequency"]=interface["frequency"] + new_config["width"]=interface[ "width"] + new_config["type"]=interface["type"] + device_details.append(new_config) + + LOGGER.info("device details %s",device_details) + return render_template('opticalconfig/details.html', device=device_details,config_id=config_uuid,device_name=device_name,type=config_type) + + return render_template( + 'opticalconfig/details.html', device=device_details, config_id=config_uuid, + device_name=device_name, type=config_type + ) + + +@opticalconfig.route('/delete', methods=['GET']) +def delete_opitcalconfig (opticalconfig_uuid) : + try : + opticalconfigId = OpticalConfigId() + opticalconfigId.opticalconfig_uuid = opticalconfig_uuid + context_client.connect() + context_client.DeleteOpticalConfig(opticalconfigId) + context_client.close() + flash(f'OpticalConfig "{opticalconfig_uuid}" deleted successfully!', 'success') + except Exception as e: # pylint: disable=broad-except + flash(f'Problem deleting optical config {opticalconfig_uuid}', 'danger') + current_app.logger.exception(e) + return redirect(url_for('opticalconfig.home')) + + +@opticalconfig.route('/update_opticalconfig', methods=['POST']) +def update_externally(): + if (request.method == 'POST'): + data = request.get_json() + devices = data.get('devices') + + myResponse = [] + status_code = '' + for device in devices : + port = device.get("port") + channel_name = f"channel-{port}" + device_name = device.get("device_name") + + if device_name: + opticalconfig_uuid = opticalconfig_get_uuid(device_name=device_name) + opticalconfigId=OpticalConfigId() + opticalconfigId.opticalconfig_uuid = opticalconfig_uuid + context_client.connect() + opticalconfig = context_client.SelectOpticalConfig(opticalconfigId) + context_client.close() + + if opticalconfig and opticalconfig.opticalconfig_id.opticalconfig_uuid != '' : + new_opticalconfig = OpticalConfig() + new_opticalconfig.CopyFrom(opticalconfig) + config = json.loads(opticalconfig.config) + channels = config['channels'] + target_channel = next((item for item in channels if item["name"]['index'] == channel_name) , None) + target_power = device.get( "target-output-power") + freq = device.get("frequency") + mode = device.get("operational-mode") + status = device.get("status","ENABLED") + + if target_channel: + if target_power is not None : + target_channel["target-output-power"] =str(target_power) + if freq is not None : + target_channel["frequency"] = freq + if mode is not None : + target_channel["operational-mode"] = mode + if status is not None : + target_channel["status"] = "ENABLED" + #del target_channel['name'] + config["new_config"]=target_channel + config["new_config"]["channel_name"]=channel_name + config["flow"]=[(port,'0')] + opticalconfig.config =json.dumps(config) + + try: + device_client.connect() + device_client.ConfigureOpticalDevice(opticalconfig) + device_client.close() + + myResponse.append(f"device {device_name} port {port} is updated successfully") + status_code = 200 + except Exception as e: # pylint: disable=broad-except + myResponse.append(f"Problem updating the device. {e}") + status_code = 500 + break + else : + myResponse.append(f"requested channel {channel_name} is not existed") + status_code = 400 + break + else : + myResponse.append(f"requested device {device_name} is not existed") + status_code = 400 + break + + response=make_response(f'{myResponse}') + response.status_code=status_code + return response + + #return redirect(url_for('opticalconfig.show_details',config_uuid=opticalconfig_uuid)) + #return redirect(url_for('opticalconfig.home')) + +@opticalconfig.route('//update', methods=['GET', 'POST']) +def update(config_uuid, channel_name): + form = UpdateDeviceForm() + + opticalconfigId = OpticalConfigId() + opticalconfigId.opticalconfig_uuid = config_uuid + context_client.connect() + response = context_client.SelectOpticalConfig(opticalconfigId) + context_client.close() + + opticalconfig = OpticalConfig() + opticalconfig.CopyFrom(response) + config =json.loads(opticalconfig.config) + new_config={} + for channel in config['channels']: + if (channel["name"] == channel_name): + new_config=channel + form.frequency.default = channel["frequency"] + form.operational_mode.default=channel["operational-mode"] + form.power.default=channel["target-output-power"] + form.line_port.choices = [("","")] + + for transceiver in config["transceivers"]['transceiver']: + form.line_port.choices.append((transceiver,transceiver)) + + # listing enum values + if form.validate_on_submit(): + new_config["target-output-power"] =form.power.data if form.power.data != '' else new_config['target-output-power'] + new_config["frequency"]=form.frequency.data if form.frequency.data != '' else new_config['frequency'] + new_config["operational-mode"]=form.operational_mode.data if form.operational_mode.data != '' else new_config['operational-mode'] + new_config["line-port"]=form.line_port.data if form.line_port.data != '' else new_config['line-port'] + opticalconfig.config =json.dumps(new_config) + + try: + device_client.connect() + device_client.ConfigureOpticalDevice(opticalconfig) + device_client.close() + flash(f' device was updated.', 'success') + return redirect(url_for('opticalconfig.show_details',config_uuid=config_uuid)) + except Exception as e: # pylint: disable=broad-except + flash(f'Problem updating the device. {e}', 'danger') + return render_template('device/update.html', device=response, form=form, submit_text='Update Device',channel_name=channel_name) + + +@opticalconfig.route('refresh_all',methods=['POST','GET']) +def refresh_all (): + context_client.connect() + opticalConfig_list:OpticalConfigList = context_client.GetOpticalConfig(Empty()) + context_client.close() + device_client.connect() + device_client.GetDeviceConfiguration(opticalConfig_list) + device_client.close() + return home() + + +@opticalconfig.route('/add_transceiver', methods=['GET','POST']) +def add_transceiver (config_uuid): + config={} + addtrancseiver=AddTrancseiver() + opticalconfigId=OpticalConfig() + opticalconfigId.opticalconfig_uuid=config_uuid + context_client.connect() + response = context_client.SelectOpticalConfig(opticalconfigId) + context_client.close() + opticlConfig=OpticalConfig() + opticlConfig.CopyFrom(response) + + if addtrancseiver.validate_on_submit(): + config["add_transceiver"]=addtrancseiver.transceiver.data + opticlConfig.config=json.dumps(config) + + try: + device_client.connect() + device_client.ConfigureOpticalDevice(opticlConfig) + device_client.close() + flash(f' device was updated.', 'success') + return redirect(url_for('opticalconfig.update',config_uuid=config_uuid)) + except Exception as e: # pylint: disable=broad-except + flash(f'Problem updating the device. {e}', 'danger') + return render_template('opticalconfig/add_transceiver.html',form=addtrancseiver, submit_text='Add Trancseiver') + + +@opticalconfig.route('//update_status', methods=['GET','POST']) +def update_status (config_uuid,channel_name): + config = {} + form = UpdateStatusForm() + + opticalconfigId=OpticalConfigId() + opticalconfigId.opticalconfig_uuid=config_uuid + context_client.connect() + response = context_client.SelectOpticalConfig(opticalconfigId) + context_client.close() + opticlConfig=OpticalConfig() + opticlConfig.CopyFrom(response) + config=json.loads(opticlConfig.config) + new_config={} + port="" + if form.validate_on_submit(): + if channel_name: + port = channel_name.split('-')[1] + new_config["status"]=form.status.data + new_config["name"]=channel_name + config["flow"]=[(port,'0')] + config["new_config"]=new_config + opticlConfig.config=json.dumps(config) + + try: + device_client.connect() + device_client.ConfigureOpticalDevice(opticlConfig) + device_client.close() + flash(f' device was updated.', 'success') + return redirect(url_for('opticalconfig.show_details',config_uuid=config_uuid)) + except Exception as e: # pylint: disable=broad-except + flash(f'Problem updating the device. {e}', 'danger') + return render_template( + 'opticalconfig/update_status.html', form=form, channel_name=channel_name, + submit_text='Update Device Status' + ) + +@opticalconfig.route('/configure_openroadm', methods=['POST']) +def update_openroadm(): + if (request.method == 'POST'): + ports_list= [] + data = request.get_json() + LOGGER.info(f"data {data}") + devices=data.get('devices') + LOGGER.info(f"devices {devices}") + myResponse =[] + status_code='' + config={} + target_interface={} + for device in devices : + frequency = device.get("frequency") + width= device.get("width") + ports=device.get('ports') + device_name=device.get("device_name") + LOGGER.info(f"device from post {device}") + target_interface["frequency"]=frequency + target_interface["width"]=width + target_interface["administrative-state"]="inService" + target_interface["config_type"]=device.get("config_type") + + if (device_name): + opticalconfig_uuid = opticalconfig_get_uuid(device_name=device_name) + opticalconfigId=OpticalConfigId() + opticalconfigId.opticalconfig_uuid=opticalconfig_uuid + context_client.connect() + opticalconfig = context_client.SelectOpticalConfig(opticalconfigId) + context_client.close() + config =json.loads(opticalconfig.config) + for port in ports : + ports_list.append({ + "supporting-circuit-pack-name":port["circuit_pack"], + 'supporting-interface-list':port["interface_list"], + 'supporting-port':port["port"] + }) + target_interface["ports"]=ports_list + config["new_config"]=target_interface + opticalconfig.config =json.dumps(config) + try: + device_client.connect() + device_client.ConfigureOpticalDevice(opticalconfig) + device_client.close() + myResponse.append(f"device {device_name} port {port} is updated successfully") + status_code = 200 + except Exception as e: # pylint: disable=broad-except + myResponse.append(f"Problem updating the device. {e}") + status_code = 500 + break + else : + myResponse.append(f"requested device {device_name} is not existed") + status_code = 400 + break + + response=make_response(f'{myResponse}') + response.status_code=status_code + return response diff --git a/src/webui/service/policy_rule/__init__.py b/src/webui/service/policy_rule/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/webui/service/policy_rule/__init__.py +++ b/src/webui/service/policy_rule/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/webui/service/policy_rule/routes.py b/src/webui/service/policy_rule/routes.py index 4fbecabe6a3ba40303f8b42f4887ac6935efab5f..8c2464a79808db310a6d2296ec5c422188b0de0d 100644 --- a/src/webui/service/policy_rule/routes.py +++ b/src/webui/service/policy_rule/routes.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/webui/service/qkd_app/__init__.py b/src/webui/service/qkd_app/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..023830645e0fcb60e3f8583674a954810af222f2 --- /dev/null +++ b/src/webui/service/qkd_app/__init__.py @@ -0,0 +1,13 @@ +# 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. diff --git a/src/webui/service/qkd_app/routes.py b/src/webui/service/qkd_app/routes.py new file mode 100644 index 0000000000000000000000000000000000000000..a5e6111e70056fa85d3c6b9f26a8cc1a86dee241 --- /dev/null +++ b/src/webui/service/qkd_app/routes.py @@ -0,0 +1,167 @@ +# 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 grpc +import logging +from flask import current_app, render_template, Blueprint, flash, session, redirect, url_for +from common.proto.qkd_app_pb2 import App, AppId, QKDAppStatusEnum, QKDAppTypesEnum +from common.proto.context_pb2 import Uuid, ContextId +from common.tools.context_queries.Context import get_context +from common.tools.context_queries.Device import get_device +from context.client.ContextClient import ContextClient +from qkd_app.client.QKDAppClient import QKDAppClient + +# Set up logging +LOGGER = logging.getLogger(__name__) + +# Blueprint for QKDApp routes +qkd_app = Blueprint('qkd_app', __name__, url_prefix='/qkd_app') + +# Initialize clients +qkd_app_client = QKDAppClient() +context_client = ContextClient() + +@qkd_app.get('/') +def home(): + if 'context_uuid' not in session or 'topology_uuid' not in session: + flash("Please select a context!", "warning") + return redirect(url_for("main.home")) + + context_uuid = session['context_uuid'] + topology_uuid = session['topology_uuid'] + + # Connect to context client + context_client.connect() + device_names = dict() + + try: + + # Fetch context object + context_obj = get_context(context_client, context_uuid, rw_copy=False) + if context_obj is None: + flash('Context({:s}) not found'.format(str(context_uuid)), 'danger') + apps = list() + else: + try: + # Call ListApps using the context_id + apps_response = qkd_app_client.ListApps(context_obj.context_id) + apps = apps_response.apps + except grpc.RpcError as e: + LOGGER.error(f"gRPC error while fetching apps: {e.details()}") + if e.code() != grpc.StatusCode.NOT_FOUND: raise + if e.details() != 'Context({:s}) not found'.format(context_uuid): raise + apps = list() + else: + # Map local and remote device names + for app in apps: + if app.local_device_id.device_uuid.uuid not in device_names: + device = get_device(context_client, app.local_device_id.device_uuid.uuid) + if device: + device_names[app.local_device_id.device_uuid.uuid] = device.name + + if app.remote_device_id.device_uuid.uuid and app.remote_device_id.device_uuid.uuid not in device_names: + device = get_device(context_client, app.remote_device_id.device_uuid.uuid) + if device: + device_names[app.remote_device_id.device_uuid.uuid] = device.name + finally: + context_client.close() + + # Render the template with app list and device names + return render_template( + 'qkd_app/home.html', + apps=apps, + device_names=device_names, + ate=QKDAppTypesEnum, + ase=QKDAppStatusEnum + ) + +@qkd_app.route('detail/', methods=['GET', 'POST']) +def detail(app_uuid: str): + """ + Displays details for a specific QKD app identified by its UUID. + """ + try: + qkd_app_client.connect() + + # Wrap the app_uuid in a Uuid object and fetch details + uuid_message = Uuid(uuid=app_uuid) + app_id = AppId(app_uuid=uuid_message) + app_detail = qkd_app_client.GetApp(app_id) + + if not app_detail: + flash(f"App with UUID {app_uuid} not found", "danger") + return redirect(url_for("qkd_app.home")) + + # Fetch device details + context_client.connect() + device_names = {} + + try: + if app_detail.local_device_id.device_uuid.uuid: + local_device = get_device(context_client, app_detail.local_device_id.device_uuid.uuid) + if local_device: + device_names[app_detail.local_device_id.device_uuid.uuid] = local_device.name + + if app_detail.remote_device_id.device_uuid.uuid: + remote_device = get_device(context_client, app_detail.remote_device_id.device_uuid.uuid) + if remote_device: + device_names[app_detail.remote_device_id.device_uuid.uuid] = remote_device.name + + except grpc.RpcError as e: + LOGGER.error(f"Failed to retrieve device details for app {app_uuid}: {e}") + flash(f"Error retrieving device details: {e.details()}", "danger") + return redirect(url_for("qkd_app.home")) + + finally: + context_client.close() + + return render_template( + 'qkd_app/detail.html', + app=app_detail, + ase=QKDAppStatusEnum, + ate=QKDAppTypesEnum, + device_names=device_names + ) + + except grpc.RpcError as e: + LOGGER.error(f"Failed to retrieve app details for {app_uuid}: {e}") + flash(f"Error retrieving app details: {e.details()}", "danger") + return redirect(url_for("qkd_app.home")) + + finally: + qkd_app_client.close() + +@qkd_app.get('/delete') +def delete(app_uuid: str): + """ + Deletes a specific QKD app identified by its UUID. + """ + try: + request = AppId(app_uuid=Uuid(uuid=app_uuid)) + + qkd_app_client.connect() + qkd_app_client.DeleteApp(request) # Call the DeleteApp method + qkd_app_client.close() + + flash(f'App "{app_uuid}" deleted successfully!', 'success') + + except grpc.RpcError as e: + LOGGER.error(f"Problem deleting app {app_uuid}: {e}") + flash(f"Problem deleting app {app_uuid}: {e.details()}", 'danger') + + except Exception as e: + LOGGER.exception(f"Unexpected error while deleting app {app_uuid}: {e}") + flash(f"Unexpected error: {str(e)}", 'danger') + + return redirect(url_for('qkd_app.home')) diff --git a/src/webui/service/service/__init__.py b/src/webui/service/service/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..0dc5506ab42d67d67a88cf8976409472213fe098 100644 --- a/src/webui/service/service/__init__.py +++ b/src/webui/service/service/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -12,3 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. + diff --git a/src/webui/service/service/forms.py b/src/webui/service/service/forms.py index f07acf54365b79245583e7f9567b8bc4a5cfd89d..5228ce4101a8739aa9314c07179c76c738a78bde 100644 --- a/src/webui/service/service/forms.py +++ b/src/webui/service/service/forms.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -17,6 +17,11 @@ from flask_wtf import FlaskForm from wtforms import StringField, SelectField, IntegerField, DecimalField from wtforms.validators import InputRequired, Optional, NumberRange, ValidationError, StopValidation +# Custom uuid validator +def validate_uuid_address(form, field): + if not re.match(r'^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$', field.data): + raise ValidationError('Invalid uuid format') + # Custom IPv4 address validator def validate_ipv4_address(form, field): try: @@ -60,7 +65,25 @@ class CustomInputRequired(): raise StopValidation(self.message) class AddServiceForm_1(FlaskForm): - service_type = SelectField('Type of service', choices=[('', 'Select a type of service to add'), ('ACL_L2', 'ACL_L2'), ('ACL_IPV4', 'ACL_IPV4'), ('ACL_IPV6', 'ACL_IPV6'), ('L2VPN', 'L2VPN'), ('L3VPN', 'L3VPN')], validators=[InputRequired()]) + service_type = SelectField('Type of service', choices=[('', 'Select a type of service to add'), ('ACL_L2', 'ACL_L2'), ('ACL_IPV4', 'ACL_IPV4'), ('ACL_IPV6', 'ACL_IPV6'), ('L2VPN', 'L2VPN'), ('L3VPN', 'L3VPN'), ('QKD', 'QKD')], validators=[InputRequired()]) + +class AddServiceForm_QKD(FlaskForm): + #GENERIC SERVICE PARAMETERS (COMMON & MANDATORY) + service_name = StringField('Service Name', validators=[CustomInputRequired()]) + service_type = SelectField('Service Type', choices=[(6, '6 (QKD)')], validators=[CustomInputRequired()]) + service_device_1 = SelectField('Device_1', choices=[('', 'Select a device (Mandatory)')], validators=[CustomInputRequired()]) + service_device_2 = SelectField('Device_2', choices=[('', 'Select a device (Mandatory)')], validators=[CustomInputRequired()]) + service_endpoint_1 = StringField('Device_1 Endpoint', validators=[CustomInputRequired()]) + service_endpoint_2 = StringField('Device_2 Endpoint', validators=[CustomInputRequired()]) + + #GENERIC SERVICE CONSTRAINT PARAMETERS (ALL OPTIONAL) + service_capacity = DecimalField('Service Capacity', places=2, default=10.00, validators=[Optional(), NumberRange(min=0)]) + service_latency = DecimalField('Service Latency', places=2, default=15.20, validators=[Optional(), NumberRange(min=0)]) + service_availability= DecimalField('Service Availability', places=2, validators=[Optional(), NumberRange(min=0)]) + service_isolation = SelectField('Service Isolation', choices=[('', 'Select (Optional)'), ('NO_ISOLATION', 'NO_ISOLATION'), ('PHYSICAL_ISOLATION', 'PHYSICAL_ISOLATION'), + ('LOGICAL_ISOLATION', 'LOGICAL_ISOLATION'), ('PROCESS_ISOLATION', 'PROCESS_ISOLATION'), ('PHYSICAL_MEMORY_ISOLATION', 'PHYSICAL_MEMORY_ISOLATION'), + ('PHYSICAL_NETWORK_ISOLATION', 'PHYSICAL_NETWORK_ISOLATION'), ('VIRTUAL_RESOURCE_ISOLATION', 'VIRTUAL_RESOURCE_ISOLATION'), + ('NETWORK_FUNCTIONS_ISOLATION', 'NETWORK_FUNCTIONS_ISOLATION'), ('SERVICE_ISOLATION', 'SERVICE_ISOLATION')], validators=[Optional()]) class AddServiceForm_ACL_L2(FlaskForm): #GENERIC SERVICE PARAMETERS (COMMON & MANDATORY) @@ -259,3 +282,4 @@ class AddServiceForm_L3VPN(FlaskForm): Device_2_IF_address_ip = StringField('Device_2 IP Address', validators=[CustomInputRequired(), validate_ipv4_address]) Device_2_IF_address_prefix = IntegerField('Device_2 IP Prefix length', validators=[CustomInputRequired(), validate_uint32]) Device_2_IF_description = StringField ('Device_2 SubIF Description', validators=[Optional()]) + diff --git a/src/webui/service/service/routes.py b/src/webui/service/service/routes.py index 92025b2bec4f7c70b446a8c422e2cdb166c95466..02062e98198c98948b4967b4a2a4df5cde9b1ce5 100644 --- a/src/webui/service/service/routes.py +++ b/src/webui/service/service/routes.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. @@ -35,14 +35,14 @@ from common.tools.object_factory.Constraint import ( from common.tools.object_factory.Context import json_context_id from common.tools.object_factory.Device import json_device_id from common.tools.object_factory.EndPoint import json_endpoint_id -from common.tools.object_factory.Service import json_service_l2nm_planned, json_service_l3nm_planned +from common.tools.object_factory.Service import json_service_l2nm_planned, json_service_l3nm_planned, json_service_qkd_planned from common.tools.object_factory.Topology import json_topology_id from context.client.ContextClient import ContextClient from device.client.DeviceClient import DeviceClient from service.client.ServiceClient import ServiceClient from webui.service.service.forms import ( AddServiceForm_1, AddServiceForm_ACL_L2, AddServiceForm_ACL_IPV4, AddServiceForm_ACL_IPV6, - AddServiceForm_L2VPN, AddServiceForm_L3VPN + AddServiceForm_L2VPN, AddServiceForm_L3VPN, AddServiceForm_QKD ) LOGGER = logging.getLogger(__name__) @@ -329,10 +329,83 @@ def add_configure(): form_1 = AddServiceForm_1() if form_1.validate_on_submit(): service_type = str(form_1.service_type.data) - if service_type in {'ACL_L2', 'ACL_IPV4', 'ACL_IPV6', 'L2VPN', 'L3VPN'}: + if service_type in {'ACL_L2', 'ACL_IPV4', 'ACL_IPV6', 'L2VPN', 'L3VPN', 'QKD'}: return redirect(url_for('service.add_configure_{:s}'.format(service_type))) return render_template('service/add.html', form_1=form_1, submit_text='Continue to configuraton') +@service.route('add/configure/QKD', methods=['GET', 'POST']) +def add_configure_QKD(): + form_qkd = AddServiceForm_QKD() + service_obj = Service() + + context_uuid, topology_uuid = get_context_and_topology_uuids() + if context_uuid and topology_uuid: + context_client.connect() + grpc_topology = get_topology(context_client, topology_uuid, context_uuid=context_uuid, rw_copy=False) + if grpc_topology: + topo_device_uuids = {device_id.device_uuid.uuid for device_id in grpc_topology.device_ids} + devices = get_filtered_devices(context_client, topo_device_uuids) + grpc_devices = context_client.ListDevices(Empty()) + devices = [ + device for device in grpc_devices.devices + if device.device_id.device_uuid.uuid in topo_device_uuids and DeviceDriverEnum.DEVICEDRIVER_QKD in device.device_drivers + ] + choices = get_device_choices(devices) + add_device_choices_to_form(choices, form_qkd.service_device_1) + add_device_choices_to_form(choices, form_qkd.service_device_2) + else: + flash('Context({:s})/Topology({:s}) not found'.format(str(context_uuid), str(topology_uuid)), 'danger') + else: + flash('Missing context or topology UUID', 'danger') + + if form_qkd.validate_on_submit(): + try: + [selected_device_1, selected_device_2, selected_endpoint_1, selected_endpoint_2] = validate_selected_devices_and_endpoints(form_qkd, devices) + except Exception as e: + flash('{:s}'.format(str(e.args[0])), 'danger') + current_app.logger.exception(e) + return render_template('service/configure_QKD.html', form_qkd=form_qkd, submit_text='Add New Service') + + service_uuid, service_type, endpoint_ids = set_service_parameters(service_obj, form_qkd, selected_device_1, selected_device_2, selected_endpoint_1, selected_endpoint_2) + constraints = add_constraints(form_qkd) + params_device_1_with_data = get_device_params(form_qkd, 1, service_type) + params_device_2_with_data = get_device_params(form_qkd, 2, service_type) + print(params_device_1_with_data) + print(params_device_2_with_data) + params_settings = {} + config_rules = [ + json_config_rule_set( + '/settings', params_settings + ), + json_config_rule_set( + '/device[{:s}]/endpoint[{:s}]/settings'.format(str(selected_device_1.name), str(selected_endpoint_1)), params_device_1_with_data + ), + json_config_rule_set( + '/device[{:s}]/endpoint[{:s}]/settings'.format(str(selected_device_2.name), str(selected_endpoint_2)), params_device_2_with_data + ) + ] + + service_client.connect() + context_client.connect() + device_client.connect() + descriptor_json = json_service_qkd_planned(service_uuid = service_uuid, endpoint_ids = endpoint_ids, constraints = constraints, config_rules = config_rules, context_uuid= context_uuid) + descriptor_json = {"services": [descriptor_json]} + try: + process_descriptors(descriptor_json) + flash('Service "{:s}" added successfully!'.format(service_obj.service_id.service_uuid.uuid), 'success') + return redirect(url_for('service.home', service_uuid=service_obj.service_id.service_uuid.uuid)) + except Exception as e: + flash('Problem adding service: {:s}'.format((str(e.args[0]))), 'danger') + current_app.logger.exception(e) + finally: + context_client.close() + device_client.close() + service_client.close() + + + return render_template('service/configure_QKD.html', form_qkd=form_qkd, submit_text='Add New Service') + + @service.route('add/configure/ACL_L2', methods=['GET', 'POST']) def add_configure_ACL_L2(): form_acl = AddServiceForm_ACL_L2() @@ -666,6 +739,9 @@ def get_device_params(form, device_num, form_type): 'ni_description': str(getattr(form, 'NI_description').data), 'subif_description': str(getattr(form, f'Device_{device_num}_IF_description').data), } + elif form_type == 6: + device_params = { + } else: raise ValueError(f'Unsupported form type: {form_type}') diff --git a/src/webui/service/slice/__init__.py b/src/webui/service/slice/__init__.py index 3ee6f7071f145e06c3aeaefc09a43ccd88e619e3..53d5157f750bfb085125cbd33faff1cec5924e14 100644 --- a/src/webui/service/slice/__init__.py +++ b/src/webui/service/slice/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/webui/service/slice/routes.py b/src/webui/service/slice/routes.py index 588b0a57116268a2571da870bae3fc6470b8e54e..922f8af96dc916f0ca5658e120cdf3dfa4ec9b21 100644 --- a/src/webui/service/slice/routes.py +++ b/src/webui/service/slice/routes.py @@ -1,4 +1,4 @@ -# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# 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. diff --git a/src/webui/service/static/topology_icons/emu-qkd-node.png b/src/webui/service/static/topology_icons/emu-qkd-node.png new file mode 100644 index 0000000000000000000000000000000000000000..d4dc1abaf42a56ff07d1f4a2c5d250b56486584d Binary files /dev/null and b/src/webui/service/static/topology_icons/emu-qkd-node.png differ diff --git a/src/webui/service/static/topology_icons/qkd-node.png b/src/webui/service/static/topology_icons/qkd-node.png new file mode 100644 index 0000000000000000000000000000000000000000..79f40d2a600bd7f9e55d0360a132800c09a8ac85 Binary files /dev/null and b/src/webui/service/static/topology_icons/qkd-node.png differ diff --git a/src/webui/service/templates/base.html b/src/webui/service/templates/base.html index 66e188465994a47f173dcca93237b46cd86adb16..d2eadf121b4857c035f24746787c05a1c9f070be 100644 --- a/src/webui/service/templates/base.html +++ b/src/webui/service/templates/base.html @@ -1,7 +1,7 @@ + + {% extends 'base.html' %} + + {% block content %} +

Optical Configurations

+ + + {% endblock %} diff --git a/src/webui/service/templates/bgpls/add.html b/src/webui/service/templates/bgpls/add.html index f69eee52eb1ee58bf95033fde5009c7b4180da64..5eb527f79ed0e81012b0f00bfe77146b1ca7f1c9 100644 --- a/src/webui/service/templates/bgpls/add.html +++ b/src/webui/service/templates/bgpls/add.html @@ -1,5 +1,5 @@ + +{% extends 'base.html' %} + +{% block content %} + + +

Device {{ device.name }} ({{ device.device_id.device_uuid.uuid }})

+ +
+
+ +
+
+
+ +
+
+
    +
  • ACL +
      + {% set acl_names = [] %} + {% for config in device.device_config.config_rules %} + {% if config.WhichOneof('config_rule') == 'custom' %} + {% if '/acl/' in config.custom.resource_key %} + {% if 'acl-set' in config.custom.resource_key %} + {% set acl_name = config.custom.resource_key.split('acl-set[')[1].split('][')[0] %} + {% else %} + {% set acl_name = config.custom.resource_key.split('ress[')[1].split('][')[0] %} + {% endif %} + {% if acl_name|length == 0 %} + {% set acl_name = 'Undefined' %} + {% endif %} + {% if acl_name not in acl_names %} + {% set _ = acl_names.append(acl_name) %} + {% endif %} + {% endif %} + {% endif %} + {% endfor %} + {% for acl_name in acl_names %} +
    • {{ acl_name }} +
        + {% for config in device.device_config.config_rules %} + {% if config.WhichOneof('config_rule') == 'custom' %} + {% if '/acl/' in config.custom.resource_key and acl_name in config.custom.resource_key.split('][')[0] %} + {% if 'acl-entry' in config.custom.resource_key %} + {% set rule_number = config.custom.resource_key.split('acl-entry[')[1].split(']')[0] %} +
      • Rule {{ rule_number }}: {{ config.custom.resource_value }}
      • + {% else %} +
      • Interface: {{ config.custom.resource_value }}
      • + {% endif %} + {% endif %} + {% endif %} + {% endfor %} +
      +
    • + {% endfor %} +
    +
  • +
+ +
    +
  • Routing Policy +
      + {% set pol_names = [] %} + {% for config in device.device_config.config_rules %} + {% if config.WhichOneof('config_rule') == 'custom' %} + {% if '/routing_policy/' in config.custom.resource_key %} + {% if 'policy_definition' in config.custom.resource_key %} + {% set pol_name = config.custom.resource_key.split('policy_definition[')[1].split(']')[0] %} + {% endif %} + {% if pol_name|length == 0 %} + {% set pol_name = 'Undefined' %} + {% endif %} + {% if pol_name not in pol_names %} + {% set _ = pol_names.append(pol_name) %} + {% endif %} + {% endif %} + {% endif %} + {% endfor %} + {% for pol_name in pol_names %} +
    • {{ pol_name }} +
        + {% for config in device.device_config.config_rules %} + {% if config.WhichOneof('config_rule') == 'custom' %} + {% if '/routing_policy/' in config.custom.resource_key and pol_name in config.custom.resource_key.split('[')[1].split(']')[0] %} + {% if 'policy_definition' not in config.custom.resource_key %} +
      • {{ config.custom.resource_value }}
      • + {% endif %} + {% endif %} + {% endif %} + {% endfor %} +
      +
    • + {% endfor %} +
    +
  • +
+ +
    +
  • VRFs +
      +
    • VRF default +
        + {% for config in device.device_config.config_rules %} + {% if config.WhichOneof('config_rule') == 'custom' %} + {% if '/network_instance' in config.custom.resource_key and config.custom.resource_key.split('[')[1].split(']')[0] in 'default' %} + {% if ']/' in config.custom.resource_key%} + {% set aux = config.custom.resource_key.split(']/')[1].split('[')[0] %} +
      • {{ aux.replace('_', ' ').title() }}: {{ config.custom.resource_value }}
      • + {% else %} +
      • Network Instance: {{ config.custom.resource_value }}
      • + {% endif %} + {% endif %} + {% endif %} + {% endfor %} +
      +
    • + +
    • L3VPN +
        + {% set vpn_names = [] %} + {% for config in device.device_config.config_rules %} + {% if config.WhichOneof('config_rule') == 'custom' %} + {% if '/network_instance' in config.custom.resource_key %} + + {% if 'L3VRF' in config.custom.resource_value %} + {% set vpn_name = config.custom.resource_key.split('network_instance[')[1].split(']')[0] %} + {% if vpn_name not in vpn_names %} + {% set _ = vpn_names.append(vpn_name) %} + {% endif %} + {% endif %} + {% endif %} + {% endif %} + {% endfor %} + {% for vpn_name in vpn_names %} +
      • {{ vpn_name }} +
          + {% for config in device.device_config.config_rules %} + {% if config.WhichOneof('config_rule') == 'custom' %} + {% if '/network_instance' in config.custom.resource_key and config.custom.resource_key.split('[')[1].split(']')[0] in vpn_name %} + {% if ']/' in config.custom.resource_key%} + {% set aux = config.custom.resource_key.split(']/')[1].split('[')[0] %} +
        • {{ aux.replace('_', ' ').title() }}: {{ config.custom.resource_value }}
        • + {% else %} +
        • Network Instance: {{ config.custom.resource_value }}
        • + {% endif %} + {% endif %} + {% endif %} + {% endfor %} +
        +
      • + {% endfor %} +
      +
    • + +
    • L2VPN +
        + {% set vpn_names = [] %} + {% for config in device.device_config.config_rules %} + {% if config.WhichOneof('config_rule') == 'custom' %} + {% if '/network_instance' in config.custom.resource_key %} + + {% if 'L2VSI' in config.custom.resource_value %} + {% set vpn_name = config.custom.resource_key.split('network_instance[')[1].split(']')[0] %} + {% if vpn_name not in vpn_names %} + {% set _ = vpn_names.append(vpn_name) %} + {% endif %} + {% endif %} + {% endif %} + {% endif %} + {% endfor %} + {% for vpn_name in vpn_names %} +
      • {{ vpn_name }} +
          + {% for config in device.device_config.config_rules %} + {% if config.WhichOneof('config_rule') == 'custom' %} + {% if '/network_instance' in config.custom.resource_key and config.custom.resource_key.split('[')[1].split(']')[0] in vpn_name %} + {% if ']/' in config.custom.resource_key%} + {% set aux = config.custom.resource_key.split(']/')[1].split('[')[0] %} +
        • {{ aux.replace('_', ' ').title() }}: {{ config.custom.resource_value }}
        • + {% else %} +
        • Network Instance: {{ config.custom.resource_value }}
        • + {% endif %} + {% endif %} + {% endif %} + {% endfor %} +
        +
      • + {% endfor %} +
      +
    • +
    +
  • +
+ +
    +
  • Interfaces +
      +
    • Logical Interfaces +
        + {% set interface_names = [] %} + {% for config in device.device_config.config_rules %} + {% if config.WhichOneof('config_rule') == 'custom' %} + {% if '/interface[' in config.custom.resource_key %} + {% if 'ethernetCsmacd' in config.custom.resource_value %} + {% set interface_name = config.custom.resource_key.split('interface[')[1].split(']')[0] %} +
      • {{ interface_name}}: {{config.custom.resource_value}}
      • + {% endif %} + {% endif %} + {% endif %} + {% endfor %} +
      +
    • + +
    • Loopback +
        + {% set interface_names = [] %} + {% for config in device.device_config.config_rules %} + {% if config.WhichOneof('config_rule') == 'custom' %} + {% if '/interface[' in config.custom.resource_key %} + {% if 'softwareLoopback' in config.custom.resource_value %} + {% set interface_name = config.custom.resource_key.split('interface[')[1].split(']')[0] %} + {% if interface_name not in interface_names %} + {% set _ = interface_names.append(interface_name) %} + {% endif %} + {% endif %} + {% endif %} + {% endif %} + {% endfor %} + {% for interface_name in interface_names %} +
      • {{ interface_name }} +
          + {% for config in device.device_config.config_rules %} + {% if config.WhichOneof('config_rule') == 'custom' %} + {% if '/interface' in config.custom.resource_key and config.custom.resource_key.split('[')[1].split(']')[0] in interface_name %} + {% if 'subinterface' in config.custom.resource_key %} + {% set subinterface_name = config.custom.resource_key.split('subinterface[')[1].split(']')[0] %} +
        • Subinterface {{subinterface_name}}: {{ config.custom.resource_value }}
        • + {% else %} +
        • {{ config.custom.resource_value }}
        • + {% endif %} + {% endif %} + {% endif %} + {% endfor %} +
        +
      • + {% endfor %} +
      +
    • + +
    • Interfaces L3 +
        + {% set interface_names = [] %} + {% for config in device.device_config.config_rules %} + {% if config.WhichOneof('config_rule') == 'custom' %} + {% if '/interface[' in config.custom.resource_key %} + {% if 'l3ipvlan' in config.custom.resource_value %} + {% set interface_name = config.custom.resource_key.split('interface[')[1].split(']')[0] %} + {% if interface_name not in interface_names %} + {% set _ = interface_names.append(interface_name) %} + {% endif %} + {% endif %} + {% endif %} + {% endif %} + {% endfor %} + {% for interface_name in interface_names %} +
      • {{ interface_name }} +
          + {% for config in device.device_config.config_rules %} + {% if config.WhichOneof('config_rule') == 'custom' %} + {% if '/interface' in config.custom.resource_key and '/subinterface' in config.custom.resource_key and config.custom.resource_key.split('[')[1].split(']')[0] in interface_name %} +
        • {{ config.custom.resource_value }}
        • + {% endif %} + {% endif %} + {% endfor %} +
        +
      • + {% endfor %} +
      +
    • + +
    • Interfaces L2 +
        + {% set interface_names = [] %} + {% for config in device.device_config.config_rules %} + {% if config.WhichOneof('config_rule') == 'custom' %} + {% if '/interface[' in config.custom.resource_key %} + {% if 'l2vlan' in config.custom.resource_value or 'mplsTunnel' in config.custom.resource_value %} + {% set interface_name = config.custom.resource_key.split('interface[')[1].split(']')[0] %} + {% if interface_name not in interface_names %} + {% set _ = interface_names.append(interface_name) %} + {% endif %} + {% endif %} + {% endif %} + {% endif %} + {% endfor %} + {% for interface_name in interface_names %} +
      • {{ interface_name }} +
          + {% for config in device.device_config.config_rules %} + {% if config.WhichOneof('config_rule') == 'custom' %} + {% if 'subinterface' in config.custom.resource_key %} + {% if '/interface' in config.custom.resource_key and '/subinterface' in config.custom.resource_key and config.custom.resource_key.split('[')[1].split(']')[0] in interface_name %} +
        • {{ config.custom.resource_value }}
        • + {% endif %} + {% else %} + {% if '/interface' in config.custom.resource_key and config.custom.resource_key.split('[')[1].split(']')[0] in interface_name %} +
        • {{ config.custom.resource_value }}
        • + {% endif %} + {% endif %} + {% endif %} + {% endfor %} +
        +
      • + {% endfor %} +
      +
    • +
    +
  • +
+ + +
+
+ +{% endblock %} diff --git a/src/webui/service/templates/device/update.html b/src/webui/service/templates/device/update.html index 9f451e117d9a4d37658340d79e0982fd5e0819b6..69b0d203fa6e9a5ea09d09ab4b15e640635cd610 100644 --- a/src/webui/service/templates/device/update.html +++ b/src/webui/service/templates/device/update.html @@ -1,5 +1,5 @@ + +{% extends 'base.html' %} + +{% block content %} +

Link {{ link.name }} ({{ link.link_id.link_uuid.uuid }})

+
+
+ +
+
+ + +
+
+ +
+
+
+ UUID: {{ link.link_id.link_uuid.uuid }}
+ Name: {{ link.name }}
+
+
+ + + + + + + + + + + {% for endpoint in link.link_endpoint_ids %} + + + + + + + {% endfor %} + +
Endpoint UUIDNameDeviceEndpoint Type
+ {{ endpoint.endpoint_uuid.uuid }} + + {{ endpoints_data.get(endpoint.endpoint_uuid.uuid, (endpoint.endpoint_uuid.uuid, ''))[0] }} + + + {{ device_names.get(endpoint.device_id.device_uuid.uuid, endpoint.device_id.device_uuid.uuid) }} + + + + + + + {{ endpoints_data.get(endpoint.endpoint_uuid.uuid, ('', '-'))[1] }} +
+
+
+ + + +Optical Link Detail: + + + + + + + + + {% for field_descriptor, field_value in link.optical_details.ListFields() %} + {% if field_descriptor.name != "c_slots" and field_descriptor.name != "s_slots" and field_descriptor.name != "l_slots" %} + + + + + {%endif%} + {% endfor %} + {%if c_slots %} + + + + + {%endif%} + {%if l_slots %} + + + + + {%endif%} + {%if s_slots %} + + + + + {%endif%} + +
KeyValue
+ {{ field_descriptor.name }} + + {{ field_value }} +
+ c_slots + + {{ c_slots }} +
+ l_slots + + {{ l_slots }} +
+ s_slots + + {{ s_slots }} +
+ + + +{% endblock %} diff --git a/src/webui/service/templates/optical_link/home.html b/src/webui/service/templates/optical_link/home.html new file mode 100644 index 0000000000000000000000000000000000000000..188e1a4946dee7ff3985ab3633df0b096ea15eff --- /dev/null +++ b/src/webui/service/templates/optical_link/home.html @@ -0,0 +1,122 @@ + + +{% extends 'base.html' %} + + {% block content %} +

Optical Links

+ +
+ +
+ {{ links | length }} links found in context {{ session['context_uuid'] }} +
+
+ + +
+ +
+ + + + + + + + + + + + {% if links %} + {% for link in links %} + + + + + + + + + {% endfor %} + {% else %} + + + + {% endif %} + + +
UUIDNameEndpoints
+ {{ link.link_id.link_uuid.uuid }} + + {{ link.name }} + + + + + + + + + +
No links found
+ + + +{% endblock %} diff --git a/src/webui/service/templates/opticalconfig/add_transceiver.html b/src/webui/service/templates/opticalconfig/add_transceiver.html new file mode 100644 index 0000000000000000000000000000000000000000..7e97224a99196304642cb0f5c00a8174c4d26ca8 --- /dev/null +++ b/src/webui/service/templates/opticalconfig/add_transceiver.html @@ -0,0 +1,56 @@ + + +{% extends 'base.html' %} + +{% block content %} +

Add Transceiver

+
+
+ {{ form.hidden_tag() }} +
+
+
+ {{ form.transceiver.label(class="col-sm-2 col-form-label") }} +
+ {% if form.transceiver.errors %} + {{ form.transceiver(class="form-control is-invalid") }} +
+ {% for error in form.transceiver.errors %} + {{ error }} + {% endfor %} +
+ {% else %} + + {{ form.transceiver(class="col-sm-7 form-control") }} + + {% endif %} +
+ +
+ + +
+
+
+ +{% endblock %} diff --git a/src/webui/service/templates/opticalconfig/details.html b/src/webui/service/templates/opticalconfig/details.html new file mode 100644 index 0000000000000000000000000000000000000000..0edb762d3f4e17705370d13da8f4118b00187b0a --- /dev/null +++ b/src/webui/service/templates/opticalconfig/details.html @@ -0,0 +1,168 @@ + + +{% extends 'base.html' %} + +{% block content %} + +

Optical Configurations

+ +
+ {% if device %} +
+ Device ID: +
{{config_id}}
+
+
+
+
+
+ +
+
+ + +
+
+
+
+ Device Name: + {{device_name}} +
+
+ + {% if type == 'optical-transponder' %} + + + + + + + + + + + + + {% for channel in device %} + + + + + + + + + {% endfor %} + +
channel nameFrequencyTarget Output PowerOperational ModeLine PortChannel Status
{{channel.name.index}}{{channel.frequency}}{{channel.targetOutputPower}}{{channel.operationalMode}}{{channel.line_port}}{{channel.status}}
+ {% elif type == 'openroadm' %} + + + + + + + + + + + + + + + {% for channel in device %} + + + + + + + + + + + {% endfor %} + +
name typeadministrative statecircuit pack nameportinterface listfrequencywidth
{{channel.name}}{{channel.type}}{{channel.administrative_state}}{{channel.circuit_pack_name}}{{channel.port}}{{channel.interface_list}}{{channel.frequency}}{{channel.width}}
+ {% else %} + + + + + + + + + + + + + + + + {% for channel in device %} + + + + + + + + + + + + {% endfor %} + +
Channel IndexOptical Band ParentBand NameLower FrequencyUpper FrequencytypeSource PortDestination PortChannel Status
{{channel.channel_index}}{{channel.optical_band_parent}}{{channel.band_name}}{{channel.lower_frequency}}{{channel.upper_frequency}}{{channel.type}}{{channel.src_port}}{{channel.dest_port}}{{channel.status}}
+ {% endif%} +
+ +{% else %} +
+

No devices found

+
+{% endif %} + + + +{% endblock %} diff --git a/src/webui/service/templates/opticalconfig/home.html b/src/webui/service/templates/opticalconfig/home.html new file mode 100644 index 0000000000000000000000000000000000000000..6a6437270e4622684c58c1e59fa1ab760a3e4f46 --- /dev/null +++ b/src/webui/service/templates/opticalconfig/home.html @@ -0,0 +1,113 @@ + + +{% extends 'base.html' %} + +{% block content %} +

Optical Configurations

+ {% if config %} +
+
+
+ +
+ +
+
+ + + +
+
+
+ + + + + + + + + + + + + + + {% for device in config %} + + + + + {% if device.channels_number %} + + {%else%} + + {%endif%} + {% if device.opticalconfig_id %} + + {%endif%} + + {% endfor %} + + +
UUIDDevice NameDevice TypeChannels Number
{{device.opticalconfig_id.opticalconfig_uuid}}{{device.device_name}} {{device.type}}{{ device.channels_number }}__ + + + + + + +
+ +
+ + {% else %} +
+

No devices found

+
+ {% endif %} + + + + + + + +{% endblock %} diff --git a/src/webui/service/templates/opticalconfig/update_interface.html b/src/webui/service/templates/opticalconfig/update_interface.html new file mode 100644 index 0000000000000000000000000000000000000000..af20d08f6cf8e96ec767655ce8dc7327504ffda1 --- /dev/null +++ b/src/webui/service/templates/opticalconfig/update_interface.html @@ -0,0 +1,90 @@ + + +{% extends 'base.html' %} + +{% block content %} +
+ +

Update Device {{ device.opticalconfig_id.opticalconfig_uuid }}

+

interface :{{interface_name}}

+
+
+
+ {{ form.hidden_tag() }} +
+
+
+ {{ form.ip.label(class="col-sm-2 col-form-label") }} +
+ {% if form.ip.errors %} + {{ form.ip(class="form-control is-invalid") }} +
+ {% for error in form.ip.errors %} + {{ error }} + {% endfor %} +
+ {% else %} + + {{ form.ip(class="col-sm-7 form-control") }} + + {% endif %} +
+
+
+ {{ form.prefix_length.label(class="col-sm-2 col-form-label") }} +
+ {% if form.prefix_length.errors %} + {{ form.prefix_length(class="form-control is-invalid") }} +
+ {% for error in form.prefix_length.errors %} + {{ error }} + {% endfor %} +
+ {% else %} + + + {{ form.prefix_length(class="col-sm-7 form-control") }} + + {% endif %} +
+ + +
+
+
+
+
+ + +
+
+ + +
+
+
+ +
+
+ +{% endblock %} diff --git a/src/webui/service/templates/opticalconfig/update_status.html b/src/webui/service/templates/opticalconfig/update_status.html new file mode 100644 index 0000000000000000000000000000000000000000..08111e4846cd6e03d6e835c5e2957307ecc47bdb --- /dev/null +++ b/src/webui/service/templates/opticalconfig/update_status.html @@ -0,0 +1,67 @@ + + +{% extends 'base.html' %} + +{% block content %} +

Update Channel Status

+
+
+ channel : {{channel_name}} +
+
+ {{ form.hidden_tag() }} +
+
+
+ {{ form.status.label(class="col-sm-2 col-form-label") }} +
+ {% if form.status.errors %} + {{ form.status(class="form-control is-invalid") }} +
+ {% for error in form.status.errors %} + {{ error }} + {% endfor %} +
+ {% else %} + + {{ form.status(class="col-sm-7 form-control") }} + + {% endif %} +
+ +
+
+
+ +
+ + +
+
+
+ +
+
+
+ +{% endblock %} diff --git a/src/webui/service/templates/policy_rule/home.html b/src/webui/service/templates/policy_rule/home.html index e28557e819e664be4e5314d86ea5a47fd1ac1681..cbf6a80629a385523ed6e3fa7c9f9c768892b1c4 100644 --- a/src/webui/service/templates/policy_rule/home.html +++ b/src/webui/service/templates/policy_rule/home.html @@ -1,5 +1,5 @@ + +{% extends 'base.html' %} + +{% block content %} +

App {{ app.app_id.app_uuid.uuid }}

+ + +
+
+ +
+
+ +
+
+ + +
+
+ UUID: {{ app.app_id.app_uuid.uuid }}
+ Status: {{ ase.Name(app.app_status).replace('QKDAPPSTATUS_', '') }}
+ Type: {{ ate.Name(app.app_type).replace('QKDAPPTYPES_', '').replace('CLIENT', 'EXTERNAL') }}
+
+ + +
+
Associated Devices
+ + + + + + + + + + + + + {% if app.remote_device_id.device_uuid.uuid %} + + + + + {% endif %} + +
DeviceEndpoint Type
+ + {{ device_names.get(app.local_device_id.device_uuid.uuid, app.local_device_id.device_uuid.uuid) }} + + + + + + + Local Device
+ + {{ device_names.get(app.remote_device_id.device_uuid.uuid, app.remote_device_id.device_uuid.uuid) }} + + + + + + + Remote Device
+
+
+ + +
+
+
App QoS
+ + + + + + + + + + + + + + + + + + + + + + + + + +
QoS ParameterValue
Max Bandwidth{{ app.qos.max_bandwidth }} bps
Min Bandwidth{{ app.qos.min_bandwidth or 'N/A' }} bps
Jitter{{ app.qos.jitter or 'N/A' }} ms
TTL{{ app.qos.ttl or 'N/A' }} seconds
+
+
+ + + + +{% endblock %} diff --git a/src/webui/service/templates/qkd_app/home.html b/src/webui/service/templates/qkd_app/home.html new file mode 100644 index 0000000000000000000000000000000000000000..21e03f2efbcbd513988109050a28e86af5b2961e --- /dev/null +++ b/src/webui/service/templates/qkd_app/home.html @@ -0,0 +1,94 @@ + + +{% extends 'base.html' %} + +{% block content %} +

Apps

+ +
+
+ {{ apps | length }} apps found in context {{ session['context_uuid'] }} +
+
+ + + + + + + + + + + + + + {% if apps %} + {% for app in apps %} + + + + + + + + + {% endfor %} + {% else %} + + + + {% endif %} + +
UUIDStatusTypeDevice 1Device 2
+ {{ app.app_id.app_uuid.uuid }} + + {{ ase.Name(app.app_status).replace('QKDAPPSTATUS_', '') }} + + {{ ate.Name(app.app_type).replace('QKDAPPTYPES_', '').replace('CLIENT', 'EXTERNAL') }} + +
  • + + {{ device_names.get(app.local_device_id.device_uuid.uuid, app.local_device_id.device_uuid.uuid) }} + + + + + +
  • +
    + {% if app.remote_device_id.device_uuid.uuid %} +
  • + + {{ device_names.get(app.remote_device_id.device_uuid.uuid, app.remote_device_id.device_uuid.uuid) }} + + + + + +
  • + {% endif %} +
    + + + + + + +
    No apps found
    + +{% endblock %} diff --git a/src/webui/service/templates/service/add-xr.html b/src/webui/service/templates/service/add-xr.html index fcf7cbf3d58dd3709b84fa7b4483fe270d03fb01..e6f59580694aecb6c1d716476850899d7c2ddb3e 100644 --- a/src/webui/service/templates/service/add-xr.html +++ b/src/webui/service/templates/service/add-xr.html @@ -1,5 +1,5 @@ + +{% extends 'base.html' %} + +{% block content %} +

    Add New Service [QKD]

    +
    +
    +
    + {{ form_qkd.hidden_tag() }} +
    +

    Generic Service Parameters

    + {% if form_qkd.qkd_params is not none %} +
    + {{ form_qkd.service_name.label(class="col-sm-2 col-form-label") }} +
    + {% if form_qkd.service_name.errors %} + {{ form_qkd.service_name(class="form-control is-invalid", placeholder="Mandatory") }} +
    + {% for error in form_qkd.service_name.errors %} + {{ error }} + {% endfor %} +
    + {% else %} + {{ form_qkd.service_name(class="form-control", placeholder="Mandatory") }} + {% endif %} +
    +
    +
    + {{ form_qkd.service_type.label(class="col-sm-2 col-form-label") }} +
    + {% if form_qkd.service_type.errors %} + {{ form_qkd.service_type(class="form-control is-invalid", placeholder="Mandatory") }} +
    + {% for error in form_qkd.service_type.errors %} + {{ error }} + {% endfor %} +
    + {% else %} + {{ form_qkd.service_type(class="form-control", placeholder="Mandatory") }} + {% endif %} +
    +
    +
    + {{ form_qkd.service_device_1.label(class="col-sm-2 col-form-label") }} +
    + {% if form_qkd.service_device_1.errors %} + {{ form_qkd.service_device_1(class="form-control is-invalid", placeholder="Mandatory") }} +
    + {% for error in form_qkd.service_device_1.errors %} + {{ error }} + {% endfor %} +
    + {% else %} + {{ form_qkd.service_device_1(class="form-control", placeholder="Mandatory") }} + {% endif %} +
    + {{ form_qkd.service_device_2.label(class="col-sm-2 col-form-label") }} +
    + {% if form_qkd.service_device_2.errors %} + {{ form_qkd.service_device_2(class="form-control is-invalid", placeholder="Mandatory") }} +
    + {% for error in form_qkd.service_device_2.errors %} + {{ error }} + {% endfor %} +
    + {% else %} + {{ form_qkd.service_device_2(class="form-control", placeholder="Mandatory") }} + {% endif %} +
    +
    +
    + {{ form_qkd.service_endpoint_1.label(class="col-sm-2 col-form-label") }} +
    + {% if form_qkd.service_endpoint_1.errors %} + {{ form_qkd.service_endpoint_1(class="form-control is-invalid", placeholder="Mandatory") }} +
    + {% for error in form_qkd.service_endpoint_1.errors %} + {{ error }} + {% endfor %} +
    + {% else %} + {{ form_qkd.service_endpoint_1(class="form-control", placeholder="Mandatory") }} + {% endif %} +
    + {{ form_qkd.service_endpoint_2.label(class="col-sm-2 col-form-label") }} +
    + {% if form_qkd.service_endpoint_2.errors %} + {{ form_qkd.service_endpoint_2(class="form-control is-invalid", placeholder="Mandatory") }} +
    + {% for error in form_qkd.service_endpoint_2.errors %} + {{ error }} + {% endfor %} +
    + {% else %} + {{ form_qkd.service_endpoint_2(class="form-control", placeholder="Mandatory") }} + {% endif %} +
    +
    +
    +

    Generic Service Constraints

    +
    + {{ form_qkd.service_capacity.label(class="col-sm-2 col-form-label") }} +
    + {% if form_qkd.service_capacity.errors %} + {{ form_qkd.service_capacity(class="form-control is-invalid") }} +
    + {% for error in form_qkd.service_capacity.errors %} + {{ error }} + {% endfor %} +
    + {% else %} + {{ form_qkd.service_capacity(class="form-control") }} + {% endif %} +
    +
    +
    + {{ form_qkd.service_latency.label(class="col-sm-2 col-form-label") }} +
    + {% if form_qkd.service_latency.errors %} + {{ form_qkd.service_latency(class="form-control is-invalid") }} +
    + {% for error in form_qkd.service_latency.errors %} + {{ error }} + {% endfor %} +
    + {% else %} + {{ form_qkd.service_latency(class="form-control") }} + {% endif %} +
    +
    +
    + {{ form_qkd.service_availability.label(class="col-sm-2 col-form-label") }} +
    + {% if form_qkd.service_availability.errors %} + {{ form_qkd.service_availability(class="form-control is-invalid") }} +
    + {% for error in form_qkd.service_availability.errors %} + {{ error }} + {% endfor %} +
    + {% else %} + {{ form_qkd.service_availability(class="form-control") }} + {% endif %} +
    +
    +
    + {{ form_qkd.service_isolation.label(class="col-sm-2 col-form-label") }} +
    + {% if form_qkd.service_isolation.errors %} + {{ form_qkd.service_isolation(class="form-control is-invalid") }} +
    + {% for error in form_qkd.service_isolation.errors %} + {{ error }} + {% endfor %} +
    + {% else %} + {{ form_qkd.service_isolation(class="form-control") }} + {% endif %} +
    +
    + {% endif %} + + +
    +
    + {% endblock %} + diff --git a/src/webui/service/templates/service/detail.html b/src/webui/service/templates/service/detail.html index d97c26db95e975e579a003e9bbd593cc46074fcc..e8dfa618abc9e83551608fafce849c04a9a19487 100644 --- a/src/webui/service/templates/service/detail.html +++ b/src/webui/service/templates/service/detail.html @@ -1,5 +1,5 @@