From c9818c6a499b10adbf6bb60f99d79e7a575b8732 Mon Sep 17 00:00:00 2001
From: Lluis Gifre <lluis.gifre@cttc.es>
Date: Thu, 10 Feb 2022 18:33:14 +0000
Subject: [PATCH] Integrate OFC'22 functional test into develop

---
 .gitlab-ci.yml                                |    2 -
 INSTALL.md                                    |   22 +-
 README.md                                     |    9 +-
 configure_dashboards.sh                       |   40 +-
 data/.gitignore                               |    1 +
 deploy_in_kubernetes.sh                       |   63 +-
 manifests/computeservice.yaml                 |    9 +-
 manifests/contextservice.yaml                 |    3 +-
 manifests/deviceservice.yaml                  |    2 +-
 manifests/monitoringservice.yaml              |   10 +-
 manifests/serviceservice.yaml                 |    2 +-
 manifests/webuiservice.yaml                   |    3 -
 ofc22                                         |    1 +
 open_dashboard.sh                             |   15 +
 proto/service.proto                           |    7 +-
 run_tests_locally.sh                          |   22 +-
 src/automation/.gitlab-ci.yml                 |   49 +-
 src/automation/pom.xml                        |   13 +-
 .../src/main/docker/Dockerfile.multistage.jvm |    2 +-
 .../automation/AutomationGatewayImpl.java     |   18 +-
 .../automation/AutomationService.java         |    5 +-
 .../automation/AutomationServiceImpl.java     |   41 +-
 .../automation/ContextSubscriber.java         |   57 +-
 .../eu/teraflow/automation/Serializer.java    |  208 +
 .../automation/context/ContextGateway.java    |    5 +-
 .../context/ContextGatewayImpl.java           |  108 +-
 .../automation/context/ContextService.java    |    5 +-
 .../context/ContextServiceImpl.java           |    7 +-
 .../automation/context/model/Event.java       |   12 +-
 .../automation/device/DeviceGateway.java      |    6 +-
 .../automation/device/DeviceGatewayImpl.java  |  138 +-
 .../automation/device/DeviceService.java      |    6 +-
 .../automation/device/DeviceServiceImpl.java  |    6 +-
 .../automation/device/model/ConfigRule.java   |   12 +-
 .../automation/device/{ => model}/Device.java |   44 +-
 .../automation/device/model/DeviceConfig.java |   10 +-
 .../automation/device/model/DeviceEvent.java  |   13 +-
 .../automation/device/model/DeviceId.java     |   13 -
 .../automation/device/model/DeviceType.java   |   14 -
 .../automation/device/model/Uuid.java         |   14 -
 .../automation/model/DeviceRoleId.java        |   17 +-
 .../src/main/resources/application.yaml       |   21 +-
 .../resources/teraflow-automation-banner.txt  |    9 +
 .../AutomationFunctionalServiceTest.java      |   24 +-
 .../automation/AutomationServiceTest.java     |  119 +-
 .../teraflow/automation/SerializerTest.java   |  365 +
 .../grpc/context/ContextOuterClass.java       | 7974 ++++++++++-------
 .../grpc/context/ContextService.java          |   12 +
 .../grpc/context/ContextServiceBean.java      |   49 +
 .../grpc/context/ContextServiceClient.java    |   25 +
 .../grpc/context/ContextServiceGrpc.java      |  437 +
 .../context/MutinyContextServiceGrpc.java     |  144 +
 .../target/kubernetes/kubernetes.yml          |   50 +-
 src/automation/util/set_version.sh            |   17 +
 src/common/DeviceTypes.py                     |   11 +
 src/common/Settings.py                        |   18 +-
 src/common/orm/model/Model.py                 |   12 +-
 src/common/rpc_method_wrapper/Decorator.py    |    6 +-
 src/common/tests/EventTools.py                |   69 +
 src/{compute => common}/tests/MockService.py  |    0
 .../tests/MockServicerImpl_Context.py         |   59 +-
 src/common/tests/MockServicerImpl_Device.py   |   37 +
 .../tests/MockServicerImpl_Service.py         |   13 +-
 src/common/tools/client/RetryDecorator.py     |   36 +-
 src/common/tools/grpc/Tools.py                |   21 +
 .../tools/grpc}/__init__.py                   |    0
 src/common/tools/object_factory/ConfigRule.py |   13 +
 src/common/tools/object_factory/Connection.py |   18 +
 src/common/tools/object_factory/Constraint.py |    6 +
 src/common/tools/object_factory/Context.py    |    9 +
 src/common/tools/object_factory/Device.py     |   93 +
 src/common/tools/object_factory/EndPoint.py   |   19 +
 src/common/tools/object_factory/Link.py       |    8 +
 src/common/tools/object_factory/Service.py    |   34 +
 src/common/tools/object_factory/Topology.py   |   14 +
 .../tools/object_factory}/__init__.py         |    0
 src/compute/Dockerfile                        |    2 +-
 src/compute/client/ComputeClient.py           |   15 +-
 src/compute/requirements.in                   |   23 +-
 src/compute/service/__main__.py               |    7 +-
 .../nbi_plugins/ietf_l2vpn/L2VPN_Service.py   |    7 +-
 .../ietf_l2vpn/L2VPN_SiteNetworkAccesses.py   |   13 +-
 src/compute/tests/Constants.py                |   59 +
 src/compute/tests/Tools.py                    |    7 -
 src/compute/tests/mock_osm/MockOSM.py         |  116 +-
 .../tests/mock_osm/WimconnectorIETFL2VPN.py   |    2 +-
 src/compute/tests/test_unitary.py             |   21 +-
 src/context/Dockerfile                        |    2 +-
 src/context/client/ContextClient.py           |   73 +-
 src/context/client/EventsCollector.py         |   80 +
 src/context/requirements.in                   |   20 +-
 src/context/service/Populate.py               |   40 +-
 src/context/service/__main__.py               |    8 +-
 .../grpc_server/ContextServiceServicerImpl.py |  859 +-
 src/context/service/rest_server/Resources.py  |   45 +-
 src/context/tests/Objects.py                  |  185 +
 src/context/tests/Tools.py                    |   27 -
 src/context/tests/example_objects.py          |  220 -
 src/context/tests/test_unitary.py             |  382 +-
 .../client/DbscanServingClient.py             |    3 +-
 src/device/Dockerfile                         |    2 +-
 src/device/client/DeviceClient.py             |   11 +-
 src/device/requirements.in                    |   35 +-
 .../service/DeviceServiceServicerImpl.py      |  128 +-
 src/device/service/MonitoringLoops.py         |   10 +-
 src/device/service/__main__.py                |   19 +-
 .../service/driver_api/DriverFactory.py       |    6 +-
 .../service/driver_api/DriverInstanceCache.py |    3 +-
 src/device/service/driver_api/FilterFields.py |   12 +-
 src/device/service/drivers/__init__.py        |   20 +-
 .../drivers/emulated/EmulatedDriver.py        |   84 +-
 src/device/tests/CommonObjects.py             |   35 +-
 src/device/tests/Device_Emulated.py           |  133 +-
 .../tests/Device_OpenConfig_Template.py       |   39 +-
 .../tests/Device_Transport_Api_Template.py    |   54 +-
 src/device/tests/Tools.py                     |   25 -
 src/device/tests/device_p4.py                 |   35 +-
 src/device/tests/test_unitary.py              |  169 +-
 .../client/l3_attackmitigatorClient.py        |    6 +-
 .../l3_centralizedattackdetectorClient.py     |    5 +-
 src/monitoring/Config.py                      |   14 +
 src/monitoring/Dockerfile                     |    2 +-
 src/monitoring/requirements.in                |    5 +-
 src/monitoring/service/EventTools.py          |   49 +-
 src/monitoring/service/MonitoringService.py   |   13 +-
 .../service/MonitoringServiceServicerImpl.py  |   38 +-
 src/monitoring/service/SqliteTools.py         |    5 +-
 src/monitoring/service/__main__.py            |   77 +-
 src/monitoring/tests/test_unitary.py          |   42 +-
 .../client/OpticalAttackMitigatorClient.py    |    3 +-
 .../OpticalCentralizedAttackDetectorClient.py |    9 +-
 src/service/Dockerfile                        |    2 +-
 src/service/client/ServiceClient.py           |   16 +-
 src/service/requirements.in                   |   39 +-
 .../service/ServiceServiceServicerImpl.py     |  199 +-
 src/service/service/Tools.py                  |  203 +-
 src/service/service/__main__.py               |   16 +-
 .../service/database/DatabaseServiceTools.py  |    3 +-
 src/service/service/database/LinkModel.py     |   26 +
 .../service/database/RelationModels.py        |   18 +-
 src/service/service/database/TopologyModel.py |   54 +-
 .../service/path_computation_element/Enums.py |   23 +
 .../PathComputationElement.py                 |  357 +
 .../service/path_computation_element/Tools.py |   29 +
 .../path_computation_element/TopologyViews.py |   43 +
 .../path_computation_element/__init__.py      |    0
 .../service/service_handlers/__init__.py      |    7 +
 .../L3NMEmulatedServiceHandler.py             |    4 +
 .../tapi_tapi/TapiServiceHandler.py           |  156 +
 .../service_handlers/tapi_tapi/__init__.py    |    0
 src/service/tests/.gitignore                  |    1 -
 src/service/tests/CommonObjects.py            |   33 +-
 src/service/tests/ServiceHandler_L3NM_EMU.py  |  202 +-
 src/service/tests/ServiceHandler_L3NM_OC.py   |  135 +
 src/service/tests/test_unitary.py             |  176 +-
 src/tester_functional/.gitlab-ci.yml          |   67 -
 src/tester_functional/Dockerfile              |   35 -
 src/tester_functional/definitions.py          |  165 -
 src/tester_functional/requirements.in         |    6 -
 .../test_context_device_service.py            |  102 -
 src/tester_integration/.gitlab-ci.yml         |   78 -
 src/tester_integration/Dockerfile             |   35 -
 src/tester_integration/definitions.py         |  165 -
 src/tester_integration/requirements.in        |    6 -
 .../test_context_device_service.py            |  138 -
 src/tests/.gitlab-ci.yml                      |    3 +
 src/tests/__init__.py                         |    0
 src/tests/ofc22/README.md                     |   93 +
 src/tests/ofc22/__init__.py                   |    0
 src/tests/ofc22/deploy_in_kubernetes.sh       |   13 +
 src/tests/ofc22/expose_services.yaml          |   57 +
 src/tests/ofc22/run_test_01_bootstrap.sh      |   26 +
 src/tests/ofc22/run_test_02_create_service.sh |   23 +
 src/tests/ofc22/run_test_03_delete_service.sh |   23 +
 src/tests/ofc22/run_test_04_cleanup.sh        |   23 +
 src/tests/ofc22/show_deploy.sh                |    4 +
 src/tests/ofc22/show_logs_automation.sh       |    2 +
 src/tests/ofc22/show_logs_compute.sh          |    2 +
 src/tests/ofc22/show_logs_context.sh          |    2 +
 src/tests/ofc22/show_logs_device.sh           |    2 +
 src/tests/ofc22/show_logs_monitoring.sh       |    2 +
 src/tests/ofc22/show_logs_service.sh          |    2 +
 src/tests/ofc22/show_logs_webui.sh            |    2 +
 src/tests/ofc22/tests/.gitignore              |    2 +
 src/tests/ofc22/tests/Objects.py              |  218 +
 src/tests/ofc22/tests/__init__.py             |    0
 .../ofc22/tests/test_functional_bootstrap.py  |  190 +
 .../ofc22/tests/test_functional_cleanup.py    |  109 +
 .../tests/test_functional_create_service.py   |  115 +
 .../tests/test_functional_delete_service.py   |  120 +
 src/webui/Config.py                           |    4 +-
 src/webui/grafana_dashboard.json              |    2 +-
 src/webui/service/__main__.py                 |    6 +
 src/webui/service/service/routes.py           |   20 +-
 src/webui/service/templates/service/home.html |    6 +
 src/webui/tests/test_unitary.py               |    5 +-
 196 files changed, 10919 insertions(+), 6776 deletions(-)
 create mode 120000 ofc22
 create mode 100755 open_dashboard.sh
 create mode 100644 src/automation/src/main/java/eu/teraflow/automation/Serializer.java
 rename src/automation/src/main/java/eu/teraflow/automation/device/{ => model}/Device.java (53%)
 delete mode 100644 src/automation/src/main/java/eu/teraflow/automation/device/model/DeviceId.java
 delete mode 100644 src/automation/src/main/java/eu/teraflow/automation/device/model/DeviceType.java
 delete mode 100644 src/automation/src/main/java/eu/teraflow/automation/device/model/Uuid.java
 create mode 100644 src/automation/src/main/resources/teraflow-automation-banner.txt
 create mode 100644 src/automation/src/test/java/eu/teraflow/automation/SerializerTest.java
 create mode 100755 src/automation/util/set_version.sh
 create mode 100644 src/common/DeviceTypes.py
 create mode 100644 src/common/tests/EventTools.py
 rename src/{compute => common}/tests/MockService.py (100%)
 rename src/{compute => common}/tests/MockServicerImpl_Context.py (74%)
 create mode 100644 src/common/tests/MockServicerImpl_Device.py
 rename src/{compute => common}/tests/MockServicerImpl_Service.py (74%)
 create mode 100644 src/common/tools/grpc/Tools.py
 rename src/{tester_functional => common/tools/grpc}/__init__.py (100%)
 create mode 100644 src/common/tools/object_factory/ConfigRule.py
 create mode 100644 src/common/tools/object_factory/Connection.py
 create mode 100644 src/common/tools/object_factory/Constraint.py
 create mode 100644 src/common/tools/object_factory/Context.py
 create mode 100644 src/common/tools/object_factory/Device.py
 create mode 100644 src/common/tools/object_factory/EndPoint.py
 create mode 100644 src/common/tools/object_factory/Link.py
 create mode 100644 src/common/tools/object_factory/Service.py
 create mode 100644 src/common/tools/object_factory/Topology.py
 rename src/{tester_integration => common/tools/object_factory}/__init__.py (100%)
 create mode 100644 src/compute/tests/Constants.py
 delete mode 100644 src/compute/tests/Tools.py
 create mode 100644 src/context/client/EventsCollector.py
 create mode 100644 src/context/tests/Objects.py
 delete mode 100644 src/context/tests/Tools.py
 delete mode 100644 src/context/tests/example_objects.py
 delete mode 100644 src/device/tests/Tools.py
 create mode 100644 src/service/service/database/LinkModel.py
 create mode 100644 src/service/service/path_computation_element/Enums.py
 create mode 100644 src/service/service/path_computation_element/PathComputationElement.py
 create mode 100644 src/service/service/path_computation_element/Tools.py
 create mode 100644 src/service/service/path_computation_element/TopologyViews.py
 create mode 100644 src/service/service/path_computation_element/__init__.py
 create mode 100644 src/service/service/service_handlers/tapi_tapi/TapiServiceHandler.py
 create mode 100644 src/service/service/service_handlers/tapi_tapi/__init__.py
 create mode 100644 src/service/tests/ServiceHandler_L3NM_OC.py
 delete mode 100644 src/tester_functional/.gitlab-ci.yml
 delete mode 100644 src/tester_functional/Dockerfile
 delete mode 100644 src/tester_functional/definitions.py
 delete mode 100644 src/tester_functional/requirements.in
 delete mode 100644 src/tester_functional/test_context_device_service.py
 delete mode 100644 src/tester_integration/.gitlab-ci.yml
 delete mode 100644 src/tester_integration/Dockerfile
 delete mode 100644 src/tester_integration/definitions.py
 delete mode 100644 src/tester_integration/requirements.in
 delete mode 100644 src/tester_integration/test_context_device_service.py
 create mode 100644 src/tests/.gitlab-ci.yml
 create mode 100644 src/tests/__init__.py
 create mode 100644 src/tests/ofc22/README.md
 create mode 100644 src/tests/ofc22/__init__.py
 create mode 100755 src/tests/ofc22/deploy_in_kubernetes.sh
 create mode 100644 src/tests/ofc22/expose_services.yaml
 create mode 100755 src/tests/ofc22/run_test_01_bootstrap.sh
 create mode 100755 src/tests/ofc22/run_test_02_create_service.sh
 create mode 100755 src/tests/ofc22/run_test_03_delete_service.sh
 create mode 100755 src/tests/ofc22/run_test_04_cleanup.sh
 create mode 100755 src/tests/ofc22/show_deploy.sh
 create mode 100755 src/tests/ofc22/show_logs_automation.sh
 create mode 100755 src/tests/ofc22/show_logs_compute.sh
 create mode 100755 src/tests/ofc22/show_logs_context.sh
 create mode 100755 src/tests/ofc22/show_logs_device.sh
 create mode 100755 src/tests/ofc22/show_logs_monitoring.sh
 create mode 100755 src/tests/ofc22/show_logs_service.sh
 create mode 100755 src/tests/ofc22/show_logs_webui.sh
 create mode 100644 src/tests/ofc22/tests/.gitignore
 create mode 100644 src/tests/ofc22/tests/Objects.py
 create mode 100644 src/tests/ofc22/tests/__init__.py
 create mode 100644 src/tests/ofc22/tests/test_functional_bootstrap.py
 create mode 100644 src/tests/ofc22/tests/test_functional_cleanup.py
 create mode 100644 src/tests/ofc22/tests/test_functional_create_service.py
 create mode 100644 src/tests/ofc22/tests/test_functional_delete_service.py

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 3249b820f..0a9142153 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -19,8 +19,6 @@ include:
   - local: '/src/dbscanserving/.gitlab-ci.yml'
   - local: '/src/opticalattackmitigator/.gitlab-ci.yml'
   - local: '/src/opticalcentralizedattackdetector/.gitlab-ci.yml'
-  #- local: '/src/tester_integration/.gitlab-ci.yml'
-  #- local: '/src/tester_functional/.gitlab-ci.yml'
   - local: '/src/automation/.gitlab-ci.yml'
   - local: '/src/webui/.gitlab-ci.yml'
   # - local: '/src/l3_distributedattackdetector/.gitlab-ci.yml'
diff --git a/INSTALL.md b/INSTALL.md
index 84e3c8068..670af4873 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -1,22 +1,4 @@
 # TeraFlow OS SDN Controller Installation Instructions 
-Assuming you have a running Kubernetes deployment installed following the instructions provided in [Wiki: Installing Kubernetes on your Linux machine](../../../wikis/Installing-Kubernetes-on-your-Linux-machine), the following instructions will let you deploy TeraFlow OS SDN Controller in your local Kubernetes environment.
+Assuming you have a running Kubernetes deployment installed following the instructions provided in [Wiki: Installing Kubernetes on your Linux machine](https://gitlab.com/teraflow-h2020/controller/-/wikis/Installing-Kubernetes-on-your-Linux-machine), the following instructions will let you deploy TeraFlow OS SDN Controller in your local Kubernetes environment.
 
-Among others, it is assumed that you can run the command <code> kubectl cluster-info</code> in the machine you use for running the deployment script below.
-
-
-## 1. Clone the repository
-Create a folder (e.g., ~/deploy-test/teraflow/controller) to place the source code, move to that folder, clone the repository, and checkout the target branch you want to deploy (e.g., master or develop):
-
-<code>mkdir -p ~/deploy-test/teraflow/controller; cd ~/deploy-test/teraflow/controller</code>
-
-<code>git clone https://gitlab.com/teraflow-h2020/controller.git .</code>
-
-<code>git checkout develop</code>
-
-
-## 2. Adapt deployment script
-Find the script <code>deploy_to_kubernetes.sh</code> and modify the configuration settings at the top of the script according to your local Kubernetes environment.
-
-
-## 3. Run the deployment script
-Execute the script <code>deploy_to_kubernetes.sh</code> to build and deploy the components at your local Kubernetes environment.
+Then, follow the instructions in [Wiki: Deploying a TeraFlow OS test instance](https://gitlab.com/teraflow-h2020/controller/-/wikis/Deploying-a-TeraFlow-OS-test-instance) to deploy your instance of TeraFlow OS.
diff --git a/README.md b/README.md
index 77f581608..f6b194b19 100644
--- a/README.md
+++ b/README.md
@@ -7,4 +7,11 @@ Branch "master" : [![pipeline status](https://gitlab.com/teraflow-h2020/controll
 Branch "develop" : [![pipeline status](https://gitlab.com/teraflow-h2020/controller/badges/develop/pipeline.svg)](https://gitlab.com/teraflow-h2020/controller/-/commits/develop) [![coverage report](https://gitlab.com/teraflow-h2020/controller/badges/develop/coverage.svg)](https://gitlab.com/teraflow-h2020/controller/-/commits/develop)
 
 # Installation Instructions
-To install TeraFlow OS SDN Controller in your local Kubernetes deployment, we assume you deployed Kubernetes following the instructions provided in [Wiki: Installing Kubernetes on your Linux machine](../../../wikis/Installing-Kubernetes-on-your-Linux-machine). Then, follow instructions in [INSTALL.md](./INSTALL.md).
+To install TeraFlow OS SDN Controller in your local Kubernetes deployment, we assume you deployed Kubernetes following the instructions provided in [Wiki: Installing Kubernetes on your Linux machine](https://gitlab.com/teraflow-h2020/controller/-/wikis/Installing-Kubernetes-on-your-Linux-machine).
+
+Then, follow the instructions in [Wiki: Deploying a TeraFlow OS test instance](https://gitlab.com/teraflow-h2020/controller/-/wikis/Deploying-a-TeraFlow-OS-test-instance) to deploy your instance of TeraFlow OS.
+
+# Functional Tests
+A functional test has been defined to enable experimentation with the TeraFlow OS:
+
+[Demo at OFC'22 (Bootstrap devices, Manage L3VPN services, Monitor Device Endpoints)](./src/tests/ofc22)
diff --git a/configure_dashboards.sh b/configure_dashboards.sh
index 7a1e4eb54..9822d1360 100755
--- a/configure_dashboards.sh
+++ b/configure_dashboards.sh
@@ -1,30 +1,34 @@
 #!/bin/bash
 
-# Set the name of the Kubernetes namespace to deploy to.
-K8S_NAMESPACE="tf-dev"
-K8S_HOSTNAME="kubernetes-master"
+# If not already set, set the name of the Kubernetes namespace and hostname to deploy to.
+K8S_NAMESPACE=${K8S_NAMESPACE:-'tf-dev'}
+K8S_HOSTNAME=${K8S_HOSTNAME:-'kubernetes-master'}
 
-export INFLUXDB_HOSTNAME=$(kubectl get node $K8S_HOSTNAME -o 'jsonpath={.status.addresses[?(@.type=="InternalIP")].address}')
-export INFLUXDB_PORT=$(kubectl get service influx-tests --namespace $K8S_NAMESPACE -o 'jsonpath={.spec.ports[?(@.port==8086)].nodePort}')
-export INFLUXDB_USER=$(kubectl --namespace $K8S_NAMESPACE get secrets influxdb-secrets -o jsonpath='{.data.INFLUXDB_ADMIN_USER}' | base64 --decode)
-export INFLUXDB_PASSWORD=$(kubectl --namespace $K8S_NAMESPACE get secrets influxdb-secrets -o jsonpath='{.data.INFLUXDB_ADMIN_PASSWORD}' | base64 --decode)
-export INFLUXDB_DATABASE=$(kubectl --namespace $K8S_NAMESPACE get secrets influxdb-secrets -o jsonpath='{.data.INFLUXDB_DB}' | base64 --decode)
-export INFLUXDB_URL="http://${INFLUXDB_HOSTNAME}:${INFLUXDB_PORT}"
+INFLUXDB_USER=$(kubectl --namespace $K8S_NAMESPACE get secrets influxdb-secrets -o jsonpath='{.data.INFLUXDB_ADMIN_USER}' | base64 --decode)
+INFLUXDB_PASSWORD=$(kubectl --namespace $K8S_NAMESPACE get secrets influxdb-secrets -o jsonpath='{.data.INFLUXDB_ADMIN_PASSWORD}' | base64 --decode)
+INFLUXDB_DATABASE=$(kubectl --namespace $K8S_NAMESPACE get secrets influxdb-secrets -o jsonpath='{.data.INFLUXDB_DB}' | base64 --decode)
 
-export GRAFANA_HOSTNAME=$(kubectl get node $K8S_HOSTNAME -o 'jsonpath={.status.addresses[?(@.type=="InternalIP")].address}')
-export GRAFANA_PORT=$(kubectl get service webuiservice-public --namespace $K8S_NAMESPACE -o 'jsonpath={.spec.ports[?(@.port==3000)].nodePort}')
-export GRAFANA_USERNAME="admin"
-export GRAFANA_PASSWORD="admin123+"
-export GRAFANA_URL="http://${GRAFANA_USERNAME}:${GRAFANA_PASSWORD}@${GRAFANA_HOSTNAME}:${GRAFANA_PORT}"
+GRAFANA_HOSTNAME=$(kubectl get node $K8S_HOSTNAME -o 'jsonpath={.status.addresses[?(@.type=="InternalIP")].address}')
+GRAFANA_PORT=$(kubectl get service webuiservice-public --namespace $K8S_NAMESPACE -o 'jsonpath={.spec.ports[?(@.port==3000)].nodePort}')
+GRAFANA_USERNAME="admin"
+GRAFANA_PASSWORD=${GRAFANA_PASSWORD:-"admin123+"}
+GRAFANA_URL="http://${GRAFANA_USERNAME}:${GRAFANA_PASSWORD}@${GRAFANA_HOSTNAME}:${GRAFANA_PORT}"
 
-echo ${GRAFANA_URL}/api/datasources
+# Configure Grafana Admin Password
+# Ref: https://grafana.com/docs/grafana/latest/http_api/user/#change-password
+curl -X PUT -H "Content-Type: application/json" -d '{
+  "oldPassword": "admin",
+  "newPassword": "'${GRAFANA_PASSWORD}'",
+  "confirmNew" : "'${GRAFANA_PASSWORD}'"
+}' http://admin:admin@${GRAFANA_HOSTNAME}:${GRAFANA_PORT}/api/user/password
+echo
 
 # Create InfluxDB DataSource
 # Ref: https://grafana.com/docs/grafana/latest/http_api/data_source/
 curl -X POST -H "Content-Type: application/json" -d '{
   "type"     : "influxdb",
   "name"     : "InfluxDB",
-  "url"      : "'"$INFLUXDB_URL"'",
+  "url"      : "http://monitoringservice:8086",
   "access"   : "proxy",
   "basicAuth": false,
   "user"     : "'"$INFLUXDB_USER"'",
@@ -40,3 +44,7 @@ curl -X POST -H "Content-Type: application/json" \
   -d '@src/webui/grafana_dashboard.json' \
   ${GRAFANA_URL}/api/dashboards/db
 echo
+
+DASHBOARD_URL="${GRAFANA_URL}/api/dashboards/uid/tf-l3-monit"
+DASHBOARD_ID=$(python -c 'import json, requests; print(requests.get("'${DASHBOARD_URL}'").json()["dashboard"]["id"])')
+curl -X POST ${GRAFANA_URL}/api/user/stars/dashboard/${DASHBOARD_ID}
diff --git a/data/.gitignore b/data/.gitignore
index 6722cd96e..5ca4d5198 100644
--- a/data/.gitignore
+++ b/data/.gitignore
@@ -1 +1,2 @@
+*.dot
 *.xml
diff --git a/deploy_in_kubernetes.sh b/deploy_in_kubernetes.sh
index 58e35d249..9fd49fded 100755
--- a/deploy_in_kubernetes.sh
+++ b/deploy_in_kubernetes.sh
@@ -4,26 +4,31 @@
 # Define your deployment settings here
 ########################################################################################################################
 
-# Set the URL of your local Docker registry where the images will be uploaded to. Leave it blank if you do not want to
-# use any Docker registry.
-REGISTRY_IMAGE=""
-#REGISTRY_IMAGE="http://my-container-registry.local/"
+# If not already set, set the URL of your local Docker registry where the images will be uploaded to. Leave it blank if
+# you do not want to use any Docker registry.
+export REGISTRY_IMAGE=${REGISTRY_IMAGE:-""}
+#export REGISTRY_IMAGE="http://my-container-registry.local/"
 
-# Set the list of components you want to build images for, and deploy.
-COMPONENTS="context device automation policy service compute monitoring dbscanserving opticalattackmitigator opticalcentralizedattackdetector webui"
+# If not already set, set the list of components you want to build images for, and deploy.
+export COMPONENTS=${COMPONENTS:-"context device automation policy service compute monitoring dbscanserving opticalattackmitigator opticalcentralizedattackdetector webui"}
 
-# Set the tag you want to use for your images.
-IMAGE_TAG="tf-dev"
+# If not already set, set the tag you want to use for your images.
+export IMAGE_TAG=${IMAGE_TAG:-"tf-dev"}
 
-# Set the name of the Kubernetes namespace to deploy to.
-K8S_NAMESPACE="tf-dev"
+# If not already set, set the name of the Kubernetes namespace to deploy to.
+export K8S_NAMESPACE=${K8S_NAMESPACE:-"tf-dev"}
+
+# If not already set, set the name of the Kubernetes hostname to deploy to.
+export K8S_HOSTNAME=${K8S_HOSTNAME:-"kubernetes-master"}
+
+# If not already set, set additional manifest files to be applied after the deployment
+export EXTRA_MANIFESTS=${EXTRA_MANIFESTS:-""}
 
 ########################################################################################################################
 # Automated steps start here
 ########################################################################################################################
 
 # Constants
-CLONE_URL="https://gitlab.com/teraflow-h2020/controller.git"
 GITLAB_REPO_URL="registry.gitlab.com/teraflow-h2020/controller"
 TMP_FOLDER="./tmp"
 
@@ -33,16 +38,24 @@ mkdir -p $TMP_MANIFESTS_FOLDER
 TMP_LOGS_FOLDER="$TMP_FOLDER/logs"
 mkdir -p $TMP_LOGS_FOLDER
 
-# Re-create the namespace to prevent being affected by garbage on it
+echo "Deleting and Creating a new namespace..."
 kubectl delete namespace $K8S_NAMESPACE
 kubectl create namespace $K8S_NAMESPACE
 printf "\n"
 
-# creating the secrets for the influxdb deployment
+echo "Creating secrets for InfluxDB..."
 #TODO: make sure to change this when having a production deployment
 kubectl create secret generic influxdb-secrets --namespace=$K8S_NAMESPACE --from-literal=INFLUXDB_DB="monitoring" --from-literal=INFLUXDB_ADMIN_USER="teraflow" --from-literal=INFLUXDB_ADMIN_PASSWORD="teraflow" --from-literal=INFLUXDB_HTTP_AUTH_ENABLED="True"
 kubectl create secret generic monitoring-secrets --namespace=$K8S_NAMESPACE --from-literal=INFLUXDB_DATABASE="monitoring" --from-literal=INFLUXDB_USER="teraflow" --from-literal=INFLUXDB_PASSWORD="teraflow" --from-literal=INFLUXDB_HOSTNAME="localhost"
+printf "\n"
 
+echo "Pulling/Updating Docker images..."
+docker pull redis:6.2
+docker pull influxdb:1.8
+docker pull grafana/grafana:8.2.6
+printf "\n"
+
+echo "Deploying components..."
 for COMPONENT in $COMPONENTS; do
     echo "Processing '$COMPONENT' component..."
     IMAGE_NAME="$COMPONENT:$IMAGE_TAG"
@@ -85,9 +98,31 @@ for COMPONENT in $COMPONENTS; do
     echo "  Deploying '$COMPONENT' component to Kubernetes..."
     DEPLOY_LOG="$TMP_LOGS_FOLDER/push_${COMPONENT}.log"
     kubectl --namespace $K8S_NAMESPACE apply -f "$MANIFEST" > "$DEPLOY_LOG"
+    kubectl --namespace $K8S_NAMESPACE scale deployment --replicas=0 ${COMPONENT}service >> "$DEPLOY_LOG"
+    kubectl --namespace $K8S_NAMESPACE scale deployment --replicas=1 ${COMPONENT}service >> "$DEPLOY_LOG"
+    printf "\n"
+done
+
+echo "Deploying extra manifests..."
+for EXTRA_MANIFEST in $EXTRA_MANIFESTS; do
+    echo "Processing manifest '$EXTRA_MANIFEST'..."
+    kubectl --namespace $K8S_NAMESPACE apply -f $EXTRA_MANIFEST
     printf "\n"
 done
 
+# By now, leave this control here. Some component dependencies are not well handled
+for COMPONENT in $COMPONENTS; do
+    echo "Waiting for '$COMPONENT' component..."
+    kubectl wait --namespace $K8S_NAMESPACE --for='condition=available' --timeout=300s deployment/${COMPONENT}service
+    printf "\n"
+done
+
+echo "Configuring DataStores and Dashboards..."
+./configure_dashboards.sh
+printf "\n\n"
+
+echo "Reporting Deployment..."
 kubectl --namespace $K8S_NAMESPACE get all
+printf "\n"
 
-echo "Done!"
\ No newline at end of file
+echo "Done!"
diff --git a/manifests/computeservice.yaml b/manifests/computeservice.yaml
index 73380f75d..16507dfcb 100644
--- a/manifests/computeservice.yaml
+++ b/manifests/computeservice.yaml
@@ -21,7 +21,7 @@ spec:
         - containerPort: 9090
         env:
         - name: LOG_LEVEL
-          value: "DEBUG"
+          value: "INFO"
         readinessProbe:
           exec:
             command: ["/bin/grpc_health_probe", "-addr=:9090"]
@@ -58,8 +58,6 @@ apiVersion: v1
 kind: Service
 metadata:
   name: computeservice-public
-  labels:
-    app: computeservice
 spec:
   type: NodePort
   selector:
@@ -69,8 +67,5 @@ spec:
     protocol: TCP
     port: 8080
     targetPort: 8080
-  - name: grpc
-    protocol: TCP
-    port: 9090
-    targetPort: 9090
+    nodePort: 30808
 ---
diff --git a/manifests/contextservice.yaml b/manifests/contextservice.yaml
index 7ccf3e4f0..c8fcb38f7 100644
--- a/manifests/contextservice.yaml
+++ b/manifests/contextservice.yaml
@@ -41,7 +41,7 @@ spec:
         - name: LOG_LEVEL
           value: "INFO"
         - name: POPULATE_FAKE_DATA
-          value: "true"
+          value: "false"
         readinessProbe:
           exec:
             command: ["/bin/grpc_health_probe", "-addr=:1010"]
@@ -89,4 +89,5 @@ spec:
     protocol: TCP
     port: 8080
     targetPort: 8080
+    nodePort: 31808
 ---
diff --git a/manifests/deviceservice.yaml b/manifests/deviceservice.yaml
index 35c192790..476aaa4f2 100644
--- a/manifests/deviceservice.yaml
+++ b/manifests/deviceservice.yaml
@@ -20,7 +20,7 @@ spec:
         - containerPort: 2020
         env:
         - name: LOG_LEVEL
-          value: "DEBUG"
+          value: "INFO"
         readinessProbe:
           exec:
             command: ["/bin/grpc_health_probe", "-addr=:2020"]
diff --git a/manifests/monitoringservice.yaml b/manifests/monitoringservice.yaml
index d1b4023fa..a908d7d64 100644
--- a/manifests/monitoringservice.yaml
+++ b/manifests/monitoringservice.yaml
@@ -1,16 +1,16 @@
 apiVersion: apps/v1
 kind: Deployment
 metadata:
-  name: monitoring
+  name: monitoringservice
 spec:
   selector:
     matchLabels:
-      app: monitoring
+      app: monitoringservice
   replicas: 1
   template:
     metadata:
       labels:
-        app: monitoring
+        app: monitoringservice
     spec:
       terminationGracePeriodSeconds: 5
       restartPolicy: Always
@@ -60,11 +60,11 @@ spec:
 apiVersion: v1
 kind: Service
 metadata:
-  name: monitoring
+  name: monitoringservice
 spec:
   type: ClusterIP
   selector:
-    app: monitoring
+    app: monitoringservice
   ports:
   - name: grpc
     protocol: TCP
diff --git a/manifests/serviceservice.yaml b/manifests/serviceservice.yaml
index e9337807d..27acc7d19 100644
--- a/manifests/serviceservice.yaml
+++ b/manifests/serviceservice.yaml
@@ -20,7 +20,7 @@ spec:
         - containerPort: 3030
         env:
         - name: LOG_LEVEL
-          value: "DEBUG"
+          value: "INFO"
         readinessProbe:
           exec:
             command: ["/bin/grpc_health_probe", "-addr=:3030"]
diff --git a/manifests/webuiservice.yaml b/manifests/webuiservice.yaml
index 4ae3b56be..4e71d43ef 100644
--- a/manifests/webuiservice.yaml
+++ b/manifests/webuiservice.yaml
@@ -51,9 +51,6 @@ spec:
           - containerPort: 3000
             name: http-grafana
             protocol: TCP
-        env:
-        - name: GF_SECURITY_ADMIN_PASSWORD
-          value: admin123+
         readinessProbe:
           failureThreshold: 3
           httpGet:
diff --git a/ofc22 b/ofc22
new file mode 120000
index 000000000..1102ec2a6
--- /dev/null
+++ b/ofc22
@@ -0,0 +1 @@
+src/tests/ofc22/
\ No newline at end of file
diff --git a/open_dashboard.sh b/open_dashboard.sh
new file mode 100755
index 000000000..94425279e
--- /dev/null
+++ b/open_dashboard.sh
@@ -0,0 +1,15 @@
+#/bin/bash
+
+# this script opens the dashboard
+
+K8S_NAMESPACE=${K8S_NAMESPACE:-'tf-dev'}
+
+GRAFANA_IP=`kubectl get service/webuiservice -n ${K8S_NAMESPACE} -o jsonpath='{.spec.clusterIP}'`
+GRAFANA_PORT=`kubectl get service/webuiservice -n ${K8S_NAMESPACE} -o jsonpath='{.spec.ports[1].port}'`
+URL=http://${GRAFANA_IP}:${GRAFANA_PORT}
+
+echo Opening Dashboard on URL ${URL}
+
+# curl -kL ${URL}
+
+python3 -m webbrowser ${URL}
diff --git a/proto/service.proto b/proto/service.proto
index 98e827c8a..54157f81d 100644
--- a/proto/service.proto
+++ b/proto/service.proto
@@ -4,8 +4,7 @@ package service;
 import "context.proto";
 
 service ServiceService {
-  rpc CreateService    (context.Service  ) returns (context.ServiceId     ) {}
-  rpc UpdateService    (context.Service  ) returns (context.ServiceId     ) {}
-  rpc DeleteService    (context.ServiceId) returns (context.Empty         ) {}
-  rpc GetConnectionList(context.ServiceId) returns (context.ConnectionList) {}
+  rpc CreateService(context.Service  ) returns (context.ServiceId) {}
+  rpc UpdateService(context.Service  ) returns (context.ServiceId) {}
+  rpc DeleteService(context.ServiceId) returns (context.Empty    ) {}
 }
diff --git a/run_tests_locally.sh b/run_tests_locally.sh
index 11add2a82..7885567a2 100755
--- a/run_tests_locally.sh
+++ b/run_tests_locally.sh
@@ -11,16 +11,23 @@ cat $PROJECTDIR/coverage/.coveragerc.template | sed s+~/teraflow/controller+$PRO
 
 # Run unitary tests and analyze coverage of code at same time
 
+K8S_NAMESPACE="tf-dev"
+K8S_HOSTNAME="kubernetes-master"
 # Populate environment variables for context to use Redis in a development machine running Kubernetes
 # Uncomment below lines to create a Redis instance within Context for testing purposes.
-#kubectl delete namespace tf-dev
-#kubectl create namespace tf-dev
-#kubectl --namespace tf-dev apply -f ../manifests/contextservice.yaml
-#kubectl --namespace tf-dev expose deployment contextservice --port=6379 --type=NodePort --name=redis-tests
+#kubectl delete namespace $K8S_NAMESPACE
+#kubectl create namespace $K8S_NAMESPACE
+#kubectl --namespace $K8S_NAMESPACE apply -f ../manifests/contextservice.yaml
+#kubectl --namespace $K8S_NAMESPACE expose deployment contextservice --port=6379 --type=NodePort --name=redis-tests
 #echo "Waiting 10 seconds for Redis to start..."
 #sleep 10
-export REDIS_SERVICE_HOST=$(kubectl get node kubernetes-master -o 'jsonpath={.status.addresses[?(@.type=="InternalIP")].address}')
-export REDIS_SERVICE_PORT=$(kubectl get service redis-tests --namespace tf-dev -o 'jsonpath={.spec.ports[?(@.port==6379)].nodePort}')
+export REDIS_SERVICE_HOST=$(kubectl get node $K8S_HOSTNAME -o 'jsonpath={.status.addresses[?(@.type=="InternalIP")].address}')
+export REDIS_SERVICE_PORT=$(kubectl get service redis-tests --namespace $K8S_NAMESPACE -o 'jsonpath={.spec.ports[?(@.port==6379)].nodePort}')
+export INFLUXDB_HOSTNAME=$(kubectl get node $K8S_HOSTNAME -o 'jsonpath={.status.addresses[?(@.type=="InternalIP")].address}')
+export INFLUXDB_PORT=$(kubectl get service influx-tests --namespace $K8S_NAMESPACE -o 'jsonpath={.spec.ports[?(@.port==8086)].nodePort}')
+export INFLUXDB_USER=$(kubectl --namespace $K8S_NAMESPACE get secrets influxdb-secrets -o jsonpath='{.data.INFLUXDB_ADMIN_USER}' | base64 --decode)
+export INFLUXDB_PASSWORD=$(kubectl --namespace $K8S_NAMESPACE get secrets influxdb-secrets -o jsonpath='{.data.INFLUXDB_ADMIN_PASSWORD}' | base64 --decode)
+export INFLUXDB_DATABASE=$(kubectl --namespace $K8S_NAMESPACE get secrets influxdb-secrets -o jsonpath='{.data.INFLUXDB_DB}' | base64 --decode)
 
 # First destroy old coverage file
 rm -f $COVERAGEFILE
@@ -62,3 +69,6 @@ coverage run --rcfile=$RCFILE --append -m pytest --log-level=INFO --verbose \
 
 coverage run --rcfile=$RCFILE --append -m pytest --log-level=INFO --verbose \
     webui/tests/test_unitary.py
+
+coverage run --rcfile=$RCFILE --append -m pytest --log-level=INFO --verbose \
+    monitoring/tests/test_unitary.py
diff --git a/src/automation/.gitlab-ci.yml b/src/automation/.gitlab-ci.yml
index 0e87fa4b3..86e02f9c5 100644
--- a/src/automation/.gitlab-ci.yml
+++ b/src/automation/.gitlab-ci.yml
@@ -1,8 +1,10 @@
+variables:
+  IMAGE_NAME: 'automation'
+  IMAGE_TAG: '0.1.0'
+  REPORTS_PATH: "src/${IMAGE_NAME}/reports"
+
 # Package application needed to run tests & build the image on next stage
 build automation:
-  variables:
-    IMAGE_NAME: 'automation' # name of the microservice
-    IMAGE_TAG: '0.0.1' # tag of the container image (production, development, etc)
   stage: build
   script:
     - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/src/main/docker/Dockerfile.multistage.jvm ./src/$IMAGE_NAME/ --target builder
@@ -19,20 +21,38 @@ build automation:
 # Run tests, build & push the image
 unit_test automation:
   variables:
-    IMAGE_NAME: 'automation' # name of the microservice
-    IMAGE_TAG: '0.0.1' # tag of the container image (production, development, etc)
-  stage: unit_test
+    REPORTS_CONTAINER: "${IMAGE_NAME}-reports"
+  stage: test
   needs:
     - build automation
   before_script:
     - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
+    - docker rm ${REPORTS_CONTAINER} || true
   script:
     - docker 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}
+    - docker cp ${REPORTS_CONTAINER}:/app/target/site/jacoco/index.html ${REPORTS_PATH}/coverage.html
+    - docker cp ${REPORTS_CONTAINER}:/app/target/site/jacoco/jacoco.xml ${REPORTS_PATH}/jacoco.xml
+    - docker cp ${REPORTS_CONTAINER}:/app/target/surefire-reports/ ${REPORTS_PATH}/
+    - cat ${REPORTS_PATH}/coverage.html | grep -o 'Total[^%]*%' | sed 's/<.*>/ /; s/Total/JaCoCo Coverage Total:/'
+    # 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 tag "$IMAGE_NAME:$IMAGE_TAG" "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG"
     - docker push "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG"
   after_script:
-    - docker rm -f $IMAGE_NAME
+    - docker rm ${REPORTS_CONTAINER}
+    - docker rm -f "$IMAGE_NAME:$IMAGE_TAG"
+  coverage: '/JaCoCo Coverage Total: ([0-9]{1,3})%/'
+  artifacts:
+    when: always
+    paths:
+      - ${REPORTS_PATH}/jacoco.xml
+      - ${REPORTS_PATH}/coverage.html
+    reports:
+      junit:
+        - ${REPORTS_PATH}/surefire-reports/TEST-*.xml
   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"'
@@ -41,6 +61,19 @@ unit_test automation:
         - manifests/${IMAGE_NAME}service.yaml
         - .gitlab-ci.yml
 
+visualize_coverage automation:
+  stage: unit_test
+  needs:
+    - unit_test automation
+  before_script:
+    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
+  script:
+    - stat ${REPORTS_PATH}/jacoco.xml || true
+    - 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
+  artifacts:
+    reports:
+      cobertura: ${REPORTS_PATH}/cobertura.xml
+
 # Deployment of automation service in Kubernetes Cluster
 deploy automation:
   stage: deploy
@@ -55,7 +88,7 @@ deploy automation:
     - kubectl get all
   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    
+      when: manual
     - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"'
       when: manual
 
diff --git a/src/automation/pom.xml b/src/automation/pom.xml
index 042185673..62a8859de 100644
--- a/src/automation/pom.xml
+++ b/src/automation/pom.xml
@@ -5,7 +5,7 @@
 
   <groupId>eu.teraflow</groupId>
   <artifactId>automation</artifactId>
-  <version>0.0.1</version>
+  <version>0.1.0</version>
   <name>TeraFlow Automation Component</name>
   <description>TeraFlow Automation Component</description>
 
@@ -274,6 +274,15 @@
           <groupId>org.jacoco</groupId>
           <artifactId>jacoco-maven-plugin</artifactId>
           <version>${jacoco.version}</version>
+          <configuration>
+          <excludes>
+            <exclude>automation/*</exclude>
+            <exclude>context/*</exclude>
+            <exclude>device/*</exclude>
+            <exclude>monitoring/*</exclude>
+            <exclude>kpi_sample_types/*</exclude>
+          </excludes>
+          </configuration>
           <executions>
             <execution>
               <id>instrument-unit-tests</id>
@@ -400,7 +409,7 @@
             <execution>
               <phase>compile</phase>
               <goals>
-                <goal>check</goal>
+                <goal>apply</goal>
               </goals>
             </execution>
           </executions>
diff --git a/src/automation/src/main/docker/Dockerfile.multistage.jvm b/src/automation/src/main/docker/Dockerfile.multistage.jvm
index 696c8e184..8480304de 100644
--- a/src/automation/src/main/docker/Dockerfile.multistage.jvm
+++ b/src/automation/src/main/docker/Dockerfile.multistage.jvm
@@ -15,7 +15,7 @@ RUN mvn --errors --batch-mode package -Dmaven.test.skip=true
 # Stage 2
 FROM builder AS unit-test
 
-RUN mvn --errors --batch-mode test
+RUN mvn --errors --batch-mode -Pgenerate-consolidated-coverage verify
 
 # Stage 3
 FROM registry.access.redhat.com/ubi8/ubi-minimal:8.4 AS release
diff --git a/src/automation/src/main/java/eu/teraflow/automation/AutomationGatewayImpl.java b/src/automation/src/main/java/eu/teraflow/automation/AutomationGatewayImpl.java
index 8e9805156..cbaf16d1c 100644
--- a/src/automation/src/main/java/eu/teraflow/automation/AutomationGatewayImpl.java
+++ b/src/automation/src/main/java/eu/teraflow/automation/AutomationGatewayImpl.java
@@ -2,8 +2,6 @@ package eu.teraflow.automation;
 
 import automation.Automation;
 import context.ContextOuterClass;
-import eu.teraflow.automation.device.model.DeviceId;
-import eu.teraflow.automation.device.model.Uuid;
 import io.quarkus.grpc.GrpcService;
 import io.smallrye.mutiny.Uni;
 import javax.inject.Inject;
@@ -12,10 +10,12 @@ import javax.inject.Inject;
 public class AutomationGatewayImpl implements AutomationGateway {
 
     private final AutomationService automationService;
+    private final Serializer serializer;
 
     @Inject
-    public AutomationGatewayImpl(AutomationService automationService) {
+    public AutomationGatewayImpl(AutomationService automationService, Serializer serializer) {
         this.automationService = automationService;
+        this.serializer = serializer;
     }
 
     @Override
@@ -32,9 +32,12 @@ public class AutomationGatewayImpl implements AutomationGateway {
 
     @Override
     public Uni<Automation.DeviceRoleState> ztpAdd(Automation.DeviceRole request) {
+        final var deviceId = serializer.deserialize(request.getDevRoleId().getDevId());
 
-        automationService.addDevice(getDeviceId(request.getDevRoleId().getDevId()));
+        // TODO tie this with return
+        automationService.addDevice(deviceId);
 
+        // TODO Set all fields of device role state (create models, serializer)
         return Uni.createFrom()
                 .item(
                         () ->
@@ -67,11 +70,4 @@ public class AutomationGatewayImpl implements AutomationGateway {
     public Uni<Automation.DeviceDeletionResult> ztpDeleteAll(Automation.Empty empty) {
         return Uni.createFrom().item(() -> Automation.DeviceDeletionResult.newBuilder().build());
     }
-
-    private DeviceId getDeviceId(ContextOuterClass.DeviceId serializedDeviceId) {
-
-        Uuid uuid = new Uuid(serializedDeviceId.getDeviceUuid().getUuid());
-
-        return new DeviceId(uuid);
-    }
 }
diff --git a/src/automation/src/main/java/eu/teraflow/automation/AutomationService.java b/src/automation/src/main/java/eu/teraflow/automation/AutomationService.java
index 1c76fc487..39357039a 100644
--- a/src/automation/src/main/java/eu/teraflow/automation/AutomationService.java
+++ b/src/automation/src/main/java/eu/teraflow/automation/AutomationService.java
@@ -1,10 +1,9 @@
 package eu.teraflow.automation;
 
-import eu.teraflow.automation.device.Device;
-import eu.teraflow.automation.device.model.DeviceId;
+import eu.teraflow.automation.device.model.Device;
 import io.smallrye.mutiny.Uni;
 
 public interface AutomationService {
 
-    Uni<Device> addDevice(DeviceId deviceId);
+    Uni<Device> addDevice(String deviceId);
 }
diff --git a/src/automation/src/main/java/eu/teraflow/automation/AutomationServiceImpl.java b/src/automation/src/main/java/eu/teraflow/automation/AutomationServiceImpl.java
index fc62e77ec..0742cec19 100644
--- a/src/automation/src/main/java/eu/teraflow/automation/AutomationServiceImpl.java
+++ b/src/automation/src/main/java/eu/teraflow/automation/AutomationServiceImpl.java
@@ -1,9 +1,8 @@
 package eu.teraflow.automation;
 
 import eu.teraflow.automation.context.ContextService;
-import eu.teraflow.automation.device.Device;
 import eu.teraflow.automation.device.DeviceService;
-import eu.teraflow.automation.device.model.*;
+import eu.teraflow.automation.device.model.Device;
 import io.smallrye.mutiny.Uni;
 import javax.enterprise.context.ApplicationScoped;
 import javax.inject.Inject;
@@ -23,34 +22,46 @@ public class AutomationServiceImpl implements AutomationService {
     }
 
     @Override
-    public Uni<Device> addDevice(DeviceId deviceId) {
+    public Uni<Device> addDevice(String deviceId) {
 
-        final var deviceUni = contextService.getDevice(deviceId);
+        final var deserializedDeviceUni = contextService.getDevice(deviceId);
 
-        deviceUni
+        deserializedDeviceUni
+                // TODO fix subscribe
                 .subscribe()
                 .with(
                         device -> {
-                            if (!(device
-                                    .getDeviceOperationalStatus()
-                                    .toString()
-                                    .equals(DeviceOperationalStatus.ENABLED.toString()))) {
+                            final var id = deviceId;
 
-                                final var initialConfig = deviceService.getInitialConfiguration(deviceId);
+                            if (!device.isEnabled()) {
+                                LOGGER.infof("Retrieved %s", device);
 
-                                device.setDeviceOperationalStatus(DeviceOperationalStatus.ENABLED);
+                                final var initialConfiguration =
+                                        deviceService.getInitialConfiguration(device.getDeviceId());
 
-                                initialConfig
+                                device.enableDevice();
+                                LOGGER.infof("Enabled device [%s]", id);
+
+                                initialConfiguration
                                         .subscribe()
                                         .with(
                                                 deviceConfig -> {
                                                     device.setDeviceConfiguration(deviceConfig);
-                                                    deviceService.configureDevice(device);
-                                                    LOGGER.infof("Received response %s", device);
+                                                    final var configuredDeviceIdUni = deviceService.configureDevice(device);
+
+                                                    configuredDeviceIdUni
+                                                            .subscribe()
+                                                            .with(
+                                                                    configuredDeviceId ->
+                                                                            LOGGER.infof(
+                                                                                    "Device [%s] has been enabled and configured successfully with %s.\n",
+                                                                                    id, deviceConfig));
                                                 });
+                            } else {
+                                LOGGER.infof("%s has been already enabled. Ignoring...", device);
                             }
                         });
 
-        return deviceUni;
+        return deserializedDeviceUni;
     }
 }
diff --git a/src/automation/src/main/java/eu/teraflow/automation/ContextSubscriber.java b/src/automation/src/main/java/eu/teraflow/automation/ContextSubscriber.java
index 195634d00..8d340582f 100644
--- a/src/automation/src/main/java/eu/teraflow/automation/ContextSubscriber.java
+++ b/src/automation/src/main/java/eu/teraflow/automation/ContextSubscriber.java
@@ -1,9 +1,7 @@
 package eu.teraflow.automation;
 
 import eu.teraflow.automation.context.ContextService;
-import eu.teraflow.automation.device.model.DeviceEvent;
 import io.quarkus.runtime.StartupEvent;
-import io.smallrye.mutiny.Multi;
 import java.time.Duration;
 import javax.enterprise.context.ApplicationScoped;
 import javax.enterprise.event.Observes;
@@ -31,28 +29,53 @@ public class ContextSubscriber {
 
     public void listenForDeviceEvents() {
 
-        Multi<DeviceEvent> deviceEventsMulti =
-                contextService
-                        .getDeviceEvents()
-                        .onFailure()
-                        .retry()
-                        .withBackOff(Duration.ofSeconds(1))
-                        .withJitter(0.2)
-                        .atMost(10);
-
-        deviceEventsMulti
-                .onItem()
-                .transformToUniAndConcatenate(
-                        deviceEvent -> automationService.addDevice(deviceEvent.getDeviceId()));
+        contextService
+                .getDeviceEvents()
+                .onFailure()
+                .retry()
+                .withBackOff(Duration.ofSeconds(1))
+                .withJitter(0.2)
+                .atMost(10)
+                .onFailure()
+                .recoverWithCompletion()
+                .subscribe()
+                .with(
+                        deviceEvent -> {
+                            LOGGER.debugf("Received %s via contextService:getDeviceEvents", deviceEvent);
+                            if (deviceEvent == null || deviceEvent.getEvent() == null) {
+                                LOGGER.warn("Received device event is null, ignoring...");
+                                return;
+                            }
+                            final var eventType = deviceEvent.getEvent().getEventTypeEnum();
+                            final var deviceId = deviceEvent.getDeviceId();
+                            final var event = deviceEvent.getEvent();
+
+                            switch (eventType) {
+                                case CREATE:
+                                    LOGGER.infof("Received %s for device [%s]", event, deviceId);
+                                    automationService.addDevice(deviceEvent.getDeviceId());
+                                    break;
+
+                                case UPDATE:
+                                case REMOVE:
+                                case UNDEFINED:
+                                    {
+                                        LOGGER.warnf(
+                                                "Received %s for device [%s]. [%s] event handling is not yet implemented, ignoring...",
+                                                event, deviceId, eventType);
+                                    }
+                                    break;
+                            }
+                        });
     }
 
     void onStart(@Observes StartupEvent ev) {
 
         if (automationConfiguration.shouldSubscribeToContextComponent()) {
-            LOGGER.info("Listening for Device events...");
+            LOGGER.info("Subscribing to Context service for device events...");
             listenForDeviceEvents();
         } else {
-            LOGGER.info("Not listening for Device events...");
+            LOGGER.info("Not subscribing to Context service for device events...");
         }
     }
 }
diff --git a/src/automation/src/main/java/eu/teraflow/automation/Serializer.java b/src/automation/src/main/java/eu/teraflow/automation/Serializer.java
new file mode 100644
index 000000000..ed64e53cf
--- /dev/null
+++ b/src/automation/src/main/java/eu/teraflow/automation/Serializer.java
@@ -0,0 +1,208 @@
+package eu.teraflow.automation;
+
+import context.ContextOuterClass;
+import context.ContextOuterClass.DeviceId;
+import context.ContextOuterClass.DeviceOperationalStatusEnum;
+import context.ContextOuterClass.Uuid;
+import eu.teraflow.automation.context.model.Event;
+import eu.teraflow.automation.context.model.EventTypeEnum;
+import eu.teraflow.automation.device.model.ConfigActionEnum;
+import eu.teraflow.automation.device.model.ConfigRule;
+import eu.teraflow.automation.device.model.Device;
+import eu.teraflow.automation.device.model.DeviceConfig;
+import eu.teraflow.automation.device.model.DeviceEvent;
+import eu.teraflow.automation.device.model.DeviceOperationalStatus;
+import java.util.stream.Collectors;
+import javax.inject.Singleton;
+
+@Singleton
+public class Serializer {
+
+    public String deserialize(DeviceId deviceId) {
+        return deviceId.getDeviceUuid().getUuid();
+    }
+
+    public DeviceId serializeDeviceId(String expectedDeviceId) {
+        final var uuid = Uuid.newBuilder().setUuid(expectedDeviceId).build();
+
+        return ContextOuterClass.DeviceId.newBuilder().setDeviceUuid(uuid).build();
+    }
+
+    public ContextOuterClass.EventTypeEnum serialize(EventTypeEnum eventTypeEnum) {
+        switch (eventTypeEnum) {
+            case CREATE:
+                return ContextOuterClass.EventTypeEnum.EVENTTYPE_CREATE;
+            case REMOVE:
+                return ContextOuterClass.EventTypeEnum.EVENTTYPE_REMOVE;
+            case UPDATE:
+                return ContextOuterClass.EventTypeEnum.EVENTTYPE_UPDATE;
+            case UNDEFINED:
+                return ContextOuterClass.EventTypeEnum.EVENTTYPE_UNDEFINED;
+            default:
+                return ContextOuterClass.EventTypeEnum.UNRECOGNIZED;
+        }
+    }
+
+    public EventTypeEnum deserialize(ContextOuterClass.EventTypeEnum serializedEventType) {
+        switch (serializedEventType) {
+            case EVENTTYPE_CREATE:
+                return EventTypeEnum.CREATE;
+            case EVENTTYPE_REMOVE:
+                return EventTypeEnum.REMOVE;
+            case EVENTTYPE_UPDATE:
+                return EventTypeEnum.UPDATE;
+            case EVENTTYPE_UNDEFINED:
+            case UNRECOGNIZED:
+            default:
+                return EventTypeEnum.UNDEFINED;
+        }
+    }
+
+    public ContextOuterClass.Event serialize(Event event) {
+        final var builder = ContextOuterClass.Event.newBuilder();
+
+        final var eventType = serialize(event.getEventTypeEnum());
+        builder.setEventType(eventType);
+        builder.setTimestamp(event.getTimestamp());
+
+        return builder.build();
+    }
+
+    public Event deserialize(ContextOuterClass.Event serializedEvent) {
+        final var timestamp = serializedEvent.getTimestamp();
+        final var eventType = deserialize(serializedEvent.getEventType());
+
+        return new Event(timestamp, eventType);
+    }
+
+    public ContextOuterClass.DeviceEvent serialize(DeviceEvent deviceEvent) {
+        final var builder = ContextOuterClass.DeviceEvent.newBuilder();
+
+        builder.setDeviceId(serializeDeviceId(deviceEvent.getDeviceId()));
+        builder.setEvent(serialize(deviceEvent.getEvent()));
+
+        return builder.build();
+    }
+
+    public DeviceEvent deserialize(ContextOuterClass.DeviceEvent deviceEvent) {
+        final var deviceId = deserialize(deviceEvent.getDeviceId());
+        final var event = deserialize(deviceEvent.getEvent());
+
+        return new DeviceEvent(deviceId, event);
+    }
+
+    public ContextOuterClass.ConfigActionEnum serialize(ConfigActionEnum configAction) {
+        switch (configAction) {
+            case SET:
+                return ContextOuterClass.ConfigActionEnum.CONFIGACTION_SET;
+            case DELETE:
+                return ContextOuterClass.ConfigActionEnum.CONFIGACTION_DELETE;
+            case UNDEFINED:
+            default:
+                return ContextOuterClass.ConfigActionEnum.CONFIGACTION_UNDEFINED;
+        }
+    }
+
+    public ConfigActionEnum deserialize(ContextOuterClass.ConfigActionEnum serializedConfigAction) {
+        switch (serializedConfigAction) {
+            case CONFIGACTION_SET:
+                return ConfigActionEnum.SET;
+            case CONFIGACTION_DELETE:
+                return ConfigActionEnum.DELETE;
+            case UNRECOGNIZED:
+            case CONFIGACTION_UNDEFINED:
+            default:
+                return ConfigActionEnum.UNDEFINED;
+        }
+    }
+
+    public ContextOuterClass.ConfigRule serialize(ConfigRule configRule) {
+        final var builder = ContextOuterClass.ConfigRule.newBuilder();
+
+        builder.setAction(serialize(configRule.getConfigActionEnum()));
+        builder.setResourceKey(configRule.getResourceKey());
+        builder.setResourceValue(configRule.getResourceValue());
+
+        return builder.build();
+    }
+
+    public ConfigRule deserialize(ContextOuterClass.ConfigRule configRule) {
+        final var configActionEnum = deserialize(configRule.getAction());
+
+        return new ConfigRule(
+                configActionEnum, configRule.getResourceKey(), configRule.getResourceValue());
+    }
+
+    public ContextOuterClass.DeviceConfig serialize(DeviceConfig deviceConfig) {
+        final var builder = ContextOuterClass.DeviceConfig.newBuilder();
+
+        final var serializedConfigRules =
+                deviceConfig.getConfigRules().stream().map(this::serialize).collect(Collectors.toList());
+        builder.addAllConfigRules(serializedConfigRules);
+
+        return builder.build();
+    }
+
+    public DeviceConfig deserialize(ContextOuterClass.DeviceConfig deviceConfig) {
+        final var configRules =
+                deviceConfig.getConfigRulesList().stream()
+                        .map(this::deserialize)
+                        .collect(Collectors.toList());
+
+        return new DeviceConfig(configRules);
+    }
+
+    public ContextOuterClass.DeviceOperationalStatusEnum serialize(DeviceOperationalStatus opStatus) {
+        switch (opStatus) {
+            case ENABLED:
+                return DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_ENABLED;
+            case DISABLED:
+                return DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_DISABLED;
+            case UNDEFINED:
+            default:
+                return DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_UNDEFINED;
+        }
+    }
+
+    public DeviceOperationalStatus deserialize(
+            ContextOuterClass.DeviceOperationalStatusEnum opStatus) {
+        switch (opStatus) {
+            case DEVICEOPERATIONALSTATUS_ENABLED:
+                return DeviceOperationalStatus.ENABLED;
+            case DEVICEOPERATIONALSTATUS_DISABLED:
+                return DeviceOperationalStatus.DISABLED;
+            case DEVICEOPERATIONALSTATUS_UNDEFINED:
+            case UNRECOGNIZED:
+            default:
+                return DeviceOperationalStatus.UNDEFINED;
+        }
+    }
+
+    public ContextOuterClass.Device serialize(Device device) {
+        final var builder = ContextOuterClass.Device.newBuilder();
+
+        builder.setDeviceId(serializeDeviceId(device.getDeviceId()));
+        builder.setDeviceType(device.getDeviceType());
+        builder.setDeviceConfig(serialize(device.getDeviceConfig()));
+        builder.setDeviceOperationalStatus(serialize(device.getDeviceOperationalStatus()));
+
+        return builder.build();
+    }
+
+    public Device deserialize(ContextOuterClass.Device device) {
+        final var id = deserialize(device.getDeviceId());
+        final var type = device.getDeviceType();
+        final var config = deserialize(device.getDeviceConfig());
+        final var operationalStatus = deserialize(device.getDeviceOperationalStatus());
+
+        return new Device(id, type, config, operationalStatus);
+    }
+
+    public Uuid serializeUuid(String uuid) {
+        return Uuid.newBuilder().setUuid(uuid).build();
+    }
+
+    public String deserialize(Uuid uuid) {
+        return uuid.getUuid();
+    }
+}
diff --git a/src/automation/src/main/java/eu/teraflow/automation/context/ContextGateway.java b/src/automation/src/main/java/eu/teraflow/automation/context/ContextGateway.java
index e08a706ed..4f75487e0 100644
--- a/src/automation/src/main/java/eu/teraflow/automation/context/ContextGateway.java
+++ b/src/automation/src/main/java/eu/teraflow/automation/context/ContextGateway.java
@@ -1,14 +1,13 @@
 package eu.teraflow.automation.context;
 
-import eu.teraflow.automation.device.Device;
+import eu.teraflow.automation.device.model.Device;
 import eu.teraflow.automation.device.model.DeviceEvent;
-import eu.teraflow.automation.device.model.DeviceId;
 import io.smallrye.mutiny.Multi;
 import io.smallrye.mutiny.Uni;
 
 public interface ContextGateway {
 
-    Uni<Device> getDevice(DeviceId deviceId);
+    Uni<Device> getDevice(String deviceId);
 
     Multi<DeviceEvent> getDeviceEvents();
 }
diff --git a/src/automation/src/main/java/eu/teraflow/automation/context/ContextGatewayImpl.java b/src/automation/src/main/java/eu/teraflow/automation/context/ContextGatewayImpl.java
index 6b0ff132e..30083a144 100644
--- a/src/automation/src/main/java/eu/teraflow/automation/context/ContextGatewayImpl.java
+++ b/src/automation/src/main/java/eu/teraflow/automation/context/ContextGatewayImpl.java
@@ -1,108 +1,48 @@
 package eu.teraflow.automation.context;
 
 import context.ContextOuterClass;
-import context.ContextService;
-import eu.teraflow.automation.context.model.Event;
-import eu.teraflow.automation.context.model.EventTypeEnum;
-import eu.teraflow.automation.device.Device;
+import context.MutinyContextServiceGrpc.MutinyContextServiceStub;
+import eu.teraflow.automation.Serializer;
 import eu.teraflow.automation.device.model.*;
+import eu.teraflow.automation.device.model.Device;
 import io.quarkus.grpc.GrpcClient;
 import io.smallrye.mutiny.Multi;
 import io.smallrye.mutiny.Uni;
 import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import org.jboss.logging.Logger;
 
 @ApplicationScoped
 public class ContextGatewayImpl implements ContextGateway {
+    private static final Logger LOGGER = Logger.getLogger(ContextGatewayImpl.class);
 
     @GrpcClient("context")
-    ContextService delegate;
+    MutinyContextServiceStub streamingDelegateContext;
 
-    @Override
-    public Multi<DeviceEvent> getDeviceEvents() {
+    private final Serializer serializer;
 
-        final var serializedEmpty = getSerializedEmpty();
-        final var deviceEventsMulti = delegate.getDeviceEvents(serializedEmpty);
-
-        return deviceEventsMulti.onItem().transform(this::getDeviceEvent);
+    @Inject
+    public ContextGatewayImpl(Serializer serializer) {
+        this.serializer = serializer;
     }
 
     @Override
-    public Uni<Device> getDevice(DeviceId deviceId) {
-        final var serializedDeviceId = getSerializedDeviceId(deviceId);
-        final var serializedDeviceUni = delegate.getDevice(serializedDeviceId);
-
-        return serializedDeviceUni.onItem().transform(this::getDevice);
-    }
-
-    private ContextOuterClass.Empty getSerializedEmpty() {
-
-        return ContextOuterClass.Empty.newBuilder().build();
-    }
-
-    private DeviceEvent getDeviceEvent(ContextOuterClass.DeviceEvent deviceEvent) {
-
-        final var serializedDeviceId = deviceEvent.getDeviceId();
-        final var deviceId = getDeviceId(serializedDeviceId);
-
-        final var serializedEvent = deviceEvent.getEvent();
-        final var event = getEvent(serializedEvent);
-
-        return new DeviceEvent(event, deviceId);
-    }
-
-    private Event getEvent(ContextOuterClass.Event event) {
-        return new Event(event.getTimestamp(), getEventType(event.getEventType()));
-    }
-
-    private EventTypeEnum getEventType(ContextOuterClass.EventTypeEnum eventType) {
-
-        if (eventType == ContextOuterClass.EventTypeEnum.EVENTTYPE_CREATE) {
-            return EventTypeEnum.CREATE;
-        } else if (eventType == ContextOuterClass.EventTypeEnum.EVENTTYPE_REMOVE) {
-            return EventTypeEnum.REMOVE;
-        } else if (eventType == ContextOuterClass.EventTypeEnum.EVENTTYPE_UPDATE) {
-            return EventTypeEnum.UPDATE;
-        } else {
-            return EventTypeEnum.UNDEFINED;
-        }
-    }
-
-    private Device getDevice(ContextOuterClass.Device device) {
-
-        final var deviceId = getDeviceId(device.getDeviceId());
-        final var deviceType = getDeviceType(device.getDeviceType());
-        final var deviceOperationalStatus =
-                getDeviceOperationalStatus(device.getDeviceOperationalStatus());
-
-        return new Device(deviceId, deviceType, deviceOperationalStatus);
-    }
-
-    private DeviceId getDeviceId(ContextOuterClass.DeviceId deviceId) {
-        Uuid uuid = new Uuid(deviceId.getDeviceUuid().getUuid());
-        return new DeviceId(uuid);
-    }
+    public Multi<DeviceEvent> getDeviceEvents() {
+        final var serializedEmpty = ContextOuterClass.Empty.newBuilder().build();
 
-    private DeviceType getDeviceType(String deviceType) {
-        return new DeviceType(deviceType);
+        return streamingDelegateContext
+                .getDeviceEvents(serializedEmpty)
+                .onItem()
+                .transform(serializer::deserialize);
     }
 
-    private DeviceOperationalStatus getDeviceOperationalStatus(
-            ContextOuterClass.DeviceOperationalStatusEnum deviceOperationalStatusEnum) {
-
-        if (deviceOperationalStatusEnum
-                == ContextOuterClass.DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_ENABLED) {
-            return DeviceOperationalStatus.ENABLED;
-        } else if (deviceOperationalStatusEnum
-                == ContextOuterClass.DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_DISABLED) {
-            return DeviceOperationalStatus.DISABLED;
-        } else {
-            return DeviceOperationalStatus.UNDEFINED;
-        }
-    }
+    @Override
+    public Uni<Device> getDevice(String deviceId) {
+        final var serializedDeviceId = serializer.serializeDeviceId(deviceId);
 
-    private ContextOuterClass.DeviceId getSerializedDeviceId(DeviceId deviceId) {
-        final var deviceIdUuid =
-                ContextOuterClass.Uuid.newBuilder().setUuid(deviceId.toString()).build();
-        return ContextOuterClass.DeviceId.newBuilder().setDeviceUuid(deviceIdUuid).build();
+        return streamingDelegateContext
+                .getDevice(serializedDeviceId)
+                .onItem()
+                .transform(serializer::deserialize);
     }
 }
diff --git a/src/automation/src/main/java/eu/teraflow/automation/context/ContextService.java b/src/automation/src/main/java/eu/teraflow/automation/context/ContextService.java
index 2a2cd61af..0f2da0eae 100644
--- a/src/automation/src/main/java/eu/teraflow/automation/context/ContextService.java
+++ b/src/automation/src/main/java/eu/teraflow/automation/context/ContextService.java
@@ -1,14 +1,13 @@
 package eu.teraflow.automation.context;
 
-import eu.teraflow.automation.device.Device;
+import eu.teraflow.automation.device.model.Device;
 import eu.teraflow.automation.device.model.DeviceEvent;
-import eu.teraflow.automation.device.model.DeviceId;
 import io.smallrye.mutiny.Multi;
 import io.smallrye.mutiny.Uni;
 
 public interface ContextService {
 
-    Uni<Device> getDevice(DeviceId deviceId);
+    Uni<Device> getDevice(String deviceId);
 
     Multi<DeviceEvent> getDeviceEvents();
 }
diff --git a/src/automation/src/main/java/eu/teraflow/automation/context/ContextServiceImpl.java b/src/automation/src/main/java/eu/teraflow/automation/context/ContextServiceImpl.java
index 3277964e8..94063a377 100644
--- a/src/automation/src/main/java/eu/teraflow/automation/context/ContextServiceImpl.java
+++ b/src/automation/src/main/java/eu/teraflow/automation/context/ContextServiceImpl.java
@@ -1,8 +1,7 @@
 package eu.teraflow.automation.context;
 
-import eu.teraflow.automation.device.Device;
+import eu.teraflow.automation.device.model.Device;
 import eu.teraflow.automation.device.model.DeviceEvent;
-import eu.teraflow.automation.device.model.DeviceId;
 import io.smallrye.mutiny.Multi;
 import io.smallrye.mutiny.Uni;
 import javax.enterprise.context.ApplicationScoped;
@@ -19,14 +18,12 @@ public class ContextServiceImpl implements ContextService {
     }
 
     @Override
-    public Uni<Device> getDevice(DeviceId deviceId) {
-
+    public Uni<Device> getDevice(String deviceId) {
         return contextGateway.getDevice(deviceId);
     }
 
     @Override
     public Multi<DeviceEvent> getDeviceEvents() {
-
         return contextGateway.getDeviceEvents();
     }
 }
diff --git a/src/automation/src/main/java/eu/teraflow/automation/context/model/Event.java b/src/automation/src/main/java/eu/teraflow/automation/context/model/Event.java
index fa09c7899..73d95b8a9 100644
--- a/src/automation/src/main/java/eu/teraflow/automation/context/model/Event.java
+++ b/src/automation/src/main/java/eu/teraflow/automation/context/model/Event.java
@@ -2,8 +2,9 @@ package eu.teraflow.automation.context.model;
 
 public class Event {
 
-    private double timestamp;
-    private EventTypeEnum eventType;
+    // TODO convert double to meaningful timestamp type
+    private final double timestamp;
+    private final EventTypeEnum eventType;
 
     public Event(double timestamp, EventTypeEnum eventType) {
         this.timestamp = timestamp;
@@ -17,4 +18,11 @@ public class Event {
     public EventTypeEnum getEventTypeEnum() {
         return eventType;
     }
+
+    @Override
+    public String toString() {
+        return String.format(
+                "%s{timestamp=\"%f\", eventType=\"%s\"}",
+                getClass().getSimpleName(), timestamp, eventType.toString());
+    }
 }
diff --git a/src/automation/src/main/java/eu/teraflow/automation/device/DeviceGateway.java b/src/automation/src/main/java/eu/teraflow/automation/device/DeviceGateway.java
index ed9a2961c..7439fb541 100644
--- a/src/automation/src/main/java/eu/teraflow/automation/device/DeviceGateway.java
+++ b/src/automation/src/main/java/eu/teraflow/automation/device/DeviceGateway.java
@@ -1,11 +1,11 @@
 package eu.teraflow.automation.device;
 
+import eu.teraflow.automation.device.model.Device;
 import eu.teraflow.automation.device.model.DeviceConfig;
-import eu.teraflow.automation.device.model.DeviceId;
 import io.smallrye.mutiny.Uni;
 
 public interface DeviceGateway {
-    Uni<DeviceConfig> getInitialConfiguration(DeviceId deviceId);
+    Uni<DeviceConfig> getInitialConfiguration(String deviceId);
 
-    Uni<DeviceId> configureDevice(Device device);
+    Uni<String> configureDevice(Device device);
 }
diff --git a/src/automation/src/main/java/eu/teraflow/automation/device/DeviceGatewayImpl.java b/src/automation/src/main/java/eu/teraflow/automation/device/DeviceGatewayImpl.java
index 78e72598e..d0983c12d 100644
--- a/src/automation/src/main/java/eu/teraflow/automation/device/DeviceGatewayImpl.java
+++ b/src/automation/src/main/java/eu/teraflow/automation/device/DeviceGatewayImpl.java
@@ -1,138 +1,46 @@
 package eu.teraflow.automation.device;
 
-import context.ContextOuterClass;
-import context.ContextOuterClass.DeviceConfig;
-import context.ContextOuterClass.Uuid;
 import device.DeviceService;
-import eu.teraflow.automation.device.model.*;
+import eu.teraflow.automation.Serializer;
+import eu.teraflow.automation.device.model.Device;
+import eu.teraflow.automation.device.model.DeviceConfig;
 import io.quarkus.grpc.GrpcClient;
 import io.smallrye.mutiny.Uni;
-import java.util.ArrayList;
-import java.util.List;
 import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import org.jboss.logging.Logger;
 
 @ApplicationScoped
 public class DeviceGatewayImpl implements DeviceGateway {
+    private static final Logger LOGGER = Logger.getLogger(DeviceGatewayImpl.class);
 
     @GrpcClient("device")
     DeviceService deviceDelegate;
 
-    @Override
-    public Uni<eu.teraflow.automation.device.model.DeviceConfig> getInitialConfiguration(
-            DeviceId deviceId) {
-        final var serializedId = getSerializedDeviceId(deviceId);
-        final var serializedDeviceConfigUni = deviceDelegate.getInitialConfig(serializedId);
+    private final Serializer serializer;
 
-        return serializedDeviceConfigUni.onItem().transform(this::getDeviceConfig);
+    @Inject
+    public DeviceGatewayImpl(Serializer serializer) {
+        this.serializer = serializer;
     }
 
     @Override
-    public Uni<DeviceId> configureDevice(Device device) {
-        final var deviceBuilder = ContextOuterClass.Device.newBuilder();
-
-        final var serializedId = getSerializedDeviceId(device.getDeviceId());
-        deviceBuilder.setDeviceId(serializedId);
-
-        final var serializedConfigUni = getSerializedConfigUni(device.getDeviceConfig());
-        final var serializedConfig = serializedConfigUni.await().indefinitely();
-        deviceBuilder.setDeviceConfig(serializedConfig);
-
-        final var serializedDevice = deviceBuilder.build();
-        final var deviceIdUni = deviceDelegate.configureDevice(serializedDevice);
-
-        return deviceIdUni.onItem().transform(this::getDeviceId);
-    }
-
-    private List<ContextOuterClass.ConfigRule> getSerializedConfigRule(
-            List<ConfigRule> configRuleList) {
-
-        List<ContextOuterClass.ConfigRule> serializedConfigRuleList = new ArrayList<>();
-        for (ConfigRule item : configRuleList) {
-            final var configActionEnum = getSerializedConfigActionEnum(item.getConfigActionEnum());
-            final var resourceKey = item.getResourceKey();
-            final var resourceValue = item.getResourceValue();
-            final var serializedConfigRule =
-                    ContextOuterClass.ConfigRule.newBuilder()
-                            .setAction(configActionEnum)
-                            .setResourceKey(resourceKey)
-                            .setResourceValue(resourceValue)
-                            .build();
-            serializedConfigRuleList.add(serializedConfigRule);
-        }
-        return serializedConfigRuleList;
-    }
-
-    private ContextOuterClass.ConfigActionEnum getSerializedConfigActionEnum(
-            ConfigActionEnum configActionEnum) {
-
-        if (configActionEnum == ConfigActionEnum.SET) {
-            return ContextOuterClass.ConfigActionEnum.CONFIGACTION_SET;
-        } else if (configActionEnum == ConfigActionEnum.UNDEFINED) {
-            return ContextOuterClass.ConfigActionEnum.CONFIGACTION_UNDEFINED;
-        } else {
-            return ContextOuterClass.ConfigActionEnum.CONFIGACTION_DELETE;
-        }
-    }
-
-    private ConfigActionEnum getConfigActionEnum(
-            ContextOuterClass.ConfigActionEnum configActionEnum) {
-
-        if (configActionEnum == ContextOuterClass.ConfigActionEnum.CONFIGACTION_SET) {
-            return ConfigActionEnum.SET;
-        } else if (configActionEnum == ContextOuterClass.ConfigActionEnum.CONFIGACTION_UNDEFINED) {
-            return ConfigActionEnum.UNDEFINED;
-        } else {
-            return ConfigActionEnum.DELETE;
-        }
-    }
-
-    private ContextOuterClass.DeviceId getSerializedDeviceId(DeviceId deviceId) {
-        final var deviceIdUuid = Uuid.newBuilder().setUuid(deviceId.toString()).build();
-        return ContextOuterClass.DeviceId.newBuilder().setDeviceUuid(deviceIdUuid).build();
-    }
-
-    private DeviceId getDeviceId(ContextOuterClass.DeviceId deviceId) {
-        eu.teraflow.automation.device.model.Uuid uuid =
-                new eu.teraflow.automation.device.model.Uuid(deviceId.getDeviceUuid().getUuid());
-        return new DeviceId(uuid);
-    }
-
-    private eu.teraflow.automation.device.model.DeviceConfig getDeviceConfig(
-            ContextOuterClass.DeviceConfig deviceConfig) {
-
-        final var serializedConfigRuleList = deviceConfig.getConfigRulesList();
-        final var configRuleList = getConfigRuleList(serializedConfigRuleList);
-        return new eu.teraflow.automation.device.model.DeviceConfig(configRuleList);
-    }
-
-    private List<ConfigRule> getConfigRuleList(
-            List<ContextOuterClass.ConfigRule> serializedConfigRuleList) {
-
-        List<ConfigRule> configRuleList = new ArrayList<>();
-
-        for (ContextOuterClass.ConfigRule item : serializedConfigRuleList) {
+    public Uni<DeviceConfig> getInitialConfiguration(String deviceId) {
+        final var serializedDeviceId = serializer.serializeDeviceId(deviceId);
 
-            ConfigRule configRule =
-                    new ConfigRule(
-                            getConfigActionEnum(item.getAction()),
-                            item.getResourceKey(),
-                            item.getResourceValue());
-            configRuleList.add(configRule);
-        }
-        return configRuleList;
+        return deviceDelegate
+                .getInitialConfig(serializedDeviceId)
+                .onItem()
+                .transform(serializer::deserialize);
     }
 
-    private Uni<DeviceConfig> getSerializedConfigUni(
-            eu.teraflow.automation.device.model.DeviceConfig deviceConfig) {
-
-        final var serializedDeviceConfig = DeviceConfig.newBuilder();
-
-        final var configRuleList = deviceConfig.getConfigRules();
-        final var serializedConfigRuleList = getSerializedConfigRule(configRuleList);
-        for (int i = 0; i < serializedConfigRuleList.size(); i++) {
-            serializedDeviceConfig.setConfigRules(i, serializedConfigRuleList.get(i));
-        }
+    @Override
+    public Uni<String> configureDevice(Device device) {
+        final var serializedDevice = serializer.serialize(device);
 
-        return Uni.createFrom().item(serializedDeviceConfig.build());
+        return deviceDelegate
+                .configureDevice(serializedDevice)
+                .onItem()
+                .transform(serializer::deserialize);
     }
 }
diff --git a/src/automation/src/main/java/eu/teraflow/automation/device/DeviceService.java b/src/automation/src/main/java/eu/teraflow/automation/device/DeviceService.java
index 0ada5cde2..cbf412bb3 100644
--- a/src/automation/src/main/java/eu/teraflow/automation/device/DeviceService.java
+++ b/src/automation/src/main/java/eu/teraflow/automation/device/DeviceService.java
@@ -1,12 +1,12 @@
 package eu.teraflow.automation.device;
 
+import eu.teraflow.automation.device.model.Device;
 import eu.teraflow.automation.device.model.DeviceConfig;
-import eu.teraflow.automation.device.model.DeviceId;
 import io.smallrye.mutiny.Uni;
 
 public interface DeviceService {
 
-    Uni<DeviceConfig> getInitialConfiguration(DeviceId deviceId);
+    Uni<DeviceConfig> getInitialConfiguration(String deviceId);
 
-    Uni<DeviceId> configureDevice(Device device);
+    Uni<String> configureDevice(Device device);
 }
diff --git a/src/automation/src/main/java/eu/teraflow/automation/device/DeviceServiceImpl.java b/src/automation/src/main/java/eu/teraflow/automation/device/DeviceServiceImpl.java
index 57c118255..a17e956c9 100644
--- a/src/automation/src/main/java/eu/teraflow/automation/device/DeviceServiceImpl.java
+++ b/src/automation/src/main/java/eu/teraflow/automation/device/DeviceServiceImpl.java
@@ -1,7 +1,7 @@
 package eu.teraflow.automation.device;
 
+import eu.teraflow.automation.device.model.Device;
 import eu.teraflow.automation.device.model.DeviceConfig;
-import eu.teraflow.automation.device.model.DeviceId;
 import io.smallrye.mutiny.Uni;
 import javax.enterprise.context.ApplicationScoped;
 import javax.inject.Inject;
@@ -17,13 +17,13 @@ public class DeviceServiceImpl implements DeviceService {
     }
 
     @Override
-    public Uni<DeviceConfig> getInitialConfiguration(DeviceId deviceId) {
+    public Uni<DeviceConfig> getInitialConfiguration(String deviceId) {
 
         return deviceGateway.getInitialConfiguration(deviceId);
     }
 
     @Override
-    public Uni<DeviceId> configureDevice(Device device) {
+    public Uni<String> configureDevice(Device device) {
 
         return deviceGateway.configureDevice(device);
     }
diff --git a/src/automation/src/main/java/eu/teraflow/automation/device/model/ConfigRule.java b/src/automation/src/main/java/eu/teraflow/automation/device/model/ConfigRule.java
index 7c9eecd68..4cbba7d48 100644
--- a/src/automation/src/main/java/eu/teraflow/automation/device/model/ConfigRule.java
+++ b/src/automation/src/main/java/eu/teraflow/automation/device/model/ConfigRule.java
@@ -2,9 +2,9 @@ package eu.teraflow.automation.device.model;
 
 public class ConfigRule {
 
-    private ConfigActionEnum configActionEnum;
-    private String resourceKey;
-    private String resourceValue;
+    private final ConfigActionEnum configActionEnum;
+    private final String resourceKey;
+    private final String resourceValue;
 
     public ConfigRule(ConfigActionEnum configActionEnum, String resourceKey, String resourceValue) {
         this.configActionEnum = configActionEnum;
@@ -23,4 +23,10 @@ public class ConfigRule {
     public String getResourceValue() {
         return resourceValue;
     }
+
+    @Override
+    public String toString() {
+        return String.format(
+                "%s<%s, %s,%s>", getClass().getSimpleName(), configActionEnum, resourceKey, resourceValue);
+    }
 }
diff --git a/src/automation/src/main/java/eu/teraflow/automation/device/Device.java b/src/automation/src/main/java/eu/teraflow/automation/device/model/Device.java
similarity index 53%
rename from src/automation/src/main/java/eu/teraflow/automation/device/Device.java
rename to src/automation/src/main/java/eu/teraflow/automation/device/model/Device.java
index d2abfee95..2c87fcd19 100644
--- a/src/automation/src/main/java/eu/teraflow/automation/device/Device.java
+++ b/src/automation/src/main/java/eu/teraflow/automation/device/model/Device.java
@@ -1,20 +1,15 @@
-package eu.teraflow.automation.device;
-
-import eu.teraflow.automation.device.model.DeviceConfig;
-import eu.teraflow.automation.device.model.DeviceId;
-import eu.teraflow.automation.device.model.DeviceOperationalStatus;
-import eu.teraflow.automation.device.model.DeviceType;
+package eu.teraflow.automation.device.model;
 
 public class Device {
 
-    private final DeviceId deviceId;
-    private final DeviceType deviceType;
+    private final String deviceId;
+    private final String deviceType;
     private DeviceConfig deviceConfig;
     private DeviceOperationalStatus deviceOperationalStatus;
 
     public Device(
-            DeviceId deviceId,
-            DeviceType deviceType,
+            String deviceId,
+            String deviceType,
             DeviceConfig deviceConfig,
             DeviceOperationalStatus deviceOperationalStatus) {
 
@@ -25,18 +20,25 @@ public class Device {
     }
 
     public Device(
-            DeviceId deviceId, DeviceType deviceType, DeviceOperationalStatus deviceOperationalStatus) {
-
+            String deviceId, String deviceType, DeviceOperationalStatus deviceOperationalStatus) {
         this.deviceId = deviceId;
         this.deviceType = deviceType;
         this.deviceOperationalStatus = deviceOperationalStatus;
     }
 
-    public DeviceId getDeviceId() {
+    public boolean isEnabled() {
+        return deviceOperationalStatus == DeviceOperationalStatus.ENABLED;
+    }
+
+    public void enableDevice() {
+        this.deviceOperationalStatus = DeviceOperationalStatus.ENABLED;
+    }
+
+    public String getDeviceId() {
         return deviceId;
     }
 
-    public DeviceType getDeviceType() {
+    public String getDeviceType() {
         return deviceType;
     }
 
@@ -48,18 +50,14 @@ public class Device {
         return deviceOperationalStatus;
     }
 
-    public void setDeviceOperationalStatus(DeviceOperationalStatus status) {
-
-        this.deviceOperationalStatus = status;
-    }
-
     public void setDeviceConfiguration(DeviceConfig deviceConfig) {
-
         this.deviceConfig = deviceConfig;
     }
 
-    public boolean isConfigured() {
-
-        return this.deviceOperationalStatus == DeviceOperationalStatus.ENABLED;
+    @Override
+    public String toString() {
+        return String.format(
+                "%s{id=\"%s\", type=\"%s\", operationalStatus=\"%s\", config=%s",
+                getClass().getSimpleName(), deviceId, deviceType, deviceOperationalStatus, deviceConfig);
     }
 }
diff --git a/src/automation/src/main/java/eu/teraflow/automation/device/model/DeviceConfig.java b/src/automation/src/main/java/eu/teraflow/automation/device/model/DeviceConfig.java
index c70e743dc..7936eba19 100644
--- a/src/automation/src/main/java/eu/teraflow/automation/device/model/DeviceConfig.java
+++ b/src/automation/src/main/java/eu/teraflow/automation/device/model/DeviceConfig.java
@@ -1,10 +1,11 @@
 package eu.teraflow.automation.device.model;
 
 import java.util.List;
+import java.util.stream.Collectors;
 
 public class DeviceConfig {
 
-    private List<ConfigRule> configRules;
+    private final List<ConfigRule> configRules;
 
     public DeviceConfig(List<ConfigRule> configRules) {
 
@@ -14,4 +15,11 @@ public class DeviceConfig {
     public List<ConfigRule> getConfigRules() {
         return configRules;
     }
+
+    @Override
+    public String toString() {
+        final var configRulesDescription =
+                configRules.stream().map(ConfigRule::toString).collect(Collectors.joining(", "));
+        return String.format("%s[%s]", getClass().getSimpleName(), configRulesDescription);
+    }
 }
diff --git a/src/automation/src/main/java/eu/teraflow/automation/device/model/DeviceEvent.java b/src/automation/src/main/java/eu/teraflow/automation/device/model/DeviceEvent.java
index ef3f8ae76..01b8cc8ca 100644
--- a/src/automation/src/main/java/eu/teraflow/automation/device/model/DeviceEvent.java
+++ b/src/automation/src/main/java/eu/teraflow/automation/device/model/DeviceEvent.java
@@ -4,10 +4,10 @@ import eu.teraflow.automation.context.model.Event;
 
 public class DeviceEvent {
 
-    private Event event;
-    private DeviceId deviceId;
+    private final Event event;
+    private final String deviceId;
 
-    public DeviceEvent(Event event, DeviceId deviceId) {
+    public DeviceEvent(String deviceId, Event event) {
         this.event = event;
         this.deviceId = deviceId;
     }
@@ -16,7 +16,12 @@ public class DeviceEvent {
         return event;
     }
 
-    public DeviceId getDeviceId() {
+    public String getDeviceId() {
         return deviceId;
     }
+
+    @Override
+    public String toString() {
+        return String.format("%s[%s, %s]", getClass().getSimpleName(), deviceId, event.toString());
+    }
 }
diff --git a/src/automation/src/main/java/eu/teraflow/automation/device/model/DeviceId.java b/src/automation/src/main/java/eu/teraflow/automation/device/model/DeviceId.java
deleted file mode 100644
index b52672631..000000000
--- a/src/automation/src/main/java/eu/teraflow/automation/device/model/DeviceId.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package eu.teraflow.automation.device.model;
-
-public class DeviceId {
-    private Uuid id;
-
-    public DeviceId(Uuid id) {
-        this.id = id;
-    }
-
-    public Uuid getId() {
-        return id;
-    }
-}
diff --git a/src/automation/src/main/java/eu/teraflow/automation/device/model/DeviceType.java b/src/automation/src/main/java/eu/teraflow/automation/device/model/DeviceType.java
deleted file mode 100644
index 2d61875d4..000000000
--- a/src/automation/src/main/java/eu/teraflow/automation/device/model/DeviceType.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package eu.teraflow.automation.device.model;
-
-public class DeviceType {
-    String deviceType;
-
-    public DeviceType(String deviceType) {
-
-        this.deviceType = deviceType;
-    }
-
-    public String getDeviceType() {
-        return deviceType;
-    }
-}
diff --git a/src/automation/src/main/java/eu/teraflow/automation/device/model/Uuid.java b/src/automation/src/main/java/eu/teraflow/automation/device/model/Uuid.java
deleted file mode 100644
index 0a58ee6a8..000000000
--- a/src/automation/src/main/java/eu/teraflow/automation/device/model/Uuid.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package eu.teraflow.automation.device.model;
-
-public class Uuid {
-
-    private String id;
-
-    public Uuid(String id) {
-        this.id = id;
-    }
-
-    public String getId() {
-        return id;
-    }
-}
diff --git a/src/automation/src/main/java/eu/teraflow/automation/model/DeviceRoleId.java b/src/automation/src/main/java/eu/teraflow/automation/model/DeviceRoleId.java
index d795fed4a..cb8aa7096 100644
--- a/src/automation/src/main/java/eu/teraflow/automation/model/DeviceRoleId.java
+++ b/src/automation/src/main/java/eu/teraflow/automation/model/DeviceRoleId.java
@@ -1,23 +1,20 @@
 package eu.teraflow.automation.model;
 
-import eu.teraflow.automation.device.model.DeviceId;
-import eu.teraflow.automation.device.model.Uuid;
-
 public class DeviceRoleId {
 
-    private final Uuid devRoleId;
-    private final DeviceId deviceId;
+    private final String id;
+    private final String deviceId;
 
-    public DeviceRoleId(Uuid devRoleId, DeviceId deviceId) {
-        this.devRoleId = devRoleId;
+    public DeviceRoleId(String id, String deviceId) {
+        this.id = id;
         this.deviceId = deviceId;
     }
 
-    public Uuid getDevRoleId() {
-        return devRoleId;
+    public String getId() {
+        return id;
     }
 
-    public DeviceId getDeviceId() {
+    public String getDeviceId() {
         return deviceId;
     }
 }
diff --git a/src/automation/src/main/resources/application.yaml b/src/automation/src/main/resources/application.yaml
index 8d5ae6ed5..75afe1d4c 100644
--- a/src/automation/src/main/resources/application.yaml
+++ b/src/automation/src/main/resources/application.yaml
@@ -1,6 +1,8 @@
 automation:
   should-subscribe-to-context-component: true
 quarkus:
+  banner:
+    path: teraflow-automation-banner.txt
   grpc:
     server:
       port: 9999
@@ -8,27 +10,30 @@ quarkus:
     clients:
       context:
         host: ${quarkus.kubernetes.env.vars.context-service-host}
+        port: 1010
       device:
         host: ${quarkus.kubernetes.env.vars.device-service-host}
+        port: 2020
+
   http:
     port: 8080
+
   container-image:
     group: teraflow-h2020
     name: controller/automation
-    tag: 0.0.1
     registry: registry.gitlab.com
+
   kubernetes:
     name: automationservice
     image-pull-policy: Always
-    service-type: NodePort
     labels:
       app: automationservice
     readiness-probe:
-      initial-delay: 5s
-      period: 45s
+      initial-delay: 2s
+      period: 10s
     liveness-probe:
-      initial-delay: 5s
-      period: 45s
+      initial-delay: 2s
+      period: 10s
     ports:
       http:
         host-port: 8080
@@ -38,5 +43,5 @@ quarkus:
         container-port: 9999
     env:
       vars:
-        context-service-host: ContextService
-        device-service-host: DeviceService
\ No newline at end of file
+        context-service-host: "contextservice"
+        device-service-host: "deviceservice"
diff --git a/src/automation/src/main/resources/teraflow-automation-banner.txt b/src/automation/src/main/resources/teraflow-automation-banner.txt
new file mode 100644
index 000000000..379252417
--- /dev/null
+++ b/src/automation/src/main/resources/teraflow-automation-banner.txt
@@ -0,0 +1,9 @@
+
+  _______             ______ _                               _                        _   _
+ |__   __|           |  ____| |                   /\        | |                      | | (_)
+    | | ___ _ __ __ _| |__  | | _____      __    /  \  _   _| |_ ___  _ __ ___   __ _| |_ _  ___  _ __
+    | |/ _ \ '__/ _` |  __| | |/ _ \ \ /\ / /   / /\ \| | | | __/ _ \| '_ ` _ \ / _` | __| |/ _ \| '_ \
+    | |  __/ | | (_| | |    | | (_) \ V  V /   / ____ \ |_| | || (_) | | | | | | (_| | |_| | (_) | | | |
+    |_|\___|_|  \__,_|_|    |_|\___/ \_/\_/   /_/    \_\__,_|\__\___/|_| |_| |_|\__,_|\__|_|\___/|_| |_|
+
+
diff --git a/src/automation/src/test/java/eu/teraflow/automation/AutomationFunctionalServiceTest.java b/src/automation/src/test/java/eu/teraflow/automation/AutomationFunctionalServiceTest.java
index 81d568f25..c03fcaf40 100644
--- a/src/automation/src/test/java/eu/teraflow/automation/AutomationFunctionalServiceTest.java
+++ b/src/automation/src/test/java/eu/teraflow/automation/AutomationFunctionalServiceTest.java
@@ -5,9 +5,9 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
 import automation.Automation;
 import context.ContextOuterClass;
 import eu.teraflow.automation.context.ContextGateway;
-import eu.teraflow.automation.device.Device;
 import eu.teraflow.automation.device.DeviceGateway;
 import eu.teraflow.automation.device.model.*;
+import eu.teraflow.automation.device.model.Device;
 import io.quarkus.test.junit.QuarkusTest;
 import io.quarkus.test.junit.mockito.InjectMock;
 import io.smallrye.mutiny.Uni;
@@ -51,9 +51,8 @@ public class AutomationFunctionalServiceTest {
                         .setDevId(outDeviceId)
                         .build();
 
-        Uuid uuid = new Uuid(outDeviceRoleId.getDevId().toString());
-        DeviceId deviceId = new DeviceId(uuid);
-        DeviceType deviceType = new DeviceType("cisco");
+        String deviceId = outDeviceRoleId.getDevRoleId().toString();
+        String deviceType = "cisco";
 
         ConfigRule configRule1 = new ConfigRule(ConfigActionEnum.UNDEFINED, "1", "1");
         ConfigRule configRule2 = new ConfigRule(ConfigActionEnum.SET, "2", "2");
@@ -63,7 +62,7 @@ public class AutomationFunctionalServiceTest {
 
         DeviceConfig expectedDeviceConfig = new DeviceConfig(configRuleList);
         Uni<DeviceConfig> expectedDeviceConfigUni = Uni.createFrom().item(expectedDeviceConfig);
-        Uni<DeviceId> expectedDeviceId = Uni.createFrom().item(deviceId);
+        Uni<String> expectedDeviceId = Uni.createFrom().item(deviceId);
 
         Device device = new Device(deviceId, deviceType, DeviceOperationalStatus.DISABLED);
         Uni<Device> deviceUni = Uni.createFrom().item(device);
@@ -93,9 +92,8 @@ public class AutomationFunctionalServiceTest {
                                 assertThat(rulesList.get(i).getResourceKey()).isEqualTo(String.valueOf(i + 1));
                                 assertThat(rulesList.get(i).getResourceValue()).isEqualTo(String.valueOf(i + 1));
                             }
-
-                            assertThat(deviceConfig.getDeviceId().getId().getId())
-                                    .isEqualTo(deviceId.getId().getId());
+                            assertThat(deviceConfig.getDeviceType()).isEqualTo("cisco");
+                            assertThat(deviceConfig.getDeviceId()).isEqualTo(deviceId);
                         });
     }
 
@@ -121,9 +119,8 @@ public class AutomationFunctionalServiceTest {
                         .setDevId(outDeviceId)
                         .build();
 
-        Uuid uuid = new Uuid(outDeviceRoleId.getDevId().toString());
-        DeviceId deviceId = new DeviceId(uuid);
-        DeviceType deviceType = new DeviceType("ztp");
+        String deviceId = outDeviceRoleId.getDevId().toString();
+        String deviceType = "ztp";
 
         List<ConfigRule> configRuleList = new ArrayList<>();
 
@@ -163,9 +160,8 @@ public class AutomationFunctionalServiceTest {
                                 assertThat(configRule.getResourceValue())
                                         .isEqualTo(expectedConfigRule.getResourceValue());
                             }
-
-                            assertThat(deviceConfig.getDeviceId().getId().getId())
-                                    .isEqualTo(deviceId.getId().getId());
+                            assertThat(deviceConfig.getDeviceType()).isEqualTo("ztp");
+                            assertThat(deviceConfig.getDeviceId()).isEqualTo(deviceId);
                         });
     }
 }
diff --git a/src/automation/src/test/java/eu/teraflow/automation/AutomationServiceTest.java b/src/automation/src/test/java/eu/teraflow/automation/AutomationServiceTest.java
index 85e056b87..fbceb55ec 100644
--- a/src/automation/src/test/java/eu/teraflow/automation/AutomationServiceTest.java
+++ b/src/automation/src/test/java/eu/teraflow/automation/AutomationServiceTest.java
@@ -7,22 +7,20 @@ import automation.Automation.DeviceRole;
 import automation.Automation.DeviceRoleId;
 import automation.AutomationService;
 import context.ContextOuterClass;
-import context.ContextOuterClass.Uuid;
 import eu.teraflow.automation.context.ContextGateway;
-import eu.teraflow.automation.device.Device;
 import eu.teraflow.automation.device.DeviceGateway;
 import eu.teraflow.automation.device.model.*;
+import eu.teraflow.automation.device.model.Device;
 import io.quarkus.grpc.GrpcClient;
 import io.quarkus.test.junit.QuarkusTest;
 import io.quarkus.test.junit.mockito.InjectMock;
 import io.smallrye.mutiny.Uni;
-import java.util.ArrayList;
 import java.util.List;
-import java.util.UUID;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
+import javax.inject.Inject;
 import org.jboss.logging.Logger;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
@@ -32,67 +30,69 @@ class AutomationServiceTest {
     private static final Logger LOGGER = Logger.getLogger(AutomationServiceTest.class);
 
     @GrpcClient AutomationService client;
+    private final Serializer serializer;
 
     @InjectMock DeviceGateway deviceGateway;
     @InjectMock ContextGateway contextGateway;
 
+    @Inject
+    AutomationServiceTest(Serializer serializer) {
+        this.serializer = serializer;
+    }
+
     @Test
     void shouldAddDeviceRole() throws ExecutionException, InterruptedException, TimeoutException {
-        CompletableFuture<String> message = new CompletableFuture<>();
-
-        final var serializedUuid =
-                Uuid.newBuilder()
-                        .setUuid(UUID.fromString("0f14d0ab-9608-7862-a9e4-5ed26688389b").toString())
-                        .build();
-        final var deviceRoleId = DeviceRoleId.newBuilder().setDevRoleId(serializedUuid).build();
-        final var deviceRole = DeviceRole.newBuilder().setDevRoleId(deviceRoleId).build();
-
-        eu.teraflow.automation.device.model.Uuid uuid =
-                new eu.teraflow.automation.device.model.Uuid(deviceRoleId.getDevId().toString());
-        DeviceId deviceId = new DeviceId(uuid);
-        DeviceType deviceType = new DeviceType("ztp");
-
-        List<ConfigRule> configRuleList = new ArrayList<>();
-
-        ConfigRule configRule1 =
-                new ConfigRule(ConfigActionEnum.UNDEFINED, "001", "initial-configuration");
-        configRuleList.add(configRule1);
-
-        DeviceConfig deviceConfig = new DeviceConfig(configRuleList);
-        //        Uni<DeviceConfig> deviceConfigUni = Uni.createFrom().item(deviceConfig);
-        Uni<DeviceId> expectedDeviceId = Uni.createFrom().item(deviceId);
-
-        DeviceConfig expectedDeviceConfig = new DeviceConfig(configRuleList);
-        Uni<DeviceConfig> expectedDeviceConfigUni = Uni.createFrom().item(expectedDeviceConfig);
-
-        Device device =
-                new Device(deviceId, deviceType, deviceConfig, DeviceOperationalStatus.DISABLED);
-        Uni<Device> deviceUni = Uni.createFrom().item(device);
-
-        Mockito.when(contextGateway.getDevice(Mockito.any())).thenReturn(deviceUni);
+        final var message = new CompletableFuture<>();
+        final var DEVICE_ID = "0f14d0ab-9608-7862-a9e4-5ed26688389b";
+        final var DEVICE_ROLE_ID = "0f14d0ab-9608-7862-a9e4-5ed26688389a";
+        final var DEVICE_TYPE = "ztp";
+
+        final var emptyDeviceConfig = new DeviceConfig(List.of());
+        final var disabledDevice =
+                new Device(DEVICE_ID, DEVICE_TYPE, emptyDeviceConfig, DeviceOperationalStatus.DISABLED);
+        Mockito.when(contextGateway.getDevice(Mockito.any()))
+                .thenReturn(Uni.createFrom().item(disabledDevice));
+
+        final var configRule = new ConfigRule(ConfigActionEnum.SET, "001", "initial-configuration");
+        final var initialDeviceConfig = new DeviceConfig(List.of(configRule));
         Mockito.when(deviceGateway.getInitialConfiguration(Mockito.any()))
-                .thenReturn(expectedDeviceConfigUni);
-        Mockito.when(deviceGateway.configureDevice(Mockito.any())).thenReturn(expectedDeviceId);
+                .thenReturn(Uni.createFrom().item(initialDeviceConfig));
 
+        Mockito.when(deviceGateway.configureDevice(Mockito.any()))
+                .thenReturn(Uni.createFrom().item(DEVICE_ID));
+
+        // TODO 1. add (de)serialization for device role (and its components) in serializer module
+        // TODO 2. use it here
+        final var serializedDeviceRoleId =
+                DeviceRoleId.newBuilder()
+                        .setDevRoleId(serializer.serializeUuid(DEVICE_ROLE_ID))
+                        .setDevId(serializer.serializeDeviceId(DEVICE_ID))
+                        .build();
+        final var serializedDeviceRole =
+                DeviceRole.newBuilder().setDevRoleId(serializedDeviceRoleId).build();
         client
-                .ztpAdd(deviceRole)
+                .ztpAdd(serializedDeviceRole)
                 .subscribe()
                 .with(
                         deviceRoleState -> {
-                            LOGGER.infof("Received response %s", deviceRoleState);
-                            message.complete(deviceRoleState.getDevRoleId().getDevRoleId().toString());
+                            LOGGER.infof("Received %s", deviceRoleState);
+                            final var devRoleId = deviceRoleState.getDevRoleId();
+
+                            final var deviceId = serializer.deserialize(devRoleId.getDevId());
+                            assertThat(deviceId).isEqualTo(DEVICE_ID);
+
+                            final var devRoleUuid = serializer.deserialize(devRoleId.getDevRoleId());
+                            message.complete(devRoleUuid);
                         });
-        assertThat(message.get(5, TimeUnit.SECONDS)).isEqualTo(deviceRoleId.getDevRoleId().toString());
+        assertThat(message.get(5, TimeUnit.SECONDS)).isEqualTo(DEVICE_ROLE_ID);
     }
 
     @Test
     void shouldUpdateDeviceRole() throws ExecutionException, InterruptedException, TimeoutException {
         CompletableFuture<String> message = new CompletableFuture<>();
+        final var UUID_VALUE = "0f14d0ab-9605-7862-a9e4-5ed26688389b";
 
-        final var uuid =
-                Uuid.newBuilder()
-                        .setUuid(UUID.fromString("0f14d0ab-9605-7862-a9e4-5ed26688389b").toString())
-                        .build();
+        final var uuid = serializer.serializeUuid(UUID_VALUE);
         final var deviceRoleId = DeviceRoleId.newBuilder().setDevRoleId(uuid).build();
         final var deviceRole = DeviceRole.newBuilder().setDevRoleId(deviceRoleId).build();
 
@@ -104,18 +104,15 @@ class AutomationServiceTest {
                             LOGGER.infof("Received response %s", deviceRoleState);
                             message.complete(deviceRoleState.getDevRoleId().toString());
                         });
-        assertThat(message.get(5, TimeUnit.SECONDS)).contains("0f14d0ab-9605-7862-a9e4-5ed26688389b");
+        assertThat(message.get(5, TimeUnit.SECONDS)).contains(UUID_VALUE);
     }
 
     @Test
     void shouldGetDeviceRole() throws ExecutionException, InterruptedException, TimeoutException {
-
         CompletableFuture<String> message = new CompletableFuture<>();
+        final var UUID_VALUE = "0f14d0ab-9605-7862-a9e4-5ed26688389b";
 
-        final var uuid =
-                Uuid.newBuilder()
-                        .setUuid(UUID.fromString("0f14d0ab-9605-4a62-a5c4-5ed26688389b").toString())
-                        .build();
+        final var uuid = serializer.serializeUuid(UUID_VALUE);
         final var deviceRoleId = DeviceRoleId.newBuilder().setDevRoleId(uuid).build();
 
         client
@@ -126,19 +123,15 @@ class AutomationServiceTest {
                             LOGGER.infof("Received response %s", deviceRole);
                             message.complete(deviceRole.getDevRoleId().toString());
                         });
-        assertThat(message.get(5, TimeUnit.SECONDS)).contains("0f14d0ab-9605-4a62-a5c4-5ed26688389b");
+        assertThat(message.get(5, TimeUnit.SECONDS)).contains(UUID_VALUE);
     }
 
     @Test
     void shouldGetAllDeviceRolesByDeviceId()
             throws ExecutionException, InterruptedException, TimeoutException {
-
         CompletableFuture<String> message = new CompletableFuture<>();
 
-        final var uuid =
-                Uuid.newBuilder()
-                        .setUuid(UUID.fromString("1b14d0ab-9605-4a62-a9e4-5ed26688389b").toString())
-                        .build();
+        final var uuid = serializer.serializeUuid("0f14d0ab-9605-7862-a9e4-5ed26688389b");
         final var deviceId = ContextOuterClass.DeviceId.newBuilder().setDeviceUuid(uuid).build();
 
         client
@@ -155,10 +148,9 @@ class AutomationServiceTest {
     @Test
     void shouldDeleteDeviceRole() throws ExecutionException, InterruptedException, TimeoutException {
         CompletableFuture<String> message = new CompletableFuture<>();
-        final var uuid =
-                Uuid.newBuilder()
-                        .setUuid(UUID.fromString("0c15d0ab-9605-4a62-a5c4-5ed26688389b").toString())
-                        .build();
+        final var UUID_VALUE = "0f14d0ab-9605-7862-a9e4-5ed26688389b";
+
+        final var uuid = serializer.serializeUuid(UUID_VALUE);
         final var deviceRoleId = DeviceRoleId.newBuilder().setDevRoleId(uuid).build();
         final var deviceRole = DeviceRole.newBuilder().setDevRoleId(deviceRoleId).build();
 
@@ -170,13 +162,12 @@ class AutomationServiceTest {
                             LOGGER.infof("Received response %s", deviceRoleState);
                             message.complete(deviceRoleState.getDevRoleId().toString());
                         });
-        assertThat(message.get(5, TimeUnit.SECONDS)).contains("0c15d0ab-9605-4a62-a5c4-5ed26688389b");
+        assertThat(message.get(5, TimeUnit.SECONDS)).contains(UUID_VALUE);
     }
 
     @Test
     void shouldDeleteAllDevicesRolesByDeviceId()
             throws ExecutionException, InterruptedException, TimeoutException {
-
         CompletableFuture<String> message = new CompletableFuture<>();
         final var empty = Automation.Empty.newBuilder().build();
 
diff --git a/src/automation/src/test/java/eu/teraflow/automation/SerializerTest.java b/src/automation/src/test/java/eu/teraflow/automation/SerializerTest.java
new file mode 100644
index 000000000..de4a7930d
--- /dev/null
+++ b/src/automation/src/test/java/eu/teraflow/automation/SerializerTest.java
@@ -0,0 +1,365 @@
+package eu.teraflow.automation;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import context.ContextOuterClass;
+import context.ContextOuterClass.DeviceId;
+import context.ContextOuterClass.DeviceOperationalStatusEnum;
+import context.ContextOuterClass.Uuid;
+import eu.teraflow.automation.context.model.Event;
+import eu.teraflow.automation.context.model.EventTypeEnum;
+import eu.teraflow.automation.device.model.ConfigActionEnum;
+import eu.teraflow.automation.device.model.ConfigRule;
+import eu.teraflow.automation.device.model.Device;
+import eu.teraflow.automation.device.model.DeviceConfig;
+import eu.teraflow.automation.device.model.DeviceEvent;
+import eu.teraflow.automation.device.model.DeviceOperationalStatus;
+import io.quarkus.test.junit.QuarkusTest;
+import java.util.List;
+import java.util.stream.Stream;
+import javax.inject.Inject;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+@QuarkusTest
+class SerializerTest {
+
+    @Inject Serializer serializer;
+
+    @Test
+    void shouldSerializeDeviceId() {
+        final var expectedId = "expectedDeviceId";
+        final var expectedUuid = Uuid.newBuilder().setUuid(expectedId).build();
+        final var expectedDeviceId = DeviceId.newBuilder().setDeviceUuid(expectedUuid).build();
+
+        final var serializedDeviceId = serializer.serializeDeviceId("expectedDeviceId");
+
+        assertThat(serializedDeviceId).usingRecursiveComparison().isEqualTo(expectedDeviceId);
+    }
+
+    @Test
+    void shouldDeserializeDeviceId() {
+        final var expectedDeviceId = "expectedDeviceId";
+
+        final var serializedDeviceId = serializer.serializeDeviceId("expectedDeviceId");
+        final var deviceId = serializer.deserialize(serializedDeviceId);
+
+        assertThat(deviceId).isEqualTo(expectedDeviceId);
+    }
+
+    private static Stream<Arguments> provideEventTypeEnum() {
+        return Stream.of(
+                Arguments.of(EventTypeEnum.CREATE, ContextOuterClass.EventTypeEnum.EVENTTYPE_CREATE),
+                Arguments.of(EventTypeEnum.REMOVE, ContextOuterClass.EventTypeEnum.EVENTTYPE_REMOVE),
+                Arguments.of(EventTypeEnum.UNDEFINED, ContextOuterClass.EventTypeEnum.EVENTTYPE_UNDEFINED),
+                Arguments.of(EventTypeEnum.UPDATE, ContextOuterClass.EventTypeEnum.EVENTTYPE_UPDATE));
+    }
+
+    @ParameterizedTest
+    @MethodSource("provideEventTypeEnum")
+    void shouldSerializeEventType(
+            EventTypeEnum eventType, ContextOuterClass.EventTypeEnum expectedSerializedType) {
+        final var serializedType = serializer.serialize(eventType);
+        assertThat(serializedType.getNumber()).isEqualTo(expectedSerializedType.getNumber());
+    }
+
+    @ParameterizedTest
+    @MethodSource("provideEventTypeEnum")
+    void shouldDeserializeEventType(
+            EventTypeEnum expectedEventType, ContextOuterClass.EventTypeEnum serializedEventType) {
+        final var eventType = serializer.deserialize(serializedEventType);
+        assertThat(eventType).isEqualTo(expectedEventType);
+    }
+
+    @Test
+    void shouldSerializeEvent() {
+        final var expectedEvent =
+                ContextOuterClass.Event.newBuilder()
+                        .setTimestamp(1)
+                        .setEventType(ContextOuterClass.EventTypeEnum.EVENTTYPE_CREATE)
+                        .build();
+
+        final var event = new Event(1, EventTypeEnum.CREATE);
+        final var serializedEvent = serializer.serialize(event);
+
+        assertThat(serializedEvent).usingRecursiveComparison().isEqualTo(expectedEvent);
+    }
+
+    @Test
+    void shouldDeserializeEvent() {
+        final var expectedEvent = new Event(1, EventTypeEnum.CREATE);
+
+        final var serializedEvent =
+                ContextOuterClass.Event.newBuilder()
+                        .setTimestamp(1)
+                        .setEventType(ContextOuterClass.EventTypeEnum.EVENTTYPE_CREATE)
+                        .build();
+        final var event = serializer.deserialize(serializedEvent);
+
+        assertThat(event).usingRecursiveComparison().isEqualTo(expectedEvent);
+    }
+
+    @Test
+    void shouldSerializeDeviceEvent() {
+        final var expectedUuid = Uuid.newBuilder().setUuid("deviceId");
+        final var expectedDeviceId = DeviceId.newBuilder().setDeviceUuid(expectedUuid).build();
+        final var expectedEvent =
+                ContextOuterClass.Event.newBuilder()
+                        .setTimestamp(1)
+                        .setEventType(ContextOuterClass.EventTypeEnum.EVENTTYPE_CREATE)
+                        .build();
+        final var expectedDeviceEvent =
+                ContextOuterClass.DeviceEvent.newBuilder()
+                        .setDeviceId(expectedDeviceId)
+                        .setEvent(expectedEvent)
+                        .build();
+
+        final var creationEvent = new Event(1, EventTypeEnum.CREATE);
+        final var deviceEvent = new DeviceEvent("deviceId", creationEvent);
+        final var serializedDeviceEvent = serializer.serialize(deviceEvent);
+
+        assertThat(serializedDeviceEvent).usingRecursiveComparison().isEqualTo(expectedDeviceEvent);
+    }
+
+    @Test
+    void shouldDeserializeDeviceEvent() {
+        final var dummyDeviceId = "deviceId";
+        final var expectedEventType = EventTypeEnum.REMOVE;
+        final var expectedTimestamp = 1;
+        final var creationEvent = new Event(expectedTimestamp, expectedEventType);
+        final var expectedDeviceEvent = new DeviceEvent(dummyDeviceId, creationEvent);
+
+        final var deviceUuid = Uuid.newBuilder().setUuid("deviceId");
+        final var deviceId = DeviceId.newBuilder().setDeviceUuid(deviceUuid).build();
+        final var event =
+                ContextOuterClass.Event.newBuilder()
+                        .setTimestamp(1)
+                        .setEventType(ContextOuterClass.EventTypeEnum.EVENTTYPE_REMOVE)
+                        .build();
+        final var serializedDeviceEvent =
+                ContextOuterClass.DeviceEvent.newBuilder().setDeviceId(deviceId).setEvent(event).build();
+        final var deviceEvent = serializer.deserialize(serializedDeviceEvent);
+
+        assertThat(deviceEvent).usingRecursiveComparison().isEqualTo(expectedDeviceEvent);
+    }
+
+    private static Stream<Arguments> provideConfigActionEnum() {
+        return Stream.of(
+                Arguments.of(ConfigActionEnum.SET, ContextOuterClass.ConfigActionEnum.CONFIGACTION_SET),
+                Arguments.of(
+                        ConfigActionEnum.DELETE, ContextOuterClass.ConfigActionEnum.CONFIGACTION_DELETE),
+                Arguments.of(
+                        ConfigActionEnum.UNDEFINED, ContextOuterClass.ConfigActionEnum.CONFIGACTION_UNDEFINED));
+    }
+
+    @ParameterizedTest
+    @MethodSource("provideConfigActionEnum")
+    void shouldSerializeConfigActionEnum(
+            ConfigActionEnum configAction, ContextOuterClass.ConfigActionEnum expectedConfigAction) {
+        final var serializedConfigAction = serializer.serialize(configAction);
+        assertThat(serializedConfigAction.getNumber()).isEqualTo(expectedConfigAction.getNumber());
+    }
+
+    @ParameterizedTest
+    @MethodSource("provideConfigActionEnum")
+    void shouldDeserializeConfigActionEnum(
+            ConfigActionEnum expectedConfigAction,
+            ContextOuterClass.ConfigActionEnum serializedConfigAction) {
+        final var configAction = serializer.deserialize(serializedConfigAction);
+        assertThat(configAction).isEqualTo(expectedConfigAction);
+    }
+
+    @Test
+    void shouldSerializeConfigRule() {
+        final var expectedConfigRule =
+                ContextOuterClass.ConfigRule.newBuilder()
+                        .setAction(ContextOuterClass.ConfigActionEnum.CONFIGACTION_SET)
+                        .setResourceKey("resourceKey")
+                        .setResourceValue("resourceValue")
+                        .build();
+
+        final var configRule = new ConfigRule(ConfigActionEnum.SET, "resourceKey", "resourceValue");
+        final var serializedConfigRule = serializer.serialize(configRule);
+
+        assertThat(serializedConfigRule).usingRecursiveComparison().isEqualTo(expectedConfigRule);
+    }
+
+    @Test
+    void shouldDeserializeConfigRule() {
+        final var expectedConfigRule =
+                new ConfigRule(ConfigActionEnum.DELETE, "resourceKey", "resourceValue");
+
+        final var serializedConfigRule =
+                ContextOuterClass.ConfigRule.newBuilder()
+                        .setAction(ContextOuterClass.ConfigActionEnum.CONFIGACTION_DELETE)
+                        .setResourceKey("resourceKey")
+                        .setResourceValue("resourceValue")
+                        .build();
+        final var configRule = serializer.deserialize(serializedConfigRule);
+
+        assertThat(configRule).usingRecursiveComparison().isEqualTo(expectedConfigRule);
+    }
+
+    @Test
+    void shouldSerializeDeviceConfig() {
+        final var expectedConfigRuleA =
+                ContextOuterClass.ConfigRule.newBuilder()
+                        .setAction(ContextOuterClass.ConfigActionEnum.CONFIGACTION_SET)
+                        .setResourceKey("resourceKeyA")
+                        .setResourceValue("resourceValueA")
+                        .build();
+        final var expectedConfigRuleB =
+                ContextOuterClass.ConfigRule.newBuilder()
+                        .setAction(ContextOuterClass.ConfigActionEnum.CONFIGACTION_DELETE)
+                        .setResourceKey("resourceKeyB")
+                        .setResourceValue("resourceValueB")
+                        .build();
+        final var expectedDeviceConfig =
+                ContextOuterClass.DeviceConfig.newBuilder()
+                        .addAllConfigRules(List.of(expectedConfigRuleA, expectedConfigRuleB))
+                        .build();
+
+        final var configRuleA = new ConfigRule(ConfigActionEnum.SET, "resourceKeyA", "resourceValueA");
+        final var configRuleB =
+                new ConfigRule(ConfigActionEnum.DELETE, "resourceKeyB", "resourceValueB");
+        final var deviceConfig = new DeviceConfig(List.of(configRuleA, configRuleB));
+        final var serializedDeviceConfig = serializer.serialize(deviceConfig);
+
+        assertThat(serializedDeviceConfig).usingRecursiveComparison().isEqualTo(expectedDeviceConfig);
+    }
+
+    @Test
+    void shouldDeserializeDeviceConfig() {
+        final var expectedConfigRuleA =
+                new ConfigRule(ConfigActionEnum.SET, "resourceKeyA", "resourceValueA");
+        final var expectedConfigRuleB =
+                new ConfigRule(ConfigActionEnum.DELETE, "resourceKeyB", "resourceValueB");
+        final var expectedDeviceConfig =
+                new DeviceConfig(List.of(expectedConfigRuleA, expectedConfigRuleB));
+
+        final var configRuleA =
+                ContextOuterClass.ConfigRule.newBuilder()
+                        .setAction(ContextOuterClass.ConfigActionEnum.CONFIGACTION_SET)
+                        .setResourceKey("resourceKeyA")
+                        .setResourceValue("resourceValueA")
+                        .build();
+        final var configRuleB =
+                ContextOuterClass.ConfigRule.newBuilder()
+                        .setAction(ContextOuterClass.ConfigActionEnum.CONFIGACTION_DELETE)
+                        .setResourceKey("resourceKeyB")
+                        .setResourceValue("resourceValueB")
+                        .build();
+        final var serializedDeviceConfig =
+                ContextOuterClass.DeviceConfig.newBuilder()
+                        .addAllConfigRules(List.of(configRuleA, configRuleB))
+                        .build();
+        final var deviceConfig = serializer.deserialize(serializedDeviceConfig);
+
+        assertThat(deviceConfig).usingRecursiveComparison().isEqualTo(expectedDeviceConfig);
+    }
+
+    private static Stream<Arguments> provideOperationalStatusEnum() {
+        return Stream.of(
+                Arguments.of(
+                        DeviceOperationalStatus.ENABLED,
+                        DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_ENABLED),
+                Arguments.of(
+                        DeviceOperationalStatus.DISABLED,
+                        DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_DISABLED),
+                Arguments.of(
+                        DeviceOperationalStatus.UNDEFINED,
+                        DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_UNDEFINED));
+    }
+
+    @ParameterizedTest
+    @MethodSource("provideOperationalStatusEnum")
+    void shouldSerializeOperationalStatusEnum(
+            DeviceOperationalStatus opStatus,
+            ContextOuterClass.DeviceOperationalStatusEnum expectedOpStatus) {
+        final var serializedOpStatus = serializer.serialize(opStatus);
+        assertThat(serializedOpStatus.getNumber()).isEqualTo(expectedOpStatus.getNumber());
+    }
+
+    @ParameterizedTest
+    @MethodSource("provideOperationalStatusEnum")
+    void shouldDeserializeOperationalStatusEnum(
+            DeviceOperationalStatus expectedOpStatus,
+            ContextOuterClass.DeviceOperationalStatusEnum serializedOpStatus) {
+        final var operationalStatus = serializer.deserialize(serializedOpStatus);
+        assertThat(operationalStatus).isEqualTo(expectedOpStatus);
+    }
+
+    @Test
+    void shouldSerializeDevice() {
+        final var expectedConfigRule =
+                ContextOuterClass.ConfigRule.newBuilder()
+                        .setAction(ContextOuterClass.ConfigActionEnum.CONFIGACTION_SET)
+                        .setResourceKey("resourceKey")
+                        .setResourceValue("resourceValue")
+                        .build();
+        final var expectedDeviceConfig =
+                ContextOuterClass.DeviceConfig.newBuilder().addConfigRules(expectedConfigRule).build();
+        final var deviceBuilder = ContextOuterClass.Device.newBuilder();
+        deviceBuilder.setDeviceId(serializer.serializeDeviceId("deviceId"));
+        deviceBuilder.setDeviceType("deviceType");
+        deviceBuilder.setDeviceConfig(expectedDeviceConfig);
+        deviceBuilder.setDeviceOperationalStatus(serializer.serialize(DeviceOperationalStatus.ENABLED));
+        final var expectedDevice = deviceBuilder.build();
+
+        final var deviceConfig =
+                new DeviceConfig(
+                        List.of(new ConfigRule(ConfigActionEnum.SET, "resourceKey", "resourceValue")));
+        final var device =
+                new Device("deviceId", "deviceType", deviceConfig, DeviceOperationalStatus.ENABLED);
+        final var serializedDevice = serializer.serialize(device);
+
+        assertThat(serializedDevice).usingRecursiveComparison().isEqualTo(expectedDevice);
+    }
+
+    @Test
+    void shouldDeserializeDevice() {
+        final var expectedConfig =
+                new DeviceConfig(
+                        List.of(new ConfigRule(ConfigActionEnum.DELETE, "resourceKey", "resourceValue")));
+        final var expectedDevice =
+                new Device("deviceId", "deviceType", expectedConfig, DeviceOperationalStatus.ENABLED);
+
+        final var configRule =
+                ContextOuterClass.ConfigRule.newBuilder()
+                        .setAction(ContextOuterClass.ConfigActionEnum.CONFIGACTION_DELETE)
+                        .setResourceKey("resourceKey")
+                        .setResourceValue("resourceValue")
+                        .build();
+        final var deviceConfig =
+                ContextOuterClass.DeviceConfig.newBuilder().addConfigRules(configRule).build();
+        final var deviceBuilder = ContextOuterClass.Device.newBuilder();
+        deviceBuilder.setDeviceId(serializer.serializeDeviceId("deviceId"));
+        deviceBuilder.setDeviceType("deviceType");
+        deviceBuilder.setDeviceConfig(deviceConfig);
+        deviceBuilder.setDeviceOperationalStatus(serializer.serialize(DeviceOperationalStatus.ENABLED));
+        final var serializedDevice = deviceBuilder.build();
+        final var device = serializer.deserialize(serializedDevice);
+
+        assertThat(device).usingRecursiveComparison().isEqualTo(expectedDevice);
+    }
+
+    @Test
+    void shouldSerializeUuid() {
+        final var expectedUuid = "uuid";
+
+        final var serializeUuid = serializer.serializeUuid("uuid");
+
+        assertThat(serializeUuid.getUuid()).isEqualTo(expectedUuid);
+    }
+
+    @Test
+    void shouldDeserializeUuid() {
+        final var expectedUuid = "uuid";
+
+        final var uuid = serializer.deserialize(Uuid.newBuilder().setUuid("uuid").build());
+
+        assertThat(uuid).isEqualTo(expectedUuid);
+    }
+}
diff --git a/src/automation/target/generated-sources/grpc/context/ContextOuterClass.java b/src/automation/target/generated-sources/grpc/context/ContextOuterClass.java
index 3decce929..168ddf78b 100644
--- a/src/automation/target/generated-sources/grpc/context/ContextOuterClass.java
+++ b/src/automation/target/generated-sources/grpc/context/ContextOuterClass.java
@@ -27653,79 +27653,49 @@ public final class ContextOuterClass {
 
   }
 
-  public interface EndPointIdOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:context.EndPointId)
+  public interface ConnectionIdOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:context.ConnectionId)
       com.google.protobuf.MessageOrBuilder {
 
     /**
-     * <code>.context.TopologyId topology_id = 1;</code>
-     * @return Whether the topologyId field is set.
-     */
-    boolean hasTopologyId();
-    /**
-     * <code>.context.TopologyId topology_id = 1;</code>
-     * @return The topologyId.
-     */
-    context.ContextOuterClass.TopologyId getTopologyId();
-    /**
-     * <code>.context.TopologyId topology_id = 1;</code>
-     */
-    context.ContextOuterClass.TopologyIdOrBuilder getTopologyIdOrBuilder();
-
-    /**
-     * <code>.context.DeviceId device_id = 2;</code>
-     * @return Whether the deviceId field is set.
-     */
-    boolean hasDeviceId();
-    /**
-     * <code>.context.DeviceId device_id = 2;</code>
-     * @return The deviceId.
-     */
-    context.ContextOuterClass.DeviceId getDeviceId();
-    /**
-     * <code>.context.DeviceId device_id = 2;</code>
-     */
-    context.ContextOuterClass.DeviceIdOrBuilder getDeviceIdOrBuilder();
-
-    /**
-     * <code>.context.Uuid endpoint_uuid = 3;</code>
-     * @return Whether the endpointUuid field is set.
+     * <code>.context.Uuid connection_uuid = 1;</code>
+     * @return Whether the connectionUuid field is set.
      */
-    boolean hasEndpointUuid();
+    boolean hasConnectionUuid();
     /**
-     * <code>.context.Uuid endpoint_uuid = 3;</code>
-     * @return The endpointUuid.
+     * <code>.context.Uuid connection_uuid = 1;</code>
+     * @return The connectionUuid.
      */
-    context.ContextOuterClass.Uuid getEndpointUuid();
+    context.ContextOuterClass.Uuid getConnectionUuid();
     /**
-     * <code>.context.Uuid endpoint_uuid = 3;</code>
+     * <code>.context.Uuid connection_uuid = 1;</code>
      */
-    context.ContextOuterClass.UuidOrBuilder getEndpointUuidOrBuilder();
+    context.ContextOuterClass.UuidOrBuilder getConnectionUuidOrBuilder();
   }
   /**
    * <pre>
-   * ----- Endpoint ------------------------------------------------------------------------------------------------------
+   * ----- Connection ----------------------------------------------------------------------------------------------------
    * </pre>
    *
-   * Protobuf type {@code context.EndPointId}
+   * Protobuf type {@code context.ConnectionId}
    */
-  public static final class EndPointId extends
+  public static final class ConnectionId extends
       com.google.protobuf.GeneratedMessageV3 implements
-      // @@protoc_insertion_point(message_implements:context.EndPointId)
-      EndPointIdOrBuilder {
+      // @@protoc_insertion_point(message_implements:context.ConnectionId)
+      ConnectionIdOrBuilder {
   private static final long serialVersionUID = 0L;
-    // Use EndPointId.newBuilder() to construct.
-    private EndPointId(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
+    // Use ConnectionId.newBuilder() to construct.
+    private ConnectionId(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
       super(builder);
     }
-    private EndPointId() {
+    private ConnectionId() {
     }
 
     @java.lang.Override
     @SuppressWarnings({"unused"})
     protected java.lang.Object newInstance(
         UnusedPrivateParameter unused) {
-      return new EndPointId();
+      return new ConnectionId();
     }
 
     @java.lang.Override
@@ -27733,7 +27703,7 @@ public final class ContextOuterClass {
     getUnknownFields() {
       return this.unknownFields;
     }
-    private EndPointId(
+    private ConnectionId(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
@@ -27752,40 +27722,14 @@ public final class ContextOuterClass {
               done = true;
               break;
             case 10: {
-              context.ContextOuterClass.TopologyId.Builder subBuilder = null;
-              if (topologyId_ != null) {
-                subBuilder = topologyId_.toBuilder();
-              }
-              topologyId_ = input.readMessage(context.ContextOuterClass.TopologyId.parser(), extensionRegistry);
-              if (subBuilder != null) {
-                subBuilder.mergeFrom(topologyId_);
-                topologyId_ = subBuilder.buildPartial();
-              }
-
-              break;
-            }
-            case 18: {
-              context.ContextOuterClass.DeviceId.Builder subBuilder = null;
-              if (deviceId_ != null) {
-                subBuilder = deviceId_.toBuilder();
-              }
-              deviceId_ = input.readMessage(context.ContextOuterClass.DeviceId.parser(), extensionRegistry);
-              if (subBuilder != null) {
-                subBuilder.mergeFrom(deviceId_);
-                deviceId_ = subBuilder.buildPartial();
-              }
-
-              break;
-            }
-            case 26: {
               context.ContextOuterClass.Uuid.Builder subBuilder = null;
-              if (endpointUuid_ != null) {
-                subBuilder = endpointUuid_.toBuilder();
+              if (connectionUuid_ != null) {
+                subBuilder = connectionUuid_.toBuilder();
               }
-              endpointUuid_ = input.readMessage(context.ContextOuterClass.Uuid.parser(), extensionRegistry);
+              connectionUuid_ = input.readMessage(context.ContextOuterClass.Uuid.parser(), extensionRegistry);
               if (subBuilder != null) {
-                subBuilder.mergeFrom(endpointUuid_);
-                endpointUuid_ = subBuilder.buildPartial();
+                subBuilder.mergeFrom(connectionUuid_);
+                connectionUuid_ = subBuilder.buildPartial();
               }
 
               break;
@@ -27811,93 +27755,41 @@ public final class ContextOuterClass {
     }
     public static final com.google.protobuf.Descriptors.Descriptor
         getDescriptor() {
-      return context.ContextOuterClass.internal_static_context_EndPointId_descriptor;
+      return context.ContextOuterClass.internal_static_context_ConnectionId_descriptor;
     }
 
     @java.lang.Override
     protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
         internalGetFieldAccessorTable() {
-      return context.ContextOuterClass.internal_static_context_EndPointId_fieldAccessorTable
+      return context.ContextOuterClass.internal_static_context_ConnectionId_fieldAccessorTable
           .ensureFieldAccessorsInitialized(
-              context.ContextOuterClass.EndPointId.class, context.ContextOuterClass.EndPointId.Builder.class);
-    }
-
-    public static final int TOPOLOGY_ID_FIELD_NUMBER = 1;
-    private context.ContextOuterClass.TopologyId topologyId_;
-    /**
-     * <code>.context.TopologyId topology_id = 1;</code>
-     * @return Whether the topologyId field is set.
-     */
-    @java.lang.Override
-    public boolean hasTopologyId() {
-      return topologyId_ != null;
-    }
-    /**
-     * <code>.context.TopologyId topology_id = 1;</code>
-     * @return The topologyId.
-     */
-    @java.lang.Override
-    public context.ContextOuterClass.TopologyId getTopologyId() {
-      return topologyId_ == null ? context.ContextOuterClass.TopologyId.getDefaultInstance() : topologyId_;
-    }
-    /**
-     * <code>.context.TopologyId topology_id = 1;</code>
-     */
-    @java.lang.Override
-    public context.ContextOuterClass.TopologyIdOrBuilder getTopologyIdOrBuilder() {
-      return getTopologyId();
-    }
-
-    public static final int DEVICE_ID_FIELD_NUMBER = 2;
-    private context.ContextOuterClass.DeviceId deviceId_;
-    /**
-     * <code>.context.DeviceId device_id = 2;</code>
-     * @return Whether the deviceId field is set.
-     */
-    @java.lang.Override
-    public boolean hasDeviceId() {
-      return deviceId_ != null;
-    }
-    /**
-     * <code>.context.DeviceId device_id = 2;</code>
-     * @return The deviceId.
-     */
-    @java.lang.Override
-    public context.ContextOuterClass.DeviceId getDeviceId() {
-      return deviceId_ == null ? context.ContextOuterClass.DeviceId.getDefaultInstance() : deviceId_;
-    }
-    /**
-     * <code>.context.DeviceId device_id = 2;</code>
-     */
-    @java.lang.Override
-    public context.ContextOuterClass.DeviceIdOrBuilder getDeviceIdOrBuilder() {
-      return getDeviceId();
+              context.ContextOuterClass.ConnectionId.class, context.ContextOuterClass.ConnectionId.Builder.class);
     }
 
-    public static final int ENDPOINT_UUID_FIELD_NUMBER = 3;
-    private context.ContextOuterClass.Uuid endpointUuid_;
+    public static final int CONNECTION_UUID_FIELD_NUMBER = 1;
+    private context.ContextOuterClass.Uuid connectionUuid_;
     /**
-     * <code>.context.Uuid endpoint_uuid = 3;</code>
-     * @return Whether the endpointUuid field is set.
+     * <code>.context.Uuid connection_uuid = 1;</code>
+     * @return Whether the connectionUuid field is set.
      */
     @java.lang.Override
-    public boolean hasEndpointUuid() {
-      return endpointUuid_ != null;
+    public boolean hasConnectionUuid() {
+      return connectionUuid_ != null;
     }
     /**
-     * <code>.context.Uuid endpoint_uuid = 3;</code>
-     * @return The endpointUuid.
+     * <code>.context.Uuid connection_uuid = 1;</code>
+     * @return The connectionUuid.
      */
     @java.lang.Override
-    public context.ContextOuterClass.Uuid getEndpointUuid() {
-      return endpointUuid_ == null ? context.ContextOuterClass.Uuid.getDefaultInstance() : endpointUuid_;
+    public context.ContextOuterClass.Uuid getConnectionUuid() {
+      return connectionUuid_ == null ? context.ContextOuterClass.Uuid.getDefaultInstance() : connectionUuid_;
     }
     /**
-     * <code>.context.Uuid endpoint_uuid = 3;</code>
+     * <code>.context.Uuid connection_uuid = 1;</code>
      */
     @java.lang.Override
-    public context.ContextOuterClass.UuidOrBuilder getEndpointUuidOrBuilder() {
-      return getEndpointUuid();
+    public context.ContextOuterClass.UuidOrBuilder getConnectionUuidOrBuilder() {
+      return getConnectionUuid();
     }
 
     private byte memoizedIsInitialized = -1;
@@ -27914,14 +27806,8 @@ public final class ContextOuterClass {
     @java.lang.Override
     public void writeTo(com.google.protobuf.CodedOutputStream output)
                         throws java.io.IOException {
-      if (topologyId_ != null) {
-        output.writeMessage(1, getTopologyId());
-      }
-      if (deviceId_ != null) {
-        output.writeMessage(2, getDeviceId());
-      }
-      if (endpointUuid_ != null) {
-        output.writeMessage(3, getEndpointUuid());
+      if (connectionUuid_ != null) {
+        output.writeMessage(1, getConnectionUuid());
       }
       unknownFields.writeTo(output);
     }
@@ -27932,17 +27818,9 @@ public final class ContextOuterClass {
       if (size != -1) return size;
 
       size = 0;
-      if (topologyId_ != null) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(1, getTopologyId());
-      }
-      if (deviceId_ != null) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(2, getDeviceId());
-      }
-      if (endpointUuid_ != null) {
+      if (connectionUuid_ != null) {
         size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(3, getEndpointUuid());
+          .computeMessageSize(1, getConnectionUuid());
       }
       size += unknownFields.getSerializedSize();
       memoizedSize = size;
@@ -27954,25 +27832,15 @@ public final class ContextOuterClass {
       if (obj == this) {
        return true;
       }
-      if (!(obj instanceof context.ContextOuterClass.EndPointId)) {
+      if (!(obj instanceof context.ContextOuterClass.ConnectionId)) {
         return super.equals(obj);
       }
-      context.ContextOuterClass.EndPointId other = (context.ContextOuterClass.EndPointId) obj;
+      context.ContextOuterClass.ConnectionId other = (context.ContextOuterClass.ConnectionId) obj;
 
-      if (hasTopologyId() != other.hasTopologyId()) return false;
-      if (hasTopologyId()) {
-        if (!getTopologyId()
-            .equals(other.getTopologyId())) return false;
-      }
-      if (hasDeviceId() != other.hasDeviceId()) return false;
-      if (hasDeviceId()) {
-        if (!getDeviceId()
-            .equals(other.getDeviceId())) return false;
-      }
-      if (hasEndpointUuid() != other.hasEndpointUuid()) return false;
-      if (hasEndpointUuid()) {
-        if (!getEndpointUuid()
-            .equals(other.getEndpointUuid())) return false;
+      if (hasConnectionUuid() != other.hasConnectionUuid()) return false;
+      if (hasConnectionUuid()) {
+        if (!getConnectionUuid()
+            .equals(other.getConnectionUuid())) return false;
       }
       if (!unknownFields.equals(other.unknownFields)) return false;
       return true;
@@ -27985,86 +27853,78 @@ public final class ContextOuterClass {
       }
       int hash = 41;
       hash = (19 * hash) + getDescriptor().hashCode();
-      if (hasTopologyId()) {
-        hash = (37 * hash) + TOPOLOGY_ID_FIELD_NUMBER;
-        hash = (53 * hash) + getTopologyId().hashCode();
-      }
-      if (hasDeviceId()) {
-        hash = (37 * hash) + DEVICE_ID_FIELD_NUMBER;
-        hash = (53 * hash) + getDeviceId().hashCode();
-      }
-      if (hasEndpointUuid()) {
-        hash = (37 * hash) + ENDPOINT_UUID_FIELD_NUMBER;
-        hash = (53 * hash) + getEndpointUuid().hashCode();
+      if (hasConnectionUuid()) {
+        hash = (37 * hash) + CONNECTION_UUID_FIELD_NUMBER;
+        hash = (53 * hash) + getConnectionUuid().hashCode();
       }
       hash = (29 * hash) + unknownFields.hashCode();
       memoizedHashCode = hash;
       return hash;
     }
 
-    public static context.ContextOuterClass.EndPointId parseFrom(
+    public static context.ContextOuterClass.ConnectionId parseFrom(
         java.nio.ByteBuffer data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static context.ContextOuterClass.EndPointId parseFrom(
+    public static context.ContextOuterClass.ConnectionId parseFrom(
         java.nio.ByteBuffer data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static context.ContextOuterClass.EndPointId parseFrom(
+    public static context.ContextOuterClass.ConnectionId parseFrom(
         com.google.protobuf.ByteString data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static context.ContextOuterClass.EndPointId parseFrom(
+    public static context.ContextOuterClass.ConnectionId parseFrom(
         com.google.protobuf.ByteString data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static context.ContextOuterClass.EndPointId parseFrom(byte[] data)
+    public static context.ContextOuterClass.ConnectionId parseFrom(byte[] data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static context.ContextOuterClass.EndPointId parseFrom(
+    public static context.ContextOuterClass.ConnectionId parseFrom(
         byte[] data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static context.ContextOuterClass.EndPointId parseFrom(java.io.InputStream input)
+    public static context.ContextOuterClass.ConnectionId parseFrom(java.io.InputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseWithIOException(PARSER, input);
     }
-    public static context.ContextOuterClass.EndPointId parseFrom(
+    public static context.ContextOuterClass.ConnectionId parseFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseWithIOException(PARSER, input, extensionRegistry);
     }
-    public static context.ContextOuterClass.EndPointId parseDelimitedFrom(java.io.InputStream input)
+    public static context.ContextOuterClass.ConnectionId parseDelimitedFrom(java.io.InputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseDelimitedWithIOException(PARSER, input);
     }
-    public static context.ContextOuterClass.EndPointId parseDelimitedFrom(
+    public static context.ContextOuterClass.ConnectionId parseDelimitedFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
     }
-    public static context.ContextOuterClass.EndPointId parseFrom(
+    public static context.ContextOuterClass.ConnectionId parseFrom(
         com.google.protobuf.CodedInputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseWithIOException(PARSER, input);
     }
-    public static context.ContextOuterClass.EndPointId parseFrom(
+    public static context.ContextOuterClass.ConnectionId parseFrom(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -28077,7 +27937,7 @@ public final class ContextOuterClass {
     public static Builder newBuilder() {
       return DEFAULT_INSTANCE.toBuilder();
     }
-    public static Builder newBuilder(context.ContextOuterClass.EndPointId prototype) {
+    public static Builder newBuilder(context.ContextOuterClass.ConnectionId prototype) {
       return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
     }
     @java.lang.Override
@@ -28094,29 +27954,29 @@ public final class ContextOuterClass {
     }
     /**
      * <pre>
-     * ----- Endpoint ------------------------------------------------------------------------------------------------------
+     * ----- Connection ----------------------------------------------------------------------------------------------------
      * </pre>
      *
-     * Protobuf type {@code context.EndPointId}
+     * Protobuf type {@code context.ConnectionId}
      */
     public static final class Builder extends
         com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:context.EndPointId)
-        context.ContextOuterClass.EndPointIdOrBuilder {
+        // @@protoc_insertion_point(builder_implements:context.ConnectionId)
+        context.ContextOuterClass.ConnectionIdOrBuilder {
       public static final com.google.protobuf.Descriptors.Descriptor
           getDescriptor() {
-        return context.ContextOuterClass.internal_static_context_EndPointId_descriptor;
+        return context.ContextOuterClass.internal_static_context_ConnectionId_descriptor;
       }
 
       @java.lang.Override
       protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
           internalGetFieldAccessorTable() {
-        return context.ContextOuterClass.internal_static_context_EndPointId_fieldAccessorTable
+        return context.ContextOuterClass.internal_static_context_ConnectionId_fieldAccessorTable
             .ensureFieldAccessorsInitialized(
-                context.ContextOuterClass.EndPointId.class, context.ContextOuterClass.EndPointId.Builder.class);
+                context.ContextOuterClass.ConnectionId.class, context.ContextOuterClass.ConnectionId.Builder.class);
       }
 
-      // Construct using context.ContextOuterClass.EndPointId.newBuilder()
+      // Construct using context.ContextOuterClass.ConnectionId.newBuilder()
       private Builder() {
         maybeForceBuilderInitialization();
       }
@@ -28134,23 +27994,11 @@ public final class ContextOuterClass {
       @java.lang.Override
       public Builder clear() {
         super.clear();
-        if (topologyIdBuilder_ == null) {
-          topologyId_ = null;
-        } else {
-          topologyId_ = null;
-          topologyIdBuilder_ = null;
-        }
-        if (deviceIdBuilder_ == null) {
-          deviceId_ = null;
-        } else {
-          deviceId_ = null;
-          deviceIdBuilder_ = null;
-        }
-        if (endpointUuidBuilder_ == null) {
-          endpointUuid_ = null;
+        if (connectionUuidBuilder_ == null) {
+          connectionUuid_ = null;
         } else {
-          endpointUuid_ = null;
-          endpointUuidBuilder_ = null;
+          connectionUuid_ = null;
+          connectionUuidBuilder_ = null;
         }
         return this;
       }
@@ -28158,17 +28006,17 @@ public final class ContextOuterClass {
       @java.lang.Override
       public com.google.protobuf.Descriptors.Descriptor
           getDescriptorForType() {
-        return context.ContextOuterClass.internal_static_context_EndPointId_descriptor;
+        return context.ContextOuterClass.internal_static_context_ConnectionId_descriptor;
       }
 
       @java.lang.Override
-      public context.ContextOuterClass.EndPointId getDefaultInstanceForType() {
-        return context.ContextOuterClass.EndPointId.getDefaultInstance();
+      public context.ContextOuterClass.ConnectionId getDefaultInstanceForType() {
+        return context.ContextOuterClass.ConnectionId.getDefaultInstance();
       }
 
       @java.lang.Override
-      public context.ContextOuterClass.EndPointId build() {
-        context.ContextOuterClass.EndPointId result = buildPartial();
+      public context.ContextOuterClass.ConnectionId build() {
+        context.ContextOuterClass.ConnectionId result = buildPartial();
         if (!result.isInitialized()) {
           throw newUninitializedMessageException(result);
         }
@@ -28176,22 +28024,12 @@ public final class ContextOuterClass {
       }
 
       @java.lang.Override
-      public context.ContextOuterClass.EndPointId buildPartial() {
-        context.ContextOuterClass.EndPointId result = new context.ContextOuterClass.EndPointId(this);
-        if (topologyIdBuilder_ == null) {
-          result.topologyId_ = topologyId_;
-        } else {
-          result.topologyId_ = topologyIdBuilder_.build();
-        }
-        if (deviceIdBuilder_ == null) {
-          result.deviceId_ = deviceId_;
-        } else {
-          result.deviceId_ = deviceIdBuilder_.build();
-        }
-        if (endpointUuidBuilder_ == null) {
-          result.endpointUuid_ = endpointUuid_;
+      public context.ContextOuterClass.ConnectionId buildPartial() {
+        context.ContextOuterClass.ConnectionId result = new context.ContextOuterClass.ConnectionId(this);
+        if (connectionUuidBuilder_ == null) {
+          result.connectionUuid_ = connectionUuid_;
         } else {
-          result.endpointUuid_ = endpointUuidBuilder_.build();
+          result.connectionUuid_ = connectionUuidBuilder_.build();
         }
         onBuilt();
         return result;
@@ -28231,24 +28069,18 @@ public final class ContextOuterClass {
       }
       @java.lang.Override
       public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof context.ContextOuterClass.EndPointId) {
-          return mergeFrom((context.ContextOuterClass.EndPointId)other);
+        if (other instanceof context.ContextOuterClass.ConnectionId) {
+          return mergeFrom((context.ContextOuterClass.ConnectionId)other);
         } else {
           super.mergeFrom(other);
           return this;
         }
       }
 
-      public Builder mergeFrom(context.ContextOuterClass.EndPointId other) {
-        if (other == context.ContextOuterClass.EndPointId.getDefaultInstance()) return this;
-        if (other.hasTopologyId()) {
-          mergeTopologyId(other.getTopologyId());
-        }
-        if (other.hasDeviceId()) {
-          mergeDeviceId(other.getDeviceId());
-        }
-        if (other.hasEndpointUuid()) {
-          mergeEndpointUuid(other.getEndpointUuid());
+      public Builder mergeFrom(context.ContextOuterClass.ConnectionId other) {
+        if (other == context.ContextOuterClass.ConnectionId.getDefaultInstance()) return this;
+        if (other.hasConnectionUuid()) {
+          mergeConnectionUuid(other.getConnectionUuid());
         }
         this.mergeUnknownFields(other.unknownFields);
         onChanged();
@@ -28265,11 +28097,11 @@ public final class ContextOuterClass {
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws java.io.IOException {
-        context.ContextOuterClass.EndPointId parsedMessage = null;
+        context.ContextOuterClass.ConnectionId parsedMessage = null;
         try {
           parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
         } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          parsedMessage = (context.ContextOuterClass.EndPointId) e.getUnfinishedMessage();
+          parsedMessage = (context.ContextOuterClass.ConnectionId) e.getUnfinishedMessage();
           throw e.unwrapIOException();
         } finally {
           if (parsedMessage != null) {
@@ -28279,361 +28111,1694 @@ public final class ContextOuterClass {
         return this;
       }
 
-      private context.ContextOuterClass.TopologyId topologyId_;
+      private context.ContextOuterClass.Uuid connectionUuid_;
       private com.google.protobuf.SingleFieldBuilderV3<
-          context.ContextOuterClass.TopologyId, context.ContextOuterClass.TopologyId.Builder, context.ContextOuterClass.TopologyIdOrBuilder> topologyIdBuilder_;
+          context.ContextOuterClass.Uuid, context.ContextOuterClass.Uuid.Builder, context.ContextOuterClass.UuidOrBuilder> connectionUuidBuilder_;
       /**
-       * <code>.context.TopologyId topology_id = 1;</code>
-       * @return Whether the topologyId field is set.
+       * <code>.context.Uuid connection_uuid = 1;</code>
+       * @return Whether the connectionUuid field is set.
        */
-      public boolean hasTopologyId() {
-        return topologyIdBuilder_ != null || topologyId_ != null;
+      public boolean hasConnectionUuid() {
+        return connectionUuidBuilder_ != null || connectionUuid_ != null;
       }
       /**
-       * <code>.context.TopologyId topology_id = 1;</code>
-       * @return The topologyId.
+       * <code>.context.Uuid connection_uuid = 1;</code>
+       * @return The connectionUuid.
        */
-      public context.ContextOuterClass.TopologyId getTopologyId() {
-        if (topologyIdBuilder_ == null) {
-          return topologyId_ == null ? context.ContextOuterClass.TopologyId.getDefaultInstance() : topologyId_;
+      public context.ContextOuterClass.Uuid getConnectionUuid() {
+        if (connectionUuidBuilder_ == null) {
+          return connectionUuid_ == null ? context.ContextOuterClass.Uuid.getDefaultInstance() : connectionUuid_;
         } else {
-          return topologyIdBuilder_.getMessage();
+          return connectionUuidBuilder_.getMessage();
         }
       }
       /**
-       * <code>.context.TopologyId topology_id = 1;</code>
+       * <code>.context.Uuid connection_uuid = 1;</code>
        */
-      public Builder setTopologyId(context.ContextOuterClass.TopologyId value) {
-        if (topologyIdBuilder_ == null) {
+      public Builder setConnectionUuid(context.ContextOuterClass.Uuid value) {
+        if (connectionUuidBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
           }
-          topologyId_ = value;
+          connectionUuid_ = value;
           onChanged();
         } else {
-          topologyIdBuilder_.setMessage(value);
+          connectionUuidBuilder_.setMessage(value);
         }
 
         return this;
       }
       /**
-       * <code>.context.TopologyId topology_id = 1;</code>
+       * <code>.context.Uuid connection_uuid = 1;</code>
        */
-      public Builder setTopologyId(
-          context.ContextOuterClass.TopologyId.Builder builderForValue) {
-        if (topologyIdBuilder_ == null) {
-          topologyId_ = builderForValue.build();
+      public Builder setConnectionUuid(
+          context.ContextOuterClass.Uuid.Builder builderForValue) {
+        if (connectionUuidBuilder_ == null) {
+          connectionUuid_ = builderForValue.build();
           onChanged();
         } else {
-          topologyIdBuilder_.setMessage(builderForValue.build());
+          connectionUuidBuilder_.setMessage(builderForValue.build());
         }
 
         return this;
       }
       /**
-       * <code>.context.TopologyId topology_id = 1;</code>
+       * <code>.context.Uuid connection_uuid = 1;</code>
        */
-      public Builder mergeTopologyId(context.ContextOuterClass.TopologyId value) {
-        if (topologyIdBuilder_ == null) {
-          if (topologyId_ != null) {
-            topologyId_ =
-              context.ContextOuterClass.TopologyId.newBuilder(topologyId_).mergeFrom(value).buildPartial();
+      public Builder mergeConnectionUuid(context.ContextOuterClass.Uuid value) {
+        if (connectionUuidBuilder_ == null) {
+          if (connectionUuid_ != null) {
+            connectionUuid_ =
+              context.ContextOuterClass.Uuid.newBuilder(connectionUuid_).mergeFrom(value).buildPartial();
           } else {
-            topologyId_ = value;
+            connectionUuid_ = value;
           }
           onChanged();
         } else {
-          topologyIdBuilder_.mergeFrom(value);
+          connectionUuidBuilder_.mergeFrom(value);
         }
 
         return this;
       }
       /**
-       * <code>.context.TopologyId topology_id = 1;</code>
+       * <code>.context.Uuid connection_uuid = 1;</code>
        */
-      public Builder clearTopologyId() {
-        if (topologyIdBuilder_ == null) {
-          topologyId_ = null;
+      public Builder clearConnectionUuid() {
+        if (connectionUuidBuilder_ == null) {
+          connectionUuid_ = null;
           onChanged();
         } else {
-          topologyId_ = null;
-          topologyIdBuilder_ = null;
+          connectionUuid_ = null;
+          connectionUuidBuilder_ = null;
         }
 
         return this;
       }
       /**
-       * <code>.context.TopologyId topology_id = 1;</code>
+       * <code>.context.Uuid connection_uuid = 1;</code>
        */
-      public context.ContextOuterClass.TopologyId.Builder getTopologyIdBuilder() {
+      public context.ContextOuterClass.Uuid.Builder getConnectionUuidBuilder() {
         
         onChanged();
-        return getTopologyIdFieldBuilder().getBuilder();
+        return getConnectionUuidFieldBuilder().getBuilder();
       }
       /**
-       * <code>.context.TopologyId topology_id = 1;</code>
+       * <code>.context.Uuid connection_uuid = 1;</code>
        */
-      public context.ContextOuterClass.TopologyIdOrBuilder getTopologyIdOrBuilder() {
-        if (topologyIdBuilder_ != null) {
-          return topologyIdBuilder_.getMessageOrBuilder();
+      public context.ContextOuterClass.UuidOrBuilder getConnectionUuidOrBuilder() {
+        if (connectionUuidBuilder_ != null) {
+          return connectionUuidBuilder_.getMessageOrBuilder();
         } else {
-          return topologyId_ == null ?
-              context.ContextOuterClass.TopologyId.getDefaultInstance() : topologyId_;
+          return connectionUuid_ == null ?
+              context.ContextOuterClass.Uuid.getDefaultInstance() : connectionUuid_;
         }
       }
       /**
-       * <code>.context.TopologyId topology_id = 1;</code>
+       * <code>.context.Uuid connection_uuid = 1;</code>
        */
       private com.google.protobuf.SingleFieldBuilderV3<
-          context.ContextOuterClass.TopologyId, context.ContextOuterClass.TopologyId.Builder, context.ContextOuterClass.TopologyIdOrBuilder> 
-          getTopologyIdFieldBuilder() {
-        if (topologyIdBuilder_ == null) {
-          topologyIdBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              context.ContextOuterClass.TopologyId, context.ContextOuterClass.TopologyId.Builder, context.ContextOuterClass.TopologyIdOrBuilder>(
-                  getTopologyId(),
+          context.ContextOuterClass.Uuid, context.ContextOuterClass.Uuid.Builder, context.ContextOuterClass.UuidOrBuilder> 
+          getConnectionUuidFieldBuilder() {
+        if (connectionUuidBuilder_ == null) {
+          connectionUuidBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
+              context.ContextOuterClass.Uuid, context.ContextOuterClass.Uuid.Builder, context.ContextOuterClass.UuidOrBuilder>(
+                  getConnectionUuid(),
                   getParentForChildren(),
                   isClean());
-          topologyId_ = null;
+          connectionUuid_ = null;
         }
-        return topologyIdBuilder_;
-      }
-
-      private context.ContextOuterClass.DeviceId deviceId_;
-      private com.google.protobuf.SingleFieldBuilderV3<
-          context.ContextOuterClass.DeviceId, context.ContextOuterClass.DeviceId.Builder, context.ContextOuterClass.DeviceIdOrBuilder> deviceIdBuilder_;
-      /**
-       * <code>.context.DeviceId device_id = 2;</code>
-       * @return Whether the deviceId field is set.
-       */
-      public boolean hasDeviceId() {
-        return deviceIdBuilder_ != null || deviceId_ != null;
+        return connectionUuidBuilder_;
       }
-      /**
-       * <code>.context.DeviceId device_id = 2;</code>
-       * @return The deviceId.
-       */
-      public context.ContextOuterClass.DeviceId getDeviceId() {
-        if (deviceIdBuilder_ == null) {
-          return deviceId_ == null ? context.ContextOuterClass.DeviceId.getDefaultInstance() : deviceId_;
-        } else {
-          return deviceIdBuilder_.getMessage();
-        }
+      @java.lang.Override
+      public final Builder setUnknownFields(
+          final com.google.protobuf.UnknownFieldSet unknownFields) {
+        return super.setUnknownFields(unknownFields);
       }
-      /**
-       * <code>.context.DeviceId device_id = 2;</code>
-       */
-      public Builder setDeviceId(context.ContextOuterClass.DeviceId value) {
-        if (deviceIdBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          deviceId_ = value;
-          onChanged();
-        } else {
-          deviceIdBuilder_.setMessage(value);
-        }
 
-        return this;
-      }
+      @java.lang.Override
+      public final Builder mergeUnknownFields(
+          final com.google.protobuf.UnknownFieldSet unknownFields) {
+        return super.mergeUnknownFields(unknownFields);
+      }
+
+
+      // @@protoc_insertion_point(builder_scope:context.ConnectionId)
+    }
+
+    // @@protoc_insertion_point(class_scope:context.ConnectionId)
+    private static final context.ContextOuterClass.ConnectionId DEFAULT_INSTANCE;
+    static {
+      DEFAULT_INSTANCE = new context.ContextOuterClass.ConnectionId();
+    }
+
+    public static context.ContextOuterClass.ConnectionId getDefaultInstance() {
+      return DEFAULT_INSTANCE;
+    }
+
+    private static final com.google.protobuf.Parser<ConnectionId>
+        PARSER = new com.google.protobuf.AbstractParser<ConnectionId>() {
+      @java.lang.Override
+      public ConnectionId parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new ConnectionId(input, extensionRegistry);
+      }
+    };
+
+    public static com.google.protobuf.Parser<ConnectionId> parser() {
+      return PARSER;
+    }
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<ConnectionId> getParserForType() {
+      return PARSER;
+    }
+
+    @java.lang.Override
+    public context.ContextOuterClass.ConnectionId getDefaultInstanceForType() {
+      return DEFAULT_INSTANCE;
+    }
+
+  }
+
+  public interface ConnectionOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:context.Connection)
+      com.google.protobuf.MessageOrBuilder {
+
+    /**
+     * <code>.context.ConnectionId connection_id = 1;</code>
+     * @return Whether the connectionId field is set.
+     */
+    boolean hasConnectionId();
+    /**
+     * <code>.context.ConnectionId connection_id = 1;</code>
+     * @return The connectionId.
+     */
+    context.ContextOuterClass.ConnectionId getConnectionId();
+    /**
+     * <code>.context.ConnectionId connection_id = 1;</code>
+     */
+    context.ContextOuterClass.ConnectionIdOrBuilder getConnectionIdOrBuilder();
+
+    /**
+     * <code>.context.ServiceId service_id = 2;</code>
+     * @return Whether the serviceId field is set.
+     */
+    boolean hasServiceId();
+    /**
+     * <code>.context.ServiceId service_id = 2;</code>
+     * @return The serviceId.
+     */
+    context.ContextOuterClass.ServiceId getServiceId();
+    /**
+     * <code>.context.ServiceId service_id = 2;</code>
+     */
+    context.ContextOuterClass.ServiceIdOrBuilder getServiceIdOrBuilder();
+
+    /**
+     * <code>repeated .context.EndPointId path_hops_endpoint_ids = 3;</code>
+     */
+    java.util.List<context.ContextOuterClass.EndPointId> 
+        getPathHopsEndpointIdsList();
+    /**
+     * <code>repeated .context.EndPointId path_hops_endpoint_ids = 3;</code>
+     */
+    context.ContextOuterClass.EndPointId getPathHopsEndpointIds(int index);
+    /**
+     * <code>repeated .context.EndPointId path_hops_endpoint_ids = 3;</code>
+     */
+    int getPathHopsEndpointIdsCount();
+    /**
+     * <code>repeated .context.EndPointId path_hops_endpoint_ids = 3;</code>
+     */
+    java.util.List<? extends context.ContextOuterClass.EndPointIdOrBuilder> 
+        getPathHopsEndpointIdsOrBuilderList();
+    /**
+     * <code>repeated .context.EndPointId path_hops_endpoint_ids = 3;</code>
+     */
+    context.ContextOuterClass.EndPointIdOrBuilder getPathHopsEndpointIdsOrBuilder(
+        int index);
+
+    /**
+     * <code>repeated .context.ServiceId sub_service_ids = 4;</code>
+     */
+    java.util.List<context.ContextOuterClass.ServiceId> 
+        getSubServiceIdsList();
+    /**
+     * <code>repeated .context.ServiceId sub_service_ids = 4;</code>
+     */
+    context.ContextOuterClass.ServiceId getSubServiceIds(int index);
+    /**
+     * <code>repeated .context.ServiceId sub_service_ids = 4;</code>
+     */
+    int getSubServiceIdsCount();
+    /**
+     * <code>repeated .context.ServiceId sub_service_ids = 4;</code>
+     */
+    java.util.List<? extends context.ContextOuterClass.ServiceIdOrBuilder> 
+        getSubServiceIdsOrBuilderList();
+    /**
+     * <code>repeated .context.ServiceId sub_service_ids = 4;</code>
+     */
+    context.ContextOuterClass.ServiceIdOrBuilder getSubServiceIdsOrBuilder(
+        int index);
+  }
+  /**
+   * Protobuf type {@code context.Connection}
+   */
+  public static final class Connection extends
+      com.google.protobuf.GeneratedMessageV3 implements
+      // @@protoc_insertion_point(message_implements:context.Connection)
+      ConnectionOrBuilder {
+  private static final long serialVersionUID = 0L;
+    // Use Connection.newBuilder() to construct.
+    private Connection(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
+      super(builder);
+    }
+    private Connection() {
+      pathHopsEndpointIds_ = java.util.Collections.emptyList();
+      subServiceIds_ = java.util.Collections.emptyList();
+    }
+
+    @java.lang.Override
+    @SuppressWarnings({"unused"})
+    protected java.lang.Object newInstance(
+        UnusedPrivateParameter unused) {
+      return new Connection();
+    }
+
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+    getUnknownFields() {
+      return this.unknownFields;
+    }
+    private Connection(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      this();
+      if (extensionRegistry == null) {
+        throw new java.lang.NullPointerException();
+      }
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            case 10: {
+              context.ContextOuterClass.ConnectionId.Builder subBuilder = null;
+              if (connectionId_ != null) {
+                subBuilder = connectionId_.toBuilder();
+              }
+              connectionId_ = input.readMessage(context.ContextOuterClass.ConnectionId.parser(), extensionRegistry);
+              if (subBuilder != null) {
+                subBuilder.mergeFrom(connectionId_);
+                connectionId_ = subBuilder.buildPartial();
+              }
+
+              break;
+            }
+            case 18: {
+              context.ContextOuterClass.ServiceId.Builder subBuilder = null;
+              if (serviceId_ != null) {
+                subBuilder = serviceId_.toBuilder();
+              }
+              serviceId_ = input.readMessage(context.ContextOuterClass.ServiceId.parser(), extensionRegistry);
+              if (subBuilder != null) {
+                subBuilder.mergeFrom(serviceId_);
+                serviceId_ = subBuilder.buildPartial();
+              }
+
+              break;
+            }
+            case 26: {
+              if (!((mutable_bitField0_ & 0x00000001) != 0)) {
+                pathHopsEndpointIds_ = new java.util.ArrayList<context.ContextOuterClass.EndPointId>();
+                mutable_bitField0_ |= 0x00000001;
+              }
+              pathHopsEndpointIds_.add(
+                  input.readMessage(context.ContextOuterClass.EndPointId.parser(), extensionRegistry));
+              break;
+            }
+            case 34: {
+              if (!((mutable_bitField0_ & 0x00000002) != 0)) {
+                subServiceIds_ = new java.util.ArrayList<context.ContextOuterClass.ServiceId>();
+                mutable_bitField0_ |= 0x00000002;
+              }
+              subServiceIds_.add(
+                  input.readMessage(context.ContextOuterClass.ServiceId.parser(), extensionRegistry));
+              break;
+            }
+            default: {
+              if (!parseUnknownField(
+                  input, unknownFields, extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e).setUnfinishedMessage(this);
+      } finally {
+        if (((mutable_bitField0_ & 0x00000001) != 0)) {
+          pathHopsEndpointIds_ = java.util.Collections.unmodifiableList(pathHopsEndpointIds_);
+        }
+        if (((mutable_bitField0_ & 0x00000002) != 0)) {
+          subServiceIds_ = java.util.Collections.unmodifiableList(subServiceIds_);
+        }
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return context.ContextOuterClass.internal_static_context_Connection_descriptor;
+    }
+
+    @java.lang.Override
+    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return context.ContextOuterClass.internal_static_context_Connection_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              context.ContextOuterClass.Connection.class, context.ContextOuterClass.Connection.Builder.class);
+    }
+
+    public static final int CONNECTION_ID_FIELD_NUMBER = 1;
+    private context.ContextOuterClass.ConnectionId connectionId_;
+    /**
+     * <code>.context.ConnectionId connection_id = 1;</code>
+     * @return Whether the connectionId field is set.
+     */
+    @java.lang.Override
+    public boolean hasConnectionId() {
+      return connectionId_ != null;
+    }
+    /**
+     * <code>.context.ConnectionId connection_id = 1;</code>
+     * @return The connectionId.
+     */
+    @java.lang.Override
+    public context.ContextOuterClass.ConnectionId getConnectionId() {
+      return connectionId_ == null ? context.ContextOuterClass.ConnectionId.getDefaultInstance() : connectionId_;
+    }
+    /**
+     * <code>.context.ConnectionId connection_id = 1;</code>
+     */
+    @java.lang.Override
+    public context.ContextOuterClass.ConnectionIdOrBuilder getConnectionIdOrBuilder() {
+      return getConnectionId();
+    }
+
+    public static final int SERVICE_ID_FIELD_NUMBER = 2;
+    private context.ContextOuterClass.ServiceId serviceId_;
+    /**
+     * <code>.context.ServiceId service_id = 2;</code>
+     * @return Whether the serviceId field is set.
+     */
+    @java.lang.Override
+    public boolean hasServiceId() {
+      return serviceId_ != null;
+    }
+    /**
+     * <code>.context.ServiceId service_id = 2;</code>
+     * @return The serviceId.
+     */
+    @java.lang.Override
+    public context.ContextOuterClass.ServiceId getServiceId() {
+      return serviceId_ == null ? context.ContextOuterClass.ServiceId.getDefaultInstance() : serviceId_;
+    }
+    /**
+     * <code>.context.ServiceId service_id = 2;</code>
+     */
+    @java.lang.Override
+    public context.ContextOuterClass.ServiceIdOrBuilder getServiceIdOrBuilder() {
+      return getServiceId();
+    }
+
+    public static final int PATH_HOPS_ENDPOINT_IDS_FIELD_NUMBER = 3;
+    private java.util.List<context.ContextOuterClass.EndPointId> pathHopsEndpointIds_;
+    /**
+     * <code>repeated .context.EndPointId path_hops_endpoint_ids = 3;</code>
+     */
+    @java.lang.Override
+    public java.util.List<context.ContextOuterClass.EndPointId> getPathHopsEndpointIdsList() {
+      return pathHopsEndpointIds_;
+    }
+    /**
+     * <code>repeated .context.EndPointId path_hops_endpoint_ids = 3;</code>
+     */
+    @java.lang.Override
+    public java.util.List<? extends context.ContextOuterClass.EndPointIdOrBuilder> 
+        getPathHopsEndpointIdsOrBuilderList() {
+      return pathHopsEndpointIds_;
+    }
+    /**
+     * <code>repeated .context.EndPointId path_hops_endpoint_ids = 3;</code>
+     */
+    @java.lang.Override
+    public int getPathHopsEndpointIdsCount() {
+      return pathHopsEndpointIds_.size();
+    }
+    /**
+     * <code>repeated .context.EndPointId path_hops_endpoint_ids = 3;</code>
+     */
+    @java.lang.Override
+    public context.ContextOuterClass.EndPointId getPathHopsEndpointIds(int index) {
+      return pathHopsEndpointIds_.get(index);
+    }
+    /**
+     * <code>repeated .context.EndPointId path_hops_endpoint_ids = 3;</code>
+     */
+    @java.lang.Override
+    public context.ContextOuterClass.EndPointIdOrBuilder getPathHopsEndpointIdsOrBuilder(
+        int index) {
+      return pathHopsEndpointIds_.get(index);
+    }
+
+    public static final int SUB_SERVICE_IDS_FIELD_NUMBER = 4;
+    private java.util.List<context.ContextOuterClass.ServiceId> subServiceIds_;
+    /**
+     * <code>repeated .context.ServiceId sub_service_ids = 4;</code>
+     */
+    @java.lang.Override
+    public java.util.List<context.ContextOuterClass.ServiceId> getSubServiceIdsList() {
+      return subServiceIds_;
+    }
+    /**
+     * <code>repeated .context.ServiceId sub_service_ids = 4;</code>
+     */
+    @java.lang.Override
+    public java.util.List<? extends context.ContextOuterClass.ServiceIdOrBuilder> 
+        getSubServiceIdsOrBuilderList() {
+      return subServiceIds_;
+    }
+    /**
+     * <code>repeated .context.ServiceId sub_service_ids = 4;</code>
+     */
+    @java.lang.Override
+    public int getSubServiceIdsCount() {
+      return subServiceIds_.size();
+    }
+    /**
+     * <code>repeated .context.ServiceId sub_service_ids = 4;</code>
+     */
+    @java.lang.Override
+    public context.ContextOuterClass.ServiceId getSubServiceIds(int index) {
+      return subServiceIds_.get(index);
+    }
+    /**
+     * <code>repeated .context.ServiceId sub_service_ids = 4;</code>
+     */
+    @java.lang.Override
+    public context.ContextOuterClass.ServiceIdOrBuilder getSubServiceIdsOrBuilder(
+        int index) {
+      return subServiceIds_.get(index);
+    }
+
+    private byte memoizedIsInitialized = -1;
+    @java.lang.Override
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized == 1) return true;
+      if (isInitialized == 0) return false;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    @java.lang.Override
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      if (connectionId_ != null) {
+        output.writeMessage(1, getConnectionId());
+      }
+      if (serviceId_ != null) {
+        output.writeMessage(2, getServiceId());
+      }
+      for (int i = 0; i < pathHopsEndpointIds_.size(); i++) {
+        output.writeMessage(3, pathHopsEndpointIds_.get(i));
+      }
+      for (int i = 0; i < subServiceIds_.size(); i++) {
+        output.writeMessage(4, subServiceIds_.get(i));
+      }
+      unknownFields.writeTo(output);
+    }
+
+    @java.lang.Override
+    public int getSerializedSize() {
+      int size = memoizedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (connectionId_ != null) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(1, getConnectionId());
+      }
+      if (serviceId_ != null) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(2, getServiceId());
+      }
+      for (int i = 0; i < pathHopsEndpointIds_.size(); i++) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(3, pathHopsEndpointIds_.get(i));
+      }
+      for (int i = 0; i < subServiceIds_.size(); i++) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(4, subServiceIds_.get(i));
+      }
+      size += unknownFields.getSerializedSize();
+      memoizedSize = size;
+      return size;
+    }
+
+    @java.lang.Override
+    public boolean equals(final java.lang.Object obj) {
+      if (obj == this) {
+       return true;
+      }
+      if (!(obj instanceof context.ContextOuterClass.Connection)) {
+        return super.equals(obj);
+      }
+      context.ContextOuterClass.Connection other = (context.ContextOuterClass.Connection) obj;
+
+      if (hasConnectionId() != other.hasConnectionId()) return false;
+      if (hasConnectionId()) {
+        if (!getConnectionId()
+            .equals(other.getConnectionId())) return false;
+      }
+      if (hasServiceId() != other.hasServiceId()) return false;
+      if (hasServiceId()) {
+        if (!getServiceId()
+            .equals(other.getServiceId())) return false;
+      }
+      if (!getPathHopsEndpointIdsList()
+          .equals(other.getPathHopsEndpointIdsList())) return false;
+      if (!getSubServiceIdsList()
+          .equals(other.getSubServiceIdsList())) return false;
+      if (!unknownFields.equals(other.unknownFields)) return false;
+      return true;
+    }
+
+    @java.lang.Override
+    public int hashCode() {
+      if (memoizedHashCode != 0) {
+        return memoizedHashCode;
+      }
+      int hash = 41;
+      hash = (19 * hash) + getDescriptor().hashCode();
+      if (hasConnectionId()) {
+        hash = (37 * hash) + CONNECTION_ID_FIELD_NUMBER;
+        hash = (53 * hash) + getConnectionId().hashCode();
+      }
+      if (hasServiceId()) {
+        hash = (37 * hash) + SERVICE_ID_FIELD_NUMBER;
+        hash = (53 * hash) + getServiceId().hashCode();
+      }
+      if (getPathHopsEndpointIdsCount() > 0) {
+        hash = (37 * hash) + PATH_HOPS_ENDPOINT_IDS_FIELD_NUMBER;
+        hash = (53 * hash) + getPathHopsEndpointIdsList().hashCode();
+      }
+      if (getSubServiceIdsCount() > 0) {
+        hash = (37 * hash) + SUB_SERVICE_IDS_FIELD_NUMBER;
+        hash = (53 * hash) + getSubServiceIdsList().hashCode();
+      }
+      hash = (29 * hash) + unknownFields.hashCode();
+      memoizedHashCode = hash;
+      return hash;
+    }
+
+    public static context.ContextOuterClass.Connection parseFrom(
+        java.nio.ByteBuffer data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static context.ContextOuterClass.Connection parseFrom(
+        java.nio.ByteBuffer data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static context.ContextOuterClass.Connection parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static context.ContextOuterClass.Connection parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static context.ContextOuterClass.Connection parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static context.ContextOuterClass.Connection parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static context.ContextOuterClass.Connection parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseWithIOException(PARSER, input);
+    }
+    public static context.ContextOuterClass.Connection parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseWithIOException(PARSER, input, extensionRegistry);
+    }
+    public static context.ContextOuterClass.Connection parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseDelimitedWithIOException(PARSER, input);
+    }
+    public static context.ContextOuterClass.Connection parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
+    }
+    public static context.ContextOuterClass.Connection parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseWithIOException(PARSER, input);
+    }
+    public static context.ContextOuterClass.Connection parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return com.google.protobuf.GeneratedMessageV3
+          .parseWithIOException(PARSER, input, extensionRegistry);
+    }
+
+    @java.lang.Override
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder() {
+      return DEFAULT_INSTANCE.toBuilder();
+    }
+    public static Builder newBuilder(context.ContextOuterClass.Connection prototype) {
+      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+    }
+    @java.lang.Override
+    public Builder toBuilder() {
+      return this == DEFAULT_INSTANCE
+          ? new Builder() : new Builder().mergeFrom(this);
+    }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code context.Connection}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
+        // @@protoc_insertion_point(builder_implements:context.Connection)
+        context.ContextOuterClass.ConnectionOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return context.ContextOuterClass.internal_static_context_Connection_descriptor;
+      }
+
+      @java.lang.Override
+      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return context.ContextOuterClass.internal_static_context_Connection_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                context.ContextOuterClass.Connection.class, context.ContextOuterClass.Connection.Builder.class);
+      }
+
+      // Construct using context.ContextOuterClass.Connection.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessageV3
+                .alwaysUseFieldBuilders) {
+          getPathHopsEndpointIdsFieldBuilder();
+          getSubServiceIdsFieldBuilder();
+        }
+      }
+      @java.lang.Override
+      public Builder clear() {
+        super.clear();
+        if (connectionIdBuilder_ == null) {
+          connectionId_ = null;
+        } else {
+          connectionId_ = null;
+          connectionIdBuilder_ = null;
+        }
+        if (serviceIdBuilder_ == null) {
+          serviceId_ = null;
+        } else {
+          serviceId_ = null;
+          serviceIdBuilder_ = null;
+        }
+        if (pathHopsEndpointIdsBuilder_ == null) {
+          pathHopsEndpointIds_ = java.util.Collections.emptyList();
+          bitField0_ = (bitField0_ & ~0x00000001);
+        } else {
+          pathHopsEndpointIdsBuilder_.clear();
+        }
+        if (subServiceIdsBuilder_ == null) {
+          subServiceIds_ = java.util.Collections.emptyList();
+          bitField0_ = (bitField0_ & ~0x00000002);
+        } else {
+          subServiceIdsBuilder_.clear();
+        }
+        return this;
+      }
+
+      @java.lang.Override
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return context.ContextOuterClass.internal_static_context_Connection_descriptor;
+      }
+
+      @java.lang.Override
+      public context.ContextOuterClass.Connection getDefaultInstanceForType() {
+        return context.ContextOuterClass.Connection.getDefaultInstance();
+      }
+
+      @java.lang.Override
+      public context.ContextOuterClass.Connection build() {
+        context.ContextOuterClass.Connection result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      @java.lang.Override
+      public context.ContextOuterClass.Connection buildPartial() {
+        context.ContextOuterClass.Connection result = new context.ContextOuterClass.Connection(this);
+        int from_bitField0_ = bitField0_;
+        if (connectionIdBuilder_ == null) {
+          result.connectionId_ = connectionId_;
+        } else {
+          result.connectionId_ = connectionIdBuilder_.build();
+        }
+        if (serviceIdBuilder_ == null) {
+          result.serviceId_ = serviceId_;
+        } else {
+          result.serviceId_ = serviceIdBuilder_.build();
+        }
+        if (pathHopsEndpointIdsBuilder_ == null) {
+          if (((bitField0_ & 0x00000001) != 0)) {
+            pathHopsEndpointIds_ = java.util.Collections.unmodifiableList(pathHopsEndpointIds_);
+            bitField0_ = (bitField0_ & ~0x00000001);
+          }
+          result.pathHopsEndpointIds_ = pathHopsEndpointIds_;
+        } else {
+          result.pathHopsEndpointIds_ = pathHopsEndpointIdsBuilder_.build();
+        }
+        if (subServiceIdsBuilder_ == null) {
+          if (((bitField0_ & 0x00000002) != 0)) {
+            subServiceIds_ = java.util.Collections.unmodifiableList(subServiceIds_);
+            bitField0_ = (bitField0_ & ~0x00000002);
+          }
+          result.subServiceIds_ = subServiceIds_;
+        } else {
+          result.subServiceIds_ = subServiceIdsBuilder_.build();
+        }
+        onBuilt();
+        return result;
+      }
+
+      @java.lang.Override
+      public Builder clone() {
+        return super.clone();
+      }
+      @java.lang.Override
+      public Builder setField(
+          com.google.protobuf.Descriptors.FieldDescriptor field,
+          java.lang.Object value) {
+        return super.setField(field, value);
+      }
+      @java.lang.Override
+      public Builder clearField(
+          com.google.protobuf.Descriptors.FieldDescriptor field) {
+        return super.clearField(field);
+      }
+      @java.lang.Override
+      public Builder clearOneof(
+          com.google.protobuf.Descriptors.OneofDescriptor oneof) {
+        return super.clearOneof(oneof);
+      }
+      @java.lang.Override
+      public Builder setRepeatedField(
+          com.google.protobuf.Descriptors.FieldDescriptor field,
+          int index, java.lang.Object value) {
+        return super.setRepeatedField(field, index, value);
+      }
+      @java.lang.Override
+      public Builder addRepeatedField(
+          com.google.protobuf.Descriptors.FieldDescriptor field,
+          java.lang.Object value) {
+        return super.addRepeatedField(field, value);
+      }
+      @java.lang.Override
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof context.ContextOuterClass.Connection) {
+          return mergeFrom((context.ContextOuterClass.Connection)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(context.ContextOuterClass.Connection other) {
+        if (other == context.ContextOuterClass.Connection.getDefaultInstance()) return this;
+        if (other.hasConnectionId()) {
+          mergeConnectionId(other.getConnectionId());
+        }
+        if (other.hasServiceId()) {
+          mergeServiceId(other.getServiceId());
+        }
+        if (pathHopsEndpointIdsBuilder_ == null) {
+          if (!other.pathHopsEndpointIds_.isEmpty()) {
+            if (pathHopsEndpointIds_.isEmpty()) {
+              pathHopsEndpointIds_ = other.pathHopsEndpointIds_;
+              bitField0_ = (bitField0_ & ~0x00000001);
+            } else {
+              ensurePathHopsEndpointIdsIsMutable();
+              pathHopsEndpointIds_.addAll(other.pathHopsEndpointIds_);
+            }
+            onChanged();
+          }
+        } else {
+          if (!other.pathHopsEndpointIds_.isEmpty()) {
+            if (pathHopsEndpointIdsBuilder_.isEmpty()) {
+              pathHopsEndpointIdsBuilder_.dispose();
+              pathHopsEndpointIdsBuilder_ = null;
+              pathHopsEndpointIds_ = other.pathHopsEndpointIds_;
+              bitField0_ = (bitField0_ & ~0x00000001);
+              pathHopsEndpointIdsBuilder_ = 
+                com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ?
+                   getPathHopsEndpointIdsFieldBuilder() : null;
+            } else {
+              pathHopsEndpointIdsBuilder_.addAllMessages(other.pathHopsEndpointIds_);
+            }
+          }
+        }
+        if (subServiceIdsBuilder_ == null) {
+          if (!other.subServiceIds_.isEmpty()) {
+            if (subServiceIds_.isEmpty()) {
+              subServiceIds_ = other.subServiceIds_;
+              bitField0_ = (bitField0_ & ~0x00000002);
+            } else {
+              ensureSubServiceIdsIsMutable();
+              subServiceIds_.addAll(other.subServiceIds_);
+            }
+            onChanged();
+          }
+        } else {
+          if (!other.subServiceIds_.isEmpty()) {
+            if (subServiceIdsBuilder_.isEmpty()) {
+              subServiceIdsBuilder_.dispose();
+              subServiceIdsBuilder_ = null;
+              subServiceIds_ = other.subServiceIds_;
+              bitField0_ = (bitField0_ & ~0x00000002);
+              subServiceIdsBuilder_ = 
+                com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ?
+                   getSubServiceIdsFieldBuilder() : null;
+            } else {
+              subServiceIdsBuilder_.addAllMessages(other.subServiceIds_);
+            }
+          }
+        }
+        this.mergeUnknownFields(other.unknownFields);
+        onChanged();
+        return this;
+      }
+
+      @java.lang.Override
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      @java.lang.Override
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        context.ContextOuterClass.Connection parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (context.ContextOuterClass.Connection) e.getUnfinishedMessage();
+          throw e.unwrapIOException();
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      private context.ContextOuterClass.ConnectionId connectionId_;
+      private com.google.protobuf.SingleFieldBuilderV3<
+          context.ContextOuterClass.ConnectionId, context.ContextOuterClass.ConnectionId.Builder, context.ContextOuterClass.ConnectionIdOrBuilder> connectionIdBuilder_;
+      /**
+       * <code>.context.ConnectionId connection_id = 1;</code>
+       * @return Whether the connectionId field is set.
+       */
+      public boolean hasConnectionId() {
+        return connectionIdBuilder_ != null || connectionId_ != null;
+      }
+      /**
+       * <code>.context.ConnectionId connection_id = 1;</code>
+       * @return The connectionId.
+       */
+      public context.ContextOuterClass.ConnectionId getConnectionId() {
+        if (connectionIdBuilder_ == null) {
+          return connectionId_ == null ? context.ContextOuterClass.ConnectionId.getDefaultInstance() : connectionId_;
+        } else {
+          return connectionIdBuilder_.getMessage();
+        }
+      }
+      /**
+       * <code>.context.ConnectionId connection_id = 1;</code>
+       */
+      public Builder setConnectionId(context.ContextOuterClass.ConnectionId value) {
+        if (connectionIdBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          connectionId_ = value;
+          onChanged();
+        } else {
+          connectionIdBuilder_.setMessage(value);
+        }
+
+        return this;
+      }
+      /**
+       * <code>.context.ConnectionId connection_id = 1;</code>
+       */
+      public Builder setConnectionId(
+          context.ContextOuterClass.ConnectionId.Builder builderForValue) {
+        if (connectionIdBuilder_ == null) {
+          connectionId_ = builderForValue.build();
+          onChanged();
+        } else {
+          connectionIdBuilder_.setMessage(builderForValue.build());
+        }
+
+        return this;
+      }
+      /**
+       * <code>.context.ConnectionId connection_id = 1;</code>
+       */
+      public Builder mergeConnectionId(context.ContextOuterClass.ConnectionId value) {
+        if (connectionIdBuilder_ == null) {
+          if (connectionId_ != null) {
+            connectionId_ =
+              context.ContextOuterClass.ConnectionId.newBuilder(connectionId_).mergeFrom(value).buildPartial();
+          } else {
+            connectionId_ = value;
+          }
+          onChanged();
+        } else {
+          connectionIdBuilder_.mergeFrom(value);
+        }
+
+        return this;
+      }
+      /**
+       * <code>.context.ConnectionId connection_id = 1;</code>
+       */
+      public Builder clearConnectionId() {
+        if (connectionIdBuilder_ == null) {
+          connectionId_ = null;
+          onChanged();
+        } else {
+          connectionId_ = null;
+          connectionIdBuilder_ = null;
+        }
+
+        return this;
+      }
+      /**
+       * <code>.context.ConnectionId connection_id = 1;</code>
+       */
+      public context.ContextOuterClass.ConnectionId.Builder getConnectionIdBuilder() {
+        
+        onChanged();
+        return getConnectionIdFieldBuilder().getBuilder();
+      }
+      /**
+       * <code>.context.ConnectionId connection_id = 1;</code>
+       */
+      public context.ContextOuterClass.ConnectionIdOrBuilder getConnectionIdOrBuilder() {
+        if (connectionIdBuilder_ != null) {
+          return connectionIdBuilder_.getMessageOrBuilder();
+        } else {
+          return connectionId_ == null ?
+              context.ContextOuterClass.ConnectionId.getDefaultInstance() : connectionId_;
+        }
+      }
+      /**
+       * <code>.context.ConnectionId connection_id = 1;</code>
+       */
+      private com.google.protobuf.SingleFieldBuilderV3<
+          context.ContextOuterClass.ConnectionId, context.ContextOuterClass.ConnectionId.Builder, context.ContextOuterClass.ConnectionIdOrBuilder> 
+          getConnectionIdFieldBuilder() {
+        if (connectionIdBuilder_ == null) {
+          connectionIdBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
+              context.ContextOuterClass.ConnectionId, context.ContextOuterClass.ConnectionId.Builder, context.ContextOuterClass.ConnectionIdOrBuilder>(
+                  getConnectionId(),
+                  getParentForChildren(),
+                  isClean());
+          connectionId_ = null;
+        }
+        return connectionIdBuilder_;
+      }
+
+      private context.ContextOuterClass.ServiceId serviceId_;
+      private com.google.protobuf.SingleFieldBuilderV3<
+          context.ContextOuterClass.ServiceId, context.ContextOuterClass.ServiceId.Builder, context.ContextOuterClass.ServiceIdOrBuilder> serviceIdBuilder_;
+      /**
+       * <code>.context.ServiceId service_id = 2;</code>
+       * @return Whether the serviceId field is set.
+       */
+      public boolean hasServiceId() {
+        return serviceIdBuilder_ != null || serviceId_ != null;
+      }
+      /**
+       * <code>.context.ServiceId service_id = 2;</code>
+       * @return The serviceId.
+       */
+      public context.ContextOuterClass.ServiceId getServiceId() {
+        if (serviceIdBuilder_ == null) {
+          return serviceId_ == null ? context.ContextOuterClass.ServiceId.getDefaultInstance() : serviceId_;
+        } else {
+          return serviceIdBuilder_.getMessage();
+        }
+      }
+      /**
+       * <code>.context.ServiceId service_id = 2;</code>
+       */
+      public Builder setServiceId(context.ContextOuterClass.ServiceId value) {
+        if (serviceIdBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          serviceId_ = value;
+          onChanged();
+        } else {
+          serviceIdBuilder_.setMessage(value);
+        }
+
+        return this;
+      }
+      /**
+       * <code>.context.ServiceId service_id = 2;</code>
+       */
+      public Builder setServiceId(
+          context.ContextOuterClass.ServiceId.Builder builderForValue) {
+        if (serviceIdBuilder_ == null) {
+          serviceId_ = builderForValue.build();
+          onChanged();
+        } else {
+          serviceIdBuilder_.setMessage(builderForValue.build());
+        }
+
+        return this;
+      }
+      /**
+       * <code>.context.ServiceId service_id = 2;</code>
+       */
+      public Builder mergeServiceId(context.ContextOuterClass.ServiceId value) {
+        if (serviceIdBuilder_ == null) {
+          if (serviceId_ != null) {
+            serviceId_ =
+              context.ContextOuterClass.ServiceId.newBuilder(serviceId_).mergeFrom(value).buildPartial();
+          } else {
+            serviceId_ = value;
+          }
+          onChanged();
+        } else {
+          serviceIdBuilder_.mergeFrom(value);
+        }
+
+        return this;
+      }
+      /**
+       * <code>.context.ServiceId service_id = 2;</code>
+       */
+      public Builder clearServiceId() {
+        if (serviceIdBuilder_ == null) {
+          serviceId_ = null;
+          onChanged();
+        } else {
+          serviceId_ = null;
+          serviceIdBuilder_ = null;
+        }
+
+        return this;
+      }
+      /**
+       * <code>.context.ServiceId service_id = 2;</code>
+       */
+      public context.ContextOuterClass.ServiceId.Builder getServiceIdBuilder() {
+        
+        onChanged();
+        return getServiceIdFieldBuilder().getBuilder();
+      }
+      /**
+       * <code>.context.ServiceId service_id = 2;</code>
+       */
+      public context.ContextOuterClass.ServiceIdOrBuilder getServiceIdOrBuilder() {
+        if (serviceIdBuilder_ != null) {
+          return serviceIdBuilder_.getMessageOrBuilder();
+        } else {
+          return serviceId_ == null ?
+              context.ContextOuterClass.ServiceId.getDefaultInstance() : serviceId_;
+        }
+      }
+      /**
+       * <code>.context.ServiceId service_id = 2;</code>
+       */
+      private com.google.protobuf.SingleFieldBuilderV3<
+          context.ContextOuterClass.ServiceId, context.ContextOuterClass.ServiceId.Builder, context.ContextOuterClass.ServiceIdOrBuilder> 
+          getServiceIdFieldBuilder() {
+        if (serviceIdBuilder_ == null) {
+          serviceIdBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
+              context.ContextOuterClass.ServiceId, context.ContextOuterClass.ServiceId.Builder, context.ContextOuterClass.ServiceIdOrBuilder>(
+                  getServiceId(),
+                  getParentForChildren(),
+                  isClean());
+          serviceId_ = null;
+        }
+        return serviceIdBuilder_;
+      }
+
+      private java.util.List<context.ContextOuterClass.EndPointId> pathHopsEndpointIds_ =
+        java.util.Collections.emptyList();
+      private void ensurePathHopsEndpointIdsIsMutable() {
+        if (!((bitField0_ & 0x00000001) != 0)) {
+          pathHopsEndpointIds_ = new java.util.ArrayList<context.ContextOuterClass.EndPointId>(pathHopsEndpointIds_);
+          bitField0_ |= 0x00000001;
+         }
+      }
+
+      private com.google.protobuf.RepeatedFieldBuilderV3<
+          context.ContextOuterClass.EndPointId, context.ContextOuterClass.EndPointId.Builder, context.ContextOuterClass.EndPointIdOrBuilder> pathHopsEndpointIdsBuilder_;
+
       /**
-       * <code>.context.DeviceId device_id = 2;</code>
+       * <code>repeated .context.EndPointId path_hops_endpoint_ids = 3;</code>
        */
-      public Builder setDeviceId(
-          context.ContextOuterClass.DeviceId.Builder builderForValue) {
-        if (deviceIdBuilder_ == null) {
-          deviceId_ = builderForValue.build();
+      public java.util.List<context.ContextOuterClass.EndPointId> getPathHopsEndpointIdsList() {
+        if (pathHopsEndpointIdsBuilder_ == null) {
+          return java.util.Collections.unmodifiableList(pathHopsEndpointIds_);
+        } else {
+          return pathHopsEndpointIdsBuilder_.getMessageList();
+        }
+      }
+      /**
+       * <code>repeated .context.EndPointId path_hops_endpoint_ids = 3;</code>
+       */
+      public int getPathHopsEndpointIdsCount() {
+        if (pathHopsEndpointIdsBuilder_ == null) {
+          return pathHopsEndpointIds_.size();
+        } else {
+          return pathHopsEndpointIdsBuilder_.getCount();
+        }
+      }
+      /**
+       * <code>repeated .context.EndPointId path_hops_endpoint_ids = 3;</code>
+       */
+      public context.ContextOuterClass.EndPointId getPathHopsEndpointIds(int index) {
+        if (pathHopsEndpointIdsBuilder_ == null) {
+          return pathHopsEndpointIds_.get(index);
+        } else {
+          return pathHopsEndpointIdsBuilder_.getMessage(index);
+        }
+      }
+      /**
+       * <code>repeated .context.EndPointId path_hops_endpoint_ids = 3;</code>
+       */
+      public Builder setPathHopsEndpointIds(
+          int index, context.ContextOuterClass.EndPointId value) {
+        if (pathHopsEndpointIdsBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensurePathHopsEndpointIdsIsMutable();
+          pathHopsEndpointIds_.set(index, value);
           onChanged();
         } else {
-          deviceIdBuilder_.setMessage(builderForValue.build());
+          pathHopsEndpointIdsBuilder_.setMessage(index, value);
         }
-
         return this;
       }
       /**
-       * <code>.context.DeviceId device_id = 2;</code>
+       * <code>repeated .context.EndPointId path_hops_endpoint_ids = 3;</code>
        */
-      public Builder mergeDeviceId(context.ContextOuterClass.DeviceId value) {
-        if (deviceIdBuilder_ == null) {
-          if (deviceId_ != null) {
-            deviceId_ =
-              context.ContextOuterClass.DeviceId.newBuilder(deviceId_).mergeFrom(value).buildPartial();
-          } else {
-            deviceId_ = value;
+      public Builder setPathHopsEndpointIds(
+          int index, context.ContextOuterClass.EndPointId.Builder builderForValue) {
+        if (pathHopsEndpointIdsBuilder_ == null) {
+          ensurePathHopsEndpointIdsIsMutable();
+          pathHopsEndpointIds_.set(index, builderForValue.build());
+          onChanged();
+        } else {
+          pathHopsEndpointIdsBuilder_.setMessage(index, builderForValue.build());
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .context.EndPointId path_hops_endpoint_ids = 3;</code>
+       */
+      public Builder addPathHopsEndpointIds(context.ContextOuterClass.EndPointId value) {
+        if (pathHopsEndpointIdsBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
           }
+          ensurePathHopsEndpointIdsIsMutable();
+          pathHopsEndpointIds_.add(value);
           onChanged();
         } else {
-          deviceIdBuilder_.mergeFrom(value);
+          pathHopsEndpointIdsBuilder_.addMessage(value);
         }
-
         return this;
       }
       /**
-       * <code>.context.DeviceId device_id = 2;</code>
+       * <code>repeated .context.EndPointId path_hops_endpoint_ids = 3;</code>
        */
-      public Builder clearDeviceId() {
-        if (deviceIdBuilder_ == null) {
-          deviceId_ = null;
+      public Builder addPathHopsEndpointIds(
+          int index, context.ContextOuterClass.EndPointId value) {
+        if (pathHopsEndpointIdsBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensurePathHopsEndpointIdsIsMutable();
+          pathHopsEndpointIds_.add(index, value);
           onChanged();
         } else {
-          deviceId_ = null;
-          deviceIdBuilder_ = null;
+          pathHopsEndpointIdsBuilder_.addMessage(index, value);
         }
-
         return this;
       }
       /**
-       * <code>.context.DeviceId device_id = 2;</code>
+       * <code>repeated .context.EndPointId path_hops_endpoint_ids = 3;</code>
        */
-      public context.ContextOuterClass.DeviceId.Builder getDeviceIdBuilder() {
-        
-        onChanged();
-        return getDeviceIdFieldBuilder().getBuilder();
+      public Builder addPathHopsEndpointIds(
+          context.ContextOuterClass.EndPointId.Builder builderForValue) {
+        if (pathHopsEndpointIdsBuilder_ == null) {
+          ensurePathHopsEndpointIdsIsMutable();
+          pathHopsEndpointIds_.add(builderForValue.build());
+          onChanged();
+        } else {
+          pathHopsEndpointIdsBuilder_.addMessage(builderForValue.build());
+        }
+        return this;
       }
       /**
-       * <code>.context.DeviceId device_id = 2;</code>
+       * <code>repeated .context.EndPointId path_hops_endpoint_ids = 3;</code>
        */
-      public context.ContextOuterClass.DeviceIdOrBuilder getDeviceIdOrBuilder() {
-        if (deviceIdBuilder_ != null) {
-          return deviceIdBuilder_.getMessageOrBuilder();
+      public Builder addPathHopsEndpointIds(
+          int index, context.ContextOuterClass.EndPointId.Builder builderForValue) {
+        if (pathHopsEndpointIdsBuilder_ == null) {
+          ensurePathHopsEndpointIdsIsMutable();
+          pathHopsEndpointIds_.add(index, builderForValue.build());
+          onChanged();
         } else {
-          return deviceId_ == null ?
-              context.ContextOuterClass.DeviceId.getDefaultInstance() : deviceId_;
+          pathHopsEndpointIdsBuilder_.addMessage(index, builderForValue.build());
         }
+        return this;
       }
       /**
-       * <code>.context.DeviceId device_id = 2;</code>
+       * <code>repeated .context.EndPointId path_hops_endpoint_ids = 3;</code>
        */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          context.ContextOuterClass.DeviceId, context.ContextOuterClass.DeviceId.Builder, context.ContextOuterClass.DeviceIdOrBuilder> 
-          getDeviceIdFieldBuilder() {
-        if (deviceIdBuilder_ == null) {
-          deviceIdBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              context.ContextOuterClass.DeviceId, context.ContextOuterClass.DeviceId.Builder, context.ContextOuterClass.DeviceIdOrBuilder>(
-                  getDeviceId(),
+      public Builder addAllPathHopsEndpointIds(
+          java.lang.Iterable<? extends context.ContextOuterClass.EndPointId> values) {
+        if (pathHopsEndpointIdsBuilder_ == null) {
+          ensurePathHopsEndpointIdsIsMutable();
+          com.google.protobuf.AbstractMessageLite.Builder.addAll(
+              values, pathHopsEndpointIds_);
+          onChanged();
+        } else {
+          pathHopsEndpointIdsBuilder_.addAllMessages(values);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .context.EndPointId path_hops_endpoint_ids = 3;</code>
+       */
+      public Builder clearPathHopsEndpointIds() {
+        if (pathHopsEndpointIdsBuilder_ == null) {
+          pathHopsEndpointIds_ = java.util.Collections.emptyList();
+          bitField0_ = (bitField0_ & ~0x00000001);
+          onChanged();
+        } else {
+          pathHopsEndpointIdsBuilder_.clear();
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .context.EndPointId path_hops_endpoint_ids = 3;</code>
+       */
+      public Builder removePathHopsEndpointIds(int index) {
+        if (pathHopsEndpointIdsBuilder_ == null) {
+          ensurePathHopsEndpointIdsIsMutable();
+          pathHopsEndpointIds_.remove(index);
+          onChanged();
+        } else {
+          pathHopsEndpointIdsBuilder_.remove(index);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .context.EndPointId path_hops_endpoint_ids = 3;</code>
+       */
+      public context.ContextOuterClass.EndPointId.Builder getPathHopsEndpointIdsBuilder(
+          int index) {
+        return getPathHopsEndpointIdsFieldBuilder().getBuilder(index);
+      }
+      /**
+       * <code>repeated .context.EndPointId path_hops_endpoint_ids = 3;</code>
+       */
+      public context.ContextOuterClass.EndPointIdOrBuilder getPathHopsEndpointIdsOrBuilder(
+          int index) {
+        if (pathHopsEndpointIdsBuilder_ == null) {
+          return pathHopsEndpointIds_.get(index);  } else {
+          return pathHopsEndpointIdsBuilder_.getMessageOrBuilder(index);
+        }
+      }
+      /**
+       * <code>repeated .context.EndPointId path_hops_endpoint_ids = 3;</code>
+       */
+      public java.util.List<? extends context.ContextOuterClass.EndPointIdOrBuilder> 
+           getPathHopsEndpointIdsOrBuilderList() {
+        if (pathHopsEndpointIdsBuilder_ != null) {
+          return pathHopsEndpointIdsBuilder_.getMessageOrBuilderList();
+        } else {
+          return java.util.Collections.unmodifiableList(pathHopsEndpointIds_);
+        }
+      }
+      /**
+       * <code>repeated .context.EndPointId path_hops_endpoint_ids = 3;</code>
+       */
+      public context.ContextOuterClass.EndPointId.Builder addPathHopsEndpointIdsBuilder() {
+        return getPathHopsEndpointIdsFieldBuilder().addBuilder(
+            context.ContextOuterClass.EndPointId.getDefaultInstance());
+      }
+      /**
+       * <code>repeated .context.EndPointId path_hops_endpoint_ids = 3;</code>
+       */
+      public context.ContextOuterClass.EndPointId.Builder addPathHopsEndpointIdsBuilder(
+          int index) {
+        return getPathHopsEndpointIdsFieldBuilder().addBuilder(
+            index, context.ContextOuterClass.EndPointId.getDefaultInstance());
+      }
+      /**
+       * <code>repeated .context.EndPointId path_hops_endpoint_ids = 3;</code>
+       */
+      public java.util.List<context.ContextOuterClass.EndPointId.Builder> 
+           getPathHopsEndpointIdsBuilderList() {
+        return getPathHopsEndpointIdsFieldBuilder().getBuilderList();
+      }
+      private com.google.protobuf.RepeatedFieldBuilderV3<
+          context.ContextOuterClass.EndPointId, context.ContextOuterClass.EndPointId.Builder, context.ContextOuterClass.EndPointIdOrBuilder> 
+          getPathHopsEndpointIdsFieldBuilder() {
+        if (pathHopsEndpointIdsBuilder_ == null) {
+          pathHopsEndpointIdsBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3<
+              context.ContextOuterClass.EndPointId, context.ContextOuterClass.EndPointId.Builder, context.ContextOuterClass.EndPointIdOrBuilder>(
+                  pathHopsEndpointIds_,
+                  ((bitField0_ & 0x00000001) != 0),
                   getParentForChildren(),
                   isClean());
-          deviceId_ = null;
+          pathHopsEndpointIds_ = null;
         }
-        return deviceIdBuilder_;
+        return pathHopsEndpointIdsBuilder_;
       }
 
-      private context.ContextOuterClass.Uuid endpointUuid_;
-      private com.google.protobuf.SingleFieldBuilderV3<
-          context.ContextOuterClass.Uuid, context.ContextOuterClass.Uuid.Builder, context.ContextOuterClass.UuidOrBuilder> endpointUuidBuilder_;
+      private java.util.List<context.ContextOuterClass.ServiceId> subServiceIds_ =
+        java.util.Collections.emptyList();
+      private void ensureSubServiceIdsIsMutable() {
+        if (!((bitField0_ & 0x00000002) != 0)) {
+          subServiceIds_ = new java.util.ArrayList<context.ContextOuterClass.ServiceId>(subServiceIds_);
+          bitField0_ |= 0x00000002;
+         }
+      }
+
+      private com.google.protobuf.RepeatedFieldBuilderV3<
+          context.ContextOuterClass.ServiceId, context.ContextOuterClass.ServiceId.Builder, context.ContextOuterClass.ServiceIdOrBuilder> subServiceIdsBuilder_;
+
       /**
-       * <code>.context.Uuid endpoint_uuid = 3;</code>
-       * @return Whether the endpointUuid field is set.
+       * <code>repeated .context.ServiceId sub_service_ids = 4;</code>
        */
-      public boolean hasEndpointUuid() {
-        return endpointUuidBuilder_ != null || endpointUuid_ != null;
+      public java.util.List<context.ContextOuterClass.ServiceId> getSubServiceIdsList() {
+        if (subServiceIdsBuilder_ == null) {
+          return java.util.Collections.unmodifiableList(subServiceIds_);
+        } else {
+          return subServiceIdsBuilder_.getMessageList();
+        }
       }
       /**
-       * <code>.context.Uuid endpoint_uuid = 3;</code>
-       * @return The endpointUuid.
+       * <code>repeated .context.ServiceId sub_service_ids = 4;</code>
        */
-      public context.ContextOuterClass.Uuid getEndpointUuid() {
-        if (endpointUuidBuilder_ == null) {
-          return endpointUuid_ == null ? context.ContextOuterClass.Uuid.getDefaultInstance() : endpointUuid_;
+      public int getSubServiceIdsCount() {
+        if (subServiceIdsBuilder_ == null) {
+          return subServiceIds_.size();
         } else {
-          return endpointUuidBuilder_.getMessage();
+          return subServiceIdsBuilder_.getCount();
         }
       }
       /**
-       * <code>.context.Uuid endpoint_uuid = 3;</code>
+       * <code>repeated .context.ServiceId sub_service_ids = 4;</code>
        */
-      public Builder setEndpointUuid(context.ContextOuterClass.Uuid value) {
-        if (endpointUuidBuilder_ == null) {
+      public context.ContextOuterClass.ServiceId getSubServiceIds(int index) {
+        if (subServiceIdsBuilder_ == null) {
+          return subServiceIds_.get(index);
+        } else {
+          return subServiceIdsBuilder_.getMessage(index);
+        }
+      }
+      /**
+       * <code>repeated .context.ServiceId sub_service_ids = 4;</code>
+       */
+      public Builder setSubServiceIds(
+          int index, context.ContextOuterClass.ServiceId value) {
+        if (subServiceIdsBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
           }
-          endpointUuid_ = value;
+          ensureSubServiceIdsIsMutable();
+          subServiceIds_.set(index, value);
           onChanged();
         } else {
-          endpointUuidBuilder_.setMessage(value);
+          subServiceIdsBuilder_.setMessage(index, value);
         }
-
         return this;
       }
       /**
-       * <code>.context.Uuid endpoint_uuid = 3;</code>
+       * <code>repeated .context.ServiceId sub_service_ids = 4;</code>
        */
-      public Builder setEndpointUuid(
-          context.ContextOuterClass.Uuid.Builder builderForValue) {
-        if (endpointUuidBuilder_ == null) {
-          endpointUuid_ = builderForValue.build();
+      public Builder setSubServiceIds(
+          int index, context.ContextOuterClass.ServiceId.Builder builderForValue) {
+        if (subServiceIdsBuilder_ == null) {
+          ensureSubServiceIdsIsMutable();
+          subServiceIds_.set(index, builderForValue.build());
           onChanged();
         } else {
-          endpointUuidBuilder_.setMessage(builderForValue.build());
+          subServiceIdsBuilder_.setMessage(index, builderForValue.build());
         }
-
         return this;
       }
       /**
-       * <code>.context.Uuid endpoint_uuid = 3;</code>
+       * <code>repeated .context.ServiceId sub_service_ids = 4;</code>
        */
-      public Builder mergeEndpointUuid(context.ContextOuterClass.Uuid value) {
-        if (endpointUuidBuilder_ == null) {
-          if (endpointUuid_ != null) {
-            endpointUuid_ =
-              context.ContextOuterClass.Uuid.newBuilder(endpointUuid_).mergeFrom(value).buildPartial();
-          } else {
-            endpointUuid_ = value;
+      public Builder addSubServiceIds(context.ContextOuterClass.ServiceId value) {
+        if (subServiceIdsBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
           }
+          ensureSubServiceIdsIsMutable();
+          subServiceIds_.add(value);
           onChanged();
         } else {
-          endpointUuidBuilder_.mergeFrom(value);
+          subServiceIdsBuilder_.addMessage(value);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .context.ServiceId sub_service_ids = 4;</code>
+       */
+      public Builder addSubServiceIds(
+          int index, context.ContextOuterClass.ServiceId value) {
+        if (subServiceIdsBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensureSubServiceIdsIsMutable();
+          subServiceIds_.add(index, value);
+          onChanged();
+        } else {
+          subServiceIdsBuilder_.addMessage(index, value);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .context.ServiceId sub_service_ids = 4;</code>
+       */
+      public Builder addSubServiceIds(
+          context.ContextOuterClass.ServiceId.Builder builderForValue) {
+        if (subServiceIdsBuilder_ == null) {
+          ensureSubServiceIdsIsMutable();
+          subServiceIds_.add(builderForValue.build());
+          onChanged();
+        } else {
+          subServiceIdsBuilder_.addMessage(builderForValue.build());
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .context.ServiceId sub_service_ids = 4;</code>
+       */
+      public Builder addSubServiceIds(
+          int index, context.ContextOuterClass.ServiceId.Builder builderForValue) {
+        if (subServiceIdsBuilder_ == null) {
+          ensureSubServiceIdsIsMutable();
+          subServiceIds_.add(index, builderForValue.build());
+          onChanged();
+        } else {
+          subServiceIdsBuilder_.addMessage(index, builderForValue.build());
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .context.ServiceId sub_service_ids = 4;</code>
+       */
+      public Builder addAllSubServiceIds(
+          java.lang.Iterable<? extends context.ContextOuterClass.ServiceId> values) {
+        if (subServiceIdsBuilder_ == null) {
+          ensureSubServiceIdsIsMutable();
+          com.google.protobuf.AbstractMessageLite.Builder.addAll(
+              values, subServiceIds_);
+          onChanged();
+        } else {
+          subServiceIdsBuilder_.addAllMessages(values);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .context.ServiceId sub_service_ids = 4;</code>
+       */
+      public Builder clearSubServiceIds() {
+        if (subServiceIdsBuilder_ == null) {
+          subServiceIds_ = java.util.Collections.emptyList();
+          bitField0_ = (bitField0_ & ~0x00000002);
+          onChanged();
+        } else {
+          subServiceIdsBuilder_.clear();
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .context.ServiceId sub_service_ids = 4;</code>
+       */
+      public Builder removeSubServiceIds(int index) {
+        if (subServiceIdsBuilder_ == null) {
+          ensureSubServiceIdsIsMutable();
+          subServiceIds_.remove(index);
+          onChanged();
+        } else {
+          subServiceIdsBuilder_.remove(index);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .context.ServiceId sub_service_ids = 4;</code>
+       */
+      public context.ContextOuterClass.ServiceId.Builder getSubServiceIdsBuilder(
+          int index) {
+        return getSubServiceIdsFieldBuilder().getBuilder(index);
+      }
+      /**
+       * <code>repeated .context.ServiceId sub_service_ids = 4;</code>
+       */
+      public context.ContextOuterClass.ServiceIdOrBuilder getSubServiceIdsOrBuilder(
+          int index) {
+        if (subServiceIdsBuilder_ == null) {
+          return subServiceIds_.get(index);  } else {
+          return subServiceIdsBuilder_.getMessageOrBuilder(index);
         }
-
-        return this;
       }
       /**
-       * <code>.context.Uuid endpoint_uuid = 3;</code>
+       * <code>repeated .context.ServiceId sub_service_ids = 4;</code>
        */
-      public Builder clearEndpointUuid() {
-        if (endpointUuidBuilder_ == null) {
-          endpointUuid_ = null;
-          onChanged();
+      public java.util.List<? extends context.ContextOuterClass.ServiceIdOrBuilder> 
+           getSubServiceIdsOrBuilderList() {
+        if (subServiceIdsBuilder_ != null) {
+          return subServiceIdsBuilder_.getMessageOrBuilderList();
         } else {
-          endpointUuid_ = null;
-          endpointUuidBuilder_ = null;
+          return java.util.Collections.unmodifiableList(subServiceIds_);
         }
-
-        return this;
       }
       /**
-       * <code>.context.Uuid endpoint_uuid = 3;</code>
+       * <code>repeated .context.ServiceId sub_service_ids = 4;</code>
        */
-      public context.ContextOuterClass.Uuid.Builder getEndpointUuidBuilder() {
-        
-        onChanged();
-        return getEndpointUuidFieldBuilder().getBuilder();
+      public context.ContextOuterClass.ServiceId.Builder addSubServiceIdsBuilder() {
+        return getSubServiceIdsFieldBuilder().addBuilder(
+            context.ContextOuterClass.ServiceId.getDefaultInstance());
       }
       /**
-       * <code>.context.Uuid endpoint_uuid = 3;</code>
+       * <code>repeated .context.ServiceId sub_service_ids = 4;</code>
        */
-      public context.ContextOuterClass.UuidOrBuilder getEndpointUuidOrBuilder() {
-        if (endpointUuidBuilder_ != null) {
-          return endpointUuidBuilder_.getMessageOrBuilder();
-        } else {
-          return endpointUuid_ == null ?
-              context.ContextOuterClass.Uuid.getDefaultInstance() : endpointUuid_;
-        }
+      public context.ContextOuterClass.ServiceId.Builder addSubServiceIdsBuilder(
+          int index) {
+        return getSubServiceIdsFieldBuilder().addBuilder(
+            index, context.ContextOuterClass.ServiceId.getDefaultInstance());
       }
       /**
-       * <code>.context.Uuid endpoint_uuid = 3;</code>
+       * <code>repeated .context.ServiceId sub_service_ids = 4;</code>
        */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          context.ContextOuterClass.Uuid, context.ContextOuterClass.Uuid.Builder, context.ContextOuterClass.UuidOrBuilder> 
-          getEndpointUuidFieldBuilder() {
-        if (endpointUuidBuilder_ == null) {
-          endpointUuidBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              context.ContextOuterClass.Uuid, context.ContextOuterClass.Uuid.Builder, context.ContextOuterClass.UuidOrBuilder>(
-                  getEndpointUuid(),
+      public java.util.List<context.ContextOuterClass.ServiceId.Builder> 
+           getSubServiceIdsBuilderList() {
+        return getSubServiceIdsFieldBuilder().getBuilderList();
+      }
+      private com.google.protobuf.RepeatedFieldBuilderV3<
+          context.ContextOuterClass.ServiceId, context.ContextOuterClass.ServiceId.Builder, context.ContextOuterClass.ServiceIdOrBuilder> 
+          getSubServiceIdsFieldBuilder() {
+        if (subServiceIdsBuilder_ == null) {
+          subServiceIdsBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3<
+              context.ContextOuterClass.ServiceId, context.ContextOuterClass.ServiceId.Builder, context.ContextOuterClass.ServiceIdOrBuilder>(
+                  subServiceIds_,
+                  ((bitField0_ & 0x00000002) != 0),
                   getParentForChildren(),
                   isClean());
-          endpointUuid_ = null;
+          subServiceIds_ = null;
         }
-        return endpointUuidBuilder_;
+        return subServiceIdsBuilder_;
       }
       @java.lang.Override
       public final Builder setUnknownFields(
@@ -28648,128 +29813,95 @@ public final class ContextOuterClass {
       }
 
 
-      // @@protoc_insertion_point(builder_scope:context.EndPointId)
+      // @@protoc_insertion_point(builder_scope:context.Connection)
     }
 
-    // @@protoc_insertion_point(class_scope:context.EndPointId)
-    private static final context.ContextOuterClass.EndPointId DEFAULT_INSTANCE;
+    // @@protoc_insertion_point(class_scope:context.Connection)
+    private static final context.ContextOuterClass.Connection DEFAULT_INSTANCE;
     static {
-      DEFAULT_INSTANCE = new context.ContextOuterClass.EndPointId();
+      DEFAULT_INSTANCE = new context.ContextOuterClass.Connection();
     }
 
-    public static context.ContextOuterClass.EndPointId getDefaultInstance() {
+    public static context.ContextOuterClass.Connection getDefaultInstance() {
       return DEFAULT_INSTANCE;
     }
 
-    private static final com.google.protobuf.Parser<EndPointId>
-        PARSER = new com.google.protobuf.AbstractParser<EndPointId>() {
+    private static final com.google.protobuf.Parser<Connection>
+        PARSER = new com.google.protobuf.AbstractParser<Connection>() {
       @java.lang.Override
-      public EndPointId parsePartialFrom(
+      public Connection parsePartialFrom(
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws com.google.protobuf.InvalidProtocolBufferException {
-        return new EndPointId(input, extensionRegistry);
+        return new Connection(input, extensionRegistry);
       }
     };
 
-    public static com.google.protobuf.Parser<EndPointId> parser() {
+    public static com.google.protobuf.Parser<Connection> parser() {
       return PARSER;
     }
 
     @java.lang.Override
-    public com.google.protobuf.Parser<EndPointId> getParserForType() {
+    public com.google.protobuf.Parser<Connection> getParserForType() {
       return PARSER;
     }
 
     @java.lang.Override
-    public context.ContextOuterClass.EndPointId getDefaultInstanceForType() {
+    public context.ContextOuterClass.Connection getDefaultInstanceForType() {
       return DEFAULT_INSTANCE;
     }
 
   }
 
-  public interface EndPointOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:context.EndPoint)
+  public interface ConnectionIdListOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:context.ConnectionIdList)
       com.google.protobuf.MessageOrBuilder {
 
     /**
-     * <code>.context.EndPointId endpoint_id = 1;</code>
-     * @return Whether the endpointId field is set.
-     */
-    boolean hasEndpointId();
-    /**
-     * <code>.context.EndPointId endpoint_id = 1;</code>
-     * @return The endpointId.
-     */
-    context.ContextOuterClass.EndPointId getEndpointId();
-    /**
-     * <code>.context.EndPointId endpoint_id = 1;</code>
-     */
-    context.ContextOuterClass.EndPointIdOrBuilder getEndpointIdOrBuilder();
-
-    /**
-     * <code>string endpoint_type = 2;</code>
-     * @return The endpointType.
-     */
-    java.lang.String getEndpointType();
-    /**
-     * <code>string endpoint_type = 2;</code>
-     * @return The bytes for endpointType.
-     */
-    com.google.protobuf.ByteString
-        getEndpointTypeBytes();
-
-    /**
-     * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
-     * @return A list containing the kpiSampleTypes.
+     * <code>repeated .context.ConnectionId connection_ids = 1;</code>
      */
-    java.util.List<kpi_sample_types.KpiSampleTypes.KpiSampleType> getKpiSampleTypesList();
+    java.util.List<context.ContextOuterClass.ConnectionId> 
+        getConnectionIdsList();
     /**
-     * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
-     * @return The count of kpiSampleTypes.
+     * <code>repeated .context.ConnectionId connection_ids = 1;</code>
      */
-    int getKpiSampleTypesCount();
+    context.ContextOuterClass.ConnectionId getConnectionIds(int index);
     /**
-     * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
-     * @param index The index of the element to return.
-     * @return The kpiSampleTypes at the given index.
+     * <code>repeated .context.ConnectionId connection_ids = 1;</code>
      */
-    kpi_sample_types.KpiSampleTypes.KpiSampleType getKpiSampleTypes(int index);
+    int getConnectionIdsCount();
     /**
-     * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
-     * @return A list containing the enum numeric values on the wire for kpiSampleTypes.
+     * <code>repeated .context.ConnectionId connection_ids = 1;</code>
      */
-    java.util.List<java.lang.Integer>
-    getKpiSampleTypesValueList();
+    java.util.List<? extends context.ContextOuterClass.ConnectionIdOrBuilder> 
+        getConnectionIdsOrBuilderList();
     /**
-     * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
-     * @param index The index of the value to return.
-     * @return The enum numeric value on the wire of kpiSampleTypes at the given index.
+     * <code>repeated .context.ConnectionId connection_ids = 1;</code>
      */
-    int getKpiSampleTypesValue(int index);
+    context.ContextOuterClass.ConnectionIdOrBuilder getConnectionIdsOrBuilder(
+        int index);
   }
   /**
-   * Protobuf type {@code context.EndPoint}
+   * Protobuf type {@code context.ConnectionIdList}
    */
-  public static final class EndPoint extends
+  public static final class ConnectionIdList extends
       com.google.protobuf.GeneratedMessageV3 implements
-      // @@protoc_insertion_point(message_implements:context.EndPoint)
-      EndPointOrBuilder {
+      // @@protoc_insertion_point(message_implements:context.ConnectionIdList)
+      ConnectionIdListOrBuilder {
   private static final long serialVersionUID = 0L;
-    // Use EndPoint.newBuilder() to construct.
-    private EndPoint(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
+    // Use ConnectionIdList.newBuilder() to construct.
+    private ConnectionIdList(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
       super(builder);
     }
-    private EndPoint() {
-      endpointType_ = "";
-      kpiSampleTypes_ = java.util.Collections.emptyList();
+    private ConnectionIdList() {
+      connectionIds_ = java.util.Collections.emptyList();
     }
 
     @java.lang.Override
     @SuppressWarnings({"unused"})
     protected java.lang.Object newInstance(
         UnusedPrivateParameter unused) {
-      return new EndPoint();
+      return new ConnectionIdList();
     }
 
     @java.lang.Override
@@ -28777,7 +29909,7 @@ public final class ContextOuterClass {
     getUnknownFields() {
       return this.unknownFields;
     }
-    private EndPoint(
+    private ConnectionIdList(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
@@ -28797,45 +29929,12 @@ public final class ContextOuterClass {
               done = true;
               break;
             case 10: {
-              context.ContextOuterClass.EndPointId.Builder subBuilder = null;
-              if (endpointId_ != null) {
-                subBuilder = endpointId_.toBuilder();
-              }
-              endpointId_ = input.readMessage(context.ContextOuterClass.EndPointId.parser(), extensionRegistry);
-              if (subBuilder != null) {
-                subBuilder.mergeFrom(endpointId_);
-                endpointId_ = subBuilder.buildPartial();
-              }
-
-              break;
-            }
-            case 18: {
-              java.lang.String s = input.readStringRequireUtf8();
-
-              endpointType_ = s;
-              break;
-            }
-            case 24: {
-              int rawValue = input.readEnum();
               if (!((mutable_bitField0_ & 0x00000001) != 0)) {
-                kpiSampleTypes_ = new java.util.ArrayList<java.lang.Integer>();
+                connectionIds_ = new java.util.ArrayList<context.ContextOuterClass.ConnectionId>();
                 mutable_bitField0_ |= 0x00000001;
               }
-              kpiSampleTypes_.add(rawValue);
-              break;
-            }
-            case 26: {
-              int length = input.readRawVarint32();
-              int oldLimit = input.pushLimit(length);
-              while(input.getBytesUntilLimit() > 0) {
-                int rawValue = input.readEnum();
-                if (!((mutable_bitField0_ & 0x00000001) != 0)) {
-                  kpiSampleTypes_ = new java.util.ArrayList<java.lang.Integer>();
-                  mutable_bitField0_ |= 0x00000001;
-                }
-                kpiSampleTypes_.add(rawValue);
-              }
-              input.popLimit(oldLimit);
+              connectionIds_.add(
+                  input.readMessage(context.ContextOuterClass.ConnectionId.parser(), extensionRegistry));
               break;
             }
             default: {
@@ -28850,150 +29949,68 @@ public final class ContextOuterClass {
       } catch (com.google.protobuf.InvalidProtocolBufferException e) {
         throw e.setUnfinishedMessage(this);
       } catch (java.io.IOException e) {
-        throw new com.google.protobuf.InvalidProtocolBufferException(
-            e).setUnfinishedMessage(this);
-      } finally {
-        if (((mutable_bitField0_ & 0x00000001) != 0)) {
-          kpiSampleTypes_ = java.util.Collections.unmodifiableList(kpiSampleTypes_);
-        }
-        this.unknownFields = unknownFields.build();
-        makeExtensionsImmutable();
-      }
-    }
-    public static final com.google.protobuf.Descriptors.Descriptor
-        getDescriptor() {
-      return context.ContextOuterClass.internal_static_context_EndPoint_descriptor;
-    }
-
-    @java.lang.Override
-    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-        internalGetFieldAccessorTable() {
-      return context.ContextOuterClass.internal_static_context_EndPoint_fieldAccessorTable
-          .ensureFieldAccessorsInitialized(
-              context.ContextOuterClass.EndPoint.class, context.ContextOuterClass.EndPoint.Builder.class);
-    }
-
-    public static final int ENDPOINT_ID_FIELD_NUMBER = 1;
-    private context.ContextOuterClass.EndPointId endpointId_;
-    /**
-     * <code>.context.EndPointId endpoint_id = 1;</code>
-     * @return Whether the endpointId field is set.
-     */
-    @java.lang.Override
-    public boolean hasEndpointId() {
-      return endpointId_ != null;
-    }
-    /**
-     * <code>.context.EndPointId endpoint_id = 1;</code>
-     * @return The endpointId.
-     */
-    @java.lang.Override
-    public context.ContextOuterClass.EndPointId getEndpointId() {
-      return endpointId_ == null ? context.ContextOuterClass.EndPointId.getDefaultInstance() : endpointId_;
-    }
-    /**
-     * <code>.context.EndPointId endpoint_id = 1;</code>
-     */
-    @java.lang.Override
-    public context.ContextOuterClass.EndPointIdOrBuilder getEndpointIdOrBuilder() {
-      return getEndpointId();
-    }
-
-    public static final int ENDPOINT_TYPE_FIELD_NUMBER = 2;
-    private volatile java.lang.Object endpointType_;
-    /**
-     * <code>string endpoint_type = 2;</code>
-     * @return The endpointType.
-     */
-    @java.lang.Override
-    public java.lang.String getEndpointType() {
-      java.lang.Object ref = endpointType_;
-      if (ref instanceof java.lang.String) {
-        return (java.lang.String) ref;
-      } else {
-        com.google.protobuf.ByteString bs = 
-            (com.google.protobuf.ByteString) ref;
-        java.lang.String s = bs.toStringUtf8();
-        endpointType_ = s;
-        return s;
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e).setUnfinishedMessage(this);
+      } finally {
+        if (((mutable_bitField0_ & 0x00000001) != 0)) {
+          connectionIds_ = java.util.Collections.unmodifiableList(connectionIds_);
+        }
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
       }
     }
-    /**
-     * <code>string endpoint_type = 2;</code>
-     * @return The bytes for endpointType.
-     */
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return context.ContextOuterClass.internal_static_context_ConnectionIdList_descriptor;
+    }
+
     @java.lang.Override
-    public com.google.protobuf.ByteString
-        getEndpointTypeBytes() {
-      java.lang.Object ref = endpointType_;
-      if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
-            com.google.protobuf.ByteString.copyFromUtf8(
-                (java.lang.String) ref);
-        endpointType_ = b;
-        return b;
-      } else {
-        return (com.google.protobuf.ByteString) ref;
-      }
+    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return context.ContextOuterClass.internal_static_context_ConnectionIdList_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              context.ContextOuterClass.ConnectionIdList.class, context.ContextOuterClass.ConnectionIdList.Builder.class);
     }
 
-    public static final int KPI_SAMPLE_TYPES_FIELD_NUMBER = 3;
-    private java.util.List<java.lang.Integer> kpiSampleTypes_;
-    private static final com.google.protobuf.Internal.ListAdapter.Converter<
-        java.lang.Integer, kpi_sample_types.KpiSampleTypes.KpiSampleType> kpiSampleTypes_converter_ =
-            new com.google.protobuf.Internal.ListAdapter.Converter<
-                java.lang.Integer, kpi_sample_types.KpiSampleTypes.KpiSampleType>() {
-              public kpi_sample_types.KpiSampleTypes.KpiSampleType convert(java.lang.Integer from) {
-                @SuppressWarnings("deprecation")
-                kpi_sample_types.KpiSampleTypes.KpiSampleType result = kpi_sample_types.KpiSampleTypes.KpiSampleType.valueOf(from);
-                return result == null ? kpi_sample_types.KpiSampleTypes.KpiSampleType.UNRECOGNIZED : result;
-              }
-            };
+    public static final int CONNECTION_IDS_FIELD_NUMBER = 1;
+    private java.util.List<context.ContextOuterClass.ConnectionId> connectionIds_;
     /**
-     * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
-     * @return A list containing the kpiSampleTypes.
+     * <code>repeated .context.ConnectionId connection_ids = 1;</code>
      */
     @java.lang.Override
-    public java.util.List<kpi_sample_types.KpiSampleTypes.KpiSampleType> getKpiSampleTypesList() {
-      return new com.google.protobuf.Internal.ListAdapter<
-          java.lang.Integer, kpi_sample_types.KpiSampleTypes.KpiSampleType>(kpiSampleTypes_, kpiSampleTypes_converter_);
+    public java.util.List<context.ContextOuterClass.ConnectionId> getConnectionIdsList() {
+      return connectionIds_;
     }
     /**
-     * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
-     * @return The count of kpiSampleTypes.
+     * <code>repeated .context.ConnectionId connection_ids = 1;</code>
      */
     @java.lang.Override
-    public int getKpiSampleTypesCount() {
-      return kpiSampleTypes_.size();
+    public java.util.List<? extends context.ContextOuterClass.ConnectionIdOrBuilder> 
+        getConnectionIdsOrBuilderList() {
+      return connectionIds_;
     }
     /**
-     * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
-     * @param index The index of the element to return.
-     * @return The kpiSampleTypes at the given index.
+     * <code>repeated .context.ConnectionId connection_ids = 1;</code>
      */
     @java.lang.Override
-    public kpi_sample_types.KpiSampleTypes.KpiSampleType getKpiSampleTypes(int index) {
-      return kpiSampleTypes_converter_.convert(kpiSampleTypes_.get(index));
+    public int getConnectionIdsCount() {
+      return connectionIds_.size();
     }
     /**
-     * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
-     * @return A list containing the enum numeric values on the wire for kpiSampleTypes.
+     * <code>repeated .context.ConnectionId connection_ids = 1;</code>
      */
     @java.lang.Override
-    public java.util.List<java.lang.Integer>
-    getKpiSampleTypesValueList() {
-      return kpiSampleTypes_;
+    public context.ContextOuterClass.ConnectionId getConnectionIds(int index) {
+      return connectionIds_.get(index);
     }
     /**
-     * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
-     * @param index The index of the value to return.
-     * @return The enum numeric value on the wire of kpiSampleTypes at the given index.
+     * <code>repeated .context.ConnectionId connection_ids = 1;</code>
      */
     @java.lang.Override
-    public int getKpiSampleTypesValue(int index) {
-      return kpiSampleTypes_.get(index);
+    public context.ContextOuterClass.ConnectionIdOrBuilder getConnectionIdsOrBuilder(
+        int index) {
+      return connectionIds_.get(index);
     }
-    private int kpiSampleTypesMemoizedSerializedSize;
 
     private byte memoizedIsInitialized = -1;
     @java.lang.Override
@@ -29009,19 +30026,8 @@ public final class ContextOuterClass {
     @java.lang.Override
     public void writeTo(com.google.protobuf.CodedOutputStream output)
                         throws java.io.IOException {
-      getSerializedSize();
-      if (endpointId_ != null) {
-        output.writeMessage(1, getEndpointId());
-      }
-      if (!getEndpointTypeBytes().isEmpty()) {
-        com.google.protobuf.GeneratedMessageV3.writeString(output, 2, endpointType_);
-      }
-      if (getKpiSampleTypesList().size() > 0) {
-        output.writeUInt32NoTag(26);
-        output.writeUInt32NoTag(kpiSampleTypesMemoizedSerializedSize);
-      }
-      for (int i = 0; i < kpiSampleTypes_.size(); i++) {
-        output.writeEnumNoTag(kpiSampleTypes_.get(i));
+      for (int i = 0; i < connectionIds_.size(); i++) {
+        output.writeMessage(1, connectionIds_.get(i));
       }
       unknownFields.writeTo(output);
     }
@@ -29032,24 +30038,9 @@ public final class ContextOuterClass {
       if (size != -1) return size;
 
       size = 0;
-      if (endpointId_ != null) {
+      for (int i = 0; i < connectionIds_.size(); i++) {
         size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(1, getEndpointId());
-      }
-      if (!getEndpointTypeBytes().isEmpty()) {
-        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, endpointType_);
-      }
-      {
-        int dataSize = 0;
-        for (int i = 0; i < kpiSampleTypes_.size(); i++) {
-          dataSize += com.google.protobuf.CodedOutputStream
-            .computeEnumSizeNoTag(kpiSampleTypes_.get(i));
-        }
-        size += dataSize;
-        if (!getKpiSampleTypesList().isEmpty()) {  size += 1;
-          size += com.google.protobuf.CodedOutputStream
-            .computeUInt32SizeNoTag(dataSize);
-        }kpiSampleTypesMemoizedSerializedSize = dataSize;
+          .computeMessageSize(1, connectionIds_.get(i));
       }
       size += unknownFields.getSerializedSize();
       memoizedSize = size;
@@ -29061,19 +30052,13 @@ public final class ContextOuterClass {
       if (obj == this) {
        return true;
       }
-      if (!(obj instanceof context.ContextOuterClass.EndPoint)) {
+      if (!(obj instanceof context.ContextOuterClass.ConnectionIdList)) {
         return super.equals(obj);
       }
-      context.ContextOuterClass.EndPoint other = (context.ContextOuterClass.EndPoint) obj;
+      context.ContextOuterClass.ConnectionIdList other = (context.ContextOuterClass.ConnectionIdList) obj;
 
-      if (hasEndpointId() != other.hasEndpointId()) return false;
-      if (hasEndpointId()) {
-        if (!getEndpointId()
-            .equals(other.getEndpointId())) return false;
-      }
-      if (!getEndpointType()
-          .equals(other.getEndpointType())) return false;
-      if (!kpiSampleTypes_.equals(other.kpiSampleTypes_)) return false;
+      if (!getConnectionIdsList()
+          .equals(other.getConnectionIdsList())) return false;
       if (!unknownFields.equals(other.unknownFields)) return false;
       return true;
     }
@@ -29085,84 +30070,78 @@ public final class ContextOuterClass {
       }
       int hash = 41;
       hash = (19 * hash) + getDescriptor().hashCode();
-      if (hasEndpointId()) {
-        hash = (37 * hash) + ENDPOINT_ID_FIELD_NUMBER;
-        hash = (53 * hash) + getEndpointId().hashCode();
-      }
-      hash = (37 * hash) + ENDPOINT_TYPE_FIELD_NUMBER;
-      hash = (53 * hash) + getEndpointType().hashCode();
-      if (getKpiSampleTypesCount() > 0) {
-        hash = (37 * hash) + KPI_SAMPLE_TYPES_FIELD_NUMBER;
-        hash = (53 * hash) + kpiSampleTypes_.hashCode();
+      if (getConnectionIdsCount() > 0) {
+        hash = (37 * hash) + CONNECTION_IDS_FIELD_NUMBER;
+        hash = (53 * hash) + getConnectionIdsList().hashCode();
       }
       hash = (29 * hash) + unknownFields.hashCode();
       memoizedHashCode = hash;
       return hash;
     }
 
-    public static context.ContextOuterClass.EndPoint parseFrom(
+    public static context.ContextOuterClass.ConnectionIdList parseFrom(
         java.nio.ByteBuffer data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static context.ContextOuterClass.EndPoint parseFrom(
+    public static context.ContextOuterClass.ConnectionIdList parseFrom(
         java.nio.ByteBuffer data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static context.ContextOuterClass.EndPoint parseFrom(
+    public static context.ContextOuterClass.ConnectionIdList parseFrom(
         com.google.protobuf.ByteString data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static context.ContextOuterClass.EndPoint parseFrom(
+    public static context.ContextOuterClass.ConnectionIdList parseFrom(
         com.google.protobuf.ByteString data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static context.ContextOuterClass.EndPoint parseFrom(byte[] data)
+    public static context.ContextOuterClass.ConnectionIdList parseFrom(byte[] data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static context.ContextOuterClass.EndPoint parseFrom(
+    public static context.ContextOuterClass.ConnectionIdList parseFrom(
         byte[] data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static context.ContextOuterClass.EndPoint parseFrom(java.io.InputStream input)
+    public static context.ContextOuterClass.ConnectionIdList parseFrom(java.io.InputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseWithIOException(PARSER, input);
     }
-    public static context.ContextOuterClass.EndPoint parseFrom(
+    public static context.ContextOuterClass.ConnectionIdList parseFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseWithIOException(PARSER, input, extensionRegistry);
     }
-    public static context.ContextOuterClass.EndPoint parseDelimitedFrom(java.io.InputStream input)
+    public static context.ContextOuterClass.ConnectionIdList parseDelimitedFrom(java.io.InputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseDelimitedWithIOException(PARSER, input);
     }
-    public static context.ContextOuterClass.EndPoint parseDelimitedFrom(
+    public static context.ContextOuterClass.ConnectionIdList parseDelimitedFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
     }
-    public static context.ContextOuterClass.EndPoint parseFrom(
+    public static context.ContextOuterClass.ConnectionIdList parseFrom(
         com.google.protobuf.CodedInputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseWithIOException(PARSER, input);
     }
-    public static context.ContextOuterClass.EndPoint parseFrom(
+    public static context.ContextOuterClass.ConnectionIdList parseFrom(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -29175,7 +30154,7 @@ public final class ContextOuterClass {
     public static Builder newBuilder() {
       return DEFAULT_INSTANCE.toBuilder();
     }
-    public static Builder newBuilder(context.ContextOuterClass.EndPoint prototype) {
+    public static Builder newBuilder(context.ContextOuterClass.ConnectionIdList prototype) {
       return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
     }
     @java.lang.Override
@@ -29191,26 +30170,26 @@ public final class ContextOuterClass {
       return builder;
     }
     /**
-     * Protobuf type {@code context.EndPoint}
+     * Protobuf type {@code context.ConnectionIdList}
      */
     public static final class Builder extends
         com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:context.EndPoint)
-        context.ContextOuterClass.EndPointOrBuilder {
+        // @@protoc_insertion_point(builder_implements:context.ConnectionIdList)
+        context.ContextOuterClass.ConnectionIdListOrBuilder {
       public static final com.google.protobuf.Descriptors.Descriptor
           getDescriptor() {
-        return context.ContextOuterClass.internal_static_context_EndPoint_descriptor;
+        return context.ContextOuterClass.internal_static_context_ConnectionIdList_descriptor;
       }
 
       @java.lang.Override
       protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
           internalGetFieldAccessorTable() {
-        return context.ContextOuterClass.internal_static_context_EndPoint_fieldAccessorTable
+        return context.ContextOuterClass.internal_static_context_ConnectionIdList_fieldAccessorTable
             .ensureFieldAccessorsInitialized(
-                context.ContextOuterClass.EndPoint.class, context.ContextOuterClass.EndPoint.Builder.class);
+                context.ContextOuterClass.ConnectionIdList.class, context.ContextOuterClass.ConnectionIdList.Builder.class);
       }
 
-      // Construct using context.ContextOuterClass.EndPoint.newBuilder()
+      // Construct using context.ContextOuterClass.ConnectionIdList.newBuilder()
       private Builder() {
         maybeForceBuilderInitialization();
       }
@@ -29223,38 +30202,35 @@ public final class ContextOuterClass {
       private void maybeForceBuilderInitialization() {
         if (com.google.protobuf.GeneratedMessageV3
                 .alwaysUseFieldBuilders) {
+          getConnectionIdsFieldBuilder();
         }
       }
       @java.lang.Override
       public Builder clear() {
         super.clear();
-        if (endpointIdBuilder_ == null) {
-          endpointId_ = null;
+        if (connectionIdsBuilder_ == null) {
+          connectionIds_ = java.util.Collections.emptyList();
+          bitField0_ = (bitField0_ & ~0x00000001);
         } else {
-          endpointId_ = null;
-          endpointIdBuilder_ = null;
+          connectionIdsBuilder_.clear();
         }
-        endpointType_ = "";
-
-        kpiSampleTypes_ = java.util.Collections.emptyList();
-        bitField0_ = (bitField0_ & ~0x00000001);
         return this;
       }
 
       @java.lang.Override
       public com.google.protobuf.Descriptors.Descriptor
           getDescriptorForType() {
-        return context.ContextOuterClass.internal_static_context_EndPoint_descriptor;
+        return context.ContextOuterClass.internal_static_context_ConnectionIdList_descriptor;
       }
 
       @java.lang.Override
-      public context.ContextOuterClass.EndPoint getDefaultInstanceForType() {
-        return context.ContextOuterClass.EndPoint.getDefaultInstance();
+      public context.ContextOuterClass.ConnectionIdList getDefaultInstanceForType() {
+        return context.ContextOuterClass.ConnectionIdList.getDefaultInstance();
       }
 
       @java.lang.Override
-      public context.ContextOuterClass.EndPoint build() {
-        context.ContextOuterClass.EndPoint result = buildPartial();
+      public context.ContextOuterClass.ConnectionIdList build() {
+        context.ContextOuterClass.ConnectionIdList result = buildPartial();
         if (!result.isInitialized()) {
           throw newUninitializedMessageException(result);
         }
@@ -29262,20 +30238,18 @@ public final class ContextOuterClass {
       }
 
       @java.lang.Override
-      public context.ContextOuterClass.EndPoint buildPartial() {
-        context.ContextOuterClass.EndPoint result = new context.ContextOuterClass.EndPoint(this);
+      public context.ContextOuterClass.ConnectionIdList buildPartial() {
+        context.ContextOuterClass.ConnectionIdList result = new context.ContextOuterClass.ConnectionIdList(this);
         int from_bitField0_ = bitField0_;
-        if (endpointIdBuilder_ == null) {
-          result.endpointId_ = endpointId_;
+        if (connectionIdsBuilder_ == null) {
+          if (((bitField0_ & 0x00000001) != 0)) {
+            connectionIds_ = java.util.Collections.unmodifiableList(connectionIds_);
+            bitField0_ = (bitField0_ & ~0x00000001);
+          }
+          result.connectionIds_ = connectionIds_;
         } else {
-          result.endpointId_ = endpointIdBuilder_.build();
-        }
-        result.endpointType_ = endpointType_;
-        if (((bitField0_ & 0x00000001) != 0)) {
-          kpiSampleTypes_ = java.util.Collections.unmodifiableList(kpiSampleTypes_);
-          bitField0_ = (bitField0_ & ~0x00000001);
+          result.connectionIds_ = connectionIdsBuilder_.build();
         }
-        result.kpiSampleTypes_ = kpiSampleTypes_;
         onBuilt();
         return result;
       }
@@ -29314,32 +30288,41 @@ public final class ContextOuterClass {
       }
       @java.lang.Override
       public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof context.ContextOuterClass.EndPoint) {
-          return mergeFrom((context.ContextOuterClass.EndPoint)other);
+        if (other instanceof context.ContextOuterClass.ConnectionIdList) {
+          return mergeFrom((context.ContextOuterClass.ConnectionIdList)other);
         } else {
           super.mergeFrom(other);
           return this;
         }
       }
 
-      public Builder mergeFrom(context.ContextOuterClass.EndPoint other) {
-        if (other == context.ContextOuterClass.EndPoint.getDefaultInstance()) return this;
-        if (other.hasEndpointId()) {
-          mergeEndpointId(other.getEndpointId());
-        }
-        if (!other.getEndpointType().isEmpty()) {
-          endpointType_ = other.endpointType_;
-          onChanged();
-        }
-        if (!other.kpiSampleTypes_.isEmpty()) {
-          if (kpiSampleTypes_.isEmpty()) {
-            kpiSampleTypes_ = other.kpiSampleTypes_;
-            bitField0_ = (bitField0_ & ~0x00000001);
-          } else {
-            ensureKpiSampleTypesIsMutable();
-            kpiSampleTypes_.addAll(other.kpiSampleTypes_);
+      public Builder mergeFrom(context.ContextOuterClass.ConnectionIdList other) {
+        if (other == context.ContextOuterClass.ConnectionIdList.getDefaultInstance()) return this;
+        if (connectionIdsBuilder_ == null) {
+          if (!other.connectionIds_.isEmpty()) {
+            if (connectionIds_.isEmpty()) {
+              connectionIds_ = other.connectionIds_;
+              bitField0_ = (bitField0_ & ~0x00000001);
+            } else {
+              ensureConnectionIdsIsMutable();
+              connectionIds_.addAll(other.connectionIds_);
+            }
+            onChanged();
+          }
+        } else {
+          if (!other.connectionIds_.isEmpty()) {
+            if (connectionIdsBuilder_.isEmpty()) {
+              connectionIdsBuilder_.dispose();
+              connectionIdsBuilder_ = null;
+              connectionIds_ = other.connectionIds_;
+              bitField0_ = (bitField0_ & ~0x00000001);
+              connectionIdsBuilder_ = 
+                com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ?
+                   getConnectionIdsFieldBuilder() : null;
+            } else {
+              connectionIdsBuilder_.addAllMessages(other.connectionIds_);
+            }
           }
-          onChanged();
         }
         this.mergeUnknownFields(other.unknownFields);
         onChanged();
@@ -29356,11 +30339,11 @@ public final class ContextOuterClass {
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws java.io.IOException {
-        context.ContextOuterClass.EndPoint parsedMessage = null;
+        context.ContextOuterClass.ConnectionIdList parsedMessage = null;
         try {
           parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
         } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          parsedMessage = (context.ContextOuterClass.EndPoint) e.getUnfinishedMessage();
+          parsedMessage = (context.ContextOuterClass.ConnectionIdList) e.getUnfinishedMessage();
           throw e.unwrapIOException();
         } finally {
           if (parsedMessage != null) {
@@ -29371,339 +30354,244 @@ public final class ContextOuterClass {
       }
       private int bitField0_;
 
-      private context.ContextOuterClass.EndPointId endpointId_;
-      private com.google.protobuf.SingleFieldBuilderV3<
-          context.ContextOuterClass.EndPointId, context.ContextOuterClass.EndPointId.Builder, context.ContextOuterClass.EndPointIdOrBuilder> endpointIdBuilder_;
-      /**
-       * <code>.context.EndPointId endpoint_id = 1;</code>
-       * @return Whether the endpointId field is set.
-       */
-      public boolean hasEndpointId() {
-        return endpointIdBuilder_ != null || endpointId_ != null;
+      private java.util.List<context.ContextOuterClass.ConnectionId> connectionIds_ =
+        java.util.Collections.emptyList();
+      private void ensureConnectionIdsIsMutable() {
+        if (!((bitField0_ & 0x00000001) != 0)) {
+          connectionIds_ = new java.util.ArrayList<context.ContextOuterClass.ConnectionId>(connectionIds_);
+          bitField0_ |= 0x00000001;
+         }
       }
+
+      private com.google.protobuf.RepeatedFieldBuilderV3<
+          context.ContextOuterClass.ConnectionId, context.ContextOuterClass.ConnectionId.Builder, context.ContextOuterClass.ConnectionIdOrBuilder> connectionIdsBuilder_;
+
       /**
-       * <code>.context.EndPointId endpoint_id = 1;</code>
-       * @return The endpointId.
+       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
        */
-      public context.ContextOuterClass.EndPointId getEndpointId() {
-        if (endpointIdBuilder_ == null) {
-          return endpointId_ == null ? context.ContextOuterClass.EndPointId.getDefaultInstance() : endpointId_;
+      public java.util.List<context.ContextOuterClass.ConnectionId> getConnectionIdsList() {
+        if (connectionIdsBuilder_ == null) {
+          return java.util.Collections.unmodifiableList(connectionIds_);
         } else {
-          return endpointIdBuilder_.getMessage();
+          return connectionIdsBuilder_.getMessageList();
         }
       }
       /**
-       * <code>.context.EndPointId endpoint_id = 1;</code>
+       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
        */
-      public Builder setEndpointId(context.ContextOuterClass.EndPointId value) {
-        if (endpointIdBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          endpointId_ = value;
-          onChanged();
+      public int getConnectionIdsCount() {
+        if (connectionIdsBuilder_ == null) {
+          return connectionIds_.size();
         } else {
-          endpointIdBuilder_.setMessage(value);
+          return connectionIdsBuilder_.getCount();
         }
-
-        return this;
       }
       /**
-       * <code>.context.EndPointId endpoint_id = 1;</code>
+       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
        */
-      public Builder setEndpointId(
-          context.ContextOuterClass.EndPointId.Builder builderForValue) {
-        if (endpointIdBuilder_ == null) {
-          endpointId_ = builderForValue.build();
-          onChanged();
+      public context.ContextOuterClass.ConnectionId getConnectionIds(int index) {
+        if (connectionIdsBuilder_ == null) {
+          return connectionIds_.get(index);
         } else {
-          endpointIdBuilder_.setMessage(builderForValue.build());
+          return connectionIdsBuilder_.getMessage(index);
         }
-
-        return this;
       }
       /**
-       * <code>.context.EndPointId endpoint_id = 1;</code>
+       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
        */
-      public Builder mergeEndpointId(context.ContextOuterClass.EndPointId value) {
-        if (endpointIdBuilder_ == null) {
-          if (endpointId_ != null) {
-            endpointId_ =
-              context.ContextOuterClass.EndPointId.newBuilder(endpointId_).mergeFrom(value).buildPartial();
-          } else {
-            endpointId_ = value;
+      public Builder setConnectionIds(
+          int index, context.ContextOuterClass.ConnectionId value) {
+        if (connectionIdsBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
           }
+          ensureConnectionIdsIsMutable();
+          connectionIds_.set(index, value);
           onChanged();
         } else {
-          endpointIdBuilder_.mergeFrom(value);
+          connectionIdsBuilder_.setMessage(index, value);
         }
-
         return this;
       }
       /**
-       * <code>.context.EndPointId endpoint_id = 1;</code>
+       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
        */
-      public Builder clearEndpointId() {
-        if (endpointIdBuilder_ == null) {
-          endpointId_ = null;
+      public Builder setConnectionIds(
+          int index, context.ContextOuterClass.ConnectionId.Builder builderForValue) {
+        if (connectionIdsBuilder_ == null) {
+          ensureConnectionIdsIsMutable();
+          connectionIds_.set(index, builderForValue.build());
           onChanged();
         } else {
-          endpointId_ = null;
-          endpointIdBuilder_ = null;
+          connectionIdsBuilder_.setMessage(index, builderForValue.build());
         }
-
         return this;
       }
       /**
-       * <code>.context.EndPointId endpoint_id = 1;</code>
-       */
-      public context.ContextOuterClass.EndPointId.Builder getEndpointIdBuilder() {
-        
-        onChanged();
-        return getEndpointIdFieldBuilder().getBuilder();
-      }
-      /**
-       * <code>.context.EndPointId endpoint_id = 1;</code>
-       */
-      public context.ContextOuterClass.EndPointIdOrBuilder getEndpointIdOrBuilder() {
-        if (endpointIdBuilder_ != null) {
-          return endpointIdBuilder_.getMessageOrBuilder();
-        } else {
-          return endpointId_ == null ?
-              context.ContextOuterClass.EndPointId.getDefaultInstance() : endpointId_;
-        }
-      }
-      /**
-       * <code>.context.EndPointId endpoint_id = 1;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          context.ContextOuterClass.EndPointId, context.ContextOuterClass.EndPointId.Builder, context.ContextOuterClass.EndPointIdOrBuilder> 
-          getEndpointIdFieldBuilder() {
-        if (endpointIdBuilder_ == null) {
-          endpointIdBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              context.ContextOuterClass.EndPointId, context.ContextOuterClass.EndPointId.Builder, context.ContextOuterClass.EndPointIdOrBuilder>(
-                  getEndpointId(),
-                  getParentForChildren(),
-                  isClean());
-          endpointId_ = null;
-        }
-        return endpointIdBuilder_;
-      }
-
-      private java.lang.Object endpointType_ = "";
-      /**
-       * <code>string endpoint_type = 2;</code>
-       * @return The endpointType.
-       */
-      public java.lang.String getEndpointType() {
-        java.lang.Object ref = endpointType_;
-        if (!(ref instanceof java.lang.String)) {
-          com.google.protobuf.ByteString bs =
-              (com.google.protobuf.ByteString) ref;
-          java.lang.String s = bs.toStringUtf8();
-          endpointType_ = s;
-          return s;
-        } else {
-          return (java.lang.String) ref;
-        }
-      }
-      /**
-       * <code>string endpoint_type = 2;</code>
-       * @return The bytes for endpointType.
+       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
        */
-      public com.google.protobuf.ByteString
-          getEndpointTypeBytes() {
-        java.lang.Object ref = endpointType_;
-        if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
-              com.google.protobuf.ByteString.copyFromUtf8(
-                  (java.lang.String) ref);
-          endpointType_ = b;
-          return b;
+      public Builder addConnectionIds(context.ContextOuterClass.ConnectionId value) {
+        if (connectionIdsBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensureConnectionIdsIsMutable();
+          connectionIds_.add(value);
+          onChanged();
         } else {
-          return (com.google.protobuf.ByteString) ref;
-        }
-      }
-      /**
-       * <code>string endpoint_type = 2;</code>
-       * @param value The endpointType to set.
-       * @return This builder for chaining.
-       */
-      public Builder setEndpointType(
-          java.lang.String value) {
-        if (value == null) {
-    throw new NullPointerException();
-  }
-  
-        endpointType_ = value;
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>string endpoint_type = 2;</code>
-       * @return This builder for chaining.
-       */
-      public Builder clearEndpointType() {
-        
-        endpointType_ = getDefaultInstance().getEndpointType();
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>string endpoint_type = 2;</code>
-       * @param value The bytes for endpointType to set.
-       * @return This builder for chaining.
-       */
-      public Builder setEndpointTypeBytes(
-          com.google.protobuf.ByteString value) {
-        if (value == null) {
-    throw new NullPointerException();
-  }
-  checkByteStringIsUtf8(value);
-        
-        endpointType_ = value;
-        onChanged();
-        return this;
-      }
-
-      private java.util.List<java.lang.Integer> kpiSampleTypes_ =
-        java.util.Collections.emptyList();
-      private void ensureKpiSampleTypesIsMutable() {
-        if (!((bitField0_ & 0x00000001) != 0)) {
-          kpiSampleTypes_ = new java.util.ArrayList<java.lang.Integer>(kpiSampleTypes_);
-          bitField0_ |= 0x00000001;
-        }
-      }
-      /**
-       * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
-       * @return A list containing the kpiSampleTypes.
-       */
-      public java.util.List<kpi_sample_types.KpiSampleTypes.KpiSampleType> getKpiSampleTypesList() {
-        return new com.google.protobuf.Internal.ListAdapter<
-            java.lang.Integer, kpi_sample_types.KpiSampleTypes.KpiSampleType>(kpiSampleTypes_, kpiSampleTypes_converter_);
+          connectionIdsBuilder_.addMessage(value);
+        }
+        return this;
       }
       /**
-       * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
-       * @return The count of kpiSampleTypes.
+       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
        */
-      public int getKpiSampleTypesCount() {
-        return kpiSampleTypes_.size();
+      public Builder addConnectionIds(
+          int index, context.ContextOuterClass.ConnectionId value) {
+        if (connectionIdsBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensureConnectionIdsIsMutable();
+          connectionIds_.add(index, value);
+          onChanged();
+        } else {
+          connectionIdsBuilder_.addMessage(index, value);
+        }
+        return this;
       }
       /**
-       * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
-       * @param index The index of the element to return.
-       * @return The kpiSampleTypes at the given index.
+       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
        */
-      public kpi_sample_types.KpiSampleTypes.KpiSampleType getKpiSampleTypes(int index) {
-        return kpiSampleTypes_converter_.convert(kpiSampleTypes_.get(index));
+      public Builder addConnectionIds(
+          context.ContextOuterClass.ConnectionId.Builder builderForValue) {
+        if (connectionIdsBuilder_ == null) {
+          ensureConnectionIdsIsMutable();
+          connectionIds_.add(builderForValue.build());
+          onChanged();
+        } else {
+          connectionIdsBuilder_.addMessage(builderForValue.build());
+        }
+        return this;
       }
       /**
-       * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
-       * @param index The index to set the value at.
-       * @param value The kpiSampleTypes to set.
-       * @return This builder for chaining.
+       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
        */
-      public Builder setKpiSampleTypes(
-          int index, kpi_sample_types.KpiSampleTypes.KpiSampleType value) {
-        if (value == null) {
-          throw new NullPointerException();
+      public Builder addConnectionIds(
+          int index, context.ContextOuterClass.ConnectionId.Builder builderForValue) {
+        if (connectionIdsBuilder_ == null) {
+          ensureConnectionIdsIsMutable();
+          connectionIds_.add(index, builderForValue.build());
+          onChanged();
+        } else {
+          connectionIdsBuilder_.addMessage(index, builderForValue.build());
         }
-        ensureKpiSampleTypesIsMutable();
-        kpiSampleTypes_.set(index, value.getNumber());
-        onChanged();
         return this;
       }
       /**
-       * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
-       * @param value The kpiSampleTypes to add.
-       * @return This builder for chaining.
+       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
        */
-      public Builder addKpiSampleTypes(kpi_sample_types.KpiSampleTypes.KpiSampleType value) {
-        if (value == null) {
-          throw new NullPointerException();
+      public Builder addAllConnectionIds(
+          java.lang.Iterable<? extends context.ContextOuterClass.ConnectionId> values) {
+        if (connectionIdsBuilder_ == null) {
+          ensureConnectionIdsIsMutable();
+          com.google.protobuf.AbstractMessageLite.Builder.addAll(
+              values, connectionIds_);
+          onChanged();
+        } else {
+          connectionIdsBuilder_.addAllMessages(values);
         }
-        ensureKpiSampleTypesIsMutable();
-        kpiSampleTypes_.add(value.getNumber());
-        onChanged();
         return this;
       }
       /**
-       * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
-       * @param values The kpiSampleTypes to add.
-       * @return This builder for chaining.
+       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
        */
-      public Builder addAllKpiSampleTypes(
-          java.lang.Iterable<? extends kpi_sample_types.KpiSampleTypes.KpiSampleType> values) {
-        ensureKpiSampleTypesIsMutable();
-        for (kpi_sample_types.KpiSampleTypes.KpiSampleType value : values) {
-          kpiSampleTypes_.add(value.getNumber());
+      public Builder clearConnectionIds() {
+        if (connectionIdsBuilder_ == null) {
+          connectionIds_ = java.util.Collections.emptyList();
+          bitField0_ = (bitField0_ & ~0x00000001);
+          onChanged();
+        } else {
+          connectionIdsBuilder_.clear();
         }
-        onChanged();
         return this;
       }
       /**
-       * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
-       * @return This builder for chaining.
+       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
        */
-      public Builder clearKpiSampleTypes() {
-        kpiSampleTypes_ = java.util.Collections.emptyList();
-        bitField0_ = (bitField0_ & ~0x00000001);
-        onChanged();
+      public Builder removeConnectionIds(int index) {
+        if (connectionIdsBuilder_ == null) {
+          ensureConnectionIdsIsMutable();
+          connectionIds_.remove(index);
+          onChanged();
+        } else {
+          connectionIdsBuilder_.remove(index);
+        }
         return this;
       }
       /**
-       * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
-       * @return A list containing the enum numeric values on the wire for kpiSampleTypes.
+       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
        */
-      public java.util.List<java.lang.Integer>
-      getKpiSampleTypesValueList() {
-        return java.util.Collections.unmodifiableList(kpiSampleTypes_);
+      public context.ContextOuterClass.ConnectionId.Builder getConnectionIdsBuilder(
+          int index) {
+        return getConnectionIdsFieldBuilder().getBuilder(index);
       }
       /**
-       * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
-       * @param index The index of the value to return.
-       * @return The enum numeric value on the wire of kpiSampleTypes at the given index.
+       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
        */
-      public int getKpiSampleTypesValue(int index) {
-        return kpiSampleTypes_.get(index);
+      public context.ContextOuterClass.ConnectionIdOrBuilder getConnectionIdsOrBuilder(
+          int index) {
+        if (connectionIdsBuilder_ == null) {
+          return connectionIds_.get(index);  } else {
+          return connectionIdsBuilder_.getMessageOrBuilder(index);
+        }
       }
       /**
-       * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
-       * @param index The index of the value to return.
-       * @return The enum numeric value on the wire of kpiSampleTypes at the given index.
-       * @return This builder for chaining.
+       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
        */
-      public Builder setKpiSampleTypesValue(
-          int index, int value) {
-        ensureKpiSampleTypesIsMutable();
-        kpiSampleTypes_.set(index, value);
-        onChanged();
-        return this;
+      public java.util.List<? extends context.ContextOuterClass.ConnectionIdOrBuilder> 
+           getConnectionIdsOrBuilderList() {
+        if (connectionIdsBuilder_ != null) {
+          return connectionIdsBuilder_.getMessageOrBuilderList();
+        } else {
+          return java.util.Collections.unmodifiableList(connectionIds_);
+        }
       }
       /**
-       * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
-       * @param value The enum numeric value on the wire for kpiSampleTypes to add.
-       * @return This builder for chaining.
+       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
        */
-      public Builder addKpiSampleTypesValue(int value) {
-        ensureKpiSampleTypesIsMutable();
-        kpiSampleTypes_.add(value);
-        onChanged();
-        return this;
+      public context.ContextOuterClass.ConnectionId.Builder addConnectionIdsBuilder() {
+        return getConnectionIdsFieldBuilder().addBuilder(
+            context.ContextOuterClass.ConnectionId.getDefaultInstance());
       }
       /**
-       * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
-       * @param values The enum numeric values on the wire for kpiSampleTypes to add.
-       * @return This builder for chaining.
+       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
        */
-      public Builder addAllKpiSampleTypesValue(
-          java.lang.Iterable<java.lang.Integer> values) {
-        ensureKpiSampleTypesIsMutable();
-        for (int value : values) {
-          kpiSampleTypes_.add(value);
+      public context.ContextOuterClass.ConnectionId.Builder addConnectionIdsBuilder(
+          int index) {
+        return getConnectionIdsFieldBuilder().addBuilder(
+            index, context.ContextOuterClass.ConnectionId.getDefaultInstance());
+      }
+      /**
+       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
+       */
+      public java.util.List<context.ContextOuterClass.ConnectionId.Builder> 
+           getConnectionIdsBuilderList() {
+        return getConnectionIdsFieldBuilder().getBuilderList();
+      }
+      private com.google.protobuf.RepeatedFieldBuilderV3<
+          context.ContextOuterClass.ConnectionId, context.ContextOuterClass.ConnectionId.Builder, context.ContextOuterClass.ConnectionIdOrBuilder> 
+          getConnectionIdsFieldBuilder() {
+        if (connectionIdsBuilder_ == null) {
+          connectionIdsBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3<
+              context.ContextOuterClass.ConnectionId, context.ContextOuterClass.ConnectionId.Builder, context.ContextOuterClass.ConnectionIdOrBuilder>(
+                  connectionIds_,
+                  ((bitField0_ & 0x00000001) != 0),
+                  getParentForChildren(),
+                  isClean());
+          connectionIds_ = null;
         }
-        onChanged();
-        return this;
+        return connectionIdsBuilder_;
       }
       @java.lang.Override
       public final Builder setUnknownFields(
@@ -29718,108 +30606,95 @@ public final class ContextOuterClass {
       }
 
 
-      // @@protoc_insertion_point(builder_scope:context.EndPoint)
+      // @@protoc_insertion_point(builder_scope:context.ConnectionIdList)
     }
 
-    // @@protoc_insertion_point(class_scope:context.EndPoint)
-    private static final context.ContextOuterClass.EndPoint DEFAULT_INSTANCE;
+    // @@protoc_insertion_point(class_scope:context.ConnectionIdList)
+    private static final context.ContextOuterClass.ConnectionIdList DEFAULT_INSTANCE;
     static {
-      DEFAULT_INSTANCE = new context.ContextOuterClass.EndPoint();
+      DEFAULT_INSTANCE = new context.ContextOuterClass.ConnectionIdList();
     }
 
-    public static context.ContextOuterClass.EndPoint getDefaultInstance() {
+    public static context.ContextOuterClass.ConnectionIdList getDefaultInstance() {
       return DEFAULT_INSTANCE;
     }
 
-    private static final com.google.protobuf.Parser<EndPoint>
-        PARSER = new com.google.protobuf.AbstractParser<EndPoint>() {
+    private static final com.google.protobuf.Parser<ConnectionIdList>
+        PARSER = new com.google.protobuf.AbstractParser<ConnectionIdList>() {
       @java.lang.Override
-      public EndPoint parsePartialFrom(
+      public ConnectionIdList parsePartialFrom(
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws com.google.protobuf.InvalidProtocolBufferException {
-        return new EndPoint(input, extensionRegistry);
+        return new ConnectionIdList(input, extensionRegistry);
       }
     };
 
-    public static com.google.protobuf.Parser<EndPoint> parser() {
+    public static com.google.protobuf.Parser<ConnectionIdList> parser() {
       return PARSER;
     }
 
     @java.lang.Override
-    public com.google.protobuf.Parser<EndPoint> getParserForType() {
+    public com.google.protobuf.Parser<ConnectionIdList> getParserForType() {
       return PARSER;
     }
 
     @java.lang.Override
-    public context.ContextOuterClass.EndPoint getDefaultInstanceForType() {
+    public context.ContextOuterClass.ConnectionIdList getDefaultInstanceForType() {
       return DEFAULT_INSTANCE;
     }
 
   }
 
-  public interface ConfigRuleOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:context.ConfigRule)
+  public interface ConnectionListOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:context.ConnectionList)
       com.google.protobuf.MessageOrBuilder {
 
     /**
-     * <code>.context.ConfigActionEnum action = 1;</code>
-     * @return The enum numeric value on the wire for action.
-     */
-    int getActionValue();
-    /**
-     * <code>.context.ConfigActionEnum action = 1;</code>
-     * @return The action.
+     * <code>repeated .context.Connection connections = 1;</code>
      */
-    context.ContextOuterClass.ConfigActionEnum getAction();
-
+    java.util.List<context.ContextOuterClass.Connection> 
+        getConnectionsList();
     /**
-     * <code>string resource_key = 2;</code>
-     * @return The resourceKey.
+     * <code>repeated .context.Connection connections = 1;</code>
      */
-    java.lang.String getResourceKey();
+    context.ContextOuterClass.Connection getConnections(int index);
     /**
-     * <code>string resource_key = 2;</code>
-     * @return The bytes for resourceKey.
+     * <code>repeated .context.Connection connections = 1;</code>
      */
-    com.google.protobuf.ByteString
-        getResourceKeyBytes();
-
+    int getConnectionsCount();
     /**
-     * <code>string resource_value = 3;</code>
-     * @return The resourceValue.
+     * <code>repeated .context.Connection connections = 1;</code>
      */
-    java.lang.String getResourceValue();
+    java.util.List<? extends context.ContextOuterClass.ConnectionOrBuilder> 
+        getConnectionsOrBuilderList();
     /**
-     * <code>string resource_value = 3;</code>
-     * @return The bytes for resourceValue.
+     * <code>repeated .context.Connection connections = 1;</code>
      */
-    com.google.protobuf.ByteString
-        getResourceValueBytes();
+    context.ContextOuterClass.ConnectionOrBuilder getConnectionsOrBuilder(
+        int index);
   }
   /**
-   * Protobuf type {@code context.ConfigRule}
+   * Protobuf type {@code context.ConnectionList}
    */
-  public static final class ConfigRule extends
+  public static final class ConnectionList extends
       com.google.protobuf.GeneratedMessageV3 implements
-      // @@protoc_insertion_point(message_implements:context.ConfigRule)
-      ConfigRuleOrBuilder {
+      // @@protoc_insertion_point(message_implements:context.ConnectionList)
+      ConnectionListOrBuilder {
   private static final long serialVersionUID = 0L;
-    // Use ConfigRule.newBuilder() to construct.
-    private ConfigRule(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
+    // Use ConnectionList.newBuilder() to construct.
+    private ConnectionList(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
       super(builder);
     }
-    private ConfigRule() {
-      action_ = 0;
-      resourceKey_ = "";
-      resourceValue_ = "";
+    private ConnectionList() {
+      connections_ = java.util.Collections.emptyList();
     }
 
     @java.lang.Override
     @SuppressWarnings({"unused"})
     protected java.lang.Object newInstance(
         UnusedPrivateParameter unused) {
-      return new ConfigRule();
+      return new ConnectionList();
     }
 
     @java.lang.Override
@@ -29827,7 +30702,7 @@ public final class ContextOuterClass {
     getUnknownFields() {
       return this.unknownFields;
     }
-    private ConfigRule(
+    private ConnectionList(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
@@ -29835,6 +30710,7 @@ public final class ContextOuterClass {
       if (extensionRegistry == null) {
         throw new java.lang.NullPointerException();
       }
+      int mutable_bitField0_ = 0;
       com.google.protobuf.UnknownFieldSet.Builder unknownFields =
           com.google.protobuf.UnknownFieldSet.newBuilder();
       try {
@@ -29845,22 +30721,13 @@ public final class ContextOuterClass {
             case 0:
               done = true;
               break;
-            case 8: {
-              int rawValue = input.readEnum();
-
-              action_ = rawValue;
-              break;
-            }
-            case 18: {
-              java.lang.String s = input.readStringRequireUtf8();
-
-              resourceKey_ = s;
-              break;
-            }
-            case 26: {
-              java.lang.String s = input.readStringRequireUtf8();
-
-              resourceValue_ = s;
+            case 10: {
+              if (!((mutable_bitField0_ & 0x00000001) != 0)) {
+                connections_ = new java.util.ArrayList<context.ContextOuterClass.Connection>();
+                mutable_bitField0_ |= 0x00000001;
+              }
+              connections_.add(
+                  input.readMessage(context.ContextOuterClass.Connection.parser(), extensionRegistry));
               break;
             }
             default: {
@@ -29878,116 +30745,64 @@ public final class ContextOuterClass {
         throw new com.google.protobuf.InvalidProtocolBufferException(
             e).setUnfinishedMessage(this);
       } finally {
+        if (((mutable_bitField0_ & 0x00000001) != 0)) {
+          connections_ = java.util.Collections.unmodifiableList(connections_);
+        }
         this.unknownFields = unknownFields.build();
         makeExtensionsImmutable();
       }
     }
     public static final com.google.protobuf.Descriptors.Descriptor
         getDescriptor() {
-      return context.ContextOuterClass.internal_static_context_ConfigRule_descriptor;
+      return context.ContextOuterClass.internal_static_context_ConnectionList_descriptor;
     }
 
     @java.lang.Override
     protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
         internalGetFieldAccessorTable() {
-      return context.ContextOuterClass.internal_static_context_ConfigRule_fieldAccessorTable
+      return context.ContextOuterClass.internal_static_context_ConnectionList_fieldAccessorTable
           .ensureFieldAccessorsInitialized(
-              context.ContextOuterClass.ConfigRule.class, context.ContextOuterClass.ConfigRule.Builder.class);
+              context.ContextOuterClass.ConnectionList.class, context.ContextOuterClass.ConnectionList.Builder.class);
     }
 
-    public static final int ACTION_FIELD_NUMBER = 1;
-    private int action_;
-    /**
-     * <code>.context.ConfigActionEnum action = 1;</code>
-     * @return The enum numeric value on the wire for action.
-     */
-    @java.lang.Override public int getActionValue() {
-      return action_;
-    }
+    public static final int CONNECTIONS_FIELD_NUMBER = 1;
+    private java.util.List<context.ContextOuterClass.Connection> connections_;
     /**
-     * <code>.context.ConfigActionEnum action = 1;</code>
-     * @return The action.
+     * <code>repeated .context.Connection connections = 1;</code>
      */
-    @java.lang.Override public context.ContextOuterClass.ConfigActionEnum getAction() {
-      @SuppressWarnings("deprecation")
-      context.ContextOuterClass.ConfigActionEnum result = context.ContextOuterClass.ConfigActionEnum.valueOf(action_);
-      return result == null ? context.ContextOuterClass.ConfigActionEnum.UNRECOGNIZED : result;
+    @java.lang.Override
+    public java.util.List<context.ContextOuterClass.Connection> getConnectionsList() {
+      return connections_;
     }
-
-    public static final int RESOURCE_KEY_FIELD_NUMBER = 2;
-    private volatile java.lang.Object resourceKey_;
     /**
-     * <code>string resource_key = 2;</code>
-     * @return The resourceKey.
+     * <code>repeated .context.Connection connections = 1;</code>
      */
     @java.lang.Override
-    public java.lang.String getResourceKey() {
-      java.lang.Object ref = resourceKey_;
-      if (ref instanceof java.lang.String) {
-        return (java.lang.String) ref;
-      } else {
-        com.google.protobuf.ByteString bs = 
-            (com.google.protobuf.ByteString) ref;
-        java.lang.String s = bs.toStringUtf8();
-        resourceKey_ = s;
-        return s;
-      }
+    public java.util.List<? extends context.ContextOuterClass.ConnectionOrBuilder> 
+        getConnectionsOrBuilderList() {
+      return connections_;
     }
     /**
-     * <code>string resource_key = 2;</code>
-     * @return The bytes for resourceKey.
+     * <code>repeated .context.Connection connections = 1;</code>
      */
     @java.lang.Override
-    public com.google.protobuf.ByteString
-        getResourceKeyBytes() {
-      java.lang.Object ref = resourceKey_;
-      if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
-            com.google.protobuf.ByteString.copyFromUtf8(
-                (java.lang.String) ref);
-        resourceKey_ = b;
-        return b;
-      } else {
-        return (com.google.protobuf.ByteString) ref;
-      }
+    public int getConnectionsCount() {
+      return connections_.size();
     }
-
-    public static final int RESOURCE_VALUE_FIELD_NUMBER = 3;
-    private volatile java.lang.Object resourceValue_;
     /**
-     * <code>string resource_value = 3;</code>
-     * @return The resourceValue.
+     * <code>repeated .context.Connection connections = 1;</code>
      */
     @java.lang.Override
-    public java.lang.String getResourceValue() {
-      java.lang.Object ref = resourceValue_;
-      if (ref instanceof java.lang.String) {
-        return (java.lang.String) ref;
-      } else {
-        com.google.protobuf.ByteString bs = 
-            (com.google.protobuf.ByteString) ref;
-        java.lang.String s = bs.toStringUtf8();
-        resourceValue_ = s;
-        return s;
-      }
+    public context.ContextOuterClass.Connection getConnections(int index) {
+      return connections_.get(index);
     }
     /**
-     * <code>string resource_value = 3;</code>
-     * @return The bytes for resourceValue.
+     * <code>repeated .context.Connection connections = 1;</code>
      */
     @java.lang.Override
-    public com.google.protobuf.ByteString
-        getResourceValueBytes() {
-      java.lang.Object ref = resourceValue_;
-      if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
-            com.google.protobuf.ByteString.copyFromUtf8(
-                (java.lang.String) ref);
-        resourceValue_ = b;
-        return b;
-      } else {
-        return (com.google.protobuf.ByteString) ref;
-      }
+    public context.ContextOuterClass.ConnectionOrBuilder getConnectionsOrBuilder(
+        int index) {
+      return connections_.get(index);
     }
 
     private byte memoizedIsInitialized = -1;
@@ -30004,14 +30819,8 @@ public final class ContextOuterClass {
     @java.lang.Override
     public void writeTo(com.google.protobuf.CodedOutputStream output)
                         throws java.io.IOException {
-      if (action_ != context.ContextOuterClass.ConfigActionEnum.CONFIGACTION_UNDEFINED.getNumber()) {
-        output.writeEnum(1, action_);
-      }
-      if (!getResourceKeyBytes().isEmpty()) {
-        com.google.protobuf.GeneratedMessageV3.writeString(output, 2, resourceKey_);
-      }
-      if (!getResourceValueBytes().isEmpty()) {
-        com.google.protobuf.GeneratedMessageV3.writeString(output, 3, resourceValue_);
+      for (int i = 0; i < connections_.size(); i++) {
+        output.writeMessage(1, connections_.get(i));
       }
       unknownFields.writeTo(output);
     }
@@ -30022,15 +30831,9 @@ public final class ContextOuterClass {
       if (size != -1) return size;
 
       size = 0;
-      if (action_ != context.ContextOuterClass.ConfigActionEnum.CONFIGACTION_UNDEFINED.getNumber()) {
+      for (int i = 0; i < connections_.size(); i++) {
         size += com.google.protobuf.CodedOutputStream
-          .computeEnumSize(1, action_);
-      }
-      if (!getResourceKeyBytes().isEmpty()) {
-        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, resourceKey_);
-      }
-      if (!getResourceValueBytes().isEmpty()) {
-        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, resourceValue_);
+          .computeMessageSize(1, connections_.get(i));
       }
       size += unknownFields.getSerializedSize();
       memoizedSize = size;
@@ -30042,16 +30845,13 @@ public final class ContextOuterClass {
       if (obj == this) {
        return true;
       }
-      if (!(obj instanceof context.ContextOuterClass.ConfigRule)) {
+      if (!(obj instanceof context.ContextOuterClass.ConnectionList)) {
         return super.equals(obj);
       }
-      context.ContextOuterClass.ConfigRule other = (context.ContextOuterClass.ConfigRule) obj;
+      context.ContextOuterClass.ConnectionList other = (context.ContextOuterClass.ConnectionList) obj;
 
-      if (action_ != other.action_) return false;
-      if (!getResourceKey()
-          .equals(other.getResourceKey())) return false;
-      if (!getResourceValue()
-          .equals(other.getResourceValue())) return false;
+      if (!getConnectionsList()
+          .equals(other.getConnectionsList())) return false;
       if (!unknownFields.equals(other.unknownFields)) return false;
       return true;
     }
@@ -30063,80 +30863,78 @@ public final class ContextOuterClass {
       }
       int hash = 41;
       hash = (19 * hash) + getDescriptor().hashCode();
-      hash = (37 * hash) + ACTION_FIELD_NUMBER;
-      hash = (53 * hash) + action_;
-      hash = (37 * hash) + RESOURCE_KEY_FIELD_NUMBER;
-      hash = (53 * hash) + getResourceKey().hashCode();
-      hash = (37 * hash) + RESOURCE_VALUE_FIELD_NUMBER;
-      hash = (53 * hash) + getResourceValue().hashCode();
+      if (getConnectionsCount() > 0) {
+        hash = (37 * hash) + CONNECTIONS_FIELD_NUMBER;
+        hash = (53 * hash) + getConnectionsList().hashCode();
+      }
       hash = (29 * hash) + unknownFields.hashCode();
       memoizedHashCode = hash;
       return hash;
     }
 
-    public static context.ContextOuterClass.ConfigRule parseFrom(
+    public static context.ContextOuterClass.ConnectionList parseFrom(
         java.nio.ByteBuffer data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static context.ContextOuterClass.ConfigRule parseFrom(
+    public static context.ContextOuterClass.ConnectionList parseFrom(
         java.nio.ByteBuffer data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static context.ContextOuterClass.ConfigRule parseFrom(
+    public static context.ContextOuterClass.ConnectionList parseFrom(
         com.google.protobuf.ByteString data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static context.ContextOuterClass.ConfigRule parseFrom(
+    public static context.ContextOuterClass.ConnectionList parseFrom(
         com.google.protobuf.ByteString data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static context.ContextOuterClass.ConfigRule parseFrom(byte[] data)
+    public static context.ContextOuterClass.ConnectionList parseFrom(byte[] data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static context.ContextOuterClass.ConfigRule parseFrom(
+    public static context.ContextOuterClass.ConnectionList parseFrom(
         byte[] data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static context.ContextOuterClass.ConfigRule parseFrom(java.io.InputStream input)
+    public static context.ContextOuterClass.ConnectionList parseFrom(java.io.InputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseWithIOException(PARSER, input);
     }
-    public static context.ContextOuterClass.ConfigRule parseFrom(
+    public static context.ContextOuterClass.ConnectionList parseFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseWithIOException(PARSER, input, extensionRegistry);
     }
-    public static context.ContextOuterClass.ConfigRule parseDelimitedFrom(java.io.InputStream input)
+    public static context.ContextOuterClass.ConnectionList parseDelimitedFrom(java.io.InputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseDelimitedWithIOException(PARSER, input);
     }
-    public static context.ContextOuterClass.ConfigRule parseDelimitedFrom(
+    public static context.ContextOuterClass.ConnectionList parseDelimitedFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
     }
-    public static context.ContextOuterClass.ConfigRule parseFrom(
+    public static context.ContextOuterClass.ConnectionList parseFrom(
         com.google.protobuf.CodedInputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseWithIOException(PARSER, input);
     }
-    public static context.ContextOuterClass.ConfigRule parseFrom(
+    public static context.ContextOuterClass.ConnectionList parseFrom(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -30149,7 +30947,7 @@ public final class ContextOuterClass {
     public static Builder newBuilder() {
       return DEFAULT_INSTANCE.toBuilder();
     }
-    public static Builder newBuilder(context.ContextOuterClass.ConfigRule prototype) {
+    public static Builder newBuilder(context.ContextOuterClass.ConnectionList prototype) {
       return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
     }
     @java.lang.Override
@@ -30165,26 +30963,26 @@ public final class ContextOuterClass {
       return builder;
     }
     /**
-     * Protobuf type {@code context.ConfigRule}
+     * Protobuf type {@code context.ConnectionList}
      */
     public static final class Builder extends
         com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:context.ConfigRule)
-        context.ContextOuterClass.ConfigRuleOrBuilder {
+        // @@protoc_insertion_point(builder_implements:context.ConnectionList)
+        context.ContextOuterClass.ConnectionListOrBuilder {
       public static final com.google.protobuf.Descriptors.Descriptor
           getDescriptor() {
-        return context.ContextOuterClass.internal_static_context_ConfigRule_descriptor;
+        return context.ContextOuterClass.internal_static_context_ConnectionList_descriptor;
       }
 
       @java.lang.Override
       protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
           internalGetFieldAccessorTable() {
-        return context.ContextOuterClass.internal_static_context_ConfigRule_fieldAccessorTable
+        return context.ContextOuterClass.internal_static_context_ConnectionList_fieldAccessorTable
             .ensureFieldAccessorsInitialized(
-                context.ContextOuterClass.ConfigRule.class, context.ContextOuterClass.ConfigRule.Builder.class);
+                context.ContextOuterClass.ConnectionList.class, context.ContextOuterClass.ConnectionList.Builder.class);
       }
 
-      // Construct using context.ContextOuterClass.ConfigRule.newBuilder()
+      // Construct using context.ContextOuterClass.ConnectionList.newBuilder()
       private Builder() {
         maybeForceBuilderInitialization();
       }
@@ -30197,34 +30995,35 @@ public final class ContextOuterClass {
       private void maybeForceBuilderInitialization() {
         if (com.google.protobuf.GeneratedMessageV3
                 .alwaysUseFieldBuilders) {
+          getConnectionsFieldBuilder();
         }
       }
       @java.lang.Override
       public Builder clear() {
         super.clear();
-        action_ = 0;
-
-        resourceKey_ = "";
-
-        resourceValue_ = "";
-
+        if (connectionsBuilder_ == null) {
+          connections_ = java.util.Collections.emptyList();
+          bitField0_ = (bitField0_ & ~0x00000001);
+        } else {
+          connectionsBuilder_.clear();
+        }
         return this;
       }
 
       @java.lang.Override
       public com.google.protobuf.Descriptors.Descriptor
           getDescriptorForType() {
-        return context.ContextOuterClass.internal_static_context_ConfigRule_descriptor;
+        return context.ContextOuterClass.internal_static_context_ConnectionList_descriptor;
       }
 
       @java.lang.Override
-      public context.ContextOuterClass.ConfigRule getDefaultInstanceForType() {
-        return context.ContextOuterClass.ConfigRule.getDefaultInstance();
+      public context.ContextOuterClass.ConnectionList getDefaultInstanceForType() {
+        return context.ContextOuterClass.ConnectionList.getDefaultInstance();
       }
 
       @java.lang.Override
-      public context.ContextOuterClass.ConfigRule build() {
-        context.ContextOuterClass.ConfigRule result = buildPartial();
+      public context.ContextOuterClass.ConnectionList build() {
+        context.ContextOuterClass.ConnectionList result = buildPartial();
         if (!result.isInitialized()) {
           throw newUninitializedMessageException(result);
         }
@@ -30232,11 +31031,18 @@ public final class ContextOuterClass {
       }
 
       @java.lang.Override
-      public context.ContextOuterClass.ConfigRule buildPartial() {
-        context.ContextOuterClass.ConfigRule result = new context.ContextOuterClass.ConfigRule(this);
-        result.action_ = action_;
-        result.resourceKey_ = resourceKey_;
-        result.resourceValue_ = resourceValue_;
+      public context.ContextOuterClass.ConnectionList buildPartial() {
+        context.ContextOuterClass.ConnectionList result = new context.ContextOuterClass.ConnectionList(this);
+        int from_bitField0_ = bitField0_;
+        if (connectionsBuilder_ == null) {
+          if (((bitField0_ & 0x00000001) != 0)) {
+            connections_ = java.util.Collections.unmodifiableList(connections_);
+            bitField0_ = (bitField0_ & ~0x00000001);
+          }
+          result.connections_ = connections_;
+        } else {
+          result.connections_ = connectionsBuilder_.build();
+        }
         onBuilt();
         return result;
       }
@@ -30275,26 +31081,41 @@ public final class ContextOuterClass {
       }
       @java.lang.Override
       public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof context.ContextOuterClass.ConfigRule) {
-          return mergeFrom((context.ContextOuterClass.ConfigRule)other);
+        if (other instanceof context.ContextOuterClass.ConnectionList) {
+          return mergeFrom((context.ContextOuterClass.ConnectionList)other);
         } else {
           super.mergeFrom(other);
           return this;
         }
       }
 
-      public Builder mergeFrom(context.ContextOuterClass.ConfigRule other) {
-        if (other == context.ContextOuterClass.ConfigRule.getDefaultInstance()) return this;
-        if (other.action_ != 0) {
-          setActionValue(other.getActionValue());
-        }
-        if (!other.getResourceKey().isEmpty()) {
-          resourceKey_ = other.resourceKey_;
-          onChanged();
-        }
-        if (!other.getResourceValue().isEmpty()) {
-          resourceValue_ = other.resourceValue_;
-          onChanged();
+      public Builder mergeFrom(context.ContextOuterClass.ConnectionList other) {
+        if (other == context.ContextOuterClass.ConnectionList.getDefaultInstance()) return this;
+        if (connectionsBuilder_ == null) {
+          if (!other.connections_.isEmpty()) {
+            if (connections_.isEmpty()) {
+              connections_ = other.connections_;
+              bitField0_ = (bitField0_ & ~0x00000001);
+            } else {
+              ensureConnectionsIsMutable();
+              connections_.addAll(other.connections_);
+            }
+            onChanged();
+          }
+        } else {
+          if (!other.connections_.isEmpty()) {
+            if (connectionsBuilder_.isEmpty()) {
+              connectionsBuilder_.dispose();
+              connectionsBuilder_ = null;
+              connections_ = other.connections_;
+              bitField0_ = (bitField0_ & ~0x00000001);
+              connectionsBuilder_ = 
+                com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ?
+                   getConnectionsFieldBuilder() : null;
+            } else {
+              connectionsBuilder_.addAllMessages(other.connections_);
+            }
+          }
         }
         this.mergeUnknownFields(other.unknownFields);
         onChanged();
@@ -30311,11 +31132,11 @@ public final class ContextOuterClass {
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws java.io.IOException {
-        context.ContextOuterClass.ConfigRule parsedMessage = null;
+        context.ContextOuterClass.ConnectionList parsedMessage = null;
         try {
           parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
         } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          parsedMessage = (context.ContextOuterClass.ConfigRule) e.getUnfinishedMessage();
+          parsedMessage = (context.ContextOuterClass.ConnectionList) e.getUnfinishedMessage();
           throw e.unwrapIOException();
         } finally {
           if (parsedMessage != null) {
@@ -30324,211 +31145,246 @@ public final class ContextOuterClass {
         }
         return this;
       }
+      private int bitField0_;
+
+      private java.util.List<context.ContextOuterClass.Connection> connections_ =
+        java.util.Collections.emptyList();
+      private void ensureConnectionsIsMutable() {
+        if (!((bitField0_ & 0x00000001) != 0)) {
+          connections_ = new java.util.ArrayList<context.ContextOuterClass.Connection>(connections_);
+          bitField0_ |= 0x00000001;
+         }
+      }
+
+      private com.google.protobuf.RepeatedFieldBuilderV3<
+          context.ContextOuterClass.Connection, context.ContextOuterClass.Connection.Builder, context.ContextOuterClass.ConnectionOrBuilder> connectionsBuilder_;
 
-      private int action_ = 0;
       /**
-       * <code>.context.ConfigActionEnum action = 1;</code>
-       * @return The enum numeric value on the wire for action.
+       * <code>repeated .context.Connection connections = 1;</code>
        */
-      @java.lang.Override public int getActionValue() {
-        return action_;
+      public java.util.List<context.ContextOuterClass.Connection> getConnectionsList() {
+        if (connectionsBuilder_ == null) {
+          return java.util.Collections.unmodifiableList(connections_);
+        } else {
+          return connectionsBuilder_.getMessageList();
+        }
       }
       /**
-       * <code>.context.ConfigActionEnum action = 1;</code>
-       * @param value The enum numeric value on the wire for action to set.
-       * @return This builder for chaining.
+       * <code>repeated .context.Connection connections = 1;</code>
        */
-      public Builder setActionValue(int value) {
-        
-        action_ = value;
-        onChanged();
+      public int getConnectionsCount() {
+        if (connectionsBuilder_ == null) {
+          return connections_.size();
+        } else {
+          return connectionsBuilder_.getCount();
+        }
+      }
+      /**
+       * <code>repeated .context.Connection connections = 1;</code>
+       */
+      public context.ContextOuterClass.Connection getConnections(int index) {
+        if (connectionsBuilder_ == null) {
+          return connections_.get(index);
+        } else {
+          return connectionsBuilder_.getMessage(index);
+        }
+      }
+      /**
+       * <code>repeated .context.Connection connections = 1;</code>
+       */
+      public Builder setConnections(
+          int index, context.ContextOuterClass.Connection value) {
+        if (connectionsBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensureConnectionsIsMutable();
+          connections_.set(index, value);
+          onChanged();
+        } else {
+          connectionsBuilder_.setMessage(index, value);
+        }
         return this;
       }
       /**
-       * <code>.context.ConfigActionEnum action = 1;</code>
-       * @return The action.
+       * <code>repeated .context.Connection connections = 1;</code>
        */
-      @java.lang.Override
-      public context.ContextOuterClass.ConfigActionEnum getAction() {
-        @SuppressWarnings("deprecation")
-        context.ContextOuterClass.ConfigActionEnum result = context.ContextOuterClass.ConfigActionEnum.valueOf(action_);
-        return result == null ? context.ContextOuterClass.ConfigActionEnum.UNRECOGNIZED : result;
+      public Builder setConnections(
+          int index, context.ContextOuterClass.Connection.Builder builderForValue) {
+        if (connectionsBuilder_ == null) {
+          ensureConnectionsIsMutable();
+          connections_.set(index, builderForValue.build());
+          onChanged();
+        } else {
+          connectionsBuilder_.setMessage(index, builderForValue.build());
+        }
+        return this;
       }
       /**
-       * <code>.context.ConfigActionEnum action = 1;</code>
-       * @param value The action to set.
-       * @return This builder for chaining.
+       * <code>repeated .context.Connection connections = 1;</code>
        */
-      public Builder setAction(context.ContextOuterClass.ConfigActionEnum value) {
-        if (value == null) {
-          throw new NullPointerException();
+      public Builder addConnections(context.ContextOuterClass.Connection value) {
+        if (connectionsBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensureConnectionsIsMutable();
+          connections_.add(value);
+          onChanged();
+        } else {
+          connectionsBuilder_.addMessage(value);
         }
-        
-        action_ = value.getNumber();
-        onChanged();
         return this;
       }
       /**
-       * <code>.context.ConfigActionEnum action = 1;</code>
-       * @return This builder for chaining.
+       * <code>repeated .context.Connection connections = 1;</code>
        */
-      public Builder clearAction() {
-        
-        action_ = 0;
-        onChanged();
+      public Builder addConnections(
+          int index, context.ContextOuterClass.Connection value) {
+        if (connectionsBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensureConnectionsIsMutable();
+          connections_.add(index, value);
+          onChanged();
+        } else {
+          connectionsBuilder_.addMessage(index, value);
+        }
         return this;
       }
-
-      private java.lang.Object resourceKey_ = "";
       /**
-       * <code>string resource_key = 2;</code>
-       * @return The resourceKey.
+       * <code>repeated .context.Connection connections = 1;</code>
        */
-      public java.lang.String getResourceKey() {
-        java.lang.Object ref = resourceKey_;
-        if (!(ref instanceof java.lang.String)) {
-          com.google.protobuf.ByteString bs =
-              (com.google.protobuf.ByteString) ref;
-          java.lang.String s = bs.toStringUtf8();
-          resourceKey_ = s;
-          return s;
+      public Builder addConnections(
+          context.ContextOuterClass.Connection.Builder builderForValue) {
+        if (connectionsBuilder_ == null) {
+          ensureConnectionsIsMutable();
+          connections_.add(builderForValue.build());
+          onChanged();
         } else {
-          return (java.lang.String) ref;
+          connectionsBuilder_.addMessage(builderForValue.build());
         }
+        return this;
       }
       /**
-       * <code>string resource_key = 2;</code>
-       * @return The bytes for resourceKey.
+       * <code>repeated .context.Connection connections = 1;</code>
        */
-      public com.google.protobuf.ByteString
-          getResourceKeyBytes() {
-        java.lang.Object ref = resourceKey_;
-        if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
-              com.google.protobuf.ByteString.copyFromUtf8(
-                  (java.lang.String) ref);
-          resourceKey_ = b;
-          return b;
+      public Builder addConnections(
+          int index, context.ContextOuterClass.Connection.Builder builderForValue) {
+        if (connectionsBuilder_ == null) {
+          ensureConnectionsIsMutable();
+          connections_.add(index, builderForValue.build());
+          onChanged();
         } else {
-          return (com.google.protobuf.ByteString) ref;
+          connectionsBuilder_.addMessage(index, builderForValue.build());
         }
+        return this;
       }
       /**
-       * <code>string resource_key = 2;</code>
-       * @param value The resourceKey to set.
-       * @return This builder for chaining.
+       * <code>repeated .context.Connection connections = 1;</code>
        */
-      public Builder setResourceKey(
-          java.lang.String value) {
-        if (value == null) {
-    throw new NullPointerException();
-  }
-  
-        resourceKey_ = value;
-        onChanged();
+      public Builder addAllConnections(
+          java.lang.Iterable<? extends context.ContextOuterClass.Connection> values) {
+        if (connectionsBuilder_ == null) {
+          ensureConnectionsIsMutable();
+          com.google.protobuf.AbstractMessageLite.Builder.addAll(
+              values, connections_);
+          onChanged();
+        } else {
+          connectionsBuilder_.addAllMessages(values);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .context.Connection connections = 1;</code>
+       */
+      public Builder clearConnections() {
+        if (connectionsBuilder_ == null) {
+          connections_ = java.util.Collections.emptyList();
+          bitField0_ = (bitField0_ & ~0x00000001);
+          onChanged();
+        } else {
+          connectionsBuilder_.clear();
+        }
         return this;
       }
       /**
-       * <code>string resource_key = 2;</code>
-       * @return This builder for chaining.
+       * <code>repeated .context.Connection connections = 1;</code>
        */
-      public Builder clearResourceKey() {
-        
-        resourceKey_ = getDefaultInstance().getResourceKey();
-        onChanged();
+      public Builder removeConnections(int index) {
+        if (connectionsBuilder_ == null) {
+          ensureConnectionsIsMutable();
+          connections_.remove(index);
+          onChanged();
+        } else {
+          connectionsBuilder_.remove(index);
+        }
         return this;
       }
       /**
-       * <code>string resource_key = 2;</code>
-       * @param value The bytes for resourceKey to set.
-       * @return This builder for chaining.
+       * <code>repeated .context.Connection connections = 1;</code>
        */
-      public Builder setResourceKeyBytes(
-          com.google.protobuf.ByteString value) {
-        if (value == null) {
-    throw new NullPointerException();
-  }
-  checkByteStringIsUtf8(value);
-        
-        resourceKey_ = value;
-        onChanged();
-        return this;
+      public context.ContextOuterClass.Connection.Builder getConnectionsBuilder(
+          int index) {
+        return getConnectionsFieldBuilder().getBuilder(index);
       }
-
-      private java.lang.Object resourceValue_ = "";
       /**
-       * <code>string resource_value = 3;</code>
-       * @return The resourceValue.
+       * <code>repeated .context.Connection connections = 1;</code>
        */
-      public java.lang.String getResourceValue() {
-        java.lang.Object ref = resourceValue_;
-        if (!(ref instanceof java.lang.String)) {
-          com.google.protobuf.ByteString bs =
-              (com.google.protobuf.ByteString) ref;
-          java.lang.String s = bs.toStringUtf8();
-          resourceValue_ = s;
-          return s;
-        } else {
-          return (java.lang.String) ref;
+      public context.ContextOuterClass.ConnectionOrBuilder getConnectionsOrBuilder(
+          int index) {
+        if (connectionsBuilder_ == null) {
+          return connections_.get(index);  } else {
+          return connectionsBuilder_.getMessageOrBuilder(index);
         }
       }
       /**
-       * <code>string resource_value = 3;</code>
-       * @return The bytes for resourceValue.
+       * <code>repeated .context.Connection connections = 1;</code>
        */
-      public com.google.protobuf.ByteString
-          getResourceValueBytes() {
-        java.lang.Object ref = resourceValue_;
-        if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
-              com.google.protobuf.ByteString.copyFromUtf8(
-                  (java.lang.String) ref);
-          resourceValue_ = b;
-          return b;
+      public java.util.List<? extends context.ContextOuterClass.ConnectionOrBuilder> 
+           getConnectionsOrBuilderList() {
+        if (connectionsBuilder_ != null) {
+          return connectionsBuilder_.getMessageOrBuilderList();
         } else {
-          return (com.google.protobuf.ByteString) ref;
+          return java.util.Collections.unmodifiableList(connections_);
         }
       }
       /**
-       * <code>string resource_value = 3;</code>
-       * @param value The resourceValue to set.
-       * @return This builder for chaining.
+       * <code>repeated .context.Connection connections = 1;</code>
        */
-      public Builder setResourceValue(
-          java.lang.String value) {
-        if (value == null) {
-    throw new NullPointerException();
-  }
-  
-        resourceValue_ = value;
-        onChanged();
-        return this;
+      public context.ContextOuterClass.Connection.Builder addConnectionsBuilder() {
+        return getConnectionsFieldBuilder().addBuilder(
+            context.ContextOuterClass.Connection.getDefaultInstance());
       }
       /**
-       * <code>string resource_value = 3;</code>
-       * @return This builder for chaining.
+       * <code>repeated .context.Connection connections = 1;</code>
        */
-      public Builder clearResourceValue() {
-        
-        resourceValue_ = getDefaultInstance().getResourceValue();
-        onChanged();
-        return this;
+      public context.ContextOuterClass.Connection.Builder addConnectionsBuilder(
+          int index) {
+        return getConnectionsFieldBuilder().addBuilder(
+            index, context.ContextOuterClass.Connection.getDefaultInstance());
       }
       /**
-       * <code>string resource_value = 3;</code>
-       * @param value The bytes for resourceValue to set.
-       * @return This builder for chaining.
+       * <code>repeated .context.Connection connections = 1;</code>
        */
-      public Builder setResourceValueBytes(
-          com.google.protobuf.ByteString value) {
-        if (value == null) {
-    throw new NullPointerException();
-  }
-  checkByteStringIsUtf8(value);
-        
-        resourceValue_ = value;
-        onChanged();
-        return this;
+      public java.util.List<context.ContextOuterClass.Connection.Builder> 
+           getConnectionsBuilderList() {
+        return getConnectionsFieldBuilder().getBuilderList();
+      }
+      private com.google.protobuf.RepeatedFieldBuilderV3<
+          context.ContextOuterClass.Connection, context.ContextOuterClass.Connection.Builder, context.ContextOuterClass.ConnectionOrBuilder> 
+          getConnectionsFieldBuilder() {
+        if (connectionsBuilder_ == null) {
+          connectionsBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3<
+              context.ContextOuterClass.Connection, context.ContextOuterClass.Connection.Builder, context.ContextOuterClass.ConnectionOrBuilder>(
+                  connections_,
+                  ((bitField0_ & 0x00000001) != 0),
+                  getParentForChildren(),
+                  isClean());
+          connections_ = null;
+        }
+        return connectionsBuilder_;
       }
       @java.lang.Override
       public final Builder setUnknownFields(
@@ -30543,100 +31399,100 @@ public final class ContextOuterClass {
       }
 
 
-      // @@protoc_insertion_point(builder_scope:context.ConfigRule)
+      // @@protoc_insertion_point(builder_scope:context.ConnectionList)
     }
 
-    // @@protoc_insertion_point(class_scope:context.ConfigRule)
-    private static final context.ContextOuterClass.ConfigRule DEFAULT_INSTANCE;
+    // @@protoc_insertion_point(class_scope:context.ConnectionList)
+    private static final context.ContextOuterClass.ConnectionList DEFAULT_INSTANCE;
     static {
-      DEFAULT_INSTANCE = new context.ContextOuterClass.ConfigRule();
+      DEFAULT_INSTANCE = new context.ContextOuterClass.ConnectionList();
     }
 
-    public static context.ContextOuterClass.ConfigRule getDefaultInstance() {
+    public static context.ContextOuterClass.ConnectionList getDefaultInstance() {
       return DEFAULT_INSTANCE;
     }
 
-    private static final com.google.protobuf.Parser<ConfigRule>
-        PARSER = new com.google.protobuf.AbstractParser<ConfigRule>() {
+    private static final com.google.protobuf.Parser<ConnectionList>
+        PARSER = new com.google.protobuf.AbstractParser<ConnectionList>() {
       @java.lang.Override
-      public ConfigRule parsePartialFrom(
+      public ConnectionList parsePartialFrom(
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws com.google.protobuf.InvalidProtocolBufferException {
-        return new ConfigRule(input, extensionRegistry);
+        return new ConnectionList(input, extensionRegistry);
       }
     };
 
-    public static com.google.protobuf.Parser<ConfigRule> parser() {
+    public static com.google.protobuf.Parser<ConnectionList> parser() {
       return PARSER;
     }
 
     @java.lang.Override
-    public com.google.protobuf.Parser<ConfigRule> getParserForType() {
+    public com.google.protobuf.Parser<ConnectionList> getParserForType() {
       return PARSER;
     }
 
     @java.lang.Override
-    public context.ContextOuterClass.ConfigRule getDefaultInstanceForType() {
+    public context.ContextOuterClass.ConnectionList getDefaultInstanceForType() {
       return DEFAULT_INSTANCE;
     }
 
   }
 
-  public interface ConstraintOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:context.Constraint)
+  public interface ConnectionEventOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:context.ConnectionEvent)
       com.google.protobuf.MessageOrBuilder {
 
     /**
-     * <code>string constraint_type = 1;</code>
-     * @return The constraintType.
+     * <code>.context.Event event = 1;</code>
+     * @return Whether the event field is set.
      */
-    java.lang.String getConstraintType();
+    boolean hasEvent();
     /**
-     * <code>string constraint_type = 1;</code>
-     * @return The bytes for constraintType.
+     * <code>.context.Event event = 1;</code>
+     * @return The event.
      */
-    com.google.protobuf.ByteString
-        getConstraintTypeBytes();
+    context.ContextOuterClass.Event getEvent();
+    /**
+     * <code>.context.Event event = 1;</code>
+     */
+    context.ContextOuterClass.EventOrBuilder getEventOrBuilder();
 
     /**
-     * <code>string constraint_value = 2;</code>
-     * @return The constraintValue.
+     * <code>.context.ConnectionId connection_id = 2;</code>
+     * @return Whether the connectionId field is set.
      */
-    java.lang.String getConstraintValue();
+    boolean hasConnectionId();
     /**
-     * <code>string constraint_value = 2;</code>
-     * @return The bytes for constraintValue.
+     * <code>.context.ConnectionId connection_id = 2;</code>
+     * @return The connectionId.
      */
-    com.google.protobuf.ByteString
-        getConstraintValueBytes();
+    context.ContextOuterClass.ConnectionId getConnectionId();
+    /**
+     * <code>.context.ConnectionId connection_id = 2;</code>
+     */
+    context.ContextOuterClass.ConnectionIdOrBuilder getConnectionIdOrBuilder();
   }
   /**
-   * <pre>
-   * ----- Constraint ----------------------------------------------------------------------------------------------------
-   * </pre>
-   *
-   * Protobuf type {@code context.Constraint}
+   * Protobuf type {@code context.ConnectionEvent}
    */
-  public static final class Constraint extends
+  public static final class ConnectionEvent extends
       com.google.protobuf.GeneratedMessageV3 implements
-      // @@protoc_insertion_point(message_implements:context.Constraint)
-      ConstraintOrBuilder {
+      // @@protoc_insertion_point(message_implements:context.ConnectionEvent)
+      ConnectionEventOrBuilder {
   private static final long serialVersionUID = 0L;
-    // Use Constraint.newBuilder() to construct.
-    private Constraint(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
+    // Use ConnectionEvent.newBuilder() to construct.
+    private ConnectionEvent(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
       super(builder);
     }
-    private Constraint() {
-      constraintType_ = "";
-      constraintValue_ = "";
+    private ConnectionEvent() {
     }
 
     @java.lang.Override
     @SuppressWarnings({"unused"})
     protected java.lang.Object newInstance(
         UnusedPrivateParameter unused) {
-      return new Constraint();
+      return new ConnectionEvent();
     }
 
     @java.lang.Override
@@ -30644,7 +31500,7 @@ public final class ContextOuterClass {
     getUnknownFields() {
       return this.unknownFields;
     }
-    private Constraint(
+    private ConnectionEvent(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
@@ -30663,15 +31519,29 @@ public final class ContextOuterClass {
               done = true;
               break;
             case 10: {
-              java.lang.String s = input.readStringRequireUtf8();
+              context.ContextOuterClass.Event.Builder subBuilder = null;
+              if (event_ != null) {
+                subBuilder = event_.toBuilder();
+              }
+              event_ = input.readMessage(context.ContextOuterClass.Event.parser(), extensionRegistry);
+              if (subBuilder != null) {
+                subBuilder.mergeFrom(event_);
+                event_ = subBuilder.buildPartial();
+              }
 
-              constraintType_ = s;
               break;
             }
             case 18: {
-              java.lang.String s = input.readStringRequireUtf8();
+              context.ContextOuterClass.ConnectionId.Builder subBuilder = null;
+              if (connectionId_ != null) {
+                subBuilder = connectionId_.toBuilder();
+              }
+              connectionId_ = input.readMessage(context.ContextOuterClass.ConnectionId.parser(), extensionRegistry);
+              if (subBuilder != null) {
+                subBuilder.mergeFrom(connectionId_);
+                connectionId_ = subBuilder.buildPartial();
+              }
 
-              constraintValue_ = s;
               break;
             }
             default: {
@@ -30695,91 +31565,67 @@ public final class ContextOuterClass {
     }
     public static final com.google.protobuf.Descriptors.Descriptor
         getDescriptor() {
-      return context.ContextOuterClass.internal_static_context_Constraint_descriptor;
+      return context.ContextOuterClass.internal_static_context_ConnectionEvent_descriptor;
     }
 
     @java.lang.Override
     protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
         internalGetFieldAccessorTable() {
-      return context.ContextOuterClass.internal_static_context_Constraint_fieldAccessorTable
+      return context.ContextOuterClass.internal_static_context_ConnectionEvent_fieldAccessorTable
           .ensureFieldAccessorsInitialized(
-              context.ContextOuterClass.Constraint.class, context.ContextOuterClass.Constraint.Builder.class);
+              context.ContextOuterClass.ConnectionEvent.class, context.ContextOuterClass.ConnectionEvent.Builder.class);
     }
 
-    public static final int CONSTRAINT_TYPE_FIELD_NUMBER = 1;
-    private volatile java.lang.Object constraintType_;
+    public static final int EVENT_FIELD_NUMBER = 1;
+    private context.ContextOuterClass.Event event_;
     /**
-     * <code>string constraint_type = 1;</code>
-     * @return The constraintType.
+     * <code>.context.Event event = 1;</code>
+     * @return Whether the event field is set.
+     */
+    @java.lang.Override
+    public boolean hasEvent() {
+      return event_ != null;
+    }
+    /**
+     * <code>.context.Event event = 1;</code>
+     * @return The event.
+     */
+    @java.lang.Override
+    public context.ContextOuterClass.Event getEvent() {
+      return event_ == null ? context.ContextOuterClass.Event.getDefaultInstance() : event_;
+    }
+    /**
+     * <code>.context.Event event = 1;</code>
      */
     @java.lang.Override
-    public java.lang.String getConstraintType() {
-      java.lang.Object ref = constraintType_;
-      if (ref instanceof java.lang.String) {
-        return (java.lang.String) ref;
-      } else {
-        com.google.protobuf.ByteString bs = 
-            (com.google.protobuf.ByteString) ref;
-        java.lang.String s = bs.toStringUtf8();
-        constraintType_ = s;
-        return s;
-      }
+    public context.ContextOuterClass.EventOrBuilder getEventOrBuilder() {
+      return getEvent();
     }
+
+    public static final int CONNECTION_ID_FIELD_NUMBER = 2;
+    private context.ContextOuterClass.ConnectionId connectionId_;
     /**
-     * <code>string constraint_type = 1;</code>
-     * @return The bytes for constraintType.
+     * <code>.context.ConnectionId connection_id = 2;</code>
+     * @return Whether the connectionId field is set.
      */
     @java.lang.Override
-    public com.google.protobuf.ByteString
-        getConstraintTypeBytes() {
-      java.lang.Object ref = constraintType_;
-      if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
-            com.google.protobuf.ByteString.copyFromUtf8(
-                (java.lang.String) ref);
-        constraintType_ = b;
-        return b;
-      } else {
-        return (com.google.protobuf.ByteString) ref;
-      }
+    public boolean hasConnectionId() {
+      return connectionId_ != null;
     }
-
-    public static final int CONSTRAINT_VALUE_FIELD_NUMBER = 2;
-    private volatile java.lang.Object constraintValue_;
     /**
-     * <code>string constraint_value = 2;</code>
-     * @return The constraintValue.
+     * <code>.context.ConnectionId connection_id = 2;</code>
+     * @return The connectionId.
      */
     @java.lang.Override
-    public java.lang.String getConstraintValue() {
-      java.lang.Object ref = constraintValue_;
-      if (ref instanceof java.lang.String) {
-        return (java.lang.String) ref;
-      } else {
-        com.google.protobuf.ByteString bs = 
-            (com.google.protobuf.ByteString) ref;
-        java.lang.String s = bs.toStringUtf8();
-        constraintValue_ = s;
-        return s;
-      }
+    public context.ContextOuterClass.ConnectionId getConnectionId() {
+      return connectionId_ == null ? context.ContextOuterClass.ConnectionId.getDefaultInstance() : connectionId_;
     }
     /**
-     * <code>string constraint_value = 2;</code>
-     * @return The bytes for constraintValue.
+     * <code>.context.ConnectionId connection_id = 2;</code>
      */
     @java.lang.Override
-    public com.google.protobuf.ByteString
-        getConstraintValueBytes() {
-      java.lang.Object ref = constraintValue_;
-      if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
-            com.google.protobuf.ByteString.copyFromUtf8(
-                (java.lang.String) ref);
-        constraintValue_ = b;
-        return b;
-      } else {
-        return (com.google.protobuf.ByteString) ref;
-      }
+    public context.ContextOuterClass.ConnectionIdOrBuilder getConnectionIdOrBuilder() {
+      return getConnectionId();
     }
 
     private byte memoizedIsInitialized = -1;
@@ -30796,11 +31642,11 @@ public final class ContextOuterClass {
     @java.lang.Override
     public void writeTo(com.google.protobuf.CodedOutputStream output)
                         throws java.io.IOException {
-      if (!getConstraintTypeBytes().isEmpty()) {
-        com.google.protobuf.GeneratedMessageV3.writeString(output, 1, constraintType_);
+      if (event_ != null) {
+        output.writeMessage(1, getEvent());
       }
-      if (!getConstraintValueBytes().isEmpty()) {
-        com.google.protobuf.GeneratedMessageV3.writeString(output, 2, constraintValue_);
+      if (connectionId_ != null) {
+        output.writeMessage(2, getConnectionId());
       }
       unknownFields.writeTo(output);
     }
@@ -30811,11 +31657,13 @@ public final class ContextOuterClass {
       if (size != -1) return size;
 
       size = 0;
-      if (!getConstraintTypeBytes().isEmpty()) {
-        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, constraintType_);
+      if (event_ != null) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(1, getEvent());
       }
-      if (!getConstraintValueBytes().isEmpty()) {
-        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, constraintValue_);
+      if (connectionId_ != null) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(2, getConnectionId());
       }
       size += unknownFields.getSerializedSize();
       memoizedSize = size;
@@ -30827,15 +31675,21 @@ public final class ContextOuterClass {
       if (obj == this) {
        return true;
       }
-      if (!(obj instanceof context.ContextOuterClass.Constraint)) {
+      if (!(obj instanceof context.ContextOuterClass.ConnectionEvent)) {
         return super.equals(obj);
       }
-      context.ContextOuterClass.Constraint other = (context.ContextOuterClass.Constraint) obj;
+      context.ContextOuterClass.ConnectionEvent other = (context.ContextOuterClass.ConnectionEvent) obj;
 
-      if (!getConstraintType()
-          .equals(other.getConstraintType())) return false;
-      if (!getConstraintValue()
-          .equals(other.getConstraintValue())) return false;
+      if (hasEvent() != other.hasEvent()) return false;
+      if (hasEvent()) {
+        if (!getEvent()
+            .equals(other.getEvent())) return false;
+      }
+      if (hasConnectionId() != other.hasConnectionId()) return false;
+      if (hasConnectionId()) {
+        if (!getConnectionId()
+            .equals(other.getConnectionId())) return false;
+      }
       if (!unknownFields.equals(other.unknownFields)) return false;
       return true;
     }
@@ -30847,78 +31701,82 @@ public final class ContextOuterClass {
       }
       int hash = 41;
       hash = (19 * hash) + getDescriptor().hashCode();
-      hash = (37 * hash) + CONSTRAINT_TYPE_FIELD_NUMBER;
-      hash = (53 * hash) + getConstraintType().hashCode();
-      hash = (37 * hash) + CONSTRAINT_VALUE_FIELD_NUMBER;
-      hash = (53 * hash) + getConstraintValue().hashCode();
+      if (hasEvent()) {
+        hash = (37 * hash) + EVENT_FIELD_NUMBER;
+        hash = (53 * hash) + getEvent().hashCode();
+      }
+      if (hasConnectionId()) {
+        hash = (37 * hash) + CONNECTION_ID_FIELD_NUMBER;
+        hash = (53 * hash) + getConnectionId().hashCode();
+      }
       hash = (29 * hash) + unknownFields.hashCode();
       memoizedHashCode = hash;
       return hash;
     }
 
-    public static context.ContextOuterClass.Constraint parseFrom(
+    public static context.ContextOuterClass.ConnectionEvent parseFrom(
         java.nio.ByteBuffer data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static context.ContextOuterClass.Constraint parseFrom(
+    public static context.ContextOuterClass.ConnectionEvent parseFrom(
         java.nio.ByteBuffer data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static context.ContextOuterClass.Constraint parseFrom(
+    public static context.ContextOuterClass.ConnectionEvent parseFrom(
         com.google.protobuf.ByteString data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static context.ContextOuterClass.Constraint parseFrom(
+    public static context.ContextOuterClass.ConnectionEvent parseFrom(
         com.google.protobuf.ByteString data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static context.ContextOuterClass.Constraint parseFrom(byte[] data)
+    public static context.ContextOuterClass.ConnectionEvent parseFrom(byte[] data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static context.ContextOuterClass.Constraint parseFrom(
+    public static context.ContextOuterClass.ConnectionEvent parseFrom(
         byte[] data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static context.ContextOuterClass.Constraint parseFrom(java.io.InputStream input)
+    public static context.ContextOuterClass.ConnectionEvent parseFrom(java.io.InputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseWithIOException(PARSER, input);
     }
-    public static context.ContextOuterClass.Constraint parseFrom(
+    public static context.ContextOuterClass.ConnectionEvent parseFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseWithIOException(PARSER, input, extensionRegistry);
     }
-    public static context.ContextOuterClass.Constraint parseDelimitedFrom(java.io.InputStream input)
+    public static context.ContextOuterClass.ConnectionEvent parseDelimitedFrom(java.io.InputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseDelimitedWithIOException(PARSER, input);
     }
-    public static context.ContextOuterClass.Constraint parseDelimitedFrom(
+    public static context.ContextOuterClass.ConnectionEvent parseDelimitedFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
     }
-    public static context.ContextOuterClass.Constraint parseFrom(
+    public static context.ContextOuterClass.ConnectionEvent parseFrom(
         com.google.protobuf.CodedInputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseWithIOException(PARSER, input);
     }
-    public static context.ContextOuterClass.Constraint parseFrom(
+    public static context.ContextOuterClass.ConnectionEvent parseFrom(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -30931,7 +31789,7 @@ public final class ContextOuterClass {
     public static Builder newBuilder() {
       return DEFAULT_INSTANCE.toBuilder();
     }
-    public static Builder newBuilder(context.ContextOuterClass.Constraint prototype) {
+    public static Builder newBuilder(context.ContextOuterClass.ConnectionEvent prototype) {
       return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
     }
     @java.lang.Override
@@ -30947,30 +31805,26 @@ public final class ContextOuterClass {
       return builder;
     }
     /**
-     * <pre>
-     * ----- Constraint ----------------------------------------------------------------------------------------------------
-     * </pre>
-     *
-     * Protobuf type {@code context.Constraint}
+     * Protobuf type {@code context.ConnectionEvent}
      */
     public static final class Builder extends
         com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:context.Constraint)
-        context.ContextOuterClass.ConstraintOrBuilder {
+        // @@protoc_insertion_point(builder_implements:context.ConnectionEvent)
+        context.ContextOuterClass.ConnectionEventOrBuilder {
       public static final com.google.protobuf.Descriptors.Descriptor
           getDescriptor() {
-        return context.ContextOuterClass.internal_static_context_Constraint_descriptor;
+        return context.ContextOuterClass.internal_static_context_ConnectionEvent_descriptor;
       }
 
       @java.lang.Override
       protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
           internalGetFieldAccessorTable() {
-        return context.ContextOuterClass.internal_static_context_Constraint_fieldAccessorTable
+        return context.ContextOuterClass.internal_static_context_ConnectionEvent_fieldAccessorTable
             .ensureFieldAccessorsInitialized(
-                context.ContextOuterClass.Constraint.class, context.ContextOuterClass.Constraint.Builder.class);
+                context.ContextOuterClass.ConnectionEvent.class, context.ContextOuterClass.ConnectionEvent.Builder.class);
       }
 
-      // Construct using context.ContextOuterClass.Constraint.newBuilder()
+      // Construct using context.ContextOuterClass.ConnectionEvent.newBuilder()
       private Builder() {
         maybeForceBuilderInitialization();
       }
@@ -30988,27 +31842,35 @@ public final class ContextOuterClass {
       @java.lang.Override
       public Builder clear() {
         super.clear();
-        constraintType_ = "";
-
-        constraintValue_ = "";
-
+        if (eventBuilder_ == null) {
+          event_ = null;
+        } else {
+          event_ = null;
+          eventBuilder_ = null;
+        }
+        if (connectionIdBuilder_ == null) {
+          connectionId_ = null;
+        } else {
+          connectionId_ = null;
+          connectionIdBuilder_ = null;
+        }
         return this;
       }
 
       @java.lang.Override
       public com.google.protobuf.Descriptors.Descriptor
           getDescriptorForType() {
-        return context.ContextOuterClass.internal_static_context_Constraint_descriptor;
+        return context.ContextOuterClass.internal_static_context_ConnectionEvent_descriptor;
       }
 
       @java.lang.Override
-      public context.ContextOuterClass.Constraint getDefaultInstanceForType() {
-        return context.ContextOuterClass.Constraint.getDefaultInstance();
+      public context.ContextOuterClass.ConnectionEvent getDefaultInstanceForType() {
+        return context.ContextOuterClass.ConnectionEvent.getDefaultInstance();
       }
 
       @java.lang.Override
-      public context.ContextOuterClass.Constraint build() {
-        context.ContextOuterClass.Constraint result = buildPartial();
+      public context.ContextOuterClass.ConnectionEvent build() {
+        context.ContextOuterClass.ConnectionEvent result = buildPartial();
         if (!result.isInitialized()) {
           throw newUninitializedMessageException(result);
         }
@@ -31016,10 +31878,18 @@ public final class ContextOuterClass {
       }
 
       @java.lang.Override
-      public context.ContextOuterClass.Constraint buildPartial() {
-        context.ContextOuterClass.Constraint result = new context.ContextOuterClass.Constraint(this);
-        result.constraintType_ = constraintType_;
-        result.constraintValue_ = constraintValue_;
+      public context.ContextOuterClass.ConnectionEvent buildPartial() {
+        context.ContextOuterClass.ConnectionEvent result = new context.ContextOuterClass.ConnectionEvent(this);
+        if (eventBuilder_ == null) {
+          result.event_ = event_;
+        } else {
+          result.event_ = eventBuilder_.build();
+        }
+        if (connectionIdBuilder_ == null) {
+          result.connectionId_ = connectionId_;
+        } else {
+          result.connectionId_ = connectionIdBuilder_.build();
+        }
         onBuilt();
         return result;
       }
@@ -31058,23 +31928,21 @@ public final class ContextOuterClass {
       }
       @java.lang.Override
       public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof context.ContextOuterClass.Constraint) {
-          return mergeFrom((context.ContextOuterClass.Constraint)other);
+        if (other instanceof context.ContextOuterClass.ConnectionEvent) {
+          return mergeFrom((context.ContextOuterClass.ConnectionEvent)other);
         } else {
           super.mergeFrom(other);
           return this;
         }
       }
 
-      public Builder mergeFrom(context.ContextOuterClass.Constraint other) {
-        if (other == context.ContextOuterClass.Constraint.getDefaultInstance()) return this;
-        if (!other.getConstraintType().isEmpty()) {
-          constraintType_ = other.constraintType_;
-          onChanged();
+      public Builder mergeFrom(context.ContextOuterClass.ConnectionEvent other) {
+        if (other == context.ContextOuterClass.ConnectionEvent.getDefaultInstance()) return this;
+        if (other.hasEvent()) {
+          mergeEvent(other.getEvent());
         }
-        if (!other.getConstraintValue().isEmpty()) {
-          constraintValue_ = other.constraintValue_;
-          onChanged();
+        if (other.hasConnectionId()) {
+          mergeConnectionId(other.getConnectionId());
         }
         this.mergeUnknownFields(other.unknownFields);
         onChanged();
@@ -31091,11 +31959,11 @@ public final class ContextOuterClass {
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws java.io.IOException {
-        context.ContextOuterClass.Constraint parsedMessage = null;
+        context.ContextOuterClass.ConnectionEvent parsedMessage = null;
         try {
           parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
         } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          parsedMessage = (context.ContextOuterClass.Constraint) e.getUnfinishedMessage();
+          parsedMessage = (context.ContextOuterClass.ConnectionEvent) e.getUnfinishedMessage();
           throw e.unwrapIOException();
         } finally {
           if (parsedMessage != null) {
@@ -31104,157 +31972,243 @@ public final class ContextOuterClass {
         }
         return this;
       }
-
-      private java.lang.Object constraintType_ = "";
+
+      private context.ContextOuterClass.Event event_;
+      private com.google.protobuf.SingleFieldBuilderV3<
+          context.ContextOuterClass.Event, context.ContextOuterClass.Event.Builder, context.ContextOuterClass.EventOrBuilder> eventBuilder_;
+      /**
+       * <code>.context.Event event = 1;</code>
+       * @return Whether the event field is set.
+       */
+      public boolean hasEvent() {
+        return eventBuilder_ != null || event_ != null;
+      }
+      /**
+       * <code>.context.Event event = 1;</code>
+       * @return The event.
+       */
+      public context.ContextOuterClass.Event getEvent() {
+        if (eventBuilder_ == null) {
+          return event_ == null ? context.ContextOuterClass.Event.getDefaultInstance() : event_;
+        } else {
+          return eventBuilder_.getMessage();
+        }
+      }
+      /**
+       * <code>.context.Event event = 1;</code>
+       */
+      public Builder setEvent(context.ContextOuterClass.Event value) {
+        if (eventBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          event_ = value;
+          onChanged();
+        } else {
+          eventBuilder_.setMessage(value);
+        }
+
+        return this;
+      }
+      /**
+       * <code>.context.Event event = 1;</code>
+       */
+      public Builder setEvent(
+          context.ContextOuterClass.Event.Builder builderForValue) {
+        if (eventBuilder_ == null) {
+          event_ = builderForValue.build();
+          onChanged();
+        } else {
+          eventBuilder_.setMessage(builderForValue.build());
+        }
+
+        return this;
+      }
+      /**
+       * <code>.context.Event event = 1;</code>
+       */
+      public Builder mergeEvent(context.ContextOuterClass.Event value) {
+        if (eventBuilder_ == null) {
+          if (event_ != null) {
+            event_ =
+              context.ContextOuterClass.Event.newBuilder(event_).mergeFrom(value).buildPartial();
+          } else {
+            event_ = value;
+          }
+          onChanged();
+        } else {
+          eventBuilder_.mergeFrom(value);
+        }
+
+        return this;
+      }
       /**
-       * <code>string constraint_type = 1;</code>
-       * @return The constraintType.
+       * <code>.context.Event event = 1;</code>
        */
-      public java.lang.String getConstraintType() {
-        java.lang.Object ref = constraintType_;
-        if (!(ref instanceof java.lang.String)) {
-          com.google.protobuf.ByteString bs =
-              (com.google.protobuf.ByteString) ref;
-          java.lang.String s = bs.toStringUtf8();
-          constraintType_ = s;
-          return s;
+      public Builder clearEvent() {
+        if (eventBuilder_ == null) {
+          event_ = null;
+          onChanged();
         } else {
-          return (java.lang.String) ref;
+          event_ = null;
+          eventBuilder_ = null;
         }
+
+        return this;
       }
       /**
-       * <code>string constraint_type = 1;</code>
-       * @return The bytes for constraintType.
+       * <code>.context.Event event = 1;</code>
        */
-      public com.google.protobuf.ByteString
-          getConstraintTypeBytes() {
-        java.lang.Object ref = constraintType_;
-        if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
-              com.google.protobuf.ByteString.copyFromUtf8(
-                  (java.lang.String) ref);
-          constraintType_ = b;
-          return b;
+      public context.ContextOuterClass.Event.Builder getEventBuilder() {
+        
+        onChanged();
+        return getEventFieldBuilder().getBuilder();
+      }
+      /**
+       * <code>.context.Event event = 1;</code>
+       */
+      public context.ContextOuterClass.EventOrBuilder getEventOrBuilder() {
+        if (eventBuilder_ != null) {
+          return eventBuilder_.getMessageOrBuilder();
         } else {
-          return (com.google.protobuf.ByteString) ref;
+          return event_ == null ?
+              context.ContextOuterClass.Event.getDefaultInstance() : event_;
         }
       }
       /**
-       * <code>string constraint_type = 1;</code>
-       * @param value The constraintType to set.
-       * @return This builder for chaining.
+       * <code>.context.Event event = 1;</code>
        */
-      public Builder setConstraintType(
-          java.lang.String value) {
-        if (value == null) {
-    throw new NullPointerException();
-  }
-  
-        constraintType_ = value;
-        onChanged();
-        return this;
+      private com.google.protobuf.SingleFieldBuilderV3<
+          context.ContextOuterClass.Event, context.ContextOuterClass.Event.Builder, context.ContextOuterClass.EventOrBuilder> 
+          getEventFieldBuilder() {
+        if (eventBuilder_ == null) {
+          eventBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
+              context.ContextOuterClass.Event, context.ContextOuterClass.Event.Builder, context.ContextOuterClass.EventOrBuilder>(
+                  getEvent(),
+                  getParentForChildren(),
+                  isClean());
+          event_ = null;
+        }
+        return eventBuilder_;
       }
+
+      private context.ContextOuterClass.ConnectionId connectionId_;
+      private com.google.protobuf.SingleFieldBuilderV3<
+          context.ContextOuterClass.ConnectionId, context.ContextOuterClass.ConnectionId.Builder, context.ContextOuterClass.ConnectionIdOrBuilder> connectionIdBuilder_;
       /**
-       * <code>string constraint_type = 1;</code>
-       * @return This builder for chaining.
+       * <code>.context.ConnectionId connection_id = 2;</code>
+       * @return Whether the connectionId field is set.
        */
-      public Builder clearConstraintType() {
-        
-        constraintType_ = getDefaultInstance().getConstraintType();
-        onChanged();
-        return this;
+      public boolean hasConnectionId() {
+        return connectionIdBuilder_ != null || connectionId_ != null;
       }
       /**
-       * <code>string constraint_type = 1;</code>
-       * @param value The bytes for constraintType to set.
-       * @return This builder for chaining.
+       * <code>.context.ConnectionId connection_id = 2;</code>
+       * @return The connectionId.
        */
-      public Builder setConstraintTypeBytes(
-          com.google.protobuf.ByteString value) {
-        if (value == null) {
-    throw new NullPointerException();
-  }
-  checkByteStringIsUtf8(value);
-        
-        constraintType_ = value;
-        onChanged();
-        return this;
+      public context.ContextOuterClass.ConnectionId getConnectionId() {
+        if (connectionIdBuilder_ == null) {
+          return connectionId_ == null ? context.ContextOuterClass.ConnectionId.getDefaultInstance() : connectionId_;
+        } else {
+          return connectionIdBuilder_.getMessage();
+        }
       }
-
-      private java.lang.Object constraintValue_ = "";
       /**
-       * <code>string constraint_value = 2;</code>
-       * @return The constraintValue.
+       * <code>.context.ConnectionId connection_id = 2;</code>
        */
-      public java.lang.String getConstraintValue() {
-        java.lang.Object ref = constraintValue_;
-        if (!(ref instanceof java.lang.String)) {
-          com.google.protobuf.ByteString bs =
-              (com.google.protobuf.ByteString) ref;
-          java.lang.String s = bs.toStringUtf8();
-          constraintValue_ = s;
-          return s;
+      public Builder setConnectionId(context.ContextOuterClass.ConnectionId value) {
+        if (connectionIdBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          connectionId_ = value;
+          onChanged();
         } else {
-          return (java.lang.String) ref;
+          connectionIdBuilder_.setMessage(value);
         }
+
+        return this;
       }
       /**
-       * <code>string constraint_value = 2;</code>
-       * @return The bytes for constraintValue.
+       * <code>.context.ConnectionId connection_id = 2;</code>
        */
-      public com.google.protobuf.ByteString
-          getConstraintValueBytes() {
-        java.lang.Object ref = constraintValue_;
-        if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
-              com.google.protobuf.ByteString.copyFromUtf8(
-                  (java.lang.String) ref);
-          constraintValue_ = b;
-          return b;
+      public Builder setConnectionId(
+          context.ContextOuterClass.ConnectionId.Builder builderForValue) {
+        if (connectionIdBuilder_ == null) {
+          connectionId_ = builderForValue.build();
+          onChanged();
         } else {
-          return (com.google.protobuf.ByteString) ref;
+          connectionIdBuilder_.setMessage(builderForValue.build());
         }
+
+        return this;
       }
       /**
-       * <code>string constraint_value = 2;</code>
-       * @param value The constraintValue to set.
-       * @return This builder for chaining.
+       * <code>.context.ConnectionId connection_id = 2;</code>
        */
-      public Builder setConstraintValue(
-          java.lang.String value) {
-        if (value == null) {
-    throw new NullPointerException();
-  }
-  
-        constraintValue_ = value;
-        onChanged();
+      public Builder mergeConnectionId(context.ContextOuterClass.ConnectionId value) {
+        if (connectionIdBuilder_ == null) {
+          if (connectionId_ != null) {
+            connectionId_ =
+              context.ContextOuterClass.ConnectionId.newBuilder(connectionId_).mergeFrom(value).buildPartial();
+          } else {
+            connectionId_ = value;
+          }
+          onChanged();
+        } else {
+          connectionIdBuilder_.mergeFrom(value);
+        }
+
         return this;
       }
       /**
-       * <code>string constraint_value = 2;</code>
-       * @return This builder for chaining.
+       * <code>.context.ConnectionId connection_id = 2;</code>
        */
-      public Builder clearConstraintValue() {
-        
-        constraintValue_ = getDefaultInstance().getConstraintValue();
-        onChanged();
+      public Builder clearConnectionId() {
+        if (connectionIdBuilder_ == null) {
+          connectionId_ = null;
+          onChanged();
+        } else {
+          connectionId_ = null;
+          connectionIdBuilder_ = null;
+        }
+
         return this;
       }
       /**
-       * <code>string constraint_value = 2;</code>
-       * @param value The bytes for constraintValue to set.
-       * @return This builder for chaining.
+       * <code>.context.ConnectionId connection_id = 2;</code>
        */
-      public Builder setConstraintValueBytes(
-          com.google.protobuf.ByteString value) {
-        if (value == null) {
-    throw new NullPointerException();
-  }
-  checkByteStringIsUtf8(value);
+      public context.ContextOuterClass.ConnectionId.Builder getConnectionIdBuilder() {
         
-        constraintValue_ = value;
         onChanged();
-        return this;
+        return getConnectionIdFieldBuilder().getBuilder();
+      }
+      /**
+       * <code>.context.ConnectionId connection_id = 2;</code>
+       */
+      public context.ContextOuterClass.ConnectionIdOrBuilder getConnectionIdOrBuilder() {
+        if (connectionIdBuilder_ != null) {
+          return connectionIdBuilder_.getMessageOrBuilder();
+        } else {
+          return connectionId_ == null ?
+              context.ContextOuterClass.ConnectionId.getDefaultInstance() : connectionId_;
+        }
+      }
+      /**
+       * <code>.context.ConnectionId connection_id = 2;</code>
+       */
+      private com.google.protobuf.SingleFieldBuilderV3<
+          context.ContextOuterClass.ConnectionId, context.ContextOuterClass.ConnectionId.Builder, context.ContextOuterClass.ConnectionIdOrBuilder> 
+          getConnectionIdFieldBuilder() {
+        if (connectionIdBuilder_ == null) {
+          connectionIdBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
+              context.ContextOuterClass.ConnectionId, context.ContextOuterClass.ConnectionId.Builder, context.ContextOuterClass.ConnectionIdOrBuilder>(
+                  getConnectionId(),
+                  getParentForChildren(),
+                  isClean());
+          connectionId_ = null;
+        }
+        return connectionIdBuilder_;
       }
       @java.lang.Override
       public final Builder setUnknownFields(
@@ -31269,89 +32223,119 @@ public final class ContextOuterClass {
       }
 
 
-      // @@protoc_insertion_point(builder_scope:context.Constraint)
+      // @@protoc_insertion_point(builder_scope:context.ConnectionEvent)
     }
 
-    // @@protoc_insertion_point(class_scope:context.Constraint)
-    private static final context.ContextOuterClass.Constraint DEFAULT_INSTANCE;
+    // @@protoc_insertion_point(class_scope:context.ConnectionEvent)
+    private static final context.ContextOuterClass.ConnectionEvent DEFAULT_INSTANCE;
     static {
-      DEFAULT_INSTANCE = new context.ContextOuterClass.Constraint();
+      DEFAULT_INSTANCE = new context.ContextOuterClass.ConnectionEvent();
     }
 
-    public static context.ContextOuterClass.Constraint getDefaultInstance() {
+    public static context.ContextOuterClass.ConnectionEvent getDefaultInstance() {
       return DEFAULT_INSTANCE;
     }
 
-    private static final com.google.protobuf.Parser<Constraint>
-        PARSER = new com.google.protobuf.AbstractParser<Constraint>() {
+    private static final com.google.protobuf.Parser<ConnectionEvent>
+        PARSER = new com.google.protobuf.AbstractParser<ConnectionEvent>() {
       @java.lang.Override
-      public Constraint parsePartialFrom(
+      public ConnectionEvent parsePartialFrom(
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws com.google.protobuf.InvalidProtocolBufferException {
-        return new Constraint(input, extensionRegistry);
+        return new ConnectionEvent(input, extensionRegistry);
       }
     };
 
-    public static com.google.protobuf.Parser<Constraint> parser() {
+    public static com.google.protobuf.Parser<ConnectionEvent> parser() {
       return PARSER;
     }
 
     @java.lang.Override
-    public com.google.protobuf.Parser<Constraint> getParserForType() {
+    public com.google.protobuf.Parser<ConnectionEvent> getParserForType() {
       return PARSER;
     }
 
     @java.lang.Override
-    public context.ContextOuterClass.Constraint getDefaultInstanceForType() {
+    public context.ContextOuterClass.ConnectionEvent getDefaultInstanceForType() {
       return DEFAULT_INSTANCE;
     }
 
   }
 
-  public interface ConnectionIdOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:context.ConnectionId)
-      com.google.protobuf.MessageOrBuilder {
+  public interface EndPointIdOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:context.EndPointId)
+      com.google.protobuf.MessageOrBuilder {
+
+    /**
+     * <code>.context.TopologyId topology_id = 1;</code>
+     * @return Whether the topologyId field is set.
+     */
+    boolean hasTopologyId();
+    /**
+     * <code>.context.TopologyId topology_id = 1;</code>
+     * @return The topologyId.
+     */
+    context.ContextOuterClass.TopologyId getTopologyId();
+    /**
+     * <code>.context.TopologyId topology_id = 1;</code>
+     */
+    context.ContextOuterClass.TopologyIdOrBuilder getTopologyIdOrBuilder();
+
+    /**
+     * <code>.context.DeviceId device_id = 2;</code>
+     * @return Whether the deviceId field is set.
+     */
+    boolean hasDeviceId();
+    /**
+     * <code>.context.DeviceId device_id = 2;</code>
+     * @return The deviceId.
+     */
+    context.ContextOuterClass.DeviceId getDeviceId();
+    /**
+     * <code>.context.DeviceId device_id = 2;</code>
+     */
+    context.ContextOuterClass.DeviceIdOrBuilder getDeviceIdOrBuilder();
 
     /**
-     * <code>.context.Uuid connection_uuid = 1;</code>
-     * @return Whether the connectionUuid field is set.
+     * <code>.context.Uuid endpoint_uuid = 3;</code>
+     * @return Whether the endpointUuid field is set.
      */
-    boolean hasConnectionUuid();
+    boolean hasEndpointUuid();
     /**
-     * <code>.context.Uuid connection_uuid = 1;</code>
-     * @return The connectionUuid.
+     * <code>.context.Uuid endpoint_uuid = 3;</code>
+     * @return The endpointUuid.
      */
-    context.ContextOuterClass.Uuid getConnectionUuid();
+    context.ContextOuterClass.Uuid getEndpointUuid();
     /**
-     * <code>.context.Uuid connection_uuid = 1;</code>
+     * <code>.context.Uuid endpoint_uuid = 3;</code>
      */
-    context.ContextOuterClass.UuidOrBuilder getConnectionUuidOrBuilder();
+    context.ContextOuterClass.UuidOrBuilder getEndpointUuidOrBuilder();
   }
   /**
    * <pre>
-   * ----- Connection ----------------------------------------------------------------------------------------------------
+   * ----- Endpoint ------------------------------------------------------------------------------------------------------
    * </pre>
    *
-   * Protobuf type {@code context.ConnectionId}
+   * Protobuf type {@code context.EndPointId}
    */
-  public static final class ConnectionId extends
+  public static final class EndPointId extends
       com.google.protobuf.GeneratedMessageV3 implements
-      // @@protoc_insertion_point(message_implements:context.ConnectionId)
-      ConnectionIdOrBuilder {
+      // @@protoc_insertion_point(message_implements:context.EndPointId)
+      EndPointIdOrBuilder {
   private static final long serialVersionUID = 0L;
-    // Use ConnectionId.newBuilder() to construct.
-    private ConnectionId(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
+    // Use EndPointId.newBuilder() to construct.
+    private EndPointId(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
       super(builder);
     }
-    private ConnectionId() {
+    private EndPointId() {
     }
 
     @java.lang.Override
     @SuppressWarnings({"unused"})
     protected java.lang.Object newInstance(
         UnusedPrivateParameter unused) {
-      return new ConnectionId();
+      return new EndPointId();
     }
 
     @java.lang.Override
@@ -31359,7 +32343,7 @@ public final class ContextOuterClass {
     getUnknownFields() {
       return this.unknownFields;
     }
-    private ConnectionId(
+    private EndPointId(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
@@ -31378,14 +32362,40 @@ public final class ContextOuterClass {
               done = true;
               break;
             case 10: {
+              context.ContextOuterClass.TopologyId.Builder subBuilder = null;
+              if (topologyId_ != null) {
+                subBuilder = topologyId_.toBuilder();
+              }
+              topologyId_ = input.readMessage(context.ContextOuterClass.TopologyId.parser(), extensionRegistry);
+              if (subBuilder != null) {
+                subBuilder.mergeFrom(topologyId_);
+                topologyId_ = subBuilder.buildPartial();
+              }
+
+              break;
+            }
+            case 18: {
+              context.ContextOuterClass.DeviceId.Builder subBuilder = null;
+              if (deviceId_ != null) {
+                subBuilder = deviceId_.toBuilder();
+              }
+              deviceId_ = input.readMessage(context.ContextOuterClass.DeviceId.parser(), extensionRegistry);
+              if (subBuilder != null) {
+                subBuilder.mergeFrom(deviceId_);
+                deviceId_ = subBuilder.buildPartial();
+              }
+
+              break;
+            }
+            case 26: {
               context.ContextOuterClass.Uuid.Builder subBuilder = null;
-              if (connectionUuid_ != null) {
-                subBuilder = connectionUuid_.toBuilder();
+              if (endpointUuid_ != null) {
+                subBuilder = endpointUuid_.toBuilder();
               }
-              connectionUuid_ = input.readMessage(context.ContextOuterClass.Uuid.parser(), extensionRegistry);
+              endpointUuid_ = input.readMessage(context.ContextOuterClass.Uuid.parser(), extensionRegistry);
               if (subBuilder != null) {
-                subBuilder.mergeFrom(connectionUuid_);
-                connectionUuid_ = subBuilder.buildPartial();
+                subBuilder.mergeFrom(endpointUuid_);
+                endpointUuid_ = subBuilder.buildPartial();
               }
 
               break;
@@ -31411,41 +32421,93 @@ public final class ContextOuterClass {
     }
     public static final com.google.protobuf.Descriptors.Descriptor
         getDescriptor() {
-      return context.ContextOuterClass.internal_static_context_ConnectionId_descriptor;
+      return context.ContextOuterClass.internal_static_context_EndPointId_descriptor;
     }
 
     @java.lang.Override
     protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
         internalGetFieldAccessorTable() {
-      return context.ContextOuterClass.internal_static_context_ConnectionId_fieldAccessorTable
+      return context.ContextOuterClass.internal_static_context_EndPointId_fieldAccessorTable
           .ensureFieldAccessorsInitialized(
-              context.ContextOuterClass.ConnectionId.class, context.ContextOuterClass.ConnectionId.Builder.class);
+              context.ContextOuterClass.EndPointId.class, context.ContextOuterClass.EndPointId.Builder.class);
     }
 
-    public static final int CONNECTION_UUID_FIELD_NUMBER = 1;
-    private context.ContextOuterClass.Uuid connectionUuid_;
+    public static final int TOPOLOGY_ID_FIELD_NUMBER = 1;
+    private context.ContextOuterClass.TopologyId topologyId_;
     /**
-     * <code>.context.Uuid connection_uuid = 1;</code>
-     * @return Whether the connectionUuid field is set.
+     * <code>.context.TopologyId topology_id = 1;</code>
+     * @return Whether the topologyId field is set.
      */
     @java.lang.Override
-    public boolean hasConnectionUuid() {
-      return connectionUuid_ != null;
+    public boolean hasTopologyId() {
+      return topologyId_ != null;
     }
     /**
-     * <code>.context.Uuid connection_uuid = 1;</code>
-     * @return The connectionUuid.
+     * <code>.context.TopologyId topology_id = 1;</code>
+     * @return The topologyId.
      */
     @java.lang.Override
-    public context.ContextOuterClass.Uuid getConnectionUuid() {
-      return connectionUuid_ == null ? context.ContextOuterClass.Uuid.getDefaultInstance() : connectionUuid_;
+    public context.ContextOuterClass.TopologyId getTopologyId() {
+      return topologyId_ == null ? context.ContextOuterClass.TopologyId.getDefaultInstance() : topologyId_;
     }
     /**
-     * <code>.context.Uuid connection_uuid = 1;</code>
+     * <code>.context.TopologyId topology_id = 1;</code>
      */
     @java.lang.Override
-    public context.ContextOuterClass.UuidOrBuilder getConnectionUuidOrBuilder() {
-      return getConnectionUuid();
+    public context.ContextOuterClass.TopologyIdOrBuilder getTopologyIdOrBuilder() {
+      return getTopologyId();
+    }
+
+    public static final int DEVICE_ID_FIELD_NUMBER = 2;
+    private context.ContextOuterClass.DeviceId deviceId_;
+    /**
+     * <code>.context.DeviceId device_id = 2;</code>
+     * @return Whether the deviceId field is set.
+     */
+    @java.lang.Override
+    public boolean hasDeviceId() {
+      return deviceId_ != null;
+    }
+    /**
+     * <code>.context.DeviceId device_id = 2;</code>
+     * @return The deviceId.
+     */
+    @java.lang.Override
+    public context.ContextOuterClass.DeviceId getDeviceId() {
+      return deviceId_ == null ? context.ContextOuterClass.DeviceId.getDefaultInstance() : deviceId_;
+    }
+    /**
+     * <code>.context.DeviceId device_id = 2;</code>
+     */
+    @java.lang.Override
+    public context.ContextOuterClass.DeviceIdOrBuilder getDeviceIdOrBuilder() {
+      return getDeviceId();
+    }
+
+    public static final int ENDPOINT_UUID_FIELD_NUMBER = 3;
+    private context.ContextOuterClass.Uuid endpointUuid_;
+    /**
+     * <code>.context.Uuid endpoint_uuid = 3;</code>
+     * @return Whether the endpointUuid field is set.
+     */
+    @java.lang.Override
+    public boolean hasEndpointUuid() {
+      return endpointUuid_ != null;
+    }
+    /**
+     * <code>.context.Uuid endpoint_uuid = 3;</code>
+     * @return The endpointUuid.
+     */
+    @java.lang.Override
+    public context.ContextOuterClass.Uuid getEndpointUuid() {
+      return endpointUuid_ == null ? context.ContextOuterClass.Uuid.getDefaultInstance() : endpointUuid_;
+    }
+    /**
+     * <code>.context.Uuid endpoint_uuid = 3;</code>
+     */
+    @java.lang.Override
+    public context.ContextOuterClass.UuidOrBuilder getEndpointUuidOrBuilder() {
+      return getEndpointUuid();
     }
 
     private byte memoizedIsInitialized = -1;
@@ -31462,8 +32524,14 @@ public final class ContextOuterClass {
     @java.lang.Override
     public void writeTo(com.google.protobuf.CodedOutputStream output)
                         throws java.io.IOException {
-      if (connectionUuid_ != null) {
-        output.writeMessage(1, getConnectionUuid());
+      if (topologyId_ != null) {
+        output.writeMessage(1, getTopologyId());
+      }
+      if (deviceId_ != null) {
+        output.writeMessage(2, getDeviceId());
+      }
+      if (endpointUuid_ != null) {
+        output.writeMessage(3, getEndpointUuid());
       }
       unknownFields.writeTo(output);
     }
@@ -31474,9 +32542,17 @@ public final class ContextOuterClass {
       if (size != -1) return size;
 
       size = 0;
-      if (connectionUuid_ != null) {
+      if (topologyId_ != null) {
         size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(1, getConnectionUuid());
+          .computeMessageSize(1, getTopologyId());
+      }
+      if (deviceId_ != null) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(2, getDeviceId());
+      }
+      if (endpointUuid_ != null) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(3, getEndpointUuid());
       }
       size += unknownFields.getSerializedSize();
       memoizedSize = size;
@@ -31488,15 +32564,25 @@ public final class ContextOuterClass {
       if (obj == this) {
        return true;
       }
-      if (!(obj instanceof context.ContextOuterClass.ConnectionId)) {
+      if (!(obj instanceof context.ContextOuterClass.EndPointId)) {
         return super.equals(obj);
       }
-      context.ContextOuterClass.ConnectionId other = (context.ContextOuterClass.ConnectionId) obj;
+      context.ContextOuterClass.EndPointId other = (context.ContextOuterClass.EndPointId) obj;
 
-      if (hasConnectionUuid() != other.hasConnectionUuid()) return false;
-      if (hasConnectionUuid()) {
-        if (!getConnectionUuid()
-            .equals(other.getConnectionUuid())) return false;
+      if (hasTopologyId() != other.hasTopologyId()) return false;
+      if (hasTopologyId()) {
+        if (!getTopologyId()
+            .equals(other.getTopologyId())) return false;
+      }
+      if (hasDeviceId() != other.hasDeviceId()) return false;
+      if (hasDeviceId()) {
+        if (!getDeviceId()
+            .equals(other.getDeviceId())) return false;
+      }
+      if (hasEndpointUuid() != other.hasEndpointUuid()) return false;
+      if (hasEndpointUuid()) {
+        if (!getEndpointUuid()
+            .equals(other.getEndpointUuid())) return false;
       }
       if (!unknownFields.equals(other.unknownFields)) return false;
       return true;
@@ -31509,78 +32595,86 @@ public final class ContextOuterClass {
       }
       int hash = 41;
       hash = (19 * hash) + getDescriptor().hashCode();
-      if (hasConnectionUuid()) {
-        hash = (37 * hash) + CONNECTION_UUID_FIELD_NUMBER;
-        hash = (53 * hash) + getConnectionUuid().hashCode();
+      if (hasTopologyId()) {
+        hash = (37 * hash) + TOPOLOGY_ID_FIELD_NUMBER;
+        hash = (53 * hash) + getTopologyId().hashCode();
+      }
+      if (hasDeviceId()) {
+        hash = (37 * hash) + DEVICE_ID_FIELD_NUMBER;
+        hash = (53 * hash) + getDeviceId().hashCode();
+      }
+      if (hasEndpointUuid()) {
+        hash = (37 * hash) + ENDPOINT_UUID_FIELD_NUMBER;
+        hash = (53 * hash) + getEndpointUuid().hashCode();
       }
       hash = (29 * hash) + unknownFields.hashCode();
       memoizedHashCode = hash;
       return hash;
     }
 
-    public static context.ContextOuterClass.ConnectionId parseFrom(
+    public static context.ContextOuterClass.EndPointId parseFrom(
         java.nio.ByteBuffer data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static context.ContextOuterClass.ConnectionId parseFrom(
+    public static context.ContextOuterClass.EndPointId parseFrom(
         java.nio.ByteBuffer data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static context.ContextOuterClass.ConnectionId parseFrom(
+    public static context.ContextOuterClass.EndPointId parseFrom(
         com.google.protobuf.ByteString data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static context.ContextOuterClass.ConnectionId parseFrom(
+    public static context.ContextOuterClass.EndPointId parseFrom(
         com.google.protobuf.ByteString data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static context.ContextOuterClass.ConnectionId parseFrom(byte[] data)
+    public static context.ContextOuterClass.EndPointId parseFrom(byte[] data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static context.ContextOuterClass.ConnectionId parseFrom(
+    public static context.ContextOuterClass.EndPointId parseFrom(
         byte[] data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static context.ContextOuterClass.ConnectionId parseFrom(java.io.InputStream input)
+    public static context.ContextOuterClass.EndPointId parseFrom(java.io.InputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseWithIOException(PARSER, input);
     }
-    public static context.ContextOuterClass.ConnectionId parseFrom(
+    public static context.ContextOuterClass.EndPointId parseFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseWithIOException(PARSER, input, extensionRegistry);
     }
-    public static context.ContextOuterClass.ConnectionId parseDelimitedFrom(java.io.InputStream input)
+    public static context.ContextOuterClass.EndPointId parseDelimitedFrom(java.io.InputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseDelimitedWithIOException(PARSER, input);
     }
-    public static context.ContextOuterClass.ConnectionId parseDelimitedFrom(
+    public static context.ContextOuterClass.EndPointId parseDelimitedFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
     }
-    public static context.ContextOuterClass.ConnectionId parseFrom(
+    public static context.ContextOuterClass.EndPointId parseFrom(
         com.google.protobuf.CodedInputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseWithIOException(PARSER, input);
     }
-    public static context.ContextOuterClass.ConnectionId parseFrom(
+    public static context.ContextOuterClass.EndPointId parseFrom(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -31593,7 +32687,7 @@ public final class ContextOuterClass {
     public static Builder newBuilder() {
       return DEFAULT_INSTANCE.toBuilder();
     }
-    public static Builder newBuilder(context.ContextOuterClass.ConnectionId prototype) {
+    public static Builder newBuilder(context.ContextOuterClass.EndPointId prototype) {
       return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
     }
     @java.lang.Override
@@ -31610,29 +32704,29 @@ public final class ContextOuterClass {
     }
     /**
      * <pre>
-     * ----- Connection ----------------------------------------------------------------------------------------------------
+     * ----- Endpoint ------------------------------------------------------------------------------------------------------
      * </pre>
      *
-     * Protobuf type {@code context.ConnectionId}
+     * Protobuf type {@code context.EndPointId}
      */
     public static final class Builder extends
         com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:context.ConnectionId)
-        context.ContextOuterClass.ConnectionIdOrBuilder {
+        // @@protoc_insertion_point(builder_implements:context.EndPointId)
+        context.ContextOuterClass.EndPointIdOrBuilder {
       public static final com.google.protobuf.Descriptors.Descriptor
           getDescriptor() {
-        return context.ContextOuterClass.internal_static_context_ConnectionId_descriptor;
+        return context.ContextOuterClass.internal_static_context_EndPointId_descriptor;
       }
 
       @java.lang.Override
       protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
           internalGetFieldAccessorTable() {
-        return context.ContextOuterClass.internal_static_context_ConnectionId_fieldAccessorTable
+        return context.ContextOuterClass.internal_static_context_EndPointId_fieldAccessorTable
             .ensureFieldAccessorsInitialized(
-                context.ContextOuterClass.ConnectionId.class, context.ContextOuterClass.ConnectionId.Builder.class);
+                context.ContextOuterClass.EndPointId.class, context.ContextOuterClass.EndPointId.Builder.class);
       }
 
-      // Construct using context.ContextOuterClass.ConnectionId.newBuilder()
+      // Construct using context.ContextOuterClass.EndPointId.newBuilder()
       private Builder() {
         maybeForceBuilderInitialization();
       }
@@ -31650,11 +32744,23 @@ public final class ContextOuterClass {
       @java.lang.Override
       public Builder clear() {
         super.clear();
-        if (connectionUuidBuilder_ == null) {
-          connectionUuid_ = null;
+        if (topologyIdBuilder_ == null) {
+          topologyId_ = null;
         } else {
-          connectionUuid_ = null;
-          connectionUuidBuilder_ = null;
+          topologyId_ = null;
+          topologyIdBuilder_ = null;
+        }
+        if (deviceIdBuilder_ == null) {
+          deviceId_ = null;
+        } else {
+          deviceId_ = null;
+          deviceIdBuilder_ = null;
+        }
+        if (endpointUuidBuilder_ == null) {
+          endpointUuid_ = null;
+        } else {
+          endpointUuid_ = null;
+          endpointUuidBuilder_ = null;
         }
         return this;
       }
@@ -31662,17 +32768,17 @@ public final class ContextOuterClass {
       @java.lang.Override
       public com.google.protobuf.Descriptors.Descriptor
           getDescriptorForType() {
-        return context.ContextOuterClass.internal_static_context_ConnectionId_descriptor;
+        return context.ContextOuterClass.internal_static_context_EndPointId_descriptor;
       }
 
       @java.lang.Override
-      public context.ContextOuterClass.ConnectionId getDefaultInstanceForType() {
-        return context.ContextOuterClass.ConnectionId.getDefaultInstance();
+      public context.ContextOuterClass.EndPointId getDefaultInstanceForType() {
+        return context.ContextOuterClass.EndPointId.getDefaultInstance();
       }
 
       @java.lang.Override
-      public context.ContextOuterClass.ConnectionId build() {
-        context.ContextOuterClass.ConnectionId result = buildPartial();
+      public context.ContextOuterClass.EndPointId build() {
+        context.ContextOuterClass.EndPointId result = buildPartial();
         if (!result.isInitialized()) {
           throw newUninitializedMessageException(result);
         }
@@ -31680,12 +32786,22 @@ public final class ContextOuterClass {
       }
 
       @java.lang.Override
-      public context.ContextOuterClass.ConnectionId buildPartial() {
-        context.ContextOuterClass.ConnectionId result = new context.ContextOuterClass.ConnectionId(this);
-        if (connectionUuidBuilder_ == null) {
-          result.connectionUuid_ = connectionUuid_;
+      public context.ContextOuterClass.EndPointId buildPartial() {
+        context.ContextOuterClass.EndPointId result = new context.ContextOuterClass.EndPointId(this);
+        if (topologyIdBuilder_ == null) {
+          result.topologyId_ = topologyId_;
         } else {
-          result.connectionUuid_ = connectionUuidBuilder_.build();
+          result.topologyId_ = topologyIdBuilder_.build();
+        }
+        if (deviceIdBuilder_ == null) {
+          result.deviceId_ = deviceId_;
+        } else {
+          result.deviceId_ = deviceIdBuilder_.build();
+        }
+        if (endpointUuidBuilder_ == null) {
+          result.endpointUuid_ = endpointUuid_;
+        } else {
+          result.endpointUuid_ = endpointUuidBuilder_.build();
         }
         onBuilt();
         return result;
@@ -31725,165 +32841,409 @@ public final class ContextOuterClass {
       }
       @java.lang.Override
       public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof context.ContextOuterClass.ConnectionId) {
-          return mergeFrom((context.ContextOuterClass.ConnectionId)other);
+        if (other instanceof context.ContextOuterClass.EndPointId) {
+          return mergeFrom((context.ContextOuterClass.EndPointId)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(context.ContextOuterClass.EndPointId other) {
+        if (other == context.ContextOuterClass.EndPointId.getDefaultInstance()) return this;
+        if (other.hasTopologyId()) {
+          mergeTopologyId(other.getTopologyId());
+        }
+        if (other.hasDeviceId()) {
+          mergeDeviceId(other.getDeviceId());
+        }
+        if (other.hasEndpointUuid()) {
+          mergeEndpointUuid(other.getEndpointUuid());
+        }
+        this.mergeUnknownFields(other.unknownFields);
+        onChanged();
+        return this;
+      }
+
+      @java.lang.Override
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      @java.lang.Override
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        context.ContextOuterClass.EndPointId parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (context.ContextOuterClass.EndPointId) e.getUnfinishedMessage();
+          throw e.unwrapIOException();
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+
+      private context.ContextOuterClass.TopologyId topologyId_;
+      private com.google.protobuf.SingleFieldBuilderV3<
+          context.ContextOuterClass.TopologyId, context.ContextOuterClass.TopologyId.Builder, context.ContextOuterClass.TopologyIdOrBuilder> topologyIdBuilder_;
+      /**
+       * <code>.context.TopologyId topology_id = 1;</code>
+       * @return Whether the topologyId field is set.
+       */
+      public boolean hasTopologyId() {
+        return topologyIdBuilder_ != null || topologyId_ != null;
+      }
+      /**
+       * <code>.context.TopologyId topology_id = 1;</code>
+       * @return The topologyId.
+       */
+      public context.ContextOuterClass.TopologyId getTopologyId() {
+        if (topologyIdBuilder_ == null) {
+          return topologyId_ == null ? context.ContextOuterClass.TopologyId.getDefaultInstance() : topologyId_;
+        } else {
+          return topologyIdBuilder_.getMessage();
+        }
+      }
+      /**
+       * <code>.context.TopologyId topology_id = 1;</code>
+       */
+      public Builder setTopologyId(context.ContextOuterClass.TopologyId value) {
+        if (topologyIdBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          topologyId_ = value;
+          onChanged();
+        } else {
+          topologyIdBuilder_.setMessage(value);
+        }
+
+        return this;
+      }
+      /**
+       * <code>.context.TopologyId topology_id = 1;</code>
+       */
+      public Builder setTopologyId(
+          context.ContextOuterClass.TopologyId.Builder builderForValue) {
+        if (topologyIdBuilder_ == null) {
+          topologyId_ = builderForValue.build();
+          onChanged();
+        } else {
+          topologyIdBuilder_.setMessage(builderForValue.build());
+        }
+
+        return this;
+      }
+      /**
+       * <code>.context.TopologyId topology_id = 1;</code>
+       */
+      public Builder mergeTopologyId(context.ContextOuterClass.TopologyId value) {
+        if (topologyIdBuilder_ == null) {
+          if (topologyId_ != null) {
+            topologyId_ =
+              context.ContextOuterClass.TopologyId.newBuilder(topologyId_).mergeFrom(value).buildPartial();
+          } else {
+            topologyId_ = value;
+          }
+          onChanged();
+        } else {
+          topologyIdBuilder_.mergeFrom(value);
+        }
+
+        return this;
+      }
+      /**
+       * <code>.context.TopologyId topology_id = 1;</code>
+       */
+      public Builder clearTopologyId() {
+        if (topologyIdBuilder_ == null) {
+          topologyId_ = null;
+          onChanged();
+        } else {
+          topologyId_ = null;
+          topologyIdBuilder_ = null;
+        }
+
+        return this;
+      }
+      /**
+       * <code>.context.TopologyId topology_id = 1;</code>
+       */
+      public context.ContextOuterClass.TopologyId.Builder getTopologyIdBuilder() {
+        
+        onChanged();
+        return getTopologyIdFieldBuilder().getBuilder();
+      }
+      /**
+       * <code>.context.TopologyId topology_id = 1;</code>
+       */
+      public context.ContextOuterClass.TopologyIdOrBuilder getTopologyIdOrBuilder() {
+        if (topologyIdBuilder_ != null) {
+          return topologyIdBuilder_.getMessageOrBuilder();
+        } else {
+          return topologyId_ == null ?
+              context.ContextOuterClass.TopologyId.getDefaultInstance() : topologyId_;
+        }
+      }
+      /**
+       * <code>.context.TopologyId topology_id = 1;</code>
+       */
+      private com.google.protobuf.SingleFieldBuilderV3<
+          context.ContextOuterClass.TopologyId, context.ContextOuterClass.TopologyId.Builder, context.ContextOuterClass.TopologyIdOrBuilder> 
+          getTopologyIdFieldBuilder() {
+        if (topologyIdBuilder_ == null) {
+          topologyIdBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
+              context.ContextOuterClass.TopologyId, context.ContextOuterClass.TopologyId.Builder, context.ContextOuterClass.TopologyIdOrBuilder>(
+                  getTopologyId(),
+                  getParentForChildren(),
+                  isClean());
+          topologyId_ = null;
+        }
+        return topologyIdBuilder_;
+      }
+
+      private context.ContextOuterClass.DeviceId deviceId_;
+      private com.google.protobuf.SingleFieldBuilderV3<
+          context.ContextOuterClass.DeviceId, context.ContextOuterClass.DeviceId.Builder, context.ContextOuterClass.DeviceIdOrBuilder> deviceIdBuilder_;
+      /**
+       * <code>.context.DeviceId device_id = 2;</code>
+       * @return Whether the deviceId field is set.
+       */
+      public boolean hasDeviceId() {
+        return deviceIdBuilder_ != null || deviceId_ != null;
+      }
+      /**
+       * <code>.context.DeviceId device_id = 2;</code>
+       * @return The deviceId.
+       */
+      public context.ContextOuterClass.DeviceId getDeviceId() {
+        if (deviceIdBuilder_ == null) {
+          return deviceId_ == null ? context.ContextOuterClass.DeviceId.getDefaultInstance() : deviceId_;
         } else {
-          super.mergeFrom(other);
-          return this;
+          return deviceIdBuilder_.getMessage();
         }
       }
-
-      public Builder mergeFrom(context.ContextOuterClass.ConnectionId other) {
-        if (other == context.ContextOuterClass.ConnectionId.getDefaultInstance()) return this;
-        if (other.hasConnectionUuid()) {
-          mergeConnectionUuid(other.getConnectionUuid());
+      /**
+       * <code>.context.DeviceId device_id = 2;</code>
+       */
+      public Builder setDeviceId(context.ContextOuterClass.DeviceId value) {
+        if (deviceIdBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          deviceId_ = value;
+          onChanged();
+        } else {
+          deviceIdBuilder_.setMessage(value);
         }
-        this.mergeUnknownFields(other.unknownFields);
-        onChanged();
+
         return this;
       }
+      /**
+       * <code>.context.DeviceId device_id = 2;</code>
+       */
+      public Builder setDeviceId(
+          context.ContextOuterClass.DeviceId.Builder builderForValue) {
+        if (deviceIdBuilder_ == null) {
+          deviceId_ = builderForValue.build();
+          onChanged();
+        } else {
+          deviceIdBuilder_.setMessage(builderForValue.build());
+        }
 
-      @java.lang.Override
-      public final boolean isInitialized() {
-        return true;
+        return this;
       }
-
-      @java.lang.Override
-      public Builder mergeFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws java.io.IOException {
-        context.ContextOuterClass.ConnectionId parsedMessage = null;
-        try {
-          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
-        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          parsedMessage = (context.ContextOuterClass.ConnectionId) e.getUnfinishedMessage();
-          throw e.unwrapIOException();
-        } finally {
-          if (parsedMessage != null) {
-            mergeFrom(parsedMessage);
+      /**
+       * <code>.context.DeviceId device_id = 2;</code>
+       */
+      public Builder mergeDeviceId(context.ContextOuterClass.DeviceId value) {
+        if (deviceIdBuilder_ == null) {
+          if (deviceId_ != null) {
+            deviceId_ =
+              context.ContextOuterClass.DeviceId.newBuilder(deviceId_).mergeFrom(value).buildPartial();
+          } else {
+            deviceId_ = value;
           }
+          onChanged();
+        } else {
+          deviceIdBuilder_.mergeFrom(value);
         }
+
         return this;
       }
+      /**
+       * <code>.context.DeviceId device_id = 2;</code>
+       */
+      public Builder clearDeviceId() {
+        if (deviceIdBuilder_ == null) {
+          deviceId_ = null;
+          onChanged();
+        } else {
+          deviceId_ = null;
+          deviceIdBuilder_ = null;
+        }
 
-      private context.ContextOuterClass.Uuid connectionUuid_;
+        return this;
+      }
+      /**
+       * <code>.context.DeviceId device_id = 2;</code>
+       */
+      public context.ContextOuterClass.DeviceId.Builder getDeviceIdBuilder() {
+        
+        onChanged();
+        return getDeviceIdFieldBuilder().getBuilder();
+      }
+      /**
+       * <code>.context.DeviceId device_id = 2;</code>
+       */
+      public context.ContextOuterClass.DeviceIdOrBuilder getDeviceIdOrBuilder() {
+        if (deviceIdBuilder_ != null) {
+          return deviceIdBuilder_.getMessageOrBuilder();
+        } else {
+          return deviceId_ == null ?
+              context.ContextOuterClass.DeviceId.getDefaultInstance() : deviceId_;
+        }
+      }
+      /**
+       * <code>.context.DeviceId device_id = 2;</code>
+       */
       private com.google.protobuf.SingleFieldBuilderV3<
-          context.ContextOuterClass.Uuid, context.ContextOuterClass.Uuid.Builder, context.ContextOuterClass.UuidOrBuilder> connectionUuidBuilder_;
+          context.ContextOuterClass.DeviceId, context.ContextOuterClass.DeviceId.Builder, context.ContextOuterClass.DeviceIdOrBuilder> 
+          getDeviceIdFieldBuilder() {
+        if (deviceIdBuilder_ == null) {
+          deviceIdBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
+              context.ContextOuterClass.DeviceId, context.ContextOuterClass.DeviceId.Builder, context.ContextOuterClass.DeviceIdOrBuilder>(
+                  getDeviceId(),
+                  getParentForChildren(),
+                  isClean());
+          deviceId_ = null;
+        }
+        return deviceIdBuilder_;
+      }
+
+      private context.ContextOuterClass.Uuid endpointUuid_;
+      private com.google.protobuf.SingleFieldBuilderV3<
+          context.ContextOuterClass.Uuid, context.ContextOuterClass.Uuid.Builder, context.ContextOuterClass.UuidOrBuilder> endpointUuidBuilder_;
       /**
-       * <code>.context.Uuid connection_uuid = 1;</code>
-       * @return Whether the connectionUuid field is set.
+       * <code>.context.Uuid endpoint_uuid = 3;</code>
+       * @return Whether the endpointUuid field is set.
        */
-      public boolean hasConnectionUuid() {
-        return connectionUuidBuilder_ != null || connectionUuid_ != null;
+      public boolean hasEndpointUuid() {
+        return endpointUuidBuilder_ != null || endpointUuid_ != null;
       }
       /**
-       * <code>.context.Uuid connection_uuid = 1;</code>
-       * @return The connectionUuid.
+       * <code>.context.Uuid endpoint_uuid = 3;</code>
+       * @return The endpointUuid.
        */
-      public context.ContextOuterClass.Uuid getConnectionUuid() {
-        if (connectionUuidBuilder_ == null) {
-          return connectionUuid_ == null ? context.ContextOuterClass.Uuid.getDefaultInstance() : connectionUuid_;
+      public context.ContextOuterClass.Uuid getEndpointUuid() {
+        if (endpointUuidBuilder_ == null) {
+          return endpointUuid_ == null ? context.ContextOuterClass.Uuid.getDefaultInstance() : endpointUuid_;
         } else {
-          return connectionUuidBuilder_.getMessage();
+          return endpointUuidBuilder_.getMessage();
         }
       }
       /**
-       * <code>.context.Uuid connection_uuid = 1;</code>
+       * <code>.context.Uuid endpoint_uuid = 3;</code>
        */
-      public Builder setConnectionUuid(context.ContextOuterClass.Uuid value) {
-        if (connectionUuidBuilder_ == null) {
+      public Builder setEndpointUuid(context.ContextOuterClass.Uuid value) {
+        if (endpointUuidBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
           }
-          connectionUuid_ = value;
+          endpointUuid_ = value;
           onChanged();
         } else {
-          connectionUuidBuilder_.setMessage(value);
+          endpointUuidBuilder_.setMessage(value);
         }
 
         return this;
       }
       /**
-       * <code>.context.Uuid connection_uuid = 1;</code>
+       * <code>.context.Uuid endpoint_uuid = 3;</code>
        */
-      public Builder setConnectionUuid(
+      public Builder setEndpointUuid(
           context.ContextOuterClass.Uuid.Builder builderForValue) {
-        if (connectionUuidBuilder_ == null) {
-          connectionUuid_ = builderForValue.build();
+        if (endpointUuidBuilder_ == null) {
+          endpointUuid_ = builderForValue.build();
           onChanged();
         } else {
-          connectionUuidBuilder_.setMessage(builderForValue.build());
+          endpointUuidBuilder_.setMessage(builderForValue.build());
         }
 
         return this;
       }
       /**
-       * <code>.context.Uuid connection_uuid = 1;</code>
+       * <code>.context.Uuid endpoint_uuid = 3;</code>
        */
-      public Builder mergeConnectionUuid(context.ContextOuterClass.Uuid value) {
-        if (connectionUuidBuilder_ == null) {
-          if (connectionUuid_ != null) {
-            connectionUuid_ =
-              context.ContextOuterClass.Uuid.newBuilder(connectionUuid_).mergeFrom(value).buildPartial();
+      public Builder mergeEndpointUuid(context.ContextOuterClass.Uuid value) {
+        if (endpointUuidBuilder_ == null) {
+          if (endpointUuid_ != null) {
+            endpointUuid_ =
+              context.ContextOuterClass.Uuid.newBuilder(endpointUuid_).mergeFrom(value).buildPartial();
           } else {
-            connectionUuid_ = value;
+            endpointUuid_ = value;
           }
           onChanged();
         } else {
-          connectionUuidBuilder_.mergeFrom(value);
+          endpointUuidBuilder_.mergeFrom(value);
         }
 
         return this;
       }
       /**
-       * <code>.context.Uuid connection_uuid = 1;</code>
+       * <code>.context.Uuid endpoint_uuid = 3;</code>
        */
-      public Builder clearConnectionUuid() {
-        if (connectionUuidBuilder_ == null) {
-          connectionUuid_ = null;
+      public Builder clearEndpointUuid() {
+        if (endpointUuidBuilder_ == null) {
+          endpointUuid_ = null;
           onChanged();
         } else {
-          connectionUuid_ = null;
-          connectionUuidBuilder_ = null;
+          endpointUuid_ = null;
+          endpointUuidBuilder_ = null;
         }
 
         return this;
       }
       /**
-       * <code>.context.Uuid connection_uuid = 1;</code>
+       * <code>.context.Uuid endpoint_uuid = 3;</code>
        */
-      public context.ContextOuterClass.Uuid.Builder getConnectionUuidBuilder() {
+      public context.ContextOuterClass.Uuid.Builder getEndpointUuidBuilder() {
         
         onChanged();
-        return getConnectionUuidFieldBuilder().getBuilder();
+        return getEndpointUuidFieldBuilder().getBuilder();
       }
       /**
-       * <code>.context.Uuid connection_uuid = 1;</code>
+       * <code>.context.Uuid endpoint_uuid = 3;</code>
        */
-      public context.ContextOuterClass.UuidOrBuilder getConnectionUuidOrBuilder() {
-        if (connectionUuidBuilder_ != null) {
-          return connectionUuidBuilder_.getMessageOrBuilder();
+      public context.ContextOuterClass.UuidOrBuilder getEndpointUuidOrBuilder() {
+        if (endpointUuidBuilder_ != null) {
+          return endpointUuidBuilder_.getMessageOrBuilder();
         } else {
-          return connectionUuid_ == null ?
-              context.ContextOuterClass.Uuid.getDefaultInstance() : connectionUuid_;
+          return endpointUuid_ == null ?
+              context.ContextOuterClass.Uuid.getDefaultInstance() : endpointUuid_;
         }
       }
       /**
-       * <code>.context.Uuid connection_uuid = 1;</code>
+       * <code>.context.Uuid endpoint_uuid = 3;</code>
        */
       private com.google.protobuf.SingleFieldBuilderV3<
           context.ContextOuterClass.Uuid, context.ContextOuterClass.Uuid.Builder, context.ContextOuterClass.UuidOrBuilder> 
-          getConnectionUuidFieldBuilder() {
-        if (connectionUuidBuilder_ == null) {
-          connectionUuidBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
+          getEndpointUuidFieldBuilder() {
+        if (endpointUuidBuilder_ == null) {
+          endpointUuidBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
               context.ContextOuterClass.Uuid, context.ContextOuterClass.Uuid.Builder, context.ContextOuterClass.UuidOrBuilder>(
-                  getConnectionUuid(),
+                  getEndpointUuid(),
                   getParentForChildren(),
                   isClean());
-          connectionUuid_ = null;
+          endpointUuid_ = null;
         }
-        return connectionUuidBuilder_;
+        return endpointUuidBuilder_;
       }
       @java.lang.Override
       public final Builder setUnknownFields(
@@ -31898,125 +33258,128 @@ public final class ContextOuterClass {
       }
 
 
-      // @@protoc_insertion_point(builder_scope:context.ConnectionId)
+      // @@protoc_insertion_point(builder_scope:context.EndPointId)
     }
 
-    // @@protoc_insertion_point(class_scope:context.ConnectionId)
-    private static final context.ContextOuterClass.ConnectionId DEFAULT_INSTANCE;
+    // @@protoc_insertion_point(class_scope:context.EndPointId)
+    private static final context.ContextOuterClass.EndPointId DEFAULT_INSTANCE;
     static {
-      DEFAULT_INSTANCE = new context.ContextOuterClass.ConnectionId();
+      DEFAULT_INSTANCE = new context.ContextOuterClass.EndPointId();
     }
 
-    public static context.ContextOuterClass.ConnectionId getDefaultInstance() {
+    public static context.ContextOuterClass.EndPointId getDefaultInstance() {
       return DEFAULT_INSTANCE;
     }
 
-    private static final com.google.protobuf.Parser<ConnectionId>
-        PARSER = new com.google.protobuf.AbstractParser<ConnectionId>() {
+    private static final com.google.protobuf.Parser<EndPointId>
+        PARSER = new com.google.protobuf.AbstractParser<EndPointId>() {
       @java.lang.Override
-      public ConnectionId parsePartialFrom(
+      public EndPointId parsePartialFrom(
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws com.google.protobuf.InvalidProtocolBufferException {
-        return new ConnectionId(input, extensionRegistry);
+        return new EndPointId(input, extensionRegistry);
       }
     };
 
-    public static com.google.protobuf.Parser<ConnectionId> parser() {
+    public static com.google.protobuf.Parser<EndPointId> parser() {
       return PARSER;
     }
 
     @java.lang.Override
-    public com.google.protobuf.Parser<ConnectionId> getParserForType() {
+    public com.google.protobuf.Parser<EndPointId> getParserForType() {
       return PARSER;
     }
 
     @java.lang.Override
-    public context.ContextOuterClass.ConnectionId getDefaultInstanceForType() {
+    public context.ContextOuterClass.EndPointId getDefaultInstanceForType() {
       return DEFAULT_INSTANCE;
     }
 
   }
 
-  public interface ConnectionOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:context.Connection)
+  public interface EndPointOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:context.EndPoint)
       com.google.protobuf.MessageOrBuilder {
 
     /**
-     * <code>.context.ConnectionId connection_id = 1;</code>
-     * @return Whether the connectionId field is set.
-     */
-    boolean hasConnectionId();
-    /**
-     * <code>.context.ConnectionId connection_id = 1;</code>
-     * @return The connectionId.
+     * <code>.context.EndPointId endpoint_id = 1;</code>
+     * @return Whether the endpointId field is set.
      */
-    context.ContextOuterClass.ConnectionId getConnectionId();
+    boolean hasEndpointId();
     /**
-     * <code>.context.ConnectionId connection_id = 1;</code>
+     * <code>.context.EndPointId endpoint_id = 1;</code>
+     * @return The endpointId.
      */
-    context.ContextOuterClass.ConnectionIdOrBuilder getConnectionIdOrBuilder();
-
+    context.ContextOuterClass.EndPointId getEndpointId();
     /**
-     * <code>.context.ServiceId related_service_id = 2;</code>
-     * @return Whether the relatedServiceId field is set.
+     * <code>.context.EndPointId endpoint_id = 1;</code>
      */
-    boolean hasRelatedServiceId();
+    context.ContextOuterClass.EndPointIdOrBuilder getEndpointIdOrBuilder();
+
     /**
-     * <code>.context.ServiceId related_service_id = 2;</code>
-     * @return The relatedServiceId.
+     * <code>string endpoint_type = 2;</code>
+     * @return The endpointType.
      */
-    context.ContextOuterClass.ServiceId getRelatedServiceId();
+    java.lang.String getEndpointType();
     /**
-     * <code>.context.ServiceId related_service_id = 2;</code>
+     * <code>string endpoint_type = 2;</code>
+     * @return The bytes for endpointType.
      */
-    context.ContextOuterClass.ServiceIdOrBuilder getRelatedServiceIdOrBuilder();
+    com.google.protobuf.ByteString
+        getEndpointTypeBytes();
 
     /**
-     * <code>repeated .context.EndPointId path = 3;</code>
+     * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
+     * @return A list containing the kpiSampleTypes.
      */
-    java.util.List<context.ContextOuterClass.EndPointId> 
-        getPathList();
+    java.util.List<kpi_sample_types.KpiSampleTypes.KpiSampleType> getKpiSampleTypesList();
     /**
-     * <code>repeated .context.EndPointId path = 3;</code>
+     * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
+     * @return The count of kpiSampleTypes.
      */
-    context.ContextOuterClass.EndPointId getPath(int index);
+    int getKpiSampleTypesCount();
     /**
-     * <code>repeated .context.EndPointId path = 3;</code>
+     * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
+     * @param index The index of the element to return.
+     * @return The kpiSampleTypes at the given index.
      */
-    int getPathCount();
+    kpi_sample_types.KpiSampleTypes.KpiSampleType getKpiSampleTypes(int index);
     /**
-     * <code>repeated .context.EndPointId path = 3;</code>
+     * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
+     * @return A list containing the enum numeric values on the wire for kpiSampleTypes.
      */
-    java.util.List<? extends context.ContextOuterClass.EndPointIdOrBuilder> 
-        getPathOrBuilderList();
+    java.util.List<java.lang.Integer>
+    getKpiSampleTypesValueList();
     /**
-     * <code>repeated .context.EndPointId path = 3;</code>
+     * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
+     * @param index The index of the value to return.
+     * @return The enum numeric value on the wire of kpiSampleTypes at the given index.
      */
-    context.ContextOuterClass.EndPointIdOrBuilder getPathOrBuilder(
-        int index);
+    int getKpiSampleTypesValue(int index);
   }
   /**
-   * Protobuf type {@code context.Connection}
+   * Protobuf type {@code context.EndPoint}
    */
-  public static final class Connection extends
+  public static final class EndPoint extends
       com.google.protobuf.GeneratedMessageV3 implements
-      // @@protoc_insertion_point(message_implements:context.Connection)
-      ConnectionOrBuilder {
+      // @@protoc_insertion_point(message_implements:context.EndPoint)
+      EndPointOrBuilder {
   private static final long serialVersionUID = 0L;
-    // Use Connection.newBuilder() to construct.
-    private Connection(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
+    // Use EndPoint.newBuilder() to construct.
+    private EndPoint(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
       super(builder);
     }
-    private Connection() {
-      path_ = java.util.Collections.emptyList();
+    private EndPoint() {
+      endpointType_ = "";
+      kpiSampleTypes_ = java.util.Collections.emptyList();
     }
 
     @java.lang.Override
     @SuppressWarnings({"unused"})
     protected java.lang.Object newInstance(
         UnusedPrivateParameter unused) {
-      return new Connection();
+      return new EndPoint();
     }
 
     @java.lang.Override
@@ -32024,7 +33387,7 @@ public final class ContextOuterClass {
     getUnknownFields() {
       return this.unknownFields;
     }
-    private Connection(
+    private EndPoint(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
@@ -32044,38 +33407,45 @@ public final class ContextOuterClass {
               done = true;
               break;
             case 10: {
-              context.ContextOuterClass.ConnectionId.Builder subBuilder = null;
-              if (connectionId_ != null) {
-                subBuilder = connectionId_.toBuilder();
+              context.ContextOuterClass.EndPointId.Builder subBuilder = null;
+              if (endpointId_ != null) {
+                subBuilder = endpointId_.toBuilder();
               }
-              connectionId_ = input.readMessage(context.ContextOuterClass.ConnectionId.parser(), extensionRegistry);
+              endpointId_ = input.readMessage(context.ContextOuterClass.EndPointId.parser(), extensionRegistry);
               if (subBuilder != null) {
-                subBuilder.mergeFrom(connectionId_);
-                connectionId_ = subBuilder.buildPartial();
+                subBuilder.mergeFrom(endpointId_);
+                endpointId_ = subBuilder.buildPartial();
               }
 
               break;
             }
             case 18: {
-              context.ContextOuterClass.ServiceId.Builder subBuilder = null;
-              if (relatedServiceId_ != null) {
-                subBuilder = relatedServiceId_.toBuilder();
-              }
-              relatedServiceId_ = input.readMessage(context.ContextOuterClass.ServiceId.parser(), extensionRegistry);
-              if (subBuilder != null) {
-                subBuilder.mergeFrom(relatedServiceId_);
-                relatedServiceId_ = subBuilder.buildPartial();
-              }
+              java.lang.String s = input.readStringRequireUtf8();
 
+              endpointType_ = s;
               break;
             }
-            case 26: {
+            case 24: {
+              int rawValue = input.readEnum();
               if (!((mutable_bitField0_ & 0x00000001) != 0)) {
-                path_ = new java.util.ArrayList<context.ContextOuterClass.EndPointId>();
+                kpiSampleTypes_ = new java.util.ArrayList<java.lang.Integer>();
                 mutable_bitField0_ |= 0x00000001;
               }
-              path_.add(
-                  input.readMessage(context.ContextOuterClass.EndPointId.parser(), extensionRegistry));
+              kpiSampleTypes_.add(rawValue);
+              break;
+            }
+            case 26: {
+              int length = input.readRawVarint32();
+              int oldLimit = input.pushLimit(length);
+              while(input.getBytesUntilLimit() > 0) {
+                int rawValue = input.readEnum();
+                if (!((mutable_bitField0_ & 0x00000001) != 0)) {
+                  kpiSampleTypes_ = new java.util.ArrayList<java.lang.Integer>();
+                  mutable_bitField0_ |= 0x00000001;
+                }
+                kpiSampleTypes_.add(rawValue);
+              }
+              input.popLimit(oldLimit);
               break;
             }
             default: {
@@ -32094,7 +33464,7 @@ public final class ContextOuterClass {
             e).setUnfinishedMessage(this);
       } finally {
         if (((mutable_bitField0_ & 0x00000001) != 0)) {
-          path_ = java.util.Collections.unmodifiableList(path_);
+          kpiSampleTypes_ = java.util.Collections.unmodifiableList(kpiSampleTypes_);
         }
         this.unknownFields = unknownFields.build();
         makeExtensionsImmutable();
@@ -32102,108 +33472,138 @@ public final class ContextOuterClass {
     }
     public static final com.google.protobuf.Descriptors.Descriptor
         getDescriptor() {
-      return context.ContextOuterClass.internal_static_context_Connection_descriptor;
+      return context.ContextOuterClass.internal_static_context_EndPoint_descriptor;
     }
 
     @java.lang.Override
     protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
         internalGetFieldAccessorTable() {
-      return context.ContextOuterClass.internal_static_context_Connection_fieldAccessorTable
+      return context.ContextOuterClass.internal_static_context_EndPoint_fieldAccessorTable
           .ensureFieldAccessorsInitialized(
-              context.ContextOuterClass.Connection.class, context.ContextOuterClass.Connection.Builder.class);
+              context.ContextOuterClass.EndPoint.class, context.ContextOuterClass.EndPoint.Builder.class);
     }
 
-    public static final int CONNECTION_ID_FIELD_NUMBER = 1;
-    private context.ContextOuterClass.ConnectionId connectionId_;
+    public static final int ENDPOINT_ID_FIELD_NUMBER = 1;
+    private context.ContextOuterClass.EndPointId endpointId_;
     /**
-     * <code>.context.ConnectionId connection_id = 1;</code>
-     * @return Whether the connectionId field is set.
+     * <code>.context.EndPointId endpoint_id = 1;</code>
+     * @return Whether the endpointId field is set.
      */
     @java.lang.Override
-    public boolean hasConnectionId() {
-      return connectionId_ != null;
+    public boolean hasEndpointId() {
+      return endpointId_ != null;
     }
     /**
-     * <code>.context.ConnectionId connection_id = 1;</code>
-     * @return The connectionId.
+     * <code>.context.EndPointId endpoint_id = 1;</code>
+     * @return The endpointId.
      */
     @java.lang.Override
-    public context.ContextOuterClass.ConnectionId getConnectionId() {
-      return connectionId_ == null ? context.ContextOuterClass.ConnectionId.getDefaultInstance() : connectionId_;
+    public context.ContextOuterClass.EndPointId getEndpointId() {
+      return endpointId_ == null ? context.ContextOuterClass.EndPointId.getDefaultInstance() : endpointId_;
     }
     /**
-     * <code>.context.ConnectionId connection_id = 1;</code>
+     * <code>.context.EndPointId endpoint_id = 1;</code>
      */
     @java.lang.Override
-    public context.ContextOuterClass.ConnectionIdOrBuilder getConnectionIdOrBuilder() {
-      return getConnectionId();
+    public context.ContextOuterClass.EndPointIdOrBuilder getEndpointIdOrBuilder() {
+      return getEndpointId();
     }
 
-    public static final int RELATED_SERVICE_ID_FIELD_NUMBER = 2;
-    private context.ContextOuterClass.ServiceId relatedServiceId_;
-    /**
-     * <code>.context.ServiceId related_service_id = 2;</code>
-     * @return Whether the relatedServiceId field is set.
-     */
-    @java.lang.Override
-    public boolean hasRelatedServiceId() {
-      return relatedServiceId_ != null;
-    }
+    public static final int ENDPOINT_TYPE_FIELD_NUMBER = 2;
+    private volatile java.lang.Object endpointType_;
     /**
-     * <code>.context.ServiceId related_service_id = 2;</code>
-     * @return The relatedServiceId.
+     * <code>string endpoint_type = 2;</code>
+     * @return The endpointType.
      */
     @java.lang.Override
-    public context.ContextOuterClass.ServiceId getRelatedServiceId() {
-      return relatedServiceId_ == null ? context.ContextOuterClass.ServiceId.getDefaultInstance() : relatedServiceId_;
+    public java.lang.String getEndpointType() {
+      java.lang.Object ref = endpointType_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        endpointType_ = s;
+        return s;
+      }
     }
     /**
-     * <code>.context.ServiceId related_service_id = 2;</code>
+     * <code>string endpoint_type = 2;</code>
+     * @return The bytes for endpointType.
      */
     @java.lang.Override
-    public context.ContextOuterClass.ServiceIdOrBuilder getRelatedServiceIdOrBuilder() {
-      return getRelatedServiceId();
+    public com.google.protobuf.ByteString
+        getEndpointTypeBytes() {
+      java.lang.Object ref = endpointType_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        endpointType_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
     }
 
-    public static final int PATH_FIELD_NUMBER = 3;
-    private java.util.List<context.ContextOuterClass.EndPointId> path_;
+    public static final int KPI_SAMPLE_TYPES_FIELD_NUMBER = 3;
+    private java.util.List<java.lang.Integer> kpiSampleTypes_;
+    private static final com.google.protobuf.Internal.ListAdapter.Converter<
+        java.lang.Integer, kpi_sample_types.KpiSampleTypes.KpiSampleType> kpiSampleTypes_converter_ =
+            new com.google.protobuf.Internal.ListAdapter.Converter<
+                java.lang.Integer, kpi_sample_types.KpiSampleTypes.KpiSampleType>() {
+              public kpi_sample_types.KpiSampleTypes.KpiSampleType convert(java.lang.Integer from) {
+                @SuppressWarnings("deprecation")
+                kpi_sample_types.KpiSampleTypes.KpiSampleType result = kpi_sample_types.KpiSampleTypes.KpiSampleType.valueOf(from);
+                return result == null ? kpi_sample_types.KpiSampleTypes.KpiSampleType.UNRECOGNIZED : result;
+              }
+            };
     /**
-     * <code>repeated .context.EndPointId path = 3;</code>
+     * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
+     * @return A list containing the kpiSampleTypes.
      */
     @java.lang.Override
-    public java.util.List<context.ContextOuterClass.EndPointId> getPathList() {
-      return path_;
+    public java.util.List<kpi_sample_types.KpiSampleTypes.KpiSampleType> getKpiSampleTypesList() {
+      return new com.google.protobuf.Internal.ListAdapter<
+          java.lang.Integer, kpi_sample_types.KpiSampleTypes.KpiSampleType>(kpiSampleTypes_, kpiSampleTypes_converter_);
     }
     /**
-     * <code>repeated .context.EndPointId path = 3;</code>
+     * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
+     * @return The count of kpiSampleTypes.
      */
     @java.lang.Override
-    public java.util.List<? extends context.ContextOuterClass.EndPointIdOrBuilder> 
-        getPathOrBuilderList() {
-      return path_;
+    public int getKpiSampleTypesCount() {
+      return kpiSampleTypes_.size();
     }
     /**
-     * <code>repeated .context.EndPointId path = 3;</code>
+     * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
+     * @param index The index of the element to return.
+     * @return The kpiSampleTypes at the given index.
      */
     @java.lang.Override
-    public int getPathCount() {
-      return path_.size();
+    public kpi_sample_types.KpiSampleTypes.KpiSampleType getKpiSampleTypes(int index) {
+      return kpiSampleTypes_converter_.convert(kpiSampleTypes_.get(index));
     }
     /**
-     * <code>repeated .context.EndPointId path = 3;</code>
+     * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
+     * @return A list containing the enum numeric values on the wire for kpiSampleTypes.
      */
     @java.lang.Override
-    public context.ContextOuterClass.EndPointId getPath(int index) {
-      return path_.get(index);
+    public java.util.List<java.lang.Integer>
+    getKpiSampleTypesValueList() {
+      return kpiSampleTypes_;
     }
     /**
-     * <code>repeated .context.EndPointId path = 3;</code>
+     * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
+     * @param index The index of the value to return.
+     * @return The enum numeric value on the wire of kpiSampleTypes at the given index.
      */
     @java.lang.Override
-    public context.ContextOuterClass.EndPointIdOrBuilder getPathOrBuilder(
-        int index) {
-      return path_.get(index);
+    public int getKpiSampleTypesValue(int index) {
+      return kpiSampleTypes_.get(index);
     }
+    private int kpiSampleTypesMemoizedSerializedSize;
 
     private byte memoizedIsInitialized = -1;
     @java.lang.Override
@@ -32219,14 +33619,19 @@ public final class ContextOuterClass {
     @java.lang.Override
     public void writeTo(com.google.protobuf.CodedOutputStream output)
                         throws java.io.IOException {
-      if (connectionId_ != null) {
-        output.writeMessage(1, getConnectionId());
+      getSerializedSize();
+      if (endpointId_ != null) {
+        output.writeMessage(1, getEndpointId());
       }
-      if (relatedServiceId_ != null) {
-        output.writeMessage(2, getRelatedServiceId());
+      if (!getEndpointTypeBytes().isEmpty()) {
+        com.google.protobuf.GeneratedMessageV3.writeString(output, 2, endpointType_);
+      }
+      if (getKpiSampleTypesList().size() > 0) {
+        output.writeUInt32NoTag(26);
+        output.writeUInt32NoTag(kpiSampleTypesMemoizedSerializedSize);
       }
-      for (int i = 0; i < path_.size(); i++) {
-        output.writeMessage(3, path_.get(i));
+      for (int i = 0; i < kpiSampleTypes_.size(); i++) {
+        output.writeEnumNoTag(kpiSampleTypes_.get(i));
       }
       unknownFields.writeTo(output);
     }
@@ -32237,17 +33642,24 @@ public final class ContextOuterClass {
       if (size != -1) return size;
 
       size = 0;
-      if (connectionId_ != null) {
+      if (endpointId_ != null) {
         size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(1, getConnectionId());
+          .computeMessageSize(1, getEndpointId());
       }
-      if (relatedServiceId_ != null) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(2, getRelatedServiceId());
+      if (!getEndpointTypeBytes().isEmpty()) {
+        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, endpointType_);
       }
-      for (int i = 0; i < path_.size(); i++) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(3, path_.get(i));
+      {
+        int dataSize = 0;
+        for (int i = 0; i < kpiSampleTypes_.size(); i++) {
+          dataSize += com.google.protobuf.CodedOutputStream
+            .computeEnumSizeNoTag(kpiSampleTypes_.get(i));
+        }
+        size += dataSize;
+        if (!getKpiSampleTypesList().isEmpty()) {  size += 1;
+          size += com.google.protobuf.CodedOutputStream
+            .computeUInt32SizeNoTag(dataSize);
+        }kpiSampleTypesMemoizedSerializedSize = dataSize;
       }
       size += unknownFields.getSerializedSize();
       memoizedSize = size;
@@ -32259,23 +33671,19 @@ public final class ContextOuterClass {
       if (obj == this) {
        return true;
       }
-      if (!(obj instanceof context.ContextOuterClass.Connection)) {
+      if (!(obj instanceof context.ContextOuterClass.EndPoint)) {
         return super.equals(obj);
       }
-      context.ContextOuterClass.Connection other = (context.ContextOuterClass.Connection) obj;
+      context.ContextOuterClass.EndPoint other = (context.ContextOuterClass.EndPoint) obj;
 
-      if (hasConnectionId() != other.hasConnectionId()) return false;
-      if (hasConnectionId()) {
-        if (!getConnectionId()
-            .equals(other.getConnectionId())) return false;
-      }
-      if (hasRelatedServiceId() != other.hasRelatedServiceId()) return false;
-      if (hasRelatedServiceId()) {
-        if (!getRelatedServiceId()
-            .equals(other.getRelatedServiceId())) return false;
+      if (hasEndpointId() != other.hasEndpointId()) return false;
+      if (hasEndpointId()) {
+        if (!getEndpointId()
+            .equals(other.getEndpointId())) return false;
       }
-      if (!getPathList()
-          .equals(other.getPathList())) return false;
+      if (!getEndpointType()
+          .equals(other.getEndpointType())) return false;
+      if (!kpiSampleTypes_.equals(other.kpiSampleTypes_)) return false;
       if (!unknownFields.equals(other.unknownFields)) return false;
       return true;
     }
@@ -32287,86 +33695,84 @@ public final class ContextOuterClass {
       }
       int hash = 41;
       hash = (19 * hash) + getDescriptor().hashCode();
-      if (hasConnectionId()) {
-        hash = (37 * hash) + CONNECTION_ID_FIELD_NUMBER;
-        hash = (53 * hash) + getConnectionId().hashCode();
-      }
-      if (hasRelatedServiceId()) {
-        hash = (37 * hash) + RELATED_SERVICE_ID_FIELD_NUMBER;
-        hash = (53 * hash) + getRelatedServiceId().hashCode();
+      if (hasEndpointId()) {
+        hash = (37 * hash) + ENDPOINT_ID_FIELD_NUMBER;
+        hash = (53 * hash) + getEndpointId().hashCode();
       }
-      if (getPathCount() > 0) {
-        hash = (37 * hash) + PATH_FIELD_NUMBER;
-        hash = (53 * hash) + getPathList().hashCode();
+      hash = (37 * hash) + ENDPOINT_TYPE_FIELD_NUMBER;
+      hash = (53 * hash) + getEndpointType().hashCode();
+      if (getKpiSampleTypesCount() > 0) {
+        hash = (37 * hash) + KPI_SAMPLE_TYPES_FIELD_NUMBER;
+        hash = (53 * hash) + kpiSampleTypes_.hashCode();
       }
       hash = (29 * hash) + unknownFields.hashCode();
       memoizedHashCode = hash;
       return hash;
     }
 
-    public static context.ContextOuterClass.Connection parseFrom(
+    public static context.ContextOuterClass.EndPoint parseFrom(
         java.nio.ByteBuffer data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static context.ContextOuterClass.Connection parseFrom(
+    public static context.ContextOuterClass.EndPoint parseFrom(
         java.nio.ByteBuffer data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static context.ContextOuterClass.Connection parseFrom(
+    public static context.ContextOuterClass.EndPoint parseFrom(
         com.google.protobuf.ByteString data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static context.ContextOuterClass.Connection parseFrom(
+    public static context.ContextOuterClass.EndPoint parseFrom(
         com.google.protobuf.ByteString data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static context.ContextOuterClass.Connection parseFrom(byte[] data)
+    public static context.ContextOuterClass.EndPoint parseFrom(byte[] data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static context.ContextOuterClass.Connection parseFrom(
+    public static context.ContextOuterClass.EndPoint parseFrom(
         byte[] data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static context.ContextOuterClass.Connection parseFrom(java.io.InputStream input)
+    public static context.ContextOuterClass.EndPoint parseFrom(java.io.InputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseWithIOException(PARSER, input);
     }
-    public static context.ContextOuterClass.Connection parseFrom(
+    public static context.ContextOuterClass.EndPoint parseFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseWithIOException(PARSER, input, extensionRegistry);
     }
-    public static context.ContextOuterClass.Connection parseDelimitedFrom(java.io.InputStream input)
+    public static context.ContextOuterClass.EndPoint parseDelimitedFrom(java.io.InputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseDelimitedWithIOException(PARSER, input);
     }
-    public static context.ContextOuterClass.Connection parseDelimitedFrom(
+    public static context.ContextOuterClass.EndPoint parseDelimitedFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
     }
-    public static context.ContextOuterClass.Connection parseFrom(
+    public static context.ContextOuterClass.EndPoint parseFrom(
         com.google.protobuf.CodedInputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseWithIOException(PARSER, input);
     }
-    public static context.ContextOuterClass.Connection parseFrom(
+    public static context.ContextOuterClass.EndPoint parseFrom(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -32379,7 +33785,7 @@ public final class ContextOuterClass {
     public static Builder newBuilder() {
       return DEFAULT_INSTANCE.toBuilder();
     }
-    public static Builder newBuilder(context.ContextOuterClass.Connection prototype) {
+    public static Builder newBuilder(context.ContextOuterClass.EndPoint prototype) {
       return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
     }
     @java.lang.Override
@@ -32395,26 +33801,26 @@ public final class ContextOuterClass {
       return builder;
     }
     /**
-     * Protobuf type {@code context.Connection}
+     * Protobuf type {@code context.EndPoint}
      */
     public static final class Builder extends
         com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:context.Connection)
-        context.ContextOuterClass.ConnectionOrBuilder {
+        // @@protoc_insertion_point(builder_implements:context.EndPoint)
+        context.ContextOuterClass.EndPointOrBuilder {
       public static final com.google.protobuf.Descriptors.Descriptor
           getDescriptor() {
-        return context.ContextOuterClass.internal_static_context_Connection_descriptor;
+        return context.ContextOuterClass.internal_static_context_EndPoint_descriptor;
       }
 
       @java.lang.Override
       protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
           internalGetFieldAccessorTable() {
-        return context.ContextOuterClass.internal_static_context_Connection_fieldAccessorTable
+        return context.ContextOuterClass.internal_static_context_EndPoint_fieldAccessorTable
             .ensureFieldAccessorsInitialized(
-                context.ContextOuterClass.Connection.class, context.ContextOuterClass.Connection.Builder.class);
+                context.ContextOuterClass.EndPoint.class, context.ContextOuterClass.EndPoint.Builder.class);
       }
 
-      // Construct using context.ContextOuterClass.Connection.newBuilder()
+      // Construct using context.ContextOuterClass.EndPoint.newBuilder()
       private Builder() {
         maybeForceBuilderInitialization();
       }
@@ -32427,47 +33833,38 @@ public final class ContextOuterClass {
       private void maybeForceBuilderInitialization() {
         if (com.google.protobuf.GeneratedMessageV3
                 .alwaysUseFieldBuilders) {
-          getPathFieldBuilder();
         }
       }
       @java.lang.Override
       public Builder clear() {
         super.clear();
-        if (connectionIdBuilder_ == null) {
-          connectionId_ = null;
-        } else {
-          connectionId_ = null;
-          connectionIdBuilder_ = null;
-        }
-        if (relatedServiceIdBuilder_ == null) {
-          relatedServiceId_ = null;
-        } else {
-          relatedServiceId_ = null;
-          relatedServiceIdBuilder_ = null;
-        }
-        if (pathBuilder_ == null) {
-          path_ = java.util.Collections.emptyList();
-          bitField0_ = (bitField0_ & ~0x00000001);
+        if (endpointIdBuilder_ == null) {
+          endpointId_ = null;
         } else {
-          pathBuilder_.clear();
+          endpointId_ = null;
+          endpointIdBuilder_ = null;
         }
+        endpointType_ = "";
+
+        kpiSampleTypes_ = java.util.Collections.emptyList();
+        bitField0_ = (bitField0_ & ~0x00000001);
         return this;
       }
 
       @java.lang.Override
       public com.google.protobuf.Descriptors.Descriptor
           getDescriptorForType() {
-        return context.ContextOuterClass.internal_static_context_Connection_descriptor;
+        return context.ContextOuterClass.internal_static_context_EndPoint_descriptor;
       }
 
       @java.lang.Override
-      public context.ContextOuterClass.Connection getDefaultInstanceForType() {
-        return context.ContextOuterClass.Connection.getDefaultInstance();
+      public context.ContextOuterClass.EndPoint getDefaultInstanceForType() {
+        return context.ContextOuterClass.EndPoint.getDefaultInstance();
       }
 
       @java.lang.Override
-      public context.ContextOuterClass.Connection build() {
-        context.ContextOuterClass.Connection result = buildPartial();
+      public context.ContextOuterClass.EndPoint build() {
+        context.ContextOuterClass.EndPoint result = buildPartial();
         if (!result.isInitialized()) {
           throw newUninitializedMessageException(result);
         }
@@ -32475,28 +33872,20 @@ public final class ContextOuterClass {
       }
 
       @java.lang.Override
-      public context.ContextOuterClass.Connection buildPartial() {
-        context.ContextOuterClass.Connection result = new context.ContextOuterClass.Connection(this);
+      public context.ContextOuterClass.EndPoint buildPartial() {
+        context.ContextOuterClass.EndPoint result = new context.ContextOuterClass.EndPoint(this);
         int from_bitField0_ = bitField0_;
-        if (connectionIdBuilder_ == null) {
-          result.connectionId_ = connectionId_;
-        } else {
-          result.connectionId_ = connectionIdBuilder_.build();
-        }
-        if (relatedServiceIdBuilder_ == null) {
-          result.relatedServiceId_ = relatedServiceId_;
+        if (endpointIdBuilder_ == null) {
+          result.endpointId_ = endpointId_;
         } else {
-          result.relatedServiceId_ = relatedServiceIdBuilder_.build();
+          result.endpointId_ = endpointIdBuilder_.build();
         }
-        if (pathBuilder_ == null) {
-          if (((bitField0_ & 0x00000001) != 0)) {
-            path_ = java.util.Collections.unmodifiableList(path_);
-            bitField0_ = (bitField0_ & ~0x00000001);
-          }
-          result.path_ = path_;
-        } else {
-          result.path_ = pathBuilder_.build();
+        result.endpointType_ = endpointType_;
+        if (((bitField0_ & 0x00000001) != 0)) {
+          kpiSampleTypes_ = java.util.Collections.unmodifiableList(kpiSampleTypes_);
+          bitField0_ = (bitField0_ & ~0x00000001);
         }
+        result.kpiSampleTypes_ = kpiSampleTypes_;
         onBuilt();
         return result;
       }
@@ -32535,47 +33924,32 @@ public final class ContextOuterClass {
       }
       @java.lang.Override
       public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof context.ContextOuterClass.Connection) {
-          return mergeFrom((context.ContextOuterClass.Connection)other);
+        if (other instanceof context.ContextOuterClass.EndPoint) {
+          return mergeFrom((context.ContextOuterClass.EndPoint)other);
         } else {
           super.mergeFrom(other);
           return this;
         }
       }
 
-      public Builder mergeFrom(context.ContextOuterClass.Connection other) {
-        if (other == context.ContextOuterClass.Connection.getDefaultInstance()) return this;
-        if (other.hasConnectionId()) {
-          mergeConnectionId(other.getConnectionId());
+      public Builder mergeFrom(context.ContextOuterClass.EndPoint other) {
+        if (other == context.ContextOuterClass.EndPoint.getDefaultInstance()) return this;
+        if (other.hasEndpointId()) {
+          mergeEndpointId(other.getEndpointId());
         }
-        if (other.hasRelatedServiceId()) {
-          mergeRelatedServiceId(other.getRelatedServiceId());
+        if (!other.getEndpointType().isEmpty()) {
+          endpointType_ = other.endpointType_;
+          onChanged();
         }
-        if (pathBuilder_ == null) {
-          if (!other.path_.isEmpty()) {
-            if (path_.isEmpty()) {
-              path_ = other.path_;
-              bitField0_ = (bitField0_ & ~0x00000001);
-            } else {
-              ensurePathIsMutable();
-              path_.addAll(other.path_);
-            }
-            onChanged();
-          }
-        } else {
-          if (!other.path_.isEmpty()) {
-            if (pathBuilder_.isEmpty()) {
-              pathBuilder_.dispose();
-              pathBuilder_ = null;
-              path_ = other.path_;
-              bitField0_ = (bitField0_ & ~0x00000001);
-              pathBuilder_ = 
-                com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ?
-                   getPathFieldBuilder() : null;
-            } else {
-              pathBuilder_.addAllMessages(other.path_);
-            }
+        if (!other.kpiSampleTypes_.isEmpty()) {
+          if (kpiSampleTypes_.isEmpty()) {
+            kpiSampleTypes_ = other.kpiSampleTypes_;
+            bitField0_ = (bitField0_ & ~0x00000001);
+          } else {
+            ensureKpiSampleTypesIsMutable();
+            kpiSampleTypes_.addAll(other.kpiSampleTypes_);
           }
+          onChanged();
         }
         this.mergeUnknownFields(other.unknownFields);
         onChanged();
@@ -32592,497 +33966,354 @@ public final class ContextOuterClass {
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws java.io.IOException {
-        context.ContextOuterClass.Connection parsedMessage = null;
+        context.ContextOuterClass.EndPoint parsedMessage = null;
         try {
           parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
         } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          parsedMessage = (context.ContextOuterClass.Connection) e.getUnfinishedMessage();
-          throw e.unwrapIOException();
-        } finally {
-          if (parsedMessage != null) {
-            mergeFrom(parsedMessage);
-          }
-        }
-        return this;
-      }
-      private int bitField0_;
-
-      private context.ContextOuterClass.ConnectionId connectionId_;
-      private com.google.protobuf.SingleFieldBuilderV3<
-          context.ContextOuterClass.ConnectionId, context.ContextOuterClass.ConnectionId.Builder, context.ContextOuterClass.ConnectionIdOrBuilder> connectionIdBuilder_;
-      /**
-       * <code>.context.ConnectionId connection_id = 1;</code>
-       * @return Whether the connectionId field is set.
-       */
-      public boolean hasConnectionId() {
-        return connectionIdBuilder_ != null || connectionId_ != null;
-      }
-      /**
-       * <code>.context.ConnectionId connection_id = 1;</code>
-       * @return The connectionId.
-       */
-      public context.ContextOuterClass.ConnectionId getConnectionId() {
-        if (connectionIdBuilder_ == null) {
-          return connectionId_ == null ? context.ContextOuterClass.ConnectionId.getDefaultInstance() : connectionId_;
-        } else {
-          return connectionIdBuilder_.getMessage();
-        }
-      }
-      /**
-       * <code>.context.ConnectionId connection_id = 1;</code>
-       */
-      public Builder setConnectionId(context.ContextOuterClass.ConnectionId value) {
-        if (connectionIdBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          connectionId_ = value;
-          onChanged();
-        } else {
-          connectionIdBuilder_.setMessage(value);
-        }
-
-        return this;
-      }
-      /**
-       * <code>.context.ConnectionId connection_id = 1;</code>
-       */
-      public Builder setConnectionId(
-          context.ContextOuterClass.ConnectionId.Builder builderForValue) {
-        if (connectionIdBuilder_ == null) {
-          connectionId_ = builderForValue.build();
-          onChanged();
-        } else {
-          connectionIdBuilder_.setMessage(builderForValue.build());
-        }
-
-        return this;
-      }
-      /**
-       * <code>.context.ConnectionId connection_id = 1;</code>
-       */
-      public Builder mergeConnectionId(context.ContextOuterClass.ConnectionId value) {
-        if (connectionIdBuilder_ == null) {
-          if (connectionId_ != null) {
-            connectionId_ =
-              context.ContextOuterClass.ConnectionId.newBuilder(connectionId_).mergeFrom(value).buildPartial();
-          } else {
-            connectionId_ = value;
-          }
-          onChanged();
-        } else {
-          connectionIdBuilder_.mergeFrom(value);
-        }
-
-        return this;
-      }
-      /**
-       * <code>.context.ConnectionId connection_id = 1;</code>
-       */
-      public Builder clearConnectionId() {
-        if (connectionIdBuilder_ == null) {
-          connectionId_ = null;
-          onChanged();
-        } else {
-          connectionId_ = null;
-          connectionIdBuilder_ = null;
-        }
-
-        return this;
-      }
-      /**
-       * <code>.context.ConnectionId connection_id = 1;</code>
-       */
-      public context.ContextOuterClass.ConnectionId.Builder getConnectionIdBuilder() {
-        
-        onChanged();
-        return getConnectionIdFieldBuilder().getBuilder();
-      }
-      /**
-       * <code>.context.ConnectionId connection_id = 1;</code>
-       */
-      public context.ContextOuterClass.ConnectionIdOrBuilder getConnectionIdOrBuilder() {
-        if (connectionIdBuilder_ != null) {
-          return connectionIdBuilder_.getMessageOrBuilder();
-        } else {
-          return connectionId_ == null ?
-              context.ContextOuterClass.ConnectionId.getDefaultInstance() : connectionId_;
-        }
-      }
-      /**
-       * <code>.context.ConnectionId connection_id = 1;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilderV3<
-          context.ContextOuterClass.ConnectionId, context.ContextOuterClass.ConnectionId.Builder, context.ContextOuterClass.ConnectionIdOrBuilder> 
-          getConnectionIdFieldBuilder() {
-        if (connectionIdBuilder_ == null) {
-          connectionIdBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              context.ContextOuterClass.ConnectionId, context.ContextOuterClass.ConnectionId.Builder, context.ContextOuterClass.ConnectionIdOrBuilder>(
-                  getConnectionId(),
-                  getParentForChildren(),
-                  isClean());
-          connectionId_ = null;
+          parsedMessage = (context.ContextOuterClass.EndPoint) e.getUnfinishedMessage();
+          throw e.unwrapIOException();
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
         }
-        return connectionIdBuilder_;
+        return this;
       }
+      private int bitField0_;
 
-      private context.ContextOuterClass.ServiceId relatedServiceId_;
+      private context.ContextOuterClass.EndPointId endpointId_;
       private com.google.protobuf.SingleFieldBuilderV3<
-          context.ContextOuterClass.ServiceId, context.ContextOuterClass.ServiceId.Builder, context.ContextOuterClass.ServiceIdOrBuilder> relatedServiceIdBuilder_;
+          context.ContextOuterClass.EndPointId, context.ContextOuterClass.EndPointId.Builder, context.ContextOuterClass.EndPointIdOrBuilder> endpointIdBuilder_;
       /**
-       * <code>.context.ServiceId related_service_id = 2;</code>
-       * @return Whether the relatedServiceId field is set.
+       * <code>.context.EndPointId endpoint_id = 1;</code>
+       * @return Whether the endpointId field is set.
        */
-      public boolean hasRelatedServiceId() {
-        return relatedServiceIdBuilder_ != null || relatedServiceId_ != null;
+      public boolean hasEndpointId() {
+        return endpointIdBuilder_ != null || endpointId_ != null;
       }
       /**
-       * <code>.context.ServiceId related_service_id = 2;</code>
-       * @return The relatedServiceId.
+       * <code>.context.EndPointId endpoint_id = 1;</code>
+       * @return The endpointId.
        */
-      public context.ContextOuterClass.ServiceId getRelatedServiceId() {
-        if (relatedServiceIdBuilder_ == null) {
-          return relatedServiceId_ == null ? context.ContextOuterClass.ServiceId.getDefaultInstance() : relatedServiceId_;
+      public context.ContextOuterClass.EndPointId getEndpointId() {
+        if (endpointIdBuilder_ == null) {
+          return endpointId_ == null ? context.ContextOuterClass.EndPointId.getDefaultInstance() : endpointId_;
         } else {
-          return relatedServiceIdBuilder_.getMessage();
+          return endpointIdBuilder_.getMessage();
         }
       }
       /**
-       * <code>.context.ServiceId related_service_id = 2;</code>
+       * <code>.context.EndPointId endpoint_id = 1;</code>
        */
-      public Builder setRelatedServiceId(context.ContextOuterClass.ServiceId value) {
-        if (relatedServiceIdBuilder_ == null) {
+      public Builder setEndpointId(context.ContextOuterClass.EndPointId value) {
+        if (endpointIdBuilder_ == null) {
           if (value == null) {
             throw new NullPointerException();
           }
-          relatedServiceId_ = value;
+          endpointId_ = value;
           onChanged();
         } else {
-          relatedServiceIdBuilder_.setMessage(value);
+          endpointIdBuilder_.setMessage(value);
         }
 
         return this;
       }
       /**
-       * <code>.context.ServiceId related_service_id = 2;</code>
+       * <code>.context.EndPointId endpoint_id = 1;</code>
        */
-      public Builder setRelatedServiceId(
-          context.ContextOuterClass.ServiceId.Builder builderForValue) {
-        if (relatedServiceIdBuilder_ == null) {
-          relatedServiceId_ = builderForValue.build();
+      public Builder setEndpointId(
+          context.ContextOuterClass.EndPointId.Builder builderForValue) {
+        if (endpointIdBuilder_ == null) {
+          endpointId_ = builderForValue.build();
           onChanged();
         } else {
-          relatedServiceIdBuilder_.setMessage(builderForValue.build());
+          endpointIdBuilder_.setMessage(builderForValue.build());
         }
 
         return this;
       }
       /**
-       * <code>.context.ServiceId related_service_id = 2;</code>
+       * <code>.context.EndPointId endpoint_id = 1;</code>
        */
-      public Builder mergeRelatedServiceId(context.ContextOuterClass.ServiceId value) {
-        if (relatedServiceIdBuilder_ == null) {
-          if (relatedServiceId_ != null) {
-            relatedServiceId_ =
-              context.ContextOuterClass.ServiceId.newBuilder(relatedServiceId_).mergeFrom(value).buildPartial();
+      public Builder mergeEndpointId(context.ContextOuterClass.EndPointId value) {
+        if (endpointIdBuilder_ == null) {
+          if (endpointId_ != null) {
+            endpointId_ =
+              context.ContextOuterClass.EndPointId.newBuilder(endpointId_).mergeFrom(value).buildPartial();
           } else {
-            relatedServiceId_ = value;
+            endpointId_ = value;
           }
           onChanged();
         } else {
-          relatedServiceIdBuilder_.mergeFrom(value);
+          endpointIdBuilder_.mergeFrom(value);
         }
 
         return this;
       }
       /**
-       * <code>.context.ServiceId related_service_id = 2;</code>
+       * <code>.context.EndPointId endpoint_id = 1;</code>
        */
-      public Builder clearRelatedServiceId() {
-        if (relatedServiceIdBuilder_ == null) {
-          relatedServiceId_ = null;
+      public Builder clearEndpointId() {
+        if (endpointIdBuilder_ == null) {
+          endpointId_ = null;
           onChanged();
         } else {
-          relatedServiceId_ = null;
-          relatedServiceIdBuilder_ = null;
+          endpointId_ = null;
+          endpointIdBuilder_ = null;
         }
 
         return this;
       }
       /**
-       * <code>.context.ServiceId related_service_id = 2;</code>
+       * <code>.context.EndPointId endpoint_id = 1;</code>
        */
-      public context.ContextOuterClass.ServiceId.Builder getRelatedServiceIdBuilder() {
+      public context.ContextOuterClass.EndPointId.Builder getEndpointIdBuilder() {
         
         onChanged();
-        return getRelatedServiceIdFieldBuilder().getBuilder();
+        return getEndpointIdFieldBuilder().getBuilder();
       }
       /**
-       * <code>.context.ServiceId related_service_id = 2;</code>
+       * <code>.context.EndPointId endpoint_id = 1;</code>
        */
-      public context.ContextOuterClass.ServiceIdOrBuilder getRelatedServiceIdOrBuilder() {
-        if (relatedServiceIdBuilder_ != null) {
-          return relatedServiceIdBuilder_.getMessageOrBuilder();
+      public context.ContextOuterClass.EndPointIdOrBuilder getEndpointIdOrBuilder() {
+        if (endpointIdBuilder_ != null) {
+          return endpointIdBuilder_.getMessageOrBuilder();
         } else {
-          return relatedServiceId_ == null ?
-              context.ContextOuterClass.ServiceId.getDefaultInstance() : relatedServiceId_;
+          return endpointId_ == null ?
+              context.ContextOuterClass.EndPointId.getDefaultInstance() : endpointId_;
         }
       }
       /**
-       * <code>.context.ServiceId related_service_id = 2;</code>
+       * <code>.context.EndPointId endpoint_id = 1;</code>
        */
       private com.google.protobuf.SingleFieldBuilderV3<
-          context.ContextOuterClass.ServiceId, context.ContextOuterClass.ServiceId.Builder, context.ContextOuterClass.ServiceIdOrBuilder> 
-          getRelatedServiceIdFieldBuilder() {
-        if (relatedServiceIdBuilder_ == null) {
-          relatedServiceIdBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
-              context.ContextOuterClass.ServiceId, context.ContextOuterClass.ServiceId.Builder, context.ContextOuterClass.ServiceIdOrBuilder>(
-                  getRelatedServiceId(),
+          context.ContextOuterClass.EndPointId, context.ContextOuterClass.EndPointId.Builder, context.ContextOuterClass.EndPointIdOrBuilder> 
+          getEndpointIdFieldBuilder() {
+        if (endpointIdBuilder_ == null) {
+          endpointIdBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
+              context.ContextOuterClass.EndPointId, context.ContextOuterClass.EndPointId.Builder, context.ContextOuterClass.EndPointIdOrBuilder>(
+                  getEndpointId(),
                   getParentForChildren(),
                   isClean());
-          relatedServiceId_ = null;
+          endpointId_ = null;
         }
-        return relatedServiceIdBuilder_;
-      }
-
-      private java.util.List<context.ContextOuterClass.EndPointId> path_ =
-        java.util.Collections.emptyList();
-      private void ensurePathIsMutable() {
-        if (!((bitField0_ & 0x00000001) != 0)) {
-          path_ = new java.util.ArrayList<context.ContextOuterClass.EndPointId>(path_);
-          bitField0_ |= 0x00000001;
-         }
+        return endpointIdBuilder_;
       }
 
-      private com.google.protobuf.RepeatedFieldBuilderV3<
-          context.ContextOuterClass.EndPointId, context.ContextOuterClass.EndPointId.Builder, context.ContextOuterClass.EndPointIdOrBuilder> pathBuilder_;
-
+      private java.lang.Object endpointType_ = "";
       /**
-       * <code>repeated .context.EndPointId path = 3;</code>
+       * <code>string endpoint_type = 2;</code>
+       * @return The endpointType.
        */
-      public java.util.List<context.ContextOuterClass.EndPointId> getPathList() {
-        if (pathBuilder_ == null) {
-          return java.util.Collections.unmodifiableList(path_);
+      public java.lang.String getEndpointType() {
+        java.lang.Object ref = endpointType_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          endpointType_ = s;
+          return s;
         } else {
-          return pathBuilder_.getMessageList();
+          return (java.lang.String) ref;
         }
       }
       /**
-       * <code>repeated .context.EndPointId path = 3;</code>
+       * <code>string endpoint_type = 2;</code>
+       * @return The bytes for endpointType.
        */
-      public int getPathCount() {
-        if (pathBuilder_ == null) {
-          return path_.size();
+      public com.google.protobuf.ByteString
+          getEndpointTypeBytes() {
+        java.lang.Object ref = endpointType_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          endpointType_ = b;
+          return b;
         } else {
-          return pathBuilder_.getCount();
+          return (com.google.protobuf.ByteString) ref;
         }
       }
       /**
-       * <code>repeated .context.EndPointId path = 3;</code>
+       * <code>string endpoint_type = 2;</code>
+       * @param value The endpointType to set.
+       * @return This builder for chaining.
        */
-      public context.ContextOuterClass.EndPointId getPath(int index) {
-        if (pathBuilder_ == null) {
-          return path_.get(index);
-        } else {
-          return pathBuilder_.getMessage(index);
-        }
+      public Builder setEndpointType(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  
+        endpointType_ = value;
+        onChanged();
+        return this;
       }
       /**
-       * <code>repeated .context.EndPointId path = 3;</code>
+       * <code>string endpoint_type = 2;</code>
+       * @return This builder for chaining.
        */
-      public Builder setPath(
-          int index, context.ContextOuterClass.EndPointId value) {
-        if (pathBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensurePathIsMutable();
-          path_.set(index, value);
-          onChanged();
-        } else {
-          pathBuilder_.setMessage(index, value);
-        }
+      public Builder clearEndpointType() {
+        
+        endpointType_ = getDefaultInstance().getEndpointType();
+        onChanged();
         return this;
       }
       /**
-       * <code>repeated .context.EndPointId path = 3;</code>
+       * <code>string endpoint_type = 2;</code>
+       * @param value The bytes for endpointType to set.
+       * @return This builder for chaining.
        */
-      public Builder setPath(
-          int index, context.ContextOuterClass.EndPointId.Builder builderForValue) {
-        if (pathBuilder_ == null) {
-          ensurePathIsMutable();
-          path_.set(index, builderForValue.build());
-          onChanged();
-        } else {
-          pathBuilder_.setMessage(index, builderForValue.build());
-        }
+      public Builder setEndpointTypeBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  checkByteStringIsUtf8(value);
+        
+        endpointType_ = value;
+        onChanged();
         return this;
       }
-      /**
-       * <code>repeated .context.EndPointId path = 3;</code>
-       */
-      public Builder addPath(context.ContextOuterClass.EndPointId value) {
-        if (pathBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensurePathIsMutable();
-          path_.add(value);
-          onChanged();
-        } else {
-          pathBuilder_.addMessage(value);
+
+      private java.util.List<java.lang.Integer> kpiSampleTypes_ =
+        java.util.Collections.emptyList();
+      private void ensureKpiSampleTypesIsMutable() {
+        if (!((bitField0_ & 0x00000001) != 0)) {
+          kpiSampleTypes_ = new java.util.ArrayList<java.lang.Integer>(kpiSampleTypes_);
+          bitField0_ |= 0x00000001;
         }
-        return this;
       }
       /**
-       * <code>repeated .context.EndPointId path = 3;</code>
+       * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
+       * @return A list containing the kpiSampleTypes.
        */
-      public Builder addPath(
-          int index, context.ContextOuterClass.EndPointId value) {
-        if (pathBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensurePathIsMutable();
-          path_.add(index, value);
-          onChanged();
-        } else {
-          pathBuilder_.addMessage(index, value);
-        }
-        return this;
+      public java.util.List<kpi_sample_types.KpiSampleTypes.KpiSampleType> getKpiSampleTypesList() {
+        return new com.google.protobuf.Internal.ListAdapter<
+            java.lang.Integer, kpi_sample_types.KpiSampleTypes.KpiSampleType>(kpiSampleTypes_, kpiSampleTypes_converter_);
       }
       /**
-       * <code>repeated .context.EndPointId path = 3;</code>
+       * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
+       * @return The count of kpiSampleTypes.
        */
-      public Builder addPath(
-          context.ContextOuterClass.EndPointId.Builder builderForValue) {
-        if (pathBuilder_ == null) {
-          ensurePathIsMutable();
-          path_.add(builderForValue.build());
-          onChanged();
-        } else {
-          pathBuilder_.addMessage(builderForValue.build());
-        }
-        return this;
+      public int getKpiSampleTypesCount() {
+        return kpiSampleTypes_.size();
       }
       /**
-       * <code>repeated .context.EndPointId path = 3;</code>
+       * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
+       * @param index The index of the element to return.
+       * @return The kpiSampleTypes at the given index.
        */
-      public Builder addPath(
-          int index, context.ContextOuterClass.EndPointId.Builder builderForValue) {
-        if (pathBuilder_ == null) {
-          ensurePathIsMutable();
-          path_.add(index, builderForValue.build());
-          onChanged();
-        } else {
-          pathBuilder_.addMessage(index, builderForValue.build());
-        }
-        return this;
+      public kpi_sample_types.KpiSampleTypes.KpiSampleType getKpiSampleTypes(int index) {
+        return kpiSampleTypes_converter_.convert(kpiSampleTypes_.get(index));
       }
       /**
-       * <code>repeated .context.EndPointId path = 3;</code>
+       * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
+       * @param index The index to set the value at.
+       * @param value The kpiSampleTypes to set.
+       * @return This builder for chaining.
        */
-      public Builder addAllPath(
-          java.lang.Iterable<? extends context.ContextOuterClass.EndPointId> values) {
-        if (pathBuilder_ == null) {
-          ensurePathIsMutable();
-          com.google.protobuf.AbstractMessageLite.Builder.addAll(
-              values, path_);
-          onChanged();
-        } else {
-          pathBuilder_.addAllMessages(values);
+      public Builder setKpiSampleTypes(
+          int index, kpi_sample_types.KpiSampleTypes.KpiSampleType value) {
+        if (value == null) {
+          throw new NullPointerException();
         }
+        ensureKpiSampleTypesIsMutable();
+        kpiSampleTypes_.set(index, value.getNumber());
+        onChanged();
         return this;
       }
       /**
-       * <code>repeated .context.EndPointId path = 3;</code>
+       * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
+       * @param value The kpiSampleTypes to add.
+       * @return This builder for chaining.
        */
-      public Builder clearPath() {
-        if (pathBuilder_ == null) {
-          path_ = java.util.Collections.emptyList();
-          bitField0_ = (bitField0_ & ~0x00000001);
-          onChanged();
-        } else {
-          pathBuilder_.clear();
+      public Builder addKpiSampleTypes(kpi_sample_types.KpiSampleTypes.KpiSampleType value) {
+        if (value == null) {
+          throw new NullPointerException();
         }
+        ensureKpiSampleTypesIsMutable();
+        kpiSampleTypes_.add(value.getNumber());
+        onChanged();
         return this;
       }
       /**
-       * <code>repeated .context.EndPointId path = 3;</code>
+       * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
+       * @param values The kpiSampleTypes to add.
+       * @return This builder for chaining.
        */
-      public Builder removePath(int index) {
-        if (pathBuilder_ == null) {
-          ensurePathIsMutable();
-          path_.remove(index);
-          onChanged();
-        } else {
-          pathBuilder_.remove(index);
+      public Builder addAllKpiSampleTypes(
+          java.lang.Iterable<? extends kpi_sample_types.KpiSampleTypes.KpiSampleType> values) {
+        ensureKpiSampleTypesIsMutable();
+        for (kpi_sample_types.KpiSampleTypes.KpiSampleType value : values) {
+          kpiSampleTypes_.add(value.getNumber());
         }
+        onChanged();
         return this;
       }
       /**
-       * <code>repeated .context.EndPointId path = 3;</code>
+       * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
+       * @return This builder for chaining.
        */
-      public context.ContextOuterClass.EndPointId.Builder getPathBuilder(
-          int index) {
-        return getPathFieldBuilder().getBuilder(index);
+      public Builder clearKpiSampleTypes() {
+        kpiSampleTypes_ = java.util.Collections.emptyList();
+        bitField0_ = (bitField0_ & ~0x00000001);
+        onChanged();
+        return this;
       }
       /**
-       * <code>repeated .context.EndPointId path = 3;</code>
+       * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
+       * @return A list containing the enum numeric values on the wire for kpiSampleTypes.
        */
-      public context.ContextOuterClass.EndPointIdOrBuilder getPathOrBuilder(
-          int index) {
-        if (pathBuilder_ == null) {
-          return path_.get(index);  } else {
-          return pathBuilder_.getMessageOrBuilder(index);
-        }
+      public java.util.List<java.lang.Integer>
+      getKpiSampleTypesValueList() {
+        return java.util.Collections.unmodifiableList(kpiSampleTypes_);
       }
       /**
-       * <code>repeated .context.EndPointId path = 3;</code>
+       * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
+       * @param index The index of the value to return.
+       * @return The enum numeric value on the wire of kpiSampleTypes at the given index.
        */
-      public java.util.List<? extends context.ContextOuterClass.EndPointIdOrBuilder> 
-           getPathOrBuilderList() {
-        if (pathBuilder_ != null) {
-          return pathBuilder_.getMessageOrBuilderList();
-        } else {
-          return java.util.Collections.unmodifiableList(path_);
-        }
+      public int getKpiSampleTypesValue(int index) {
+        return kpiSampleTypes_.get(index);
       }
       /**
-       * <code>repeated .context.EndPointId path = 3;</code>
+       * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
+       * @param index The index of the value to return.
+       * @return The enum numeric value on the wire of kpiSampleTypes at the given index.
+       * @return This builder for chaining.
        */
-      public context.ContextOuterClass.EndPointId.Builder addPathBuilder() {
-        return getPathFieldBuilder().addBuilder(
-            context.ContextOuterClass.EndPointId.getDefaultInstance());
+      public Builder setKpiSampleTypesValue(
+          int index, int value) {
+        ensureKpiSampleTypesIsMutable();
+        kpiSampleTypes_.set(index, value);
+        onChanged();
+        return this;
       }
       /**
-       * <code>repeated .context.EndPointId path = 3;</code>
+       * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
+       * @param value The enum numeric value on the wire for kpiSampleTypes to add.
+       * @return This builder for chaining.
        */
-      public context.ContextOuterClass.EndPointId.Builder addPathBuilder(
-          int index) {
-        return getPathFieldBuilder().addBuilder(
-            index, context.ContextOuterClass.EndPointId.getDefaultInstance());
+      public Builder addKpiSampleTypesValue(int value) {
+        ensureKpiSampleTypesIsMutable();
+        kpiSampleTypes_.add(value);
+        onChanged();
+        return this;
       }
       /**
-       * <code>repeated .context.EndPointId path = 3;</code>
+       * <code>repeated .kpi_sample_types.KpiSampleType kpi_sample_types = 3;</code>
+       * @param values The enum numeric values on the wire for kpiSampleTypes to add.
+       * @return This builder for chaining.
        */
-      public java.util.List<context.ContextOuterClass.EndPointId.Builder> 
-           getPathBuilderList() {
-        return getPathFieldBuilder().getBuilderList();
-      }
-      private com.google.protobuf.RepeatedFieldBuilderV3<
-          context.ContextOuterClass.EndPointId, context.ContextOuterClass.EndPointId.Builder, context.ContextOuterClass.EndPointIdOrBuilder> 
-          getPathFieldBuilder() {
-        if (pathBuilder_ == null) {
-          pathBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3<
-              context.ContextOuterClass.EndPointId, context.ContextOuterClass.EndPointId.Builder, context.ContextOuterClass.EndPointIdOrBuilder>(
-                  path_,
-                  ((bitField0_ & 0x00000001) != 0),
-                  getParentForChildren(),
-                  isClean());
-          path_ = null;
+      public Builder addAllKpiSampleTypesValue(
+          java.lang.Iterable<java.lang.Integer> values) {
+        ensureKpiSampleTypesIsMutable();
+        for (int value : values) {
+          kpiSampleTypes_.add(value);
         }
-        return pathBuilder_;
+        onChanged();
+        return this;
       }
       @java.lang.Override
       public final Builder setUnknownFields(
@@ -33097,95 +34328,108 @@ public final class ContextOuterClass {
       }
 
 
-      // @@protoc_insertion_point(builder_scope:context.Connection)
+      // @@protoc_insertion_point(builder_scope:context.EndPoint)
     }
 
-    // @@protoc_insertion_point(class_scope:context.Connection)
-    private static final context.ContextOuterClass.Connection DEFAULT_INSTANCE;
+    // @@protoc_insertion_point(class_scope:context.EndPoint)
+    private static final context.ContextOuterClass.EndPoint DEFAULT_INSTANCE;
     static {
-      DEFAULT_INSTANCE = new context.ContextOuterClass.Connection();
+      DEFAULT_INSTANCE = new context.ContextOuterClass.EndPoint();
     }
 
-    public static context.ContextOuterClass.Connection getDefaultInstance() {
+    public static context.ContextOuterClass.EndPoint getDefaultInstance() {
       return DEFAULT_INSTANCE;
     }
 
-    private static final com.google.protobuf.Parser<Connection>
-        PARSER = new com.google.protobuf.AbstractParser<Connection>() {
+    private static final com.google.protobuf.Parser<EndPoint>
+        PARSER = new com.google.protobuf.AbstractParser<EndPoint>() {
       @java.lang.Override
-      public Connection parsePartialFrom(
+      public EndPoint parsePartialFrom(
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws com.google.protobuf.InvalidProtocolBufferException {
-        return new Connection(input, extensionRegistry);
+        return new EndPoint(input, extensionRegistry);
       }
     };
 
-    public static com.google.protobuf.Parser<Connection> parser() {
+    public static com.google.protobuf.Parser<EndPoint> parser() {
       return PARSER;
     }
 
     @java.lang.Override
-    public com.google.protobuf.Parser<Connection> getParserForType() {
+    public com.google.protobuf.Parser<EndPoint> getParserForType() {
       return PARSER;
     }
 
     @java.lang.Override
-    public context.ContextOuterClass.Connection getDefaultInstanceForType() {
+    public context.ContextOuterClass.EndPoint getDefaultInstanceForType() {
       return DEFAULT_INSTANCE;
     }
 
   }
 
-  public interface ConnectionIdListOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:context.ConnectionIdList)
+  public interface ConfigRuleOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:context.ConfigRule)
       com.google.protobuf.MessageOrBuilder {
 
     /**
-     * <code>repeated .context.ConnectionId connection_ids = 1;</code>
+     * <code>.context.ConfigActionEnum action = 1;</code>
+     * @return The enum numeric value on the wire for action.
      */
-    java.util.List<context.ContextOuterClass.ConnectionId> 
-        getConnectionIdsList();
+    int getActionValue();
     /**
-     * <code>repeated .context.ConnectionId connection_ids = 1;</code>
+     * <code>.context.ConfigActionEnum action = 1;</code>
+     * @return The action.
      */
-    context.ContextOuterClass.ConnectionId getConnectionIds(int index);
+    context.ContextOuterClass.ConfigActionEnum getAction();
+
     /**
-     * <code>repeated .context.ConnectionId connection_ids = 1;</code>
+     * <code>string resource_key = 2;</code>
+     * @return The resourceKey.
      */
-    int getConnectionIdsCount();
+    java.lang.String getResourceKey();
     /**
-     * <code>repeated .context.ConnectionId connection_ids = 1;</code>
+     * <code>string resource_key = 2;</code>
+     * @return The bytes for resourceKey.
      */
-    java.util.List<? extends context.ContextOuterClass.ConnectionIdOrBuilder> 
-        getConnectionIdsOrBuilderList();
+    com.google.protobuf.ByteString
+        getResourceKeyBytes();
+
     /**
-     * <code>repeated .context.ConnectionId connection_ids = 1;</code>
+     * <code>string resource_value = 3;</code>
+     * @return The resourceValue.
      */
-    context.ContextOuterClass.ConnectionIdOrBuilder getConnectionIdsOrBuilder(
-        int index);
+    java.lang.String getResourceValue();
+    /**
+     * <code>string resource_value = 3;</code>
+     * @return The bytes for resourceValue.
+     */
+    com.google.protobuf.ByteString
+        getResourceValueBytes();
   }
   /**
-   * Protobuf type {@code context.ConnectionIdList}
+   * Protobuf type {@code context.ConfigRule}
    */
-  public static final class ConnectionIdList extends
+  public static final class ConfigRule extends
       com.google.protobuf.GeneratedMessageV3 implements
-      // @@protoc_insertion_point(message_implements:context.ConnectionIdList)
-      ConnectionIdListOrBuilder {
+      // @@protoc_insertion_point(message_implements:context.ConfigRule)
+      ConfigRuleOrBuilder {
   private static final long serialVersionUID = 0L;
-    // Use ConnectionIdList.newBuilder() to construct.
-    private ConnectionIdList(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
+    // Use ConfigRule.newBuilder() to construct.
+    private ConfigRule(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
       super(builder);
     }
-    private ConnectionIdList() {
-      connectionIds_ = java.util.Collections.emptyList();
+    private ConfigRule() {
+      action_ = 0;
+      resourceKey_ = "";
+      resourceValue_ = "";
     }
 
     @java.lang.Override
     @SuppressWarnings({"unused"})
     protected java.lang.Object newInstance(
         UnusedPrivateParameter unused) {
-      return new ConnectionIdList();
+      return new ConfigRule();
     }
 
     @java.lang.Override
@@ -33193,7 +34437,7 @@ public final class ContextOuterClass {
     getUnknownFields() {
       return this.unknownFields;
     }
-    private ConnectionIdList(
+    private ConfigRule(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
@@ -33201,7 +34445,6 @@ public final class ContextOuterClass {
       if (extensionRegistry == null) {
         throw new java.lang.NullPointerException();
       }
-      int mutable_bitField0_ = 0;
       com.google.protobuf.UnknownFieldSet.Builder unknownFields =
           com.google.protobuf.UnknownFieldSet.newBuilder();
       try {
@@ -33212,13 +34455,22 @@ public final class ContextOuterClass {
             case 0:
               done = true;
               break;
-            case 10: {
-              if (!((mutable_bitField0_ & 0x00000001) != 0)) {
-                connectionIds_ = new java.util.ArrayList<context.ContextOuterClass.ConnectionId>();
-                mutable_bitField0_ |= 0x00000001;
-              }
-              connectionIds_.add(
-                  input.readMessage(context.ContextOuterClass.ConnectionId.parser(), extensionRegistry));
+            case 8: {
+              int rawValue = input.readEnum();
+
+              action_ = rawValue;
+              break;
+            }
+            case 18: {
+              java.lang.String s = input.readStringRequireUtf8();
+
+              resourceKey_ = s;
+              break;
+            }
+            case 26: {
+              java.lang.String s = input.readStringRequireUtf8();
+
+              resourceValue_ = s;
               break;
             }
             default: {
@@ -33236,64 +34488,116 @@ public final class ContextOuterClass {
         throw new com.google.protobuf.InvalidProtocolBufferException(
             e).setUnfinishedMessage(this);
       } finally {
-        if (((mutable_bitField0_ & 0x00000001) != 0)) {
-          connectionIds_ = java.util.Collections.unmodifiableList(connectionIds_);
-        }
         this.unknownFields = unknownFields.build();
         makeExtensionsImmutable();
       }
     }
     public static final com.google.protobuf.Descriptors.Descriptor
         getDescriptor() {
-      return context.ContextOuterClass.internal_static_context_ConnectionIdList_descriptor;
+      return context.ContextOuterClass.internal_static_context_ConfigRule_descriptor;
     }
 
     @java.lang.Override
     protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
         internalGetFieldAccessorTable() {
-      return context.ContextOuterClass.internal_static_context_ConnectionIdList_fieldAccessorTable
+      return context.ContextOuterClass.internal_static_context_ConfigRule_fieldAccessorTable
           .ensureFieldAccessorsInitialized(
-              context.ContextOuterClass.ConnectionIdList.class, context.ContextOuterClass.ConnectionIdList.Builder.class);
+              context.ContextOuterClass.ConfigRule.class, context.ContextOuterClass.ConfigRule.Builder.class);
     }
 
-    public static final int CONNECTION_IDS_FIELD_NUMBER = 1;
-    private java.util.List<context.ContextOuterClass.ConnectionId> connectionIds_;
+    public static final int ACTION_FIELD_NUMBER = 1;
+    private int action_;
     /**
-     * <code>repeated .context.ConnectionId connection_ids = 1;</code>
+     * <code>.context.ConfigActionEnum action = 1;</code>
+     * @return The enum numeric value on the wire for action.
      */
-    @java.lang.Override
-    public java.util.List<context.ContextOuterClass.ConnectionId> getConnectionIdsList() {
-      return connectionIds_;
+    @java.lang.Override public int getActionValue() {
+      return action_;
     }
     /**
-     * <code>repeated .context.ConnectionId connection_ids = 1;</code>
+     * <code>.context.ConfigActionEnum action = 1;</code>
+     * @return The action.
+     */
+    @java.lang.Override public context.ContextOuterClass.ConfigActionEnum getAction() {
+      @SuppressWarnings("deprecation")
+      context.ContextOuterClass.ConfigActionEnum result = context.ContextOuterClass.ConfigActionEnum.valueOf(action_);
+      return result == null ? context.ContextOuterClass.ConfigActionEnum.UNRECOGNIZED : result;
+    }
+
+    public static final int RESOURCE_KEY_FIELD_NUMBER = 2;
+    private volatile java.lang.Object resourceKey_;
+    /**
+     * <code>string resource_key = 2;</code>
+     * @return The resourceKey.
      */
     @java.lang.Override
-    public java.util.List<? extends context.ContextOuterClass.ConnectionIdOrBuilder> 
-        getConnectionIdsOrBuilderList() {
-      return connectionIds_;
+    public java.lang.String getResourceKey() {
+      java.lang.Object ref = resourceKey_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        resourceKey_ = s;
+        return s;
+      }
     }
     /**
-     * <code>repeated .context.ConnectionId connection_ids = 1;</code>
+     * <code>string resource_key = 2;</code>
+     * @return The bytes for resourceKey.
      */
     @java.lang.Override
-    public int getConnectionIdsCount() {
-      return connectionIds_.size();
+    public com.google.protobuf.ByteString
+        getResourceKeyBytes() {
+      java.lang.Object ref = resourceKey_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        resourceKey_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
     }
+
+    public static final int RESOURCE_VALUE_FIELD_NUMBER = 3;
+    private volatile java.lang.Object resourceValue_;
     /**
-     * <code>repeated .context.ConnectionId connection_ids = 1;</code>
+     * <code>string resource_value = 3;</code>
+     * @return The resourceValue.
      */
     @java.lang.Override
-    public context.ContextOuterClass.ConnectionId getConnectionIds(int index) {
-      return connectionIds_.get(index);
+    public java.lang.String getResourceValue() {
+      java.lang.Object ref = resourceValue_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        resourceValue_ = s;
+        return s;
+      }
     }
     /**
-     * <code>repeated .context.ConnectionId connection_ids = 1;</code>
+     * <code>string resource_value = 3;</code>
+     * @return The bytes for resourceValue.
      */
     @java.lang.Override
-    public context.ContextOuterClass.ConnectionIdOrBuilder getConnectionIdsOrBuilder(
-        int index) {
-      return connectionIds_.get(index);
+    public com.google.protobuf.ByteString
+        getResourceValueBytes() {
+      java.lang.Object ref = resourceValue_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        resourceValue_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
     }
 
     private byte memoizedIsInitialized = -1;
@@ -33310,8 +34614,14 @@ public final class ContextOuterClass {
     @java.lang.Override
     public void writeTo(com.google.protobuf.CodedOutputStream output)
                         throws java.io.IOException {
-      for (int i = 0; i < connectionIds_.size(); i++) {
-        output.writeMessage(1, connectionIds_.get(i));
+      if (action_ != context.ContextOuterClass.ConfigActionEnum.CONFIGACTION_UNDEFINED.getNumber()) {
+        output.writeEnum(1, action_);
+      }
+      if (!getResourceKeyBytes().isEmpty()) {
+        com.google.protobuf.GeneratedMessageV3.writeString(output, 2, resourceKey_);
+      }
+      if (!getResourceValueBytes().isEmpty()) {
+        com.google.protobuf.GeneratedMessageV3.writeString(output, 3, resourceValue_);
       }
       unknownFields.writeTo(output);
     }
@@ -33322,9 +34632,15 @@ public final class ContextOuterClass {
       if (size != -1) return size;
 
       size = 0;
-      for (int i = 0; i < connectionIds_.size(); i++) {
+      if (action_ != context.ContextOuterClass.ConfigActionEnum.CONFIGACTION_UNDEFINED.getNumber()) {
         size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(1, connectionIds_.get(i));
+          .computeEnumSize(1, action_);
+      }
+      if (!getResourceKeyBytes().isEmpty()) {
+        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, resourceKey_);
+      }
+      if (!getResourceValueBytes().isEmpty()) {
+        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, resourceValue_);
       }
       size += unknownFields.getSerializedSize();
       memoizedSize = size;
@@ -33336,13 +34652,16 @@ public final class ContextOuterClass {
       if (obj == this) {
        return true;
       }
-      if (!(obj instanceof context.ContextOuterClass.ConnectionIdList)) {
+      if (!(obj instanceof context.ContextOuterClass.ConfigRule)) {
         return super.equals(obj);
       }
-      context.ContextOuterClass.ConnectionIdList other = (context.ContextOuterClass.ConnectionIdList) obj;
+      context.ContextOuterClass.ConfigRule other = (context.ContextOuterClass.ConfigRule) obj;
 
-      if (!getConnectionIdsList()
-          .equals(other.getConnectionIdsList())) return false;
+      if (action_ != other.action_) return false;
+      if (!getResourceKey()
+          .equals(other.getResourceKey())) return false;
+      if (!getResourceValue()
+          .equals(other.getResourceValue())) return false;
       if (!unknownFields.equals(other.unknownFields)) return false;
       return true;
     }
@@ -33354,78 +34673,80 @@ public final class ContextOuterClass {
       }
       int hash = 41;
       hash = (19 * hash) + getDescriptor().hashCode();
-      if (getConnectionIdsCount() > 0) {
-        hash = (37 * hash) + CONNECTION_IDS_FIELD_NUMBER;
-        hash = (53 * hash) + getConnectionIdsList().hashCode();
-      }
+      hash = (37 * hash) + ACTION_FIELD_NUMBER;
+      hash = (53 * hash) + action_;
+      hash = (37 * hash) + RESOURCE_KEY_FIELD_NUMBER;
+      hash = (53 * hash) + getResourceKey().hashCode();
+      hash = (37 * hash) + RESOURCE_VALUE_FIELD_NUMBER;
+      hash = (53 * hash) + getResourceValue().hashCode();
       hash = (29 * hash) + unknownFields.hashCode();
       memoizedHashCode = hash;
       return hash;
     }
 
-    public static context.ContextOuterClass.ConnectionIdList parseFrom(
+    public static context.ContextOuterClass.ConfigRule parseFrom(
         java.nio.ByteBuffer data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static context.ContextOuterClass.ConnectionIdList parseFrom(
+    public static context.ContextOuterClass.ConfigRule parseFrom(
         java.nio.ByteBuffer data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static context.ContextOuterClass.ConnectionIdList parseFrom(
+    public static context.ContextOuterClass.ConfigRule parseFrom(
         com.google.protobuf.ByteString data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static context.ContextOuterClass.ConnectionIdList parseFrom(
+    public static context.ContextOuterClass.ConfigRule parseFrom(
         com.google.protobuf.ByteString data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static context.ContextOuterClass.ConnectionIdList parseFrom(byte[] data)
+    public static context.ContextOuterClass.ConfigRule parseFrom(byte[] data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static context.ContextOuterClass.ConnectionIdList parseFrom(
+    public static context.ContextOuterClass.ConfigRule parseFrom(
         byte[] data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static context.ContextOuterClass.ConnectionIdList parseFrom(java.io.InputStream input)
+    public static context.ContextOuterClass.ConfigRule parseFrom(java.io.InputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseWithIOException(PARSER, input);
     }
-    public static context.ContextOuterClass.ConnectionIdList parseFrom(
+    public static context.ContextOuterClass.ConfigRule parseFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseWithIOException(PARSER, input, extensionRegistry);
     }
-    public static context.ContextOuterClass.ConnectionIdList parseDelimitedFrom(java.io.InputStream input)
+    public static context.ContextOuterClass.ConfigRule parseDelimitedFrom(java.io.InputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseDelimitedWithIOException(PARSER, input);
     }
-    public static context.ContextOuterClass.ConnectionIdList parseDelimitedFrom(
+    public static context.ContextOuterClass.ConfigRule parseDelimitedFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
     }
-    public static context.ContextOuterClass.ConnectionIdList parseFrom(
+    public static context.ContextOuterClass.ConfigRule parseFrom(
         com.google.protobuf.CodedInputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseWithIOException(PARSER, input);
     }
-    public static context.ContextOuterClass.ConnectionIdList parseFrom(
+    public static context.ContextOuterClass.ConfigRule parseFrom(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -33438,7 +34759,7 @@ public final class ContextOuterClass {
     public static Builder newBuilder() {
       return DEFAULT_INSTANCE.toBuilder();
     }
-    public static Builder newBuilder(context.ContextOuterClass.ConnectionIdList prototype) {
+    public static Builder newBuilder(context.ContextOuterClass.ConfigRule prototype) {
       return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
     }
     @java.lang.Override
@@ -33454,26 +34775,26 @@ public final class ContextOuterClass {
       return builder;
     }
     /**
-     * Protobuf type {@code context.ConnectionIdList}
+     * Protobuf type {@code context.ConfigRule}
      */
     public static final class Builder extends
         com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:context.ConnectionIdList)
-        context.ContextOuterClass.ConnectionIdListOrBuilder {
+        // @@protoc_insertion_point(builder_implements:context.ConfigRule)
+        context.ContextOuterClass.ConfigRuleOrBuilder {
       public static final com.google.protobuf.Descriptors.Descriptor
           getDescriptor() {
-        return context.ContextOuterClass.internal_static_context_ConnectionIdList_descriptor;
+        return context.ContextOuterClass.internal_static_context_ConfigRule_descriptor;
       }
 
       @java.lang.Override
       protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
           internalGetFieldAccessorTable() {
-        return context.ContextOuterClass.internal_static_context_ConnectionIdList_fieldAccessorTable
+        return context.ContextOuterClass.internal_static_context_ConfigRule_fieldAccessorTable
             .ensureFieldAccessorsInitialized(
-                context.ContextOuterClass.ConnectionIdList.class, context.ContextOuterClass.ConnectionIdList.Builder.class);
+                context.ContextOuterClass.ConfigRule.class, context.ContextOuterClass.ConfigRule.Builder.class);
       }
 
-      // Construct using context.ContextOuterClass.ConnectionIdList.newBuilder()
+      // Construct using context.ContextOuterClass.ConfigRule.newBuilder()
       private Builder() {
         maybeForceBuilderInitialization();
       }
@@ -33486,35 +34807,34 @@ public final class ContextOuterClass {
       private void maybeForceBuilderInitialization() {
         if (com.google.protobuf.GeneratedMessageV3
                 .alwaysUseFieldBuilders) {
-          getConnectionIdsFieldBuilder();
         }
       }
       @java.lang.Override
       public Builder clear() {
         super.clear();
-        if (connectionIdsBuilder_ == null) {
-          connectionIds_ = java.util.Collections.emptyList();
-          bitField0_ = (bitField0_ & ~0x00000001);
-        } else {
-          connectionIdsBuilder_.clear();
-        }
+        action_ = 0;
+
+        resourceKey_ = "";
+
+        resourceValue_ = "";
+
         return this;
       }
 
       @java.lang.Override
       public com.google.protobuf.Descriptors.Descriptor
           getDescriptorForType() {
-        return context.ContextOuterClass.internal_static_context_ConnectionIdList_descriptor;
+        return context.ContextOuterClass.internal_static_context_ConfigRule_descriptor;
       }
 
       @java.lang.Override
-      public context.ContextOuterClass.ConnectionIdList getDefaultInstanceForType() {
-        return context.ContextOuterClass.ConnectionIdList.getDefaultInstance();
+      public context.ContextOuterClass.ConfigRule getDefaultInstanceForType() {
+        return context.ContextOuterClass.ConfigRule.getDefaultInstance();
       }
 
       @java.lang.Override
-      public context.ContextOuterClass.ConnectionIdList build() {
-        context.ContextOuterClass.ConnectionIdList result = buildPartial();
+      public context.ContextOuterClass.ConfigRule build() {
+        context.ContextOuterClass.ConfigRule result = buildPartial();
         if (!result.isInitialized()) {
           throw newUninitializedMessageException(result);
         }
@@ -33522,18 +34842,11 @@ public final class ContextOuterClass {
       }
 
       @java.lang.Override
-      public context.ContextOuterClass.ConnectionIdList buildPartial() {
-        context.ContextOuterClass.ConnectionIdList result = new context.ContextOuterClass.ConnectionIdList(this);
-        int from_bitField0_ = bitField0_;
-        if (connectionIdsBuilder_ == null) {
-          if (((bitField0_ & 0x00000001) != 0)) {
-            connectionIds_ = java.util.Collections.unmodifiableList(connectionIds_);
-            bitField0_ = (bitField0_ & ~0x00000001);
-          }
-          result.connectionIds_ = connectionIds_;
-        } else {
-          result.connectionIds_ = connectionIdsBuilder_.build();
-        }
+      public context.ContextOuterClass.ConfigRule buildPartial() {
+        context.ContextOuterClass.ConfigRule result = new context.ContextOuterClass.ConfigRule(this);
+        result.action_ = action_;
+        result.resourceKey_ = resourceKey_;
+        result.resourceValue_ = resourceValue_;
         onBuilt();
         return result;
       }
@@ -33572,41 +34885,26 @@ public final class ContextOuterClass {
       }
       @java.lang.Override
       public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof context.ContextOuterClass.ConnectionIdList) {
-          return mergeFrom((context.ContextOuterClass.ConnectionIdList)other);
+        if (other instanceof context.ContextOuterClass.ConfigRule) {
+          return mergeFrom((context.ContextOuterClass.ConfigRule)other);
         } else {
           super.mergeFrom(other);
           return this;
         }
       }
 
-      public Builder mergeFrom(context.ContextOuterClass.ConnectionIdList other) {
-        if (other == context.ContextOuterClass.ConnectionIdList.getDefaultInstance()) return this;
-        if (connectionIdsBuilder_ == null) {
-          if (!other.connectionIds_.isEmpty()) {
-            if (connectionIds_.isEmpty()) {
-              connectionIds_ = other.connectionIds_;
-              bitField0_ = (bitField0_ & ~0x00000001);
-            } else {
-              ensureConnectionIdsIsMutable();
-              connectionIds_.addAll(other.connectionIds_);
-            }
-            onChanged();
-          }
-        } else {
-          if (!other.connectionIds_.isEmpty()) {
-            if (connectionIdsBuilder_.isEmpty()) {
-              connectionIdsBuilder_.dispose();
-              connectionIdsBuilder_ = null;
-              connectionIds_ = other.connectionIds_;
-              bitField0_ = (bitField0_ & ~0x00000001);
-              connectionIdsBuilder_ = 
-                com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ?
-                   getConnectionIdsFieldBuilder() : null;
-            } else {
-              connectionIdsBuilder_.addAllMessages(other.connectionIds_);
-            }
-          }
+      public Builder mergeFrom(context.ContextOuterClass.ConfigRule other) {
+        if (other == context.ContextOuterClass.ConfigRule.getDefaultInstance()) return this;
+        if (other.action_ != 0) {
+          setActionValue(other.getActionValue());
+        }
+        if (!other.getResourceKey().isEmpty()) {
+          resourceKey_ = other.resourceKey_;
+          onChanged();
+        }
+        if (!other.getResourceValue().isEmpty()) {
+          resourceValue_ = other.resourceValue_;
+          onChanged();
         }
         this.mergeUnknownFields(other.unknownFields);
         onChanged();
@@ -33623,11 +34921,11 @@ public final class ContextOuterClass {
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws java.io.IOException {
-        context.ContextOuterClass.ConnectionIdList parsedMessage = null;
+        context.ContextOuterClass.ConfigRule parsedMessage = null;
         try {
           parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
         } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          parsedMessage = (context.ContextOuterClass.ConnectionIdList) e.getUnfinishedMessage();
+          parsedMessage = (context.ContextOuterClass.ConfigRule) e.getUnfinishedMessage();
           throw e.unwrapIOException();
         } finally {
           if (parsedMessage != null) {
@@ -33636,246 +34934,211 @@ public final class ContextOuterClass {
         }
         return this;
       }
-      private int bitField0_;
-
-      private java.util.List<context.ContextOuterClass.ConnectionId> connectionIds_ =
-        java.util.Collections.emptyList();
-      private void ensureConnectionIdsIsMutable() {
-        if (!((bitField0_ & 0x00000001) != 0)) {
-          connectionIds_ = new java.util.ArrayList<context.ContextOuterClass.ConnectionId>(connectionIds_);
-          bitField0_ |= 0x00000001;
-         }
-      }
-
-      private com.google.protobuf.RepeatedFieldBuilderV3<
-          context.ContextOuterClass.ConnectionId, context.ContextOuterClass.ConnectionId.Builder, context.ContextOuterClass.ConnectionIdOrBuilder> connectionIdsBuilder_;
 
+      private int action_ = 0;
       /**
-       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
-       */
-      public java.util.List<context.ContextOuterClass.ConnectionId> getConnectionIdsList() {
-        if (connectionIdsBuilder_ == null) {
-          return java.util.Collections.unmodifiableList(connectionIds_);
-        } else {
-          return connectionIdsBuilder_.getMessageList();
-        }
-      }
-      /**
-       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
-       */
-      public int getConnectionIdsCount() {
-        if (connectionIdsBuilder_ == null) {
-          return connectionIds_.size();
-        } else {
-          return connectionIdsBuilder_.getCount();
-        }
-      }
-      /**
-       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
-       */
-      public context.ContextOuterClass.ConnectionId getConnectionIds(int index) {
-        if (connectionIdsBuilder_ == null) {
-          return connectionIds_.get(index);
-        } else {
-          return connectionIdsBuilder_.getMessage(index);
-        }
-      }
-      /**
-       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
+       * <code>.context.ConfigActionEnum action = 1;</code>
+       * @return The enum numeric value on the wire for action.
        */
-      public Builder setConnectionIds(
-          int index, context.ContextOuterClass.ConnectionId value) {
-        if (connectionIdsBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureConnectionIdsIsMutable();
-          connectionIds_.set(index, value);
-          onChanged();
-        } else {
-          connectionIdsBuilder_.setMessage(index, value);
-        }
-        return this;
+      @java.lang.Override public int getActionValue() {
+        return action_;
       }
       /**
-       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
+       * <code>.context.ConfigActionEnum action = 1;</code>
+       * @param value The enum numeric value on the wire for action to set.
+       * @return This builder for chaining.
        */
-      public Builder setConnectionIds(
-          int index, context.ContextOuterClass.ConnectionId.Builder builderForValue) {
-        if (connectionIdsBuilder_ == null) {
-          ensureConnectionIdsIsMutable();
-          connectionIds_.set(index, builderForValue.build());
-          onChanged();
-        } else {
-          connectionIdsBuilder_.setMessage(index, builderForValue.build());
-        }
+      public Builder setActionValue(int value) {
+        
+        action_ = value;
+        onChanged();
         return this;
       }
       /**
-       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
+       * <code>.context.ConfigActionEnum action = 1;</code>
+       * @return The action.
        */
-      public Builder addConnectionIds(context.ContextOuterClass.ConnectionId value) {
-        if (connectionIdsBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureConnectionIdsIsMutable();
-          connectionIds_.add(value);
-          onChanged();
-        } else {
-          connectionIdsBuilder_.addMessage(value);
-        }
-        return this;
+      @java.lang.Override
+      public context.ContextOuterClass.ConfigActionEnum getAction() {
+        @SuppressWarnings("deprecation")
+        context.ContextOuterClass.ConfigActionEnum result = context.ContextOuterClass.ConfigActionEnum.valueOf(action_);
+        return result == null ? context.ContextOuterClass.ConfigActionEnum.UNRECOGNIZED : result;
       }
       /**
-       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
+       * <code>.context.ConfigActionEnum action = 1;</code>
+       * @param value The action to set.
+       * @return This builder for chaining.
        */
-      public Builder addConnectionIds(
-          int index, context.ContextOuterClass.ConnectionId value) {
-        if (connectionIdsBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureConnectionIdsIsMutable();
-          connectionIds_.add(index, value);
-          onChanged();
-        } else {
-          connectionIdsBuilder_.addMessage(index, value);
+      public Builder setAction(context.ContextOuterClass.ConfigActionEnum value) {
+        if (value == null) {
+          throw new NullPointerException();
         }
+        
+        action_ = value.getNumber();
+        onChanged();
         return this;
       }
       /**
-       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
+       * <code>.context.ConfigActionEnum action = 1;</code>
+       * @return This builder for chaining.
        */
-      public Builder addConnectionIds(
-          context.ContextOuterClass.ConnectionId.Builder builderForValue) {
-        if (connectionIdsBuilder_ == null) {
-          ensureConnectionIdsIsMutable();
-          connectionIds_.add(builderForValue.build());
-          onChanged();
-        } else {
-          connectionIdsBuilder_.addMessage(builderForValue.build());
-        }
+      public Builder clearAction() {
+        
+        action_ = 0;
+        onChanged();
         return this;
       }
+
+      private java.lang.Object resourceKey_ = "";
       /**
-       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
+       * <code>string resource_key = 2;</code>
+       * @return The resourceKey.
        */
-      public Builder addConnectionIds(
-          int index, context.ContextOuterClass.ConnectionId.Builder builderForValue) {
-        if (connectionIdsBuilder_ == null) {
-          ensureConnectionIdsIsMutable();
-          connectionIds_.add(index, builderForValue.build());
-          onChanged();
+      public java.lang.String getResourceKey() {
+        java.lang.Object ref = resourceKey_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          resourceKey_ = s;
+          return s;
         } else {
-          connectionIdsBuilder_.addMessage(index, builderForValue.build());
+          return (java.lang.String) ref;
         }
-        return this;
       }
       /**
-       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
+       * <code>string resource_key = 2;</code>
+       * @return The bytes for resourceKey.
        */
-      public Builder addAllConnectionIds(
-          java.lang.Iterable<? extends context.ContextOuterClass.ConnectionId> values) {
-        if (connectionIdsBuilder_ == null) {
-          ensureConnectionIdsIsMutable();
-          com.google.protobuf.AbstractMessageLite.Builder.addAll(
-              values, connectionIds_);
-          onChanged();
+      public com.google.protobuf.ByteString
+          getResourceKeyBytes() {
+        java.lang.Object ref = resourceKey_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          resourceKey_ = b;
+          return b;
         } else {
-          connectionIdsBuilder_.addAllMessages(values);
+          return (com.google.protobuf.ByteString) ref;
         }
-        return this;
       }
       /**
-       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
+       * <code>string resource_key = 2;</code>
+       * @param value The resourceKey to set.
+       * @return This builder for chaining.
        */
-      public Builder clearConnectionIds() {
-        if (connectionIdsBuilder_ == null) {
-          connectionIds_ = java.util.Collections.emptyList();
-          bitField0_ = (bitField0_ & ~0x00000001);
-          onChanged();
-        } else {
-          connectionIdsBuilder_.clear();
-        }
+      public Builder setResourceKey(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  
+        resourceKey_ = value;
+        onChanged();
         return this;
       }
       /**
-       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
+       * <code>string resource_key = 2;</code>
+       * @return This builder for chaining.
        */
-      public Builder removeConnectionIds(int index) {
-        if (connectionIdsBuilder_ == null) {
-          ensureConnectionIdsIsMutable();
-          connectionIds_.remove(index);
-          onChanged();
-        } else {
-          connectionIdsBuilder_.remove(index);
-        }
+      public Builder clearResourceKey() {
+        
+        resourceKey_ = getDefaultInstance().getResourceKey();
+        onChanged();
         return this;
       }
       /**
-       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
+       * <code>string resource_key = 2;</code>
+       * @param value The bytes for resourceKey to set.
+       * @return This builder for chaining.
        */
-      public context.ContextOuterClass.ConnectionId.Builder getConnectionIdsBuilder(
-          int index) {
-        return getConnectionIdsFieldBuilder().getBuilder(index);
+      public Builder setResourceKeyBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  checkByteStringIsUtf8(value);
+        
+        resourceKey_ = value;
+        onChanged();
+        return this;
       }
+
+      private java.lang.Object resourceValue_ = "";
       /**
-       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
+       * <code>string resource_value = 3;</code>
+       * @return The resourceValue.
        */
-      public context.ContextOuterClass.ConnectionIdOrBuilder getConnectionIdsOrBuilder(
-          int index) {
-        if (connectionIdsBuilder_ == null) {
-          return connectionIds_.get(index);  } else {
-          return connectionIdsBuilder_.getMessageOrBuilder(index);
+      public java.lang.String getResourceValue() {
+        java.lang.Object ref = resourceValue_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          resourceValue_ = s;
+          return s;
+        } else {
+          return (java.lang.String) ref;
         }
       }
       /**
-       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
+       * <code>string resource_value = 3;</code>
+       * @return The bytes for resourceValue.
        */
-      public java.util.List<? extends context.ContextOuterClass.ConnectionIdOrBuilder> 
-           getConnectionIdsOrBuilderList() {
-        if (connectionIdsBuilder_ != null) {
-          return connectionIdsBuilder_.getMessageOrBuilderList();
+      public com.google.protobuf.ByteString
+          getResourceValueBytes() {
+        java.lang.Object ref = resourceValue_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          resourceValue_ = b;
+          return b;
         } else {
-          return java.util.Collections.unmodifiableList(connectionIds_);
+          return (com.google.protobuf.ByteString) ref;
         }
       }
       /**
-       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
+       * <code>string resource_value = 3;</code>
+       * @param value The resourceValue to set.
+       * @return This builder for chaining.
        */
-      public context.ContextOuterClass.ConnectionId.Builder addConnectionIdsBuilder() {
-        return getConnectionIdsFieldBuilder().addBuilder(
-            context.ContextOuterClass.ConnectionId.getDefaultInstance());
+      public Builder setResourceValue(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  
+        resourceValue_ = value;
+        onChanged();
+        return this;
       }
       /**
-       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
+       * <code>string resource_value = 3;</code>
+       * @return This builder for chaining.
        */
-      public context.ContextOuterClass.ConnectionId.Builder addConnectionIdsBuilder(
-          int index) {
-        return getConnectionIdsFieldBuilder().addBuilder(
-            index, context.ContextOuterClass.ConnectionId.getDefaultInstance());
+      public Builder clearResourceValue() {
+        
+        resourceValue_ = getDefaultInstance().getResourceValue();
+        onChanged();
+        return this;
       }
       /**
-       * <code>repeated .context.ConnectionId connection_ids = 1;</code>
+       * <code>string resource_value = 3;</code>
+       * @param value The bytes for resourceValue to set.
+       * @return This builder for chaining.
        */
-      public java.util.List<context.ContextOuterClass.ConnectionId.Builder> 
-           getConnectionIdsBuilderList() {
-        return getConnectionIdsFieldBuilder().getBuilderList();
-      }
-      private com.google.protobuf.RepeatedFieldBuilderV3<
-          context.ContextOuterClass.ConnectionId, context.ContextOuterClass.ConnectionId.Builder, context.ContextOuterClass.ConnectionIdOrBuilder> 
-          getConnectionIdsFieldBuilder() {
-        if (connectionIdsBuilder_ == null) {
-          connectionIdsBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3<
-              context.ContextOuterClass.ConnectionId, context.ContextOuterClass.ConnectionId.Builder, context.ContextOuterClass.ConnectionIdOrBuilder>(
-                  connectionIds_,
-                  ((bitField0_ & 0x00000001) != 0),
-                  getParentForChildren(),
-                  isClean());
-          connectionIds_ = null;
-        }
-        return connectionIdsBuilder_;
+      public Builder setResourceValueBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  checkByteStringIsUtf8(value);
+        
+        resourceValue_ = value;
+        onChanged();
+        return this;
       }
       @java.lang.Override
       public final Builder setUnknownFields(
@@ -33890,95 +35153,100 @@ public final class ContextOuterClass {
       }
 
 
-      // @@protoc_insertion_point(builder_scope:context.ConnectionIdList)
+      // @@protoc_insertion_point(builder_scope:context.ConfigRule)
     }
 
-    // @@protoc_insertion_point(class_scope:context.ConnectionIdList)
-    private static final context.ContextOuterClass.ConnectionIdList DEFAULT_INSTANCE;
+    // @@protoc_insertion_point(class_scope:context.ConfigRule)
+    private static final context.ContextOuterClass.ConfigRule DEFAULT_INSTANCE;
     static {
-      DEFAULT_INSTANCE = new context.ContextOuterClass.ConnectionIdList();
+      DEFAULT_INSTANCE = new context.ContextOuterClass.ConfigRule();
     }
 
-    public static context.ContextOuterClass.ConnectionIdList getDefaultInstance() {
+    public static context.ContextOuterClass.ConfigRule getDefaultInstance() {
       return DEFAULT_INSTANCE;
     }
 
-    private static final com.google.protobuf.Parser<ConnectionIdList>
-        PARSER = new com.google.protobuf.AbstractParser<ConnectionIdList>() {
+    private static final com.google.protobuf.Parser<ConfigRule>
+        PARSER = new com.google.protobuf.AbstractParser<ConfigRule>() {
       @java.lang.Override
-      public ConnectionIdList parsePartialFrom(
+      public ConfigRule parsePartialFrom(
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws com.google.protobuf.InvalidProtocolBufferException {
-        return new ConnectionIdList(input, extensionRegistry);
+        return new ConfigRule(input, extensionRegistry);
       }
     };
 
-    public static com.google.protobuf.Parser<ConnectionIdList> parser() {
+    public static com.google.protobuf.Parser<ConfigRule> parser() {
       return PARSER;
     }
 
     @java.lang.Override
-    public com.google.protobuf.Parser<ConnectionIdList> getParserForType() {
+    public com.google.protobuf.Parser<ConfigRule> getParserForType() {
       return PARSER;
     }
 
     @java.lang.Override
-    public context.ContextOuterClass.ConnectionIdList getDefaultInstanceForType() {
+    public context.ContextOuterClass.ConfigRule getDefaultInstanceForType() {
       return DEFAULT_INSTANCE;
     }
 
   }
 
-  public interface ConnectionListOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:context.ConnectionList)
+  public interface ConstraintOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:context.Constraint)
       com.google.protobuf.MessageOrBuilder {
 
     /**
-     * <code>repeated .context.Connection connections = 1;</code>
-     */
-    java.util.List<context.ContextOuterClass.Connection> 
-        getConnectionsList();
-    /**
-     * <code>repeated .context.Connection connections = 1;</code>
+     * <code>string constraint_type = 1;</code>
+     * @return The constraintType.
      */
-    context.ContextOuterClass.Connection getConnections(int index);
+    java.lang.String getConstraintType();
     /**
-     * <code>repeated .context.Connection connections = 1;</code>
+     * <code>string constraint_type = 1;</code>
+     * @return The bytes for constraintType.
      */
-    int getConnectionsCount();
+    com.google.protobuf.ByteString
+        getConstraintTypeBytes();
+
     /**
-     * <code>repeated .context.Connection connections = 1;</code>
+     * <code>string constraint_value = 2;</code>
+     * @return The constraintValue.
      */
-    java.util.List<? extends context.ContextOuterClass.ConnectionOrBuilder> 
-        getConnectionsOrBuilderList();
+    java.lang.String getConstraintValue();
     /**
-     * <code>repeated .context.Connection connections = 1;</code>
+     * <code>string constraint_value = 2;</code>
+     * @return The bytes for constraintValue.
      */
-    context.ContextOuterClass.ConnectionOrBuilder getConnectionsOrBuilder(
-        int index);
+    com.google.protobuf.ByteString
+        getConstraintValueBytes();
   }
   /**
-   * Protobuf type {@code context.ConnectionList}
+   * <pre>
+   * ----- Constraint ----------------------------------------------------------------------------------------------------
+   * </pre>
+   *
+   * Protobuf type {@code context.Constraint}
    */
-  public static final class ConnectionList extends
+  public static final class Constraint extends
       com.google.protobuf.GeneratedMessageV3 implements
-      // @@protoc_insertion_point(message_implements:context.ConnectionList)
-      ConnectionListOrBuilder {
+      // @@protoc_insertion_point(message_implements:context.Constraint)
+      ConstraintOrBuilder {
   private static final long serialVersionUID = 0L;
-    // Use ConnectionList.newBuilder() to construct.
-    private ConnectionList(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
+    // Use Constraint.newBuilder() to construct.
+    private Constraint(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
       super(builder);
     }
-    private ConnectionList() {
-      connections_ = java.util.Collections.emptyList();
+    private Constraint() {
+      constraintType_ = "";
+      constraintValue_ = "";
     }
 
     @java.lang.Override
     @SuppressWarnings({"unused"})
     protected java.lang.Object newInstance(
         UnusedPrivateParameter unused) {
-      return new ConnectionList();
+      return new Constraint();
     }
 
     @java.lang.Override
@@ -33986,7 +35254,7 @@ public final class ContextOuterClass {
     getUnknownFields() {
       return this.unknownFields;
     }
-    private ConnectionList(
+    private Constraint(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
@@ -33994,7 +35262,6 @@ public final class ContextOuterClass {
       if (extensionRegistry == null) {
         throw new java.lang.NullPointerException();
       }
-      int mutable_bitField0_ = 0;
       com.google.protobuf.UnknownFieldSet.Builder unknownFields =
           com.google.protobuf.UnknownFieldSet.newBuilder();
       try {
@@ -34006,12 +35273,15 @@ public final class ContextOuterClass {
               done = true;
               break;
             case 10: {
-              if (!((mutable_bitField0_ & 0x00000001) != 0)) {
-                connections_ = new java.util.ArrayList<context.ContextOuterClass.Connection>();
-                mutable_bitField0_ |= 0x00000001;
-              }
-              connections_.add(
-                  input.readMessage(context.ContextOuterClass.Connection.parser(), extensionRegistry));
+              java.lang.String s = input.readStringRequireUtf8();
+
+              constraintType_ = s;
+              break;
+            }
+            case 18: {
+              java.lang.String s = input.readStringRequireUtf8();
+
+              constraintValue_ = s;
               break;
             }
             default: {
@@ -34029,64 +35299,97 @@ public final class ContextOuterClass {
         throw new com.google.protobuf.InvalidProtocolBufferException(
             e).setUnfinishedMessage(this);
       } finally {
-        if (((mutable_bitField0_ & 0x00000001) != 0)) {
-          connections_ = java.util.Collections.unmodifiableList(connections_);
-        }
         this.unknownFields = unknownFields.build();
         makeExtensionsImmutable();
       }
     }
     public static final com.google.protobuf.Descriptors.Descriptor
         getDescriptor() {
-      return context.ContextOuterClass.internal_static_context_ConnectionList_descriptor;
+      return context.ContextOuterClass.internal_static_context_Constraint_descriptor;
     }
 
     @java.lang.Override
     protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
         internalGetFieldAccessorTable() {
-      return context.ContextOuterClass.internal_static_context_ConnectionList_fieldAccessorTable
+      return context.ContextOuterClass.internal_static_context_Constraint_fieldAccessorTable
           .ensureFieldAccessorsInitialized(
-              context.ContextOuterClass.ConnectionList.class, context.ContextOuterClass.ConnectionList.Builder.class);
+              context.ContextOuterClass.Constraint.class, context.ContextOuterClass.Constraint.Builder.class);
     }
 
-    public static final int CONNECTIONS_FIELD_NUMBER = 1;
-    private java.util.List<context.ContextOuterClass.Connection> connections_;
-    /**
-     * <code>repeated .context.Connection connections = 1;</code>
-     */
-    @java.lang.Override
-    public java.util.List<context.ContextOuterClass.Connection> getConnectionsList() {
-      return connections_;
-    }
+    public static final int CONSTRAINT_TYPE_FIELD_NUMBER = 1;
+    private volatile java.lang.Object constraintType_;
     /**
-     * <code>repeated .context.Connection connections = 1;</code>
+     * <code>string constraint_type = 1;</code>
+     * @return The constraintType.
      */
     @java.lang.Override
-    public java.util.List<? extends context.ContextOuterClass.ConnectionOrBuilder> 
-        getConnectionsOrBuilderList() {
-      return connections_;
+    public java.lang.String getConstraintType() {
+      java.lang.Object ref = constraintType_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        constraintType_ = s;
+        return s;
+      }
     }
     /**
-     * <code>repeated .context.Connection connections = 1;</code>
+     * <code>string constraint_type = 1;</code>
+     * @return The bytes for constraintType.
      */
     @java.lang.Override
-    public int getConnectionsCount() {
-      return connections_.size();
+    public com.google.protobuf.ByteString
+        getConstraintTypeBytes() {
+      java.lang.Object ref = constraintType_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        constraintType_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
     }
+
+    public static final int CONSTRAINT_VALUE_FIELD_NUMBER = 2;
+    private volatile java.lang.Object constraintValue_;
     /**
-     * <code>repeated .context.Connection connections = 1;</code>
+     * <code>string constraint_value = 2;</code>
+     * @return The constraintValue.
      */
     @java.lang.Override
-    public context.ContextOuterClass.Connection getConnections(int index) {
-      return connections_.get(index);
+    public java.lang.String getConstraintValue() {
+      java.lang.Object ref = constraintValue_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        constraintValue_ = s;
+        return s;
+      }
     }
     /**
-     * <code>repeated .context.Connection connections = 1;</code>
+     * <code>string constraint_value = 2;</code>
+     * @return The bytes for constraintValue.
      */
     @java.lang.Override
-    public context.ContextOuterClass.ConnectionOrBuilder getConnectionsOrBuilder(
-        int index) {
-      return connections_.get(index);
+    public com.google.protobuf.ByteString
+        getConstraintValueBytes() {
+      java.lang.Object ref = constraintValue_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        constraintValue_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
     }
 
     private byte memoizedIsInitialized = -1;
@@ -34103,8 +35406,11 @@ public final class ContextOuterClass {
     @java.lang.Override
     public void writeTo(com.google.protobuf.CodedOutputStream output)
                         throws java.io.IOException {
-      for (int i = 0; i < connections_.size(); i++) {
-        output.writeMessage(1, connections_.get(i));
+      if (!getConstraintTypeBytes().isEmpty()) {
+        com.google.protobuf.GeneratedMessageV3.writeString(output, 1, constraintType_);
+      }
+      if (!getConstraintValueBytes().isEmpty()) {
+        com.google.protobuf.GeneratedMessageV3.writeString(output, 2, constraintValue_);
       }
       unknownFields.writeTo(output);
     }
@@ -34115,9 +35421,11 @@ public final class ContextOuterClass {
       if (size != -1) return size;
 
       size = 0;
-      for (int i = 0; i < connections_.size(); i++) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(1, connections_.get(i));
+      if (!getConstraintTypeBytes().isEmpty()) {
+        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, constraintType_);
+      }
+      if (!getConstraintValueBytes().isEmpty()) {
+        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, constraintValue_);
       }
       size += unknownFields.getSerializedSize();
       memoizedSize = size;
@@ -34129,13 +35437,15 @@ public final class ContextOuterClass {
       if (obj == this) {
        return true;
       }
-      if (!(obj instanceof context.ContextOuterClass.ConnectionList)) {
+      if (!(obj instanceof context.ContextOuterClass.Constraint)) {
         return super.equals(obj);
       }
-      context.ContextOuterClass.ConnectionList other = (context.ContextOuterClass.ConnectionList) obj;
+      context.ContextOuterClass.Constraint other = (context.ContextOuterClass.Constraint) obj;
 
-      if (!getConnectionsList()
-          .equals(other.getConnectionsList())) return false;
+      if (!getConstraintType()
+          .equals(other.getConstraintType())) return false;
+      if (!getConstraintValue()
+          .equals(other.getConstraintValue())) return false;
       if (!unknownFields.equals(other.unknownFields)) return false;
       return true;
     }
@@ -34147,78 +35457,78 @@ public final class ContextOuterClass {
       }
       int hash = 41;
       hash = (19 * hash) + getDescriptor().hashCode();
-      if (getConnectionsCount() > 0) {
-        hash = (37 * hash) + CONNECTIONS_FIELD_NUMBER;
-        hash = (53 * hash) + getConnectionsList().hashCode();
-      }
+      hash = (37 * hash) + CONSTRAINT_TYPE_FIELD_NUMBER;
+      hash = (53 * hash) + getConstraintType().hashCode();
+      hash = (37 * hash) + CONSTRAINT_VALUE_FIELD_NUMBER;
+      hash = (53 * hash) + getConstraintValue().hashCode();
       hash = (29 * hash) + unknownFields.hashCode();
       memoizedHashCode = hash;
       return hash;
     }
 
-    public static context.ContextOuterClass.ConnectionList parseFrom(
+    public static context.ContextOuterClass.Constraint parseFrom(
         java.nio.ByteBuffer data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static context.ContextOuterClass.ConnectionList parseFrom(
+    public static context.ContextOuterClass.Constraint parseFrom(
         java.nio.ByteBuffer data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static context.ContextOuterClass.ConnectionList parseFrom(
+    public static context.ContextOuterClass.Constraint parseFrom(
         com.google.protobuf.ByteString data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static context.ContextOuterClass.ConnectionList parseFrom(
+    public static context.ContextOuterClass.Constraint parseFrom(
         com.google.protobuf.ByteString data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static context.ContextOuterClass.ConnectionList parseFrom(byte[] data)
+    public static context.ContextOuterClass.Constraint parseFrom(byte[] data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static context.ContextOuterClass.ConnectionList parseFrom(
+    public static context.ContextOuterClass.Constraint parseFrom(
         byte[] data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static context.ContextOuterClass.ConnectionList parseFrom(java.io.InputStream input)
+    public static context.ContextOuterClass.Constraint parseFrom(java.io.InputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseWithIOException(PARSER, input);
     }
-    public static context.ContextOuterClass.ConnectionList parseFrom(
+    public static context.ContextOuterClass.Constraint parseFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseWithIOException(PARSER, input, extensionRegistry);
     }
-    public static context.ContextOuterClass.ConnectionList parseDelimitedFrom(java.io.InputStream input)
+    public static context.ContextOuterClass.Constraint parseDelimitedFrom(java.io.InputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseDelimitedWithIOException(PARSER, input);
     }
-    public static context.ContextOuterClass.ConnectionList parseDelimitedFrom(
+    public static context.ContextOuterClass.Constraint parseDelimitedFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
     }
-    public static context.ContextOuterClass.ConnectionList parseFrom(
+    public static context.ContextOuterClass.Constraint parseFrom(
         com.google.protobuf.CodedInputStream input)
         throws java.io.IOException {
       return com.google.protobuf.GeneratedMessageV3
           .parseWithIOException(PARSER, input);
     }
-    public static context.ContextOuterClass.ConnectionList parseFrom(
+    public static context.ContextOuterClass.Constraint parseFrom(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -34231,7 +35541,7 @@ public final class ContextOuterClass {
     public static Builder newBuilder() {
       return DEFAULT_INSTANCE.toBuilder();
     }
-    public static Builder newBuilder(context.ContextOuterClass.ConnectionList prototype) {
+    public static Builder newBuilder(context.ContextOuterClass.Constraint prototype) {
       return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
     }
     @java.lang.Override
@@ -34247,26 +35557,30 @@ public final class ContextOuterClass {
       return builder;
     }
     /**
-     * Protobuf type {@code context.ConnectionList}
+     * <pre>
+     * ----- Constraint ----------------------------------------------------------------------------------------------------
+     * </pre>
+     *
+     * Protobuf type {@code context.Constraint}
      */
     public static final class Builder extends
         com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:context.ConnectionList)
-        context.ContextOuterClass.ConnectionListOrBuilder {
+        // @@protoc_insertion_point(builder_implements:context.Constraint)
+        context.ContextOuterClass.ConstraintOrBuilder {
       public static final com.google.protobuf.Descriptors.Descriptor
           getDescriptor() {
-        return context.ContextOuterClass.internal_static_context_ConnectionList_descriptor;
+        return context.ContextOuterClass.internal_static_context_Constraint_descriptor;
       }
 
       @java.lang.Override
       protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
           internalGetFieldAccessorTable() {
-        return context.ContextOuterClass.internal_static_context_ConnectionList_fieldAccessorTable
+        return context.ContextOuterClass.internal_static_context_Constraint_fieldAccessorTable
             .ensureFieldAccessorsInitialized(
-                context.ContextOuterClass.ConnectionList.class, context.ContextOuterClass.ConnectionList.Builder.class);
+                context.ContextOuterClass.Constraint.class, context.ContextOuterClass.Constraint.Builder.class);
       }
 
-      // Construct using context.ContextOuterClass.ConnectionList.newBuilder()
+      // Construct using context.ContextOuterClass.Constraint.newBuilder()
       private Builder() {
         maybeForceBuilderInitialization();
       }
@@ -34278,36 +35592,33 @@ public final class ContextOuterClass {
       }
       private void maybeForceBuilderInitialization() {
         if (com.google.protobuf.GeneratedMessageV3
-                .alwaysUseFieldBuilders) {
-          getConnectionsFieldBuilder();
-        }
-      }
-      @java.lang.Override
-      public Builder clear() {
-        super.clear();
-        if (connectionsBuilder_ == null) {
-          connections_ = java.util.Collections.emptyList();
-          bitField0_ = (bitField0_ & ~0x00000001);
-        } else {
-          connectionsBuilder_.clear();
+                .alwaysUseFieldBuilders) {
         }
+      }
+      @java.lang.Override
+      public Builder clear() {
+        super.clear();
+        constraintType_ = "";
+
+        constraintValue_ = "";
+
         return this;
       }
 
       @java.lang.Override
       public com.google.protobuf.Descriptors.Descriptor
           getDescriptorForType() {
-        return context.ContextOuterClass.internal_static_context_ConnectionList_descriptor;
+        return context.ContextOuterClass.internal_static_context_Constraint_descriptor;
       }
 
       @java.lang.Override
-      public context.ContextOuterClass.ConnectionList getDefaultInstanceForType() {
-        return context.ContextOuterClass.ConnectionList.getDefaultInstance();
+      public context.ContextOuterClass.Constraint getDefaultInstanceForType() {
+        return context.ContextOuterClass.Constraint.getDefaultInstance();
       }
 
       @java.lang.Override
-      public context.ContextOuterClass.ConnectionList build() {
-        context.ContextOuterClass.ConnectionList result = buildPartial();
+      public context.ContextOuterClass.Constraint build() {
+        context.ContextOuterClass.Constraint result = buildPartial();
         if (!result.isInitialized()) {
           throw newUninitializedMessageException(result);
         }
@@ -34315,18 +35626,10 @@ public final class ContextOuterClass {
       }
 
       @java.lang.Override
-      public context.ContextOuterClass.ConnectionList buildPartial() {
-        context.ContextOuterClass.ConnectionList result = new context.ContextOuterClass.ConnectionList(this);
-        int from_bitField0_ = bitField0_;
-        if (connectionsBuilder_ == null) {
-          if (((bitField0_ & 0x00000001) != 0)) {
-            connections_ = java.util.Collections.unmodifiableList(connections_);
-            bitField0_ = (bitField0_ & ~0x00000001);
-          }
-          result.connections_ = connections_;
-        } else {
-          result.connections_ = connectionsBuilder_.build();
-        }
+      public context.ContextOuterClass.Constraint buildPartial() {
+        context.ContextOuterClass.Constraint result = new context.ContextOuterClass.Constraint(this);
+        result.constraintType_ = constraintType_;
+        result.constraintValue_ = constraintValue_;
         onBuilt();
         return result;
       }
@@ -34365,41 +35668,23 @@ public final class ContextOuterClass {
       }
       @java.lang.Override
       public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof context.ContextOuterClass.ConnectionList) {
-          return mergeFrom((context.ContextOuterClass.ConnectionList)other);
+        if (other instanceof context.ContextOuterClass.Constraint) {
+          return mergeFrom((context.ContextOuterClass.Constraint)other);
         } else {
           super.mergeFrom(other);
           return this;
         }
       }
 
-      public Builder mergeFrom(context.ContextOuterClass.ConnectionList other) {
-        if (other == context.ContextOuterClass.ConnectionList.getDefaultInstance()) return this;
-        if (connectionsBuilder_ == null) {
-          if (!other.connections_.isEmpty()) {
-            if (connections_.isEmpty()) {
-              connections_ = other.connections_;
-              bitField0_ = (bitField0_ & ~0x00000001);
-            } else {
-              ensureConnectionsIsMutable();
-              connections_.addAll(other.connections_);
-            }
-            onChanged();
-          }
-        } else {
-          if (!other.connections_.isEmpty()) {
-            if (connectionsBuilder_.isEmpty()) {
-              connectionsBuilder_.dispose();
-              connectionsBuilder_ = null;
-              connections_ = other.connections_;
-              bitField0_ = (bitField0_ & ~0x00000001);
-              connectionsBuilder_ = 
-                com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ?
-                   getConnectionsFieldBuilder() : null;
-            } else {
-              connectionsBuilder_.addAllMessages(other.connections_);
-            }
-          }
+      public Builder mergeFrom(context.ContextOuterClass.Constraint other) {
+        if (other == context.ContextOuterClass.Constraint.getDefaultInstance()) return this;
+        if (!other.getConstraintType().isEmpty()) {
+          constraintType_ = other.constraintType_;
+          onChanged();
+        }
+        if (!other.getConstraintValue().isEmpty()) {
+          constraintValue_ = other.constraintValue_;
+          onChanged();
         }
         this.mergeUnknownFields(other.unknownFields);
         onChanged();
@@ -34416,11 +35701,11 @@ public final class ContextOuterClass {
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws java.io.IOException {
-        context.ContextOuterClass.ConnectionList parsedMessage = null;
+        context.ContextOuterClass.Constraint parsedMessage = null;
         try {
           parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
         } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          parsedMessage = (context.ContextOuterClass.ConnectionList) e.getUnfinishedMessage();
+          parsedMessage = (context.ContextOuterClass.Constraint) e.getUnfinishedMessage();
           throw e.unwrapIOException();
         } finally {
           if (parsedMessage != null) {
@@ -34429,246 +35714,157 @@ public final class ContextOuterClass {
         }
         return this;
       }
-      private int bitField0_;
-
-      private java.util.List<context.ContextOuterClass.Connection> connections_ =
-        java.util.Collections.emptyList();
-      private void ensureConnectionsIsMutable() {
-        if (!((bitField0_ & 0x00000001) != 0)) {
-          connections_ = new java.util.ArrayList<context.ContextOuterClass.Connection>(connections_);
-          bitField0_ |= 0x00000001;
-         }
-      }
-
-      private com.google.protobuf.RepeatedFieldBuilderV3<
-          context.ContextOuterClass.Connection, context.ContextOuterClass.Connection.Builder, context.ContextOuterClass.ConnectionOrBuilder> connectionsBuilder_;
 
+      private java.lang.Object constraintType_ = "";
       /**
-       * <code>repeated .context.Connection connections = 1;</code>
-       */
-      public java.util.List<context.ContextOuterClass.Connection> getConnectionsList() {
-        if (connectionsBuilder_ == null) {
-          return java.util.Collections.unmodifiableList(connections_);
-        } else {
-          return connectionsBuilder_.getMessageList();
-        }
-      }
-      /**
-       * <code>repeated .context.Connection connections = 1;</code>
-       */
-      public int getConnectionsCount() {
-        if (connectionsBuilder_ == null) {
-          return connections_.size();
-        } else {
-          return connectionsBuilder_.getCount();
-        }
-      }
-      /**
-       * <code>repeated .context.Connection connections = 1;</code>
-       */
-      public context.ContextOuterClass.Connection getConnections(int index) {
-        if (connectionsBuilder_ == null) {
-          return connections_.get(index);
-        } else {
-          return connectionsBuilder_.getMessage(index);
-        }
-      }
-      /**
-       * <code>repeated .context.Connection connections = 1;</code>
-       */
-      public Builder setConnections(
-          int index, context.ContextOuterClass.Connection value) {
-        if (connectionsBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureConnectionsIsMutable();
-          connections_.set(index, value);
-          onChanged();
-        } else {
-          connectionsBuilder_.setMessage(index, value);
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .context.Connection connections = 1;</code>
-       */
-      public Builder setConnections(
-          int index, context.ContextOuterClass.Connection.Builder builderForValue) {
-        if (connectionsBuilder_ == null) {
-          ensureConnectionsIsMutable();
-          connections_.set(index, builderForValue.build());
-          onChanged();
-        } else {
-          connectionsBuilder_.setMessage(index, builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .context.Connection connections = 1;</code>
-       */
-      public Builder addConnections(context.ContextOuterClass.Connection value) {
-        if (connectionsBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureConnectionsIsMutable();
-          connections_.add(value);
-          onChanged();
-        } else {
-          connectionsBuilder_.addMessage(value);
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .context.Connection connections = 1;</code>
-       */
-      public Builder addConnections(
-          int index, context.ContextOuterClass.Connection value) {
-        if (connectionsBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureConnectionsIsMutable();
-          connections_.add(index, value);
-          onChanged();
-        } else {
-          connectionsBuilder_.addMessage(index, value);
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .context.Connection connections = 1;</code>
-       */
-      public Builder addConnections(
-          context.ContextOuterClass.Connection.Builder builderForValue) {
-        if (connectionsBuilder_ == null) {
-          ensureConnectionsIsMutable();
-          connections_.add(builderForValue.build());
-          onChanged();
-        } else {
-          connectionsBuilder_.addMessage(builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .context.Connection connections = 1;</code>
+       * <code>string constraint_type = 1;</code>
+       * @return The constraintType.
        */
-      public Builder addConnections(
-          int index, context.ContextOuterClass.Connection.Builder builderForValue) {
-        if (connectionsBuilder_ == null) {
-          ensureConnectionsIsMutable();
-          connections_.add(index, builderForValue.build());
-          onChanged();
+      public java.lang.String getConstraintType() {
+        java.lang.Object ref = constraintType_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          constraintType_ = s;
+          return s;
         } else {
-          connectionsBuilder_.addMessage(index, builderForValue.build());
+          return (java.lang.String) ref;
         }
-        return this;
       }
       /**
-       * <code>repeated .context.Connection connections = 1;</code>
+       * <code>string constraint_type = 1;</code>
+       * @return The bytes for constraintType.
        */
-      public Builder addAllConnections(
-          java.lang.Iterable<? extends context.ContextOuterClass.Connection> values) {
-        if (connectionsBuilder_ == null) {
-          ensureConnectionsIsMutable();
-          com.google.protobuf.AbstractMessageLite.Builder.addAll(
-              values, connections_);
-          onChanged();
+      public com.google.protobuf.ByteString
+          getConstraintTypeBytes() {
+        java.lang.Object ref = constraintType_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          constraintType_ = b;
+          return b;
         } else {
-          connectionsBuilder_.addAllMessages(values);
+          return (com.google.protobuf.ByteString) ref;
         }
-        return this;
       }
       /**
-       * <code>repeated .context.Connection connections = 1;</code>
-       */
-      public Builder clearConnections() {
-        if (connectionsBuilder_ == null) {
-          connections_ = java.util.Collections.emptyList();
-          bitField0_ = (bitField0_ & ~0x00000001);
-          onChanged();
-        } else {
-          connectionsBuilder_.clear();
-        }
+       * <code>string constraint_type = 1;</code>
+       * @param value The constraintType to set.
+       * @return This builder for chaining.
+       */
+      public Builder setConstraintType(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  
+        constraintType_ = value;
+        onChanged();
         return this;
       }
       /**
-       * <code>repeated .context.Connection connections = 1;</code>
+       * <code>string constraint_type = 1;</code>
+       * @return This builder for chaining.
        */
-      public Builder removeConnections(int index) {
-        if (connectionsBuilder_ == null) {
-          ensureConnectionsIsMutable();
-          connections_.remove(index);
-          onChanged();
-        } else {
-          connectionsBuilder_.remove(index);
-        }
+      public Builder clearConstraintType() {
+        
+        constraintType_ = getDefaultInstance().getConstraintType();
+        onChanged();
         return this;
       }
       /**
-       * <code>repeated .context.Connection connections = 1;</code>
+       * <code>string constraint_type = 1;</code>
+       * @param value The bytes for constraintType to set.
+       * @return This builder for chaining.
        */
-      public context.ContextOuterClass.Connection.Builder getConnectionsBuilder(
-          int index) {
-        return getConnectionsFieldBuilder().getBuilder(index);
+      public Builder setConstraintTypeBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  checkByteStringIsUtf8(value);
+        
+        constraintType_ = value;
+        onChanged();
+        return this;
       }
+
+      private java.lang.Object constraintValue_ = "";
       /**
-       * <code>repeated .context.Connection connections = 1;</code>
+       * <code>string constraint_value = 2;</code>
+       * @return The constraintValue.
        */
-      public context.ContextOuterClass.ConnectionOrBuilder getConnectionsOrBuilder(
-          int index) {
-        if (connectionsBuilder_ == null) {
-          return connections_.get(index);  } else {
-          return connectionsBuilder_.getMessageOrBuilder(index);
+      public java.lang.String getConstraintValue() {
+        java.lang.Object ref = constraintValue_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          constraintValue_ = s;
+          return s;
+        } else {
+          return (java.lang.String) ref;
         }
       }
       /**
-       * <code>repeated .context.Connection connections = 1;</code>
+       * <code>string constraint_value = 2;</code>
+       * @return The bytes for constraintValue.
        */
-      public java.util.List<? extends context.ContextOuterClass.ConnectionOrBuilder> 
-           getConnectionsOrBuilderList() {
-        if (connectionsBuilder_ != null) {
-          return connectionsBuilder_.getMessageOrBuilderList();
+      public com.google.protobuf.ByteString
+          getConstraintValueBytes() {
+        java.lang.Object ref = constraintValue_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          constraintValue_ = b;
+          return b;
         } else {
-          return java.util.Collections.unmodifiableList(connections_);
+          return (com.google.protobuf.ByteString) ref;
         }
       }
       /**
-       * <code>repeated .context.Connection connections = 1;</code>
+       * <code>string constraint_value = 2;</code>
+       * @param value The constraintValue to set.
+       * @return This builder for chaining.
        */
-      public context.ContextOuterClass.Connection.Builder addConnectionsBuilder() {
-        return getConnectionsFieldBuilder().addBuilder(
-            context.ContextOuterClass.Connection.getDefaultInstance());
+      public Builder setConstraintValue(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  
+        constraintValue_ = value;
+        onChanged();
+        return this;
       }
       /**
-       * <code>repeated .context.Connection connections = 1;</code>
+       * <code>string constraint_value = 2;</code>
+       * @return This builder for chaining.
        */
-      public context.ContextOuterClass.Connection.Builder addConnectionsBuilder(
-          int index) {
-        return getConnectionsFieldBuilder().addBuilder(
-            index, context.ContextOuterClass.Connection.getDefaultInstance());
+      public Builder clearConstraintValue() {
+        
+        constraintValue_ = getDefaultInstance().getConstraintValue();
+        onChanged();
+        return this;
       }
       /**
-       * <code>repeated .context.Connection connections = 1;</code>
+       * <code>string constraint_value = 2;</code>
+       * @param value The bytes for constraintValue to set.
+       * @return This builder for chaining.
        */
-      public java.util.List<context.ContextOuterClass.Connection.Builder> 
-           getConnectionsBuilderList() {
-        return getConnectionsFieldBuilder().getBuilderList();
-      }
-      private com.google.protobuf.RepeatedFieldBuilderV3<
-          context.ContextOuterClass.Connection, context.ContextOuterClass.Connection.Builder, context.ContextOuterClass.ConnectionOrBuilder> 
-          getConnectionsFieldBuilder() {
-        if (connectionsBuilder_ == null) {
-          connectionsBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3<
-              context.ContextOuterClass.Connection, context.ContextOuterClass.Connection.Builder, context.ContextOuterClass.ConnectionOrBuilder>(
-                  connections_,
-                  ((bitField0_ & 0x00000001) != 0),
-                  getParentForChildren(),
-                  isClean());
-          connections_ = null;
-        }
-        return connectionsBuilder_;
+      public Builder setConstraintValueBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  checkByteStringIsUtf8(value);
+        
+        constraintValue_ = value;
+        onChanged();
+        return this;
       }
       @java.lang.Override
       public final Builder setUnknownFields(
@@ -34683,41 +35879,41 @@ public final class ContextOuterClass {
       }
 
 
-      // @@protoc_insertion_point(builder_scope:context.ConnectionList)
+      // @@protoc_insertion_point(builder_scope:context.Constraint)
     }
 
-    // @@protoc_insertion_point(class_scope:context.ConnectionList)
-    private static final context.ContextOuterClass.ConnectionList DEFAULT_INSTANCE;
+    // @@protoc_insertion_point(class_scope:context.Constraint)
+    private static final context.ContextOuterClass.Constraint DEFAULT_INSTANCE;
     static {
-      DEFAULT_INSTANCE = new context.ContextOuterClass.ConnectionList();
+      DEFAULT_INSTANCE = new context.ContextOuterClass.Constraint();
     }
 
-    public static context.ContextOuterClass.ConnectionList getDefaultInstance() {
+    public static context.ContextOuterClass.Constraint getDefaultInstance() {
       return DEFAULT_INSTANCE;
     }
 
-    private static final com.google.protobuf.Parser<ConnectionList>
-        PARSER = new com.google.protobuf.AbstractParser<ConnectionList>() {
+    private static final com.google.protobuf.Parser<Constraint>
+        PARSER = new com.google.protobuf.AbstractParser<Constraint>() {
       @java.lang.Override
-      public ConnectionList parsePartialFrom(
+      public Constraint parsePartialFrom(
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws com.google.protobuf.InvalidProtocolBufferException {
-        return new ConnectionList(input, extensionRegistry);
+        return new Constraint(input, extensionRegistry);
       }
     };
 
-    public static com.google.protobuf.Parser<ConnectionList> parser() {
+    public static com.google.protobuf.Parser<Constraint> parser() {
       return PARSER;
     }
 
     @java.lang.Override
-    public com.google.protobuf.Parser<ConnectionList> getParserForType() {
+    public com.google.protobuf.Parser<Constraint> getParserForType() {
       return PARSER;
     }
 
     @java.lang.Override
-    public context.ContextOuterClass.ConnectionList getDefaultInstanceForType() {
+    public context.ContextOuterClass.Constraint getDefaultInstanceForType() {
       return DEFAULT_INSTANCE;
     }
 
@@ -36420,45 +37616,50 @@ public final class ContextOuterClass {
     com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
       internal_static_context_ServiceEvent_fieldAccessorTable;
   private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_context_EndPointId_descriptor;
+    internal_static_context_ConnectionId_descriptor;
   private static final 
     com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_context_EndPointId_fieldAccessorTable;
+      internal_static_context_ConnectionId_fieldAccessorTable;
   private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_context_EndPoint_descriptor;
+    internal_static_context_Connection_descriptor;
   private static final 
     com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_context_EndPoint_fieldAccessorTable;
+      internal_static_context_Connection_fieldAccessorTable;
   private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_context_ConfigRule_descriptor;
+    internal_static_context_ConnectionIdList_descriptor;
   private static final 
     com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_context_ConfigRule_fieldAccessorTable;
+      internal_static_context_ConnectionIdList_fieldAccessorTable;
   private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_context_Constraint_descriptor;
+    internal_static_context_ConnectionList_descriptor;
   private static final 
     com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_context_Constraint_fieldAccessorTable;
+      internal_static_context_ConnectionList_fieldAccessorTable;
   private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_context_ConnectionId_descriptor;
+    internal_static_context_ConnectionEvent_descriptor;
   private static final 
     com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_context_ConnectionId_fieldAccessorTable;
+      internal_static_context_ConnectionEvent_fieldAccessorTable;
   private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_context_Connection_descriptor;
+    internal_static_context_EndPointId_descriptor;
   private static final 
     com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_context_Connection_fieldAccessorTable;
+      internal_static_context_EndPointId_fieldAccessorTable;
   private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_context_ConnectionIdList_descriptor;
+    internal_static_context_EndPoint_descriptor;
   private static final 
     com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_context_ConnectionIdList_fieldAccessorTable;
+      internal_static_context_EndPoint_fieldAccessorTable;
   private static final com.google.protobuf.Descriptors.Descriptor
-    internal_static_context_ConnectionList_descriptor;
+    internal_static_context_ConfigRule_descriptor;
   private static final 
     com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
-      internal_static_context_ConnectionList_fieldAccessorTable;
+      internal_static_context_ConfigRule_fieldAccessorTable;
+  private static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_context_Constraint_descriptor;
+  private static final 
+    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internal_static_context_Constraint_fieldAccessorTable;
   private static final com.google.protobuf.Descriptors.Descriptor
     internal_static_context_TeraFlowController_descriptor;
   private static final 
@@ -36543,94 +37744,107 @@ public final class ContextOuterClass {
       "\"\n\010services\030\001 \003(\0132\020.context.Service\"U\n\014S" +
       "erviceEvent\022\035\n\005event\030\001 \001(\0132\016.context.Eve" +
       "nt\022&\n\nservice_id\030\002 \001(\0132\022.context.Service" +
-      "Id\"\202\001\n\nEndPointId\022(\n\013topology_id\030\001 \001(\0132\023" +
-      ".context.TopologyId\022$\n\tdevice_id\030\002 \001(\0132\021" +
-      ".context.DeviceId\022$\n\rendpoint_uuid\030\003 \001(\013" +
-      "2\r.context.Uuid\"\206\001\n\010EndPoint\022(\n\013endpoint" +
-      "_id\030\001 \001(\0132\023.context.EndPointId\022\025\n\rendpoi" +
-      "nt_type\030\002 \001(\t\0229\n\020kpi_sample_types\030\003 \003(\0162" +
-      "\037.kpi_sample_types.KpiSampleType\"e\n\nConf" +
-      "igRule\022)\n\006action\030\001 \001(\0162\031.context.ConfigA" +
-      "ctionEnum\022\024\n\014resource_key\030\002 \001(\t\022\026\n\016resou" +
-      "rce_value\030\003 \001(\t\"?\n\nConstraint\022\027\n\017constra" +
-      "int_type\030\001 \001(\t\022\030\n\020constraint_value\030\002 \001(\t" +
-      "\"6\n\014ConnectionId\022&\n\017connection_uuid\030\001 \001(" +
-      "\0132\r.context.Uuid\"\215\001\n\nConnection\022,\n\rconne" +
-      "ction_id\030\001 \001(\0132\025.context.ConnectionId\022.\n" +
-      "\022related_service_id\030\002 \001(\0132\022.context.Serv" +
-      "iceId\022!\n\004path\030\003 \003(\0132\023.context.EndPointId" +
-      "\"A\n\020ConnectionIdList\022-\n\016connection_ids\030\001" +
-      " \003(\0132\025.context.ConnectionId\":\n\016Connectio" +
-      "nList\022(\n\013connections\030\001 \003(\0132\023.context.Con" +
-      "nection\"^\n\022TeraFlowController\022&\n\ncontext" +
-      "_id\030\001 \001(\0132\022.context.ContextId\022\022\n\nip_addr" +
-      "ess\030\002 \001(\t\022\014\n\004port\030\003 \001(\r\"U\n\024Authenticatio" +
-      "nResult\022&\n\ncontext_id\030\001 \001(\0132\022.context.Co" +
-      "ntextId\022\025\n\rauthenticated\030\002 \001(\010*j\n\rEventT" +
-      "ypeEnum\022\027\n\023EVENTTYPE_UNDEFINED\020\000\022\024\n\020EVEN" +
-      "TTYPE_CREATE\020\001\022\024\n\020EVENTTYPE_UPDATE\020\002\022\024\n\020" +
-      "EVENTTYPE_REMOVE\020\003*\305\001\n\020DeviceDriverEnum\022" +
-      "\032\n\026DEVICEDRIVER_UNDEFINED\020\000\022\033\n\027DEVICEDRI" +
-      "VER_OPENCONFIG\020\001\022\036\n\032DEVICEDRIVER_TRANSPO" +
-      "RT_API\020\002\022\023\n\017DEVICEDRIVER_P4\020\003\022&\n\"DEVICED" +
-      "RIVER_IETF_NETWORK_TOPOLOGY\020\004\022\033\n\027DEVICED" +
-      "RIVER_ONF_TR_352\020\005*\217\001\n\033DeviceOperational" +
-      "StatusEnum\022%\n!DEVICEOPERATIONALSTATUS_UN" +
-      "DEFINED\020\000\022$\n DEVICEOPERATIONALSTATUS_DIS" +
-      "ABLED\020\001\022#\n\037DEVICEOPERATIONALSTATUS_ENABL" +
-      "ED\020\002*\201\001\n\017ServiceTypeEnum\022\027\n\023SERVICETYPE_" +
-      "UNKNOWN\020\000\022\024\n\020SERVICETYPE_L3NM\020\001\022\024\n\020SERVI" +
-      "CETYPE_L2NM\020\002\022)\n%SERVICETYPE_TAPI_CONNEC" +
-      "TIVITY_SERVICE\020\003*\210\001\n\021ServiceStatusEnum\022\033" +
-      "\n\027SERVICESTATUS_UNDEFINED\020\000\022\031\n\025SERVICEST" +
-      "ATUS_PLANNED\020\001\022\030\n\024SERVICESTATUS_ACTIVE\020\002" +
-      "\022!\n\035SERVICESTATUS_PENDING_REMOVAL\020\003*]\n\020C" +
-      "onfigActionEnum\022\032\n\026CONFIGACTION_UNDEFINE" +
-      "D\020\000\022\024\n\020CONFIGACTION_SET\020\001\022\027\n\023CONFIGACTIO" +
-      "N_DELETE\020\0022\245\r\n\016ContextService\022:\n\016ListCon" +
-      "textIds\022\016.context.Empty\032\026.context.Contex" +
-      "tIdList\"\000\0226\n\014ListContexts\022\016.context.Empt" +
-      "y\032\024.context.ContextList\"\000\0224\n\nGetContext\022" +
-      "\022.context.ContextId\032\020.context.Context\"\000\022" +
-      "4\n\nSetContext\022\020.context.Context\032\022.contex" +
-      "t.ContextId\"\000\0225\n\rRemoveContext\022\022.context" +
-      ".ContextId\032\016.context.Empty\"\000\022=\n\020GetConte" +
-      "xtEvents\022\016.context.Empty\032\025.context.Conte" +
-      "xtEvent\"\0000\001\022@\n\017ListTopologyIds\022\022.context" +
-      ".ContextId\032\027.context.TopologyIdList\"\000\022=\n" +
-      "\016ListTopologies\022\022.context.ContextId\032\025.co" +
-      "ntext.TopologyList\"\000\0227\n\013GetTopology\022\023.co" +
-      "ntext.TopologyId\032\021.context.Topology\"\000\0227\n" +
-      "\013SetTopology\022\021.context.Topology\032\023.contex" +
-      "t.TopologyId\"\000\0227\n\016RemoveTopology\022\023.conte" +
-      "xt.TopologyId\032\016.context.Empty\"\000\022?\n\021GetTo" +
-      "pologyEvents\022\016.context.Empty\032\026.context.T" +
-      "opologyEvent\"\0000\001\0228\n\rListDeviceIds\022\016.cont" +
-      "ext.Empty\032\025.context.DeviceIdList\"\000\0224\n\013Li" +
-      "stDevices\022\016.context.Empty\032\023.context.Devi" +
-      "ceList\"\000\0221\n\tGetDevice\022\021.context.DeviceId" +
-      "\032\017.context.Device\"\000\0221\n\tSetDevice\022\017.conte" +
-      "xt.Device\032\021.context.DeviceId\"\000\0223\n\014Remove" +
-      "Device\022\021.context.DeviceId\032\016.context.Empt" +
-      "y\"\000\022;\n\017GetDeviceEvents\022\016.context.Empty\032\024" +
-      ".context.DeviceEvent\"\0000\001\0224\n\013ListLinkIds\022" +
-      "\016.context.Empty\032\023.context.LinkIdList\"\000\0220" +
-      "\n\tListLinks\022\016.context.Empty\032\021.context.Li" +
-      "nkList\"\000\022+\n\007GetLink\022\017.context.LinkId\032\r.c" +
-      "ontext.Link\"\000\022+\n\007SetLink\022\r.context.Link\032" +
-      "\017.context.LinkId\"\000\022/\n\nRemoveLink\022\017.conte" +
-      "xt.LinkId\032\016.context.Empty\"\000\0227\n\rGetLinkEv" +
-      "ents\022\016.context.Empty\032\022.context.LinkEvent" +
-      "\"\0000\001\022>\n\016ListServiceIds\022\022.context.Context" +
-      "Id\032\026.context.ServiceIdList\"\000\022:\n\014ListServ" +
-      "ices\022\022.context.ContextId\032\024.context.Servi" +
-      "ceList\"\000\0224\n\nGetService\022\022.context.Service" +
-      "Id\032\020.context.Service\"\000\0224\n\nSetService\022\020.c" +
-      "ontext.Service\032\022.context.ServiceId\"\000\0225\n\r" +
-      "RemoveService\022\022.context.ServiceId\032\016.cont" +
-      "ext.Empty\"\000\022=\n\020GetServiceEvents\022\016.contex" +
-      "t.Empty\032\025.context.ServiceEvent\"\0000\001b\006prot" +
-      "o3"
+      "Id\"6\n\014ConnectionId\022&\n\017connection_uuid\030\001 " +
+      "\001(\0132\r.context.Uuid\"\304\001\n\nConnection\022,\n\rcon" +
+      "nection_id\030\001 \001(\0132\025.context.ConnectionId\022" +
+      "&\n\nservice_id\030\002 \001(\0132\022.context.ServiceId\022" +
+      "3\n\026path_hops_endpoint_ids\030\003 \003(\0132\023.contex" +
+      "t.EndPointId\022+\n\017sub_service_ids\030\004 \003(\0132\022." +
+      "context.ServiceId\"A\n\020ConnectionIdList\022-\n" +
+      "\016connection_ids\030\001 \003(\0132\025.context.Connecti" +
+      "onId\":\n\016ConnectionList\022(\n\013connections\030\001 " +
+      "\003(\0132\023.context.Connection\"^\n\017ConnectionEv" +
+      "ent\022\035\n\005event\030\001 \001(\0132\016.context.Event\022,\n\rco" +
+      "nnection_id\030\002 \001(\0132\025.context.ConnectionId" +
+      "\"\202\001\n\nEndPointId\022(\n\013topology_id\030\001 \001(\0132\023.c" +
+      "ontext.TopologyId\022$\n\tdevice_id\030\002 \001(\0132\021.c" +
+      "ontext.DeviceId\022$\n\rendpoint_uuid\030\003 \001(\0132\r" +
+      ".context.Uuid\"\206\001\n\010EndPoint\022(\n\013endpoint_i" +
+      "d\030\001 \001(\0132\023.context.EndPointId\022\025\n\rendpoint" +
+      "_type\030\002 \001(\t\0229\n\020kpi_sample_types\030\003 \003(\0162\037." +
+      "kpi_sample_types.KpiSampleType\"e\n\nConfig" +
+      "Rule\022)\n\006action\030\001 \001(\0162\031.context.ConfigAct" +
+      "ionEnum\022\024\n\014resource_key\030\002 \001(\t\022\026\n\016resourc" +
+      "e_value\030\003 \001(\t\"?\n\nConstraint\022\027\n\017constrain" +
+      "t_type\030\001 \001(\t\022\030\n\020constraint_value\030\002 \001(\t\"^" +
+      "\n\022TeraFlowController\022&\n\ncontext_id\030\001 \001(\013" +
+      "2\022.context.ContextId\022\022\n\nip_address\030\002 \001(\t" +
+      "\022\014\n\004port\030\003 \001(\r\"U\n\024AuthenticationResult\022&" +
+      "\n\ncontext_id\030\001 \001(\0132\022.context.ContextId\022\025" +
+      "\n\rauthenticated\030\002 \001(\010*j\n\rEventTypeEnum\022\027" +
+      "\n\023EVENTTYPE_UNDEFINED\020\000\022\024\n\020EVENTTYPE_CRE" +
+      "ATE\020\001\022\024\n\020EVENTTYPE_UPDATE\020\002\022\024\n\020EVENTTYPE" +
+      "_REMOVE\020\003*\305\001\n\020DeviceDriverEnum\022\032\n\026DEVICE" +
+      "DRIVER_UNDEFINED\020\000\022\033\n\027DEVICEDRIVER_OPENC" +
+      "ONFIG\020\001\022\036\n\032DEVICEDRIVER_TRANSPORT_API\020\002\022" +
+      "\023\n\017DEVICEDRIVER_P4\020\003\022&\n\"DEVICEDRIVER_IET" +
+      "F_NETWORK_TOPOLOGY\020\004\022\033\n\027DEVICEDRIVER_ONF" +
+      "_TR_352\020\005*\217\001\n\033DeviceOperationalStatusEnu" +
+      "m\022%\n!DEVICEOPERATIONALSTATUS_UNDEFINED\020\000" +
+      "\022$\n DEVICEOPERATIONALSTATUS_DISABLED\020\001\022#" +
+      "\n\037DEVICEOPERATIONALSTATUS_ENABLED\020\002*\201\001\n\017" +
+      "ServiceTypeEnum\022\027\n\023SERVICETYPE_UNKNOWN\020\000" +
+      "\022\024\n\020SERVICETYPE_L3NM\020\001\022\024\n\020SERVICETYPE_L2" +
+      "NM\020\002\022)\n%SERVICETYPE_TAPI_CONNECTIVITY_SE" +
+      "RVICE\020\003*\210\001\n\021ServiceStatusEnum\022\033\n\027SERVICE" +
+      "STATUS_UNDEFINED\020\000\022\031\n\025SERVICESTATUS_PLAN" +
+      "NED\020\001\022\030\n\024SERVICESTATUS_ACTIVE\020\002\022!\n\035SERVI" +
+      "CESTATUS_PENDING_REMOVAL\020\003*]\n\020ConfigActi" +
+      "onEnum\022\032\n\026CONFIGACTION_UNDEFINED\020\000\022\024\n\020CO" +
+      "NFIGACTION_SET\020\001\022\027\n\023CONFIGACTION_DELETE\020" +
+      "\0022\255\020\n\016ContextService\022:\n\016ListContextIds\022\016" +
+      ".context.Empty\032\026.context.ContextIdList\"\000" +
+      "\0226\n\014ListContexts\022\016.context.Empty\032\024.conte" +
+      "xt.ContextList\"\000\0224\n\nGetContext\022\022.context" +
+      ".ContextId\032\020.context.Context\"\000\0224\n\nSetCon" +
+      "text\022\020.context.Context\032\022.context.Context" +
+      "Id\"\000\0225\n\rRemoveContext\022\022.context.ContextI" +
+      "d\032\016.context.Empty\"\000\022=\n\020GetContextEvents\022" +
+      "\016.context.Empty\032\025.context.ContextEvent\"\000" +
+      "0\001\022@\n\017ListTopologyIds\022\022.context.ContextI" +
+      "d\032\027.context.TopologyIdList\"\000\022=\n\016ListTopo" +
+      "logies\022\022.context.ContextId\032\025.context.Top" +
+      "ologyList\"\000\0227\n\013GetTopology\022\023.context.Top" +
+      "ologyId\032\021.context.Topology\"\000\0227\n\013SetTopol" +
+      "ogy\022\021.context.Topology\032\023.context.Topolog" +
+      "yId\"\000\0227\n\016RemoveTopology\022\023.context.Topolo" +
+      "gyId\032\016.context.Empty\"\000\022?\n\021GetTopologyEve" +
+      "nts\022\016.context.Empty\032\026.context.TopologyEv" +
+      "ent\"\0000\001\0228\n\rListDeviceIds\022\016.context.Empty" +
+      "\032\025.context.DeviceIdList\"\000\0224\n\013ListDevices" +
+      "\022\016.context.Empty\032\023.context.DeviceList\"\000\022" +
+      "1\n\tGetDevice\022\021.context.DeviceId\032\017.contex" +
+      "t.Device\"\000\0221\n\tSetDevice\022\017.context.Device" +
+      "\032\021.context.DeviceId\"\000\0223\n\014RemoveDevice\022\021." +
+      "context.DeviceId\032\016.context.Empty\"\000\022;\n\017Ge" +
+      "tDeviceEvents\022\016.context.Empty\032\024.context." +
+      "DeviceEvent\"\0000\001\0224\n\013ListLinkIds\022\016.context" +
+      ".Empty\032\023.context.LinkIdList\"\000\0220\n\tListLin" +
+      "ks\022\016.context.Empty\032\021.context.LinkList\"\000\022" +
+      "+\n\007GetLink\022\017.context.LinkId\032\r.context.Li" +
+      "nk\"\000\022+\n\007SetLink\022\r.context.Link\032\017.context" +
+      ".LinkId\"\000\022/\n\nRemoveLink\022\017.context.LinkId" +
+      "\032\016.context.Empty\"\000\0227\n\rGetLinkEvents\022\016.co" +
+      "ntext.Empty\032\022.context.LinkEvent\"\0000\001\022>\n\016L" +
+      "istServiceIds\022\022.context.ContextId\032\026.cont" +
+      "ext.ServiceIdList\"\000\022:\n\014ListServices\022\022.co" +
+      "ntext.ContextId\032\024.context.ServiceList\"\000\022" +
+      "4\n\nGetService\022\022.context.ServiceId\032\020.cont" +
+      "ext.Service\"\000\0224\n\nSetService\022\020.context.Se" +
+      "rvice\032\022.context.ServiceId\"\000\0225\n\rRemoveSer" +
+      "vice\022\022.context.ServiceId\032\016.context.Empty" +
+      "\"\000\022=\n\020GetServiceEvents\022\016.context.Empty\032\025" +
+      ".context.ServiceEvent\"\0000\001\022D\n\021ListConnect" +
+      "ionIds\022\022.context.ServiceId\032\031.context.Con" +
+      "nectionIdList\"\000\022@\n\017ListConnections\022\022.con" +
+      "text.ServiceId\032\027.context.ConnectionList\"" +
+      "\000\022=\n\rGetConnection\022\025.context.ConnectionI" +
+      "d\032\023.context.Connection\"\000\022=\n\rSetConnectio" +
+      "n\022\023.context.Connection\032\025.context.Connect" +
+      "ionId\"\000\022;\n\020RemoveConnection\022\025.context.Co" +
+      "nnectionId\032\016.context.Empty\"\000\022C\n\023GetConne" +
+      "ctionEvents\022\016.context.Empty\032\030.context.Co" +
+      "nnectionEvent\"\0000\001b\006proto3"
     };
     descriptor = com.google.protobuf.Descriptors.FileDescriptor
       .internalBuildGeneratedFileFrom(descriptorData,
@@ -36823,62 +38037,68 @@ public final class ContextOuterClass {
       com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
         internal_static_context_ServiceEvent_descriptor,
         new java.lang.String[] { "Event", "ServiceId", });
-    internal_static_context_EndPointId_descriptor =
+    internal_static_context_ConnectionId_descriptor =
       getDescriptor().getMessageTypes().get(31);
+    internal_static_context_ConnectionId_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+        internal_static_context_ConnectionId_descriptor,
+        new java.lang.String[] { "ConnectionUuid", });
+    internal_static_context_Connection_descriptor =
+      getDescriptor().getMessageTypes().get(32);
+    internal_static_context_Connection_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+        internal_static_context_Connection_descriptor,
+        new java.lang.String[] { "ConnectionId", "ServiceId", "PathHopsEndpointIds", "SubServiceIds", });
+    internal_static_context_ConnectionIdList_descriptor =
+      getDescriptor().getMessageTypes().get(33);
+    internal_static_context_ConnectionIdList_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+        internal_static_context_ConnectionIdList_descriptor,
+        new java.lang.String[] { "ConnectionIds", });
+    internal_static_context_ConnectionList_descriptor =
+      getDescriptor().getMessageTypes().get(34);
+    internal_static_context_ConnectionList_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+        internal_static_context_ConnectionList_descriptor,
+        new java.lang.String[] { "Connections", });
+    internal_static_context_ConnectionEvent_descriptor =
+      getDescriptor().getMessageTypes().get(35);
+    internal_static_context_ConnectionEvent_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+        internal_static_context_ConnectionEvent_descriptor,
+        new java.lang.String[] { "Event", "ConnectionId", });
+    internal_static_context_EndPointId_descriptor =
+      getDescriptor().getMessageTypes().get(36);
     internal_static_context_EndPointId_fieldAccessorTable = new
       com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
         internal_static_context_EndPointId_descriptor,
         new java.lang.String[] { "TopologyId", "DeviceId", "EndpointUuid", });
     internal_static_context_EndPoint_descriptor =
-      getDescriptor().getMessageTypes().get(32);
+      getDescriptor().getMessageTypes().get(37);
     internal_static_context_EndPoint_fieldAccessorTable = new
       com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
         internal_static_context_EndPoint_descriptor,
         new java.lang.String[] { "EndpointId", "EndpointType", "KpiSampleTypes", });
     internal_static_context_ConfigRule_descriptor =
-      getDescriptor().getMessageTypes().get(33);
+      getDescriptor().getMessageTypes().get(38);
     internal_static_context_ConfigRule_fieldAccessorTable = new
       com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
         internal_static_context_ConfigRule_descriptor,
         new java.lang.String[] { "Action", "ResourceKey", "ResourceValue", });
     internal_static_context_Constraint_descriptor =
-      getDescriptor().getMessageTypes().get(34);
+      getDescriptor().getMessageTypes().get(39);
     internal_static_context_Constraint_fieldAccessorTable = new
       com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
         internal_static_context_Constraint_descriptor,
         new java.lang.String[] { "ConstraintType", "ConstraintValue", });
-    internal_static_context_ConnectionId_descriptor =
-      getDescriptor().getMessageTypes().get(35);
-    internal_static_context_ConnectionId_fieldAccessorTable = new
-      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
-        internal_static_context_ConnectionId_descriptor,
-        new java.lang.String[] { "ConnectionUuid", });
-    internal_static_context_Connection_descriptor =
-      getDescriptor().getMessageTypes().get(36);
-    internal_static_context_Connection_fieldAccessorTable = new
-      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
-        internal_static_context_Connection_descriptor,
-        new java.lang.String[] { "ConnectionId", "RelatedServiceId", "Path", });
-    internal_static_context_ConnectionIdList_descriptor =
-      getDescriptor().getMessageTypes().get(37);
-    internal_static_context_ConnectionIdList_fieldAccessorTable = new
-      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
-        internal_static_context_ConnectionIdList_descriptor,
-        new java.lang.String[] { "ConnectionIds", });
-    internal_static_context_ConnectionList_descriptor =
-      getDescriptor().getMessageTypes().get(38);
-    internal_static_context_ConnectionList_fieldAccessorTable = new
-      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
-        internal_static_context_ConnectionList_descriptor,
-        new java.lang.String[] { "Connections", });
     internal_static_context_TeraFlowController_descriptor =
-      getDescriptor().getMessageTypes().get(39);
+      getDescriptor().getMessageTypes().get(40);
     internal_static_context_TeraFlowController_fieldAccessorTable = new
       com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
         internal_static_context_TeraFlowController_descriptor,
         new java.lang.String[] { "ContextId", "IpAddress", "Port", });
     internal_static_context_AuthenticationResult_descriptor =
-      getDescriptor().getMessageTypes().get(40);
+      getDescriptor().getMessageTypes().get(41);
     internal_static_context_AuthenticationResult_fieldAccessorTable = new
       com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
         internal_static_context_AuthenticationResult_descriptor,
diff --git a/src/automation/target/generated-sources/grpc/context/ContextService.java b/src/automation/target/generated-sources/grpc/context/ContextService.java
index 8e5095d25..cbd51163f 100644
--- a/src/automation/target/generated-sources/grpc/context/ContextService.java
+++ b/src/automation/target/generated-sources/grpc/context/ContextService.java
@@ -58,6 +58,16 @@ public interface ContextService extends MutinyService {
     
     io.smallrye.mutiny.Uni<context.ContextOuterClass.Empty> removeService(context.ContextOuterClass.ServiceId request);
     
+    io.smallrye.mutiny.Uni<context.ContextOuterClass.ConnectionIdList> listConnectionIds(context.ContextOuterClass.ServiceId request);
+    
+    io.smallrye.mutiny.Uni<context.ContextOuterClass.ConnectionList> listConnections(context.ContextOuterClass.ServiceId request);
+    
+    io.smallrye.mutiny.Uni<context.ContextOuterClass.Connection> getConnection(context.ContextOuterClass.ConnectionId request);
+    
+    io.smallrye.mutiny.Uni<context.ContextOuterClass.ConnectionId> setConnection(context.ContextOuterClass.Connection request);
+    
+    io.smallrye.mutiny.Uni<context.ContextOuterClass.Empty> removeConnection(context.ContextOuterClass.ConnectionId request);
+    
     
     io.smallrye.mutiny.Multi<context.ContextOuterClass.ContextEvent> getContextEvents(context.ContextOuterClass.Empty request);
     
@@ -69,6 +79,8 @@ public interface ContextService extends MutinyService {
     
     io.smallrye.mutiny.Multi<context.ContextOuterClass.ServiceEvent> getServiceEvents(context.ContextOuterClass.Empty request);
     
+    io.smallrye.mutiny.Multi<context.ContextOuterClass.ConnectionEvent> getConnectionEvents(context.ContextOuterClass.Empty request);
+    
     
 
 }
\ No newline at end of file
diff --git a/src/automation/target/generated-sources/grpc/context/ContextServiceBean.java b/src/automation/target/generated-sources/grpc/context/ContextServiceBean.java
index fbecd5d2f..6900cf3c8 100644
--- a/src/automation/target/generated-sources/grpc/context/ContextServiceBean.java
+++ b/src/automation/target/generated-sources/grpc/context/ContextServiceBean.java
@@ -215,6 +215,46 @@ public class ContextServiceBean extends MutinyContextServiceGrpc.ContextServiceI
           throw new io.grpc.StatusRuntimeException(io.grpc.Status.UNIMPLEMENTED);
        }
     }
+    @Override
+    public io.smallrye.mutiny.Uni<context.ContextOuterClass.ConnectionIdList> listConnectionIds(context.ContextOuterClass.ServiceId request) {
+       try {
+         return delegate.listConnectionIds(request);
+       } catch (UnsupportedOperationException e) {
+          throw new io.grpc.StatusRuntimeException(io.grpc.Status.UNIMPLEMENTED);
+       }
+    }
+    @Override
+    public io.smallrye.mutiny.Uni<context.ContextOuterClass.ConnectionList> listConnections(context.ContextOuterClass.ServiceId request) {
+       try {
+         return delegate.listConnections(request);
+       } catch (UnsupportedOperationException e) {
+          throw new io.grpc.StatusRuntimeException(io.grpc.Status.UNIMPLEMENTED);
+       }
+    }
+    @Override
+    public io.smallrye.mutiny.Uni<context.ContextOuterClass.Connection> getConnection(context.ContextOuterClass.ConnectionId request) {
+       try {
+         return delegate.getConnection(request);
+       } catch (UnsupportedOperationException e) {
+          throw new io.grpc.StatusRuntimeException(io.grpc.Status.UNIMPLEMENTED);
+       }
+    }
+    @Override
+    public io.smallrye.mutiny.Uni<context.ContextOuterClass.ConnectionId> setConnection(context.ContextOuterClass.Connection request) {
+       try {
+         return delegate.setConnection(request);
+       } catch (UnsupportedOperationException e) {
+          throw new io.grpc.StatusRuntimeException(io.grpc.Status.UNIMPLEMENTED);
+       }
+    }
+    @Override
+    public io.smallrye.mutiny.Uni<context.ContextOuterClass.Empty> removeConnection(context.ContextOuterClass.ConnectionId request) {
+       try {
+         return delegate.removeConnection(request);
+       } catch (UnsupportedOperationException e) {
+          throw new io.grpc.StatusRuntimeException(io.grpc.Status.UNIMPLEMENTED);
+       }
+    }
 
     @Override
     public io.smallrye.mutiny.Multi<context.ContextOuterClass.ContextEvent> getContextEvents(context.ContextOuterClass.Empty request) {
@@ -261,4 +301,13 @@ public class ContextServiceBean extends MutinyContextServiceGrpc.ContextServiceI
        }
     }
 
+    @Override
+    public io.smallrye.mutiny.Multi<context.ContextOuterClass.ConnectionEvent> getConnectionEvents(context.ContextOuterClass.Empty request) {
+       try {
+         return delegate.getConnectionEvents(request);
+       } catch (UnsupportedOperationException e) {
+          throw new io.grpc.StatusRuntimeException(io.grpc.Status.UNIMPLEMENTED);
+       }
+    }
+
 }
\ No newline at end of file
diff --git a/src/automation/target/generated-sources/grpc/context/ContextServiceClient.java b/src/automation/target/generated-sources/grpc/context/ContextServiceClient.java
index 6e815b940..a3d74cb7d 100644
--- a/src/automation/target/generated-sources/grpc/context/ContextServiceClient.java
+++ b/src/automation/target/generated-sources/grpc/context/ContextServiceClient.java
@@ -120,6 +120,26 @@ public class ContextServiceClient implements ContextService, MutinyClient<Mutiny
     public io.smallrye.mutiny.Uni<context.ContextOuterClass.Empty> removeService(context.ContextOuterClass.ServiceId request) {
        return stub.removeService(request);
     }
+    @Override
+    public io.smallrye.mutiny.Uni<context.ContextOuterClass.ConnectionIdList> listConnectionIds(context.ContextOuterClass.ServiceId request) {
+       return stub.listConnectionIds(request);
+    }
+    @Override
+    public io.smallrye.mutiny.Uni<context.ContextOuterClass.ConnectionList> listConnections(context.ContextOuterClass.ServiceId request) {
+       return stub.listConnections(request);
+    }
+    @Override
+    public io.smallrye.mutiny.Uni<context.ContextOuterClass.Connection> getConnection(context.ContextOuterClass.ConnectionId request) {
+       return stub.getConnection(request);
+    }
+    @Override
+    public io.smallrye.mutiny.Uni<context.ContextOuterClass.ConnectionId> setConnection(context.ContextOuterClass.Connection request) {
+       return stub.setConnection(request);
+    }
+    @Override
+    public io.smallrye.mutiny.Uni<context.ContextOuterClass.Empty> removeConnection(context.ContextOuterClass.ConnectionId request) {
+       return stub.removeConnection(request);
+    }
 
     @Override
     public io.smallrye.mutiny.Multi<context.ContextOuterClass.ContextEvent> getContextEvents(context.ContextOuterClass.Empty request) {
@@ -146,4 +166,9 @@ public class ContextServiceClient implements ContextService, MutinyClient<Mutiny
        return stub.getServiceEvents(request);
     }
 
+    @Override
+    public io.smallrye.mutiny.Multi<context.ContextOuterClass.ConnectionEvent> getConnectionEvents(context.ContextOuterClass.Empty request) {
+       return stub.getConnectionEvents(request);
+    }
+
 }
\ No newline at end of file
diff --git a/src/automation/target/generated-sources/grpc/context/ContextServiceGrpc.java b/src/automation/target/generated-sources/grpc/context/ContextServiceGrpc.java
index 03f2a66f6..be9f381ff 100644
--- a/src/automation/target/generated-sources/grpc/context/ContextServiceGrpc.java
+++ b/src/automation/target/generated-sources/grpc/context/ContextServiceGrpc.java
@@ -944,6 +944,192 @@ public final class ContextServiceGrpc {
     return getGetServiceEventsMethod;
   }
 
+  private static volatile io.grpc.MethodDescriptor<context.ContextOuterClass.ServiceId,
+      context.ContextOuterClass.ConnectionIdList> getListConnectionIdsMethod;
+
+  @io.grpc.stub.annotations.RpcMethod(
+      fullMethodName = SERVICE_NAME + '/' + "ListConnectionIds",
+      requestType = context.ContextOuterClass.ServiceId.class,
+      responseType = context.ContextOuterClass.ConnectionIdList.class,
+      methodType = io.grpc.MethodDescriptor.MethodType.UNARY)
+  public static io.grpc.MethodDescriptor<context.ContextOuterClass.ServiceId,
+      context.ContextOuterClass.ConnectionIdList> getListConnectionIdsMethod() {
+    io.grpc.MethodDescriptor<context.ContextOuterClass.ServiceId, context.ContextOuterClass.ConnectionIdList> getListConnectionIdsMethod;
+    if ((getListConnectionIdsMethod = ContextServiceGrpc.getListConnectionIdsMethod) == null) {
+      synchronized (ContextServiceGrpc.class) {
+        if ((getListConnectionIdsMethod = ContextServiceGrpc.getListConnectionIdsMethod) == null) {
+          ContextServiceGrpc.getListConnectionIdsMethod = getListConnectionIdsMethod =
+              io.grpc.MethodDescriptor.<context.ContextOuterClass.ServiceId, context.ContextOuterClass.ConnectionIdList>newBuilder()
+              .setType(io.grpc.MethodDescriptor.MethodType.UNARY)
+              .setFullMethodName(generateFullMethodName(SERVICE_NAME, "ListConnectionIds"))
+              .setSampledToLocalTracing(true)
+              .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
+                  context.ContextOuterClass.ServiceId.getDefaultInstance()))
+              .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
+                  context.ContextOuterClass.ConnectionIdList.getDefaultInstance()))
+              .setSchemaDescriptor(new ContextServiceMethodDescriptorSupplier("ListConnectionIds"))
+              .build();
+        }
+      }
+    }
+    return getListConnectionIdsMethod;
+  }
+
+  private static volatile io.grpc.MethodDescriptor<context.ContextOuterClass.ServiceId,
+      context.ContextOuterClass.ConnectionList> getListConnectionsMethod;
+
+  @io.grpc.stub.annotations.RpcMethod(
+      fullMethodName = SERVICE_NAME + '/' + "ListConnections",
+      requestType = context.ContextOuterClass.ServiceId.class,
+      responseType = context.ContextOuterClass.ConnectionList.class,
+      methodType = io.grpc.MethodDescriptor.MethodType.UNARY)
+  public static io.grpc.MethodDescriptor<context.ContextOuterClass.ServiceId,
+      context.ContextOuterClass.ConnectionList> getListConnectionsMethod() {
+    io.grpc.MethodDescriptor<context.ContextOuterClass.ServiceId, context.ContextOuterClass.ConnectionList> getListConnectionsMethod;
+    if ((getListConnectionsMethod = ContextServiceGrpc.getListConnectionsMethod) == null) {
+      synchronized (ContextServiceGrpc.class) {
+        if ((getListConnectionsMethod = ContextServiceGrpc.getListConnectionsMethod) == null) {
+          ContextServiceGrpc.getListConnectionsMethod = getListConnectionsMethod =
+              io.grpc.MethodDescriptor.<context.ContextOuterClass.ServiceId, context.ContextOuterClass.ConnectionList>newBuilder()
+              .setType(io.grpc.MethodDescriptor.MethodType.UNARY)
+              .setFullMethodName(generateFullMethodName(SERVICE_NAME, "ListConnections"))
+              .setSampledToLocalTracing(true)
+              .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
+                  context.ContextOuterClass.ServiceId.getDefaultInstance()))
+              .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
+                  context.ContextOuterClass.ConnectionList.getDefaultInstance()))
+              .setSchemaDescriptor(new ContextServiceMethodDescriptorSupplier("ListConnections"))
+              .build();
+        }
+      }
+    }
+    return getListConnectionsMethod;
+  }
+
+  private static volatile io.grpc.MethodDescriptor<context.ContextOuterClass.ConnectionId,
+      context.ContextOuterClass.Connection> getGetConnectionMethod;
+
+  @io.grpc.stub.annotations.RpcMethod(
+      fullMethodName = SERVICE_NAME + '/' + "GetConnection",
+      requestType = context.ContextOuterClass.ConnectionId.class,
+      responseType = context.ContextOuterClass.Connection.class,
+      methodType = io.grpc.MethodDescriptor.MethodType.UNARY)
+  public static io.grpc.MethodDescriptor<context.ContextOuterClass.ConnectionId,
+      context.ContextOuterClass.Connection> getGetConnectionMethod() {
+    io.grpc.MethodDescriptor<context.ContextOuterClass.ConnectionId, context.ContextOuterClass.Connection> getGetConnectionMethod;
+    if ((getGetConnectionMethod = ContextServiceGrpc.getGetConnectionMethod) == null) {
+      synchronized (ContextServiceGrpc.class) {
+        if ((getGetConnectionMethod = ContextServiceGrpc.getGetConnectionMethod) == null) {
+          ContextServiceGrpc.getGetConnectionMethod = getGetConnectionMethod =
+              io.grpc.MethodDescriptor.<context.ContextOuterClass.ConnectionId, context.ContextOuterClass.Connection>newBuilder()
+              .setType(io.grpc.MethodDescriptor.MethodType.UNARY)
+              .setFullMethodName(generateFullMethodName(SERVICE_NAME, "GetConnection"))
+              .setSampledToLocalTracing(true)
+              .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
+                  context.ContextOuterClass.ConnectionId.getDefaultInstance()))
+              .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
+                  context.ContextOuterClass.Connection.getDefaultInstance()))
+              .setSchemaDescriptor(new ContextServiceMethodDescriptorSupplier("GetConnection"))
+              .build();
+        }
+      }
+    }
+    return getGetConnectionMethod;
+  }
+
+  private static volatile io.grpc.MethodDescriptor<context.ContextOuterClass.Connection,
+      context.ContextOuterClass.ConnectionId> getSetConnectionMethod;
+
+  @io.grpc.stub.annotations.RpcMethod(
+      fullMethodName = SERVICE_NAME + '/' + "SetConnection",
+      requestType = context.ContextOuterClass.Connection.class,
+      responseType = context.ContextOuterClass.ConnectionId.class,
+      methodType = io.grpc.MethodDescriptor.MethodType.UNARY)
+  public static io.grpc.MethodDescriptor<context.ContextOuterClass.Connection,
+      context.ContextOuterClass.ConnectionId> getSetConnectionMethod() {
+    io.grpc.MethodDescriptor<context.ContextOuterClass.Connection, context.ContextOuterClass.ConnectionId> getSetConnectionMethod;
+    if ((getSetConnectionMethod = ContextServiceGrpc.getSetConnectionMethod) == null) {
+      synchronized (ContextServiceGrpc.class) {
+        if ((getSetConnectionMethod = ContextServiceGrpc.getSetConnectionMethod) == null) {
+          ContextServiceGrpc.getSetConnectionMethod = getSetConnectionMethod =
+              io.grpc.MethodDescriptor.<context.ContextOuterClass.Connection, context.ContextOuterClass.ConnectionId>newBuilder()
+              .setType(io.grpc.MethodDescriptor.MethodType.UNARY)
+              .setFullMethodName(generateFullMethodName(SERVICE_NAME, "SetConnection"))
+              .setSampledToLocalTracing(true)
+              .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
+                  context.ContextOuterClass.Connection.getDefaultInstance()))
+              .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
+                  context.ContextOuterClass.ConnectionId.getDefaultInstance()))
+              .setSchemaDescriptor(new ContextServiceMethodDescriptorSupplier("SetConnection"))
+              .build();
+        }
+      }
+    }
+    return getSetConnectionMethod;
+  }
+
+  private static volatile io.grpc.MethodDescriptor<context.ContextOuterClass.ConnectionId,
+      context.ContextOuterClass.Empty> getRemoveConnectionMethod;
+
+  @io.grpc.stub.annotations.RpcMethod(
+      fullMethodName = SERVICE_NAME + '/' + "RemoveConnection",
+      requestType = context.ContextOuterClass.ConnectionId.class,
+      responseType = context.ContextOuterClass.Empty.class,
+      methodType = io.grpc.MethodDescriptor.MethodType.UNARY)
+  public static io.grpc.MethodDescriptor<context.ContextOuterClass.ConnectionId,
+      context.ContextOuterClass.Empty> getRemoveConnectionMethod() {
+    io.grpc.MethodDescriptor<context.ContextOuterClass.ConnectionId, context.ContextOuterClass.Empty> getRemoveConnectionMethod;
+    if ((getRemoveConnectionMethod = ContextServiceGrpc.getRemoveConnectionMethod) == null) {
+      synchronized (ContextServiceGrpc.class) {
+        if ((getRemoveConnectionMethod = ContextServiceGrpc.getRemoveConnectionMethod) == null) {
+          ContextServiceGrpc.getRemoveConnectionMethod = getRemoveConnectionMethod =
+              io.grpc.MethodDescriptor.<context.ContextOuterClass.ConnectionId, context.ContextOuterClass.Empty>newBuilder()
+              .setType(io.grpc.MethodDescriptor.MethodType.UNARY)
+              .setFullMethodName(generateFullMethodName(SERVICE_NAME, "RemoveConnection"))
+              .setSampledToLocalTracing(true)
+              .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
+                  context.ContextOuterClass.ConnectionId.getDefaultInstance()))
+              .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
+                  context.ContextOuterClass.Empty.getDefaultInstance()))
+              .setSchemaDescriptor(new ContextServiceMethodDescriptorSupplier("RemoveConnection"))
+              .build();
+        }
+      }
+    }
+    return getRemoveConnectionMethod;
+  }
+
+  private static volatile io.grpc.MethodDescriptor<context.ContextOuterClass.Empty,
+      context.ContextOuterClass.ConnectionEvent> getGetConnectionEventsMethod;
+
+  @io.grpc.stub.annotations.RpcMethod(
+      fullMethodName = SERVICE_NAME + '/' + "GetConnectionEvents",
+      requestType = context.ContextOuterClass.Empty.class,
+      responseType = context.ContextOuterClass.ConnectionEvent.class,
+      methodType = io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING)
+  public static io.grpc.MethodDescriptor<context.ContextOuterClass.Empty,
+      context.ContextOuterClass.ConnectionEvent> getGetConnectionEventsMethod() {
+    io.grpc.MethodDescriptor<context.ContextOuterClass.Empty, context.ContextOuterClass.ConnectionEvent> getGetConnectionEventsMethod;
+    if ((getGetConnectionEventsMethod = ContextServiceGrpc.getGetConnectionEventsMethod) == null) {
+      synchronized (ContextServiceGrpc.class) {
+        if ((getGetConnectionEventsMethod = ContextServiceGrpc.getGetConnectionEventsMethod) == null) {
+          ContextServiceGrpc.getGetConnectionEventsMethod = getGetConnectionEventsMethod =
+              io.grpc.MethodDescriptor.<context.ContextOuterClass.Empty, context.ContextOuterClass.ConnectionEvent>newBuilder()
+              .setType(io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING)
+              .setFullMethodName(generateFullMethodName(SERVICE_NAME, "GetConnectionEvents"))
+              .setSampledToLocalTracing(true)
+              .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
+                  context.ContextOuterClass.Empty.getDefaultInstance()))
+              .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
+                  context.ContextOuterClass.ConnectionEvent.getDefaultInstance()))
+              .setSchemaDescriptor(new ContextServiceMethodDescriptorSupplier("GetConnectionEvents"))
+              .build();
+        }
+      }
+    }
+    return getGetConnectionEventsMethod;
+  }
+
   /**
    * Creates a new async stub that supports all call types for the service
    */
@@ -1202,6 +1388,48 @@ public final class ContextServiceGrpc {
       io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getGetServiceEventsMethod(), responseObserver);
     }
 
+    /**
+     */
+    public void listConnectionIds(context.ContextOuterClass.ServiceId request,
+        io.grpc.stub.StreamObserver<context.ContextOuterClass.ConnectionIdList> responseObserver) {
+      io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getListConnectionIdsMethod(), responseObserver);
+    }
+
+    /**
+     */
+    public void listConnections(context.ContextOuterClass.ServiceId request,
+        io.grpc.stub.StreamObserver<context.ContextOuterClass.ConnectionList> responseObserver) {
+      io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getListConnectionsMethod(), responseObserver);
+    }
+
+    /**
+     */
+    public void getConnection(context.ContextOuterClass.ConnectionId request,
+        io.grpc.stub.StreamObserver<context.ContextOuterClass.Connection> responseObserver) {
+      io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getGetConnectionMethod(), responseObserver);
+    }
+
+    /**
+     */
+    public void setConnection(context.ContextOuterClass.Connection request,
+        io.grpc.stub.StreamObserver<context.ContextOuterClass.ConnectionId> responseObserver) {
+      io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getSetConnectionMethod(), responseObserver);
+    }
+
+    /**
+     */
+    public void removeConnection(context.ContextOuterClass.ConnectionId request,
+        io.grpc.stub.StreamObserver<context.ContextOuterClass.Empty> responseObserver) {
+      io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getRemoveConnectionMethod(), responseObserver);
+    }
+
+    /**
+     */
+    public void getConnectionEvents(context.ContextOuterClass.Empty request,
+        io.grpc.stub.StreamObserver<context.ContextOuterClass.ConnectionEvent> responseObserver) {
+      io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getGetConnectionEventsMethod(), responseObserver);
+    }
+
     @java.lang.Override public final io.grpc.ServerServiceDefinition bindService() {
       return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor())
           .addMethod(
@@ -1414,6 +1642,48 @@ public final class ContextServiceGrpc {
                 context.ContextOuterClass.Empty,
                 context.ContextOuterClass.ServiceEvent>(
                   this, METHODID_GET_SERVICE_EVENTS)))
+          .addMethod(
+            getListConnectionIdsMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+              new MethodHandlers<
+                context.ContextOuterClass.ServiceId,
+                context.ContextOuterClass.ConnectionIdList>(
+                  this, METHODID_LIST_CONNECTION_IDS)))
+          .addMethod(
+            getListConnectionsMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+              new MethodHandlers<
+                context.ContextOuterClass.ServiceId,
+                context.ContextOuterClass.ConnectionList>(
+                  this, METHODID_LIST_CONNECTIONS)))
+          .addMethod(
+            getGetConnectionMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+              new MethodHandlers<
+                context.ContextOuterClass.ConnectionId,
+                context.ContextOuterClass.Connection>(
+                  this, METHODID_GET_CONNECTION)))
+          .addMethod(
+            getSetConnectionMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+              new MethodHandlers<
+                context.ContextOuterClass.Connection,
+                context.ContextOuterClass.ConnectionId>(
+                  this, METHODID_SET_CONNECTION)))
+          .addMethod(
+            getRemoveConnectionMethod(),
+            io.grpc.stub.ServerCalls.asyncUnaryCall(
+              new MethodHandlers<
+                context.ContextOuterClass.ConnectionId,
+                context.ContextOuterClass.Empty>(
+                  this, METHODID_REMOVE_CONNECTION)))
+          .addMethod(
+            getGetConnectionEventsMethod(),
+            io.grpc.stub.ServerCalls.asyncServerStreamingCall(
+              new MethodHandlers<
+                context.ContextOuterClass.Empty,
+                context.ContextOuterClass.ConnectionEvent>(
+                  this, METHODID_GET_CONNECTION_EVENTS)))
           .build();
     }
   }
@@ -1671,6 +1941,54 @@ public final class ContextServiceGrpc {
       io.grpc.stub.ClientCalls.asyncServerStreamingCall(
           getChannel().newCall(getGetServiceEventsMethod(), getCallOptions()), request, responseObserver);
     }
+
+    /**
+     */
+    public void listConnectionIds(context.ContextOuterClass.ServiceId request,
+        io.grpc.stub.StreamObserver<context.ContextOuterClass.ConnectionIdList> responseObserver) {
+      io.grpc.stub.ClientCalls.asyncUnaryCall(
+          getChannel().newCall(getListConnectionIdsMethod(), getCallOptions()), request, responseObserver);
+    }
+
+    /**
+     */
+    public void listConnections(context.ContextOuterClass.ServiceId request,
+        io.grpc.stub.StreamObserver<context.ContextOuterClass.ConnectionList> responseObserver) {
+      io.grpc.stub.ClientCalls.asyncUnaryCall(
+          getChannel().newCall(getListConnectionsMethod(), getCallOptions()), request, responseObserver);
+    }
+
+    /**
+     */
+    public void getConnection(context.ContextOuterClass.ConnectionId request,
+        io.grpc.stub.StreamObserver<context.ContextOuterClass.Connection> responseObserver) {
+      io.grpc.stub.ClientCalls.asyncUnaryCall(
+          getChannel().newCall(getGetConnectionMethod(), getCallOptions()), request, responseObserver);
+    }
+
+    /**
+     */
+    public void setConnection(context.ContextOuterClass.Connection request,
+        io.grpc.stub.StreamObserver<context.ContextOuterClass.ConnectionId> responseObserver) {
+      io.grpc.stub.ClientCalls.asyncUnaryCall(
+          getChannel().newCall(getSetConnectionMethod(), getCallOptions()), request, responseObserver);
+    }
+
+    /**
+     */
+    public void removeConnection(context.ContextOuterClass.ConnectionId request,
+        io.grpc.stub.StreamObserver<context.ContextOuterClass.Empty> responseObserver) {
+      io.grpc.stub.ClientCalls.asyncUnaryCall(
+          getChannel().newCall(getRemoveConnectionMethod(), getCallOptions()), request, responseObserver);
+    }
+
+    /**
+     */
+    public void getConnectionEvents(context.ContextOuterClass.Empty request,
+        io.grpc.stub.StreamObserver<context.ContextOuterClass.ConnectionEvent> responseObserver) {
+      io.grpc.stub.ClientCalls.asyncServerStreamingCall(
+          getChannel().newCall(getGetConnectionEventsMethod(), getCallOptions()), request, responseObserver);
+    }
   }
 
   /**
@@ -1901,6 +2219,49 @@ public final class ContextServiceGrpc {
       return io.grpc.stub.ClientCalls.blockingServerStreamingCall(
           getChannel(), getGetServiceEventsMethod(), getCallOptions(), request);
     }
+
+    /**
+     */
+    public context.ContextOuterClass.ConnectionIdList listConnectionIds(context.ContextOuterClass.ServiceId request) {
+      return io.grpc.stub.ClientCalls.blockingUnaryCall(
+          getChannel(), getListConnectionIdsMethod(), getCallOptions(), request);
+    }
+
+    /**
+     */
+    public context.ContextOuterClass.ConnectionList listConnections(context.ContextOuterClass.ServiceId request) {
+      return io.grpc.stub.ClientCalls.blockingUnaryCall(
+          getChannel(), getListConnectionsMethod(), getCallOptions(), request);
+    }
+
+    /**
+     */
+    public context.ContextOuterClass.Connection getConnection(context.ContextOuterClass.ConnectionId request) {
+      return io.grpc.stub.ClientCalls.blockingUnaryCall(
+          getChannel(), getGetConnectionMethod(), getCallOptions(), request);
+    }
+
+    /**
+     */
+    public context.ContextOuterClass.ConnectionId setConnection(context.ContextOuterClass.Connection request) {
+      return io.grpc.stub.ClientCalls.blockingUnaryCall(
+          getChannel(), getSetConnectionMethod(), getCallOptions(), request);
+    }
+
+    /**
+     */
+    public context.ContextOuterClass.Empty removeConnection(context.ContextOuterClass.ConnectionId request) {
+      return io.grpc.stub.ClientCalls.blockingUnaryCall(
+          getChannel(), getRemoveConnectionMethod(), getCallOptions(), request);
+    }
+
+    /**
+     */
+    public java.util.Iterator<context.ContextOuterClass.ConnectionEvent> getConnectionEvents(
+        context.ContextOuterClass.Empty request) {
+      return io.grpc.stub.ClientCalls.blockingServerStreamingCall(
+          getChannel(), getGetConnectionEventsMethod(), getCallOptions(), request);
+    }
   }
 
   /**
@@ -2116,6 +2477,46 @@ public final class ContextServiceGrpc {
       return io.grpc.stub.ClientCalls.futureUnaryCall(
           getChannel().newCall(getRemoveServiceMethod(), getCallOptions()), request);
     }
+
+    /**
+     */
+    public com.google.common.util.concurrent.ListenableFuture<context.ContextOuterClass.ConnectionIdList> listConnectionIds(
+        context.ContextOuterClass.ServiceId request) {
+      return io.grpc.stub.ClientCalls.futureUnaryCall(
+          getChannel().newCall(getListConnectionIdsMethod(), getCallOptions()), request);
+    }
+
+    /**
+     */
+    public com.google.common.util.concurrent.ListenableFuture<context.ContextOuterClass.ConnectionList> listConnections(
+        context.ContextOuterClass.ServiceId request) {
+      return io.grpc.stub.ClientCalls.futureUnaryCall(
+          getChannel().newCall(getListConnectionsMethod(), getCallOptions()), request);
+    }
+
+    /**
+     */
+    public com.google.common.util.concurrent.ListenableFuture<context.ContextOuterClass.Connection> getConnection(
+        context.ContextOuterClass.ConnectionId request) {
+      return io.grpc.stub.ClientCalls.futureUnaryCall(
+          getChannel().newCall(getGetConnectionMethod(), getCallOptions()), request);
+    }
+
+    /**
+     */
+    public com.google.common.util.concurrent.ListenableFuture<context.ContextOuterClass.ConnectionId> setConnection(
+        context.ContextOuterClass.Connection request) {
+      return io.grpc.stub.ClientCalls.futureUnaryCall(
+          getChannel().newCall(getSetConnectionMethod(), getCallOptions()), request);
+    }
+
+    /**
+     */
+    public com.google.common.util.concurrent.ListenableFuture<context.ContextOuterClass.Empty> removeConnection(
+        context.ContextOuterClass.ConnectionId request) {
+      return io.grpc.stub.ClientCalls.futureUnaryCall(
+          getChannel().newCall(getRemoveConnectionMethod(), getCallOptions()), request);
+    }
   }
 
   private static final int METHODID_LIST_CONTEXT_IDS = 0;
@@ -2148,6 +2549,12 @@ public final class ContextServiceGrpc {
   private static final int METHODID_SET_SERVICE = 27;
   private static final int METHODID_REMOVE_SERVICE = 28;
   private static final int METHODID_GET_SERVICE_EVENTS = 29;
+  private static final int METHODID_LIST_CONNECTION_IDS = 30;
+  private static final int METHODID_LIST_CONNECTIONS = 31;
+  private static final int METHODID_GET_CONNECTION = 32;
+  private static final int METHODID_SET_CONNECTION = 33;
+  private static final int METHODID_REMOVE_CONNECTION = 34;
+  private static final int METHODID_GET_CONNECTION_EVENTS = 35;
 
   private static final class MethodHandlers<Req, Resp> implements
       io.grpc.stub.ServerCalls.UnaryMethod<Req, Resp>,
@@ -2286,6 +2693,30 @@ public final class ContextServiceGrpc {
           serviceImpl.getServiceEvents((context.ContextOuterClass.Empty) request,
               (io.grpc.stub.StreamObserver<context.ContextOuterClass.ServiceEvent>) responseObserver);
           break;
+        case METHODID_LIST_CONNECTION_IDS:
+          serviceImpl.listConnectionIds((context.ContextOuterClass.ServiceId) request,
+              (io.grpc.stub.StreamObserver<context.ContextOuterClass.ConnectionIdList>) responseObserver);
+          break;
+        case METHODID_LIST_CONNECTIONS:
+          serviceImpl.listConnections((context.ContextOuterClass.ServiceId) request,
+              (io.grpc.stub.StreamObserver<context.ContextOuterClass.ConnectionList>) responseObserver);
+          break;
+        case METHODID_GET_CONNECTION:
+          serviceImpl.getConnection((context.ContextOuterClass.ConnectionId) request,
+              (io.grpc.stub.StreamObserver<context.ContextOuterClass.Connection>) responseObserver);
+          break;
+        case METHODID_SET_CONNECTION:
+          serviceImpl.setConnection((context.ContextOuterClass.Connection) request,
+              (io.grpc.stub.StreamObserver<context.ContextOuterClass.ConnectionId>) responseObserver);
+          break;
+        case METHODID_REMOVE_CONNECTION:
+          serviceImpl.removeConnection((context.ContextOuterClass.ConnectionId) request,
+              (io.grpc.stub.StreamObserver<context.ContextOuterClass.Empty>) responseObserver);
+          break;
+        case METHODID_GET_CONNECTION_EVENTS:
+          serviceImpl.getConnectionEvents((context.ContextOuterClass.Empty) request,
+              (io.grpc.stub.StreamObserver<context.ContextOuterClass.ConnectionEvent>) responseObserver);
+          break;
         default:
           throw new AssertionError();
       }
@@ -2377,6 +2808,12 @@ public final class ContextServiceGrpc {
               .addMethod(getSetServiceMethod())
               .addMethod(getRemoveServiceMethod())
               .addMethod(getGetServiceEventsMethod())
+              .addMethod(getListConnectionIdsMethod())
+              .addMethod(getListConnectionsMethod())
+              .addMethod(getGetConnectionMethod())
+              .addMethod(getSetConnectionMethod())
+              .addMethod(getRemoveConnectionMethod())
+              .addMethod(getGetConnectionEventsMethod())
               .build();
         }
       }
diff --git a/src/automation/target/generated-sources/grpc/context/MutinyContextServiceGrpc.java b/src/automation/target/generated-sources/grpc/context/MutinyContextServiceGrpc.java
index 7642fdfd5..85abba20a 100644
--- a/src/automation/target/generated-sources/grpc/context/MutinyContextServiceGrpc.java
+++ b/src/automation/target/generated-sources/grpc/context/MutinyContextServiceGrpc.java
@@ -161,6 +161,31 @@ public final class MutinyContextServiceGrpc implements io.quarkus.grpc.runtime.M
         }
 
         
+        public io.smallrye.mutiny.Uni<context.ContextOuterClass.ConnectionIdList> listConnectionIds(context.ContextOuterClass.ServiceId request) {
+            return io.quarkus.grpc.runtime.ClientCalls.oneToOne(request, delegateStub::listConnectionIds);
+        }
+
+        
+        public io.smallrye.mutiny.Uni<context.ContextOuterClass.ConnectionList> listConnections(context.ContextOuterClass.ServiceId request) {
+            return io.quarkus.grpc.runtime.ClientCalls.oneToOne(request, delegateStub::listConnections);
+        }
+
+        
+        public io.smallrye.mutiny.Uni<context.ContextOuterClass.Connection> getConnection(context.ContextOuterClass.ConnectionId request) {
+            return io.quarkus.grpc.runtime.ClientCalls.oneToOne(request, delegateStub::getConnection);
+        }
+
+        
+        public io.smallrye.mutiny.Uni<context.ContextOuterClass.ConnectionId> setConnection(context.ContextOuterClass.Connection request) {
+            return io.quarkus.grpc.runtime.ClientCalls.oneToOne(request, delegateStub::setConnection);
+        }
+
+        
+        public io.smallrye.mutiny.Uni<context.ContextOuterClass.Empty> removeConnection(context.ContextOuterClass.ConnectionId request) {
+            return io.quarkus.grpc.runtime.ClientCalls.oneToOne(request, delegateStub::removeConnection);
+        }
+
+        
         public io.smallrye.mutiny.Multi<context.ContextOuterClass.ContextEvent> getContextEvents(context.ContextOuterClass.Empty request) {
             return io.quarkus.grpc.runtime.ClientCalls.oneToMany(request, delegateStub::getContextEvents);
         }
@@ -185,6 +210,11 @@ public final class MutinyContextServiceGrpc implements io.quarkus.grpc.runtime.M
             return io.quarkus.grpc.runtime.ClientCalls.oneToMany(request, delegateStub::getServiceEvents);
         }
 
+        
+        public io.smallrye.mutiny.Multi<context.ContextOuterClass.ConnectionEvent> getConnectionEvents(context.ContextOuterClass.Empty request) {
+            return io.quarkus.grpc.runtime.ClientCalls.oneToMany(request, delegateStub::getConnectionEvents);
+        }
+
     }
 
     
@@ -328,6 +358,31 @@ public final class MutinyContextServiceGrpc implements io.quarkus.grpc.runtime.M
         }
 
         
+        public io.smallrye.mutiny.Uni<context.ContextOuterClass.ConnectionIdList> listConnectionIds(context.ContextOuterClass.ServiceId request) {
+            throw new io.grpc.StatusRuntimeException(io.grpc.Status.UNIMPLEMENTED);
+        }
+
+        
+        public io.smallrye.mutiny.Uni<context.ContextOuterClass.ConnectionList> listConnections(context.ContextOuterClass.ServiceId request) {
+            throw new io.grpc.StatusRuntimeException(io.grpc.Status.UNIMPLEMENTED);
+        }
+
+        
+        public io.smallrye.mutiny.Uni<context.ContextOuterClass.Connection> getConnection(context.ContextOuterClass.ConnectionId request) {
+            throw new io.grpc.StatusRuntimeException(io.grpc.Status.UNIMPLEMENTED);
+        }
+
+        
+        public io.smallrye.mutiny.Uni<context.ContextOuterClass.ConnectionId> setConnection(context.ContextOuterClass.Connection request) {
+            throw new io.grpc.StatusRuntimeException(io.grpc.Status.UNIMPLEMENTED);
+        }
+
+        
+        public io.smallrye.mutiny.Uni<context.ContextOuterClass.Empty> removeConnection(context.ContextOuterClass.ConnectionId request) {
+            throw new io.grpc.StatusRuntimeException(io.grpc.Status.UNIMPLEMENTED);
+        }
+
+        
         public io.smallrye.mutiny.Multi<context.ContextOuterClass.ContextEvent> getContextEvents(context.ContextOuterClass.Empty request) {
             throw new io.grpc.StatusRuntimeException(io.grpc.Status.UNIMPLEMENTED);
         }
@@ -352,6 +407,11 @@ public final class MutinyContextServiceGrpc implements io.quarkus.grpc.runtime.M
             throw new io.grpc.StatusRuntimeException(io.grpc.Status.UNIMPLEMENTED);
         }
 
+        
+        public io.smallrye.mutiny.Multi<context.ContextOuterClass.ConnectionEvent> getConnectionEvents(context.ContextOuterClass.Empty request) {
+            throw new io.grpc.StatusRuntimeException(io.grpc.Status.UNIMPLEMENTED);
+        }
+
         @java.lang.Override public final io.grpc.ServerServiceDefinition bindService() {
             return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor())
                     .addMethod(
@@ -564,6 +624,48 @@ public final class MutinyContextServiceGrpc implements io.quarkus.grpc.runtime.M
                                             context.ContextOuterClass.Empty,
                                             context.ContextOuterClass.ServiceEvent>(
                                             this, METHODID_GET_SERVICE_EVENTS, compression)))
+                    .addMethod(
+                            context.ContextServiceGrpc.getListConnectionIdsMethod(),
+                            asyncUnaryCall(
+                                    new MethodHandlers<
+                                            context.ContextOuterClass.ServiceId,
+                                            context.ContextOuterClass.ConnectionIdList>(
+                                            this, METHODID_LIST_CONNECTION_IDS, compression)))
+                    .addMethod(
+                            context.ContextServiceGrpc.getListConnectionsMethod(),
+                            asyncUnaryCall(
+                                    new MethodHandlers<
+                                            context.ContextOuterClass.ServiceId,
+                                            context.ContextOuterClass.ConnectionList>(
+                                            this, METHODID_LIST_CONNECTIONS, compression)))
+                    .addMethod(
+                            context.ContextServiceGrpc.getGetConnectionMethod(),
+                            asyncUnaryCall(
+                                    new MethodHandlers<
+                                            context.ContextOuterClass.ConnectionId,
+                                            context.ContextOuterClass.Connection>(
+                                            this, METHODID_GET_CONNECTION, compression)))
+                    .addMethod(
+                            context.ContextServiceGrpc.getSetConnectionMethod(),
+                            asyncUnaryCall(
+                                    new MethodHandlers<
+                                            context.ContextOuterClass.Connection,
+                                            context.ContextOuterClass.ConnectionId>(
+                                            this, METHODID_SET_CONNECTION, compression)))
+                    .addMethod(
+                            context.ContextServiceGrpc.getRemoveConnectionMethod(),
+                            asyncUnaryCall(
+                                    new MethodHandlers<
+                                            context.ContextOuterClass.ConnectionId,
+                                            context.ContextOuterClass.Empty>(
+                                            this, METHODID_REMOVE_CONNECTION, compression)))
+                    .addMethod(
+                            context.ContextServiceGrpc.getGetConnectionEventsMethod(),
+                            asyncServerStreamingCall(
+                                    new MethodHandlers<
+                                            context.ContextOuterClass.Empty,
+                                            context.ContextOuterClass.ConnectionEvent>(
+                                            this, METHODID_GET_CONNECTION_EVENTS, compression)))
                     .build();
         }
     }
@@ -598,6 +700,12 @@ public final class MutinyContextServiceGrpc implements io.quarkus.grpc.runtime.M
     private static final int METHODID_SET_SERVICE = 27;
     private static final int METHODID_REMOVE_SERVICE = 28;
     private static final int METHODID_GET_SERVICE_EVENTS = 29;
+    private static final int METHODID_LIST_CONNECTION_IDS = 30;
+    private static final int METHODID_LIST_CONNECTIONS = 31;
+    private static final int METHODID_GET_CONNECTION = 32;
+    private static final int METHODID_SET_CONNECTION = 33;
+    private static final int METHODID_REMOVE_CONNECTION = 34;
+    private static final int METHODID_GET_CONNECTION_EVENTS = 35;
 
     private static final class MethodHandlers<Req, Resp> implements
             io.grpc.stub.ServerCalls.UnaryMethod<Req, Resp>,
@@ -798,6 +906,42 @@ public final class MutinyContextServiceGrpc implements io.quarkus.grpc.runtime.M
                             compression,
                             serviceImpl::getServiceEvents);
                     break;
+                case METHODID_LIST_CONNECTION_IDS:
+                    io.quarkus.grpc.runtime.ServerCalls.oneToOne((context.ContextOuterClass.ServiceId) request,
+                            (io.grpc.stub.StreamObserver<context.ContextOuterClass.ConnectionIdList>) responseObserver,
+                            compression,
+                            serviceImpl::listConnectionIds);
+                    break;
+                case METHODID_LIST_CONNECTIONS:
+                    io.quarkus.grpc.runtime.ServerCalls.oneToOne((context.ContextOuterClass.ServiceId) request,
+                            (io.grpc.stub.StreamObserver<context.ContextOuterClass.ConnectionList>) responseObserver,
+                            compression,
+                            serviceImpl::listConnections);
+                    break;
+                case METHODID_GET_CONNECTION:
+                    io.quarkus.grpc.runtime.ServerCalls.oneToOne((context.ContextOuterClass.ConnectionId) request,
+                            (io.grpc.stub.StreamObserver<context.ContextOuterClass.Connection>) responseObserver,
+                            compression,
+                            serviceImpl::getConnection);
+                    break;
+                case METHODID_SET_CONNECTION:
+                    io.quarkus.grpc.runtime.ServerCalls.oneToOne((context.ContextOuterClass.Connection) request,
+                            (io.grpc.stub.StreamObserver<context.ContextOuterClass.ConnectionId>) responseObserver,
+                            compression,
+                            serviceImpl::setConnection);
+                    break;
+                case METHODID_REMOVE_CONNECTION:
+                    io.quarkus.grpc.runtime.ServerCalls.oneToOne((context.ContextOuterClass.ConnectionId) request,
+                            (io.grpc.stub.StreamObserver<context.ContextOuterClass.Empty>) responseObserver,
+                            compression,
+                            serviceImpl::removeConnection);
+                    break;
+                case METHODID_GET_CONNECTION_EVENTS:
+                    io.quarkus.grpc.runtime.ServerCalls.oneToMany((context.ContextOuterClass.Empty) request,
+                            (io.grpc.stub.StreamObserver<context.ContextOuterClass.ConnectionEvent>) responseObserver,
+                            compression,
+                            serviceImpl::getConnectionEvents);
+                    break;
                 default:
                     throw new java.lang.AssertionError();
             }
diff --git a/src/automation/target/kubernetes/kubernetes.yml b/src/automation/target/kubernetes/kubernetes.yml
index 47b852adf..e01e23a3f 100644
--- a/src/automation/target/kubernetes/kubernetes.yml
+++ b/src/automation/target/kubernetes/kubernetes.yml
@@ -3,51 +3,51 @@ apiVersion: v1
 kind: Service
 metadata:
   annotations:
-    app.quarkus.io/commit-id: cb66db4bc415be2e94c17f4152e9805301b202b5
-    app.quarkus.io/build-timestamp: 2022-01-05 - 10:42:14 +0000
+    app.quarkus.io/commit-id: 1d9391e04561028e64164362c608dfd97a869928
+    app.quarkus.io/build-timestamp: 2022-02-10 - 12:24:30 +0000
   labels:
     app.kubernetes.io/name: automationservice
-    app.kubernetes.io/version: 0.0.1
+    app.kubernetes.io/version: 0.1.0
     app: automationservice
   name: automationservice
 spec:
   ports:
-    - name: grpc-server
-      port: 9999
-      targetPort: 9999
     - name: http
       port: 8080
       targetPort: 8080
+    - name: grpc-server
+      port: 9999
+      targetPort: 9999
   selector:
     app.kubernetes.io/name: automationservice
-    app.kubernetes.io/version: 0.0.1
-  type: NodePort
+    app.kubernetes.io/version: 0.1.0
+  type: ClusterIP
 ---
 apiVersion: apps/v1
 kind: Deployment
 metadata:
   annotations:
-    app.quarkus.io/commit-id: cb66db4bc415be2e94c17f4152e9805301b202b5
-    app.quarkus.io/build-timestamp: 2022-01-05 - 10:42:14 +0000
+    app.quarkus.io/commit-id: 1d9391e04561028e64164362c608dfd97a869928
+    app.quarkus.io/build-timestamp: 2022-02-10 - 12:24:30 +0000
   labels:
     app: automationservice
-    app.kubernetes.io/version: 0.0.1
+    app.kubernetes.io/version: 0.1.0
     app.kubernetes.io/name: automationservice
   name: automationservice
 spec:
   replicas: 1
   selector:
     matchLabels:
-      app.kubernetes.io/version: 0.0.1
+      app.kubernetes.io/version: 0.1.0
       app.kubernetes.io/name: automationservice
   template:
     metadata:
       annotations:
-        app.quarkus.io/commit-id: cb66db4bc415be2e94c17f4152e9805301b202b5
-        app.quarkus.io/build-timestamp: 2022-01-05 - 10:42:14 +0000
+        app.quarkus.io/commit-id: 1d9391e04561028e64164362c608dfd97a869928
+        app.quarkus.io/build-timestamp: 2022-02-10 - 12:24:30 +0000
       labels:
         app: automationservice
-        app.kubernetes.io/version: 0.0.1
+        app.kubernetes.io/version: 0.1.0
         app.kubernetes.io/name: automationservice
     spec:
       containers:
@@ -57,10 +57,10 @@ spec:
                 fieldRef:
                   fieldPath: metadata.namespace
             - name: DEVICE_SERVICE_HOST
-              value: DeviceService
+              value: deviceservice
             - name: CONTEXT_SERVICE_HOST
-              value: ContextService
-          image: registry.gitlab.com/teraflow-h2020/controller/automation:0.0.1
+              value: contextservice
+          image: registry.gitlab.com/teraflow-h2020/controller/automation:0.1.0
           imagePullPolicy: Always
           livenessProbe:
             failureThreshold: 3
@@ -68,25 +68,25 @@ spec:
               path: /q/health/live
               port: 8080
               scheme: HTTP
-            initialDelaySeconds: 5
-            periodSeconds: 45
+            initialDelaySeconds: 2
+            periodSeconds: 10
             successThreshold: 1
             timeoutSeconds: 10
           name: automationservice
           ports:
-            - containerPort: 9999
-              name: grpc-server
-              protocol: TCP
             - containerPort: 8080
               name: http
               protocol: TCP
+            - containerPort: 9999
+              name: grpc-server
+              protocol: TCP
           readinessProbe:
             failureThreshold: 3
             httpGet:
               path: /q/health/ready
               port: 8080
               scheme: HTTP
-            initialDelaySeconds: 5
-            periodSeconds: 45
+            initialDelaySeconds: 2
+            periodSeconds: 10
             successThreshold: 1
             timeoutSeconds: 10
diff --git a/src/automation/util/set_version.sh b/src/automation/util/set_version.sh
new file mode 100755
index 000000000..bb99ccb54
--- /dev/null
+++ b/src/automation/util/set_version.sh
@@ -0,0 +1,17 @@
+#!/usr/bin/env bash
+set -eu
+
+if (( $# != 1 )); then
+  echo "Usage: set_version.sh <version>" >&2
+  exit 1
+fi
+
+version="$1"
+
+if [ "$(git status --untracked-files=no --porcelain)" ]; then
+    printf "Uncommitted changes in tracked files.\nPlease commit first and then run the script!\n"
+    exit 0;
+fi
+
+./mvnw versions:set versions:commit -DnewVersion="${version}"
+git commit -am "release(automation): ${version}"
diff --git a/src/common/DeviceTypes.py b/src/common/DeviceTypes.py
new file mode 100644
index 000000000..28b1f8c7d
--- /dev/null
+++ b/src/common/DeviceTypes.py
@@ -0,0 +1,11 @@
+from enum import Enum
+
+class DeviceTypeEnum(Enum):
+    EMULATED_OPTICAL_LINE_SYSTEM = 'emu-optical-line-system'
+    EMULATED_PACKET_ROUTER       = 'emu-packet-router'
+    OPTICAL_ROADM                = 'optical-roadm'
+    OPTICAL_TRANDPONDER          = 'optical-trandponder'
+    OPTICAL_LINE_SYSTEM          = 'optical-line-system'
+    PACKET_ROUTER                = 'packet-router'
+    PACKET_SWITCH                = 'packet-switch'
+    P4_SWITCH                    = 'p4-switch'
diff --git a/src/common/Settings.py b/src/common/Settings.py
index 73508da50..61a402ec1 100644
--- a/src/common/Settings.py
+++ b/src/common/Settings.py
@@ -1,4 +1,20 @@
-import os
+import logging, os, time
+from typing import List
+
+LOGGER = logging.getLogger(__name__)
+
+DEFAULT_RESTART_DELAY = 5.0 # seconds
+
+def wait_for_environment_variables(
+    required_environment_variables : List[str] = [], wait_delay_seconds : float = DEFAULT_RESTART_DELAY
+):
+    if 'KUBERNETES_PORT' not in os.environ: return # We're not running in Kubernetes, nothing to wait for
+    missing_variables = set(required_environment_variables).difference(set(os.environ.keys()))
+    if len(missing_variables) == 0: return # We have all environment variables defined
+    msg = 'Variables({:s}) are missing in Environment({:s}), restarting in {:f} seconds...'
+    LOGGER.error(msg.format(str(missing_variables), str(os.environ), wait_delay_seconds))
+    time.sleep(wait_delay_seconds)
+    raise Exception('Restarting...')
 
 def get_setting(name, **kwargs):
     value = os.environ.get(name)
diff --git a/src/common/orm/model/Model.py b/src/common/orm/model/Model.py
index cf66a859f..558271ba5 100644
--- a/src/common/orm/model/Model.py
+++ b/src/common/orm/model/Model.py
@@ -106,11 +106,13 @@ class Model(metaclass=MetaModel):
     @property
     def instance_key(self) -> str: return self._instance_key
 
-    def lock(self, extra_keys : List[List[str]] = []):
-        lock_keys = Model.get_backend_key_locks(
-            [self._instance_key, self._instances_key, self._references_key] + extra_keys)
-        acquired,self._owner_key = self._backend.lock(lock_keys, owner_key=self._owner_key)
-        if acquired: return
+    def lock(self, extra_keys : List[List[str]] = [], blocking : bool = True):
+        while True:
+            lock_keys = Model.get_backend_key_locks(
+                [self._instance_key, self._instances_key, self._references_key] + extra_keys)
+            acquired,self._owner_key = self._backend.lock(lock_keys, owner_key=self._owner_key)
+            if acquired: return
+            if not blocking: break
         raise MutexException('Unable to lock keys {:s} using owner_key {:s}'.format(
             str(lock_keys), str(self._owner_key)))
 
diff --git a/src/common/rpc_method_wrapper/Decorator.py b/src/common/rpc_method_wrapper/Decorator.py
index cfbc76ff8..3cacb0e2a 100644
--- a/src/common/rpc_method_wrapper/Decorator.py
+++ b/src/common/rpc_method_wrapper/Decorator.py
@@ -54,8 +54,10 @@ def safe_and_metered_rpc_method(metrics : Dict[str, MetricWrapperBase], logger :
                 COUNTER_COMPLETED.inc()
                 return reply
             except ServiceException as e:   # pragma: no cover (ServiceException not thrown)
-                logger.exception('{:s} exception'.format(function_name))
-                COUNTER_FAILED.inc()
+                if e.code not in [grpc.StatusCode.NOT_FOUND, grpc.StatusCode.ALREADY_EXISTS]:
+                    # Assume not found or already exists is just a condition, not an error
+                    logger.exception('{:s} exception'.format(function_name))
+                    COUNTER_FAILED.inc()
                 grpc_context.abort(e.code, e.details)
             except Exception as e:          # pragma: no cover, pylint: disable=broad-except
                 logger.exception('{:s} exception'.format(function_name))
diff --git a/src/common/tests/EventTools.py b/src/common/tests/EventTools.py
new file mode 100644
index 000000000..c263be309
--- /dev/null
+++ b/src/common/tests/EventTools.py
@@ -0,0 +1,69 @@
+import json, logging
+from typing import Dict, List, Tuple
+from common.tools.grpc.Tools import grpc_message_to_json_string
+from context.client.EventsCollector import EventsCollector
+from context.proto.context_pb2 import (
+    ConnectionEvent, ContextEvent, DeviceEvent, EventTypeEnum, LinkEvent, ServiceEvent, TopologyEvent)
+
+LOGGER = logging.getLogger(__name__)
+
+EVENT_CREATE = EventTypeEnum.EVENTTYPE_CREATE
+EVENT_UPDATE = EventTypeEnum.EVENTTYPE_UPDATE
+EVENT_REMOVE = EventTypeEnum.EVENTTYPE_REMOVE
+
+def class_to_classname(klass): return klass.__name__
+def instance_to_classname(instance): return type(instance).__name__
+
+CLASSNAME_CONTEXT_EVENT    = class_to_classname(ContextEvent)
+CLASSNAME_TOPOLOGY_EVENT   = class_to_classname(TopologyEvent)
+CLASSNAME_DEVICE_EVENT     = class_to_classname(DeviceEvent)
+CLASSNAME_LINK_EVENT       = class_to_classname(LinkEvent)
+CLASSNAME_SERVICE_EVENT    = class_to_classname(ServiceEvent)
+CLASSNAME_CONNECTION_EVENT = class_to_classname(ConnectionEvent)
+
+EVENT_CLASS_NAME__TO__ENTITY_ID_SELECTOR = {
+    CLASSNAME_CONTEXT_EVENT   : lambda event: event.context_id,
+    CLASSNAME_TOPOLOGY_EVENT  : lambda event: event.topology_id,
+    CLASSNAME_DEVICE_EVENT    : lambda event: event.device_id,
+    CLASSNAME_LINK_EVENT      : lambda event: event.link_id,
+    CLASSNAME_SERVICE_EVENT   : lambda event: event.service_id,
+    CLASSNAME_CONNECTION_EVENT: lambda event: event.connection_id,
+}
+
+def event_to_key(event):
+    event_class_name = instance_to_classname(event)
+    entity_id_selector_function = EVENT_CLASS_NAME__TO__ENTITY_ID_SELECTOR.get(event_class_name)
+    entity_id = entity_id_selector_function(event)
+    return (event_class_name, event.event.event_type, grpc_message_to_json_string(entity_id))
+
+def check_events(events_collector : EventsCollector, expected_events : List[Tuple[str, int, Dict]]):
+    expected_events_map = {}
+    num_events_expected = 0
+    for event_classname, event_type_id, event_ids in expected_events:
+        event_key = (event_classname, event_type_id, json.dumps(event_ids, sort_keys=True))
+        event_count = expected_events_map.get(event_key, 0)
+        expected_events_map[event_key] = event_count + 1
+        num_events_expected += 1
+
+    events_received = events_collector.get_events(block=True, count=num_events_expected)
+    for i, event_received in enumerate(events_received):
+        LOGGER.info('event_received[{:d}] = {:s}'.format(i, str(event_received)))
+        event_key = event_to_key(event_received)
+        event_count = expected_events_map.pop(event_key, 0)
+        event_count -= 1
+        if event_count != 0: expected_events_map[event_key] = event_count
+
+    if len(expected_events_map) > 0:
+        missing_events = {}
+        unexpected_events = {}
+        for event_key,event_count in expected_events_map.items():
+            if event_count > 0:
+                if (event_key[0] == 'DeviceEvent') and (event_key[1] == EVENT_UPDATE):
+                    continue # sometimes device update events, specially with massive port updates, might be lost
+                missing_events[event_key] = event_count
+            if event_count < 0:
+                unexpected_events[event_key] = -event_count
+        msg = ['EventCheck failed:']
+        if len(missing_events) > 0: msg.append('missing_events={:s}'.format(str(missing_events)))
+        if len(unexpected_events) > 0: msg.append('unexpected_events={:s}'.format(str(unexpected_events)))
+        if len(msg) > 1: raise Exception(' '.join(msg))
diff --git a/src/compute/tests/MockService.py b/src/common/tests/MockService.py
similarity index 100%
rename from src/compute/tests/MockService.py
rename to src/common/tests/MockService.py
diff --git a/src/compute/tests/MockServicerImpl_Context.py b/src/common/tests/MockServicerImpl_Context.py
similarity index 74%
rename from src/compute/tests/MockServicerImpl_Context.py
rename to src/common/tests/MockServicerImpl_Context.py
index d79a755d4..a283fd117 100644
--- a/src/compute/tests/MockServicerImpl_Context.py
+++ b/src/common/tests/MockServicerImpl_Context.py
@@ -1,11 +1,12 @@
 import grpc, logging
 from typing import Any, Dict, Iterator, List
+from common.tools.grpc.Tools import grpc_message_to_json_string
 from context.proto.context_pb2 import (
-    Context, ContextEvent, ContextId, ContextIdList, ContextList, Device, DeviceEvent, DeviceId, DeviceIdList,
-    DeviceList, Empty, Link, LinkEvent, LinkId, LinkIdList, LinkList, Service, ServiceEvent, ServiceId, ServiceIdList,
-    ServiceList, Topology, TopologyEvent, TopologyId, TopologyIdList, TopologyList)
+    Connection, ConnectionEvent, ConnectionId, ConnectionIdList, ConnectionList, Context, ContextEvent, ContextId,
+    ContextIdList, ContextList, Device, DeviceEvent, DeviceId, DeviceIdList, DeviceList, Empty, Link, LinkEvent,
+    LinkId, LinkIdList, LinkList, Service, ServiceEvent, ServiceId, ServiceIdList, ServiceList, Topology,
+    TopologyEvent, TopologyId, TopologyIdList, TopologyList)
 from context.proto.context_pb2_grpc import ContextServiceServicer
-from .Tools import grpc_message_to_json_string
 
 LOGGER = logging.getLogger(__name__)
 
@@ -22,7 +23,7 @@ def get_entry(
     LOGGER.debug('[get_entry] AFTER database={:s}'.format(str(database)))
     container = get_container(database, container_name)
     if entry_uuid not in container:
-        context.abort(grpc.StatusCode.INTERNAL, str('{:s}({:s}) not found'.format(container_name, entry_uuid)))
+        context.abort(grpc.StatusCode.NOT_FOUND, str('{:s}({:s}) not found'.format(container_name, entry_uuid)))
     return container[entry_uuid]
 
 def set_entry(database : Dict[str, Dict[str, Any]], container_name : str, entry_uuid : str, entry : Any) -> Any:
@@ -37,7 +38,7 @@ def del_entry(
 ) -> Any:
     container = get_container(database, container_name)
     if entry_uuid not in container:
-        context.abort(grpc.StatusCode.INTERNAL, str('{:s}({:s}) not found'.format(container_name, entry_uuid)))
+        context.abort(grpc.StatusCode.NOT_FOUND, str('{:s}({:s}) not found'.format(container_name, entry_uuid)))
     del container[entry_uuid]
     return Empty()
 
@@ -63,7 +64,7 @@ class MockServicerImpl_Context(ContextServiceServicer):
 
     def SetContext(self, request: Context, context : grpc.ServicerContext) -> ContextId:
         LOGGER.info('[SetContext] request={:s}'.format(grpc_message_to_json_string(request)))
-        return set_entry(self.database, 'context', request.context_uuid.uuid, request).context_id
+        return set_entry(self.database, 'context', request.context_id.context_uuid.uuid, request).context_id
 
     def RemoveContext(self, request: ContextId, context : grpc.ServicerContext) -> Empty:
         LOGGER.info('[RemoveContext] request={:s}'.format(grpc_message_to_json_string(request)))
@@ -120,7 +121,7 @@ class MockServicerImpl_Context(ContextServiceServicer):
 
     def SetDevice(self, request: Context, context : grpc.ServicerContext) -> DeviceId:
         LOGGER.info('[SetDevice] request={:s}'.format(grpc_message_to_json_string(request)))
-        return set_entry(self.database, 'device', request.device_uuid.uuid, request).device_id
+        return set_entry(self.database, 'device', request.device_id.device_uuid.uuid, request).device_id
 
     def RemoveDevice(self, request: DeviceId, context : grpc.ServicerContext) -> Empty:
         LOGGER.info('[RemoveDevice] request={:s}'.format(grpc_message_to_json_string(request)))
@@ -146,7 +147,7 @@ class MockServicerImpl_Context(ContextServiceServicer):
 
     def SetLink(self, request: Context, context : grpc.ServicerContext) -> LinkId:
         LOGGER.info('[SetLink] request={:s}'.format(grpc_message_to_json_string(request)))
-        return set_entry(self.database, 'link', request.link_uuid.uuid, request).link_id
+        return set_entry(self.database, 'link', request.link_id.link_uuid.uuid, request).link_id
 
     def RemoveLink(self, request: LinkId, context : grpc.ServicerContext) -> Empty:
         LOGGER.info('[RemoveLink] request={:s}'.format(grpc_message_to_json_string(request)))
@@ -186,3 +187,43 @@ class MockServicerImpl_Context(ContextServiceServicer):
 
     def GetServiceEvents(self, request: Empty, context : grpc.ServicerContext) -> Iterator[ServiceEvent]:
         LOGGER.info('[GetServiceEvents] request={:s}'.format(grpc_message_to_json_string(request)))
+
+
+    # ----- Connection -------------------------------------------------------------------------------------------------
+
+    def ListConnectionIds(self, request: ServiceId, context : grpc.ServicerContext) -> ConnectionIdList:
+        LOGGER.info('[ListConnectionIds] request={:s}'.format(grpc_message_to_json_string(request)))
+        container_name = 'service_connections[{:s}/{:s}]'.format(
+            str(request.context_id.context_uuid.uuid), str(request.service_uuid.uuid))
+        return ConnectionIdList(connection_ids=[c.connection_id for c in get_entries(self.database, container_name)])
+
+    def ListConnections(self, request: ServiceId, context : grpc.ServicerContext) -> ConnectionList:
+        LOGGER.info('[ListConnections] request={:s}'.format(grpc_message_to_json_string(request)))
+        container_name = 'service_connections[{:s}/{:s}]'.format(
+            str(request.context_id.context_uuid.uuid), str(request.service_uuid.uuid))
+        return ConnectionList(connections=get_entries(self.database, container_name))
+
+    def GetConnection(self, request: ConnectionId, context : grpc.ServicerContext) -> Connection:
+        LOGGER.info('[GetConnection] request={:s}'.format(grpc_message_to_json_string(request)))
+        return get_entry(context, self.database, 'connection', request.connection_uuid.uuid)
+
+    def SetConnection(self, request: Connection, context : grpc.ServicerContext) -> ConnectionId:
+        LOGGER.info('[SetConnection] request={:s}'.format(grpc_message_to_json_string(request)))
+        service_connection__container_name = 'service_connection[{:s}/{:s}]'.format(
+            str(request.service_id.context_id.context_uuid.uuid), str(request.service_id.service_uuid.uuid))
+        set_entry(
+            self.database, service_connection__container_name, request.connection_id.connection_uuid.uuid, request)
+        return set_entry(
+            self.database, 'connection', request.connection_id.connection_uuid.uuid, request).connection_id
+
+    def RemoveConnection(self, request: ConnectionId, context : grpc.ServicerContext) -> Empty:
+        LOGGER.info('[RemoveConnection] request={:s}'.format(grpc_message_to_json_string(request)))
+        connection = get_entry(context, self.database, 'connection', request.connection_uuid.uuid)
+        service_id = connection.service_id
+        service_connection__container_name = 'service_connection[{:s}/{:s}]'.format(
+            str(service_id.context_id.context_uuid.uuid), str(service_id.service_uuid.uuid))
+        del_entry(context, self.database, service_connection__container_name, request.connection_uuid.uuid)
+        return del_entry(context, self.database, 'connection', request.connection_uuid.uuid)
+
+    def GetConnectionEvents(self, request: Empty, context : grpc.ServicerContext) -> Iterator[ConnectionEvent]:
+        LOGGER.info('[GetConnectionEvents] request={:s}'.format(grpc_message_to_json_string(request)))
diff --git a/src/common/tests/MockServicerImpl_Device.py b/src/common/tests/MockServicerImpl_Device.py
new file mode 100644
index 000000000..621f6efa8
--- /dev/null
+++ b/src/common/tests/MockServicerImpl_Device.py
@@ -0,0 +1,37 @@
+import grpc, logging
+from common.Settings import get_setting
+from common.tools.grpc.Tools import grpc_message_to_json_string
+from context.client.ContextClient import ContextClient
+from context.proto.context_pb2 import Device, DeviceConfig, DeviceId, Empty
+from device.proto.device_pb2 import MonitoringSettings
+from device.proto.device_pb2_grpc import DeviceServiceServicer
+
+LOGGER = logging.getLogger(__name__)
+
+class MockServicerImpl_Device(DeviceServiceServicer):
+    def __init__(self):
+        LOGGER.info('[__init__] Creating Servicer...')
+        self.context_client = ContextClient(
+            get_setting('CONTEXTSERVICE_SERVICE_HOST'),
+            get_setting('CONTEXTSERVICE_SERVICE_PORT_GRPC'))
+        LOGGER.info('[__init__] Servicer Created')
+
+    def AddDevice(self, request : Device, context : grpc.ServicerContext) -> DeviceId:
+        LOGGER.info('[AddDevice] request={:s}'.format(grpc_message_to_json_string(request)))
+        return self.context_client.SetDevice(request)
+
+    def ConfigureDevice(self, request : Device, context : grpc.ServicerContext) -> DeviceId:
+        LOGGER.info('[ConfigureDevice] request={:s}'.format(grpc_message_to_json_string(request)))
+        return self.context_client.SetDevice(request)
+
+    def DeleteDevice(self, request : DeviceId, context : grpc.ServicerContext) -> Empty:
+        LOGGER.info('[DeleteDevice] request={:s}'.format(grpc_message_to_json_string(request)))
+        return self.context_client.RemoveDevice(request)
+
+    def GetInitialConfig(self, request : DeviceId, context : grpc.ServicerContext) -> DeviceConfig:
+        LOGGER.info('[GetInitialConfig] request={:s}'.format(grpc_message_to_json_string(request)))
+        return DeviceConfig()
+
+    def MonitorDeviceKpi(self, request : MonitoringSettings, context : grpc.ServicerContext) -> Empty:
+        LOGGER.info('[MonitorDeviceKpi] request={:s}'.format(grpc_message_to_json_string(request)))
+        return Empty()
diff --git a/src/compute/tests/MockServicerImpl_Service.py b/src/common/tests/MockServicerImpl_Service.py
similarity index 74%
rename from src/compute/tests/MockServicerImpl_Service.py
rename to src/common/tests/MockServicerImpl_Service.py
index 75fdc3073..010ba42a5 100644
--- a/src/compute/tests/MockServicerImpl_Service.py
+++ b/src/common/tests/MockServicerImpl_Service.py
@@ -1,9 +1,9 @@
 import grpc, logging
 from common.Settings import get_setting
+from common.tools.grpc.Tools import grpc_message_to_json_string
 from context.client.ContextClient import ContextClient
-from service.proto.context_pb2 import ConnectionList, Empty, Service, ServiceId
+from service.proto.context_pb2 import Empty, Service, ServiceId, ServiceStatusEnum
 from service.proto.service_pb2_grpc import ServiceServiceServicer
-from .Tools import grpc_message_to_json_string
 
 LOGGER = logging.getLogger(__name__)
 
@@ -21,12 +21,11 @@ class MockServicerImpl_Service(ServiceServiceServicer):
 
     def UpdateService(self, request : Service, context : grpc.ServicerContext) -> ServiceId:
         LOGGER.info('[UpdateService] request={:s}'.format(grpc_message_to_json_string(request)))
-        return self.context_client.SetService(request)
+        service = Service()
+        service.CopyFrom(request)
+        service.service_status.service_status = ServiceStatusEnum.SERVICESTATUS_ACTIVE
+        return self.context_client.SetService(service)
 
     def DeleteService(self, request : ServiceId, context : grpc.ServicerContext) -> Empty:
         LOGGER.info('[DeleteService] request={:s}'.format(grpc_message_to_json_string(request)))
         return self.context_client.RemoveService(request)
-
-    def GetConnectionList(self, request : ServiceId, context : grpc.ServicerContext) -> ConnectionList:
-        LOGGER.info('[GetConnectionList] request={:s}'.format(grpc_message_to_json_string(request)))
-        return ConnectionList()
diff --git a/src/common/tools/client/RetryDecorator.py b/src/common/tools/client/RetryDecorator.py
index d3f7f3e38..a969086dd 100644
--- a/src/common/tools/client/RetryDecorator.py
+++ b/src/common/tools/client/RetryDecorator.py
@@ -1,6 +1,6 @@
-# This decorator re-executes the decorated function when it raises an exception. It enables to control the exception
-# classes that should trigger the re-execution, the maximum number of retries, the delay between retries, and set the
-# execution of a preparation method before every retry. The delay is specfied by means of user-customizable functions.
+# This decorator re-executes the decorated function when it raises an exception. It enables to control the maximum
+# number of retries, the delay between retries, and to set the execution of a preparation method before every retry.
+# The delay is specfied by means of user-customizable functions.
 #
 # Delay functions should return a compute function with a single parameter, the number of retry. For instance:
 #   delay_linear(initial=0, increment=0):
@@ -16,10 +16,8 @@
 #       adds an increasing delay between retries, starting with 1 second, and incresing it exponentially by steps of 2
 #       seconds, up to 10 seconds,  every time an exception is caught within the current execution.
 #       E.g. 1.0, 2.0, 4.0, 8.0, 10.0, 10.0, 10.0, ...
-
+#
 # Arguments:
-# - exceptions: defines the set of exception classes to be catched for reconnection. Others are re-raised.
-#   By default all exceptions are re-raised.
 # - max_retries: defines the maximum number of retries acceptable before giving up. By default, 0 retries are executed.
 # - delay_function: defines the delay computation method to be used. By default, delay_linear with a fixed delay of 0.1
 #   seconds is used.
@@ -31,7 +29,10 @@
 # - prepare_method_kwargs: defines the dictionary of keyword arguments to be provided to the preparation method. If no
 #   preparation method is specified, the argument is silently ignored. By default, an empty dictionary is defined.
 
-import time
+import grpc, logging, time
+from grpc._channel import _InactiveRpcError
+
+LOGGER = logging.getLogger(__name__)
 
 def delay_linear(initial=0, increment=0, maximum=None):
     def compute(num_try):
@@ -42,12 +43,12 @@ def delay_linear(initial=0, increment=0, maximum=None):
 
 def delay_exponential(initial=1, increment=1, maximum=None):
     def compute(num_try):
-        delay = initial * (num_try - 1) ^ increment
+        delay = initial * pow((num_try - 1), increment)
         if maximum is not None: delay = max(delay, maximum)
         return delay
     return compute
 
-def retry(exceptions=set(), max_retries=0, delay_function=delay_linear(initial=0, increment=0),
+def retry(max_retries=0, delay_function=delay_linear(initial=0, increment=0),
           prepare_method_name=None, prepare_method_args=[], prepare_method_kwargs={}):
     def _reconnect(func):
         def wrapper(self, *args, **kwargs):
@@ -58,14 +59,19 @@ def retry(exceptions=set(), max_retries=0, delay_function=delay_linear(initial=0
             while not given_up:
                 try:
                     return func(self, *args, **kwargs)
-                except Exception as e:
-                    if not isinstance(e, tuple(exceptions)): raise
+                except (grpc.RpcError, _InactiveRpcError) as e:
+                    if e.code() not in [grpc.StatusCode.UNAVAILABLE]: raise
 
                     num_try += 1
                     given_up = num_try > max_retries
-                    if given_up: raise Exception('Giving up... {} tries failed'.format(max_retries))
-                    if delay_function is not None: time.sleep(delay_function(num_try))
+                    if given_up: raise Exception('Giving up... {:d} tries failed'.format(max_retries)) from e
+                    if delay_function is not None:
+                        delay = delay_function(num_try)
+                        time.sleep(delay)
+                        LOGGER.info('Retry {:d}/{:d} after {:f} seconds...'.format(num_try, max_retries, delay))
+                    else:
+                        LOGGER.info('Retry {:d}/{:d} immediate...'.format(num_try, max_retries))
 
                     if prepare_method_name is not None: prepare_method(*prepare_method_args, **prepare_method_kwargs)
-        return(wrapper)
-    return(_reconnect)
+        return wrapper
+    return _reconnect
diff --git a/src/common/tools/grpc/Tools.py b/src/common/tools/grpc/Tools.py
new file mode 100644
index 000000000..762aefbef
--- /dev/null
+++ b/src/common/tools/grpc/Tools.py
@@ -0,0 +1,21 @@
+import json
+from google.protobuf.json_format import MessageToDict
+
+def grpc_message_to_json(
+    message, including_default_value_fields=True, preserving_proto_field_name=True, use_integers_for_enums=False):
+
+    return MessageToDict(
+        message, including_default_value_fields=including_default_value_fields,
+        preserving_proto_field_name=preserving_proto_field_name, use_integers_for_enums=use_integers_for_enums)
+
+def grpc_message_list_to_json(message_list):
+    if message_list is None: return None
+    return [grpc_message_to_json(message) for message in message_list]
+
+def grpc_message_to_json_string(message):
+    if message is None: return str(None)
+    return json.dumps(grpc_message_to_json(message), sort_keys=True)
+
+def grpc_message_list_to_json_string(message_list):
+    if message_list is None: return str(None)
+    return json.dumps(grpc_message_list_to_json(message_list), sort_keys=True)
diff --git a/src/tester_functional/__init__.py b/src/common/tools/grpc/__init__.py
similarity index 100%
rename from src/tester_functional/__init__.py
rename to src/common/tools/grpc/__init__.py
diff --git a/src/common/tools/object_factory/ConfigRule.py b/src/common/tools/object_factory/ConfigRule.py
new file mode 100644
index 000000000..352703b24
--- /dev/null
+++ b/src/common/tools/object_factory/ConfigRule.py
@@ -0,0 +1,13 @@
+import json
+from typing import Any, Dict, Union
+from context.proto.context_pb2 import ConfigActionEnum
+
+def json_config_rule(action : ConfigActionEnum, resource_key : str, resource_value : Union[str, Dict[str, Any]]):
+    if not isinstance(resource_value, str): resource_value = json.dumps(resource_value, sort_keys=True)
+    return {'action': action, 'resource_key': resource_key, 'resource_value': resource_value}
+
+def json_config_rule_set(resource_key : str, resource_value : Union[str, Dict[str, Any]]):
+    return json_config_rule(ConfigActionEnum.CONFIGACTION_SET, resource_key, resource_value)
+
+def json_config_rule_delete(resource_key : str, resource_value : Union[str, Dict[str, Any]]):
+    return json_config_rule(ConfigActionEnum.CONFIGACTION_DELETE, resource_key, resource_value)
diff --git a/src/common/tools/object_factory/Connection.py b/src/common/tools/object_factory/Connection.py
new file mode 100644
index 000000000..6fa21a2fc
--- /dev/null
+++ b/src/common/tools/object_factory/Connection.py
@@ -0,0 +1,18 @@
+import copy
+from typing import Dict, List, Optional
+
+def json_connection_id(connection_uuid : str):
+    return {'connection_uuid': {'uuid': connection_uuid}}
+
+def json_connection(
+        connection_uuid : str, service_id : Optional[Dict] = None, path_hops_endpoint_ids : List[Dict] = [],
+        sub_service_ids : List[Dict] = []
+    ):
+
+    result = {
+        'connection_id'         : json_connection_id(connection_uuid),
+        'path_hops_endpoint_ids': copy.deepcopy(path_hops_endpoint_ids),
+        'sub_service_ids'       : copy.deepcopy(sub_service_ids),
+    }
+    if service_id is not None: result['service_id'] = copy.deepcopy(service_id)
+    return result
diff --git a/src/common/tools/object_factory/Constraint.py b/src/common/tools/object_factory/Constraint.py
new file mode 100644
index 000000000..ffa9a1314
--- /dev/null
+++ b/src/common/tools/object_factory/Constraint.py
@@ -0,0 +1,6 @@
+import json
+from typing import Any, Dict, Union
+
+def json_constraint(constraint_type : str, constraint_value : Union[str, Dict[str, Any]]):
+    if not isinstance(constraint_value, str): constraint_value = json.dumps(constraint_value, sort_keys=True)
+    return {'constraint_type': constraint_type, 'constraint_value': constraint_value}
diff --git a/src/common/tools/object_factory/Context.py b/src/common/tools/object_factory/Context.py
new file mode 100644
index 000000000..682d30c4f
--- /dev/null
+++ b/src/common/tools/object_factory/Context.py
@@ -0,0 +1,9 @@
+def json_context_id(context_uuid : str):
+    return {'context_uuid': {'uuid': context_uuid}}
+
+def json_context(context_uuid : str):
+    return {
+        'context_id'  : json_context_id(context_uuid),
+        'topology_ids': [],
+        'service_ids' : [],
+    }
diff --git a/src/common/tools/object_factory/Device.py b/src/common/tools/object_factory/Device.py
new file mode 100644
index 000000000..fe271d00a
--- /dev/null
+++ b/src/common/tools/object_factory/Device.py
@@ -0,0 +1,93 @@
+import copy
+from typing import Dict, List, Tuple
+from common.DeviceTypes import DeviceTypeEnum
+from common.tools.object_factory.ConfigRule import json_config_rule_set
+from context.proto.context_pb2 import DeviceDriverEnum, DeviceOperationalStatusEnum
+
+DEVICE_DISABLED = DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_DISABLED
+
+DEVICE_EMUPR_TYPE   = DeviceTypeEnum.EMULATED_PACKET_ROUTER.value
+DEVICE_EMUOLS_TYPE   = DeviceTypeEnum.EMULATED_OPTICAL_LINE_SYSTEM.value
+DEVICE_EMU_DRIVERS  = [DeviceDriverEnum.DEVICEDRIVER_UNDEFINED]
+DEVICE_EMU_ADDRESS  = '127.0.0.1'
+DEVICE_EMU_PORT     = '0'
+
+DEVICE_PR_TYPE      = DeviceTypeEnum.PACKET_ROUTER.value
+DEVICE_PR_DRIVERS   = [DeviceDriverEnum.DEVICEDRIVER_OPENCONFIG]
+
+DEVICE_TAPI_TYPE    = DeviceTypeEnum.OPTICAL_LINE_SYSTEM.value
+DEVICE_TAPI_DRIVERS = [DeviceDriverEnum.DEVICEDRIVER_TRANSPORT_API]
+
+DEVICE_P4_TYPE      = DeviceTypeEnum.P4_SWITCH.value
+DEVICE_P4_DRIVERS   = [DeviceDriverEnum.DEVICEDRIVER_P4]
+
+def json_device_id(device_uuid : str):
+    return {'device_uuid': {'uuid': device_uuid}}
+
+def json_device(
+        device_uuid : str, device_type : str, status : DeviceOperationalStatusEnum, endpoints : List[Dict] = [],
+        config_rules : List[Dict] = [], drivers : List[Dict] = []
+    ):
+    return {
+        'device_id'                : json_device_id(device_uuid),
+        'device_type'              : device_type,
+        'device_config'            : {'config_rules': copy.deepcopy(config_rules)},
+        'device_operational_status': status,
+        'device_drivers'           : copy.deepcopy(drivers),
+        'device_endpoints'         : copy.deepcopy(endpoints),
+    }
+
+def json_device_emulated_packet_router_disabled(
+        device_uuid : str, endpoints : List[Dict] = [], config_rules : List[Dict] = [],
+        drivers : List[Dict] = DEVICE_EMU_DRIVERS
+    ):
+    return json_device(
+        device_uuid, DEVICE_EMUPR_TYPE, DEVICE_DISABLED, endpoints=endpoints, config_rules=config_rules,
+        drivers=drivers)
+
+def json_device_emulated_tapi_disabled(
+        device_uuid : str, endpoints : List[Dict] = [], config_rules : List[Dict] = [],
+        drivers : List[Dict] = DEVICE_EMU_DRIVERS
+    ):
+    return json_device(
+        device_uuid, DEVICE_EMUOLS_TYPE, DEVICE_DISABLED, endpoints=endpoints, config_rules=config_rules,
+        drivers=drivers)
+
+def json_device_packetrouter_disabled(
+        device_uuid : str, endpoints : List[Dict] = [], config_rules : List[Dict] = [],
+        drivers : List[Dict] = DEVICE_PR_DRIVERS
+    ):
+    return json_device(
+        device_uuid, DEVICE_PR_TYPE, DEVICE_DISABLED, endpoints=endpoints, config_rules=config_rules, drivers=drivers)
+
+def json_device_tapi_disabled(
+        device_uuid : str, endpoints : List[Dict] = [], config_rules : List[Dict] = [],
+        drivers : List[Dict] = DEVICE_TAPI_DRIVERS
+    ):
+    return json_device(
+        device_uuid, DEVICE_TAPI_TYPE, DEVICE_DISABLED, endpoints=endpoints, config_rules=config_rules, drivers=drivers)
+
+def json_device_p4_disabled(
+        device_uuid : str, endpoints : List[Dict] = [], config_rules : List[Dict] = [],
+        drivers : List[Dict] = DEVICE_P4_DRIVERS
+    ):
+    return json_device(
+        device_uuid, DEVICE_P4_TYPE, DEVICE_DISABLED, endpoints=endpoints, config_rules=config_rules, drivers=drivers)
+
+def json_device_connect_rules(address : str, port : int, settings : Dict = {}):
+    return [
+        json_config_rule_set('_connect/address',  address),
+        json_config_rule_set('_connect/port',     port),
+        json_config_rule_set('_connect/settings', settings),
+    ]
+
+def json_device_emulated_connect_rules(
+        endpoint_descriptors : List[Tuple[str, str, List[int]]], address : str = DEVICE_EMU_ADDRESS,
+        port : int = DEVICE_EMU_PORT
+    ):
+
+    settings = {'endpoints': [
+        {'uuid': endpoint_uuid, 'type': endpoint_type, 'sample_types': sample_types}
+        for endpoint_uuid,endpoint_type,sample_types in endpoint_descriptors
+    ]}
+    return json_device_connect_rules(address, port, settings=settings)
diff --git a/src/common/tools/object_factory/EndPoint.py b/src/common/tools/object_factory/EndPoint.py
new file mode 100644
index 000000000..d5115d7a0
--- /dev/null
+++ b/src/common/tools/object_factory/EndPoint.py
@@ -0,0 +1,19 @@
+import copy
+from typing import Dict, List, Optional
+
+def json_endpoint_id(device_id : Dict, endpoint_uuid : str, topology_id : Optional[Dict] = None):
+    result = {'device_id': copy.deepcopy(device_id), 'endpoint_uuid': {'uuid': endpoint_uuid}}
+    if topology_id is not None: result['topology_id'] = copy.deepcopy(topology_id)
+    return result
+
+def json_endpoint(
+        device_id : Dict, endpoint_uuid : str, endpoint_type : str, topology_id : Optional[Dict] = None,
+        kpi_sample_types : List[int] = []
+    ):
+
+    result = {
+        'endpoint_id': json_endpoint_id(device_id, endpoint_uuid, topology_id=topology_id),
+        'endpoint_type': endpoint_type,
+    }
+    if len(kpi_sample_types) > 0: result['kpi_sample_types'] = copy.deepcopy(kpi_sample_types)
+    return result
diff --git a/src/common/tools/object_factory/Link.py b/src/common/tools/object_factory/Link.py
new file mode 100644
index 000000000..a18cc1b90
--- /dev/null
+++ b/src/common/tools/object_factory/Link.py
@@ -0,0 +1,8 @@
+import copy
+from typing import Dict, List
+
+def json_link_id(link_uuid : str):
+    return {'link_uuid': {'uuid': link_uuid}}
+
+def json_link(link_uuid : str, endpoint_ids : List[Dict]):
+    return {'link_id': json_link_id(link_uuid), 'link_endpoint_ids': copy.deepcopy(endpoint_ids)}
diff --git a/src/common/tools/object_factory/Service.py b/src/common/tools/object_factory/Service.py
new file mode 100644
index 000000000..68a9a8263
--- /dev/null
+++ b/src/common/tools/object_factory/Service.py
@@ -0,0 +1,34 @@
+import copy
+from typing import Dict, List, Optional
+from common.Constants import DEFAULT_CONTEXT_UUID
+from common.tools.object_factory.Context import json_context_id
+from context.proto.context_pb2 import ServiceStatusEnum, ServiceTypeEnum
+
+def json_service_id(service_uuid : str, context_id : Optional[Dict] = None):
+    result = {'service_uuid': {'uuid': service_uuid}}
+    if context_id is not None: result['context_id'] = copy.deepcopy(context_id)
+    return result
+
+def json_service(
+    service_uuid : str, service_type : ServiceTypeEnum, context_id : Optional[Dict] = None,
+    status : ServiceStatusEnum = ServiceStatusEnum.SERVICESTATUS_PLANNED,
+    endpoint_ids : List[Dict] = [], constraints : List[Dict] = [], config_rules : List[Dict] = []):
+
+    return {
+        'service_id'          : json_service_id(service_uuid, context_id=context_id),
+        'service_type'        : service_type,
+        'service_status'      : {'service_status': status},
+        'service_endpoint_ids': copy.deepcopy(endpoint_ids),
+        'service_constraints' : copy.deepcopy(constraints),
+        'service_config'      : {'config_rules': copy.deepcopy(config_rules)},
+    }
+
+def json_service_l3nm_planned(
+        service_uuid : str, endpoint_ids : List[Dict] = [], constraints : List[Dict] = [],
+        config_rules : List[Dict] = []
+    ):
+
+    return json_service(
+        service_uuid, ServiceTypeEnum.SERVICETYPE_L3NM, context_id=json_context_id(DEFAULT_CONTEXT_UUID),
+        status=ServiceStatusEnum.SERVICESTATUS_PLANNED, endpoint_ids=endpoint_ids, constraints=constraints,
+        config_rules=config_rules)
diff --git a/src/common/tools/object_factory/Topology.py b/src/common/tools/object_factory/Topology.py
new file mode 100644
index 000000000..e19e0d98c
--- /dev/null
+++ b/src/common/tools/object_factory/Topology.py
@@ -0,0 +1,14 @@
+import copy
+from typing import Dict, Optional
+
+def json_topology_id(topology_uuid : str, context_id : Optional[Dict] = None):
+    result = {'topology_uuid': {'uuid': topology_uuid}}
+    if context_id is not None: result['context_id'] = copy.deepcopy(context_id)
+    return result
+
+def json_topology(topology_uuid : str, context_id : Optional[Dict] = None):
+    return {
+        'topology_id': json_topology_id(topology_uuid, context_id=context_id),
+        'device_ids' : [],
+        'link_ids'   : [],
+    }
diff --git a/src/tester_integration/__init__.py b/src/common/tools/object_factory/__init__.py
similarity index 100%
rename from src/tester_integration/__init__.py
rename to src/common/tools/object_factory/__init__.py
diff --git a/src/compute/Dockerfile b/src/compute/Dockerfile
index 99d4e3ed1..abf38cde8 100644
--- a/src/compute/Dockerfile
+++ b/src/compute/Dockerfile
@@ -25,7 +25,7 @@ RUN mkdir -p /var/teraflow/compute
 # Get Python packages per module
 COPY compute/requirements.in compute/requirements.in
 RUN pip-compile --output-file=compute/requirements.txt compute/requirements.in
-RUN python3 -m pip install -r compute/requirements.in
+RUN python3 -m pip install -r compute/requirements.txt
 
 # Add files into working directory
 COPY common/. common
diff --git a/src/compute/client/ComputeClient.py b/src/compute/client/ComputeClient.py
index 19a26b943..80a7b153e 100644
--- a/src/compute/client/ComputeClient.py
+++ b/src/compute/client/ComputeClient.py
@@ -7,6 +7,7 @@ from compute.proto.context_pb2 import (
 LOGGER = logging.getLogger(__name__)
 MAX_RETRIES = 15
 DELAY_FUNCTION = delay_exponential(initial=0.01, increment=2.0, maximum=5.0)
+RETRY_DECORATOR = retry(max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
 
 class ComputeClient:
     def __init__(self, address, port):
@@ -26,49 +27,49 @@ class ComputeClient:
         self.channel = None
         self.stub = None
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def CheckCredentials(self, request : TeraFlowController) -> AuthenticationResult:
         LOGGER.debug('CheckCredentials request: {:s}'.format(str(request)))
         response = self.stub.CheckCredentials(request)
         LOGGER.debug('CheckCredentials result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def GetConnectivityServiceStatus(self, request : ServiceId) -> ServiceStatus:
         LOGGER.debug('GetConnectivityServiceStatus request: {:s}'.format(str(request)))
         response = self.stub.GetConnectivityServiceStatus(request)
         LOGGER.debug('GetConnectivityServiceStatus result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def CreateConnectivityService(self, request : Service) -> ServiceId:
         LOGGER.debug('CreateConnectivityService request: {:s}'.format(str(request)))
         response = self.stub.CreateConnectivityService(request)
         LOGGER.debug('CreateConnectivityService result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def EditConnectivityService(self, request : Service) -> ServiceId:
         LOGGER.debug('EditConnectivityService request: {:s}'.format(str(request)))
         response = self.stub.EditConnectivityService(request)
         LOGGER.debug('EditConnectivityService result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def DeleteConnectivityService(self, request : Service) -> Empty:
         LOGGER.debug('DeleteConnectivityService request: {:s}'.format(str(request)))
         response = self.stub.DeleteConnectivityService(request)
         LOGGER.debug('DeleteConnectivityService result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def GetAllActiveConnectivityServices(self, request : Empty) -> ServiceIdList:
         LOGGER.debug('GetAllActiveConnectivityServices request: {:s}'.format(str(request)))
         response = self.stub.GetAllActiveConnectivityServices(request)
         LOGGER.debug('GetAllActiveConnectivityServices result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def ClearAllConnectivityServices(self, request : Empty) -> Empty:
         LOGGER.debug('ClearAllConnectivityServices request: {:s}'.format(str(request)))
         response = self.stub.ClearAllConnectivityServices(request)
diff --git a/src/compute/requirements.in b/src/compute/requirements.in
index 42a2f3d40..fcf7e912c 100644
--- a/src/compute/requirements.in
+++ b/src/compute/requirements.in
@@ -1,11 +1,12 @@
-Flask
-Flask-HTTPAuth
-Flask-RESTful
-grpcio-health-checking
-grpcio
-jsonschema
-prometheus-client
-pytest
-pytest-benchmark
-requests
-coverage
+Flask==2.0.2
+Flask-HTTPAuth==4.5.0
+Flask-RESTful==0.3.9
+grpcio==1.43.0
+grpcio-health-checking==1.43.0
+jsonschema==4.4.0
+prometheus-client==0.13.0
+protobuf==3.19.3
+pytest==6.2.5
+pytest-benchmark==3.4.1
+requests==2.27.1
+coverage==6.3
diff --git a/src/compute/service/__main__.py b/src/compute/service/__main__.py
index eacc1f6c4..92ea3fd8b 100644
--- a/src/compute/service/__main__.py
+++ b/src/compute/service/__main__.py
@@ -1,6 +1,6 @@
 import logging, signal, sys, threading
 from prometheus_client import start_http_server
-from common.Settings import get_setting
+from common.Settings import get_setting, wait_for_environment_variables
 from compute.Config import (
     GRPC_SERVICE_PORT, GRPC_MAX_WORKERS, GRPC_GRACE_PERIOD, LOG_LEVEL, RESTAPI_SERVICE_PORT, RESTAPI_BASE_URL,
     METRICS_PORT)
@@ -29,6 +29,11 @@ def main():
     logging.basicConfig(level=log_level)
     LOGGER = logging.getLogger(__name__)
 
+    wait_for_environment_variables([
+        'CONTEXTSERVICE_SERVICE_HOST', 'CONTEXTSERVICE_SERVICE_PORT_GRPC',
+        'SERVICESERVICE_SERVICE_HOST', 'SERVICESERVICE_SERVICE_PORT_GRPC'
+    ])
+
     signal.signal(signal.SIGINT,  signal_handler)
     signal.signal(signal.SIGTERM, signal_handler)
 
diff --git a/src/compute/service/rest_server/nbi_plugins/ietf_l2vpn/L2VPN_Service.py b/src/compute/service/rest_server/nbi_plugins/ietf_l2vpn/L2VPN_Service.py
index 752a027ad..a58252adc 100644
--- a/src/compute/service/rest_server/nbi_plugins/ietf_l2vpn/L2VPN_Service.py
+++ b/src/compute/service/rest_server/nbi_plugins/ietf_l2vpn/L2VPN_Service.py
@@ -1,17 +1,15 @@
 import logging
-from typing import Dict, List
 from flask import request
 from flask.json import jsonify
 from flask_restful import Resource
-from werkzeug.exceptions import UnsupportedMediaType
 from common.Constants import DEFAULT_CONTEXT_UUID
 from common.Settings import get_setting
 from context.client.ContextClient import ContextClient
 from context.proto.context_pb2 import ServiceId
 from service.client.ServiceClient import ServiceClient
-from service.proto.context_pb2 import Service, ServiceStatusEnum, ServiceTypeEnum
+from service.proto.context_pb2 import ServiceStatusEnum
 from .tools.Authentication import HTTP_AUTH
-from .tools.HttpStatusCodes import HTTP_CREATED, HTTP_GATEWAYTIMEOUT, HTTP_NOCONTENT, HTTP_OK, HTTP_SERVERERROR
+from .tools.HttpStatusCodes import HTTP_GATEWAYTIMEOUT, HTTP_NOCONTENT, HTTP_OK, HTTP_SERVERERROR
 
 LOGGER = logging.getLogger(__name__)
 
@@ -37,7 +35,6 @@ class L2VPN_Service(Resource):
             service_reply = self.context_client.GetService(service_id_request)
             if service_reply.service_id != service_id_request: # pylint: disable=no-member
                 raise Exception('Service retrieval failed. Wrong Service Id was returned')
-
             service_ready_status = ServiceStatusEnum.SERVICESTATUS_ACTIVE
             service_status = service_reply.service_status.service_status
             response = jsonify({})
diff --git a/src/compute/service/rest_server/nbi_plugins/ietf_l2vpn/L2VPN_SiteNetworkAccesses.py b/src/compute/service/rest_server/nbi_plugins/ietf_l2vpn/L2VPN_SiteNetworkAccesses.py
index 1f02e50a4..d11350506 100644
--- a/src/compute/service/rest_server/nbi_plugins/ietf_l2vpn/L2VPN_SiteNetworkAccesses.py
+++ b/src/compute/service/rest_server/nbi_plugins/ietf_l2vpn/L2VPN_SiteNetworkAccesses.py
@@ -7,8 +7,9 @@ from flask_restful import Resource
 from werkzeug.exceptions import UnsupportedMediaType
 from common.Constants import DEFAULT_CONTEXT_UUID
 from common.Settings import get_setting
+from common.tools.grpc.Tools import grpc_message_to_json_string
 from context.client.ContextClient import ContextClient
-from context.proto.context_pb2 import Service, ServiceId, ServiceStatusEnum
+from context.proto.context_pb2 import ConfigActionEnum, Service, ServiceId
 from service.client.ServiceClient import ServiceClient
 from .schemas.site_network_access import SCHEMA_SITE_NETWORK_ACCESS
 from .tools.Authentication import HTTP_AUTH
@@ -74,6 +75,7 @@ def process_site_network_access(context_client : ContextClient, site_network_acc
     else:
         # not found, add it
         config_rule = service.service_config.config_rules.add()             # pylint: disable=no-member
+        config_rule.action = ConfigActionEnum.CONFIGACTION_SET
         config_rule.resource_key = 'settings'
         config_rule.resource_value = json.dumps({
             'route_distinguisher': route_distinguisher,
@@ -104,15 +106,13 @@ def process_site_network_access(context_client : ContextClient, site_network_acc
     else:
         # not found, add it
         config_rule = service.service_config.config_rules.add()             # pylint: disable=no-member
+        config_rule.action = ConfigActionEnum.CONFIGACTION_SET
         config_rule.resource_key = endpoint_settings_key
         config_rule.resource_value = json.dumps({
             'router_id': router_id,
             'sub_interface_index': DEFAULT_SUB_INTERFACE_INDEX,
         }, sort_keys=True)
 
-    if len(service.service_endpoint_ids) >= 2:
-        service.service_status.service_status = ServiceStatusEnum.SERVICESTATUS_ACTIVE
-
     return service
 
 def process_list_site_network_access(
@@ -125,6 +125,7 @@ def process_list_site_network_access(
     for site_network_access in request_data['ietf-l2vpn-svc:site-network-access']:
         try:
             service_request = process_site_network_access(context_client, site_network_access)
+            LOGGER.debug('service_request = {:s}'.format(grpc_message_to_json_string(service_request)))
             service_reply = service_client.UpdateService(service_request)
             if service_reply != service_request.service_id: # pylint: disable=no-member
                 raise Exception('Service update failed. Wrong Service Id was returned')
@@ -144,10 +145,6 @@ class L2VPN_SiteNetworkAccesses(Resource):
         self.service_client = ServiceClient(
             get_setting('SERVICESERVICE_SERVICE_HOST'), get_setting('SERVICESERVICE_SERVICE_PORT_GRPC'))
 
-    #@HTTP_AUTH.login_required
-    #def get(self):
-    #    return {}
-
     @HTTP_AUTH.login_required
     def post(self, site_id : str):
         if not request.is_json: raise UnsupportedMediaType('JSON payload is required')
diff --git a/src/compute/tests/Constants.py b/src/compute/tests/Constants.py
new file mode 100644
index 000000000..ea2e510a8
--- /dev/null
+++ b/src/compute/tests/Constants.py
@@ -0,0 +1,59 @@
+WIM_USERNAME = 'admin'
+WIM_PASSWORD = 'admin'
+
+# Ref: https://osm.etsi.org/wikipub/index.php/WIM
+WIM_MAPPING  = [
+    {
+        'device-id'           : 'dev-1',            # pop_switch_dpid
+        #'device_interface_id' : ??,                # pop_switch_port
+        'service_endpoint_id' : 'ep-1',             # wan_service_endpoint_id
+        'service_mapping_info': {                   # wan_service_mapping_info, other extra info
+            'bearer': {'bearer-reference': 'dev-1:ep-1:10.0.0.1'},
+            'site-id': '1',
+        },
+        #'switch_dpid'         : ??,                # wan_switch_dpid
+        #'switch_port'         : ??,                # wan_switch_port
+        #'datacenter_id'       : ??,                # vim_account
+    },
+    {
+        'device-id'           : 'dev-2',            # pop_switch_dpid
+        #'device_interface_id' : ??,                # pop_switch_port
+        'service_endpoint_id' : 'ep-2',             # wan_service_endpoint_id
+        'service_mapping_info': {                   # wan_service_mapping_info, other extra info
+            'bearer': {'bearer-reference': 'dev-2:ep-2:10.0.0.2'},
+            'site-id': '2',
+        },
+        #'switch_dpid'         : ??,                # wan_switch_dpid
+        #'switch_port'         : ??,                # wan_switch_port
+        #'datacenter_id'       : ??,                # vim_account
+    },
+    {
+        'device-id'           : 'dev-3',            # pop_switch_dpid
+        #'device_interface_id' : ??,                # pop_switch_port
+        'service_endpoint_id' : 'ep-3',             # wan_service_endpoint_id
+        'service_mapping_info': {                   # wan_service_mapping_info, other extra info
+            'bearer': {'bearer-reference': 'dev-3:ep-3:10.0.0.3'},
+            'site-id': '3',
+        },
+        #'switch_dpid'         : ??,                # wan_switch_dpid
+        #'switch_port'         : ??,                # wan_switch_port
+        #'datacenter_id'       : ??,                # vim_account
+    },
+]
+
+SERVICE_TYPE = 'ELINE'
+
+SERVICE_CONNECTION_POINTS_1 = [
+    {'service_endpoint_id': 'ep-1',
+        'service_endpoint_encapsulation_type': 'dot1q',
+        'service_endpoint_encapsulation_info': {'vlan': 1234}},
+    {'service_endpoint_id': 'ep-2',
+        'service_endpoint_encapsulation_type': 'dot1q',
+        'service_endpoint_encapsulation_info': {'vlan': 1234}},
+]
+
+SERVICE_CONNECTION_POINTS_2 = [
+    {'service_endpoint_id': 'ep-3',
+        'service_endpoint_encapsulation_type': 'dot1q',
+        'service_endpoint_encapsulation_info': {'vlan': 1234}},
+]
diff --git a/src/compute/tests/Tools.py b/src/compute/tests/Tools.py
deleted file mode 100644
index a96c38ce5..000000000
--- a/src/compute/tests/Tools.py
+++ /dev/null
@@ -1,7 +0,0 @@
-import json
-from google.protobuf.json_format import MessageToDict
-
-def grpc_message_to_json_string(message):
-    return json.dumps(MessageToDict(
-        message, including_default_value_fields=True, preserving_proto_field_name=True, use_integers_for_enums=False),
-        sort_keys=True)
diff --git a/src/compute/tests/mock_osm/MockOSM.py b/src/compute/tests/mock_osm/MockOSM.py
index c50ee6c88..b96afebd9 100644
--- a/src/compute/tests/mock_osm/MockOSM.py
+++ b/src/compute/tests/mock_osm/MockOSM.py
@@ -3,92 +3,46 @@ from .WimconnectorIETFL2VPN import WimconnectorIETFL2VPN
 
 LOGGER = logging.getLogger(__name__)
 
-WIM_USERNAME = 'admin'
-WIM_PASSWORD = 'admin'
-
-# Ref: https://osm.etsi.org/wikipub/index.php/WIM
-WIM_MAPPING  = [
-    {
-        'device-id'           : 'dev-1',            # pop_switch_dpid
-        #'device_interface_id' : ??,                # pop_switch_port
-        'service_endpoint_id' : 'ep-1',             # wan_service_endpoint_id
-        'service_mapping_info': {                   # wan_service_mapping_info, other extra info
-            'bearer': {'bearer-reference': 'dev-1:ep-1:10.0.0.1'},
-            'site-id': '1',
-        },
-        #'switch_dpid'         : ??,                # wan_switch_dpid
-        #'switch_port'         : ??,                # wan_switch_port
-        #'datacenter_id'       : ??,                # vim_account
-    },
-    {
-        'device-id'           : 'dev-2',            # pop_switch_dpid
-        #'device_interface_id' : ??,                # pop_switch_port
-        'service_endpoint_id' : 'ep-2',             # wan_service_endpoint_id
-        'service_mapping_info': {                   # wan_service_mapping_info, other extra info
-            'bearer': {'bearer-reference': 'dev-2:ep-2:10.0.0.2'},
-            'site-id': '2',
-        },
-        #'switch_dpid'         : ??,                # wan_switch_dpid
-        #'switch_port'         : ??,                # wan_switch_port
-        #'datacenter_id'       : ??,                # vim_account
-    },
-    {
-        'device-id'           : 'dev-3',            # pop_switch_dpid
-        #'device_interface_id' : ??,                # pop_switch_port
-        'service_endpoint_id' : 'ep-3',             # wan_service_endpoint_id
-        'service_mapping_info': {                   # wan_service_mapping_info, other extra info
-            'bearer': {'bearer-reference': 'dev-3:ep-3:10.0.0.3'},
-            'site-id': '3',
-        },
-        #'switch_dpid'         : ??,                # wan_switch_dpid
-        #'switch_port'         : ??,                # wan_switch_port
-        #'datacenter_id'       : ??,                # vim_account
-    },
-]
-
-SERVICE_TYPE = 'ELINE'
-SERVICE_CONNECTION_POINTS_1 = [
-    {'service_endpoint_id': 'ep-1',
-        'service_endpoint_encapsulation_type': 'dot1q',
-        'service_endpoint_encapsulation_info': {'vlan': 1234}},
-    {'service_endpoint_id': 'ep-2',
-        'service_endpoint_encapsulation_type': 'dot1q',
-        'service_endpoint_encapsulation_info': {'vlan': 1234}},
-]
-
-SERVICE_CONNECTION_POINTS_2 = [
-    {'service_endpoint_id': 'ep-3',
-        'service_endpoint_encapsulation_type': 'dot1q',
-        'service_endpoint_encapsulation_info': {'vlan': 1234}},
-]
-
 class MockOSM:
-    def __init__(self, wim_url):
-        wim = {'wim_url': wim_url}
-        wim_account = {'user': WIM_USERNAME, 'password': WIM_PASSWORD}
-        config = {'mapping_not_needed': False, 'service_endpoint_mapping': WIM_MAPPING}
+    def __init__(self, url, mapping, username, password):
+        wim = {'wim_url': url}
+        wim_account = {'user': username, 'password': password}
+        config = {'mapping_not_needed': False, 'service_endpoint_mapping': mapping}
         self.wim = WimconnectorIETFL2VPN(wim, wim_account, config=config)
-        self.service_uuid = None
-        self.conn_info = None
+        self.conn_info = {} # internal database emulating OSM storage provided to WIM Connectors
 
-    def create_connectivity_service(self):
+    def create_connectivity_service(self, service_type, connection_points):
+        LOGGER.info('[create_connectivity_service] service_type={:s}'.format(str(service_type)))
+        LOGGER.info('[create_connectivity_service] connection_points={:s}'.format(str(connection_points)))
         self.wim.check_credentials()
-        LOGGER.info('[create_connectivity_service] connection_points={:s}'.format(str(SERVICE_CONNECTION_POINTS_1)))
-        result = self.wim.create_connectivity_service(SERVICE_TYPE, SERVICE_CONNECTION_POINTS_1)
+        result = self.wim.create_connectivity_service(service_type, connection_points)
         LOGGER.info('[create_connectivity_service] result={:s}'.format(str(result)))
-        self.service_uuid, self.conn_info = result
-
-    def get_connectivity_service_status(self):
+        service_uuid, conn_info = result
+        self.conn_info[service_uuid] = conn_info
+        return service_uuid
+
+    def get_connectivity_service_status(self, service_uuid):
+        LOGGER.info('[get_connectivity_service] service_uuid={:s}'.format(str(service_uuid)))
+        conn_info = self.conn_info.get(service_uuid)
+        if conn_info is None: raise Exception('ServiceId({:s}) not found'.format(str(service_uuid)))
+        LOGGER.info('[get_connectivity_service] conn_info={:s}'.format(str(conn_info)))
         self.wim.check_credentials()
-        result = self.wim.get_connectivity_service_status(self.service_uuid, conn_info=self.conn_info)
+        result = self.wim.get_connectivity_service_status(service_uuid, conn_info=conn_info)
         LOGGER.info('[get_connectivity_service] result={:s}'.format(str(result)))
-
-    def edit_connectivity_service(self):
-        self.wim.check_credentials()
-        LOGGER.info('[edit_connectivity_service] connection_points={:s}'.format(str(SERVICE_CONNECTION_POINTS_2)))
-        self.wim.edit_connectivity_service(
-            self.service_uuid, conn_info=self.conn_info, connection_points=SERVICE_CONNECTION_POINTS_2)
-
-    def delete_connectivity_service(self):
+        return result
+
+    def edit_connectivity_service(self, service_uuid, connection_points):
+        LOGGER.info('[edit_connectivity_service] service_uuid={:s}'.format(str(service_uuid)))
+        LOGGER.info('[edit_connectivity_service] connection_points={:s}'.format(str(connection_points)))
+        conn_info = self.conn_info.get(service_uuid)
+        if conn_info is None: raise Exception('ServiceId({:s}) not found'.format(str(service_uuid)))
+        LOGGER.info('[edit_connectivity_service] conn_info={:s}'.format(str(conn_info)))
+        self.wim.edit_connectivity_service(service_uuid, conn_info=conn_info, connection_points=connection_points)
+
+    def delete_connectivity_service(self, service_uuid):
+        LOGGER.info('[delete_connectivity_service] service_uuid={:s}'.format(str(service_uuid)))
+        conn_info = self.conn_info.get(service_uuid)
+        if conn_info is None: raise Exception('ServiceId({:s}) not found'.format(str(service_uuid)))
+        LOGGER.info('[delete_connectivity_service] conn_info={:s}'.format(str(conn_info)))
         self.wim.check_credentials()
-        self.wim.delete_connectivity_service(self.service_uuid, conn_info=self.conn_info)
+        self.wim.delete_connectivity_service(service_uuid, conn_info=conn_info)
diff --git a/src/compute/tests/mock_osm/WimconnectorIETFL2VPN.py b/src/compute/tests/mock_osm/WimconnectorIETFL2VPN.py
index 182115bad..d5ce65a1e 100644
--- a/src/compute/tests/mock_osm/WimconnectorIETFL2VPN.py
+++ b/src/compute/tests/mock_osm/WimconnectorIETFL2VPN.py
@@ -98,7 +98,7 @@ class WimconnectorIETFL2VPN(SdnConnectorBase):
                 self.wim["wim_url"], service_uuid
             )
             response = requests.get(servicepoint, auth=self.auth)
-
+            self.logger.warning('response.status_code={:s}'.format(str(response.status_code)))
             if response.status_code != requests.codes.ok:
                 raise SdnConnectorError(
                     "Unable to obtain connectivity servcice status",
diff --git a/src/compute/tests/test_unitary.py b/src/compute/tests/test_unitary.py
index 001999f1b..22f741190 100644
--- a/src/compute/tests/test_unitary.py
+++ b/src/compute/tests/test_unitary.py
@@ -1,12 +1,14 @@
 import logging, os, pytest, time
+from common.tests.MockService import MockService
+from common.tests.MockServicerImpl_Context import MockServicerImpl_Context
+from common.tests.MockServicerImpl_Service import MockServicerImpl_Service
 from compute.Config import RESTAPI_SERVICE_PORT, RESTAPI_BASE_URL
 from compute.service.rest_server.RestServer import RestServer
 from context.proto.context_pb2_grpc import add_ContextServiceServicer_to_server
 from service.proto.service_pb2_grpc import add_ServiceServiceServicer_to_server
 from .mock_osm.MockOSM import MockOSM
-from .MockService import MockService
-from .MockServicerImpl_Context import MockServicerImpl_Context
-from .MockServicerImpl_Service import MockServicerImpl_Service
+from .Constants import (
+    SERVICE_CONNECTION_POINTS_1, SERVICE_CONNECTION_POINTS_2, SERVICE_TYPE, WIM_MAPPING, WIM_USERNAME, WIM_PASSWORD)
 
 LOGGER = logging.getLogger(__name__)
 LOGGER.setLevel(logging.DEBUG)
@@ -58,16 +60,19 @@ def compute_service_rest(mockservice):  # pylint: disable=redefined-outer-name
 @pytest.fixture(scope='session')
 def osm_wim(compute_service_rest): # pylint: disable=redefined-outer-name
     wim_url = 'http://{:s}:{:d}'.format(LOCALHOST, COMPUTE_RESTAPI_PORT)
-    return MockOSM(wim_url)
+    return MockOSM(wim_url, WIM_MAPPING, WIM_USERNAME, WIM_PASSWORD)
 
 def test_compute_create_connectivity_service_rest_api(osm_wim : MockOSM): # pylint: disable=redefined-outer-name
-    osm_wim.create_connectivity_service()
+    osm_wim.create_connectivity_service(SERVICE_TYPE, SERVICE_CONNECTION_POINTS_1)
 
 def test_compute_get_connectivity_service_status_rest_api(osm_wim : MockOSM): # pylint: disable=redefined-outer-name
-    osm_wim.get_connectivity_service_status()
+    service_uuid = list(osm_wim.conn_info.keys())[0] # this test adds a single service
+    osm_wim.get_connectivity_service_status(service_uuid)
 
 def test_compute_edit_connectivity_service_rest_api(osm_wim : MockOSM): # pylint: disable=redefined-outer-name
-    osm_wim.edit_connectivity_service()
+    service_uuid = list(osm_wim.conn_info.keys())[0] # this test adds a single service
+    osm_wim.edit_connectivity_service(service_uuid, SERVICE_CONNECTION_POINTS_2)
 
 def test_compute_delete_connectivity_service_rest_api(osm_wim : MockOSM): # pylint: disable=redefined-outer-name
-    osm_wim.delete_connectivity_service()
+    service_uuid = list(osm_wim.conn_info.keys())[0] # this test adds a single service
+    osm_wim.delete_connectivity_service(service_uuid)
diff --git a/src/context/Dockerfile b/src/context/Dockerfile
index 57175a3ab..0999bb86d 100644
--- a/src/context/Dockerfile
+++ b/src/context/Dockerfile
@@ -25,7 +25,7 @@ RUN mkdir -p /var/teraflow/context
 # Get Python packages per module
 COPY context/requirements.in context/requirements.in
 RUN pip-compile --output-file=context/requirements.txt context/requirements.in
-RUN python3 -m pip install -r context/requirements.in
+RUN python3 -m pip install -r context/requirements.txt
 
 # Add files into working directory
 COPY common/. common
diff --git a/src/context/client/ContextClient.py b/src/context/client/ContextClient.py
index 84e3031c2..9e7f4bea7 100644
--- a/src/context/client/ContextClient.py
+++ b/src/context/client/ContextClient.py
@@ -11,6 +11,7 @@ from context.proto.context_pb2_grpc import ContextServiceStub
 LOGGER = logging.getLogger(__name__)
 MAX_RETRIES = 15
 DELAY_FUNCTION = delay_exponential(initial=0.01, increment=2.0, maximum=5.0)
+RETRY_DECORATOR = retry(max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
 
 class ContextClient:
     def __init__(self, address, port):
@@ -30,252 +31,252 @@ class ContextClient:
         self.channel = None
         self.stub = None
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def ListContextIds(self, request: Empty) -> ContextIdList:
         LOGGER.debug('ListContextIds request: {:s}'.format(str(request)))
         response = self.stub.ListContextIds(request)
         LOGGER.debug('ListContextIds result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def ListContexts(self, request: Empty) -> ContextList:
         LOGGER.debug('ListContexts request: {:s}'.format(str(request)))
         response = self.stub.ListContexts(request)
         LOGGER.debug('ListContexts result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def GetContext(self, request: ContextId) -> Context:
         LOGGER.debug('GetContext request: {:s}'.format(str(request)))
         response = self.stub.GetContext(request)
         LOGGER.debug('GetContext result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def SetContext(self, request: Context) -> ContextId:
         LOGGER.debug('SetContext request: {:s}'.format(str(request)))
         response = self.stub.SetContext(request)
         LOGGER.debug('SetContext result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def RemoveContext(self, request: ContextId) -> Empty:
         LOGGER.debug('RemoveContext request: {:s}'.format(str(request)))
         response = self.stub.RemoveContext(request)
         LOGGER.debug('RemoveContext result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def GetContextEvents(self, request: Empty) -> Iterator[ContextEvent]:
         LOGGER.debug('GetContextEvents request: {:s}'.format(str(request)))
         response = self.stub.GetContextEvents(request)
         LOGGER.debug('GetContextEvents result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def ListTopologyIds(self, request: ContextId) -> TopologyIdList:
         LOGGER.debug('ListTopologyIds request: {:s}'.format(str(request)))
         response = self.stub.ListTopologyIds(request)
         LOGGER.debug('ListTopologyIds result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def ListTopologies(self, request: ContextId) -> TopologyList:
         LOGGER.debug('ListTopologies request: {:s}'.format(str(request)))
         response = self.stub.ListTopologies(request)
         LOGGER.debug('ListTopologies result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def GetTopology(self, request: TopologyId) -> Topology:
         LOGGER.debug('GetTopology request: {:s}'.format(str(request)))
         response = self.stub.GetTopology(request)
         LOGGER.debug('GetTopology result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def SetTopology(self, request: Topology) -> TopologyId:
         LOGGER.debug('SetTopology request: {:s}'.format(str(request)))
         response = self.stub.SetTopology(request)
         LOGGER.debug('SetTopology result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def RemoveTopology(self, request: TopologyId) -> Empty:
         LOGGER.debug('RemoveTopology request: {:s}'.format(str(request)))
         response = self.stub.RemoveTopology(request)
         LOGGER.debug('RemoveTopology result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def GetTopologyEvents(self, request: Empty) -> Iterator[TopologyEvent]:
         LOGGER.debug('GetTopologyEvents request: {:s}'.format(str(request)))
         response = self.stub.GetTopologyEvents(request)
         LOGGER.debug('GetTopologyEvents result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def ListDeviceIds(self, request: Empty) -> DeviceIdList:
         LOGGER.debug('ListDeviceIds request: {:s}'.format(str(request)))
         response = self.stub.ListDeviceIds(request)
         LOGGER.debug('ListDeviceIds result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def ListDevices(self, request: Empty) -> DeviceList:
         LOGGER.debug('ListDevices request: {:s}'.format(str(request)))
         response = self.stub.ListDevices(request)
         LOGGER.debug('ListDevices result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def GetDevice(self, request: DeviceId) -> Device:
         LOGGER.debug('GetDevice request: {:s}'.format(str(request)))
         response = self.stub.GetDevice(request)
         LOGGER.debug('GetDevice result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def SetDevice(self, request: Device) -> DeviceId:
         LOGGER.debug('SetDevice request: {:s}'.format(str(request)))
         response = self.stub.SetDevice(request)
         LOGGER.debug('SetDevice result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def RemoveDevice(self, request: DeviceId) -> Empty:
         LOGGER.debug('RemoveDevice request: {:s}'.format(str(request)))
         response = self.stub.RemoveDevice(request)
         LOGGER.debug('RemoveDevice result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def GetDeviceEvents(self, request: Empty) -> Iterator[DeviceEvent]:
         LOGGER.debug('GetDeviceEvents request: {:s}'.format(str(request)))
         response = self.stub.GetDeviceEvents(request)
         LOGGER.debug('GetDeviceEvents result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def ListLinkIds(self, request: Empty) -> LinkIdList:
         LOGGER.debug('ListLinkIds request: {:s}'.format(str(request)))
         response = self.stub.ListLinkIds(request)
         LOGGER.debug('ListLinkIds result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def ListLinks(self, request: Empty) -> LinkList:
         LOGGER.debug('ListLinks request: {:s}'.format(str(request)))
         response = self.stub.ListLinks(request)
         LOGGER.debug('ListLinks result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def GetLink(self, request: LinkId) -> Link:
         LOGGER.debug('GetLink request: {:s}'.format(str(request)))
         response = self.stub.GetLink(request)
         LOGGER.debug('GetLink result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def SetLink(self, request: Link) -> LinkId:
         LOGGER.debug('SetLink request: {:s}'.format(str(request)))
         response = self.stub.SetLink(request)
         LOGGER.debug('SetLink result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def RemoveLink(self, request: LinkId) -> Empty:
         LOGGER.debug('RemoveLink request: {:s}'.format(str(request)))
         response = self.stub.RemoveLink(request)
         LOGGER.debug('RemoveLink result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def GetLinkEvents(self, request: Empty) -> Iterator[LinkEvent]:
         LOGGER.debug('GetLinkEvents request: {:s}'.format(str(request)))
         response = self.stub.GetLinkEvents(request)
         LOGGER.debug('GetLinkEvents result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def ListServiceIds(self, request: ContextId) -> ServiceIdList:
         LOGGER.debug('ListServiceIds request: {:s}'.format(str(request)))
         response = self.stub.ListServiceIds(request)
         LOGGER.debug('ListServiceIds result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def ListServices(self, request: ContextId) -> ServiceList:
         LOGGER.debug('ListServices request: {:s}'.format(str(request)))
         response = self.stub.ListServices(request)
         LOGGER.debug('ListServices result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def GetService(self, request: ServiceId) -> Service:
         LOGGER.debug('GetService request: {:s}'.format(str(request)))
         response = self.stub.GetService(request)
         LOGGER.debug('GetService result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def SetService(self, request: Service) -> ServiceId:
         LOGGER.debug('SetService request: {:s}'.format(str(request)))
         response = self.stub.SetService(request)
         LOGGER.debug('SetService result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def RemoveService(self, request: ServiceId) -> Empty:
         LOGGER.debug('RemoveService request: {:s}'.format(str(request)))
         response = self.stub.RemoveService(request)
         LOGGER.debug('RemoveService result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def GetServiceEvents(self, request: Empty) -> Iterator[ServiceEvent]:
         LOGGER.debug('GetServiceEvents request: {:s}'.format(str(request)))
         response = self.stub.GetServiceEvents(request)
         LOGGER.debug('GetServiceEvents result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def ListConnectionIds(self, request: ServiceId) -> ConnectionIdList:
         LOGGER.debug('ListConnectionIds request: {:s}'.format(str(request)))
         response = self.stub.ListConnectionIds(request)
         LOGGER.debug('ListConnectionIds result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def ListConnections(self, request: ServiceId) -> ConnectionList:
         LOGGER.debug('ListConnections request: {:s}'.format(str(request)))
         response = self.stub.ListConnections(request)
         LOGGER.debug('ListConnections result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def GetConnection(self, request: ConnectionId) -> Connection:
         LOGGER.debug('GetConnection request: {:s}'.format(str(request)))
         response = self.stub.GetConnection(request)
         LOGGER.debug('GetConnection result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def SetConnection(self, request: Connection) -> ConnectionId:
         LOGGER.debug('SetConnection request: {:s}'.format(str(request)))
         response = self.stub.SetConnection(request)
         LOGGER.debug('SetConnection result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def RemoveConnection(self, request: ConnectionId) -> Empty:
         LOGGER.debug('RemoveConnection request: {:s}'.format(str(request)))
         response = self.stub.RemoveConnection(request)
         LOGGER.debug('RemoveConnection result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def GetConnectionEvents(self, request: Empty) -> Iterator[ConnectionEvent]:
         LOGGER.debug('GetConnectionEvents request: {:s}'.format(str(request)))
         response = self.stub.GetConnectionEvents(request)
diff --git a/src/context/client/EventsCollector.py b/src/context/client/EventsCollector.py
new file mode 100644
index 000000000..3f0ce45fd
--- /dev/null
+++ b/src/context/client/EventsCollector.py
@@ -0,0 +1,80 @@
+import grpc, logging, queue, threading
+from common.tools.grpc.Tools import grpc_message_to_json_string
+from context.client.ContextClient import ContextClient
+from context.proto.context_pb2 import Empty
+
+LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.DEBUG)
+
+class EventsCollector:
+    def __init__(
+        self, context_client_grpc : ContextClient, log_events_received=False
+    ) -> None:
+        self._events_queue = queue.Queue()
+        self._log_events_received = log_events_received
+
+        self._context_stream    = context_client_grpc.GetContextEvents(Empty())
+        self._topology_stream   = context_client_grpc.GetTopologyEvents(Empty())
+        self._device_stream     = context_client_grpc.GetDeviceEvents(Empty())
+        self._link_stream       = context_client_grpc.GetLinkEvents(Empty())
+        self._service_stream    = context_client_grpc.GetServiceEvents(Empty())
+        self._connection_stream = context_client_grpc.GetConnectionEvents(Empty())
+
+        self._context_thread    = threading.Thread(target=self._collect, args=(self._context_stream   ,), daemon=False)
+        self._topology_thread   = threading.Thread(target=self._collect, args=(self._topology_stream  ,), daemon=False)
+        self._device_thread     = threading.Thread(target=self._collect, args=(self._device_stream    ,), daemon=False)
+        self._link_thread       = threading.Thread(target=self._collect, args=(self._link_stream      ,), daemon=False)
+        self._service_thread    = threading.Thread(target=self._collect, args=(self._service_stream   ,), daemon=False)
+        self._connection_thread = threading.Thread(target=self._collect, args=(self._connection_stream,), daemon=False)
+
+    def _collect(self, events_stream) -> None:
+        try:
+            for event in events_stream:
+                if self._log_events_received:
+                    LOGGER.info('[_collect] event: {:s}'.format(grpc_message_to_json_string(event)))
+                self._events_queue.put_nowait(event)
+        except grpc.RpcError as e:
+            if e.code() != grpc.StatusCode.CANCELLED: # pylint: disable=no-member
+                raise # pragma: no cover
+
+    def start(self):
+        self._context_thread.start()
+        self._topology_thread.start()
+        self._device_thread.start()
+        self._link_thread.start()
+        self._service_thread.start()
+        self._connection_thread.start()
+
+    def get_event(self, block : bool = True, timeout : float = 0.1):
+        return self._events_queue.get(block=block, timeout=timeout)
+
+    def get_events(self, block : bool = True, timeout : float = 0.1, count : int = None):
+        events = []
+        if count is None:
+            while True:
+                try:
+                    events.append(self.get_event(block=block, timeout=timeout))
+                except queue.Empty: # pylint: disable=catching-non-exception
+                    break
+        else:
+            for _ in range(count):
+                try:
+                    events.append(self.get_event(block=block, timeout=timeout))
+                except queue.Empty: # pylint: disable=catching-non-exception
+                    pass
+        return sorted(events, key=lambda e: e.event.timestamp)
+
+    def stop(self):
+        self._context_stream.cancel()
+        self._topology_stream.cancel()
+        self._device_stream.cancel()
+        self._link_stream.cancel()
+        self._service_stream.cancel()
+        self._connection_stream.cancel()
+
+        self._context_thread.join()
+        self._topology_thread.join()
+        self._device_thread.join()
+        self._link_thread.join()
+        self._service_thread.join()
+        self._connection_thread.join()
diff --git a/src/context/requirements.in b/src/context/requirements.in
index 86097934b..4c32f5c71 100644
--- a/src/context/requirements.in
+++ b/src/context/requirements.in
@@ -1,9 +1,11 @@
-flask-restful
-grpcio-health-checking
-grpcio
-prometheus-client
-pytest
-pytest-benchmark
-redis
-requests
-coverage
+Flask==2.0.2
+Flask-RESTful==0.3.9
+grpcio==1.43.0
+grpcio-health-checking==1.43.0
+prometheus-client==0.13.0
+protobuf==3.19.3
+pytest==6.2.5
+pytest-benchmark==3.4.1
+redis==4.1.2
+requests==2.27.1
+coverage==6.3
diff --git a/src/context/service/Populate.py b/src/context/service/Populate.py
index 91460b7ce..377a52fc2 100644
--- a/src/context/service/Populate.py
+++ b/src/context/service/Populate.py
@@ -1,35 +1,35 @@
 import copy
 from context.client.ContextClient import ContextClient
 from context.proto.context_pb2 import Connection, Context, Device, Link, Service, Topology
-from context.tests.example_objects import (
-    CONNECTION_DEV1_DEV3, CONTEXT, TOPOLOGY, DEVICE1, DEVICE1_ID, DEVICE2, DEVICE2_ID, DEVICE3, DEVICE3_ID,
-    LINK_DEV1_DEV2, LINK_DEV1_DEV2_ID, LINK_DEV1_DEV3, LINK_DEV1_DEV3_ID, LINK_DEV2_DEV3, LINK_DEV2_DEV3_ID,
-    SERVICE_DEV1_DEV2, SERVICE_DEV1_DEV3, SERVICE_DEV2_DEV3)
+from context.tests.Objects import (
+    CONNECTION_R1_R3, CONTEXT, TOPOLOGY, DEVICE_R1, DEVICE_R1_ID, DEVICE_R2, DEVICE_R2_ID, DEVICE_R3, DEVICE_R3_ID,
+    LINK_R1_R2, LINK_R1_R2_ID, LINK_R1_R3, LINK_R1_R3_ID, LINK_R2_R3, LINK_R2_R3_ID, SERVICE_R1_R2, SERVICE_R1_R3,
+    SERVICE_R2_R3)
 
 def populate(address, port):
     client = ContextClient(address=address, port=port)
 
     client.SetContext(Context(**CONTEXT))
     client.SetTopology(Topology(**TOPOLOGY))
-    client.SetDevice(Device(**DEVICE1))
-    client.SetDevice(Device(**DEVICE2))
-    client.SetDevice(Device(**DEVICE3))
+    client.SetDevice(Device(**DEVICE_R1))
+    client.SetDevice(Device(**DEVICE_R2))
+    client.SetDevice(Device(**DEVICE_R3))
 
-    client.SetLink(Link(**LINK_DEV1_DEV2))
-    client.SetLink(Link(**LINK_DEV1_DEV3))
-    client.SetLink(Link(**LINK_DEV2_DEV3))
+    client.SetLink(Link(**LINK_R1_R2))
+    client.SetLink(Link(**LINK_R1_R3))
+    client.SetLink(Link(**LINK_R2_R3))
 
     TOPOLOGY_WITH_DEVICES_AND_LINKS = copy.deepcopy(TOPOLOGY)
-    TOPOLOGY_WITH_DEVICES_AND_LINKS['device_ids'].append(DEVICE1_ID)
-    TOPOLOGY_WITH_DEVICES_AND_LINKS['device_ids'].append(DEVICE2_ID)
-    TOPOLOGY_WITH_DEVICES_AND_LINKS['device_ids'].append(DEVICE3_ID)
-    TOPOLOGY_WITH_DEVICES_AND_LINKS['link_ids'].append(LINK_DEV1_DEV2_ID)
-    TOPOLOGY_WITH_DEVICES_AND_LINKS['link_ids'].append(LINK_DEV1_DEV3_ID)
-    TOPOLOGY_WITH_DEVICES_AND_LINKS['link_ids'].append(LINK_DEV2_DEV3_ID)
+    TOPOLOGY_WITH_DEVICES_AND_LINKS['device_ids'].append(DEVICE_R1_ID)
+    TOPOLOGY_WITH_DEVICES_AND_LINKS['device_ids'].append(DEVICE_R2_ID)
+    TOPOLOGY_WITH_DEVICES_AND_LINKS['device_ids'].append(DEVICE_R3_ID)
+    TOPOLOGY_WITH_DEVICES_AND_LINKS['link_ids'].append(LINK_R1_R2_ID)
+    TOPOLOGY_WITH_DEVICES_AND_LINKS['link_ids'].append(LINK_R1_R3_ID)
+    TOPOLOGY_WITH_DEVICES_AND_LINKS['link_ids'].append(LINK_R2_R3_ID)
     client.SetTopology(Topology(**TOPOLOGY_WITH_DEVICES_AND_LINKS))
 
-    client.SetService(Service(**SERVICE_DEV1_DEV2))
-    client.SetService(Service(**SERVICE_DEV2_DEV3))
+    client.SetService(Service(**SERVICE_R1_R2))
+    client.SetService(Service(**SERVICE_R2_R3))
 
-    client.SetService(Service(**SERVICE_DEV1_DEV3))
-    client.SetConnection(Connection(**CONNECTION_DEV1_DEV3))
+    client.SetService(Service(**SERVICE_R1_R3))
+    client.SetConnection(Connection(**CONNECTION_R1_R3))
diff --git a/src/context/service/__main__.py b/src/context/service/__main__.py
index 495c203c9..8fc20ccb3 100644
--- a/src/context/service/__main__.py
+++ b/src/context/service/__main__.py
@@ -8,10 +8,10 @@ from common.message_broker.MessageBroker import MessageBroker
 from context.Config import (
     GRPC_SERVICE_PORT, GRPC_MAX_WORKERS, GRPC_GRACE_PERIOD, LOG_LEVEL, POPULATE_FAKE_DATA, RESTAPI_SERVICE_PORT,
     RESTAPI_BASE_URL, METRICS_PORT)
-from context.service.Populate import populate
-from context.service.grpc_server.ContextService import ContextService
-from context.service.rest_server.Server import Server
-from context.service.rest_server.Resources import RESOURCES
+from .grpc_server.ContextService import ContextService
+from .rest_server.Resources import RESOURCES
+from .rest_server.Server import Server
+from .Populate import populate
 
 terminate = threading.Event()
 LOGGER = None
diff --git a/src/context/service/grpc_server/ContextServiceServicerImpl.py b/src/context/service/grpc_server/ContextServiceServicerImpl.py
index 73c61f355..d035012d0 100644
--- a/src/context/service/grpc_server/ContextServiceServicerImpl.py
+++ b/src/context/service/grpc_server/ContextServiceServicerImpl.py
@@ -1,4 +1,4 @@
-import grpc, json, logging, operator
+import grpc, json, logging, operator, threading
 from typing import Iterator, List, Set, Tuple
 from common.message_broker.MessageBroker import MessageBroker
 from common.orm.Database import Database
@@ -27,7 +27,7 @@ from context.service.database.RelationModels import (
 from context.service.database.ServiceModel import (
     ServiceModel, grpc_to_enum__service_status, grpc_to_enum__service_type)
 from context.service.database.TopologyModel import TopologyModel
-from context.service.grpc_server.Constants import (
+from .Constants import (
     CONSUME_TIMEOUT, TOPIC_CONNECTION, TOPIC_CONTEXT, TOPIC_DEVICE, TOPIC_LINK, TOPIC_SERVICE, TOPIC_TOPOLOGY)
 
 LOGGER = logging.getLogger(__name__)
@@ -46,6 +46,7 @@ METRICS = create_metrics(SERVICE_NAME, METHOD_NAMES)
 class ContextServiceServicerImpl(ContextServiceServicer):
     def __init__(self, database : Database, messagebroker : MessageBroker):
         LOGGER.debug('Creating Servicer...')
+        self.lock = threading.Lock()
         self.database = database
         self.messagebroker = messagebroker
         LOGGER.debug('Servicer Created')
@@ -55,71 +56,76 @@ class ContextServiceServicerImpl(ContextServiceServicer):
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def ListContextIds(self, request: Empty, context : grpc.ServicerContext) -> ContextIdList:
-        db_contexts : List[ContextModel] = get_all_objects(self.database, ContextModel)
-        db_contexts = sorted(db_contexts, key=operator.attrgetter('pk'))
-        return ContextIdList(context_ids=[db_context.dump_id() for db_context in db_contexts])
+        with self.lock:
+            db_contexts : List[ContextModel] = get_all_objects(self.database, ContextModel)
+            db_contexts = sorted(db_contexts, key=operator.attrgetter('pk'))
+            return ContextIdList(context_ids=[db_context.dump_id() for db_context in db_contexts])
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def ListContexts(self, request: Empty, context : grpc.ServicerContext) -> ContextList:
-        db_contexts : List[ContextModel] = get_all_objects(self.database, ContextModel)
-        db_contexts = sorted(db_contexts, key=operator.attrgetter('pk'))
-        return ContextList(contexts=[db_context.dump() for db_context in db_contexts])
+        with self.lock:
+            db_contexts : List[ContextModel] = get_all_objects(self.database, ContextModel)
+            db_contexts = sorted(db_contexts, key=operator.attrgetter('pk'))
+            return ContextList(contexts=[db_context.dump() for db_context in db_contexts])
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def GetContext(self, request: ContextId, context : grpc.ServicerContext) -> Context:
-        context_uuid = request.context_uuid.uuid
-        db_context : ContextModel = get_object(self.database, ContextModel, context_uuid)
-        return Context(**db_context.dump(include_services=True, include_topologies=True))
+        with self.lock:
+            context_uuid = request.context_uuid.uuid
+            db_context : ContextModel = get_object(self.database, ContextModel, context_uuid)
+            return Context(**db_context.dump(include_services=True, include_topologies=True))
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def SetContext(self, request: Context, context : grpc.ServicerContext) -> ContextId:
-        context_uuid = request.context_id.context_uuid.uuid
-
-        for i,topology_id in enumerate(request.topology_ids):
-            topology_context_uuid = topology_id.context_id.context_uuid.uuid
-            if topology_context_uuid != context_uuid:
-                raise InvalidArgumentException(
-                    'request.topology_ids[{:d}].context_id.context_uuid.uuid'.format(i), topology_context_uuid,
-                    ['should be == {:s}({:s})'.format('request.context_id.context_uuid.uuid', context_uuid)])
-
-        for i,service_id in enumerate(request.service_ids):
-            service_context_uuid = service_id.context_id.context_uuid.uuid
-            if service_context_uuid != context_uuid:
-                raise InvalidArgumentException(
-                    'request.service_ids[{:d}].context_id.context_uuid.uuid'.format(i), service_context_uuid,
-                    ['should be == {:s}({:s})'.format('request.context_id.context_uuid.uuid', context_uuid)])
-
-        result : Tuple[ContextModel, bool] = update_or_create_object(
-            self.database, ContextModel, context_uuid, {'context_uuid': context_uuid})
-        db_context, updated = result
-
-        for i,topology_id in enumerate(request.topology_ids):
-            topology_context_uuid = topology_id.context_id.context_uuid.uuid
-            topology_uuid = topology_id.topology_uuid.uuid
-            get_object(self.database, TopologyModel, [context_uuid, topology_uuid]) # just to confirm it exists
-
-        for i,service_id in enumerate(request.service_ids):
-            service_context_uuid = service_id.context_id.context_uuid.uuid
-            service_uuid = service_id.service_uuid.uuid
-            get_object(self.database, ServiceModel, [context_uuid, service_uuid]) # just to confirm it exists
-
-        event_type = EventTypeEnum.EVENTTYPE_UPDATE if updated else EventTypeEnum.EVENTTYPE_CREATE
-        dict_context_id = db_context.dump_id()
-        notify_event(self.messagebroker, TOPIC_CONTEXT, event_type, {'context_id': dict_context_id})
-        return ContextId(**dict_context_id)
+        with self.lock:
+            context_uuid = request.context_id.context_uuid.uuid
+
+            for i,topology_id in enumerate(request.topology_ids):
+                topology_context_uuid = topology_id.context_id.context_uuid.uuid
+                if topology_context_uuid != context_uuid:
+                    raise InvalidArgumentException(
+                        'request.topology_ids[{:d}].context_id.context_uuid.uuid'.format(i), topology_context_uuid,
+                        ['should be == {:s}({:s})'.format('request.context_id.context_uuid.uuid', context_uuid)])
+
+            for i,service_id in enumerate(request.service_ids):
+                service_context_uuid = service_id.context_id.context_uuid.uuid
+                if service_context_uuid != context_uuid:
+                    raise InvalidArgumentException(
+                        'request.service_ids[{:d}].context_id.context_uuid.uuid'.format(i), service_context_uuid,
+                        ['should be == {:s}({:s})'.format('request.context_id.context_uuid.uuid', context_uuid)])
+
+            result : Tuple[ContextModel, bool] = update_or_create_object(
+                self.database, ContextModel, context_uuid, {'context_uuid': context_uuid})
+            db_context, updated = result
+
+            for i,topology_id in enumerate(request.topology_ids):
+                topology_context_uuid = topology_id.context_id.context_uuid.uuid
+                topology_uuid = topology_id.topology_uuid.uuid
+                get_object(self.database, TopologyModel, [context_uuid, topology_uuid]) # just to confirm it exists
+
+            for i,service_id in enumerate(request.service_ids):
+                service_context_uuid = service_id.context_id.context_uuid.uuid
+                service_uuid = service_id.service_uuid.uuid
+                get_object(self.database, ServiceModel, [context_uuid, service_uuid]) # just to confirm it exists
+
+            event_type = EventTypeEnum.EVENTTYPE_UPDATE if updated else EventTypeEnum.EVENTTYPE_CREATE
+            dict_context_id = db_context.dump_id()
+            notify_event(self.messagebroker, TOPIC_CONTEXT, event_type, {'context_id': dict_context_id})
+            return ContextId(**dict_context_id)
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def RemoveContext(self, request: ContextId, context : grpc.ServicerContext) -> Empty:
-        context_uuid = request.context_uuid.uuid
-        db_context = ContextModel(self.database, context_uuid, auto_load=False)
-        found = db_context.load()
-        if not found: return Empty()
+        with self.lock:
+            context_uuid = request.context_uuid.uuid
+            db_context = ContextModel(self.database, context_uuid, auto_load=False)
+            found = db_context.load()
+            if not found: return Empty()
 
-        dict_context_id = db_context.dump_id()
-        db_context.delete()
-        event_type = EventTypeEnum.EVENTTYPE_REMOVE
-        notify_event(self.messagebroker, TOPIC_CONTEXT, event_type, {'context_id': dict_context_id})
-        return Empty()
+            dict_context_id = db_context.dump_id()
+            db_context.delete()
+            event_type = EventTypeEnum.EVENTTYPE_REMOVE
+            notify_event(self.messagebroker, TOPIC_CONTEXT, event_type, {'context_id': dict_context_id})
+            return Empty()
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def GetContextEvents(self, request: Empty, context : grpc.ServicerContext) -> Iterator[ContextEvent]:
@@ -131,74 +137,79 @@ class ContextServiceServicerImpl(ContextServiceServicer):
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def ListTopologyIds(self, request: ContextId, context : grpc.ServicerContext) -> TopologyIdList:
-        context_uuid = request.context_uuid.uuid
-        db_context : ContextModel = get_object(self.database, ContextModel, context_uuid)
-        db_topologies : Set[TopologyModel] = get_related_objects(db_context, TopologyModel)
-        db_topologies = sorted(db_topologies, key=operator.attrgetter('pk'))
-        return TopologyIdList(topology_ids=[db_topology.dump_id() for db_topology in db_topologies])
+        with self.lock:
+            context_uuid = request.context_uuid.uuid
+            db_context : ContextModel = get_object(self.database, ContextModel, context_uuid)
+            db_topologies : Set[TopologyModel] = get_related_objects(db_context, TopologyModel)
+            db_topologies = sorted(db_topologies, key=operator.attrgetter('pk'))
+            return TopologyIdList(topology_ids=[db_topology.dump_id() for db_topology in db_topologies])
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def ListTopologies(self, request: ContextId, context : grpc.ServicerContext) -> TopologyList:
-        context_uuid = request.context_uuid.uuid
-        db_context : ContextModel = get_object(self.database, ContextModel, context_uuid)
-        db_topologies : Set[TopologyModel] = get_related_objects(db_context, TopologyModel)
-        db_topologies = sorted(db_topologies, key=operator.attrgetter('pk'))
-        return TopologyList(topologies=[db_topology.dump() for db_topology in db_topologies])
+        with self.lock:
+            context_uuid = request.context_uuid.uuid
+            db_context : ContextModel = get_object(self.database, ContextModel, context_uuid)
+            db_topologies : Set[TopologyModel] = get_related_objects(db_context, TopologyModel)
+            db_topologies = sorted(db_topologies, key=operator.attrgetter('pk'))
+            return TopologyList(topologies=[db_topology.dump() for db_topology in db_topologies])
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def GetTopology(self, request: TopologyId, context : grpc.ServicerContext) -> Topology:
-        str_key = key_to_str([request.context_id.context_uuid.uuid, request.topology_uuid.uuid])
-        db_topology : TopologyModel = get_object(self.database, TopologyModel, str_key)
-        return Topology(**db_topology.dump(include_devices=True, include_links=True))
+        with self.lock:
+            str_key = key_to_str([request.context_id.context_uuid.uuid, request.topology_uuid.uuid])
+            db_topology : TopologyModel = get_object(self.database, TopologyModel, str_key)
+            return Topology(**db_topology.dump(include_devices=True, include_links=True))
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def SetTopology(self, request: Topology, context : grpc.ServicerContext) -> TopologyId:
-        context_uuid = request.topology_id.context_id.context_uuid.uuid
-        db_context : ContextModel = get_object(self.database, ContextModel, context_uuid)
-
-        topology_uuid = request.topology_id.topology_uuid.uuid
-        str_topology_key = key_to_str([context_uuid, topology_uuid])
-        result : Tuple[TopologyModel, bool] = update_or_create_object(
-            self.database, TopologyModel, str_topology_key, {'context_fk': db_context, 'topology_uuid': topology_uuid})
-        db_topology,updated = result
-
-        for device_id in request.device_ids:
-            device_uuid = device_id.device_uuid.uuid
-            db_device = get_object(self.database, DeviceModel, device_uuid)
-            str_topology_device_key = key_to_str([str_topology_key, device_uuid], separator='--')
-            result : Tuple[TopologyDeviceModel, bool] = update_or_create_object(
-                self.database, TopologyDeviceModel, str_topology_device_key,
-                {'topology_fk': db_topology, 'device_fk': db_device})
-            #db_topology_device,topology_device_updated = result
-
-        for link_id in request.link_ids:
-            link_uuid = link_id.link_uuid.uuid
-            db_link = get_object(self.database, LinkModel, link_uuid)
-
-            str_topology_link_key = key_to_str([str_topology_key, link_uuid], separator='--')
-            result : Tuple[TopologyLinkModel, bool] = update_or_create_object(
-                self.database, TopologyLinkModel, str_topology_link_key,
-                {'topology_fk': db_topology, 'link_fk': db_link})
-            #db_topology_link,topology_link_updated = result
-
-        event_type = EventTypeEnum.EVENTTYPE_UPDATE if updated else EventTypeEnum.EVENTTYPE_CREATE
-        dict_topology_id = db_topology.dump_id()
-        notify_event(self.messagebroker, TOPIC_TOPOLOGY, event_type, {'topology_id': dict_topology_id})
-        return TopologyId(**dict_topology_id)
+        with self.lock:
+            context_uuid = request.topology_id.context_id.context_uuid.uuid
+            db_context : ContextModel = get_object(self.database, ContextModel, context_uuid)
+
+            topology_uuid = request.topology_id.topology_uuid.uuid
+            str_topology_key = key_to_str([context_uuid, topology_uuid])
+            result : Tuple[TopologyModel, bool] = update_or_create_object(
+                self.database, TopologyModel, str_topology_key, {'context_fk': db_context, 'topology_uuid': topology_uuid})
+            db_topology,updated = result
+
+            for device_id in request.device_ids:
+                device_uuid = device_id.device_uuid.uuid
+                db_device = get_object(self.database, DeviceModel, device_uuid)
+                str_topology_device_key = key_to_str([str_topology_key, device_uuid], separator='--')
+                result : Tuple[TopologyDeviceModel, bool] = update_or_create_object(
+                    self.database, TopologyDeviceModel, str_topology_device_key,
+                    {'topology_fk': db_topology, 'device_fk': db_device})
+                #db_topology_device,topology_device_updated = result
+
+            for link_id in request.link_ids:
+                link_uuid = link_id.link_uuid.uuid
+                db_link = get_object(self.database, LinkModel, link_uuid)
+
+                str_topology_link_key = key_to_str([str_topology_key, link_uuid], separator='--')
+                result : Tuple[TopologyLinkModel, bool] = update_or_create_object(
+                    self.database, TopologyLinkModel, str_topology_link_key,
+                    {'topology_fk': db_topology, 'link_fk': db_link})
+                #db_topology_link,topology_link_updated = result
+
+            event_type = EventTypeEnum.EVENTTYPE_UPDATE if updated else EventTypeEnum.EVENTTYPE_CREATE
+            dict_topology_id = db_topology.dump_id()
+            notify_event(self.messagebroker, TOPIC_TOPOLOGY, event_type, {'topology_id': dict_topology_id})
+            return TopologyId(**dict_topology_id)
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def RemoveTopology(self, request: TopologyId, context : grpc.ServicerContext) -> Empty:
-        context_uuid = request.context_id.context_uuid.uuid
-        topology_uuid = request.topology_uuid.uuid
-        db_topology = TopologyModel(self.database, key_to_str([context_uuid, topology_uuid]), auto_load=False)
-        found = db_topology.load()
-        if not found: return Empty()
+        with self.lock:
+            context_uuid = request.context_id.context_uuid.uuid
+            topology_uuid = request.topology_uuid.uuid
+            db_topology = TopologyModel(self.database, key_to_str([context_uuid, topology_uuid]), auto_load=False)
+            found = db_topology.load()
+            if not found: return Empty()
 
-        dict_topology_id = db_topology.dump_id()
-        db_topology.delete()
-        event_type = EventTypeEnum.EVENTTYPE_REMOVE
-        notify_event(self.messagebroker, TOPIC_TOPOLOGY, event_type, {'topology_id': dict_topology_id})
-        return Empty()
+            dict_topology_id = db_topology.dump_id()
+            db_topology.delete()
+            event_type = EventTypeEnum.EVENTTYPE_REMOVE
+            notify_event(self.messagebroker, TOPIC_TOPOLOGY, event_type, {'topology_id': dict_topology_id})
+            return Empty()
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def GetTopologyEvents(self, request: Empty, context : grpc.ServicerContext) -> Iterator[TopologyEvent]:
@@ -210,118 +221,123 @@ class ContextServiceServicerImpl(ContextServiceServicer):
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def ListDeviceIds(self, request: Empty, context : grpc.ServicerContext) -> DeviceIdList:
-        db_devices : List[DeviceModel] = get_all_objects(self.database, DeviceModel)
-        db_devices = sorted(db_devices, key=operator.attrgetter('pk'))
-        return DeviceIdList(device_ids=[db_device.dump_id() for db_device in db_devices])
+        with self.lock:
+            db_devices : List[DeviceModel] = get_all_objects(self.database, DeviceModel)
+            db_devices = sorted(db_devices, key=operator.attrgetter('pk'))
+            return DeviceIdList(device_ids=[db_device.dump_id() for db_device in db_devices])
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def ListDevices(self, request: Empty, context : grpc.ServicerContext) -> DeviceList:
-        db_devices : List[DeviceModel] = get_all_objects(self.database, DeviceModel)
-        db_devices = sorted(db_devices, key=operator.attrgetter('pk'))
-        return DeviceList(devices=[db_device.dump() for db_device in db_devices])
+        with self.lock:
+            db_devices : List[DeviceModel] = get_all_objects(self.database, DeviceModel)
+            db_devices = sorted(db_devices, key=operator.attrgetter('pk'))
+            return DeviceList(devices=[db_device.dump() for db_device in db_devices])
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def GetDevice(self, request: DeviceId, context : grpc.ServicerContext) -> Device:
-        device_uuid = request.device_uuid.uuid
-        db_device : DeviceModel = get_object(self.database, DeviceModel, device_uuid)
-        return Device(**db_device.dump(
-            include_config_rules=True, include_drivers=True, include_endpoints=True))
+        with self.lock:
+            device_uuid = request.device_uuid.uuid
+            db_device : DeviceModel = get_object(self.database, DeviceModel, device_uuid)
+            return Device(**db_device.dump(
+                include_config_rules=True, include_drivers=True, include_endpoints=True))
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def SetDevice(self, request: Device, context : grpc.ServicerContext) -> DeviceId:
-        device_uuid = request.device_id.device_uuid.uuid
-
-        for i,endpoint in enumerate(request.device_endpoints):
-            endpoint_device_uuid = endpoint.endpoint_id.device_id.device_uuid.uuid
-            if len(endpoint_device_uuid) == 0: endpoint_device_uuid = device_uuid
-            if device_uuid != endpoint_device_uuid:
-                raise InvalidArgumentException(
-                    'request.device_endpoints[{:d}].device_id.device_uuid.uuid'.format(i), endpoint_device_uuid,
-                    ['should be == {:s}({:s})'.format('request.device_id.device_uuid.uuid', device_uuid)])
-
-        config_rules = grpc_config_rules_to_raw(request.device_config.config_rules)
-        running_config_result = update_config(self.database, device_uuid, 'running', config_rules)
-        db_running_config = running_config_result[0][0]
-
-        result : Tuple[DeviceModel, bool] = update_or_create_object(self.database, DeviceModel, device_uuid, {
-            'device_uuid'              : device_uuid,
-            'device_type'              : request.device_type,
-            'device_operational_status': grpc_to_enum__device_operational_status(request.device_operational_status),
-            'device_config_fk'         : db_running_config,
-        })
-        db_device, updated = result
-
-        set_drivers(self.database, db_device, request.device_drivers)
-
-        for i,endpoint in enumerate(request.device_endpoints):
-            endpoint_uuid = endpoint.endpoint_id.endpoint_uuid.uuid
-            endpoint_device_uuid = endpoint.endpoint_id.device_id.device_uuid.uuid
-            if len(endpoint_device_uuid) == 0: endpoint_device_uuid = device_uuid
-
-            str_endpoint_key = key_to_str([device_uuid, endpoint_uuid])
-            endpoint_attributes = {
-                'device_fk'    : db_device,
-                'endpoint_uuid': endpoint_uuid,
-                'endpoint_type': endpoint.endpoint_type,
-            }
-
-            endpoint_topology_context_uuid = endpoint.endpoint_id.topology_id.context_id.context_uuid.uuid
-            endpoint_topology_uuid = endpoint.endpoint_id.topology_id.topology_uuid.uuid
-            if len(endpoint_topology_context_uuid) > 0 and len(endpoint_topology_uuid) > 0:
-                str_topology_key = key_to_str([endpoint_topology_context_uuid, endpoint_topology_uuid])
-                db_topology : TopologyModel = get_object(self.database, TopologyModel, str_topology_key)
-
-                str_topology_device_key = key_to_str([str_topology_key, device_uuid], separator='--')
-                result : Tuple[TopologyDeviceModel, bool] = get_or_create_object(
-                    self.database, TopologyDeviceModel, str_topology_device_key, {
-                        'topology_fk': db_topology, 'device_fk': db_device})
-                #db_topology_device, topology_device_created = result
-
-                str_endpoint_key = key_to_str([str_endpoint_key, str_topology_key], separator=':')
-                endpoint_attributes['topology_fk'] = db_topology
-
-            result : Tuple[EndPointModel, bool] = update_or_create_object(
-                self.database, EndPointModel, str_endpoint_key, endpoint_attributes)
-            db_endpoint, endpoint_updated = result
-
-            set_kpi_sample_types(self.database, db_endpoint, endpoint.kpi_sample_types)
-
-        event_type = EventTypeEnum.EVENTTYPE_UPDATE if updated else EventTypeEnum.EVENTTYPE_CREATE
-        dict_device_id = db_device.dump_id()
-        notify_event(self.messagebroker, TOPIC_DEVICE, event_type, {'device_id': dict_device_id})
-        return DeviceId(**dict_device_id)
+        with self.lock:
+            device_uuid = request.device_id.device_uuid.uuid
+
+            for i,endpoint in enumerate(request.device_endpoints):
+                endpoint_device_uuid = endpoint.endpoint_id.device_id.device_uuid.uuid
+                if len(endpoint_device_uuid) == 0: endpoint_device_uuid = device_uuid
+                if device_uuid != endpoint_device_uuid:
+                    raise InvalidArgumentException(
+                        'request.device_endpoints[{:d}].device_id.device_uuid.uuid'.format(i), endpoint_device_uuid,
+                        ['should be == {:s}({:s})'.format('request.device_id.device_uuid.uuid', device_uuid)])
+
+            config_rules = grpc_config_rules_to_raw(request.device_config.config_rules)
+            running_config_result = update_config(self.database, device_uuid, 'running', config_rules)
+            db_running_config = running_config_result[0][0]
+
+            result : Tuple[DeviceModel, bool] = update_or_create_object(self.database, DeviceModel, device_uuid, {
+                'device_uuid'              : device_uuid,
+                'device_type'              : request.device_type,
+                'device_operational_status': grpc_to_enum__device_operational_status(request.device_operational_status),
+                'device_config_fk'         : db_running_config,
+            })
+            db_device, updated = result
+
+            set_drivers(self.database, db_device, request.device_drivers)
+
+            for i,endpoint in enumerate(request.device_endpoints):
+                endpoint_uuid = endpoint.endpoint_id.endpoint_uuid.uuid
+                endpoint_device_uuid = endpoint.endpoint_id.device_id.device_uuid.uuid
+                if len(endpoint_device_uuid) == 0: endpoint_device_uuid = device_uuid
+
+                str_endpoint_key = key_to_str([device_uuid, endpoint_uuid])
+                endpoint_attributes = {
+                    'device_fk'    : db_device,
+                    'endpoint_uuid': endpoint_uuid,
+                    'endpoint_type': endpoint.endpoint_type,
+                }
+
+                endpoint_topology_context_uuid = endpoint.endpoint_id.topology_id.context_id.context_uuid.uuid
+                endpoint_topology_uuid = endpoint.endpoint_id.topology_id.topology_uuid.uuid
+                if len(endpoint_topology_context_uuid) > 0 and len(endpoint_topology_uuid) > 0:
+                    str_topology_key = key_to_str([endpoint_topology_context_uuid, endpoint_topology_uuid])
+                    db_topology : TopologyModel = get_object(self.database, TopologyModel, str_topology_key)
+
+                    str_topology_device_key = key_to_str([str_topology_key, device_uuid], separator='--')
+                    result : Tuple[TopologyDeviceModel, bool] = get_or_create_object(
+                        self.database, TopologyDeviceModel, str_topology_device_key, {
+                            'topology_fk': db_topology, 'device_fk': db_device})
+                    #db_topology_device, topology_device_created = result
+
+                    str_endpoint_key = key_to_str([str_endpoint_key, str_topology_key], separator=':')
+                    endpoint_attributes['topology_fk'] = db_topology
+
+                result : Tuple[EndPointModel, bool] = update_or_create_object(
+                    self.database, EndPointModel, str_endpoint_key, endpoint_attributes)
+                db_endpoint, endpoint_updated = result
+
+                set_kpi_sample_types(self.database, db_endpoint, endpoint.kpi_sample_types)
+
+            event_type = EventTypeEnum.EVENTTYPE_UPDATE if updated else EventTypeEnum.EVENTTYPE_CREATE
+            dict_device_id = db_device.dump_id()
+            notify_event(self.messagebroker, TOPIC_DEVICE, event_type, {'device_id': dict_device_id})
+            return DeviceId(**dict_device_id)
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def RemoveDevice(self, request: DeviceId, context : grpc.ServicerContext) -> Empty:
-        device_uuid = request.device_uuid.uuid
-        db_device = DeviceModel(self.database, device_uuid, auto_load=False)
-        found = db_device.load()
-        if not found: return Empty()
+        with self.lock:
+            device_uuid = request.device_uuid.uuid
+            db_device = DeviceModel(self.database, device_uuid, auto_load=False)
+            found = db_device.load()
+            if not found: return Empty()
 
-        dict_device_id = db_device.dump_id()
+            dict_device_id = db_device.dump_id()
 
-        for db_endpoint_pk,_ in db_device.references(EndPointModel):
-            db_endpoint = EndPointModel(self.database, db_endpoint_pk)
-            for db_kpi_sample_type_pk,_ in db_endpoint.references(KpiSampleTypeModel):
-                KpiSampleTypeModel(self.database, db_kpi_sample_type_pk).delete()
-            db_endpoint.delete()
+            for db_endpoint_pk,_ in db_device.references(EndPointModel):
+                db_endpoint = EndPointModel(self.database, db_endpoint_pk)
+                for db_kpi_sample_type_pk,_ in db_endpoint.references(KpiSampleTypeModel):
+                    KpiSampleTypeModel(self.database, db_kpi_sample_type_pk).delete()
+                db_endpoint.delete()
 
-        for db_topology_device_pk,_ in db_device.references(TopologyDeviceModel):
-            TopologyDeviceModel(self.database, db_topology_device_pk).delete()
+            for db_topology_device_pk,_ in db_device.references(TopologyDeviceModel):
+                TopologyDeviceModel(self.database, db_topology_device_pk).delete()
 
-        for db_driver_pk,_ in db_device.references(DriverModel):
-            DriverModel(self.database, db_driver_pk).delete()
+            for db_driver_pk,_ in db_device.references(DriverModel):
+                DriverModel(self.database, db_driver_pk).delete()
 
-        db_config = ConfigModel(self.database, db_device.device_config_fk)
-        for db_config_rule_pk,_ in db_config.references(ConfigRuleModel):
-            ConfigRuleModel(self.database, db_config_rule_pk).delete()
+            db_config = ConfigModel(self.database, db_device.device_config_fk)
+            for db_config_rule_pk,_ in db_config.references(ConfigRuleModel):
+                ConfigRuleModel(self.database, db_config_rule_pk).delete()
 
-        db_device.delete()
-        db_config.delete()
+            db_device.delete()
+            db_config.delete()
 
-        event_type = EventTypeEnum.EVENTTYPE_REMOVE
-        notify_event(self.messagebroker, TOPIC_DEVICE, event_type, {'device_id': dict_device_id})
-        return Empty()
+            event_type = EventTypeEnum.EVENTTYPE_REMOVE
+            notify_event(self.messagebroker, TOPIC_DEVICE, event_type, {'device_id': dict_device_id})
+            return Empty()
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def GetDeviceEvents(self, request: Empty, context : grpc.ServicerContext) -> Iterator[DeviceEvent]:
@@ -333,84 +349,89 @@ class ContextServiceServicerImpl(ContextServiceServicer):
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def ListLinkIds(self, request: Empty, context : grpc.ServicerContext) -> LinkIdList:
-        db_links : List[LinkModel] = get_all_objects(self.database, LinkModel)
-        db_links = sorted(db_links, key=operator.attrgetter('pk'))
-        return LinkIdList(link_ids=[db_link.dump_id() for db_link in db_links])
+        with self.lock:
+            db_links : List[LinkModel] = get_all_objects(self.database, LinkModel)
+            db_links = sorted(db_links, key=operator.attrgetter('pk'))
+            return LinkIdList(link_ids=[db_link.dump_id() for db_link in db_links])
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def ListLinks(self, request: Empty, context : grpc.ServicerContext) -> LinkList:
-        db_links : List[LinkModel] = get_all_objects(self.database, LinkModel)
-        db_links = sorted(db_links, key=operator.attrgetter('pk'))
-        return LinkList(links=[db_link.dump() for db_link in db_links])
+        with self.lock:
+            db_links : List[LinkModel] = get_all_objects(self.database, LinkModel)
+            db_links = sorted(db_links, key=operator.attrgetter('pk'))
+            return LinkList(links=[db_link.dump() for db_link in db_links])
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def GetLink(self, request: LinkId, context : grpc.ServicerContext) -> Link:
-        link_uuid = request.link_uuid.uuid
-        db_link : LinkModel = get_object(self.database, LinkModel, link_uuid)
-        return Link(**db_link.dump())
+        with self.lock:
+            link_uuid = request.link_uuid.uuid
+            db_link : LinkModel = get_object(self.database, LinkModel, link_uuid)
+            return Link(**db_link.dump())
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def SetLink(self, request: Link, context : grpc.ServicerContext) -> LinkId:
-        link_uuid = request.link_id.link_uuid.uuid
-        result : Tuple[LinkModel, bool] = update_or_create_object(
-            self.database, LinkModel, link_uuid, {'link_uuid': link_uuid})
-        db_link, updated = result
-
-        for endpoint_id in request.link_endpoint_ids:
-            endpoint_uuid                  = endpoint_id.endpoint_uuid.uuid
-            endpoint_device_uuid           = endpoint_id.device_id.device_uuid.uuid
-            endpoint_topology_uuid         = endpoint_id.topology_id.topology_uuid.uuid
-            endpoint_topology_context_uuid = endpoint_id.topology_id.context_id.context_uuid.uuid
-
-            str_endpoint_key = key_to_str([endpoint_device_uuid, endpoint_uuid])
-
-            db_topology = None
-            if len(endpoint_topology_context_uuid) > 0 and len(endpoint_topology_uuid) > 0:
-                str_topology_key = key_to_str([endpoint_topology_context_uuid, endpoint_topology_uuid])
-                db_topology : TopologyModel = get_object(self.database, TopologyModel, str_topology_key)
-                str_topology_device_key = key_to_str([str_topology_key, endpoint_device_uuid], separator='--')
-                get_object(self.database, TopologyDeviceModel, str_topology_device_key) # check device is in topology
-                str_endpoint_key = key_to_str([str_endpoint_key, str_topology_key], separator=':')
-
-            db_endpoint : EndPointModel = get_object(self.database, EndPointModel, str_endpoint_key)
-
-            str_link_endpoint_key = key_to_str([link_uuid, endpoint_device_uuid], separator='--')
-            result : Tuple[LinkEndPointModel, bool] = get_or_create_object(
-                self.database, LinkEndPointModel, str_link_endpoint_key, {
-                    'link_fk': db_link, 'endpoint_fk': db_endpoint})
-            #db_link_endpoint, link_endpoint_created = result
-
-            if db_topology is not None:
-                str_topology_link_key = key_to_str([str_topology_key, link_uuid], separator='--')
-                result : Tuple[TopologyLinkModel, bool] = get_or_create_object(
-                    self.database, TopologyLinkModel, str_topology_link_key, {
-                        'topology_fk': db_topology, 'link_fk': db_link})
-                #db_topology_link, topology_link_created = result
-
-        event_type = EventTypeEnum.EVENTTYPE_UPDATE if updated else EventTypeEnum.EVENTTYPE_CREATE
-        dict_link_id = db_link.dump_id()
-        notify_event(self.messagebroker, TOPIC_LINK, event_type, {'link_id': dict_link_id})
-        return LinkId(**dict_link_id)
+        with self.lock:
+            link_uuid = request.link_id.link_uuid.uuid
+            result : Tuple[LinkModel, bool] = update_or_create_object(
+                self.database, LinkModel, link_uuid, {'link_uuid': link_uuid})
+            db_link, updated = result
+
+            for endpoint_id in request.link_endpoint_ids:
+                endpoint_uuid                  = endpoint_id.endpoint_uuid.uuid
+                endpoint_device_uuid           = endpoint_id.device_id.device_uuid.uuid
+                endpoint_topology_uuid         = endpoint_id.topology_id.topology_uuid.uuid
+                endpoint_topology_context_uuid = endpoint_id.topology_id.context_id.context_uuid.uuid
+
+                str_endpoint_key = key_to_str([endpoint_device_uuid, endpoint_uuid])
+
+                db_topology = None
+                if len(endpoint_topology_context_uuid) > 0 and len(endpoint_topology_uuid) > 0:
+                    str_topology_key = key_to_str([endpoint_topology_context_uuid, endpoint_topology_uuid])
+                    db_topology : TopologyModel = get_object(self.database, TopologyModel, str_topology_key)
+                    str_topology_device_key = key_to_str([str_topology_key, endpoint_device_uuid], separator='--')
+                    get_object(self.database, TopologyDeviceModel, str_topology_device_key) # check device is in topology
+                    str_endpoint_key = key_to_str([str_endpoint_key, str_topology_key], separator=':')
+
+                db_endpoint : EndPointModel = get_object(self.database, EndPointModel, str_endpoint_key)
+
+                str_link_endpoint_key = key_to_str([link_uuid, endpoint_device_uuid], separator='--')
+                result : Tuple[LinkEndPointModel, bool] = get_or_create_object(
+                    self.database, LinkEndPointModel, str_link_endpoint_key, {
+                        'link_fk': db_link, 'endpoint_fk': db_endpoint})
+                #db_link_endpoint, link_endpoint_created = result
+
+                if db_topology is not None:
+                    str_topology_link_key = key_to_str([str_topology_key, link_uuid], separator='--')
+                    result : Tuple[TopologyLinkModel, bool] = get_or_create_object(
+                        self.database, TopologyLinkModel, str_topology_link_key, {
+                            'topology_fk': db_topology, 'link_fk': db_link})
+                    #db_topology_link, topology_link_created = result
+
+            event_type = EventTypeEnum.EVENTTYPE_UPDATE if updated else EventTypeEnum.EVENTTYPE_CREATE
+            dict_link_id = db_link.dump_id()
+            notify_event(self.messagebroker, TOPIC_LINK, event_type, {'link_id': dict_link_id})
+            return LinkId(**dict_link_id)
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def RemoveLink(self, request: LinkId, context : grpc.ServicerContext) -> Empty:
-        link_uuid = request.link_uuid.uuid
-        db_link = LinkModel(self.database, link_uuid, auto_load=False)
-        found = db_link.load()
-        if not found: return Empty()
+        with self.lock:
+            link_uuid = request.link_uuid.uuid
+            db_link = LinkModel(self.database, link_uuid, auto_load=False)
+            found = db_link.load()
+            if not found: return Empty()
 
-        dict_link_id = db_link.dump_id()
+            dict_link_id = db_link.dump_id()
 
-        for db_link_endpoint_pk,_ in db_link.references(LinkEndPointModel):
-            LinkEndPointModel(self.database, db_link_endpoint_pk).delete()
+            for db_link_endpoint_pk,_ in db_link.references(LinkEndPointModel):
+                LinkEndPointModel(self.database, db_link_endpoint_pk).delete()
 
-        for db_topology_link_pk,_ in db_link.references(TopologyLinkModel):
-            TopologyLinkModel(self.database, db_topology_link_pk).delete()
+            for db_topology_link_pk,_ in db_link.references(TopologyLinkModel):
+                TopologyLinkModel(self.database, db_topology_link_pk).delete()
 
-        db_link.delete()
-        event_type = EventTypeEnum.EVENTTYPE_REMOVE
-        notify_event(self.messagebroker, TOPIC_LINK, event_type, {'link_id': dict_link_id})
-        return Empty()
+            db_link.delete()
+            event_type = EventTypeEnum.EVENTTYPE_REMOVE
+            notify_event(self.messagebroker, TOPIC_LINK, event_type, {'link_id': dict_link_id})
+            return Empty()
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def GetLinkEvents(self, request: Empty, context : grpc.ServicerContext) -> Iterator[LinkEvent]:
@@ -422,111 +443,116 @@ class ContextServiceServicerImpl(ContextServiceServicer):
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def ListServiceIds(self, request: ContextId, context : grpc.ServicerContext) -> ServiceIdList:
-        db_context : ContextModel = get_object(self.database, ContextModel, request.context_uuid.uuid)
-        db_services : Set[ServiceModel] = get_related_objects(db_context, ServiceModel)
-        db_services = sorted(db_services, key=operator.attrgetter('pk'))
-        return ServiceIdList(service_ids=[db_service.dump_id() for db_service in db_services])
+        with self.lock:
+            db_context : ContextModel = get_object(self.database, ContextModel, request.context_uuid.uuid)
+            db_services : Set[ServiceModel] = get_related_objects(db_context, ServiceModel)
+            db_services = sorted(db_services, key=operator.attrgetter('pk'))
+            return ServiceIdList(service_ids=[db_service.dump_id() for db_service in db_services])
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def ListServices(self, request: ContextId, context : grpc.ServicerContext) -> ServiceList:
-        db_context : ContextModel = get_object(self.database, ContextModel, request.context_uuid.uuid)
-        db_services : Set[ServiceModel] = get_related_objects(db_context, ServiceModel)
-        db_services = sorted(db_services, key=operator.attrgetter('pk'))
-        return ServiceList(services=[db_service.dump() for db_service in db_services])
+        with self.lock:
+            db_context : ContextModel = get_object(self.database, ContextModel, request.context_uuid.uuid)
+            db_services : Set[ServiceModel] = get_related_objects(db_context, ServiceModel)
+            db_services = sorted(db_services, key=operator.attrgetter('pk'))
+            return ServiceList(services=[db_service.dump() for db_service in db_services])
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def GetService(self, request: ServiceId, context : grpc.ServicerContext) -> Service:
-        str_key = key_to_str([request.context_id.context_uuid.uuid, request.service_uuid.uuid])
-        db_service : ServiceModel = get_object(self.database, ServiceModel, str_key)
-        return Service(**db_service.dump(
-            include_endpoint_ids=True, include_constraints=True, include_config_rules=True))
+        with self.lock:
+            str_key = key_to_str([request.context_id.context_uuid.uuid, request.service_uuid.uuid])
+            db_service : ServiceModel = get_object(self.database, ServiceModel, str_key)
+            return Service(**db_service.dump(
+                include_endpoint_ids=True, include_constraints=True, include_config_rules=True))
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def SetService(self, request: Service, context : grpc.ServicerContext) -> ServiceId:
-        context_uuid = request.service_id.context_id.context_uuid.uuid
-        db_context : ContextModel = get_object(self.database, ContextModel, context_uuid)
-
-        for i,endpoint_id in enumerate(request.service_endpoint_ids):
-            endpoint_topology_context_uuid = endpoint_id.topology_id.context_id.context_uuid.uuid
-            if len(endpoint_topology_context_uuid) > 0 and context_uuid != endpoint_topology_context_uuid:
-                raise InvalidArgumentException(
-                    'request.service_endpoint_ids[{:d}].topology_id.context_id.context_uuid.uuid'.format(i),
-                    endpoint_topology_context_uuid,
-                    ['should be == {:s}({:s})'.format('request.service_id.context_id.context_uuid.uuid', context_uuid)])
-
-        service_uuid = request.service_id.service_uuid.uuid
-        str_service_key = key_to_str([context_uuid, service_uuid])
-
-        constraints_result = set_constraints(
-            self.database, str_service_key, 'constraints', request.service_constraints)
-        db_constraints = constraints_result[0][0]
-
-        config_rules = grpc_config_rules_to_raw(request.service_config.config_rules)
-        running_config_result = update_config(self.database, str_service_key, 'running', config_rules)
-        db_running_config = running_config_result[0][0]
-
-        result : Tuple[ServiceModel, bool] = update_or_create_object(self.database, ServiceModel, str_service_key, {
-            'context_fk'            : db_context,
-            'service_uuid'          : service_uuid,
-            'service_type'          : grpc_to_enum__service_type(request.service_type),
-            'service_constraints_fk': db_constraints,
-            'service_status'        : grpc_to_enum__service_status(request.service_status.service_status),
-            'service_config_fk'     : db_running_config,
-        })
-        db_service, updated = result
-
-        for i,endpoint_id in enumerate(request.service_endpoint_ids):
-            endpoint_uuid                  = endpoint_id.endpoint_uuid.uuid
-            endpoint_device_uuid           = endpoint_id.device_id.device_uuid.uuid
-            endpoint_topology_uuid         = endpoint_id.topology_id.topology_uuid.uuid
-            endpoint_topology_context_uuid = endpoint_id.topology_id.context_id.context_uuid.uuid
-
-            str_endpoint_key = key_to_str([endpoint_device_uuid, endpoint_uuid])
-            if len(endpoint_topology_context_uuid) > 0 and len(endpoint_topology_uuid) > 0:
-                str_topology_key = key_to_str([endpoint_topology_context_uuid, endpoint_topology_uuid])
-                str_endpoint_key = key_to_str([str_endpoint_key, str_topology_key], separator=':')
-
-            db_endpoint : EndPointModel = get_object(self.database, EndPointModel, str_endpoint_key)
-
-            str_service_endpoint_key = key_to_str([service_uuid, endpoint_device_uuid], separator='--')
-            result : Tuple[ServiceEndPointModel, bool] = get_or_create_object(
-                self.database, ServiceEndPointModel, str_service_endpoint_key, {
-                    'service_fk': db_service, 'endpoint_fk': db_endpoint})
-            #db_service_endpoint, service_endpoint_created = result
-
-        event_type = EventTypeEnum.EVENTTYPE_UPDATE if updated else EventTypeEnum.EVENTTYPE_CREATE
-        dict_service_id = db_service.dump_id()
-        notify_event(self.messagebroker, TOPIC_SERVICE, event_type, {'service_id': dict_service_id})
-        return ServiceId(**dict_service_id)
+        with self.lock:
+            context_uuid = request.service_id.context_id.context_uuid.uuid
+            db_context : ContextModel = get_object(self.database, ContextModel, context_uuid)
+
+            for i,endpoint_id in enumerate(request.service_endpoint_ids):
+                endpoint_topology_context_uuid = endpoint_id.topology_id.context_id.context_uuid.uuid
+                if len(endpoint_topology_context_uuid) > 0 and context_uuid != endpoint_topology_context_uuid:
+                    raise InvalidArgumentException(
+                        'request.service_endpoint_ids[{:d}].topology_id.context_id.context_uuid.uuid'.format(i),
+                        endpoint_topology_context_uuid,
+                        ['should be == {:s}({:s})'.format('request.service_id.context_id.context_uuid.uuid', context_uuid)])
+
+            service_uuid = request.service_id.service_uuid.uuid
+            str_service_key = key_to_str([context_uuid, service_uuid])
+
+            constraints_result = set_constraints(
+                self.database, str_service_key, 'constraints', request.service_constraints)
+            db_constraints = constraints_result[0][0]
+
+            config_rules = grpc_config_rules_to_raw(request.service_config.config_rules)
+            running_config_result = update_config(self.database, str_service_key, 'running', config_rules)
+            db_running_config = running_config_result[0][0]
+
+            result : Tuple[ServiceModel, bool] = update_or_create_object(self.database, ServiceModel, str_service_key, {
+                'context_fk'            : db_context,
+                'service_uuid'          : service_uuid,
+                'service_type'          : grpc_to_enum__service_type(request.service_type),
+                'service_constraints_fk': db_constraints,
+                'service_status'        : grpc_to_enum__service_status(request.service_status.service_status),
+                'service_config_fk'     : db_running_config,
+            })
+            db_service, updated = result
+
+            for i,endpoint_id in enumerate(request.service_endpoint_ids):
+                endpoint_uuid                  = endpoint_id.endpoint_uuid.uuid
+                endpoint_device_uuid           = endpoint_id.device_id.device_uuid.uuid
+                endpoint_topology_uuid         = endpoint_id.topology_id.topology_uuid.uuid
+                endpoint_topology_context_uuid = endpoint_id.topology_id.context_id.context_uuid.uuid
+
+                str_endpoint_key = key_to_str([endpoint_device_uuid, endpoint_uuid])
+                if len(endpoint_topology_context_uuid) > 0 and len(endpoint_topology_uuid) > 0:
+                    str_topology_key = key_to_str([endpoint_topology_context_uuid, endpoint_topology_uuid])
+                    str_endpoint_key = key_to_str([str_endpoint_key, str_topology_key], separator=':')
+
+                db_endpoint : EndPointModel = get_object(self.database, EndPointModel, str_endpoint_key)
+
+                str_service_endpoint_key = key_to_str([service_uuid, str_endpoint_key], separator='--')
+                result : Tuple[ServiceEndPointModel, bool] = get_or_create_object(
+                    self.database, ServiceEndPointModel, str_service_endpoint_key, {
+                        'service_fk': db_service, 'endpoint_fk': db_endpoint})
+                #db_service_endpoint, service_endpoint_created = result
+
+            event_type = EventTypeEnum.EVENTTYPE_UPDATE if updated else EventTypeEnum.EVENTTYPE_CREATE
+            dict_service_id = db_service.dump_id()
+            notify_event(self.messagebroker, TOPIC_SERVICE, event_type, {'service_id': dict_service_id})
+            return ServiceId(**dict_service_id)
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def RemoveService(self, request: ServiceId, context : grpc.ServicerContext) -> Empty:
-        context_uuid = request.context_id.context_uuid.uuid
-        service_uuid = request.service_uuid.uuid
-        db_service = ServiceModel(self.database, key_to_str([context_uuid, service_uuid]), auto_load=False)
-        found = db_service.load()
-        if not found: return Empty()
+        with self.lock:
+            context_uuid = request.context_id.context_uuid.uuid
+            service_uuid = request.service_uuid.uuid
+            db_service = ServiceModel(self.database, key_to_str([context_uuid, service_uuid]), auto_load=False)
+            found = db_service.load()
+            if not found: return Empty()
 
-        dict_service_id = db_service.dump_id()
+            dict_service_id = db_service.dump_id()
 
-        for db_service_endpoint_pk,_ in db_service.references(ServiceEndPointModel):
-            ServiceEndPointModel(self.database, db_service_endpoint_pk).delete()
+            for db_service_endpoint_pk,_ in db_service.references(ServiceEndPointModel):
+                ServiceEndPointModel(self.database, db_service_endpoint_pk).delete()
 
-        db_config = ConfigModel(self.database, db_service.service_config_fk)
-        for db_config_rule_pk,_ in db_config.references(ConfigRuleModel):
-            ConfigRuleModel(self.database, db_config_rule_pk).delete()
+            db_config = ConfigModel(self.database, db_service.service_config_fk)
+            for db_config_rule_pk,_ in db_config.references(ConfigRuleModel):
+                ConfigRuleModel(self.database, db_config_rule_pk).delete()
 
-        db_constraints = ConstraintsModel(self.database, db_service.service_constraints_fk)
-        for db_constraint_pk,_ in db_constraints.references(ConstraintModel):
-            ConstraintModel(self.database, db_constraint_pk).delete()
+            db_constraints = ConstraintsModel(self.database, db_service.service_constraints_fk)
+            for db_constraint_pk,_ in db_constraints.references(ConstraintModel):
+                ConstraintModel(self.database, db_constraint_pk).delete()
 
-        db_service.delete()
-        db_config.delete()
-        db_constraints.delete()
+            db_service.delete()
+            db_config.delete()
+            db_constraints.delete()
 
-        event_type = EventTypeEnum.EVENTTYPE_REMOVE
-        notify_event(self.messagebroker, TOPIC_SERVICE, event_type, {'service_id': dict_service_id})
-        return Empty()
+            event_type = EventTypeEnum.EVENTTYPE_REMOVE
+            notify_event(self.messagebroker, TOPIC_SERVICE, event_type, {'service_id': dict_service_id})
+            return Empty()
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def GetServiceEvents(self, request: Empty, context : grpc.ServicerContext) -> Iterator[ServiceEvent]:
@@ -538,88 +564,93 @@ class ContextServiceServicerImpl(ContextServiceServicer):
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def ListConnectionIds(self, request: ServiceId, context : grpc.ServicerContext) -> ConnectionIdList:
-        str_key = key_to_str([request.context_id.context_uuid.uuid, request.service_uuid.uuid])
-        db_service : ServiceModel = get_object(self.database, ServiceModel, str_key)
-        db_connections : Set[ConnectionModel] = get_related_objects(db_service, ConnectionModel)
-        db_connections = sorted(db_connections, key=operator.attrgetter('pk'))
-        return ConnectionIdList(connection_ids=[db_connection.dump_id() for db_connection in db_connections])
+        with self.lock:
+            str_key = key_to_str([request.context_id.context_uuid.uuid, request.service_uuid.uuid])
+            db_service : ServiceModel = get_object(self.database, ServiceModel, str_key)
+            db_connections : Set[ConnectionModel] = get_related_objects(db_service, ConnectionModel)
+            db_connections = sorted(db_connections, key=operator.attrgetter('pk'))
+            return ConnectionIdList(connection_ids=[db_connection.dump_id() for db_connection in db_connections])
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def ListConnections(self, request: ContextId, context : grpc.ServicerContext) -> ServiceList:
-        str_key = key_to_str([request.context_id.context_uuid.uuid, request.service_uuid.uuid])
-        db_service : ServiceModel = get_object(self.database, ServiceModel, str_key)
-        db_connections : Set[ConnectionModel] = get_related_objects(db_service, ConnectionModel)
-        db_connections = sorted(db_connections, key=operator.attrgetter('pk'))
-        return ConnectionList(connections=[db_connection.dump() for db_connection in db_connections])
+        with self.lock:
+            str_key = key_to_str([request.context_id.context_uuid.uuid, request.service_uuid.uuid])
+            db_service : ServiceModel = get_object(self.database, ServiceModel, str_key)
+            db_connections : Set[ConnectionModel] = get_related_objects(db_service, ConnectionModel)
+            db_connections = sorted(db_connections, key=operator.attrgetter('pk'))
+            return ConnectionList(connections=[db_connection.dump() for db_connection in db_connections])
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def GetConnection(self, request: ConnectionId, context : grpc.ServicerContext) -> Connection:
-        db_connection : ConnectionModel = get_object(self.database, ConnectionModel, request.connection_uuid.uuid)
-        return Connection(**db_connection.dump(include_path=True, include_sub_service_ids=True))
+        with self.lock:
+            db_connection : ConnectionModel = get_object(self.database, ConnectionModel, request.connection_uuid.uuid)
+            return Connection(**db_connection.dump(include_path=True, include_sub_service_ids=True))
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def SetConnection(self, request: Connection, context : grpc.ServicerContext) -> ConnectionId:
-        connection_uuid = request.connection_id.connection_uuid.uuid
+        with self.lock:
+            connection_uuid = request.connection_id.connection_uuid.uuid
 
-        connection_attributes = {'connection_uuid': connection_uuid}
+            connection_attributes = {'connection_uuid': connection_uuid}
 
-        service_context_uuid = request.service_id.context_id.context_uuid.uuid
-        service_uuid = request.service_id.service_uuid.uuid
-        if len(service_context_uuid) > 0 and len(service_uuid) > 0:
-            str_service_key = key_to_str([service_context_uuid, service_uuid])
-            db_service : ServiceModel = get_object(self.database, ServiceModel, str_service_key)
-            connection_attributes['service_fk'] = db_service
+            service_context_uuid = request.service_id.context_id.context_uuid.uuid
+            service_uuid = request.service_id.service_uuid.uuid
+            if len(service_context_uuid) > 0 and len(service_uuid) > 0:
+                str_service_key = key_to_str([service_context_uuid, service_uuid])
+                db_service : ServiceModel = get_object(self.database, ServiceModel, str_service_key)
+                connection_attributes['service_fk'] = db_service
 
-        path_hops_result = set_path(self.database, connection_uuid, request.path_hops_endpoint_ids, path_name = '')
-        db_path = path_hops_result[0]
-        connection_attributes['path_fk'] = db_path
+            path_hops_result = set_path(self.database, connection_uuid, request.path_hops_endpoint_ids, path_name = '')
+            db_path = path_hops_result[0]
+            connection_attributes['path_fk'] = db_path
 
-        result : Tuple[ConnectionModel, bool] = update_or_create_object(
-            self.database, ConnectionModel, connection_uuid, connection_attributes)
-        db_connection, updated = result
+            result : Tuple[ConnectionModel, bool] = update_or_create_object(
+                self.database, ConnectionModel, connection_uuid, connection_attributes)
+            db_connection, updated = result
 
-        for sub_service_id in request.sub_service_ids:
-            sub_service_uuid         = sub_service_id.service_uuid.uuid
-            sub_service_context_uuid = sub_service_id.context_id.context_uuid.uuid
-            str_sub_service_key = key_to_str([sub_service_context_uuid, sub_service_uuid])
-            db_service : ServiceModel = get_object(self.database, ServiceModel, str_sub_service_key)
+            for sub_service_id in request.sub_service_ids:
+                sub_service_uuid         = sub_service_id.service_uuid.uuid
+                sub_service_context_uuid = sub_service_id.context_id.context_uuid.uuid
+                str_sub_service_key = key_to_str([sub_service_context_uuid, sub_service_uuid])
+                db_service : ServiceModel = get_object(self.database, ServiceModel, str_sub_service_key)
 
-            str_connection_sub_service_key = key_to_str([connection_uuid, str_sub_service_key], separator='--')
-            result : Tuple[ConnectionSubServiceModel, bool] = get_or_create_object(
-                self.database, ConnectionSubServiceModel, str_connection_sub_service_key, {
-                    'connection_fk': db_connection, 'sub_service_fk': db_service})
-            #db_connection_sub_service, connection_sub_service_created = result
+                str_connection_sub_service_key = key_to_str([connection_uuid, str_sub_service_key], separator='--')
+                result : Tuple[ConnectionSubServiceModel, bool] = get_or_create_object(
+                    self.database, ConnectionSubServiceModel, str_connection_sub_service_key, {
+                        'connection_fk': db_connection, 'sub_service_fk': db_service})
+                #db_connection_sub_service, connection_sub_service_created = result
 
-        event_type = EventTypeEnum.EVENTTYPE_UPDATE if updated else EventTypeEnum.EVENTTYPE_CREATE
-        dict_connection_id = db_connection.dump_id()
-        notify_event(self.messagebroker, TOPIC_CONNECTION, event_type, {'connection_id': dict_connection_id})
-        return ConnectionId(**dict_connection_id)
+            event_type = EventTypeEnum.EVENTTYPE_UPDATE if updated else EventTypeEnum.EVENTTYPE_CREATE
+            dict_connection_id = db_connection.dump_id()
+            notify_event(self.messagebroker, TOPIC_CONNECTION, event_type, {'connection_id': dict_connection_id})
+            return ConnectionId(**dict_connection_id)
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def RemoveConnection(self, request: ConnectionId, context : grpc.ServicerContext) -> Empty:
-        db_connection = ConnectionModel(self.database, request.connection_uuid.uuid, auto_load=False)
-        found = db_connection.load()
-        if not found: return Empty()
-
-        dict_connection_id = db_connection.dump_id()
-
-        db_path = PathModel(self.database, db_connection.path_fk)
-        for db_path_hop_pk,_ in db_path.references(PathHopModel):
-            PathHopModel(self.database, db_path_hop_pk).delete()
-
-        # Do not remove sub-services automatically. They are supported by real services, so Service component should
-        # deal with the correct removal workflow to deconfigure the devices.
-        for db_connection_sub_service_pk,_ in db_connection.references(ConnectionSubServiceModel):
-            db_connection_sub_service : ConnectionSubServiceModel = get_object(
-                self.database, ConnectionSubServiceModel, db_connection_sub_service_pk)
-            db_connection_sub_service.delete()
-
-        db_connection.delete()
-        db_path.delete()
-
-        event_type = EventTypeEnum.EVENTTYPE_REMOVE
-        notify_event(self.messagebroker, TOPIC_CONNECTION, event_type, {'connection_id': dict_connection_id})
-        return Empty()
+        with self.lock:
+            db_connection = ConnectionModel(self.database, request.connection_uuid.uuid, auto_load=False)
+            found = db_connection.load()
+            if not found: return Empty()
+
+            dict_connection_id = db_connection.dump_id()
+
+            db_path = PathModel(self.database, db_connection.path_fk)
+            for db_path_hop_pk,_ in db_path.references(PathHopModel):
+                PathHopModel(self.database, db_path_hop_pk).delete()
+
+            # Do not remove sub-services automatically. They are supported by real services, so Service component should
+            # deal with the correct removal workflow to deconfigure the devices.
+            for db_connection_sub_service_pk,_ in db_connection.references(ConnectionSubServiceModel):
+                db_connection_sub_service : ConnectionSubServiceModel = get_object(
+                    self.database, ConnectionSubServiceModel, db_connection_sub_service_pk)
+                db_connection_sub_service.delete()
+
+            db_connection.delete()
+            db_path.delete()
+
+            event_type = EventTypeEnum.EVENTTYPE_REMOVE
+            notify_event(self.messagebroker, TOPIC_CONNECTION, event_type, {'connection_id': dict_connection_id})
+            return Empty()
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def GetConnectionEvents(self, request: Empty, context : grpc.ServicerContext) -> Iterator[ConnectionEvent]:
diff --git a/src/context/service/rest_server/Resources.py b/src/context/service/rest_server/Resources.py
index 9abf60d48..a580861c8 100644
--- a/src/context/service/rest_server/Resources.py
+++ b/src/context/service/rest_server/Resources.py
@@ -1,14 +1,13 @@
+from flask import make_response
 from flask.json import jsonify
 from flask_restful import Resource
-from google.protobuf.json_format import MessageToDict
 from common.orm.Database import Database
+from common.tools.grpc.Tools import grpc_message_to_json
 from context.proto.context_pb2 import ConnectionId, ContextId, DeviceId, Empty, LinkId, ServiceId, TopologyId
 from context.service.grpc_server.ContextServiceServicerImpl import ContextServiceServicerImpl
 
 def format_grpc_to_json(grpc_reply):
-    return jsonify(MessageToDict(
-        grpc_reply, including_default_value_fields=True, preserving_proto_field_name=True,
-        use_integers_for_enums=False))
+    return jsonify(grpc_message_to_json(grpc_reply))
 
 def grpc_connection_id(connection_uuid):
     return ConnectionId(**{
@@ -120,6 +119,41 @@ class Connection(_Resource):
     def get(self, connection_uuid : str):
         return format_grpc_to_json(self.servicer.GetConnection(grpc_connection_id(connection_uuid), None))
 
+class DumpText(Resource):
+    def __init__(self, database : Database) -> None:
+        super().__init__()
+        self.database = database
+
+    def get(self):
+        db_entries = self.database.dump()
+        num_entries = len(db_entries)
+        response = ['----- Database Dump [{:3d} entries] -------------------------'.format(len(db_entries))]
+        for db_entry in db_entries:
+            response.append('  [{:>4s}] {:40s} :: {:s}'.format(*db_entry)) # pragma: no cover
+        response.append('-----------------------------------------------------------')
+        headers = {'Content-Type': 'text/plain'}
+        return make_response('\n'.join(response), 200, headers)
+
+class DumpHtml(Resource):
+    def __init__(self, database : Database) -> None:
+        super().__init__()
+        self.database = database
+
+    def get(self):
+        db_entries = self.database.dump()
+        num_entries = len(db_entries)
+        response = []
+        response.append('<HTML><HEAD><TITLE>Database Dump [{:3d} entries]</TITLE></HEAD><BODY>'.format(num_entries))
+        response.append('<H3>Database Dump [{:3d} entries]</H3><HR/>'.format(num_entries))
+        response.append('<TABLE border=1>')
+        response.append('<TR><TH>Type</TH><TH>Key</TH><TH>Value</TH></TR>')
+        for db_entry in db_entries:
+            response.append('<TR><TD>{:s}</TD><TD>{:s}</TD><TD>{:s}</TD></TR>'.format(*db_entry))
+        response.append('</TABLE></BODY></HTML>')
+
+        headers = {'Content-Type': 'text/html'}
+        return make_response(''.join(response), 200, headers)
+
 
 # Use 'path' type in Service and Sink because service_uuid and link_uuid might contain char '/' and Flask is unable to
 # recognize them in 'string' type.
@@ -148,4 +182,7 @@ RESOURCES = [
     ('api.connection_ids', ConnectionIds, '/context/<string:context_uuid>/service/<path:service_uuid>/connection_ids'),
     ('api.connections',    Connections,   '/context/<string:context_uuid>/service/<path:service_uuid>/connections'),
     ('api.connection',     Connection,    '/connection/<path:connection_uuid>'),
+
+    ('api.dump.text',      DumpText,      '/dump/text'),
+    ('api.dump.html',      DumpHtml,      '/dump/html'),
 ]
diff --git a/src/context/tests/Objects.py b/src/context/tests/Objects.py
new file mode 100644
index 000000000..a3643682e
--- /dev/null
+++ b/src/context/tests/Objects.py
@@ -0,0 +1,185 @@
+from common.Constants import DEFAULT_CONTEXT_UUID, DEFAULT_TOPOLOGY_UUID
+from common.tools.object_factory.ConfigRule import json_config_rule_set
+from common.tools.object_factory.Connection import json_connection, json_connection_id
+from common.tools.object_factory.Constraint import json_constraint
+from common.tools.object_factory.Context import json_context, json_context_id
+from common.tools.object_factory.Device import json_device_id, json_device_packetrouter_disabled
+from common.tools.object_factory.EndPoint import json_endpoint, json_endpoint_id
+from common.tools.object_factory.Link import json_link, json_link_id
+from common.tools.object_factory.Service import json_service_id, json_service_l3nm_planned
+from common.tools.object_factory.Topology import json_topology, json_topology_id
+from context.proto.kpi_sample_types_pb2 import KpiSampleType
+
+
+# ----- Context --------------------------------------------------------------------------------------------------------
+CONTEXT_ID = json_context_id(DEFAULT_CONTEXT_UUID)
+CONTEXT    = json_context(DEFAULT_CONTEXT_UUID)
+
+
+# ----- Topology -------------------------------------------------------------------------------------------------------
+TOPOLOGY_ID = json_topology_id(DEFAULT_TOPOLOGY_UUID, context_id=CONTEXT_ID)
+TOPOLOGY    = json_topology(DEFAULT_TOPOLOGY_UUID, context_id=CONTEXT_ID)
+
+
+# ----- KPI Sample Types -----------------------------------------------------------------------------------------------
+PACKET_PORT_SAMPLE_TYPES = [
+    KpiSampleType.KPISAMPLETYPE_PACKETS_TRANSMITTED,
+    KpiSampleType.KPISAMPLETYPE_PACKETS_RECEIVED,
+    KpiSampleType.KPISAMPLETYPE_BYTES_TRANSMITTED,
+    KpiSampleType.KPISAMPLETYPE_BYTES_RECEIVED,
+]
+
+
+# ----- Device ---------------------------------------------------------------------------------------------------------
+DEVICE_R1_UUID  = 'R1'
+DEVICE_R1_ID    = json_device_id(DEVICE_R1_UUID)
+DEVICE_R1_EPS   = [
+    json_endpoint(DEVICE_R1_ID, 'EP2',   '10G', topology_id=TOPOLOGY_ID, kpi_sample_types=PACKET_PORT_SAMPLE_TYPES),
+    json_endpoint(DEVICE_R1_ID, 'EP3',   '10G', topology_id=TOPOLOGY_ID, kpi_sample_types=PACKET_PORT_SAMPLE_TYPES),
+    json_endpoint(DEVICE_R1_ID, 'EP100', '10G', topology_id=TOPOLOGY_ID, kpi_sample_types=PACKET_PORT_SAMPLE_TYPES),
+]
+DEVICE_R1_RULES = [
+    json_config_rule_set('dev/rsrc1/value', 'value1'),
+    json_config_rule_set('dev/rsrc2/value', 'value2'),
+    json_config_rule_set('dev/rsrc3/value', 'value3'),
+]
+DEVICE_R1       = json_device_packetrouter_disabled(
+    DEVICE_R1_UUID, endpoints=DEVICE_R1_EPS, config_rules=DEVICE_R1_RULES)
+
+
+DEVICE_R2_UUID  = 'R2'
+DEVICE_R2_ID    = json_device_id(DEVICE_R2_UUID)
+DEVICE_R2_EPS   = [
+    json_endpoint(DEVICE_R2_ID, 'EP1',   '10G', topology_id=TOPOLOGY_ID, kpi_sample_types=PACKET_PORT_SAMPLE_TYPES),
+    json_endpoint(DEVICE_R2_ID, 'EP3',   '10G', topology_id=TOPOLOGY_ID, kpi_sample_types=PACKET_PORT_SAMPLE_TYPES),
+    json_endpoint(DEVICE_R2_ID, 'EP100', '10G', topology_id=TOPOLOGY_ID, kpi_sample_types=PACKET_PORT_SAMPLE_TYPES),
+]
+DEVICE_R2_RULES = [
+    json_config_rule_set('dev/rsrc1/value', 'value4'),
+    json_config_rule_set('dev/rsrc2/value', 'value5'),
+    json_config_rule_set('dev/rsrc3/value', 'value6'),
+]
+DEVICE_R2       = json_device_packetrouter_disabled(
+    DEVICE_R2_UUID, endpoints=DEVICE_R2_EPS, config_rules=DEVICE_R2_RULES)
+
+
+DEVICE_R3_UUID  = 'R3'
+DEVICE_R3_ID    = json_device_id(DEVICE_R3_UUID)
+DEVICE_R3_EPS   = [
+    json_endpoint(DEVICE_R3_ID, 'EP1',   '10G', topology_id=TOPOLOGY_ID, kpi_sample_types=PACKET_PORT_SAMPLE_TYPES),
+    json_endpoint(DEVICE_R3_ID, 'EP2',   '10G', topology_id=TOPOLOGY_ID, kpi_sample_types=PACKET_PORT_SAMPLE_TYPES),
+    json_endpoint(DEVICE_R3_ID, 'EP100', '10G', topology_id=TOPOLOGY_ID, kpi_sample_types=PACKET_PORT_SAMPLE_TYPES),
+]
+DEVICE_R3_RULES = [
+    json_config_rule_set('dev/rsrc1/value', 'value4'),
+    json_config_rule_set('dev/rsrc2/value', 'value5'),
+    json_config_rule_set('dev/rsrc3/value', 'value6'),
+]
+DEVICE_R3       = json_device_packetrouter_disabled(
+    DEVICE_R3_UUID, endpoints=DEVICE_R3_EPS, config_rules=DEVICE_R3_RULES)
+
+
+# ----- Link -----------------------------------------------------------------------------------------------------------
+LINK_R1_R2_UUID  = 'R1/EP2-R2/EP1'
+LINK_R1_R2_ID    = json_link_id(LINK_R1_R2_UUID)
+LINK_R1_R2_EPIDS = [
+    json_endpoint_id(DEVICE_R1_ID, 'EP2', topology_id=TOPOLOGY_ID),
+    json_endpoint_id(DEVICE_R2_ID, 'EP1', topology_id=TOPOLOGY_ID),
+]
+LINK_R1_R2       = json_link(LINK_R1_R2_UUID, LINK_R1_R2_EPIDS)
+
+
+LINK_R2_R3_UUID  = 'R2/EP3-R3/EP2'
+LINK_R2_R3_ID    = json_link_id(LINK_R2_R3_UUID)
+LINK_R2_R3_EPIDS = [
+    json_endpoint_id(DEVICE_R2_ID, 'EP3', topology_id=TOPOLOGY_ID),
+    json_endpoint_id(DEVICE_R3_ID, 'EP2', topology_id=TOPOLOGY_ID),
+]
+LINK_R2_R3       = json_link(LINK_R2_R3_UUID, LINK_R2_R3_EPIDS)
+
+
+LINK_R1_R3_UUID  = 'R1/EP3-R3/EP1'
+LINK_R1_R3_ID    = json_link_id(LINK_R1_R3_UUID)
+LINK_R1_R3_EPIDS = [
+    json_endpoint_id(DEVICE_R1_ID, 'EP3', topology_id=TOPOLOGY_ID),
+    json_endpoint_id(DEVICE_R3_ID, 'EP1', topology_id=TOPOLOGY_ID),
+]
+LINK_R1_R3       = json_link(LINK_R1_R3_UUID, LINK_R1_R3_EPIDS)
+
+
+# ----- Service --------------------------------------------------------------------------------------------------------
+SERVICE_R1_R2_UUID  = 'SVC:R1/EP100-R2/EP100'
+SERVICE_R1_R2_ID    = json_service_id(SERVICE_R1_R2_UUID, context_id=CONTEXT_ID)
+SERVICE_R1_R2_EPIDS = [
+    json_endpoint_id(DEVICE_R1_ID, 'EP100', topology_id=TOPOLOGY_ID),
+    json_endpoint_id(DEVICE_R2_ID, 'EP100', topology_id=TOPOLOGY_ID),
+]
+SERVICE_R1_R2_CONST = [
+    json_constraint('latency_ms', '15.2'),
+    json_constraint('jitter_us',  '1.2'),
+]
+SERVICE_R1_R2_RULES = [
+    json_config_rule_set('svc/rsrc1/value', 'value7'),
+    json_config_rule_set('svc/rsrc2/value', 'value8'),
+    json_config_rule_set('svc/rsrc3/value', 'value9'),
+]
+SERVICE_R1_R2       = json_service_l3nm_planned(
+    SERVICE_R1_R2_UUID, endpoint_ids=SERVICE_R1_R2_EPIDS, constraints=SERVICE_R1_R2_CONST,
+    config_rules=SERVICE_R1_R2_RULES)
+
+
+SERVICE_R1_R3_UUID  = 'SVC:R1/EP100-R3/EP100'
+SERVICE_R1_R3_ID    = json_service_id(SERVICE_R1_R3_UUID, context_id=CONTEXT_ID)
+SERVICE_R1_R3_EPIDS = [
+    json_endpoint_id(DEVICE_R1_ID, 'EP100', topology_id=TOPOLOGY_ID),
+    json_endpoint_id(DEVICE_R3_ID, 'EP100', topology_id=TOPOLOGY_ID),
+]
+SERVICE_R1_R3_CONST = [
+    json_constraint('latency_ms', '5.8'),
+    json_constraint('jitter_us',  '0.1'),
+]
+SERVICE_R1_R3_RULES = [
+    json_config_rule_set('svc/rsrc1/value', 'value7'),
+    json_config_rule_set('svc/rsrc2/value', 'value8'),
+    json_config_rule_set('svc/rsrc3/value', 'value9'),
+]
+SERVICE_R1_R3       = json_service_l3nm_planned(
+    SERVICE_R1_R3_UUID, endpoint_ids=SERVICE_R1_R3_EPIDS, constraints=SERVICE_R1_R3_CONST,
+    config_rules=SERVICE_R1_R3_RULES)
+
+
+SERVICE_R2_R3_UUID  = 'SVC:R2/EP100-R3/EP100'
+SERVICE_R2_R3_ID    = json_service_id(SERVICE_R2_R3_UUID, context_id=CONTEXT_ID)
+SERVICE_R2_R3_EPIDS = [
+    json_endpoint_id(DEVICE_R2_ID, 'EP100', topology_id=TOPOLOGY_ID),
+    json_endpoint_id(DEVICE_R3_ID, 'EP100', topology_id=TOPOLOGY_ID),
+]
+SERVICE_R2_R3_CONST = [
+    json_constraint('latency_ms', '23.1'),
+    json_constraint('jitter_us',  '3.4'),
+]
+SERVICE_R2_R3_RULES = [
+    json_config_rule_set('svc/rsrc1/value', 'value7'),
+    json_config_rule_set('svc/rsrc2/value', 'value8'),
+    json_config_rule_set('svc/rsrc3/value', 'value9'),
+]
+SERVICE_R2_R3       = json_service_l3nm_planned(
+    SERVICE_R2_R3_UUID, endpoint_ids=SERVICE_R2_R3_EPIDS, constraints=SERVICE_R2_R3_CONST,
+    config_rules=SERVICE_R2_R3_RULES)
+
+
+# ----- Connection -----------------------------------------------------------------------------------------------------
+CONNECTION_R1_R3_UUID   = 'CON:R1/EP100-R3/EP100'
+CONNECTION_R1_R3_ID     = json_connection_id(CONNECTION_R1_R3_UUID)
+CONNECTION_R1_R3_EPIDS  = [
+    json_endpoint_id(DEVICE_R1_ID, 'EP100', topology_id=TOPOLOGY_ID),
+    json_endpoint_id(DEVICE_R1_ID, 'EP2',   topology_id=TOPOLOGY_ID),
+    json_endpoint_id(DEVICE_R2_ID, 'EP1',   topology_id=TOPOLOGY_ID),
+    json_endpoint_id(DEVICE_R2_ID, 'EP3',   topology_id=TOPOLOGY_ID),
+    json_endpoint_id(DEVICE_R3_ID, 'EP2',   topology_id=TOPOLOGY_ID),
+    json_endpoint_id(DEVICE_R3_ID, 'EP100', topology_id=TOPOLOGY_ID),
+]
+CONNECTION_R1_R3_SVCIDS = [SERVICE_R1_R2_ID, SERVICE_R2_R3_ID]
+CONNECTION_R1_R3        = json_connection(
+    CONNECTION_R1_R3_UUID, service_id=SERVICE_R1_R3_ID, path_hops_endpoint_ids=CONNECTION_R1_R3_EPIDS,
+    sub_service_ids=CONNECTION_R1_R3_SVCIDS)
diff --git a/src/context/tests/Tools.py b/src/context/tests/Tools.py
deleted file mode 100644
index b4d1d8953..000000000
--- a/src/context/tests/Tools.py
+++ /dev/null
@@ -1,27 +0,0 @@
-import json
-from copy import deepcopy
-from typing import Any, Dict, Union
-from context.proto.context_pb2 import ConfigActionEnum
-
-def config_rule(action : ConfigActionEnum, resource_key : str, resource_value : Union[str, Dict[str, Any]]):
-    if not isinstance(resource_value, str): resource_value = json.dumps(resource_value, sort_keys=True)
-    return {'action': action, 'resource_key': resource_key, 'resource_value': resource_value}
-
-def config_rule_set(resource_key : str, resource_value : Union[str, Dict[str, Any]]):
-    return config_rule(ConfigActionEnum.CONFIGACTION_SET, resource_key, resource_value)
-
-def config_rule_delete(resource_key : str, resource_value : Union[str, Dict[str, Any]]):
-    return config_rule(ConfigActionEnum.CONFIGACTION_DELETE, resource_key, resource_value)
-
-def endpoint_id(device_id, endpoint_uuid, topology_id=None):
-    result = {'device_id': deepcopy(device_id), 'endpoint_uuid': {'uuid': endpoint_uuid}}
-    if topology_id is not None: result['topology_id'] = deepcopy(topology_id)
-    return result
-
-def endpoint(device_id, endpoint_uuid, endpoint_type, topology_id=None, kpi_sample_types=[]):
-    result = {
-        'endpoint_id': endpoint_id(device_id, endpoint_uuid, topology_id=topology_id),
-        'endpoint_type': endpoint_type,
-    }
-    if len(kpi_sample_types) > 0: result['kpi_sample_types'] = deepcopy(kpi_sample_types)
-    return result
diff --git a/src/context/tests/example_objects.py b/src/context/tests/example_objects.py
deleted file mode 100644
index ef2117bc6..000000000
--- a/src/context/tests/example_objects.py
+++ /dev/null
@@ -1,220 +0,0 @@
-from copy import deepcopy
-from common.Constants import DEFAULT_CONTEXT_UUID, DEFAULT_TOPOLOGY_UUID
-from context.proto.context_pb2 import (
-    DeviceDriverEnum, DeviceOperationalStatusEnum, ServiceStatusEnum, ServiceTypeEnum)
-from context.proto.kpi_sample_types_pb2 import KpiSampleType
-from .Tools import config_rule_set, endpoint, endpoint_id
-
-# Some example objects to be used by the tests
-
-## use "deepcopy" to prevent propagating forced changes during tests
-CONTEXT_ID = {'context_uuid': {'uuid': DEFAULT_CONTEXT_UUID}}
-CONTEXT = {
-    'context_id': deepcopy(CONTEXT_ID),
-    'topology_ids': [],
-    'service_ids': [],
-}
-
-TOPOLOGY_ID = {
-    'context_id': deepcopy(CONTEXT_ID),
-    'topology_uuid': {'uuid': DEFAULT_TOPOLOGY_UUID},
-}
-TOPOLOGY = {
-    'topology_id': deepcopy(TOPOLOGY_ID),
-    'device_ids': [],
-    'link_ids': [],
-}
-
-PACKET_PORT_SAMPLE_TYPES = [
-    KpiSampleType.KPISAMPLETYPE_PACKETS_TRANSMITTED,
-    KpiSampleType.KPISAMPLETYPE_PACKETS_RECEIVED,
-    KpiSampleType.KPISAMPLETYPE_BYTES_TRANSMITTED,
-    KpiSampleType.KPISAMPLETYPE_BYTES_RECEIVED,
-]
-
-def _endpoint_id(device_id, endpoint_uuid):
-    return endpoint_id(device_id, endpoint_uuid, topology_id=TOPOLOGY_ID)
-
-def _endpoint(device_id, endpoint_uuid, endpoint_type):
-    return endpoint(
-        device_id, endpoint_uuid, endpoint_type, topology_id=TOPOLOGY_ID, kpi_sample_types=PACKET_PORT_SAMPLE_TYPES)
-
-DEVICE1_UUID = 'DEV1'
-DEVICE1_ID = {'device_uuid': {'uuid': DEVICE1_UUID}}
-DEVICE1 = {
-    'device_id': deepcopy(DEVICE1_ID),
-    'device_type': 'packet-router',
-    'device_config': {'config_rules': [
-        config_rule_set('dev/rsrc1/value', 'value1'),
-        config_rule_set('dev/rsrc2/value', 'value2'),
-        config_rule_set('dev/rsrc3/value', 'value3'),
-    ]},
-    'device_operational_status': DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_ENABLED,
-    'device_drivers': [DeviceDriverEnum.DEVICEDRIVER_OPENCONFIG, DeviceDriverEnum.DEVICEDRIVER_P4],
-    'device_endpoints': [
-        _endpoint(DEVICE1_ID, 'EP2',   'port-packet-100G'),
-        _endpoint(DEVICE1_ID, 'EP3',   'port-packet-100G'),
-        _endpoint(DEVICE1_ID, 'EP100', 'port-packet-10G' ),
-    ],
-}
-
-DEVICE2_UUID = 'DEV2'
-DEVICE2_ID = {'device_uuid': {'uuid': DEVICE2_UUID}}
-DEVICE2 = {
-    'device_id': deepcopy(DEVICE2_ID),
-    'device_type': 'packet-router',
-    'device_config': {'config_rules': [
-        config_rule_set('dev/rsrc1/value', 'value4'),
-        config_rule_set('dev/rsrc2/value', 'value5'),
-        config_rule_set('dev/rsrc3/value', 'value6'),
-    ]},
-    'device_operational_status': DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_ENABLED,
-    'device_drivers': [DeviceDriverEnum.DEVICEDRIVER_OPENCONFIG, DeviceDriverEnum.DEVICEDRIVER_P4],
-    'device_endpoints': [
-        _endpoint(DEVICE2_ID, 'EP1',   'port-packet-100G'),
-        _endpoint(DEVICE2_ID, 'EP3',   'port-packet-100G'),
-        _endpoint(DEVICE2_ID, 'EP100', 'port-packet-10G' ),
-    ],
-}
-
-DEVICE3_UUID = 'DEV3'
-DEVICE3_ID = {'device_uuid': {'uuid': DEVICE3_UUID}}
-DEVICE3 = {
-    'device_id': deepcopy(DEVICE3_ID),
-    'device_type': 'packet-router',
-    'device_config': {'config_rules': [
-        config_rule_set('dev/rsrc1/value', 'value4'),
-        config_rule_set('dev/rsrc2/value', 'value5'),
-        config_rule_set('dev/rsrc3/value', 'value6'),
-    ]},
-    'device_operational_status': DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_ENABLED,
-    'device_drivers': [DeviceDriverEnum.DEVICEDRIVER_OPENCONFIG, DeviceDriverEnum.DEVICEDRIVER_P4],
-    'device_endpoints': [
-        _endpoint(DEVICE3_ID, 'EP1',   'port-packet-100G'),
-        _endpoint(DEVICE3_ID, 'EP2',   'port-packet-100G'),
-        _endpoint(DEVICE3_ID, 'EP100', 'port-packet-10G' ),
-    ],
-}
-
-LINK_DEV1_DEV2_UUID = 'DEV1/EP2 ==> DEV2/EP1'
-LINK_DEV1_DEV2_ID = {'link_uuid': {'uuid': LINK_DEV1_DEV2_UUID}}
-LINK_DEV1_DEV2 = {
-    'link_id': deepcopy(LINK_DEV1_DEV2_ID),
-    'link_endpoint_ids' : [
-        _endpoint_id(DEVICE1_ID, 'EP2'),
-        _endpoint_id(DEVICE2_ID, 'EP1'),
-    ]
-}
-
-LINK_DEV2_DEV3_UUID = 'DEV2/EP3 ==> DEV3/EP2'
-LINK_DEV2_DEV3_ID = {'link_uuid': {'uuid': LINK_DEV2_DEV3_UUID}}
-LINK_DEV2_DEV3 = {
-    'link_id': deepcopy(LINK_DEV2_DEV3_ID),
-    'link_endpoint_ids' : [
-        _endpoint_id(DEVICE2_ID, 'EP3'),
-        _endpoint_id(DEVICE3_ID, 'EP2'),
-    ]
-}
-
-LINK_DEV1_DEV3_UUID = 'DEV1/EP3 ==> DEV3/EP1'
-LINK_DEV1_DEV3_ID = {'link_uuid': {'uuid': LINK_DEV1_DEV3_UUID}}
-LINK_DEV1_DEV3 = {
-    'link_id': deepcopy(LINK_DEV1_DEV3_ID),
-    'link_endpoint_ids' : [
-        _endpoint_id(DEVICE1_ID, 'EP3'),
-        _endpoint_id(DEVICE3_ID, 'EP1'),
-    ]
-}
-
-SERVICE_DEV1_DEV2_UUID = 'SVC:DEV1/EP100-DEV2/EP100'
-SERVICE_DEV1_DEV2_ID = {
-    'context_id': deepcopy(CONTEXT_ID),
-    'service_uuid': {'uuid': SERVICE_DEV1_DEV2_UUID},
-}
-SERVICE_DEV1_DEV2 = {
-    'service_id': deepcopy(SERVICE_DEV1_DEV2_ID),
-    'service_type': ServiceTypeEnum.SERVICETYPE_L3NM,
-    'service_endpoint_ids' : [
-        _endpoint_id(DEVICE1_ID, 'EP100'),
-        _endpoint_id(DEVICE2_ID, 'EP100'),
-    ],
-    'service_constraints': [
-        {'constraint_type': 'latency_ms', 'constraint_value': '15.2'},
-        {'constraint_type': 'jitter_us', 'constraint_value': '1.2'},
-    ],
-    'service_status': {'service_status': ServiceStatusEnum.SERVICESTATUS_ACTIVE},
-    'service_config': {'config_rules': [
-        config_rule_set('svc/rsrc1/value', 'value7'),
-        config_rule_set('svc/rsrc2/value', 'value8'),
-        config_rule_set('svc/rsrc3/value', 'value9'),
-    ]},
-}
-
-SERVICE_DEV1_DEV3_UUID = 'SVC:DEV1/EP100-DEV3/EP100'
-SERVICE_DEV1_DEV3_ID = {
-    'context_id': deepcopy(CONTEXT_ID),
-    'service_uuid': {'uuid': SERVICE_DEV1_DEV3_UUID},
-}
-SERVICE_DEV1_DEV3 = {
-    'service_id': deepcopy(SERVICE_DEV1_DEV3_ID),
-    'service_type': ServiceTypeEnum.SERVICETYPE_L3NM,
-    'service_endpoint_ids' : [
-        _endpoint_id(DEVICE1_ID, 'EP100'),
-        _endpoint_id(DEVICE3_ID, 'EP100'),
-    ],
-    'service_constraints': [
-        {'constraint_type': 'latency_ms', 'constraint_value': '5.8'},
-        {'constraint_type': 'jitter_us', 'constraint_value': '0.1'},
-    ],
-    'service_status': {'service_status': ServiceStatusEnum.SERVICESTATUS_ACTIVE},
-    'service_config': {'config_rules': [
-        config_rule_set('svc/rsrc1/value', 'value7'),
-        config_rule_set('svc/rsrc2/value', 'value8'),
-        config_rule_set('svc/rsrc3/value', 'value9'),
-    ]},
-}
-
-SERVICE_DEV2_DEV3_UUID = 'SVC:DEV2/EP100-DEV3/EP100'
-SERVICE_DEV2_DEV3_ID = {
-    'context_id': deepcopy(CONTEXT_ID),
-    'service_uuid': {'uuid': SERVICE_DEV2_DEV3_UUID},
-}
-SERVICE_DEV2_DEV3 = {
-    'service_id': deepcopy(SERVICE_DEV2_DEV3_ID),
-    'service_type': ServiceTypeEnum.SERVICETYPE_L3NM,
-    'service_endpoint_ids' : [
-        _endpoint_id(DEVICE2_ID, 'EP100'),
-        _endpoint_id(DEVICE3_ID, 'EP100'),
-    ],
-    'service_constraints': [
-        {'constraint_type': 'latency_ms', 'constraint_value': '23.1'},
-        {'constraint_type': 'jitter_us', 'constraint_value': '3.4'},
-    ],
-    'service_status': {'service_status': ServiceStatusEnum.SERVICESTATUS_ACTIVE},
-    'service_config': {'config_rules': [
-        config_rule_set('svc/rsrc1/value', 'value7'),
-        config_rule_set('svc/rsrc2/value', 'value8'),
-        config_rule_set('svc/rsrc3/value', 'value9'),
-    ]},
-}
-
-CONNECTION_DEV1_DEV3_UUID = 'CON:DEV1/EP100-DEV3/EP100'
-CONNECTION_DEV1_DEV3_ID = {
-    'connection_uuid': {'uuid': CONNECTION_DEV1_DEV3_UUID},
-}
-CONNECTION_DEV1_DEV3 = {
-    'connection_id': deepcopy(CONNECTION_DEV1_DEV3_ID),
-    'service_id': deepcopy(SERVICE_DEV1_DEV3_ID),
-    'path_hops_endpoint_ids' : [
-        _endpoint_id(DEVICE1_ID, 'EP100'),
-        _endpoint_id(DEVICE1_ID, 'EP2'),
-        _endpoint_id(DEVICE2_ID, 'EP1'),
-        _endpoint_id(DEVICE2_ID, 'EP3'),
-        _endpoint_id(DEVICE3_ID, 'EP2'),
-        _endpoint_id(DEVICE3_ID, 'EP100'),
-    ],
-    'sub_service_ids': [
-        deepcopy(SERVICE_DEV1_DEV2_ID),
-        deepcopy(SERVICE_DEV2_DEV3_ID),
-    ],
-}
diff --git a/src/context/tests/test_unitary.py b/src/context/tests/test_unitary.py
index 7d3cd9b96..9225d0b67 100644
--- a/src/context/tests/test_unitary.py
+++ b/src/context/tests/test_unitary.py
@@ -1,6 +1,5 @@
 # pylint: disable=too-many-lines
-import copy, grpc, logging, os, pytest, requests, threading, time, urllib
-from queue import Queue, Empty
+import copy, grpc, logging, os, pytest, requests, time, urllib
 from typing import Tuple
 from common.Constants import DEFAULT_CONTEXT_UUID, DEFAULT_TOPOLOGY_UUID
 from common.orm.Database import Database
@@ -15,6 +14,7 @@ from common.type_checkers.Assertions import (
 from context.Config import (
     GRPC_SERVICE_PORT, GRPC_MAX_WORKERS, GRPC_GRACE_PERIOD, RESTAPI_SERVICE_PORT, RESTAPI_BASE_URL)
 from context.client.ContextClient import ContextClient
+from context.client.EventsCollector import EventsCollector
 from context.proto.context_pb2 import (
     Connection, ConnectionEvent, ConnectionId, Context, ContextEvent, ContextId, Device, DeviceEvent, DeviceId,
     DeviceOperationalStatusEnum, Empty, EventTypeEnum, Link, LinkEvent, LinkId, Service, ServiceEvent, ServiceId,
@@ -25,12 +25,11 @@ from context.service.grpc_server.ContextService import ContextService
 from context.service.Populate import populate
 from context.service.rest_server.Server import Server as RestServer
 from context.service.rest_server.Resources import RESOURCES
-from .example_objects import (
-    CONNECTION_DEV1_DEV3, CONNECTION_DEV1_DEV3_ID, CONNECTION_DEV1_DEV3_UUID, CONTEXT, CONTEXT_ID, DEVICE1, DEVICE1_ID,
-    DEVICE1_UUID, DEVICE2, DEVICE2_ID, DEVICE2_UUID, DEVICE3, DEVICE3_ID, DEVICE3_UUID, LINK_DEV1_DEV2,
-    LINK_DEV1_DEV2_ID, LINK_DEV1_DEV2_UUID, SERVICE_DEV1_DEV2, SERVICE_DEV1_DEV2_ID, SERVICE_DEV1_DEV2_UUID,
-    SERVICE_DEV1_DEV3, SERVICE_DEV1_DEV3_ID, SERVICE_DEV1_DEV3_UUID, SERVICE_DEV2_DEV3, SERVICE_DEV2_DEV3_ID,
-    SERVICE_DEV2_DEV3_UUID, TOPOLOGY, TOPOLOGY_ID)
+from .Objects import (
+    CONNECTION_R1_R3, CONNECTION_R1_R3_ID, CONNECTION_R1_R3_UUID, CONTEXT, CONTEXT_ID, DEVICE_R1, DEVICE_R1_ID,
+    DEVICE_R1_UUID, DEVICE_R2, DEVICE_R2_ID, DEVICE_R2_UUID, DEVICE_R3, DEVICE_R3_ID, DEVICE_R3_UUID, LINK_R1_R2,
+    LINK_R1_R2_ID, LINK_R1_R2_UUID, SERVICE_R1_R2, SERVICE_R1_R2_ID, SERVICE_R1_R2_UUID, SERVICE_R1_R3,
+    SERVICE_R1_R3_ID, SERVICE_R1_R3_UUID, SERVICE_R2_R3, SERVICE_R2_R3_ID, SERVICE_R2_R3_UUID, TOPOLOGY, TOPOLOGY_ID)
 
 LOGGER = logging.getLogger(__name__)
 LOGGER.setLevel(logging.DEBUG)
@@ -98,74 +97,6 @@ def do_rest_request(url : str):
     assert reply.status_code == 200, 'Reply failed with code {}'.format(reply.status_code)
     return reply.json()
 
-class EventsCollector:
-    def __init__(self, context_client_grpc : ContextClient) -> None: # pylint: disable=redefined-outer-name
-        self._events_queue = Queue()
-
-        self._context_stream    = context_client_grpc.GetContextEvents(Empty())
-        self._topology_stream   = context_client_grpc.GetTopologyEvents(Empty())
-        self._device_stream     = context_client_grpc.GetDeviceEvents(Empty())
-        self._link_stream       = context_client_grpc.GetLinkEvents(Empty())
-        self._service_stream    = context_client_grpc.GetServiceEvents(Empty())
-        self._connection_stream = context_client_grpc.GetConnectionEvents(Empty())
-
-        self._context_thread    = threading.Thread(target=self._collect, args=(self._context_stream   ,), daemon=False)
-        self._topology_thread   = threading.Thread(target=self._collect, args=(self._topology_stream  ,), daemon=False)
-        self._device_thread     = threading.Thread(target=self._collect, args=(self._device_stream    ,), daemon=False)
-        self._link_thread       = threading.Thread(target=self._collect, args=(self._link_stream      ,), daemon=False)
-        self._service_thread    = threading.Thread(target=self._collect, args=(self._service_stream   ,), daemon=False)
-        self._connection_thread = threading.Thread(target=self._collect, args=(self._connection_stream,), daemon=False)
-
-    def _collect(self, events_stream) -> None:
-        try:
-            for event in events_stream:
-                self._events_queue.put_nowait(event)
-        except grpc.RpcError as e:
-            if e.code() != grpc.StatusCode.CANCELLED: # pylint: disable=no-member
-                raise # pragma: no cover
-
-    def start(self):
-        self._context_thread.start()
-        self._topology_thread.start()
-        self._device_thread.start()
-        self._link_thread.start()
-        self._service_thread.start()
-        self._connection_thread.start()
-
-    def get_event(self, block : bool = True, timeout : float = 0.1):
-        return self._events_queue.get(block=block, timeout=timeout)
-
-    def get_events(self, block : bool = True, timeout : float = 0.1, count : int = None):
-        events = []
-        if count is None:
-            while True:
-                try:
-                    events.append(self.get_event(block=block, timeout=timeout))
-                except Empty: # pylint: disable=catching-non-exception
-                    break
-        else:
-            for _ in range(count):
-                try:
-                    events.append(self.get_event(block=block, timeout=timeout))
-                except Empty: # pylint: disable=catching-non-exception
-                    pass
-        return sorted(events, key=lambda e: e.event.timestamp)
-
-    def stop(self):
-        self._context_stream.cancel()
-        self._topology_stream.cancel()
-        self._device_stream.cancel()
-        self._link_stream.cancel()
-        self._service_stream.cancel()
-        self._connection_stream.cancel()
-
-        self._context_thread.join()
-        self._topology_thread.join()
-        self._device_thread.join()
-        self._link_thread.join()
-        self._service_thread.join()
-        self._connection_thread.join()
-
 
 # ----- Test gRPC methods ----------------------------------------------------------------------------------------------
 
@@ -218,7 +149,7 @@ def test_grpc_context(
     assert e.value.details() == msg
 
     with pytest.raises(grpc.RpcError) as e:
-        WRONG_SERVICE_ID = copy.deepcopy(SERVICE_DEV1_DEV2_ID)
+        WRONG_SERVICE_ID = copy.deepcopy(SERVICE_R1_R2_ID)
         WRONG_SERVICE_ID['context_id']['context_uuid']['uuid'] = 'wrong-context-uuid'
         WRONG_CONTEXT = copy.deepcopy(CONTEXT)
         WRONG_CONTEXT['service_ids'].append(WRONG_SERVICE_ID)
@@ -455,9 +386,9 @@ def test_grpc_device(
 
     # ----- Get when the object does not exist -------------------------------------------------------------------------
     with pytest.raises(grpc.RpcError) as e:
-        context_client_grpc.GetDevice(DeviceId(**DEVICE1_ID))
+        context_client_grpc.GetDevice(DeviceId(**DEVICE_R1_ID))
     assert e.value.code() == grpc.StatusCode.NOT_FOUND
-    assert e.value.details() == 'Device({:s}) not found'.format(DEVICE1_UUID)
+    assert e.value.details() == 'Device({:s}) not found'.format(DEVICE_R1_UUID)
 
     # ----- List when the object does not exist ------------------------------------------------------------------------
     response = context_client_grpc.ListDeviceIds(Empty())
@@ -476,32 +407,32 @@ def test_grpc_device(
 
     # ----- Create the object ------------------------------------------------------------------------------------------
     with pytest.raises(grpc.RpcError) as e:
-        WRONG_DEVICE = copy.deepcopy(DEVICE1)
+        WRONG_DEVICE = copy.deepcopy(DEVICE_R1)
         WRONG_DEVICE['device_endpoints'][0]['endpoint_id']['device_id']['device_uuid']['uuid'] = 'wrong-device-uuid'
         context_client_grpc.SetDevice(Device(**WRONG_DEVICE))
     assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
     msg = 'request.device_endpoints[0].device_id.device_uuid.uuid(wrong-device-uuid) is invalid; '\
-          'should be == request.device_id.device_uuid.uuid(DEV1)'
+          'should be == request.device_id.device_uuid.uuid({:s})'.format(DEVICE_R1_UUID)
     assert e.value.details() == msg
 
-    response = context_client_grpc.SetDevice(Device(**DEVICE1))
-    assert response.device_uuid.uuid == DEVICE1_UUID
+    response = context_client_grpc.SetDevice(Device(**DEVICE_R1))
+    assert response.device_uuid.uuid == DEVICE_R1_UUID
 
     # ----- Check create event -----------------------------------------------------------------------------------------
     event = events_collector.get_event(block=True)
     assert isinstance(event, DeviceEvent)
     assert event.event.event_type == EventTypeEnum.EVENTTYPE_CREATE
-    assert event.device_id.device_uuid.uuid == DEVICE1_UUID
+    assert event.device_id.device_uuid.uuid == DEVICE_R1_UUID
 
     # ----- Update the object ------------------------------------------------------------------------------------------
-    response = context_client_grpc.SetDevice(Device(**DEVICE1))
-    assert response.device_uuid.uuid == DEVICE1_UUID
+    response = context_client_grpc.SetDevice(Device(**DEVICE_R1))
+    assert response.device_uuid.uuid == DEVICE_R1_UUID
 
     # ----- Check update event -----------------------------------------------------------------------------------------
     event = events_collector.get_event(block=True)
     assert isinstance(event, DeviceEvent)
     assert event.event.event_type == EventTypeEnum.EVENTTYPE_UPDATE
-    assert event.device_id.device_uuid.uuid == DEVICE1_UUID
+    assert event.device_id.device_uuid.uuid == DEVICE_R1_UUID
 
     # ----- Dump state of database after create/update the object ------------------------------------------------------
     db_entries = context_database.dump()
@@ -509,34 +440,34 @@ def test_grpc_device(
     for db_entry in db_entries:
         LOGGER.info('  [{:>4s}] {:40s} :: {:s}'.format(*db_entry)) # pragma: no cover
     LOGGER.info('-----------------------------------------------------------')
-    assert len(db_entries) == 41
+    assert len(db_entries) == 40
 
     # ----- Get when the object exists ---------------------------------------------------------------------------------
-    response = context_client_grpc.GetDevice(DeviceId(**DEVICE1_ID))
-    assert response.device_id.device_uuid.uuid == DEVICE1_UUID
+    response = context_client_grpc.GetDevice(DeviceId(**DEVICE_R1_ID))
+    assert response.device_id.device_uuid.uuid == DEVICE_R1_UUID
     assert response.device_type == 'packet-router'
     assert len(response.device_config.config_rules) == 3
-    assert response.device_operational_status == DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_ENABLED
-    assert len(response.device_drivers) == 2
+    assert response.device_operational_status == DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_DISABLED
+    assert len(response.device_drivers) == 1
     assert len(response.device_endpoints) == 3
 
     # ----- List when the object exists --------------------------------------------------------------------------------
     response = context_client_grpc.ListDeviceIds(Empty())
     assert len(response.device_ids) == 1
-    assert response.device_ids[0].device_uuid.uuid == DEVICE1_UUID
+    assert response.device_ids[0].device_uuid.uuid == DEVICE_R1_UUID
 
     response = context_client_grpc.ListDevices(Empty())
     assert len(response.devices) == 1
-    assert response.devices[0].device_id.device_uuid.uuid == DEVICE1_UUID
+    assert response.devices[0].device_id.device_uuid.uuid == DEVICE_R1_UUID
     assert response.devices[0].device_type == 'packet-router'
     assert len(response.devices[0].device_config.config_rules) == 3
-    assert response.devices[0].device_operational_status == DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_ENABLED
-    assert len(response.devices[0].device_drivers) == 2
+    assert response.devices[0].device_operational_status == DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_DISABLED
+    assert len(response.devices[0].device_drivers) == 1
     assert len(response.devices[0].device_endpoints) == 3
 
     # ----- Create object relation -------------------------------------------------------------------------------------
     TOPOLOGY_WITH_DEVICE = copy.deepcopy(TOPOLOGY)
-    TOPOLOGY_WITH_DEVICE['device_ids'].append(DEVICE1_ID)
+    TOPOLOGY_WITH_DEVICE['device_ids'].append(DEVICE_R1_ID)
     response = context_client_grpc.SetTopology(Topology(**TOPOLOGY_WITH_DEVICE))
     assert response.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID
     assert response.topology_uuid.uuid == DEFAULT_TOPOLOGY_UUID
@@ -553,7 +484,7 @@ def test_grpc_device(
     assert response.topology_id.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID
     assert response.topology_id.topology_uuid.uuid == DEFAULT_TOPOLOGY_UUID
     assert len(response.device_ids) == 1
-    assert response.device_ids[0].device_uuid.uuid == DEVICE1_UUID
+    assert response.device_ids[0].device_uuid.uuid == DEVICE_R1_UUID
     assert len(response.link_ids) == 0
 
     # ----- Dump state of database after creating the object relation --------------------------------------------------
@@ -562,10 +493,10 @@ def test_grpc_device(
     for db_entry in db_entries:
         LOGGER.info('  [{:>4s}] {:40s} :: {:s}'.format(*db_entry)) # pragma: no cover
     LOGGER.info('-----------------------------------------------------------')
-    assert len(db_entries) == 41
+    assert len(db_entries) == 40
 
     # ----- Remove the object ------------------------------------------------------------------------------------------
-    context_client_grpc.RemoveDevice(DeviceId(**DEVICE1_ID))
+    context_client_grpc.RemoveDevice(DeviceId(**DEVICE_R1_ID))
     context_client_grpc.RemoveTopology(TopologyId(**TOPOLOGY_ID))
     context_client_grpc.RemoveContext(ContextId(**CONTEXT_ID))
 
@@ -574,7 +505,7 @@ def test_grpc_device(
 
     assert isinstance(events[0], DeviceEvent)
     assert events[0].event.event_type == EventTypeEnum.EVENTTYPE_REMOVE
-    assert events[0].device_id.device_uuid.uuid == DEVICE1_UUID
+    assert events[0].device_id.device_uuid.uuid == DEVICE_R1_UUID
 
     assert isinstance(events[1], TopologyEvent)
     assert events[1].event.event_type == EventTypeEnum.EVENTTYPE_REMOVE
@@ -617,11 +548,11 @@ def test_grpc_link(
     assert response.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID
     assert response.topology_uuid.uuid == DEFAULT_TOPOLOGY_UUID
 
-    response = context_client_grpc.SetDevice(Device(**DEVICE1))
-    assert response.device_uuid.uuid == DEVICE1_UUID
+    response = context_client_grpc.SetDevice(Device(**DEVICE_R1))
+    assert response.device_uuid.uuid == DEVICE_R1_UUID
 
-    response = context_client_grpc.SetDevice(Device(**DEVICE2))
-    assert response.device_uuid.uuid == DEVICE2_UUID
+    response = context_client_grpc.SetDevice(Device(**DEVICE_R2))
+    assert response.device_uuid.uuid == DEVICE_R2_UUID
 
     events = events_collector.get_events(block=True, count=4)
 
@@ -636,17 +567,17 @@ def test_grpc_link(
 
     assert isinstance(events[2], DeviceEvent)
     assert events[2].event.event_type == EventTypeEnum.EVENTTYPE_CREATE
-    assert events[2].device_id.device_uuid.uuid == DEVICE1_UUID
+    assert events[2].device_id.device_uuid.uuid == DEVICE_R1_UUID
 
     assert isinstance(events[3], DeviceEvent)
     assert events[3].event.event_type == EventTypeEnum.EVENTTYPE_CREATE
-    assert events[3].device_id.device_uuid.uuid == DEVICE2_UUID
+    assert events[3].device_id.device_uuid.uuid == DEVICE_R2_UUID
 
     # ----- Get when the object does not exist -------------------------------------------------------------------------
     with pytest.raises(grpc.RpcError) as e:
-        context_client_grpc.GetLink(LinkId(**LINK_DEV1_DEV2_ID))
+        context_client_grpc.GetLink(LinkId(**LINK_R1_R2_ID))
     assert e.value.code() == grpc.StatusCode.NOT_FOUND
-    assert e.value.details() == 'Link({:s}) not found'.format(LINK_DEV1_DEV2_UUID)
+    assert e.value.details() == 'Link({:s}) not found'.format(LINK_R1_R2_UUID)
 
     # ----- List when the object does not exist ------------------------------------------------------------------------
     response = context_client_grpc.ListLinkIds(Empty())
@@ -661,27 +592,27 @@ def test_grpc_link(
     for db_entry in db_entries:
         LOGGER.info('  [{:>4s}] {:40s} :: {:s}'.format(*db_entry)) # pragma: no cover
     LOGGER.info('-----------------------------------------------------------')
-    assert len(db_entries) == 69
+    assert len(db_entries) == 67
 
     # ----- Create the object ------------------------------------------------------------------------------------------
-    response = context_client_grpc.SetLink(Link(**LINK_DEV1_DEV2))
-    assert response.link_uuid.uuid == LINK_DEV1_DEV2_UUID
+    response = context_client_grpc.SetLink(Link(**LINK_R1_R2))
+    assert response.link_uuid.uuid == LINK_R1_R2_UUID
 
     # ----- Check create event -----------------------------------------------------------------------------------------
     event = events_collector.get_event(block=True)
     assert isinstance(event, LinkEvent)
     assert event.event.event_type == EventTypeEnum.EVENTTYPE_CREATE
-    assert event.link_id.link_uuid.uuid == LINK_DEV1_DEV2_UUID
+    assert event.link_id.link_uuid.uuid == LINK_R1_R2_UUID
 
     # ----- Update the object ------------------------------------------------------------------------------------------
-    response = context_client_grpc.SetLink(Link(**LINK_DEV1_DEV2))
-    assert response.link_uuid.uuid == LINK_DEV1_DEV2_UUID
+    response = context_client_grpc.SetLink(Link(**LINK_R1_R2))
+    assert response.link_uuid.uuid == LINK_R1_R2_UUID
 
     # ----- Check update event -----------------------------------------------------------------------------------------
     event = events_collector.get_event(block=True)
     assert isinstance(event, LinkEvent)
     assert event.event.event_type == EventTypeEnum.EVENTTYPE_UPDATE
-    assert event.link_id.link_uuid.uuid == LINK_DEV1_DEV2_UUID
+    assert event.link_id.link_uuid.uuid == LINK_R1_R2_UUID
 
     # ----- Dump state of database after create/update the object ------------------------------------------------------
     db_entries = context_database.dump()
@@ -689,26 +620,26 @@ def test_grpc_link(
     for db_entry in db_entries:
         LOGGER.info('  [{:>4s}] {:40s} :: {:s}'.format(*db_entry)) # pragma: no cover
     LOGGER.info('-----------------------------------------------------------')
-    assert len(db_entries) == 77
+    assert len(db_entries) == 75
 
     # ----- Get when the object exists ---------------------------------------------------------------------------------
-    response = context_client_grpc.GetLink(LinkId(**LINK_DEV1_DEV2_ID))
-    assert response.link_id.link_uuid.uuid == LINK_DEV1_DEV2_UUID
+    response = context_client_grpc.GetLink(LinkId(**LINK_R1_R2_ID))
+    assert response.link_id.link_uuid.uuid == LINK_R1_R2_UUID
     assert len(response.link_endpoint_ids) == 2
 
     # ----- List when the object exists --------------------------------------------------------------------------------
     response = context_client_grpc.ListLinkIds(Empty())
     assert len(response.link_ids) == 1
-    assert response.link_ids[0].link_uuid.uuid == LINK_DEV1_DEV2_UUID
+    assert response.link_ids[0].link_uuid.uuid == LINK_R1_R2_UUID
 
     response = context_client_grpc.ListLinks(Empty())
     assert len(response.links) == 1
-    assert response.links[0].link_id.link_uuid.uuid == LINK_DEV1_DEV2_UUID
+    assert response.links[0].link_id.link_uuid.uuid == LINK_R1_R2_UUID
     assert len(response.links[0].link_endpoint_ids) == 2
 
     # ----- Create object relation -------------------------------------------------------------------------------------
     TOPOLOGY_WITH_LINK = copy.deepcopy(TOPOLOGY)
-    TOPOLOGY_WITH_LINK['link_ids'].append(LINK_DEV1_DEV2_ID)
+    TOPOLOGY_WITH_LINK['link_ids'].append(LINK_R1_R2_ID)
     response = context_client_grpc.SetTopology(Topology(**TOPOLOGY_WITH_LINK))
     assert response.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID
     assert response.topology_uuid.uuid == DEFAULT_TOPOLOGY_UUID
@@ -725,22 +656,22 @@ def test_grpc_link(
     assert response.topology_id.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID
     assert response.topology_id.topology_uuid.uuid == DEFAULT_TOPOLOGY_UUID
     assert len(response.device_ids) == 2
-    assert response.device_ids[0].device_uuid.uuid == DEVICE1_UUID
-    assert response.device_ids[1].device_uuid.uuid == DEVICE2_UUID
+    assert response.device_ids[0].device_uuid.uuid == DEVICE_R1_UUID
+    assert response.device_ids[1].device_uuid.uuid == DEVICE_R2_UUID
     assert len(response.link_ids) == 1
-    assert response.link_ids[0].link_uuid.uuid == LINK_DEV1_DEV2_UUID
+    assert response.link_ids[0].link_uuid.uuid == LINK_R1_R2_UUID
 
     db_entries = context_database.dump()
     LOGGER.info('----- Database Dump [{:3d} entries] -------------------------'.format(len(db_entries)))
     for db_entry in db_entries:
         LOGGER.info('  [{:>4s}] {:40s} :: {:s}'.format(*db_entry)) # pragma: no cover
     LOGGER.info('-----------------------------------------------------------')
-    assert len(db_entries) == 77
+    assert len(db_entries) == 75
 
     # ----- Remove the object ------------------------------------------------------------------------------------------
-    context_client_grpc.RemoveLink(LinkId(**LINK_DEV1_DEV2_ID))
-    context_client_grpc.RemoveDevice(DeviceId(**DEVICE1_ID))
-    context_client_grpc.RemoveDevice(DeviceId(**DEVICE2_ID))
+    context_client_grpc.RemoveLink(LinkId(**LINK_R1_R2_ID))
+    context_client_grpc.RemoveDevice(DeviceId(**DEVICE_R1_ID))
+    context_client_grpc.RemoveDevice(DeviceId(**DEVICE_R2_ID))
     context_client_grpc.RemoveTopology(TopologyId(**TOPOLOGY_ID))
     context_client_grpc.RemoveContext(ContextId(**CONTEXT_ID))
 
@@ -749,15 +680,15 @@ def test_grpc_link(
 
     assert isinstance(events[0], LinkEvent)
     assert events[0].event.event_type == EventTypeEnum.EVENTTYPE_REMOVE
-    assert events[0].link_id.link_uuid.uuid == LINK_DEV1_DEV2_UUID
+    assert events[0].link_id.link_uuid.uuid == LINK_R1_R2_UUID
 
     assert isinstance(events[1], DeviceEvent)
     assert events[1].event.event_type == EventTypeEnum.EVENTTYPE_REMOVE
-    assert events[1].device_id.device_uuid.uuid == DEVICE1_UUID
+    assert events[1].device_id.device_uuid.uuid == DEVICE_R1_UUID
 
     assert isinstance(events[2], DeviceEvent)
     assert events[2].event.event_type == EventTypeEnum.EVENTTYPE_REMOVE
-    assert events[2].device_id.device_uuid.uuid == DEVICE2_UUID
+    assert events[2].device_id.device_uuid.uuid == DEVICE_R2_UUID
 
     assert isinstance(events[3], TopologyEvent)
     assert events[3].event.event_type == EventTypeEnum.EVENTTYPE_REMOVE
@@ -800,11 +731,11 @@ def test_grpc_service(
     assert response.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID
     assert response.topology_uuid.uuid == DEFAULT_TOPOLOGY_UUID
 
-    response = context_client_grpc.SetDevice(Device(**DEVICE1))
-    assert response.device_uuid.uuid == DEVICE1_UUID
+    response = context_client_grpc.SetDevice(Device(**DEVICE_R1))
+    assert response.device_uuid.uuid == DEVICE_R1_UUID
 
-    response = context_client_grpc.SetDevice(Device(**DEVICE2))
-    assert response.device_uuid.uuid == DEVICE2_UUID
+    response = context_client_grpc.SetDevice(Device(**DEVICE_R2))
+    assert response.device_uuid.uuid == DEVICE_R2_UUID
 
     events = events_collector.get_events(block=True, count=4)
 
@@ -819,17 +750,17 @@ def test_grpc_service(
 
     assert isinstance(events[2], DeviceEvent)
     assert events[2].event.event_type == EventTypeEnum.EVENTTYPE_CREATE
-    assert events[2].device_id.device_uuid.uuid == DEVICE1_UUID
+    assert events[2].device_id.device_uuid.uuid == DEVICE_R1_UUID
 
     assert isinstance(events[3], DeviceEvent)
     assert events[3].event.event_type == EventTypeEnum.EVENTTYPE_CREATE
-    assert events[3].device_id.device_uuid.uuid == DEVICE2_UUID
+    assert events[3].device_id.device_uuid.uuid == DEVICE_R2_UUID
 
     # ----- Get when the object does not exist -------------------------------------------------------------------------
     with pytest.raises(grpc.RpcError) as e:
-        context_client_grpc.GetService(ServiceId(**SERVICE_DEV1_DEV2_ID))
+        context_client_grpc.GetService(ServiceId(**SERVICE_R1_R2_ID))
     assert e.value.code() == grpc.StatusCode.NOT_FOUND
-    assert e.value.details() == 'Service({:s}/{:s}) not found'.format(DEFAULT_CONTEXT_UUID, SERVICE_DEV1_DEV2_UUID)
+    assert e.value.details() == 'Service({:s}/{:s}) not found'.format(DEFAULT_CONTEXT_UUID, SERVICE_R1_R2_UUID)
 
     # ----- List when the object does not exist ------------------------------------------------------------------------
     response = context_client_grpc.ListServiceIds(ContextId(**CONTEXT_ID))
@@ -844,25 +775,25 @@ def test_grpc_service(
     for db_entry in db_entries:
         LOGGER.info('  [{:>4s}] {:40s} :: {:s}'.format(*db_entry)) # pragma: no cover
     LOGGER.info('-----------------------------------------------------------')
-    assert len(db_entries) == 69
+    assert len(db_entries) == 67
 
     # ----- Create the object ------------------------------------------------------------------------------------------
     with pytest.raises(grpc.RpcError) as e:
-        WRONG_SERVICE = copy.deepcopy(SERVICE_DEV1_DEV2)
+        WRONG_SERVICE = copy.deepcopy(SERVICE_R1_R2)
         WRONG_SERVICE['service_endpoint_ids'][0]\
             ['topology_id']['context_id']['context_uuid']['uuid'] = 'wrong-context-uuid'
         context_client_grpc.SetService(Service(**WRONG_SERVICE))
     assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
     msg = 'request.service_endpoint_ids[0].topology_id.context_id.context_uuid.uuid(wrong-context-uuid) is invalid; '\
-          'should be == request.service_id.context_id.context_uuid.uuid(admin)'
+          'should be == request.service_id.context_id.context_uuid.uuid({:s})'.format(DEFAULT_CONTEXT_UUID)
     assert e.value.details() == msg
 
-    response = context_client_grpc.SetService(Service(**SERVICE_DEV1_DEV2))
+    response = context_client_grpc.SetService(Service(**SERVICE_R1_R2))
     assert response.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID
-    assert response.service_uuid.uuid == SERVICE_DEV1_DEV2_UUID
+    assert response.service_uuid.uuid == SERVICE_R1_R2_UUID
 
     CONTEXT_WITH_SERVICE = copy.deepcopy(CONTEXT)
-    CONTEXT_WITH_SERVICE['service_ids'].append(SERVICE_DEV1_DEV2_ID)
+    CONTEXT_WITH_SERVICE['service_ids'].append(SERVICE_R1_R2_ID)
     response = context_client_grpc.SetContext(Context(**CONTEXT_WITH_SERVICE))
     assert response.context_uuid.uuid == DEFAULT_CONTEXT_UUID
 
@@ -872,23 +803,23 @@ def test_grpc_service(
     assert isinstance(events[0], ServiceEvent)
     assert events[0].event.event_type == EventTypeEnum.EVENTTYPE_CREATE
     assert events[0].service_id.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID
-    assert events[0].service_id.service_uuid.uuid == SERVICE_DEV1_DEV2_UUID
+    assert events[0].service_id.service_uuid.uuid == SERVICE_R1_R2_UUID
 
     assert isinstance(events[1], ContextEvent)
     assert events[1].event.event_type == EventTypeEnum.EVENTTYPE_UPDATE
     assert events[1].context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID
 
     # ----- Update the object ------------------------------------------------------------------------------------------
-    response = context_client_grpc.SetService(Service(**SERVICE_DEV1_DEV2))
+    response = context_client_grpc.SetService(Service(**SERVICE_R1_R2))
     assert response.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID
-    assert response.service_uuid.uuid == SERVICE_DEV1_DEV2_UUID
+    assert response.service_uuid.uuid == SERVICE_R1_R2_UUID
 
     # ----- Check update event -----------------------------------------------------------------------------------------
     event = events_collector.get_event(block=True)
     assert isinstance(event, ServiceEvent)
     assert event.event.event_type == EventTypeEnum.EVENTTYPE_UPDATE
     assert event.service_id.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID
-    assert event.service_id.service_uuid.uuid == SERVICE_DEV1_DEV2_UUID
+    assert event.service_id.service_uuid.uuid == SERVICE_R1_R2_UUID
 
     # ----- Dump state of database after create/update the object ------------------------------------------------------
     db_entries = context_database.dump()
@@ -896,38 +827,38 @@ def test_grpc_service(
     for db_entry in db_entries:
         LOGGER.info('  [{:>4s}] {:40s} :: {:s}'.format(*db_entry)) # pragma: no cover
     LOGGER.info('-----------------------------------------------------------')
-    assert len(db_entries) == 86
+    assert len(db_entries) == 84
 
     # ----- Get when the object exists ---------------------------------------------------------------------------------
-    response = context_client_grpc.GetService(ServiceId(**SERVICE_DEV1_DEV2_ID))
+    response = context_client_grpc.GetService(ServiceId(**SERVICE_R1_R2_ID))
     assert response.service_id.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID
-    assert response.service_id.service_uuid.uuid == SERVICE_DEV1_DEV2_UUID
+    assert response.service_id.service_uuid.uuid == SERVICE_R1_R2_UUID
     assert response.service_type == ServiceTypeEnum.SERVICETYPE_L3NM
     assert len(response.service_endpoint_ids) == 2
     assert len(response.service_constraints) == 2
-    assert response.service_status.service_status == ServiceStatusEnum.SERVICESTATUS_ACTIVE
+    assert response.service_status.service_status == ServiceStatusEnum.SERVICESTATUS_PLANNED
     assert len(response.service_config.config_rules) == 3
 
     # ----- List when the object exists --------------------------------------------------------------------------------
     response = context_client_grpc.ListServiceIds(ContextId(**CONTEXT_ID))
     assert len(response.service_ids) == 1
     assert response.service_ids[0].context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID
-    assert response.service_ids[0].service_uuid.uuid == SERVICE_DEV1_DEV2_UUID
+    assert response.service_ids[0].service_uuid.uuid == SERVICE_R1_R2_UUID
 
     response = context_client_grpc.ListServices(ContextId(**CONTEXT_ID))
     assert len(response.services) == 1
     assert response.services[0].service_id.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID
-    assert response.services[0].service_id.service_uuid.uuid == SERVICE_DEV1_DEV2_UUID
+    assert response.services[0].service_id.service_uuid.uuid == SERVICE_R1_R2_UUID
     assert response.services[0].service_type == ServiceTypeEnum.SERVICETYPE_L3NM
     assert len(response.services[0].service_endpoint_ids) == 2
     assert len(response.services[0].service_constraints) == 2
-    assert response.services[0].service_status.service_status == ServiceStatusEnum.SERVICESTATUS_ACTIVE
+    assert response.services[0].service_status.service_status == ServiceStatusEnum.SERVICESTATUS_PLANNED
     assert len(response.services[0].service_config.config_rules) == 3
 
     # ----- Remove the object ------------------------------------------------------------------------------------------
-    context_client_grpc.RemoveService(ServiceId(**SERVICE_DEV1_DEV2_ID))
-    context_client_grpc.RemoveDevice(DeviceId(**DEVICE1_ID))
-    context_client_grpc.RemoveDevice(DeviceId(**DEVICE2_ID))
+    context_client_grpc.RemoveService(ServiceId(**SERVICE_R1_R2_ID))
+    context_client_grpc.RemoveDevice(DeviceId(**DEVICE_R1_ID))
+    context_client_grpc.RemoveDevice(DeviceId(**DEVICE_R2_ID))
     context_client_grpc.RemoveTopology(TopologyId(**TOPOLOGY_ID))
     context_client_grpc.RemoveContext(ContextId(**CONTEXT_ID))
 
@@ -936,15 +867,15 @@ def test_grpc_service(
 
     assert isinstance(events[0], ServiceEvent)
     assert events[0].service_id.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID
-    assert events[0].service_id.service_uuid.uuid == SERVICE_DEV1_DEV2_UUID
+    assert events[0].service_id.service_uuid.uuid == SERVICE_R1_R2_UUID
 
     assert isinstance(events[1], DeviceEvent)
     assert events[1].event.event_type == EventTypeEnum.EVENTTYPE_REMOVE
-    assert events[1].device_id.device_uuid.uuid == DEVICE1_UUID
+    assert events[1].device_id.device_uuid.uuid == DEVICE_R1_UUID
 
     assert isinstance(events[2], DeviceEvent)
     assert events[2].event.event_type == EventTypeEnum.EVENTTYPE_REMOVE
-    assert events[2].device_id.device_uuid.uuid == DEVICE2_UUID
+    assert events[2].device_id.device_uuid.uuid == DEVICE_R2_UUID
 
     assert isinstance(events[3], TopologyEvent)
     assert events[3].event.event_type == EventTypeEnum.EVENTTYPE_REMOVE
@@ -987,39 +918,39 @@ def test_grpc_connection(
     assert response.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID
     assert response.topology_uuid.uuid == DEFAULT_TOPOLOGY_UUID
 
-    response = context_client_grpc.SetDevice(Device(**DEVICE1))
-    assert response.device_uuid.uuid == DEVICE1_UUID
+    response = context_client_grpc.SetDevice(Device(**DEVICE_R1))
+    assert response.device_uuid.uuid == DEVICE_R1_UUID
 
-    response = context_client_grpc.SetDevice(Device(**DEVICE2))
-    assert response.device_uuid.uuid == DEVICE2_UUID
+    response = context_client_grpc.SetDevice(Device(**DEVICE_R2))
+    assert response.device_uuid.uuid == DEVICE_R2_UUID
 
-    response = context_client_grpc.SetDevice(Device(**DEVICE3))
-    assert response.device_uuid.uuid == DEVICE3_UUID
+    response = context_client_grpc.SetDevice(Device(**DEVICE_R3))
+    assert response.device_uuid.uuid == DEVICE_R3_UUID
 
-    response = context_client_grpc.SetService(Service(**SERVICE_DEV1_DEV2))
+    response = context_client_grpc.SetService(Service(**SERVICE_R1_R2))
     assert response.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID
-    assert response.service_uuid.uuid == SERVICE_DEV1_DEV2_UUID
+    assert response.service_uuid.uuid == SERVICE_R1_R2_UUID
 
     CONTEXT_WITH_SERVICE = copy.deepcopy(CONTEXT)
-    CONTEXT_WITH_SERVICE['service_ids'].append(SERVICE_DEV1_DEV2_ID)
+    CONTEXT_WITH_SERVICE['service_ids'].append(SERVICE_R1_R2_ID)
     response = context_client_grpc.SetContext(Context(**CONTEXT_WITH_SERVICE))
     assert response.context_uuid.uuid == DEFAULT_CONTEXT_UUID
 
-    response = context_client_grpc.SetService(Service(**SERVICE_DEV2_DEV3))
+    response = context_client_grpc.SetService(Service(**SERVICE_R2_R3))
     assert response.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID
-    assert response.service_uuid.uuid == SERVICE_DEV2_DEV3_UUID
+    assert response.service_uuid.uuid == SERVICE_R2_R3_UUID
 
     CONTEXT_WITH_SERVICE = copy.deepcopy(CONTEXT)
-    CONTEXT_WITH_SERVICE['service_ids'].append(SERVICE_DEV2_DEV3_ID)
+    CONTEXT_WITH_SERVICE['service_ids'].append(SERVICE_R2_R3_ID)
     response = context_client_grpc.SetContext(Context(**CONTEXT_WITH_SERVICE))
     assert response.context_uuid.uuid == DEFAULT_CONTEXT_UUID
 
-    response = context_client_grpc.SetService(Service(**SERVICE_DEV1_DEV3))
+    response = context_client_grpc.SetService(Service(**SERVICE_R1_R3))
     assert response.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID
-    assert response.service_uuid.uuid == SERVICE_DEV1_DEV3_UUID
+    assert response.service_uuid.uuid == SERVICE_R1_R3_UUID
 
     CONTEXT_WITH_SERVICE = copy.deepcopy(CONTEXT)
-    CONTEXT_WITH_SERVICE['service_ids'].append(SERVICE_DEV1_DEV3_ID)
+    CONTEXT_WITH_SERVICE['service_ids'].append(SERVICE_R1_R3_ID)
     response = context_client_grpc.SetContext(Context(**CONTEXT_WITH_SERVICE))
     assert response.context_uuid.uuid == DEFAULT_CONTEXT_UUID
 
@@ -1036,20 +967,20 @@ def test_grpc_connection(
 
     assert isinstance(events[2], DeviceEvent)
     assert events[2].event.event_type == EventTypeEnum.EVENTTYPE_CREATE
-    assert events[2].device_id.device_uuid.uuid == DEVICE1_UUID
+    assert events[2].device_id.device_uuid.uuid == DEVICE_R1_UUID
 
     assert isinstance(events[3], DeviceEvent)
     assert events[3].event.event_type == EventTypeEnum.EVENTTYPE_CREATE
-    assert events[3].device_id.device_uuid.uuid == DEVICE2_UUID
+    assert events[3].device_id.device_uuid.uuid == DEVICE_R2_UUID
 
     assert isinstance(events[4], DeviceEvent)
     assert events[4].event.event_type == EventTypeEnum.EVENTTYPE_CREATE
-    assert events[4].device_id.device_uuid.uuid == DEVICE3_UUID
+    assert events[4].device_id.device_uuid.uuid == DEVICE_R3_UUID
 
     assert isinstance(events[5], ServiceEvent)
     assert events[5].event.event_type == EventTypeEnum.EVENTTYPE_CREATE
     assert events[5].service_id.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID
-    assert events[5].service_id.service_uuid.uuid == SERVICE_DEV1_DEV2_UUID
+    assert events[5].service_id.service_uuid.uuid == SERVICE_R1_R2_UUID
 
     assert isinstance(events[6], ContextEvent)
     assert events[6].event.event_type == EventTypeEnum.EVENTTYPE_UPDATE
@@ -1058,7 +989,7 @@ def test_grpc_connection(
     assert isinstance(events[7], ServiceEvent)
     assert events[7].event.event_type == EventTypeEnum.EVENTTYPE_CREATE
     assert events[7].service_id.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID
-    assert events[7].service_id.service_uuid.uuid == SERVICE_DEV2_DEV3_UUID
+    assert events[7].service_id.service_uuid.uuid == SERVICE_R2_R3_UUID
 
     assert isinstance(events[8], ContextEvent)
     assert events[8].event.event_type == EventTypeEnum.EVENTTYPE_UPDATE
@@ -1067,7 +998,7 @@ def test_grpc_connection(
     assert isinstance(events[9], ServiceEvent)
     assert events[9].event.event_type == EventTypeEnum.EVENTTYPE_CREATE
     assert events[9].service_id.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID
-    assert events[9].service_id.service_uuid.uuid == SERVICE_DEV1_DEV3_UUID
+    assert events[9].service_id.service_uuid.uuid == SERVICE_R1_R3_UUID
 
     assert isinstance(events[10], ContextEvent)
     assert events[10].event.event_type == EventTypeEnum.EVENTTYPE_UPDATE
@@ -1075,15 +1006,15 @@ def test_grpc_connection(
 
     # ----- Get when the object does not exist -------------------------------------------------------------------------
     with pytest.raises(grpc.RpcError) as e:
-        context_client_grpc.GetConnection(ConnectionId(**CONNECTION_DEV1_DEV3_ID))
+        context_client_grpc.GetConnection(ConnectionId(**CONNECTION_R1_R3_ID))
     assert e.value.code() == grpc.StatusCode.NOT_FOUND
-    assert e.value.details() == 'Connection({:s}) not found'.format(CONNECTION_DEV1_DEV3_UUID)
+    assert e.value.details() == 'Connection({:s}) not found'.format(CONNECTION_R1_R3_UUID)
 
     # ----- List when the object does not exist ------------------------------------------------------------------------
-    response = context_client_grpc.ListConnectionIds(ServiceId(**SERVICE_DEV1_DEV3_ID))
+    response = context_client_grpc.ListConnectionIds(ServiceId(**SERVICE_R1_R3_ID))
     assert len(response.connection_ids) == 0
 
-    response = context_client_grpc.ListConnections(ServiceId(**SERVICE_DEV1_DEV3_ID))
+    response = context_client_grpc.ListConnections(ServiceId(**SERVICE_R1_R3_ID))
     assert len(response.connections) == 0
 
     # ----- Dump state of database before create the object ------------------------------------------------------------
@@ -1092,38 +1023,39 @@ def test_grpc_connection(
     for db_entry in db_entries:
         LOGGER.info('  [{:>4s}] {:40s} :: {:s}'.format(*db_entry)) # pragma: no cover
     LOGGER.info('-----------------------------------------------------------')
-    assert len(db_entries) == 140
+    assert len(db_entries) == 137
 
     # ----- Create the object ------------------------------------------------------------------------------------------
     with pytest.raises(grpc.RpcError) as e:
-        WRONG_CONNECTION = copy.deepcopy(CONNECTION_DEV1_DEV3)
+        WRONG_CONNECTION = copy.deepcopy(CONNECTION_R1_R3)
         WRONG_CONNECTION['path_hops_endpoint_ids'][0]\
             ['topology_id']['context_id']['context_uuid']['uuid'] = 'wrong-context-uuid'
         context_client_grpc.SetConnection(Connection(**WRONG_CONNECTION))
     assert e.value.code() == grpc.StatusCode.NOT_FOUND
     # TODO: should we check that all endpoints belong to same topology?
     # TODO: should we check that endpoints form links over the topology?
-    msg = 'EndPoint(DEV1/EP100:wrong-context-uuid/admin) not found'
+    msg = 'EndPoint({:s}/{:s}:wrong-context-uuid/{:s}) not found'.format(
+        DEVICE_R1_UUID, WRONG_CONNECTION['path_hops_endpoint_ids'][0]['endpoint_uuid']['uuid'], DEFAULT_TOPOLOGY_UUID)
     assert e.value.details() == msg
 
-    response = context_client_grpc.SetConnection(Connection(**CONNECTION_DEV1_DEV3))
-    assert response.connection_uuid.uuid == CONNECTION_DEV1_DEV3_UUID
+    response = context_client_grpc.SetConnection(Connection(**CONNECTION_R1_R3))
+    assert response.connection_uuid.uuid == CONNECTION_R1_R3_UUID
 
     # ----- Check create event -----------------------------------------------------------------------------------------
     event = events_collector.get_event(block=True)
     assert isinstance(event, ConnectionEvent)
     assert event.event.event_type == EventTypeEnum.EVENTTYPE_CREATE
-    assert event.connection_id.connection_uuid.uuid == CONNECTION_DEV1_DEV3_UUID
+    assert event.connection_id.connection_uuid.uuid == CONNECTION_R1_R3_UUID
 
     # ----- Update the object ------------------------------------------------------------------------------------------
-    response = context_client_grpc.SetConnection(Connection(**CONNECTION_DEV1_DEV3))
-    assert response.connection_uuid.uuid == CONNECTION_DEV1_DEV3_UUID
+    response = context_client_grpc.SetConnection(Connection(**CONNECTION_R1_R3))
+    assert response.connection_uuid.uuid == CONNECTION_R1_R3_UUID
 
     # ----- Check update event -----------------------------------------------------------------------------------------
     event = events_collector.get_event(block=True)
     assert isinstance(event, ConnectionEvent)
     assert event.event.event_type == EventTypeEnum.EVENTTYPE_UPDATE
-    assert event.connection_id.connection_uuid.uuid == CONNECTION_DEV1_DEV3_UUID
+    assert event.connection_id.connection_uuid.uuid == CONNECTION_R1_R3_UUID
 
     # ----- Dump state of database after create/update the object ------------------------------------------------------
     db_entries = context_database.dump()
@@ -1131,35 +1063,35 @@ def test_grpc_connection(
     for db_entry in db_entries:
         LOGGER.info('  [{:>4s}] {:40s} :: {:s}'.format(*db_entry)) # pragma: no cover
     LOGGER.info('-----------------------------------------------------------')
-    assert len(db_entries) == 156
+    assert len(db_entries) == 153
 
     # ----- Get when the object exists ---------------------------------------------------------------------------------
-    response = context_client_grpc.GetConnection(ConnectionId(**CONNECTION_DEV1_DEV3_ID))
-    assert response.connection_id.connection_uuid.uuid == CONNECTION_DEV1_DEV3_UUID
+    response = context_client_grpc.GetConnection(ConnectionId(**CONNECTION_R1_R3_ID))
+    assert response.connection_id.connection_uuid.uuid == CONNECTION_R1_R3_UUID
     assert response.service_id.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID
-    assert response.service_id.service_uuid.uuid == SERVICE_DEV1_DEV3_UUID
+    assert response.service_id.service_uuid.uuid == SERVICE_R1_R3_UUID
     assert len(response.path_hops_endpoint_ids) == 6
     assert len(response.sub_service_ids) == 2
 
     # ----- List when the object exists --------------------------------------------------------------------------------
-    response = context_client_grpc.ListConnectionIds(ServiceId(**SERVICE_DEV1_DEV3_ID))
+    response = context_client_grpc.ListConnectionIds(ServiceId(**SERVICE_R1_R3_ID))
     assert len(response.connection_ids) == 1
-    assert response.connection_ids[0].connection_uuid.uuid == CONNECTION_DEV1_DEV3_UUID
+    assert response.connection_ids[0].connection_uuid.uuid == CONNECTION_R1_R3_UUID
 
-    response = context_client_grpc.ListConnections(ServiceId(**SERVICE_DEV1_DEV3_ID))
+    response = context_client_grpc.ListConnections(ServiceId(**SERVICE_R1_R3_ID))
     assert len(response.connections) == 1
-    assert response.connections[0].connection_id.connection_uuid.uuid == CONNECTION_DEV1_DEV3_UUID
+    assert response.connections[0].connection_id.connection_uuid.uuid == CONNECTION_R1_R3_UUID
     assert len(response.connections[0].path_hops_endpoint_ids) == 6
     assert len(response.connections[0].sub_service_ids) == 2
 
     # ----- Remove the object ------------------------------------------------------------------------------------------
-    context_client_grpc.RemoveConnection(ConnectionId(**CONNECTION_DEV1_DEV3_ID))
-    context_client_grpc.RemoveService(ServiceId(**SERVICE_DEV1_DEV3_ID))
-    context_client_grpc.RemoveService(ServiceId(**SERVICE_DEV2_DEV3_ID))
-    context_client_grpc.RemoveService(ServiceId(**SERVICE_DEV1_DEV2_ID))
-    context_client_grpc.RemoveDevice(DeviceId(**DEVICE1_ID))
-    context_client_grpc.RemoveDevice(DeviceId(**DEVICE2_ID))
-    context_client_grpc.RemoveDevice(DeviceId(**DEVICE3_ID))
+    context_client_grpc.RemoveConnection(ConnectionId(**CONNECTION_R1_R3_ID))
+    context_client_grpc.RemoveService(ServiceId(**SERVICE_R1_R3_ID))
+    context_client_grpc.RemoveService(ServiceId(**SERVICE_R2_R3_ID))
+    context_client_grpc.RemoveService(ServiceId(**SERVICE_R1_R2_ID))
+    context_client_grpc.RemoveDevice(DeviceId(**DEVICE_R1_ID))
+    context_client_grpc.RemoveDevice(DeviceId(**DEVICE_R2_ID))
+    context_client_grpc.RemoveDevice(DeviceId(**DEVICE_R3_ID))
     context_client_grpc.RemoveTopology(TopologyId(**TOPOLOGY_ID))
     context_client_grpc.RemoveContext(ContextId(**CONTEXT_ID))
 
@@ -1168,34 +1100,34 @@ def test_grpc_connection(
 
     assert isinstance(events[0], ConnectionEvent)
     assert events[0].event.event_type == EventTypeEnum.EVENTTYPE_REMOVE
-    assert events[0].connection_id.connection_uuid.uuid == CONNECTION_DEV1_DEV3_UUID
+    assert events[0].connection_id.connection_uuid.uuid == CONNECTION_R1_R3_UUID
 
     assert isinstance(events[1], ServiceEvent)
     assert events[1].event.event_type == EventTypeEnum.EVENTTYPE_REMOVE
     assert events[1].service_id.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID
-    assert events[1].service_id.service_uuid.uuid == SERVICE_DEV1_DEV3_UUID
+    assert events[1].service_id.service_uuid.uuid == SERVICE_R1_R3_UUID
 
     assert isinstance(events[2], ServiceEvent)
     assert events[2].event.event_type == EventTypeEnum.EVENTTYPE_REMOVE
     assert events[2].service_id.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID
-    assert events[2].service_id.service_uuid.uuid == SERVICE_DEV2_DEV3_UUID
+    assert events[2].service_id.service_uuid.uuid == SERVICE_R2_R3_UUID
 
     assert isinstance(events[3], ServiceEvent)
     assert events[3].event.event_type == EventTypeEnum.EVENTTYPE_REMOVE
     assert events[3].service_id.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID
-    assert events[3].service_id.service_uuid.uuid == SERVICE_DEV1_DEV2_UUID
+    assert events[3].service_id.service_uuid.uuid == SERVICE_R1_R2_UUID
 
     assert isinstance(events[4], DeviceEvent)
     assert events[4].event.event_type == EventTypeEnum.EVENTTYPE_REMOVE
-    assert events[4].device_id.device_uuid.uuid == DEVICE1_UUID
+    assert events[4].device_id.device_uuid.uuid == DEVICE_R1_UUID
 
     assert isinstance(events[5], DeviceEvent)
     assert events[5].event.event_type == EventTypeEnum.EVENTTYPE_REMOVE
-    assert events[5].device_id.device_uuid.uuid == DEVICE2_UUID
+    assert events[5].device_id.device_uuid.uuid == DEVICE_R2_UUID
 
     assert isinstance(events[6], DeviceEvent)
     assert events[6].event.event_type == EventTypeEnum.EVENTTYPE_REMOVE
-    assert events[6].device_id.device_uuid.uuid == DEVICE3_UUID
+    assert events[6].device_id.device_uuid.uuid == DEVICE_R3_UUID
 
     assert isinstance(events[7], TopologyEvent)
     assert events[7].event.event_type == EventTypeEnum.EVENTTYPE_REMOVE
@@ -1269,7 +1201,7 @@ def test_rest_get_services(context_service_rest : RestServer): # pylint: disable
 
 def test_rest_get_service(context_service_rest : RestServer): # pylint: disable=redefined-outer-name
     context_uuid = urllib.parse.quote(DEFAULT_CONTEXT_UUID)
-    service_uuid = urllib.parse.quote(SERVICE_DEV1_DEV2_UUID, safe='')
+    service_uuid = urllib.parse.quote(SERVICE_R1_R2_UUID, safe='')
     reply = do_rest_request('/context/{:s}/service/{:s}'.format(context_uuid, service_uuid))
     validate_service(reply)
 
@@ -1282,7 +1214,7 @@ def test_rest_get_devices(context_service_rest : RestServer): # pylint: disable=
     validate_devices(reply)
 
 def test_rest_get_device(context_service_rest : RestServer): # pylint: disable=redefined-outer-name
-    device_uuid = urllib.parse.quote(DEVICE1_UUID, safe='')
+    device_uuid = urllib.parse.quote(DEVICE_R1_UUID, safe='')
     reply = do_rest_request('/device/{:s}'.format(device_uuid))
     validate_device(reply)
 
@@ -1295,24 +1227,24 @@ def test_rest_get_links(context_service_rest : RestServer): # pylint: disable=re
     validate_links(reply)
 
 def test_rest_get_link(context_service_rest : RestServer): # pylint: disable=redefined-outer-name
-    link_uuid = urllib.parse.quote(LINK_DEV1_DEV2_UUID, safe='')
+    link_uuid = urllib.parse.quote(LINK_R1_R2_UUID, safe='')
     reply = do_rest_request('/link/{:s}'.format(link_uuid))
     validate_link(reply)
 
 def test_rest_get_connection_ids(context_service_rest : RestServer): # pylint: disable=redefined-outer-name
     context_uuid = urllib.parse.quote(DEFAULT_CONTEXT_UUID)
-    service_uuid = urllib.parse.quote(SERVICE_DEV1_DEV3_UUID, safe='')
+    service_uuid = urllib.parse.quote(SERVICE_R1_R3_UUID, safe='')
     reply = do_rest_request('/context/{:s}/service/{:s}/connection_ids'.format(context_uuid, service_uuid))
     validate_connection_ids(reply)
 
 def test_rest_get_connections(context_service_rest : RestServer): # pylint: disable=redefined-outer-name
     context_uuid = urllib.parse.quote(DEFAULT_CONTEXT_UUID)
-    service_uuid = urllib.parse.quote(SERVICE_DEV1_DEV3_UUID, safe='')
+    service_uuid = urllib.parse.quote(SERVICE_R1_R3_UUID, safe='')
     reply = do_rest_request('/context/{:s}/service/{:s}/connections'.format(context_uuid, service_uuid))
     validate_connections(reply)
 
 def test_rest_get_connection(context_service_rest : RestServer): # pylint: disable=redefined-outer-name
-    connection_uuid = urllib.parse.quote(CONNECTION_DEV1_DEV3_UUID, safe='')
+    connection_uuid = urllib.parse.quote(CONNECTION_R1_R3_UUID, safe='')
     reply = do_rest_request('/connection/{:s}'.format(connection_uuid))
     validate_connection(reply)
 
diff --git a/src/dbscanserving/client/DbscanServingClient.py b/src/dbscanserving/client/DbscanServingClient.py
index 4d6614b5d..f4547f6cf 100644
--- a/src/dbscanserving/client/DbscanServingClient.py
+++ b/src/dbscanserving/client/DbscanServingClient.py
@@ -6,6 +6,7 @@ from dbscanserving.proto.dbscanserving_pb2_grpc import DetectorStub
 LOGGER = logging.getLogger(__name__)
 MAX_RETRIES = 15
 DELAY_FUNCTION = delay_exponential(initial=0.01, increment=2.0, maximum=5.0)
+RETRY_DECORATOR = retry(max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
 
 class DbscanServingClient:
     def __init__(self, address, port):
@@ -25,7 +26,7 @@ class DbscanServingClient:
         self.channel = None
         self.stub = None
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def Detect(self, request : DetectionRequest) -> DetectionResponse:
         LOGGER.debug('Detect request: {:s}'.format(str(request)))
         response = self.stub.Detect(request)
diff --git a/src/device/Dockerfile b/src/device/Dockerfile
index 70e3c8dcb..060f42b85 100644
--- a/src/device/Dockerfile
+++ b/src/device/Dockerfile
@@ -25,7 +25,7 @@ RUN mkdir -p /var/teraflow/device
 # Get Python packages per module
 COPY device/requirements.in device/requirements.in
 RUN pip-compile --output-file=device/requirements.txt device/requirements.in
-RUN python3 -m pip install -r device/requirements.in
+RUN python3 -m pip install -r device/requirements.txt
 
 # Add files into working directory
 COPY common/. common
diff --git a/src/device/client/DeviceClient.py b/src/device/client/DeviceClient.py
index 17f0ac715..4c26a6082 100644
--- a/src/device/client/DeviceClient.py
+++ b/src/device/client/DeviceClient.py
@@ -7,6 +7,7 @@ from device.proto.device_pb2_grpc import DeviceServiceStub
 LOGGER = logging.getLogger(__name__)
 MAX_RETRIES = 15
 DELAY_FUNCTION = delay_exponential(initial=0.01, increment=2.0, maximum=5.0)
+RETRY_DECORATOR = retry(max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
 
 class DeviceClient:
     def __init__(self, address, port):
@@ -26,35 +27,35 @@ class DeviceClient:
         self.channel = None
         self.stub = None
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def AddDevice(self, request : Device) -> DeviceId:
         LOGGER.debug('AddDevice request: {:s}'.format(str(request)))
         response = self.stub.AddDevice(request)
         LOGGER.debug('AddDevice result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def ConfigureDevice(self, request : Device) -> DeviceId:
         LOGGER.debug('ConfigureDevice request: {:s}'.format(str(request)))
         response = self.stub.ConfigureDevice(request)
         LOGGER.debug('ConfigureDevice result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def DeleteDevice(self, request : DeviceId) -> Empty:
         LOGGER.debug('DeleteDevice request: {:s}'.format(str(request)))
         response = self.stub.DeleteDevice(request)
         LOGGER.debug('DeleteDevice result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def GetInitialConfig(self, request : DeviceId) -> DeviceConfig:
         LOGGER.debug('GetInitialConfig request: {:s}'.format(str(request)))
         response = self.stub.GetInitialConfig(request)
         LOGGER.debug('GetInitialConfig result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def MonitorDeviceKpi(self, request : MonitoringSettings) -> Empty:
         LOGGER.debug('MonitorDeviceKpi request: {:s}'.format(str(request)))
         response = self.stub.MonitorDeviceKpi(request)
diff --git a/src/device/requirements.in b/src/device/requirements.in
index 6a86f5385..dde08cf19 100644
--- a/src/device/requirements.in
+++ b/src/device/requirements.in
@@ -1,17 +1,20 @@
-anytree
-apscheduler
-fastcache
-grpcio-health-checking
-grpcio
-Jinja2
-netconf-client #1.7.3
-prometheus-client
-pytest
-pytest-benchmark
-python-json-logger
-pytz
-redis
-requests
-xmltodict
+anytree==2.8.0
+APScheduler==3.8.1
+fastcache==1.1.0
+grpcio==1.43.0
+grpcio-health-checking==1.43.0
+Jinja2==3.0.3
+netconf-client==2.0.0 #1.7.3
 p4runtime==1.3.0
-coverage
+paramiko==2.9.2
+prometheus-client==0.13.0
+protobuf==3.19.3
+pytest==6.2.5
+pytest-benchmark==3.4.1
+python-dateutil==2.8.2
+python-json-logger==2.0.2
+pytz==2021.3
+redis==4.1.2
+requests==2.27.1
+xmltodict==0.12.0
+coverage==6.3
diff --git a/src/device/service/DeviceServiceServicerImpl.py b/src/device/service/DeviceServiceServicerImpl.py
index 485cf0a27..44a343de4 100644
--- a/src/device/service/DeviceServiceServicerImpl.py
+++ b/src/device/service/DeviceServiceServicerImpl.py
@@ -1,18 +1,16 @@
-import grpc, json, logging
-from typing import Any, List, Tuple
-from google.protobuf.json_format import MessageToDict
+import grpc, json, logging, re
+from typing import Any, Dict, List, Tuple
 from common.orm.Database import Database
 from common.orm.HighLevel import get_object, update_or_create_object
 from common.orm.backend.Tools import key_to_str
 from common.rpc_method_wrapper.Decorator import create_metrics, safe_and_metered_rpc_method
 from common.rpc_method_wrapper.ServiceExceptions import InvalidArgumentException, OperationFailedException
+from common.tools.grpc.Tools import grpc_message_to_json
 from context.client.ContextClient import ContextClient
 from context.proto.kpi_sample_types_pb2 import KpiSampleType
 from device.proto.context_pb2 import ConfigActionEnum, Device, DeviceConfig, DeviceId, Empty
 from device.proto.device_pb2 import MonitoringSettings
 from device.proto.device_pb2_grpc import DeviceServiceServicer
-from device.service.database.RelationModels import EndPointMonitorKpiModel
-from .MonitoringLoops import MonitoringLoops
 from .database.ConfigModel import (
     ConfigModel, ConfigRuleModel, ORM_ConfigActionEnum, get_config_rules, grpc_config_rules_to_raw, update_config)
 from .database.DatabaseTools import (
@@ -22,10 +20,12 @@ from .database.DeviceModel import DeviceModel, DriverModel
 from .database.EndPointModel import EndPointModel, EndPointMonitorModel
 from .database.KpiModel import KpiModel
 from .database.KpiSampleType import ORM_KpiSampleTypeEnum, grpc_to_enum__kpi_sample_type
+from .database.RelationModels import EndPointMonitorKpiModel
 from .driver_api._Driver import _Driver, RESOURCE_ENDPOINTS #, RESOURCE_INTERFACES, RESOURCE_NETWORK_INSTANCES
 from .driver_api.DriverInstanceCache import DriverInstanceCache
 from .driver_api.Tools import (
     check_delete_errors, check_set_errors, check_subscribe_errors, check_unsubscribe_errors)
+from .MonitoringLoops import MonitoringLoops
 
 LOGGER = logging.getLogger(__name__)
 
@@ -59,9 +59,7 @@ class DeviceServiceServicerImpl(DeviceServiceServicer):
             else:
                 unexpected_config_rules.append(config_rule)
         if len(unexpected_config_rules) > 0:
-            unexpected_config_rules = MessageToDict(
-                request.device_config, including_default_value_fields=True,
-                preserving_proto_field_name=True, use_integers_for_enums=True)
+            unexpected_config_rules = grpc_message_to_json(request.device_config)
             unexpected_config_rules = unexpected_config_rules['config_rules']
             unexpected_config_rules = list(filter(
                 lambda cr: cr['resource_key'].replace('_connect/', '') not in connection_config_rules,
@@ -75,9 +73,7 @@ class DeviceServiceServicerImpl(DeviceServiceServicer):
         if len(request.device_endpoints) > 0:
             unexpected_endpoints = []
             for device_endpoint in request.device_endpoints:
-                unexpected_endpoints.append(MessageToDict(
-                    device_endpoint, including_default_value_fields=True, preserving_proto_field_name=True,
-                    use_integers_for_enums=True))
+                unexpected_endpoints.append(grpc_message_to_json(device_endpoint))
             str_unexpected_endpoints = json.dumps(unexpected_endpoints, sort_keys=True)
             raise InvalidArgumentException(
                 'device.device_endpoints', str_unexpected_endpoints,
@@ -85,9 +81,7 @@ class DeviceServiceServicerImpl(DeviceServiceServicer):
                               'interrogation of the physical device.')
 
         # Remove device configuration
-        json_request = MessageToDict(
-            request, including_default_value_fields=True, preserving_proto_field_name=True,
-            use_integers_for_enums=True)
+        json_request = grpc_message_to_json(request, use_integers_for_enums=True)
         json_request['device_config'] = {}
         request = Device(**json_request)
 
@@ -111,32 +105,42 @@ class DeviceServiceServicerImpl(DeviceServiceServicer):
         driver.Connect()
 
         endpoints = driver.GetConfig([RESOURCE_ENDPOINTS])
-        #LOGGER.info('[AddDevice] endpoints = {:s}'.format(str(endpoints)))
-        for resource_key, resource_value in endpoints:
-            endpoint_uuid = resource_value.get('uuid')
-            endpoint_type = resource_value.get('type')
-            str_endpoint_key = key_to_str([device_uuid, endpoint_uuid])
-            db_endpoint, _ = update_or_create_object(
-                self.database, EndPointModel, str_endpoint_key, {
-                'device_fk'    : db_device,
-                'endpoint_uuid': endpoint_uuid,
-                'endpoint_type': endpoint_type,
-                'resource_key' : resource_key,
-            })
-            sample_types = resource_value.get('sample_types', {})
-            for sample_type, monitor_resource_key in sample_types.items():
-                str_endpoint_monitor_key = key_to_str([str_endpoint_key, str(sample_type)])
-                update_or_create_object(self.database, EndPointMonitorModel, str_endpoint_monitor_key, {
-                    'endpoint_fk'    : db_endpoint,
-                    'resource_key'   : monitor_resource_key,
-                    'kpi_sample_type': grpc_to_enum__kpi_sample_type(sample_type),
+        try:
+            for resource_key, resource_value in endpoints:
+                if isinstance(resource_value, Exception):
+                    LOGGER.error('Error retrieving "{:s}": {:s}'.format(str(RESOURCE_ENDPOINTS), str(resource_value)))
+                    continue
+                endpoint_uuid = resource_value.get('uuid')
+                endpoint_type = resource_value.get('type')
+                str_endpoint_key = key_to_str([device_uuid, endpoint_uuid])
+                db_endpoint, _ = update_or_create_object(
+                    self.database, EndPointModel, str_endpoint_key, {
+                    'device_fk'    : db_device,
+                    'endpoint_uuid': endpoint_uuid,
+                    'endpoint_type': endpoint_type,
+                    'resource_key' : resource_key,
                 })
+                sample_types : Dict[int, str] = resource_value.get('sample_types', {})
+                for sample_type, monitor_resource_key in sample_types.items():
+                    str_endpoint_monitor_key = key_to_str([str_endpoint_key, str(sample_type)])
+                    update_or_create_object(self.database, EndPointMonitorModel, str_endpoint_monitor_key, {
+                        'endpoint_fk'    : db_endpoint,
+                        'resource_key'   : monitor_resource_key,
+                        'kpi_sample_type': grpc_to_enum__kpi_sample_type(sample_type),
+                    })
+        except: # pylint: disable=bare-except
+            LOGGER.exception('[AddDevice] endpoints = {:s}'.format(str(endpoints)))
+
+        raw_running_config_rules = driver.GetConfig()
+        running_config_rules = []
+        for resource_key, resource_value in raw_running_config_rules:
+            if isinstance(resource_value, Exception):
+                msg = 'Error retrieving config rules: {:s} => {:s}'
+                LOGGER.error(msg.format(str(resource_key), str(resource_value)))
+                continue
+            config_rule = (ORM_ConfigActionEnum.SET, resource_key, json.dumps(resource_value, sort_keys=True))
+            running_config_rules.append(config_rule)
 
-        running_config_rules = driver.GetConfig()
-        running_config_rules = [
-            (ORM_ConfigActionEnum.SET, config_rule[0], json.dumps(config_rule[1], sort_keys=True))
-            for config_rule in running_config_rules
-        ]
         #for running_config_rule in running_config_rules:
         #    LOGGER.info('[AddDevice] running_config_rule: {:s}'.format(str(running_config_rule)))
         update_config(self.database, device_uuid, 'running', running_config_rules)
@@ -216,6 +220,8 @@ class DeviceServiceServicerImpl(DeviceServiceServicer):
     def DeleteDevice(self, request : DeviceId, context : grpc.ServicerContext) -> Empty:
         device_uuid = request.device_uuid.uuid
 
+        self.monitoring_loops.remove(device_uuid)
+
         sync_device_from_context(device_uuid, self.context_client, self.database)
         db_device : DeviceModel = get_object(self.database, DeviceModel, device_uuid, raise_if_not_found=False)
         if db_device is None: return Empty()
@@ -224,24 +230,27 @@ class DeviceServiceServicerImpl(DeviceServiceServicer):
         delete_device_from_context(db_device, self.context_client)
 
         for db_kpi_pk,_ in db_device.references(KpiModel):
-            KpiModel(self.database, db_kpi_pk).delete()
+            db_kpi = get_object(self.database, KpiModel, db_kpi_pk)
+            for db_endpoint_monitor_kpi_pk,_ in db_kpi.references(EndPointMonitorKpiModel):
+                get_object(self.database, EndPointMonitorKpiModel, db_endpoint_monitor_kpi_pk).delete()
+            db_kpi.delete()
 
         for db_endpoint_pk,_ in db_device.references(EndPointModel):
             db_endpoint = EndPointModel(self.database, db_endpoint_pk)
             for db_endpoint_monitor_pk,_ in db_endpoint.references(EndPointMonitorModel):
-                EndPointMonitorModel(self.database, db_endpoint_monitor_pk).delete()
+                get_object(self.database, EndPointMonitorModel, db_endpoint_monitor_pk).delete()
             db_endpoint.delete()
 
         for db_driver_pk,_ in db_device.references(DriverModel):
-            DriverModel(self.database, db_driver_pk).delete()
+            get_object(self.database, DriverModel, db_driver_pk).delete()
 
         db_initial_config = ConfigModel(self.database, db_device.device_initial_config_fk)
         for db_config_rule_pk,_ in db_initial_config.references(ConfigRuleModel):
-            ConfigRuleModel(self.database, db_config_rule_pk).delete()
+            get_object(self.database, ConfigRuleModel, db_config_rule_pk).delete()
 
         db_running_config = ConfigModel(self.database, db_device.device_running_config_fk)
         for db_config_rule_pk,_ in db_running_config.references(ConfigRuleModel):
-            ConfigRuleModel(self.database, db_config_rule_pk).delete()
+            get_object(self.database, ConfigRuleModel, db_config_rule_pk).delete()
 
         db_device.delete()
         db_initial_config.delete()
@@ -309,12 +318,13 @@ class DeviceServiceServicerImpl(DeviceServiceServicer):
             db_endpoint_monitor : EndPointMonitorModel = get_object(
                 self.database, EndPointMonitorModel, str_endpoint_monitor_key, raise_if_not_found=False)
             if db_endpoint_monitor is None:
-                msg = 'SampleType({:s}/{:s}) not supported for EndPoint({:s}).'.format(
+                msg = 'SampleType({:s}/{:s}) not supported for Device({:s})/EndPoint({:s}).'.format(
                     str(sample_type), str(KpiSampleType.Name(sample_type).upper().replace('KPISAMPLETYPE_', '')),
-                    str(endpoint_uuid))
+                    str(device_uuid), str(endpoint_uuid))
                 raise OperationFailedException('MonitorDeviceKpi', extra_details=msg)
 
-            str_endpoint_monitor_kpi_key = key_to_str([device_uuid, db_endpoint_monitor.resource_key], separator=':')
+            endpoint_monitor_resource_key = re.sub('[^A-Za-z0-9]', '.', db_endpoint_monitor.resource_key)
+            str_endpoint_monitor_kpi_key = key_to_str([device_uuid, endpoint_monitor_resource_key], separator=':')
             attributes = {
                 'endpoint_monitor_fk': db_endpoint_monitor,
                 'kpi_fk'             : db_kpi,
@@ -390,4 +400,30 @@ class DeviceServiceServicerImpl(DeviceServiceServicer):
             # requests.
             #self.monitoring_loops.remove(device_uuid)
 
+        running_config_rules = [
+            (config_rule[0], json.dumps(config_rule[1], sort_keys=True))
+            for config_rule in driver.GetConfig()
+        ]
+        context_config_rules = {
+            config_rule[1]: config_rule[2]
+            for config_rule in get_config_rules(self.database, device_uuid, 'running')
+        }
+
+        # each in context, not in running => delete in context
+        # each in running, not in context => add to context
+        # each in context and in running, context.value != running.value => update in context
+
+        running_config_rules_actions : List[Tuple[ORM_ConfigActionEnum, str, str]] = []
+        for config_rule_key,config_rule_value in running_config_rules:
+            running_config_rules_actions.append((ORM_ConfigActionEnum.SET, config_rule_key, config_rule_value))
+            context_config_rules.pop(config_rule_key, None)
+        for context_rule_key,context_rule_value in context_config_rules.items():
+            running_config_rules_actions.append((ORM_ConfigActionEnum.DELETE, context_rule_key, context_rule_value))
+
+        #msg = '[MonitorDeviceKpi] running_config_rules_action[{:d}]: {:s}'
+        #for i,running_config_rules_action in enumerate(running_config_rules_actions):
+        #    LOGGER.info(msg.format(i, str(running_config_rules_action)))
+        update_config(self.database, device_uuid, 'running', running_config_rules_actions)
+
+        sync_device_to_context(db_device, self.context_client)
         return Empty()
diff --git a/src/device/service/MonitoringLoops.py b/src/device/service/MonitoringLoops.py
index 2e96e8df1..c0682ddc4 100644
--- a/src/device/service/MonitoringLoops.py
+++ b/src/device/service/MonitoringLoops.py
@@ -1,12 +1,13 @@
-import logging, queue, threading
+import logging, queue, re, threading
+from datetime import datetime
 from typing import Dict
 from common.orm.Database import Database
 from common.orm.HighLevel import get_object
 from common.orm.backend.Tools import key_to_str
-from device.service.database.RelationModels import EndPointMonitorKpiModel
 from monitoring.client.monitoring_client import MonitoringClient
 from monitoring.proto.monitoring_pb2 import Kpi
 from .database.KpiModel import KpiModel
+from .database.RelationModels import EndPointMonitorKpiModel
 from .driver_api._Driver import _Driver
 
 LOGGER = logging.getLogger(__name__)
@@ -37,7 +38,7 @@ class MonitoringLoop:
 
     def stop(self):
         self._terminate.set()
-        self._samples_stream.cancel()
+        #self._samples_stream.close() # leave the work to the garbage collector by now
         self._collector_thread.join()
 
 class MonitoringLoops:
@@ -90,6 +91,7 @@ class MonitoringLoops:
                 continue
 
             device_uuid, timestamp, endpoint_monitor_resource_key, value = sample
+            endpoint_monitor_resource_key = re.sub('[^A-Za-z0-9]', '.', endpoint_monitor_resource_key)
             str_endpoint_monitor_kpi_key = key_to_str([device_uuid, endpoint_monitor_resource_key], separator=':')
 
             #db_entries = self._database.dump()
@@ -127,7 +129,7 @@ class MonitoringLoops:
             try:
                 self._monitoring_client.IncludeKpi(Kpi(**{
                     'kpi_id'   : {'kpi_id': {'uuid': db_kpi.kpi_uuid}},
-                    'timestamp': str(timestamp),
+                    'timestamp': datetime.utcfromtimestamp(timestamp).isoformat() + 'Z',
                     'kpi_value': {kpi_value_field_name: kpi_value_field_cast(value)}
                 }))
             except: # pylint: disable=bare-except
diff --git a/src/device/service/__main__.py b/src/device/service/__main__.py
index 86f9b3ec1..1ee211b03 100644
--- a/src/device/service/__main__.py
+++ b/src/device/service/__main__.py
@@ -1,6 +1,6 @@
 import logging, signal, sys, threading
 from prometheus_client import start_http_server
-from common.Settings import get_setting
+from common.Settings import get_setting, wait_for_environment_variables
 from context.client.ContextClient import ContextClient
 from device.Config import (
     CONTEXT_SERVICE_HOST, CONTEXT_SERVICE_PORT, GRPC_SERVICE_PORT, GRPC_MAX_WORKERS, GRPC_GRACE_PERIOD, LOG_LEVEL,
@@ -12,7 +12,7 @@ from .driver_api.DriverInstanceCache import DriverInstanceCache
 from .drivers import DRIVERS
 
 terminate = threading.Event()
-LOGGER = None
+LOGGER : logging.Logger = None
 
 def signal_handler(signal, frame): # pylint: disable=redefined-outer-name
     LOGGER.warning('Terminate signal received')
@@ -26,14 +26,23 @@ def main():
     grace_period            = get_setting('GRACE_PERIOD',                        default=GRPC_GRACE_PERIOD      )
     log_level               = get_setting('LOG_LEVEL',                           default=LOG_LEVEL              )
     metrics_port            = get_setting('METRICS_PORT',                        default=METRICS_PORT           )
+
+    logging.basicConfig(level=log_level)
+    logging.getLogger('apscheduler.executors.default').setLevel(logging.WARNING)
+    logging.getLogger('apscheduler.scheduler').setLevel(logging.WARNING)
+    logging.getLogger('monitoring-client').setLevel(logging.WARNING)
+    LOGGER = logging.getLogger(__name__)
+
+    wait_for_environment_variables([
+        'CONTEXTSERVICE_SERVICE_HOST', 'CONTEXTSERVICE_SERVICE_PORT_GRPC',
+        'MONITORINGSERVICE_SERVICE_HOST', 'MONITORINGSERVICE_SERVICE_PORT_GRPC'
+    ])
+
     context_service_host    = get_setting('CONTEXTSERVICE_SERVICE_HOST',         default=CONTEXT_SERVICE_HOST   )
     context_service_port    = get_setting('CONTEXTSERVICE_SERVICE_PORT_GRPC',    default=CONTEXT_SERVICE_PORT   )
     monitoring_service_host = get_setting('MONITORINGSERVICE_SERVICE_HOST',      default=MONITORING_SERVICE_HOST)
     monitoring_service_port = get_setting('MONITORINGSERVICE_SERVICE_PORT_GRPC', default=MONITORING_SERVICE_PORT)
 
-    logging.basicConfig(level=log_level)
-    LOGGER = logging.getLogger(__name__)
-
     signal.signal(signal.SIGINT,  signal_handler)
     signal.signal(signal.SIGTERM, signal_handler)
 
diff --git a/src/device/service/driver_api/DriverFactory.py b/src/device/service/driver_api/DriverFactory.py
index 10b4961fc..51e6d5782 100644
--- a/src/device/service/driver_api/DriverFactory.py
+++ b/src/device/service/driver_api/DriverFactory.py
@@ -1,11 +1,11 @@
 import logging, operator
 from enum import Enum
 from typing import Any, Dict, Iterable, List, Set, Tuple
-from device.service.driver_api._Driver import _Driver
-from device.service.driver_api.Exceptions import (
+from ._Driver import _Driver
+from .Exceptions import (
     UnsatisfiedFilterException, UnsupportedDriverClassException, UnsupportedFilterFieldException,
     UnsupportedFilterFieldValueException)
-from device.service.driver_api.FilterFields import FILTER_FIELD_ALLOWED_VALUES, FilterFieldEnum
+from .FilterFields import FILTER_FIELD_ALLOWED_VALUES, FilterFieldEnum
 
 LOGGER = logging.getLogger(__name__)
 
diff --git a/src/device/service/driver_api/DriverInstanceCache.py b/src/device/service/driver_api/DriverInstanceCache.py
index f960e37cb..6a3ee7907 100644
--- a/src/device/service/driver_api/DriverInstanceCache.py
+++ b/src/device/service/driver_api/DriverInstanceCache.py
@@ -1,10 +1,9 @@
 import logging, threading
 from typing import Any, Dict, Optional
-
-from device.service.driver_api.FilterFields import FilterFieldEnum
 from ._Driver import _Driver
 from .DriverFactory import DriverFactory
 from .Exceptions import DriverInstanceCacheTerminatedException
+from .FilterFields import FilterFieldEnum
 
 LOGGER = logging.getLogger(__name__)
 
diff --git a/src/device/service/driver_api/FilterFields.py b/src/device/service/driver_api/FilterFields.py
index 892e7f720..c4cf352c1 100644
--- a/src/device/service/driver_api/FilterFields.py
+++ b/src/device/service/driver_api/FilterFields.py
@@ -1,15 +1,7 @@
 from enum import Enum
+from common.DeviceTypes import DeviceTypeEnum
 from device.service.database.DeviceModel import ORM_DeviceDriverEnum
 
-class DeviceTypeFilterFieldEnum(Enum):
-    EMULATED            = 'emulated'
-    OPTICAL_ROADM       = 'optical-roadm'
-    OPTICAL_TRANDPONDER = 'optical-trandponder'
-    OPTICAL_LINE_SYSTEM = 'optical-line-system'
-    PACKET_ROUTER       = 'packet-router'
-    PACKET_SWITCH       = 'packet-switch'
-    P4_SWITCH           = 'p4-switch'
-
 class FilterFieldEnum(Enum):
     DEVICE_TYPE   = 'device_type'
     DRIVER        = 'driver'
@@ -19,7 +11,7 @@ class FilterFieldEnum(Enum):
 
 # Map allowed filter fields to allowed values per Filter field. If no restriction (free text) None is specified
 FILTER_FIELD_ALLOWED_VALUES = {
-    FilterFieldEnum.DEVICE_TYPE.value   : {i.value for i in DeviceTypeFilterFieldEnum},
+    FilterFieldEnum.DEVICE_TYPE.value   : {i.value for i in DeviceTypeEnum},
     FilterFieldEnum.DRIVER.value        : {i.value for i in ORM_DeviceDriverEnum},
     FilterFieldEnum.VENDOR.value        : None,
     FilterFieldEnum.MODEL.value         : None,
diff --git a/src/device/service/drivers/__init__.py b/src/device/service/drivers/__init__.py
index 54c944bab..4aa526f5a 100644
--- a/src/device/service/drivers/__init__.py
+++ b/src/device/service/drivers/__init__.py
@@ -1,4 +1,5 @@
-from ..driver_api.FilterFields import FilterFieldEnum, DeviceTypeFilterFieldEnum, ORM_DeviceDriverEnum
+from common.DeviceTypes import DeviceTypeEnum
+from ..driver_api.FilterFields import FilterFieldEnum, ORM_DeviceDriverEnum
 from .emulated.EmulatedDriver import EmulatedDriver
 from .openconfig.OpenConfigDriver import OpenConfigDriver
 from .transport_api.TransportApiDriver import TransportApiDriver
@@ -7,25 +8,32 @@ from .p4.p4_driver import P4Driver
 DRIVERS = [
     (EmulatedDriver, [
         {
-            FilterFieldEnum.DEVICE_TYPE: DeviceTypeFilterFieldEnum.EMULATED,
-            FilterFieldEnum.DRIVER     : ORM_DeviceDriverEnum.UNDEFINED,
+            FilterFieldEnum.DEVICE_TYPE: [
+                DeviceTypeEnum.EMULATED_OPTICAL_LINE_SYSTEM,
+                DeviceTypeEnum.EMULATED_PACKET_ROUTER,
+            ],
+            FilterFieldEnum.DRIVER     : [
+                ORM_DeviceDriverEnum.UNDEFINED,
+                ORM_DeviceDriverEnum.OPENCONFIG,
+                ORM_DeviceDriverEnum.TRANSPORT_API
+            ],
         }
     ]),
     (OpenConfigDriver, [
         {
-            FilterFieldEnum.DEVICE_TYPE: DeviceTypeFilterFieldEnum.PACKET_ROUTER,
+            FilterFieldEnum.DEVICE_TYPE: DeviceTypeEnum.PACKET_ROUTER,
             FilterFieldEnum.DRIVER     : ORM_DeviceDriverEnum.OPENCONFIG,
         }
     ]),
     (TransportApiDriver, [
         {
-            FilterFieldEnum.DEVICE_TYPE: DeviceTypeFilterFieldEnum.OPTICAL_LINE_SYSTEM,
+            FilterFieldEnum.DEVICE_TYPE: DeviceTypeEnum.OPTICAL_LINE_SYSTEM,
             FilterFieldEnum.DRIVER     : ORM_DeviceDriverEnum.TRANSPORT_API,
         }
     ]),
     (P4Driver, [
         {
-            FilterFieldEnum.DEVICE_TYPE: DeviceTypeFilterFieldEnum.P4_SWITCH,
+            FilterFieldEnum.DEVICE_TYPE: DeviceTypeEnum.P4_SWITCH,
             FilterFieldEnum.DRIVER     : ORM_DeviceDriverEnum.P4,
         }
     ]),
diff --git a/src/device/service/drivers/emulated/EmulatedDriver.py b/src/device/service/drivers/emulated/EmulatedDriver.py
index c92554fe3..a1af85da4 100644
--- a/src/device/service/drivers/emulated/EmulatedDriver.py
+++ b/src/device/service/drivers/emulated/EmulatedDriver.py
@@ -1,5 +1,4 @@
-import json
-import anytree, logging, pytz, queue, random, threading
+import anytree, json, logging, math, pytz, queue, random, re, threading
 from datetime import datetime, timedelta
 from typing import Any, Dict, Iterator, List, Optional, Tuple, Union
 from apscheduler.executors.pool import ThreadPoolExecutor
@@ -47,8 +46,67 @@ def compose_resource_endpoint(endpoint_data : Dict[str, Any]) -> Tuple[str, Any]
     endpoint_resource_value = {'uuid': endpoint_uuid, 'type': endpoint_type, 'sample_types': sample_types}
     return endpoint_resource_key, endpoint_resource_value
 
-def do_sampling(resource_key : str, out_samples : queue.Queue):
-    out_samples.put_nowait((datetime.timestamp(datetime.utcnow()), resource_key, random.random()))
+RE_GET_ENDPOINT_METRIC = re.compile(r'.*\/endpoint\[([^\]]+)\]\/state\/(.*)')
+RE_GET_ENDPOINT_FROM_INTERFACE = re.compile(r'.*\/interface\[([^\]]+)\].*')
+
+class SyntheticSamplingParameters:
+    def __init__(self) -> None:
+        self.__lock = threading.Lock()
+        self.__data = {}
+        self.__configured_endpoints = set()
+
+    def set_endpoint_configured(self, endpoint_uuid : str):
+        with self.__lock:
+            self.__configured_endpoints.add(endpoint_uuid)
+
+    def unset_endpoint_configured(self, endpoint_uuid : str):
+        with self.__lock:
+            self.__configured_endpoints.discard(endpoint_uuid)
+
+    def get(self, resource_key : str) -> Tuple[float, float, float, float]:
+        with self.__lock:
+            match = RE_GET_ENDPOINT_METRIC.match(resource_key)
+            if match is None:
+                msg = '[SyntheticSamplingParameters:get] unable to extract endpoint-metric from resource_key "{:s}"'
+                LOGGER.error(msg.format(resource_key))
+                return (0, 0, 1, 0, 0)
+            endpoint_uuid = match.group(1)
+
+            # If endpoint is not configured, generate a flat synthetic traffic aligned at 0
+            if endpoint_uuid not in self.__configured_endpoints: return (0, 0, 1, 0, 0)
+
+            metric = match.group(2)
+            metric_sense = metric.lower().replace('packets_', '').replace('bytes_', '')
+
+            msg = '[SyntheticSamplingParameters:get] resource_key={:s}, endpoint_uuid={:s}, metric={:s}, metric_sense={:s}'
+            LOGGER.info(msg.format(resource_key, endpoint_uuid, metric, metric_sense))
+
+            parameters_key = '{:s}-{:s}'.format(endpoint_uuid, metric_sense)
+            parameters = self.__data.get(parameters_key)
+            if parameters is not None: return parameters
+
+            # assume packets
+            amplitude  = 1.e7 * random.random()
+            phase      = 60 * random.random()
+            period     = 3600 * random.random()
+            offset     = 1.e8 * random.random() + amplitude
+            avg_bytes_per_packet = random.randint(500, 1500)
+            parameters = (amplitude, phase, period, offset, avg_bytes_per_packet)
+            return self.__data.setdefault(parameters_key, parameters)
+
+def do_sampling(
+        synthetic_sampling_parameters : SyntheticSamplingParameters, resource_key : str, out_samples : queue.Queue
+    ):
+    amplitude, phase, period, offset, avg_bytes_per_packet = synthetic_sampling_parameters.get(resource_key)
+    if 'bytes' in resource_key.lower():
+        # convert to bytes
+        amplitude = avg_bytes_per_packet * amplitude
+        offset = avg_bytes_per_packet * offset
+    timestamp = datetime.timestamp(datetime.utcnow())
+    waveform  = amplitude * math.sin(2 * math.pi * timestamp / period + phase) + offset
+    noise     = amplitude * random.random()
+    value     = abs(0.95 * waveform + 0.05 * noise)
+    out_samples.put_nowait((timestamp, resource_key, value))
 
 class EmulatedDriver(_Driver):
     def __init__(self, address : str, port : int, **settings) -> None: # pylint: disable=super-init-not-called
@@ -73,6 +131,7 @@ class EmulatedDriver(_Driver):
             job_defaults = {'coalesce': False, 'max_instances': 3},
             timezone=pytz.utc)
         self.__out_samples = queue.Queue()
+        self.__synthetic_sampling_parameters = SyntheticSamplingParameters()
 
     def Connect(self) -> bool:
         # If started, assume it is already connected
@@ -148,6 +207,12 @@ class EmulatedDriver(_Driver):
                     pass
 
                 set_subnode_value(resolver, self.__running, resource_path, resource_value)
+
+                match = RE_GET_ENDPOINT_FROM_INTERFACE.match(resource_key)
+                if match is not None:
+                    endpoint_uuid = match.group(1)
+                    self.__synthetic_sampling_parameters.set_endpoint_configured(endpoint_uuid)
+
                 results.append(True)
         return results
 
@@ -176,6 +241,11 @@ class EmulatedDriver(_Driver):
                     results.append(False)
                     continue
 
+                match = RE_GET_ENDPOINT_FROM_INTERFACE.match(resource_key)
+                if match is not None:
+                    endpoint_uuid = match.group(1)
+                    self.__synthetic_sampling_parameters.unset_endpoint_configured(endpoint_uuid)
+
                 parent = resource_node.parent
                 children = list(parent.children)
                 children.remove(resource_node)
@@ -211,9 +281,9 @@ class EmulatedDriver(_Driver):
 
                 job_id = 'k={:s}/d={:f}/i={:f}'.format(resource_key, sampling_duration, sampling_interval)
                 job = self.__scheduler.add_job(
-                    do_sampling, args=(resource_key, self.__out_samples), kwargs={},
-                    id=job_id, trigger='interval', seconds=sampling_interval,
-                    start_date=start_date, end_date=end_date, timezone=pytz.utc)
+                    do_sampling, args=(self.__synthetic_sampling_parameters, resource_key, self.__out_samples),
+                    kwargs={}, id=job_id, trigger='interval', seconds=sampling_interval, start_date=start_date,
+                    end_date=end_date, timezone=pytz.utc)
 
                 subscription_path = resource_path + ['{:.3f}:{:.3f}'.format(sampling_duration, sampling_interval)]
                 set_subnode_value(resolver, self.__running, subscription_path, job)
diff --git a/src/device/tests/CommonObjects.py b/src/device/tests/CommonObjects.py
index 2b51dcd23..40aef4abf 100644
--- a/src/device/tests/CommonObjects.py
+++ b/src/device/tests/CommonObjects.py
@@ -1,21 +1,22 @@
-from copy import deepcopy
 from common.Constants import DEFAULT_CONTEXT_UUID, DEFAULT_TOPOLOGY_UUID
+from common.tools.object_factory.Context import json_context, json_context_id
+from common.tools.object_factory.Topology import json_topology, json_topology_id
+from context.proto.kpi_sample_types_pb2 import KpiSampleType
 
-# use "deepcopy" to prevent propagating forced changes during tests
+# ----- Context --------------------------------------------------------------------------------------------------------
+CONTEXT_ID = json_context_id(DEFAULT_CONTEXT_UUID)
+CONTEXT    = json_context(DEFAULT_CONTEXT_UUID)
 
-CONTEXT_ID = {'context_uuid': {'uuid': DEFAULT_CONTEXT_UUID}}
-CONTEXT = {
-    'context_id': deepcopy(CONTEXT_ID),
-    'topology_ids': [],
-    'service_ids': [],
-}
 
-TOPOLOGY_ID = {
-    'context_id': deepcopy(CONTEXT_ID),
-    'topology_uuid': {'uuid': DEFAULT_TOPOLOGY_UUID},
-}
-TOPOLOGY = {
-    'topology_id': deepcopy(TOPOLOGY_ID),
-    'device_ids': [],
-    'link_ids': [],
-}
+# ----- Topology -------------------------------------------------------------------------------------------------------
+TOPOLOGY_ID = json_topology_id(DEFAULT_TOPOLOGY_UUID, context_id=CONTEXT_ID)
+TOPOLOGY    = json_topology(DEFAULT_TOPOLOGY_UUID, context_id=CONTEXT_ID)
+
+
+# ----- KPI Sample Types -----------------------------------------------------------------------------------------------
+PACKET_PORT_SAMPLE_TYPES = [
+    KpiSampleType.KPISAMPLETYPE_PACKETS_TRANSMITTED,
+    KpiSampleType.KPISAMPLETYPE_PACKETS_RECEIVED,
+    KpiSampleType.KPISAMPLETYPE_BYTES_TRANSMITTED,
+    KpiSampleType.KPISAMPLETYPE_BYTES_RECEIVED,
+]
diff --git a/src/device/tests/Device_Emulated.py b/src/device/tests/Device_Emulated.py
index 27595dd8a..10b21fe27 100644
--- a/src/device/tests/Device_Emulated.py
+++ b/src/device/tests/Device_Emulated.py
@@ -1,101 +1,76 @@
-import operator
-from copy import deepcopy
-from device.proto.context_pb2 import DeviceDriverEnum, DeviceOperationalStatusEnum
-from device.service.database.KpiSampleType import ORM_KpiSampleTypeEnum
-from .Tools import config_rule_set, config_rule_delete
+from common.tools.object_factory.ConfigRule import json_config_rule_delete, json_config_rule_set
+from common.tools.object_factory.Device import (
+    json_device_emulated_connect_rules, json_device_emulated_packet_router_disabled, json_device_id)
+from context.proto.kpi_sample_types_pb2 import KpiSampleType
+from device.tests.CommonObjects import PACKET_PORT_SAMPLE_TYPES
 
-# use "deepcopy" to prevent propagating forced changes during tests
-
-DEVICE_EMU_UUID           = 'EMULATED'
-DEVICE_EMU_TYPE           = 'emulated'
-DEVICE_EMU_ADDRESS        = '127.0.0.1'
-DEVICE_EMU_PORT           = '0'
-DEVICE_EMU_DRIVERS        = [DeviceDriverEnum.DEVICEDRIVER_UNDEFINED]
-
-DEVICE_EMU_ID = {'device_uuid': {'uuid': DEVICE_EMU_UUID}}
-DEVICE_EMU = {
-    'device_id': deepcopy(DEVICE_EMU_ID),
-    'device_type': DEVICE_EMU_TYPE,
-    'device_config': {'config_rules': []},
-    'device_operational_status': DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_DISABLED,
-    'device_drivers': DEVICE_EMU_DRIVERS,
-    'device_endpoints': [],
-}
-
-PACKET_PORT_SAMPLE_TYPES = [
-    ORM_KpiSampleTypeEnum.PACKETS_TRANSMITTED,
-    ORM_KpiSampleTypeEnum.PACKETS_RECEIVED,
-    ORM_KpiSampleTypeEnum.BYTES_TRANSMITTED,
-    ORM_KpiSampleTypeEnum.BYTES_RECEIVED,
-]
-
-ENDPOINT_UUIDS = ['EP1', 'EP2', 'EP3', 'EP4']
-
-DEVICE_EMU_ENDPOINTS = []
-for endpoint_uuid in ENDPOINT_UUIDS:
-    DEVICE_EMU_ENDPOINTS.append((endpoint_uuid, '10Gbps', PACKET_PORT_SAMPLE_TYPES))
+DEVICE_EMU_UUID     = 'EMULATED'
+DEVICE_EMU_ID       = json_device_id(DEVICE_EMU_UUID)
+DEVICE_EMU          = json_device_emulated_packet_router_disabled(DEVICE_EMU_UUID)
+DEVICE_EMU_EP_UUIDS = ['EP1', 'EP2', 'EP3', 'EP4']
+DEVICE_EMU_EP_DESCS = [(ep_uuid, '10Gbps', PACKET_PORT_SAMPLE_TYPES) for ep_uuid in DEVICE_EMU_EP_UUIDS]
+DEVICE_EMU_CONNECT_RULES = json_device_emulated_connect_rules(DEVICE_EMU_EP_DESCS)
 
 RSRC_EP       = '/endpoints/endpoint[{:s}]'
 RSRC_SUBIF    = RSRC_EP    + '/subinterfaces/subinterface[{:d}]'
 RSRC_ADDRIPV4 = RSRC_SUBIF + '/ipv4/address[{:s}]'
 
 DEVICE_EMU_ENDPOINTS_COOKED = []
-for endpoint_uuid,endpoint_type,endpoint_sample_types in DEVICE_EMU_ENDPOINTS:
+for endpoint_uuid,endpoint_type,endpoint_sample_types in DEVICE_EMU_EP_DESCS:
     endpoint_resource_key = RSRC_EP.format(str(endpoint_uuid))
     sample_types = {}
     for endpoint_sample_type in endpoint_sample_types:
-        sample_type_name = endpoint_sample_type.name.lower()
-        sample_types[endpoint_sample_type.value] = '{:s}/state/{:s}'.format(endpoint_resource_key, sample_type_name)
+        sample_type_name = KpiSampleType.Name(endpoint_sample_type).lower().replace('kpisampletype_', '')
+        sample_types[endpoint_sample_type] = '{:s}/state/{:s}'.format(endpoint_resource_key, sample_type_name)
     endpoint_resource_value = {'uuid': endpoint_uuid, 'type': endpoint_type, 'sample_types': sample_types}
     DEVICE_EMU_ENDPOINTS_COOKED.append((endpoint_resource_key, endpoint_resource_value))
 
-DEVICE_EMU_CONNECT_RULES = [
-    config_rule_set('_connect/address',  DEVICE_EMU_ADDRESS ),
-    config_rule_set('_connect/port',     DEVICE_EMU_PORT    ),
-    config_rule_set('_connect/settings', {'endpoints': [
-        {
-            'uuid': endpoint_uuid, 'type': endpoint_type,
-            'sample_types': list(map(operator.attrgetter('value'), endpoint_sample_types)),
-        }
-        for endpoint_uuid,endpoint_type,endpoint_sample_types in DEVICE_EMU_ENDPOINTS
-    ]}),
+DEVICE_EMU_CONFIG_ENDPOINTS = [
+    json_config_rule_set(RSRC_EP.format('EP1'), {'enabled' : True}),
+    json_config_rule_set(RSRC_EP.format('EP2'), {'enabled' : True}),
+    json_config_rule_set(RSRC_EP.format('EP3'), {'enabled' : True}),
+    json_config_rule_set(RSRC_EP.format('EP4'), {'enabled' : True}),
 ]
 
-DEVICE_EMU_CONFIG_ENDPOINTS = []
-for endpoint_uuid in ENDPOINT_UUIDS:
-    DEVICE_EMU_CONFIG_ENDPOINTS.append(config_rule_set(RSRC_EP.format(endpoint_uuid), {'enabled' : True}))
+DEVICE_EMU_CONFIG_ADDRESSES = [
+    json_config_rule_set(RSRC_SUBIF   .format('EP1', 0), {'index': 0}),
+    json_config_rule_set(RSRC_ADDRIPV4.format('EP1', 0, '10.1.0.1'), {'ip': '10.1.0.1', 'prefix_length': 24}),
+
+    json_config_rule_set(RSRC_SUBIF   .format('EP2', 0), {'index': 0}),
+    json_config_rule_set(RSRC_ADDRIPV4.format('EP2', 0, '10.2.0.1'), {'ip': '10.2.0.1', 'prefix_length': 24}),
 
-DEVICE_EMU_CONFIG_ADDRESSES = []
-for endpoint_uuid in ENDPOINT_UUIDS:
-    endpoint_number = int(endpoint_uuid.replace('EP', ''))
-    subinterface_index = 0
-    subinterface_address = '10.{:d}.{:d}.1'.format(endpoint_number, subinterface_index)
-    subinterface_prefix_length = 24
-    DEVICE_EMU_CONFIG_ADDRESSES.extend([
-        config_rule_set(RSRC_SUBIF   .format(endpoint_uuid, subinterface_index), {
-            'index': subinterface_index}),
-        config_rule_set(RSRC_ADDRIPV4.format(endpoint_uuid, subinterface_index, subinterface_address), {
-            'ip': subinterface_address, 'prefix_length': subinterface_prefix_length}),
-    ])
+    json_config_rule_set(RSRC_SUBIF   .format('EP3', 0), {'index': 0}),
+    json_config_rule_set(RSRC_ADDRIPV4.format('EP3', 0, '10.3.0.1'), {'ip': '10.3.0.1', 'prefix_length': 24}),
+
+    json_config_rule_set(RSRC_SUBIF   .format('EP4', 0), {'index': 0}),
+    json_config_rule_set(RSRC_ADDRIPV4.format('EP4', 0, '10.4.0.1'), {'ip': '10.4.0.1', 'prefix_length': 24}),
+]
 
 DEVICE_EMU_RECONFIG_ADDRESSES = [
-    config_rule_delete(RSRC_SUBIF   .format('EP2', 0            ), {}),
-    config_rule_delete(RSRC_ADDRIPV4.format('EP2', 0, '10.2.0.1'), {'ip': '10.2.0.1', 'prefix_length': 24}),
+    json_config_rule_delete(RSRC_SUBIF   .format('EP2', 0), {}),
+    json_config_rule_delete(RSRC_ADDRIPV4.format('EP2', 0, '10.2.0.1'), {'ip': '10.2.0.1', 'prefix_length': 24}),
 
-    config_rule_set   (RSRC_SUBIF   .format('EP2', 1            ), {'index': 1}),
-    config_rule_set   (RSRC_ADDRIPV4.format('EP2', 1, '10.2.1.1'), {'ip': '10.2.1.1', 'prefix_length': 24}),
+    json_config_rule_set   (RSRC_SUBIF   .format('EP2', 1), {'index': 1}),
+    json_config_rule_set   (RSRC_ADDRIPV4.format('EP2', 1, '10.2.1.1'), {'ip': '10.2.1.1', 'prefix_length': 24}),
 ]
 
-DEVICE_EMU_DECONFIG_ADDRESSES = []
-for endpoint_uuid in ENDPOINT_UUIDS:
-    endpoint_number = int(endpoint_uuid.replace('EP', ''))
-    subinterface_index = 1 if endpoint_uuid == 'EP2' else 0
-    subinterface_address = '10.{:d}.{:d}.1'.format(endpoint_number, subinterface_index)
-    DEVICE_EMU_DECONFIG_ADDRESSES.extend([
-        config_rule_delete(RSRC_SUBIF   .format(endpoint_uuid, subinterface_index), {}),
-        config_rule_delete(RSRC_ADDRIPV4.format(endpoint_uuid, subinterface_index, subinterface_address), {}),
-    ])
+DEVICE_EMU_DECONFIG_ADDRESSES = [
+    json_config_rule_delete(RSRC_SUBIF   .format('EP1', 0), {}),
+    json_config_rule_delete(RSRC_ADDRIPV4.format('EP1', 0, '10.1.0.1'), {}),
+
+    json_config_rule_delete(RSRC_SUBIF   .format('EP2', 1), {}),
+    json_config_rule_delete(RSRC_ADDRIPV4.format('EP2', 1, '10.2.1.1'), {}),
+
+    json_config_rule_delete(RSRC_SUBIF   .format('EP3', 0), {}),
+    json_config_rule_delete(RSRC_ADDRIPV4.format('EP3', 0, '10.3.0.1'), {}),
 
-DEVICE_EMU_DECONFIG_ENDPOINTS = []
-for endpoint_uuid in ENDPOINT_UUIDS:
-    DEVICE_EMU_DECONFIG_ENDPOINTS.append(config_rule_delete(RSRC_EP.format(endpoint_uuid), {}))
+    json_config_rule_delete(RSRC_SUBIF   .format('EP4', 0), {}),
+    json_config_rule_delete(RSRC_ADDRIPV4.format('EP4', 0, '10.4.0.1'), {}),
+]
+
+DEVICE_EMU_DECONFIG_ENDPOINTS = [
+    json_config_rule_delete(RSRC_EP.format('EP1'), {}),
+    json_config_rule_delete(RSRC_EP.format('EP2'), {}),
+    json_config_rule_delete(RSRC_EP.format('EP3'), {}),
+    json_config_rule_delete(RSRC_EP.format('EP4'), {}),
+]
diff --git a/src/device/tests/Device_OpenConfig_Template.py b/src/device/tests/Device_OpenConfig_Template.py
index 5f917c5c4..86fe00a5a 100644
--- a/src/device/tests/Device_OpenConfig_Template.py
+++ b/src/device/tests/Device_OpenConfig_Template.py
@@ -1,38 +1,21 @@
-from copy import deepcopy
-from device.proto.context_pb2 import DeviceDriverEnum, DeviceOperationalStatusEnum
-from .Tools import config_rule_set, config_rule_delete
+from common.tools.object_factory.Device import (
+    json_device_connect_rules, json_device_id, json_device_packetrouter_disabled)
 
-# use "deepcopy" to prevent propagating forced changes during tests
-
-DEVICE_OC_UUID     = 'DEV2'
-DEVICE_OC_TYPE     = 'packet-router'
+DEVICE_OC_UUID     = 'DEV-UUID'   # populate the name of the device to test
 DEVICE_OC_ADDRESS  = '127.0.0.1'  # populate the Netconf Server IP address of the device to test
-DEVICE_OC_PORT     = '830'        # populate the Netconf Server port of the device to test
+DEVICE_OC_PORT     = 830          # populate the Netconf Server port of the device to test
 DEVICE_OC_USERNAME = 'username'   # populate the Netconf Server username of the device to test
 DEVICE_OC_PASSWORD = 'password'   # populate the Netconf Server password of the device to test
 DEVICE_OC_TIMEOUT  = 120
-DEVICE_OC_DRIVERS  = [DeviceDriverEnum.DEVICEDRIVER_OPENCONFIG]
 
-DEVICE_OC_ID = {'device_uuid': {'uuid': DEVICE_OC_UUID}}
-DEVICE_OC = {
-    'device_id': deepcopy(DEVICE_OC_ID),
-    'device_type': DEVICE_OC_TYPE,
-    'device_config': {'config_rules': []},
-    'device_operational_status': DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_DISABLED,
-    'device_drivers': DEVICE_OC_DRIVERS,
-    'device_endpoints': [],                     # populated through the driver, leave this list empty
-}
+DEVICE_OC_ID = json_device_id(DEVICE_OC_UUID)
+DEVICE_OC    = json_device_packetrouter_disabled(DEVICE_OC_UUID)
 
-DEVICE_OC_CONNECT_RULES = [
-    config_rule_set('_connect/address', DEVICE_OC_ADDRESS),
-    config_rule_set('_connect/port',    DEVICE_OC_PORT   ),
-    config_rule_set('_connect/settings', {
-        'username': DEVICE_OC_USERNAME,
-        'password': DEVICE_OC_PASSWORD,
-        'timeout' : DEVICE_OC_TIMEOUT,
-    }),
-]
+DEVICE_OC_CONNECT_RULES = json_device_connect_rules(DEVICE_OC_ADDRESS, DEVICE_OC_PORT, {
+    'username': DEVICE_OC_USERNAME,
+    'password': DEVICE_OC_PASSWORD,
+    'timeout' : DEVICE_OC_TIMEOUT,
+})
 
 DEVICE_OC_CONFIG_RULES   = []           # populate your configuration rules to test
-
 DEVICE_OC_DECONFIG_RULES = []           # populate your deconfiguration rules to test
diff --git a/src/device/tests/Device_Transport_Api_Template.py b/src/device/tests/Device_Transport_Api_Template.py
index 6032f0ff8..c8d6658a6 100644
--- a/src/device/tests/Device_Transport_Api_Template.py
+++ b/src/device/tests/Device_Transport_Api_Template.py
@@ -1,40 +1,34 @@
-from copy import deepcopy
-from device.proto.context_pb2 import DeviceDriverEnum, DeviceOperationalStatusEnum
-from .Tools import config_rule_set, config_rule_delete
+from common.tools.object_factory.ConfigRule import json_config_rule_delete, json_config_rule_set
+from common.tools.object_factory.Device import (
+    json_device_connect_rules, json_device_id, json_device_tapi_disabled)
 
-# use "deepcopy" to prevent propagating forced changes during tests
+DEVICE_TAPI_UUID    = 'DEVICE-TAPI'     # populate 'device-uuid' of the TAPI server
+DEVICE_TAPI_ADDRESS = '0.0.0.0'         # populate 'address' of the TAPI server
+DEVICE_TAPI_PORT    = 4900              # populate 'port' of the TAPI server
+DEVICE_TAPI_TIMEOUT = 120               # populate 'timeout' of the TAPI server
 
-DEVICE_TAPI_UUID         = 'DEVICE-TAPI'
-DEVICE_TAPI_TYPE         = 'optical-line-system'
-DEVICE_TAPI_ADDRESS      = '0.0.0.0'
-DEVICE_TAPI_PORT         = '4900'
-DEVICE_TAPI_TIMEOUT      = '120'
-DEVICE_TAPI_DRIVERS      = [DeviceDriverEnum.DEVICEDRIVER_TRANSPORT_API]
+DEVICE_TAPI_ID = json_device_id(DEVICE_TAPI_UUID)
+DEVICE_TAPI    = json_device_tapi_disabled(DEVICE_TAPI_UUID)
 
-DEVICE_TAPI_ID = {'device_uuid': {'uuid': DEVICE_TAPI_UUID}}
-DEVICE_TAPI = {
-    'device_id': deepcopy(DEVICE_TAPI_ID),
-    'device_type': DEVICE_TAPI_TYPE,
-    'device_config': {'config_rules': []},
-    'device_operational_status': DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_DISABLED,
-    'device_drivers': DEVICE_TAPI_DRIVERS,
-    'device_endpoints': [],
-}
-
-DEVICE_TAPI_CONNECT_RULES = [
-    config_rule_set('_connect/address',  DEVICE_TAPI_ADDRESS),
-    config_rule_set('_connect/port',     DEVICE_TAPI_PORT),
-    config_rule_set('_connect/timeout',  DEVICE_TAPI_TIMEOUT),
-]
+DEVICE_TAPI_CONNECT_RULES = json_device_connect_rules(DEVICE_TAPI_ADDRESS, DEVICE_TAPI_PORT, {
+    'timeout' : DEVICE_TAPI_TIMEOUT,
+})
 
 DEVICE_TAPI_CONFIG_RULES = [
-    config_rule_set('network_instance[DemoOFC-NetInst]/interface[13/1/3]', {
-        'name': 'DemoOFC-NetInst', 'id': '13/1/3',
+    json_config_rule_set('node_4_port_16-input_to_node_2_port_17-output', {
+        'uuid'                    : 'service-uuid',     # populate 'service-uuid' of the service to test
+        'input_sip'               : 'input-sip-uuid',   # populate 'input-sip-uuid' of the service to test
+        'output_sip'              : 'output-sip-uuid',  # populate 'output-sip-uuid' of the service to test
+        'capacity_unit'           : 'GHz',              # populate 'capacity-unit' of the service to test
+        'capacity_value'          : 1,                  # populate 'capacity-value' of the service to test
+        'direction'               : 'UNIDIRECTIONAL',   # populate 'direction' of the service to test
+        'layer_protocol_name'     : 'PHOTONIC_MEDIA',
+        'layer_protocol_qualifier': 'tapi-photonic-media:PHOTONIC_LAYER_QUALIFIER_NMC',
     })
 ]
 
 DEVICE_TAPI_DECONFIG_RULES = [
-    config_rule_delete('network_instance[DemoOFC-NetInst]/interface[13/1/3]', {
-        'name': 'DemoOFC-NetInst', 'id': '13/1/3'
+    json_config_rule_delete('node_4_port_16-input_to_node_2_port_17-output', {
+        'uuid': 'service-uuid'                          # populate 'service-uuid' of the service to test
     })
-]
\ No newline at end of file
+]
diff --git a/src/device/tests/Tools.py b/src/device/tests/Tools.py
deleted file mode 100644
index 2d8e99de3..000000000
--- a/src/device/tests/Tools.py
+++ /dev/null
@@ -1,25 +0,0 @@
-import json
-from copy import deepcopy
-from typing import Any, Dict, Union
-from device.proto.context_pb2 import ConfigActionEnum
-
-def config_rule(action : ConfigActionEnum, resource_key : str, resource_value : Union[str, Dict[str, Any]]):
-    if not isinstance(resource_value, str): resource_value = json.dumps(resource_value, sort_keys=True)
-    return {'action': action, 'resource_key': resource_key, 'resource_value': resource_value}
-
-def config_rule_set(resource_key : str, resource_value : Union[str, Dict[str, Any]]):
-    return config_rule(ConfigActionEnum.CONFIGACTION_SET, resource_key, resource_value)
-
-def config_rule_delete(resource_key : str, resource_value : Union[str, Dict[str, Any]]):
-    return config_rule(ConfigActionEnum.CONFIGACTION_DELETE, resource_key, resource_value)
-
-def endpoint_id(device_id, endpoint_uuid, topology_id=None):
-    result = {'device_id': deepcopy(device_id), 'endpoint_uuid': {'uuid': endpoint_uuid}}
-    if topology_id is not None: result['topology_id'] = deepcopy(topology_id)
-    return result
-
-def endpoint(device_id, endpoint_uuid, endpoint_type, topology_id=None):
-    return {
-        'endpoint_id': endpoint_id(device_id, endpoint_uuid, topology_id=topology_id),
-        'endpoint_type': endpoint_type,
-    }
diff --git a/src/device/tests/device_p4.py b/src/device/tests/device_p4.py
index 55c102586..3af354d7b 100644
--- a/src/device/tests/device_p4.py
+++ b/src/device/tests/device_p4.py
@@ -2,19 +2,13 @@
 P4 device example configuration.
 """
 
-from copy import deepcopy
-try:
-    from .context_pb2 import DeviceDriverEnum, DeviceOperationalStatusEnum
-except ImportError:
-    from device.proto.context_pb2 import DeviceDriverEnum, DeviceOperationalStatusEnum
-from .Tools import config_rule_set
+from common.tools.object_factory.ConfigRule import json_config_rule_set
+from common.tools.object_factory.Device import json_device_p4_disabled
 
 DEVICE_P4_ID = 0
 DEVICE_P4_NAME = 'device:leaf1'
-DEVICE_P4_TYPE = 'p4-switch'
 DEVICE_P4_ADDRESS = '127.0.0.1'
 DEVICE_P4_PORT = '50101'
-DEVICE_P4_DRIVERS = [DeviceDriverEnum.DEVICEDRIVER_P4]
 DEVICE_P4_VENDOR = 'Open Networking Foundation'
 DEVICE_P4_HW_VER = 'BMv2 simple_switch'
 DEVICE_P4_SW_VER = 'Stratum'
@@ -23,27 +17,20 @@ DEVICE_P4_WORKERS = 2
 DEVICE_P4_GRACE_PERIOD = 60
 
 DEVICE_P4_UUID = {'device_uuid': {'uuid': DEVICE_P4_NAME}}
-DEVICE_P4 = {
-    'device_id': deepcopy(DEVICE_P4_UUID),
-    'device_type': DEVICE_P4_TYPE,
-    'device_config': {'config_rules': []},
-    'device_operational_status': DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_DISABLED,
-    'device_drivers': DEVICE_P4_DRIVERS,
-    'device_endpoints': [],
-}
+DEVICE_P4 = json_device_p4_disabled(DEVICE_P4_UUID)
 
 DEVICE_P4_CONNECT_RULES = [
-    config_rule_set('_connect/address', DEVICE_P4_ADDRESS),
-    config_rule_set('_connect/port', DEVICE_P4_PORT),
-    config_rule_set('_connect/settings', {
-        'id': int(DEVICE_P4_ID),
-        'name': DEVICE_P4_NAME,
-        'hw-ver': DEVICE_P4_HW_VER,
-        'sw-ver': DEVICE_P4_SW_VER,
+    json_config_rule_set('_connect/address', DEVICE_P4_ADDRESS),
+    json_config_rule_set('_connect/port', DEVICE_P4_PORT),
+    json_config_rule_set('_connect/settings', {
+        'id'      : int(DEVICE_P4_ID),
+        'name'    : DEVICE_P4_NAME,
+        'hw-ver'  : DEVICE_P4_HW_VER,
+        'sw-ver'  : DEVICE_P4_SW_VER,
         'pipeconf': DEVICE_P4_PIPECONF
     }),
 ]
 
 DEVICE_P4_CONFIG_RULES = [
-    config_rule_set('key1', 'value1'),
+    json_config_rule_set('key1', 'value1'),
 ]
diff --git a/src/device/tests/test_unitary.py b/src/device/tests/test_unitary.py
index 7eaee6e9f..06f43671b 100644
--- a/src/device/tests/test_unitary.py
+++ b/src/device/tests/test_unitary.py
@@ -1,12 +1,12 @@
-import copy, grpc, json, logging, operator, os, pytest, time
-from datetime import datetime
+import calendar, copy, dateutil.parser, grpc, json, logging, operator, os, pytest, queue, time
+from datetime import datetime, timezone
 from typing import Tuple
-from queue import Queue, Empty
-from google.protobuf.json_format import MessageToDict
 from common.orm.Database import Database
 from common.orm.Factory import get_database_backend, BackendEnum as DatabaseBackendEnum
 from common.message_broker.Factory import get_messagebroker_backend, BackendEnum as MessageBrokerBackendEnum
 from common.message_broker.MessageBroker import MessageBroker
+from common.tools.grpc.Tools import grpc_message_to_json_string
+from common.tools.object_factory.EndPoint import json_endpoint, json_endpoint_id
 from context.Config import (
     GRPC_SERVICE_PORT as CONTEXT_GRPC_SERVICE_PORT, GRPC_MAX_WORKERS as CONTEXT_GRPC_MAX_WORKERS,
     GRPC_GRACE_PERIOD as CONTEXT_GRPC_GRACE_PERIOD)
@@ -26,16 +26,17 @@ from device.service.driver_api.DriverFactory import DriverFactory
 from device.service.driver_api.DriverInstanceCache import DriverInstanceCache
 from device.service.drivers import DRIVERS
 from device.tests.MockMonitoringService import MockMonitoringService
-from device.tests.Tools import endpoint, endpoint_id
 from monitoring.Config import (
     GRPC_SERVICE_PORT as MONITORING_GRPC_SERVICE_PORT, GRPC_MAX_WORKERS as MONITORING_GRPC_MAX_WORKERS,
     GRPC_GRACE_PERIOD as MONITORING_GRPC_GRACE_PERIOD)
 from monitoring.client.monitoring_client import MonitoringClient
 from .CommonObjects import CONTEXT, TOPOLOGY
+
 from .Device_Emulated import (
     DEVICE_EMU, DEVICE_EMU_CONFIG_ADDRESSES, DEVICE_EMU_CONFIG_ENDPOINTS, DEVICE_EMU_CONNECT_RULES,
-    DEVICE_EMU_DECONFIG_ADDRESSES, DEVICE_EMU_DECONFIG_ENDPOINTS, DEVICE_EMU_ENDPOINTS, DEVICE_EMU_ENDPOINTS_COOKED,
+    DEVICE_EMU_DECONFIG_ADDRESSES, DEVICE_EMU_DECONFIG_ENDPOINTS, DEVICE_EMU_EP_DESCS, DEVICE_EMU_ENDPOINTS_COOKED,
     DEVICE_EMU_ID, DEVICE_EMU_RECONFIG_ADDRESSES, DEVICE_EMU_UUID)
+
 try:
     from .Device_OpenConfig_Infinera import(
         DEVICE_OC, DEVICE_OC_CONFIG_RULES, DEVICE_OC_DECONFIG_RULES, DEVICE_OC_CONNECT_RULES, DEVICE_OC_ID,
@@ -43,11 +44,6 @@ try:
     ENABLE_OPENCONFIG = True
 except ImportError:
     ENABLE_OPENCONFIG = False
-    # Create a Device_OpenConfig_??.py file with the details for your device to test it and import it as follows in the
-    # try block of this import statement.
-    #   from .Device_OpenConfig_?? import(
-    #       DEVICE_OC, DEVICE_OC_CONFIG_RULES, DEVICE_OC_DECONFIG_RULES, DEVICE_OC_CONNECT_RULES, DEVICE_OC_ID,
-    #       DEVICE_OC_UUID)
 
 try:
     from .Device_Transport_Api_CTTC import (
@@ -56,24 +52,23 @@ try:
     ENABLE_TAPI = True
 except ImportError:
     ENABLE_TAPI = False
-    # Create a Device_Transport_Api_??.py file with the details for your device to test it and import it as follows in
-    # the try block of this import statement.
-    #   from .Device_Transport_Api_?? import(
-    #       DEVICE_TAPI, DEVICE_TAPI_CONFIG_RULES, DEVICE_TAPI_DECONFIG_RULES, DEVICE_TAPI_CONNECT_RULES,
-    #       DEVICE_TAPI_ID, DEVICE_TAPI_UUID)
-
-#ENABLE_OPENCONFIG = False
-#ENABLE_TAPI       = False
 
 from .mock_p4runtime_service import MockP4RuntimeService
 try:
     from .device_p4 import(
-        DEVICE_P4, DEVICE_P4_ID, DEVICE_P4_UUID, DEVICE_P4_NAME,
-        DEVICE_P4_ADDRESS, DEVICE_P4_PORT, DEVICE_P4_WORKERS,
-        DEVICE_P4_GRACE_PERIOD, DEVICE_P4_CONNECT_RULES,
-        DEVICE_P4_CONFIG_RULES)
+        DEVICE_P4, DEVICE_P4_ID, DEVICE_P4_UUID, DEVICE_P4_NAME, DEVICE_P4_ADDRESS, DEVICE_P4_PORT, DEVICE_P4_WORKERS,
+        DEVICE_P4_GRACE_PERIOD, DEVICE_P4_CONNECT_RULES, DEVICE_P4_CONFIG_RULES)
+    ENABLE_P4 = True
 except ImportError:
-    raise ImportError("Test configuration for P4 devices not found")
+    ENABLE_P4 = False
+
+ENABLE_OPENCONFIG = False # uncomment to disable tests of OpenConfig devices
+ENABLE_TAPI       = False # uncomment to disable tests of TAPI devices
+ENABLE_P4         = False # uncomment to disable tests of P4 devices
+
+logging.getLogger('apscheduler.executors.default').setLevel(logging.WARNING)
+logging.getLogger('apscheduler.scheduler').setLevel(logging.WARNING)
+logging.getLogger('monitoring-client').setLevel(logging.WARNING)
 
 LOGGER = logging.getLogger(__name__)
 LOGGER.setLevel(logging.DEBUG)
@@ -167,10 +162,6 @@ def p4runtime_service():
     yield _service
     _service.stop()
 
-def grpc_message_to_json_string(message):
-    return str(MessageToDict(
-        message, including_default_value_fields=True, preserving_proto_field_name=True, use_integers_for_enums=False))
-
 
 def test_prepare_environment(
     context_client : ContextClient,     # pylint: disable=redefined-outer-name
@@ -193,7 +184,7 @@ def test_device_emulated_add_error_cases(
 
     with pytest.raises(grpc.RpcError) as e:
         DEVICE_EMU_WITH_ENDPOINTS = copy.deepcopy(DEVICE_EMU)
-        DEVICE_EMU_WITH_ENDPOINTS['device_endpoints'].append(endpoint(DEVICE_EMU_ID, 'ep-id', 'ep-type'))
+        DEVICE_EMU_WITH_ENDPOINTS['device_endpoints'].append(json_endpoint(DEVICE_EMU_ID, 'ep-id', 'ep-type'))
         device_client.AddDevice(Device(**DEVICE_EMU_WITH_ENDPOINTS))
     assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
     msg_head = 'device.device_endpoints(['
@@ -360,14 +351,13 @@ def test_device_emulated_monitor(
     #LOGGER.info('driver_config = {:s}'.format(str(driver_config)))
     assert len(driver_config) == len(DEVICE_EMU_ENDPOINTS_COOKED) + len(DEVICE_EMU_CONFIG_ADDRESSES)
 
-    SAMPLING_DURATION_SEC = 3.0
-    SAMPLING_INTERVAL_SEC = 0.5
+    SAMPLING_DURATION_SEC = 10.0
+    SAMPLING_INTERVAL_SEC = 2.0
 
     MONITORING_SETTINGS_LIST = []
     KPI_UUIDS__TO__NUM_SAMPLES_RECEIVED = {}
-    for endpoint_uuid,_,sample_types in DEVICE_EMU_ENDPOINTS:
-        for sample_type in sample_types:
-            sample_type_id = sample_type.value
+    for endpoint_uuid,_,sample_types in DEVICE_EMU_EP_DESCS:
+        for sample_type_id in sample_types:
             sample_type_name = str(KpiSampleType.Name(sample_type_id)).upper().replace('KPISAMPLETYPE_', '')
             kpi_uuid = '{:s}-{:s}-{:s}-kpi_uuid'.format(DEVICE_EMU_UUID, endpoint_uuid, str(sample_type_id))
             monitoring_settings = {
@@ -377,7 +367,7 @@ def test_device_emulated_monitor(
                         sample_type_name, endpoint_uuid, DEVICE_EMU_UUID),
                     'kpi_sample_type': sample_type_id,
                     'device_id': DEVICE_EMU_ID,
-                    'endpoint_id': endpoint_id(DEVICE_EMU_ID, endpoint_uuid),
+                    'endpoint_id': json_endpoint_id(DEVICE_EMU_ID, endpoint_uuid),
                 },
                 'sampling_duration_s': SAMPLING_DURATION_SEC,
                 'sampling_interval_s': SAMPLING_INTERVAL_SEC,
@@ -396,25 +386,31 @@ def test_device_emulated_monitor(
     # wait to receive the expected number of samples
     # if takes more than 1.5 times the sampling duration, assume there is an error
     time_ini = time.time()
-    queue_samples : Queue = monitoring_service.queue_samples
+    queue_samples : queue.Queue = monitoring_service.queue_samples
     received_samples = []
     while (len(received_samples) < NUM_SAMPLES_EXPECTED) and (time.time() - time_ini < SAMPLING_DURATION_SEC * 1.5):
         try:
             received_sample = queue_samples.get(block=True, timeout=SAMPLING_INTERVAL_SEC / NUM_SAMPLES_EXPECTED)
             #LOGGER.info('received_sample = {:s}'.format(str(received_sample)))
             received_samples.append(received_sample)
-        except Empty:
+        except queue.Empty:
             continue
 
     t_end_monitoring = datetime.timestamp(datetime.utcnow())
 
-    LOGGER.info('received_samples = {:s}'.format(str(received_samples)))
+    #LOGGER.info('received_samples = {:s}'.format(str(received_samples)))
+    LOGGER.info('len(received_samples) = {:s}'.format(str(len(received_samples))))
+    LOGGER.info('NUM_SAMPLES_EXPECTED = {:s}'.format(str(NUM_SAMPLES_EXPECTED)))
     assert len(received_samples) == NUM_SAMPLES_EXPECTED
     for received_sample in received_samples:
         kpi_uuid = received_sample.kpi_id.kpi_id.uuid
         assert kpi_uuid in KPI_UUIDS__TO__NUM_SAMPLES_RECEIVED
         assert isinstance(received_sample.timestamp, str)
-        timestamp = float(received_sample.timestamp)
+        try:
+            timestamp = float(received_sample.timestamp)
+        except ValueError:
+            dt_time = dateutil.parser.isoparse(received_sample.timestamp).replace(tzinfo=timezone.utc)
+            timestamp = float(calendar.timegm(dt_time.timetuple())) + (dt_time.microsecond / 1.e6)
         assert timestamp > t_start_monitoring
         assert timestamp < t_end_monitoring
         assert received_sample.kpi_value.HasField('floatVal')
@@ -460,9 +456,13 @@ def test_device_emulated_deconfigure(
     RESULTING_CONFIG_RULES = RESULTING_CONFIG_RULES.values()
     driver_config = sorted(driver.GetConfig(), key=operator.itemgetter(0))
     driver_config = json.loads(json.dumps(driver_config)) # prevent integer keys to fail matching with string keys
-    #LOGGER.info('driver_config = {:s}'.format(str(driver_config)))
+    driver_config = list(filter(
+        lambda config_rule: (
+            not isinstance(config_rule[1], str) or not config_rule[1].startswith('do_sampling (trigger:')),
+        driver_config))
+    LOGGER.info('driver_config = {:s}'.format(str(driver_config)))
+    LOGGER.info('RESULTING_CONFIG_RULES = {:s}'.format(str(RESULTING_CONFIG_RULES)))
     assert len(driver_config) == len(RESULTING_CONFIG_RULES)
-    #LOGGER.info('RESULTING_CONFIG_RULES = {:s}'.format(str(RESULTING_CONFIG_RULES)))
     for config_rule in RESULTING_CONFIG_RULES:
         config_rule = [config_rule['resource_key'], json.loads(config_rule['resource_value'])]
         #LOGGER.info('config_rule = {:s}'.format(str(config_rule)))
@@ -478,7 +478,16 @@ def test_device_emulated_deconfigure(
     assert len(driver_config) == 0
 
     device_data = context_client.GetDevice(DeviceId(**DEVICE_EMU_ID))
-    assert len(device_data.device_config.config_rules) == 0
+    config_rules = device_data.device_config.config_rules
+    LOGGER.info('config_rules = {:s}'.format(str(config_rules)))
+    clean_config_rules = []
+    for config_rule in config_rules:
+        config_rule_value = json.loads(config_rule.resource_value)
+        if not isinstance(config_rule_value, str): clean_config_rules.append(config_rule)
+        if config_rule_value.startswith('do_sampling (trigger:'): continue
+        clean_config_rules.append(config_rule)
+    LOGGER.info('clean_config_rules = {:s}'.format(str(clean_config_rules)))
+    assert len(clean_config_rules) == 0
 
 
 def test_device_emulated_delete(
@@ -498,7 +507,7 @@ def test_device_openconfig_add_error_cases(
     device_client : DeviceClient,       # pylint: disable=redefined-outer-name
     device_service : DeviceService):    # pylint: disable=redefined-outer-name
 
-    if not ENABLE_OPENCONFIG: return # if there is no device to test against, asusme test is silently passed.
+    if not ENABLE_OPENCONFIG: pytest.skip('Skipping test: No OpenConfig device has been configured')
 
     with pytest.raises(grpc.RpcError) as e:
         DEVICE_OC_WITH_EXTRA_RULES = copy.deepcopy(DEVICE_OC)
@@ -518,7 +527,7 @@ def test_device_openconfig_add_correct(
     device_client : DeviceClient,       # pylint: disable=redefined-outer-name
     device_service : DeviceService):    # pylint: disable=redefined-outer-name
 
-    if not ENABLE_OPENCONFIG: return # if there is no device to test against, asusme test is silently passed.
+    if not ENABLE_OPENCONFIG: pytest.skip('Skipping test: No OpenConfig device has been configured')
 
     DEVICE_OC_WITH_CONNECT_RULES = copy.deepcopy(DEVICE_OC)
     DEVICE_OC_WITH_CONNECT_RULES['device_config']['config_rules'].extend(DEVICE_OC_CONNECT_RULES)
@@ -532,7 +541,7 @@ def test_device_openconfig_get(
     device_client : DeviceClient,       # pylint: disable=redefined-outer-name
     device_service : DeviceService):    # pylint: disable=redefined-outer-name
 
-    if not ENABLE_OPENCONFIG: return # if there is no device to test against, asusme test is silently passed.
+    if not ENABLE_OPENCONFIG: pytest.skip('Skipping test: No OpenConfig device has been configured')
 
     initial_config = device_client.GetInitialConfig(DeviceId(**DEVICE_OC_ID))
     LOGGER.info('initial_config = {:s}'.format(grpc_message_to_json_string(initial_config)))
@@ -546,7 +555,7 @@ def test_device_openconfig_configure(
     device_client : DeviceClient,       # pylint: disable=redefined-outer-name
     device_service : DeviceService):    # pylint: disable=redefined-outer-name
 
-    if not ENABLE_OPENCONFIG: return # if there is no device to test against, asusme test is silently passed.
+    if not ENABLE_OPENCONFIG: pytest.skip('Skipping test: No OpenConfig device has been configured')
 
     driver : _Driver = device_service.driver_instance_cache.get(DEVICE_OC_UUID) # we know the driver exists now
     assert driver is not None
@@ -581,7 +590,7 @@ def test_device_openconfig_deconfigure(
     device_client : DeviceClient,       # pylint: disable=redefined-outer-name
     device_service : DeviceService):    # pylint: disable=redefined-outer-name
 
-    if not ENABLE_OPENCONFIG: return # if there is no device to test against, asusme test is silently passed.
+    if not ENABLE_OPENCONFIG: pytest.skip('Skipping test: No OpenConfig device has been configured')
 
     driver : _Driver = device_service.driver_instance_cache.get(DEVICE_OC_UUID) # we know the driver exists now
     assert driver is not None
@@ -616,7 +625,7 @@ def test_device_openconfig_delete(
     device_client : DeviceClient,       # pylint: disable=redefined-outer-name
     device_service : DeviceService):    # pylint: disable=redefined-outer-name
 
-    if not ENABLE_OPENCONFIG: return # if there is no device to test against, asusme test is silently passed.
+    if not ENABLE_OPENCONFIG: pytest.skip('Skipping test: No OpenConfig device has been configured')
 
     device_client.DeleteDevice(DeviceId(**DEVICE_OC_ID))
     driver : _Driver = device_service.driver_instance_cache.get(DEVICE_OC_UUID, {})
@@ -628,7 +637,7 @@ def test_device_openconfig_delete(
 def test_device_tapi_add_error_cases(
     device_client : DeviceClient):      # pylint: disable=redefined-outer-name
 
-    if not ENABLE_TAPI: return # if there is no device to test against, asusme test is silently passed.
+    if not ENABLE_TAPI: pytest.skip('Skipping test: No TAPI device has been configured')
 
     with pytest.raises(grpc.RpcError) as e:
         DEVICE_TAPI_WITH_EXTRA_RULES = copy.deepcopy(DEVICE_TAPI)
@@ -647,7 +656,7 @@ def test_device_tapi_add_correct(
     device_client: DeviceClient,        # pylint: disable=redefined-outer-name
     device_service: DeviceService):     # pylint: disable=redefined-outer-name
 
-    if not ENABLE_TAPI: return # if there is no device to test against, asusme test is silently passed.
+    if not ENABLE_TAPI: pytest.skip('Skipping test: No TAPI device has been configured')
 
     DEVICE_TAPI_WITH_CONNECT_RULES = copy.deepcopy(DEVICE_TAPI)
     DEVICE_TAPI_WITH_CONNECT_RULES['device_config']['config_rules'].extend(DEVICE_TAPI_CONNECT_RULES)
@@ -660,7 +669,7 @@ def test_device_tapi_get(
     context_client: ContextClient,      # pylint: disable=redefined-outer-name
     device_client: DeviceClient):       # pylint: disable=redefined-outer-name
 
-    if not ENABLE_TAPI: return # if there is no device to test against, asusme test is silently passed.
+    if not ENABLE_TAPI: pytest.skip('Skipping test: No TAPI device has been configured')
 
     initial_config = device_client.GetInitialConfig(DeviceId(**DEVICE_TAPI_ID))
     LOGGER.info('initial_config = {:s}'.format(grpc_message_to_json_string(initial_config)))
@@ -674,7 +683,7 @@ def test_device_tapi_configure(
     device_client: DeviceClient,        # pylint: disable=redefined-outer-name
     device_service: DeviceService):     # pylint: disable=redefined-outer-name
 
-    if not ENABLE_TAPI: return # if there is no device to test against, asusme test is silently passed.
+    if not ENABLE_TAPI: pytest.skip('Skipping test: No TAPI device has been configured')
 
     driver : _Driver = device_service.driver_instance_cache.get(DEVICE_TAPI_UUID)
     assert driver is not None
@@ -709,7 +718,7 @@ def test_device_tapi_deconfigure(
     device_client: DeviceClient,        # pylint: disable=redefined-outer-name
     device_service: DeviceService):     # pylint: disable=redefined-outer-name
 
-    if not ENABLE_TAPI: return # if there is no device to test against, asusme test is silently passed.
+    if not ENABLE_TAPI: pytest.skip('Skipping test: No TAPI device has been configured')
 
     driver: _Driver = device_service.driver_instance_cache.get(DEVICE_TAPI_UUID)
     assert driver is not None
@@ -743,7 +752,7 @@ def test_device_tapi_delete(
     device_client : DeviceClient,       # pylint: disable=redefined-outer-name
     device_service : DeviceService):    # pylint: disable=redefined-outer-name
 
-    if not ENABLE_TAPI: return # if there is no device to test against, asusme test is silently passed.
+    if not ENABLE_TAPI: pytest.skip('Skipping test: No TAPI device has been configured')
 
     device_client.DeleteDevice(DeviceId(**DEVICE_TAPI_ID))
     driver : _Driver = device_service.driver_instance_cache.get(DEVICE_TAPI_UUID, {})
@@ -757,6 +766,8 @@ def test_device_p4_add_error_cases(
         device_client: DeviceClient,     # pylint: disable=redefined-outer-name
         device_service: DeviceService):  # pylint: disable=redefined-outer-name
 
+    if not ENABLE_P4: pytest.skip('Skipping test: No P4 device has been configured')
+
     with pytest.raises(grpc.RpcError) as e:
         device_p4_with_extra_rules = copy.deepcopy(DEVICE_P4)
         device_p4_with_extra_rules['device_config']['config_rules'].extend(
@@ -773,10 +784,12 @@ def test_device_p4_add_error_cases(
 
 
 def test_device_p4_add_correct(
-        context_client: ContextClient,   # pylint: disable=redefined-outer-name
-        device_client: DeviceClient,     # pylint: disable=redefined-outer-name
-        device_service: DeviceService,   # pylint: disable=redefined-outer-name
-        p4runtime_service: MockP4RuntimeService):
+        context_client: ContextClient,              # pylint: disable=redefined-outer-name
+        device_client: DeviceClient,                # pylint: disable=redefined-outer-name
+        device_service: DeviceService,              # pylint: disable=redefined-outer-name
+        p4runtime_service: MockP4RuntimeService):   # pylint: disable=redefined-outer-name
+
+    if not ENABLE_P4: pytest.skip('Skipping test: No P4 device has been configured')
 
     device_p4_with_connect_rules = copy.deepcopy(DEVICE_P4)
     device_p4_with_connect_rules['device_config']['config_rules'].extend(
@@ -787,10 +800,12 @@ def test_device_p4_add_correct(
 
 
 def test_device_p4_get(
-        context_client: ContextClient,   # pylint: disable=redefined-outer-name
-        device_client: DeviceClient,     # pylint: disable=redefined-outer-name
-        device_service: DeviceService,   # pylint: disable=redefined-outer-name
-        p4runtime_service: MockP4RuntimeService):
+        context_client: ContextClient,              # pylint: disable=redefined-outer-name
+        device_client: DeviceClient,                # pylint: disable=redefined-outer-name
+        device_service: DeviceService,              # pylint: disable=redefined-outer-name
+        p4runtime_service: MockP4RuntimeService):   # pylint: disable=redefined-outer-name
+
+    if not ENABLE_P4: pytest.skip('Skipping test: No P4 device has been configured')
 
     initial_config = device_client.GetInitialConfig(DeviceId(**DEVICE_P4_UUID))
     LOGGER.info('initial_config = {:s}'.format(
@@ -802,26 +817,28 @@ def test_device_p4_get(
 
 
 def test_device_p4_configure(
-        context_client: ContextClient,   # pylint: disable=redefined-outer-name
-        device_client: DeviceClient,     # pylint: disable=redefined-outer-name
-        device_service: DeviceService,   # pylint: disable=redefined-outer-name
-        p4runtime_service: MockP4RuntimeService):
-    pytest.skip("Skipping test for unimplemented method")
+        context_client: ContextClient,              # pylint: disable=redefined-outer-name
+        device_client: DeviceClient,                # pylint: disable=redefined-outer-name
+        device_service: DeviceService,              # pylint: disable=redefined-outer-name
+        p4runtime_service: MockP4RuntimeService):   # pylint: disable=redefined-outer-name
+    pytest.skip('Skipping test for unimplemented method')
 
 
 def test_device_p4_deconfigure(
-        context_client: ContextClient,   # pylint: disable=redefined-outer-name
-        device_client: DeviceClient,     # pylint: disable=redefined-outer-name
-        device_service: DeviceService,   # pylint: disable=redefined-outer-name
-        p4runtime_service: MockP4RuntimeService):
-    pytest.skip("Skipping test for unimplemented method")
+        context_client: ContextClient,              # pylint: disable=redefined-outer-name
+        device_client: DeviceClient,                # pylint: disable=redefined-outer-name
+        device_service: DeviceService,              # pylint: disable=redefined-outer-name
+        p4runtime_service: MockP4RuntimeService):   # pylint: disable=redefined-outer-name
+    pytest.skip('Skipping test for unimplemented method')
 
 
 def test_device_p4_delete(
-        context_client: ContextClient,   # pylint: disable=redefined-outer-name
-        device_client: DeviceClient,     # pylint: disable=redefined-outer-name
-        device_service: DeviceService,   # pylint: disable=redefined-outer-name
-        p4runtime_service: MockP4RuntimeService):
+        context_client: ContextClient,              # pylint: disable=redefined-outer-name
+        device_client: DeviceClient,                # pylint: disable=redefined-outer-name
+        device_service: DeviceService,              # pylint: disable=redefined-outer-name
+        p4runtime_service: MockP4RuntimeService):   # pylint: disable=redefined-outer-name
+
+    if not ENABLE_P4: pytest.skip('Skipping test: No P4 device has been configured')
 
     device_client.DeleteDevice(DeviceId(**DEVICE_P4_UUID))
     driver : _Driver = device_service.driver_instance_cache.get(DEVICE_P4_NAME)
diff --git a/src/l3_attackmitigator/client/l3_attackmitigatorClient.py b/src/l3_attackmitigator/client/l3_attackmitigatorClient.py
index 190d63884..a15e88c4d 100644
--- a/src/l3_attackmitigator/client/l3_attackmitigatorClient.py
+++ b/src/l3_attackmitigator/client/l3_attackmitigatorClient.py
@@ -11,7 +11,7 @@ from l3_attackmitigator.proto.l3_attackmitigator_pb2 import (
 LOGGER = logging.getLogger(__name__)
 MAX_RETRIES = 15
 DELAY_FUNCTION = delay_exponential(initial=0.01, increment=2.0, maximum=5.0)
-
+RETRY_DECORATOR = retry(max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
 
 class l3_attackmitigatorClient:
     def __init__(self, address, port):
@@ -32,14 +32,14 @@ class l3_attackmitigatorClient:
         self.channel = None
         self.stub = None
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def SendOutput(self, request: Output) -> EmptyMitigator:
         LOGGER.debug('SendOutput request: {}'.format(request))
         response = self.stub.SendOutput(request)
         LOGGER.debug('SendOutput result: {}'.format(response))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def GetMitigation(self, request: EmptyMitigator) -> EmptyMitigator:
         LOGGER.debug('GetMitigation request: {}'.format(request))
         response = self.stub.GetMitigation(request)
diff --git a/src/l3_centralizedattackdetector/client/l3_centralizedattackdetectorClient.py b/src/l3_centralizedattackdetector/client/l3_centralizedattackdetectorClient.py
index 64b66f3ce..c6512c8f0 100644
--- a/src/l3_centralizedattackdetector/client/l3_centralizedattackdetectorClient.py
+++ b/src/l3_centralizedattackdetector/client/l3_centralizedattackdetectorClient.py
@@ -12,6 +12,7 @@ from l3_centralizedattackdetector.proto.l3_centralizedattackdetector_pb2 import
 LOGGER = logging.getLogger(__name__)
 MAX_RETRIES = 15
 DELAY_FUNCTION = delay_exponential(initial=0.01, increment=2.0, maximum=5.0)
+RETRY_DECORATOR = retry(max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
 
 class l3_centralizedattackdetectorClient:
     def __init__(self, address, port):
@@ -32,14 +33,14 @@ class l3_centralizedattackdetectorClient:
         self.channel = None
         self.stub = None
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def SendInput(self, request: ModelInput) -> Empty:
         LOGGER.debug('SendInput request: {}'.format(request))
         response = self.stub.SendInput(request)
         LOGGER.debug('SendInput result: {}'.format(response))
         return response
     
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def GetOutput(self, request: Empty) -> ModelOutput:
         LOGGER.debug('GetOutput request: {}'.format(request))
         response = self.stub.GetOutput(request)
diff --git a/src/monitoring/Config.py b/src/monitoring/Config.py
index 11036b0d1..b88cf34e0 100644
--- a/src/monitoring/Config.py
+++ b/src/monitoring/Config.py
@@ -7,6 +7,20 @@ LOG_LEVEL = logging.WARNING
 GRPC_SERVICE_PORT = 7070
 GRPC_MAX_WORKERS  = 10
 GRPC_GRACE_PERIOD = 60
+GRPC_SERVICE_HOST = '127.0.0.1'
 
 # Prometheus settings
 METRICS_PORT = 9192
+
+# Dependency micro-service connection settings
+CONTEXT_SERVICE_HOST = '127.0.0.1'
+CONTEXT_GRPC_SERVICE_PORT = 1010
+
+DEVICE_SERVICE_HOST         = '127.0.0.1'
+DEVICE_GRPC_SERVICE_PORT    = 2020
+DEVICE_GRPC_MAX_WORKERS     = 10
+DEVICE_GRPC_GRACE_PERIOD    = 60
+
+
+
+
diff --git a/src/monitoring/Dockerfile b/src/monitoring/Dockerfile
index af2fd6085..97efacbad 100644
--- a/src/monitoring/Dockerfile
+++ b/src/monitoring/Dockerfile
@@ -29,7 +29,6 @@ RUN mkdir -p /var/teraflow/device/proto
 RUN mkdir -p /var/teraflow/device/client
 RUN mkdir -p /var/teraflow/context
 
-
 # Get Python packages per module
 COPY monitoring/requirements.in requirements.in
 RUN pip-compile --output-file=requirements.txt requirements.in
@@ -49,3 +48,4 @@ RUN rm -r common/rpc_method_wrapper/tests
 RUN rm -r context/tests/test_unitary.py
 
 ENTRYPOINT ["python", "-m", "monitoring.service"]
+
diff --git a/src/monitoring/requirements.in b/src/monitoring/requirements.in
index 70d0c3ee9..77b66b794 100644
--- a/src/monitoring/requirements.in
+++ b/src/monitoring/requirements.in
@@ -10,4 +10,7 @@ pytest
 pytest-benchmark
 influxdb
 redis
-coverage
\ No newline at end of file
+anytree
+apscheduler
+xmltodict
+coverage
diff --git a/src/monitoring/service/EventTools.py b/src/monitoring/service/EventTools.py
index a28ff36a3..8465174bb 100644
--- a/src/monitoring/service/EventTools.py
+++ b/src/monitoring/service/EventTools.py
@@ -19,13 +19,21 @@ class EventsDeviceCollector:
     def __init__(self, context_client_grpc : ContextClient, monitoring_client_grpc : MonitoringClient) -> None: # pylint: disable=redefined-outer-name
         self._events_queue = Queue()
 
-        self._device_stream   = context_client_grpc.GetDeviceEvents(Empty())
-        self._context_client  = context_client_grpc
+        self._device_stream     = context_client_grpc.GetDeviceEvents(Empty())
+        self._context_client    = context_client_grpc
+        self._channel           = context_client_grpc.channel
         self._monitoring_client = monitoring_client_grpc
 
         self._device_thread   = threading.Thread(target=self._collect, args=(self._device_stream  ,), daemon=False)
 
-    def _collect(self, events_stream) -> None:
+    def grpc_server_on(self):
+        try:
+            grpc.channel_ready_future(self._channel).result(timeout=15)
+            return True
+        except grpc.FutureTimeoutError:
+            return False
+
+    def _collect(self, events_stream):
         try:
             for event in events_stream:
                 self._events_queue.put_nowait(event)
@@ -34,39 +42,39 @@ class EventsDeviceCollector:
                 raise # pragma: no cover
 
     def start(self):
-        self._device_thread.start()
+        try:
+            self._device_thread.start()
+        except RuntimeError as e:
+            LOGGER.exception('Start EventTools exception')
 
     def get_event(self, block : bool = True, timeout : float = 0.1):
         return self._events_queue.get(block=block, timeout=timeout)
 
     def stop(self):
-
         self._device_stream.cancel()
-
         self._device_thread.join()
 
     def listen_events(self):
-        LOGGER.info('getting Kpi by KpiID')
-        qsize = self._events_queue.qsize()
         try:
             kpi_id_list = []
-            if qsize > 0:
-                for i in range(qsize):
-                    print("Queue size: "+str(qsize))
-                    event = self.get_event(block=True)
-                    if event.event.event_type == EventTypeEnum.EVENTTYPE_CREATE:
-                        device = self._context_client.GetDevice(event.device_id)
-                        print("Endpoints value: " + str(len(device.device_endpoints)))
-                        for j,end_point in enumerate(device.device_endpoints):
-
-                            # for k,rule in enumerate(device.device_config.config_rules):
+
+            while not self._events_queue.empty():
+                LOGGER.info('getting Kpi by KpiID')
+                event = self.get_event(block=True)
+                if event.event.event_type == EventTypeEnum.EVENTTYPE_CREATE:
+                    device = self._context_client.GetDevice(event.device_id)
+                    for j,end_point in enumerate(device.device_endpoints):
+                        #for i, value in enumerate(kpi_sample_types_pb2.KpiSampleType.values()):
+                        for i, value in enumerate(end_point.kpi_sample_types):
+                            #if value == kpi_sample_types_pb2.KpiSampleType.KPISAMPLETYPE_UNKNOWN: continue
+
                             kpi_descriptor = monitoring_pb2.KpiDescriptor()
 
                             kpi_descriptor.kpi_description                      = device.device_type
-                            kpi_descriptor.kpi_sample_type                      = kpi_sample_types_pb2.KpiSampleType.KPISAMPLETYPE_PACKETS_TRANSMITTED
+                            kpi_descriptor.kpi_sample_type                      = value
+                            #kpi_descriptor.service_id.service_uuid.uuid         = ""
                             kpi_descriptor.device_id.CopyFrom(device.device_id)
                             kpi_descriptor.endpoint_id.CopyFrom(end_point.endpoint_id)
-                            kpi_descriptor.service_id.service_uuid.uuid         = "SERV"+str(i+1)
 
                             kpi_id = self._monitoring_client.CreateKpi(kpi_descriptor)
                             kpi_id_list.append(kpi_id)
@@ -78,3 +86,4 @@ class EventsDeviceCollector:
 
         except Exception as e:  # pragma: no cover
             LOGGER.exception('ListenEvents exception')
+
diff --git a/src/monitoring/service/MonitoringService.py b/src/monitoring/service/MonitoringService.py
index 665ce44f7..8874277f0 100644
--- a/src/monitoring/service/MonitoringService.py
+++ b/src/monitoring/service/MonitoringService.py
@@ -1,6 +1,6 @@
 from concurrent import futures
 
-import grpc
+import grpc, logging
 
 from monitoring.service.MonitoringServiceServicerImpl import MonitoringServiceServicerImpl
 from monitoring.Config import GRPC_SERVICE_PORT, GRPC_MAX_WORKERS, GRPC_GRACE_PERIOD
@@ -11,8 +11,7 @@ from grpc_health.v1 import health_pb2
 from grpc_health.v1.health_pb2_grpc import add_HealthServicer_to_server
 
 from common.logger import getJSONLogger
-LOGGER = getJSONLogger('monitoringservice-server')
-LOGGER.setLevel('DEBUG')
+LOGGER = getJSONLogger('monitoring-server')
 
 BIND_ADDRESS = '0.0.0.0'
 
@@ -43,9 +42,11 @@ class MonitoringService:
         add_HealthServicer_to_server(self.health_servicer, self.server)
 
         # start server
-        endpoint = '{}:{}'.format(self.address, self.port)
-        LOGGER.info('Listening on {}'.format(endpoint))
-        self.server.add_insecure_port(endpoint)
+        self.endpoint = '{:s}:{:s}'.format(str(self.address), str(self.port))
+        LOGGER.info('Starting Service (tentative endpoint: {:s}, max_workers: {:s})...'.format(
+            str(self.endpoint), str(self.max_workers)))
+
+        self.server.add_insecure_port(self.endpoint)
         self.server.start()
         self.health_servicer.set('', health_pb2.HealthCheckResponse.SERVING) # pylint: disable=maybe-no-member
 
diff --git a/src/monitoring/service/MonitoringServiceServicerImpl.py b/src/monitoring/service/MonitoringServiceServicerImpl.py
index fcadaa0c9..8bd7e2c57 100644
--- a/src/monitoring/service/MonitoringServiceServicerImpl.py
+++ b/src/monitoring/service/MonitoringServiceServicerImpl.py
@@ -1,24 +1,24 @@
-import os,grpc
+import os,grpc, logging
+import socket
 
 from prometheus_client import Summary
 from prometheus_client import Counter
+from common.Settings import get_setting
 
+from monitoring.Config import DEVICE_GRPC_SERVICE_PORT, DEVICE_SERVICE_HOST
+from monitoring.proto.kpi_sample_types_pb2 import KpiSampleType
 from monitoring.service import SqliteTools, InfluxTools
 from monitoring.proto import monitoring_pb2
 from monitoring.proto import monitoring_pb2_grpc
 
 from common.rpc_method_wrapper.ServiceExceptions import ServiceException
-from common.logger import getJSONLogger
 
 from context.proto import context_pb2
 
-
-from device.Config import GRPC_SERVICE_PORT
 from device.client.DeviceClient import DeviceClient
 from device.proto import device_pb2
 
-LOGGER = getJSONLogger('monitoringservice-server')
-LOGGER.setLevel('DEBUG')
+LOGGER = logging.getLogger(__name__)
 
 MONITORING_GETINSTANTKPI_REQUEST_TIME = Summary('monitoring_getinstantkpi_processing_seconds', 'Time spent processing monitoring instant kpi request')
 MONITORING_INCLUDEKPI_COUNTER = Counter('monitoring_includekpi_counter', 'Monitoring include kpi request counter')
@@ -28,6 +28,9 @@ INFLUXDB_USER = os.environ.get("INFLUXDB_USER")
 INFLUXDB_PASSWORD = os.environ.get("INFLUXDB_PASSWORD")
 INFLUXDB_DATABASE = os.environ.get("INFLUXDB_DATABASE")
 
+DEVICE_SERVICE_HOST = get_setting('DEVICESERVICE_SERVICE_HOST',      default=DEVICE_SERVICE_HOST     )
+DEVICE_SERVICE_PORT = get_setting('DEVICESERVICE_SERVICE_PORT_GRPC', default=DEVICE_GRPC_SERVICE_PORT)
+
 
 class MonitoringServiceServicerImpl(monitoring_pb2_grpc.MonitoringServiceServicer):
     def __init__(self):
@@ -35,6 +38,7 @@ class MonitoringServiceServicerImpl(monitoring_pb2_grpc.MonitoringServiceService
 
         # Init sqlite monitoring db
         self.sql_db = SqliteTools.SQLite('monitoring.db')
+        self.deviceClient = DeviceClient(address=DEVICE_SERVICE_HOST, port=DEVICE_GRPC_SERVICE_PORT)  # instantiate the client
 
         # Create influx_db client
         self.influx_db = InfluxTools.Influx(INFLUXDB_HOSTNAME,"8086",INFLUXDB_USER,INFLUXDB_PASSWORD,INFLUXDB_DATABASE)
@@ -83,8 +87,11 @@ class MonitoringServiceServicerImpl(monitoring_pb2_grpc.MonitoringServiceService
             monitor_device_request.sampling_duration_s                              = request.sampling_duration_s
             monitor_device_request.sampling_interval_s                              = request.sampling_interval_s
 
-            deviceClient = DeviceClient(address="localhost", port=GRPC_SERVICE_PORT )  # instantiate the client
-            # deviceClient.MonitorDeviceKpi(monitor_device_request)
+            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+            if s.connect_ex((DEVICE_SERVICE_HOST, DEVICE_GRPC_SERVICE_PORT)) == 0:
+                self.deviceClient.MonitorDeviceKpi(monitor_device_request)
+            else:
+                LOGGER.warning('Device service is not reachable')
 
             return context_pb2.Empty()
         except ServiceException as e:
@@ -103,19 +110,22 @@ class MonitoringServiceServicerImpl(monitoring_pb2_grpc.MonitoringServiceService
 
         try:
             kpiDescriptor = self.GetKpiDescriptor(request.kpi_id, grpc_context)
+            if kpiDescriptor is None:
+                LOGGER.warning('Ignoring sample with KPIId({:s}): not found in database'.format(str(request.kpi_id)))
+                return context_pb2.Empty()
 
-            kpiSampleType   = kpiDescriptor.kpi_sample_type
+            kpiSampleType   = KpiSampleType.Name(kpiDescriptor.kpi_sample_type).upper().replace('KPISAMPLETYPE_', '')
             kpiId           = request.kpi_id.kpi_id.uuid
             deviceId        = kpiDescriptor.device_id.device_uuid.uuid
             endpointId      = kpiDescriptor.endpoint_id.endpoint_uuid.uuid
             serviceId       = kpiDescriptor.service_id.service_uuid.uuid
             time_stamp      = request.timestamp
-            kpi_value       = request.kpi_value.intVal
+            kpi_value       = getattr(request.kpi_value, request.kpi_value.WhichOneof('value'))
 
             # Build the structure to be included as point in the influxDB
             self.influx_db.write_KPI(time_stamp,kpiId,kpiSampleType,deviceId,endpointId,serviceId,kpi_value)
 
-            self.influx_db.read_KPI_points()
+            #self.influx_db.read_KPI_points()
 
             return context_pb2.Empty()
         except ServiceException as e:
@@ -142,7 +152,9 @@ class MonitoringServiceServicerImpl(monitoring_pb2_grpc.MonitoringServiceService
         LOGGER.info('getting Kpi by KpiID')
         try:
             kpi_db = self.sql_db.get_KPI(int(request.kpi_id.uuid))
-            print(self.sql_db.get_KPIS())
+            #LOGGER.info('sql_db.get_KPIS={:s}'.format(str(self.sql_db.get_KPIS())))
+            #LOGGER.info('kpi_db={:s}'.format(str(kpi_db)))
+            if kpi_db is None: return None
 
             kpiDescriptor = monitoring_pb2.KpiDescriptor()
 
@@ -159,5 +171,3 @@ class MonitoringServiceServicerImpl(monitoring_pb2_grpc.MonitoringServiceService
 
         except Exception as e:  # pragma: no cover
             LOGGER.exception('GetKpiDescriptor exception')
-
-
diff --git a/src/monitoring/service/SqliteTools.py b/src/monitoring/service/SqliteTools.py
index d03d6699b..e54f23013 100644
--- a/src/monitoring/service/SqliteTools.py
+++ b/src/monitoring/service/SqliteTools.py
@@ -53,6 +53,7 @@ class SQLite():
         
     def get_KPIS(self):
         data = self.client.execute("SELECT * FROM KPI")
-        for row in data:
-            print(row)
+        #print("\n")
+        #for row in data:
+        #    print(row)
         return data.fetchall()
\ No newline at end of file
diff --git a/src/monitoring/service/__main__.py b/src/monitoring/service/__main__.py
index ea189e1c9..917b756bb 100644
--- a/src/monitoring/service/__main__.py
+++ b/src/monitoring/service/__main__.py
@@ -1,43 +1,45 @@
-import logging, os, signal, sys, threading
-import time
+import logging, signal, sys, threading, socket
 
+from common.Settings import get_setting, wait_for_environment_variables
 from context.client.ContextClient import ContextClient
-from monitoring.Config import GRPC_SERVICE_PORT, GRPC_MAX_WORKERS, GRPC_GRACE_PERIOD, LOG_LEVEL, METRICS_PORT
+from monitoring.Config import (
+    GRPC_SERVICE_PORT, GRPC_MAX_WORKERS, GRPC_GRACE_PERIOD, LOG_LEVEL, METRICS_PORT, CONTEXT_GRPC_SERVICE_PORT,
+    CONTEXT_SERVICE_HOST)
 
-from common.logger import getJSONLogger
 from monitoring.client.monitoring_client import MonitoringClient
 from monitoring.proto import monitoring_pb2
 from monitoring.service.EventTools import EventsDeviceCollector
 from monitoring.service.MonitoringService import MonitoringService
 
-LOGGER = getJSONLogger('monitoringservice-server')
-LOGGER.setLevel('DEBUG')
-
 from prometheus_client import start_http_server
 
 terminate = threading.Event()
-logger = None
+LOGGER = None
+LOCALHOST = '127.0.0.1'
 
 def signal_handler(signal, frame):
-    global terminate, logger
     LOGGER.warning('Terminate signal received')
     terminate.set()
 
 def start_monitoring():
-    LOGGER.info('Start Monitoring...')
-    context_client_grpc = ContextClient(address='localhost', port='2020')
-    monitoring_client = MonitoringClient(server='localhost', port='7070')  # instantiate the client
+    LOGGER.info('Start Monitoring...',)
 
-    while True:
-        if terminate.is_set():
-            LOGGER.warning("Stopping execution...")
+    grpc_service_port    = get_setting('MONITORINGSERVICE_SERVICE_PORT_GRPC', default=GRPC_SERVICE_PORT        )
+    context_service_host = get_setting('CONTEXTSERVICE_SERVICE_HOST',         default=CONTEXT_SERVICE_HOST     )
+    context_service_port = get_setting('CONTEXTSERVICE_SERVICE_PORT_GRPC',    default=CONTEXT_GRPC_SERVICE_PORT)
 
-            break
+    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    if s.connect_ex((context_service_host, int(context_service_port))) != 0:
+        LOGGER.info('Context service is not reachable')
+        return
 
-        # Start Listening Events
-        events_collector = EventsDeviceCollector(context_client_grpc, monitoring_client)
-        events_collector.start()
+    context_client_grpc = ContextClient(address=context_service_host, port=context_service_port)
+    monitoring_client = MonitoringClient(server=LOCALHOST, port=grpc_service_port)  # instantiate the client
+    events_collector = EventsDeviceCollector(context_client_grpc, monitoring_client)
+    events_collector.start()
 
+    # Iterate while terminate is not set
+    while not terminate.is_set():
         list_new_kpi_ids = events_collector.listen_events()
 
         # Monitor Kpis
@@ -49,43 +51,50 @@ def start_monitoring():
                 monitor_kpi_request.sampling_duration_s = 120
                 monitor_kpi_request.sampling_interval_s = 5
 
-                # MonitorKpi(monitor_kpi_request)
-
-
+                monitoring_client.MonitorKpi(monitor_kpi_request)
+    else:
+        # Terminate is set, looping terminates
+        LOGGER.warning("Stopping execution...")
 
+    events_collector.start()
 
 def main():
-    global terminate, logger
+    global LOGGER
 
-    service_port = GRPC_SERVICE_PORT
-    max_workers  = GRPC_MAX_WORKERS
-    grace_period = GRPC_GRACE_PERIOD
-    log_level    = LOG_LEVEL
-    metrics_port = METRICS_PORT
+    grpc_service_port = get_setting('MONITORINGSERVICE_SERVICE_PORT_GRPC', default=GRPC_SERVICE_PORT)
+    max_workers       = get_setting('MAX_WORKERS',                         default=GRPC_MAX_WORKERS )
+    grace_period      = get_setting('GRACE_PERIOD',                        default=GRPC_GRACE_PERIOD)
+    log_level         = get_setting('LOG_LEVEL',                           default=LOG_LEVEL        )
+    metrics_port      = get_setting('METRICS_PORT',                        default=METRICS_PORT     )
 
     logging.basicConfig(level=log_level)
-    logger = logging.getLogger(__name__)
+    LOGGER = logging.getLogger(__name__)
+
+    wait_for_environment_variables([
+        'CONTEXTSERVICE_SERVICE_HOST', 'CONTEXTSERVICE_SERVICE_PORT_GRPC',
+        'DEVICESERVICE_SERVICE_HOST', 'DEVICESERVICE_SERVICE_PORT_GRPC'
+    ])
 
     signal.signal(signal.SIGINT,  signal_handler)
     signal.signal(signal.SIGTERM, signal_handler)
 
-    logger.info('Starting...')
+    LOGGER.info('Starting...')
     # Start metrics server
     start_http_server(metrics_port)
 
     # Starting monitoring service
-    grpc_service = MonitoringService(port=service_port, max_workers=max_workers, grace_period=grace_period)
+    grpc_service = MonitoringService(port=grpc_service_port, max_workers=max_workers, grace_period=grace_period)
     grpc_service.start()
 
-    # start_monitoring()
+    start_monitoring()
 
     # Wait for Ctrl+C or termination signal
     while not terminate.wait(timeout=0.1): pass
 
-    logger.info('Terminating...')
+    LOGGER.info('Terminating...')
     grpc_service.stop()
 
-    logger.info('Bye')
+    LOGGER.info('Bye')
     return 0
 
 if __name__ == '__main__':
diff --git a/src/monitoring/tests/test_unitary.py b/src/monitoring/tests/test_unitary.py
index b77699c5b..6e1c69d5a 100644
--- a/src/monitoring/tests/test_unitary.py
+++ b/src/monitoring/tests/test_unitary.py
@@ -1,14 +1,15 @@
-import logging, grpc
+import logging
 import os
-import sqlite3
-
+import socket
 import pytest
 from typing import Tuple
 
+
 from monitoring.proto import context_pb2, kpi_sample_types_pb2
 from monitoring.proto import monitoring_pb2
 from monitoring.client.monitoring_client import MonitoringClient
-from monitoring.Config import GRPC_SERVICE_PORT, GRPC_MAX_WORKERS, GRPC_GRACE_PERIOD
+from monitoring.Config import GRPC_SERVICE_PORT, GRPC_MAX_WORKERS, GRPC_GRACE_PERIOD, DEVICE_GRPC_GRACE_PERIOD, DEVICE_GRPC_MAX_WORKERS, DEVICE_GRPC_SERVICE_PORT, DEVICE_SERVICE_HOST
+from monitoring.proto.kpi_sample_types_pb2 import KpiSampleType
 from monitoring.service import SqliteTools, InfluxTools
 from monitoring.service.MonitoringService import MonitoringService
 from monitoring.service.EventTools import EventsDeviceCollector
@@ -23,7 +24,7 @@ from context.client.ContextClient import ContextClient
 from context.service.grpc_server.ContextService import ContextService
 from context.service.Populate import populate
 from context.proto.context_pb2 import EventTypeEnum, DeviceEvent, Device
-from context.tests.example_objects import (DEVICE1, DEVICE1_UUID)
+from context.tests.Objects import (DEVICE_R1, DEVICE_R1_UUID)
 
 LOGGER = logging.getLogger(__name__)
 LOGGER.setLevel(logging.DEBUG)
@@ -37,12 +38,16 @@ LISTEN_ADDRESS = '[::]'
 GRPC_PORT_MONITORING = 7070
 
 GRPC_PORT_CONTEXT    = 10000 + grpc_port_context    # avoid privileged ports
+DEVICE_GRPC_SERVICE_PORT = 10000 + DEVICE_GRPC_SERVICE_PORT # avoid privileged ports
+MONITORING_GRPC_SERVICE_PORT = GRPC_PORT_MONITORING # avoid privileged ports
+
 
 SCENARIOS = [ # comment/uncomment scenarios to activate/deactivate them in the test unit
     ('all_inmemory', DatabaseBackendEnum.INMEMORY, {},           MessageBrokerBackendEnum.INMEMORY, {}          ),
 ]
 
 INFLUXDB_HOSTNAME = os.environ.get("INFLUXDB_HOSTNAME")
+INFLUXDB_PORT = os.environ.get("INFLUXDB_PORT")
 INFLUXDB_USER = os.environ.get("INFLUXDB_USER")
 INFLUXDB_PASSWORD = os.environ.get("INFLUXDB_PASSWORD")
 INFLUXDB_DATABASE = os.environ.get("INFLUXDB_DATABASE")
@@ -131,7 +136,7 @@ def sql_db():
 
 @pytest.fixture(scope='session')
 def influx_db():
-    influx_db = InfluxTools.Influx(INFLUXDB_HOSTNAME, "8086", INFLUXDB_USER, INFLUXDB_PASSWORD, INFLUXDB_DATABASE)
+    influx_db = InfluxTools.Influx(INFLUXDB_HOSTNAME, INFLUXDB_PORT, INFLUXDB_USER, INFLUXDB_PASSWORD, INFLUXDB_DATABASE)
     return influx_db
 
 @pytest.fixture(scope='session')
@@ -170,6 +175,16 @@ def include_kpi_request():
 
     return include_kpi_request
 
+@pytest.fixture(scope='session')
+def address():
+    address = '127.0.0.1'
+    return address
+
+@pytest.fixture(scope='session')
+def port():
+    port = 7070
+    return port
+
 ###########################
 # Tests Implementation
 ###########################
@@ -328,8 +343,8 @@ def test_events_tools(context_client_grpc: ContextClient,  # pylint: disable=red
     populate('localhost', GRPC_PORT_CONTEXT) # place this call in the appropriate line, according to your tests
 
     # ----- Update the object ------------------------------------------------------------------------------------------
-    response = context_client_grpc.SetDevice(Device(**DEVICE1))
-    assert response.device_uuid.uuid == DEVICE1_UUID
+    response = context_client_grpc.SetDevice(Device(**DEVICE_R1))
+    assert response.device_uuid.uuid == DEVICE_R1_UUID
 
     events_collector.stop()
 
@@ -364,7 +379,7 @@ def test_get_device_events(context_client_grpc: ContextClient,  # pylint: disabl
 
     assert isinstance(event, DeviceEvent)
     assert event.event.event_type == EventTypeEnum.EVENTTYPE_CREATE
-    assert event.device_id.device_uuid.uuid == DEVICE1_UUID
+    assert event.device_id.device_uuid.uuid == DEVICE_R1_UUID
 
     events_collector.stop()
 
@@ -397,3 +412,12 @@ def test_listen_events(monitoring_client: MonitoringClient,
 
     assert bool(kpi_id_list) == True
 
+def test_socket_ports(address, port):
+    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    result = s.connect_ex((address,port))
+
+    if result == 0:
+        print('socket is open')
+    else:
+        print('socket is not open')
+    s.close()
diff --git a/src/opticalattackmitigator/client/OpticalAttackMitigatorClient.py b/src/opticalattackmitigator/client/OpticalAttackMitigatorClient.py
index f303dcc3f..4c4a54249 100644
--- a/src/opticalattackmitigator/client/OpticalAttackMitigatorClient.py
+++ b/src/opticalattackmitigator/client/OpticalAttackMitigatorClient.py
@@ -6,6 +6,7 @@ from opticalattackmitigator.proto.optical_attack_mitigator_pb2_grpc import Attac
 LOGGER = logging.getLogger(__name__)
 MAX_RETRIES = 15
 DELAY_FUNCTION = delay_exponential(initial=0.01, increment=2.0, maximum=5.0)
+RETRY_DECORATOR = retry(max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
 
 class OpticalAttackMitigatorClient:
     def __init__(self, address, port):
@@ -25,7 +26,7 @@ class OpticalAttackMitigatorClient:
         self.channel = None
         self.stub = None
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def NotifyAttack(self, request : AttackDescription) -> AttackResponse:
         LOGGER.debug('NotifyAttack request: {:s}'.format(str(request)))
         response = self.stub.NotifyAttack(request)
diff --git a/src/opticalcentralizedattackdetector/client/OpticalCentralizedAttackDetectorClient.py b/src/opticalcentralizedattackdetector/client/OpticalCentralizedAttackDetectorClient.py
index c28507581..3dd214750 100644
--- a/src/opticalcentralizedattackdetector/client/OpticalCentralizedAttackDetectorClient.py
+++ b/src/opticalcentralizedattackdetector/client/OpticalCentralizedAttackDetectorClient.py
@@ -7,6 +7,7 @@ from opticalcentralizedattackdetector.proto.optical_centralized_attack_detector_
 LOGGER = logging.getLogger(__name__)
 MAX_RETRIES = 15
 DELAY_FUNCTION = delay_exponential(initial=0.01, increment=2.0, maximum=5.0)
+RETRY_DECORATOR = retry(max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
 
 class OpticalCentralizedAttackDetectorClient:
     def __init__(self, address, port):
@@ -26,28 +27,28 @@ class OpticalCentralizedAttackDetectorClient:
         self.channel = None
         self.stub = None
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def NotifyServiceUpdate(self, request : Service) -> Empty:
         LOGGER.debug('NotifyServiceUpdate request: {:s}'.format(str(request)))
         response = self.stub.NotifyServiceUpdate(request)
         LOGGER.debug('NotifyServiceUpdate result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def DetectAttack(self, request : Empty) -> Empty:
         LOGGER.debug('DetectAttack request: {:s}'.format(str(request)))
         response = self.stub.DetectAttack(request)
         LOGGER.debug('DetectAttack result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def ReportSummarizedKpi(self, request : KpiList) -> Empty:
         LOGGER.debug('ReportSummarizedKpi request: {:s}'.format(str(request)))
         response = self.stub.ReportSummarizedKpi(request)
         LOGGER.debug('ReportSummarizedKpi result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def ReportKpi(self, request : KpiList) -> Empty:
         LOGGER.debug('ReportKpi request: {:s}'.format(str(request)))
         response = self.stub.ReportKpi(request)
diff --git a/src/service/Dockerfile b/src/service/Dockerfile
index 3e8dcaa31..e49d39892 100644
--- a/src/service/Dockerfile
+++ b/src/service/Dockerfile
@@ -25,7 +25,7 @@ RUN mkdir -p /var/teraflow/service
 # Get Python packages per module
 COPY service/requirements.in service/requirements.in
 RUN pip-compile --output-file=service/requirements.txt service/requirements.in
-RUN python3 -m pip install -r service/requirements.in
+RUN python3 -m pip install -r service/requirements.txt
 
 # Add files into working directory
 COPY common/. common
diff --git a/src/service/client/ServiceClient.py b/src/service/client/ServiceClient.py
index b9d123b88..a303a89ca 100644
--- a/src/service/client/ServiceClient.py
+++ b/src/service/client/ServiceClient.py
@@ -1,11 +1,12 @@
 import grpc, logging
 from common.tools.client.RetryDecorator import retry, delay_exponential
-from service.proto.context_pb2 import ConnectionList, Empty, Service, ServiceId
+from service.proto.context_pb2 import Empty, Service, ServiceId
 from service.proto.service_pb2_grpc import ServiceServiceStub
 
 LOGGER = logging.getLogger(__name__)
 MAX_RETRIES = 15
 DELAY_FUNCTION = delay_exponential(initial=0.01, increment=2.0, maximum=5.0)
+RETRY_DECORATOR = retry(max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
 
 class ServiceClient:
     def __init__(self, address, port):
@@ -25,30 +26,23 @@ class ServiceClient:
         self.channel = None
         self.stub = None
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def CreateService(self, request : Service) -> ServiceId:
         LOGGER.debug('CreateService request: {:s}'.format(str(request)))
         response = self.stub.CreateService(request)
         LOGGER.debug('CreateService result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def UpdateService(self, request : Service) -> ServiceId:
         LOGGER.debug('UpdateService request: {:s}'.format(str(request)))
         response = self.stub.UpdateService(request)
         LOGGER.debug('UpdateService result: {:s}'.format(str(response)))
         return response
 
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
+    @RETRY_DECORATOR
     def DeleteService(self, request : ServiceId) -> Empty:
         LOGGER.debug('DeleteService request: {:s}'.format(str(request)))
         response = self.stub.DeleteService(request)
         LOGGER.debug('DeleteService result: {:s}'.format(str(response)))
         return response
-
-    @retry(exceptions=set(), max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
-    def GetConnectionList(self, request : ServiceId) -> ConnectionList:
-        LOGGER.debug('GetConnectionList request: {:s}'.format(str(request)))
-        response = self.stub.GetConnectionList(request)
-        LOGGER.debug('GetConnectionList result: {:s}'.format(str(response)))
-        return response
diff --git a/src/service/requirements.in b/src/service/requirements.in
index eb922871f..8f2241b47 100644
--- a/src/service/requirements.in
+++ b/src/service/requirements.in
@@ -1,18 +1,23 @@
-anytree
-apscheduler
-fastcache
-flask-restful
-grpcio-health-checking
-grpcio
-Jinja2
-netconf-client #1.7.3
-prometheus-client
-pytest
-pytest-benchmark
-python-json-logger
-pytz
-redis
-requests
-xmltodict
+anytree==2.8.0
+APScheduler==3.8.1
+fastcache==1.1.0
+Flask==2.0.2
+Flask-RESTful==0.3.9
+grpcio==1.43.0
+grpcio-health-checking==1.43.0
+Jinja2==3.0.3
+netconf-client==2.0.0 #1.7.3
+networkx==2.6.3
 p4runtime==1.3.0
-coverage
+paramiko==2.9.2
+prometheus-client==0.13.0
+protobuf==3.19.3
+pydot==1.4.2
+pytest==6.2.5
+pytest-benchmark==3.4.1
+python-json-logger==2.0.2
+pytz==2021.3
+redis==4.1.2
+requests==2.27.1
+xmltodict==0.12.0
+coverage==6.3
diff --git a/src/service/service/ServiceServiceServicerImpl.py b/src/service/service/ServiceServiceServicerImpl.py
index ca93c0980..0dbcd22af 100644
--- a/src/service/service/ServiceServiceServicerImpl.py
+++ b/src/service/service/ServiceServiceServicerImpl.py
@@ -1,35 +1,27 @@
+from typing import Dict, List
 import grpc, json, logging
-from typing import Any, List, Optional, Tuple
-from google.protobuf.json_format import MessageToDict
 from common.orm.Database import Database
 from common.orm.HighLevel import get_object
 from common.orm.backend.Tools import key_to_str
 from common.rpc_method_wrapper.Decorator import create_metrics, safe_and_metered_rpc_method
-from common.rpc_method_wrapper.ServiceExceptions import (
-    InvalidArgumentException, NotFoundException, OperationFailedException)
+from common.rpc_method_wrapper.ServiceExceptions import InvalidArgumentException, NotFoundException
+from common.tools.grpc.Tools import grpc_message_to_json, grpc_message_to_json_string
 from context.client.ContextClient import ContextClient
 from device.client.DeviceClient import DeviceClient
-from service.proto.context_pb2 import ConnectionList, Empty, Service, ServiceId
+from service.proto.context_pb2 import Empty, Service, ServiceId
 from service.proto.service_pb2_grpc import ServiceServiceServicer
-from .database.ConfigModel import ConfigModel, ConfigRuleModel
-from .database.ConstraintModel import ConstraintModel, ConstraintsModel
+from service.service.database.DeviceModel import DeviceModel
 from .database.DatabaseServiceTools import (
-    delete_service_from_context, sync_service_from_context, sync_service_to_context, update_service_in_local_database)
-from .database.RelationModels import ServiceEndPointModel
+    sync_service_from_context, sync_service_to_context, update_service_in_local_database)
 from .database.ServiceModel import ServiceModel
-from .service_handler_api._ServiceHandler import _ServiceHandler
+from .path_computation_element.PathComputationElement import PathComputationElement, dump_connectivity
 from .service_handler_api.ServiceHandlerFactory import ServiceHandlerFactory
-from .service_handler_api.Tools import (
-    check_errors_deleteconfig, check_errors_deleteconstraint, check_errors_deleteendpoint, check_errors_setconfig,
-    check_errors_setconstraint, check_errors_setendpoint)
-from .Tools import (
-    classify_config_rules, classify_constraints, classify_endpointids, get_service_handler_class,
-    sync_devices_from_context)
+from .Tools import delete_service, sync_devices_from_context, update_service
 
 LOGGER = logging.getLogger(__name__)
 
 SERVICE_NAME = 'Service'
-METHOD_NAMES = ['CreateService', 'UpdateService', 'DeleteService',  'GetConnectionList']
+METHOD_NAMES = ['CreateService', 'UpdateService', 'DeleteService']
 METRICS = create_metrics(SERVICE_NAME, METHOD_NAMES)
 
 class ServiceServiceServicerImpl(ServiceServiceServicer):
@@ -53,9 +45,7 @@ class ServiceServiceServicerImpl(ServiceServiceServicer):
         if len(request.service_endpoint_ids) > 0:
             unexpected_endpoints = []
             for service_endpoint_id in request.service_endpoint_ids:
-                unexpected_endpoints.append(MessageToDict(
-                    service_endpoint_id, including_default_value_fields=True, preserving_proto_field_name=True,
-                    use_integers_for_enums=True))
+                unexpected_endpoints.append(grpc_message_to_json(service_endpoint_id))
             str_unexpected_endpoints = json.dumps(unexpected_endpoints, sort_keys=True)
             raise InvalidArgumentException(
                 'service.service_endpoint_ids', str_unexpected_endpoints,
@@ -65,9 +55,7 @@ class ServiceServiceServicerImpl(ServiceServiceServicer):
         if len(request.service_constraints) > 0:
             unexpected_constraints = []
             for service_constraint in request.service_constraints:
-                unexpected_constraints.append(MessageToDict(
-                    service_constraint, including_default_value_fields=True, preserving_proto_field_name=True,
-                    use_integers_for_enums=True))
+                unexpected_constraints.append(grpc_message_to_json(service_constraint))
             str_unexpected_constraints = json.dumps(unexpected_constraints, sort_keys=True)
             raise InvalidArgumentException(
                 'service.service_constraints', str_unexpected_constraints,
@@ -75,9 +63,7 @@ class ServiceServiceServicerImpl(ServiceServiceServicer):
                               'Constraints should be configured after creating the service.')
 
         if len(request.service_config.config_rules) > 0:
-            unexpected_config_rules = MessageToDict(
-                request.service_config, including_default_value_fields=True,
-                preserving_proto_field_name=True, use_integers_for_enums=True)
+            unexpected_config_rules = grpc_message_to_json(request.service_config)
             unexpected_config_rules = unexpected_config_rules['config_rules']
             str_unexpected_config_rules = json.dumps(unexpected_config_rules, sort_keys=True)
             raise InvalidArgumentException(
@@ -96,110 +82,85 @@ class ServiceServiceServicerImpl(ServiceServiceServicer):
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def UpdateService(self, request : Service, context : grpc.ServicerContext) -> ServiceId:
+        LOGGER.info('[UpdateService] begin ; request = {:s}'.format(grpc_message_to_json_string(request)))
+
         service_id = request.service_id
         service_uuid = service_id.service_uuid.uuid
         service_context_uuid = service_id.context_id.context_uuid.uuid
-        str_service_key = key_to_str([service_context_uuid, service_uuid])
 
-        # Sync before updating service to ensure we have devices, endpoints, constraints, and config rules to be
-        # set/deleted before actuallymodifying them in the local in-memory database.
+        pce = PathComputationElement()
+        pce.load_topology(self.context_client)
+        pce.load_connectivity(self.context_client, service_id)
+        #pce.dump_topology_to_file('../data/topo.dot')
+        #pce.dump_connectivity_to_file('../data/conn-before.txt')
+        connectivity = pce.route_service(request)
+        #pce.dump_connectivity_to_file('../data/conn-after.txt')
+
+        LOGGER.info('[UpdateService] connectivity = {:s}'.format(str(dump_connectivity(connectivity))))
+
+        if connectivity is None:
+            # just update local database and context
+            str_service_key = key_to_str([service_context_uuid, service_uuid])
+            db_service = get_object(self.database, ServiceModel, str_service_key, raise_if_not_found=False)
+            LOGGER.info('[UpdateService] before db_service = {:s}'.format(str(db_service.dump(
+                include_endpoint_ids=True, include_constraints=True, include_config_rules=True))))
+            db_devices : Dict[str, DeviceModel] = sync_devices_from_context(
+                self.context_client, self.database, db_service, request.service_endpoint_ids)
+            LOGGER.info('[UpdateService] db_devices[{:d}] = {:s}'.format(
+                len(db_devices), str({
+                    device_uuid:db_device.dump(include_config_rules=True, include_drivers=True, include_endpoints=True)
+                    for device_uuid,db_device in db_devices.items()
+                })))
+            sync_service_from_context(service_context_uuid, service_uuid, self.context_client, self.database)
+            db_service,_ = update_service_in_local_database(self.database, request)
+            LOGGER.info('[UpdateService] after db_service = {:s}'.format(str(db_service.dump(
+                include_endpoint_ids=True, include_constraints=True, include_config_rules=True))))
+            sync_service_to_context(db_service, self.context_client)
+        else:
+            for sub_service, sub_connections in connectivity.get('requirements', []):
+                for sub_connection in sub_connections:
+                    update_service(
+                        self.database, self.context_client, self.device_client, self.service_handler_factory,
+                        sub_service, sub_connection)
+
+            for connection in connectivity.get('connections'):
+                db_service = update_service(
+                    self.database, self.context_client, self.device_client, self.service_handler_factory,
+                    request, connection)
+
+            str_service_key = key_to_str([service_context_uuid, service_uuid])
+            db_service = get_object(self.database, ServiceModel, str_service_key, raise_if_not_found=False)
+            if db_service is None: raise NotFoundException('Service', str_service_key)
 
-        sync_service_from_context(service_context_uuid, service_uuid, self.context_client, self.database)
-        db_service = get_object(self.database, ServiceModel, str_service_key, raise_if_not_found=False)
-        if db_service is None: raise NotFoundException('Service', str_service_key)
         LOGGER.info('[UpdateService] db_service = {:s}'.format(str(db_service.dump(
             include_endpoint_ids=True, include_constraints=True, include_config_rules=True))))
 
-        db_devices = sync_devices_from_context(self.context_client, db_service, request.service_endpoint_ids)
-
-        resources_to_set    : List[Tuple[str, Any]] = [] # resource_key, resource_value
-        resources_to_delete : List[Tuple[str, Any]] = [] # resource_key, resource_value
-        classify_config_rules(db_service, request.service_config.config_rules, resources_to_set, resources_to_delete)
-
-        constraints_to_set    : List[Tuple[str, str]] = [] # constraint_type, constraint_value
-        constraints_to_delete : List[Tuple[str, str]] = [] # constraint_type, constraint_value
-        classify_constraints(db_service, request.service_constraints, constraints_to_set, constraints_to_delete)
-
-        endpointids_to_set    : List[Tuple[str, str, Optional[str]]] = [] # device_uuid, endpoint_uuid, topology_uuid
-        endpointids_to_delete : List[Tuple[str, str, Optional[str]]] = [] # device_uuid, endpoint_uuid, topology_uuid
-        classify_endpointids(db_service, request.service_endpoint_ids, endpointids_to_set, endpointids_to_delete)
-
-        service_handler_class = get_service_handler_class(self.service_handler_factory, db_service, db_devices)
-        service_handler_settings = {}
-        service_handler : _ServiceHandler = service_handler_class(
-            db_service, self.database, self.context_client, self.device_client, **service_handler_settings)
-
-        errors = []
-
-        if len(errors) == 0:
-            results_deleteendpoint = service_handler.DeleteEndpoint(endpointids_to_delete)
-            errors.extend(check_errors_deleteendpoint(endpointids_to_delete, results_deleteendpoint))
-
-        if len(errors) == 0:
-            results_deleteconstraint = service_handler.DeleteConstraint(constraints_to_delete)
-            errors.extend(check_errors_deleteconstraint(constraints_to_delete, results_deleteconstraint))
-
-        if len(errors) == 0:
-            results_deleteconfig = service_handler.DeleteConfig(resources_to_delete)
-            errors.extend(check_errors_deleteconfig(resources_to_delete, results_deleteconfig))
-
-        if len(errors) == 0:
-            results_setconfig = service_handler.SetConfig(resources_to_set)
-            errors.extend(check_errors_setconfig(resources_to_set, results_setconfig))
-
-        if len(errors) == 0:
-            results_setconstraint = service_handler.SetConstraint(constraints_to_set)
-            errors.extend(check_errors_setconstraint(constraints_to_set, results_setconstraint))
-
-        if len(errors) == 0:
-            results_setendpoint = service_handler.SetEndpoint(endpointids_to_set)
-            errors.extend(check_errors_setendpoint(endpointids_to_set, results_setendpoint))
-
-        if len(errors) > 0:
-            raise OperationFailedException('UpdateService', extra_details=errors)
-
-        db_service,_ = update_service_in_local_database(self.database, request)
-        LOGGER.info('[UpdateService] db_service = {:s}'.format(str(db_service.dump(
-            include_endpoint_ids=True, include_constraints=True, include_config_rules=True))))
-
-        #db_entries = self.database.dump()
-        #LOGGER.info('----- Database Dump [{:3d} entries] -------------------------'.format(len(db_entries)))
-        #for db_entry in db_entries:
-        #    LOGGER.info('  [{:>4s}] {:40s} :: {:s}'.format(*db_entry)) # pragma: no cover
-        #LOGGER.info('-----------------------------------------------------------')
-
-        sync_service_to_context(db_service, self.context_client)
         return ServiceId(**db_service.dump_id())
 
     @safe_and_metered_rpc_method(METRICS, LOGGER)
     def DeleteService(self, request : ServiceId, context : grpc.ServicerContext) -> Empty:
-        service_uuid = request.service_uuid.uuid
-        service_context_uuid = request.context_id.context_uuid.uuid
-
-        sync_service_from_context(service_context_uuid, service_uuid, self.context_client, self.database)
-        str_service_key = key_to_str([service_context_uuid, service_uuid])
-        db_service : ServiceModel = get_object(self.database, ServiceModel, str_service_key, raise_if_not_found=False)
-        if db_service is None: return Empty()
-
-        delete_service_from_context(db_service, self.context_client)
-
-        for db_service_endpoint_pk,_ in db_service.references(ServiceEndPointModel):
-            ServiceEndPointModel(self.database, db_service_endpoint_pk).delete()
-
-        db_running_config = ConfigModel(self.database, db_service.service_config_fk)
-        for db_config_rule_pk,_ in db_running_config.references(ConfigRuleModel):
-            ConfigRuleModel(self.database, db_config_rule_pk).delete()
+        LOGGER.info('[DeleteService] begin ; request = {:s}'.format(grpc_message_to_json_string(request)))
+
+        pce = PathComputationElement()
+        pce.load_topology(self.context_client)
+        pce.load_connectivity(self.context_client, request)
+        #pce.dump_topology_to_file('../data/topo.dot')
+        #pce.dump_connectivity_to_file('../data/conn-before.txt')
+        connectivity = pce.get_connectivity_from_service_id(request)
+        if connectivity is None: return Empty()
+        #pce.dump_connectivity_to_file('../data/conn-after.txt')
+
+        LOGGER.info('[DeleteService] connectivity = {:s}'.format(str(dump_connectivity(connectivity))))
+
+        for connection in connectivity.get('connections'):
+            delete_service(
+                self.database, self.context_client, self.device_client, self.service_handler_factory,
+                request, connection)
+
+        for sub_service, sub_connections in connectivity.get('requirements', []):
+            for sub_connection in sub_connections:
+                delete_service(
+                    self.database, self.context_client, self.device_client, self.service_handler_factory,
+                    sub_service.service_id, sub_connection)
 
-        db_running_constraints = ConstraintsModel(self.database, db_service.service_constraints_fk)
-        for db_constraint_pk,_ in db_running_constraints.references(ConstraintModel):
-            ConstraintModel(self.database, db_constraint_pk).delete()
-
-        db_service.delete()
-        db_running_config.delete()
-        db_running_constraints.delete()
         return Empty()
-
-    @safe_and_metered_rpc_method(METRICS, LOGGER)
-    def GetConnectionList(self, request : ServiceId, context : grpc.ServicerContext) -> ConnectionList:
-        #raise ServiceException(grpc.StatusCode.UNIMPLEMENTED, 'RPC GetConnectionList() not implemented')
-        return ConnectionList()
diff --git a/src/service/service/Tools.py b/src/service/service/Tools.py
index 80084f363..3cae8412f 100644
--- a/src/service/service/Tools.py
+++ b/src/service/service/Tools.py
@@ -1,33 +1,43 @@
 import logging
 from typing import Any, Dict, List, Optional, Tuple
+from common.orm.Database import Database
 from common.orm.HighLevel import get_object, get_related_objects
-from common.rpc_method_wrapper.ServiceExceptions import NotFoundException
+from common.orm.backend.Tools import key_to_str
+from common.rpc_method_wrapper.ServiceExceptions import (
+    InvalidArgumentException, NotFoundException, OperationFailedException)
 from context.client.ContextClient import ContextClient
-from service.proto.context_pb2 import ConfigRule, Constraint, EndPointId
-from service.service.database.ConstraintModel import get_constraints, grpc_constraints_to_raw
-from service.service.database.DatabaseDeviceTools import sync_device_from_context
-from service.service.database.EndPointModel import EndPointModel, grpc_endpointids_to_raw
-from .database.ConfigModel import ORM_ConfigActionEnum, get_config_rules, grpc_config_rules_to_raw
+from context.proto.context_pb2 import ConfigRule, Connection, Constraint, EndPointId, Service, ServiceId, ServiceStatusEnum
+from device.client.DeviceClient import DeviceClient
+from .database.ConfigModel import (
+    ConfigModel, ConfigRuleModel, ORM_ConfigActionEnum, get_config_rules, grpc_config_rules_to_raw)
+from .database.ConstraintModel import ConstraintModel, ConstraintsModel, get_constraints, grpc_constraints_to_raw
+from .database.DatabaseDeviceTools import sync_device_from_context
+from .database.DatabaseServiceTools import (
+    delete_service_from_context, sync_service_from_context, sync_service_to_context, update_service_in_local_database)
 from .database.DeviceModel import DeviceModel, DriverModel
+from .database.EndPointModel import EndPointModel, grpc_endpointids_to_raw
 from .database.RelationModels import ServiceEndPointModel
 from .database.ServiceModel import ServiceModel
 from .service_handler_api._ServiceHandler import _ServiceHandler
 from .service_handler_api.FilterFields import FilterFieldEnum
 from .service_handler_api.ServiceHandlerFactory import ServiceHandlerFactory
+from .service_handler_api.Tools import (
+    check_errors_deleteconfig, check_errors_deleteconstraint, check_errors_deleteendpoint, check_errors_setconfig,
+    check_errors_setconstraint, check_errors_setendpoint)
 
 LOGGER = logging.getLogger(__name__)
 
 def sync_devices_from_context(
-    context_client : ContextClient, db_service : ServiceModel, service_endpoint_ids : List[EndPointId]
+        context_client : ContextClient, database : Database, db_service : Optional[ServiceModel],
+        service_endpoint_ids : List[EndPointId]
     ) -> Dict[str, DeviceModel]:
 
-    database = db_service.database
-
     required_device_uuids = set()
-    db_endpoints = get_related_objects(db_service, ServiceEndPointModel, 'endpoint_fk')
-    for db_endpoint in db_endpoints:
-        db_device = DeviceModel(database, db_endpoint.device_fk)
-        required_device_uuids.add(db_device.device_uuid)
+    if db_service is not None:
+        db_endpoints = get_related_objects(db_service, ServiceEndPointModel, 'endpoint_fk')
+        for db_endpoint in db_endpoints:
+            db_device = get_object(database, DeviceModel, db_endpoint.device_fk, raise_if_not_found=False)
+            required_device_uuids.add(db_device.device_uuid)
 
     for endpoint_id in service_endpoint_ids:
         required_device_uuids.add(endpoint_id.device_id.device_uuid.uuid)
@@ -67,6 +77,8 @@ def classify_config_rules(
         elif action == ORM_ConfigActionEnum.DELETE:
             if key in context_config_rules:
                 resources_to_delete.append((key, value))
+        else:
+            raise InvalidArgumentException('config_rule.action', str(action), extra_details=str(request_config_rules))
 
     #LOGGER.info('[classify_config_rules] resources_to_set = {:s}'.format(str(resources_to_set)))
     #LOGGER.info('[classify_config_rules] resources_to_delete = {:s}'.format(str(resources_to_delete)))
@@ -119,13 +131,15 @@ def classify_endpointids(
     request_endpoint_ids = grpc_endpointids_to_raw(service_endpoint_ids)
     #LOGGER.info('[classify_endpointids] request_endpoint_ids = {:s}'.format(str(request_endpoint_ids)))
 
+    if len(service_endpoint_ids) != 2: return
     for endpoint_id in request_endpoint_ids:
-        if endpoint_id not in context_endpoint_ids:
-            endpointids_to_set.append(endpoint_id)
-        context_endpoint_ids.discard(endpoint_id)
+        #if endpoint_id not in context_endpoint_ids:
+        #    endpointids_to_set.append(endpoint_id)
+        #context_endpoint_ids.discard(endpoint_id)
+        endpointids_to_set.append(endpoint_id)
 
-    for endpoint_id in context_endpoint_ids:
-        endpointids_to_delete.append(endpoint_id)
+    #for endpoint_id in context_endpoint_ids:
+    #    endpointids_to_delete.append(endpoint_id)
 
     #LOGGER.info('[classify_endpointids] endpointids_to_set = {:s}'.format(str(endpointids_to_set)))
     #LOGGER.info('[classify_endpointids] endpointids_to_delete = {:s}'.format(str(endpointids_to_delete)))
@@ -158,3 +172,156 @@ def get_service_handler_class(
     msg = 'ServiceHandler({:s}) selected for service({:s}) with filter_fields({:s})...'
     LOGGER.info(msg.format(str(service_handler_class.__name__), str(str_service_key), str(filter_fields)))
     return service_handler_class
+
+def update_service(
+        database : Database, context_client : ContextClient, device_client : DeviceClient,
+        service_handler_factory : ServiceHandlerFactory, service : Service, connection : Connection
+    ) -> ServiceModel:
+
+    service_id = service.service_id
+    service_uuid = service_id.service_uuid.uuid
+    service_context_uuid = service_id.context_id.context_uuid.uuid
+    str_service_key = key_to_str([service_context_uuid, service_uuid])
+
+    # Sync before updating service to ensure we have devices, endpoints, constraints, and config rules to be
+    # set/deleted before actuallymodifying them in the local in-memory database.
+
+    sync_service_from_context(service_context_uuid, service_uuid, context_client, database)
+    db_service = get_object(database, ServiceModel, str_service_key, raise_if_not_found=False)
+    db_devices = sync_devices_from_context(context_client, database, db_service, service.service_endpoint_ids)
+
+    if db_service is None: db_service,_ = update_service_in_local_database(database, service)
+    LOGGER.info('[update_service] db_service = {:s}'.format(str(db_service.dump(
+        include_endpoint_ids=True, include_constraints=True, include_config_rules=True))))
+
+    resources_to_set    : List[Tuple[str, Any]] = [] # resource_key, resource_value
+    resources_to_delete : List[Tuple[str, Any]] = [] # resource_key, resource_value
+    classify_config_rules(db_service, service.service_config.config_rules, resources_to_set, resources_to_delete)
+
+    constraints_to_set    : List[Tuple[str, str]] = [] # constraint_type, constraint_value
+    constraints_to_delete : List[Tuple[str, str]] = [] # constraint_type, constraint_value
+    classify_constraints(db_service, service.service_constraints, constraints_to_set, constraints_to_delete)
+
+    endpointids_to_set    : List[Tuple[str, str, Optional[str]]] = [] # device_uuid, endpoint_uuid, topology_uuid
+    endpointids_to_delete : List[Tuple[str, str, Optional[str]]] = [] # device_uuid, endpoint_uuid, topology_uuid
+    classify_endpointids(db_service, service.service_endpoint_ids, endpointids_to_set, endpointids_to_delete)
+
+    service_handler_class = get_service_handler_class(service_handler_factory, db_service, db_devices)
+    service_handler_settings = {}
+    service_handler : _ServiceHandler = service_handler_class(
+        db_service, database, context_client, device_client, **service_handler_settings)
+
+    errors = []
+
+    if len(errors) == 0:
+        results_deleteendpoint = service_handler.DeleteEndpoint(endpointids_to_delete)
+        errors.extend(check_errors_deleteendpoint(endpointids_to_delete, results_deleteendpoint))
+
+    if len(errors) == 0:
+        results_deleteconstraint = service_handler.DeleteConstraint(constraints_to_delete)
+        errors.extend(check_errors_deleteconstraint(constraints_to_delete, results_deleteconstraint))
+
+    if len(errors) == 0:
+        results_deleteconfig = service_handler.DeleteConfig(resources_to_delete)
+        errors.extend(check_errors_deleteconfig(resources_to_delete, results_deleteconfig))
+
+    if len(errors) == 0:
+        results_setconfig = service_handler.SetConfig(resources_to_set)
+        errors.extend(check_errors_setconfig(resources_to_set, results_setconfig))
+
+    if len(errors) == 0:
+        results_setconstraint = service_handler.SetConstraint(constraints_to_set)
+        errors.extend(check_errors_setconstraint(constraints_to_set, results_setconstraint))
+
+    if len(errors) == 0:
+        results_setendpoint = service_handler.SetEndpoint(endpointids_to_set)
+        errors.extend(check_errors_setendpoint(endpointids_to_set, results_setendpoint))
+
+    if len(errors) > 0:
+        raise OperationFailedException('UpdateService', extra_details=errors)
+
+    LOGGER.info('[update_service] len(service.service_endpoint_ids) = {:d}'.format(len(service.service_endpoint_ids)))
+    if len(service.service_endpoint_ids) >= 2:
+        service.service_status.service_status = ServiceStatusEnum.SERVICESTATUS_ACTIVE
+
+    db_service,_ = update_service_in_local_database(database, service)
+    LOGGER.info('[update_service] db_service = {:s}'.format(str(db_service.dump(
+        include_endpoint_ids=True, include_constraints=True, include_config_rules=True))))
+
+    sync_service_to_context(db_service, context_client)
+    context_client.SetConnection(connection)
+    return db_service
+
+def delete_service(
+        database : Database, context_client : ContextClient, device_client : DeviceClient,
+        service_handler_factory : ServiceHandlerFactory, service_id : ServiceId, connection : Connection
+    ) -> None:
+
+    context_client.RemoveConnection(connection.connection_id)
+
+    service_uuid = service_id.service_uuid.uuid
+    service_context_uuid = service_id.context_id.context_uuid.uuid
+    str_service_key = key_to_str([service_context_uuid, service_uuid])
+
+    # Sync before updating service to ensure we have devices, endpoints, constraints, and config rules to be
+    # set/deleted before actuallymodifying them in the local in-memory database.
+
+    sync_service_from_context(service_context_uuid, service_uuid, context_client, database)
+    db_service : ServiceModel = get_object(database, ServiceModel, str_service_key, raise_if_not_found=False)
+    if db_service is None: return
+    LOGGER.info('[delete_service] db_service = {:s}'.format(str(db_service.dump(
+        include_endpoint_ids=True, include_constraints=True, include_config_rules=True))))
+
+    db_devices = sync_devices_from_context(context_client, database, db_service, [])
+
+    resources_to_delete : List[Tuple[str, str]] = [     # resource_key, resource_value
+        (config_rule[1], config_rule[2])
+        for config_rule in get_config_rules(db_service.database, db_service.pk, 'running')
+    ]
+
+    constraints_to_delete : List[Tuple[str, str]] = [   # constraint_type, constraint_value
+        (constraint[0], constraint[1])
+        for constraint in get_constraints(db_service.database, db_service.pk, 'running')
+    ]
+
+    # device_uuid, endpoint_uuid, topology_uuid
+    endpointids_to_delete : List[Tuple[str, str, Optional[str]]] = list(set(get_service_endpointids(db_service)))
+
+    service_handler_class = get_service_handler_class(service_handler_factory, db_service, db_devices)
+    service_handler_settings = {}
+    service_handler : _ServiceHandler = service_handler_class(
+        db_service, database, context_client, device_client, **service_handler_settings)
+
+    errors = []
+
+    if len(errors) == 0:
+        results_deleteendpoint = service_handler.DeleteEndpoint(endpointids_to_delete)
+        errors.extend(check_errors_deleteendpoint(endpointids_to_delete, results_deleteendpoint))
+
+    if len(errors) == 0:
+        results_deleteconstraint = service_handler.DeleteConstraint(constraints_to_delete)
+        errors.extend(check_errors_deleteconstraint(constraints_to_delete, results_deleteconstraint))
+
+    if len(errors) == 0:
+        results_deleteconfig = service_handler.DeleteConfig(resources_to_delete)
+        errors.extend(check_errors_deleteconfig(resources_to_delete, results_deleteconfig))
+
+    if len(errors) > 0:
+        raise OperationFailedException('DeleteService', extra_details=errors)
+
+    delete_service_from_context(db_service, context_client)
+
+    for db_service_endpoint_pk,_ in db_service.references(ServiceEndPointModel):
+        ServiceEndPointModel(database, db_service_endpoint_pk).delete()
+
+    db_running_config = ConfigModel(database, db_service.service_config_fk)
+    for db_config_rule_pk,_ in db_running_config.references(ConfigRuleModel):
+        ConfigRuleModel(database, db_config_rule_pk).delete()
+
+    db_running_constraints = ConstraintsModel(database, db_service.service_constraints_fk)
+    for db_constraint_pk,_ in db_running_constraints.references(ConstraintModel):
+        ConstraintModel(database, db_constraint_pk).delete()
+
+    db_service.delete()
+    db_running_config.delete()
+    db_running_constraints.delete()
diff --git a/src/service/service/__main__.py b/src/service/service/__main__.py
index d6a0e9fd3..7727f2478 100644
--- a/src/service/service/__main__.py
+++ b/src/service/service/__main__.py
@@ -1,6 +1,6 @@
 import logging, signal, sys, threading
 from prometheus_client import start_http_server
-from common.Settings import get_setting
+from common.Settings import get_setting, wait_for_environment_variables
 from context.client.ContextClient import ContextClient
 from device.client.DeviceClient import DeviceClient
 from service.Config import (
@@ -11,7 +11,7 @@ from .service_handler_api.ServiceHandlerFactory import ServiceHandlerFactory
 from .service_handlers import SERVICE_HANDLERS
 
 terminate = threading.Event()
-LOGGER = None
+LOGGER : logging.Logger = None
 
 def signal_handler(signal, frame): # pylint: disable=redefined-outer-name
     LOGGER.warning('Terminate signal received')
@@ -25,14 +25,20 @@ def main():
     grace_period         = get_setting('GRACE_PERIOD',                     default=GRPC_GRACE_PERIOD   )
     log_level            = get_setting('LOG_LEVEL',                        default=LOG_LEVEL           )
     metrics_port         = get_setting('METRICS_PORT',                     default=METRICS_PORT        )
+
+    logging.basicConfig(level=log_level)
+    LOGGER = logging.getLogger(__name__)
+
+    wait_for_environment_variables([
+        'CONTEXTSERVICE_SERVICE_HOST', 'CONTEXTSERVICE_SERVICE_PORT_GRPC',
+        'DEVICESERVICE_SERVICE_HOST', 'DEVICESERVICE_SERVICE_PORT_GRPC'
+    ])
+
     context_service_host = get_setting('CONTEXTSERVICE_SERVICE_HOST',      default=CONTEXT_SERVICE_HOST)
     context_service_port = get_setting('CONTEXTSERVICE_SERVICE_PORT_GRPC', default=CONTEXT_SERVICE_PORT)
     device_service_host  = get_setting('DEVICESERVICE_SERVICE_HOST',       default=DEVICE_SERVICE_HOST )
     device_service_port  = get_setting('DEVICESERVICE_SERVICE_PORT_GRPC',  default=DEVICE_SERVICE_PORT )
 
-    logging.basicConfig(level=log_level)
-    LOGGER = logging.getLogger(__name__)
-
     signal.signal(signal.SIGINT,  signal_handler)
     signal.signal(signal.SIGTERM, signal_handler)
 
diff --git a/src/service/service/database/DatabaseServiceTools.py b/src/service/service/database/DatabaseServiceTools.py
index 0b538f82a..0aaaadb9a 100644
--- a/src/service/service/database/DatabaseServiceTools.py
+++ b/src/service/service/database/DatabaseServiceTools.py
@@ -59,7 +59,8 @@ def update_service_in_local_database(database : Database, service : Service) ->
     if len(topology_uuid) > 0:
         str_topology_key = key_to_str([service_context_uuid, topology_uuid])
         result : Tuple[TopologyModel, bool] = get_or_create_object(
-            database, TopologyModel, str_topology_key, defaults={'context_fk': db_context, 'topology_uuid': topology_uuid})
+            database, TopologyModel, str_topology_key, defaults={
+                'context_fk': db_context, 'topology_uuid': topology_uuid})
         #db_topology, _ = result
 
     str_service_key = key_to_str([service_context_uuid, service_uuid])
diff --git a/src/service/service/database/LinkModel.py b/src/service/service/database/LinkModel.py
new file mode 100644
index 000000000..48d67bfa6
--- /dev/null
+++ b/src/service/service/database/LinkModel.py
@@ -0,0 +1,26 @@
+import logging, operator
+from typing import Dict, List
+from common.orm.fields.PrimaryKeyField import PrimaryKeyField
+from common.orm.fields.StringField import StringField
+from common.orm.model.Model import Model
+from common.orm.HighLevel import get_related_objects
+
+LOGGER = logging.getLogger(__name__)
+
+class LinkModel(Model):
+    pk = PrimaryKeyField()
+    link_uuid = StringField(required=True, allow_empty=False)
+
+    def dump_id(self) -> Dict:
+        return {'link_uuid': {'uuid': self.link_uuid}}
+
+    def dump_endpoint_ids(self) -> List[Dict]:
+        from .RelationModels import LinkEndPointModel # pylint: disable=import-outside-toplevel
+        db_endpoints = get_related_objects(self, LinkEndPointModel, 'endpoint_fk')
+        return [db_endpoint.dump_id() for db_endpoint in sorted(db_endpoints, key=operator.attrgetter('pk'))]
+
+    def dump(self) -> Dict:
+        return {
+            'link_id': self.dump_id(),
+            'link_endpoint_ids': self.dump_endpoint_ids(),
+        }
diff --git a/src/service/service/database/RelationModels.py b/src/service/service/database/RelationModels.py
index fbf93feff..4531e0594 100644
--- a/src/service/service/database/RelationModels.py
+++ b/src/service/service/database/RelationModels.py
@@ -4,16 +4,16 @@ from common.orm.fields.PrimaryKeyField import PrimaryKeyField
 from common.orm.model.Model import Model
 from .DeviceModel import DeviceModel
 from .EndPointModel import EndPointModel
-#from .LinkModel import LinkModel
+from .LinkModel import LinkModel
 from .ServiceModel import ServiceModel
 from .TopologyModel import TopologyModel
 
 LOGGER = logging.getLogger(__name__)
 
-#class LinkEndPointModel(Model): # pylint: disable=abstract-method
-#    pk = PrimaryKeyField()
-#    link_fk = ForeignKeyField(LinkModel)
-#    endpoint_fk = ForeignKeyField(EndPointModel)
+class LinkEndPointModel(Model): # pylint: disable=abstract-method
+    pk = PrimaryKeyField()
+    link_fk = ForeignKeyField(LinkModel)
+    endpoint_fk = ForeignKeyField(EndPointModel)
 
 class ServiceEndPointModel(Model): # pylint: disable=abstract-method
     pk = PrimaryKeyField()
@@ -25,7 +25,7 @@ class TopologyDeviceModel(Model): # pylint: disable=abstract-method
     topology_fk = ForeignKeyField(TopologyModel)
     device_fk = ForeignKeyField(DeviceModel)
 
-#class TopologyLinkModel(Model): # pylint: disable=abstract-method
-#    pk = PrimaryKeyField()
-#    topology_fk = ForeignKeyField(TopologyModel)
-#    link_fk = ForeignKeyField(LinkModel)
+class TopologyLinkModel(Model): # pylint: disable=abstract-method
+    pk = PrimaryKeyField()
+    topology_fk = ForeignKeyField(TopologyModel)
+    link_fk = ForeignKeyField(LinkModel)
diff --git a/src/service/service/database/TopologyModel.py b/src/service/service/database/TopologyModel.py
index 54a7e75e5..fc1f2d241 100644
--- a/src/service/service/database/TopologyModel.py
+++ b/src/service/service/database/TopologyModel.py
@@ -1,10 +1,10 @@
-import logging #, operator
-#from typing import Dict, List
+import logging, operator
+from typing import Dict, List
 from common.orm.fields.ForeignKeyField import ForeignKeyField
 from common.orm.fields.PrimaryKeyField import PrimaryKeyField
 from common.orm.fields.StringField import StringField
 from common.orm.model.Model import Model
-#from common.orm.HighLevel import get_related_objects
+from common.orm.HighLevel import get_related_objects
 from .ContextModel import ContextModel
 
 LOGGER = logging.getLogger(__name__)
@@ -14,27 +14,27 @@ class TopologyModel(Model):
     context_fk = ForeignKeyField(ContextModel)
     topology_uuid = StringField(required=True, allow_empty=False)
 
-#    def dump_id(self) -> Dict:
-#        context_id = ContextModel(self.database, self.context_fk).dump_id()
-#        return {
-#            'context_id': context_id,
-#            'topology_uuid': {'uuid': self.topology_uuid},
-#        }
-#
-#    def dump_device_ids(self) -> List[Dict]:
-#        from .RelationModels import TopologyDeviceModel # pylint: disable=import-outside-toplevel
-#        db_devices = get_related_objects(self, TopologyDeviceModel, 'device_fk')
-#        return [db_device.dump_id() for db_device in sorted(db_devices, key=operator.attrgetter('pk'))]
-#
-#    def dump_link_ids(self) -> List[Dict]:
-#        from .RelationModels import TopologyLinkModel # pylint: disable=import-outside-toplevel
-#        db_links = get_related_objects(self, TopologyLinkModel, 'link_fk')
-#        return [db_link.dump_id() for db_link in sorted(db_links, key=operator.attrgetter('pk'))]
-#
-#    def dump(   # pylint: disable=arguments-differ
-#            self, include_devices=True, include_links=True
-#        ) -> Dict:
-#        result = {'topology_id': self.dump_id()}
-#        if include_devices: result['device_ids'] = self.dump_device_ids()
-#        if include_links: result['link_ids'] = self.dump_link_ids()
-#        return result
+    def dump_id(self) -> Dict:
+        context_id = ContextModel(self.database, self.context_fk).dump_id()
+        return {
+            'context_id': context_id,
+            'topology_uuid': {'uuid': self.topology_uuid},
+        }
+
+    def dump_device_ids(self) -> List[Dict]:
+        from .RelationModels import TopologyDeviceModel # pylint: disable=import-outside-toplevel
+        db_devices = get_related_objects(self, TopologyDeviceModel, 'device_fk')
+        return [db_device.dump_id() for db_device in sorted(db_devices, key=operator.attrgetter('pk'))]
+
+    def dump_link_ids(self) -> List[Dict]:
+        from .RelationModels import TopologyLinkModel # pylint: disable=import-outside-toplevel
+        db_links = get_related_objects(self, TopologyLinkModel, 'link_fk')
+        return [db_link.dump_id() for db_link in sorted(db_links, key=operator.attrgetter('pk'))]
+
+    def dump(   # pylint: disable=arguments-differ
+            self, include_devices=True, include_links=True
+        ) -> Dict:
+        result = {'topology_id': self.dump_id()}
+        if include_devices: result['device_ids'] = self.dump_device_ids()
+        if include_links: result['link_ids'] = self.dump_link_ids()
+        return result
diff --git a/src/service/service/path_computation_element/Enums.py b/src/service/service/path_computation_element/Enums.py
new file mode 100644
index 000000000..085d230a3
--- /dev/null
+++ b/src/service/service/path_computation_element/Enums.py
@@ -0,0 +1,23 @@
+from enum import Enum
+
+class NodeTypeEnum(Enum):
+    DEVICE   = 'device'
+    ENDPOINT = 'endpoint'
+
+class EndPointTypeEnum(Enum):
+    COPPER    = 'copper'
+    OPTICAL   = 'optical'
+    MICROWAVE = 'microwave'
+
+class EdgeTypeEnum(Enum):
+    INTERNAL  = 'internal'
+    COPPER    = 'copper'
+    OPTICAL   = 'optical'
+    MICROWAVE = 'microwave'
+    VIRTUAL   = 'virtual'
+    OTHER     = 'other'
+
+class LayerTypeEnum(Enum):
+    COPPER    = 'copper'
+    OPTICAL   = 'optical'
+    MICROWAVE = 'microwave'
diff --git a/src/service/service/path_computation_element/PathComputationElement.py b/src/service/service/path_computation_element/PathComputationElement.py
new file mode 100644
index 000000000..4e521f786
--- /dev/null
+++ b/src/service/service/path_computation_element/PathComputationElement.py
@@ -0,0 +1,357 @@
+import grpc, json, logging, networkx, uuid
+from queue import Queue
+from typing import Dict, List, Tuple
+from networkx.drawing.nx_pydot import write_dot
+from common.Constants import DEFAULT_CONTEXT_UUID
+from common.DeviceTypes import DeviceTypeEnum
+from common.tools.grpc.Tools import (
+    grpc_message_list_to_json, grpc_message_list_to_json_string, grpc_message_to_json, grpc_message_to_json_string)
+from context.client.ContextClient import ContextClient
+from context.proto.context_pb2 import (
+    ConfigActionEnum, Connection, Device, Empty, EndPoint, EndPointId, Service, ServiceId, ServiceStatusEnum,
+    ServiceTypeEnum)
+from .Enums import EdgeTypeEnum, NodeTypeEnum
+from .Tools import get_device, get_device_key, get_edge_type, get_endpoint, get_endpoint_key, get_link_key
+
+LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.INFO)
+
+SUB_SERVICE_TYPES = {
+    DeviceTypeEnum.EMULATED_PACKET_ROUTER.value      : ServiceTypeEnum.SERVICETYPE_L3NM,
+    DeviceTypeEnum.EMULATED_OPTICAL_LINE_SYSTEM.value: ServiceTypeEnum.SERVICETYPE_TAPI_CONNECTIVITY_SERVICE,
+    DeviceTypeEnum.PACKET_ROUTER.value               : ServiceTypeEnum.SERVICETYPE_L3NM,
+    DeviceTypeEnum.OPTICAL_LINE_SYSTEM.value         : ServiceTypeEnum.SERVICETYPE_TAPI_CONNECTIVITY_SERVICE,
+}
+DEFAULT_SUB_SERVICE_TYPE = ServiceTypeEnum.SERVICETYPE_UNKNOWN
+
+def dump_requirements(requirements):
+    if requirements is None: return None
+    return [
+        {
+            'sub_service': grpc_message_to_json(sub_service),
+            'sub_connections': grpc_message_list_to_json(sub_connections),
+        }
+        for sub_service,sub_connections in requirements
+    ]
+
+def dump_connectivity(connectivity):
+    if connectivity is None: return None
+    return {
+        'service': grpc_message_to_json(connectivity.get('service')),
+        'connections': grpc_message_list_to_json(connectivity.get('connections', [])),
+        'requirements': dump_requirements(connectivity.get('requirements', [])),
+    }
+
+def dump_hops(hops):
+    if hops is None: return None
+    return [
+        'in_endpoint={:s}, device={:s}, out_endpoint={:s}'.format(
+            grpc_message_to_json_string(in_endpoint), grpc_message_to_json_string(device),
+            grpc_message_to_json_string(out_endpoint))
+        for in_endpoint,device,out_endpoint in hops
+    ]
+
+class PathComputationElement:
+    def __init__(self) -> None:
+        self.__topology = networkx.Graph()
+        self.__connectivity = {} # (a_ep_key, z_ep_key) => {service, connection, sub_services: [], sub_connections: []}
+        self.__service_endpoints = {} # (context_uuid, service_uuid) => (a_ep_key, z_ep_key)
+
+    def dump_topology_to_file(self, dot_filepath : str):
+        write_dot(self.__topology, dot_filepath)
+
+    def dump_connectivity_to_file(self, filepath : str):
+        with open(filepath, 'w', encoding='UTF-8') as f:
+            f.write(str(self.__connectivity)) # do not use json; it contains protobuf objects
+
+    def load_topology(self, context_client : ContextClient):
+        response_devices = context_client.ListDevices(Empty())
+        devices = response_devices.devices
+        LOGGER.debug('Devices[{:d}] = {:s}'.format(len(devices), grpc_message_to_json_string(response_devices)))
+        assert len(devices) > 0
+
+        response_links = context_client.ListLinks(Empty())
+        links = response_links.links
+        LOGGER.debug('Links[{:d}] = {:s}'.format(len(links), grpc_message_to_json_string(response_links)))
+        assert len(links) > 0
+
+        for device in response_devices.devices:
+            device_uuid = get_device_key(device.device_id)
+            self.__topology.add_node(device_uuid, node_type=NodeTypeEnum.DEVICE, device=device)
+            for endpoint in device.device_endpoints:
+                endpoint_key = get_endpoint_key(endpoint.endpoint_id, device_uuid=device_uuid)
+                self.__topology.add_node(endpoint_key, node_type=NodeTypeEnum.ENDPOINT, endpoint=endpoint)
+                self.__topology.add_edge(device_uuid, endpoint_key, edge_type=EdgeTypeEnum.INTERNAL)
+
+        for link in response_links.links:
+            link_uuid = get_link_key(link.link_id)
+            if len(link.link_endpoint_ids) != 2:
+                msg = 'Link({:s}) with {:d} != 2 endpoints'
+                raise NotImplementedError(msg.format(link_uuid, len(link.link_endpoint_ids)))
+            endpoint_keys = [get_endpoint_key(endpoint_id) for endpoint_id in link.link_endpoint_ids]
+            edge_type = get_edge_type(self.__topology, endpoint_keys)
+            self.__topology.add_edge(endpoint_keys[0], endpoint_keys[1], link=link, edge_type=edge_type)
+
+    def load_connectivity(self, context_client : ContextClient, service_id : ServiceId):
+        pending_service_ids = Queue()
+        pending_service_ids.put((service_id, True))
+
+        connectivity = {}
+        requirements : List[Tuple[Service, List[Connection]]] = connectivity.setdefault('requirements', [])
+        connections : List[Connection] = connectivity.setdefault('connections', [])
+
+        while not pending_service_ids.empty():
+            service_id,is_main = pending_service_ids.get()
+
+            try:
+                service = context_client.GetService(service_id)
+                LOGGER.debug('[load_connectivity] GetService({:s}) = {:s}'.format(
+                    grpc_message_to_json_string(service_id), grpc_message_to_json_string(service)))
+            except grpc.RpcError as e:
+                if is_main and e.code() == grpc.StatusCode.NOT_FOUND: continue # pylint: disable=no-member
+                raise
+
+            # TODO: implement support for services with more than 2 endpoints;
+            # Right now, services with less than 2 endpoints are ignored; with more than 2 endpoints throws exception.
+            # e.g., compute pairs such as:
+            #   list(filter(lambda ep: ep[0] < ep[1], itertools.product(service_endpoint_ids, service_endpoint_ids)))
+            service_endpoint_ids = service.service_endpoint_ids
+            if len(service_endpoint_ids) < 2: continue
+            if len(service_endpoint_ids) > 2: raise NotImplementedError('Service with more than 2 endpoints')
+
+            service_connections = context_client.ListConnections(service_id)
+            LOGGER.debug('[load_connectivity] ListConnections({:s}) = {:s}'.format(
+                grpc_message_to_json_string(service_id), grpc_message_to_json_string(service_connections)))
+
+            if is_main:
+                connectivity['service'] = service
+                a_endpoint_key = get_endpoint_key(service_endpoint_ids[0])
+                z_endpoint_key = get_endpoint_key(service_endpoint_ids[-1])
+                self.__connectivity[(a_endpoint_key, z_endpoint_key)] = connectivity
+                self.__connectivity[(z_endpoint_key, a_endpoint_key)] = connectivity
+                context_service_id = (service_id.context_id.context_uuid.uuid, service_id.service_uuid.uuid)
+                self.__service_endpoints[context_service_id] = (a_endpoint_key, z_endpoint_key)
+                connections.extend(service_connections.connections)
+            else:
+                requirements.append((service, service_connections.connections))
+
+            for connection in service_connections.connections:
+                for service_id in connection.sub_service_ids:
+                    pending_service_ids.put((service_id, False))
+
+    def get_connectivity_from_service_id(self, service_id : ServiceId) -> Dict:
+        LOGGER.debug('[get_connectivity_from_service_id] service_id={:s}'.format(
+            grpc_message_to_json_string(service_id)))
+
+        context_uuid = service_id.context_id.context_uuid.uuid
+        service_uuid = service_id.service_uuid.uuid
+        context_service_id = (context_uuid, service_uuid)
+        if context_service_id in self.__service_endpoints:
+            a_endpoint_key, z_endpoint_key = self.__service_endpoints[context_service_id]
+        else:
+            return None
+
+        if (a_endpoint_key, z_endpoint_key) in self.__connectivity:
+            connectivity = self.__connectivity.get((a_endpoint_key, z_endpoint_key))
+        elif (z_endpoint_key, a_endpoint_key) in self.__connectivity:
+            connectivity = self.__connectivity.get((z_endpoint_key, a_endpoint_key))
+        else:
+            connectivity = None
+
+        if connectivity is None or connectivity.get('connections') is None: return None
+        LOGGER.debug('[get_connectivity_from_service_id] Connectivity: {:s}'.format(
+            str(dump_connectivity(connectivity))))
+        return connectivity
+
+    def get_connectivity(self, service : Service) -> Tuple[Dict, str, str]:
+        LOGGER.debug('[get_connectivity] service.service_id = {:s}'.format(
+            grpc_message_to_json_string(service.service_id)))
+
+        context_uuid = service.service_id.context_id.context_uuid.uuid
+        service_uuid = service.service_id.service_uuid.uuid
+        context_service_id = (context_uuid, service_uuid)
+
+        if context_service_id in self.__service_endpoints:
+            LOGGER.debug('[get_connectivity] exists')
+            a_endpoint_key, z_endpoint_key = self.__service_endpoints[context_service_id]
+
+            LOGGER.debug('[get_connectivity] a_endpoint_key={:s}'.format(str(a_endpoint_key)))
+            LOGGER.debug('[get_connectivity] z_endpoint_key={:s}'.format(str(z_endpoint_key)))
+        else:
+            LOGGER.debug('[get_connectivity] new')
+            # TODO: implement support for services with more than 2 endpoints;
+            # Right now, less than 2 reports None, more than 2 endpoints throws an exception.
+            # e.g., compute pairs such as:
+            #   list(filter(lambda ep: ep[0] < ep[1], itertools.product(service_endpoint_ids, service_endpoint_ids)))
+            service_endpoint_ids = service.service_endpoint_ids
+
+            LOGGER.debug('[get_connectivity] service_endpoint_ids[{:d}] = {:s}'.format(
+                len(service_endpoint_ids), grpc_message_list_to_json_string(service_endpoint_ids)))
+
+            if len(service_endpoint_ids) < 2: return None
+            if len(service_endpoint_ids) > 2: raise NotImplementedError('Service with more than 2 endpoints')
+
+            a_endpoint_key = get_endpoint_key(service_endpoint_ids[0])
+            z_endpoint_key = get_endpoint_key(service_endpoint_ids[-1])
+            LOGGER.debug('[get_connectivity] a_endpoint_key={:s}'.format(str(a_endpoint_key)))
+            LOGGER.debug('[get_connectivity] z_endpoint_key={:s}'.format(str(z_endpoint_key)))
+
+        if (a_endpoint_key, z_endpoint_key) in self.__connectivity:
+            connectivity = self.__connectivity.get((a_endpoint_key, z_endpoint_key))
+        elif (z_endpoint_key, a_endpoint_key) in self.__connectivity:
+            connectivity = self.__connectivity.get((z_endpoint_key, a_endpoint_key))
+        else:
+            connectivity = None
+
+        LOGGER.debug('[get_connectivity] connectivity = {:s}'.format(str(dump_connectivity(connectivity))))
+
+        if connectivity is None or connectivity.get('connections') is None: return None, a_endpoint_key, z_endpoint_key
+        return connectivity, a_endpoint_key, z_endpoint_key
+
+    def route_service(self, service : Service):
+        if self.__topology is None: raise Exception('Topology has not been loaded')
+
+        connectivity = self.get_connectivity(service)
+        if connectivity is None:
+            LOGGER.debug('[route_service] connectivity = None')
+            return None
+        _, a_endpoint_key, z_endpoint_key = connectivity
+
+        LOGGER.debug('[route_service] a_endpoint_key={:s}'.format(str(a_endpoint_key)))
+        LOGGER.debug('[route_service] z_endpoint_key={:s}'.format(str(z_endpoint_key)))
+
+        # TODO: consider implementing something like a K-shortest path instead of a simple shortest path
+        # pylint: disable=no-value-for-parameter,unexpected-keyword-arg
+        #paths = networkx.all_shortest_paths(self.__topology, source=a_endpoint_key, target=z_endpoint_key)
+        path_node_keys = networkx.shortest_path(
+            self.__topology, source=a_endpoint_key, target=z_endpoint_key)
+        LOGGER.debug('[route_service] Path[{:d}] = {:s}'.format(len(path_node_keys), str(path_node_keys)))
+
+        if len(path_node_keys) % 3 != 0:
+            msg = 'Weird path: length({:d}) mod 3 != 0. Path should be a sequence of endpoint-device-endpoint, '\
+                  ' so it must be multiple of 3'
+            raise Exception(msg.format(len(path_node_keys)))
+
+        hops : List[Tuple[EndPoint, Device, EndPoint]] = []
+        device_type__to__hops : Dict[str, List[int]] = {}
+        for i in range(0, len(path_node_keys), 3):
+            hop_device = get_device(self.__topology, path_node_keys[i+1])
+            hop_a_endpoint = get_endpoint(self.__topology, path_node_keys[i+0])
+            hop_z_endpoint = get_endpoint(self.__topology, path_node_keys[i+2])
+
+            hop_device_key = get_device_key(hop_device.device_id)
+            hop_a_endpoint_device_key = get_device_key(hop_a_endpoint.endpoint_id.device_id)
+            hop_z_endpoint_device_key = get_device_key(hop_z_endpoint.endpoint_id.device_id)
+
+            if hop_a_endpoint_device_key != hop_device_key:
+                msg = 'Weird path: Hop[{:d}] a_endpoint.device({:s}) != device({:s})'
+                raise Exception(msg.format(i/3, str(hop_a_endpoint_device_key), str(hop_device_key)))
+            if hop_z_endpoint_device_key != hop_device_key:
+                msg = 'Weird path: Hop[{:d}] z_endpoint.device({:s}) != device({:s})'
+                raise Exception(msg.format(i/3, str(hop_z_endpoint_device_key), str(hop_device_key)))
+
+            hops.append((hop_a_endpoint, hop_device, hop_z_endpoint))
+            device_type__to__hops.setdefault(hop_device.device_type, []).append(len(hops) - 1)
+
+        LOGGER.debug('[route_service] hops[{:d}] = {:s}'.format(
+            len(hops), str(dump_hops(hops))))
+        LOGGER.debug('[route_service] device_type__to__hops = {:s}'.format(str(device_type__to__hops)))
+
+        context_uuid = service.service_id.context_id.context_uuid.uuid
+        service_uuid = service.service_id.service_uuid.uuid
+
+        # create main service's connection
+        main_service_device_type = hops[0][1].device_type
+        main_service_hop_indexes = device_type__to__hops.pop(main_service_device_type)
+
+        # create sub-service and sub-services' connections
+        sub_service_ids = []
+        requirements : List[Tuple[Service, List[Connection]]] = []
+        for sub_service_device_type, sub_service_hop_indexes in device_type__to__hops.items():
+            LOGGER.debug('[route_service] sub_service_device_type = {:s}'.format(str(sub_service_device_type)))
+            LOGGER.debug('[route_service] sub_service_hop_indexes = {:s}'.format(str(sub_service_hop_indexes)))
+
+            # create sub-service
+            sub_service_uuid = '{:s}:optical'.format(service_uuid)
+            sub_service_id = {
+                'context_id': {'context_uuid': {'uuid': context_uuid}},
+                'service_uuid': {'uuid': sub_service_uuid},
+            }
+            sub_service = Service(**{
+                'service_id': sub_service_id,
+                'service_type' : SUB_SERVICE_TYPES.get(sub_service_device_type, DEFAULT_SUB_SERVICE_TYPE),
+                'service_status': {'service_status': ServiceStatusEnum.SERVICESTATUS_PLANNED},
+                'service_endpoint_ids': [
+                    hops[sub_service_hop_indexes[ 0]][ 0].endpoint_id,
+                    hops[sub_service_hop_indexes[-1]][-1].endpoint_id,
+                ],
+                'service_config': {'config_rules': [
+                    {
+                        'action': ConfigActionEnum.CONFIGACTION_SET,
+                        'resource_key': 'settings',
+                        'resource_value': json.dumps({
+                            'capacity_value':   1,
+                            'capacity_unit':    'GHz',
+                            'layer_proto_name': 'PHOTONIC_MEDIA',
+                            'layer_proto_qual': 'tapi-photonic-media:PHOTONIC_LAYER_QUALIFIER_NMC',
+                            'direction':        'UNIDIRECTIONAL',
+                        }, sort_keys=True)
+                    }
+                ]},
+            })
+            LOGGER.debug('[route_service] sub_service = {:s}'.format(grpc_message_to_json_string(sub_service)))
+
+            # create sub-service's connection
+            sub_connection_uuid = '{:s}:{:s}'.format(sub_service_uuid, sub_service_device_type)
+            sub_conn_path_hops = []
+            for i in sub_service_hop_indexes:
+                sub_conn_path_hops.extend([hops[i][0].endpoint_id, hops[i][2].endpoint_id])
+            sub_connection = Connection(**{
+                'connection_id': {'connection_uuid': {'uuid': sub_connection_uuid}},
+                'service_id': sub_service_id,
+                'path_hops_endpoint_ids': sub_conn_path_hops,
+            })
+
+            LOGGER.debug('[route_service] sub_connection = {:s}'.format(grpc_message_to_json_string(sub_connection)))
+
+            sub_service_ids.append(sub_service_id)
+            requirements.append((sub_service, [sub_connection]))
+
+        LOGGER.debug('[route_service] sub_service_ids = {:s}'.format(str(sub_service_ids)))
+        LOGGER.debug('[route_service] requirements = {:s}'.format(str(dump_requirements(requirements))))
+        LOGGER.debug('[route_service] requirements[{:d}] = {:s}'.format(
+            len(requirements), str(dump_requirements(requirements))))
+
+        connections : List[Connection] = []
+
+        connection_uuid = '{:s}:{:s}'.format(service_uuid, main_service_device_type)
+        connection_path_hops : List[EndPointId] = []
+        for i in main_service_hop_indexes:
+            connection_path_hops.extend([hops[i][0].endpoint_id, hops[i][2].endpoint_id])
+        connection = Connection(**{
+            'connection_id': {'connection_uuid': {'uuid': connection_uuid}},
+            'service_id': grpc_message_to_json(service.service_id),
+            'path_hops_endpoint_ids': connection_path_hops,
+            'sub_service_ids': sub_service_ids,
+        })
+        LOGGER.debug('[route_service] connection = {:s}'.format(grpc_message_to_json_string(connection)))
+        connections.append(connection)
+            
+        LOGGER.debug('[route_service] connections[{:d}] = {:s}'.format(
+            len(connections), grpc_message_list_to_json_string(connections)))
+
+        connectivity = {
+            'service': service,
+            'connections': connections,
+            'requirements': requirements,
+        }
+
+        LOGGER.debug('[route_service] connectivity = {:s}'.format(str(dump_connectivity(connectivity))))
+
+        self.__connectivity[(a_endpoint_key, z_endpoint_key)] = connectivity
+        self.__connectivity[(z_endpoint_key, a_endpoint_key)] = connectivity
+
+        context_service_id = (context_uuid, service_uuid)
+        self.__service_endpoints[context_service_id] = (a_endpoint_key, z_endpoint_key)
+
+        return connectivity
diff --git a/src/service/service/path_computation_element/Tools.py b/src/service/service/path_computation_element/Tools.py
new file mode 100644
index 000000000..ef5c943c9
--- /dev/null
+++ b/src/service/service/path_computation_element/Tools.py
@@ -0,0 +1,29 @@
+import networkx
+from typing import List, Optional
+from context.proto.context_pb2 import Device, DeviceId, EndPoint, EndPointId, LinkId
+from .Enums import EdgeTypeEnum
+
+def get_device_key(device_id : DeviceId) -> str:
+    return device_id.device_uuid.uuid # pylint: disable=no-member
+
+def get_endpoint_key(endpoint_id : EndPointId, device_uuid : Optional[str] = None) -> str:
+    if device_uuid is None: device_uuid = endpoint_id.device_id.device_uuid.uuid # pylint: disable=no-member
+    endpoint_uuid = endpoint_id.endpoint_uuid.uuid # pylint: disable=no-member
+    return '{:s}/{:s}'.format(device_uuid, endpoint_uuid)
+
+def get_link_key(link_id : LinkId) -> str:
+    return link_id.link_uuid.uuid # pylint: disable=no-member
+
+def get_device(topology : networkx.Graph, device_key : str) -> Device:
+    return topology.nodes[device_key]['device']
+
+def get_endpoint(topology : networkx.Graph, endpoint_key : str) -> EndPoint:
+    return topology.nodes[endpoint_key]['endpoint']
+
+def get_edge_type(topology : networkx.Graph, endpoint_keys : List[str]) -> EdgeTypeEnum:
+    # pylint: disable=no-member,protected-access
+    endpoint_types = {get_endpoint(topology, endpoint_key).endpoint_type for endpoint_key in endpoint_keys}
+    edge_type = None if len(endpoint_types) > 1 else \
+        EdgeTypeEnum._value2member_map_.get(endpoint_types.pop())
+    if edge_type is None: edge_type = EdgeTypeEnum.OTHER
+    return edge_type
diff --git a/src/service/service/path_computation_element/TopologyViews.py b/src/service/service/path_computation_element/TopologyViews.py
new file mode 100644
index 000000000..140b1f451
--- /dev/null
+++ b/src/service/service/path_computation_element/TopologyViews.py
@@ -0,0 +1,43 @@
+import functools, networkx
+from typing import List, Optional, Union
+from context.proto.context_pb2 import EndPoint
+from context.service.database.EndPointModel import EndPointModel
+from .Enums import EdgeTypeEnum, LayerTypeEnum
+#from .Tools import get_endpoint
+
+def select_copper_edges(topology, n1, n2):
+    selected_edges = {EdgeTypeEnum.COPPER, EdgeTypeEnum.INTERNAL, EdgeTypeEnum.OTHER}
+    return topology[n1][n2].get('edge_type', EdgeTypeEnum.OTHER) in selected_edges
+
+def select_optical_edges(topology, n1, n2):
+    selected_edges = {EdgeTypeEnum.OPTICAL, EdgeTypeEnum.INTERNAL, EdgeTypeEnum.OTHER}
+    return topology[n1][n2].get('edge_type', EdgeTypeEnum.OTHER) in selected_edges
+
+def select_microwave_edges(topology, n1, n2):
+    selected_edges = {EdgeTypeEnum.MICROWAVE, EdgeTypeEnum.INTERNAL, EdgeTypeEnum.OTHER}
+    return topology[n1][n2].get('edge_type', EdgeTypeEnum.OTHER) in selected_edges
+
+SELECT_LAYER = {
+    LayerTypeEnum.COPPER    : select_copper_edges,
+    LayerTypeEnum.OPTICAL   : select_optical_edges,
+    LayerTypeEnum.MICROWAVE : select_microwave_edges,
+}
+
+def get_layer(topology : networkx.Graph, layer : LayerTypeEnum):
+    filter_edge = functools.partial(SELECT_LAYER[layer], topology)
+    return networkx.subgraph_view(topology, filter_edge=filter_edge)
+
+def select_layer_from_endpoints(endpoints : List[Union[EndPointModel, EndPoint]]) -> Optional[LayerTypeEnum]:
+    endpoint_types = set()
+    for endpoint in endpoints: endpoint_types.add(endpoint.endpoint_type)
+    if len(endpoint_types) != 1: return None
+    # pylint: disable=no-member,protected-access
+    return LayerTypeEnum._value2member_map_.get(endpoint_types.pop())
+
+#a_endpoint = get_endpoint(self.__topology, a_endpoint_key)
+#z_endpoint = get_endpoint(self.__topology, z_endpoint_key)
+#endpoints = [a_endpoint, z_endpoint]
+#layer_type = select_layer_from_endpoints(endpoints)
+#topology = self.__topology if layer_type is None else get_layer(self.__topology, layer_type)
+#write_dot(topology, '../data/layer-{:s}.dot'.format('all' if layer_type is None else str(layer_type.value)))
+
diff --git a/src/service/service/path_computation_element/__init__.py b/src/service/service/path_computation_element/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/service/service/service_handlers/__init__.py b/src/service/service/service_handlers/__init__.py
index 73777c52e..a33757eb1 100644
--- a/src/service/service/service_handlers/__init__.py
+++ b/src/service/service/service_handlers/__init__.py
@@ -1,6 +1,7 @@
 from ..service_handler_api.FilterFields import FilterFieldEnum, ORM_DeviceDriverEnum, ORM_ServiceTypeEnum
 from .l3nm_emulated.L3NMEmulatedServiceHandler import L3NMEmulatedServiceHandler
 from .l3nm_openconfig.L3NMOpenConfigServiceHandler import L3NMOpenConfigServiceHandler
+from .tapi_tapi.TapiServiceHandler import TapiServiceHandler
 
 SERVICE_HANDLERS = [
     (L3NMEmulatedServiceHandler, [
@@ -15,4 +16,10 @@ SERVICE_HANDLERS = [
             FilterFieldEnum.DEVICE_DRIVER : ORM_DeviceDriverEnum.OPENCONFIG,
         }
     ]),
+    (TapiServiceHandler, [
+        {
+            FilterFieldEnum.SERVICE_TYPE  : ORM_ServiceTypeEnum.TAPI_CONNECTIVITY_SERVICE,
+            FilterFieldEnum.DEVICE_DRIVER : ORM_DeviceDriverEnum.TRANSPORT_API,
+        }
+    ]),
 ]
diff --git a/src/service/service/service_handlers/l3nm_emulated/L3NMEmulatedServiceHandler.py b/src/service/service/service_handlers/l3nm_emulated/L3NMEmulatedServiceHandler.py
index 4b5636c6b..fe85596ba 100644
--- a/src/service/service/service_handlers/l3nm_emulated/L3NMEmulatedServiceHandler.py
+++ b/src/service/service/service_handlers/l3nm_emulated/L3NMEmulatedServiceHandler.py
@@ -147,6 +147,10 @@ class L3NMEmulatedServiceHandler(_ServiceHandler):
                         '/interface[{:s}]/subinterface[{:d}]'.format(endpoint_uuid, sub_interface_index), {
                             'name': endpoint_uuid, 'index': sub_interface_index,
                     }),
+                    config_rule_delete(
+                        '/interface[{:s}]'.format(endpoint_uuid), {
+                            'name': endpoint_uuid,
+                    }),
                     config_rule_delete(
                         '/network_instance[{:s}]'.format(network_instance_name), {
                             'name': network_instance_name
diff --git a/src/service/service/service_handlers/tapi_tapi/TapiServiceHandler.py b/src/service/service/service_handlers/tapi_tapi/TapiServiceHandler.py
new file mode 100644
index 000000000..7f23fdc75
--- /dev/null
+++ b/src/service/service/service_handlers/tapi_tapi/TapiServiceHandler.py
@@ -0,0 +1,156 @@
+import anytree, json, logging
+from typing import Any, Dict, List, Optional, Tuple, Union
+from common.orm.Database import Database
+from common.orm.HighLevel import get_object
+from common.orm.backend.Tools import key_to_str
+from common.type_checkers.Checkers import chk_type
+from context.client.ContextClient import ContextClient
+from device.client.DeviceClient import DeviceClient
+from device.proto.context_pb2 import Device
+from service.service.database.ConfigModel import ORM_ConfigActionEnum, get_config_rules
+from service.service.database.ContextModel import ContextModel
+from service.service.database.DeviceModel import DeviceModel
+from service.service.database.ServiceModel import ServiceModel
+from service.service.service_handler_api._ServiceHandler import _ServiceHandler
+from service.service.service_handler_api.AnyTreeTools import TreeNode, delete_subnode, get_subnode, set_subnode_value
+from service.service.service_handlers.Tools import config_rule_set, config_rule_delete
+
+LOGGER = logging.getLogger(__name__)
+
+class TapiServiceHandler(_ServiceHandler):
+    def __init__(   # pylint: disable=super-init-not-called
+        self, db_service : ServiceModel, database : Database, context_client : ContextClient,
+        device_client : DeviceClient, **settings
+    ) -> None:
+        self.__db_service = db_service
+        self.__database = database
+        self.__context_client = context_client # pylint: disable=unused-private-member
+        self.__device_client = device_client
+
+        self.__db_context : ContextModel = get_object(self.__database, ContextModel, self.__db_service.context_fk)
+        str_service_key = key_to_str([self.__db_context.context_uuid, self.__db_service.service_uuid])
+        db_config = get_config_rules(self.__database, str_service_key, 'running')
+        self.__resolver = anytree.Resolver(pathattr='name')
+        self.__config = TreeNode('.')
+        for action, resource_key, resource_value in db_config:
+            if action == ORM_ConfigActionEnum.SET:
+                try:
+                    resource_value = json.loads(resource_value)
+                except: # pylint: disable=bare-except
+                    pass
+                set_subnode_value(self.__resolver, self.__config, resource_key, resource_value)
+            elif action == ORM_ConfigActionEnum.DELETE:
+                delete_subnode(self.__resolver, self.__config, resource_key)
+
+    def SetEndpoint(self, endpoints : List[Tuple[str, str, Optional[str]]]) -> List[Union[bool, Exception]]:
+        chk_type('endpoints', endpoints, list)
+        if len(endpoints) != 2: return []
+
+        service_uuid = self.__db_service.service_uuid
+        service_settings : TreeNode = get_subnode(self.__resolver, self.__config, 'settings', None)
+        if service_settings is None: raise Exception('Unable to settings for Service({:s})'.format(str(service_uuid)))
+
+        json_settings : Dict = service_settings.value
+        capacity_value   = json_settings.get('capacity_value',   1)
+        capacity_unit    = json_settings.get('capacity_unit',    'GHz')
+        layer_proto_name = json_settings.get('layer_proto_name', 'PHOTONIC_MEDIA')
+        layer_proto_qual = json_settings.get('layer_proto_qual', 'tapi-photonic-media:PHOTONIC_LAYER_QUALIFIER_NMC')
+        direction        = json_settings.get('direction',        'UNIDIRECTIONAL')
+
+        results = []
+        try:
+            device_uuid = endpoints[0][0]
+            db_device : DeviceModel = get_object(self.__database, DeviceModel, device_uuid, raise_if_not_found=True)
+            json_device = db_device.dump(include_config_rules=False, include_drivers=True, include_endpoints=True)
+            json_device_config : Dict = json_device.setdefault('device_config', {})
+            json_device_config_rules : List = json_device_config.setdefault('config_rules', [])
+            json_device_config_rules.extend([
+                config_rule_set('/service[{:s}]'.format(service_uuid), {
+                    'uuid'                    : service_uuid,
+                    'input_sip'               : endpoints[0][1],
+                    'output_sip'              : endpoints[1][1],
+                    'capacity_unit'           : capacity_unit,
+                    'capacity_value'          : capacity_value,
+                    'layer_protocol_name'     : layer_proto_name,
+                    'layer_protocol_qualifier': layer_proto_qual,
+                    'direction'               : direction,
+                }),
+            ])
+            self.__device_client.ConfigureDevice(Device(**json_device))
+            results.append(True)
+        except Exception as e: # pylint: disable=broad-except
+            LOGGER.exception('Unable to SetEndpoint for Service({:s})'.format(str(service_uuid)))
+            results.append(e)
+
+        return results
+
+    def DeleteEndpoint(self, endpoints : List[Tuple[str, str, Optional[str]]]) -> List[Union[bool, Exception]]:
+        chk_type('endpoints', endpoints, list)
+        if len(endpoints) != 2: return []
+
+        service_uuid = self.__db_service.service_uuid
+        results = []
+        try:
+            device_uuid = endpoints[0][0]
+            db_device : DeviceModel = get_object(self.__database, DeviceModel, device_uuid, raise_if_not_found=True)
+            json_device = db_device.dump(include_config_rules=False, include_drivers=True, include_endpoints=True)
+            json_device_config : Dict = json_device.setdefault('device_config', {})
+            json_device_config_rules : List = json_device_config.setdefault('config_rules', [])
+            json_device_config_rules.extend([
+                config_rule_delete('/service[{:s}]'.format(service_uuid), {'uuid': service_uuid})
+            ])
+            self.__device_client.ConfigureDevice(Device(**json_device))
+            results.append(True)
+        except Exception as e: # pylint: disable=broad-except
+            LOGGER.exception('Unable to DeleteEndpoint for Service({:s})'.format(str(service_uuid)))
+            results.append(e)
+
+        return results
+
+    def SetConstraint(self, constraints : List[Tuple[str, Any]]) -> List[Union[bool, Exception]]:
+        chk_type('constraints', constraints, list)
+        if len(constraints) == 0: return []
+
+        msg = '[SetConstraint] Method not implemented. Constraints({:s}) are being ignored.'
+        LOGGER.warning(msg.format(str(constraints)))
+        return [True for _ in range(len(constraints))]
+
+    def DeleteConstraint(self, constraints : List[Tuple[str, Any]]) -> List[Union[bool, Exception]]:
+        chk_type('constraints', constraints, list)
+        if len(constraints) == 0: return []
+
+        msg = '[DeleteConstraint] Method not implemented. Constraints({:s}) are being ignored.'
+        LOGGER.warning(msg.format(str(constraints)))
+        return [True for _ in range(len(constraints))]
+
+    def SetConfig(self, resources : List[Tuple[str, Any]]) -> List[Union[bool, Exception]]:
+        chk_type('resources', resources, list)
+        if len(resources) == 0: return []
+
+        results = []
+        for resource in resources:
+            try:
+                resource_key, resource_value = resource
+                resource_value = json.loads(resource_value)
+                set_subnode_value(self.__resolver, self.__config, resource_key, resource_value)
+                results.append(True)
+            except Exception as e: # pylint: disable=broad-except
+                LOGGER.exception('Unable to SetConfig({:s})'.format(str(resource)))
+                results.append(e)
+
+        return results
+
+    def DeleteConfig(self, resources : List[Tuple[str, Any]]) -> List[Union[bool, Exception]]:
+        chk_type('resources', resources, list)
+        if len(resources) == 0: return []
+
+        results = []
+        for resource in resources:
+            try:
+                resource_key, _ = resource
+                delete_subnode(self.__resolver, self.__config, resource_key)
+            except Exception as e: # pylint: disable=broad-except
+                LOGGER.exception('Unable to DeleteConfig({:s})'.format(str(resource)))
+                results.append(e)
+
+        return results
diff --git a/src/service/service/service_handlers/tapi_tapi/__init__.py b/src/service/service/service_handlers/tapi_tapi/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/service/tests/.gitignore b/src/service/tests/.gitignore
index f2f83148d..6b97d6fe3 100644
--- a/src/service/tests/.gitignore
+++ b/src/service/tests/.gitignore
@@ -1,2 +1 @@
 # Add here your files containing confidential testbed details such as IP addresses, ports, usernames, passwords, etc.
-ServiceHandler_L3NM_OC.py
diff --git a/src/service/tests/CommonObjects.py b/src/service/tests/CommonObjects.py
index 2b51dcd23..bcff9db14 100644
--- a/src/service/tests/CommonObjects.py
+++ b/src/service/tests/CommonObjects.py
@@ -1,21 +1,20 @@
-from copy import deepcopy
 from common.Constants import DEFAULT_CONTEXT_UUID, DEFAULT_TOPOLOGY_UUID
+from common.tools.object_factory.Context import json_context, json_context_id
+from common.tools.object_factory.Topology import json_topology, json_topology_id
+from context.proto.kpi_sample_types_pb2 import KpiSampleType
 
-# use "deepcopy" to prevent propagating forced changes during tests
+# ----- Context --------------------------------------------------------------------------------------------------------
+CONTEXT_ID = json_context_id(DEFAULT_CONTEXT_UUID)
+CONTEXT    = json_context(DEFAULT_CONTEXT_UUID)
 
-CONTEXT_ID = {'context_uuid': {'uuid': DEFAULT_CONTEXT_UUID}}
-CONTEXT = {
-    'context_id': deepcopy(CONTEXT_ID),
-    'topology_ids': [],
-    'service_ids': [],
-}
+# ----- Topology -------------------------------------------------------------------------------------------------------
+TOPOLOGY_ID = json_topology_id(DEFAULT_TOPOLOGY_UUID, context_id=CONTEXT_ID)
+TOPOLOGY    = json_topology(DEFAULT_TOPOLOGY_UUID, context_id=CONTEXT_ID)
 
-TOPOLOGY_ID = {
-    'context_id': deepcopy(CONTEXT_ID),
-    'topology_uuid': {'uuid': DEFAULT_TOPOLOGY_UUID},
-}
-TOPOLOGY = {
-    'topology_id': deepcopy(TOPOLOGY_ID),
-    'device_ids': [],
-    'link_ids': [],
-}
+# ----- Monitoring Samples ---------------------------------------------------------------------------------------------
+PACKET_PORT_SAMPLE_TYPES = [
+    KpiSampleType.KPISAMPLETYPE_PACKETS_TRANSMITTED,
+    KpiSampleType.KPISAMPLETYPE_PACKETS_RECEIVED,
+    KpiSampleType.KPISAMPLETYPE_BYTES_TRANSMITTED,
+    KpiSampleType.KPISAMPLETYPE_BYTES_RECEIVED,
+]
diff --git a/src/service/tests/ServiceHandler_L3NM_EMU.py b/src/service/tests/ServiceHandler_L3NM_EMU.py
index cfaf49d08..b3cf75056 100644
--- a/src/service/tests/ServiceHandler_L3NM_EMU.py
+++ b/src/service/tests/ServiceHandler_L3NM_EMU.py
@@ -1,102 +1,120 @@
-from copy import deepcopy
-from service.proto.context_pb2 import DeviceDriverEnum, DeviceOperationalStatusEnum, ServiceStatusEnum, ServiceTypeEnum
-from service.service.service_handlers.Tools import config_rule_set, constraint, device_id, endpoint_id
-from .CommonObjects import CONTEXT_ID
-
-# use "deepcopy" to prevent propagating forced changes during tests
+from typing import Dict, List, Tuple
+from common.tools.object_factory.ConfigRule import json_config_rule_set
+from common.tools.object_factory.Constraint import json_constraint
+from common.tools.object_factory.Device import (
+    json_device_emulated_packet_router_disabled, json_device_emulated_tapi_disabled, json_device_id)
+from common.tools.object_factory.EndPoint import json_endpoint, json_endpoint_id
+from common.tools.object_factory.Link import json_link, json_link_id
+from common.tools.object_factory.Service import json_service_id, json_service_l3nm_planned
+from .CommonObjects import CONTEXT, CONTEXT_ID, PACKET_PORT_SAMPLE_TYPES, TOPOLOGY, TOPOLOGY_ID
 
 SERVICE_HANDLER_NAME = 'l3nm_emulated'
 
-SERVICE_UUID = 'SVC_L3NM_EMU'
-
-SERVICE_ID = {
-    'context_id': deepcopy(CONTEXT_ID),
-    'service_uuid': {'uuid': SERVICE_UUID}
-}
-
-SERVICE_DESCRIPTOR = {
-    'service_id': deepcopy(SERVICE_ID),
-    'service_type': ServiceTypeEnum.SERVICETYPE_L3NM,
-    'service_endpoint_ids' : [],
-    'service_constraints': [],
-    'service_status': {'service_status': ServiceStatusEnum.SERVICESTATUS_PLANNED},
-    'service_config': {'config_rules': []},
-}
-
-DEVICE1_UUID = 'EMULATED-ROUTER-1'
-DEVICE2_UUID = 'EMULATED-ROUTER-2'
-
-DEVICE_ATTRIBUTES = { # device_uuid => {device_settings}
-    DEVICE1_UUID: {
-        'type'    : 'emulated',
-        'drivers' : [DeviceDriverEnum.DEVICEDRIVER_UNDEFINED],
-        'endpoint': 'EP100',
-    },
-    DEVICE2_UUID: {
-        'type'    : 'emulated',
-        'drivers' : [DeviceDriverEnum.DEVICEDRIVER_UNDEFINED],
-        'endpoint': 'EP100',
-    },
-}
-
-SERVICE_DEVICE_UUIDS = [DEVICE1_UUID, DEVICE2_UUID]
-
-SERVICE_ENDPOINT_IDS = [
-    endpoint_id(device_uuid, DEVICE_ATTRIBUTES[device_uuid]['endpoint'])
-    for device_uuid in SERVICE_DEVICE_UUIDS
-]
+def json_endpoint_ids(device_id : Dict, endpoint_descriptors : List[Tuple[str, str]]):
+    return [
+        json_endpoint_id(device_id, ep_uuid)
+        for ep_uuid, _ in endpoint_descriptors
+    ]
 
-SERVICE_CONFIG_RULES = [
-    config_rule_set(
-        'settings', {
-            'route_distinguisher': '60001:801', 'mtu': 1512, 'address_families': ['IPV4']
-        }),
-    config_rule_set(
-        'device[{:s}]/endpoint[{:s}]/settings'.format(DEVICE1_UUID, DEVICE_ATTRIBUTES[DEVICE1_UUID]['endpoint']), {
-            'router_id': '10.0.0.1', 'sub_interface_index': 1,
-        }),
-    config_rule_set(
-        'device[{:s}]/endpoint[{:s}]/settings'.format(DEVICE2_UUID, DEVICE_ATTRIBUTES[DEVICE2_UUID]['endpoint']), {
-            'router_id': '10.0.0.2', 'sub_interface_index': 1,
-        }),
-]
+def json_endpoints(device_id : Dict, endpoint_descriptors : List[Tuple[str, str]]):
+    return [
+        json_endpoint(device_id, ep_uuid, ep_type, kpi_sample_types=PACKET_PORT_SAMPLE_TYPES)
+        for ep_uuid, ep_type in endpoint_descriptors
+    ]
+
+# ----- Devices --------------------------------------------------------------------------------------------------------
+DEVICE_R1_UUID          = 'R1'
+DEVICE_R1_ENDPOINT_DEFS = [('EP1', 'optical'), ('EP100', 'copper')]
+DEVICE_R1_ID            = json_device_id(DEVICE_R1_UUID)
+DEVICE_R1_ENDPOINTS     = json_endpoints(DEVICE_R1_ID, DEVICE_R1_ENDPOINT_DEFS)
+DEVICE_R1_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_R1_ID, DEVICE_R1_ENDPOINT_DEFS)
+DEVICE_R1               = json_device_emulated_packet_router_disabled(DEVICE_R1_UUID, endpoints=DEVICE_R1_ENDPOINTS)
+ENDPOINT_ID_R1_EP1      = DEVICE_R1_ENDPOINT_IDS[0]
+ENDPOINT_ID_R1_EP100    = DEVICE_R1_ENDPOINT_IDS[1]
+
+DEVICE_R2_UUID          = 'R2'
+DEVICE_R2_ENDPOINT_DEFS = [('EP1', 'optical'), ('EP100', 'copper')]
+DEVICE_R2_ID            = json_device_id(DEVICE_R2_UUID)
+DEVICE_R2_ENDPOINTS     = json_endpoints(DEVICE_R2_ID, DEVICE_R2_ENDPOINT_DEFS)
+DEVICE_R2_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_R2_ID, DEVICE_R2_ENDPOINT_DEFS)
+DEVICE_R2               = json_device_emulated_packet_router_disabled(DEVICE_R2_UUID, endpoints=DEVICE_R2_ENDPOINTS)
+ENDPOINT_ID_R2_EP1      = DEVICE_R2_ENDPOINT_IDS[0]
+ENDPOINT_ID_R2_EP100    = DEVICE_R2_ENDPOINT_IDS[1]
+
+DEVICE_R3_UUID          = 'R3'
+DEVICE_R3_ENDPOINT_DEFS = [('EP1', 'optical'), ('EP100', 'copper')]
+DEVICE_R3_ID            = json_device_id(DEVICE_R3_UUID)
+DEVICE_R3_ENDPOINTS     = json_endpoints(DEVICE_R3_ID, DEVICE_R3_ENDPOINT_DEFS)
+DEVICE_R3_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_R3_ID, DEVICE_R3_ENDPOINT_DEFS)
+DEVICE_R3               = json_device_emulated_packet_router_disabled(DEVICE_R3_UUID, endpoints=DEVICE_R3_ENDPOINTS)
+ENDPOINT_ID_R3_EP1      = DEVICE_R3_ENDPOINT_IDS[0]
+ENDPOINT_ID_R3_EP100    = DEVICE_R3_ENDPOINT_IDS[1]
 
-SERVICE_CONSTRAINTS = [
-    constraint('latency_ms', 15.2),
-    constraint('jitter_us', 1.2),
+DEVICE_O1_UUID          = 'O1'
+DEVICE_O1_ENDPOINT_DEFS = [('EP1', 'optical'), ('EP2', 'optical'), ('EP3', 'optical')]
+DEVICE_O1_ID            = json_device_id(DEVICE_O1_UUID)
+DEVICE_O1_ENDPOINTS     = json_endpoints(DEVICE_O1_ID, DEVICE_O1_ENDPOINT_DEFS)
+DEVICE_O1_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_O1_ID, DEVICE_O1_ENDPOINT_DEFS)
+DEVICE_O1               = json_device_emulated_tapi_disabled(DEVICE_O1_UUID, endpoints=DEVICE_O1_ENDPOINTS)
+ENDPOINT_ID_O1_EP1      = DEVICE_O1_ENDPOINT_IDS[0]
+ENDPOINT_ID_O1_EP2      = DEVICE_O1_ENDPOINT_IDS[1]
+ENDPOINT_ID_O1_EP3      = DEVICE_O1_ENDPOINT_IDS[2]
+
+
+# ----- Links ----------------------------------------------------------------------------------------------------------
+LINK_R1_O1_UUID = '{:s}/{:s}-{:s}/{:s}'.format(
+    DEVICE_R1_UUID, ENDPOINT_ID_R1_EP1['endpoint_uuid']['uuid'],
+    DEVICE_O1_UUID, ENDPOINT_ID_O1_EP1['endpoint_uuid']['uuid'])
+LINK_R1_O1_ID   = json_link_id(LINK_R1_O1_UUID)
+LINK_R1_O1      = json_link(LINK_R1_O1_UUID, [ENDPOINT_ID_R1_EP1, ENDPOINT_ID_O1_EP1])
+
+LINK_R2_O1_UUID = '{:s}/{:s}-{:s}/{:s}'.format(
+    DEVICE_R2_UUID, ENDPOINT_ID_R2_EP1['endpoint_uuid']['uuid'],
+    DEVICE_O1_UUID, ENDPOINT_ID_O1_EP2['endpoint_uuid']['uuid'])
+LINK_R2_O1_ID   = json_link_id(LINK_R2_O1_UUID)
+LINK_R2_O1      = json_link(LINK_R2_O1_UUID, [ENDPOINT_ID_R2_EP1, ENDPOINT_ID_O1_EP2])
+
+LINK_R3_O1_UUID = '{:s}/{:s}-{:s}/{:s}'.format(
+    DEVICE_R3_UUID, ENDPOINT_ID_R3_EP1['endpoint_uuid']['uuid'],
+    DEVICE_O1_UUID, ENDPOINT_ID_O1_EP3['endpoint_uuid']['uuid'])
+LINK_R3_O1_ID   = json_link_id(LINK_R3_O1_UUID)
+LINK_R3_O1      = json_link(LINK_R3_O1_UUID, [ENDPOINT_ID_R3_EP1, ENDPOINT_ID_O1_EP3])
+
+
+# ----- Service --------------------------------------------------------------------------------------------------------
+SERVICE_R1_R3_UUID         = 'SVC:{:s}/{:s}-{:s}/{:s}'.format(
+    DEVICE_R1_UUID, ENDPOINT_ID_R1_EP100['endpoint_uuid']['uuid'],
+    DEVICE_R3_UUID, ENDPOINT_ID_R3_EP100['endpoint_uuid']['uuid'])
+SERVICE_R1_R3_ENDPOINT_IDS = [ENDPOINT_ID_R1_EP100, ENDPOINT_ID_R3_EP100]
+SERVICE_R1_R3_CONSTRAINTS  = [
+    json_constraint('latency_ms', 15.2),
+    json_constraint('jitter_us', 1.2),
+]
+SERVICE_R1_R3_CONFIG_RULES = [
+    json_config_rule_set(
+        'settings',
+        {'route_distinguisher': '60001:801', 'mtu': 1512, 'address_families': ['IPV4']}),
+    json_config_rule_set(
+        'device[{:s}]/endpoint[{:s}]/settings'.format(DEVICE_R1_UUID, ENDPOINT_ID_R1_EP100['endpoint_uuid']['uuid']),
+        {'router_id': '10.0.0.1', 'sub_interface_index': 1}),
+    json_config_rule_set(
+        'device[{:s}]/endpoint[{:s}]/settings'.format(DEVICE_R3_UUID, ENDPOINT_ID_R3_EP100['endpoint_uuid']['uuid']),
+        {'router_id': '10.0.0.3', 'sub_interface_index': 1}),
 ]
+SERVICE_R1_R3_ID           = json_service_id(SERVICE_R1_R3_UUID, context_id=CONTEXT_ID)
+SERVICE_R1_R3_DESCRIPTOR   = json_service_l3nm_planned(SERVICE_R1_R3_UUID)
 
-def get_device_descriptor(device_uuid, enabled=True):
-    device_operational_status = (
-        DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_ENABLED \
-        if enabled else \
-        DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_DISABLED)
-    return {
-        'device_id': device_id(device_uuid),
-        'device_type': DEVICE_ATTRIBUTES[device_uuid]['type'],
-        'device_config': {'config_rules': []},
-        'device_operational_status': device_operational_status,
-        'device_drivers': DEVICE_ATTRIBUTES[device_uuid]['drivers'],
-        'device_endpoints': [],
-    }
-
-def get_connect_rules(device_uuid):
-    return [
-        config_rule_set('_connect/address', '127.0.0.1'),
-        config_rule_set('_connect/port',    '0'),
-        config_rule_set('_connect/settings', {'endpoints': [
-            {'uuid': endpoint_uuid, 'type': '10Gbps', 'sample_types': []}
-            for endpoint_uuid in ['EP1', 'EP2', 'EP3', 'EP100']
-        ]}),
-    ]
 
+# ----- Test Descriptor ------------------------------------------------------------------------------------------------
 TEST_SERVICE_HANDLER = (SERVICE_HANDLER_NAME, {
-    'service_id'            : SERVICE_ID,
-    'service_descriptor'    : SERVICE_DESCRIPTOR,
-    'service_endpoint_ids'  : SERVICE_ENDPOINT_IDS,
-    'service_config_rules'  : SERVICE_CONFIG_RULES,
-    'service_constraints'   : SERVICE_CONSTRAINTS,
-    'service_device_uuids'  : SERVICE_DEVICE_UUIDS,
-    'get_device_descriptor' : get_device_descriptor,
-    'get_connect_rules'     : get_connect_rules,
+    'contexts'              : [CONTEXT],
+    'topologies'            : [TOPOLOGY],
+    'devices'               : [DEVICE_R1, DEVICE_R2, DEVICE_R3, DEVICE_O1],
+    'links'                 : [LINK_R1_O1, LINK_R2_O1, LINK_R3_O1],
+
+    'service_id'            : SERVICE_R1_R3_ID,
+    'service_descriptor'    : SERVICE_R1_R3_DESCRIPTOR,
+    'service_endpoint_ids'  : SERVICE_R1_R3_ENDPOINT_IDS,
+    'service_config_rules'  : SERVICE_R1_R3_CONFIG_RULES,
+    'service_constraints'   : SERVICE_R1_R3_CONSTRAINTS,
 })
diff --git a/src/service/tests/ServiceHandler_L3NM_OC.py b/src/service/tests/ServiceHandler_L3NM_OC.py
new file mode 100644
index 000000000..a6940cbb3
--- /dev/null
+++ b/src/service/tests/ServiceHandler_L3NM_OC.py
@@ -0,0 +1,135 @@
+import uuid
+from typing import Dict, List, Tuple
+from common.tools.object_factory.ConfigRule import json_config_rule_set
+from common.tools.object_factory.Constraint import json_constraint
+from common.tools.object_factory.Device import (
+    json_device_connect_rules, json_device_emulated_packet_router_disabled, json_device_emulated_tapi_disabled,
+    json_device_id)
+from common.tools.object_factory.EndPoint import json_endpoint, json_endpoint_id
+from common.tools.object_factory.Link import json_link, json_link_id
+from common.tools.object_factory.Service import json_service_id, json_service_l3nm_planned
+from .CommonObjects import CONTEXT, CONTEXT_ID, PACKET_PORT_SAMPLE_TYPES, TOPOLOGY, TOPOLOGY_ID
+
+SERVICE_HANDLER_NAME = 'l3nm_openconfig'
+
+def json_endpoint_ids(device_id : Dict, endpoint_descriptors : List[Tuple[str, str]]):
+    return [
+        json_endpoint_id(device_id, ep_uuid, topology_id=TOPOLOGY_ID)
+        for ep_uuid, _ in endpoint_descriptors
+    ]
+
+def json_endpoints(device_id : Dict, endpoint_descriptors : List[Tuple[str, str]]):
+    return [
+        json_endpoint(device_id, ep_uuid, ep_type, topology_id=TOPOLOGY_ID, kpi_sample_types=PACKET_PORT_SAMPLE_TYPES)
+        for ep_uuid, ep_type in endpoint_descriptors
+    ]
+
+# ----- Devices --------------------------------------------------------------------------------------------------------
+DEVICE_R1_UUID          = 'R1'
+DEVICE_R1_ENDPOINT_DEFS = [('EP1', 'optical'), ('EP100', 'copper')]
+DEVICE_R1_ADDRESS       = '10.0.0.1'
+DEVICE_R1_PORT          = 830
+DEVICE_R1_USERNAME      = 'admin'
+DEVICE_R1_PASSWORD      = 'admin'
+DEVICE_R1_TIMEOUT       = 120
+DEVICE_R1_ID            = json_device_id(DEVICE_R1_UUID)
+DEVICE_R1_ENDPOINTS     = json_endpoints(DEVICE_R1_ID, DEVICE_R1_ENDPOINT_DEFS)
+DEVICE_R1_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_R1_ID, DEVICE_R1_ENDPOINT_DEFS)
+DEVICE_R1               = json_device_emulated_packet_router_disabled(DEVICE_R1_UUID, endpoints=DEVICE_R1_ENDPOINTS)
+ENDPOINT_ID_R1_EP1      = DEVICE_R1_ENDPOINT_IDS[0]
+ENDPOINT_ID_R1_EP100    = DEVICE_R1_ENDPOINT_IDS[1]
+DEVICE_R1_CONNECT_RULES = json_device_connect_rules(DEVICE_R1_ADDRESS, DEVICE_R1_PORT, {
+    'username': DEVICE_R1_USERNAME,
+    'password': DEVICE_R1_PASSWORD,
+    'timeout' : DEVICE_R1_TIMEOUT,
+})
+
+
+DEVICE_R2_UUID          = 'R2'
+DEVICE_R2_ENDPOINT_DEFS = [('EP1', 'optical'), ('EP100', 'copper')]
+DEVICE_R2_ADDRESS       = '10.0.0.2'
+DEVICE_R2_PORT          = 830
+DEVICE_R2_USERNAME      = 'admin'
+DEVICE_R2_PASSWORD      = 'admin'
+DEVICE_R2_TIMEOUT       = 120
+DEVICE_R2_ID            = json_device_id(DEVICE_R2_UUID)
+DEVICE_R2_ENDPOINTS     = json_endpoints(DEVICE_R2_ID, DEVICE_R2_ENDPOINT_DEFS)
+DEVICE_R2_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_R2_ID, DEVICE_R2_ENDPOINT_DEFS)
+DEVICE_R2               = json_device_emulated_packet_router_disabled(DEVICE_R2_UUID, endpoints=DEVICE_R2_ENDPOINTS)
+ENDPOINT_ID_R2_EP1      = DEVICE_R2_ENDPOINT_IDS[0]
+ENDPOINT_ID_R2_EP100    = DEVICE_R2_ENDPOINT_IDS[1]
+DEVICE_R2_CONNECT_RULES = json_device_connect_rules(DEVICE_R2_ADDRESS, DEVICE_R2_PORT, {
+    'username': DEVICE_R2_USERNAME,
+    'password': DEVICE_R2_PASSWORD,
+    'timeout' : DEVICE_R2_TIMEOUT,
+})
+
+
+DEVICE_O1_UUID          = 'O1'
+DEVICE_O1_ENDPOINT_DEFS = [(str(uuid.uuid4()), 'optical'), (str(uuid.uuid4()), 'optical')]
+DEVICE_O1_ADDRESS       = '10.0.0.3'
+DEVICE_O1_PORT          = 4900
+DEVICE_O1_TIMEOUT       = 120
+DEVICE_O1_ID            = json_device_id(DEVICE_O1_UUID)
+DEVICE_O1_ENDPOINTS     = json_endpoints(DEVICE_O1_ID, DEVICE_O1_ENDPOINT_DEFS)
+DEVICE_O1_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_O1_ID, DEVICE_O1_ENDPOINT_DEFS)
+DEVICE_O1               = json_device_emulated_tapi_disabled(DEVICE_O1_UUID, endpoints=DEVICE_O1_ENDPOINTS)
+ENDPOINT_ID_O1_EP1      = DEVICE_O1_ENDPOINT_IDS[0]
+ENDPOINT_ID_O1_EP2      = DEVICE_O1_ENDPOINT_IDS[1]
+DEVICE_O1_CONNECT_RULES = json_device_connect_rules(DEVICE_O1_ADDRESS, DEVICE_O1_PORT, {
+    'timeout' : DEVICE_O1_TIMEOUT,
+})
+
+
+# ----- Links ----------------------------------------------------------------------------------------------------------
+LINK_R1_O1_UUID = '{:s}/{:s}-{:s}/{:s}'.format(
+    DEVICE_R1_UUID, ENDPOINT_ID_R1_EP1['endpoint_uuid']['uuid'],
+    DEVICE_O1_UUID, ENDPOINT_ID_O1_EP1['endpoint_uuid']['uuid'])
+LINK_R1_O1_ID   = json_link_id(LINK_R1_O1_UUID)
+LINK_R1_O1      = json_link(LINK_R1_O1_UUID, [ENDPOINT_ID_R1_EP1, ENDPOINT_ID_O1_EP1])
+
+
+LINK_R2_O1_UUID = '{:s}/{:s}-{:s}/{:s}'.format(
+    DEVICE_R2_UUID, ENDPOINT_ID_R2_EP1['endpoint_uuid']['uuid'],
+    DEVICE_O1_UUID, ENDPOINT_ID_O1_EP2['endpoint_uuid']['uuid'])
+LINK_R2_O1_ID   = json_link_id(LINK_R2_O1_UUID)
+LINK_R2_O1      = json_link(LINK_R2_O1_UUID, [ENDPOINT_ID_R2_EP1, ENDPOINT_ID_O1_EP2])
+
+
+# ----- Service --------------------------------------------------------------------------------------------------------
+SERVICE_R1_R2_UUID         = 'SVC:{:s}/{:s}-{:s}/{:s}'.format(
+    DEVICE_R1_UUID, ENDPOINT_ID_R1_EP100['endpoint_uuid']['uuid'],
+    DEVICE_R2_UUID, ENDPOINT_ID_R2_EP100['endpoint_uuid']['uuid'])
+SERVICE_R1_R2_ENDPOINT_IDS = [ENDPOINT_ID_R1_EP100, ENDPOINT_ID_R2_EP100]
+SERVICE_R1_R2_CONSTRAINTS  = [
+    json_constraint('latency_ms', 15.2),
+    json_constraint('jitter_us', 1.2),
+]
+SERVICE_R1_R2_CONFIG_RULES = [
+    json_config_rule_set(
+        'settings',
+        {'route_distinguisher': '60001:801', 'mtu': 1512, 'address_families': ['IPV4']}),
+    json_config_rule_set(
+        'device[{:s}]/endpoint[{:s}]/settings'.format(DEVICE_R1_UUID, ENDPOINT_ID_R1_EP100['endpoint_uuid']['uuid']),
+        {'router_id': '10.0.0.1', 'sub_interface_index': 1}),
+    json_config_rule_set(
+        'device[{:s}]/endpoint[{:s}]/settings'.format(DEVICE_R2_UUID, ENDPOINT_ID_R2_EP100['endpoint_uuid']['uuid']),
+        {'router_id': '10.0.0.3', 'sub_interface_index': 1}),
+]
+SERVICE_R1_R2_ID           = json_service_id(SERVICE_R1_R2_UUID, context_id=CONTEXT_ID)
+SERVICE_R1_R2_DESCRIPTOR   = json_service_l3nm_planned(SERVICE_R1_R2_UUID)
+
+
+# ----- Test Descriptor ------------------------------------------------------------------------------------------------
+TEST_SERVICE_HANDLER = (SERVICE_HANDLER_NAME, {
+    'contexts'              : [CONTEXT],
+    'topologies'            : [TOPOLOGY],
+    'devices'               : [DEVICE_R1, DEVICE_R2, DEVICE_O1],
+    'links'                 : [LINK_R1_O1, LINK_R2_O1],
+
+    'service_id'            : SERVICE_R1_R2_ID,
+    'service_descriptor'    : SERVICE_R1_R2_DESCRIPTOR,
+    'service_endpoint_ids'  : SERVICE_R1_R2_ENDPOINT_IDS,
+    'service_config_rules'  : SERVICE_R1_R2_CONFIG_RULES,
+    'service_constraints'   : SERVICE_R1_R2_CONSTRAINTS,
+})
diff --git a/src/service/tests/test_unitary.py b/src/service/tests/test_unitary.py
index e03f2017a..298318a0e 100644
--- a/src/service/tests/test_unitary.py
+++ b/src/service/tests/test_unitary.py
@@ -1,30 +1,14 @@
 import copy, grpc, logging, os, pytest
-from typing import Tuple
-from google.protobuf.json_format import MessageToDict
-from common.orm.Database import Database
-from common.orm.Factory import get_database_backend, BackendEnum as DatabaseBackendEnum
-from common.message_broker.Factory import get_messagebroker_backend, BackendEnum as MessageBrokerBackendEnum
-from common.message_broker.MessageBroker import MessageBroker
+from common.tests.MockService import MockService
+from common.tests.MockServicerImpl_Context import MockServicerImpl_Context
+from common.tests.MockServicerImpl_Device import MockServicerImpl_Device
 from common.tests.PytestGenerateTests import pytest_generate_tests # (required) pylint: disable=unused-import
-from context.Config import (
-    GRPC_SERVICE_PORT as CONTEXT_GRPC_SERVICE_PORT, GRPC_MAX_WORKERS as CONTEXT_GRPC_MAX_WORKERS,
-    GRPC_GRACE_PERIOD as CONTEXT_GRPC_GRACE_PERIOD)
+from common.tools.grpc.Tools import grpc_message_to_json_string
 from context.client.ContextClient import ContextClient
-from context.proto.context_pb2 import Context, DeviceId, Topology, Device
-from context.service.grpc_server.ContextService import ContextService
-from device.Config import (
-    GRPC_SERVICE_PORT as DEVICE_GRPC_SERVICE_PORT, GRPC_MAX_WORKERS as DEVICE_GRPC_MAX_WORKERS,
-    GRPC_GRACE_PERIOD as DEVICE_GRPC_GRACE_PERIOD)
+from context.proto.context_pb2 import Context, ContextId, DeviceId, Link, LinkId, Topology, Device, TopologyId
+from context.proto.context_pb2_grpc import add_ContextServiceServicer_to_server
 from device.client.DeviceClient import DeviceClient
-from device.service.DeviceService import DeviceService
-from device.service.driver_api.DriverFactory import DriverFactory
-from device.service.driver_api.DriverInstanceCache import DriverInstanceCache
-from device.service.drivers import DRIVERS
-from device.tests.MockMonitoringService import MockMonitoringService
-from monitoring.Config import (
-    GRPC_SERVICE_PORT as MONITORING_GRPC_SERVICE_PORT, GRPC_MAX_WORKERS as MONITORING_GRPC_MAX_WORKERS,
-    GRPC_GRACE_PERIOD as MONITORING_GRPC_GRACE_PERIOD)
-from monitoring.client.monitoring_client import MonitoringClient
+from device.proto.device_pb2_grpc import add_DeviceServiceServicer_to_server
 from service.Config import (
     GRPC_SERVICE_PORT as SERVICE_GRPC_SERVICE_PORT, GRPC_MAX_WORKERS as SERVICE_GRPC_MAX_WORKERS,
     GRPC_GRACE_PERIOD as SERVICE_GRPC_GRACE_PERIOD)
@@ -33,88 +17,47 @@ from service.proto.context_pb2 import Service, ServiceId
 from service.service.ServiceService import ServiceService
 from service.service.service_handler_api.ServiceHandlerFactory import ServiceHandlerFactory
 from service.service.service_handlers import SERVICE_HANDLERS
-from .CommonObjects import CONTEXT, TOPOLOGY
 
 LOGGER = logging.getLogger(__name__)
 LOGGER.setLevel(logging.DEBUG)
 
-CONTEXT_GRPC_SERVICE_PORT = 10000 + CONTEXT_GRPC_SERVICE_PORT # avoid privileged ports
-DEVICE_GRPC_SERVICE_PORT = 10000 + DEVICE_GRPC_SERVICE_PORT # avoid privileged ports
-SERVICE_GRPC_SERVICE_PORT = 10000 + SERVICE_GRPC_SERVICE_PORT # avoid privileged ports
-MONITORING_GRPC_SERVICE_PORT = 10000 + MONITORING_GRPC_SERVICE_PORT # avoid privileged ports
-
-DEFAULT_REDIS_SERVICE_HOST = '127.0.0.1'
-DEFAULT_REDIS_SERVICE_PORT = 6379
-DEFAULT_REDIS_DATABASE_ID  = 0
-
-REDIS_CONFIG = {
-    'REDIS_SERVICE_HOST': os.environ.get('REDIS_SERVICE_HOST', DEFAULT_REDIS_SERVICE_HOST),
-    'REDIS_SERVICE_PORT': os.environ.get('REDIS_SERVICE_PORT', DEFAULT_REDIS_SERVICE_PORT),
-    'REDIS_DATABASE_ID' : os.environ.get('REDIS_DATABASE_ID',  DEFAULT_REDIS_DATABASE_ID ),
-}
-
-SCENARIOS = [
-    ('all_inmemory', DatabaseBackendEnum.INMEMORY, {},           MessageBrokerBackendEnum.INMEMORY, {}          ),
-    #('all_redis',    DatabaseBackendEnum.REDIS,    REDIS_CONFIG, MessageBrokerBackendEnum.REDIS,    REDIS_CONFIG),
-]
-
-@pytest.fixture(scope='session', ids=[str(scenario[0]) for scenario in SCENARIOS], params=SCENARIOS)
-def context_db_mb(request) -> Tuple[Database, MessageBroker]:
-    name,db_backend,db_settings,mb_backend,mb_settings = request.param
-    msg = 'Running scenario {:s} db_backend={:s}, db_settings={:s}, mb_backend={:s}, mb_settings={:s}...'
-    LOGGER.info(msg.format(str(name), str(db_backend.value), str(db_settings), str(mb_backend.value), str(mb_settings)))
-    _database = Database(get_database_backend(backend=db_backend, **db_settings))
-    _message_broker = MessageBroker(get_messagebroker_backend(backend=mb_backend, **mb_settings))
-    yield _database, _message_broker
-    _message_broker.terminate()
+LOCALHOST = '127.0.0.1'
+MOCKSERVER_GRPC_PORT = 10000
 
-@pytest.fixture(scope='session')
-def context_service(context_db_mb : Tuple[Database, MessageBroker]): # pylint: disable=redefined-outer-name
-    _service = ContextService(
-        context_db_mb[0], context_db_mb[1], port=CONTEXT_GRPC_SERVICE_PORT, max_workers=CONTEXT_GRPC_MAX_WORKERS,
-        grace_period=CONTEXT_GRPC_GRACE_PERIOD)
-    _service.start()
-    yield _service
-    _service.stop()
+class MockService_Combined(MockService):
+    # Mock Server implementing Context and Service to simplify unitary tests of Compute
 
-@pytest.fixture(scope='session')
-def context_client(context_service : ContextService): # pylint: disable=redefined-outer-name
-    _client = ContextClient(address='127.0.0.1', port=CONTEXT_GRPC_SERVICE_PORT)
-    yield _client
-    _client.close()
+    def __init__(self, cls_name='MockService_Service'):
+        super().__init__(LOCALHOST, MOCKSERVER_GRPC_PORT, cls_name=cls_name)
 
-@pytest.fixture(scope='session')
-def monitoring_service():
-    _service = MockMonitoringService(port=MONITORING_GRPC_SERVICE_PORT, max_workers=MONITORING_GRPC_MAX_WORKERS,
-        grace_period=MONITORING_GRPC_GRACE_PERIOD)
-    _service.start()
-    yield _service
-    _service.stop()
+    # pylint: disable=attribute-defined-outside-init
+    def install_servicers(self):
+        self.context_servicer = MockServicerImpl_Context()
+        add_ContextServiceServicer_to_server(self.context_servicer, self.server)
+        self.device_servicer = MockServicerImpl_Device()
+        add_DeviceServiceServicer_to_server(self.device_servicer, self.server)
 
-@pytest.fixture(scope='session')
-def monitoring_client(monitoring_service : MockMonitoringService): # pylint: disable=redefined-outer-name
-    _client = MonitoringClient(server='127.0.0.1', port=MONITORING_GRPC_SERVICE_PORT)
-    #yield _client
-    #_client.close()
-    return _client
+os.environ['CONTEXTSERVICE_SERVICE_HOST'] = LOCALHOST
+os.environ['CONTEXTSERVICE_SERVICE_PORT_GRPC'] = str(MOCKSERVER_GRPC_PORT)
+os.environ['DEVICESERVICE_SERVICE_HOST'] = LOCALHOST
+os.environ['DEVICESERVICE_SERVICE_PORT_GRPC'] = str(MOCKSERVER_GRPC_PORT)
 
 @pytest.fixture(scope='session')
-def device_service(
-    context_client : ContextClient,         # pylint: disable=redefined-outer-name
-    monitoring_client : MonitoringClient):  # pylint: disable=redefined-outer-name
-
-    _driver_factory = DriverFactory(DRIVERS)
-    _driver_instance_cache = DriverInstanceCache(_driver_factory)
-    _service = DeviceService(
-        context_client, monitoring_client, _driver_instance_cache, port=DEVICE_GRPC_SERVICE_PORT,
-        max_workers=DEVICE_GRPC_MAX_WORKERS, grace_period=DEVICE_GRPC_GRACE_PERIOD)
+def mockservice():
+    _service = MockService_Combined()
     _service.start()
     yield _service
     _service.stop()
 
 @pytest.fixture(scope='session')
-def device_client(device_service : DeviceService): # pylint: disable=redefined-outer-name
-    _client = DeviceClient(address='127.0.0.1', port=DEVICE_GRPC_SERVICE_PORT)
+def context_client(mockservice : MockService_Combined): # pylint: disable=redefined-outer-name
+    _client = ContextClient(address=LOCALHOST, port=MOCKSERVER_GRPC_PORT)
+    yield _client
+    _client.close()
+
+@pytest.fixture(scope='session')
+def device_client(mockservice : MockService_Combined): # pylint: disable=redefined-outer-name
+    _client = DeviceClient(address=LOCALHOST, port=MOCKSERVER_GRPC_PORT)
     yield _client
     _client.close()
 
@@ -133,14 +76,10 @@ def service_service(
 
 @pytest.fixture(scope='session')
 def service_client(service_service : ServiceService): # pylint: disable=redefined-outer-name
-    _client = ServiceClient(address='127.0.0.1', port=SERVICE_GRPC_SERVICE_PORT)
+    _client = ServiceClient(address=LOCALHOST, port=SERVICE_GRPC_SERVICE_PORT)
     yield _client
     _client.close()
 
-def grpc_message_to_json_string(message):
-    return str(MessageToDict(
-        message, including_default_value_fields=True, preserving_proto_field_name=True, use_integers_for_enums=False))
-
 try:
     from .ServiceHandlersToTest import SERVICE_HANDLERS_TO_TEST
 except ImportError:
@@ -152,21 +91,19 @@ class TestServiceHandlers:
 
     def test_prepare_environment(
         self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints,
-        service_device_uuids, get_device_descriptor, get_connect_rules,
+        contexts, topologies, devices, links,
         context_client : ContextClient, # pylint: disable=redefined-outer-name
         device_client : DeviceClient):  # pylint: disable=redefined-outer-name
 
-        context_client.SetContext(Context(**CONTEXT))
-        context_client.SetTopology(Topology(**TOPOLOGY))
+        for context in contexts: context_client.SetContext(Context(**context))
+        for topology in topologies: context_client.SetTopology(Topology(**topology))
+        for device in devices: device_client.AddDevice(Device(**device))
+        for link in links: context_client.SetLink(Link(**link))
 
-        for device_uuid in service_device_uuids:
-            device_with_connect_rules = copy.deepcopy(get_device_descriptor(device_uuid))
-            device_with_connect_rules['device_config']['config_rules'].extend(get_connect_rules(device_uuid))
-            device_client.AddDevice(Device(**device_with_connect_rules))
 
     def test_service_create_error_cases(
         self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints,
-        service_device_uuids, get_device_descriptor, get_connect_rules,
+        contexts, topologies, devices, links,
         service_client : ServiceClient):    # pylint: disable=redefined-outer-name
 
         with pytest.raises(grpc.RpcError) as e:
@@ -205,7 +142,7 @@ class TestServiceHandlers:
 
     def test_service_create_correct(
         self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints,
-        service_device_uuids, get_device_descriptor, get_connect_rules,
+        contexts, topologies, devices, links,
         service_client : ServiceClient):    # pylint: disable=redefined-outer-name
 
         service_client.CreateService(Service(**service_descriptor))
@@ -213,20 +150,19 @@ class TestServiceHandlers:
 
     def test_service_get_created(
         self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints,
-        service_device_uuids, get_device_descriptor, get_connect_rules,
+        contexts, topologies, devices, links,
         context_client : ContextClient):    # pylint: disable=redefined-outer-name
 
         service_data = context_client.GetService(ServiceId(**service_id))
         LOGGER.info('service_data = {:s}'.format(grpc_message_to_json_string(service_data)))
 
 
-    def test_service_update(
+    def test_service_update_configure(
         self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints,
-        service_device_uuids, get_device_descriptor, get_connect_rules,
+        contexts, topologies, devices, links,
         context_client : ContextClient,     # pylint: disable=redefined-outer-name
         service_client : ServiceClient):    # pylint: disable=redefined-outer-name
 
-        # Configure
         service_with_settings = copy.deepcopy(service_descriptor)
         service_with_settings['service_endpoint_ids'].extend(service_endpoint_ids)
         service_with_settings['service_config']['config_rules'].extend(service_config_rules)
@@ -240,7 +176,13 @@ class TestServiceHandlers:
                 LOGGER.info('device_data[{:s}][#{:d}] => {:s}'.format(
                     str(device_id), i, grpc_message_to_json_string(config_rule)))
 
-        # Deconfigure
+
+    def test_service_update_deconfigure(
+        self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints,
+        contexts, topologies, devices, links,
+        context_client : ContextClient,     # pylint: disable=redefined-outer-name
+        service_client : ServiceClient):    # pylint: disable=redefined-outer-name
+
         service_with_settings = copy.deepcopy(service_descriptor)
         service_with_settings['service_endpoint_ids'].extend([]) # remove endpoints
         service_client.UpdateService(Service(**service_with_settings))
@@ -255,7 +197,7 @@ class TestServiceHandlers:
 
     def test_service_get_updated(
         self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints,
-        service_device_uuids, get_device_descriptor, get_connect_rules,
+        contexts, topologies, devices, links,
         context_client : ContextClient):    # pylint: disable=redefined-outer-name
 
         service_data = context_client.GetService(ServiceId(**service_id))
@@ -264,7 +206,19 @@ class TestServiceHandlers:
 
     def test_service_delete(
         self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints,
-        service_device_uuids, get_device_descriptor, get_connect_rules,
+        contexts, topologies, devices, links,
         service_client : ServiceClient):    # pylint: disable=redefined-outer-name
 
         service_client.DeleteService(ServiceId(**service_id))
+
+
+    def test_cleanup_environment(
+        self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints,
+        contexts, topologies, devices, links,
+        context_client : ContextClient, # pylint: disable=redefined-outer-name
+        device_client : DeviceClient):  # pylint: disable=redefined-outer-name
+
+        for link in links: context_client.RemoveLink(LinkId(**link['link_id']))
+        for device in devices: device_client.DeleteDevice(DeviceId(**device['device_id']))
+        for topology in topologies: context_client.RemoveTopology(TopologyId(**topology['topology_id']))
+        for context in contexts: context_client.RemoveContext(ContextId(**context['context_id']))
diff --git a/src/tester_functional/.gitlab-ci.yml b/src/tester_functional/.gitlab-ci.yml
deleted file mode 100644
index 15f2cd434..000000000
--- a/src/tester_functional/.gitlab-ci.yml
+++ /dev/null
@@ -1,67 +0,0 @@
-# Build, tag, and push the Docker images to the GitLab Docker registry
-build funct_test:
-  variables:
-    IMAGE_NAME: 'tester_functional' # 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 build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile ./src/
-    - docker tag "$IMAGE_NAME:$IMAGE_TAG" "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG"
-    - docker push "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG"
-  rules:
-    - changes:
-      - src/common/**
-      - src/context/**
-      - src/device/**
-      - src/service/**
-      - src/$IMAGE_NAME/**
-      - .gitlab-ci.yml
-
-# Pull, execute, and run unitary tests for the Docker image from the GitLab registry
-unit_test funct_test:
-  variables:
-    IMAGE_NAME: 'tester_functional' # name of the microservice
-    IMAGE_TAG: 'latest' # tag of the container image (production, development, etc)
-  stage: test
-  needs:
-    - build funct_test
-  before_script:
-    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
-  script:
-    - docker pull "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG"
-  rules:
-    - changes:
-      - src/common/**
-      - src/context/**
-      - src/device/**
-      - src/service/**
-      - src/$IMAGE_NAME/**
-      - .gitlab-ci.yml
-
-# Run functional tests in Kubernetes Cluster
-funct_test execute:
-  variables:
-    IMAGE_NAME: 'tester_functional' # name of the microservice
-    IMAGE_TAG: 'latest' # tag of the container image (production, development, etc)
-  stage: funct_test
-  needs:
-    - build funct_test
-    - unit_test funct_test
-    - deploy context
-    - deploy device
-    - deploy service
-    - dependencies all
-    - integ_test execute
-  before_script:
-    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
-  script:
-    - kubectl version
-    - kubectl get all
-    - kubectl delete pod $(echo $IMAGE_NAME | sed -r 's/[^a-zA-Z0-9\.\-]/-/g') --wait=true --ignore-not-found=true
-    - kubectl get all
-    - kubectl run $(echo $IMAGE_NAME | sed -r 's/[^a-zA-Z0-9\.\-]/-/g') --image "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG" --restart=Never -i --rm
-    - kubectl get all
-  #when: manual
-  #allow_failure: false
diff --git a/src/tester_functional/Dockerfile b/src/tester_functional/Dockerfile
deleted file mode 100644
index 36883f30b..000000000
--- a/src/tester_functional/Dockerfile
+++ /dev/null
@@ -1,35 +0,0 @@
-FROM python:3-slim
-
-# Install dependencies
-RUN apt-get --yes --quiet --quiet update && \
-    apt-get --yes --quiet --quiet install wget g++ && \
-    rm -rf /var/lib/apt/lists/*
-
-# Set Python to show logs as they occur
-ENV PYTHONUNBUFFERED=0
-
-# Get generic Python packages
-RUN python3 -m pip install --upgrade pip setuptools wheel pip-tools
-
-# Set working directory
-WORKDIR /var/teraflow
-
-# Create module sub-folders
-RUN mkdir -p /var/teraflow/tester_functional
-
-# Get Python packages per module
-COPY tester_functional/requirements.in tester_functional/requirements.in
-RUN pip-compile --output-file=tester_functional/requirements.txt tester_functional/requirements.in
-RUN python3 -m pip install -r tester_functional/requirements.in
-
-# Add files into working directory
-COPY common/. common
-COPY context/. context
-COPY device/. device
-COPY service/. service
-COPY tester_functional/. tester_functional
-
-# Run integration tester
-ENTRYPOINT ["pytest", "-v", "--log-level=DEBUG", \
-            "tester_functional/test_context_device_service.py" \
-]
diff --git a/src/tester_functional/definitions.py b/src/tester_functional/definitions.py
deleted file mode 100644
index 2b38e74bc..000000000
--- a/src/tester_functional/definitions.py
+++ /dev/null
@@ -1,165 +0,0 @@
-import copy
-from common.database.api.context.Constants import DEFAULT_CONTEXT_ID, DEFAULT_TOPOLOGY_ID
-from common.database.api.context.service.ServiceState import ServiceState
-from common.database.api.context.service.ServiceType import ServiceType
-from common.database.api.context.topology.device.OperationalStatus import OperationalStatus
-
-# use "copy.deepcopy" to prevent propagating forced changes during tests
-dc = copy.deepcopy
-
-CONTEXT_ID = {'contextUuid': {'uuid': DEFAULT_CONTEXT_ID}}
-
-TOPOLOGY_ID = {'contextId': dc(CONTEXT_ID), 'topoId': {'uuid': DEFAULT_TOPOLOGY_ID}}
-
-DEVICE_ID_DEV1 = {'device_id': {'uuid': 'dev1'}}
-DEVICE_DEV1 = {
-    'device_id': dc(DEVICE_ID_DEV1), 'device_type': 'ROADM', 'device_config': {'device_config': '<config/>'},
-    'devOperationalStatus': OperationalStatus.ENABLED.value,
-    'endpointList' : [
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV1), 'port_id': {'uuid' : 'port2'}},
-         'port_type': 'WDM'},
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV1), 'port_id': {'uuid' : 'port3'}},
-         'port_type': 'WDM'},
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV1), 'port_id': {'uuid' : 'port101'}},
-         'port_type': 'OCH'},
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV1), 'port_id': {'uuid' : 'port102'}},
-         'port_type': 'OCH'},
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV1), 'port_id': {'uuid' : 'port103'}},
-         'port_type': 'OCH'},
-    ]
-}
-
-DEVICE_ID_DEV2 = {'device_id': {'uuid': 'dev2'}}
-DEVICE_DEV2 = {
-    'device_id': dc(DEVICE_ID_DEV2), 'device_type': 'ROADM', 'device_config': {'device_config': '<config/>'},
-    'devOperationalStatus': OperationalStatus.ENABLED.value,
-    'endpointList' : [
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV2), 'port_id': {'uuid' : 'port1'}},
-         'port_type': 'WDM'},
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV2), 'port_id': {'uuid' : 'port3'}},
-         'port_type': 'WDM'},
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV2), 'port_id': {'uuid' : 'port101'}},
-         'port_type': 'OCH'},
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV2), 'port_id': {'uuid' : 'port102'}},
-         'port_type': 'OCH'},
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV2), 'port_id': {'uuid' : 'port103'}},
-         'port_type': 'OCH'},
-    ]
-}
-
-DEVICE_ID_DEV3 = {'device_id': {'uuid': 'dev3'}}
-DEVICE_DEV3 = {
-    'device_id': dc(DEVICE_ID_DEV3), 'device_type': 'ROADM', 'device_config': {'device_config': '<config/>'},
-    'devOperationalStatus': OperationalStatus.ENABLED.value,
-    'endpointList' : [
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV3), 'port_id': {'uuid' : 'port1'}},
-         'port_type': 'WDM'},
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV3), 'port_id': {'uuid' : 'port2'}},
-         'port_type': 'WDM'},
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV3), 'port_id': {'uuid' : 'port101'}},
-         'port_type': 'OCH'},
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV3), 'port_id': {'uuid' : 'port102'}},
-         'port_type': 'OCH'},
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV3), 'port_id': {'uuid' : 'port103'}},
-         'port_type': 'OCH'},
-    ]
-}
-
-LINK_ID_DEV1_DEV2 = {'link_id': {'uuid': 'dev1/port2 ==> dev2/port1'}}
-LINK_DEV1_DEV2 = {
-    'link_id': dc(LINK_ID_DEV1_DEV2),
-    'endpointList' : [
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV1), 'port_id': {'uuid' : 'port2'}},
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV2), 'port_id': {'uuid' : 'port1'}},
-    ]
-}
-
-LINK_ID_DEV1_DEV3 = {'link_id': {'uuid': 'dev1/port3 ==> dev3/port1'}}
-LINK_DEV1_DEV3 = {
-    'link_id': dc(LINK_ID_DEV1_DEV3),
-    'endpointList' : [
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV1), 'port_id': {'uuid' : 'port3'}},
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV3), 'port_id': {'uuid' : 'port1'}},
-    ]
-}
-
-LINK_ID_DEV2_DEV1 = {'link_id': {'uuid': 'dev2/port1 ==> dev1/port2'}}
-LINK_DEV2_DEV1 = {
-    'link_id': dc(LINK_ID_DEV2_DEV1),
-    'endpointList' : [
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV2), 'port_id': {'uuid' : 'port1'}},
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV1), 'port_id': {'uuid' : 'port2'}},
-    ]
-}
-
-LINK_ID_DEV2_DEV3 = {'link_id': {'uuid': 'dev2/port3 ==> dev3/port2'}}
-LINK_DEV2_DEV3 = {
-    'link_id': dc(LINK_ID_DEV2_DEV3),
-    'endpointList' : [
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV2), 'port_id': {'uuid' : 'port3'}},
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV3), 'port_id': {'uuid' : 'port2'}},
-    ]
-}
-
-LINK_ID_DEV3_DEV1 = {'link_id': {'uuid': 'dev3/port1 ==> dev1/port3'}}
-LINK_DEV3_DEV1 = {
-    'link_id': dc(LINK_ID_DEV3_DEV1),
-    'endpointList' : [
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV3), 'port_id': {'uuid' : 'port1'}},
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV1), 'port_id': {'uuid' : 'port3'}},
-    ]
-}
-
-LINK_ID_DEV3_DEV2 = {'link_id': {'uuid': 'dev3/port2 ==> dev2/port3'}}
-LINK_DEV3_DEV2 = {
-    'link_id': dc(LINK_ID_DEV3_DEV2),
-    'endpointList' : [
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV3), 'port_id': {'uuid' : 'port2'}},
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV2), 'port_id': {'uuid' : 'port3'}},
-    ]
-}
-
-SERVICE_ID_SVC1 = {'contextId': dc(CONTEXT_ID), 'cs_id': {'uuid': 'svc1'}}
-SERVICE_SVC1 = {
-    'cs_id': dc(SERVICE_ID_SVC1), 'serviceType': ServiceType.L3NM.value,
-    'serviceConfig': {'serviceConfig': '<config/>'}, 'serviceState': {'serviceState': ServiceState.PLANNED.value},
-    'constraint': [
-        {'constraint_type': 'latency_ms', 'constraint_value': '100'},
-        {'constraint_type': 'hops', 'constraint_value': '5'},
-    ],
-    'endpointList' : [
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV1), 'port_id': {'uuid' : 'port101'}},
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV2), 'port_id': {'uuid' : 'port101'}},
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV3), 'port_id': {'uuid' : 'port101'}},
-    ]
-}
-
-SERVICE_ID_SVC2 = {'contextId': dc(CONTEXT_ID), 'cs_id': {'uuid': 'svc2'}}
-SERVICE_SVC2 = {
-    'cs_id': dc(SERVICE_ID_SVC2), 'serviceType': ServiceType.L3NM.value,
-    'serviceConfig': {'serviceConfig': '<config/>'}, 'serviceState': {'serviceState': ServiceState.PLANNED.value},
-    'constraint': [
-        {'constraint_type': 'latency_ms', 'constraint_value': '100'},
-        {'constraint_type': 'hops', 'constraint_value': '5'},
-    ],
-    'endpointList' : [
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV1), 'port_id': {'uuid' : 'port102'}},
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV2), 'port_id': {'uuid' : 'port102'}},
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV3), 'port_id': {'uuid' : 'port102'}},
-    ]
-}
-
-SERVICE_ID_SVC3 = {'contextId': dc(CONTEXT_ID), 'cs_id': {'uuid': 'svc3'}}
-SERVICE_SVC3 = {
-    'cs_id': dc(SERVICE_ID_SVC3), 'serviceType': ServiceType.L3NM.value,
-    'serviceConfig': {'serviceConfig': '<config/>'}, 'serviceState': {'serviceState': ServiceState.PLANNED.value},
-    'constraint': [
-        {'constraint_type': 'latency_ms', 'constraint_value': '100'},
-        {'constraint_type': 'hops', 'constraint_value': '5'},
-    ],
-    'endpointList' : [
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV1), 'port_id': {'uuid' : 'port103'}},
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV2), 'port_id': {'uuid' : 'port103'}},
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV3), 'port_id': {'uuid' : 'port103'}},
-    ]
-}
diff --git a/src/tester_functional/requirements.in b/src/tester_functional/requirements.in
deleted file mode 100644
index 25abdad1b..000000000
--- a/src/tester_functional/requirements.in
+++ /dev/null
@@ -1,6 +0,0 @@
-grpcio-health-checking
-grpcio
-prometheus-client
-pytest
-pytest-benchmark
-redis
diff --git a/src/tester_functional/test_context_device_service.py b/src/tester_functional/test_context_device_service.py
deleted file mode 100644
index 6483569de..000000000
--- a/src/tester_functional/test_context_device_service.py
+++ /dev/null
@@ -1,102 +0,0 @@
-import logging, pytest
-from google.protobuf.json_format import MessageToDict
-from common.Settings import get_setting
-from common.database.Factory import get_database, DatabaseEngineEnum
-from common.database.api.Database import Database
-from common.tests.Assertions import validate_device_id, validate_link_id, validate_service_id, \
-    validate_service_list_is_not_empty, validate_topology_has_devices, validate_topology_has_links, \
-    validate_topology_is_empty
-from context.client.ContextClient import ContextClient
-from context.proto.context_pb2 import Device, Empty, Link
-from device.client.DeviceClient import DeviceClient
-from tester_functional.definitions import DEVICE_DEV1, DEVICE_DEV2, DEVICE_DEV3
-from tester_functional.definitions import LINK_DEV1_DEV2, LINK_DEV1_DEV3, LINK_DEV2_DEV1, LINK_DEV2_DEV3, \
-    LINK_DEV3_DEV1, LINK_DEV3_DEV2
-from tester_functional.definitions import SERVICE_SVC1, SERVICE_SVC2, SERVICE_SVC3
-from service.client.ServiceClient import ServiceClient
-from service.proto.service_pb2 import Service
-
-LOGGER = logging.getLogger(__name__)
-LOGGER.setLevel(logging.DEBUG)
-
-@pytest.fixture(scope='session')
-def redis_database():
-    _database = get_database(engine=DatabaseEngineEnum.REDIS, REDIS_DATABASE_ID=0)
-    return _database
-
-@pytest.fixture(scope='session')
-def context_client():
-    service_host = get_setting('CONTEXTSERVICE_SERVICE_HOST')
-    service_port = get_setting('CONTEXTSERVICE_SERVICE_PORT_GRPC')
-    _client = ContextClient(address=service_host, port=service_port)
-    yield _client
-    _client.close()
-
-@pytest.fixture(scope='session')
-def device_client():
-    service_host = get_setting('DEVICESERVICE_SERVICE_HOST')
-    service_port = get_setting('DEVICESERVICE_SERVICE_PORT_GRPC')
-    _client = DeviceClient(address=service_host, port=service_port)
-    yield _client
-    _client.close()
-
-@pytest.fixture(scope='session')
-def service_client():
-    service_host = get_setting('SERVICESERVICE_SERVICE_HOST')
-    service_port = get_setting('SERVICESERVICE_SERVICE_PORT_GRPC')
-    _client = ServiceClient(address=service_host, port=service_port)
-    yield _client
-    _client.close()
-
-def test_clean_database(redis_database : Database):
-    # should work
-    redis_database.clear_all()
-
-def test_get_topology_empty(context_client : ContextClient):
-    # should work
-    validate_topology_is_empty(MessageToDict(
-        context_client.GetTopology(Empty()),
-        including_default_value_fields=True, preserving_proto_field_name=True,
-        use_integers_for_enums=False))
-
-def test_add_devices(context_client : ContextClient, device_client : DeviceClient):
-    # should work
-    for device in [DEVICE_DEV1, DEVICE_DEV2, DEVICE_DEV3]:
-        validate_device_id(MessageToDict(
-            device_client.AddDevice(Device(**device)),
-            including_default_value_fields=True, preserving_proto_field_name=True,
-            use_integers_for_enums=False))
-
-    # should work
-    validate_topology_has_devices(MessageToDict(
-        context_client.GetTopology(Empty()),
-        including_default_value_fields=True, preserving_proto_field_name=True,
-        use_integers_for_enums=False))
-
-def test_add_links(context_client : ContextClient):
-    # should work
-    for link in [LINK_DEV1_DEV2, LINK_DEV1_DEV3, LINK_DEV2_DEV1, LINK_DEV2_DEV3, LINK_DEV3_DEV1, LINK_DEV3_DEV2]:
-        validate_link_id(MessageToDict(
-            context_client.AddLink(Link(**link)),
-            including_default_value_fields=True, preserving_proto_field_name=True,
-            use_integers_for_enums=False))
-
-    # should work
-    validate_topology_has_links(MessageToDict(
-        context_client.GetTopology(Empty()),
-        including_default_value_fields=True, preserving_proto_field_name=True,
-        use_integers_for_enums=False))
-
-def test_add_services(service_client : ServiceClient):
-    # should work
-    for service in [SERVICE_SVC1, SERVICE_SVC2, SERVICE_SVC3]:
-        validate_service_id(MessageToDict(
-            service_client.CreateService(Service(**service)),
-            including_default_value_fields=True, preserving_proto_field_name=True,
-            use_integers_for_enums=False))
-
-    # should work
-    validate_service_list_is_not_empty(MessageToDict(
-        service_client.GetServiceList(Empty()),
-        including_default_value_fields=True, preserving_proto_field_name=True,
-        use_integers_for_enums=False))
diff --git a/src/tester_integration/.gitlab-ci.yml b/src/tester_integration/.gitlab-ci.yml
deleted file mode 100644
index 02eccbc9b..000000000
--- a/src/tester_integration/.gitlab-ci.yml
+++ /dev/null
@@ -1,78 +0,0 @@
-# Build, tag, and push the Docker images to the GitLab Docker registry
-build integ_test:
-  variables:
-    IMAGE_NAME: 'tester_integration' # name of the microservice
-    IMAGE_NAME_TEST: 'tester_integration-test' # 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 build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile ./src/
-    - docker tag "$IMAGE_NAME:$IMAGE_TAG" "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG"
-    - docker push "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG"
-  rules:
-    - changes:
-      - src/common/**
-      - src/context/**
-      - src/device/**
-      - src/service/**
-      - src/$IMAGE_NAME/**
-      - .gitlab-ci.yml
-
-# Pull, execute, and run unitary tests for the Docker image from the GitLab registry
-unit_test integ_test:
-  variables:
-    IMAGE_NAME: 'tester_functional' # name of the microservice
-    IMAGE_TAG: 'latest' # tag of the container image (production, development, etc)
-  stage: test
-  needs:
-    - build integ_test
-  before_script:
-    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
-  script:
-    - docker pull "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG"
-  rules:
-    - changes:
-      - src/common/**
-      - src/context/**
-      - src/device/**
-      - src/service/**
-      - src/$IMAGE_NAME/**
-      - .gitlab-ci.yml
-
-# Pull, execute, and run integration tests for the Docker image from the GitLab registry
-integ_test execute:
-  variables:
-    IMAGE_NAME: 'tester_integration' # name of the microservice
-    IMAGE_NAME_TEST: 'tester_integration-test' # name of the microservice
-    IMAGE_TAG: 'latest' # tag of the container image (production, development, etc)
-  stage: integ_test
-  needs:
-    - build integ_test
-    - unit_test context
-    - unit_test device
-    - unit_test service
-    - unit_test integ_test
-    - dependencies all
-  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  
-  script:
-    - docker pull "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG"
-    - docker run -d -p 6379:6379 --name redis --network=teraflowbridge "redis:6.2"
-    - docker ps -a
-    - sleep 5
-    - docker ps -a
-    - docker run -d --name $IMAGE_NAME --network=teraflowbridge --env "DB_ENGINE=redis" --env "REDIS_SERVICE_HOST=$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' redis)" --env "REDIS_SERVICE_PORT=6379" --env "REDIS_DATABASE_ID=0" "$IMAGE_NAME:$IMAGE_TAG" bash -c "pytest --log-level=INFO --verbose common/database/tests/test_engine_redis.py tester_integration/test_context_device_service.py"
-  after_script:
-    - docker stop $IMAGE_NAME redis
-    - docker rm $IMAGE_NAME redis
-  rules:
-    - changes:
-      - src/common/**
-      - src/context/**
-      - src/device/**
-      - src/service/**
-      - src/$IMAGE_NAME/**
-      - .gitlab-ci.yml
diff --git a/src/tester_integration/Dockerfile b/src/tester_integration/Dockerfile
deleted file mode 100644
index 31ab8884b..000000000
--- a/src/tester_integration/Dockerfile
+++ /dev/null
@@ -1,35 +0,0 @@
-FROM python:3-slim
-
-# Install dependencies
-RUN apt-get --yes --quiet --quiet update && \
-    apt-get --yes --quiet --quiet install wget g++ && \
-    rm -rf /var/lib/apt/lists/*
-
-# Set Python to show logs as they occur
-ENV PYTHONUNBUFFERED=0
-
-# Get generic Python packages
-RUN python3 -m pip install --upgrade pip setuptools wheel pip-tools
-
-# Set working directory
-WORKDIR /var/teraflow
-
-# Create module sub-folders
-RUN mkdir -p /var/teraflow/tester_integration
-
-# Get Python packages per module
-COPY tester_integration/requirements.in tester_integration/requirements.in
-RUN pip-compile --output-file=tester_integration/requirements.txt tester_integration/requirements.in
-RUN python3 -m pip install -r tester_integration/requirements.in
-
-# Add files into working directory
-COPY common/. common
-COPY context/. context
-COPY device/. device
-COPY service/. service
-COPY tester_integration/. tester_integration
-
-# Run integration tester
-ENTRYPOINT ["pytest", "-v", "--log-level=DEBUG", \
-            "tester_integration/test_context_device_service.py" \
-]
diff --git a/src/tester_integration/definitions.py b/src/tester_integration/definitions.py
deleted file mode 100644
index 2b38e74bc..000000000
--- a/src/tester_integration/definitions.py
+++ /dev/null
@@ -1,165 +0,0 @@
-import copy
-from common.database.api.context.Constants import DEFAULT_CONTEXT_ID, DEFAULT_TOPOLOGY_ID
-from common.database.api.context.service.ServiceState import ServiceState
-from common.database.api.context.service.ServiceType import ServiceType
-from common.database.api.context.topology.device.OperationalStatus import OperationalStatus
-
-# use "copy.deepcopy" to prevent propagating forced changes during tests
-dc = copy.deepcopy
-
-CONTEXT_ID = {'contextUuid': {'uuid': DEFAULT_CONTEXT_ID}}
-
-TOPOLOGY_ID = {'contextId': dc(CONTEXT_ID), 'topoId': {'uuid': DEFAULT_TOPOLOGY_ID}}
-
-DEVICE_ID_DEV1 = {'device_id': {'uuid': 'dev1'}}
-DEVICE_DEV1 = {
-    'device_id': dc(DEVICE_ID_DEV1), 'device_type': 'ROADM', 'device_config': {'device_config': '<config/>'},
-    'devOperationalStatus': OperationalStatus.ENABLED.value,
-    'endpointList' : [
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV1), 'port_id': {'uuid' : 'port2'}},
-         'port_type': 'WDM'},
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV1), 'port_id': {'uuid' : 'port3'}},
-         'port_type': 'WDM'},
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV1), 'port_id': {'uuid' : 'port101'}},
-         'port_type': 'OCH'},
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV1), 'port_id': {'uuid' : 'port102'}},
-         'port_type': 'OCH'},
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV1), 'port_id': {'uuid' : 'port103'}},
-         'port_type': 'OCH'},
-    ]
-}
-
-DEVICE_ID_DEV2 = {'device_id': {'uuid': 'dev2'}}
-DEVICE_DEV2 = {
-    'device_id': dc(DEVICE_ID_DEV2), 'device_type': 'ROADM', 'device_config': {'device_config': '<config/>'},
-    'devOperationalStatus': OperationalStatus.ENABLED.value,
-    'endpointList' : [
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV2), 'port_id': {'uuid' : 'port1'}},
-         'port_type': 'WDM'},
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV2), 'port_id': {'uuid' : 'port3'}},
-         'port_type': 'WDM'},
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV2), 'port_id': {'uuid' : 'port101'}},
-         'port_type': 'OCH'},
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV2), 'port_id': {'uuid' : 'port102'}},
-         'port_type': 'OCH'},
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV2), 'port_id': {'uuid' : 'port103'}},
-         'port_type': 'OCH'},
-    ]
-}
-
-DEVICE_ID_DEV3 = {'device_id': {'uuid': 'dev3'}}
-DEVICE_DEV3 = {
-    'device_id': dc(DEVICE_ID_DEV3), 'device_type': 'ROADM', 'device_config': {'device_config': '<config/>'},
-    'devOperationalStatus': OperationalStatus.ENABLED.value,
-    'endpointList' : [
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV3), 'port_id': {'uuid' : 'port1'}},
-         'port_type': 'WDM'},
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV3), 'port_id': {'uuid' : 'port2'}},
-         'port_type': 'WDM'},
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV3), 'port_id': {'uuid' : 'port101'}},
-         'port_type': 'OCH'},
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV3), 'port_id': {'uuid' : 'port102'}},
-         'port_type': 'OCH'},
-        {'port_id': {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV3), 'port_id': {'uuid' : 'port103'}},
-         'port_type': 'OCH'},
-    ]
-}
-
-LINK_ID_DEV1_DEV2 = {'link_id': {'uuid': 'dev1/port2 ==> dev2/port1'}}
-LINK_DEV1_DEV2 = {
-    'link_id': dc(LINK_ID_DEV1_DEV2),
-    'endpointList' : [
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV1), 'port_id': {'uuid' : 'port2'}},
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV2), 'port_id': {'uuid' : 'port1'}},
-    ]
-}
-
-LINK_ID_DEV1_DEV3 = {'link_id': {'uuid': 'dev1/port3 ==> dev3/port1'}}
-LINK_DEV1_DEV3 = {
-    'link_id': dc(LINK_ID_DEV1_DEV3),
-    'endpointList' : [
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV1), 'port_id': {'uuid' : 'port3'}},
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV3), 'port_id': {'uuid' : 'port1'}},
-    ]
-}
-
-LINK_ID_DEV2_DEV1 = {'link_id': {'uuid': 'dev2/port1 ==> dev1/port2'}}
-LINK_DEV2_DEV1 = {
-    'link_id': dc(LINK_ID_DEV2_DEV1),
-    'endpointList' : [
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV2), 'port_id': {'uuid' : 'port1'}},
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV1), 'port_id': {'uuid' : 'port2'}},
-    ]
-}
-
-LINK_ID_DEV2_DEV3 = {'link_id': {'uuid': 'dev2/port3 ==> dev3/port2'}}
-LINK_DEV2_DEV3 = {
-    'link_id': dc(LINK_ID_DEV2_DEV3),
-    'endpointList' : [
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV2), 'port_id': {'uuid' : 'port3'}},
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV3), 'port_id': {'uuid' : 'port2'}},
-    ]
-}
-
-LINK_ID_DEV3_DEV1 = {'link_id': {'uuid': 'dev3/port1 ==> dev1/port3'}}
-LINK_DEV3_DEV1 = {
-    'link_id': dc(LINK_ID_DEV3_DEV1),
-    'endpointList' : [
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV3), 'port_id': {'uuid' : 'port1'}},
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV1), 'port_id': {'uuid' : 'port3'}},
-    ]
-}
-
-LINK_ID_DEV3_DEV2 = {'link_id': {'uuid': 'dev3/port2 ==> dev2/port3'}}
-LINK_DEV3_DEV2 = {
-    'link_id': dc(LINK_ID_DEV3_DEV2),
-    'endpointList' : [
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV3), 'port_id': {'uuid' : 'port2'}},
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV2), 'port_id': {'uuid' : 'port3'}},
-    ]
-}
-
-SERVICE_ID_SVC1 = {'contextId': dc(CONTEXT_ID), 'cs_id': {'uuid': 'svc1'}}
-SERVICE_SVC1 = {
-    'cs_id': dc(SERVICE_ID_SVC1), 'serviceType': ServiceType.L3NM.value,
-    'serviceConfig': {'serviceConfig': '<config/>'}, 'serviceState': {'serviceState': ServiceState.PLANNED.value},
-    'constraint': [
-        {'constraint_type': 'latency_ms', 'constraint_value': '100'},
-        {'constraint_type': 'hops', 'constraint_value': '5'},
-    ],
-    'endpointList' : [
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV1), 'port_id': {'uuid' : 'port101'}},
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV2), 'port_id': {'uuid' : 'port101'}},
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV3), 'port_id': {'uuid' : 'port101'}},
-    ]
-}
-
-SERVICE_ID_SVC2 = {'contextId': dc(CONTEXT_ID), 'cs_id': {'uuid': 'svc2'}}
-SERVICE_SVC2 = {
-    'cs_id': dc(SERVICE_ID_SVC2), 'serviceType': ServiceType.L3NM.value,
-    'serviceConfig': {'serviceConfig': '<config/>'}, 'serviceState': {'serviceState': ServiceState.PLANNED.value},
-    'constraint': [
-        {'constraint_type': 'latency_ms', 'constraint_value': '100'},
-        {'constraint_type': 'hops', 'constraint_value': '5'},
-    ],
-    'endpointList' : [
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV1), 'port_id': {'uuid' : 'port102'}},
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV2), 'port_id': {'uuid' : 'port102'}},
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV3), 'port_id': {'uuid' : 'port102'}},
-    ]
-}
-
-SERVICE_ID_SVC3 = {'contextId': dc(CONTEXT_ID), 'cs_id': {'uuid': 'svc3'}}
-SERVICE_SVC3 = {
-    'cs_id': dc(SERVICE_ID_SVC3), 'serviceType': ServiceType.L3NM.value,
-    'serviceConfig': {'serviceConfig': '<config/>'}, 'serviceState': {'serviceState': ServiceState.PLANNED.value},
-    'constraint': [
-        {'constraint_type': 'latency_ms', 'constraint_value': '100'},
-        {'constraint_type': 'hops', 'constraint_value': '5'},
-    ],
-    'endpointList' : [
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV1), 'port_id': {'uuid' : 'port103'}},
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV2), 'port_id': {'uuid' : 'port103'}},
-        {'topoId': dc(TOPOLOGY_ID), 'dev_id': dc(DEVICE_ID_DEV3), 'port_id': {'uuid' : 'port103'}},
-    ]
-}
diff --git a/src/tester_integration/requirements.in b/src/tester_integration/requirements.in
deleted file mode 100644
index 25abdad1b..000000000
--- a/src/tester_integration/requirements.in
+++ /dev/null
@@ -1,6 +0,0 @@
-grpcio-health-checking
-grpcio
-prometheus-client
-pytest
-pytest-benchmark
-redis
diff --git a/src/tester_integration/test_context_device_service.py b/src/tester_integration/test_context_device_service.py
deleted file mode 100644
index 2d128800c..000000000
--- a/src/tester_integration/test_context_device_service.py
+++ /dev/null
@@ -1,138 +0,0 @@
-import logging, pytest
-from google.protobuf.json_format import MessageToDict
-from common.database.Factory import get_database, DatabaseEngineEnum
-from common.database.api.Database import Database
-from common.tests.Assertions import validate_device_id, validate_link_id, validate_service_id, \
-    validate_service_list_is_not_empty, validate_topology_has_devices, validate_topology_has_links, \
-    validate_topology_is_empty
-from context.Config import GRPC_SERVICE_PORT as GRPC_CONTEXT_SERVICE_PORT, \
-    GRPC_MAX_WORKERS as GRPC_CONTEXT_MAX_WORKERS, GRPC_GRACE_PERIOD as GRPC_CONTEXT_GRACE_PERIOD
-from context.client.ContextClient import ContextClient
-from context.proto.context_pb2 import Device, Empty, Link
-from context.service.ContextService import ContextService
-from device.Config import GRPC_SERVICE_PORT as GRPC_DEVICE_SERVICE_PORT, \
-    GRPC_MAX_WORKERS as GRPC_DEVICE_MAX_WORKERS, GRPC_GRACE_PERIOD as GRPC_DEVICE_GRACE_PERIOD
-from device.client.DeviceClient import DeviceClient
-from device.service.DeviceService import DeviceService
-from service.service.ServiceService import ServiceService
-from tester_integration.definitions import DEVICE_DEV1, DEVICE_DEV2, DEVICE_DEV3
-from tester_integration.definitions import LINK_DEV1_DEV2, LINK_DEV1_DEV3, LINK_DEV2_DEV1, LINK_DEV2_DEV3, \
-    LINK_DEV3_DEV1, LINK_DEV3_DEV2
-from tester_integration.definitions import SERVICE_SVC1, SERVICE_SVC2, SERVICE_SVC3
-from service.Config import GRPC_SERVICE_PORT as GRPC_SERVICE_SERVICE_PORT, \
-    GRPC_MAX_WORKERS as GRPC_SERVICE_MAX_WORKERS, GRPC_GRACE_PERIOD as GRPC_SERVICE_GRACE_PERIOD
-from service.client.ServiceClient import ServiceClient
-from service.proto.service_pb2 import Service
-
-PORT_CONTEXT = 10000 + GRPC_CONTEXT_SERVICE_PORT # avoid privileged ports
-PORT_DEVICE  = 10000 + GRPC_DEVICE_SERVICE_PORT  # avoid privileged ports
-PORT_SERVICE = 10000 + GRPC_SERVICE_SERVICE_PORT # avoid privileged ports
-
-LOGGER = logging.getLogger(__name__)
-LOGGER.setLevel(logging.DEBUG)
-
-@pytest.fixture(scope='session')
-def redis_database():
-    _database = get_database(engine=DatabaseEngineEnum.REDIS, REDIS_DATABASE_ID=0)
-    return _database
-
-@pytest.fixture(scope='session')
-def context_service(redis_database : Database):
-    context_database = get_database(engine=DatabaseEngineEnum.REDIS, REDIS_DATABASE_ID=0)
-    _service = ContextService(
-        context_database, port=PORT_CONTEXT, max_workers=GRPC_CONTEXT_MAX_WORKERS,
-        grace_period=GRPC_CONTEXT_GRACE_PERIOD)
-    _service.start()
-    yield _service
-    _service.stop()
-
-@pytest.fixture(scope='session')
-def context_client(context_service):
-    _client = ContextClient(address='127.0.0.1', port=PORT_CONTEXT)
-    yield _client
-    _client.close()
-
-@pytest.fixture(scope='session')
-def device_service(redis_database : Database):
-    device_database = get_database(engine=DatabaseEngineEnum.REDIS, REDIS_DATABASE_ID=0)
-    _service = DeviceService(
-        device_database, port=PORT_DEVICE, max_workers=GRPC_DEVICE_MAX_WORKERS,
-        grace_period=GRPC_DEVICE_GRACE_PERIOD)
-    _service.start()
-    yield _service
-    _service.stop()
-
-@pytest.fixture(scope='session')
-def device_client(device_service):
-    _client = DeviceClient(address='127.0.0.1', port=PORT_DEVICE)
-    yield _client
-    _client.close()
-
-@pytest.fixture(scope='session')
-def service_service(redis_database : Database):
-    service_database = get_database(engine=DatabaseEngineEnum.REDIS, REDIS_DATABASE_ID=0)
-    _service = ServiceService(
-        service_database, port=PORT_SERVICE, max_workers=GRPC_SERVICE_MAX_WORKERS,
-        grace_period=GRPC_SERVICE_GRACE_PERIOD)
-    _service.start()
-    yield _service
-    _service.stop()
-
-@pytest.fixture(scope='session')
-def service_client(service_service):
-    _client = ServiceClient(address='127.0.0.1', port=PORT_SERVICE)
-    yield _client
-    _client.close()
-
-def test_clean_database(redis_database : Database):
-    # should work
-    redis_database.clear_all()
-
-def test_get_topology_empty(context_client : ContextClient):
-    # should work
-    validate_topology_is_empty(MessageToDict(
-        context_client.GetTopology(Empty()),
-        including_default_value_fields=True, preserving_proto_field_name=True,
-        use_integers_for_enums=False))
-
-def test_add_devices(context_client : ContextClient, device_client : DeviceClient):
-    # should work
-    for device in [DEVICE_DEV1, DEVICE_DEV2, DEVICE_DEV3]:
-        validate_device_id(MessageToDict(
-            device_client.AddDevice(Device(**device)),
-            including_default_value_fields=True, preserving_proto_field_name=True,
-            use_integers_for_enums=False))
-
-    # should work
-    validate_topology_has_devices(MessageToDict(
-        context_client.GetTopology(Empty()),
-        including_default_value_fields=True, preserving_proto_field_name=True,
-        use_integers_for_enums=False))
-
-def test_add_links(context_client : ContextClient):
-    # should work
-    for link in [LINK_DEV1_DEV2, LINK_DEV1_DEV3, LINK_DEV2_DEV1, LINK_DEV2_DEV3, LINK_DEV3_DEV1, LINK_DEV3_DEV2]:
-        validate_link_id(MessageToDict(
-            context_client.AddLink(Link(**link)),
-            including_default_value_fields=True, preserving_proto_field_name=True,
-            use_integers_for_enums=False))
-
-    # should work
-    validate_topology_has_links(MessageToDict(
-        context_client.GetTopology(Empty()),
-        including_default_value_fields=True, preserving_proto_field_name=True,
-        use_integers_for_enums=False))
-
-def test_add_services(service_client : ServiceClient):
-    # should work
-    for service in [SERVICE_SVC1, SERVICE_SVC2, SERVICE_SVC3]:
-        validate_service_id(MessageToDict(
-            service_client.CreateService(Service(**service)),
-            including_default_value_fields=True, preserving_proto_field_name=True,
-            use_integers_for_enums=False))
-
-    # should work
-    validate_service_list_is_not_empty(MessageToDict(
-        service_client.GetServiceList(Empty()),
-        including_default_value_fields=True, preserving_proto_field_name=True,
-        use_integers_for_enums=False))
diff --git a/src/tests/.gitlab-ci.yml b/src/tests/.gitlab-ci.yml
new file mode 100644
index 000000000..1d0bd49d4
--- /dev/null
+++ b/src/tests/.gitlab-ci.yml
@@ -0,0 +1,3 @@
+# include the individual .gitlab-ci.yml of each integration test
+include:
+  - local: '/src/tests/ofc22_bootstrap_monitor_l3vpn/.gitlab-ci.yml'
diff --git a/src/tests/__init__.py b/src/tests/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/tests/ofc22/README.md b/src/tests/ofc22/README.md
new file mode 100644
index 000000000..7c8e52be2
--- /dev/null
+++ b/src/tests/ofc22/README.md
@@ -0,0 +1,93 @@
+# OFC'22 Demo - Bootstrap devices, Monitor device Endpoints, Manage L3VPN Services
+This functional test reproduces the live demonstration "Demonstration of Zero-touch Device and L3-VPN Service
+Management Using the TeraFlow Cloud-native SDN Controller" carried out at
+[OFC'22](https://www.ofcconference.org/en-us/home/program-speakers/demo/).
+
+## Functional test folder
+This functional test can be found in folder `./src/tests/ofc22/`. A convenience alias `./ofc22/` pointing to that folder has been defined.
+
+## Execute with real devices
+This functional test is designed to operate both with real and emulated devices.
+By default, emulated devices are used; however, if you have access to real devices, feel free to modify the files `./ofc22/tests/Objects.py` and `./ofc22/tests/Credentials.py` to point to your devices, and map to your network topology.
+Note that the default scenario assumes devices R2 and R4 are always emulated, while devices R1, R3, and O1 can be configured as emulated or real devices.
+
+__Important:__ The OpenConfigDriver and the TrandportApiDriver are not completed. The configuration options they support are limited, and the monitoring functionality is not implemented. Use them with caution.
+
+## Deployment
+To run this functional test, it is assumed you have deployed a Kubernetes-based environment as described in [Wiki: Installing Kubernetes on your Linux machine](https://gitlab.com/teraflow-h2020/controller/-/wikis/Installing-Kubernetes-on-your-Linux-machine).
+
+After installing Kubernetes, you can run it to deploy the appropriate components. Feel free to adapt it your particular case following the instructions described in [Wiki: Deploying a TeraFlow OS test instance](https://gitlab.com/teraflow-h2020/controller/-/wikis/Deploying-a-TeraFlow-OS-test-instance).
+
+For your convenience, the configuration s sript `./ofc22/deploy_in_kubernetes.sh` has been already defined. The script will take some minutes to download the dependencies, build the micro-services, deploy them, and leave them ready for operation. The deployment will finish with a report of the items that have been created.
+
+## Access to the WebUI and Dashboard
+When the deployment completes, you can connect to the TeraFlow OS WebUI and Dashboards as described in [Wiki: Using the WebUI](https://gitlab.com/teraflow-h2020/controller/-/wikis/Using-the-WebUI), or directly navigating to `http://[your-node-ip]:30800` for the WebUI and `http://[your-node-ip]:30300` for the Grafana Dashboard.
+
+Notes:
+- the default credentials for the Grafana Dashboiard is user/pass: `admin`/`admin123+`.
+- in Grafana, you can find the "L3-Monitorng" in the "Starred dashboards" section.
+
+## Test execution
+To execute this functional test, four main steps needs to be carried out:
+1. Device bootstrapping
+2. L3VPN Service creation
+3. L3VPN Service removal
+4. Cleanup
+
+Upon the execution of each test progresses, a report will be generated indicating PASSED / FAILED / SKIPPED. If there is some error during the execution, you should see a detailed report on the error. See the troubleshooting section in that case.
+
+Feel free to check the logs of the different components using the appropriate `ofc22/show_logs_[component].sh` scripts after you execute each step.
+
+### 1. Device bootstrapping
+
+This step configures some basic entities (Context and Topology), the devices, and the links in the topology. The expected results are:
+- The devices to be incorporated into the Topology.
+- The devices to be pre-configured and initialized as ENABLED by the Automation component.
+- The monitoring for the device ports (named as endpoints in TeraFlow OS) to be activated and data collection to automatically start.
+- The links to be added to the topology.
+
+To run this step, execute the following script:
+`./ofc22/run_test_01_bootstrap.sh`
+
+When the script finishes, check in the Grafana L3-Monitoring Dashboard and you should see the monitoring data being plotted and updated every 5 seconds (by default). Given that there is no service configured, you should see a 0-valued flat plot.
+
+In the WebUI, select the "admin" Context. In the "Devices" tab you should see that 5 different emulated devices have been created and activated: 4 packet routers, and 1 optical line system controller. Besides, in the "Services" tab you should see that there is no service created. Note here that the emulated devices produce synthetic randomly-generated data and do not care about the services configured.
+
+### 2. L3VPN Service creation
+
+This step configures a new service emulating the request an OSM WIM would make by means of a Mock OSM instance.
+
+To run this step, execute the following script:
+`./ofc22/run_test_02_create_service.sh`
+
+When the script finishes, check the WebUI "Services" tab. You should see that two services have been created, one for the optical layer and another for the packet layer. Besides, you can check the "Devices" tab to see the configuration rules that have been configured in each device. In the Grafana Dashboard, given that there is now a service configured, you should see the plots with the monitored data for the device. By default, device R1-INF is selected.
+
+### 3. L3VPN Service removal
+
+This step deconfigures the previously created services emulating the request an OSM WIM would make by means of a Mock OSM instance.
+
+To run this step, execute the following script:
+`./ofc22/run_test_03_delete_service.sh`
+
+When the script finishes, check the WebUI "Services" tab. You should see that the two services have been removed. Besides, in the "Devices" tab you can see that the appropriate configuration rules have been deconfigured. In the Grafana Dashboard, given that there is no service configured, you should see a 0-valued flat plot again.
+
+### 4. Cleanup
+
+This last step just performs a cleanup of the scenario removing all the TeraFlow OS entities for completeness.
+
+To run this step, execute the following script:
+`./ofc22/run_test_04_cleanup.sh`
+
+When the script finishes, check the WebUI "Devices" tab, you should see that the devices have been removed. Besides, in the "Services" tab you can see that the "admin" Context has no services given that that context has been removed.
+
+## Troubleshooting
+
+Different scripts are provided to help in troubleshooting issues in the execution of the test. These scripts are:
+- `./ofc22/show_deployment.sh`: this script reports the items belonging to this deployment. Use it to validate that all the pods, deployments and replica sets are ready and have a state of "running"; and the services are deployed and have appropriate IP addresses and ports.
+- `ofc22/show_logs_automation.sh`: this script reports the logs for the automation component.
+- `ofc22/show_logs_compute.sh`: this script reports the logs for the compute component.
+- `ofc22/show_logs_context.sh`: this script reports the logs for the context component.
+- `ofc22/show_logs_device.sh`: this script reports the logs for the device component.
+- `ofc22/show_logs_monitoring.sh`: this script reports the logs for the monitoring component.
+- `ofc22/show_logs_service.sh`: this script reports the logs for the service component.
+- `ofc22/show_logs_webui.sh`: this script reports the logs for the webui component.
diff --git a/src/tests/ofc22/__init__.py b/src/tests/ofc22/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/tests/ofc22/deploy_in_kubernetes.sh b/src/tests/ofc22/deploy_in_kubernetes.sh
new file mode 100755
index 000000000..48c96382a
--- /dev/null
+++ b/src/tests/ofc22/deploy_in_kubernetes.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# OFC 22 deployment settings
+
+export REGISTRY_IMAGE=""
+export COMPONENTS="context device service compute webui automation monitoring"
+export IMAGE_TAG="ofc22"
+export K8S_NAMESPACE="ofc22"
+export K8S_HOSTNAME="kubernetes-master"
+export EXTRA_MANIFESTS="./ofc22/expose_services.yaml"
+export GRAFANA_PASSWORD="admin123+"
+
+./deploy_in_kubernetes.sh
diff --git a/src/tests/ofc22/expose_services.yaml b/src/tests/ofc22/expose_services.yaml
new file mode 100644
index 000000000..4f553e2d6
--- /dev/null
+++ b/src/tests/ofc22/expose_services.yaml
@@ -0,0 +1,57 @@
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: contextservice-public
+  labels:
+    app: contextservice
+spec:
+  type: NodePort
+  selector:
+    app: contextservice
+  ports:
+  - name: grpc
+    protocol: TCP
+    port: 1010
+    targetPort: 1010
+    nodePort: 30101
+  - name: redis
+    protocol: TCP
+    port: 6379
+    targetPort: 6379
+    nodePort: 30637
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: deviceservice-public
+  labels:
+    app: deviceservice
+spec:
+  type: NodePort
+  selector:
+    app: deviceservice
+  ports:
+  - name: grpc
+    protocol: TCP
+    port: 2020
+    targetPort: 2020
+    nodePort: 30202
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: monitoringservice-public
+  labels:
+    app: monitoringservice
+spec:
+  type: NodePort
+  selector:
+    app: monitoringservice
+  ports:
+  - name: influx
+    protocol: TCP
+    port: 8086
+    targetPort: 8086
+    nodePort: 30886
+---
diff --git a/src/tests/ofc22/run_test_01_bootstrap.sh b/src/tests/ofc22/run_test_01_bootstrap.sh
new file mode 100755
index 000000000..7c2655609
--- /dev/null
+++ b/src/tests/ofc22/run_test_01_bootstrap.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+PROJECTDIR=`pwd`
+
+cd $PROJECTDIR/src
+RCFILE=$PROJECTDIR/coverage/.coveragerc
+COVERAGEFILE=$PROJECTDIR/coverage/.coverage
+
+# Set the name of the Kubernetes namespace to deploy to.
+K8S_NAMESPACE="ofc22"
+K8S_NODENAME="kubernetes-master"
+
+# Flush Context database
+kubectl --namespace $K8S_NAMESPACE exec -it deployment/contextservice --container redis -- redis-cli FLUSHALL
+
+export CONTEXTSERVICE_SERVICE_HOST=$(kubectl get node $K8S_NODENAME -o 'jsonpath={.status.addresses[?(@.type=="InternalIP")].address}')
+export CONTEXTSERVICE_SERVICE_PORT_GRPC=$(kubectl get service contextservice-public --namespace $K8S_NAMESPACE -o 'jsonpath={.spec.ports[?(@.port==1010)].nodePort}')
+export DEVICESERVICE_SERVICE_HOST=$(kubectl get node $K8S_NODENAME -o 'jsonpath={.status.addresses[?(@.type=="InternalIP")].address}')
+export DEVICESERVICE_SERVICE_PORT_GRPC=$(kubectl get service deviceservice-public --namespace $K8S_NAMESPACE -o 'jsonpath={.spec.ports[?(@.port==2020)].nodePort}')
+export COMPUTESERVICE_SERVICE_HOST=$(kubectl get node $K8S_NODENAME -o 'jsonpath={.status.addresses[?(@.type=="InternalIP")].address}')
+export COMPUTESERVICE_SERVICE_PORT_HTTP=$(kubectl get service computeservice-public --namespace $K8S_NAMESPACE -o 'jsonpath={.spec.ports[?(@.port==8080)].nodePort}')
+
+# Run integration tests and analyze coverage of code at same time
+
+coverage run --rcfile=$RCFILE --append -m pytest --log-level=INFO --verbose \
+    tests/ofc22/tests/test_functional_bootstrap.py
diff --git a/src/tests/ofc22/run_test_02_create_service.sh b/src/tests/ofc22/run_test_02_create_service.sh
new file mode 100755
index 000000000..f22e900da
--- /dev/null
+++ b/src/tests/ofc22/run_test_02_create_service.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+PROJECTDIR=`pwd`
+
+cd $PROJECTDIR/src
+RCFILE=$PROJECTDIR/coverage/.coveragerc
+COVERAGEFILE=$PROJECTDIR/coverage/.coverage
+
+# Set the name of the Kubernetes namespace to deploy to.
+K8S_NAMESPACE="ofc22"
+K8S_NODENAME="kubernetes-master"
+
+export CONTEXTSERVICE_SERVICE_HOST=$(kubectl get node $K8S_NODENAME -o 'jsonpath={.status.addresses[?(@.type=="InternalIP")].address}')
+export CONTEXTSERVICE_SERVICE_PORT_GRPC=$(kubectl get service contextservice-public --namespace $K8S_NAMESPACE -o 'jsonpath={.spec.ports[?(@.port==1010)].nodePort}')
+export DEVICESERVICE_SERVICE_HOST=$(kubectl get node $K8S_NODENAME -o 'jsonpath={.status.addresses[?(@.type=="InternalIP")].address}')
+export DEVICESERVICE_SERVICE_PORT_GRPC=$(kubectl get service deviceservice-public --namespace $K8S_NAMESPACE -o 'jsonpath={.spec.ports[?(@.port==2020)].nodePort}')
+export COMPUTESERVICE_SERVICE_HOST=$(kubectl get node $K8S_NODENAME -o 'jsonpath={.status.addresses[?(@.type=="InternalIP")].address}')
+export COMPUTESERVICE_SERVICE_PORT_HTTP=$(kubectl get service computeservice-public --namespace $K8S_NAMESPACE -o 'jsonpath={.spec.ports[?(@.port==8080)].nodePort}')
+
+# Run integration tests and analyze coverage of code at same time
+
+coverage run --rcfile=$RCFILE --append -m pytest --log-level=INFO --verbose \
+    tests/ofc22/tests/test_functional_create_service.py
diff --git a/src/tests/ofc22/run_test_03_delete_service.sh b/src/tests/ofc22/run_test_03_delete_service.sh
new file mode 100755
index 000000000..3719dd2f5
--- /dev/null
+++ b/src/tests/ofc22/run_test_03_delete_service.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+PROJECTDIR=`pwd`
+
+cd $PROJECTDIR/src
+RCFILE=$PROJECTDIR/coverage/.coveragerc
+COVERAGEFILE=$PROJECTDIR/coverage/.coverage
+
+# Set the name of the Kubernetes namespace to deploy to.
+K8S_NAMESPACE="ofc22"
+K8S_NODENAME="kubernetes-master"
+
+export CONTEXTSERVICE_SERVICE_HOST=$(kubectl get node $K8S_NODENAME -o 'jsonpath={.status.addresses[?(@.type=="InternalIP")].address}')
+export CONTEXTSERVICE_SERVICE_PORT_GRPC=$(kubectl get service contextservice-public --namespace $K8S_NAMESPACE -o 'jsonpath={.spec.ports[?(@.port==1010)].nodePort}')
+export DEVICESERVICE_SERVICE_HOST=$(kubectl get node $K8S_NODENAME -o 'jsonpath={.status.addresses[?(@.type=="InternalIP")].address}')
+export DEVICESERVICE_SERVICE_PORT_GRPC=$(kubectl get service deviceservice-public --namespace $K8S_NAMESPACE -o 'jsonpath={.spec.ports[?(@.port==2020)].nodePort}')
+export COMPUTESERVICE_SERVICE_HOST=$(kubectl get node $K8S_NODENAME -o 'jsonpath={.status.addresses[?(@.type=="InternalIP")].address}')
+export COMPUTESERVICE_SERVICE_PORT_HTTP=$(kubectl get service computeservice-public --namespace $K8S_NAMESPACE -o 'jsonpath={.spec.ports[?(@.port==8080)].nodePort}')
+
+# Run integration tests and analyze coverage of code at same time
+
+coverage run --rcfile=$RCFILE --append -m pytest --log-level=INFO --verbose \
+    tests/ofc22/tests/test_functional_delete_service.py
diff --git a/src/tests/ofc22/run_test_04_cleanup.sh b/src/tests/ofc22/run_test_04_cleanup.sh
new file mode 100755
index 000000000..608c44cad
--- /dev/null
+++ b/src/tests/ofc22/run_test_04_cleanup.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+PROJECTDIR=`pwd`
+
+cd $PROJECTDIR/src
+RCFILE=$PROJECTDIR/coverage/.coveragerc
+COVERAGEFILE=$PROJECTDIR/coverage/.coverage
+
+# Set the name of the Kubernetes namespace to deploy to.
+K8S_NAMESPACE="ofc22"
+K8S_NODENAME="kubernetes-master"
+
+export CONTEXTSERVICE_SERVICE_HOST=$(kubectl get node $K8S_NODENAME -o 'jsonpath={.status.addresses[?(@.type=="InternalIP")].address}')
+export CONTEXTSERVICE_SERVICE_PORT_GRPC=$(kubectl get service contextservice-public --namespace $K8S_NAMESPACE -o 'jsonpath={.spec.ports[?(@.port==1010)].nodePort}')
+export DEVICESERVICE_SERVICE_HOST=$(kubectl get node $K8S_NODENAME -o 'jsonpath={.status.addresses[?(@.type=="InternalIP")].address}')
+export DEVICESERVICE_SERVICE_PORT_GRPC=$(kubectl get service deviceservice-public --namespace $K8S_NAMESPACE -o 'jsonpath={.spec.ports[?(@.port==2020)].nodePort}')
+export COMPUTESERVICE_SERVICE_HOST=$(kubectl get node $K8S_NODENAME -o 'jsonpath={.status.addresses[?(@.type=="InternalIP")].address}')
+export COMPUTESERVICE_SERVICE_PORT_HTTP=$(kubectl get service computeservice-public --namespace $K8S_NAMESPACE -o 'jsonpath={.spec.ports[?(@.port==8080)].nodePort}')
+
+# Run integration tests and analyze coverage of code at same time
+
+coverage run --rcfile=$RCFILE --append -m pytest --log-level=INFO --verbose \
+    tests/ofc22/tests/test_functional_cleanup.py
diff --git a/src/tests/ofc22/show_deploy.sh b/src/tests/ofc22/show_deploy.sh
new file mode 100755
index 000000000..3a6e08c9e
--- /dev/null
+++ b/src/tests/ofc22/show_deploy.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+K8S_NAMESPACE="ofc22"
+kubectl --namespace $K8S_NAMESPACE get all
diff --git a/src/tests/ofc22/show_logs_automation.sh b/src/tests/ofc22/show_logs_automation.sh
new file mode 100755
index 000000000..43d865b15
--- /dev/null
+++ b/src/tests/ofc22/show_logs_automation.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+kubectl --namespace ofc22 logs deployment/automationservice
diff --git a/src/tests/ofc22/show_logs_compute.sh b/src/tests/ofc22/show_logs_compute.sh
new file mode 100755
index 000000000..02d720c94
--- /dev/null
+++ b/src/tests/ofc22/show_logs_compute.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+kubectl --namespace ofc22 logs deployment/computeservice
diff --git a/src/tests/ofc22/show_logs_context.sh b/src/tests/ofc22/show_logs_context.sh
new file mode 100755
index 000000000..4c301470f
--- /dev/null
+++ b/src/tests/ofc22/show_logs_context.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+kubectl --namespace ofc22 logs deployment/contextservice -c server
diff --git a/src/tests/ofc22/show_logs_device.sh b/src/tests/ofc22/show_logs_device.sh
new file mode 100755
index 000000000..e2370f8f0
--- /dev/null
+++ b/src/tests/ofc22/show_logs_device.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+kubectl --namespace ofc22 logs deployment/deviceservice
diff --git a/src/tests/ofc22/show_logs_monitoring.sh b/src/tests/ofc22/show_logs_monitoring.sh
new file mode 100755
index 000000000..46249f5c2
--- /dev/null
+++ b/src/tests/ofc22/show_logs_monitoring.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+kubectl --namespace ofc22 logs deployment/monitoringservice -c server
diff --git a/src/tests/ofc22/show_logs_service.sh b/src/tests/ofc22/show_logs_service.sh
new file mode 100755
index 000000000..14b590b0e
--- /dev/null
+++ b/src/tests/ofc22/show_logs_service.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+kubectl --namespace ofc22 logs deployment/serviceservice
diff --git a/src/tests/ofc22/show_logs_webui.sh b/src/tests/ofc22/show_logs_webui.sh
new file mode 100755
index 000000000..f4954aaa3
--- /dev/null
+++ b/src/tests/ofc22/show_logs_webui.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+kubectl --namespace ofc22 logs deployment/webuiservice -c server
diff --git a/src/tests/ofc22/tests/.gitignore b/src/tests/ofc22/tests/.gitignore
new file mode 100644
index 000000000..76cb708d1
--- /dev/null
+++ b/src/tests/ofc22/tests/.gitignore
@@ -0,0 +1,2 @@
+# Add here your files containing confidential testbed details such as IP addresses, ports, usernames, passwords, etc.
+Credentials.py
diff --git a/src/tests/ofc22/tests/Objects.py b/src/tests/ofc22/tests/Objects.py
new file mode 100644
index 000000000..00b4f4f1f
--- /dev/null
+++ b/src/tests/ofc22/tests/Objects.py
@@ -0,0 +1,218 @@
+from typing import Dict, List, Tuple
+from common.Constants import DEFAULT_CONTEXT_UUID, DEFAULT_TOPOLOGY_UUID
+from common.tools.object_factory.Context import json_context, json_context_id
+from common.tools.object_factory.Device import (
+    json_device_connect_rules, json_device_emulated_connect_rules, json_device_emulated_packet_router_disabled,
+    json_device_emulated_tapi_disabled, json_device_id, json_device_packetrouter_disabled, json_device_tapi_disabled)
+from common.tools.object_factory.EndPoint import json_endpoint, json_endpoint_id
+from common.tools.object_factory.Link import json_link, json_link_id
+from common.tools.object_factory.Topology import json_topology, json_topology_id
+from context.proto.kpi_sample_types_pb2 import KpiSampleType
+
+# ----- Context --------------------------------------------------------------------------------------------------------
+CONTEXT_ID = json_context_id(DEFAULT_CONTEXT_UUID)
+CONTEXT    = json_context(DEFAULT_CONTEXT_UUID)
+
+# ----- Topology -------------------------------------------------------------------------------------------------------
+TOPOLOGY_ID = json_topology_id(DEFAULT_TOPOLOGY_UUID, context_id=CONTEXT_ID)
+TOPOLOGY    = json_topology(DEFAULT_TOPOLOGY_UUID, context_id=CONTEXT_ID)
+
+# ----- Monitoring Samples ---------------------------------------------------------------------------------------------
+PACKET_PORT_SAMPLE_TYPES = [
+    KpiSampleType.KPISAMPLETYPE_PACKETS_TRANSMITTED,
+    KpiSampleType.KPISAMPLETYPE_PACKETS_RECEIVED,
+    KpiSampleType.KPISAMPLETYPE_BYTES_TRANSMITTED,
+    KpiSampleType.KPISAMPLETYPE_BYTES_RECEIVED,
+]
+
+# ----- Device Credentials and Settings --------------------------------------------------------------------------------
+try:
+    from .Credentials import DEVICE_R1_ADDRESS, DEVICE_R1_PORT, DEVICE_R1_USERNAME, DEVICE_R1_PASSWORD
+    from .Credentials import DEVICE_R3_ADDRESS, DEVICE_R3_PORT, DEVICE_R3_USERNAME, DEVICE_R3_PASSWORD
+    from .Credentials import DEVICE_O1_ADDRESS, DEVICE_O1_PORT
+    USE_REAL_DEVICES = True     # Use real devices
+except ImportError:
+    USE_REAL_DEVICES = False    # Use emulated devices
+
+    DEVICE_R1_ADDRESS  = '0.0.0.0'
+    DEVICE_R1_PORT     = 830
+    DEVICE_R1_USERNAME = 'admin'
+    DEVICE_R1_PASSWORD = 'admin'
+
+    DEVICE_R3_ADDRESS  = '0.0.0.0'
+    DEVICE_R3_PORT     = 830
+    DEVICE_R3_USERNAME = 'admin'
+    DEVICE_R3_PASSWORD = 'admin'
+
+    DEVICE_O1_ADDRESS  = '0.0.0.0'
+    DEVICE_O1_PORT     = 4900
+
+#USE_REAL_DEVICES = False     # Force to use emulated devices
+
+def json_endpoint_ids(device_id : Dict, endpoint_descriptors : List[Tuple[str, str, List[int]]]):
+    return [
+        json_endpoint_id(device_id, ep_uuid, topology_id=None)
+        for ep_uuid, _, _ in endpoint_descriptors
+    ]
+
+def json_endpoints(device_id : Dict, endpoint_descriptors : List[Tuple[str, str, List[int]]]):
+    return [
+        json_endpoint(device_id, ep_uuid, ep_type, topology_id=None, kpi_sample_types=ep_sample_types)
+        for ep_uuid, ep_type, ep_sample_types in endpoint_descriptors
+    ]
+
+def get_link_uuid(a_device_id : Dict, a_endpoint_id : Dict, z_device_id : Dict, z_endpoint_id : Dict) -> str:
+    return '{:s}/{:s}=={:s}/{:s}'.format(
+        a_device_id['device_uuid']['uuid'], a_endpoint_id['endpoint_uuid']['uuid'],
+        z_device_id['device_uuid']['uuid'], z_endpoint_id['endpoint_uuid']['uuid'])
+
+
+# ----- Devices --------------------------------------------------------------------------------------------------------
+if not USE_REAL_DEVICES:
+    json_device_packetrouter_disabled = json_device_emulated_packet_router_disabled
+    json_device_tapi_disabled         = json_device_emulated_tapi_disabled
+
+DEVICE_R1_UUID          = 'R1-INF'
+DEVICE_R1_TIMEOUT       = 120
+DEVICE_R1_ENDPOINT_DEFS = [('13/0/0', 'optical', []), ('13/1/2', 'copper', PACKET_PORT_SAMPLE_TYPES)]
+DEVICE_R1_ID            = json_device_id(DEVICE_R1_UUID)
+#DEVICE_R1_ENDPOINTS     = json_endpoints(DEVICE_R1_ID, DEVICE_R1_ENDPOINT_DEFS)
+DEVICE_R1_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_R1_ID, DEVICE_R1_ENDPOINT_DEFS)
+DEVICE_R1               = json_device_packetrouter_disabled(DEVICE_R1_UUID)
+ENDPOINT_ID_R1_13_0_0   = DEVICE_R1_ENDPOINT_IDS[0]
+ENDPOINT_ID_R1_13_1_2   = DEVICE_R1_ENDPOINT_IDS[1]
+DEVICE_R1_CONNECT_RULES = json_device_connect_rules(DEVICE_R1_ADDRESS, DEVICE_R1_PORT, {
+    'username': DEVICE_R1_USERNAME,
+    'password': DEVICE_R1_PASSWORD,
+    'timeout' : DEVICE_R1_TIMEOUT,
+}) if USE_REAL_DEVICES else json_device_emulated_connect_rules(DEVICE_R1_ENDPOINT_DEFS)
+
+
+DEVICE_R2_UUID          = 'R2-EMU'
+DEVICE_R2_ENDPOINT_DEFS = [('13/0/0', 'optical', []), ('13/1/2', 'copper', PACKET_PORT_SAMPLE_TYPES)]
+DEVICE_R2_ID            = json_device_id(DEVICE_R2_UUID)
+#DEVICE_R2_ENDPOINTS     = json_endpoints(DEVICE_R2_ID, DEVICE_R2_ENDPOINT_DEFS)
+DEVICE_R2_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_R2_ID, DEVICE_R2_ENDPOINT_DEFS)
+DEVICE_R2               = json_device_emulated_packet_router_disabled(DEVICE_R2_UUID)
+ENDPOINT_ID_R2_13_0_0   = DEVICE_R2_ENDPOINT_IDS[0]
+ENDPOINT_ID_R2_13_1_2   = DEVICE_R2_ENDPOINT_IDS[1]
+DEVICE_R2_CONNECT_RULES = json_device_emulated_connect_rules(DEVICE_R2_ENDPOINT_DEFS)
+
+
+DEVICE_R3_UUID          = 'R3-INF'
+DEVICE_R3_TIMEOUT       = 120
+DEVICE_R3_ENDPOINT_DEFS = [('13/0/0', 'optical', []), ('13/1/2', 'copper', PACKET_PORT_SAMPLE_TYPES)]
+DEVICE_R3_ID            = json_device_id(DEVICE_R3_UUID)
+#DEVICE_R3_ENDPOINTS     = json_endpoints(DEVICE_R3_ID, DEVICE_R3_ENDPOINT_DEFS)
+DEVICE_R3_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_R3_ID, DEVICE_R3_ENDPOINT_DEFS)
+DEVICE_R3               = json_device_packetrouter_disabled(DEVICE_R3_UUID)
+ENDPOINT_ID_R3_13_0_0   = DEVICE_R3_ENDPOINT_IDS[0]
+ENDPOINT_ID_R3_13_1_2   = DEVICE_R3_ENDPOINT_IDS[1]
+DEVICE_R3_CONNECT_RULES = json_device_connect_rules(DEVICE_R3_ADDRESS, DEVICE_R3_PORT, {
+    'username': DEVICE_R3_USERNAME,
+    'password': DEVICE_R3_PASSWORD,
+    'timeout' : DEVICE_R3_TIMEOUT,
+}) if USE_REAL_DEVICES else json_device_emulated_connect_rules(DEVICE_R3_ENDPOINT_DEFS)
+
+
+DEVICE_R4_UUID          = 'R4-EMU'
+DEVICE_R4_ENDPOINT_DEFS = [('13/0/0', 'optical', []), ('13/1/2', 'copper', PACKET_PORT_SAMPLE_TYPES)]
+DEVICE_R4_ID            = json_device_id(DEVICE_R4_UUID)
+#DEVICE_R4_ENDPOINTS     = json_endpoints(DEVICE_R4_ID, DEVICE_R4_ENDPOINT_DEFS)
+DEVICE_R4_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_R4_ID, DEVICE_R4_ENDPOINT_DEFS)
+DEVICE_R4               = json_device_emulated_packet_router_disabled(DEVICE_R4_UUID)
+ENDPOINT_ID_R4_13_0_0   = DEVICE_R4_ENDPOINT_IDS[0]
+ENDPOINT_ID_R4_13_1_2   = DEVICE_R4_ENDPOINT_IDS[1]
+DEVICE_R4_CONNECT_RULES = json_device_emulated_connect_rules(DEVICE_R4_ENDPOINT_DEFS)
+
+
+DEVICE_O1_UUID          = 'O1-OLS'
+DEVICE_O1_TIMEOUT       = 120
+DEVICE_O1_ENDPOINT_DEFS = [
+    ('aade6001-f00b-5e2f-a357-6a0a9d3de870', 'optical', []), # node_1_port_13
+    ('eb287d83-f05e-53ec-ab5a-adf6bd2b5418', 'optical', []), # node_2_port_13
+    ('0ef74f99-1acc-57bd-ab9d-4b958b06c513', 'optical', []), # node_3_port_13
+    ('50296d99-58cc-5ce7-82f5-fc8ee4eec2ec', 'optical', []), # node_4_port_13
+]
+DEVICE_O1_ID            = json_device_id(DEVICE_O1_UUID)
+DEVICE_O1               = json_device_tapi_disabled(DEVICE_O1_UUID)
+#DEVICE_O1_ENDPOINTS     = json_endpoints(DEVICE_O1_ID, DEVICE_O1_ENDPOINT_DEFS)
+DEVICE_O1_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_O1_ID, DEVICE_O1_ENDPOINT_DEFS)
+ENDPOINT_ID_O1_EP1      = DEVICE_O1_ENDPOINT_IDS[0]
+ENDPOINT_ID_O1_EP2      = DEVICE_O1_ENDPOINT_IDS[1]
+ENDPOINT_ID_O1_EP3      = DEVICE_O1_ENDPOINT_IDS[2]
+ENDPOINT_ID_O1_EP4      = DEVICE_O1_ENDPOINT_IDS[3]
+DEVICE_O1_CONNECT_RULES = json_device_connect_rules(DEVICE_O1_ADDRESS, DEVICE_O1_PORT, {
+    'timeout' : DEVICE_O1_TIMEOUT,
+}) if USE_REAL_DEVICES else json_device_emulated_connect_rules(DEVICE_O1_ENDPOINT_DEFS)
+
+
+# ----- Links ----------------------------------------------------------------------------------------------------------
+LINK_R1_O1_UUID = get_link_uuid(DEVICE_R1_ID, ENDPOINT_ID_R1_13_0_0, DEVICE_O1_ID, ENDPOINT_ID_O1_EP1)
+LINK_R1_O1_ID   = json_link_id(LINK_R1_O1_UUID)
+LINK_R1_O1      = json_link(LINK_R1_O1_UUID, [ENDPOINT_ID_R1_13_0_0, ENDPOINT_ID_O1_EP1])
+
+LINK_R2_O1_UUID = get_link_uuid(DEVICE_R2_ID, ENDPOINT_ID_R2_13_0_0, DEVICE_O1_ID, ENDPOINT_ID_O1_EP2)
+LINK_R2_O1_ID   = json_link_id(LINK_R2_O1_UUID)
+LINK_R2_O1      = json_link(LINK_R2_O1_UUID, [ENDPOINT_ID_R2_13_0_0, ENDPOINT_ID_O1_EP2])
+
+LINK_R3_O1_UUID = get_link_uuid(DEVICE_R3_ID, ENDPOINT_ID_R3_13_0_0, DEVICE_O1_ID, ENDPOINT_ID_O1_EP3)
+LINK_R3_O1_ID   = json_link_id(LINK_R3_O1_UUID)
+LINK_R3_O1      = json_link(LINK_R3_O1_UUID, [ENDPOINT_ID_R3_13_0_0, ENDPOINT_ID_O1_EP3])
+
+LINK_R4_O1_UUID = get_link_uuid(DEVICE_R4_ID, ENDPOINT_ID_R4_13_0_0, DEVICE_O1_ID, ENDPOINT_ID_O1_EP4)
+LINK_R4_O1_ID   = json_link_id(LINK_R4_O1_UUID)
+LINK_R4_O1      = json_link(LINK_R4_O1_UUID, [ENDPOINT_ID_R4_13_0_0, ENDPOINT_ID_O1_EP4])
+
+
+# ----- WIM Service Settings -------------------------------------------------------------------------------------------
+
+def endpoint_id__to__sep_id(endpoint_id):
+    device_uuid = endpoint_id['device_id']['device_uuid']['uuid']
+    endpoint_uuid = endpoint_id['endpoint_uuid']['uuid']
+    return '{:s}:{:s}'.format(device_uuid, endpoint_uuid)
+
+WIM_SEP_R1_ID      = endpoint_id__to__sep_id(ENDPOINT_ID_R1_13_1_2)
+WIM_SEP_R1_IP      = '10.0.0.1'
+WIM_SEP_R1_SITE_ID = '1'
+WIM_SEP_R1_BEARER  = '{:s}:{:s}'.format(WIM_SEP_R1_ID, WIM_SEP_R1_IP)
+
+WIM_SEP_R3_ID      = endpoint_id__to__sep_id(ENDPOINT_ID_R3_13_1_2)
+WIM_SEP_R3_IP      = '10.0.0.2'
+WIM_SEP_R3_SITE_ID = '2'
+WIM_SEP_R3_BEARER  = '{:s}:{:s}'.format(WIM_SEP_R3_ID, WIM_SEP_R3_IP)
+
+WIM_USERNAME = 'admin'
+WIM_PASSWORD = 'admin'
+
+WIM_MAPPING  = [
+    {'device-id': DEVICE_R1_UUID, 'service_endpoint_id': WIM_SEP_R1_ID,
+     'service_mapping_info': {'bearer': {'bearer-reference': WIM_SEP_R1_BEARER}, 'site-id': WIM_SEP_R1_SITE_ID}},
+    {'device-id': DEVICE_R3_UUID, 'service_endpoint_id': WIM_SEP_R3_ID,
+     'service_mapping_info': {'bearer': {'bearer-reference': WIM_SEP_R3_BEARER}, 'site-id': WIM_SEP_R3_SITE_ID}},
+]
+WIM_SERVICE_TYPE = 'ELINE'
+WIM_SERVICE_VLAN_ID = 1234
+WIM_SERVICE_CONNECTION_POINTS = [
+    {'service_endpoint_id': WIM_SEP_R1_ID,
+        'service_endpoint_encapsulation_type': 'dot1q',
+        'service_endpoint_encapsulation_info': {'vlan': WIM_SERVICE_VLAN_ID}},
+    {'service_endpoint_id': WIM_SEP_R3_ID,
+        'service_endpoint_encapsulation_type': 'dot1q',
+        'service_endpoint_encapsulation_info': {'vlan': WIM_SERVICE_VLAN_ID}},
+]
+
+# ----- Object Collections ---------------------------------------------------------------------------------------------
+
+CONTEXTS = [CONTEXT]
+TOPOLOGIES = [TOPOLOGY]
+
+DEVICES = [
+    (DEVICE_R1, DEVICE_R1_CONNECT_RULES),
+    (DEVICE_R2, DEVICE_R2_CONNECT_RULES),
+    (DEVICE_R3, DEVICE_R3_CONNECT_RULES),
+    (DEVICE_R4, DEVICE_R4_CONNECT_RULES),
+    (DEVICE_O1, DEVICE_O1_CONNECT_RULES),
+]
+
+LINKS = [LINK_R1_O1, LINK_R2_O1, LINK_R3_O1, LINK_R4_O1]
diff --git a/src/tests/ofc22/tests/__init__.py b/src/tests/ofc22/tests/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/tests/ofc22/tests/test_functional_bootstrap.py b/src/tests/ofc22/tests/test_functional_bootstrap.py
new file mode 100644
index 000000000..d1ef2f6d8
--- /dev/null
+++ b/src/tests/ofc22/tests/test_functional_bootstrap.py
@@ -0,0 +1,190 @@
+import copy, logging, pytest
+from common.Settings import get_setting
+from common.tests.EventTools import EVENT_CREATE, EVENT_UPDATE, check_events
+from common.tools.object_factory.Context import json_context_id
+from common.tools.object_factory.Device import json_device_id
+from common.tools.object_factory.Link import json_link_id
+from common.tools.object_factory.Topology import json_topology_id
+from context.client.ContextClient import ContextClient
+from context.client.EventsCollector import EventsCollector
+from context.proto.context_pb2 import Context, ContextId, Device, Empty, Link, Topology
+from device.client.DeviceClient import DeviceClient
+from .Objects import CONTEXT_ID, CONTEXTS, DEVICES, LINKS, TOPOLOGIES
+
+
+LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.DEBUG)
+
+
+@pytest.fixture(scope='session')
+def context_client():
+    _client = ContextClient(get_setting('CONTEXTSERVICE_SERVICE_HOST'), get_setting('CONTEXTSERVICE_SERVICE_PORT_GRPC'))
+    yield _client
+    _client.close()
+
+
+@pytest.fixture(scope='session')
+def device_client():
+    _client = DeviceClient(get_setting('DEVICESERVICE_SERVICE_HOST'), get_setting('DEVICESERVICE_SERVICE_PORT_GRPC'))
+    yield _client
+    _client.close()
+
+
+def test_scenario_empty(context_client : ContextClient):  # pylint: disable=redefined-outer-name
+    # ----- List entities - Ensure database is empty -------------------------------------------------------------------
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == 0
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == 0
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == 0
+
+
+def test_prepare_scenario(context_client : ContextClient):  # pylint: disable=redefined-outer-name
+
+    # ----- Start the EventsCollector ----------------------------------------------------------------------------------
+    events_collector = EventsCollector(context_client)
+    events_collector.start()
+
+    expected_events = []
+
+    # ----- Create Contexts and Topologies -----------------------------------------------------------------------------
+    for context in CONTEXTS:
+        context_uuid = context['context_id']['context_uuid']['uuid']
+        LOGGER.info('Adding Context {:s}'.format(context_uuid))
+        response = context_client.SetContext(Context(**context))
+        assert response.context_uuid.uuid == context_uuid
+        expected_events.append(('ContextEvent', EVENT_CREATE, json_context_id(context_uuid)))
+
+    for topology in TOPOLOGIES:
+        context_uuid = topology['topology_id']['context_id']['context_uuid']['uuid']
+        topology_uuid = topology['topology_id']['topology_uuid']['uuid']
+        LOGGER.info('Adding Topology {:s}/{:s}'.format(context_uuid, topology_uuid))
+        response = context_client.SetTopology(Topology(**topology))
+        assert response.context_id.context_uuid.uuid == context_uuid
+        assert response.topology_uuid.uuid == topology_uuid
+        context_id = json_context_id(context_uuid)
+        expected_events.append(('TopologyEvent', EVENT_CREATE, json_topology_id(topology_uuid, context_id=context_id)))
+
+    # ----- Validate Collected Events ----------------------------------------------------------------------------------
+    check_events(events_collector, expected_events)
+
+    # ----- Stop the EventsCollector -----------------------------------------------------------------------------------
+    events_collector.stop()
+
+
+def test_scenario_ready(context_client : ContextClient):  # pylint: disable=redefined-outer-name
+    # ----- List entities - Ensure scenario is ready -------------------------------------------------------------------
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == len(CONTEXTS)
+
+    response = context_client.ListTopologies(ContextId(**CONTEXT_ID))
+    assert len(response.topologies) == len(TOPOLOGIES)
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == 0
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == 0
+
+    response = context_client.ListServices(ContextId(**CONTEXT_ID))
+    assert len(response.services) == 0
+
+
+def test_devices_bootstraping(
+    context_client : ContextClient, device_client : DeviceClient):  # pylint: disable=redefined-outer-name
+
+    # ----- Start the EventsCollector ----------------------------------------------------------------------------------
+    events_collector = EventsCollector(context_client, log_events_received=True)
+    events_collector.start()
+
+    expected_events = []
+
+    # ----- Create Devices and Validate Collected Events ---------------------------------------------------------------
+    for device, connect_rules in DEVICES:
+        device_uuid = device['device_id']['device_uuid']['uuid']
+        LOGGER.info('Adding Device {:s}'.format(device_uuid))
+
+        device_with_connect_rules = copy.deepcopy(device)
+        device_with_connect_rules['device_config']['config_rules'].extend(connect_rules)
+        response = device_client.AddDevice(Device(**device_with_connect_rules))
+        assert response.device_uuid.uuid == device_uuid
+
+        expected_events.extend([
+            # Device creation, update for automation to start the device
+            ('DeviceEvent', EVENT_CREATE, json_device_id(device_uuid)),
+            ('DeviceEvent', EVENT_UPDATE, json_device_id(device_uuid)),
+        ])
+
+        response = context_client.GetDevice(response)
+        for endpoint in response.device_endpoints:
+            for _ in endpoint.kpi_sample_types:
+                # Monitoring configures monitoring for endpoint
+                expected_events.append(('DeviceEvent', EVENT_UPDATE, json_device_id(device_uuid)))
+
+    # ----- Validate Collected Events ----------------------------------------------------------------------------------
+    check_events(events_collector, expected_events)
+
+    # ----- Stop the EventsCollector -----------------------------------------------------------------------------------
+    events_collector.stop()
+
+
+def test_devices_bootstrapped(context_client : ContextClient):  # pylint: disable=redefined-outer-name
+    # ----- List entities - Ensure bevices are created -----------------------------------------------------------------
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == len(CONTEXTS)
+
+    response = context_client.ListTopologies(ContextId(**CONTEXT_ID))
+    assert len(response.topologies) == len(TOPOLOGIES)
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == len(DEVICES)
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == 0
+
+    response = context_client.ListServices(ContextId(**CONTEXT_ID))
+    assert len(response.services) == 0
+
+
+def test_links_creation(context_client : ContextClient):  # pylint: disable=redefined-outer-name
+
+    # ----- Start the EventsCollector ----------------------------------------------------------------------------------
+    events_collector = EventsCollector(context_client)
+    events_collector.start()
+
+    expected_events = []
+
+    # ----- Create Links and Validate Collected Events -----------------------------------------------------------------
+    for link in LINKS:
+        link_uuid = link['link_id']['link_uuid']['uuid']
+        LOGGER.info('Adding Link {:s}'.format(link_uuid))
+        response = context_client.SetLink(Link(**link))
+        assert response.link_uuid.uuid == link_uuid
+        expected_events.append(('LinkEvent', EVENT_CREATE, json_link_id(link_uuid)))
+
+    # ----- Validate Collected Events ----------------------------------------------------------------------------------
+    check_events(events_collector, expected_events)
+
+    # ----- Stop the EventsCollector -----------------------------------------------------------------------------------
+    events_collector.stop()
+
+
+def test_links_created(context_client : ContextClient):  # pylint: disable=redefined-outer-name
+    # ----- List entities - Ensure links are created -------------------------------------------------------------------
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == len(CONTEXTS)
+
+    response = context_client.ListTopologies(ContextId(**CONTEXT_ID))
+    assert len(response.topologies) == len(TOPOLOGIES)
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == len(DEVICES)
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == len(LINKS)
+
+    response = context_client.ListServices(ContextId(**CONTEXT_ID))
+    assert len(response.services) == 0
diff --git a/src/tests/ofc22/tests/test_functional_cleanup.py b/src/tests/ofc22/tests/test_functional_cleanup.py
new file mode 100644
index 000000000..d8e9fcd61
--- /dev/null
+++ b/src/tests/ofc22/tests/test_functional_cleanup.py
@@ -0,0 +1,109 @@
+import logging, pytest
+from common.Settings import get_setting
+from common.tests.EventTools import EVENT_REMOVE, check_events
+from common.tools.object_factory.Context import json_context_id
+from common.tools.object_factory.Device import json_device_id
+from common.tools.object_factory.Link import json_link_id
+from common.tools.object_factory.Topology import json_topology_id
+from context.client.ContextClient import ContextClient
+from context.client.EventsCollector import EventsCollector
+from context.proto.context_pb2 import ContextId, DeviceId, Empty, LinkId, TopologyId
+from device.client.DeviceClient import DeviceClient
+from .Objects import CONTEXT_ID, CONTEXTS, DEVICES, LINKS, TOPOLOGIES
+
+LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.DEBUG)
+
+
+@pytest.fixture(scope='session')
+def context_client():
+    _client = ContextClient(get_setting('CONTEXTSERVICE_SERVICE_HOST'), get_setting('CONTEXTSERVICE_SERVICE_PORT_GRPC'))
+    yield _client
+    _client.close()
+
+
+@pytest.fixture(scope='session')
+def device_client():
+    _client = DeviceClient(get_setting('DEVICESERVICE_SERVICE_HOST'), get_setting('DEVICESERVICE_SERVICE_PORT_GRPC'))
+    yield _client
+    _client.close()
+
+
+def test_services_removed(context_client : ContextClient):  # pylint: disable=redefined-outer-name
+    # ----- List entities - Ensure service is removed ------------------------------------------------------------------
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == len(CONTEXTS)
+
+    response = context_client.ListTopologies(ContextId(**CONTEXT_ID))
+    assert len(response.topologies) == len(TOPOLOGIES)
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == len(DEVICES)
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == len(LINKS)
+
+    response = context_client.ListServices(ContextId(**CONTEXT_ID))
+    assert len(response.services) == 0
+
+
+def test_scenario_cleanup(
+    context_client : ContextClient, device_client : DeviceClient):  # pylint: disable=redefined-outer-name
+
+    # ----- Start the EventsCollector ----------------------------------------------------------------------------------
+    events_collector = EventsCollector(context_client)
+    events_collector.start()
+
+    expected_events = []
+
+    # ----- Delete Links and Validate Collected Events -----------------------------------------------------------------
+    for link in LINKS:
+        link_id = link['link_id']
+        link_uuid = link_id['link_uuid']['uuid']
+        LOGGER.info('Deleting Link {:s}'.format(link_uuid))
+        context_client.RemoveLink(LinkId(**link_id))
+        expected_events.append(('LinkEvent', EVENT_REMOVE, json_link_id(link_uuid)))
+
+    # ----- Delete Devices and Validate Collected Events ---------------------------------------------------------------
+    for device, _ in DEVICES:
+        device_id = device['device_id']
+        device_uuid = device_id['device_uuid']['uuid']
+        LOGGER.info('Deleting Device {:s}'.format(device_uuid))
+        device_client.DeleteDevice(DeviceId(**device_id))
+        expected_events.append(('DeviceEvent', EVENT_REMOVE, json_device_id(device_uuid)))
+
+    # ----- Delete Topologies and Validate Collected Events ------------------------------------------------------------
+    for topology in TOPOLOGIES:
+        topology_id = topology['topology_id']
+        context_uuid = topology_id['context_id']['context_uuid']['uuid']
+        topology_uuid = topology_id['topology_uuid']['uuid']
+        LOGGER.info('Deleting Topology {:s}/{:s}'.format(context_uuid, topology_uuid))
+        context_client.RemoveTopology(TopologyId(**topology_id))
+        context_id = json_context_id(context_uuid)
+        expected_events.append(('TopologyEvent', EVENT_REMOVE, json_topology_id(topology_uuid, context_id=context_id)))
+
+    # ----- Delete Contexts and Validate Collected Events --------------------------------------------------------------
+    for context in CONTEXTS:
+        context_id = context['context_id']
+        context_uuid = context_id['context_uuid']['uuid']
+        LOGGER.info('Deleting Context {:s}'.format(context_uuid))
+        context_client.RemoveContext(ContextId(**context_id))
+        expected_events.append(('ContextEvent', EVENT_REMOVE, json_context_id(context_uuid)))
+
+    # ----- Validate Collected Events ----------------------------------------------------------------------------------
+    check_events(events_collector, expected_events)
+
+    # ----- Stop the EventsCollector -----------------------------------------------------------------------------------
+    events_collector.stop()
+
+
+def test_scenario_empty_again(context_client : ContextClient):  # pylint: disable=redefined-outer-name
+    # ----- List entities - Ensure database is empty again -------------------------------------------------------------
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == 0
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == 0
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == 0
diff --git a/src/tests/ofc22/tests/test_functional_create_service.py b/src/tests/ofc22/tests/test_functional_create_service.py
new file mode 100644
index 000000000..679e9b0c4
--- /dev/null
+++ b/src/tests/ofc22/tests/test_functional_create_service.py
@@ -0,0 +1,115 @@
+import logging, pytest
+from common.DeviceTypes import DeviceTypeEnum
+from common.Settings import get_setting
+from common.tests.EventTools import EVENT_CREATE, EVENT_UPDATE, check_events
+from common.tools.object_factory.Connection import json_connection_id
+from common.tools.object_factory.Device import json_device_id
+from common.tools.object_factory.Service import json_service_id
+from common.tools.grpc.Tools import grpc_message_to_json_string
+from compute.tests.mock_osm.MockOSM import MockOSM
+from context.client.ContextClient import ContextClient
+from context.client.EventsCollector import EventsCollector
+from context.proto.context_pb2 import ContextId, Empty
+from .Objects import (
+    CONTEXT_ID, CONTEXTS, DEVICE_O1_UUID, DEVICE_R1_UUID, DEVICE_R3_UUID, DEVICES, LINKS, TOPOLOGIES,
+    WIM_MAPPING, WIM_PASSWORD, WIM_SERVICE_CONNECTION_POINTS, WIM_SERVICE_TYPE, WIM_USERNAME)
+
+LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.DEBUG)
+
+DEVTYPE_EMU_PR  = DeviceTypeEnum.EMULATED_PACKET_ROUTER.value
+DEVTYPE_EMU_OLS = DeviceTypeEnum.EMULATED_OPTICAL_LINE_SYSTEM.value
+
+
+@pytest.fixture(scope='session')
+def context_client():
+    _client = ContextClient(get_setting('CONTEXTSERVICE_SERVICE_HOST'), get_setting('CONTEXTSERVICE_SERVICE_PORT_GRPC'))
+    yield _client
+    _client.close()
+
+
+@pytest.fixture(scope='session')
+def osm_wim():
+    wim_url = 'http://{:s}:{:s}'.format(
+        get_setting('COMPUTESERVICE_SERVICE_HOST'), str(get_setting('COMPUTESERVICE_SERVICE_PORT_HTTP')))
+    return MockOSM(wim_url, WIM_MAPPING, WIM_USERNAME, WIM_PASSWORD)
+
+
+def test_scenario_is_correct(context_client : ContextClient):  # pylint: disable=redefined-outer-name
+    # ----- List entities - Ensure links are created -------------------------------------------------------------------
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == len(CONTEXTS)
+
+    response = context_client.ListTopologies(ContextId(**CONTEXT_ID))
+    assert len(response.topologies) == len(TOPOLOGIES)
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == len(DEVICES)
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == len(LINKS)
+
+    response = context_client.ListServices(ContextId(**CONTEXT_ID))
+    assert len(response.services) == 0
+
+
+def test_service_creation(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name
+    # ----- Start the EventsCollector ----------------------------------------------------------------------------------
+    events_collector = EventsCollector(context_client, log_events_received=True)
+    events_collector.start()
+
+    # ----- Create Service ---------------------------------------------------------------------------------------------
+    service_uuid = osm_wim.create_connectivity_service(WIM_SERVICE_TYPE, WIM_SERVICE_CONNECTION_POINTS)
+    osm_wim.get_connectivity_service_status(service_uuid)
+
+    # ----- Validate collected events ----------------------------------------------------------------------------------
+
+    packet_connection_uuid = '{:s}:{:s}'.format(service_uuid, DEVTYPE_EMU_PR)
+    optical_connection_uuid = '{:s}:optical:{:s}'.format(service_uuid, DEVTYPE_EMU_OLS)
+    optical_service_uuid = '{:s}:optical'.format(service_uuid)
+
+    expected_events = [
+        # Create packet service and add first endpoint
+        ('ServiceEvent',    EVENT_CREATE, json_service_id(service_uuid, context_id=CONTEXT_ID)),
+        ('ServiceEvent',    EVENT_UPDATE, json_service_id(service_uuid, context_id=CONTEXT_ID)),
+
+        # Configure OLS controller, create optical service, create optical connection
+        ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_O1_UUID)),
+        ('ServiceEvent',    EVENT_CREATE, json_service_id(optical_service_uuid, context_id=CONTEXT_ID)),
+        ('ConnectionEvent', EVENT_CREATE, json_connection_id(optical_connection_uuid)),
+
+        # Configure endpoint packet devices, add second endpoint to service, create connection
+        ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_R1_UUID)),
+        ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_R3_UUID)),
+        ('ServiceEvent',    EVENT_UPDATE, json_service_id(service_uuid, context_id=CONTEXT_ID)),
+        ('ConnectionEvent', EVENT_CREATE, json_connection_id(packet_connection_uuid)),
+    ]
+    check_events(events_collector, expected_events)
+
+    # ----- Stop the EventsCollector -----------------------------------------------------------------------------------
+    events_collector.stop()
+
+
+def test_scenario_service_created(context_client : ContextClient):  # pylint: disable=redefined-outer-name
+    # ----- List entities - Ensure service is created ------------------------------------------------------------------
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == len(CONTEXTS)
+
+    response = context_client.ListTopologies(ContextId(**CONTEXT_ID))
+    assert len(response.topologies) == len(TOPOLOGIES)
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == len(DEVICES)
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == len(LINKS)
+
+    response = context_client.ListServices(ContextId(**CONTEXT_ID))
+    LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response)))
+    assert len(response.services) == 2 # L3NM + TAPI
+    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)))
+        assert len(response.connections) == 1 # one connection per service
diff --git a/src/tests/ofc22/tests/test_functional_delete_service.py b/src/tests/ofc22/tests/test_functional_delete_service.py
new file mode 100644
index 000000000..edf8f2bd2
--- /dev/null
+++ b/src/tests/ofc22/tests/test_functional_delete_service.py
@@ -0,0 +1,120 @@
+import logging, pytest
+from common.DeviceTypes import DeviceTypeEnum
+from common.Settings import get_setting
+from common.tests.EventTools import EVENT_REMOVE, EVENT_UPDATE, check_events
+from common.tools.object_factory.Connection import json_connection_id
+from common.tools.object_factory.Device import json_device_id
+from common.tools.object_factory.Service import json_service_id
+from common.tools.grpc.Tools import grpc_message_to_json_string
+from compute.tests.mock_osm.MockOSM import MockOSM
+from context.client.ContextClient import ContextClient
+from context.client.EventsCollector import EventsCollector
+from context.proto.context_pb2 import ContextId, Empty
+from .Objects import (
+    CONTEXT_ID, CONTEXTS, DEVICE_O1_UUID, DEVICE_R1_UUID, DEVICE_R3_UUID, DEVICES, LINKS, TOPOLOGIES, WIM_MAPPING,
+    WIM_PASSWORD, WIM_USERNAME)
+
+
+LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.DEBUG)
+
+DEVTYPE_EMU_PR  = DeviceTypeEnum.EMULATED_PACKET_ROUTER.value
+DEVTYPE_EMU_OLS = DeviceTypeEnum.EMULATED_OPTICAL_LINE_SYSTEM.value
+
+
+@pytest.fixture(scope='session')
+def context_client():
+    _client = ContextClient(get_setting('CONTEXTSERVICE_SERVICE_HOST'), get_setting('CONTEXTSERVICE_SERVICE_PORT_GRPC'))
+    yield _client
+    _client.close()
+
+
+@pytest.fixture(scope='session')
+def osm_wim():
+    wim_url = 'http://{:s}:{:s}'.format(
+        get_setting('COMPUTESERVICE_SERVICE_HOST'), str(get_setting('COMPUTESERVICE_SERVICE_PORT_HTTP')))
+    return MockOSM(wim_url, WIM_MAPPING, WIM_USERNAME, WIM_PASSWORD)
+
+
+def test_scenario_is_correct(context_client : ContextClient):  # pylint: disable=redefined-outer-name
+    # ----- List entities - Ensure service is created ------------------------------------------------------------------
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == len(CONTEXTS)
+
+    response = context_client.ListTopologies(ContextId(**CONTEXT_ID))
+    assert len(response.topologies) == len(TOPOLOGIES)
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == len(DEVICES)
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == len(LINKS)
+
+    response = context_client.ListServices(ContextId(**CONTEXT_ID))
+    LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response)))
+    assert len(response.services) == 2 # L3NM + TAPI
+    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)))
+        assert len(response.connections) == 1 # one connection per service
+
+
+def test_service_removal(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name
+    # ----- Start the EventsCollector ----------------------------------------------------------------------------------
+    events_collector = EventsCollector(context_client, log_events_received=True)
+    events_collector.start()
+
+    # ----- Delete Service ---------------------------------------------------------------------------------------------
+    response = context_client.ListServiceIds(ContextId(**CONTEXT_ID))
+    LOGGER.info('Services[{:d}] = {:s}'.format(len(response.service_ids), grpc_message_to_json_string(response)))
+    assert len(response.service_ids) == 2 # L3NM + TAPI
+    service_uuids = set()
+    for service_id in response.service_ids:
+        service_uuid = service_id.service_uuid.uuid
+        if service_uuid.endswith(':optical'): continue
+        service_uuids.add(service_uuid)
+        osm_wim.conn_info[service_uuid] = {}
+
+    assert len(service_uuids) == 1  # assume a single service has been created
+    service_uuid = set(service_uuids).pop()
+
+    osm_wim.delete_connectivity_service(service_uuid)
+
+    # ----- Validate collected events ----------------------------------------------------------------------------------
+    packet_connection_uuid = '{:s}:{:s}'.format(service_uuid, DEVTYPE_EMU_PR)
+    optical_connection_uuid = '{:s}:optical:{:s}'.format(service_uuid, DEVTYPE_EMU_OLS)
+    optical_service_uuid = '{:s}:optical'.format(service_uuid)
+
+    expected_events = [
+        ('ConnectionEvent', EVENT_REMOVE, json_connection_id(packet_connection_uuid)),
+        ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_R1_UUID)),
+        ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_R3_UUID)),
+        ('ServiceEvent',    EVENT_REMOVE, json_service_id(service_uuid, context_id=CONTEXT_ID)),
+        ('ConnectionEvent', EVENT_REMOVE, json_connection_id(optical_connection_uuid)),
+        ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_O1_UUID)),
+        ('ServiceEvent',    EVENT_REMOVE, json_service_id(optical_service_uuid, context_id=CONTEXT_ID)),
+    ]
+    check_events(events_collector, expected_events)
+
+    # ----- Stop the EventsCollector -----------------------------------------------------------------------------------
+    events_collector.stop()
+
+
+def test_services_removed(context_client : ContextClient):  # pylint: disable=redefined-outer-name
+    # ----- List entities - Ensure service is removed ------------------------------------------------------------------
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == len(CONTEXTS)
+
+    response = context_client.ListTopologies(ContextId(**CONTEXT_ID))
+    assert len(response.topologies) == len(TOPOLOGIES)
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == len(DEVICES)
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == len(LINKS)
+
+    response = context_client.ListServices(ContextId(**CONTEXT_ID))
+    assert len(response.services) == 0
diff --git a/src/webui/Config.py b/src/webui/Config.py
index e4ea65f4a..2777dcfa5 100644
--- a/src/webui/Config.py
+++ b/src/webui/Config.py
@@ -17,7 +17,7 @@ HOST = '0.0.0.0'  # accepts connections coming from any ADDRESS
 DEBUG=False
 
 CONTEXT_SERVICE_ADDRESS = os.environ.get('CONTEXTSERVICE_SERVICE_HOST', 'contextservice')
-CONTEXT_SERVICE_PORT = 1010
+CONTEXT_SERVICE_PORT = int(os.environ.get('CONTEXTSERVICE_SERVICE_PORT_GRPC', 1010))
 
 DEVICE_SERVICE_ADDRESS = os.environ.get('DEVICESERVICE_SERVICE_HOST', 'deviceservice')
-DEVICE_SERVICE_PORT = 2020
+DEVICE_SERVICE_PORT = int(os.environ.get('DEVICESERVICE_SERVICE_PORT_GRPC', 2020))
diff --git a/src/webui/grafana_dashboard.json b/src/webui/grafana_dashboard.json
index f1fe53f1c..c9092aca5 100644
--- a/src/webui/grafana_dashboard.json
+++ b/src/webui/grafana_dashboard.json
@@ -307,7 +307,7 @@
     "timepicker": {},
     "timezone": "",
     "title": "L3 Monitoring",
-    "uid": "5d_I5W-nz",
+    "uid": "tf-l3-monit",
     "version": 2
   }
 }
diff --git a/src/webui/service/__main__.py b/src/webui/service/__main__.py
index 2107e139f..645f7e26e 100644
--- a/src/webui/service/__main__.py
+++ b/src/webui/service/__main__.py
@@ -1,5 +1,6 @@
 import os, sys, logging
 from prometheus_client import start_http_server
+from common.Settings import wait_for_environment_variables
 from webui.service import create_app
 from webui.Config import WEBUI_SERVICE_PORT, LOG_LEVEL, METRICS_PORT, HOST, SECRET_KEY, DEBUG
 
@@ -13,6 +14,11 @@ def main():
     logging.basicConfig(level=log_level)
     logger = logging.getLogger(__name__)
 
+    wait_for_environment_variables([
+        'CONTEXTSERVICE_SERVICE_HOST', 'CONTEXTSERVICE_SERVICE_PORT_GRPC',
+        'DEVICESERVICE_SERVICE_HOST', 'DEVICESERVICE_SERVICE_PORT_GRPC'
+    ])
+
     logger.info('Starting...')
 
     start_http_server(metrics_port)
diff --git a/src/webui/service/service/routes.py b/src/webui/service/service/routes.py
index c88d89789..fb00a43e2 100644
--- a/src/webui/service/service/routes.py
+++ b/src/webui/service/service/routes.py
@@ -1,3 +1,4 @@
+import grpc
 from flask import render_template, Blueprint, flash, session
 from webui.Config import CONTEXT_SERVICE_ADDRESS, CONTEXT_SERVICE_PORT
 from context.client.ContextClient import ContextClient
@@ -12,15 +13,24 @@ context_client: ContextClient = ContextClient(CONTEXT_SERVICE_ADDRESS, CONTEXT_S
 def home():
     # flash('This is an info message', 'info')
     # flash('This is a danger message', 'danger')
-    
+
+    context_uuid = session['context_uuid']
     request: ContextId = ContextId()
-    request.context_uuid.uuid = session['context_uuid']
+    request.context_uuid.uuid = context_uuid
     context_client.connect()
-    service_list: ServiceList = context_client.ListServices(request)
-    # print(service_list)
+    try:
+        service_list: ServiceList = context_client.ListServices(request)
+        # print(service_list)
+        services = service_list.services
+        context_not_found = False
+    except grpc.RpcError as e:
+        if e.code() != grpc.StatusCode.NOT_FOUND: raise
+        if e.details() != 'Context({:s}) not found'.format(context_uuid): raise
+        services = []
+        context_not_found = True
 
     context_client.close()
-    return render_template('service/home.html', services=service_list.services, 
+    return render_template('service/home.html', services=services, context_not_found=context_not_found,
                                                 ste=ServiceTypeEnum,
                                                 sse=ServiceStatusEnum)
 
diff --git a/src/webui/service/templates/service/home.html b/src/webui/service/templates/service/home.html
index 69283b544..499ffa03e 100644
--- a/src/webui/service/templates/service/home.html
+++ b/src/webui/service/templates/service/home.html
@@ -4,6 +4,7 @@
     <h1>Services</h1>
 
     <div class="row">
+        {% if context_found %}
         <!-- <div class="col">
             <a href="{{ url_for('service.add') }}" class="btn btn-primary" style="margin-bottom: 10px;">
                 <i class="bi bi-plus"></i>
@@ -21,6 +22,11 @@
                   </div>
             </form>
         </div> -->
+        {% else %}
+        <div class="col">
+            Context <i>{{ session['context_uuid'] }}</i> not found.
+        </div>
+        {% endif %}
     </div>
     
 
diff --git a/src/webui/tests/test_unitary.py b/src/webui/tests/test_unitary.py
index 0612c9d05..3b6ec7dab 100644
--- a/src/webui/tests/test_unitary.py
+++ b/src/webui/tests/test_unitary.py
@@ -4,6 +4,7 @@ from unittest import mock
 from flask.testing import FlaskClient
 from flask.app import Flask
 from flask.helpers import url_for
+from common.DeviceTypes import DeviceTypeEnum
 # from device.client.DeviceClient import DeviceClient
 from webui.service import create_app
 from webui.proto.context_pb2 import Empty, DeviceId, DeviceList, TopologyIdList
@@ -54,7 +55,7 @@ class TestWebUI(ClientTestCase):
             sess['context_uuid'] = 'admin'
         DEVICE_EMU = {
             'device_id': 'EMULATED',
-            'device_type': 'emulated',
+            'device_type': DeviceTypeEnum.EMULATED_PACKET_ROUTER.value,
             'device_config': '',
             'operational_status': 1,
             'device_drivers': 0,
@@ -133,7 +134,7 @@ class TestWebUI(ClientTestCase):
 #         sess['context_uuid'] = 'admin'
 #     DEVICE_EMU = {
 #         'device_id': 'EMULATED',
-#         'device_type': 'emulated',
+#         'device_type': DeviceTypeEnum.EMULATED_PACKET_ROUTER.value,
 #         'device_config': '',
 #         'operational_status': 1,
 #         'device_drivers': 0,
-- 
GitLab