From 7b2637c62d631a881213384a00ef1deb9f6afb05 Mon Sep 17 00:00:00 2001
From: Carlos Natalino <carlos.natalino@chalmers.se>
Date: Wed, 2 Feb 2022 14:32:53 +0000
Subject: [PATCH] First version of the WebUI

---
 .gitlab-ci.yml                                |    1 +
 deploy_in_kubernetes.sh                       |    2 +-
 install_development_dependencies.sh           |    2 +-
 manifests/webuiservice.yaml                   |   72 +
 open_webui.sh                                 |   12 +
 run_tests_locally.sh                          |    3 +
 src/context/requirements.txt                  |   72 +
 src/device/client/DeviceClient.py             |    2 +-
 src/start_webui_dev_mode.sh                   |   15 +
 src/webui/.gitlab-ci.yml                      |   89 +
 src/webui/Config.py                           |   23 +
 src/webui/Dockerfile                          |   46 +
 src/webui/__init__.py                         |    0
 src/webui/genproto.sh                         |   43 +
 src/webui/proto/__init__.py                   |    0
 src/webui/proto/context_pb2.py                | 2535 +++++++++++++++++
 src/webui/proto/device_pb2.py                 |   88 +
 src/webui/proto/monitoring_pb2.py             |  617 ++++
 src/webui/proto/service_pb2.py                |   88 +
 src/webui/requirements.in                     |   11 +
 src/webui/service/__init__.py                 |   58 +
 src/webui/service/__main__.py                 |   27 +
 src/webui/service/context/__init__.py         |    0
 src/webui/service/context/routes.py           |    9 +
 src/webui/service/device/__init__.py          |    0
 src/webui/service/device/forms.py             |   41 +
 src/webui/service/device/routes.py            |  121 +
 src/webui/service/main/__init__.py            |    0
 src/webui/service/main/forms.py               |   11 +
 src/webui/service/main/routes.py              |   37 +
 src/webui/service/service/__init__.py         |    0
 src/webui/service/service/routes.py           |   39 +
 src/webui/service/static/partners.png         |  Bin 0 -> 76488 bytes
 src/webui/service/static/site.js              |    4 +
 src/webui/service/templates/base.html         |  119 +
 src/webui/service/templates/context/home.html |   79 +
 src/webui/service/templates/device/add.html   |   93 +
 .../service/templates/device/detail.html      |   73 +
 src/webui/service/templates/device/home.html  |   93 +
 src/webui/service/templates/main/about.html   |    9 +
 src/webui/service/templates/main/home.html    |   37 +
 src/webui/service/templates/service/home.html |   95 +
 src/webui/tests/__init__.py                   |    0
 src/webui/tests/test_unitary.py               |  156 +
 src/webui/utils/__init__.py                   |    0
 src/webui/utils/form_validators.py            |   14 +
 46 files changed, 4833 insertions(+), 3 deletions(-)
 create mode 100644 manifests/webuiservice.yaml
 create mode 100755 open_webui.sh
 create mode 100644 src/context/requirements.txt
 create mode 100755 src/start_webui_dev_mode.sh
 create mode 100644 src/webui/.gitlab-ci.yml
 create mode 100644 src/webui/Config.py
 create mode 100644 src/webui/Dockerfile
 create mode 100644 src/webui/__init__.py
 create mode 100755 src/webui/genproto.sh
 create mode 100644 src/webui/proto/__init__.py
 create mode 100644 src/webui/proto/context_pb2.py
 create mode 100644 src/webui/proto/device_pb2.py
 create mode 100644 src/webui/proto/monitoring_pb2.py
 create mode 100644 src/webui/proto/service_pb2.py
 create mode 100644 src/webui/requirements.in
 create mode 100644 src/webui/service/__init__.py
 create mode 100644 src/webui/service/__main__.py
 create mode 100644 src/webui/service/context/__init__.py
 create mode 100644 src/webui/service/context/routes.py
 create mode 100644 src/webui/service/device/__init__.py
 create mode 100644 src/webui/service/device/forms.py
 create mode 100644 src/webui/service/device/routes.py
 create mode 100644 src/webui/service/main/__init__.py
 create mode 100644 src/webui/service/main/forms.py
 create mode 100644 src/webui/service/main/routes.py
 create mode 100644 src/webui/service/service/__init__.py
 create mode 100644 src/webui/service/service/routes.py
 create mode 100644 src/webui/service/static/partners.png
 create mode 100644 src/webui/service/static/site.js
 create mode 100644 src/webui/service/templates/base.html
 create mode 100644 src/webui/service/templates/context/home.html
 create mode 100644 src/webui/service/templates/device/add.html
 create mode 100644 src/webui/service/templates/device/detail.html
 create mode 100644 src/webui/service/templates/device/home.html
 create mode 100644 src/webui/service/templates/main/about.html
 create mode 100644 src/webui/service/templates/main/home.html
 create mode 100644 src/webui/service/templates/service/home.html
 create mode 100644 src/webui/tests/__init__.py
 create mode 100644 src/webui/tests/test_unitary.py
 create mode 100644 src/webui/utils/__init__.py
 create mode 100644 src/webui/utils/form_validators.py

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 9946d3290..3249b820f 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -22,6 +22,7 @@ include:
   #- 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'
   # - local: '/src/l3_centralizedattackdetector/.gitlab-ci.yml'
   # - local: '/src/l3_attackmitigator/.gitlab-ci.yml'
diff --git a/deploy_in_kubernetes.sh b/deploy_in_kubernetes.sh
index c4019c7d7..58e35d249 100755
--- a/deploy_in_kubernetes.sh
+++ b/deploy_in_kubernetes.sh
@@ -10,7 +10,7 @@ REGISTRY_IMAGE=""
 #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"
+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"
diff --git a/install_development_dependencies.sh b/install_development_dependencies.sh
index 4b66f9c92..701e844d7 100755
--- a/install_development_dependencies.sh
+++ b/install_development_dependencies.sh
@@ -7,7 +7,7 @@ pip install --upgrade pip setuptools wheel pip-tools pylint pytest pytest-benchm
 echo "" > requirements.in
 
 #TODO: include here your component
-COMPONENTS="compute context device service monitoring opticalcentralizedattackdetector opticalattackmitigator dbscanserving"
+COMPONENTS="compute context device service monitoring opticalcentralizedattackdetector opticalattackmitigator dbscanserving webui"
 
 # compiling dependencies from all components
 for component in $COMPONENTS
diff --git a/manifests/webuiservice.yaml b/manifests/webuiservice.yaml
new file mode 100644
index 000000000..901328d27
--- /dev/null
+++ b/manifests/webuiservice.yaml
@@ -0,0 +1,72 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: webuiservice
+spec:
+  selector:
+    matchLabels:
+      app: webuiservice
+  template:
+    metadata:
+      labels:
+        app: webuiservice
+    spec:
+      terminationGracePeriodSeconds: 5
+      containers:
+      - name: server
+        image: registry.gitlab.com/teraflow-h2020/controller/webui:latest
+        imagePullPolicy: Always
+        ports:
+        - containerPort: 8004 # TODO: define the real port
+        env:
+        - name: LOG_LEVEL
+          value: "DEBUG"
+        readinessProbe:
+          httpGet:
+            path: /healthz/ready
+            port: 8004
+          initialDelaySeconds: 5
+          timeoutSeconds: 1
+        livenessProbe:
+          httpGet:
+            path: /healthz/live
+            port: 8004
+          initialDelaySeconds: 5
+          timeoutSeconds: 1
+        resources:
+          requests:
+            cpu: 250m
+            memory: 512Mi
+          limits:
+            cpu: 700m
+            memory: 1024Mi
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: webuiservice
+spec:
+  type: ClusterIP
+  selector:
+    app: webuiservice
+  ports:
+  - name: http
+    port: 8004
+    targetPort: 8004
+---
+# apiVersion: v1
+# kind: Service
+# metadata:
+#   name: webuiservice-public
+#   labels:
+#     app: webuiservice
+# spec:
+#   type: NodePort
+#   selector:
+#     app: webuiservice
+#   ports:
+#   - name: http
+#     protocol: TCP
+#     port: 8004
+#     targetPort: 8004
+---
diff --git a/open_webui.sh b/open_webui.sh
new file mode 100755
index 000000000..83d25d9c7
--- /dev/null
+++ b/open_webui.sh
@@ -0,0 +1,12 @@
+# this script opens the webui
+
+WEBUI_PROTO=`kubectl get service/webuiservice -n tf-dev -o jsonpath='{.spec.ports[0].name}'`
+WEBUI_IP=`kubectl get service/webuiservice -n tf-dev -o jsonpath='{.spec.clusterIP}'`
+WEBUI_PORT=`kubectl get service/webuiservice -n tf-dev -o jsonpath='{.spec.ports[0].port}'`
+URL=${WEBUI_PROTO}://${WEBUI_IP}:${WEBUI_PORT}
+
+echo Opening web UI on URL ${URL}
+
+# curl -kL ${URL}
+
+python3 -m webbrowser ${URL}
\ No newline at end of file
diff --git a/run_tests_locally.sh b/run_tests_locally.sh
index eb421c608..11add2a82 100755
--- a/run_tests_locally.sh
+++ b/run_tests_locally.sh
@@ -59,3 +59,6 @@ coverage run --rcfile=$RCFILE --append -m pytest --log-level=INFO --verbose \
 
 coverage run --rcfile=$RCFILE --append -m pytest --log-level=INFO --verbose \
     compute/tests/test_unitary.py
+
+coverage run --rcfile=$RCFILE --append -m pytest --log-level=INFO --verbose \
+    webui/tests/test_unitary.py
diff --git a/src/context/requirements.txt b/src/context/requirements.txt
new file mode 100644
index 000000000..1f0e17131
--- /dev/null
+++ b/src/context/requirements.txt
@@ -0,0 +1,72 @@
+#
+# This file is autogenerated by pip-compile with python 3.9
+# To update, run:
+#
+#    pip-compile src/context/requirements.in
+#
+aniso8601==9.0.1
+    # via flask-restful
+attrs==21.2.0
+    # via pytest
+certifi==2021.5.30
+    # via requests
+charset-normalizer==2.0.6
+    # via requests
+click==8.0.1
+    # via flask
+flask==2.0.1
+    # via flask-restful
+flask-restful==0.3.9
+    # via -r src/context/requirements.in
+grpcio==1.41.0
+    # via
+    #   -r src/context/requirements.in
+    #   grpcio-health-checking
+grpcio-health-checking==1.41.0
+    # via -r src/context/requirements.in
+idna==3.2
+    # via requests
+iniconfig==1.1.1
+    # via pytest
+itsdangerous==2.0.1
+    # via flask
+jinja2==3.0.1
+    # via flask
+markupsafe==2.0.1
+    # via jinja2
+packaging==21.0
+    # via pytest
+pluggy==1.0.0
+    # via pytest
+prometheus-client==0.11.0
+    # via -r src/context/requirements.in
+protobuf==3.18.0
+    # via grpcio-health-checking
+py==1.10.0
+    # via pytest
+py-cpuinfo==8.0.0
+    # via pytest-benchmark
+pyparsing==2.4.7
+    # via packaging
+pytest==6.2.5
+    # via
+    #   -r src/context/requirements.in
+    #   pytest-benchmark
+pytest-benchmark==3.4.1
+    # via -r src/context/requirements.in
+pytz==2021.1
+    # via flask-restful
+redis==3.5.3
+    # via -r src/context/requirements.in
+requests==2.26.0
+    # via -r src/context/requirements.in
+six==1.16.0
+    # via
+    #   flask-restful
+    #   grpcio
+toml==0.10.2
+    # via pytest
+urllib3==1.26.7
+    # via requests
+werkzeug==2.0.1
+    # via flask
diff --git a/src/device/client/DeviceClient.py b/src/device/client/DeviceClient.py
index 7c5fa0ca2..17f0ac715 100644
--- a/src/device/client/DeviceClient.py
+++ b/src/device/client/DeviceClient.py
@@ -22,7 +22,7 @@ class DeviceClient:
         self.stub = DeviceServiceStub(self.channel)
 
     def close(self):
-        if self.channel is not None: self.channel.close()
+        if(self.channel is not None): self.channel.close()
         self.channel = None
         self.stub = None
 
diff --git a/src/start_webui_dev_mode.sh b/src/start_webui_dev_mode.sh
new file mode 100755
index 000000000..32cf9c7f1
--- /dev/null
+++ b/src/start_webui_dev_mode.sh
@@ -0,0 +1,15 @@
+# for development purposes only
+
+export CONTEXT_SERVICE_ADDRESS=`kubectl get service/contextservice -n tf-dev -o jsonpath='{.spec.clusterIP}'`
+
+echo $CONTEXT_SERVICE_ADDRESS
+
+export DEVICE_SERVICE_ADDRESS=`kubectl get service/deviceservice -n tf-dev -o jsonpath='{.spec.clusterIP}'`
+
+echo $DEVICE_SERVICE_ADDRESS
+
+export HOST="127.0.0.1"
+
+export FLASK_ENV="development"
+
+python -m webui.service
diff --git a/src/webui/.gitlab-ci.yml b/src/webui/.gitlab-ci.yml
new file mode 100644
index 000000000..d803c72de
--- /dev/null
+++ b/src/webui/.gitlab-ci.yml
@@ -0,0 +1,89 @@
+# build, tag and push the Docker image to the gitlab registry
+build webui:
+  variables:
+    IMAGE_NAME: 'webui' # 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"
+  after_script:
+    - docker images --filter="dangling=true" --quiet | xargs -r docker rmi
+  rules:
+    - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)'
+    - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"' 
+    - changes:
+      - src/$IMAGE_NAME/**/*.{py,in,yml}
+      - src/$IMAGE_NAME/Dockerfile
+      - src/$IMAGE_NAME/tests/*.py
+      - src/$IMAGE_NAME/tests/Dockerfile
+      - manifests/$IMAGE_NAME.yaml
+      - .gitlab-ci.yml
+
+# apply unit test to the webui component
+unit test webui:
+  variables:
+    IMAGE_NAME: 'webui' # name of the microservice
+    IMAGE_TAG: 'latest' # tag of the container image (production, development, etc)
+  stage: unit_test
+  needs:
+    - build webui
+  before_script:
+    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
+    - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create -d bridge teraflowbridge; fi
+    - if docker container ls | grep $IMAGE_NAME; then docker rm -f $IMAGE_NAME; else echo "$IMAGE_NAME image is not in the system"; fi
+  script:
+    - docker pull "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG"
+    - docker run --name $IMAGE_NAME -d -p 8004:8004 -v "$PWD/src/$IMAGE_NAME/tests:/opt/results" --network=teraflowbridge  --rm $CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG
+    - sleep 5
+    - docker ps -a
+    - docker logs $IMAGE_NAME
+    - docker exec -i $IMAGE_NAME bash -c "coverage run -m pytest --log-level=DEBUG --verbose ${IMAGE_NAME}/tests/test_unitary.py --junitxml=/opt/results/${IMAGE_NAME}_report.xml; coverage xml -o /opt/results/${IMAGE_NAME}_coverage.xml; ls -la /opt/results; coverage report --include='${IMAGE_NAME}/*' --show-missing"
+  coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/'
+  after_script:
+    - docker rm -f $IMAGE_NAME
+    - docker network rm teraflowbridge
+  rules:
+    - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)'
+    - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"' 
+    - changes:
+      - src/$IMAGE_NAME/**/*.{py,in,yml}
+      - src/$IMAGE_NAME/Dockerfile
+      - src/$IMAGE_NAME/tests/*.py
+      - src/$IMAGE_NAME/tests/Dockerfile
+      - manifests/$IMAGE_NAME.yaml
+      - .gitlab-ci.yml
+  artifacts:
+      when: always
+      reports:
+        junit: src/$IMAGE_NAME/tests/${IMAGE_NAME}_report.xml
+        cobertura: src/$IMAGE_NAME/tests/${IMAGE_NAME}_coverage.xml
+
+# Deployment of the webui service in Kubernetes Cluster
+deploy webui:
+  variables:
+    IMAGE_NAME: 'webui' # name of the microservice
+    IMAGE_TAG: 'latest' # tag of the container image (production, development, etc)
+  stage: deploy
+  needs:
+    - unit test webui
+    # - integ_test execute
+  script:
+    - 'sed -i "s/$IMAGE_NAME:.*/$IMAGE_NAME:$IMAGE_TAG/" manifests/$IMAGE_NAME.yaml'
+    - kubectl version
+    - kubectl get all
+    - kubectl apply -f "manifests/$IMAGE_NAME.yaml"
+    - kubectl get all
+  # environment:
+  #   name: test
+  #   url: https://example.com
+  #   kubernetes:
+  #     namespace: test
+  rules:
+    - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)'
+      when: manual    
+    - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"'
+      when: manual
\ No newline at end of file
diff --git a/src/webui/Config.py b/src/webui/Config.py
new file mode 100644
index 000000000..e4ea65f4a
--- /dev/null
+++ b/src/webui/Config.py
@@ -0,0 +1,23 @@
+import os
+import logging
+
+# General settings
+LOG_LEVEL = logging.DEBUG
+
+# gRPC settings
+WEBUI_SERVICE_PORT = 8004
+
+# Prometheus settings
+METRICS_PORT = 9192
+
+SECRET_KEY = '>s&}24@{]]#k3&^5$f3#?6?h3{W@[}/7z}2pa]>{3&5%RP<)[('
+
+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
+
+DEVICE_SERVICE_ADDRESS = os.environ.get('DEVICESERVICE_SERVICE_HOST', 'deviceservice')
+DEVICE_SERVICE_PORT = 2020
diff --git a/src/webui/Dockerfile b/src/webui/Dockerfile
new file mode 100644
index 000000000..24c5c5296
--- /dev/null
+++ b/src/webui/Dockerfile
@@ -0,0 +1,46 @@
+FROM python:3-slim
+
+# Ref: https://pythonspeed.com/articles/activate-virtualenv-dockerfile/
+
+# Install dependencies
+RUN apt-get --yes --quiet --quiet update && \
+    apt-get --yes --quiet --quiet install wget g++ && \
+    rm -rf /var/lib/apt/lists/*
+
+# Set Python to show logs as they occur
+ENV PYTHONUNBUFFERED=0
+ENV PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION='python'
+
+# Download the gRPC health probe -- not needed here... health will be asserted using HTTP
+# RUN GRPC_HEALTH_PROBE_VERSION=v0.2.0 && \
+#     wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \
+#     chmod +x /bin/grpc_health_probe
+
+# creating a user for security reasons
+RUN groupadd -r webui && useradd --no-log-init -r -m -g webui webui
+USER webui
+
+# set working directory
+RUN mkdir -p /home/webui/teraflow
+WORKDIR /home/webui/teraflow
+
+# Get Python packages per module
+ENV VIRTUAL_ENV=/home/webui/venv
+RUN python3 -m venv ${VIRTUAL_ENV}
+ENV PATH="${VIRTUAL_ENV}/bin:${PATH}"
+COPY --chown=webui:webui webui/requirements.in /home/webui/teraflow/webui/requirements.in
+RUN pip install --upgrade "pip<22" setuptools wheel pip-tools && pip-compile --output-file=webui/requirements.txt webui/requirements.in
+RUN pip install -r webui/requirements.txt
+
+# Add files into working directory
+COPY --chown=webui:webui common/. common
+COPY --chown=webui:webui context/__init__.py context/__init__.py
+COPY --chown=webui:webui context/proto/. context/proto
+COPY --chown=webui:webui context/client/. context/client
+COPY --chown=webui:webui device/__init__.py device/__init__.py
+COPY --chown=webui:webui device/proto/. device/proto
+COPY --chown=webui:webui device/client/. device/client
+COPY --chown=webui:webui webui/. webui
+
+# Start webui service
+ENTRYPOINT ["python", "-m", "webui.service"]
diff --git a/src/webui/__init__.py b/src/webui/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/webui/genproto.sh b/src/webui/genproto.sh
new file mode 100755
index 000000000..1cd87af70
--- /dev/null
+++ b/src/webui/genproto.sh
@@ -0,0 +1,43 @@
+#!/bin/bash -eu
+#
+# Copyright 2018 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#!/bin/bash -e
+
+# Make folder containing the script the root folder for its execution
+cd $(dirname $0)
+
+rm -rf proto/*.py
+rm -rf proto/__pycache__
+touch proto/__init__.py
+
+# building protos of services used
+# python -m grpc_tools.protoc -I../../proto --python_out=proto --grpc_python_out=proto compute.proto
+python -m grpc_tools.protoc -I../../proto --python_out=proto --grpc_python_out=proto context.proto
+python -m grpc_tools.protoc -I../../proto --python_out=proto --grpc_python_out=proto device.proto
+python -m grpc_tools.protoc -I../../proto --python_out=proto --grpc_python_out=proto service.proto
+python -m grpc_tools.protoc -I../../proto --python_out=proto --grpc_python_out=proto monitoring.proto
+
+# rm proto/compute_pb2_grpc.py
+rm proto/context_pb2_grpc.py
+rm proto/device_pb2_grpc.py
+rm proto/service_pb2_grpc.py
+rm proto/monitoring_pb2_grpc.py
+
+# sed -i -E 's/(import\ .*)_pb2/from . \1_pb2/g' proto/compute_pb2.py
+sed -i -E 's/(import\ .*)_pb2/from . \1_pb2/g' proto/context_pb2.py
+sed -i -E 's/(import\ .*)_pb2/from . \1_pb2/g' proto/device_pb2.py
+sed -i -E 's/(import\ .*)_pb2/from . \1_pb2/g' proto/service_pb2.py
+sed -i -E 's/(import\ .*)_pb2/from . \1_pb2/g' proto/monitoring_pb2.py
diff --git a/src/webui/proto/__init__.py b/src/webui/proto/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/webui/proto/context_pb2.py b/src/webui/proto/context_pb2.py
new file mode 100644
index 000000000..8b4848bc3
--- /dev/null
+++ b/src/webui/proto/context_pb2.py
@@ -0,0 +1,2535 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: context.proto
+"""Generated protocol buffer code."""
+from google.protobuf.internal import enum_type_wrapper
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from google.protobuf import reflection as _reflection
+from google.protobuf import symbol_database as _symbol_database
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor.FileDescriptor(
+  name='context.proto',
+  package='context',
+  syntax='proto3',
+  serialized_options=None,
+  create_key=_descriptor._internal_create_key,
+  serialized_pb=b'\n\rcontext.proto\x12\x07\x63ontext\"\x07\n\x05\x45mpty\"\x14\n\x04Uuid\x12\x0c\n\x04uuid\x18\x01 \x01(\t\"F\n\x05\x45vent\x12\x11\n\ttimestamp\x18\x01 \x01(\x01\x12*\n\nevent_type\x18\x02 \x01(\x0e\x32\x16.context.EventTypeEnum\"0\n\tContextId\x12#\n\x0c\x63ontext_uuid\x18\x01 \x01(\x0b\x32\r.context.Uuid\"\xb6\x01\n\x07\x43ontext\x12&\n\ncontext_id\x18\x01 \x01(\x0b\x32\x12.context.ContextId\x12)\n\x0ctopology_ids\x18\x02 \x03(\x0b\x32\x13.context.TopologyId\x12\'\n\x0bservice_ids\x18\x03 \x03(\x0b\x32\x12.context.ServiceId\x12/\n\ncontroller\x18\x04 \x01(\x0b\x32\x1b.context.TeraFlowController\"8\n\rContextIdList\x12\'\n\x0b\x63ontext_ids\x18\x01 \x03(\x0b\x32\x12.context.ContextId\"1\n\x0b\x43ontextList\x12\"\n\x08\x63ontexts\x18\x01 \x03(\x0b\x32\x10.context.Context\"U\n\x0c\x43ontextEvent\x12\x1d\n\x05\x65vent\x18\x01 \x01(\x0b\x32\x0e.context.Event\x12&\n\ncontext_id\x18\x02 \x01(\x0b\x32\x12.context.ContextId\"Z\n\nTopologyId\x12&\n\ncontext_id\x18\x01 \x01(\x0b\x32\x12.context.ContextId\x12$\n\rtopology_uuid\x18\x02 \x01(\x0b\x32\r.context.Uuid\"~\n\x08Topology\x12(\n\x0btopology_id\x18\x01 \x01(\x0b\x32\x13.context.TopologyId\x12%\n\ndevice_ids\x18\x02 \x03(\x0b\x32\x11.context.DeviceId\x12!\n\x08link_ids\x18\x03 \x03(\x0b\x32\x0f.context.LinkId\";\n\x0eTopologyIdList\x12)\n\x0ctopology_ids\x18\x01 \x03(\x0b\x32\x13.context.TopologyId\"5\n\x0cTopologyList\x12%\n\ntopologies\x18\x01 \x03(\x0b\x32\x11.context.Topology\"X\n\rTopologyEvent\x12\x1d\n\x05\x65vent\x18\x01 \x01(\x0b\x32\x0e.context.Event\x12(\n\x0btopology_id\x18\x02 \x01(\x0b\x32\x13.context.TopologyId\".\n\x08\x44\x65viceId\x12\"\n\x0b\x64\x65vice_uuid\x18\x01 \x01(\x0b\x32\r.context.Uuid\"\x9a\x02\n\x06\x44\x65vice\x12$\n\tdevice_id\x18\x01 \x01(\x0b\x32\x11.context.DeviceId\x12\x13\n\x0b\x64\x65vice_type\x18\x02 \x01(\t\x12,\n\rdevice_config\x18\x03 \x01(\x0b\x32\x15.context.DeviceConfig\x12G\n\x19\x64\x65vice_operational_status\x18\x04 \x01(\x0e\x32$.context.DeviceOperationalStatusEnum\x12\x31\n\x0e\x64\x65vice_drivers\x18\x05 \x03(\x0e\x32\x19.context.DeviceDriverEnum\x12+\n\x10\x64\x65vice_endpoints\x18\x06 \x03(\x0b\x32\x11.context.EndPoint\"9\n\x0c\x44\x65viceConfig\x12)\n\x0c\x63onfig_rules\x18\x01 \x03(\x0b\x32\x13.context.ConfigRule\"5\n\x0c\x44\x65viceIdList\x12%\n\ndevice_ids\x18\x01 \x03(\x0b\x32\x11.context.DeviceId\".\n\nDeviceList\x12 \n\x07\x64\x65vices\x18\x01 \x03(\x0b\x32\x0f.context.Device\"R\n\x0b\x44\x65viceEvent\x12\x1d\n\x05\x65vent\x18\x01 \x01(\x0b\x32\x0e.context.Event\x12$\n\tdevice_id\x18\x02 \x01(\x0b\x32\x11.context.DeviceId\"*\n\x06LinkId\x12 \n\tlink_uuid\x18\x01 \x01(\x0b\x32\r.context.Uuid\"X\n\x04Link\x12 \n\x07link_id\x18\x01 \x01(\x0b\x32\x0f.context.LinkId\x12.\n\x11link_endpoint_ids\x18\x02 \x03(\x0b\x32\x13.context.EndPointId\"/\n\nLinkIdList\x12!\n\x08link_ids\x18\x01 \x03(\x0b\x32\x0f.context.LinkId\"(\n\x08LinkList\x12\x1c\n\x05links\x18\x01 \x03(\x0b\x32\r.context.Link\"L\n\tLinkEvent\x12\x1d\n\x05\x65vent\x18\x01 \x01(\x0b\x32\x0e.context.Event\x12 \n\x07link_id\x18\x02 \x01(\x0b\x32\x0f.context.LinkId\"X\n\tServiceId\x12&\n\ncontext_id\x18\x01 \x01(\x0b\x32\x12.context.ContextId\x12#\n\x0cservice_uuid\x18\x02 \x01(\x0b\x32\r.context.Uuid\"\xa6\x02\n\x07Service\x12&\n\nservice_id\x18\x01 \x01(\x0b\x32\x12.context.ServiceId\x12.\n\x0cservice_type\x18\x02 \x01(\x0e\x32\x18.context.ServiceTypeEnum\x12\x31\n\x14service_endpoint_ids\x18\x03 \x03(\x0b\x32\x13.context.EndPointId\x12\x30\n\x13service_constraints\x18\x04 \x03(\x0b\x32\x13.context.Constraint\x12.\n\x0eservice_status\x18\x05 \x01(\x0b\x32\x16.context.ServiceStatus\x12.\n\x0eservice_config\x18\x06 \x01(\x0b\x32\x16.context.ServiceConfig\"C\n\rServiceStatus\x12\x32\n\x0eservice_status\x18\x01 \x01(\x0e\x32\x1a.context.ServiceStatusEnum\":\n\rServiceConfig\x12)\n\x0c\x63onfig_rules\x18\x01 \x03(\x0b\x32\x13.context.ConfigRule\"8\n\rServiceIdList\x12\'\n\x0bservice_ids\x18\x01 \x03(\x0b\x32\x12.context.ServiceId\"1\n\x0bServiceList\x12\"\n\x08services\x18\x01 \x03(\x0b\x32\x10.context.Service\"U\n\x0cServiceEvent\x12\x1d\n\x05\x65vent\x18\x01 \x01(\x0b\x32\x0e.context.Event\x12&\n\nservice_id\x18\x02 \x01(\x0b\x32\x12.context.ServiceId\"\x82\x01\n\nEndPointId\x12(\n\x0btopology_id\x18\x01 \x01(\x0b\x32\x13.context.TopologyId\x12$\n\tdevice_id\x18\x02 \x01(\x0b\x32\x11.context.DeviceId\x12$\n\rendpoint_uuid\x18\x03 \x01(\x0b\x32\r.context.Uuid\"K\n\x08\x45ndPoint\x12(\n\x0b\x65ndpoint_id\x18\x01 \x01(\x0b\x32\x13.context.EndPointId\x12\x15\n\rendpoint_type\x18\x02 \x01(\t\"e\n\nConfigRule\x12)\n\x06\x61\x63tion\x18\x01 \x01(\x0e\x32\x19.context.ConfigActionEnum\x12\x14\n\x0cresource_key\x18\x02 \x01(\t\x12\x16\n\x0eresource_value\x18\x03 \x01(\t\"?\n\nConstraint\x12\x17\n\x0f\x63onstraint_type\x18\x01 \x01(\t\x12\x18\n\x10\x63onstraint_value\x18\x02 \x01(\t\"6\n\x0c\x43onnectionId\x12&\n\x0f\x63onnection_uuid\x18\x01 \x01(\x0b\x32\r.context.Uuid\"\x8d\x01\n\nConnection\x12,\n\rconnection_id\x18\x01 \x01(\x0b\x32\x15.context.ConnectionId\x12.\n\x12related_service_id\x18\x02 \x01(\x0b\x32\x12.context.ServiceId\x12!\n\x04path\x18\x03 \x03(\x0b\x32\x13.context.EndPointId\"A\n\x10\x43onnectionIdList\x12-\n\x0e\x63onnection_ids\x18\x01 \x03(\x0b\x32\x15.context.ConnectionId\":\n\x0e\x43onnectionList\x12(\n\x0b\x63onnections\x18\x01 \x03(\x0b\x32\x13.context.Connection\"^\n\x12TeraFlowController\x12&\n\ncontext_id\x18\x01 \x01(\x0b\x32\x12.context.ContextId\x12\x12\n\nip_address\x18\x02 \x01(\t\x12\x0c\n\x04port\x18\x03 \x01(\r\"U\n\x14\x41uthenticationResult\x12&\n\ncontext_id\x18\x01 \x01(\x0b\x32\x12.context.ContextId\x12\x15\n\rauthenticated\x18\x02 \x01(\x08*j\n\rEventTypeEnum\x12\x17\n\x13\x45VENTTYPE_UNDEFINED\x10\x00\x12\x14\n\x10\x45VENTTYPE_CREATE\x10\x01\x12\x14\n\x10\x45VENTTYPE_UPDATE\x10\x02\x12\x14\n\x10\x45VENTTYPE_REMOVE\x10\x03*\xc5\x01\n\x10\x44\x65viceDriverEnum\x12\x1a\n\x16\x44\x45VICEDRIVER_UNDEFINED\x10\x00\x12\x1b\n\x17\x44\x45VICEDRIVER_OPENCONFIG\x10\x01\x12\x1e\n\x1a\x44\x45VICEDRIVER_TRANSPORT_API\x10\x02\x12\x13\n\x0f\x44\x45VICEDRIVER_P4\x10\x03\x12&\n\"DEVICEDRIVER_IETF_NETWORK_TOPOLOGY\x10\x04\x12\x1b\n\x17\x44\x45VICEDRIVER_ONF_TR_352\x10\x05*\x8f\x01\n\x1b\x44\x65viceOperationalStatusEnum\x12%\n!DEVICEOPERATIONALSTATUS_UNDEFINED\x10\x00\x12$\n DEVICEOPERATIONALSTATUS_DISABLED\x10\x01\x12#\n\x1f\x44\x45VICEOPERATIONALSTATUS_ENABLED\x10\x02*\x81\x01\n\x0fServiceTypeEnum\x12\x17\n\x13SERVICETYPE_UNKNOWN\x10\x00\x12\x14\n\x10SERVICETYPE_L3NM\x10\x01\x12\x14\n\x10SERVICETYPE_L2NM\x10\x02\x12)\n%SERVICETYPE_TAPI_CONNECTIVITY_SERVICE\x10\x03*\x88\x01\n\x11ServiceStatusEnum\x12\x1b\n\x17SERVICESTATUS_UNDEFINED\x10\x00\x12\x19\n\x15SERVICESTATUS_PLANNED\x10\x01\x12\x18\n\x14SERVICESTATUS_ACTIVE\x10\x02\x12!\n\x1dSERVICESTATUS_PENDING_REMOVAL\x10\x03*]\n\x10\x43onfigActionEnum\x12\x1a\n\x16\x43ONFIGACTION_UNDEFINED\x10\x00\x12\x14\n\x10\x43ONFIGACTION_SET\x10\x01\x12\x17\n\x13\x43ONFIGACTION_DELETE\x10\x02\x32\xa5\r\n\x0e\x43ontextService\x12:\n\x0eListContextIds\x12\x0e.context.Empty\x1a\x16.context.ContextIdList\"\x00\x12\x36\n\x0cListContexts\x12\x0e.context.Empty\x1a\x14.context.ContextList\"\x00\x12\x34\n\nGetContext\x12\x12.context.ContextId\x1a\x10.context.Context\"\x00\x12\x34\n\nSetContext\x12\x10.context.Context\x1a\x12.context.ContextId\"\x00\x12\x35\n\rRemoveContext\x12\x12.context.ContextId\x1a\x0e.context.Empty\"\x00\x12=\n\x10GetContextEvents\x12\x0e.context.Empty\x1a\x15.context.ContextEvent\"\x00\x30\x01\x12@\n\x0fListTopologyIds\x12\x12.context.ContextId\x1a\x17.context.TopologyIdList\"\x00\x12=\n\x0eListTopologies\x12\x12.context.ContextId\x1a\x15.context.TopologyList\"\x00\x12\x37\n\x0bGetTopology\x12\x13.context.TopologyId\x1a\x11.context.Topology\"\x00\x12\x37\n\x0bSetTopology\x12\x11.context.Topology\x1a\x13.context.TopologyId\"\x00\x12\x37\n\x0eRemoveTopology\x12\x13.context.TopologyId\x1a\x0e.context.Empty\"\x00\x12?\n\x11GetTopologyEvents\x12\x0e.context.Empty\x1a\x16.context.TopologyEvent\"\x00\x30\x01\x12\x38\n\rListDeviceIds\x12\x0e.context.Empty\x1a\x15.context.DeviceIdList\"\x00\x12\x34\n\x0bListDevices\x12\x0e.context.Empty\x1a\x13.context.DeviceList\"\x00\x12\x31\n\tGetDevice\x12\x11.context.DeviceId\x1a\x0f.context.Device\"\x00\x12\x31\n\tSetDevice\x12\x0f.context.Device\x1a\x11.context.DeviceId\"\x00\x12\x33\n\x0cRemoveDevice\x12\x11.context.DeviceId\x1a\x0e.context.Empty\"\x00\x12;\n\x0fGetDeviceEvents\x12\x0e.context.Empty\x1a\x14.context.DeviceEvent\"\x00\x30\x01\x12\x34\n\x0bListLinkIds\x12\x0e.context.Empty\x1a\x13.context.LinkIdList\"\x00\x12\x30\n\tListLinks\x12\x0e.context.Empty\x1a\x11.context.LinkList\"\x00\x12+\n\x07GetLink\x12\x0f.context.LinkId\x1a\r.context.Link\"\x00\x12+\n\x07SetLink\x12\r.context.Link\x1a\x0f.context.LinkId\"\x00\x12/\n\nRemoveLink\x12\x0f.context.LinkId\x1a\x0e.context.Empty\"\x00\x12\x37\n\rGetLinkEvents\x12\x0e.context.Empty\x1a\x12.context.LinkEvent\"\x00\x30\x01\x12>\n\x0eListServiceIds\x12\x12.context.ContextId\x1a\x16.context.ServiceIdList\"\x00\x12:\n\x0cListServices\x12\x12.context.ContextId\x1a\x14.context.ServiceList\"\x00\x12\x34\n\nGetService\x12\x12.context.ServiceId\x1a\x10.context.Service\"\x00\x12\x34\n\nSetService\x12\x10.context.Service\x1a\x12.context.ServiceId\"\x00\x12\x35\n\rRemoveService\x12\x12.context.ServiceId\x1a\x0e.context.Empty\"\x00\x12=\n\x10GetServiceEvents\x12\x0e.context.Empty\x1a\x15.context.ServiceEvent\"\x00\x30\x01\x62\x06proto3'
+)
+
+_EVENTTYPEENUM = _descriptor.EnumDescriptor(
+  name='EventTypeEnum',
+  full_name='context.EventTypeEnum',
+  filename=None,
+  file=DESCRIPTOR,
+  create_key=_descriptor._internal_create_key,
+  values=[
+    _descriptor.EnumValueDescriptor(
+      name='EVENTTYPE_UNDEFINED', index=0, number=0,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+    _descriptor.EnumValueDescriptor(
+      name='EVENTTYPE_CREATE', index=1, number=1,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+    _descriptor.EnumValueDescriptor(
+      name='EVENTTYPE_UPDATE', index=2, number=2,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+    _descriptor.EnumValueDescriptor(
+      name='EVENTTYPE_REMOVE', index=3, number=3,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+  ],
+  containing_type=None,
+  serialized_options=None,
+  serialized_start=3468,
+  serialized_end=3574,
+)
+_sym_db.RegisterEnumDescriptor(_EVENTTYPEENUM)
+
+EventTypeEnum = enum_type_wrapper.EnumTypeWrapper(_EVENTTYPEENUM)
+_DEVICEDRIVERENUM = _descriptor.EnumDescriptor(
+  name='DeviceDriverEnum',
+  full_name='context.DeviceDriverEnum',
+  filename=None,
+  file=DESCRIPTOR,
+  create_key=_descriptor._internal_create_key,
+  values=[
+    _descriptor.EnumValueDescriptor(
+      name='DEVICEDRIVER_UNDEFINED', index=0, number=0,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+    _descriptor.EnumValueDescriptor(
+      name='DEVICEDRIVER_OPENCONFIG', index=1, number=1,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+    _descriptor.EnumValueDescriptor(
+      name='DEVICEDRIVER_TRANSPORT_API', index=2, number=2,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+    _descriptor.EnumValueDescriptor(
+      name='DEVICEDRIVER_P4', index=3, number=3,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+    _descriptor.EnumValueDescriptor(
+      name='DEVICEDRIVER_IETF_NETWORK_TOPOLOGY', index=4, number=4,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+    _descriptor.EnumValueDescriptor(
+      name='DEVICEDRIVER_ONF_TR_352', index=5, number=5,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+  ],
+  containing_type=None,
+  serialized_options=None,
+  serialized_start=3577,
+  serialized_end=3774,
+)
+_sym_db.RegisterEnumDescriptor(_DEVICEDRIVERENUM)
+
+DeviceDriverEnum = enum_type_wrapper.EnumTypeWrapper(_DEVICEDRIVERENUM)
+_DEVICEOPERATIONALSTATUSENUM = _descriptor.EnumDescriptor(
+  name='DeviceOperationalStatusEnum',
+  full_name='context.DeviceOperationalStatusEnum',
+  filename=None,
+  file=DESCRIPTOR,
+  create_key=_descriptor._internal_create_key,
+  values=[
+    _descriptor.EnumValueDescriptor(
+      name='DEVICEOPERATIONALSTATUS_UNDEFINED', index=0, number=0,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+    _descriptor.EnumValueDescriptor(
+      name='DEVICEOPERATIONALSTATUS_DISABLED', index=1, number=1,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+    _descriptor.EnumValueDescriptor(
+      name='DEVICEOPERATIONALSTATUS_ENABLED', index=2, number=2,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+  ],
+  containing_type=None,
+  serialized_options=None,
+  serialized_start=3777,
+  serialized_end=3920,
+)
+_sym_db.RegisterEnumDescriptor(_DEVICEOPERATIONALSTATUSENUM)
+
+DeviceOperationalStatusEnum = enum_type_wrapper.EnumTypeWrapper(_DEVICEOPERATIONALSTATUSENUM)
+_SERVICETYPEENUM = _descriptor.EnumDescriptor(
+  name='ServiceTypeEnum',
+  full_name='context.ServiceTypeEnum',
+  filename=None,
+  file=DESCRIPTOR,
+  create_key=_descriptor._internal_create_key,
+  values=[
+    _descriptor.EnumValueDescriptor(
+      name='SERVICETYPE_UNKNOWN', index=0, number=0,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+    _descriptor.EnumValueDescriptor(
+      name='SERVICETYPE_L3NM', index=1, number=1,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+    _descriptor.EnumValueDescriptor(
+      name='SERVICETYPE_L2NM', index=2, number=2,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+    _descriptor.EnumValueDescriptor(
+      name='SERVICETYPE_TAPI_CONNECTIVITY_SERVICE', index=3, number=3,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+  ],
+  containing_type=None,
+  serialized_options=None,
+  serialized_start=3923,
+  serialized_end=4052,
+)
+_sym_db.RegisterEnumDescriptor(_SERVICETYPEENUM)
+
+ServiceTypeEnum = enum_type_wrapper.EnumTypeWrapper(_SERVICETYPEENUM)
+_SERVICESTATUSENUM = _descriptor.EnumDescriptor(
+  name='ServiceStatusEnum',
+  full_name='context.ServiceStatusEnum',
+  filename=None,
+  file=DESCRIPTOR,
+  create_key=_descriptor._internal_create_key,
+  values=[
+    _descriptor.EnumValueDescriptor(
+      name='SERVICESTATUS_UNDEFINED', index=0, number=0,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+    _descriptor.EnumValueDescriptor(
+      name='SERVICESTATUS_PLANNED', index=1, number=1,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+    _descriptor.EnumValueDescriptor(
+      name='SERVICESTATUS_ACTIVE', index=2, number=2,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+    _descriptor.EnumValueDescriptor(
+      name='SERVICESTATUS_PENDING_REMOVAL', index=3, number=3,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+  ],
+  containing_type=None,
+  serialized_options=None,
+  serialized_start=4055,
+  serialized_end=4191,
+)
+_sym_db.RegisterEnumDescriptor(_SERVICESTATUSENUM)
+
+ServiceStatusEnum = enum_type_wrapper.EnumTypeWrapper(_SERVICESTATUSENUM)
+_CONFIGACTIONENUM = _descriptor.EnumDescriptor(
+  name='ConfigActionEnum',
+  full_name='context.ConfigActionEnum',
+  filename=None,
+  file=DESCRIPTOR,
+  create_key=_descriptor._internal_create_key,
+  values=[
+    _descriptor.EnumValueDescriptor(
+      name='CONFIGACTION_UNDEFINED', index=0, number=0,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+    _descriptor.EnumValueDescriptor(
+      name='CONFIGACTION_SET', index=1, number=1,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+    _descriptor.EnumValueDescriptor(
+      name='CONFIGACTION_DELETE', index=2, number=2,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+  ],
+  containing_type=None,
+  serialized_options=None,
+  serialized_start=4193,
+  serialized_end=4286,
+)
+_sym_db.RegisterEnumDescriptor(_CONFIGACTIONENUM)
+
+ConfigActionEnum = enum_type_wrapper.EnumTypeWrapper(_CONFIGACTIONENUM)
+EVENTTYPE_UNDEFINED = 0
+EVENTTYPE_CREATE = 1
+EVENTTYPE_UPDATE = 2
+EVENTTYPE_REMOVE = 3
+DEVICEDRIVER_UNDEFINED = 0
+DEVICEDRIVER_OPENCONFIG = 1
+DEVICEDRIVER_TRANSPORT_API = 2
+DEVICEDRIVER_P4 = 3
+DEVICEDRIVER_IETF_NETWORK_TOPOLOGY = 4
+DEVICEDRIVER_ONF_TR_352 = 5
+DEVICEOPERATIONALSTATUS_UNDEFINED = 0
+DEVICEOPERATIONALSTATUS_DISABLED = 1
+DEVICEOPERATIONALSTATUS_ENABLED = 2
+SERVICETYPE_UNKNOWN = 0
+SERVICETYPE_L3NM = 1
+SERVICETYPE_L2NM = 2
+SERVICETYPE_TAPI_CONNECTIVITY_SERVICE = 3
+SERVICESTATUS_UNDEFINED = 0
+SERVICESTATUS_PLANNED = 1
+SERVICESTATUS_ACTIVE = 2
+SERVICESTATUS_PENDING_REMOVAL = 3
+CONFIGACTION_UNDEFINED = 0
+CONFIGACTION_SET = 1
+CONFIGACTION_DELETE = 2
+
+
+
+_EMPTY = _descriptor.Descriptor(
+  name='Empty',
+  full_name='context.Empty',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=26,
+  serialized_end=33,
+)
+
+
+_UUID = _descriptor.Descriptor(
+  name='Uuid',
+  full_name='context.Uuid',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='uuid', full_name='context.Uuid.uuid', index=0,
+      number=1, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=b"".decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=35,
+  serialized_end=55,
+)
+
+
+_EVENT = _descriptor.Descriptor(
+  name='Event',
+  full_name='context.Event',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='timestamp', full_name='context.Event.timestamp', index=0,
+      number=1, type=1, cpp_type=5, label=1,
+      has_default_value=False, default_value=float(0),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='event_type', full_name='context.Event.event_type', index=1,
+      number=2, type=14, cpp_type=8, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=57,
+  serialized_end=127,
+)
+
+
+_CONTEXTID = _descriptor.Descriptor(
+  name='ContextId',
+  full_name='context.ContextId',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='context_uuid', full_name='context.ContextId.context_uuid', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=129,
+  serialized_end=177,
+)
+
+
+_CONTEXT = _descriptor.Descriptor(
+  name='Context',
+  full_name='context.Context',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='context_id', full_name='context.Context.context_id', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='topology_ids', full_name='context.Context.topology_ids', index=1,
+      number=2, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='service_ids', full_name='context.Context.service_ids', index=2,
+      number=3, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='controller', full_name='context.Context.controller', index=3,
+      number=4, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=180,
+  serialized_end=362,
+)
+
+
+_CONTEXTIDLIST = _descriptor.Descriptor(
+  name='ContextIdList',
+  full_name='context.ContextIdList',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='context_ids', full_name='context.ContextIdList.context_ids', index=0,
+      number=1, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=364,
+  serialized_end=420,
+)
+
+
+_CONTEXTLIST = _descriptor.Descriptor(
+  name='ContextList',
+  full_name='context.ContextList',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='contexts', full_name='context.ContextList.contexts', index=0,
+      number=1, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=422,
+  serialized_end=471,
+)
+
+
+_CONTEXTEVENT = _descriptor.Descriptor(
+  name='ContextEvent',
+  full_name='context.ContextEvent',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='event', full_name='context.ContextEvent.event', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='context_id', full_name='context.ContextEvent.context_id', index=1,
+      number=2, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=473,
+  serialized_end=558,
+)
+
+
+_TOPOLOGYID = _descriptor.Descriptor(
+  name='TopologyId',
+  full_name='context.TopologyId',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='context_id', full_name='context.TopologyId.context_id', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='topology_uuid', full_name='context.TopologyId.topology_uuid', index=1,
+      number=2, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=560,
+  serialized_end=650,
+)
+
+
+_TOPOLOGY = _descriptor.Descriptor(
+  name='Topology',
+  full_name='context.Topology',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='topology_id', full_name='context.Topology.topology_id', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='device_ids', full_name='context.Topology.device_ids', index=1,
+      number=2, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='link_ids', full_name='context.Topology.link_ids', index=2,
+      number=3, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=652,
+  serialized_end=778,
+)
+
+
+_TOPOLOGYIDLIST = _descriptor.Descriptor(
+  name='TopologyIdList',
+  full_name='context.TopologyIdList',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='topology_ids', full_name='context.TopologyIdList.topology_ids', index=0,
+      number=1, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=780,
+  serialized_end=839,
+)
+
+
+_TOPOLOGYLIST = _descriptor.Descriptor(
+  name='TopologyList',
+  full_name='context.TopologyList',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='topologies', full_name='context.TopologyList.topologies', index=0,
+      number=1, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=841,
+  serialized_end=894,
+)
+
+
+_TOPOLOGYEVENT = _descriptor.Descriptor(
+  name='TopologyEvent',
+  full_name='context.TopologyEvent',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='event', full_name='context.TopologyEvent.event', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='topology_id', full_name='context.TopologyEvent.topology_id', index=1,
+      number=2, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=896,
+  serialized_end=984,
+)
+
+
+_DEVICEID = _descriptor.Descriptor(
+  name='DeviceId',
+  full_name='context.DeviceId',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='device_uuid', full_name='context.DeviceId.device_uuid', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=986,
+  serialized_end=1032,
+)
+
+
+_DEVICE = _descriptor.Descriptor(
+  name='Device',
+  full_name='context.Device',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='device_id', full_name='context.Device.device_id', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='device_type', full_name='context.Device.device_type', index=1,
+      number=2, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=b"".decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='device_config', full_name='context.Device.device_config', index=2,
+      number=3, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='device_operational_status', full_name='context.Device.device_operational_status', index=3,
+      number=4, type=14, cpp_type=8, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='device_drivers', full_name='context.Device.device_drivers', index=4,
+      number=5, type=14, cpp_type=8, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='device_endpoints', full_name='context.Device.device_endpoints', index=5,
+      number=6, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=1035,
+  serialized_end=1317,
+)
+
+
+_DEVICECONFIG = _descriptor.Descriptor(
+  name='DeviceConfig',
+  full_name='context.DeviceConfig',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='config_rules', full_name='context.DeviceConfig.config_rules', index=0,
+      number=1, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=1319,
+  serialized_end=1376,
+)
+
+
+_DEVICEIDLIST = _descriptor.Descriptor(
+  name='DeviceIdList',
+  full_name='context.DeviceIdList',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='device_ids', full_name='context.DeviceIdList.device_ids', index=0,
+      number=1, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=1378,
+  serialized_end=1431,
+)
+
+
+_DEVICELIST = _descriptor.Descriptor(
+  name='DeviceList',
+  full_name='context.DeviceList',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='devices', full_name='context.DeviceList.devices', index=0,
+      number=1, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=1433,
+  serialized_end=1479,
+)
+
+
+_DEVICEEVENT = _descriptor.Descriptor(
+  name='DeviceEvent',
+  full_name='context.DeviceEvent',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='event', full_name='context.DeviceEvent.event', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='device_id', full_name='context.DeviceEvent.device_id', index=1,
+      number=2, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=1481,
+  serialized_end=1563,
+)
+
+
+_LINKID = _descriptor.Descriptor(
+  name='LinkId',
+  full_name='context.LinkId',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='link_uuid', full_name='context.LinkId.link_uuid', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=1565,
+  serialized_end=1607,
+)
+
+
+_LINK = _descriptor.Descriptor(
+  name='Link',
+  full_name='context.Link',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='link_id', full_name='context.Link.link_id', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='link_endpoint_ids', full_name='context.Link.link_endpoint_ids', index=1,
+      number=2, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=1609,
+  serialized_end=1697,
+)
+
+
+_LINKIDLIST = _descriptor.Descriptor(
+  name='LinkIdList',
+  full_name='context.LinkIdList',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='link_ids', full_name='context.LinkIdList.link_ids', index=0,
+      number=1, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=1699,
+  serialized_end=1746,
+)
+
+
+_LINKLIST = _descriptor.Descriptor(
+  name='LinkList',
+  full_name='context.LinkList',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='links', full_name='context.LinkList.links', index=0,
+      number=1, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=1748,
+  serialized_end=1788,
+)
+
+
+_LINKEVENT = _descriptor.Descriptor(
+  name='LinkEvent',
+  full_name='context.LinkEvent',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='event', full_name='context.LinkEvent.event', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='link_id', full_name='context.LinkEvent.link_id', index=1,
+      number=2, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=1790,
+  serialized_end=1866,
+)
+
+
+_SERVICEID = _descriptor.Descriptor(
+  name='ServiceId',
+  full_name='context.ServiceId',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='context_id', full_name='context.ServiceId.context_id', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='service_uuid', full_name='context.ServiceId.service_uuid', index=1,
+      number=2, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=1868,
+  serialized_end=1956,
+)
+
+
+_SERVICE = _descriptor.Descriptor(
+  name='Service',
+  full_name='context.Service',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='service_id', full_name='context.Service.service_id', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='service_type', full_name='context.Service.service_type', index=1,
+      number=2, type=14, cpp_type=8, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='service_endpoint_ids', full_name='context.Service.service_endpoint_ids', index=2,
+      number=3, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='service_constraints', full_name='context.Service.service_constraints', index=3,
+      number=4, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='service_status', full_name='context.Service.service_status', index=4,
+      number=5, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='service_config', full_name='context.Service.service_config', index=5,
+      number=6, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=1959,
+  serialized_end=2253,
+)
+
+
+_SERVICESTATUS = _descriptor.Descriptor(
+  name='ServiceStatus',
+  full_name='context.ServiceStatus',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='service_status', full_name='context.ServiceStatus.service_status', index=0,
+      number=1, type=14, cpp_type=8, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=2255,
+  serialized_end=2322,
+)
+
+
+_SERVICECONFIG = _descriptor.Descriptor(
+  name='ServiceConfig',
+  full_name='context.ServiceConfig',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='config_rules', full_name='context.ServiceConfig.config_rules', index=0,
+      number=1, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=2324,
+  serialized_end=2382,
+)
+
+
+_SERVICEIDLIST = _descriptor.Descriptor(
+  name='ServiceIdList',
+  full_name='context.ServiceIdList',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='service_ids', full_name='context.ServiceIdList.service_ids', index=0,
+      number=1, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=2384,
+  serialized_end=2440,
+)
+
+
+_SERVICELIST = _descriptor.Descriptor(
+  name='ServiceList',
+  full_name='context.ServiceList',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='services', full_name='context.ServiceList.services', index=0,
+      number=1, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=2442,
+  serialized_end=2491,
+)
+
+
+_SERVICEEVENT = _descriptor.Descriptor(
+  name='ServiceEvent',
+  full_name='context.ServiceEvent',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='event', full_name='context.ServiceEvent.event', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='service_id', full_name='context.ServiceEvent.service_id', index=1,
+      number=2, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=2493,
+  serialized_end=2578,
+)
+
+
+_ENDPOINTID = _descriptor.Descriptor(
+  name='EndPointId',
+  full_name='context.EndPointId',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='topology_id', full_name='context.EndPointId.topology_id', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='device_id', full_name='context.EndPointId.device_id', index=1,
+      number=2, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='endpoint_uuid', full_name='context.EndPointId.endpoint_uuid', index=2,
+      number=3, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=2581,
+  serialized_end=2711,
+)
+
+
+_ENDPOINT = _descriptor.Descriptor(
+  name='EndPoint',
+  full_name='context.EndPoint',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='endpoint_id', full_name='context.EndPoint.endpoint_id', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='endpoint_type', full_name='context.EndPoint.endpoint_type', index=1,
+      number=2, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=b"".decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=2713,
+  serialized_end=2788,
+)
+
+
+_CONFIGRULE = _descriptor.Descriptor(
+  name='ConfigRule',
+  full_name='context.ConfigRule',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='action', full_name='context.ConfigRule.action', index=0,
+      number=1, type=14, cpp_type=8, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='resource_key', full_name='context.ConfigRule.resource_key', index=1,
+      number=2, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=b"".decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='resource_value', full_name='context.ConfigRule.resource_value', index=2,
+      number=3, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=b"".decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=2790,
+  serialized_end=2891,
+)
+
+
+_CONSTRAINT = _descriptor.Descriptor(
+  name='Constraint',
+  full_name='context.Constraint',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='constraint_type', full_name='context.Constraint.constraint_type', index=0,
+      number=1, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=b"".decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='constraint_value', full_name='context.Constraint.constraint_value', index=1,
+      number=2, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=b"".decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=2893,
+  serialized_end=2956,
+)
+
+
+_CONNECTIONID = _descriptor.Descriptor(
+  name='ConnectionId',
+  full_name='context.ConnectionId',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='connection_uuid', full_name='context.ConnectionId.connection_uuid', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=2958,
+  serialized_end=3012,
+)
+
+
+_CONNECTION = _descriptor.Descriptor(
+  name='Connection',
+  full_name='context.Connection',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='connection_id', full_name='context.Connection.connection_id', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='related_service_id', full_name='context.Connection.related_service_id', index=1,
+      number=2, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='path', full_name='context.Connection.path', index=2,
+      number=3, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=3015,
+  serialized_end=3156,
+)
+
+
+_CONNECTIONIDLIST = _descriptor.Descriptor(
+  name='ConnectionIdList',
+  full_name='context.ConnectionIdList',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='connection_ids', full_name='context.ConnectionIdList.connection_ids', index=0,
+      number=1, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=3158,
+  serialized_end=3223,
+)
+
+
+_CONNECTIONLIST = _descriptor.Descriptor(
+  name='ConnectionList',
+  full_name='context.ConnectionList',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='connections', full_name='context.ConnectionList.connections', index=0,
+      number=1, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=3225,
+  serialized_end=3283,
+)
+
+
+_TERAFLOWCONTROLLER = _descriptor.Descriptor(
+  name='TeraFlowController',
+  full_name='context.TeraFlowController',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='context_id', full_name='context.TeraFlowController.context_id', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='ip_address', full_name='context.TeraFlowController.ip_address', index=1,
+      number=2, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=b"".decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='port', full_name='context.TeraFlowController.port', index=2,
+      number=3, type=13, cpp_type=3, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=3285,
+  serialized_end=3379,
+)
+
+
+_AUTHENTICATIONRESULT = _descriptor.Descriptor(
+  name='AuthenticationResult',
+  full_name='context.AuthenticationResult',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='context_id', full_name='context.AuthenticationResult.context_id', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='authenticated', full_name='context.AuthenticationResult.authenticated', index=1,
+      number=2, type=8, cpp_type=7, label=1,
+      has_default_value=False, default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=3381,
+  serialized_end=3466,
+)
+
+_EVENT.fields_by_name['event_type'].enum_type = _EVENTTYPEENUM
+_CONTEXTID.fields_by_name['context_uuid'].message_type = _UUID
+_CONTEXT.fields_by_name['context_id'].message_type = _CONTEXTID
+_CONTEXT.fields_by_name['topology_ids'].message_type = _TOPOLOGYID
+_CONTEXT.fields_by_name['service_ids'].message_type = _SERVICEID
+_CONTEXT.fields_by_name['controller'].message_type = _TERAFLOWCONTROLLER
+_CONTEXTIDLIST.fields_by_name['context_ids'].message_type = _CONTEXTID
+_CONTEXTLIST.fields_by_name['contexts'].message_type = _CONTEXT
+_CONTEXTEVENT.fields_by_name['event'].message_type = _EVENT
+_CONTEXTEVENT.fields_by_name['context_id'].message_type = _CONTEXTID
+_TOPOLOGYID.fields_by_name['context_id'].message_type = _CONTEXTID
+_TOPOLOGYID.fields_by_name['topology_uuid'].message_type = _UUID
+_TOPOLOGY.fields_by_name['topology_id'].message_type = _TOPOLOGYID
+_TOPOLOGY.fields_by_name['device_ids'].message_type = _DEVICEID
+_TOPOLOGY.fields_by_name['link_ids'].message_type = _LINKID
+_TOPOLOGYIDLIST.fields_by_name['topology_ids'].message_type = _TOPOLOGYID
+_TOPOLOGYLIST.fields_by_name['topologies'].message_type = _TOPOLOGY
+_TOPOLOGYEVENT.fields_by_name['event'].message_type = _EVENT
+_TOPOLOGYEVENT.fields_by_name['topology_id'].message_type = _TOPOLOGYID
+_DEVICEID.fields_by_name['device_uuid'].message_type = _UUID
+_DEVICE.fields_by_name['device_id'].message_type = _DEVICEID
+_DEVICE.fields_by_name['device_config'].message_type = _DEVICECONFIG
+_DEVICE.fields_by_name['device_operational_status'].enum_type = _DEVICEOPERATIONALSTATUSENUM
+_DEVICE.fields_by_name['device_drivers'].enum_type = _DEVICEDRIVERENUM
+_DEVICE.fields_by_name['device_endpoints'].message_type = _ENDPOINT
+_DEVICECONFIG.fields_by_name['config_rules'].message_type = _CONFIGRULE
+_DEVICEIDLIST.fields_by_name['device_ids'].message_type = _DEVICEID
+_DEVICELIST.fields_by_name['devices'].message_type = _DEVICE
+_DEVICEEVENT.fields_by_name['event'].message_type = _EVENT
+_DEVICEEVENT.fields_by_name['device_id'].message_type = _DEVICEID
+_LINKID.fields_by_name['link_uuid'].message_type = _UUID
+_LINK.fields_by_name['link_id'].message_type = _LINKID
+_LINK.fields_by_name['link_endpoint_ids'].message_type = _ENDPOINTID
+_LINKIDLIST.fields_by_name['link_ids'].message_type = _LINKID
+_LINKLIST.fields_by_name['links'].message_type = _LINK
+_LINKEVENT.fields_by_name['event'].message_type = _EVENT
+_LINKEVENT.fields_by_name['link_id'].message_type = _LINKID
+_SERVICEID.fields_by_name['context_id'].message_type = _CONTEXTID
+_SERVICEID.fields_by_name['service_uuid'].message_type = _UUID
+_SERVICE.fields_by_name['service_id'].message_type = _SERVICEID
+_SERVICE.fields_by_name['service_type'].enum_type = _SERVICETYPEENUM
+_SERVICE.fields_by_name['service_endpoint_ids'].message_type = _ENDPOINTID
+_SERVICE.fields_by_name['service_constraints'].message_type = _CONSTRAINT
+_SERVICE.fields_by_name['service_status'].message_type = _SERVICESTATUS
+_SERVICE.fields_by_name['service_config'].message_type = _SERVICECONFIG
+_SERVICESTATUS.fields_by_name['service_status'].enum_type = _SERVICESTATUSENUM
+_SERVICECONFIG.fields_by_name['config_rules'].message_type = _CONFIGRULE
+_SERVICEIDLIST.fields_by_name['service_ids'].message_type = _SERVICEID
+_SERVICELIST.fields_by_name['services'].message_type = _SERVICE
+_SERVICEEVENT.fields_by_name['event'].message_type = _EVENT
+_SERVICEEVENT.fields_by_name['service_id'].message_type = _SERVICEID
+_ENDPOINTID.fields_by_name['topology_id'].message_type = _TOPOLOGYID
+_ENDPOINTID.fields_by_name['device_id'].message_type = _DEVICEID
+_ENDPOINTID.fields_by_name['endpoint_uuid'].message_type = _UUID
+_ENDPOINT.fields_by_name['endpoint_id'].message_type = _ENDPOINTID
+_CONFIGRULE.fields_by_name['action'].enum_type = _CONFIGACTIONENUM
+_CONNECTIONID.fields_by_name['connection_uuid'].message_type = _UUID
+_CONNECTION.fields_by_name['connection_id'].message_type = _CONNECTIONID
+_CONNECTION.fields_by_name['related_service_id'].message_type = _SERVICEID
+_CONNECTION.fields_by_name['path'].message_type = _ENDPOINTID
+_CONNECTIONIDLIST.fields_by_name['connection_ids'].message_type = _CONNECTIONID
+_CONNECTIONLIST.fields_by_name['connections'].message_type = _CONNECTION
+_TERAFLOWCONTROLLER.fields_by_name['context_id'].message_type = _CONTEXTID
+_AUTHENTICATIONRESULT.fields_by_name['context_id'].message_type = _CONTEXTID
+DESCRIPTOR.message_types_by_name['Empty'] = _EMPTY
+DESCRIPTOR.message_types_by_name['Uuid'] = _UUID
+DESCRIPTOR.message_types_by_name['Event'] = _EVENT
+DESCRIPTOR.message_types_by_name['ContextId'] = _CONTEXTID
+DESCRIPTOR.message_types_by_name['Context'] = _CONTEXT
+DESCRIPTOR.message_types_by_name['ContextIdList'] = _CONTEXTIDLIST
+DESCRIPTOR.message_types_by_name['ContextList'] = _CONTEXTLIST
+DESCRIPTOR.message_types_by_name['ContextEvent'] = _CONTEXTEVENT
+DESCRIPTOR.message_types_by_name['TopologyId'] = _TOPOLOGYID
+DESCRIPTOR.message_types_by_name['Topology'] = _TOPOLOGY
+DESCRIPTOR.message_types_by_name['TopologyIdList'] = _TOPOLOGYIDLIST
+DESCRIPTOR.message_types_by_name['TopologyList'] = _TOPOLOGYLIST
+DESCRIPTOR.message_types_by_name['TopologyEvent'] = _TOPOLOGYEVENT
+DESCRIPTOR.message_types_by_name['DeviceId'] = _DEVICEID
+DESCRIPTOR.message_types_by_name['Device'] = _DEVICE
+DESCRIPTOR.message_types_by_name['DeviceConfig'] = _DEVICECONFIG
+DESCRIPTOR.message_types_by_name['DeviceIdList'] = _DEVICEIDLIST
+DESCRIPTOR.message_types_by_name['DeviceList'] = _DEVICELIST
+DESCRIPTOR.message_types_by_name['DeviceEvent'] = _DEVICEEVENT
+DESCRIPTOR.message_types_by_name['LinkId'] = _LINKID
+DESCRIPTOR.message_types_by_name['Link'] = _LINK
+DESCRIPTOR.message_types_by_name['LinkIdList'] = _LINKIDLIST
+DESCRIPTOR.message_types_by_name['LinkList'] = _LINKLIST
+DESCRIPTOR.message_types_by_name['LinkEvent'] = _LINKEVENT
+DESCRIPTOR.message_types_by_name['ServiceId'] = _SERVICEID
+DESCRIPTOR.message_types_by_name['Service'] = _SERVICE
+DESCRIPTOR.message_types_by_name['ServiceStatus'] = _SERVICESTATUS
+DESCRIPTOR.message_types_by_name['ServiceConfig'] = _SERVICECONFIG
+DESCRIPTOR.message_types_by_name['ServiceIdList'] = _SERVICEIDLIST
+DESCRIPTOR.message_types_by_name['ServiceList'] = _SERVICELIST
+DESCRIPTOR.message_types_by_name['ServiceEvent'] = _SERVICEEVENT
+DESCRIPTOR.message_types_by_name['EndPointId'] = _ENDPOINTID
+DESCRIPTOR.message_types_by_name['EndPoint'] = _ENDPOINT
+DESCRIPTOR.message_types_by_name['ConfigRule'] = _CONFIGRULE
+DESCRIPTOR.message_types_by_name['Constraint'] = _CONSTRAINT
+DESCRIPTOR.message_types_by_name['ConnectionId'] = _CONNECTIONID
+DESCRIPTOR.message_types_by_name['Connection'] = _CONNECTION
+DESCRIPTOR.message_types_by_name['ConnectionIdList'] = _CONNECTIONIDLIST
+DESCRIPTOR.message_types_by_name['ConnectionList'] = _CONNECTIONLIST
+DESCRIPTOR.message_types_by_name['TeraFlowController'] = _TERAFLOWCONTROLLER
+DESCRIPTOR.message_types_by_name['AuthenticationResult'] = _AUTHENTICATIONRESULT
+DESCRIPTOR.enum_types_by_name['EventTypeEnum'] = _EVENTTYPEENUM
+DESCRIPTOR.enum_types_by_name['DeviceDriverEnum'] = _DEVICEDRIVERENUM
+DESCRIPTOR.enum_types_by_name['DeviceOperationalStatusEnum'] = _DEVICEOPERATIONALSTATUSENUM
+DESCRIPTOR.enum_types_by_name['ServiceTypeEnum'] = _SERVICETYPEENUM
+DESCRIPTOR.enum_types_by_name['ServiceStatusEnum'] = _SERVICESTATUSENUM
+DESCRIPTOR.enum_types_by_name['ConfigActionEnum'] = _CONFIGACTIONENUM
+_sym_db.RegisterFileDescriptor(DESCRIPTOR)
+
+Empty = _reflection.GeneratedProtocolMessageType('Empty', (_message.Message,), {
+  'DESCRIPTOR' : _EMPTY,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.Empty)
+  })
+_sym_db.RegisterMessage(Empty)
+
+Uuid = _reflection.GeneratedProtocolMessageType('Uuid', (_message.Message,), {
+  'DESCRIPTOR' : _UUID,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.Uuid)
+  })
+_sym_db.RegisterMessage(Uuid)
+
+Event = _reflection.GeneratedProtocolMessageType('Event', (_message.Message,), {
+  'DESCRIPTOR' : _EVENT,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.Event)
+  })
+_sym_db.RegisterMessage(Event)
+
+ContextId = _reflection.GeneratedProtocolMessageType('ContextId', (_message.Message,), {
+  'DESCRIPTOR' : _CONTEXTID,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.ContextId)
+  })
+_sym_db.RegisterMessage(ContextId)
+
+Context = _reflection.GeneratedProtocolMessageType('Context', (_message.Message,), {
+  'DESCRIPTOR' : _CONTEXT,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.Context)
+  })
+_sym_db.RegisterMessage(Context)
+
+ContextIdList = _reflection.GeneratedProtocolMessageType('ContextIdList', (_message.Message,), {
+  'DESCRIPTOR' : _CONTEXTIDLIST,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.ContextIdList)
+  })
+_sym_db.RegisterMessage(ContextIdList)
+
+ContextList = _reflection.GeneratedProtocolMessageType('ContextList', (_message.Message,), {
+  'DESCRIPTOR' : _CONTEXTLIST,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.ContextList)
+  })
+_sym_db.RegisterMessage(ContextList)
+
+ContextEvent = _reflection.GeneratedProtocolMessageType('ContextEvent', (_message.Message,), {
+  'DESCRIPTOR' : _CONTEXTEVENT,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.ContextEvent)
+  })
+_sym_db.RegisterMessage(ContextEvent)
+
+TopologyId = _reflection.GeneratedProtocolMessageType('TopologyId', (_message.Message,), {
+  'DESCRIPTOR' : _TOPOLOGYID,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.TopologyId)
+  })
+_sym_db.RegisterMessage(TopologyId)
+
+Topology = _reflection.GeneratedProtocolMessageType('Topology', (_message.Message,), {
+  'DESCRIPTOR' : _TOPOLOGY,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.Topology)
+  })
+_sym_db.RegisterMessage(Topology)
+
+TopologyIdList = _reflection.GeneratedProtocolMessageType('TopologyIdList', (_message.Message,), {
+  'DESCRIPTOR' : _TOPOLOGYIDLIST,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.TopologyIdList)
+  })
+_sym_db.RegisterMessage(TopologyIdList)
+
+TopologyList = _reflection.GeneratedProtocolMessageType('TopologyList', (_message.Message,), {
+  'DESCRIPTOR' : _TOPOLOGYLIST,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.TopologyList)
+  })
+_sym_db.RegisterMessage(TopologyList)
+
+TopologyEvent = _reflection.GeneratedProtocolMessageType('TopologyEvent', (_message.Message,), {
+  'DESCRIPTOR' : _TOPOLOGYEVENT,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.TopologyEvent)
+  })
+_sym_db.RegisterMessage(TopologyEvent)
+
+DeviceId = _reflection.GeneratedProtocolMessageType('DeviceId', (_message.Message,), {
+  'DESCRIPTOR' : _DEVICEID,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.DeviceId)
+  })
+_sym_db.RegisterMessage(DeviceId)
+
+Device = _reflection.GeneratedProtocolMessageType('Device', (_message.Message,), {
+  'DESCRIPTOR' : _DEVICE,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.Device)
+  })
+_sym_db.RegisterMessage(Device)
+
+DeviceConfig = _reflection.GeneratedProtocolMessageType('DeviceConfig', (_message.Message,), {
+  'DESCRIPTOR' : _DEVICECONFIG,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.DeviceConfig)
+  })
+_sym_db.RegisterMessage(DeviceConfig)
+
+DeviceIdList = _reflection.GeneratedProtocolMessageType('DeviceIdList', (_message.Message,), {
+  'DESCRIPTOR' : _DEVICEIDLIST,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.DeviceIdList)
+  })
+_sym_db.RegisterMessage(DeviceIdList)
+
+DeviceList = _reflection.GeneratedProtocolMessageType('DeviceList', (_message.Message,), {
+  'DESCRIPTOR' : _DEVICELIST,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.DeviceList)
+  })
+_sym_db.RegisterMessage(DeviceList)
+
+DeviceEvent = _reflection.GeneratedProtocolMessageType('DeviceEvent', (_message.Message,), {
+  'DESCRIPTOR' : _DEVICEEVENT,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.DeviceEvent)
+  })
+_sym_db.RegisterMessage(DeviceEvent)
+
+LinkId = _reflection.GeneratedProtocolMessageType('LinkId', (_message.Message,), {
+  'DESCRIPTOR' : _LINKID,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.LinkId)
+  })
+_sym_db.RegisterMessage(LinkId)
+
+Link = _reflection.GeneratedProtocolMessageType('Link', (_message.Message,), {
+  'DESCRIPTOR' : _LINK,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.Link)
+  })
+_sym_db.RegisterMessage(Link)
+
+LinkIdList = _reflection.GeneratedProtocolMessageType('LinkIdList', (_message.Message,), {
+  'DESCRIPTOR' : _LINKIDLIST,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.LinkIdList)
+  })
+_sym_db.RegisterMessage(LinkIdList)
+
+LinkList = _reflection.GeneratedProtocolMessageType('LinkList', (_message.Message,), {
+  'DESCRIPTOR' : _LINKLIST,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.LinkList)
+  })
+_sym_db.RegisterMessage(LinkList)
+
+LinkEvent = _reflection.GeneratedProtocolMessageType('LinkEvent', (_message.Message,), {
+  'DESCRIPTOR' : _LINKEVENT,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.LinkEvent)
+  })
+_sym_db.RegisterMessage(LinkEvent)
+
+ServiceId = _reflection.GeneratedProtocolMessageType('ServiceId', (_message.Message,), {
+  'DESCRIPTOR' : _SERVICEID,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.ServiceId)
+  })
+_sym_db.RegisterMessage(ServiceId)
+
+Service = _reflection.GeneratedProtocolMessageType('Service', (_message.Message,), {
+  'DESCRIPTOR' : _SERVICE,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.Service)
+  })
+_sym_db.RegisterMessage(Service)
+
+ServiceStatus = _reflection.GeneratedProtocolMessageType('ServiceStatus', (_message.Message,), {
+  'DESCRIPTOR' : _SERVICESTATUS,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.ServiceStatus)
+  })
+_sym_db.RegisterMessage(ServiceStatus)
+
+ServiceConfig = _reflection.GeneratedProtocolMessageType('ServiceConfig', (_message.Message,), {
+  'DESCRIPTOR' : _SERVICECONFIG,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.ServiceConfig)
+  })
+_sym_db.RegisterMessage(ServiceConfig)
+
+ServiceIdList = _reflection.GeneratedProtocolMessageType('ServiceIdList', (_message.Message,), {
+  'DESCRIPTOR' : _SERVICEIDLIST,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.ServiceIdList)
+  })
+_sym_db.RegisterMessage(ServiceIdList)
+
+ServiceList = _reflection.GeneratedProtocolMessageType('ServiceList', (_message.Message,), {
+  'DESCRIPTOR' : _SERVICELIST,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.ServiceList)
+  })
+_sym_db.RegisterMessage(ServiceList)
+
+ServiceEvent = _reflection.GeneratedProtocolMessageType('ServiceEvent', (_message.Message,), {
+  'DESCRIPTOR' : _SERVICEEVENT,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.ServiceEvent)
+  })
+_sym_db.RegisterMessage(ServiceEvent)
+
+EndPointId = _reflection.GeneratedProtocolMessageType('EndPointId', (_message.Message,), {
+  'DESCRIPTOR' : _ENDPOINTID,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.EndPointId)
+  })
+_sym_db.RegisterMessage(EndPointId)
+
+EndPoint = _reflection.GeneratedProtocolMessageType('EndPoint', (_message.Message,), {
+  'DESCRIPTOR' : _ENDPOINT,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.EndPoint)
+  })
+_sym_db.RegisterMessage(EndPoint)
+
+ConfigRule = _reflection.GeneratedProtocolMessageType('ConfigRule', (_message.Message,), {
+  'DESCRIPTOR' : _CONFIGRULE,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.ConfigRule)
+  })
+_sym_db.RegisterMessage(ConfigRule)
+
+Constraint = _reflection.GeneratedProtocolMessageType('Constraint', (_message.Message,), {
+  'DESCRIPTOR' : _CONSTRAINT,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.Constraint)
+  })
+_sym_db.RegisterMessage(Constraint)
+
+ConnectionId = _reflection.GeneratedProtocolMessageType('ConnectionId', (_message.Message,), {
+  'DESCRIPTOR' : _CONNECTIONID,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.ConnectionId)
+  })
+_sym_db.RegisterMessage(ConnectionId)
+
+Connection = _reflection.GeneratedProtocolMessageType('Connection', (_message.Message,), {
+  'DESCRIPTOR' : _CONNECTION,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.Connection)
+  })
+_sym_db.RegisterMessage(Connection)
+
+ConnectionIdList = _reflection.GeneratedProtocolMessageType('ConnectionIdList', (_message.Message,), {
+  'DESCRIPTOR' : _CONNECTIONIDLIST,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.ConnectionIdList)
+  })
+_sym_db.RegisterMessage(ConnectionIdList)
+
+ConnectionList = _reflection.GeneratedProtocolMessageType('ConnectionList', (_message.Message,), {
+  'DESCRIPTOR' : _CONNECTIONLIST,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.ConnectionList)
+  })
+_sym_db.RegisterMessage(ConnectionList)
+
+TeraFlowController = _reflection.GeneratedProtocolMessageType('TeraFlowController', (_message.Message,), {
+  'DESCRIPTOR' : _TERAFLOWCONTROLLER,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.TeraFlowController)
+  })
+_sym_db.RegisterMessage(TeraFlowController)
+
+AuthenticationResult = _reflection.GeneratedProtocolMessageType('AuthenticationResult', (_message.Message,), {
+  'DESCRIPTOR' : _AUTHENTICATIONRESULT,
+  '__module__' : 'context_pb2'
+  # @@protoc_insertion_point(class_scope:context.AuthenticationResult)
+  })
+_sym_db.RegisterMessage(AuthenticationResult)
+
+
+
+_CONTEXTSERVICE = _descriptor.ServiceDescriptor(
+  name='ContextService',
+  full_name='context.ContextService',
+  file=DESCRIPTOR,
+  index=0,
+  serialized_options=None,
+  create_key=_descriptor._internal_create_key,
+  serialized_start=4289,
+  serialized_end=5990,
+  methods=[
+  _descriptor.MethodDescriptor(
+    name='ListContextIds',
+    full_name='context.ContextService.ListContextIds',
+    index=0,
+    containing_service=None,
+    input_type=_EMPTY,
+    output_type=_CONTEXTIDLIST,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='ListContexts',
+    full_name='context.ContextService.ListContexts',
+    index=1,
+    containing_service=None,
+    input_type=_EMPTY,
+    output_type=_CONTEXTLIST,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='GetContext',
+    full_name='context.ContextService.GetContext',
+    index=2,
+    containing_service=None,
+    input_type=_CONTEXTID,
+    output_type=_CONTEXT,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='SetContext',
+    full_name='context.ContextService.SetContext',
+    index=3,
+    containing_service=None,
+    input_type=_CONTEXT,
+    output_type=_CONTEXTID,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='RemoveContext',
+    full_name='context.ContextService.RemoveContext',
+    index=4,
+    containing_service=None,
+    input_type=_CONTEXTID,
+    output_type=_EMPTY,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='GetContextEvents',
+    full_name='context.ContextService.GetContextEvents',
+    index=5,
+    containing_service=None,
+    input_type=_EMPTY,
+    output_type=_CONTEXTEVENT,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='ListTopologyIds',
+    full_name='context.ContextService.ListTopologyIds',
+    index=6,
+    containing_service=None,
+    input_type=_CONTEXTID,
+    output_type=_TOPOLOGYIDLIST,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='ListTopologies',
+    full_name='context.ContextService.ListTopologies',
+    index=7,
+    containing_service=None,
+    input_type=_CONTEXTID,
+    output_type=_TOPOLOGYLIST,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='GetTopology',
+    full_name='context.ContextService.GetTopology',
+    index=8,
+    containing_service=None,
+    input_type=_TOPOLOGYID,
+    output_type=_TOPOLOGY,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='SetTopology',
+    full_name='context.ContextService.SetTopology',
+    index=9,
+    containing_service=None,
+    input_type=_TOPOLOGY,
+    output_type=_TOPOLOGYID,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='RemoveTopology',
+    full_name='context.ContextService.RemoveTopology',
+    index=10,
+    containing_service=None,
+    input_type=_TOPOLOGYID,
+    output_type=_EMPTY,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='GetTopologyEvents',
+    full_name='context.ContextService.GetTopologyEvents',
+    index=11,
+    containing_service=None,
+    input_type=_EMPTY,
+    output_type=_TOPOLOGYEVENT,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='ListDeviceIds',
+    full_name='context.ContextService.ListDeviceIds',
+    index=12,
+    containing_service=None,
+    input_type=_EMPTY,
+    output_type=_DEVICEIDLIST,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='ListDevices',
+    full_name='context.ContextService.ListDevices',
+    index=13,
+    containing_service=None,
+    input_type=_EMPTY,
+    output_type=_DEVICELIST,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='GetDevice',
+    full_name='context.ContextService.GetDevice',
+    index=14,
+    containing_service=None,
+    input_type=_DEVICEID,
+    output_type=_DEVICE,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='SetDevice',
+    full_name='context.ContextService.SetDevice',
+    index=15,
+    containing_service=None,
+    input_type=_DEVICE,
+    output_type=_DEVICEID,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='RemoveDevice',
+    full_name='context.ContextService.RemoveDevice',
+    index=16,
+    containing_service=None,
+    input_type=_DEVICEID,
+    output_type=_EMPTY,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='GetDeviceEvents',
+    full_name='context.ContextService.GetDeviceEvents',
+    index=17,
+    containing_service=None,
+    input_type=_EMPTY,
+    output_type=_DEVICEEVENT,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='ListLinkIds',
+    full_name='context.ContextService.ListLinkIds',
+    index=18,
+    containing_service=None,
+    input_type=_EMPTY,
+    output_type=_LINKIDLIST,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='ListLinks',
+    full_name='context.ContextService.ListLinks',
+    index=19,
+    containing_service=None,
+    input_type=_EMPTY,
+    output_type=_LINKLIST,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='GetLink',
+    full_name='context.ContextService.GetLink',
+    index=20,
+    containing_service=None,
+    input_type=_LINKID,
+    output_type=_LINK,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='SetLink',
+    full_name='context.ContextService.SetLink',
+    index=21,
+    containing_service=None,
+    input_type=_LINK,
+    output_type=_LINKID,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='RemoveLink',
+    full_name='context.ContextService.RemoveLink',
+    index=22,
+    containing_service=None,
+    input_type=_LINKID,
+    output_type=_EMPTY,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='GetLinkEvents',
+    full_name='context.ContextService.GetLinkEvents',
+    index=23,
+    containing_service=None,
+    input_type=_EMPTY,
+    output_type=_LINKEVENT,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='ListServiceIds',
+    full_name='context.ContextService.ListServiceIds',
+    index=24,
+    containing_service=None,
+    input_type=_CONTEXTID,
+    output_type=_SERVICEIDLIST,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='ListServices',
+    full_name='context.ContextService.ListServices',
+    index=25,
+    containing_service=None,
+    input_type=_CONTEXTID,
+    output_type=_SERVICELIST,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='GetService',
+    full_name='context.ContextService.GetService',
+    index=26,
+    containing_service=None,
+    input_type=_SERVICEID,
+    output_type=_SERVICE,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='SetService',
+    full_name='context.ContextService.SetService',
+    index=27,
+    containing_service=None,
+    input_type=_SERVICE,
+    output_type=_SERVICEID,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='RemoveService',
+    full_name='context.ContextService.RemoveService',
+    index=28,
+    containing_service=None,
+    input_type=_SERVICEID,
+    output_type=_EMPTY,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='GetServiceEvents',
+    full_name='context.ContextService.GetServiceEvents',
+    index=29,
+    containing_service=None,
+    input_type=_EMPTY,
+    output_type=_SERVICEEVENT,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+])
+_sym_db.RegisterServiceDescriptor(_CONTEXTSERVICE)
+
+DESCRIPTOR.services_by_name['ContextService'] = _CONTEXTSERVICE
+
+# @@protoc_insertion_point(module_scope)
diff --git a/src/webui/proto/device_pb2.py b/src/webui/proto/device_pb2.py
new file mode 100644
index 000000000..e351738e6
--- /dev/null
+++ b/src/webui/proto/device_pb2.py
@@ -0,0 +1,88 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: device.proto
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from google.protobuf import reflection as _reflection
+from google.protobuf import symbol_database as _symbol_database
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+from . import context_pb2 as context__pb2
+
+
+DESCRIPTOR = _descriptor.FileDescriptor(
+  name='device.proto',
+  package='device',
+  syntax='proto3',
+  serialized_options=None,
+  create_key=_descriptor._internal_create_key,
+  serialized_pb=b'\n\x0c\x64\x65vice.proto\x12\x06\x64\x65vice\x1a\rcontext.proto2\xf0\x01\n\rDeviceService\x12\x31\n\tAddDevice\x12\x0f.context.Device\x1a\x11.context.DeviceId\"\x00\x12\x37\n\x0f\x43onfigureDevice\x12\x0f.context.Device\x1a\x11.context.DeviceId\"\x00\x12\x33\n\x0c\x44\x65leteDevice\x12\x11.context.DeviceId\x1a\x0e.context.Empty\"\x00\x12>\n\x10GetInitialConfig\x12\x11.context.DeviceId\x1a\x15.context.DeviceConfig\"\x00\x62\x06proto3'
+  ,
+  dependencies=[context__pb2.DESCRIPTOR,])
+
+
+
+_sym_db.RegisterFileDescriptor(DESCRIPTOR)
+
+
+
+_DEVICESERVICE = _descriptor.ServiceDescriptor(
+  name='DeviceService',
+  full_name='device.DeviceService',
+  file=DESCRIPTOR,
+  index=0,
+  serialized_options=None,
+  create_key=_descriptor._internal_create_key,
+  serialized_start=40,
+  serialized_end=280,
+  methods=[
+  _descriptor.MethodDescriptor(
+    name='AddDevice',
+    full_name='device.DeviceService.AddDevice',
+    index=0,
+    containing_service=None,
+    input_type=context__pb2._DEVICE,
+    output_type=context__pb2._DEVICEID,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='ConfigureDevice',
+    full_name='device.DeviceService.ConfigureDevice',
+    index=1,
+    containing_service=None,
+    input_type=context__pb2._DEVICE,
+    output_type=context__pb2._DEVICEID,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='DeleteDevice',
+    full_name='device.DeviceService.DeleteDevice',
+    index=2,
+    containing_service=None,
+    input_type=context__pb2._DEVICEID,
+    output_type=context__pb2._EMPTY,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='GetInitialConfig',
+    full_name='device.DeviceService.GetInitialConfig',
+    index=3,
+    containing_service=None,
+    input_type=context__pb2._DEVICEID,
+    output_type=context__pb2._DEVICECONFIG,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+])
+_sym_db.RegisterServiceDescriptor(_DEVICESERVICE)
+
+DESCRIPTOR.services_by_name['DeviceService'] = _DEVICESERVICE
+
+# @@protoc_insertion_point(module_scope)
diff --git a/src/webui/proto/monitoring_pb2.py b/src/webui/proto/monitoring_pb2.py
new file mode 100644
index 000000000..7368609d2
--- /dev/null
+++ b/src/webui/proto/monitoring_pb2.py
@@ -0,0 +1,617 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: monitoring.proto
+"""Generated protocol buffer code."""
+from google.protobuf.internal import enum_type_wrapper
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from google.protobuf import reflection as _reflection
+from google.protobuf import symbol_database as _symbol_database
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+from . import context_pb2 as context__pb2
+
+
+DESCRIPTOR = _descriptor.FileDescriptor(
+  name='monitoring.proto',
+  package='monitoring',
+  syntax='proto3',
+  serialized_options=None,
+  create_key=_descriptor._internal_create_key,
+  serialized_pb=b'\n\x10monitoring.proto\x12\nmonitoring\x1a\rcontext.proto\"\x84\x01\n\x10\x43reateKpiRequest\x12\x16\n\x0ekpiDescription\x18\x01 \x01(\t\x12$\n\tdevice_id\x18\x02 \x01(\x0b\x32\x11.context.DeviceId\x12\x32\n\x0fkpi_sample_type\x18\x03 \x01(\x0e\x32\x19.monitoring.KpiSampleType\"h\n\x11MonitorKpiRequest\x12!\n\x06kpi_id\x18\x01 \x01(\x0b\x32\x11.monitoring.KpiId\x12\x18\n\x10\x63onnexion_time_s\x18\x02 \x01(\r\x12\x16\n\x0esample_rate_ms\x18\x03 \x01(\r\"i\n\x17MonitorDeviceKpiRequest\x12\x1c\n\x03kpi\x18\x01 \x01(\x0b\x32\x0f.monitoring.Kpi\x12\x18\n\x10\x63onnexion_time_s\x18\x02 \x01(\r\x12\x16\n\x0esample_rate_ms\x18\x03 \x01(\r\"s\n\x11IncludeKpiRequest\x12!\n\x06kpi_id\x18\x01 \x01(\x0b\x32\x11.monitoring.KpiId\x12\x12\n\ntime_stamp\x18\x02 \x01(\t\x12\'\n\tkpi_value\x18\x03 \x01(\x0b\x32\x14.monitoring.KpiValue\"&\n\x05KpiId\x12\x1d\n\x06kpi_id\x18\x01 \x01(\x0b\x32\r.context.Uuid\"\xd6\x01\n\x03Kpi\x12!\n\x06kpi_id\x18\x01 \x01(\x0b\x32\x11.monitoring.KpiId\x12\x11\n\ttimestamp\x18\x02 \x01(\t\x12\x16\n\x0ekpiDescription\x18\x03 \x01(\t\x12\'\n\tkpi_value\x18\x04 \x01(\x0b\x32\x14.monitoring.KpiValue\x12\x32\n\x0fkpi_sample_type\x18\x05 \x01(\x0e\x32\x19.monitoring.KpiSampleType\x12$\n\tdevice_id\x18\x06 \x01(\x0b\x32\x11.context.DeviceId\"a\n\x08KpiValue\x12\x10\n\x06intVal\x18\x01 \x01(\rH\x00\x12\x12\n\x08\x66loatVal\x18\x02 \x01(\x02H\x00\x12\x13\n\tstringVal\x18\x03 \x01(\tH\x00\x12\x11\n\x07\x62oolVal\x18\x04 \x01(\x08H\x00\x42\x07\n\x05value\"+\n\x07KpiList\x12 \n\x07kpiList\x18\x01 \x03(\x0b\x32\x0f.monitoring.Kpi*x\n\rKpiSampleType\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x17\n\x13PACKETS_TRANSMITTED\x10\x65\x12\x14\n\x10PACKETS_RECEIVED\x10\x66\x12\x16\n\x11\x42YTES_TRANSMITTED\x10\xc9\x01\x12\x13\n\x0e\x42YTES_RECEIVED\x10\xca\x01\x32\x8b\x03\n\x11MonitoringService\x12>\n\tCreateKpi\x12\x1c.monitoring.CreateKpiRequest\x1a\x11.monitoring.KpiId\"\x00\x12=\n\nIncludeKpi\x12\x1d.monitoring.IncludeKpiRequest\x1a\x0e.context.Empty\"\x00\x12=\n\nMonitorKpi\x12\x1d.monitoring.MonitorKpiRequest\x1a\x0e.context.Empty\"\x00\x12I\n\x10MonitorDeviceKpi\x12#.monitoring.MonitorDeviceKpiRequest\x1a\x0e.context.Empty\"\x00\x12\x36\n\x0cGetStreamKpi\x12\x11.monitoring.KpiId\x1a\x0f.monitoring.Kpi\"\x00\x30\x01\x12\x35\n\rGetInstantKpi\x12\x11.monitoring.KpiId\x1a\x0f.monitoring.Kpi\"\x00\x62\x06proto3'
+  ,
+  dependencies=[context__pb2.DESCRIPTOR,])
+
+_KPISAMPLETYPE = _descriptor.EnumDescriptor(
+  name='KpiSampleType',
+  full_name='monitoring.KpiSampleType',
+  filename=None,
+  file=DESCRIPTOR,
+  create_key=_descriptor._internal_create_key,
+  values=[
+    _descriptor.EnumValueDescriptor(
+      name='UNKNOWN', index=0, number=0,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+    _descriptor.EnumValueDescriptor(
+      name='PACKETS_TRANSMITTED', index=1, number=101,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+    _descriptor.EnumValueDescriptor(
+      name='PACKETS_RECEIVED', index=2, number=102,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+    _descriptor.EnumValueDescriptor(
+      name='BYTES_TRANSMITTED', index=3, number=201,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+    _descriptor.EnumValueDescriptor(
+      name='BYTES_RECEIVED', index=4, number=202,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+  ],
+  containing_type=None,
+  serialized_options=None,
+  serialized_start=913,
+  serialized_end=1033,
+)
+_sym_db.RegisterEnumDescriptor(_KPISAMPLETYPE)
+
+KpiSampleType = enum_type_wrapper.EnumTypeWrapper(_KPISAMPLETYPE)
+UNKNOWN = 0
+PACKETS_TRANSMITTED = 101
+PACKETS_RECEIVED = 102
+BYTES_TRANSMITTED = 201
+BYTES_RECEIVED = 202
+
+
+
+_CREATEKPIREQUEST = _descriptor.Descriptor(
+  name='CreateKpiRequest',
+  full_name='monitoring.CreateKpiRequest',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='kpiDescription', full_name='monitoring.CreateKpiRequest.kpiDescription', index=0,
+      number=1, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=b"".decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='device_id', full_name='monitoring.CreateKpiRequest.device_id', index=1,
+      number=2, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='kpi_sample_type', full_name='monitoring.CreateKpiRequest.kpi_sample_type', index=2,
+      number=3, type=14, cpp_type=8, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=48,
+  serialized_end=180,
+)
+
+
+_MONITORKPIREQUEST = _descriptor.Descriptor(
+  name='MonitorKpiRequest',
+  full_name='monitoring.MonitorKpiRequest',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='kpi_id', full_name='monitoring.MonitorKpiRequest.kpi_id', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='connexion_time_s', full_name='monitoring.MonitorKpiRequest.connexion_time_s', index=1,
+      number=2, type=13, cpp_type=3, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='sample_rate_ms', full_name='monitoring.MonitorKpiRequest.sample_rate_ms', index=2,
+      number=3, type=13, cpp_type=3, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=182,
+  serialized_end=286,
+)
+
+
+_MONITORDEVICEKPIREQUEST = _descriptor.Descriptor(
+  name='MonitorDeviceKpiRequest',
+  full_name='monitoring.MonitorDeviceKpiRequest',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='kpi', full_name='monitoring.MonitorDeviceKpiRequest.kpi', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='connexion_time_s', full_name='monitoring.MonitorDeviceKpiRequest.connexion_time_s', index=1,
+      number=2, type=13, cpp_type=3, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='sample_rate_ms', full_name='monitoring.MonitorDeviceKpiRequest.sample_rate_ms', index=2,
+      number=3, type=13, cpp_type=3, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=288,
+  serialized_end=393,
+)
+
+
+_INCLUDEKPIREQUEST = _descriptor.Descriptor(
+  name='IncludeKpiRequest',
+  full_name='monitoring.IncludeKpiRequest',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='kpi_id', full_name='monitoring.IncludeKpiRequest.kpi_id', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='time_stamp', full_name='monitoring.IncludeKpiRequest.time_stamp', index=1,
+      number=2, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=b"".decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='kpi_value', full_name='monitoring.IncludeKpiRequest.kpi_value', index=2,
+      number=3, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=395,
+  serialized_end=510,
+)
+
+
+_KPIID = _descriptor.Descriptor(
+  name='KpiId',
+  full_name='monitoring.KpiId',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='kpi_id', full_name='monitoring.KpiId.kpi_id', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=512,
+  serialized_end=550,
+)
+
+
+_KPI = _descriptor.Descriptor(
+  name='Kpi',
+  full_name='monitoring.Kpi',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='kpi_id', full_name='monitoring.Kpi.kpi_id', index=0,
+      number=1, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='timestamp', full_name='monitoring.Kpi.timestamp', index=1,
+      number=2, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=b"".decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='kpiDescription', full_name='monitoring.Kpi.kpiDescription', index=2,
+      number=3, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=b"".decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='kpi_value', full_name='monitoring.Kpi.kpi_value', index=3,
+      number=4, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='kpi_sample_type', full_name='monitoring.Kpi.kpi_sample_type', index=4,
+      number=5, type=14, cpp_type=8, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='device_id', full_name='monitoring.Kpi.device_id', index=5,
+      number=6, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=553,
+  serialized_end=767,
+)
+
+
+_KPIVALUE = _descriptor.Descriptor(
+  name='KpiValue',
+  full_name='monitoring.KpiValue',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='intVal', full_name='monitoring.KpiValue.intVal', index=0,
+      number=1, type=13, cpp_type=3, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='floatVal', full_name='monitoring.KpiValue.floatVal', index=1,
+      number=2, type=2, cpp_type=6, label=1,
+      has_default_value=False, default_value=float(0),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='stringVal', full_name='monitoring.KpiValue.stringVal', index=2,
+      number=3, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=b"".decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='boolVal', full_name='monitoring.KpiValue.boolVal', index=3,
+      number=4, type=8, cpp_type=7, label=1,
+      has_default_value=False, default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+    _descriptor.OneofDescriptor(
+      name='value', full_name='monitoring.KpiValue.value',
+      index=0, containing_type=None,
+      create_key=_descriptor._internal_create_key,
+    fields=[]),
+  ],
+  serialized_start=769,
+  serialized_end=866,
+)
+
+
+_KPILIST = _descriptor.Descriptor(
+  name='KpiList',
+  full_name='monitoring.KpiList',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='kpiList', full_name='monitoring.KpiList.kpiList', index=0,
+      number=1, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=868,
+  serialized_end=911,
+)
+
+_CREATEKPIREQUEST.fields_by_name['device_id'].message_type = context__pb2._DEVICEID
+_CREATEKPIREQUEST.fields_by_name['kpi_sample_type'].enum_type = _KPISAMPLETYPE
+_MONITORKPIREQUEST.fields_by_name['kpi_id'].message_type = _KPIID
+_MONITORDEVICEKPIREQUEST.fields_by_name['kpi'].message_type = _KPI
+_INCLUDEKPIREQUEST.fields_by_name['kpi_id'].message_type = _KPIID
+_INCLUDEKPIREQUEST.fields_by_name['kpi_value'].message_type = _KPIVALUE
+_KPIID.fields_by_name['kpi_id'].message_type = context__pb2._UUID
+_KPI.fields_by_name['kpi_id'].message_type = _KPIID
+_KPI.fields_by_name['kpi_value'].message_type = _KPIVALUE
+_KPI.fields_by_name['kpi_sample_type'].enum_type = _KPISAMPLETYPE
+_KPI.fields_by_name['device_id'].message_type = context__pb2._DEVICEID
+_KPIVALUE.oneofs_by_name['value'].fields.append(
+  _KPIVALUE.fields_by_name['intVal'])
+_KPIVALUE.fields_by_name['intVal'].containing_oneof = _KPIVALUE.oneofs_by_name['value']
+_KPIVALUE.oneofs_by_name['value'].fields.append(
+  _KPIVALUE.fields_by_name['floatVal'])
+_KPIVALUE.fields_by_name['floatVal'].containing_oneof = _KPIVALUE.oneofs_by_name['value']
+_KPIVALUE.oneofs_by_name['value'].fields.append(
+  _KPIVALUE.fields_by_name['stringVal'])
+_KPIVALUE.fields_by_name['stringVal'].containing_oneof = _KPIVALUE.oneofs_by_name['value']
+_KPIVALUE.oneofs_by_name['value'].fields.append(
+  _KPIVALUE.fields_by_name['boolVal'])
+_KPIVALUE.fields_by_name['boolVal'].containing_oneof = _KPIVALUE.oneofs_by_name['value']
+_KPILIST.fields_by_name['kpiList'].message_type = _KPI
+DESCRIPTOR.message_types_by_name['CreateKpiRequest'] = _CREATEKPIREQUEST
+DESCRIPTOR.message_types_by_name['MonitorKpiRequest'] = _MONITORKPIREQUEST
+DESCRIPTOR.message_types_by_name['MonitorDeviceKpiRequest'] = _MONITORDEVICEKPIREQUEST
+DESCRIPTOR.message_types_by_name['IncludeKpiRequest'] = _INCLUDEKPIREQUEST
+DESCRIPTOR.message_types_by_name['KpiId'] = _KPIID
+DESCRIPTOR.message_types_by_name['Kpi'] = _KPI
+DESCRIPTOR.message_types_by_name['KpiValue'] = _KPIVALUE
+DESCRIPTOR.message_types_by_name['KpiList'] = _KPILIST
+DESCRIPTOR.enum_types_by_name['KpiSampleType'] = _KPISAMPLETYPE
+_sym_db.RegisterFileDescriptor(DESCRIPTOR)
+
+CreateKpiRequest = _reflection.GeneratedProtocolMessageType('CreateKpiRequest', (_message.Message,), {
+  'DESCRIPTOR' : _CREATEKPIREQUEST,
+  '__module__' : 'monitoring_pb2'
+  # @@protoc_insertion_point(class_scope:monitoring.CreateKpiRequest)
+  })
+_sym_db.RegisterMessage(CreateKpiRequest)
+
+MonitorKpiRequest = _reflection.GeneratedProtocolMessageType('MonitorKpiRequest', (_message.Message,), {
+  'DESCRIPTOR' : _MONITORKPIREQUEST,
+  '__module__' : 'monitoring_pb2'
+  # @@protoc_insertion_point(class_scope:monitoring.MonitorKpiRequest)
+  })
+_sym_db.RegisterMessage(MonitorKpiRequest)
+
+MonitorDeviceKpiRequest = _reflection.GeneratedProtocolMessageType('MonitorDeviceKpiRequest', (_message.Message,), {
+  'DESCRIPTOR' : _MONITORDEVICEKPIREQUEST,
+  '__module__' : 'monitoring_pb2'
+  # @@protoc_insertion_point(class_scope:monitoring.MonitorDeviceKpiRequest)
+  })
+_sym_db.RegisterMessage(MonitorDeviceKpiRequest)
+
+IncludeKpiRequest = _reflection.GeneratedProtocolMessageType('IncludeKpiRequest', (_message.Message,), {
+  'DESCRIPTOR' : _INCLUDEKPIREQUEST,
+  '__module__' : 'monitoring_pb2'
+  # @@protoc_insertion_point(class_scope:monitoring.IncludeKpiRequest)
+  })
+_sym_db.RegisterMessage(IncludeKpiRequest)
+
+KpiId = _reflection.GeneratedProtocolMessageType('KpiId', (_message.Message,), {
+  'DESCRIPTOR' : _KPIID,
+  '__module__' : 'monitoring_pb2'
+  # @@protoc_insertion_point(class_scope:monitoring.KpiId)
+  })
+_sym_db.RegisterMessage(KpiId)
+
+Kpi = _reflection.GeneratedProtocolMessageType('Kpi', (_message.Message,), {
+  'DESCRIPTOR' : _KPI,
+  '__module__' : 'monitoring_pb2'
+  # @@protoc_insertion_point(class_scope:monitoring.Kpi)
+  })
+_sym_db.RegisterMessage(Kpi)
+
+KpiValue = _reflection.GeneratedProtocolMessageType('KpiValue', (_message.Message,), {
+  'DESCRIPTOR' : _KPIVALUE,
+  '__module__' : 'monitoring_pb2'
+  # @@protoc_insertion_point(class_scope:monitoring.KpiValue)
+  })
+_sym_db.RegisterMessage(KpiValue)
+
+KpiList = _reflection.GeneratedProtocolMessageType('KpiList', (_message.Message,), {
+  'DESCRIPTOR' : _KPILIST,
+  '__module__' : 'monitoring_pb2'
+  # @@protoc_insertion_point(class_scope:monitoring.KpiList)
+  })
+_sym_db.RegisterMessage(KpiList)
+
+
+
+_MONITORINGSERVICE = _descriptor.ServiceDescriptor(
+  name='MonitoringService',
+  full_name='monitoring.MonitoringService',
+  file=DESCRIPTOR,
+  index=0,
+  serialized_options=None,
+  create_key=_descriptor._internal_create_key,
+  serialized_start=1036,
+  serialized_end=1431,
+  methods=[
+  _descriptor.MethodDescriptor(
+    name='CreateKpi',
+    full_name='monitoring.MonitoringService.CreateKpi',
+    index=0,
+    containing_service=None,
+    input_type=_CREATEKPIREQUEST,
+    output_type=_KPIID,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='IncludeKpi',
+    full_name='monitoring.MonitoringService.IncludeKpi',
+    index=1,
+    containing_service=None,
+    input_type=_INCLUDEKPIREQUEST,
+    output_type=context__pb2._EMPTY,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='MonitorKpi',
+    full_name='monitoring.MonitoringService.MonitorKpi',
+    index=2,
+    containing_service=None,
+    input_type=_MONITORKPIREQUEST,
+    output_type=context__pb2._EMPTY,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='MonitorDeviceKpi',
+    full_name='monitoring.MonitoringService.MonitorDeviceKpi',
+    index=3,
+    containing_service=None,
+    input_type=_MONITORDEVICEKPIREQUEST,
+    output_type=context__pb2._EMPTY,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='GetStreamKpi',
+    full_name='monitoring.MonitoringService.GetStreamKpi',
+    index=4,
+    containing_service=None,
+    input_type=_KPIID,
+    output_type=_KPI,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='GetInstantKpi',
+    full_name='monitoring.MonitoringService.GetInstantKpi',
+    index=5,
+    containing_service=None,
+    input_type=_KPIID,
+    output_type=_KPI,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+])
+_sym_db.RegisterServiceDescriptor(_MONITORINGSERVICE)
+
+DESCRIPTOR.services_by_name['MonitoringService'] = _MONITORINGSERVICE
+
+# @@protoc_insertion_point(module_scope)
diff --git a/src/webui/proto/service_pb2.py b/src/webui/proto/service_pb2.py
new file mode 100644
index 000000000..7a006915b
--- /dev/null
+++ b/src/webui/proto/service_pb2.py
@@ -0,0 +1,88 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: service.proto
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from google.protobuf import reflection as _reflection
+from google.protobuf import symbol_database as _symbol_database
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+from . import context_pb2 as context__pb2
+
+
+DESCRIPTOR = _descriptor.FileDescriptor(
+  name='service.proto',
+  package='service',
+  syntax='proto3',
+  serialized_options=None,
+  create_key=_descriptor._internal_create_key,
+  serialized_pb=b'\n\rservice.proto\x12\x07service\x1a\rcontext.proto2\xfd\x01\n\x0eServiceService\x12\x37\n\rCreateService\x12\x10.context.Service\x1a\x12.context.ServiceId\"\x00\x12\x37\n\rUpdateService\x12\x10.context.Service\x1a\x12.context.ServiceId\"\x00\x12\x35\n\rDeleteService\x12\x12.context.ServiceId\x1a\x0e.context.Empty\"\x00\x12\x42\n\x11GetConnectionList\x12\x12.context.ServiceId\x1a\x17.context.ConnectionList\"\x00\x62\x06proto3'
+  ,
+  dependencies=[context__pb2.DESCRIPTOR,])
+
+
+
+_sym_db.RegisterFileDescriptor(DESCRIPTOR)
+
+
+
+_SERVICESERVICE = _descriptor.ServiceDescriptor(
+  name='ServiceService',
+  full_name='service.ServiceService',
+  file=DESCRIPTOR,
+  index=0,
+  serialized_options=None,
+  create_key=_descriptor._internal_create_key,
+  serialized_start=42,
+  serialized_end=295,
+  methods=[
+  _descriptor.MethodDescriptor(
+    name='CreateService',
+    full_name='service.ServiceService.CreateService',
+    index=0,
+    containing_service=None,
+    input_type=context__pb2._SERVICE,
+    output_type=context__pb2._SERVICEID,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='UpdateService',
+    full_name='service.ServiceService.UpdateService',
+    index=1,
+    containing_service=None,
+    input_type=context__pb2._SERVICE,
+    output_type=context__pb2._SERVICEID,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='DeleteService',
+    full_name='service.ServiceService.DeleteService',
+    index=2,
+    containing_service=None,
+    input_type=context__pb2._SERVICEID,
+    output_type=context__pb2._EMPTY,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+  _descriptor.MethodDescriptor(
+    name='GetConnectionList',
+    full_name='service.ServiceService.GetConnectionList',
+    index=3,
+    containing_service=None,
+    input_type=context__pb2._SERVICEID,
+    output_type=context__pb2._CONNECTIONLIST,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+])
+_sym_db.RegisterServiceDescriptor(_SERVICESERVICE)
+
+DESCRIPTOR.services_by_name['ServiceService'] = _SERVICESERVICE
+
+# @@protoc_insertion_point(module_scope)
diff --git a/src/webui/requirements.in b/src/webui/requirements.in
new file mode 100644
index 000000000..8d30ba299
--- /dev/null
+++ b/src/webui/requirements.in
@@ -0,0 +1,11 @@
+flask
+flask-wtf
+flask-healthz
+flask-unittest
+grpcio
+grpcio-health-checking
+prometheus-client
+pytest
+pytest-benchmark
+lorem-text
+coverage
diff --git a/src/webui/service/__init__.py b/src/webui/service/__init__.py
new file mode 100644
index 000000000..28197a9f5
--- /dev/null
+++ b/src/webui/service/__init__.py
@@ -0,0 +1,58 @@
+import os
+from flask import Flask, session
+from flask_healthz import healthz, HealthError
+
+from webui.proto.context_pb2 import Empty
+from device.client.DeviceClient import DeviceClient
+from context.client.ContextClient import ContextClient
+from webui.Config import (CONTEXT_SERVICE_ADDRESS, CONTEXT_SERVICE_PORT,
+                DEVICE_SERVICE_ADDRESS, DEVICE_SERVICE_PORT)
+
+
+def get_working_context() -> str:
+    if 'context_uuid' in session:
+        return session['context_uuid']
+    else:
+        return 'Not selected'
+
+
+def liveness():
+    pass
+
+
+def readiness():
+    try:  # this component is ready when it is able to connect with the other components it depends on
+        context_client: ContextClient = ContextClient(CONTEXT_SERVICE_ADDRESS, CONTEXT_SERVICE_PORT)
+        context_client.connect()
+        context_client.close()
+        device_client: DeviceClient = DeviceClient(DEVICE_SERVICE_ADDRESS, DEVICE_SERVICE_PORT)
+        device_client.connect()
+        device_client.close()
+    except Exception as e:
+        raise HealthError('Can\'t connect with the service: ' + e.details())
+
+
+def create_app(use_config=None):
+    app = Flask(__name__)
+    if use_config:
+        app.config.from_mapping(**use_config)
+    
+    app.config.update(HEALTHZ={
+        'live': liveness,
+        'ready': readiness
+    })
+    
+    app.register_blueprint(healthz, url_prefix='/healthz')
+
+    from webui.service.main.routes import main
+    app.register_blueprint(main)
+
+    from webui.service.service.routes import service
+    app.register_blueprint(service)
+
+    from webui.service.device.routes import device
+    app.register_blueprint(device)
+
+    app.jinja_env.globals.update(get_working_context=get_working_context)
+
+    return app
diff --git a/src/webui/service/__main__.py b/src/webui/service/__main__.py
new file mode 100644
index 000000000..2107e139f
--- /dev/null
+++ b/src/webui/service/__main__.py
@@ -0,0 +1,27 @@
+import os, sys, logging
+from prometheus_client import start_http_server
+from webui.service import create_app
+from webui.Config import WEBUI_SERVICE_PORT, LOG_LEVEL, METRICS_PORT, HOST, SECRET_KEY, DEBUG
+
+def main():
+    service_port = os.environ.get('WEBUISERVICE_SERVICE_PORT', WEBUI_SERVICE_PORT)
+    log_level    = os.environ.get('LOG_LEVEL',                 LOG_LEVEL         )
+    metrics_port = os.environ.get('METRICS_PORT',              METRICS_PORT      )
+    host         = os.environ.get('HOST',                      HOST              )
+    debug        = os.environ.get('DEBUG',                     DEBUG             )
+
+    logging.basicConfig(level=log_level)
+    logger = logging.getLogger(__name__)
+
+    logger.info('Starting...')
+
+    start_http_server(metrics_port)
+
+    app = create_app(use_config={'SECRET_KEY': SECRET_KEY})
+    app.run(host=host, port=service_port, debug=debug)
+
+    logger.info('Bye')
+    return 0
+
+if __name__ == '__main__':
+    sys.exit(main())
diff --git a/src/webui/service/context/__init__.py b/src/webui/service/context/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/webui/service/context/routes.py b/src/webui/service/context/routes.py
new file mode 100644
index 000000000..052a91db0
--- /dev/null
+++ b/src/webui/service/context/routes.py
@@ -0,0 +1,9 @@
+from flask import render_template, Blueprint, flash
+
+context = Blueprint('context', __name__)
+
+@context.route('/')
+def home():
+    flash('This is an info message', 'info')
+    flash('This is a danger message', 'danger')
+    return render_template('main/home.html')
diff --git a/src/webui/service/device/__init__.py b/src/webui/service/device/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/webui/service/device/forms.py b/src/webui/service/device/forms.py
new file mode 100644
index 000000000..8bfad0f59
--- /dev/null
+++ b/src/webui/service/device/forms.py
@@ -0,0 +1,41 @@
+# external imports
+from flask_wtf import FlaskForm
+from wtforms import StringField, SelectField, TextAreaField, SubmitField
+from wtforms.validators import DataRequired, Length, NumberRange, Regexp, ValidationError
+
+from webui.utils.form_validators import key_value_validator
+from webui.proto.context_pb2 import (DeviceDriverEnum, DeviceOperationalStatusEnum)
+
+class AddDeviceForm(FlaskForm):
+    device_id = StringField('ID', 
+                           validators=[DataRequired(), Length(min=5)])
+    device_type = StringField('Type', 
+                           validators=[DataRequired(), Length(min=5)])
+    device_config = TextAreaField('Configurations', validators=[key_value_validator()])
+    operational_status = SelectField('Operational Status',
+                        #    choices=[(-1, 'Select...'), (0, 'Undefined'), (1, 'Disabled'), (2, 'Enabled')],
+                           coerce=int,
+                           validators=[NumberRange(min=0)])
+    device_drivers = TextAreaField('Drivers', validators=[DataRequired(), Regexp(r'^\d+(,\d+)*$')])
+    submit = SubmitField('Add')
+
+    def validate_operational_status(form, field):
+        if field.data not in DeviceOperationalStatusEnum.DESCRIPTOR.values_by_number:
+            raise ValidationError('The operational status value selected is incorrect!')
+    
+    def validate_device_drivers(form, field):
+        if ',' not in field.data:
+            data = str(field.data) + ','
+        else:
+            data = field.data
+        for value in data.split(','):
+            value = value.strip()
+            if len(value) == 0:
+                continue
+            try:
+                value_int = int(value)
+            except:
+                raise ValidationError(f'The value "{value}" is not a valid driver identified.')
+            if value_int not in DeviceDriverEnum.DESCRIPTOR.values_by_number:
+                values = ', '.join([str(x) for x in DeviceDriverEnum.DESCRIPTOR.values_by_number])
+                raise ValidationError(f'The device driver {value_int} is not correct. Allowed values are: {values}.')
diff --git a/src/webui/service/device/routes.py b/src/webui/service/device/routes.py
new file mode 100644
index 000000000..b5a9399a6
--- /dev/null
+++ b/src/webui/service/device/routes.py
@@ -0,0 +1,121 @@
+from flask import render_template, Blueprint, flash, session, redirect
+from device.client.DeviceClient import DeviceClient
+from context.client.ContextClient import ContextClient
+from webui.Config import (CONTEXT_SERVICE_ADDRESS, CONTEXT_SERVICE_PORT,
+                DEVICE_SERVICE_ADDRESS, DEVICE_SERVICE_PORT)
+from webui.proto.context_pb2 import (ContextId, DeviceList, DeviceId,
+    Device, DeviceDriverEnum, DeviceOperationalStatusEnum,
+    ConfigActionEnum, ConfigRule, TopologyIdList, TopologyList)
+from webui.service.device.forms import AddDeviceForm
+
+device = Blueprint('device', __name__, url_prefix='/device')
+context_client: ContextClient = ContextClient(CONTEXT_SERVICE_ADDRESS, CONTEXT_SERVICE_PORT)
+device_client: DeviceClient = DeviceClient(DEVICE_SERVICE_ADDRESS, DEVICE_SERVICE_PORT)
+
+@device.get('/')
+def home():
+    request: ContextId = ContextId()
+    request.context_uuid.uuid = session['context_uuid']
+    context_client.connect()
+    response: DeviceList = context_client.ListDevices(request)
+    context_client.close()
+    return render_template('device/home.html', devices=response.devices,
+                                               dde=DeviceDriverEnum,
+                                               dose=DeviceOperationalStatusEnum)
+
+@device.route('add', methods=['GET', 'POST'])
+def add():
+    form = AddDeviceForm()
+
+    request: ContextId = ContextId()
+    request.context_uuid.uuid = session['context_uuid']
+    context_client.connect()
+    response: TopologyIdList = context_client.ListTopologyIds(request)
+    context_client.close()
+
+    # listing enum values
+    form.operational_status.choices = [(-1, 'Select...')]
+    for key, value in DeviceOperationalStatusEnum.DESCRIPTOR.values_by_name.items():
+        form.operational_status.choices.append((DeviceOperationalStatusEnum.Value(key), key.replace('DEVICEOPERATIONALSTATUS_', '')))
+    
+    # device driver ids
+    device_driver_ids = []
+    for key in DeviceDriverEnum.DESCRIPTOR.values_by_name:
+        device_driver_ids.append(f"{DeviceDriverEnum.Value(key)}={key.replace('DEVICEDRIVER_', '')}")
+    device_driver_ids = ', '.join(device_driver_ids)
+
+    if form.validate_on_submit():
+        device: Device = Device()
+        device.device_id.device_uuid.uuid = form.device_id.data
+        device.device_type = form.device_type.data
+        if '\n' not in form.device_config.data:
+            data = form.device_config.data.strip() + '\n'
+        else:
+            data = form.device_config.data.strip()
+        
+        for config in data.split('\n'):
+            if len(config.strip()) > 0:
+                parts = config.strip().split('=')
+                config_rule: ConfigRule = ConfigRule()
+                config_rule.action = ConfigActionEnum.CONFIGACTION_SET
+                config_rule.resource_key = parts[0].strip()
+                config_rule.resource_value = parts[1].strip()
+                device.device_config.config_rules.append(config_rule)
+
+        device.device_operational_status = form.operational_status.data
+
+        if ',' not in form.device_drivers.data:
+            data = form.device_drivers.data.strip() + ','
+        else:
+            data = form.device_drivers.data.strip()
+        
+        for driver in data.split(','):
+            driver = driver.strip()
+            if len(driver) == 0:
+                continue
+            device.device_drivers.append(int(driver))
+        try:
+            device_client.connect()
+            response: DeviceId = device_client.AddDevice(device)
+            device_client.close()
+
+            flash(f'New device was created with ID "{response.device_uuid.uuid}".', 'success')
+            return redirect('/device/')
+        except Exception as e:
+            flash(f'Problem adding the device. {e.details()}', 'danger')
+        
+    return render_template('device/add.html', form=form,
+                    submit_text='Add New Device',
+                    device_driver_ids=device_driver_ids)
+
+@device.route('detail/<device_uuid>', methods=['GET', 'POST'])
+def detail(device_uuid: str):
+    request: DeviceId = DeviceId()
+    request.device_uuid.uuid = device_uuid
+    context_client.connect()
+    response: Device = context_client.GetDevice(request)
+    context_client.close()
+    return render_template('device/detail.html', device=response)
+
+@device.get('<device_uuid>/delete')
+def delete(device_uuid):
+    try:
+
+        # first, check if device exists!
+        # request: DeviceId = DeviceId()
+        # request.device_uuid.uuid = device_uuid
+        # response: Device = client.GetDevice(request)
+        # TODO: finalize implementation
+
+        request: DeviceId = DeviceId()
+        request.device_uuid.uuid = device_uuid
+        device_client.connect()
+        response = device_client.DeleteDevice(request)
+
+        device_client.close()
+
+        flash('Device deleted successfully!', 'success')
+    except Exception as e:
+        flash(f'Problem deleting the device. {e.details()}', 'danger')
+
+    return redirect('/device/')
diff --git a/src/webui/service/main/__init__.py b/src/webui/service/main/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/webui/service/main/forms.py b/src/webui/service/main/forms.py
new file mode 100644
index 000000000..aacdbf252
--- /dev/null
+++ b/src/webui/service/main/forms.py
@@ -0,0 +1,11 @@
+# external imports
+from flask_wtf import FlaskForm
+from wtforms import SelectField, SubmitField
+from wtforms.validators import DataRequired, Length
+
+
+class ContextForm(FlaskForm):
+    context = SelectField('Context',
+                           choices=[],
+                           validators=[DataRequired(), Length(min=1)])
+    submit = SubmitField('Select')
diff --git a/src/webui/service/main/routes.py b/src/webui/service/main/routes.py
new file mode 100644
index 000000000..08ccdea4a
--- /dev/null
+++ b/src/webui/service/main/routes.py
@@ -0,0 +1,37 @@
+import logging
+import sys
+from flask import render_template, Blueprint, flash, session
+from webui.Config import CONTEXT_SERVICE_ADDRESS, CONTEXT_SERVICE_PORT
+from context.client.ContextClient import ContextClient
+from webui.proto.context_pb2 import Empty
+from webui.service.main.forms import ContextForm
+
+main = Blueprint('main', __name__)
+
+context_client: ContextClient = ContextClient(CONTEXT_SERVICE_ADDRESS, CONTEXT_SERVICE_PORT)
+
+logger = logging.getLogger(__name__)
+
+@main.route('/', methods=['GET', 'POST'])
+def home():
+    # flash('This is an info message', 'info')
+    # flash('This is a danger message', 'danger')
+    context_client.connect()
+    response = context_client.ListContextIds(Empty())
+    context_client.close()
+    context_form: ContextForm = ContextForm()
+    context_form.context.choices.append(('', 'Select...'))
+    for context in response.context_ids:
+        context_form.context.choices.append((context.context_uuid.uuid, context.context_uuid))
+    if context_form.validate_on_submit():
+        session['context_uuid'] = context_form.context.data
+        flash(f'The context was successfully set to `{context_form.context.data}`.', 'success')
+    if 'context_uuid' in session:
+        context_form.context.data = session['context_uuid']
+
+    return render_template('main/home.html', context_form=context_form)
+
+
+@main.get('/about')
+def about():
+    return render_template('main/about.html')
diff --git a/src/webui/service/service/__init__.py b/src/webui/service/service/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/webui/service/service/routes.py b/src/webui/service/service/routes.py
new file mode 100644
index 000000000..c88d89789
--- /dev/null
+++ b/src/webui/service/service/routes.py
@@ -0,0 +1,39 @@
+from flask import render_template, Blueprint, flash, session
+from webui.Config import CONTEXT_SERVICE_ADDRESS, CONTEXT_SERVICE_PORT
+from context.client.ContextClient import ContextClient
+from webui.proto.context_pb2 import ContextId, ServiceList, ServiceTypeEnum, ServiceStatusEnum, ConfigActionEnum
+
+
+service = Blueprint('service', __name__, url_prefix='/service')
+
+context_client: ContextClient = ContextClient(CONTEXT_SERVICE_ADDRESS, CONTEXT_SERVICE_PORT)
+
+@service.get('/')
+def home():
+    # flash('This is an info message', 'info')
+    # flash('This is a danger message', 'danger')
+    
+    request: ContextId = ContextId()
+    request.context_uuid.uuid = session['context_uuid']
+    context_client.connect()
+    service_list: ServiceList = context_client.ListServices(request)
+    # print(service_list)
+
+    context_client.close()
+    return render_template('service/home.html', services=service_list.services, 
+                                                ste=ServiceTypeEnum,
+                                                sse=ServiceStatusEnum)
+
+
+@service.route('add', methods=['GET', 'POST'])
+def add():
+    flash('Add service route called', 'danger')
+    raise NotImplementedError()
+    return render_template('service/home.html')
+
+
+@service.get('detail/<service_uuid>')
+def detail(service_uuid: str):
+    flash('Detail service route called', 'danger')
+    raise NotImplementedError()
+    return render_template('service/home.html')
diff --git a/src/webui/service/static/partners.png b/src/webui/service/static/partners.png
new file mode 100644
index 0000000000000000000000000000000000000000..f88680212f68cdb4c17ad0de55b9d22ef9276a23
GIT binary patch
literal 76488
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
AtpET3

literal 0
HcmV?d00001

diff --git a/src/webui/service/static/site.js b/src/webui/service/static/site.js
new file mode 100644
index 000000000..e06cea8b0
--- /dev/null
+++ b/src/webui/service/static/site.js
@@ -0,0 +1,4 @@
+var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
+var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
+  return new bootstrap.Tooltip(tooltipTriggerEl)
+})
diff --git a/src/webui/service/templates/base.html b/src/webui/service/templates/base.html
new file mode 100644
index 000000000..6ada3c850
--- /dev/null
+++ b/src/webui/service/templates/base.html
@@ -0,0 +1,119 @@
+<!doctype html>
+<html lang="en">
+  <head>
+    <!-- Required meta tags -->
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+
+    <link rel="shortcut icon" href="https://teraflow-h2020.eu/sites/teraflow/files/public/favicon.png" type="image/png" />
+
+    <!-- Bootstrap CSS -->
+    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-uWxY/CJNBR+1zjPWmfnSnVxwRheevXITnMqoEIeG1LJrdI0GlVs/9cVSyPYXdcSF" crossorigin="anonymous">
+    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css">
+
+    <title>TeraFlow OFC 2022 Demo</title>
+  </head>
+  <body>
+      <div id="teraflow-branding" style="width: 260px; margin: 7px;">
+        <a href="/" title="Home" rel="home" id="main-logo" class="site-logo site-logo-pages">
+            <svg id="Capa_1" data-name="Capa 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 436.3 132.1"><defs><style>.cls-1{fill:#36a9e1;}.cls-2{fill:#1d71b8;}.cls-3{fill:none;stroke-width:2.52px;}.cls-10,.cls-3,.cls-4,.cls-5,.cls-7,.cls-8,.cls-9{stroke:#0f77b6;}.cls-3,.cls-4,.cls-8{stroke-miterlimit:10;}.cls-10,.cls-4,.cls-5,.cls-7,.cls-8,.cls-9{fill:#fff;}.cls-4{stroke-width:0.73px;}.cls-5,.cls-7{stroke-miterlimit:10;}.cls-5{stroke-width:0.75px;}.cls-6{fill:#0f77b6;}.cls-7{stroke-width:0.72px;}.cls-8{stroke-width:0.7px;}.cls-9{stroke-miterlimit:10;stroke-width:0.69px;}.cls-10{stroke-miterlimit:10;stroke-width:0.7px;}</style></defs><path class="cls-1" d="M96,57V51.3h44.1V57H121v52.3h-5.9V57Z"></path><path class="cls-1" d="M168.9,95.1l4.7,2.4a26,26,0,0,1-5.3,7.3,22.27,22.27,0,0,1-6.7,4.2,22.64,22.64,0,0,1-8.5,1.4c-7,0-12.5-2.3-16.4-6.9a23.53,23.53,0,0,1-5.9-15.6,23,23,0,0,1,5-14.5c4.2-5.4,9.9-8.1,17-8.1,7.3,0,13.2,2.8,17.5,8.3,3.1,3.9,4.7,8.8,4.7,14.7H136.4a17.48,17.48,0,0,0,4.8,12.3,15.26,15.26,0,0,0,11.4,4.8,20,20,0,0,0,6.4-1.1,19.3,19.3,0,0,0,5.3-3A33.07,33.07,0,0,0,168.9,95.1Zm0-11.6a18.66,18.66,0,0,0-3.2-7.1,15.25,15.25,0,0,0-5.6-4.3,16.87,16.87,0,0,0-7.3-1.6,16.06,16.06,0,0,0-10.9,4.1,18.15,18.15,0,0,0-5,8.9Z"></path><path class="cls-1" d="M182,66.4h5.6v6.3a20,20,0,0,1,5.3-5.5,10.67,10.67,0,0,1,5.8-1.8,9.87,9.87,0,0,1,4.9,1.5l-2.9,4.7a7.52,7.52,0,0,0-2.9-.7,8.09,8.09,0,0,0-5.3,2.3,14.64,14.64,0,0,0-3.9,7c-.7,2.4-1,7.4-1,14.8v14.5H182Z"></path><path class="cls-1" d="M246.2,66.4v42.9h-5.4V102a23.11,23.11,0,0,1-7.8,6.3,21.23,21.23,0,0,1-9.4,2.1,21,21,0,0,1-15.6-6.6,23.07,23.07,0,0,1,.1-32,21.23,21.23,0,0,1,15.7-6.6,20,20,0,0,1,17.1,8.9V66.2h5.3Zm-22.1,4.2a16.67,16.67,0,0,0-8.5,2.3,15.93,15.93,0,0,0-6.2,6.4,17.68,17.68,0,0,0-2.3,8.7,18.26,18.26,0,0,0,2.3,8.7,15.93,15.93,0,0,0,6.2,6.4,16.58,16.58,0,0,0,8.4,2.3,17.59,17.59,0,0,0,8.6-2.3,15.42,15.42,0,0,0,6.2-6.2,17.17,17.17,0,0,0,2.2-8.8,16.73,16.73,0,0,0-4.9-12.4A15.8,15.8,0,0,0,224.1,70.6Z"></path><path class="cls-2" d="M259.5,51.3h29.1V57H265.3V75.2h23.3v5.7H265.3v28.5h-5.8V51.3Z"></path><path class="cls-2" d="M296.9,49.9h5.5v59.5h-5.5Z"></path><path class="cls-2" d="M330.5,65.3a21.1,21.1,0,0,1,16.4,7.2A22.55,22.55,0,0,1,352.8,88a22.24,22.24,0,0,1-6.3,15.7c-4.2,4.5-9.5,6.7-16.1,6.7s-12-2.2-16.1-6.7A22.24,22.24,0,0,1,308,88a22.73,22.73,0,0,1,5.9-15.5A21.81,21.81,0,0,1,330.5,65.3Zm0,5.4a15.83,15.83,0,0,0-11.8,5.1,17,17,0,0,0-4.9,12.3,17.68,17.68,0,0,0,2.3,8.7,15.19,15.19,0,0,0,6.1,6.2,16.48,16.48,0,0,0,8.4,2.2A16,16,0,0,0,339,103a15.82,15.82,0,0,0,6.1-6.2,17.68,17.68,0,0,0,2.3-8.7,17.07,17.07,0,0,0-5-12.3A16.2,16.2,0,0,0,330.5,70.7Z"></path><path class="cls-2" d="M351.2,66.4h5.7L370,97.6l13.7-31.1h1l13.8,31.1,13.4-31.1h5.7L399,109.3h-1L384.3,78.6l-13.7,30.7h-1Z"></path><polyline class="cls-3" points="51 105 51 41.2 27 41.2"></polyline><polyline class="cls-3" points="38.1 33.8 56.4 33.8 56.4 93"></polyline><polyline class="cls-3" points="79.9 33.8 61.5 33.8 61.5 79.2"></polyline><polyline class="cls-3" points="90.7 41.2 66.7 41.2 66.7 105"></polyline><line class="cls-3" x1="83.1" y1="62.6" x2="66.7" y2="62.6"></line><circle class="cls-4" cx="27" cy="41.2" r="5.3"></circle><path class="cls-1" d="M23.3,41.2a3.8,3.8,0,1,0,3.8-3.8A3.8,3.8,0,0,0,23.3,41.2Z"></path><circle class="cls-5" cx="51" cy="105" r="5.4"></circle><path class="cls-1" d="M47.3,105a3.8,3.8,0,1,0,3.8-3.8A3.8,3.8,0,0,0,47.3,105Z"></path><circle class="cls-6" cx="56.36" cy="93.02" r="3.4"></circle><circle class="cls-6" cx="61.5" cy="79.2" r="2.8"></circle><circle class="cls-7" cx="66.7" cy="105.01" r="5.3"></circle><path class="cls-1" d="M63,105a3.8,3.8,0,1,0,3.8-3.8A3.8,3.8,0,0,0,63,105Z"></path><circle class="cls-8" cx="90.7" cy="41.2" r="5.1"></circle><path class="cls-1" d="M87,41.2a3.8,3.8,0,1,0,3.8-3.8A3.8,3.8,0,0,0,87,41.2Z"></path><circle class="cls-8" cx="84.7" cy="62.6" r="5.1"></circle><path class="cls-1" d="M81,62.6a3.8,3.8,0,1,0,3.8-3.8A3.8,3.8,0,0,0,81,62.6Z"></path><line class="cls-3" x1="34.8" y1="62.6" x2="51.1" y2="62.6"></line><circle class="cls-8" cx="33.1" cy="62.6" r="5.1"></circle><path class="cls-1" d="M36.9,62.6a3.8,3.8,0,1,1-3.8-3.8A3.8,3.8,0,0,1,36.9,62.6Z"></path><line class="cls-3" x1="23.7" y1="26.7" x2="94.1" y2="26.7"></line><circle class="cls-9" cx="94.09" cy="26.67" r="5"></circle><path class="cls-1" d="M90.3,26.7a3.8,3.8,0,1,0,3.8-3.8A3.8,3.8,0,0,0,90.3,26.7Z"></path><circle class="cls-6" cx="78" cy="33.8" r="3.8"></circle><circle class="cls-6" cx="40" cy="33.8" r="3.8"></circle><circle class="cls-10" cx="23.71" cy="26.71" r="5.1"></circle><path class="cls-1" d="M20,26.7a3.8,3.8,0,1,0,3.8-3.8A3.8,3.8,0,0,0,20,26.7Z"></path></svg>
+          </a>
+      </div>
+
+    <nav class="navbar navbar-expand-lg navbar-dark bg-primary" style="margin-bottom: 10px;">
+        <div class="container-fluid">
+          <a class="navbar-brand" href="#">
+            <img src="https://teraflow-h2020.eu/sites/teraflow/files/public/favicon.png" alt="" width="30" height="24" class="d-inline-block align-text-top"/>
+            TeraFlow
+          </a>
+          <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarColor02" aria-controls="navbarColor02" aria-expanded="false" aria-label="Toggle navigation">
+            <span class="navbar-toggler-icon"></span>
+          </button>
+          <div class="collapse navbar-collapse" id="navbarColor02">
+            <ul class="navbar-nav me-auto mb-2 mb-lg-0">
+              <li class="nav-item">
+                {% if request.path == '/' %}
+                <a class="nav-link active" aria-current="page" href="{{ url_for('main.home') }}">Home</a>
+                {% else %}
+                <a class="nav-link" href="{{ url_for('main.home') }}">Home</a>
+                {% endif %}
+              </li>
+              <li class="nav-item">
+                {% if '/service/' in request.path %}
+                <a class="nav-link active" aria-current="page" href="{{ url_for('service.home') }}">Service</a>
+                {% else %}
+                <a class="nav-link" href="{{ url_for('service.home') }}">Service</a>
+                {% endif %}
+                <!-- <a class="nav-link" href="{{ url_for('service.home') }}">Service</a> -->
+              </li>
+              <li class="nav-item">
+                {% if '/device/' in request.path %}
+                <a class="nav-link active" aria-current="page" href="{{ url_for('device.home') }}">Device</a>
+                {% else %}
+                <a class="nav-link" href="{{ url_for('device.home') }}">Device</a>
+                {% endif %}
+                <!-- <a class="nav-link" href="{{ url_for('service.home') }}">Service</a> -->
+              </li>
+              <!-- <li class="nav-item">
+                <a class="nav-link" href="#">Compute</a>
+              </li>
+              <li class="nav-item">
+                <a class="nav-link" href="#">Context</a>
+              </li>
+              
+              <li class="nav-item">
+                <a class="nav-link" href="#">Monitoring</a>
+              </li> -->
+              <li class="nav-item">
+                <a class="nav-link" href="{{ url_for('main.about') }}">About</a>
+              </li>
+            </ul>
+            <span class="navbar-text" style="color: #fff;">
+              Current context: <b>{{ get_working_context() }}</b>
+            </span>
+          </div>
+        </div>
+      </nav>
+
+      <main class="container">
+        <div class="row">
+          <div class="col-md-12">
+            {% with messages = get_flashed_messages(with_categories=true) %}
+              {% if messages %}
+                {% for category, message in messages %}
+                  <div class="alert alert-{{ category }} alert-dismissible fade show" role="alert">
+                    {{ message }}
+                    <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
+                  </div>
+      
+                {% endfor %}
+              {% endif %}
+            {% endwith %}
+          </div>
+        </div>
+        <div class="bg-light p-5 rounded">
+          {% block content %}{% endblock %}
+        </div>
+      </main>
+
+      <footer class="footer" style="background-color: darkgrey;">
+        <div class="row">
+          <div class="col-md-12">
+            <p class="text-muted text-center" style="color: white;">&copy; 2021-2023</p>
+          </div>
+        </div>
+      </footer>
+
+    <!-- Optional JavaScript; choose one of the two! -->
+
+    <!-- Option 1: Bootstrap Bundle with Popper -->
+    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-kQtW33rZJAHjgefvhyyzcGF3C5TFyBQBA13V1RKPf4uH+bwyzQxZ6CmMZHmNBEfJ" crossorigin="anonymous"></script>
+    <!-- <script src="{{ url_for('static', filename='site.js') }}"/> -->
+
+    <!-- Option 2: Separate Popper and Bootstrap JS -->
+    <!--
+    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.10.2/dist/umd/popper.min.js" integrity="sha384-7+zCNj/IqJ95wo16oMtfsKbZ9ccEh31eOz1HGyDuCQ6wgnyJNSYdrPa03rtR1zdB" crossorigin="anonymous"></script>
+    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.2/dist/js/bootstrap.min.js" integrity="sha384-PsUw7Xwds7x08Ew3exXhqzbhuEYmA2xnwc8BuD6SEr+UmEHlX8/MCltYEodzWA4u" crossorigin="anonymous"></script>
+    -->
+  </body>
+</html>
\ No newline at end of file
diff --git a/src/webui/service/templates/context/home.html b/src/webui/service/templates/context/home.html
new file mode 100644
index 000000000..c389ea658
--- /dev/null
+++ b/src/webui/service/templates/context/home.html
@@ -0,0 +1,79 @@
+{% extends 'base.html' %}
+
+{% block content %}
+    <h1>Service</h1>
+
+    <div class="row">
+        <div class="col">
+            <a href="{{ url_for('service.add') }}" class="btn btn-primary" style="margin-bottom: 10px;">
+                <i class="bi bi-plus"></i>
+                Add New Service
+            </a>
+        </div>
+        <div class="col">
+            {{ services | length }} services found
+        </div>
+        <div class="col">
+            <form>
+                <div class="input-group">
+                    <input type="text" aria-label="Search" placeholder="Search..." class="form-control"/>
+                    <button type="submit" class="btn btn-primary">Search</button>
+                  </div>
+            </form>
+        </div>
+    </div>
+    
+
+    <table class="table table-striped">
+        <thead>
+          <tr>
+            <th scope="col">#</th>
+            <th scope="col">Type</th>
+            <th scope="col">End points</th>
+            <th scope="col">Constraints</th>
+            <th scope="col">State</th>
+            <th scope="col">Configuration</th>
+            <th scope="col"></th>
+          </tr>
+        </thead>
+        <tbody>
+            {% if services %}
+                {% for service in services %}
+                <tr>
+                    <td><a href="{{ url_for('service.detail', contextUuid=service.cs_id.contextId.contextUuid.uuid, serviceUuid=service.cs_id.cs_id.uuid) }}">{{ service.cs_id.contextId.contextUuid.uuid }} / {{ service.cs_id.cs_id.uuid }}</a></td>
+                    <td>{{ service.serviceType }}</td>
+                    <td>
+                        <ul>
+                            {% for end_point in service.endpointList %}
+                            <li>{{ end_point }}</li>
+                            {% endfor %}
+                        </ul>
+                    </td>
+                    <td>
+                        <ul>
+                            {% for constraint in service.constraint %}
+                            <li>{{ constraint }}</li>
+                            {% endfor %}
+                        </ul>
+                    </td>
+                    <td>{{ service.serviceState }}</td>
+                    <td>{{ service.serviceConfig }}</td>
+                    <td>
+                        <a href="{{ url_for('service.detail', contextUuid=service.cs_id.contextId.contextUuid.uuid, serviceUuid=service.cs_id.cs_id.uuid) }}">
+                            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eye" viewBox="0 0 16 16">
+                                <path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z"/>
+                                <path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z"/>
+                            </svg>
+                        </a>
+                    </td>
+                </tr>
+                {% endfor %}
+            {% else %}
+                <tr>
+                    <td colspan="7">No services found</td>
+                </tr>
+            {% endif %}
+        </tbody>
+    </table>
+
+{% endblock %}
\ No newline at end of file
diff --git a/src/webui/service/templates/device/add.html b/src/webui/service/templates/device/add.html
new file mode 100644
index 000000000..dae31a376
--- /dev/null
+++ b/src/webui/service/templates/device/add.html
@@ -0,0 +1,93 @@
+{% extends 'base.html' %}
+
+{% block content %}
+    <h1>Add New Device</h1>
+
+    <form id="add_device" method="POST">
+        {{ form.hidden_tag() }}
+        <fieldset>
+            <div class="row mb-3">
+                {{ form.device_id.label(class="col-sm-2 col-form-label") }}
+                <div class="col-sm-10">
+                  {% if form.device_id.errors %}
+                        {{ form.device_id(class="form-control is-invalid") }}
+                        <div class="invalid-feedback">
+                            {% for error in form.device_id.errors %}
+                                <span>{{ error }}</span>
+                            {% endfor %}
+                        </div>
+                    {% else %}
+                        {{ form.device_id(class="form-control") }}
+                    {% endif %}
+                </div>
+            </div>
+            <div class="row mb-3">
+                {{ form.device_type.label(class="col-sm-2 col-form-label") }}
+                <div class="col-sm-10">
+                  {% if form.device_type.errors %}
+                        {{ form.device_type(class="form-control is-invalid") }}
+                        <div class="invalid-feedback">
+                            {% for error in form.device_type.errors %}
+                                <span>{{ error }}</span>
+                            {% endfor %}
+                        </div>
+                    {% else %}
+                        {{ form.device_type(class="form-control") }}
+                    {% endif %}
+                </div>
+            </div>
+            <div class="row mb-3">
+                {{ form.operational_status.label(class="col-sm-2 col-form-label") }}
+                <div class="col-sm-10">
+                  {% if form.operational_status.errors %}
+                        {{ form.operational_status(class="form-control is-invalid") }}
+                        <div class="invalid-feedback">
+                            {% for error in form.operational_status.errors %}
+                                <span>{{ error }}</span>
+                            {% endfor %}
+                        </div>
+                    {% else %}
+                        {{ form.operational_status(class="form-control") }}
+                    {% endif %}
+                </div>
+            </div>
+            <div class="row mb-3">
+                {{ form.device_config.label(class="col-sm-2 col-form-label") }}
+                <div class="col-sm-10">
+                  {% if form.device_config.errors %}
+                        {{ form.device_config(class="form-control is-invalid", rows=5) }}
+                        <div class="invalid-feedback">
+                            {% for error in form.device_config.errors %}
+                                <span>{{ error }}</span>
+                            {% endfor %}
+                        </div>
+                    {% else %}
+                        {{ form.device_config(class="form-control", rows=5) }}
+                    {% endif %}
+                </div>
+                <div id="device_config_help" class="form-text">The device configurations should follow a <i>key=value</i> format, one configuration per line.</div>
+            </div>
+            <div class="row mb-3">
+                {{ form.device_drivers.label(class="col-sm-2 col-form-label") }}
+                <div class="col-sm-10">
+                  {% if form.device_drivers.errors %}
+                        {{ form.device_drivers(class="form-control is-invalid", rows=5) }}
+                        <div class="invalid-feedback">
+                            {% for error in form.device_drivers.errors %}
+                                <span>{{ error }}</span>
+                            {% endfor %}
+                        </div>
+                    {% else %}
+                        {{ form.device_drivers(class="form-control", rows=5) }}
+                    {% endif %}
+                </div>
+                <div id="device_drivers_help" class="form-text">
+                    List the device drivers by their numerical ID, separated by commas, without spaces between them. Numerical IDs: {{ device_driver_ids }}.
+                </div>
+            </div>
+            <div class="row mb-3">
+                <button type="submit" class="btn btn-primary">{{ submit_text }}</button>
+            </div>
+        </fieldset>
+    </form>
+{% endblock %}
\ No newline at end of file
diff --git a/src/webui/service/templates/device/detail.html b/src/webui/service/templates/device/detail.html
new file mode 100644
index 000000000..c090e13b5
--- /dev/null
+++ b/src/webui/service/templates/device/detail.html
@@ -0,0 +1,73 @@
+{% extends 'base.html' %}
+
+{% block content %}
+    <h1>Device {{ device.device_id.device_uuid.uuid }}</h1>
+
+    <div class="row mb-3">
+        <div class="col-sm-3">
+            <button type="button" class="btn btn-success" onclick="window.location.href = '/device/'"><i class="bi bi-box-arrow-in-left"></i>Back to device list</button>
+        </div>
+        <div class="col-sm-3">
+            <a id="update" class="btn btn-secondary" href="#"><i class="bi bi-pencil-square"></i>Update</a>
+        </div>
+        <div class="col-sm-3">
+            <!-- <button type="button" class="btn btn-danger"><i class="bi bi-x-square"></i>Delete device</button> -->
+            <button type="button" class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#deleteModal">
+                <i class="bi bi-x-square"></i>Delete device
+              </button>
+        </div>
+    </div>
+
+    <div class="row mb-3">
+        <b>UUID:</b>
+        <div class="col-sm-10">
+            {{ device.device_id.device_uuid.uuid }}
+        </div>
+    </div>
+    <div class="row mb-3">
+        <b>Type:</b>
+        <div class="col-sm-10">
+            {{ device.device_type }}
+        </div>
+    </div>
+    <div class="row mb-3">
+        <b>Configurations:</b>
+        <div class="col-sm-10">
+            <ul>
+            {% for config in device.device_config.config_rules %}
+                <li>{{ config.resource_key }}: {{ config.resource_value }}</li>
+            {% endfor %}
+            </ul>
+        </div>
+    </div>
+    <div class="row mb-3">
+        <b>Endpoints:</b>
+        <div class="col-sm-10">
+            <ul>
+            {% for endpoint in device.device_endpoints %}
+                <li>{{ endpoint.endpoint_id.endpoint_uuid.uuid }}: {{ endpoint.endpoint_type }}</li>
+            {% endfor %}
+            </ul>
+        </div>
+    </div>
+
+    <!-- Modal -->
+<div class="modal fade" id="deleteModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
+    <div class="modal-dialog">
+      <div class="modal-content">
+        <div class="modal-header">
+          <h5 class="modal-title" id="staticBackdropLabel">Delete device?</h5>
+          <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
+        </div>
+        <div class="modal-body">
+          Are you sure you want to delete the device "{{ device.device_id.device_uuid.uuid }}"?
+        </div>
+        <div class="modal-footer">
+          <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">No</button>
+          <a type="button" class="btn btn-danger" href="{{ url_for('device.delete', device_uuid=device.device_id.device_uuid.uuid) }}"><i class="bi bi-exclamation-diamond"></i>Yes</a>
+        </div>
+      </div>
+    </div>
+  </div>
+
+{% endblock %}
\ No newline at end of file
diff --git a/src/webui/service/templates/device/home.html b/src/webui/service/templates/device/home.html
new file mode 100644
index 000000000..6010ed6a9
--- /dev/null
+++ b/src/webui/service/templates/device/home.html
@@ -0,0 +1,93 @@
+{% extends 'base.html' %}
+
+{% block content %}
+    <h1>Devices</h1>
+
+    <div class="row">
+        <!-- <div class="col">
+            <a href="{{ url_for('device.add') }}" class="btn btn-primary" style="margin-bottom: 10px;">
+                <i class="bi bi-plus"></i>
+                Add New Device
+            </a>
+        </div> -->
+        <div class="col">
+            {{ devices | length }} devices found in context <i>{{ session['context_uuid'] }}</i>
+        </div>
+        <!-- <div class="col">
+            <form>
+                <div class="input-group">
+                    <input type="text" aria-label="Search" placeholder="Search..." class="form-control"/>
+                    <button type="submit" class="btn btn-primary">Search</button>
+                  </div>
+            </form>
+        </div> -->
+    </div>
+
+    <table class="table table-striped table-hover">
+        <thead>
+          <tr>
+            <th scope="col">#</th>
+            <th scope="col">Type</th>
+            <th scope="col">Endpoints</th>
+            <th scope="col">Drivers</th>
+            <th scope="col">Status</th>
+            <th scope="col">Configuration</th>
+            <!-- <th scope="col"></th> -->
+          </tr>
+        </thead>
+        <tbody>
+            {% if devices %}
+                {% for device in devices %}
+                <tr>
+                    <td>
+                        <!-- <a href="{{ url_for('device.detail', device_uuid=device.device_id.device_uuid.uuid) }}"> -->
+                            {{ device.device_id.device_uuid.uuid }}
+                        <!-- </a> -->
+                    </td>
+                    <td>
+                        {{ device.device_type }}
+                    </td>
+                    <td>
+                        <ul>
+                            {% for end_point in device.device_endpoints %}
+                            <li>{{ end_point.endpoint_id.endpoint_uuid.uuid }}</li>
+                            {% endfor %}
+                        </ul>
+                    </td>
+                    <td>
+                        <ul>
+                            {% for driver in device.device_drivers %}
+                            <li>{{ dde.Name(driver) }}</li>
+                            {% endfor %}
+                        </ul>
+                    </td>
+                    <td>{{ dose.Name(device.device_operational_status) }}</td>
+                    <td>
+                        <ul>
+                            {% for config in device.device_config.config_rules %}
+                            <li>
+                                Key: {{ config.resource_key }}<br/>
+                                Value: {{ config.resource_value }}
+                            </li>
+                            {% endfor %}
+                        </ul>
+                    </td>
+                    <!-- <td>
+                        <a href="{{ url_for('device.detail', device_uuid=device.device_id.device_uuid.uuid) }}">
+                            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eye" viewBox="0 0 16 16">
+                                <path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z"/>
+                                <path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z"/>
+                            </svg>
+                        </a>
+                    </td> -->
+                </tr>
+                {% endfor %}
+            {% else %}
+                <tr>
+                    <td colspan="7">No devices found</td>
+                </tr>
+            {% endif %}
+        </tbody>
+    </table>
+
+{% endblock %}
\ No newline at end of file
diff --git a/src/webui/service/templates/main/about.html b/src/webui/service/templates/main/about.html
new file mode 100644
index 000000000..9ac1e29e8
--- /dev/null
+++ b/src/webui/service/templates/main/about.html
@@ -0,0 +1,9 @@
+{% extends 'base.html' %}
+{% block content %}
+    <h1>TeraFlow OS</h1>
+
+    <p>For more information, visit the <a href="https://teraflow-h2020.eu/" target="_newtf">TeraFlow H2020 webpage</a>.</p>
+
+    <img alt="Consortium" src="{{ url_for('static', filename='partners.png') }}"/>
+
+{% endblock %}
\ No newline at end of file
diff --git a/src/webui/service/templates/main/home.html b/src/webui/service/templates/main/home.html
new file mode 100644
index 000000000..2bda77eb0
--- /dev/null
+++ b/src/webui/service/templates/main/home.html
@@ -0,0 +1,37 @@
+{% extends 'base.html' %}
+
+{% block content %}
+    <h1>This is the home page</h1>
+    <p>Here we have have several things.</p>
+
+    {% for field, message in context_form.errors.items() %}
+        <div class="alert alert-dismissible fade show" role="alert">
+        <b>{{ field }}</b>: {{ message }}
+        <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
+        </div>
+
+    {% endfor %}
+
+    <h2>Select the working context</h2>
+    <form id="select_context" method="POST">
+        {{ context_form.hidden_tag() }}
+        <fieldset class="form-group">
+            <div class="input-group mb-3">
+
+                {% if context_form.context.errors %}
+                    {{ context_form.context(class="form-select is-invalid") }}
+                    <div class="invalid-feedback">
+                        {% for error in context_form.context.errors %}
+                            <span>{{ error }}</span>
+                        {% endfor %}
+                    </div>
+                {% else %}
+                    {{ context_form.context(class="form-select") }}
+                {% endif %}
+
+                {{ context_form.submit(class='btn btn-primary') }}
+            </div>
+        </fieldset>
+    </form>
+
+{% endblock %}
\ No newline at end of file
diff --git a/src/webui/service/templates/service/home.html b/src/webui/service/templates/service/home.html
new file mode 100644
index 000000000..648ce99bd
--- /dev/null
+++ b/src/webui/service/templates/service/home.html
@@ -0,0 +1,95 @@
+{% extends 'base.html' %}
+
+{% block content %}
+    <h1>Services</h1>
+
+    <div class="row">
+        <!-- <div class="col">
+            <a href="{{ url_for('service.add') }}" class="btn btn-primary" style="margin-bottom: 10px;">
+                <i class="bi bi-plus"></i>
+                Add New Service
+            </a>
+        </div> -->
+        <div class="col">
+            {{ services | length }} services found in context <i>{{ session['context_uuid'] }}</i>
+        </div>
+        <!-- <div class="col">
+            <form>
+                <div class="input-group">
+                    <input type="text" aria-label="Search" placeholder="Search..." class="form-control"/>
+                    <button type="submit" class="btn btn-primary">Search</button>
+                  </div>
+            </form>
+        </div> -->
+    </div>
+    
+
+    <table class="table table-striped table-hover">
+        <thead>
+          <tr>
+            <th scope="col">#</th>
+            <th scope="col">Type</th>
+            <th scope="col">End points</th>
+            <th scope="col">Constraints</th>
+            <th scope="col">Status</th>
+            <th scope="col">Configuration</th>
+            <!-- <th scope="col"></th> -->
+          </tr>
+        </thead>
+        <tbody>
+            {% if services %}
+                {% for service in services %}
+                <tr>
+                    <td>
+                        <!-- <a href="{{ url_for('service.detail', service_uuid=service.service_id.service_uuid.uuid) }}"> -->
+                            {{ service.service_id.service_uuid.uuid }}
+                        <!-- </a> -->
+                    </td>
+                    <td>
+                        {{ ste.Name(service.service_type) }}
+                    </td>
+                    <td>
+                        <ul>
+                            {% for end_point in service.service_endpoint_ids %}
+                            <li>{{ end_point.device_id.device_uuid.uuid }} / {{ end_point.endpoint_uuid.uuid }}</li>
+                            {% endfor %}
+                        </ul>
+                    </td>
+                    <td>
+                        <ul>
+                            {% for constraint in service.service_constraints %}
+                            <li>{{ constraint.constraint_type }}: {{ constraint.constraint_value }}</li>
+                            {% endfor %}
+                        </ul>
+                    </td>
+                    <td>{{ sse.Name(service.service_status.service_status) }}</td>
+                    <td>
+                        <ul>
+                            {% for rule in service.service_config.config_rules %}
+                            <li>
+                                Key: {{ rule.resource_key }}
+                                <br/>
+                                Value: {{ rule.resource_value }}
+                            </li>
+                            {% endfor %}
+                        </ul>
+                    </td>
+                    <!-- <td>
+                        <a href="{{ url_for('service.detail', service_uuid=service.service_id.service_uuid.uuid) }}">
+                            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eye" viewBox="0 0 16 16">
+                                <path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z"/>
+                                <path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z"/>
+                            </svg>
+                        </a>
+                    </td> -->
+                </tr>
+                {% endfor %}
+            {% else %}
+                <tr>
+                    <td colspan="7">No services found</td>
+                </tr>
+            {% endif %}
+        </tbody>
+    </table>
+
+{% endblock %}
\ No newline at end of file
diff --git a/src/webui/tests/__init__.py b/src/webui/tests/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/webui/tests/test_unitary.py b/src/webui/tests/test_unitary.py
new file mode 100644
index 000000000..0612c9d05
--- /dev/null
+++ b/src/webui/tests/test_unitary.py
@@ -0,0 +1,156 @@
+# import pytest
+from flask_unittest import ClientTestCase
+from unittest import mock
+from flask.testing import FlaskClient
+from flask.app import Flask
+from flask.helpers import url_for
+# from device.client.DeviceClient import DeviceClient
+from webui.service import create_app
+from webui.proto.context_pb2 import Empty, DeviceId, DeviceList, TopologyIdList
+
+class TestWebUI(ClientTestCase):
+    app = create_app(use_config={'TESTING': True, 
+                                 'SERVER_NAME': 'localhost.localdomain',
+                                 'SECRET_KEY': '>s&}24@{]]#k3&^5$f3#?6?h3{W@[}/7z}2pa]>{3&5%RP<)[(',
+                                 'WTF_CSRF_ENABLED': False})
+    
+    def setUp(self, client: FlaskClient) -> None:
+
+        self.mocker_delete_device = mock.patch('webui.service.device.routes.device_client.DeleteDevice')
+        self.mocker_delete_device.return_value = Empty()
+        self.mocker_delete_device.start()
+        self.addCleanup(self.mocker_delete_device.stop)
+
+        self.mocker_list_devices = mock.patch('webui.service.device.routes.context_client.ListDevices')
+        self.mocker_list_devices.return_value = DeviceList()  # returns an empty list
+        self.mocker_list_devices.start()
+        self.addCleanup(self.mocker_list_devices.stop)
+
+        self.mocker_add_device = mock.patch('webui.service.device.routes.device_client.AddDevice')
+        self.mocker_add_device.return_value = DeviceId()
+        self.mocker_add_device.start()
+        self.addCleanup(self.mocker_add_device.stop)
+
+        self.mocker_list_topology_ids = mock.patch('webui.service.device.routes.context_client.ListTopologyIds')
+        self.mocker_list_topology_ids.return_value = TopologyIdList()
+        self.mocker_list_topology_ids.start()
+        self.addCleanup(self.mocker_list_topology_ids.stop)
+
+        return super().setUp(client)
+    
+    def tearDown(self, client: FlaskClient) -> None:
+        mock.patch.stopall()
+        return super().tearDown(client)
+    
+    def test_routes(self, client):
+        with self.app.app_context():
+            url_for('main.home')
+            url_for('service.home')
+            url_for('device.home')
+            url_for('main.about')
+    
+    def test_device_add_action_success(self, client):
+        with client.session_transaction() as sess:
+            sess['context_uuid'] = 'admin'
+        DEVICE_EMU = {
+            'device_id': 'EMULATED',
+            'device_type': 'emulated',
+            'device_config': '',
+            'operational_status': 1,
+            'device_drivers': 0,
+            'device_endpoints': [],
+        }
+        rv = client.post('/device/add', data=DEVICE_EMU, follow_redirects=True)
+        self.assertInResponse(b'success', rv)
+    
+    def test_device_delete_action(self, client):
+        with client.session_transaction() as sess:
+            sess['context_uuid'] = 'admin'
+
+        rv = client.get('/device/EMULATED/delete', follow_redirects=True)
+        # mocked_list.assert_called()
+        # mocked_delete.assert_called()
+        self.assertInResponse(b'success', rv)
+    
+    def test_service_up(self, client):
+        pass
+
+
+
+# def test_service_up(client):
+#     rw = client.get('/')
+#     assert rw.status_code == 200, 'Service is not up!'
+
+# def test_home_page(client):
+#     rw = client.get('/')
+#     assert rw.status_code == 200, 'Error in the home page!'
+#     assert b'Select the working context' in rw.data
+
+# def test_service_home_page(client):
+#     with client.session_transaction() as sess:
+#         sess['context_uuid'] = 'admin'
+#     rw = client.get('/service/')
+#     assert rw.status_code == 200
+#     assert b'Services' in rw.data
+#     assert b'Add New Service' in rw.data
+
+# def test_device_home_page(client):
+#     with client.session_transaction() as sess:
+#         sess['context_uuid'] = 'admin'
+#     rw = client.get('/device/')
+#     assert rw.status_code == 200
+#     assert b'Devices' in rw.data
+#     assert b'Add New Device' in rw.data
+
+# @pytest.mark.parametrize('device_id', (
+#     'DEV1',
+#     'DEV2',
+#     'DEV3',
+# ))
+# def test_device_detail_page(client, device_id):
+#     with client.session_transaction() as sess:
+#         sess['context_uuid'] = 'admin'
+#     rw = client.get(f'/device/detail/{device_id}')
+#     assert rw.status_code == 200
+#     assert b'Device' in rw.data
+#     assert device_id in rw.data.decode()
+#     assert b'Endpoints' in rw.data, 'Missing endpoint information on the device detail page.'
+#     # assert b'Add New Device' in rw.data
+
+# def test_device_add_page(client):
+#     with client.session_transaction() as sess:
+#         sess['context_uuid'] = 'admin'
+#     rw = client.get('/device/add')
+#     assert rw.status_code == 200
+#     assert b'Add New Device' in rw.data
+#     assert b'Operational Status' in rw.data, 'Form is not correctly implemented.'
+#     assert b'Type' in rw.data, 'Form is not correctly implemented.'
+#     assert b'Configurations' in rw.data, 'Form is not correctly implemented.'
+#     assert b'Drivers' in rw.data, 'Form is not correctly implemented.'
+
+# def test_device_add_action(client):
+#     with client.session_transaction() as sess:
+#         sess['context_uuid'] = 'admin'
+#     DEVICE_EMU = {
+#         'device_id': 'EMULATED',
+#         'device_type': 'emulated',
+#         'device_config': '',
+#         'operational_status': 1,
+#         'device_drivers': 0,
+#         'device_endpoints': [],
+#     }
+#     with mock.patch('webui.service.device.routes.device_client.AddDevice') as mocked_add:
+#         mocked_add.return_value = DeviceId()
+#         rw = client.post('/device/add', data=DEVICE_EMU, follow_redirects=True)
+#     assert b'success' in rw.data
+
+# def test_device_delete_action(client):
+#     with client.session_transaction() as sess:
+#         sess['context_uuid'] = 'admin'
+#     with mock.patch('webui.service.device.routes.device_client.DeleteDevice') as mocked_delete,\
+#          mock.patch('webui.service.device.routes.context_client.ListDevices') as mocked_list:
+#         mocked_list.return_value = DeviceList()  # returns an empty list
+#         rw = client.get('/device/EMULATED/delete', follow_redirects=True)
+#         mocked_list.assert_called()
+#         mocked_delete.assert_called()
+#     assert b'success' in rw.data
diff --git a/src/webui/utils/__init__.py b/src/webui/utils/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/webui/utils/form_validators.py b/src/webui/utils/form_validators.py
new file mode 100644
index 000000000..e339fdcc0
--- /dev/null
+++ b/src/webui/utils/form_validators.py
@@ -0,0 +1,14 @@
+from wtforms.validators import ValidationError
+
+def key_value_validator():
+    def _validate(form, field):
+        if len(field.data) > 0:
+            if '\n' not in field.data:  # case in which there is only one configuration
+                if '=' not in field.data:
+                    raise ValidationError(f'Configuration "{field.data}" does not follow the key=value pattern.')
+            else:  # case in which there are several configurations
+                configurations = field.data.split('\n')
+                for configutation in configurations:
+                    if '=' not in configutation:
+                        raise ValidationError(f'Configuration "{configutation}" does not follow the key=value pattern.')
+    return _validate
-- 
GitLab