diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 1415782872cbc7726a9f7a3c182cabe4803ab6f9..2d7c2e21b73bdbca167f56b42ccdab1a5d374afc 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -17,10 +17,9 @@ stages:
   #- dependencies
   - build
   - unit_test
-  #- deploy
-  #- end2end_test
+  - end2end_test
 
-# include the individual .gitlab-ci.yml of each micro-service
+# include the individual .gitlab-ci.yml of each micro-service and tests
 include:
   #- local: '/manifests/.gitlab-ci.yml'
   - local: '/src/monitoring/.gitlab-ci.yml'
@@ -31,7 +30,8 @@ include:
   - local: '/src/dbscanserving/.gitlab-ci.yml'
   - local: '/src/opticalattackmitigator/.gitlab-ci.yml'
   - local: '/src/opticalattackdetector/.gitlab-ci.yml'
-  #- local: '/src/opticalattackmanager/.gitlab-ci.yml'
+  - local: '/src/opticalattackmanager/.gitlab-ci.yml'
+  - local: '/src/opticalcontroller/.gitlab-ci.yml'
   - local: '/src/ztp/.gitlab-ci.yml'
   - local: '/src/policy/.gitlab-ci.yml'
   - local: '/src/forecaster/.gitlab-ci.yml'
@@ -45,3 +45,6 @@ include:
   #- local: '/src/dlt/.gitlab-ci.yml'
   - local: '/src/load_generator/.gitlab-ci.yml'
   - local: '/src/bgpls_speaker/.gitlab-ci.yml'
+
+  # This should be last one: end-to-end integration tests
+  - local: '/src/tests/.gitlab-ci.yml'
diff --git a/README.md b/README.md
index 5bfb6d70d947f631e8694b3dcf6c872cf1248ea4..8825795b864938af9fd2eb67e181c719ee9fbd26 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,25 @@
 # ETSI TeraFlowSDN Controller
 
-[ETSI OpenSource Group for TeraFlowSDN](https://tfs.etsi.org/)
+The [ETSI Software Development Group TeraFlowSDN (SDG TFS)](https://tfs.etsi.org/) is developing an open source cloud native SDN controller enabling smart connectivity services for future networks beyond 5G.
 
-Former, [Teraflow H2020 project](https://teraflow-h2020.eu/) - Secured autonomic traffic management for a Tera of SDN Flows
+The project originated from "[Teraflow H2020 project](https://teraflow-h2020.eu/) - Secured autonomic traffic management for a Tera of SDN Flows", a project funded by the European Union’s Horizon 2020 Research and Innovation programme that finished on 30th June 2023.
 
-Branch "master" : [![pipeline status](https://labs.etsi.org/rep/tfs/controller/badges/master/pipeline.svg)](https://labs.etsi.org/rep/tfs/controller/-/commits/master) [![coverage report](https://labs.etsi.org/rep/tfs/controller/badges/master/coverage.svg)](https://labs.etsi.org/rep/tfs/controller/-/commits/master)
 
-Branch "develop" : [![pipeline status](https://labs.etsi.org/rep/tfs/controller/badges/develop/pipeline.svg)](https://labs.etsi.org/rep/tfs/controller/-/commits/develop) [![coverage report](https://labs.etsi.org/rep/tfs/controller/badges/develop/coverage.svg)](https://labs.etsi.org/rep/tfs/controller/-/commits/develop)
+## Available branches and releases
 
-# Installation Instructions and Functional Tests
-The [TeraFlowSDN Wiki](https://labs.etsi.org/rep/tfs/controller/-/wikis/home) pages include details on using the ETSI TeraFlowSDN release 2.0.
+[![Latest Release](https://labs.etsi.org/rep/tfs/controller/-/badges/release.svg)](https://labs.etsi.org/rep/tfs/controller/-/releases)
 
-The documentation, installation instructions, and description of the functional tests defined to enable experimentation with the ETSI TeraFlowSDN Controller can be found in the Wiki pages
+- The branch `master` ([![pipeline status](https://labs.etsi.org/rep/tfs/controller/badges/master/pipeline.svg)](https://labs.etsi.org/rep/tfs/controller/-/commits/master) [![coverage report](https://labs.etsi.org/rep/tfs/controller/badges/master/coverage.svg)](https://labs.etsi.org/rep/tfs/controller/-/commits/master)), points always to the latest stable version of the TeraFlowSDN controller.
+
+- The branches `release/X.Y.Z`, point to the code for the different release versions indicated in the branch name.
+  - Code in these branches can be considered stable, and no new features are planned.
+  - In case of bugs, point releases increasing revision number (Z) might be created.
+
+- The `develop` ([![pipeline status](https://labs.etsi.org/rep/tfs/controller/badges/develop/pipeline.svg)](https://labs.etsi.org/rep/tfs/controller/-/commits/develop) [![coverage report](https://labs.etsi.org/rep/tfs/controller/badges/develop/coverage.svg)](https://labs.etsi.org/rep/tfs/controller/-/commits/develop)) branch is the main development branch and contains the latest contributions.
+  - **Use it with care! It might not be stable.**
+  - The latest developments and contributions are added to this branch for testing and validation before reaching a release.
+
+
+## Documentation
+The [TeraFlowSDN Wiki](https://labs.etsi.org/rep/tfs/controller/-/wikis/home) pages include the main documentation for the ETSI TeraFlowSDN Controller.
+The documentation includes project documentation, installation instructions, functional tests, supported NBIs and SBIs, etc.
diff --git a/deploy/component.sh b/deploy/component.sh
index e2648818684f672c41cca19a7ac1281b797f4382..d3a94c25911cfb7200e6eef3c5bae260de6fb785 100755
--- a/deploy/component.sh
+++ b/deploy/component.sh
@@ -40,6 +40,21 @@ export TFS_GRAFANA_PASSWORD=${TFS_GRAFANA_PASSWORD:-"admin123+"}
 # Automated steps start here
 ########################################################################################################################
 
+DOCKER_BUILD="docker build"
+DOCKER_MAJOR_VERSION=$(docker --version | grep -o -E "Docker version [0-9]+\." | grep -o -E "[0-9]+" | cut -c 1-3)
+if [[ $DOCKER_MAJOR_VERSION -ge 23 ]]; then
+    # If Docker version >= 23, build command was migrated to docker-buildx
+    # In Ubuntu, in practice, means to install package docker-buildx together with docker.io
+    # Check if docker-buildx plugin is installed
+    docker buildx version 1>/dev/null 2>/dev/null
+    if [[ $? -ne 0 ]]; then
+        echo "Docker buildx command is not installed. Check: https://docs.docker.com/build/architecture/#install-buildx"
+        echo "If you installed docker through APT package docker.io, consider installing also package docker-buildx"
+        exit 1;
+    fi
+    DOCKER_BUILD="docker buildx build"
+fi
+
 # Constants
 GITLAB_REPO_URL="labs.etsi.org:5050/tfs/controller"
 TMP_FOLDER="./tmp"
@@ -60,17 +75,17 @@ for COMPONENT in $TFS_COMPONENTS; do
     BUILD_LOG="$TMP_LOGS_FOLDER/build_${COMPONENT}.log"
 
     if [ "$COMPONENT" == "ztp" ] || [ "$COMPONENT" == "policy" ]; then
-        docker build -t "$IMAGE_NAME" -f ./src/"$COMPONENT"/Dockerfile ./src/"$COMPONENT"/ > "$BUILD_LOG"
+        $DOCKER_BUILD -t "$IMAGE_NAME" -f ./src/"$COMPONENT"/Dockerfile ./src/"$COMPONENT"/ > "$BUILD_LOG"
     elif [ "$COMPONENT" == "pathcomp" ]; 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"
+        $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"
+        $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
-        docker build -t "$COMPONENT-backend:$TFS_IMAGE_TAG-builder" --target builder -f ./src/"$COMPONENT"/backend/Dockerfile . >> "$BUILD_LOG"
+        $DOCKER_BUILD -t "$COMPONENT-backend:$TFS_IMAGE_TAG-builder" --target builder -f ./src/"$COMPONENT"/backend/Dockerfile . >> "$BUILD_LOG"
     else
-        docker build -t "$IMAGE_NAME" -f ./src/"$COMPONENT"/Dockerfile . > "$BUILD_LOG"
+        $DOCKER_BUILD -t "$IMAGE_NAME" -f ./src/"$COMPONENT"/Dockerfile . > "$BUILD_LOG"
     fi
 
     if [ -n "$TFS_REGISTRY_IMAGES" ]; then
diff --git a/deploy/crdb.sh b/deploy/crdb.sh
index 5d87adf60bbb3303e9abe9cc17c4a68cbe295370..a304e83d16b63f121cec147d8d1135cfa915c2c3 100755
--- a/deploy/crdb.sh
+++ b/deploy/crdb.sh
@@ -158,9 +158,19 @@ function crdb_undeploy_single() {
 
 function crdb_drop_database_single() {
     echo "Drop database if exists"
-    CRDB_PORT_SQL=$(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_SQL}/defaultdb?sslmode=require"
-    kubectl exec -it --namespace ${CRDB_NAMESPACE} cockroachdb-0 -- \
+
+    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
+
+    CRDB_CLIENT_URL="postgresql://${CRDB_USERNAME}:${CRDB_PASSWORD}@${CRDB_HOST}:${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};"
     echo
@@ -343,7 +353,7 @@ function crdb_undeploy_cluster() {
 
 function crdb_drop_database_cluster() {
     echo "Drop database if exists"
-    kubectl exec -it --namespace ${CRDB_NAMESPACE} cockroachdb-client-secure -- \
+    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};"
     echo
diff --git a/deploy/mock_blockchain.sh b/deploy/mock_blockchain.sh
index 74d62cd526a38298c8f197fedf0c0169dbb8efca..df8496beab3798053785233b5d4e13240dbc428a 100755
--- a/deploy/mock_blockchain.sh
+++ b/deploy/mock_blockchain.sh
@@ -58,9 +58,24 @@ echo "Processing '$COMPONENT' component..."
 IMAGE_NAME="$COMPONENT:$IMAGE_TAG"
 IMAGE_URL=$(echo "$REGISTRY_IMAGE/$IMAGE_NAME" | sed 's,//,/,g' | sed 's,http:/,,g')
 
+DOCKER_BUILD="docker build"
+DOCKER_MAJOR_VERSION=$(docker --version | grep -o -E "Docker version [0-9]+\." | grep -o -E "[0-9]+" | cut -c 1-3)
+if [[ $DOCKER_MAJOR_VERSION -ge 23 ]]; then
+    # If Docker version >= 23, build command was migrated to docker-buildx
+    # In Ubuntu, in practice, means to install package docker-buildx together with docker.io
+    # Check if docker-buildx plugin is installed
+    docker buildx version 1>/dev/null 2>/dev/null
+    if [[ $? -ne 0 ]]; then
+        echo "Docker buildx command is not installed. Check: https://docs.docker.com/build/architecture/#install-buildx"
+        echo "If you installed docker through APT package docker.io, consider installing also package docker-buildx"
+        exit 1;
+    fi
+    DOCKER_BUILD="docker buildx build"
+fi
+
 echo "  Building Docker image..."
 BUILD_LOG="$TMP_LOGS_FOLDER/build_${COMPONENT}.log"
-docker build -t "$IMAGE_NAME" -f ./src/dlt/mock_blockchain/Dockerfile . > "$BUILD_LOG"
+$DOCKER_BUILD -t "$IMAGE_NAME" -f ./src/dlt/mock_blockchain/Dockerfile . > "$BUILD_LOG"
 
 if [ -n "$REGISTRY_IMAGE" ]; then
     echo "  Pushing Docker image to '$REGISTRY_IMAGE'..."
diff --git a/deploy/qdb.sh b/deploy/qdb.sh
index e930b5a6cfdba8897ec138e97e3115da8917554f..3235c6c824792d945f78f378e12728b10e621cb3 100755
--- a/deploy/qdb.sh
+++ b/deploy/qdb.sh
@@ -160,10 +160,17 @@ function qdb_undeploy() {
 }
 
 function qdb_drop_tables() {
-    QDB_HOST=$(kubectl --namespace ${QDB_NAMESPACE} get service questdb-public -o 'jsonpath={.spec.clusterIP}')
-    QDB_PORT=$(kubectl --namespace ${QDB_NAMESPACE} get service questdb-public -o 'jsonpath={.spec.ports[?(@.name=="http")].port}')
-
     echo "Drop tables, if exist"
+
+    if [[ -z "${GITLAB_CI}" ]]; then
+        #kubectl --namespace ${QDB_NAMESPACE} get service questdb-public -o yaml
+        QDB_HOST=$(kubectl --namespace ${QDB_NAMESPACE} get service questdb-public -o 'jsonpath={.spec.clusterIP}')
+        QDB_PORT=$(kubectl --namespace ${QDB_NAMESPACE} get service questdb-public -o 'jsonpath={.spec.ports[?(@.name=="http")].port}')
+    else
+        QDB_HOST="127.0.0.1"
+        QDB_PORT=${QDB_EXT_PORT_HTTP}
+    fi
+
     curl "http://${QDB_HOST}:${QDB_PORT}/exec?fmt=json&query=DROP+TABLE+IF+EXISTS+${QDB_TABLE_MONITORING_KPIS}+;"
     echo
     curl "http://${QDB_HOST}:${QDB_PORT}/exec?fmt=json&query=DROP+TABLE+IF+EXISTS+${QDB_TABLE_SLICE_GROUPS}+;"
diff --git a/deploy/tfs.sh b/deploy/tfs.sh
index 19c0d75a095bc5dc239d1d95237378bcf2fbb8da..fd49c975844e49b3ba88f51b046700feaf8edc27 100755
--- a/deploy/tfs.sh
+++ b/deploy/tfs.sh
@@ -299,8 +299,13 @@ 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
-        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)
+        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"
     fi
 
@@ -365,6 +370,12 @@ for COMPONENT in $TFS_COMPONENTS; do
     COMPONENT_OBJNAME=$(echo "${COMPONENT}" | sed "s/\_/-/")
     kubectl wait --namespace $TFS_K8S_NAMESPACE \
         --for='condition=available' --timeout=90s deployment/${COMPONENT_OBJNAME}service
+    WAIT_EXIT_CODE=$?
+    if [[ $WAIT_EXIT_CODE != 0 ]]; then
+        echo "  Failed to deploy '${COMPONENT}' component, exit code '${WAIT_EXIT_CODE}', exiting..."
+        kubectl logs --namespace $TFS_K8S_NAMESPACE deployment/${COMPONENT_OBJNAME}service --all-containers=true
+        exit $WAIT_EXIT_CODE
+    fi
     printf "\n"
 done
 
diff --git a/manifests/bgpls_speakerservice.yaml b/manifests/bgpls_speakerservice.yaml
index aa985d13ea81ad5f5aafdee4b62ca1c54915e527..bda0d4cf5e8734ebf7a1aab95179d39fd7a3d908 100644
--- a/manifests/bgpls_speakerservice.yaml
+++ b/manifests/bgpls_speakerservice.yaml
@@ -28,28 +28,28 @@ spec:
     spec:
       terminationGracePeriodSeconds: 5
       containers:
-      - name: server
-        image: localhost:32000/tfs/bgpls_speaker:dev
-        imagePullPolicy: Always
-        ports:
-        - containerPort: 20030
-        - containerPort: 9192
-        env:
-        - name: LOG_LEVEL
-          value: "INFO"
-        readinessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:20030"]
-        livenessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:20030"]
-        resources:
-          requests:
-            cpu: 250m
-            memory: 128Mi
-          limits:
-            cpu: 1000m
-            memory: 1024Mi
+        - name: server
+          image: localhost:32000/tfs/bgpls_speaker:dev
+          imagePullPolicy: Always
+          ports:
+            - containerPort: 20030
+            - containerPort: 9192
+          env:
+            - name: LOG_LEVEL
+              value: "INFO"
+          readinessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:20030"]
+          livenessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:20030"]
+          resources:
+            requests:
+              cpu: 250m
+              memory: 128Mi
+            limits:
+              cpu: 1000m
+              memory: 1024Mi
 ---
 apiVersion: v1
 kind: Service
@@ -62,11 +62,11 @@ spec:
   selector:
     app: bgpls-speakerservice
   ports:
-  - name: grpc
-    protocol: TCP
-    port: 20030
-    targetPort: 20030
-  - name: metrics
-    protocol: TCP
-    port: 9192
-    targetPort: 9192
+    - name: grpc
+      protocol: TCP
+      port: 20030
+      targetPort: 20030
+    - name: metrics
+      protocol: TCP
+      port: 9192
+      targetPort: 9192
diff --git a/manifests/cachingservice.yaml b/manifests/cachingservice.yaml
index be8fced491a823aace2b7e06be3aad1f6114d245..ee6e02e00b1ee655511a941d99b1198c1f827868 100644
--- a/manifests/cachingservice.yaml
+++ b/manifests/cachingservice.yaml
@@ -27,28 +27,28 @@ spec:
         app: cachingservice
     spec:
       containers:
-      - name: redis
-        image: redis:7.0-alpine
-        env:
-        - name: REDIS_PASSWORD
-          valueFrom:
-            secretKeyRef:
-              name: redis-secrets
-              key: REDIS_PASSWORD
-        ports:
-        - containerPort: 6379
-          name: client
-        command: ["redis-server"]
-        args:
-        - --requirepass
-        - $(REDIS_PASSWORD)
-        resources:
-          requests:
-            cpu: 50m
-            memory: 64Mi
-          limits:
-            cpu: 500m
-            memory: 512Mi
+        - name: redis
+          image: redis:7.0-alpine
+          env:
+            - name: REDIS_PASSWORD
+              valueFrom:
+                secretKeyRef:
+                  name: redis-secrets
+                  key: REDIS_PASSWORD
+          ports:
+            - containerPort: 6379
+              name: client
+          command: ["redis-server"]
+          args:
+            - --requirepass
+            - $(REDIS_PASSWORD)
+          resources:
+            requests:
+              cpu: 50m
+              memory: 64Mi
+            limits:
+              cpu: 500m
+              memory: 512Mi
 ---
 apiVersion: v1
 kind: Service
@@ -59,6 +59,6 @@ spec:
   selector:
     app: cachingservice
   ports:
-  - name: redis
-    port: 6379
-    targetPort: 6379
+    - name: redis
+      port: 6379
+      targetPort: 6379
diff --git a/manifests/contextservice.yaml b/manifests/contextservice.yaml
index df06c86b58849762277f5d99788e36b1933e9a69..c7dc59625289027e9881d99e1bf34ca2bdd622a9 100644
--- a/manifests/contextservice.yaml
+++ b/manifests/contextservice.yaml
@@ -30,39 +30,39 @@ spec:
     spec:
       terminationGracePeriodSeconds: 5
       containers:
-      - name: server
-        image: labs.etsi.org:5050/tfs/controller/context:latest
-        imagePullPolicy: Always
-        ports:
-        - containerPort: 1010
-        - containerPort: 9192
-        env:
-        - name: MB_BACKEND
-          value: "nats"
-        - name: LOG_LEVEL
-          value: "INFO"
-        - name: ALLOW_EXPLICIT_ADD_DEVICE_TO_TOPOLOGY
-          value: "FALSE"
-        - name: ALLOW_EXPLICIT_ADD_LINK_TO_TOPOLOGY
-          value: "FALSE"
-        envFrom:
-        - secretRef:
-            name: crdb-data
-        - secretRef:
-            name: nats-data
-        readinessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:1010"]
-        livenessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:1010"]
-        resources:
-          requests:
-            cpu: 250m
-            memory: 128Mi
-          limits:
-            cpu: 1000m
-            memory: 1024Mi
+        - name: server
+          image: labs.etsi.org:5050/tfs/controller/context:latest
+          imagePullPolicy: Always
+          ports:
+            - containerPort: 1010
+            - containerPort: 9192
+          env:
+            - name: MB_BACKEND
+              value: "nats"
+            - name: LOG_LEVEL
+              value: "INFO"
+            - name: ALLOW_EXPLICIT_ADD_DEVICE_TO_TOPOLOGY
+              value: "FALSE"
+            - name: ALLOW_EXPLICIT_ADD_LINK_TO_TOPOLOGY
+              value: "FALSE"
+          envFrom:
+            - secretRef:
+                name: crdb-data
+            - secretRef:
+                name: nats-data
+          readinessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:1010"]
+          livenessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:1010"]
+          resources:
+            requests:
+              cpu: 250m
+              memory: 128Mi
+            limits:
+              cpu: 1000m
+              memory: 1024Mi
 ---
 apiVersion: v1
 kind: Service
@@ -75,14 +75,14 @@ spec:
   selector:
     app: contextservice
   ports:
-  - name: grpc
-    protocol: TCP
-    port: 1010
-    targetPort: 1010
-  - name: metrics
-    protocol: TCP
-    port: 9192
-    targetPort: 9192
+    - name: grpc
+      protocol: TCP
+      port: 1010
+      targetPort: 1010
+    - name: metrics
+      protocol: TCP
+      port: 9192
+      targetPort: 9192
 ---
 apiVersion: autoscaling/v2
 kind: HorizontalPodAutoscaler
@@ -96,12 +96,12 @@ spec:
   minReplicas: 1
   maxReplicas: 20
   metrics:
-  - type: Resource
-    resource:
-      name: cpu
-      target:
-        type: Utilization
-        averageUtilization: 80
+    - type: Resource
+      resource:
+        name: cpu
+        target:
+          type: Utilization
+          averageUtilization: 80
   #behavior:
   #  scaleDown:
   #    stabilizationWindowSeconds: 30
diff --git a/manifests/dbscanservingservice.yaml b/manifests/dbscanservingservice.yaml
index b5b8fc437a9b7f47f92defdbc96ee71a56715316..2bdd1c3faad870f5646c456f815ae790642df45b 100644
--- a/manifests/dbscanservingservice.yaml
+++ b/manifests/dbscanservingservice.yaml
@@ -27,28 +27,28 @@ spec:
     spec:
       terminationGracePeriodSeconds: 5
       containers:
-      - name: server
-        image: labs.etsi.org:5050/tfs/controller/dbscanserving:latest
-        imagePullPolicy: Always
-        ports:
-        - containerPort: 10008
-        - containerPort: 9192
-        env:
-        - name: LOG_LEVEL
-          value: "INFO"
-        readinessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:10008"]
-        livenessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:10008"]
-        resources:
-          requests:
-            cpu: 250m
-            memory: 128Mi
-          limits:
-            cpu: 1000m
-            memory: 1024Mi
+        - name: server
+          image: labs.etsi.org:5050/tfs/controller/dbscanserving:latest
+          imagePullPolicy: Always
+          ports:
+            - containerPort: 10008
+            - containerPort: 9192
+          env:
+            - name: LOG_LEVEL
+              value: "INFO"
+          readinessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:10008"]
+          livenessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:10008"]
+          resources:
+            requests:
+              cpu: 250m
+              memory: 128Mi
+            limits:
+              cpu: 1000m
+              memory: 1024Mi
 ---
 apiVersion: v1
 kind: Service
@@ -61,12 +61,12 @@ spec:
   selector:
     app: dbscanservingservice
   ports:
-  - name: grpc
-    port: 10008
-    targetPort: 10008
-  - name: metrics
-    port: 9192
-    targetPort: 9192
+    - name: grpc
+      port: 10008
+      targetPort: 10008
+    - name: metrics
+      port: 9192
+      targetPort: 9192
 ---
 apiVersion: autoscaling/v2
 kind: HorizontalPodAutoscaler
@@ -80,12 +80,12 @@ spec:
   minReplicas: 1
   maxReplicas: 20
   metrics:
-  - type: Resource
-    resource:
-      name: cpu
-      target:
-        type: Utilization
-        averageUtilization: 80
+    - type: Resource
+      resource:
+        name: cpu
+        target:
+          type: Utilization
+          averageUtilization: 80
   #behavior:
   #  scaleDown:
   #    stabilizationWindowSeconds: 30
diff --git a/manifests/deviceservice.yaml b/manifests/deviceservice.yaml
index 77e421f297fefc8979b9cd6e3415c58be611a53a..fdc3cea028a181b7dafbcfa6f3ef4e798939438e 100644
--- a/manifests/deviceservice.yaml
+++ b/manifests/deviceservice.yaml
@@ -31,33 +31,33 @@ spec:
     spec:
       terminationGracePeriodSeconds: 5
       containers:
-      - name: server
-        image: labs.etsi.org:5050/tfs/controller/device:latest
-        imagePullPolicy: Always
-        ports:
-        - containerPort: 2020
-        - containerPort: 9192
-        env:
-        - name: LOG_LEVEL
-          value: "INFO"
-        startupProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:2020"]
-          failureThreshold: 30
-          periodSeconds: 1
-        readinessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:2020"]
-        livenessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:2020"]
-        resources:
-          requests:
-            cpu: 250m
-            memory: 128Mi
-          limits:
-            cpu: 1000m
-            memory: 1024Mi
+        - name: server
+          image: labs.etsi.org:5050/tfs/controller/device:latest
+          imagePullPolicy: Always
+          ports:
+            - containerPort: 2020
+            - containerPort: 9192
+          env:
+            - name: LOG_LEVEL
+              value: "INFO"
+          startupProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:2020"]
+            failureThreshold: 30
+            periodSeconds: 1
+          readinessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:2020"]
+          livenessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:2020"]
+          resources:
+            requests:
+              cpu: 250m
+              memory: 128Mi
+            limits:
+              cpu: 1000m
+              memory: 1024Mi
 ---
 apiVersion: v1
 kind: Service
@@ -70,11 +70,11 @@ spec:
   selector:
     app: deviceservice
   ports:
-  - name: grpc
-    protocol: TCP
-    port: 2020
-    targetPort: 2020
-  - name: metrics
-    protocol: TCP
-    port: 9192
-    targetPort: 9192
+    - name: grpc
+      protocol: TCP
+      port: 2020
+      targetPort: 2020
+    - name: metrics
+      protocol: TCP
+      port: 9192
+      targetPort: 9192
diff --git a/manifests/dltservice.yaml b/manifests/dltservice.yaml
index 5e8f745f78b14ea4f8881b8992ef788ce89fdcc2..f905749b444e821fce36d88fa24259d4ce03237b 100644
--- a/manifests/dltservice.yaml
+++ b/manifests/dltservice.yaml
@@ -27,57 +27,57 @@ spec:
     spec:
       terminationGracePeriodSeconds: 5
       containers:
-      - name: connector
-        image: labs.etsi.org:5050/tfs/controller/dlt-connector:latest
-        imagePullPolicy: Always
-        ports:
-        - containerPort: 8080
-        - containerPort: 9192
-        env:
-        - name: LOG_LEVEL
-          value: "INFO"
-        ## for debug purposes
-        #- name: DLT_GATEWAY_HOST
-        #  value: "mock-blockchain.tfs-bchain.svc.cluster.local"
-        #- name: DLT_GATEWAY_PORT
-        #  value: "50051"
-        readinessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:8080"]
-        livenessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:8080"]
-        resources:
-          requests:
-            cpu: 50m
-            memory: 64Mi
-          limits:
-            cpu: 500m
-            memory: 512Mi
-      - name: gateway
-        image: labs.etsi.org:5050/tfs/controller/dlt-gateway:latest
-        imagePullPolicy: Always
-        ports:
-        - containerPort: 50051
-        #readinessProbe:
-        #  httpGet:
-        #    path: /health
-        #    port: 8081
-        #  initialDelaySeconds: 5
-        #  timeoutSeconds: 5
-        #livenessProbe:
-        #  httpGet:
-        #    path: /health
-        #    port: 8081
-        #  initialDelaySeconds: 5
-        #  timeoutSeconds: 5
-        resources:
-          requests:
-            cpu: 200m
-            memory: 512Mi
-          limits:
-            cpu: 700m
-            memory: 1024Mi
+        - name: connector
+          image: labs.etsi.org:5050/tfs/controller/dlt-connector:latest
+          imagePullPolicy: Always
+          ports:
+            - containerPort: 8080
+            - containerPort: 9192
+          env:
+            - name: LOG_LEVEL
+              value: "INFO"
+          ## for debug purposes
+          #- name: DLT_GATEWAY_HOST
+          #  value: "mock-blockchain.tfs-bchain.svc.cluster.local"
+          #- name: DLT_GATEWAY_PORT
+          #  value: "50051"
+          readinessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:8080"]
+          livenessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:8080"]
+          resources:
+            requests:
+              cpu: 50m
+              memory: 64Mi
+            limits:
+              cpu: 500m
+              memory: 512Mi
+        - name: gateway
+          image: labs.etsi.org:5050/tfs/controller/dlt-gateway:latest
+          imagePullPolicy: Always
+          ports:
+            - containerPort: 50051
+          #readinessProbe:
+          #  httpGet:
+          #    path: /health
+          #    port: 8081
+          #  initialDelaySeconds: 5
+          #  timeoutSeconds: 5
+          #livenessProbe:
+          #  httpGet:
+          #    path: /health
+          #    port: 8081
+          #  initialDelaySeconds: 5
+          #  timeoutSeconds: 5
+          resources:
+            requests:
+              cpu: 200m
+              memory: 512Mi
+            limits:
+              cpu: 700m
+              memory: 1024Mi
 ---
 apiVersion: v1
 kind: Service
@@ -90,11 +90,11 @@ spec:
   selector:
     app: dltservice
   ports:
-  - name: grpc
-    protocol: TCP
-    port: 8080
-    targetPort: 8080
-  - name: metrics
-    protocol: TCP
-    port: 9192
-    targetPort: 9192
+    - name: grpc
+      protocol: TCP
+      port: 8080
+      targetPort: 8080
+    - name: metrics
+      protocol: TCP
+      port: 9192
+      targetPort: 9192
diff --git a/manifests/e2e_orchestratorservice.yaml b/manifests/e2e_orchestratorservice.yaml
index 899e17fff32e02473d7249eda937282d394efa4e..90d37771171d1f062a17d071bebe1fd1fee859ad 100644
--- a/manifests/e2e_orchestratorservice.yaml
+++ b/manifests/e2e_orchestratorservice.yaml
@@ -27,28 +27,28 @@ spec:
     spec:
       terminationGracePeriodSeconds: 5
       containers:
-      - name: server
-        image: labs.etsi.org:5050/tfs/controller/e2e_orchestrator:latest
-        imagePullPolicy: Always
-        ports:
-        - containerPort: 10050
-        - containerPort: 9192
-        env:
-        - name: LOG_LEVEL
-          value: "INFO"
-        readinessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:10050"]
-        livenessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:10050"]
-        resources:
-          requests:
-            cpu: 250m
-            memory: 128Mi
-          limits:
-            cpu: 1000m
-            memory: 1024Mi
+        - name: server
+          image: labs.etsi.org:5050/tfs/controller/e2e_orchestrator:latest
+          imagePullPolicy: Always
+          ports:
+            - containerPort: 10050
+            - containerPort: 9192
+          env:
+            - name: LOG_LEVEL
+              value: "INFO"
+          readinessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:10050"]
+          livenessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:10050"]
+          resources:
+            requests:
+              cpu: 250m
+              memory: 128Mi
+            limits:
+              cpu: 1000m
+              memory: 1024Mi
 ---
 apiVersion: v1
 kind: Service
@@ -61,12 +61,12 @@ spec:
   selector:
     app: e2e-orchestratorservice
   ports:
-  - name: grpc
-    port: 10050
-    targetPort: 10050
-  - name: metrics
-    port: 9192
-    targetPort: 9192
+    - name: grpc
+      port: 10050
+      targetPort: 10050
+    - name: metrics
+      port: 9192
+      targetPort: 9192
 ---
 apiVersion: autoscaling/v2
 kind: HorizontalPodAutoscaler
@@ -80,12 +80,12 @@ spec:
   minReplicas: 1
   maxReplicas: 20
   metrics:
-  - type: Resource
-    resource:
-      name: cpu
-      target:
-        type: Utilization
-        averageUtilization: 80
+    - type: Resource
+      resource:
+        name: cpu
+        target:
+          type: Utilization
+          averageUtilization: 80
   #behavior:
   #  scaleDown:
   #    stabilizationWindowSeconds: 30
diff --git a/manifests/forecasterservice.yaml b/manifests/forecasterservice.yaml
index 55d4add88f6fc507e9a4271cb40b20c4742c5bc7..d1136f61789cc33069aa0f3c40e578755ec70137 100644
--- a/manifests/forecasterservice.yaml
+++ b/manifests/forecasterservice.yaml
@@ -28,35 +28,35 @@ spec:
     spec:
       terminationGracePeriodSeconds: 5
       containers:
-      - name: server
-        image: labs.etsi.org:5050/tfs/controller/forecaster:latest
-        imagePullPolicy: Always
-        ports:
-        - containerPort: 10040
-        - containerPort: 9192
-        env:
-        - name: LOG_LEVEL
-          value: "INFO"
-        - name: FORECAST_TO_HISTORY_RATIO
-          value: "10"
-        startupProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:10040"]
-          failureThreshold: 30
-          periodSeconds: 1
-        readinessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:10040"]
-        livenessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:10040"]
-        resources:
-          requests:
-            cpu: 250m
-            memory: 128Mi
-          limits:
-            cpu: 1000m
-            memory: 1024Mi
+        - name: server
+          image: labs.etsi.org:5050/tfs/controller/forecaster:latest
+          imagePullPolicy: Always
+          ports:
+            - containerPort: 10040
+            - containerPort: 9192
+          env:
+            - name: LOG_LEVEL
+              value: "INFO"
+            - name: FORECAST_TO_HISTORY_RATIO
+              value: "10"
+          startupProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:10040"]
+            failureThreshold: 30
+            periodSeconds: 1
+          readinessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:10040"]
+          livenessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:10040"]
+          resources:
+            requests:
+              cpu: 250m
+              memory: 128Mi
+            limits:
+              cpu: 1000m
+              memory: 1024Mi
 ---
 apiVersion: v1
 kind: Service
@@ -69,14 +69,14 @@ spec:
   selector:
     app: forecasterservice
   ports:
-  - name: grpc
-    protocol: TCP
-    port: 10040
-    targetPort: 10040
-  - name: metrics
-    protocol: TCP
-    port: 9192
-    targetPort: 9192
+    - name: grpc
+      protocol: TCP
+      port: 10040
+      targetPort: 10040
+    - name: metrics
+      protocol: TCP
+      port: 9192
+      targetPort: 9192
 ---
 apiVersion: autoscaling/v2
 kind: HorizontalPodAutoscaler
@@ -90,12 +90,12 @@ spec:
   minReplicas: 1
   maxReplicas: 20
   metrics:
-  - type: Resource
-    resource:
-      name: cpu
-      target:
-        type: Utilization
-        averageUtilization: 80
+    - type: Resource
+      resource:
+        name: cpu
+        target:
+          type: Utilization
+          averageUtilization: 80
   #behavior:
   #  scaleDown:
   #    stabilizationWindowSeconds: 30
diff --git a/manifests/interdomainservice.yaml b/manifests/interdomainservice.yaml
index a235834025724cb11e6b26364f25ae9feb28fe8c..ad9be3a3ec507a57b3cbcf196fd04a73a9fb34ac 100644
--- a/manifests/interdomainservice.yaml
+++ b/manifests/interdomainservice.yaml
@@ -27,30 +27,30 @@ spec:
     spec:
       terminationGracePeriodSeconds: 5
       containers:
-      - name: server
-        image: labs.etsi.org:5050/tfs/controller/interdomain:latest
-        imagePullPolicy: Always
-        ports:
-        - containerPort: 10010
-        - containerPort: 9192
-        env:
-        - name: LOG_LEVEL
-          value: "INFO"
-        - name: TOPOLOGY_ABSTRACTOR
-          value: "DISABLE"
-        readinessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:10010"]
-        livenessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:10010"]
-        resources:
-          requests:
-            cpu: 250m
-            memory: 64Mi
-          limits:
-            cpu: 1000m
-            memory: 1024Mi
+        - name: server
+          image: labs.etsi.org:5050/tfs/controller/interdomain:latest
+          imagePullPolicy: Always
+          ports:
+            - containerPort: 10010
+            - containerPort: 9192
+          env:
+            - name: LOG_LEVEL
+              value: "INFO"
+            - name: TOPOLOGY_ABSTRACTOR
+              value: "DISABLE"
+          readinessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:10010"]
+          livenessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:10010"]
+          resources:
+            requests:
+              cpu: 250m
+              memory: 64Mi
+            limits:
+              cpu: 1000m
+              memory: 1024Mi
 ---
 apiVersion: v1
 kind: Service
@@ -63,11 +63,11 @@ spec:
   selector:
     app: interdomainservice
   ports:
-  - name: grpc
-    protocol: TCP
-    port: 10010
-    targetPort: 10010
-  - name: metrics
-    protocol: TCP
-    port: 9192
-    targetPort: 9192
+    - name: grpc
+      protocol: TCP
+      port: 10010
+      targetPort: 10010
+    - name: metrics
+      protocol: TCP
+      port: 9192
+      targetPort: 9192
diff --git a/manifests/l3_attackmitigatorservice.yaml b/manifests/l3_attackmitigatorservice.yaml
index ee97d2c92abb5abcad80f8ddf04800ef13144522..973b805bd7fb8c33a6b9e307afa87d8cb21ad7ec 100644
--- a/manifests/l3_attackmitigatorservice.yaml
+++ b/manifests/l3_attackmitigatorservice.yaml
@@ -27,28 +27,28 @@ spec:
     spec:
       terminationGracePeriodSeconds: 5
       containers:
-      - name: server
-        image: labs.etsi.org:5050/tfs/controller/l3_attackmitigator:latest
-        imagePullPolicy: Always
-        ports:
-        - containerPort: 10002
-        - containerPort: 9192
-        env:
-        - name: LOG_LEVEL
-          value: "DEBUG"
-        readinessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:10002"]
-        livenessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:10002"]
-        resources:
-          requests:
-            cpu: 250m
-            memory: 512Mi
-          limits:
-            cpu: 700m
-            memory: 1024Mi
+        - name: server
+          image: labs.etsi.org:5050/tfs/controller/l3_attackmitigator:latest
+          imagePullPolicy: Always
+          ports:
+            - containerPort: 10002
+            - containerPort: 9192
+          env:
+            - name: LOG_LEVEL
+              value: "INFO"
+          readinessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:10002"]
+          livenessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:10002"]
+          resources:
+            requests:
+              cpu: 250m
+              memory: 512Mi
+            limits:
+              cpu: 700m
+              memory: 1024Mi
 ---
 apiVersion: v1
 kind: Service
@@ -61,13 +61,13 @@ spec:
   selector:
     app: l3-attackmitigatorservice
   ports:
-  - name: metrics
-    protocol: TCP
-    port: 9192
-    targetPort: 9192
-  - name: grpc
-    port: 10002
-    targetPort: 10002
+    - name: metrics
+      protocol: TCP
+      port: 9192
+      targetPort: 9192
+    - name: grpc
+      port: 10002
+      targetPort: 10002
 
 ---
 apiVersion: autoscaling/v2
@@ -82,12 +82,12 @@ spec:
   minReplicas: 1
   maxReplicas: 10
   metrics:
-  - type: Resource
-    resource:
-      name: cpu
-      target:
-        type: Utilization
-        averageUtilization: 80
+    - type: Resource
+      resource:
+        name: cpu
+        target:
+          type: Utilization
+          averageUtilization: 80
   behavior:
     scaleDown:
       stabilizationWindowSeconds: 120
@@ -100,9 +100,9 @@ metadata:
   labels:
     app: l3-attackmitigatorservice
     #release: prometheus
-    #release: prom  # name of the release 
-    # ( VERY IMPORTANT: You need to know the correct release name by viewing 
-    #   the servicemonitor of Prometheus itself: Without the correct name, 
+    #release: prom  # name of the release
+    # ( VERY IMPORTANT: You need to know the correct release name by viewing
+    #   the servicemonitor of Prometheus itself: Without the correct name,
     #   Prometheus cannot identify the metrics of the Flask app as the target.)
 spec:
   selector:
@@ -112,11 +112,11 @@ spec:
       app: l3-attackmitigatorservice # same as above
       #release: prometheus # same as above
   endpoints:
-  - port: metrics # named port in target app
-    scheme: http
-    path: /metrics # path to scrape
-    interval: 5s # scrape interval
+    - port: metrics # named port in target app
+      scheme: http
+      path: /metrics # path to scrape
+      interval: 5s # scrape interval
   namespaceSelector:
     any: false
     matchNames:
-    - tfs # namespace where the app is running
+      - tfs # namespace where the app is running
diff --git a/manifests/l3_centralizedattackdetectorservice.yaml b/manifests/l3_centralizedattackdetectorservice.yaml
index 8a3be69b672200120afb4bca3892dd0c08ec2d65..98c5f9b41519f13d784a7cab7027a23d9d082714 100644
--- a/manifests/l3_centralizedattackdetectorservice.yaml
+++ b/manifests/l3_centralizedattackdetectorservice.yaml
@@ -27,36 +27,36 @@ spec:
     spec:
       terminationGracePeriodSeconds: 5
       containers:
-      - name: server
-        image: labs.etsi.org:5050/tfs/controller/l3_centralizedattackdetector:latest
-        imagePullPolicy: Always
-        ports:
-        - containerPort: 10001
-        - containerPort: 9192
-        env:
-        - name: LOG_LEVEL
-          value: "DEBUG"
-        - name: BATCH_SIZE
-          value: "256"
-        - name: CAD_CLASSIFICATION_THRESHOLD
-          value: "0.5"
-        - name: MONITORED_KPIS_TIME_INTERVAL_AGG
-          value: "60"
-        - name: TEST_ML_MODEL
-          value: "0"
-        readinessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:10001"]
-        livenessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:10001"]
-        resources:
-          requests:
-            cpu: 250m
-            memory: 512Mi
-          limits:
-            cpu: 700m
-            memory: 1024Mi
+        - name: server
+          image: labs.etsi.org:5050/tfs/controller/l3_centralizedattackdetector:latest
+          imagePullPolicy: Always
+          ports:
+            - containerPort: 10001
+            - containerPort: 9192
+          env:
+            - name: LOG_LEVEL
+              value: "INFO"
+            - name: BATCH_SIZE
+              value: "256"
+            - name: CAD_CLASSIFICATION_THRESHOLD
+              value: "0.5"
+            - name: MONITORED_KPIS_TIME_INTERVAL_AGG
+              value: "60"
+            - name: TEST_ML_MODEL
+              value: "0"
+          readinessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:10001"]
+          livenessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:10001"]
+          resources:
+            requests:
+              cpu: 250m
+              memory: 512Mi
+            limits:
+              cpu: 700m
+              memory: 1024Mi
 ---
 apiVersion: v1
 kind: Service
@@ -69,13 +69,13 @@ spec:
   selector:
     app: l3-centralizedattackdetectorservice
   ports:
-  - name: metrics
-    protocol: TCP
-    port: 9192
-    targetPort: 9192
-  - name: grpc
-    port: 10001
-    targetPort: 10001
+    - name: metrics
+      protocol: TCP
+      port: 9192
+      targetPort: 9192
+    - name: grpc
+      port: 10001
+      targetPort: 10001
 
 ---
 apiVersion: autoscaling/v2
@@ -90,12 +90,12 @@ spec:
   minReplicas: 1
   maxReplicas: 10
   metrics:
-  - type: Resource
-    resource:
-      name: cpu
-      target:
-        type: Utilization
-        averageUtilization: 80
+    - type: Resource
+      resource:
+        name: cpu
+        target:
+          type: Utilization
+          averageUtilization: 80
   behavior:
     scaleDown:
       stabilizationWindowSeconds: 120
@@ -107,9 +107,9 @@ metadata:
   labels:
     app: l3-centralizedattackdetectorservice
     #release: prometheus
-    #release: prom  # name of the release 
-    # ( VERY IMPORTANT: You need to know the correct release name by viewing 
-    #   the servicemonitor of Prometheus itself: Without the correct name, 
+    #release: prom  # name of the release
+    # ( VERY IMPORTANT: You need to know the correct release name by viewing
+    #   the servicemonitor of Prometheus itself: Without the correct name,
     #   Prometheus cannot identify the metrics of the Flask app as the target.)
 spec:
   selector:
@@ -119,11 +119,11 @@ spec:
       app: l3-centralizedattackdetectorservice # same as above
       #release: prometheus # same as above
   endpoints:
-  - port: metrics # named port in target app
-    scheme: http
-    path: /metrics # path to scrape
-    interval: 5s # scrape interval
+    - port: metrics # named port in target app
+      scheme: http
+      path: /metrics # path to scrape
+      interval: 5s # scrape interval
   namespaceSelector:
     any: false
     matchNames:
-    - tfs # namespace where the app is running
+      - tfs # namespace where the app is running
diff --git a/manifests/l3_distributedattackdetectorservice.yaml b/manifests/l3_distributedattackdetectorservice.yaml
index b363c1d5c5f82083d525959d6aedf337554f604a..bf72b5cd0752b2219ef3b5c2abad0b9330d43853 100644
--- a/manifests/l3_distributedattackdetectorservice.yaml
+++ b/manifests/l3_distributedattackdetectorservice.yaml
@@ -27,27 +27,27 @@ spec:
     spec:
       terminationGracePeriodSeconds: 5
       containers:
-      - name: server
-        image: labs.etsi.org:5050/tfs/controller/l3_distributedattackdetector:latest
-        imagePullPolicy: Always
-        ports:
-        - containerPort: 10000
-        env:
-        - name: LOG_LEVEL
-          value: "DEBUG"
-        readinessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:10000"]
-        livenessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:10000"]
-        resources:
-          requests:
-            cpu: 250m
-            memory: 512Mi
-          limits:
-            cpu: 700m
-            memory: 1024Mi
+        - name: server
+          image: labs.etsi.org:5050/tfs/controller/l3_distributedattackdetector:latest
+          imagePullPolicy: Always
+          ports:
+            - containerPort: 10000
+          env:
+            - name: LOG_LEVEL
+              value: "INFO"
+          readinessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:10000"]
+          livenessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:10000"]
+          resources:
+            requests:
+              cpu: 250m
+              memory: 512Mi
+            limits:
+              cpu: 700m
+              memory: 1024Mi
 ---
 apiVersion: v1
 kind: Service
@@ -58,6 +58,6 @@ spec:
   selector:
     app: l3-distributedattackdetectorservice
   ports:
-  - name: grpc
-    port: 10000
-    targetPort: 10000
+    - name: grpc
+      port: 10000
+      targetPort: 10000
diff --git a/manifests/load_generatorservice.yaml b/manifests/load_generatorservice.yaml
index 7cc6f19122573a612ddca774c3a785bff93f8b38..bda284ebda122780762c72b53052de28b2b25385 100644
--- a/manifests/load_generatorservice.yaml
+++ b/manifests/load_generatorservice.yaml
@@ -28,28 +28,28 @@ spec:
     spec:
       terminationGracePeriodSeconds: 5
       containers:
-      - name: server
-        image: labs.etsi.org:5050/tfs/controller/load_generator:latest
-        imagePullPolicy: Always
-        ports:
-        - containerPort: 50052
-        - containerPort: 9192
-        env:
-        - name: LOG_LEVEL
-          value: "INFO"
-        readinessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:50052"]
-        livenessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:50052"]
-        resources:
-          requests:
-            cpu: 256m
-            memory: 64Mi
-          limits:
-            cpu: 512m
-            memory: 128Mi
+        - name: server
+          image: labs.etsi.org:5050/tfs/controller/load_generator:latest
+          imagePullPolicy: Always
+          ports:
+            - containerPort: 50052
+            - containerPort: 9192
+          env:
+            - name: LOG_LEVEL
+              value: "INFO"
+          readinessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:50052"]
+          livenessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:50052"]
+          resources:
+            requests:
+              cpu: 256m
+              memory: 64Mi
+            limits:
+              cpu: 512m
+              memory: 128Mi
 ---
 apiVersion: v1
 kind: Service
@@ -62,11 +62,11 @@ spec:
   selector:
     app: load-generatorservice
   ports:
-  - name: grpc
-    protocol: TCP
-    port: 50052
-    targetPort: 50052
-  - name: metrics
-    protocol: TCP
-    port: 9192
-    targetPort: 9192
+    - name: grpc
+      protocol: TCP
+      port: 50052
+      targetPort: 50052
+    - name: metrics
+      protocol: TCP
+      port: 9192
+      targetPort: 9192
diff --git a/manifests/mock_blockchain.yaml b/manifests/mock_blockchain.yaml
index 1093610f8a0cf4d735e16e99df56cb78fd6481fc..806432be630fa2502e1c121a9c61f16e0fcd1b0c 100644
--- a/manifests/mock_blockchain.yaml
+++ b/manifests/mock_blockchain.yaml
@@ -27,27 +27,27 @@ spec:
     spec:
       terminationGracePeriodSeconds: 5
       containers:
-      - name: server
-        image: labs.etsi.org:5050/tfs/controller/mock_blockchain:latest
-        imagePullPolicy: Always
-        ports:
-        - containerPort: 50051
-        env:
-        - name: LOG_LEVEL
-          value: "INFO"
-        readinessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:50051"]
-        livenessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:50051"]
-        resources:
-          requests:
-            cpu: 100m
-            memory: 512Mi
-          limits:
-            cpu: 700m
-            memory: 1024Mi
+        - name: server
+          image: labs.etsi.org:5050/tfs/controller/mock_blockchain:latest
+          imagePullPolicy: Always
+          ports:
+            - containerPort: 50051
+          env:
+            - name: LOG_LEVEL
+              value: "INFO"
+          readinessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:50051"]
+          livenessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:50051"]
+          resources:
+            requests:
+              cpu: 100m
+              memory: 512Mi
+            limits:
+              cpu: 700m
+              memory: 1024Mi
 ---
 apiVersion: v1
 kind: Service
@@ -58,7 +58,7 @@ spec:
   selector:
     app: mock-blockchain
   ports:
-  - name: grpc
-    protocol: TCP
-    port: 50051
-    targetPort: 50051
+    - name: grpc
+      protocol: TCP
+      port: 50051
+      targetPort: 50051
diff --git a/manifests/monitoringservice.yaml b/manifests/monitoringservice.yaml
index dbcfa68a036e3323f42e423de14002ba85576171..3a4d43cd9d17d645da4d70a22ec4dde12a8d7bc2 100644
--- a/manifests/monitoringservice.yaml
+++ b/manifests/monitoringservice.yaml
@@ -28,31 +28,31 @@ spec:
     spec:
       terminationGracePeriodSeconds: 5
       containers:
-      - name: server
-        image: labs.etsi.org:5050/tfs/controller/monitoring:latest
-        imagePullPolicy: Always
-        ports:
-        - containerPort: 7070
-        - containerPort: 9192
-        env:
-        - name: LOG_LEVEL
-          value: "INFO"
-        envFrom:
-        - secretRef:
-            name: qdb-data
-        readinessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:7070"]
-        livenessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:7070"]
-        resources:
-          requests:
-            cpu: 250m
-            memory: 256Mi
-          limits:
-            cpu: 1000m
-            memory: 1024Mi
+        - name: server
+          image: labs.etsi.org:5050/tfs/controller/monitoring:latest
+          imagePullPolicy: Always
+          ports:
+            - containerPort: 7070
+            - containerPort: 9192
+          env:
+            - name: LOG_LEVEL
+              value: "INFO"
+          envFrom:
+            - secretRef:
+                name: qdb-data
+          readinessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:7070"]
+          livenessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:7070"]
+          resources:
+            requests:
+              cpu: 250m
+              memory: 256Mi
+            limits:
+              cpu: 1000m
+              memory: 1024Mi
 ---
 apiVersion: v1
 kind: Service
@@ -65,11 +65,11 @@ spec:
   selector:
     app: monitoringservice
   ports:
-  - name: grpc
-    protocol: TCP
-    port: 7070
-    targetPort: 7070
-  - name: metrics
-    protocol: TCP
-    port: 9192
-    targetPort: 9192
+    - name: grpc
+      protocol: TCP
+      port: 7070
+      targetPort: 7070
+    - name: metrics
+      protocol: TCP
+      port: 9192
+      targetPort: 9192
diff --git a/manifests/nbiservice.yaml b/manifests/nbiservice.yaml
index de97ba364d71d2b5a7f55211867a0a5062c521a4..0a3bd1ea69918429de73d58812248269ccf70a56 100644
--- a/manifests/nbiservice.yaml
+++ b/manifests/nbiservice.yaml
@@ -28,29 +28,29 @@ spec:
     spec:
       terminationGracePeriodSeconds: 5
       containers:
-      - name: server
-        image: labs.etsi.org:5050/tfs/controller/nbi:latest
-        imagePullPolicy: Always
-        ports:
-        - containerPort: 8080
-        - containerPort: 9090
-        - containerPort: 9192
-        env:
-        - name: LOG_LEVEL
-          value: "INFO"
-        readinessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:9090"]
-        livenessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:9090"]
-        resources:
-          requests:
-            cpu: 50m
-            memory: 64Mi
-          limits:
-            cpu: 500m
-            memory: 512Mi
+        - name: server
+          image: labs.etsi.org:5050/tfs/controller/nbi:latest
+          imagePullPolicy: Always
+          ports:
+            - containerPort: 8080
+            - containerPort: 9090
+            - containerPort: 9192
+          env:
+            - name: LOG_LEVEL
+              value: "INFO"
+          readinessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:9090"]
+          livenessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:9090"]
+          resources:
+            requests:
+              cpu: 50m
+              memory: 64Mi
+            limits:
+              cpu: 500m
+              memory: 512Mi
 ---
 apiVersion: v1
 kind: Service
@@ -63,15 +63,15 @@ spec:
   selector:
     app: nbiservice
   ports:
-  - name: http
-    protocol: TCP
-    port: 8080
-    targetPort: 8080
-  - name: grpc
-    protocol: TCP
-    port: 9090
-    targetPort: 9090
-  - name: metrics
-    protocol: TCP
-    port: 9192
-    targetPort: 9192
+    - name: http
+      protocol: TCP
+      port: 8080
+      targetPort: 8080
+    - name: grpc
+      protocol: TCP
+      port: 9090
+      targetPort: 9090
+    - name: metrics
+      protocol: TCP
+      port: 9192
+      targetPort: 9192
diff --git a/manifests/nginx_ingress_http.yaml b/manifests/nginx_ingress_http.yaml
index e8e8a80e4d4325a28202070a463cda959e3ed634..91440fb7a2bf417d7a020b38070570f2ed3da8df 100644
--- a/manifests/nginx_ingress_http.yaml
+++ b/manifests/nginx_ingress_http.yaml
@@ -20,40 +20,40 @@ metadata:
     nginx.ingress.kubernetes.io/rewrite-target: /$2
 spec:
   rules:
-  - http:
-      paths:
-        - path: /webui(/|$)(.*)
-          pathType: Prefix
-          backend:
-            service:
-              name: webuiservice
-              port:
-                number: 8004
-        - path: /grafana(/|$)(.*)
-          pathType: Prefix
-          backend:
-            service:
-              name: webuiservice
-              port:
-                number: 3000
-        - path: /()(restconf/.*)
-          pathType: Prefix
-          backend:
-            service:
-              name: nbiservice
-              port:
-                number: 8080
-        - path: /()(debug-api/.*)
-          pathType: Prefix
-          backend:
-            service:
-              name: nbiservice
-              port:
-                number: 8080
-        - path: /()(bmw/.*)
-          pathType: Prefix
-          backend:
-            service:
-              name: nbiservice
-              port:
-                number: 8080
+    - http:
+        paths:
+          - path: /webui(/|$)(.*)
+            pathType: Prefix
+            backend:
+              service:
+                name: webuiservice
+                port:
+                  number: 8004
+          - path: /grafana(/|$)(.*)
+            pathType: Prefix
+            backend:
+              service:
+                name: webuiservice
+                port:
+                  number: 3000
+          - path: /()(restconf/.*)
+            pathType: Prefix
+            backend:
+              service:
+                name: nbiservice
+                port:
+                  number: 8080
+          - path: /()(debug-api/.*)
+            pathType: Prefix
+            backend:
+              service:
+                name: nbiservice
+                port:
+                  number: 8080
+          - path: /()(bmw/.*)
+            pathType: Prefix
+            backend:
+              service:
+                name: nbiservice
+                port:
+                  number: 8080
diff --git a/manifests/opticalattackdetectorservice.yaml b/manifests/opticalattackdetectorservice.yaml
index 197c23dd237e5f6271fbab7e47613892c6f58f83..11fd62b61f77a30c6916fbf189758947beb96286 100644
--- a/manifests/opticalattackdetectorservice.yaml
+++ b/manifests/opticalattackdetectorservice.yaml
@@ -27,33 +27,33 @@ spec:
     spec:
       terminationGracePeriodSeconds: 5
       containers:
-      - name: server
-        image: labs.etsi.org:5050/tfs/controller/opticalattackdetector:latest
-        imagePullPolicy: Always
-        ports:
-        - containerPort: 10006
-        - containerPort: 9192
-        env:
-        - name: LOG_LEVEL
-          value: "INFO"
-        - name: REDIS_PASSWORD
-          valueFrom:
-            secretKeyRef:
-              name: redis-secrets
-              key: REDIS_PASSWORD
-        readinessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:10006"]
-        livenessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:10006"]
-        resources:
-          requests:
-            cpu: 250m
-            memory: 128Mi
-          limits:
-            cpu: 1000m
-            memory: 1024Mi
+        - name: server
+          image: labs.etsi.org:5050/tfs/controller/opticalattackdetector:latest
+          imagePullPolicy: Always
+          ports:
+            - containerPort: 10006
+            - containerPort: 9192
+          env:
+            - name: LOG_LEVEL
+              value: "INFO"
+            - name: REDIS_PASSWORD
+              valueFrom:
+                secretKeyRef:
+                  name: redis-secrets
+                  key: REDIS_PASSWORD
+          readinessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:10006"]
+          livenessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:10006"]
+          resources:
+            requests:
+              cpu: 250m
+              memory: 128Mi
+            limits:
+              cpu: 1000m
+              memory: 1024Mi
 ---
 apiVersion: v1
 kind: Service
@@ -66,12 +66,12 @@ spec:
   selector:
     app: opticalattackdetectorservice
   ports:
-  - name: grpc
-    port: 10006
-    targetPort: 10006
-  - name: metrics
-    port: 9192
-    targetPort: 9192
+    - name: grpc
+      port: 10006
+      targetPort: 10006
+    - name: metrics
+      port: 9192
+      targetPort: 9192
 ---
 apiVersion: autoscaling/v2
 kind: HorizontalPodAutoscaler
@@ -85,12 +85,12 @@ spec:
   minReplicas: 1
   maxReplicas: 20
   metrics:
-  - type: Resource
-    resource:
-      name: cpu
-      target:
-        type: Utilization
-        averageUtilization: 80
+    - type: Resource
+      resource:
+        name: cpu
+        target:
+          type: Utilization
+          averageUtilization: 80
   #behavior:
   #  scaleDown:
   #    stabilizationWindowSeconds: 30
diff --git a/manifests/opticalattackmanagerservice.yaml b/manifests/opticalattackmanagerservice.yaml
index f9838bcbb1c0d86e5d3a22d8ed982b533f984eb3..4e01d76ac838bc3b0353f95de0c493d8004e5a9a 100644
--- a/manifests/opticalattackmanagerservice.yaml
+++ b/manifests/opticalattackmanagerservice.yaml
@@ -28,33 +28,33 @@ spec:
     spec:
       terminationGracePeriodSeconds: 5
       containers:
-      - name: server
-        image: labs.etsi.org:5050/tfs/controller/opticalattackmanager:latest
-        imagePullPolicy: Always
-        ports:
-        - containerPort: 10005
-        - containerPort: 9192
-        env:
-        - name: LOG_LEVEL
-          value: "INFO"
-        - name: MONITORING_INTERVAL
-          value: "30"
-        - name: OPTICALATTACKMANAGERSERVICE_LOOP_MIN_WORKERS
-          value: "2"  # remember to align this with the resource limits
-        - name: OPTICALATTACKMANAGERSERVICE_LOOP_MAX_WORKERS
-          value: "10"  # remember to align this with the resource limits
-        - name: REDIS_PASSWORD
-          valueFrom:
-            secretKeyRef:
-              name: redis-secrets
-              key: REDIS_PASSWORD
-        resources:
-          requests:
-            cpu: 250m
-            memory: 128Mi
-          limits:
-            cpu: 10000m
-            memory: 10240Mi
+        - name: server
+          image: labs.etsi.org:5050/tfs/controller/opticalattackmanager:latest
+          imagePullPolicy: Always
+          ports:
+            - containerPort: 10005
+            - containerPort: 9192
+          env:
+            - name: LOG_LEVEL
+              value: "INFO"
+            - name: MONITORING_INTERVAL
+              value: "30"
+            - name: OPTICALATTACKMANAGERSERVICE_LOOP_MIN_WORKERS
+              value: "2" # remember to align this with the resource limits
+            - name: OPTICALATTACKMANAGERSERVICE_LOOP_MAX_WORKERS
+              value: "10" # remember to align this with the resource limits
+            - name: REDIS_PASSWORD
+              valueFrom:
+                secretKeyRef:
+                  name: redis-secrets
+                  key: REDIS_PASSWORD
+          resources:
+            requests:
+              cpu: 250m
+              memory: 128Mi
+            limits:
+              cpu: 10000m
+              memory: 10240Mi
 ---
 apiVersion: v1
 kind: Service
@@ -67,9 +67,9 @@ spec:
   selector:
     app: opticalattackmanagerservice
   ports:
-  - name: grpc
-    port: 10005
-    targetPort: 10005
-  - name: metrics
-    port: 9192
-    targetPort: 9192
+    - name: grpc
+      port: 10005
+      targetPort: 10005
+    - name: metrics
+      port: 9192
+      targetPort: 9192
diff --git a/manifests/opticalattackmitigatorservice.yaml b/manifests/opticalattackmitigatorservice.yaml
index 4d148b347157bd310ec6c921670f0434315e6e27..255e0fd86a5c948d44868e7b96e6c65825556910 100644
--- a/manifests/opticalattackmitigatorservice.yaml
+++ b/manifests/opticalattackmitigatorservice.yaml
@@ -27,28 +27,28 @@ spec:
     spec:
       terminationGracePeriodSeconds: 5
       containers:
-      - name: server
-        image: labs.etsi.org:5050/tfs/controller/opticalattackmitigator:latest
-        imagePullPolicy: Always
-        ports:
-        - containerPort: 10007
-        - containerPort: 9192
-        env:
-        - name: LOG_LEVEL
-          value: "INFO"
-        readinessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:10007"]
-        livenessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:10007"]
-        resources:
-          requests:
-            cpu: 250m
-            memory: 128Mi
-          limits:
-            cpu: 1000m
-            memory: 1024Mi
+        - name: server
+          image: labs.etsi.org:5050/tfs/controller/opticalattackmitigator:latest
+          imagePullPolicy: Always
+          ports:
+            - containerPort: 10007
+            - containerPort: 9192
+          env:
+            - name: LOG_LEVEL
+              value: "INFO"
+          readinessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:10007"]
+          livenessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:10007"]
+          resources:
+            requests:
+              cpu: 250m
+              memory: 128Mi
+            limits:
+              cpu: 1000m
+              memory: 1024Mi
 ---
 apiVersion: v1
 kind: Service
@@ -61,12 +61,12 @@ spec:
   selector:
     app: opticalattackmitigatorservice
   ports:
-  - name: grpc
-    port: 10007
-    targetPort: 10007
-  - name: metrics
-    port: 9192
-    targetPort: 9192
+    - name: grpc
+      port: 10007
+      targetPort: 10007
+    - name: metrics
+      port: 9192
+      targetPort: 9192
 ---
 apiVersion: autoscaling/v2
 kind: HorizontalPodAutoscaler
@@ -80,12 +80,12 @@ spec:
   minReplicas: 1
   maxReplicas: 20
   metrics:
-  - type: Resource
-    resource:
-      name: cpu
-      target:
-        type: Utilization
-        averageUtilization: 80
+    - type: Resource
+      resource:
+        name: cpu
+        target:
+          type: Utilization
+          averageUtilization: 80
   #behavior:
   #  scaleDown:
   #    stabilizationWindowSeconds: 30
diff --git a/manifests/opticalcontrollerservice.yaml b/manifests/opticalcontrollerservice.yaml
index 4b677ee4f7287b0790aaa0b19f034db03978fac0..f2351720c008d9ecaf53779253ba8a368ffb8bf7 100644
--- a/manifests/opticalcontrollerservice.yaml
+++ b/manifests/opticalcontrollerservice.yaml
@@ -28,28 +28,28 @@ spec:
     spec:
       terminationGracePeriodSeconds: 5
       containers:
-      - name: server
-        image:  localhost:32000/tfs/opticalcontroller:dev
-        imagePullPolicy: Never
-        ports:
-        - containerPort: 10060
-        - containerPort: 9192
-        env:
-        - name: LOG_LEVEL
-          value: "INFO"
-        #readinessProbe:
-        #  exec:
-        #    command: ["/bin/grpc_health_probe", "-addr=:10060"]
-        #livenessProbe:
-        #  exec:
-        #    command: ["/bin/grpc_health_probe", "-addr=:10060"]
-        resources:
-          requests:
-            cpu: 500m
-            memory: 128Mi
-          limits:
-            cpu: 1000m
-            memory: 1024Mi
+        - name: server
+          image: localhost:32000/tfs/opticalcontroller:dev
+          imagePullPolicy: Never
+          ports:
+            - containerPort: 10060
+            - containerPort: 9192
+          env:
+            - name: LOG_LEVEL
+              value: "INFO"
+          #readinessProbe:
+          #  exec:
+          #    command: ["/bin/grpc_health_probe", "-addr=:10060"]
+          #livenessProbe:
+          #  exec:
+          #    command: ["/bin/grpc_health_probe", "-addr=:10060"]
+          resources:
+            requests:
+              cpu: 500m
+              memory: 128Mi
+            limits:
+              cpu: 1000m
+              memory: 1024Mi
 ---
 apiVersion: v1
 kind: Service
@@ -62,11 +62,11 @@ spec:
   selector:
     app: opticalcontrollerservice
   ports:
-  - name: grpc
-    protocol: TCP
-    port: 10060
-    targetPort: 10060
-  - name: metrics
-    protocol: TCP
-    port: 9192
-    targetPort: 9192
+    - name: grpc
+      protocol: TCP
+      port: 10060
+      targetPort: 10060
+    - name: metrics
+      protocol: TCP
+      port: 9192
+      targetPort: 9192
diff --git a/manifests/pathcompservice.yaml b/manifests/pathcompservice.yaml
index 87d907a728d0b689dcedde730fad7a2e886a6659..f017e694085da963944194197c91f5b4e9bcf70c 100644
--- a/manifests/pathcompservice.yaml
+++ b/manifests/pathcompservice.yaml
@@ -28,54 +28,54 @@ spec:
     spec:
       terminationGracePeriodSeconds: 5
       containers:
-      - name: frontend
-        image: labs.etsi.org:5050/tfs/controller/pathcomp-frontend:latest
-        imagePullPolicy: Always
-        ports:
-        - containerPort: 10020
-        - containerPort: 9192
-        env:
-        - name: LOG_LEVEL
-          value: "INFO"
-        - name: ENABLE_FORECASTER
-          value: "YES"
-        readinessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:10020"]
-        livenessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:10020"]
-        resources:
-          requests:
-            cpu: 250m
-            memory: 128Mi
-          limits:
-            cpu: 1000m
-            memory: 1024Mi
-      - name: backend
-        image: labs.etsi.org:5050/tfs/controller/pathcomp-backend:latest
-        imagePullPolicy: Always
-        ports:
-        - containerPort: 8081
-        #readinessProbe:
-        #  httpGet:
-        #    path: /health
-        #    port: 8081
-        #  initialDelaySeconds: 5
-        #  timeoutSeconds: 5
-        #livenessProbe:
-        #  httpGet:
-        #    path: /health
-        #    port: 8081
-        #  initialDelaySeconds: 5
-        #  timeoutSeconds: 5
-        resources:
-          requests:
-            cpu: 250m
-            memory: 256Mi
-          limits:
-            cpu: 1000m
-            memory: 1024Mi
+        - name: frontend
+          image: labs.etsi.org:5050/tfs/controller/pathcomp-frontend:latest
+          imagePullPolicy: Always
+          ports:
+            - containerPort: 10020
+            - containerPort: 9192
+          env:
+            - name: LOG_LEVEL
+              value: "INFO"
+            - name: ENABLE_FORECASTER
+              value: "NO"
+          readinessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:10020"]
+          livenessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:10020"]
+          resources:
+            requests:
+              cpu: 250m
+              memory: 128Mi
+            limits:
+              cpu: 1000m
+              memory: 1024Mi
+        - name: backend
+          image: labs.etsi.org:5050/tfs/controller/pathcomp-backend:latest
+          imagePullPolicy: Always
+          ports:
+            - containerPort: 8081
+          #readinessProbe:
+          #  httpGet:
+          #    path: /health
+          #    port: 8081
+          #  initialDelaySeconds: 5
+          #  timeoutSeconds: 5
+          #livenessProbe:
+          #  httpGet:
+          #    path: /health
+          #    port: 8081
+          #  initialDelaySeconds: 5
+          #  timeoutSeconds: 5
+          resources:
+            requests:
+              cpu: 250m
+              memory: 256Mi
+            limits:
+              cpu: 1000m
+              memory: 1024Mi
 ---
 apiVersion: v1
 kind: Service
@@ -88,18 +88,18 @@ spec:
   selector:
     app: pathcompservice
   ports:
-  - name: grpc
-    protocol: TCP
-    port: 10020
-    targetPort: 10020
-  - name: http
-    protocol: TCP
-    port: 8081
-    targetPort: 8081
-  - name: metrics
-    protocol: TCP
-    port: 9192
-    targetPort: 9192
+    - name: grpc
+      protocol: TCP
+      port: 10020
+      targetPort: 10020
+    - name: http
+      protocol: TCP
+      port: 8081
+      targetPort: 8081
+    - name: metrics
+      protocol: TCP
+      port: 9192
+      targetPort: 9192
 ---
 apiVersion: autoscaling/v2
 kind: HorizontalPodAutoscaler
@@ -113,12 +113,12 @@ spec:
   minReplicas: 1
   maxReplicas: 20
   metrics:
-  - type: Resource
-    resource:
-      name: cpu
-      target:
-        type: Utilization
-        averageUtilization: 80
+    - type: Resource
+      resource:
+        name: cpu
+        target:
+          type: Utilization
+          averageUtilization: 80
   #behavior:
   #  scaleDown:
   #    stabilizationWindowSeconds: 30
diff --git a/manifests/policyservice.yaml b/manifests/policyservice.yaml
index b34331724665e4788d2de327bb5160eb370fed96..7ef040e7fde49c4e023b015f6f5e0bb917317fbe 100644
--- a/manifests/policyservice.yaml
+++ b/manifests/policyservice.yaml
@@ -108,22 +108,22 @@ spec:
             limits:
               cpu: 2000m
               memory: 2048Mi
----
-apiVersion: autoscaling/v2
-kind: HorizontalPodAutoscaler
-metadata:
-  name: policyservice-hpa
-spec:
-  scaleTargetRef:
-    apiVersion: apps/v1
-    kind: Deployment
-    name: policyservice
-  minReplicas: 1
-  maxReplicas: 10
-  metrics:
-  - type: Resource
-    resource:
-      name: cpu
-      target:
-        type: Utilization
-        averageUtilization: 80
+#---
+#apiVersion: autoscaling/v2
+#kind: HorizontalPodAutoscaler
+#metadata:
+#  name: policyservice-hpa
+#spec:
+#  scaleTargetRef:
+#    apiVersion: apps/v1
+#    kind: Deployment
+#    name: policyservice
+#  minReplicas: 1
+#  maxReplicas: 10
+#  metrics:
+#    - type: Resource
+#      resource:
+#        name: cpu
+#        target:
+#          type: Utilization
+#          averageUtilization: 80
diff --git a/manifests/prometheus.yaml b/manifests/prometheus.yaml
index 43a766b6e2ae67e36d161c3063a8a2d3ccc875d3..ec1ffb0c509437a715c508aa378a2a01f1c2252a 100644
--- a/manifests/prometheus.yaml
+++ b/manifests/prometheus.yaml
@@ -60,18 +60,18 @@ spec:
     spec:
       #serviceAccountName: prometheus
       containers:
-      - name: prometheus
-        image: prom/prometheus:v2.28.1
-        ports:
-        - containerPort: 9090
-        volumeMounts:
-        - name: prometheus-config-volume
-          mountPath: /etc/prometheus/prometheus.yml
-          subPath: prometheus.yml
+        - name: prometheus
+          image: prom/prometheus:v2.28.1
+          ports:
+            - containerPort: 9090
+          volumeMounts:
+            - name: prometheus-config-volume
+              mountPath: /etc/prometheus/prometheus.yml
+              subPath: prometheus.yml
       volumes:
-      - name: prometheus-config-volume
-        configMap:
-          name: prometheus-config
+        - name: prometheus-config-volume
+          configMap:
+            name: prometheus-config
       restartPolicy: Always
 ---
 apiVersion: v1
@@ -85,8 +85,9 @@ spec:
   selector:
     app: prometheus
   ports:
-  - name: http
-    protocol: TCP
-    port: 9090
-    targetPort: 9090
+    - name: http
+      protocol: TCP
+      port: 9090
+      targetPort: 9090
 ---
+
diff --git a/manifests/servicemonitors.yaml b/manifests/servicemonitors.yaml
index 1f7f3322d77e3e06a0fd902baad4481e77e143ac..ccfe774b3a4b860c5e7f393ee9e3d8ca4eb097ae 100644
--- a/manifests/servicemonitors.yaml
+++ b/manifests/servicemonitors.yaml
@@ -20,9 +20,9 @@ metadata:
   labels:
     app: contextservice
     #release: prometheus
-    #release: prom  # name of the release 
-    # ( VERY IMPORTANT: You need to know the correct release name by viewing 
-    #   the servicemonitor of Prometheus itself: Without the correct name, 
+    #release: prom  # name of the release
+    # ( VERY IMPORTANT: You need to know the correct release name by viewing
+    #   the servicemonitor of Prometheus itself: Without the correct name,
     #   Prometheus cannot identify the metrics of the Flask app as the target.)
 spec:
   selector:
@@ -32,14 +32,14 @@ spec:
       app: contextservice # same as above
       #release: prometheus # same as above
   endpoints:
-  - port: metrics # named port in target app
-    scheme: http
-    path: /metrics # path to scrape
-    interval: 5s # scrape interval
+    - port: metrics # named port in target app
+      scheme: http
+      path: /metrics # path to scrape
+      interval: 5s # scrape interval
   namespaceSelector:
     any: false
     matchNames:
-    - tfs # namespace where the app is running
+      - tfs # namespace where the app is running
 ---
 apiVersion: monitoring.coreos.com/v1
 kind: ServiceMonitor
@@ -49,9 +49,9 @@ metadata:
   labels:
     app: deviceservice
     #release: prometheus
-    #release: prom  # name of the release 
-    # ( VERY IMPORTANT: You need to know the correct release name by viewing 
-    #   the servicemonitor of Prometheus itself: Without the correct name, 
+    #release: prom  # name of the release
+    # ( VERY IMPORTANT: You need to know the correct release name by viewing
+    #   the servicemonitor of Prometheus itself: Without the correct name,
     #   Prometheus cannot identify the metrics of the Flask app as the target.)
 spec:
   selector:
@@ -61,14 +61,14 @@ spec:
       app: deviceservice # same as above
       #release: prometheus # same as above
   endpoints:
-  - port: metrics # named port in target app
-    scheme: http
-    path: /metrics # path to scrape
-    interval: 5s # scrape interval
+    - port: metrics # named port in target app
+      scheme: http
+      path: /metrics # path to scrape
+      interval: 5s # scrape interval
   namespaceSelector:
     any: false
     matchNames:
-    - tfs # namespace where the app is running
+      - tfs # namespace where the app is running
 ---
 apiVersion: monitoring.coreos.com/v1
 kind: ServiceMonitor
@@ -78,9 +78,9 @@ metadata:
   labels:
     app: serviceservice
     #release: prometheus
-    #release: prom  # name of the release 
-    # ( VERY IMPORTANT: You need to know the correct release name by viewing 
-    #   the servicemonitor of Prometheus itself: Without the correct name, 
+    #release: prom  # name of the release
+    # ( VERY IMPORTANT: You need to know the correct release name by viewing
+    #   the servicemonitor of Prometheus itself: Without the correct name,
     #   Prometheus cannot identify the metrics of the Flask app as the target.)
 spec:
   selector:
@@ -90,14 +90,14 @@ spec:
       app: serviceservice # same as above
       #release: prometheus # same as above
   endpoints:
-  - port: metrics # named port in target app
-    scheme: http
-    path: /metrics # path to scrape
-    interval: 5s # scrape interval
+    - port: metrics # named port in target app
+      scheme: http
+      path: /metrics # path to scrape
+      interval: 5s # scrape interval
   namespaceSelector:
     any: false
     matchNames:
-    - tfs # namespace where the app is running
+      - tfs # namespace where the app is running
 ---
 apiVersion: monitoring.coreos.com/v1
 kind: ServiceMonitor
@@ -107,9 +107,9 @@ metadata:
   labels:
     app: sliceservice
     #release: prometheus
-    #release: prom  # name of the release 
-    # ( VERY IMPORTANT: You need to know the correct release name by viewing 
-    #   the servicemonitor of Prometheus itself: Without the correct name, 
+    #release: prom  # name of the release
+    # ( VERY IMPORTANT: You need to know the correct release name by viewing
+    #   the servicemonitor of Prometheus itself: Without the correct name,
     #   Prometheus cannot identify the metrics of the Flask app as the target.)
 spec:
   selector:
@@ -119,14 +119,14 @@ spec:
       app: sliceservice # same as above
       #release: prometheus # same as above
   endpoints:
-  - port: metrics # named port in target app
-    scheme: http
-    path: /metrics # path to scrape
-    interval: 5s # scrape interval
+    - port: metrics # named port in target app
+      scheme: http
+      path: /metrics # path to scrape
+      interval: 5s # scrape interval
   namespaceSelector:
     any: false
     matchNames:
-    - tfs # namespace where the app is running
+      - tfs # namespace where the app is running
 ---
 apiVersion: monitoring.coreos.com/v1
 kind: ServiceMonitor
@@ -136,9 +136,9 @@ metadata:
   labels:
     app: pathcompservice
     #release: prometheus
-    #release: prom  # name of the release 
-    # ( VERY IMPORTANT: You need to know the correct release name by viewing 
-    #   the servicemonitor of Prometheus itself: Without the correct name, 
+    #release: prom  # name of the release
+    # ( VERY IMPORTANT: You need to know the correct release name by viewing
+    #   the servicemonitor of Prometheus itself: Without the correct name,
     #   Prometheus cannot identify the metrics of the Flask app as the target.)
 spec:
   selector:
@@ -148,14 +148,14 @@ spec:
       app: pathcompservice # same as above
       #release: prometheus # same as above
   endpoints:
-  - port: metrics # named port in target app
-    scheme: http
-    path: /metrics # path to scrape
-    interval: 5s # scrape interval
+    - port: metrics # named port in target app
+      scheme: http
+      path: /metrics # path to scrape
+      interval: 5s # scrape interval
   namespaceSelector:
     any: false
     matchNames:
-    - tfs # namespace where the app is running
+      - tfs # namespace where the app is running
 ---
 apiVersion: monitoring.coreos.com/v1
 kind: ServiceMonitor
@@ -165,9 +165,9 @@ metadata:
   labels:
     app: monitoringservice
     #release: prometheus
-    #release: prom  # name of the release 
-    # ( VERY IMPORTANT: You need to know the correct release name by viewing 
-    #   the servicemonitor of Prometheus itself: Without the correct name, 
+    #release: prom  # name of the release
+    # ( VERY IMPORTANT: You need to know the correct release name by viewing
+    #   the servicemonitor of Prometheus itself: Without the correct name,
     #   Prometheus cannot identify the metrics of the Flask app as the target.)
 spec:
   selector:
@@ -177,14 +177,14 @@ spec:
       app: monitoringservice # same as above
       #release: prometheus # same as above
   endpoints:
-  - port: metrics # named port in target app
-    scheme: http
-    path: /metrics # path to scrape
-    interval: 5s # scrape interval
+    - port: metrics # named port in target app
+      scheme: http
+      path: /metrics # path to scrape
+      interval: 5s # scrape interval
   namespaceSelector:
     any: false
     matchNames:
-    - tfs # namespace where the app is running
+      - tfs # namespace where the app is running
 ---
 apiVersion: monitoring.coreos.com/v1
 kind: ServiceMonitor
@@ -194,9 +194,9 @@ metadata:
   labels:
     app: dltservice
     #release: prometheus
-    #release: prom  # name of the release 
-    # ( VERY IMPORTANT: You need to know the correct release name by viewing 
-    #   the servicemonitor of Prometheus itself: Without the correct name, 
+    #release: prom  # name of the release
+    # ( VERY IMPORTANT: You need to know the correct release name by viewing
+    #   the servicemonitor of Prometheus itself: Without the correct name,
     #   Prometheus cannot identify the metrics of the Flask app as the target.)
 spec:
   selector:
@@ -206,14 +206,14 @@ spec:
       app: dltservice # same as above
       #release: prometheus # same as above
   endpoints:
-  - port: metrics # named port in target app
-    scheme: http
-    path: /metrics # path to scrape
-    interval: 5s # scrape interval
+    - port: metrics # named port in target app
+      scheme: http
+      path: /metrics # path to scrape
+      interval: 5s # scrape interval
   namespaceSelector:
     any: false
     matchNames:
-    - tfs # namespace where the app is running
+      - tfs # namespace where the app is running
 ---
 apiVersion: monitoring.coreos.com/v1
 kind: ServiceMonitor
@@ -223,9 +223,9 @@ metadata:
   labels:
     app: interdomainservice
     #release: prometheus
-    #release: prom  # name of the release 
-    # ( VERY IMPORTANT: You need to know the correct release name by viewing 
-    #   the servicemonitor of Prometheus itself: Without the correct name, 
+    #release: prom  # name of the release
+    # ( VERY IMPORTANT: You need to know the correct release name by viewing
+    #   the servicemonitor of Prometheus itself: Without the correct name,
     #   Prometheus cannot identify the metrics of the Flask app as the target.)
 spec:
   selector:
@@ -235,14 +235,14 @@ spec:
       app: interdomainservice # same as above
       #release: prometheus # same as above
   endpoints:
-  - port: metrics # named port in target app
-    scheme: http
-    path: /metrics # path to scrape
-    interval: 5s # scrape interval
+    - port: metrics # named port in target app
+      scheme: http
+      path: /metrics # path to scrape
+      interval: 5s # scrape interval
   namespaceSelector:
     any: false
     matchNames:
-    - tfs # namespace where the app is running
+      - tfs # namespace where the app is running
 ---
 apiVersion: monitoring.coreos.com/v1
 kind: ServiceMonitor
@@ -252,9 +252,9 @@ metadata:
   labels:
     app: policyservice
     #release: prometheus
-    #release: prom  # name of the release 
-    # ( VERY IMPORTANT: You need to know the correct release name by viewing 
-    #   the servicemonitor of Prometheus itself: Without the correct name, 
+    #release: prom  # name of the release
+    # ( VERY IMPORTANT: You need to know the correct release name by viewing
+    #   the servicemonitor of Prometheus itself: Without the correct name,
     #   Prometheus cannot identify the metrics of the Flask app as the target.)
 spec:
   selector:
@@ -264,14 +264,14 @@ spec:
       app: policyservice # same as above
       #release: prometheus # same as above
   endpoints:
-  - port: metrics # named port in target app
-    scheme: http
-    path: /q/metrics # path to scrape
-    interval: 5s # scrape interval
+    - port: metrics # named port in target app
+      scheme: http
+      path: /q/metrics # path to scrape
+      interval: 5s # scrape interval
   namespaceSelector:
     any: false
     matchNames:
-    - tfs # namespace where the app is running
+      - tfs # namespace where the app is running
 ---
 apiVersion: monitoring.coreos.com/v1
 kind: ServiceMonitor
@@ -281,9 +281,9 @@ metadata:
   labels:
     app: ztpservice
     #release: prometheus
-    #release: prom  # name of the release 
-    # ( VERY IMPORTANT: You need to know the correct release name by viewing 
-    #   the servicemonitor of Prometheus itself: Without the correct name, 
+    #release: prom  # name of the release
+    # ( VERY IMPORTANT: You need to know the correct release name by viewing
+    #   the servicemonitor of Prometheus itself: Without the correct name,
     #   Prometheus cannot identify the metrics of the Flask app as the target.)
 spec:
   selector:
@@ -293,14 +293,14 @@ spec:
       app: ztpservice # same as above
       #release: prometheus # same as above
   endpoints:
-  - port: metrics # named port in target app
-    scheme: http
-    path: /q/metrics # path to scrape
-    interval: 5s # scrape interval
+    - port: metrics # named port in target app
+      scheme: http
+      path: /q/metrics # path to scrape
+      interval: 5s # scrape interval
   namespaceSelector:
     any: false
     matchNames:
-    - tfs # namespace where the app is running
+      - tfs # namespace where the app is running
 ---
 apiVersion: monitoring.coreos.com/v1
 kind: ServiceMonitor
@@ -310,9 +310,9 @@ metadata:
   labels:
     app: nbiservice
     #release: prometheus
-    #release: prom  # name of the release 
-    # ( VERY IMPORTANT: You need to know the correct release name by viewing 
-    #   the servicemonitor of Prometheus itself: Without the correct name, 
+    #release: prom  # name of the release
+    # ( VERY IMPORTANT: You need to know the correct release name by viewing
+    #   the servicemonitor of Prometheus itself: Without the correct name,
     #   Prometheus cannot identify the metrics of the Flask app as the target.)
 spec:
   selector:
@@ -322,14 +322,14 @@ spec:
       app: nbiservice # same as above
       #release: prometheus # same as above
   endpoints:
-  - port: metrics # named port in target app
-    scheme: http
-    path: /metrics # path to scrape
-    interval: 5s # scrape interval
+    - port: metrics # named port in target app
+      scheme: http
+      path: /metrics # path to scrape
+      interval: 5s # scrape interval
   namespaceSelector:
     any: false
     matchNames:
-    - tfs # namespace where the app is running
+      - tfs # namespace where the app is running
 ---
 apiVersion: monitoring.coreos.com/v1
 kind: ServiceMonitor
@@ -339,9 +339,9 @@ metadata:
   labels:
     app: load-generatorservice
     #release: prometheus
-    #release: prom  # name of the release 
-    # ( VERY IMPORTANT: You need to know the correct release name by viewing 
-    #   the servicemonitor of Prometheus itself: Without the correct name, 
+    #release: prom  # name of the release
+    # ( VERY IMPORTANT: You need to know the correct release name by viewing
+    #   the servicemonitor of Prometheus itself: Without the correct name,
     #   Prometheus cannot identify the metrics of the Flask app as the target.)
 spec:
   selector:
@@ -351,14 +351,14 @@ spec:
       app: load-generatorservice # same as above
       #release: prometheus # same as above
   endpoints:
-  - port: metrics # named port in target app
-    scheme: http
-    path: /metrics # path to scrape
-    interval: 5s # scrape interval
+    - port: metrics # named port in target app
+      scheme: http
+      path: /metrics # path to scrape
+      interval: 5s # scrape interval
   namespaceSelector:
     any: false
     matchNames:
-    - tfs # namespace where the app is running
+      - tfs # namespace where the app is running
 ---
 apiVersion: monitoring.coreos.com/v1
 kind: ServiceMonitor
@@ -368,9 +368,9 @@ metadata:
   labels:
     app: dbscanservingservice
     #release: prometheus
-    #release: prom  # name of the release 
-    # ( VERY IMPORTANT: You need to know the correct release name by viewing 
-    #   the servicemonitor of Prometheus itself: Without the correct name, 
+    #release: prom  # name of the release
+    # ( VERY IMPORTANT: You need to know the correct release name by viewing
+    #   the servicemonitor of Prometheus itself: Without the correct name,
     #   Prometheus cannot identify the metrics of the Flask app as the target.)
 spec:
   selector:
@@ -380,14 +380,14 @@ spec:
       app: dbscanservingservice # same as above
       #release: prometheus # same as above
   endpoints:
-  - port: metrics # named port in target app
-    scheme: http
-    path: /metrics # path to scrape
-    interval: 5s # scrape interval
+    - port: metrics # named port in target app
+      scheme: http
+      path: /metrics # path to scrape
+      interval: 5s # scrape interval
   namespaceSelector:
     any: false
     matchNames:
-    - tfs # namespace where the app is running
+      - tfs # namespace where the app is running
 ---
 apiVersion: monitoring.coreos.com/v1
 kind: ServiceMonitor
@@ -397,9 +397,9 @@ metadata:
   labels:
     app: opticalattackmitigatorservice
     #release: prometheus
-    #release: prom  # name of the release 
-    # ( VERY IMPORTANT: You need to know the correct release name by viewing 
-    #   the servicemonitor of Prometheus itself: Without the correct name, 
+    #release: prom  # name of the release
+    # ( VERY IMPORTANT: You need to know the correct release name by viewing
+    #   the servicemonitor of Prometheus itself: Without the correct name,
     #   Prometheus cannot identify the metrics of the Flask app as the target.)
 spec:
   selector:
@@ -409,14 +409,14 @@ spec:
       app: opticalattackmitigatorservice # same as above
       #release: prometheus # same as above
   endpoints:
-  - port: metrics # named port in target app
-    scheme: http
-    path: /metrics # path to scrape
-    interval: 5s # scrape interval
+    - port: metrics # named port in target app
+      scheme: http
+      path: /metrics # path to scrape
+      interval: 5s # scrape interval
   namespaceSelector:
     any: false
     matchNames:
-    - tfs # namespace where the app is running
+      - tfs # namespace where the app is running
 ---
 apiVersion: monitoring.coreos.com/v1
 kind: ServiceMonitor
@@ -426,9 +426,9 @@ metadata:
   labels:
     app: opticalattackdetectorservice
     #release: prometheus
-    #release: prom  # name of the release 
-    # ( VERY IMPORTANT: You need to know the correct release name by viewing 
-    #   the servicemonitor of Prometheus itself: Without the correct name, 
+    #release: prom  # name of the release
+    # ( VERY IMPORTANT: You need to know the correct release name by viewing
+    #   the servicemonitor of Prometheus itself: Without the correct name,
     #   Prometheus cannot identify the metrics of the Flask app as the target.)
 spec:
   selector:
@@ -438,14 +438,14 @@ spec:
       app: opticalattackdetectorservice # same as above
       #release: prometheus # same as above
   endpoints:
-  - port: metrics # named port in target app
-    scheme: http
-    path: /metrics # path to scrape
-    interval: 5s # scrape interval
+    - port: metrics # named port in target app
+      scheme: http
+      path: /metrics # path to scrape
+      interval: 5s # scrape interval
   namespaceSelector:
     any: false
     matchNames:
-    - tfs # namespace where the app is running
+      - tfs # namespace where the app is running
 ---
 apiVersion: monitoring.coreos.com/v1
 kind: ServiceMonitor
@@ -455,9 +455,9 @@ metadata:
   labels:
     app: opticalattackmanagerservice
     #release: prometheus
-    #release: prom  # name of the release 
-    # ( VERY IMPORTANT: You need to know the correct release name by viewing 
-    #   the servicemonitor of Prometheus itself: Without the correct name, 
+    #release: prom  # name of the release
+    # ( VERY IMPORTANT: You need to know the correct release name by viewing
+    #   the servicemonitor of Prometheus itself: Without the correct name,
     #   Prometheus cannot identify the metrics of the Flask app as the target.)
 spec:
   selector:
@@ -467,11 +467,11 @@ spec:
       app: opticalattackmanagerservice # same as above
       #release: prometheus # same as above
   endpoints:
-  - port: metrics # named port in target app
-    scheme: http
-    path: /metrics # path to scrape
-    interval: 5s # scrape interval
+    - port: metrics # named port in target app
+      scheme: http
+      path: /metrics # path to scrape
+      interval: 5s # scrape interval
   namespaceSelector:
     any: false
     matchNames:
-    - tfs # namespace where the app is running
+      - tfs # namespace where the app is running
diff --git a/manifests/serviceservice.yaml b/manifests/serviceservice.yaml
index 7d7bdaa4ef9ad4972da6236071810c63a9faa4f8..2fb7ebb8756a48b0a909734b7b9a90a44d79b9ea 100644
--- a/manifests/serviceservice.yaml
+++ b/manifests/serviceservice.yaml
@@ -28,28 +28,28 @@ spec:
     spec:
       terminationGracePeriodSeconds: 5
       containers:
-      - name: server
-        image: labs.etsi.org:5050/tfs/controller/service:latest
-        imagePullPolicy: Always
-        ports:
-        - containerPort: 3030
-        - containerPort: 9192
-        env:
-        - name: LOG_LEVEL
-          value: "INFO"
-        readinessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:3030"]
-        livenessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:3030"]
-        resources:
-          requests:
-            cpu: 250m
-            memory: 128Mi
-          limits:
-            cpu: 1000m
-            memory: 1024Mi
+        - name: server
+          image: labs.etsi.org:5050/tfs/controller/service:latest
+          imagePullPolicy: Always
+          ports:
+            - containerPort: 3030
+            - containerPort: 9192
+          env:
+            - name: LOG_LEVEL
+              value: "INFO"
+          readinessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:3030"]
+          livenessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:3030"]
+          resources:
+            requests:
+              cpu: 250m
+              memory: 128Mi
+            limits:
+              cpu: 1000m
+              memory: 1024Mi
 ---
 apiVersion: v1
 kind: Service
@@ -62,14 +62,14 @@ spec:
   selector:
     app: serviceservice
   ports:
-  - name: grpc
-    protocol: TCP
-    port: 3030
-    targetPort: 3030
-  - name: metrics
-    protocol: TCP
-    port: 9192
-    targetPort: 9192
+    - name: grpc
+      protocol: TCP
+      port: 3030
+      targetPort: 3030
+    - name: metrics
+      protocol: TCP
+      port: 9192
+      targetPort: 9192
 ---
 apiVersion: autoscaling/v2
 kind: HorizontalPodAutoscaler
@@ -83,12 +83,12 @@ spec:
   minReplicas: 1
   maxReplicas: 20
   metrics:
-  - type: Resource
-    resource:
-      name: cpu
-      target:
-        type: Utilization
-        averageUtilization: 80
+    - type: Resource
+      resource:
+        name: cpu
+        target:
+          type: Utilization
+          averageUtilization: 80
   #behavior:
   #  scaleDown:
   #    stabilizationWindowSeconds: 30
diff --git a/manifests/sliceservice.yaml b/manifests/sliceservice.yaml
index e7e5c1604a8b971424ff5f7e5bf292c4b263cbfe..0daa8e70f4965274be563a8e5f703855281fe698 100644
--- a/manifests/sliceservice.yaml
+++ b/manifests/sliceservice.yaml
@@ -28,33 +28,33 @@ spec:
     spec:
       terminationGracePeriodSeconds: 5
       containers:
-      - name: server
-        image: labs.etsi.org:5050/tfs/controller/slice:latest
-        imagePullPolicy: Always
-        ports:
-        - containerPort: 4040
-        - containerPort: 9192
-        env:
-        - name: LOG_LEVEL
-          value: "INFO"
-        - name: SLICE_GROUPING
-          value: "DISABLE"
-        envFrom:
-        - secretRef:
-            name: qdb-data
-        readinessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:4040"]
-        livenessProbe:
-          exec:
-            command: ["/bin/grpc_health_probe", "-addr=:4040"]
-        resources:
-          requests:
-            cpu: 250m
-            memory: 128Mi
-          limits:
-            cpu: 1000m
-            memory: 1024Mi
+        - name: server
+          image: labs.etsi.org:5050/tfs/controller/slice:latest
+          imagePullPolicy: Always
+          ports:
+            - containerPort: 4040
+            - containerPort: 9192
+          env:
+            - name: LOG_LEVEL
+              value: "INFO"
+            - name: SLICE_GROUPING
+              value: "DISABLE"
+          envFrom:
+            - secretRef:
+                name: qdb-data
+          readinessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:4040"]
+          livenessProbe:
+            exec:
+              command: ["/bin/grpc_health_probe", "-addr=:4040"]
+          resources:
+            requests:
+              cpu: 250m
+              memory: 128Mi
+            limits:
+              cpu: 1000m
+              memory: 1024Mi
 ---
 apiVersion: v1
 kind: Service
@@ -67,14 +67,14 @@ spec:
   selector:
     app: sliceservice
   ports:
-  - name: grpc
-    protocol: TCP
-    port: 4040
-    targetPort: 4040
-  - name: metrics
-    protocol: TCP
-    port: 9192
-    targetPort: 9192
+    - name: grpc
+      protocol: TCP
+      port: 4040
+      targetPort: 4040
+    - name: metrics
+      protocol: TCP
+      port: 9192
+      targetPort: 9192
 ---
 apiVersion: autoscaling/v2
 kind: HorizontalPodAutoscaler
@@ -88,12 +88,12 @@ spec:
   minReplicas: 1
   maxReplicas: 20
   metrics:
-  - type: Resource
-    resource:
-      name: cpu
-      target:
-        type: Utilization
-        averageUtilization: 80
+    - type: Resource
+      resource:
+        name: cpu
+        target:
+          type: Utilization
+          averageUtilization: 80
   #behavior:
   #  scaleDown:
   #    stabilizationWindowSeconds: 30
diff --git a/manifests/teservice.yaml b/manifests/teservice.yaml
index 15f1619df08069f00db883f0b918c17837c707d1..ec8f2e3d6ad360eab1a1869e9564fd6c03561e06 100644
--- a/manifests/teservice.yaml
+++ b/manifests/teservice.yaml
@@ -30,37 +30,37 @@ spec:
       terminationGracePeriodSeconds: 5
       shareProcessNamespace: true
       containers:
-      - name: server
-        image: labs.etsi.org:5050/tfs/controller/te:latest
-        imagePullPolicy: Always
-        ports:
-        - containerPort: 10030
-        env:
-        - name: ERLANG_LOGGER_LEVEL
-          value: "debug"
-        - name: ERLANG_COOKIE
-          value: "tfte-unsafe-cookie"
-        - name: ERLANG_NODE_NAME
-          valueFrom:
-            fieldRef:
-              fieldPath: metadata.name
-        - name: ERLANG_NODE_IP
-          valueFrom:
-            fieldRef:
-              fieldPath: status.podIP
-        readinessProbe:
-          exec:
-            command: ["/tfte/bin/tfte", "status"]
-        livenessProbe:
-          exec:
-            command: ["/tfte/bin/tfte", "status"]
-        resources:
-          requests:
-            cpu: 250m
-            memory: 512Mi
-          limits:
-            cpu: 700m
-            memory: 1024Mi
+        - name: server
+          image: labs.etsi.org:5050/tfs/controller/te:latest
+          imagePullPolicy: Always
+          ports:
+            - containerPort: 10030
+          env:
+            - name: ERLANG_LOGGER_LEVEL
+              value: "debug"
+            - name: ERLANG_COOKIE
+              value: "tfte-unsafe-cookie"
+            - name: ERLANG_NODE_NAME
+              valueFrom:
+                fieldRef:
+                  fieldPath: metadata.name
+            - name: ERLANG_NODE_IP
+              valueFrom:
+                fieldRef:
+                  fieldPath: status.podIP
+          readinessProbe:
+            exec:
+              command: ["/tfte/bin/tfte", "status"]
+          livenessProbe:
+            exec:
+              command: ["/tfte/bin/tfte", "status"]
+          resources:
+            requests:
+              cpu: 250m
+              memory: 512Mi
+            limits:
+              cpu: 700m
+              memory: 1024Mi
 ---
 apiVersion: v1
 kind: Service
@@ -71,11 +71,11 @@ spec:
   selector:
     app: teservice
   ports:
-  - name: grpc
-    protocol: TCP
-    port: 10030
-    targetPort: 10030
-  - name: pcep
-    protocol: TCP
-    port: 4189
-    targetPort: 4189
+    - name: grpc
+      protocol: TCP
+      port: 10030
+      targetPort: 10030
+    - name: pcep
+      protocol: TCP
+      port: 4189
+      targetPort: 4189
diff --git a/manifests/webuiservice.yaml b/manifests/webuiservice.yaml
index 43caa9f04b56d6477d82c5a5bb22cb292eec8a90..bb2573c454a7bf59364a7526a1b5193111daf892 100644
--- a/manifests/webuiservice.yaml
+++ b/manifests/webuiservice.yaml
@@ -32,73 +32,73 @@ spec:
         supplementalGroups:
           - 0
       containers:
-      - name: server
-        image: labs.etsi.org:5050/tfs/controller/webui:latest
-        imagePullPolicy: Always
-        ports:
-        - containerPort: 8004
-        env:
-        - name: LOG_LEVEL
-          value: "INFO"
-        - name: WEBUISERVICE_SERVICE_BASEURL_HTTP
-          value: "/webui/"
-        readinessProbe:
-          httpGet:
-            path: /healthz/ready
-            port: 8004
-          initialDelaySeconds: 5
-          timeoutSeconds: 1
-        livenessProbe:
-          httpGet:
-            path: /healthz/live
-            port: 8004
-          initialDelaySeconds: 5
-          timeoutSeconds: 1
-        resources:
-          requests:
-            cpu: 50m
-            memory: 128Mi
-          limits:
-            cpu: 1000m
-            memory: 1024Mi
-      - name: grafana
-        image: grafana/grafana:8.5.22
-        imagePullPolicy: IfNotPresent
-        ports:
-          - containerPort: 3000
-            name: http-grafana
-            protocol: TCP
-        env:
-        - name: GF_SERVER_ROOT_URL
-          value: "http://0.0.0.0:3000/grafana/"
-        - name: GF_SERVER_SERVE_FROM_SUB_PATH
-          value: "true"
-        readinessProbe:
-          failureThreshold: 60
-          httpGet:
-            #path: /robots.txt
-            path: /login
-            port: 3000
-            scheme: HTTP
-          initialDelaySeconds: 1
-          periodSeconds: 1
-          successThreshold: 1
-          timeoutSeconds: 2
-        livenessProbe:
-          failureThreshold: 60
-          initialDelaySeconds: 1
-          periodSeconds: 1
-          successThreshold: 1
-          tcpSocket:
-            port: 3000
-          timeoutSeconds: 1
-        resources:
-          requests:
-            cpu: 250m
-            memory: 512Mi
-          limits:
-            cpu: 500m
-            memory: 1024Mi
+        - name: server
+          image: labs.etsi.org:5050/tfs/controller/webui:latest
+          imagePullPolicy: Always
+          ports:
+            - containerPort: 8004
+          env:
+            - name: LOG_LEVEL
+              value: "INFO"
+            - name: WEBUISERVICE_SERVICE_BASEURL_HTTP
+              value: "/webui/"
+          readinessProbe:
+            httpGet:
+              path: /healthz/ready
+              port: 8004
+            initialDelaySeconds: 5
+            timeoutSeconds: 1
+          livenessProbe:
+            httpGet:
+              path: /healthz/live
+              port: 8004
+            initialDelaySeconds: 5
+            timeoutSeconds: 1
+          resources:
+            requests:
+              cpu: 50m
+              memory: 128Mi
+            limits:
+              cpu: 1000m
+              memory: 1024Mi
+        - name: grafana
+          image: grafana/grafana:8.5.22
+          imagePullPolicy: IfNotPresent
+          ports:
+            - containerPort: 3000
+              name: http-grafana
+              protocol: TCP
+          env:
+            - name: GF_SERVER_ROOT_URL
+              value: "http://0.0.0.0:3000/grafana/"
+            - name: GF_SERVER_SERVE_FROM_SUB_PATH
+              value: "true"
+          readinessProbe:
+            failureThreshold: 60
+            httpGet:
+              #path: /robots.txt
+              path: /login
+              port: 3000
+              scheme: HTTP
+            initialDelaySeconds: 1
+            periodSeconds: 1
+            successThreshold: 1
+            timeoutSeconds: 2
+          livenessProbe:
+            failureThreshold: 60
+            initialDelaySeconds: 1
+            periodSeconds: 1
+            successThreshold: 1
+            tcpSocket:
+              port: 3000
+            timeoutSeconds: 1
+          resources:
+            requests:
+              cpu: 250m
+              memory: 512Mi
+            limits:
+              cpu: 500m
+              memory: 1024Mi
 ---
 apiVersion: v1
 kind: Service
@@ -111,9 +111,9 @@ spec:
   selector:
     app: webuiservice
   ports:
-  - name: webui
-    port: 8004
-    targetPort: 8004
-  - name: grafana
-    port: 3000
-    targetPort: 3000
+    - name: webui
+      port: 8004
+      targetPort: 8004
+    - name: grafana
+      port: 3000
+      targetPort: 3000
diff --git a/manifests/ztpservice.yaml b/manifests/ztpservice.yaml
index e2be80cea7b1e779fdc9bb05110ddc0d6b144101..608bab125be80decfc36ce290d1a3f666ff23229 100644
--- a/manifests/ztpservice.yaml
+++ b/manifests/ztpservice.yaml
@@ -104,22 +104,22 @@ spec:
             limits:
               cpu: 2000m
               memory: 2048Mi
----
-apiVersion: autoscaling/v2
-kind: HorizontalPodAutoscaler
-metadata:
-  name: ztpservice-hpa
-spec:
-  scaleTargetRef:
-    apiVersion: apps/v1
-    kind: Deployment
-    name: ztpservice
-  minReplicas: 1
-  maxReplicas: 10
-  metrics:
-  - type: Resource
-    resource:
-      name: cpu
-      target:
-        type: Utilization
-        averageUtilization: 80
+#---
+#apiVersion: autoscaling/v2
+#kind: HorizontalPodAutoscaler
+#metadata:
+#  name: ztpservice-hpa
+#spec:
+#  scaleTargetRef:
+#    apiVersion: apps/v1
+#    kind: Deployment
+#    name: ztpservice
+#  minReplicas: 1
+#  maxReplicas: 10
+#  metrics:
+#    - type: Resource
+#      resource:
+#        name: cpu
+#        target:
+#          type: Utilization
+#          averageUtilization: 80
diff --git a/expose_ingress_grpc.sh b/scripts/expose_ingress_grpc.sh
similarity index 100%
rename from expose_ingress_grpc.sh
rename to scripts/expose_ingress_grpc.sh
diff --git a/run_tests_docker.sh b/scripts/run_tests_docker.sh
similarity index 72%
rename from run_tests_docker.sh
rename to scripts/run_tests_docker.sh
index b7d897d76654cb1b0a357fd0e867f4e9f42a29f5..23d920487284245d5c2e23bb3c24f0f4248127a3 100755
--- a/run_tests_docker.sh
+++ b/scripts/run_tests_docker.sh
@@ -35,6 +35,21 @@ TMP_FOLDER="./tmp"
 TMP_LOGS_FOLDER="$TMP_FOLDER/logs"
 mkdir -p $TMP_LOGS_FOLDER
 
+DOCKER_BUILD="docker build"
+DOCKER_MAJOR_VERSION=$(docker --version | grep -o -E "Docker version [0-9]+\." | grep -o -E "[0-9]+" | cut -c 1-3)
+if [[ $DOCKER_MAJOR_VERSION -ge 23 ]]; then
+    # If Docker version >= 23, build command was migrated to docker-buildx
+    # In Ubuntu, in practice, means to install package docker-buildx together with docker.io
+    # Check if docker-buildx plugin is installed
+    docker buildx version 1>/dev/null 2>/dev/null
+    if [[ $? -ne 0 ]]; then
+        echo "Docker buildx command is not installed. Check: https://docs.docker.com/build/architecture/#install-buildx"
+        echo "If you installed docker through APT package docker.io, consider installing also package docker-buildx"
+        exit 1;
+    fi
+    DOCKER_BUILD="docker buildx build"
+fi
+
 for COMPONENT in $COMPONENTS; do
     echo "Processing '$COMPONENT' component..."
     IMAGE_NAME="$COMPONENT:$IMAGE_TAG"
@@ -44,9 +59,9 @@ for COMPONENT in $COMPONENTS; do
     BUILD_LOG="$TMP_LOGS_FOLDER/build_${COMPONENT}.log"
 
     if [ "$COMPONENT" == "ztp" ] || [ "$COMPONENT" == "policy" ]; then
-        docker build -t "$IMAGE_NAME" -f ./src/"$COMPONENT"/Dockerfile ./src/"$COMPONENT"/ > "$BUILD_LOG"
+        $DOCKER_BUILD -t "$IMAGE_NAME" -f ./src/"$COMPONENT"/Dockerfile ./src/"$COMPONENT"/ > "$BUILD_LOG"
     else 
-        docker build -t "$IMAGE_NAME" -f ./src/"$COMPONENT"/Dockerfile ./src/ > "$BUILD_LOG"
+        $DOCKER_BUILD -t "$IMAGE_NAME" -f ./src/"$COMPONENT"/Dockerfile ./src/ > "$BUILD_LOG"
     fi
 
     if [ -n "$REGISTRY_IMAGE" ]; then
diff --git a/src/start_webui_dev_mode.sh b/scripts/start_webui_dev_mode.sh
similarity index 100%
rename from src/start_webui_dev_mode.sh
rename to scripts/start_webui_dev_mode.sh
diff --git a/scripts/wait_context_nats.sh b/scripts/wait_context_nats.sh
new file mode 100755
index 0000000000000000000000000000000000000000..9005957412221250f32a900318a19d14715091bf
--- /dev/null
+++ b/scripts/wait_context_nats.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.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.
+
+########################################################################################################################
+# Define your deployment settings here
+########################################################################################################################
+
+# If not already set, set the name of the Kubernetes namespace to deploy to.
+export TFS_K8S_NAMESPACE=${TFS_K8S_NAMESPACE:-"tfs"}
+
+
+########################################################################################################################
+# Automated steps start here
+########################################################################################################################
+
+while ! kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server 2>&1 | grep -q 'Subscriber is Ready? True'; do sleep 1; done
diff --git a/src/bgpls_speaker/.gitlab-ci.yml b/src/bgpls_speaker/.gitlab-ci.yml
index 5020256266cf4f84b280985844f24dabad35c39c..50b5ebf69f81463af47f92b3c7129099575e8503 100644
--- a/src/bgpls_speaker/.gitlab-ci.yml
+++ b/src/bgpls_speaker/.gitlab-ci.yml
@@ -21,7 +21,7 @@ build bgpls_speaker:
   before_script:
     - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
   script:
-    - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile .
+    - docker 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:
diff --git a/src/common/tools/mutex_queues/MutexQueues.py b/src/common/tools/mutex_queues/MutexQueues.py
index 96e22a86f012cb8326c380a0ebbf0c1b40cae21c..e1843250093b9ac8c6ce4046f627e2d5251fba55 100644
--- a/src/common/tools/mutex_queues/MutexQueues.py
+++ b/src/common/tools/mutex_queues/MutexQueues.py
@@ -46,7 +46,16 @@ class MutexQueues:
         # dictionaty of queues of mutexes: queue_name => queue[mutex]
         # first mutex is the running one
         self.mutex_queues : Dict[str, Queue[threading.Event]] = dict()
-    
+
+    def add_alias(self, queue_name_a : str, queue_name_b : str) -> None:
+        with self.lock:
+            if queue_name_a in self.mutex_queues and queue_name_b not in self.mutex_queues:
+                self.mutex_queues[queue_name_b] = self.mutex_queues[queue_name_a]
+            elif queue_name_b in self.mutex_queues and queue_name_a not in self.mutex_queues:
+                self.mutex_queues[queue_name_a] = self.mutex_queues[queue_name_b]
+            elif queue_name_b not in self.mutex_queues and queue_name_a not in self.mutex_queues:
+                self.mutex_queues[queue_name_b] = self.mutex_queues.setdefault(queue_name_a, Queue())
+
     def wait_my_turn(self, queue_name : str) -> None:
         # create my mutex and enqueue it
         mutex = threading.Event()
diff --git a/src/context/.gitlab-ci.yml b/src/context/.gitlab-ci.yml
index 5de4bc1fcbb5bea98a7675253efe060df03a1237..eb12743c3dedce2642cde02a2d1b8a37e8bf19a9 100644
--- a/src/context/.gitlab-ci.yml
+++ b/src/context/.gitlab-ci.yml
@@ -21,7 +21,7 @@ build context:
   before_script:
     - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
   script:
-    - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile .
+    - docker 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:
diff --git a/src/context/service/database/Device.py b/src/context/service/database/Device.py
index 7f58ddeb55c65a17f0deb286b69a7343b1ae234b..d0674e89b03d160fc116c0f5ca5856b72769db78 100644
--- a/src/context/service/database/Device.py
+++ b/src/context/service/database/Device.py
@@ -203,15 +203,15 @@ def device_set(db_engine : Engine, messagebroker : MessageBroker, request : Devi
             stmt = stmt.returning(TopologyDeviceModel.topology_uuid)
             topology_uuids = session.execute(stmt).fetchall()
 
-            LOGGER.warning('RAW topology_uuids={:s}'.format(str(topology_uuids)))
+            #LOGGER.warning('RAW topology_uuids={:s}'.format(str(topology_uuids)))
             if len(topology_uuids) > 0:
                 topology_uuids = [topology_uuid[0] for topology_uuid in topology_uuids]
-                LOGGER.warning('NEW topology_uuids={:s}'.format(str(topology_uuids)))
+                #LOGGER.warning('NEW topology_uuids={:s}'.format(str(topology_uuids)))
                 query = session.query(TopologyModel)
                 query = query.filter(TopologyModel.topology_uuid.in_(topology_uuids))
                 device_topologies : List[TopologyModel] = query.all()
                 device_topology_ids = [obj.dump_id() for obj in device_topologies]
-                LOGGER.warning('device_topology_ids={:s}'.format(str(device_topology_ids)))
+                #LOGGER.warning('device_topology_ids={:s}'.format(str(device_topology_ids)))
 
         updated_components = False
         
@@ -233,7 +233,7 @@ def device_set(db_engine : Engine, messagebroker : MessageBroker, request : Devi
         
         changed_config_rules = upsert_config_rules(session, config_rules, device_uuid=device_uuid)
 
-        return updated or updated_endpoints or changed_config_rules, device_topology_ids
+        return updated or updated_endpoints or updated_components or changed_config_rules, device_topology_ids
 
     updated, device_topology_ids = run_transaction(sessionmaker(bind=db_engine), callback)
     device_id = json_device_id(device_uuid)
diff --git a/src/context/service/database/Link.py b/src/context/service/database/Link.py
index e2060c4542bebad82b1ed83dbcce612114862ae7..ccc22a472c4f3bcfc0655e9456f0b4403a3f6f9d 100644
--- a/src/context/service/database/Link.py
+++ b/src/context/service/database/Link.py
@@ -159,15 +159,15 @@ def link_set(db_engine : Engine, messagebroker : MessageBroker, request : Link)
             stmt = stmt.returning(TopologyLinkModel.topology_uuid)
             topology_uuids = session.execute(stmt).fetchall()
 
-            LOGGER.warning('RAW topology_uuids={:s}'.format(str(topology_uuids)))
+            #LOGGER.warning('RAW topology_uuids={:s}'.format(str(topology_uuids)))
             if len(topology_uuids) > 0:
                 topology_uuids = [topology_uuid[0] for topology_uuid in topology_uuids]
-                LOGGER.warning('NEW topology_uuids={:s}'.format(str(topology_uuids)))
+                #LOGGER.warning('NEW topology_uuids={:s}'.format(str(topology_uuids)))
                 query = session.query(TopologyModel)
                 query = query.filter(TopologyModel.topology_uuid.in_(topology_uuids))
                 link_topologies : List[TopologyModel] = query.all()
                 link_topology_ids = [obj.dump_id() for obj in link_topologies]
-                LOGGER.warning('link_topology_ids={:s}'.format(str(link_topology_ids)))
+                #LOGGER.warning('link_topology_ids={:s}'.format(str(link_topology_ids)))
 
         return updated or updated_endpoints, link_topology_ids
 
diff --git a/src/dbscanserving/.gitlab-ci.yml b/src/dbscanserving/.gitlab-ci.yml
index d665bdaf2993bc578024cfc7ef8517ae44ccef7a..2753e4c496198d5eef2d64ab66e0d9d52a179d3b 100644
--- a/src/dbscanserving/.gitlab-ci.yml
+++ b/src/dbscanserving/.gitlab-ci.yml
@@ -21,7 +21,7 @@ build dbscanserving:
   before_script:
     - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
   script:
-    - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile .
+    - docker 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:
diff --git a/src/device/.gitlab-ci.yml b/src/device/.gitlab-ci.yml
index bcc2e05e50f63fd6552bb53b4d23c0ae0e2e7302..83b18a1225d8a27fba5799fb761d2a49c7fb2090 100644
--- a/src/device/.gitlab-ci.yml
+++ b/src/device/.gitlab-ci.yml
@@ -21,7 +21,7 @@ build device:
   before_script:
     - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
   script:
-    - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile .
+    - docker 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:
diff --git a/src/device/service/DeviceServiceServicerImpl.py b/src/device/service/DeviceServiceServicerImpl.py
index 5e5d7540c0ffbc860ba912cbbcacc637b7d790c5..4f0ba5722ab6c66104e1aaaccba229c356911603 100644
--- a/src/device/service/DeviceServiceServicerImpl.py
+++ b/src/device/service/DeviceServiceServicerImpl.py
@@ -88,9 +88,11 @@ class DeviceServiceServicerImpl(DeviceServiceServicer):
 
         # update device_uuid to honor UUID provided by Context
         device_uuid = device.device_id.device_uuid.uuid
+        device_name = device.name
 
         t2 = time.time()
 
+        self.mutex_queues.add_alias(device_uuid, device_name)
         self.mutex_queues.wait_my_turn(device_uuid)
         t3 = time.time()
         try:
diff --git a/src/dlt/.gitlab-ci.yml b/src/dlt/.gitlab-ci.yml
index df30a7b1deb3360fbf8b578796fa39f3b7e736ba..7b14937a72a050b5029d38568875528f7880b041 100644
--- a/src/dlt/.gitlab-ci.yml
+++ b/src/dlt/.gitlab-ci.yml
@@ -22,8 +22,8 @@ build dlt:
     - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
   script:
     # This first build tags the builder resulting image to prevent being removed by dangling image removal command
-    - docker build -t "${IMAGE_NAME}-gateway:$IMAGE_TAG" -f ./src/$IMAGE_NAME/gateway/Dockerfile .
-    - docker build -t "${IMAGE_NAME}-connector:$IMAGE_TAG" -f ./src/$IMAGE_NAME/connector/Dockerfile .
+    - docker buildx build -t "${IMAGE_NAME}-gateway:$IMAGE_TAG" -f ./src/$IMAGE_NAME/gateway/Dockerfile .
+    - docker buildx build -t "${IMAGE_NAME}-connector:$IMAGE_TAG" -f ./src/$IMAGE_NAME/connector/Dockerfile .
     - docker tag "${IMAGE_NAME}-gateway:$IMAGE_TAG" "$CI_REGISTRY_IMAGE/${IMAGE_NAME}-gateway:$IMAGE_TAG"
     - docker tag "${IMAGE_NAME}-connector:$IMAGE_TAG" "$CI_REGISTRY_IMAGE/${IMAGE_NAME}-connector:$IMAGE_TAG"
     - docker push "$CI_REGISTRY_IMAGE/${IMAGE_NAME}-gateway:$IMAGE_TAG"
diff --git a/src/e2e_orchestrator/.gitlab-ci.yml b/src/e2e_orchestrator/.gitlab-ci.yml
index a14a215afc33067e923a7064b8f4617c61f4de9d..1dc93a8d4a4a45057532d6535465bcf985f42337 100644
--- a/src/e2e_orchestrator/.gitlab-ci.yml
+++ b/src/e2e_orchestrator/.gitlab-ci.yml
@@ -21,7 +21,7 @@ build e2eorchestrator:
   before_script:
     - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
   script:
-    - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile .
+    - docker 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:
diff --git a/src/forecaster/.gitlab-ci.yml b/src/forecaster/.gitlab-ci.yml
index 09b2f8f4e67db6ce152da608baff6f51279a1dc8..108febbf9f45354d5db1c9976955fb9ab274e032 100644
--- a/src/forecaster/.gitlab-ci.yml
+++ b/src/forecaster/.gitlab-ci.yml
@@ -21,7 +21,7 @@ build forecaster:
   before_script:
     - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
   script:
-    - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile .
+    - docker 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:
diff --git a/src/interdomain/.gitlab-ci.yml b/src/interdomain/.gitlab-ci.yml
index 486c6d0a931ff18be59ddaaa0268fcb1adfbaa2c..3cfd8c57ed339e28a709f0e219c822ea33294611 100644
--- a/src/interdomain/.gitlab-ci.yml
+++ b/src/interdomain/.gitlab-ci.yml
@@ -21,7 +21,7 @@ build interdomain:
   before_script:
     - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
   script:
-    - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile .
+    - docker 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:
diff --git a/src/l3_attackmitigator/.gitlab-ci.yml b/src/l3_attackmitigator/.gitlab-ci.yml
index c43b553a406bdbaf4cf77f80360469b87dd1c3e4..997c43649fb4ab9445b4f2830296e7e5e8654cef 100644
--- a/src/l3_attackmitigator/.gitlab-ci.yml
+++ b/src/l3_attackmitigator/.gitlab-ci.yml
@@ -21,7 +21,7 @@ build l3_attackmitigator:
   before_script:
     - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
   script:
-    - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile .
+    - docker 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:
diff --git a/src/l3_centralizedattackdetector/.gitlab-ci.yml b/src/l3_centralizedattackdetector/.gitlab-ci.yml
index 057545eb1b65aac26610c6460a47592b4e7604c2..ed0cb14d39fae9cecfb54ec0cedb9841ceec8f19 100644
--- a/src/l3_centralizedattackdetector/.gitlab-ci.yml
+++ b/src/l3_centralizedattackdetector/.gitlab-ci.yml
@@ -21,7 +21,7 @@ build l3_centralizedattackdetector:
   before_script:
     - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
   script:
-    - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile .
+    - docker 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:
diff --git a/src/l3_distributedattackdetector/.gitlab-ci.yml b/src/l3_distributedattackdetector/.gitlab-ci.yml
index 226cb642176a7d0854ee8dbdaf623cf7bcad1fc2..4740390864288ad9ab8daadc6360865ae718cf43 100644
--- a/src/l3_distributedattackdetector/.gitlab-ci.yml
+++ b/src/l3_distributedattackdetector/.gitlab-ci.yml
@@ -21,7 +21,7 @@ build l3_distributedattackdetector:
   before_script:
     - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
   script:
-    - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile .
+    - docker 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:
diff --git a/src/load_generator/.gitlab-ci.yml b/src/load_generator/.gitlab-ci.yml
index 5f2ee0d76105e57d31b0a6596d020ef53e65a631..3980c19e538931f3e8fc144b43da6729c9a97ce1 100644
--- a/src/load_generator/.gitlab-ci.yml
+++ b/src/load_generator/.gitlab-ci.yml
@@ -21,7 +21,7 @@ build load_generator:
   before_script:
     - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
   script:
-    - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile .
+    - docker 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:
diff --git a/src/monitoring/.gitlab-ci.yml b/src/monitoring/.gitlab-ci.yml
index 7c3a14975d9c7bf7d5d46be917203338bea7f1f9..6ee53bb60f57ea4b6e8477bfdd514dc59bdc7e19 100644
--- a/src/monitoring/.gitlab-ci.yml
+++ b/src/monitoring/.gitlab-ci.yml
@@ -21,7 +21,7 @@ build monitoring:
   before_script:
     - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
   script:
-    - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile .
+    - docker 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:
diff --git a/src/nbi/.gitlab-ci.yml b/src/nbi/.gitlab-ci.yml
index e0cac446a33b36a4fbe65b3da1ad5767582a77c6..2f711020284613b0a700a7dfc6a76b5bcb7f7e5c 100644
--- a/src/nbi/.gitlab-ci.yml
+++ b/src/nbi/.gitlab-ci.yml
@@ -21,7 +21,7 @@ build nbi:
   before_script:
     - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
   script:
-    - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile .
+    - docker 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:
diff --git a/src/opticalattackdetector/.gitlab-ci.yml b/src/opticalattackdetector/.gitlab-ci.yml
index d329cd265389a0e4680727e4ec62a4f970431531..61f404c167f6ac12788bf59ba2fe7a9c254e2852 100644
--- a/src/opticalattackdetector/.gitlab-ci.yml
+++ b/src/opticalattackdetector/.gitlab-ci.yml
@@ -21,7 +21,7 @@ build opticalattackdetector:
   before_script:
     - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
   script:
-    - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile .
+    - docker 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:
@@ -37,68 +37,68 @@ build opticalattackdetector:
       - manifests/${IMAGE_NAME}service.yaml
       - .gitlab-ci.yml
 
-# apply unit test to the opticalattackdetector component
-unit_test opticalattackdetector:
-  variables:
-    IMAGE_NAME: 'opticalattackdetector' # name of the microservice
-    IMAGE_TAG: 'latest' # tag of the container image (production, development, etc)
-  stage: unit_test
-  needs:
-    - build opticalattackdetector
-  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
-    - if docker container ls | grep redis; then docker rm -f redis; else echo "redis image is not in the system"; fi
-    - if docker container ls | grep dbscanserving; then docker rm -f dbscanserving; else echo "dbscanserving image is not in the system"; fi
-  script:
-    - export REDIS_PASSWORD=$(uuidgen)
-    - docker pull "redis:7.0-alpine"
-    - docker run --name redis -d --network=teraflowbridge -p 16379:6379 -e REDIS_PASSWORD=${REDIS_PASSWORD} --rm redis:7.0-alpine redis-server --requirepass ${REDIS_PASSWORD}
-    - while ! docker logs redis 2>&1 | grep -q 'Ready to accept connections'; do sleep 1; done
-    - docker logs redis
-    - REDIS_ADDRESS=$(docker inspect redis --format "{{.NetworkSettings.Networks.teraflowbridge.IPAddress}}")
-    - docker pull "$CI_REGISTRY_IMAGE/dbscanserving:$IMAGE_TAG"
-    - docker run --name dbscanserving -d -p 10008:10008 --network=teraflowbridge --rm $CI_REGISTRY_IMAGE/dbscanserving:$IMAGE_TAG "python -m dbscanserving.service"
-    - docker logs dbscanserving
-    - DBSCANSERVING_ADDRESS=$(docker inspect dbscanserving --format "{{.NetworkSettings.Networks.teraflowbridge.IPAddress}}")
-    - docker pull "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG"
-    - >
-      docker run --name $IMAGE_NAME -d -p 10006:10006 
-      -v "$PWD/src/$IMAGE_NAME/tests:/home/${IMAGE_NAME}/results" 
-      -e REDIS_PASSWORD=${REDIS_PASSWORD}
-      -e DBSCANSERVINGSERVICE_SERVICE_HOST=${DBSCANSERVING_ADDRESS}
-      -e CACHINGSERVICE_SERVICE_HOST=${REDIS_ADDRESS}
-      --network=teraflowbridge --rm $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=DEBUG --verbose $IMAGE_NAME/tests/test_unitary.py --junitxml=/home/${IMAGE_NAME}/results/${IMAGE_NAME}_report.xml"
-    - docker logs redis
-    - docker logs dbscanserving
-    - docker logs $IMAGE_NAME
-    - docker exec -i $IMAGE_NAME bash -c "coverage xml -o /home/${IMAGE_NAME}/results/${IMAGE_NAME}_coverage.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 rm -f redis
-    - docker rm -f dbscanserving
-    - 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/$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
+## apply unit test to the opticalattackdetector component
+#unit_test opticalattackdetector:
+#  variables:
+#    IMAGE_NAME: 'opticalattackdetector' # name of the microservice
+#    IMAGE_TAG: 'latest' # tag of the container image (production, development, etc)
+#  stage: unit_test
+#  needs:
+#    - build opticalattackdetector
+#  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
+#    - if docker container ls | grep redis; then docker rm -f redis; else echo "redis image is not in the system"; fi
+#    - if docker container ls | grep dbscanserving; then docker rm -f dbscanserving; else echo "dbscanserving image is not in the system"; fi
+#  script:
+#    - export REDIS_PASSWORD=$(uuidgen)
+#    - docker pull "redis:7.0-alpine"
+#    - docker run --name redis -d --network=teraflowbridge -p 16379:6379 -e REDIS_PASSWORD=${REDIS_PASSWORD} --rm redis:7.0-alpine redis-server --requirepass ${REDIS_PASSWORD}
+#    - while ! docker logs redis 2>&1 | grep -q 'Ready to accept connections'; do sleep 1; done
+#    - docker logs redis
+#    - REDIS_ADDRESS=$(docker inspect redis --format "{{.NetworkSettings.Networks.teraflowbridge.IPAddress}}")
+#    - docker pull "$CI_REGISTRY_IMAGE/dbscanserving:$IMAGE_TAG"
+#    - docker run --name dbscanserving -d -p 10008:10008 --network=teraflowbridge --rm $CI_REGISTRY_IMAGE/dbscanserving:$IMAGE_TAG "python -m dbscanserving.service"
+#    - docker logs dbscanserving
+#    - DBSCANSERVING_ADDRESS=$(docker inspect dbscanserving --format "{{.NetworkSettings.Networks.teraflowbridge.IPAddress}}")
+#    - docker pull "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG"
+#    - >
+#      docker run --name $IMAGE_NAME -d -p 10006:10006 
+#      -v "$PWD/src/$IMAGE_NAME/tests:/home/${IMAGE_NAME}/results" 
+#      -e REDIS_PASSWORD=${REDIS_PASSWORD}
+#      -e DBSCANSERVINGSERVICE_SERVICE_HOST=${DBSCANSERVING_ADDRESS}
+#      -e CACHINGSERVICE_SERVICE_HOST=${REDIS_ADDRESS}
+#      --network=teraflowbridge --rm $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=DEBUG --verbose $IMAGE_NAME/tests/test_unitary.py --junitxml=/home/${IMAGE_NAME}/results/${IMAGE_NAME}_report.xml"
+#    - docker logs redis
+#    - docker logs dbscanserving
+#    - docker logs $IMAGE_NAME
+#    - docker exec -i $IMAGE_NAME bash -c "coverage xml -o /home/${IMAGE_NAME}/results/${IMAGE_NAME}_coverage.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 rm -f redis
+#    - docker rm -f dbscanserving
+#    - 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/$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 opticalattackdetector service in Kubernetes Cluster
diff --git a/src/opticalattackmanager/.gitlab-ci.yml b/src/opticalattackmanager/.gitlab-ci.yml
index 1fe77d3159ba5d5f2d0bd99f23c4692e1f509d20..1054a8520ecc8e206bc98b44095100be67359d54 100644
--- a/src/opticalattackmanager/.gitlab-ci.yml
+++ b/src/opticalattackmanager/.gitlab-ci.yml
@@ -21,7 +21,7 @@ build opticalattackmanager:
   before_script:
     - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
   script:
-    - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile .
+    - docker 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:
@@ -38,45 +38,45 @@ build opticalattackmanager:
       - manifests/${IMAGE_NAME}service.yaml
       - .gitlab-ci.yml
 
-# Apply unit test to the component
-unit_test opticalattackmanager:
-  variables:
-    IMAGE_NAME: 'opticalattackmanager' # name of the microservice
-    IMAGE_TAG: 'latest' # tag of the container image (production, development, etc)
-  stage: unit_test
-  needs:
-    - build opticalattackmanager
-  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 10005:10005 -e LOG_LEVEL=DEBUG -v "$PWD/src/$IMAGE_NAME/tests:/home/teraflow/controller/$IMAGE_NAME/results" --network=teraflowbridge $CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG
-    - docker ps -a
-    - docker logs $IMAGE_NAME
-    - docker exec -i $IMAGE_NAME bash -c "coverage run -m pytest --log-level=DEBUG --verbose $IMAGE_NAME/tests/test_unitary.py --junitxml=/home/teraflow/controller/$IMAGE_NAME/results/${IMAGE_NAME}_report.xml; coverage report --include='${IMAGE_NAME}/*' --show-missing"
-    - ls -la src/$IMAGE_NAME/tests
-  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
+## Apply unit test to the component
+#unit_test opticalattackmanager:
+#  variables:
+#    IMAGE_NAME: 'opticalattackmanager' # name of the microservice
+#    IMAGE_TAG: 'latest' # tag of the container image (production, development, etc)
+#  stage: unit_test
+#  needs:
+#    - build opticalattackmanager
+#  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 10005:10005 -e LOG_LEVEL=DEBUG -v "$PWD/src/$IMAGE_NAME/tests:/home/teraflow/controller/$IMAGE_NAME/results" --network=teraflowbridge $CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG
+#    - docker ps -a
+#    - docker logs $IMAGE_NAME
+#    - docker exec -i $IMAGE_NAME bash -c "coverage run -m pytest --log-level=DEBUG --verbose $IMAGE_NAME/tests/test_unitary.py --junitxml=/home/teraflow/controller/$IMAGE_NAME/results/${IMAGE_NAME}_report.xml; coverage report --include='${IMAGE_NAME}/*' --show-missing"
+#    - ls -la src/$IMAGE_NAME/tests
+#  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 opticalattackmanager:
diff --git a/src/opticalattackmitigator/.gitlab-ci.yml b/src/opticalattackmitigator/.gitlab-ci.yml
index 30eb94b1b5a765eb3dbfac3e544b9bd94a6e415b..3456348fa82b0f19420abc4c4ff2ee32b2b4f3de 100644
--- a/src/opticalattackmitigator/.gitlab-ci.yml
+++ b/src/opticalattackmitigator/.gitlab-ci.yml
@@ -21,7 +21,7 @@ build opticalattackmitigator:
   before_script:
     - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
   script:
-    - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile .
+    - docker 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:
@@ -36,41 +36,41 @@ build opticalattackmitigator:
       - manifests/${IMAGE_NAME}service.yaml
       - .gitlab-ci.yml
 
-# apply unit test to the opticalattackmitigator component
-unit_test opticalattackmitigator:
-  variables:
-    IMAGE_NAME: 'opticalattackmitigator' # name of the microservice
-    IMAGE_TAG: 'latest' # tag of the container image (production, development, etc)
-  stage: unit_test
-  needs:
-    - build opticalattackmitigator
-  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
-  script:
-    - docker pull "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG"
-    - docker run --name $IMAGE_NAME -d -p 10007:10007 -v "$PWD/src/$IMAGE_NAME/tests:/home/${IMAGE_NAME}/results" --network=teraflowbridge --rm $CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG
-    - sleep 5
-    - docker ps -a
-    - docker exec -i $IMAGE_NAME bash -c "coverage run -m pytest --log-level=DEBUG --verbose $IMAGE_NAME/tests/test_unitary.py --junitxml=/home/${IMAGE_NAME}/results/${IMAGE_NAME}_report.xml; coverage xml -o /home/${IMAGE_NAME}/results/${IMAGE_NAME}_coverage.xml; 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/$IMAGE_NAME/**/*.{py,in,yml}
-      - src/$IMAGE_NAME/Dockerfile
-      - src/$IMAGE_NAME/tests/*.py
-      - manifests/${IMAGE_NAME}service.yaml
-      - .gitlab-ci.yml
-  artifacts:
-    when: always
-    reports:
-      junit: src/$IMAGE_NAME/tests/${IMAGE_NAME}_report.xml
+## apply unit test to the opticalattackmitigator component
+#unit_test opticalattackmitigator:
+#  variables:
+#    IMAGE_NAME: 'opticalattackmitigator' # name of the microservice
+#    IMAGE_TAG: 'latest' # tag of the container image (production, development, etc)
+#  stage: unit_test
+#  needs:
+#    - build opticalattackmitigator
+#  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
+#  script:
+#    - docker pull "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG"
+#    - docker run --name $IMAGE_NAME -d -p 10007:10007 -v "$PWD/src/$IMAGE_NAME/tests:/home/${IMAGE_NAME}/results" --network=teraflowbridge --rm $CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG
+#    - sleep 5
+#    - docker ps -a
+#    - docker exec -i $IMAGE_NAME bash -c "coverage run -m pytest --log-level=DEBUG --verbose $IMAGE_NAME/tests/test_unitary.py --junitxml=/home/${IMAGE_NAME}/results/${IMAGE_NAME}_report.xml; coverage xml -o /home/${IMAGE_NAME}/results/${IMAGE_NAME}_coverage.xml; 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/$IMAGE_NAME/**/*.{py,in,yml}
+#      - src/$IMAGE_NAME/Dockerfile
+#      - src/$IMAGE_NAME/tests/*.py
+#      - manifests/${IMAGE_NAME}service.yaml
+#      - .gitlab-ci.yml
+#  artifacts:
+#    when: always
+#    reports:
+#      junit: src/$IMAGE_NAME/tests/${IMAGE_NAME}_report.xml
 
 
 # Deployment of the opticalattackmitigator service in Kubernetes Cluster
diff --git a/src/opticalcontroller/.gitlab-ci.yml b/src/opticalcontroller/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..4f27f0a4240a4cf5840750b7ead31117bd6c73c4
--- /dev/null
+++ b/src/opticalcontroller/.gitlab-ci.yml
@@ -0,0 +1,105 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.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 opticalcontroller:
+  variables:
+    IMAGE_NAME: 'opticalcontroller' # 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 opticalcontroller:
+#  variables:
+#    IMAGE_NAME: 'opticalcontroller' # name of the microservice
+#    IMAGE_TAG: 'latest' # tag of the container image (production, development, etc)
+#  stage: unit_test
+#  needs:
+#    - build opticalcontroller
+#  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 --driver=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 20030:20030  -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 -m pytest --log-level=INFO --verbose $IMAGE_NAME/tests/test_unitary.py --junitxml=/opt/results/${IMAGE_NAME}_report.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
+#      - 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 opticalcontroller:
+#  variables:
+#    IMAGE_NAME: 'opticalcontroller' # name of the microservice
+#    IMAGE_TAG: 'latest' # tag of the container image (production, development, etc)
+#  stage: deploy
+#  needs:
+#    - unit test opticalcontroller
+#    # - 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/opticalcontroller/Dockerfile b/src/opticalcontroller/Dockerfile
index c3d886ab56ecf42cd2ffb96b32ef59b89f2c1207..d54566ccbec04e30e089e5fb6bb66d706c5ce356 100644
--- a/src/opticalcontroller/Dockerfile
+++ b/src/opticalcontroller/Dockerfile
@@ -16,63 +16,55 @@ FROM python:3.9-slim
 
 # Install dependencies
 RUN apt-get --yes --quiet --quiet update && \
-    apt-get --yes --quiet --quiet install wget g++ && \
+    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
-
-
-
+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
 
-RUN mkdir -p /var/teraflow/opticalcontroller
-
-WORKDIR /var/teraflow/opticalcontroller/common
+# 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/opticalcontroller/common/proto
-WORKDIR /var/teraflow/opticalcontroller/common/proto
+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-folder, get specific Python packages
-
-
-
+# Create component sub-folders, get specific Python packages
+RUN mkdir -p /var/teraflow/opticalcontroller
 WORKDIR /var/teraflow/opticalcontroller
 COPY src/opticalcontroller/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/. context/
-
+WORKDIR /var/teraflow
+COPY src/context/__init__.py context/__init__.py
+COPY src/context/client/. context/client/
 COPY src/opticalcontroller/. opticalcontroller/
-COPY src/context/. opticalcontroller/context/
 
 # Start the service
 WORKDIR /var/teraflow/opticalcontroller
diff --git a/src/pathcomp/.gitlab-ci.yml b/src/pathcomp/.gitlab-ci.yml
index 05113d0feab441543d6567f3eb3ab1cacac3a971..cc5db9818416d42fb52daf5c6bb29504c3311da4 100644
--- a/src/pathcomp/.gitlab-ci.yml
+++ b/src/pathcomp/.gitlab-ci.yml
@@ -22,9 +22,9 @@ build pathcomp:
     - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
   script:
     # This first build tags the builder resulting image to prevent being removed by dangling image removal command
-    - docker build -t "${IMAGE_NAME}-backend:${IMAGE_TAG}-builder" --target builder -f ./src/$IMAGE_NAME/backend/Dockerfile .
-    - docker build -t "${IMAGE_NAME}-backend:$IMAGE_TAG" -f ./src/$IMAGE_NAME/backend/Dockerfile .
-    - docker build -t "${IMAGE_NAME}-frontend:$IMAGE_TAG" -f ./src/$IMAGE_NAME/frontend/Dockerfile .
+    - docker buildx build -t "${IMAGE_NAME}-backend:${IMAGE_TAG}-builder" --target builder -f ./src/$IMAGE_NAME/backend/Dockerfile .
+    - docker buildx build -t "${IMAGE_NAME}-backend:$IMAGE_TAG" -f ./src/$IMAGE_NAME/backend/Dockerfile .
+    - docker buildx build -t "${IMAGE_NAME}-frontend:$IMAGE_TAG" -f ./src/$IMAGE_NAME/frontend/Dockerfile .
     - docker tag "${IMAGE_NAME}-backend:$IMAGE_TAG" "$CI_REGISTRY_IMAGE/${IMAGE_NAME}-backend:$IMAGE_TAG"
     - docker tag "${IMAGE_NAME}-frontend:$IMAGE_TAG" "$CI_REGISTRY_IMAGE/${IMAGE_NAME}-frontend:$IMAGE_TAG"
     - docker push "$CI_REGISTRY_IMAGE/${IMAGE_NAME}-backend:$IMAGE_TAG"
diff --git a/src/policy/.gitlab-ci.yml b/src/policy/.gitlab-ci.yml
index 8c326ff16e77e2bfef7e065b1e11921e65ec8e9b..6ec51e86fdb94ce2bcfe316f17612ac92608ea10 100644
--- a/src/policy/.gitlab-ci.yml
+++ b/src/policy/.gitlab-ci.yml
@@ -24,7 +24,7 @@ build policy:
     - export IMAGE_TAG=$(grep -m1 '<version>' ./src/$IMAGE_NAME_POLICY/pom.xml | grep -oP  '(?<=>).*(?=<)')
     - echo "IMAGE_TAG=${IMAGE_TAG}" >> ${BUILD_ENV_POLICY}
     - cat ${BUILD_ENV_POLICY}
-    - docker build -t "$IMAGE_NAME_POLICY:$IMAGE_TAG" -f ./src/$IMAGE_NAME_POLICY/src/main/docker/Dockerfile.multistage.jvm ./src/$IMAGE_NAME_POLICY/ --target builder
+    - docker buildx build -t "$IMAGE_NAME_POLICY:$IMAGE_TAG" -f ./src/$IMAGE_NAME_POLICY/src/main/docker/Dockerfile.multistage.jvm ./src/$IMAGE_NAME_POLICY/ --target builder
   after_script:
     - docker images --filter="dangling=true" --quiet | xargs -r docker rmi
   artifacts:
@@ -50,7 +50,7 @@ unit_test policy:
     - docker rm ${REPORTS_CONTAINER} || true
   script:
     - echo "Running tests for image ${IMAGE_TAG}"
-    - docker build -t "$IMAGE_NAME_POLICY:$IMAGE_TAG" -f ./src/$IMAGE_NAME_POLICY/src/main/docker/Dockerfile.multistage.jvm ./src/$IMAGE_NAME_POLICY/ --target unit-test
+    - docker buildx build -t "$IMAGE_NAME_POLICY:$IMAGE_TAG" -f ./src/$IMAGE_NAME_POLICY/src/main/docker/Dockerfile.multistage.jvm ./src/$IMAGE_NAME_POLICY/ --target unit-test
     # Transfer JaCoCo and Surefire reports from within tests image
     - docker create --name ${REPORTS_CONTAINER} "$IMAGE_NAME_POLICY:$IMAGE_TAG"
     - mkdir -p ${REPORTS_PATH_POLICY}
@@ -60,7 +60,7 @@ unit_test policy:
     - cat ${REPORTS_PATH_POLICY}/coverage.html | grep -o 'Total[^%]*%' | sed 's/<.*>/ /; s/Total/JaCoCo Coverage Total:/'
     - docker run -v "$(pwd)/src/${IMAGE_NAME_POLICY}:/${IMAGE_NAME_POLICY}" --rm registry.gitlab.com/haynes/jacoco2cobertura:1.0.7 python /opt/cover2cover.py ${IMAGE_NAME_POLICY}/reports/jacoco.xml ${IMAGE_NAME_POLICY}/src/main/java > ${REPORTS_PATH_POLICY}/cobertura.xml
     # Build final image
-    - docker build -t "$IMAGE_NAME_POLICY:$IMAGE_TAG" -f ./src/$IMAGE_NAME_POLICY/src/main/docker/Dockerfile.multistage.jvm ./src/$IMAGE_NAME_POLICY/ --target release
+    - docker buildx build -t "$IMAGE_NAME_POLICY:$IMAGE_TAG" -f ./src/$IMAGE_NAME_POLICY/src/main/docker/Dockerfile.multistage.jvm ./src/$IMAGE_NAME_POLICY/ --target release
     - docker tag "$IMAGE_NAME_POLICY:$IMAGE_TAG" "$CI_REGISTRY_IMAGE/$IMAGE_NAME_POLICY:$IMAGE_TAG"
     - docker push "$CI_REGISTRY_IMAGE/$IMAGE_NAME_POLICY:$IMAGE_TAG"
   after_script:
diff --git a/src/service/.gitlab-ci.yml b/src/service/.gitlab-ci.yml
index c9ff94ac915386ac05d91661fc2cb1a53bb0e65d..11fa4b07fd84dd3a80de1e09661b45838562621e 100644
--- a/src/service/.gitlab-ci.yml
+++ b/src/service/.gitlab-ci.yml
@@ -21,7 +21,7 @@ build service:
   before_script:
     - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
   script:
-    - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile .
+    - docker 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:
diff --git a/src/service/service/ServiceServiceServicerImpl.py b/src/service/service/ServiceServiceServicerImpl.py
index f65d5b59a0d9a81c44f4d04683eb87e7773efa4a..b5623885f64169f3f32283c000d1b67ce03e4673 100644
--- a/src/service/service/ServiceServiceServicerImpl.py
+++ b/src/service/service/ServiceServiceServicerImpl.py
@@ -12,19 +12,24 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import copy, grpc, json, logging, random, uuid
+import grpc, json, logging, random, uuid
 from typing import Optional
 from common.method_wrappers.Decorator import MetricsPool, safe_and_metered_rpc_method
 from common.method_wrappers.ServiceExceptions import (
     AlreadyExistsException, InvalidArgumentException, NotFoundException, NotImplementedException,
     OperationFailedException)
 from common.proto.context_pb2 import (
-    Connection, Empty, Service, ServiceId, ServiceStatusEnum, ServiceTypeEnum, ConstraintActionEnum)
+    Connection, ConstraintActionEnum, Empty, Service, ServiceId, ServiceStatusEnum,
+    ServiceTypeEnum, TopologyId
+)
 from common.proto.pathcomp_pb2 import PathCompRequest
 from common.proto.e2eorchestrator_pb2 import E2EOrchestratorRequest
 from common.proto.service_pb2_grpc import ServiceServiceServicer
 from common.tools.context_queries.Service import get_service_by_id
 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 common.Constants import DEFAULT_CONTEXT_NAME, DEFAULT_TOPOLOGY_NAME
 from context.client.ContextClient import ContextClient
 from e2e_orchestrator.client.E2EOrchestratorClient import E2EOrchestratorClient
 from pathcomp.frontend.client.PathCompClient import PathCompClient
@@ -33,12 +38,9 @@ from service.client.TEServiceClient import TEServiceClient
 from .service_handler_api.ServiceHandlerFactory import ServiceHandlerFactory
 from .task_scheduler.TaskScheduler import TasksScheduler
 from .tools.GeodesicDistance import gps_distance
-
-from common.tools.object_factory.Context import json_context_id
-from common.tools.object_factory.Topology import json_topology_id
-from common.Constants import DEFAULT_CONTEXT_NAME, DEFAULT_TOPOLOGY_NAME
-from common.proto.context_pb2 import Empty, TopologyId
-from service.service.tools.OpticalTools import add_lightpath, delete_lightpath, adapt_reply, get_device_name_from_uuid, get_optical_band
+from .tools.OpticalTools import (
+    add_lightpath, delete_lightpath, adapt_reply, get_device_name_from_uuid, get_optical_band
+)
 
 
 LOGGER = logging.getLogger(__name__)
@@ -245,9 +247,6 @@ class ServiceServiceServicerImpl(ServiceServiceServicer):
         num_expected_endpoints = num_disjoint_paths * 2
 
         tasks_scheduler = TasksScheduler(self.service_handler_factory)
-        if len(service_with_uuids.service_endpoint_ids) >= num_expected_endpoints:
-            pathcomp_request = PathCompRequest()
-            pathcomp_request.services.append(service_with_uuids)    # pylint: disable=no-member
 
         if service.service_type == ServiceTypeEnum.SERVICETYPE_OPTICAL_CONNECTIVITY:
             context_id_x = json_context_id(DEFAULT_CONTEXT_NAME)
@@ -309,19 +308,23 @@ class ServiceServiceServicerImpl(ServiceServiceServicer):
                 tasks_scheduler.compose_from_pathcompreply(
                     optical_reply, is_delete=False)
         else:
-            if num_disjoint_paths is None or num_disjoint_paths in {0, 1} :
-                pathcomp_request.shortest_path.Clear()              # pylint: disable=no-member
-            else:
-                pathcomp_request.k_disjoint_path.num_disjoint = num_disjoint_paths  # pylint: disable=no-member
+            if len(service_with_uuids.service_endpoint_ids) >= num_expected_endpoints:
+                pathcomp_request = PathCompRequest()
+                pathcomp_request.services.append(service_with_uuids)    # pylint: disable=no-member
+
+                if num_disjoint_paths is None or num_disjoint_paths in {0, 1} :
+                    pathcomp_request.shortest_path.Clear()              # pylint: disable=no-member
+                else:
+                    pathcomp_request.k_disjoint_path.num_disjoint = num_disjoint_paths  # pylint: disable=no-member
 
-            pathcomp = PathCompClient()
-            pathcomp_reply = pathcomp.Compute(pathcomp_request)
-            pathcomp.close()
+                pathcomp = PathCompClient()
+                pathcomp_reply = pathcomp.Compute(pathcomp_request)
+                pathcomp.close()
 
-            # Feed TaskScheduler with this path computation reply. TaskScheduler identifies inter-dependencies among
-            # the services and connections retrieved and produces a schedule of tasks (an ordered list of tasks to be
-            # executed) to implement the requested create/update operation.
-            tasks_scheduler.compose_from_pathcompreply(pathcomp_reply, is_delete=False)
+                # Feed TaskScheduler with this path computation reply. TaskScheduler identifies inter-dependencies among
+                # the services and connections retrieved and produces a schedule of tasks (an ordered list of tasks to be
+                # executed) to implement the requested create/update operation.
+                tasks_scheduler.compose_from_pathcompreply(pathcomp_reply, is_delete=False)
 
         tasks_scheduler.execute_all()
         return service_with_uuids.service_id
diff --git a/src/service/service/task_scheduler/TaskExecutor.py b/src/service/service/task_scheduler/TaskExecutor.py
index b9715aae637bb8845077bfc2b8b9b9d1bb030645..5c5747970c6accf3c76da6d4ffb60de48edbcdac 100644
--- a/src/service/service/task_scheduler/TaskExecutor.py
+++ b/src/service/service/task_scheduler/TaskExecutor.py
@@ -112,7 +112,6 @@ class TaskExecutor:
         return device
 
     def configure_device(self, device : Device) -> None:
-        self._context_client.SelectOpticalConfig()
         device_key = get_device_key(device.device_id)
         self._device_client.ConfigureDevice(device)
         self._store_grpc_object(CacheableObjectType.DEVICE, device_key, device)
@@ -120,22 +119,22 @@ class TaskExecutor:
     # New function Andrea for Optical Devices
     def configure_optical_device(self, device : Device, settings : str, flows : list, is_opticalband : bool):
         device_key = get_device_key(device.device_id)
-        myid = OpticalConfigId()
-        myid.opticalconfig_uuid = device.device_id.device_uuid.uuid
-        opticalconfig = OpticalConfig()
+        optical_config_id = OpticalConfigId()
+        optical_config_id.opticalconfig_uuid = device.device_id.device_uuid.uuid
+        optical_config = OpticalConfig()
         setting = settings.value if settings else ""
 
         new_config = {}
         try:
-            result = self._context_client.SelectOpticalConfig(myid)
+            result = self._context_client.SelectOpticalConfig(optical_config_id)
             new_config = json.loads(result.config)
             if result is not None :
                 new_config["new_config"] = setting
                 new_config["is_opticalband"] = is_opticalband
                 new_config["flow"] = flows
                 result.config = str(new_config)
-                opticalconfig.CopyFrom(result)
-                self._device_client.ConfigureOpticalDevice(opticalconfig)
+                optical_config.CopyFrom(result)
+                self._device_client.ConfigureOpticalDevice(optical_config)
             self._store_grpc_object(CacheableObjectType.DEVICE, device_key, device)
         except Exception as e:
             LOGGER.info("error in config my config %s",e)
diff --git a/src/slice/.gitlab-ci.yml b/src/slice/.gitlab-ci.yml
index 28db8751a4b9f2fa267adcd76fd3ae9bd45c959c..ca66b9a6f1e9ee5e456a793bdd34607c4a6ccb8d 100644
--- a/src/slice/.gitlab-ci.yml
+++ b/src/slice/.gitlab-ci.yml
@@ -21,7 +21,7 @@ build slice:
   before_script:
     - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
   script:
-    - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile .
+    - docker 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:
diff --git a/src/tests/.gitlab-ci.yml b/src/tests/.gitlab-ci.yml
index db44b9e4a8d29475a0b6cd620ffd9a6961f8cdc5..41b8bb36ca8d3ef7eae444cdc9525cfdf4e48d02 100644
--- a/src/tests/.gitlab-ci.yml
+++ b/src/tests/.gitlab-ci.yml
@@ -12,7 +12,11 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# include the individual .gitlab-ci.yml of each integration test
+# include the individual .gitlab-ci.yml of each end-to-end integration test
 include:
   - local: '/src/tests/ofc22/.gitlab-ci.yml'
-  - local: '/src/tests/oeccpsc22/.gitlab-ci.yml'
+  #- local: '/src/tests/oeccpsc22/.gitlab-ci.yml'
+  - local: '/src/tests/ecoc22/.gitlab-ci.yml'
+  #- local: '/src/tests/nfvsdn22/.gitlab-ci.yml'
+  #- local: '/src/tests/ofc23/.gitlab-ci.yml'
+  #- local: '/src/tests/ofc24/.gitlab-ci.yml'
diff --git a/src/tests/ecoc22/.gitlab-ci.yml b/src/tests/ecoc22/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..09718b4b94b49edb0e52be3c0e9c6ab581145898
--- /dev/null
+++ b/src/tests/ecoc22/.gitlab-ci.yml
@@ -0,0 +1,106 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.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 ecoc22:
+  variables:
+    TEST_NAME: 'ecoc22'
+  stage: build
+  before_script:
+    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
+  script:
+    - docker buildx build -t "${TEST_NAME}:latest" -f ./src/tests/${TEST_NAME}/Dockerfile .
+    - docker tag "${TEST_NAME}:latest" "$CI_REGISTRY_IMAGE/${TEST_NAME}:latest"
+    - docker push "$CI_REGISTRY_IMAGE/${TEST_NAME}:latest"
+  after_script:
+    - docker images --filter="dangling=true" --quiet | xargs -r docker rmi
+  rules:
+    - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)'
+    - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"'
+    - changes:
+      - src/common/**/*.py
+      - proto/*.proto
+      - src/tests/${TEST_NAME}/**/*.{py,in,sh,yml}
+      - src/tests/${TEST_NAME}/Dockerfile
+      - .gitlab-ci.yml
+
+# Deploy TeraFlowSDN and Execute end-2-end test
+end2end_test ecoc22:
+  variables:
+    TEST_NAME: 'ecoc22'
+  stage: end2end_test
+  # Disable to force running it after all other tasks
+  #needs:
+  #  - build ecoc22
+  before_script:
+    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
+  script:
+    # Download Docker image to run the test
+    - docker pull "${CI_REGISTRY_IMAGE}/${TEST_NAME}:latest"
+
+    # Check MicroK8s is ready
+    - microk8s status --wait-ready
+    - kubectl get pods --all-namespaces
+
+    # Configure TeraFlowSDN deployment
+    # Uncomment if DEBUG log level is needed for the components
+    #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/contextservice.yaml
+    #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/deviceservice.yaml
+    #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="frontend").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/pathcompservice.yaml
+    #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/serviceservice.yaml
+    #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/sliceservice.yaml
+    #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/nbiservice.yaml
+    - source src/tests/${TEST_NAME}/deploy_specs.sh
+    #- export TFS_REGISTRY_IMAGES="${CI_REGISTRY_IMAGE}"
+    #- export TFS_SKIP_BUILD="YES"
+    #- export TFS_IMAGE_TAG="latest"
+    #- echo "TFS_REGISTRY_IMAGES=${CI_REGISTRY_IMAGE}"
+
+    # Deploy TeraFlowSDN
+    - ./deploy/crdb.sh
+    - ./deploy/nats.sh
+    - ./deploy/qdb.sh
+    - ./deploy/expose_dashboard.sh
+    - ./deploy/tfs.sh
+    - ./deploy/show.sh
+    
+    # Wait for Context to be subscribed to NATS
+    #- while ! kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server 2>&1 | grep -q 'Subscriber is Ready? True'; do sleep 1; done
+    #- kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server
+
+    # Run end-to-end tests
+    - if docker ps -a | grep ${TEST_NAME}; then docker rm -f ${TEST_NAME}; fi
+    - >
+      docker run -t --name ${TEST_NAME} --network=host 
+      --volume "$PWD/tfs_runtime_env_vars.sh:/var/teraflow/tfs_runtime_env_vars.sh"
+      --volume "$PWD/src/tests/${TEST_NAME}:/opt/results"
+      $CI_REGISTRY_IMAGE/${TEST_NAME}:latest
+  after_script:
+    - source src/tests/${TEST_NAME}/deploy_specs.sh
+    - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server
+    - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/deviceservice -c server
+    - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/pathcompservice -c frontend
+    - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/serviceservice -c server
+    - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/sliceservice -c server
+    - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/nbiservice -c server
+    - if docker ps -a | grep ${TEST_NAME}; then docker rm -f ${TEST_NAME}; fi
+    - docker images --filter="dangling=true" --quiet | xargs -r docker rmi
+  #coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/'
+  rules:
+    - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)'
+    - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"'
+  artifacts:
+      when: always
+      reports:
+        junit: ./src/tests/${TEST_NAME}/report_*.xml
diff --git a/src/tests/ecoc22/Dockerfile b/src/tests/ecoc22/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..3ac134a384a5b61d4dca05fcf9076680c74fe649
--- /dev/null
+++ b/src/tests/ecoc22/Dockerfile
@@ -0,0 +1,101 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.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/tests/ecoc22
+WORKDIR /var/teraflow/tests/ecoc22
+COPY src/tests/ecoc22/requirements.in requirements.in
+RUN pip-compile --quiet --output-file=requirements.txt requirements.in
+RUN python3 -m pip install -r requirements.txt
+
+# Add component files into working directory
+WORKDIR /var/teraflow
+COPY src/__init__.py ./__init__.py
+COPY src/common/*.py ./common/
+COPY src/common/tests/. ./common/tests/
+COPY src/common/tools/. ./common/tools/
+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/monitoring/__init__.py monitoring/__init__.py
+COPY src/monitoring/client/. monitoring/client/
+COPY src/monitoring/__init__.py monitoring/__init__.py
+COPY src/monitoring/client/. monitoring/client/
+COPY src/e2e_orchestrator/__init__.py e2e_orchestrator/__init__.py
+COPY src/e2e_orchestrator/client/. e2e_orchestrator/client/
+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/tests/*.py ./tests/
+COPY src/tests/ecoc22/__init__.py ./tests/ecoc22/__init__.py
+COPY src/tests/ecoc22/descriptors_emulated.json ./tests/ecoc22/descriptors_emulated.json
+COPY src/tests/ecoc22/tests/. ./tests/ecoc22/tests/
+COPY src/tests/tools/. ./tests/tools/
+
+RUN tee ./run_tests.sh <<EOF
+#!/bin/bash
+source /var/teraflow/tfs_runtime_env_vars.sh
+export PYTHONPATH=/var/teraflow
+pytest --verbose --log-level=INFO /var/teraflow/tests/ecoc22/tests/test_functional_bootstrap.py      --junitxml=/opt/results/report_bootstrap.xml
+pytest --verbose --log-level=INFO /var/teraflow/tests/ecoc22/tests/test_functional_create_service.py --junitxml=/opt/results/report_create_service.xml
+pytest --verbose --log-level=INFO /var/teraflow/tests/ecoc22/tests/test_functional_delete_service.py --junitxml=/opt/results/report_delete_service.xml
+pytest --verbose --log-level=INFO /var/teraflow/tests/ecoc22/tests/test_functional_cleanup.py        --junitxml=/opt/results/report_cleanup.xml
+EOF
+RUN chmod ug+x ./run_tests.sh
+
+# Run the tests
+ENTRYPOINT ["./run_tests.sh"]
diff --git a/src/tests/ecoc22/deploy_specs.sh b/src/tests/ecoc22/deploy_specs.sh
index f2a19f773de041f322bec72796884cfffc5f01c7..032a8e2bb5ab3684e0f08d6455124d1c5ece710b 100755
--- a/src/tests/ecoc22/deploy_specs.sh
+++ b/src/tests/ecoc22/deploy_specs.sh
@@ -26,8 +26,17 @@ export TFS_COMPONENTS="context device pathcomp service slice nbi webui"
 # Uncomment to activate Monitoring
 #export TFS_COMPONENTS="${TFS_COMPONENTS} monitoring"
 
-# Uncomment to activate ZTP and Policy Manager
-#export TFS_COMPONENTS="${TFS_COMPONENTS} ztp policy"
+# Uncomment to activate BGP-LS Speaker
+#export TFS_COMPONENTS="${TFS_COMPONENTS} bgpls_speaker"
+
+# Uncomment to activate Optical Controller
+#export TFS_COMPONENTS="${TFS_COMPONENTS} opticalcontroller"
+
+# 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"
@@ -35,6 +44,15 @@ export TFS_COMPONENTS="context device pathcomp service slice nbi webui"
 # 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"
+
 # Set the tag you want to use for your images.
 export TFS_IMAGE_TAG="dev"
 
diff --git a/src/clean.sh b/src/tests/ecoc22/requirements.in
old mode 100755
new mode 100644
similarity index 87%
rename from src/clean.sh
rename to src/tests/ecoc22/requirements.in
index 21e887190e095062032965337cc8165d982746f8..30b11e65301a7bfc3ae89bf77e5e2734b0f3b566
--- a/src/clean.sh
+++ b/src/tests/ecoc22/requirements.in
@@ -1,4 +1,3 @@
-#!/usr/bin/env bash
 # Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,7 +12,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-
-docker rm --force monitoring
-docker network remove teraflowbridge
-
+requests==2.27.*
diff --git a/src/tests/ecoc22/tests/test_functional_bootstrap.py b/src/tests/ecoc22/tests/test_functional_bootstrap.py
index 05691d0b274df019a87bd870fec2b9ffa3245612..edafbae31e8b23b4c4ea7bde117db7309c795b8c 100644
--- a/src/tests/ecoc22/tests/test_functional_bootstrap.py
+++ b/src/tests/ecoc22/tests/test_functional_bootstrap.py
@@ -12,9 +12,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import logging
+import logging, os, time
 from common.Constants import DEFAULT_CONTEXT_NAME
-from common.proto.context_pb2 import ContextId
+from common.proto.context_pb2 import ContextId, DeviceOperationalStatusEnum, Empty
 from common.tools.descriptor.Loader import DescriptorLoader, check_descriptor_load_results, validate_empty_scenario
 from common.tools.object_factory.Context import json_context_id
 from context.client.ContextClient import ContextClient
@@ -24,7 +24,7 @@ from tests.Fixtures import context_client, device_client # pylint: disable=unuse
 LOGGER = logging.getLogger(__name__)
 LOGGER.setLevel(logging.DEBUG)
 
-DESCRIPTOR_FILE = 'ecoc22/descriptors_emulated.json'
+DESCRIPTOR_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'descriptors_emulated.json')
 ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
 
 def test_scenario_bootstrap(
@@ -43,3 +43,25 @@ def test_scenario_bootstrap(
     response = context_client.GetContext(ADMIN_CONTEXT_ID)
     assert len(response.service_ids) == 0
     assert len(response.slice_ids) == 0
+
+def test_scenario_devices_enabled(
+    context_client : ContextClient,         # pylint: disable=redefined-outer-name
+) -> None:
+    """
+    This test validates that the devices are enabled.
+    """
+    DEVICE_OP_STATUS_ENABLED = DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_ENABLED
+
+    num_devices = -1
+    num_devices_enabled, num_retry = 0, 0
+    while (num_devices != num_devices_enabled) and (num_retry < 10):
+        time.sleep(1.0)
+        response = context_client.ListDevices(Empty())
+        num_devices = len(response.devices)
+        num_devices_enabled = 0
+        for device in response.devices:
+            if device.device_operational_status != DEVICE_OP_STATUS_ENABLED: continue
+            num_devices_enabled += 1
+        LOGGER.info('Num Devices enabled: {:d}/{:d}'.format(num_devices_enabled, num_devices))
+        num_retry += 1
+    assert num_devices_enabled == num_devices
diff --git a/src/tests/ecoc22/tests/test_functional_cleanup.py b/src/tests/ecoc22/tests/test_functional_cleanup.py
index 088c19799615169bf8c60ae5a9226fe02ec0e4ff..b1396f49a24e03befa409c8c2627dfd3d582f4b5 100644
--- a/src/tests/ecoc22/tests/test_functional_cleanup.py
+++ b/src/tests/ecoc22/tests/test_functional_cleanup.py
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import logging
+import logging, os
 from common.Constants import DEFAULT_CONTEXT_NAME
 from common.proto.context_pb2 import ContextId
 from common.tools.descriptor.Loader import DescriptorLoader, validate_empty_scenario
@@ -24,7 +24,7 @@ from tests.Fixtures import context_client, device_client    # pylint: disable=un
 LOGGER = logging.getLogger(__name__)
 LOGGER.setLevel(logging.DEBUG)
 
-DESCRIPTOR_FILE = 'ecoc22/descriptors_emulated.json'
+DESCRIPTOR_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'descriptors_emulated.json')
 ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
 
 def test_scenario_cleanup(
diff --git a/src/tests/ecoc22/tests/test_functional_create_service.py b/src/tests/ecoc22/tests/test_functional_create_service.py
index dab9c7eb131434a16dad01be4fb8cd6b6b322515..b4976f15d09673699cf0d39b947c00e99759833c 100644
--- a/src/tests/ecoc22/tests/test_functional_create_service.py
+++ b/src/tests/ecoc22/tests/test_functional_create_service.py
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import logging
+import logging, os
 from common.Constants import DEFAULT_CONTEXT_NAME
 from common.proto.context_pb2 import ContextId, ServiceTypeEnum
 from common.tools.descriptor.Loader import DescriptorLoader
@@ -27,7 +27,7 @@ from .Objects import WIM_SERVICE_CONNECTION_POINTS, WIM_SERVICE_TYPE
 LOGGER = logging.getLogger(__name__)
 LOGGER.setLevel(logging.DEBUG)
 
-DESCRIPTOR_FILE = 'ecoc22/descriptors_emulated.json'
+DESCRIPTOR_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'descriptors_emulated.json')
 ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
 
 def test_service_creation(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name
diff --git a/src/tests/ecoc22/tests/test_functional_delete_service.py b/src/tests/ecoc22/tests/test_functional_delete_service.py
index 710e1a817f00f0b1664439d1c816195202a69a9d..d55f3acc04c96eea3be0f068829288e0798ecf93 100644
--- a/src/tests/ecoc22/tests/test_functional_delete_service.py
+++ b/src/tests/ecoc22/tests/test_functional_delete_service.py
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import logging
+import logging, os
 from common.Constants import DEFAULT_CONTEXT_NAME
 from common.proto.context_pb2 import ContextId, ServiceTypeEnum
 from common.tools.descriptor.Loader import DescriptorLoader
@@ -26,7 +26,7 @@ from .Fixtures import osm_wim
 LOGGER = logging.getLogger(__name__)
 LOGGER.setLevel(logging.DEBUG)
 
-DESCRIPTOR_FILE = 'ecoc22/descriptors_emulated.json'
+DESCRIPTOR_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'descriptors_emulated.json')
 ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
 
 def test_service_removal(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name
diff --git a/src/tests/ofc22/.gitlab-ci.yml b/src/tests/ofc22/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..013a389bc438cdac8307f71288f74b0a3afd9737
--- /dev/null
+++ b/src/tests/ofc22/.gitlab-ci.yml
@@ -0,0 +1,109 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.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 ofc22:
+  variables:
+    TEST_NAME: 'ofc22'
+  stage: build
+  before_script:
+    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
+  script:
+    - docker buildx build -t "${TEST_NAME}:latest" -f ./src/tests/${TEST_NAME}/Dockerfile .
+    - docker tag "${TEST_NAME}:latest" "$CI_REGISTRY_IMAGE/${TEST_NAME}:latest"
+    - docker push "$CI_REGISTRY_IMAGE/${TEST_NAME}:latest"
+  after_script:
+    - docker images --filter="dangling=true" --quiet | xargs -r docker rmi
+  rules:
+    - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)'
+    - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"'
+    - changes:
+      - src/common/**/*.py
+      - proto/*.proto
+      - src/tests/${TEST_NAME}/**/*.{py,in,sh,yml}
+      - src/tests/${TEST_NAME}/Dockerfile
+      - .gitlab-ci.yml
+
+# Deploy TeraFlowSDN and Execute end-2-end test
+end2end_test ofc22:
+  variables:
+    TEST_NAME: 'ofc22'
+  stage: end2end_test
+  # Disable to force running it after all other tasks
+  #needs:
+  #  - build ofc22
+  before_script:
+    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
+  script:
+    # Download Docker image to run the test
+    - docker pull "${CI_REGISTRY_IMAGE}/${TEST_NAME}:latest"
+
+    # Check MicroK8s is ready
+    - microk8s status --wait-ready
+    - kubectl get pods --all-namespaces
+
+    # Configure TeraFlowSDN deployment
+    # Uncomment if DEBUG log level is needed for the components
+    #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/contextservice.yaml
+    #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/deviceservice.yaml
+    #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="frontend").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/pathcompservice.yaml
+    #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/serviceservice.yaml
+    #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/sliceservice.yaml
+    #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/nbiservice.yaml
+    #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/monitoringservice.yaml
+    - source src/tests/${TEST_NAME}/deploy_specs.sh
+    #- export TFS_REGISTRY_IMAGES="${CI_REGISTRY_IMAGE}"
+    #- export TFS_SKIP_BUILD="YES"
+    #- export TFS_IMAGE_TAG="latest"
+    #- echo "TFS_REGISTRY_IMAGES=${CI_REGISTRY_IMAGE}"
+
+    # Deploy TeraFlowSDN
+    - ./deploy/crdb.sh
+    - ./deploy/nats.sh
+    - ./deploy/qdb.sh
+    - ./deploy/expose_dashboard.sh
+    - ./deploy/tfs.sh
+    - ./deploy/show.sh
+    
+    # Wait for Context to be subscribed to NATS
+    - while ! kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server 2>&1 | grep -q 'Subscriber is Ready? True'; do sleep 1; done
+    - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server
+
+    # Run end-to-end tests
+    - if docker ps -a | grep ${TEST_NAME}; then docker rm -f ${TEST_NAME}; fi
+    - >
+      docker run -t --name ${TEST_NAME} --network=host 
+      --volume "$PWD/tfs_runtime_env_vars.sh:/var/teraflow/tfs_runtime_env_vars.sh"
+      --volume "$PWD/src/tests/${TEST_NAME}:/opt/results"
+      $CI_REGISTRY_IMAGE/${TEST_NAME}:latest
+  after_script:
+    - source src/tests/${TEST_NAME}/deploy_specs.sh
+    - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server
+    - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/deviceservice -c server
+    - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/pathcompservice -c frontend
+    - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/serviceservice -c server
+    - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/sliceservice -c server
+    - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/nbiservice -c server
+    - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/monitoringservice -c server
+    - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/ztpservice -c server
+    - if docker ps -a | grep ${TEST_NAME}; then docker rm -f ${TEST_NAME}; fi
+    - docker images --filter="dangling=true" --quiet | xargs -r docker rmi
+  #coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/'
+  rules:
+    - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)'
+    - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"'
+  artifacts:
+      when: always
+      reports:
+        junit: ./src/tests/${TEST_NAME}/report_*.xml
diff --git a/src/tests/ofc22/Dockerfile b/src/tests/ofc22/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..4817bd93a313b74851e01bba53174dd14f280a18
--- /dev/null
+++ b/src/tests/ofc22/Dockerfile
@@ -0,0 +1,101 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.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/tests/ofc22
+WORKDIR /var/teraflow/tests/ofc22
+COPY src/tests/ofc22/requirements.in requirements.in
+RUN pip-compile --quiet --output-file=requirements.txt requirements.in
+RUN python3 -m pip install -r requirements.txt
+
+# Add component files into working directory
+WORKDIR /var/teraflow
+COPY src/__init__.py ./__init__.py
+COPY src/common/*.py ./common/
+COPY src/common/tests/. ./common/tests/
+COPY src/common/tools/. ./common/tools/
+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/monitoring/__init__.py monitoring/__init__.py
+COPY src/monitoring/client/. monitoring/client/
+COPY src/monitoring/__init__.py monitoring/__init__.py
+COPY src/monitoring/client/. monitoring/client/
+COPY src/e2e_orchestrator/__init__.py e2e_orchestrator/__init__.py
+COPY src/e2e_orchestrator/client/. e2e_orchestrator/client/
+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/tests/*.py ./tests/
+COPY src/tests/ofc22/__init__.py ./tests/ofc22/__init__.py
+COPY src/tests/ofc22/descriptors_emulated.json ./tests/ofc22/descriptors_emulated.json
+COPY src/tests/ofc22/tests/. ./tests/ofc22/tests/
+COPY src/tests/tools/. ./tests/tools/
+
+RUN tee ./run_tests.sh <<EOF
+#!/bin/bash
+source /var/teraflow/tfs_runtime_env_vars.sh
+export PYTHONPATH=/var/teraflow
+pytest --verbose --log-level=INFO /var/teraflow/tests/ofc22/tests/test_functional_bootstrap.py      --junitxml=/opt/results/report_bootstrap.xml
+pytest --verbose --log-level=INFO /var/teraflow/tests/ofc22/tests/test_functional_create_service.py --junitxml=/opt/results/report_create_service.xml
+pytest --verbose --log-level=INFO /var/teraflow/tests/ofc22/tests/test_functional_delete_service.py --junitxml=/opt/results/report_delete_service.xml
+pytest --verbose --log-level=INFO /var/teraflow/tests/ofc22/tests/test_functional_cleanup.py        --junitxml=/opt/results/report_cleanup.xml
+EOF
+RUN chmod ug+x ./run_tests.sh
+
+# Run the tests
+ENTRYPOINT ["./run_tests.sh"]
diff --git a/src/tests/ofc22/deploy_specs.sh b/src/tests/ofc22/deploy_specs.sh
index d0696f91dbe61d28e3e91b0d9307c2f7e5172589..aad41f33deefb2966e201478c7bca2fd65025596 100755
--- a/src/tests/ofc22/deploy_specs.sh
+++ b/src/tests/ofc22/deploy_specs.sh
@@ -26,10 +26,18 @@ export TFS_COMPONENTS="context device pathcomp service slice nbi webui"
 # Uncomment to activate Monitoring
 export TFS_COMPONENTS="${TFS_COMPONENTS} monitoring"
 
-# Uncomment to activate ZTP and Policy Manager
-#export TFS_COMPONENTS="${TFS_COMPONENTS} ztp policy"
+# Uncomment to activate BGP-LS Speaker
+#export TFS_COMPONENTS="${TFS_COMPONENTS} bgpls_speaker"
+
+# Uncomment to activate Optical Controller
+#export TFS_COMPONENTS="${TFS_COMPONENTS} opticalcontroller"
+
+# 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"
 
@@ -39,6 +47,12 @@ export TFS_COMPONENTS="${TFS_COMPONENTS} ztp"
 # 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"
+
 # Set the tag you want to use for your images.
 export TFS_IMAGE_TAG="dev"
 
diff --git a/src/start.sh b/src/tests/ofc22/requirements.in
old mode 100755
new mode 100644
similarity index 79%
rename from src/start.sh
rename to src/tests/ofc22/requirements.in
index 32a016cc07d2602d5e00b7540b03355f539ed61d..30b11e65301a7bfc3ae89bf77e5e2734b0f3b566
--- a/src/start.sh
+++ b/src/tests/ofc22/requirements.in
@@ -1,4 +1,3 @@
-#!/usr/bin/env bash
 # Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,6 +12,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-docker network create -d bridge teraflowbridge
-
-docker run -d -p 7070:7070 --name monitoring --network=teraflowbridge monitoring:dockerfile
+requests==2.27.*
diff --git a/src/tests/ofc22/tests/test_functional_bootstrap.py b/src/tests/ofc22/tests/test_functional_bootstrap.py
index f149604929bfa305377545b2fdab50751dded7a1..8b1f98cd1966aeb3a88c5065f1e09fd3cdb0b355 100644
--- a/src/tests/ofc22/tests/test_functional_bootstrap.py
+++ b/src/tests/ofc22/tests/test_functional_bootstrap.py
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import logging, time
+import logging, os, time
 from common.Constants import DEFAULT_CONTEXT_NAME
 from common.proto.context_pb2 import ContextId, DeviceOperationalStatusEnum, Empty
 from common.proto.monitoring_pb2 import KpiDescriptorList
@@ -26,7 +26,7 @@ from tests.Fixtures import context_client, device_client, monitoring_client # py
 LOGGER = logging.getLogger(__name__)
 LOGGER.setLevel(logging.DEBUG)
 
-DESCRIPTOR_FILE = 'ofc22/descriptors_emulated.json'
+DESCRIPTOR_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'descriptors_emulated.json')
 ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
 
 def test_scenario_bootstrap(
diff --git a/src/tests/ofc22/tests/test_functional_cleanup.py b/src/tests/ofc22/tests/test_functional_cleanup.py
index 122526840796310519f8fe0feb8921e51467b21f..b1396f49a24e03befa409c8c2627dfd3d582f4b5 100644
--- a/src/tests/ofc22/tests/test_functional_cleanup.py
+++ b/src/tests/ofc22/tests/test_functional_cleanup.py
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import logging
+import logging, os
 from common.Constants import DEFAULT_CONTEXT_NAME
 from common.proto.context_pb2 import ContextId
 from common.tools.descriptor.Loader import DescriptorLoader, validate_empty_scenario
@@ -24,7 +24,7 @@ from tests.Fixtures import context_client, device_client    # pylint: disable=un
 LOGGER = logging.getLogger(__name__)
 LOGGER.setLevel(logging.DEBUG)
 
-DESCRIPTOR_FILE = 'ofc22/descriptors_emulated.json'
+DESCRIPTOR_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'descriptors_emulated.json')
 ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
 
 def test_scenario_cleanup(
diff --git a/src/tests/ofc22/tests/test_functional_create_service.py b/src/tests/ofc22/tests/test_functional_create_service.py
index dd7761f3871db48752f313dc53e8b7d2e2c38489..74c74483eb82325afec2cae833ebd460566da153 100644
--- a/src/tests/ofc22/tests/test_functional_create_service.py
+++ b/src/tests/ofc22/tests/test_functional_create_service.py
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import logging, random
+import logging, os, random
 from common.Constants import DEFAULT_CONTEXT_NAME
 from common.proto.context_pb2 import ContextId, Empty, ServiceTypeEnum
 from common.proto.kpi_sample_types_pb2 import KpiSampleType
@@ -29,7 +29,7 @@ from .Objects import WIM_SERVICE_CONNECTION_POINTS, WIM_SERVICE_TYPE
 LOGGER = logging.getLogger(__name__)
 LOGGER.setLevel(logging.DEBUG)
 
-DESCRIPTOR_FILE = 'ofc22/descriptors_emulated.json'
+DESCRIPTOR_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'descriptors_emulated.json')
 ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
 
 def test_service_creation(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name
diff --git a/src/tests/ofc22/tests/test_functional_delete_service.py b/src/tests/ofc22/tests/test_functional_delete_service.py
index 4fffc115e6c0ea881dea637dd741f99715d28c6a..daff29064f07e8117a4503fc243c7acac9f88bc6 100644
--- a/src/tests/ofc22/tests/test_functional_delete_service.py
+++ b/src/tests/ofc22/tests/test_functional_delete_service.py
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import logging
+import logging, os
 from common.Constants import DEFAULT_CONTEXT_NAME
 from common.proto.context_pb2 import ContextId, ServiceTypeEnum
 from common.tools.descriptor.Loader import DescriptorLoader
@@ -26,7 +26,7 @@ from .Fixtures import osm_wim               # pylint: disable=unused-import
 LOGGER = logging.getLogger(__name__)
 LOGGER.setLevel(logging.DEBUG)
 
-DESCRIPTOR_FILE = 'ofc22/descriptors_emulated.json'
+DESCRIPTOR_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'descriptors_emulated.json')
 ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
 
 def test_service_removal(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name
diff --git a/src/tests/ofc24/.gitlab-ci.yml b/src/tests/ofc24/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..0b5593b160ee14941546242dd3a4c3571407dedf
--- /dev/null
+++ b/src/tests/ofc24/.gitlab-ci.yml
@@ -0,0 +1,106 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.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 ofc22:
+  variables:
+    TEST_NAME: 'ofc22'
+  stage: build
+  before_script:
+    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
+  script:
+    - docker buildx build -t "${TEST_NAME}:latest" -f ./src/tests/${TEST_NAME}/Dockerfile .
+    - docker tag "${TEST_NAME}:latest" "$CI_REGISTRY_IMAGE/${TEST_NAME}:latest"
+    - docker push "$CI_REGISTRY_IMAGE/${TEST_NAME}:latest"
+  after_script:
+    - docker images --filter="dangling=true" --quiet | xargs -r docker rmi
+  rules:
+    - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)'
+    - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"'
+    - changes:
+      - src/common/**/*.py
+      - proto/*.proto
+      - src/tests/${TEST_NAME}/**/*.{py,in,sh,yml}
+      - src/tests/${TEST_NAME}/Dockerfile
+      - .gitlab-ci.yml
+
+# Deploy TeraFlowSDN and Execute end-2-end test
+end2end_test ofc22:
+  variables:
+    TEST_NAME: 'ofc22'
+  stage: end2end_test
+  # Disable to force running it after all other tasks
+  #needs:
+  #  - build ofc22
+  before_script:
+    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
+  script:
+    # Download Docker image to run the test
+    - docker pull "${CI_REGISTRY_IMAGE}/${TEST_NAME}:latest"
+
+    # Check MicroK8s is ready
+    - microk8s status --wait-ready
+    - kubectl get pods --all-namespaces
+
+    # Configure TeraFlowSDN deployment
+    # Uncomment if DEBUG log level is needed for the components
+    #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/contextservice.yaml
+    #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/deviceservice.yaml
+    #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="frontend").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/pathcompservice.yaml
+    #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/serviceservice.yaml
+    #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/sliceservice.yaml
+    #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/nbiservice.yaml
+    - source src/tests/${TEST_NAME}/deploy_specs.sh
+    #- export TFS_REGISTRY_IMAGES="${CI_REGISTRY_IMAGE}"
+    #- export TFS_SKIP_BUILD="YES"
+    #- export TFS_IMAGE_TAG="latest"
+    #- echo "TFS_REGISTRY_IMAGES=${CI_REGISTRY_IMAGE}"
+
+    # Deploy TeraFlowSDN
+    - ./deploy/crdb.sh
+    - ./deploy/nats.sh
+    - ./deploy/qdb.sh
+    - ./deploy/expose_dashboard.sh
+    - ./deploy/tfs.sh
+    - ./deploy/show.sh
+    
+    # Wait for Context to be subscribed to NATS
+    #- while ! kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server 2>&1 | grep -q 'Subscriber is Ready? True'; do sleep 1; done
+    #- kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server
+
+    # Run end-to-end tests
+    - if docker ps -a | grep ${TEST_NAME}; then docker rm -f ${TEST_NAME}; fi
+    - >
+      docker run -t --name ${TEST_NAME} --network=host 
+      --volume "$PWD/tfs_runtime_env_vars.sh:/var/teraflow/tfs_runtime_env_vars.sh"
+      --volume "$PWD/src/tests/${TEST_NAME}:/opt/results"
+      $CI_REGISTRY_IMAGE/${TEST_NAME}:latest
+  after_script:
+    - source src/tests/${TEST_NAME}/deploy_specs.sh
+    - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server
+    - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/deviceservice -c server
+    - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/pathcompservice -c frontend
+    - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/serviceservice -c server
+    - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/sliceservice -c server
+    - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/nbiservice -c server
+    - if docker ps -a | grep ${TEST_NAME}; then docker rm -f ${TEST_NAME}; fi
+    - docker images --filter="dangling=true" --quiet | xargs -r docker rmi
+  #coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/'
+  rules:
+    - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)'
+    - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"'
+  artifacts:
+      when: always
+      reports:
+        junit: ./src/tests/${TEST_NAME}/report_*.xml
diff --git a/src/tests/ofc24/Dockerfile b/src/tests/ofc24/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..8efa0c72c3bdc72bd336d10a4ffdbc0af025fc25
--- /dev/null
+++ b/src/tests/ofc24/Dockerfile
@@ -0,0 +1,101 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.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/tests/ofc24
+WORKDIR /var/teraflow/tests/ofc24
+COPY src/tests/ofc24/requirements.in requirements.in
+RUN pip-compile --quiet --output-file=requirements.txt requirements.in
+RUN python3 -m pip install -r requirements.txt
+
+# Add component files into working directory
+WORKDIR /var/teraflow
+COPY src/__init__.py ./__init__.py
+COPY src/common/*.py ./common/
+COPY src/common/tests/. ./common/tests/
+COPY src/common/tools/. ./common/tools/
+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/monitoring/__init__.py monitoring/__init__.py
+#COPY src/monitoring/client/. monitoring/client/
+#COPY src/monitoring/__init__.py monitoring/__init__.py
+#COPY src/monitoring/client/. monitoring/client/
+COPY src/e2e_orchestrator/__init__.py e2e_orchestrator/__init__.py
+COPY src/e2e_orchestrator/client/. e2e_orchestrator/client/
+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/tests/*.py ./tests/
+COPY src/tests/ofc24/__init__.py ./tests/ofc24/__init__.py
+COPY src/tests/ofc24/descriptors_topology.json ./tests/ofc24/descriptors_topology.json
+COPY src/tests/ofc24/tests/. ./tests/ofc24/tests/
+COPY src/tests/tools/. ./tests/tools/
+
+RUN tee ./run_tests.sh <<EOF
+#!/bin/bash
+source /var/teraflow/tfs_runtime_env_vars.sh
+export PYTHONPATH=/var/teraflow
+pytest --verbose --log-level=INFO /var/teraflow/tests/ofc24/tests/test_functional_bootstrap.py      --junitxml=/opt/results/report_bootstrap.xml
+pytest --verbose --log-level=INFO /var/teraflow/tests/ofc24/tests/test_functional_create_service.py --junitxml=/opt/results/report_create_service.xml
+pytest --verbose --log-level=INFO /var/teraflow/tests/ofc24/tests/test_functional_delete_service.py --junitxml=/opt/results/report_delete_service.xml
+pytest --verbose --log-level=INFO /var/teraflow/tests/ofc24/tests/test_functional_cleanup.py        --junitxml=/opt/results/report_cleanup.xml
+EOF
+RUN chmod ug+x ./run_tests.sh
+
+# Run the tests
+ENTRYPOINT ["./run_tests.sh"]
diff --git a/src/tests/ofc24/deploy-node-agents.sh b/src/tests/ofc24/deploy-node-agents.sh
new file mode 100755
index 0000000000000000000000000000000000000000..5c3c8d0d2a5c4e15f4d3dda6a00d90ff00b77539
--- /dev/null
+++ b/src/tests/ofc24/deploy-node-agents.sh
@@ -0,0 +1,84 @@
+#!/bin/bash
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.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.
+
+TEST_NAME="ofc24"
+
+
+echo
+echo "Pre-deploy clean-up:"
+echo "--------------------"
+docker rm -f na-t1 na-t2 na-r1 na-r2
+docker network rm na-br
+
+
+echo
+echo "Pull Docker images:"
+echo "-------------------"
+docker pull asgamb1/flexscale-hhi.img:latest
+docker pull asgamb1/flexscale-node.img:latest
+
+echo
+echo "Create Management Network and Node Agents:"
+echo "------------------------------------------"
+docker network create -d bridge --subnet=172.254.253.0/24 --gateway=172.254.253.254 --ip-range=172.254.253.0/24 na-br
+docker run -d --name na-t1 --network=na-br --ip 172.254.253.1 \
+    --volume "$PWD/src/tests/${TEST_NAME}/startNetconfAgent.sh:/confd/examples.confd/OC23/startNetconfAgent.sh" \
+    --volume "$PWD/src/tests/${TEST_NAME}/platform_t1.xml:/confd/examples.confd/OC23/init_openconfig-platform.xml" \
+    asgamb1/flexscale-hhi.img:latest /confd/examples.confd/OC23/startNetconfAgent.sh
+docker run -d --name na-t2 --network=na-br --ip 172.254.253.2 \
+    --volume "$PWD/src/tests/${TEST_NAME}/startNetconfAgent.sh:/confd/examples.confd/OC23/startNetconfAgent.sh" \
+    --volume "$PWD/src/tests/${TEST_NAME}/platform_t2.xml:/confd/examples.confd/OC23/init_openconfig-platform.xml" \
+    asgamb1/flexscale-hhi.img:latest /confd/examples.confd/OC23/startNetconfAgent.sh
+docker run -d --name na-r1 --network=na-br --ip 172.254.253.101 \
+    --volume "$PWD/src/tests/${TEST_NAME}/startNetconfAgent.sh:/confd/examples.confd/OC23/startNetconfAgent.sh" \
+    --volume "$PWD/src/tests/${TEST_NAME}/platform_r1.xml:/confd/examples.confd/OC23/init_openconfig-platform.xml" \
+    asgamb1/flexscale-node.img:latest /confd/examples.confd/OC23/startNetconfAgent.sh
+docker run -d --name na-r2 --network=na-br --ip 172.254.253.102 \
+    --volume "$PWD/src/tests/${TEST_NAME}/startNetconfAgent.sh:/confd/examples.confd/OC23/startNetconfAgent.sh" \
+    --volume "$PWD/src/tests/${TEST_NAME}/platform_r2.xml:/confd/examples.confd/OC23/init_openconfig-platform.xml" \
+    asgamb1/flexscale-node.img:latest /confd/examples.confd/OC23/startNetconfAgent.sh
+
+
+echo
+echo "Waiting for initialization..."
+echo "-----------------------------"
+docker ps -a
+sleep 5
+docker ps -a
+while ! docker logs na-t1 2>&1 | grep -q '*** ConfD OpenConfig NETCONF agent ***'; do sleep 1; done
+while ! docker logs na-t2 2>&1 | grep -q '*** ConfD OpenConfig NETCONF agent ***'; do sleep 1; done
+while ! docker logs na-r1 2>&1 | grep -q '*** ConfD OpenConfig NETCONF agent ***'; do sleep 1; done
+while ! docker logs na-r2 2>&1 | grep -q '*** ConfD OpenConfig NETCONF agent ***'; do sleep 1; done
+sleep 2
+docker ps -a
+
+
+echo
+echo "Dump Node Agent status:"
+echo "-----------------------"
+docker ps -a
+#docker logs na-t1
+#docker logs na-t2
+#docker logs na-r1
+#docker logs na-r2
+
+
+#echo
+#echo "Post-test clean-up:"
+#echo "-------------------"
+#docker rm -f na-t1 na-t2 na-r1 na-r2
+#docker network rm na-br
+
+echo "Done!"
diff --git a/src/tests/ofc24/deploy_specs.sh b/src/tests/ofc24/deploy_specs.sh
new file mode 100755
index 0000000000000000000000000000000000000000..ca5494de25ea17c08c2df1f2d62923c59b0e81e2
--- /dev/null
+++ b/src/tests/ofc24/deploy_specs.sh
@@ -0,0 +1,163 @@
+#!/bin/bash
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.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 BGP-LS Speaker
+#export TFS_COMPONENTS="${TFS_COMPONENTS} bgpls_speaker"
+
+# Uncomment to activate Optical Controller
+export TFS_COMPONENTS="${TFS_COMPONENTS} opticalcontroller"
+
+# 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"
+
+# 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 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"
+
+# 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/ofc24/descriptors_topology.json b/src/tests/ofc24/descriptors_topology.json
new file mode 100644
index 0000000000000000000000000000000000000000..6ae521c7642b24d428b26b11c29882ca46995014
--- /dev/null
+++ b/src/tests/ofc24/descriptors_topology.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": "10.0.2.15"}},
+                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "2023"}},
+                {"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": "10.0.2.15"}},
+                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "2024"}},
+                {"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": "10.0.2.15"}},
+                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "2025"}},
+                {"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": "10.0.2.15"}},
+                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "2026"}},
+                {"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/tests/ofc24/plat_r1.xml b/src/tests/ofc24/platform_r1.xml
similarity index 99%
rename from src/tests/ofc24/plat_r1.xml
rename to src/tests/ofc24/platform_r1.xml
index 47e135c2e3752de21dbe2f17550026e9622f4de1..625d7048a8062698b67db92f94f5d17c73dda0f4 100755
--- a/src/tests/ofc24/plat_r1.xml
+++ b/src/tests/ofc24/platform_r1.xml
@@ -117,4 +117,4 @@
             </properties>
         </component>
     </components>
-</config>
\ No newline at end of file
+</config>
diff --git a/src/tests/ofc24/plat_r2.xml b/src/tests/ofc24/platform_r2.xml
similarity index 99%
rename from src/tests/ofc24/plat_r2.xml
rename to src/tests/ofc24/platform_r2.xml
index dfaaf05ad7134a950ec11f411037b9a058b7d719..65f7ee45866b792bac06473d7a59f83eab4c8f54 100755
--- a/src/tests/ofc24/plat_r2.xml
+++ b/src/tests/ofc24/platform_r2.xml
@@ -117,4 +117,4 @@
             </properties>
         </component>
     </components>
-</config>
\ No newline at end of file
+</config>
diff --git a/src/tests/ofc24/platform_t1.xml b/src/tests/ofc24/platform_t1.xml
new file mode 100755
index 0000000000000000000000000000000000000000..09f316211dcd5fce4a31de45065bddb276c5b268
--- /dev/null
+++ b/src/tests/ofc24/platform_t1.xml
@@ -0,0 +1,295 @@
+<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
+	<components xmlns="http://openconfig.net/yang/platform">
+		<component>
+			<name>device</name>
+			<config>
+				<name>device</name>
+			</config>
+			<state>
+				<name>MellanoxSwitch</name>
+				<mfg-name>SSSA-CNIT</mfg-name>
+				<hardware-version>1.0.0</hardware-version>
+				<firmware-version>1.0.0</firmware-version>
+				<software-version>1.0.0</software-version>
+				<serial-no>610610</serial-no>
+				<type xmlns:typex="http://openconfig.net/yang/platform-types">typex:OPERATING_SYSTEM</type>
+			</state>
+		</component>
+		<component>
+			<name>channel-1</name>
+			<config>
+				<name>channel-1</name>
+			</config>
+			<state>
+				<name>channel-1</name>
+				<type xmlns:typex="http://openconfig.net/yang/transport-types">typex:OPTICAL_CHANNEL</type>
+			</state>
+			<optical-channel xmlns="http://openconfig.net/yang/terminal-device">
+				<config>
+					<frequency>191600000</frequency>
+					<target-output-power>100</target-output-power>
+					<operational-mode>0</operational-mode>
+					<line-port>transceiver-1</line-port>
+				</config>
+				<state>
+					<frequency>191600000</frequency>
+					<target-output-power>0</target-output-power>
+					<operational-mode>0</operational-mode>
+					<line-port>transceiver-1</line-port>
+					<group-id>1</group-id>
+					<output-power>
+						<instant>0</instant>
+						<avg>0</avg>
+						<min>0</min>
+						<max>0</max>
+						<interval>0</interval>
+					</output-power>
+					<input-power>
+						<instant>0</instant>
+						<avg>0</avg>
+						<min>0</min>
+						<max>0</max>
+						<interval>0</interval>
+					</input-power>
+					<laser-bias-current>
+						<instant>0</instant>
+						<avg>0</avg>
+						<min>0</min>
+						<max>0</max>
+						<interval>0</interval>
+					</laser-bias-current>
+					<chromatic-dispersion>
+						<instant>0</instant>
+						<avg>0</avg>
+						<min>0</min>
+						<max>0</max>
+					</chromatic-dispersion>
+					<polarization-mode-dispersion>
+						<instant>0</instant>
+						<avg>0</avg>
+						<min>0</min>
+						<max>0</max>
+					</polarization-mode-dispersion>
+					<second-order-polarization-mode-dispersion>
+						<instant>0</instant>
+						<avg>0</avg>
+						<min>0</min>
+						<max>0</max>
+					</second-order-polarization-mode-dispersion>
+					<polarization-dependent-loss>
+						<instant>0</instant>
+						<avg>0</avg>
+						<min>0</min>
+						<max>0</max>
+						<interval>0</interval>
+					</polarization-dependent-loss>
+				</state>
+			</optical-channel>
+		</component>
+		<component>
+			<name>transceiver-1</name>
+			<config>
+				<name>transceiver-1</name>
+			</config>
+			<state>
+				<name>transceiver-1</name>
+				<type xmlns:typex="http://openconfig.net/yang/platform-types">typex:TRANSCEIVER</type>
+			</state>
+			<transceiver xmlns="http://openconfig.net/yang/platform/transceiver">
+				<config>
+					<enabled>true</enabled>
+					<form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf>
+					<ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf>
+					<fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode>
+					<module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type>
+				</config>
+				<state>
+					<enabled>true</enabled>
+					<form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf>
+					<ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf>
+					<fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode>
+					<module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type>
+					<vendor>Cisco</vendor>
+					<vendor-part>400zr-QSFP-DD</vendor-part>
+					<vendor-rev>01</vendor-rev>
+					<serial-no>1567321</serial-no>
+				</state>
+				<physical-channels>
+					<channel>
+						<index>1</index>
+						<config>
+							<index>1</index>
+							<associated-optical-channel>channel-1</associated-optical-channel>
+						</config>
+						<!--state>
+							<index>1</index>
+							<associated-optical-channel>channel-4</associated-optical-channel>
+						</state-->
+					</channel>
+				</physical-channels>
+			</transceiver>
+		</component>
+		<component>
+			<name>port-1</name>
+			<config>
+				<name>port-1</name>
+			</config>
+			<state>
+				<name>port-1</name>
+				<type xmlns:typex="http://openconfig.net/yang/platform-types">typex:PORT</type>
+			</state>
+			<subcomponents>
+				<subcomponent>
+					<name>channel-1</name>
+					<config>
+						<name>channel-1</name>
+					</config>
+					<state>
+						<name>channel-1</name>
+					</state>
+				</subcomponent>
+			</subcomponents>
+			<properties>
+				<property>
+					<name>onos-index</name>
+					<config>
+						<name>onos-index</name>
+						<value>4</value>
+					</config>
+					<state>
+						<name>onos-index</name>
+						<value>4</value>
+					</state>
+				</property>
+				<property>
+					<name>odtn-port-type</name>
+					<config>
+						<name>odtn-port-type</name>
+						<value>line</value>
+					</config>
+					<state>
+						<name>odtn-port-type</name>
+						<value>line</value>
+					</state>
+				</property>
+			</properties>
+		</component>
+	</components>
+	<terminal-device xmlns="http://openconfig.net/yang/terminal-device">
+		<logical-channels>
+			<!--Description: Optical logical link-->
+			<channel>
+
+				<!--Description: Line (OTN) Port-->
+				<index>1</index>
+				<config>
+					<index>1</index>
+					<description>Logical channel 1</description>
+					<admin-state>DISABLED</admin-state>
+					<logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type>
+					<loopback-mode>NONE</loopback-mode>
+				</config>
+				<state>
+					<index>1</index>
+					<description>Logical channel 1</description>
+					<admin-state>DISABLED</admin-state>
+					<logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type>
+					<loopback-mode>NONE</loopback-mode>
+					<link-state>UP</link-state>
+				</state>
+				<ingress>
+					<config>
+						<transceiver>transceiver-1</transceiver>
+					</config>
+					<state>
+						<transceiver>transceiver-1</transceiver>
+					</state>
+				</ingress>
+				<otn>
+					<config>
+						<tti-msg-expected>test1</tti-msg-expected>
+						<tti-msg-transmit>test1</tti-msg-transmit>
+					</config>
+					<state>
+						<tti-msg-expected>test1</tti-msg-expected>
+						<tti-msg-transmit>test1</tti-msg-transmit>
+						<tti-msg-auto>0</tti-msg-auto>
+						<tti-msg-recv>0</tti-msg-recv>
+						<rdi-msg>0</rdi-msg>
+						<errored-seconds>0</errored-seconds>
+						<severely-errored-seconds>0</severely-errored-seconds>
+						<unavailable-seconds>0</unavailable-seconds>
+						<code-violations>0</code-violations>
+						<fec-uncorrectable-words>0</fec-uncorrectable-words>
+						<fec-corrected-bytes>0</fec-corrected-bytes>
+						<fec-corrected-bits>0</fec-corrected-bits>
+						<background-block-errors>0</background-block-errors>
+						<pre-fec-ber>
+							<instant>0.0</instant>
+							<avg>0.0</avg>
+							<min>0.0</min>
+							<max>0.0</max>
+						</pre-fec-ber>
+						<post-fec-ber>
+							<instant>0.0</instant>
+							<avg>0.0</avg>
+							<min>0.0</min>
+							<max>0.0</max>
+						</post-fec-ber>
+						<q-value>
+							<instant>0.0</instant>
+							<avg>0.0</avg>
+							<min>0.0</min>
+							<max>0.0</max>
+							<interval>0</interval>
+						</q-value>
+						<esnr>
+							<instant>0.0</instant>
+							<avg>0.0</avg>
+							<min>0.0</min>
+							<max>0.0</max>
+							<interval>0</interval>
+						</esnr>
+					</state>
+				</otn>
+				<logical-channel-assignments>
+					<assignment>
+						<index>1</index>
+						<config>
+							<index>1</index>
+							<description>Optical channel assigned 100</description>
+							<allocation>100</allocation>
+							<assignment-type>OPTICAL_CHANNEL</assignment-type>
+							<optical-channel>channel-1</optical-channel>
+						</config>
+						<state>
+							<index>1</index>
+							<description>Optical channel assigned 100</description>
+							<allocation>100</allocation>
+							<assignment-type>OPTICAL_CHANNEL</assignment-type>
+							<optical-channel>channel-1</optical-channel>
+						</state>
+					</assignment>
+				</logical-channel-assignments>
+			</channel>
+		</logical-channels>
+		<operational-modes>
+			<mode>
+				<mode-id>1</mode-id>
+				<state>
+					<mode-id>1</mode-id>
+					<description>FEC1</description>
+					<vendor-id>Ericsson</vendor-id>
+				</state>
+			</mode>
+			<mode>
+				<mode-id>2</mode-id>
+				<state>
+					<mode-id>2</mode-id>
+					<description>FEC2</description>
+					<vendor-id>Ericsson</vendor-id>
+				</state>
+			</mode>
+		</operational-modes>
+	</terminal-device>
+</config>
diff --git a/src/tests/ofc24/platform_t2.xml b/src/tests/ofc24/platform_t2.xml
new file mode 100755
index 0000000000000000000000000000000000000000..03c643c91f176b531ec25bda6fbb36c8bdb1c099
--- /dev/null
+++ b/src/tests/ofc24/platform_t2.xml
@@ -0,0 +1,295 @@
+<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
+	<components xmlns="http://openconfig.net/yang/platform">
+		<component>
+			<name>device</name>
+			<config>
+				<name>device</name>
+			</config>
+			<state>
+				<name>MellanoxSwitch</name>
+				<mfg-name>SSSA-CNIT</mfg-name>
+				<hardware-version>1.0.0</hardware-version>
+				<firmware-version>1.0.0</firmware-version>
+				<software-version>1.0.0</software-version>
+				<serial-no>610610</serial-no>
+				<type xmlns:typex="http://openconfig.net/yang/platform-types">typex:OPERATING_SYSTEM</type>
+			</state>
+		</component>
+		<component>
+			<name>channel-6</name>
+			<config>
+				<name>channel-6</name>
+			</config>
+			<state>
+				<name>channel-6</name>
+				<type xmlns:typex="http://openconfig.net/yang/transport-types">typex:OPTICAL_CHANNEL</type>
+			</state>
+			<optical-channel xmlns="http://openconfig.net/yang/terminal-device">
+				<config>
+					<frequency>191600000</frequency>
+					<target-output-power>100</target-output-power>
+					<operational-mode>0</operational-mode>
+					<line-port>transceiver-6</line-port>
+				</config>
+				<state>
+					<frequency>191600000</frequency>
+					<target-output-power>0</target-output-power>
+					<operational-mode>0</operational-mode>
+					<line-port>transceiver-6</line-port>
+					<group-id>1</group-id>
+					<output-power>
+						<instant>0</instant>
+						<avg>0</avg>
+						<min>0</min>
+						<max>0</max>
+						<interval>0</interval>
+					</output-power>
+					<input-power>
+						<instant>0</instant>
+						<avg>0</avg>
+						<min>0</min>
+						<max>0</max>
+						<interval>0</interval>
+					</input-power>
+					<laser-bias-current>
+						<instant>0</instant>
+						<avg>0</avg>
+						<min>0</min>
+						<max>0</max>
+						<interval>0</interval>
+					</laser-bias-current>
+					<chromatic-dispersion>
+						<instant>0</instant>
+						<avg>0</avg>
+						<min>0</min>
+						<max>0</max>
+					</chromatic-dispersion>
+					<polarization-mode-dispersion>
+						<instant>0</instant>
+						<avg>0</avg>
+						<min>0</min>
+						<max>0</max>
+					</polarization-mode-dispersion>
+					<second-order-polarization-mode-dispersion>
+						<instant>0</instant>
+						<avg>0</avg>
+						<min>0</min>
+						<max>0</max>
+					</second-order-polarization-mode-dispersion>
+					<polarization-dependent-loss>
+						<instant>0</instant>
+						<avg>0</avg>
+						<min>0</min>
+						<max>0</max>
+						<interval>0</interval>
+					</polarization-dependent-loss>
+				</state>
+			</optical-channel>
+		</component>
+		<component>
+			<name>transceiver-6</name>
+			<config>
+				<name>transceiver-6</name>
+			</config>
+			<state>
+				<name>transceiver-6</name>
+				<type xmlns:typex="http://openconfig.net/yang/platform-types">typex:TRANSCEIVER</type>
+			</state>
+			<transceiver xmlns="http://openconfig.net/yang/platform/transceiver">
+				<config>
+					<enabled>true</enabled>
+					<form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf>
+					<ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf>
+					<fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode>
+					<module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type>
+				</config>
+				<state>
+					<enabled>true</enabled>
+					<form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf>
+					<ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf>
+					<fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode>
+					<module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type>
+					<vendor>Cisco</vendor>
+					<vendor-part>400zr-QSFP-DD</vendor-part>
+					<vendor-rev>01</vendor-rev>
+					<serial-no>1567321</serial-no>
+				</state>
+				<physical-channels>
+					<channel>
+						<index>1</index>
+						<config>
+							<index>1</index>
+							<associated-optical-channel>channel-6</associated-optical-channel>
+						</config>
+						<!--state>
+							<index>1</index>
+							<associated-optical-channel>channel-4</associated-optical-channel>
+						</state-->
+					</channel>
+				</physical-channels>
+			</transceiver>
+		</component>
+		<component>
+			<name>port-6</name>
+			<config>
+				<name>port-6</name>
+			</config>
+			<state>
+				<name>port-6</name>
+				<type xmlns:typex="http://openconfig.net/yang/platform-types">typex:PORT</type>
+			</state>
+			<subcomponents>
+				<subcomponent>
+					<name>channel-6</name>
+					<config>
+						<name>channel-6</name>
+					</config>
+					<state>
+						<name>channel-6</name>
+					</state>
+				</subcomponent>
+			</subcomponents>
+			<properties>
+				<property>
+					<name>onos-index</name>
+					<config>
+						<name>onos-index</name>
+						<value>4</value>
+					</config>
+					<state>
+						<name>onos-index</name>
+						<value>4</value>
+					</state>
+				</property>
+				<property>
+					<name>odtn-port-type</name>
+					<config>
+						<name>odtn-port-type</name>
+						<value>line</value>
+					</config>
+					<state>
+						<name>odtn-port-type</name>
+						<value>line</value>
+					</state>
+				</property>
+			</properties>
+		</component>
+	</components>
+	<terminal-device xmlns="http://openconfig.net/yang/terminal-device">
+		<logical-channels>
+			<!--Description: Optical logical link-->
+			<channel>
+
+				<!--Description: Line (OTN) Port-->
+				<index>4</index>
+				<config>
+					<index>4</index>
+					<description>Logical channel 4</description>
+					<admin-state>DISABLED</admin-state>
+					<logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type>
+					<loopback-mode>NONE</loopback-mode>
+				</config>
+				<state>
+					<index>4</index>
+					<description>Logical channel 4</description>
+					<admin-state>DISABLED</admin-state>
+					<logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type>
+					<loopback-mode>NONE</loopback-mode>
+					<link-state>UP</link-state>
+				</state>
+				<ingress>
+					<config>
+						<transceiver>transceiver-6</transceiver>
+					</config>
+					<state>
+						<transceiver>transceiver-6</transceiver>
+					</state>
+				</ingress>
+				<otn>
+					<config>
+						<tti-msg-expected>test1</tti-msg-expected>
+						<tti-msg-transmit>test1</tti-msg-transmit>
+					</config>
+					<state>
+						<tti-msg-expected>test1</tti-msg-expected>
+						<tti-msg-transmit>test1</tti-msg-transmit>
+						<tti-msg-auto>0</tti-msg-auto>
+						<tti-msg-recv>0</tti-msg-recv>
+						<rdi-msg>0</rdi-msg>
+						<errored-seconds>0</errored-seconds>
+						<severely-errored-seconds>0</severely-errored-seconds>
+						<unavailable-seconds>0</unavailable-seconds>
+						<code-violations>0</code-violations>
+						<fec-uncorrectable-words>0</fec-uncorrectable-words>
+						<fec-corrected-bytes>0</fec-corrected-bytes>
+						<fec-corrected-bits>0</fec-corrected-bits>
+						<background-block-errors>0</background-block-errors>
+						<pre-fec-ber>
+							<instant>0.0</instant>
+							<avg>0.0</avg>
+							<min>0.0</min>
+							<max>0.0</max>
+						</pre-fec-ber>
+						<post-fec-ber>
+							<instant>0.0</instant>
+							<avg>0.0</avg>
+							<min>0.0</min>
+							<max>0.0</max>
+						</post-fec-ber>
+						<q-value>
+							<instant>0.0</instant>
+							<avg>0.0</avg>
+							<min>0.0</min>
+							<max>0.0</max>
+							<interval>0</interval>
+						</q-value>
+						<esnr>
+							<instant>0.0</instant>
+							<avg>0.0</avg>
+							<min>0.0</min>
+							<max>0.0</max>
+							<interval>0</interval>
+						</esnr>
+					</state>
+				</otn>
+				<logical-channel-assignments>
+					<assignment>
+						<index>1</index>
+						<config>
+							<index>1</index>
+							<description>Optical channel assigned 100</description>
+							<allocation>100</allocation>
+							<assignment-type>OPTICAL_CHANNEL</assignment-type>
+							<optical-channel>channel-6</optical-channel>
+						</config>
+						<state>
+							<index>1</index>
+							<description>Optical channel assigned 100</description>
+							<allocation>100</allocation>
+							<assignment-type>OPTICAL_CHANNEL</assignment-type>
+							<optical-channel>channel-6</optical-channel>
+						</state>
+					</assignment>
+				</logical-channel-assignments>
+			</channel>
+		</logical-channels>
+		<operational-modes>
+			<mode>
+				<mode-id>1</mode-id>
+				<state>
+					<mode-id>1</mode-id>
+					<description>FEC1</description>
+					<vendor-id>Ericsson</vendor-id>
+				</state>
+			</mode>
+			<mode>
+				<mode-id>2</mode-id>
+				<state>
+					<mode-id>2</mode-id>
+					<description>FEC2</description>
+					<vendor-id>Ericsson</vendor-id>
+				</state>
+			</mode>
+		</operational-modes>
+	</terminal-device>
+</config>
diff --git a/src/build.sh b/src/tests/ofc24/requirements.in
old mode 100755
new mode 100644
similarity index 57%
rename from src/build.sh
rename to src/tests/ofc24/requirements.in
index b1a7d299e546e4607a494dde3ec435f093da0c8d..30b11e65301a7bfc3ae89bf77e5e2734b0f3b566
--- a/src/build.sh
+++ b/src/tests/ofc24/requirements.in
@@ -1,4 +1,3 @@
-#!/usr/bin/env bash
 # Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,21 +12,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-
-# Make folder containing the script the root folder for its execution
-cd $(dirname $0)
-
-echo "BUILD context"
-context/genproto.sh
-docker build -t "context:develop" -f context/Dockerfile --quiet .
-docker build -t "context:test" -f context/tests/Dockerfile --quiet .
-
-cd monitoring
-./genproto.sh
-cd ..
-
-echo "BUILD monitoring"
-docker build -t "monitoring:dockerfile" -f monitoring/Dockerfile .
-
-echo "Prune unused images"
-docker image prune --force
+requests==2.27.*
diff --git a/src/tests/ofc24/startNetconfAgent.sh b/src/tests/ofc24/startNetconfAgent.sh
new file mode 100755
index 0000000000000000000000000000000000000000..10b721883799c4fd257e1f627ff1480259037702
--- /dev/null
+++ b/src/tests/ofc24/startNetconfAgent.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+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/t1.xml b/src/tests/ofc24/t1.xml
deleted file mode 100755
index 712615df8dd821ff8e79df9785d6d29324a25b7d..0000000000000000000000000000000000000000
--- a/src/tests/ofc24/t1.xml
+++ /dev/null
@@ -1,298 +0,0 @@
-<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
-    <components xmlns="http://openconfig.net/yang/platform">
-        <component>
-            <name>device</name>
-            <config>
-                <name>device</name>
-            </config>
-            <state>
-				<name>MellanoxSwitch</name>
-				<mfg-name>SSSA-CNIT</mfg-name>
-				<hardware-version>1.0.0</hardware-version>
-				<firmware-version>1.0.0</firmware-version>
-				<software-version>1.0.0</software-version>
-				<serial-no>610610</serial-no>
-				<type xmlns:typex="http://openconfig.net/yang/platform-types">typex:OPERATING_SYSTEM</type>
-			</state>
-		</component>
-		<component>
-			<name>channel-1</name>
-			<config>
-					<name>channel-1</name>
-			</config>
-			<state>
-				<name>channel-1</name>
-				<type xmlns:typex="http://openconfig.net/yang/transport-types">typex:OPTICAL_CHANNEL</type>
-			</state>
-			<optical-channel xmlns="http://openconfig.net/yang/terminal-device">
-				<config>
-					<frequency>191600000</frequency>
-					<target-output-power>100</target-output-power>
-					<operational-mode>0</operational-mode>
-					<line-port>transceiver-1</line-port>
-				</config>
-				<state>
-					<frequency>191600000</frequency>
-					<target-output-power>0</target-output-power>
-					<operational-mode>0</operational-mode>
-					<line-port>transceiver-1</line-port>
-					<group-id>1</group-id>
-					<output-power>
-						<instant>0</instant>
-						<avg>0</avg>
-						<min>0</min>
-						<max>0</max>
-						<interval>0</interval>
-					</output-power>
-					<input-power>
-						<instant>0</instant>
-						<avg>0</avg>
-						<min>0</min>
-						<max>0</max>
-						<interval>0</interval>
-					</input-power>
-					<laser-bias-current>
-						<instant>0</instant>
-						<avg>0</avg>
-						<min>0</min>
-						<max>0</max>
-						<interval>0</interval>
-					</laser-bias-current>
-					<chromatic-dispersion>
-						<instant>0</instant>
-						<avg>0</avg>
-						<min>0</min>
-						<max>0</max>
-					</chromatic-dispersion>
-					<polarization-mode-dispersion>
-						<instant>0</instant>
-						<avg>0</avg>
-						<min>0</min>
-						<max>0</max>
-					</polarization-mode-dispersion>
-					<second-order-polarization-mode-dispersion>
-						<instant>0</instant>
-						<avg>0</avg>
-						<min>0</min>
-						<max>0</max>
-					</second-order-polarization-mode-dispersion>
-					<polarization-dependent-loss>
-						<instant>0</instant>
-						<avg>0</avg>
-						<min>0</min>
-						<max>0</max>
-						<interval>0</interval>
-					</polarization-dependent-loss>
-				</state>
-			</optical-channel>
-		</component>
-		<component>
-			<name>transceiver-1</name>
-			<config>
-				<name>transceiver-1</name>
-			</config>
-			<state>
-				<name>transceiver-1</name>
-				<type xmlns:typex="http://openconfig.net/yang/platform-types">typex:TRANSCEIVER</type>
-			</state>
-			<transceiver xmlns="http://openconfig.net/yang/platform/transceiver">
-				<config>
-					<enabled>true</enabled>
-					<form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf>
-					<ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf>
-					<fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode>
-					<module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type>
-				</config>
-				<state>
-					<enabled>true</enabled>
-					<form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf>
-					<ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf>
-					<fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode>
-					<module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type>
-					<vendor>Cisco</vendor>
-					<vendor-part>400zr-QSFP-DD</vendor-part>
-					<vendor-rev>01</vendor-rev>
-					<serial-no>1567321</serial-no>
-				</state>
-				<physical-channels>
-					<channel>
-						<index>1</index>
-						<config>
-							<index>1</index>
-							<associated-optical-channel>channel-1</associated-optical-channel>
-						</config>
-						<!--state>
-							<index>1</index>
-							<associated-optical-channel>channel-4</associated-optical-channel>
-						</state-->
-					</channel>
-				</physical-channels>
-			</transceiver>
-		</component>
-    <component>
-                        <name>port-1</name>
-                        <config>
-                                <name>port-1</name>
-                        </config>
-                        <state>
-                                <name>port-1</name>
-                        <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:PORT</type>
-                        </state>
-                        <subcomponents>
-                                <subcomponent>
-                                        <name>channel-1</name>
-                                        <config>
-                                                <name>channel-1</name>
-                                        </config>
-                                        <state>
-                                                <name>channel-1</name>
-                                        </state>
-                                </subcomponent>
-                        </subcomponents>
-                        <properties>
-                                <property>
-                                        <name>onos-index</name>
-                                        <config>
-                                                <name>onos-index</name>
-                                                <value>4</value>
-                                        </config>
-                                        <state>
-                                                <name>onos-index</name>
-                                                <value>4</value>
-                                        </state>
-                                </property>
-                                <property>
-                                        <name>odtn-port-type</name>
-                                        <config>
-                                                <name>odtn-port-type</name>
-                                                <value>line</value>
-                                        </config>
-                                        <state>
-                                                <name>odtn-port-type</name>
-                                                <value>line</value>
-                                        </state>
-                                </property>
-                        </properties>
-                </component>
-
-   
-	</components>
-	<terminal-device xmlns="http://openconfig.net/yang/terminal-device">
-             <logical-channels>
-                  <!--Description: Optical logical link-->
-                  <channel>
-
-			<!--Description: Line (OTN) Port-->
-			<index>1</index>
-			<config>
-				<index>1</index>
-				<description>Logical channel 1</description>
-				<admin-state>DISABLED</admin-state>
-				<logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type>
-				<loopback-mode>NONE</loopback-mode>
-			</config>
-			<state>
-				<index>1</index>
-				<description>Logical channel 1</description>
-				<admin-state>DISABLED</admin-state>
-				<logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type>
-				<loopback-mode>NONE</loopback-mode>
-				<link-state>UP</link-state>
-			</state>
-		   	<ingress>
-				<config>
-					<transceiver>transceiver-1</transceiver>
-				</config>
-				<state>
-					<transceiver>transceiver-1</transceiver>
-				</state>
-			</ingress>
-			<otn>
-				<config>
-					<tti-msg-expected>test1</tti-msg-expected>
-					<tti-msg-transmit>test1</tti-msg-transmit>
-				</config>
-				<state>
-					<tti-msg-expected>test1</tti-msg-expected>
-					<tti-msg-transmit>test1</tti-msg-transmit>
-					<tti-msg-auto>0</tti-msg-auto>
-					<tti-msg-recv>0</tti-msg-recv>
-					<rdi-msg>0</rdi-msg>
-					<errored-seconds>0</errored-seconds>
-					<severely-errored-seconds>0</severely-errored-seconds>
-					<unavailable-seconds>0</unavailable-seconds>
-					<code-violations>0</code-violations>
-					<fec-uncorrectable-words>0</fec-uncorrectable-words>
-					<fec-corrected-bytes>0</fec-corrected-bytes>
-					<fec-corrected-bits>0</fec-corrected-bits>
-					<background-block-errors>0</background-block-errors>
-					<pre-fec-ber>
-						<instant>0.0</instant>
-						<avg>0.0</avg>
-						<min>0.0</min>
-						<max>0.0</max>
-					</pre-fec-ber>
-					<post-fec-ber>
-						<instant>0.0</instant>
-						<avg>0.0</avg>
-						<min>0.0</min>
-						<max>0.0</max>
-					</post-fec-ber>
-					<q-value>
-						<instant>0.0</instant>
-						<avg>0.0</avg>
-						<min>0.0</min>
-						<max>0.0</max>
-						<interval>0</interval>
-					</q-value>
-					<esnr>
-						<instant>0.0</instant>
-						<avg>0.0</avg>
-						<min>0.0</min>
-						<max>0.0</max>
-						<interval>0</interval>
-					</esnr>
-				</state>
-			</otn>
-			<logical-channel-assignments>
-				<assignment>
-					<index>1</index>
-					<config>
-							<index>1</index>
-							<description>Optical channel assigned 100</description>
-							<allocation>100</allocation>
-							<assignment-type>OPTICAL_CHANNEL</assignment-type>
-							<optical-channel>channel-1</optical-channel>
-					</config>
-					<state>
-							<index>1</index>
-							<description>Optical channel assigned 100</description>
-							<allocation>100</allocation>
-							<assignment-type>OPTICAL_CHANNEL</assignment-type>
-							<optical-channel>channel-1</optical-channel>
-					</state>
-				</assignment>
-			</logical-channel-assignments>
-                  </channel>
-           </logical-channels>
-    	   <operational-modes>
-           <mode>
-	   	<mode-id>1</mode-id>
-			<state>
-				<mode-id>1</mode-id>
-				<description>FEC1</description>
-				<vendor-id>Ericsson</vendor-id>
-			</state>
-		</mode>
-		<mode>
-		    <mode-id>2</mode-id>
-			<state>
-				<mode-id>2</mode-id>
-				<description>FEC2</description>
-				<vendor-id>Ericsson</vendor-id>
-			</state>
-		</mode>		
-    	   </operational-modes>
-	</terminal-device>
-</config>
-
diff --git a/src/tests/ofc24/t2.xml b/src/tests/ofc24/t2.xml
deleted file mode 100755
index 3a35e7e87eac7b14cd2bfa693560cc653f3719b9..0000000000000000000000000000000000000000
--- a/src/tests/ofc24/t2.xml
+++ /dev/null
@@ -1,298 +0,0 @@
-<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
-    <components xmlns="http://openconfig.net/yang/platform">
-        <component>
-            <name>device</name>
-            <config>
-                <name>device</name>
-            </config>
-            <state>
-				<name>MellanoxSwitch</name>
-				<mfg-name>SSSA-CNIT</mfg-name>
-				<hardware-version>1.0.0</hardware-version>
-				<firmware-version>1.0.0</firmware-version>
-				<software-version>1.0.0</software-version>
-				<serial-no>610610</serial-no>
-				<type xmlns:typex="http://openconfig.net/yang/platform-types">typex:OPERATING_SYSTEM</type>
-			</state>
-		</component>
-		<component>
-			<name>channel-6</name>
-			<config>
-					<name>channel-6</name>
-			</config>
-			<state>
-				<name>channel-6</name>
-				<type xmlns:typex="http://openconfig.net/yang/transport-types">typex:OPTICAL_CHANNEL</type>
-			</state>
-			<optical-channel xmlns="http://openconfig.net/yang/terminal-device">
-				<config>
-					<frequency>191600000</frequency>
-					<target-output-power>100</target-output-power>
-					<operational-mode>0</operational-mode>
-					<line-port>transceiver-6</line-port>
-				</config>
-				<state>
-					<frequency>191600000</frequency>
-					<target-output-power>0</target-output-power>
-					<operational-mode>0</operational-mode>
-					<line-port>transceiver-6</line-port>
-					<group-id>1</group-id>
-					<output-power>
-						<instant>0</instant>
-						<avg>0</avg>
-						<min>0</min>
-						<max>0</max>
-						<interval>0</interval>
-					</output-power>
-					<input-power>
-						<instant>0</instant>
-						<avg>0</avg>
-						<min>0</min>
-						<max>0</max>
-						<interval>0</interval>
-					</input-power>
-					<laser-bias-current>
-						<instant>0</instant>
-						<avg>0</avg>
-						<min>0</min>
-						<max>0</max>
-						<interval>0</interval>
-					</laser-bias-current>
-					<chromatic-dispersion>
-						<instant>0</instant>
-						<avg>0</avg>
-						<min>0</min>
-						<max>0</max>
-					</chromatic-dispersion>
-					<polarization-mode-dispersion>
-						<instant>0</instant>
-						<avg>0</avg>
-						<min>0</min>
-						<max>0</max>
-					</polarization-mode-dispersion>
-					<second-order-polarization-mode-dispersion>
-						<instant>0</instant>
-						<avg>0</avg>
-						<min>0</min>
-						<max>0</max>
-					</second-order-polarization-mode-dispersion>
-					<polarization-dependent-loss>
-						<instant>0</instant>
-						<avg>0</avg>
-						<min>0</min>
-						<max>0</max>
-						<interval>0</interval>
-					</polarization-dependent-loss>
-				</state>
-			</optical-channel>
-		</component>
-		<component>
-			<name>transceiver-6</name>
-			<config>
-				<name>transceiver-6</name>
-			</config>
-			<state>
-				<name>transceiver-6</name>
-				<type xmlns:typex="http://openconfig.net/yang/platform-types">typex:TRANSCEIVER</type>
-			</state>
-			<transceiver xmlns="http://openconfig.net/yang/platform/transceiver">
-				<config>
-					<enabled>true</enabled>
-					<form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf>
-					<ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf>
-					<fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode>
-					<module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type>
-				</config>
-				<state>
-					<enabled>true</enabled>
-					<form-factor-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:QSFP56_DD_TYPE1</form-factor-preconf>
-					<ethernet-pmd-preconf xmlns:typex="http://openconfig.net/yang/transport-types">typex:ETH_400GBASE_ZR</ethernet-pmd-preconf>
-					<fec-mode xmlns:typex="http://openconfig.net/yang/platform-types">typex:FEC_AUTO</fec-mode>
-					<module-functional-type xmlns:typex="http://openconfig.net/yang/transport-types">typex:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type>
-					<vendor>Cisco</vendor>
-					<vendor-part>400zr-QSFP-DD</vendor-part>
-					<vendor-rev>01</vendor-rev>
-					<serial-no>1567321</serial-no>
-				</state>
-				<physical-channels>
-					<channel>
-						<index>1</index>
-						<config>
-							<index>1</index>
-							<associated-optical-channel>channel-6</associated-optical-channel>
-						</config>
-						<!--state>
-							<index>1</index>
-							<associated-optical-channel>channel-4</associated-optical-channel>
-						</state-->
-					</channel>
-				</physical-channels>
-			</transceiver>
-		</component>
-    <component>
-                        <name>port-6</name>
-                        <config>
-                                <name>port-6</name>
-                        </config>
-                        <state>
-                                <name>port-6</name>
-                        <type xmlns:typex="http://openconfig.net/yang/platform-types">typex:PORT</type>
-                        </state>
-                        <subcomponents>
-                                <subcomponent>
-                                        <name>channel-6</name>
-                                        <config>
-                                                <name>channel-6</name>
-                                        </config>
-                                        <state>
-                                                <name>channel-6</name>
-                                        </state>
-                                </subcomponent>
-                        </subcomponents>
-                        <properties>
-                                <property>
-                                        <name>onos-index</name>
-                                        <config>
-                                                <name>onos-index</name>
-                                                <value>4</value>
-                                        </config>
-                                        <state>
-                                                <name>onos-index</name>
-                                                <value>4</value>
-                                        </state>
-                                </property>
-                                <property>
-                                        <name>odtn-port-type</name>
-                                        <config>
-                                                <name>odtn-port-type</name>
-                                                <value>line</value>
-                                        </config>
-                                        <state>
-                                                <name>odtn-port-type</name>
-                                                <value>line</value>
-                                        </state>
-                                </property>
-                        </properties>
-                </component>
-
-   
-	</components>
-	<terminal-device xmlns="http://openconfig.net/yang/terminal-device">
-             <logical-channels>
-                  <!--Description: Optical logical link-->
-                  <channel>
-
-			<!--Description: Line (OTN) Port-->
-			<index>4</index>
-			<config>
-				<index>4</index>
-				<description>Logical channel 4</description>
-				<admin-state>DISABLED</admin-state>
-				<logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type>
-				<loopback-mode>NONE</loopback-mode>
-			</config>
-			<state>
-				<index>4</index>
-				<description>Logical channel 4</description>
-				<admin-state>DISABLED</admin-state>
-				<logical-channel-type xmlns:type="http://openconfig.net/yang/transport-types">type:PROT_OTN</logical-channel-type>
-				<loopback-mode>NONE</loopback-mode>
-				<link-state>UP</link-state>
-			</state>
-		   	<ingress>
-				<config>
-					<transceiver>transceiver-6</transceiver>
-				</config>
-				<state>
-					<transceiver>transceiver-6</transceiver>
-				</state>
-			</ingress>
-			<otn>
-				<config>
-					<tti-msg-expected>test1</tti-msg-expected>
-					<tti-msg-transmit>test1</tti-msg-transmit>
-				</config>
-				<state>
-					<tti-msg-expected>test1</tti-msg-expected>
-					<tti-msg-transmit>test1</tti-msg-transmit>
-					<tti-msg-auto>0</tti-msg-auto>
-					<tti-msg-recv>0</tti-msg-recv>
-					<rdi-msg>0</rdi-msg>
-					<errored-seconds>0</errored-seconds>
-					<severely-errored-seconds>0</severely-errored-seconds>
-					<unavailable-seconds>0</unavailable-seconds>
-					<code-violations>0</code-violations>
-					<fec-uncorrectable-words>0</fec-uncorrectable-words>
-					<fec-corrected-bytes>0</fec-corrected-bytes>
-					<fec-corrected-bits>0</fec-corrected-bits>
-					<background-block-errors>0</background-block-errors>
-					<pre-fec-ber>
-						<instant>0.0</instant>
-						<avg>0.0</avg>
-						<min>0.0</min>
-						<max>0.0</max>
-					</pre-fec-ber>
-					<post-fec-ber>
-						<instant>0.0</instant>
-						<avg>0.0</avg>
-						<min>0.0</min>
-						<max>0.0</max>
-					</post-fec-ber>
-					<q-value>
-						<instant>0.0</instant>
-						<avg>0.0</avg>
-						<min>0.0</min>
-						<max>0.0</max>
-						<interval>0</interval>
-					</q-value>
-					<esnr>
-						<instant>0.0</instant>
-						<avg>0.0</avg>
-						<min>0.0</min>
-						<max>0.0</max>
-						<interval>0</interval>
-					</esnr>
-				</state>
-			</otn>
-			<logical-channel-assignments>
-				<assignment>
-					<index>1</index>
-					<config>
-							<index>1</index>
-							<description>Optical channel assigned 100</description>
-							<allocation>100</allocation>
-							<assignment-type>OPTICAL_CHANNEL</assignment-type>
-							<optical-channel>channel-6</optical-channel>
-					</config>
-					<state>
-							<index>1</index>
-							<description>Optical channel assigned 100</description>
-							<allocation>100</allocation>
-							<assignment-type>OPTICAL_CHANNEL</assignment-type>
-							<optical-channel>channel-6</optical-channel>
-					</state>
-				</assignment>
-			</logical-channel-assignments>
-                  </channel>
-           </logical-channels>
-    	   <operational-modes>
-           <mode>
-	   	<mode-id>1</mode-id>
-			<state>
-				<mode-id>1</mode-id>
-				<description>FEC1</description>
-				<vendor-id>Ericsson</vendor-id>
-			</state>
-		</mode>
-		<mode>
-		    <mode-id>2</mode-id>
-			<state>
-				<mode-id>2</mode-id>
-				<description>FEC2</description>
-				<vendor-id>Ericsson</vendor-id>
-			</state>
-		</mode>		
-    	   </operational-modes>
-	</terminal-device>
-</config>
-
diff --git a/src/tests/ofc24/tests/__init__.py b/src/tests/ofc24/tests/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..1549d9811aa5d1c193a44ad45d0d7773236c0612
--- /dev/null
+++ b/src/tests/ofc24/tests/__init__.py
@@ -0,0 +1,14 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.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/ofc24/tests/test_functional_bootstrap.py b/src/tests/ofc24/tests/test_functional_bootstrap.py
new file mode 100644
index 0000000000000000000000000000000000000000..bc648d16de57c8c287c7d601f994cb81ed45bc04
--- /dev/null
+++ b/src/tests/ofc24/tests/test_functional_bootstrap.py
@@ -0,0 +1,67 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import logging, os, time
+from common.Constants import DEFAULT_CONTEXT_NAME
+from common.proto.context_pb2 import ContextId, DeviceOperationalStatusEnum, Empty
+from common.tools.descriptor.Loader import DescriptorLoader, check_descriptor_load_results, validate_empty_scenario
+from common.tools.object_factory.Context import json_context_id
+from context.client.ContextClient import ContextClient
+from device.client.DeviceClient import DeviceClient
+from tests.Fixtures import context_client, device_client # pylint: disable=unused-import
+
+LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.DEBUG)
+
+DESCRIPTOR_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'descriptors_topology.json')
+ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
+
+def test_scenario_bootstrap(
+    context_client : ContextClient, # pylint: disable=redefined-outer-name
+    device_client : DeviceClient,   # pylint: disable=redefined-outer-name
+) -> None:
+    validate_empty_scenario(context_client)
+
+    descriptor_loader = DescriptorLoader(
+        descriptors_file=DESCRIPTOR_FILE, context_client=context_client, device_client=device_client)
+    results = descriptor_loader.process()
+    check_descriptor_load_results(results, descriptor_loader)
+    descriptor_loader.validate()
+
+    # Verify the scenario has no services/slices
+    response = context_client.GetContext(ADMIN_CONTEXT_ID)
+    assert len(response.service_ids) == 0
+    assert len(response.slice_ids) == 0
+
+def test_scenario_devices_enabled(
+    context_client : ContextClient,         # pylint: disable=redefined-outer-name
+) -> None:
+    """
+    This test validates that the devices are enabled.
+    """
+    DEVICE_OP_STATUS_ENABLED = DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_ENABLED
+
+    num_devices = -1
+    num_devices_enabled, num_retry = 0, 0
+    while (num_devices != num_devices_enabled) and (num_retry < 10):
+        time.sleep(1.0)
+        response = context_client.ListDevices(Empty())
+        num_devices = len(response.devices)
+        num_devices_enabled = 0
+        for device in response.devices:
+            if device.device_operational_status != DEVICE_OP_STATUS_ENABLED: continue
+            num_devices_enabled += 1
+        LOGGER.info('Num Devices enabled: {:d}/{:d}'.format(num_devices_enabled, num_devices))
+        num_retry += 1
+    assert num_devices_enabled == num_devices
diff --git a/src/tests/ofc24/tests/test_functional_cleanup.py b/src/tests/ofc24/tests/test_functional_cleanup.py
new file mode 100644
index 0000000000000000000000000000000000000000..5f1ce23f13051759e0e688a42c7118eaff8d3c72
--- /dev/null
+++ b/src/tests/ofc24/tests/test_functional_cleanup.py
@@ -0,0 +1,44 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import logging, os
+from common.Constants import DEFAULT_CONTEXT_NAME
+from common.proto.context_pb2 import ContextId
+from common.tools.descriptor.Loader import DescriptorLoader, validate_empty_scenario
+from common.tools.object_factory.Context import json_context_id
+from context.client.ContextClient import ContextClient
+from device.client.DeviceClient import DeviceClient
+from tests.Fixtures import context_client, device_client    # pylint: disable=unused-import
+
+LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.DEBUG)
+
+DESCRIPTOR_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'descriptors_topology.json')
+ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
+
+def test_scenario_cleanup(
+    context_client : ContextClient, # pylint: disable=redefined-outer-name
+    device_client : DeviceClient,   # pylint: disable=redefined-outer-name
+) -> None:
+    # Verify the scenario has no services/slices
+    response = context_client.GetContext(ADMIN_CONTEXT_ID)
+    assert len(response.service_ids) == 0
+    assert len(response.slice_ids) == 0
+
+    # Load descriptors and validate the base scenario
+    descriptor_loader = DescriptorLoader(
+        descriptors_file=DESCRIPTOR_FILE, context_client=context_client, device_client=device_client)
+    descriptor_loader.validate()
+    descriptor_loader.unload()
+    validate_empty_scenario(context_client)
diff --git a/src/tests/ofc24/tests/test_functional_create_service.py b/src/tests/ofc24/tests/test_functional_create_service.py
new file mode 100644
index 0000000000000000000000000000000000000000..74c74483eb82325afec2cae833ebd460566da153
--- /dev/null
+++ b/src/tests/ofc24/tests/test_functional_create_service.py
@@ -0,0 +1,102 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import logging, os, random
+from common.Constants import DEFAULT_CONTEXT_NAME
+from common.proto.context_pb2 import ContextId, Empty, ServiceTypeEnum
+from common.proto.kpi_sample_types_pb2 import KpiSampleType
+from common.tools.descriptor.Loader import DescriptorLoader
+from common.tools.grpc.Tools import grpc_message_to_json_string
+from common.tools.object_factory.Context import json_context_id
+from context.client.ContextClient import ContextClient
+from monitoring.client.MonitoringClient import MonitoringClient
+from tests.Fixtures import context_client, monitoring_client                    # pylint: disable=unused-import
+from tests.tools.mock_osm.MockOSM import MockOSM
+from .Fixtures import osm_wim                                                   # pylint: disable=unused-import
+from .Objects import WIM_SERVICE_CONNECTION_POINTS, WIM_SERVICE_TYPE
+
+LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.DEBUG)
+
+DESCRIPTOR_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'descriptors_emulated.json')
+ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
+
+def test_service_creation(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name
+    # Load descriptors and validate the base scenario
+    descriptor_loader = DescriptorLoader(descriptors_file=DESCRIPTOR_FILE, context_client=context_client)
+    descriptor_loader.validate()
+
+    # Verify the scenario has no services/slices
+    response = context_client.GetContext(ADMIN_CONTEXT_ID)
+    assert len(response.service_ids) == 0
+    assert len(response.slice_ids) == 0
+
+    # Create Connectivity Service
+    service_uuid = osm_wim.create_connectivity_service(WIM_SERVICE_TYPE, WIM_SERVICE_CONNECTION_POINTS)
+    osm_wim.get_connectivity_service_status(service_uuid)
+
+    # Ensure slices and services are created
+    response = context_client.ListSlices(ADMIN_CONTEXT_ID)
+    LOGGER.info('Slices[{:d}] = {:s}'.format(len(response.slices), grpc_message_to_json_string(response)))
+    assert len(response.slices) == 1 # OSM slice
+
+    response = context_client.ListServices(ADMIN_CONTEXT_ID)
+    LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response)))
+    assert len(response.services) == 2 # 1xL3NM + 1xTAPI
+
+    for service in response.services:
+        service_id = service.service_id
+        response = context_client.ListConnections(service_id)
+        LOGGER.info('  ServiceId[{:s}] => Connections[{:d}] = {:s}'.format(
+            grpc_message_to_json_string(service_id), len(response.connections), grpc_message_to_json_string(response)))
+
+        if service.service_type == ServiceTypeEnum.SERVICETYPE_L3NM:
+            assert len(response.connections) == 1 # 1 connection per service
+        elif service.service_type == ServiceTypeEnum.SERVICETYPE_TAPI_CONNECTIVITY_SERVICE:
+            assert len(response.connections) == 1 # 1 connection per service
+        else:
+            str_service = grpc_message_to_json_string(service)
+            raise Exception('Unexpected ServiceType: {:s}'.format(str_service))
+
+
+def test_scenario_kpi_values_created(
+    monitoring_client: MonitoringClient,    # pylint: disable=redefined-outer-name
+) -> None:
+    """
+    This test validates that KPI values have been inserted into the monitoring database.
+    We short k KPI descriptors to test.
+    """
+    response = monitoring_client.GetKpiDescriptorList(Empty())
+    kpi_descriptors = random.choices(response.kpi_descriptor_list, k=2)
+
+    for kpi_descriptor in kpi_descriptors:
+        MSG = 'KPI(kpi_uuid={:s}, device_uuid={:s}, endpoint_uuid={:s}, service_uuid={:s}, kpi_sample_type={:s})...'
+        LOGGER.info(MSG.format(
+            str(kpi_descriptor.kpi_id.kpi_id.uuid), str(kpi_descriptor.device_id.device_uuid.uuid),
+            str(kpi_descriptor.endpoint_id.endpoint_uuid.uuid), str(kpi_descriptor.service_id.service_uuid.uuid),
+            str(KpiSampleType.Name(kpi_descriptor.kpi_sample_type))))
+        response = monitoring_client.GetInstantKpi(kpi_descriptor.kpi_id)
+        kpi_uuid = response.kpi_id.kpi_id.uuid
+        assert kpi_uuid == kpi_descriptor.kpi_id.kpi_id.uuid
+        kpi_value_type = response.kpi_value.WhichOneof('value')
+        if kpi_value_type is None:
+            MSG = '  KPI({:s}): No instant value found'
+            LOGGER.warning(MSG.format(str(kpi_uuid)))
+        else:
+            kpi_timestamp = response.timestamp.timestamp
+            assert kpi_timestamp > 0
+            assert kpi_value_type == 'floatVal'
+            kpi_value = getattr(response.kpi_value, kpi_value_type)
+            MSG = '  KPI({:s}): timestamp={:s} value_type={:s} value={:s}'
+            LOGGER.info(MSG.format(str(kpi_uuid), str(kpi_timestamp), str(kpi_value_type), str(kpi_value)))
diff --git a/src/tests/ofc24/tests/test_functional_delete_service.py b/src/tests/ofc24/tests/test_functional_delete_service.py
new file mode 100644
index 0000000000000000000000000000000000000000..daff29064f07e8117a4503fc243c7acac9f88bc6
--- /dev/null
+++ b/src/tests/ofc24/tests/test_functional_delete_service.py
@@ -0,0 +1,74 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import logging, os
+from common.Constants import DEFAULT_CONTEXT_NAME
+from common.proto.context_pb2 import ContextId, ServiceTypeEnum
+from common.tools.descriptor.Loader import DescriptorLoader
+from common.tools.grpc.Tools import grpc_message_to_json_string
+from common.tools.object_factory.Context import json_context_id
+from context.client.ContextClient import ContextClient
+from tests.Fixtures import context_client   # pylint: disable=unused-import
+from tests.tools.mock_osm.MockOSM import MockOSM
+from .Fixtures import osm_wim               # pylint: disable=unused-import
+
+LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.DEBUG)
+
+DESCRIPTOR_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'descriptors_emulated.json')
+ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
+
+def test_service_removal(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name
+    # Ensure slices and services are created
+    response = context_client.ListSlices(ADMIN_CONTEXT_ID)
+    LOGGER.info('Slices[{:d}] = {:s}'.format(len(response.slices), grpc_message_to_json_string(response)))
+    assert len(response.slices) == 1 # OSM slice
+
+    response = context_client.ListServices(ADMIN_CONTEXT_ID)
+    LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response)))
+    assert len(response.services) == 2 # 1xL3NM + 1xTAPI
+
+    service_uuids = set()
+    for service in response.services:
+        service_id = service.service_id
+        response = context_client.ListConnections(service_id)
+        LOGGER.info('  ServiceId[{:s}] => Connections[{:d}] = {:s}'.format(
+            grpc_message_to_json_string(service_id), len(response.connections), grpc_message_to_json_string(response)))
+
+        if service.service_type == ServiceTypeEnum.SERVICETYPE_L3NM:
+            assert len(response.connections) == 1 # 1 connection per service
+            service_uuid = service_id.service_uuid.uuid
+            service_uuids.add(service_uuid)
+            osm_wim.conn_info[service_uuid] = {}
+        elif service.service_type == ServiceTypeEnum.SERVICETYPE_TAPI_CONNECTIVITY_SERVICE:
+            assert len(response.connections) == 1 # 1 connection per service
+        else:
+            str_service = grpc_message_to_json_string(service)
+            raise Exception('Unexpected ServiceType: {:s}'.format(str_service))
+
+    # Identify service to delete
+    assert len(service_uuids) == 1  # assume a single L3NM service has been created
+    service_uuid = set(service_uuids).pop()
+
+    # Delete Connectivity Service
+    osm_wim.delete_connectivity_service(service_uuid)
+
+    # Verify the scenario has no services/slices
+    response = context_client.GetContext(ADMIN_CONTEXT_ID)
+    assert len(response.service_ids) == 0
+    assert len(response.slice_ids) == 0
+
+    # Load descriptors and validate the base scenario
+    descriptor_loader = DescriptorLoader(descriptors_file=DESCRIPTOR_FILE, context_client=context_client)
+    descriptor_loader.validate()
diff --git a/src/webui/.gitlab-ci.yml b/src/webui/.gitlab-ci.yml
index 59d21dfb6ff89d441d55ff392f20a9a746a378fe..4ef2c847b73a9afb107b53513bebdca5f349a962 100644
--- a/src/webui/.gitlab-ci.yml
+++ b/src/webui/.gitlab-ci.yml
@@ -21,7 +21,7 @@ build webui:
   before_script:
     - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
   script:
-    - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile .
+    - docker 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:
diff --git a/src/ztp/.gitlab-ci.yml b/src/ztp/.gitlab-ci.yml
index a40a14f495b46da55f47d1bbb851fc62e261b32c..bc15c9aafc96774acb9977aac40d23d52faad9fc 100644
--- a/src/ztp/.gitlab-ci.yml
+++ b/src/ztp/.gitlab-ci.yml
@@ -24,7 +24,7 @@ build ztp:
     - export IMAGE_TAG=$(grep -m1 '<version>' ./src/$IMAGE_NAME/pom.xml | grep -oP  '(?<=>).*(?=<)')
     - echo "IMAGE_TAG=${IMAGE_TAG}" >> ${BUILD_ENV}
     - cat ${BUILD_ENV}
-    - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/src/main/docker/Dockerfile.multistage.jvm ./src/$IMAGE_NAME/ --target builder
+    - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/src/main/docker/Dockerfile.multistage.jvm ./src/$IMAGE_NAME/ --target builder
   after_script:
     - docker images --filter="dangling=true" --quiet | xargs -r docker rmi
   artifacts:
@@ -50,7 +50,7 @@ unit_test ztp:
     - docker rm ${REPORTS_CONTAINER} || true
   script:
     - echo "Running tests for image ${IMAGE_TAG}"
-    - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/src/main/docker/Dockerfile.multistage.jvm ./src/$IMAGE_NAME/ --target unit-test
+    - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/src/main/docker/Dockerfile.multistage.jvm ./src/$IMAGE_NAME/ --target unit-test
     # Transfer JaCoCo and Surefire reports from within tests image
     - docker create --name ${REPORTS_CONTAINER} "$IMAGE_NAME:$IMAGE_TAG"
     - mkdir -p ${REPORTS_PATH}
@@ -60,7 +60,7 @@ unit_test ztp:
     - cat ${REPORTS_PATH}/coverage.html | grep -o 'Total[^%]*%' | sed 's/<.*>/ /; s/Total/JaCoCo Coverage Total:/'
     - docker run -v "$(pwd)/src/${IMAGE_NAME}:/${IMAGE_NAME}" --rm registry.gitlab.com/haynes/jacoco2cobertura:1.0.7 python /opt/cover2cover.py ${IMAGE_NAME}/reports/jacoco.xml ${IMAGE_NAME}/src/main/java > ${REPORTS_PATH}/cobertura.xml
     # Build final image
-    - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/src/main/docker/Dockerfile.multistage.jvm ./src/$IMAGE_NAME/ --target release
+    - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/src/main/docker/Dockerfile.multistage.jvm ./src/$IMAGE_NAME/ --target release
     - docker tag "$IMAGE_NAME:$IMAGE_TAG" "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG"
     - docker push "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG"
   after_script: