diff --git a/configure_dashboards.sh b/configure_dashboards.sh index 1c0857c89b312f2232e73aa8eef980fbb5056d0e..edfdfa370538cfb7129e365be5062f16291a67d7 100755 --- a/configure_dashboards.sh +++ b/configure_dashboards.sh @@ -22,11 +22,15 @@ INFLUXDB_USER=$(kubectl --namespace $K8S_NAMESPACE get secrets influxdb-secrets INFLUXDB_PASSWORD=$(kubectl --namespace $K8S_NAMESPACE get secrets influxdb-secrets -o jsonpath='{.data.INFLUXDB_ADMIN_PASSWORD}' | base64 --decode) INFLUXDB_DATABASE=$(kubectl --namespace $K8S_NAMESPACE get secrets influxdb-secrets -o jsonpath='{.data.INFLUXDB_DB}' | base64 --decode) -GRAFANA_HOSTNAME=$(kubectl get node $K8S_HOSTNAME -o 'jsonpath={.status.addresses[?(@.type=="InternalIP")].address}') -GRAFANA_PORT=$(kubectl get service webuiservice-public --namespace $K8S_NAMESPACE -o 'jsonpath={.spec.ports[?(@.port==3000)].nodePort}') +# GRAFANA_HOSTNAME=$(kubectl get node $K8S_HOSTNAME -o 'jsonpath={.status.addresses[?(@.type=="InternalIP")].address}') +# GRAFANA_HOSTNAME=`kubectl get service/webuiservice-public -n ${K8S_NAMESPACE} -o jsonpath='{.spec.clusterIP}'` +GRAFANA_HOSTNAME=`kubectl get nodes --selector=node-role.kubernetes.io/master -o jsonpath='{$.items[*].status.addresses[?(@.type=="InternalIP")].address}'` +# GRAFANA_PORT=$(kubectl get service webuiservice-public --namespace $K8S_NAMESPACE -o 'jsonpath={.spec.ports[?(@.port==3000)].nodePort}') +GRAFANA_PORT=`kubectl get service/webuiservice-public -n ${K8S_NAMESPACE} -o jsonpath='{.spec.ports[1].nodePort}'` GRAFANA_USERNAME="admin" GRAFANA_PASSWORD=${GRAFANA_PASSWORD:-"admin123+"} GRAFANA_URL="http://${GRAFANA_USERNAME}:${GRAFANA_PASSWORD}@${GRAFANA_HOSTNAME}:${GRAFANA_PORT}" +echo "Connecting to grafana at URL: ${GRAFANA_URL}..." # Configure Grafana Admin Password # Ref: https://grafana.com/docs/grafana/latest/http_api/user/#change-password @@ -54,12 +58,6 @@ echo # Create Monitoring Dashboard # Ref: https://grafana.com/docs/grafana/latest/http_api/dashboard/ -<<<<<<< HEAD -curl -H "Content-Type: application/json" \ - -d '@src/webui/grafana_dashboard.json' \ - ${GRAFANA_URL}/api/dashboards/db -echo -======= curl -X POST -H "Content-Type: application/json" \ -d '@src/webui/grafana_dashboard.json' \ ${GRAFANA_URL}/api/dashboards/db @@ -68,4 +66,3 @@ echo DASHBOARD_URL="${GRAFANA_URL}/api/dashboards/uid/tf-l3-monit" DASHBOARD_ID=$(python -c 'import json, requests; print(requests.get("'${DASHBOARD_URL}'").json()["dashboard"]["id"])') curl -X POST ${GRAFANA_URL}/api/user/stars/dashboard/${DASHBOARD_ID} ->>>>>>> develop diff --git a/open_webui.sh b/open_webui.sh index ced0594824576717e5b17ab6baf6fc93a98b4427..23cb704ad7a2ee5e9134b2727a02f10b6591582b 100755 --- a/open_webui.sh +++ b/open_webui.sh @@ -14,11 +14,13 @@ # this script opens the webui +K8S_NAMESPACE=${K8S_NAMESPACE:-'tf-dev'} + WEBUI_SERVICE_NAME="service/webuiservice-public" -WEBUI_PROTO=`kubectl get ${WEBUI_SERVICE_NAME} -n tf-dev -o jsonpath='{.spec.ports[0].name}'` -WEBUI_IP=`kubectl get ${WEBUI_SERVICE_NAME} -n tf-dev -o jsonpath='{.spec.clusterIP}'` -WEBUI_PORT=`kubectl get ${WEBUI_SERVICE_NAME} -n tf-dev -o jsonpath='{.spec.ports[0].port}'` -GRAFANA_PORT=`kubectl get ${WEBUI_SERVICE_NAME} -n tf-dev -o jsonpath='{.spec.ports[1].port}'` +WEBUI_PROTO=`kubectl get ${WEBUI_SERVICE_NAME} -n ${K8S_NAMESPACE} -o jsonpath='{.spec.ports[0].name}'` +WEBUI_IP=`kubectl get ${WEBUI_SERVICE_NAME} -n ${K8S_NAMESPACE} -o jsonpath='{.spec.clusterIP}'` +WEBUI_PORT=`kubectl get ${WEBUI_SERVICE_NAME} -n ${K8S_NAMESPACE} -o jsonpath='{.spec.ports[0].port}'` +GRAFANA_PORT=`kubectl get ${WEBUI_SERVICE_NAME} -n ${K8S_NAMESPACE} -o jsonpath='{.spec.ports[1].port}'` URL=${WEBUI_PROTO}://${WEBUI_IP}:${WEBUI_PORT} echo Opening web UI on URL ${URL} diff --git a/src/start_webui_dev_mode.sh b/src/start_webui_dev_mode.sh index d9e143b4873406b196b1e7f726c5d458b2994f05..74540bcb36115dc175f371acbb3f80930404eac9 100755 --- a/src/start_webui_dev_mode.sh +++ b/src/start_webui_dev_mode.sh @@ -14,11 +14,13 @@ # for development purposes only -export CONTEXTSERVICE_SERVICE_HOST=`kubectl get service/contextservice -n tf-dev -o jsonpath='{.spec.clusterIP}'` +K8S_NAMESPACE=${K8S_NAMESPACE:-'tf-dev'} + +export CONTEXTSERVICE_SERVICE_HOST=`kubectl get service/contextservice -n ${K8S_NAMESPACE} -o jsonpath='{.spec.clusterIP}'` echo Context IP: $CONTEXTSERVICE_SERVICE_HOST -export DEVICESERVICE_SERVICE_HOST=`kubectl get service/deviceservice -n tf-dev -o jsonpath='{.spec.clusterIP}'` +export DEVICESERVICE_SERVICE_HOST=`kubectl get service/deviceservice -n ${K8S_NAMESPACE} -o jsonpath='{.spec.clusterIP}'` echo Device IP: $DEVICESERVICE_SERVICE_HOST diff --git a/src/tests/ofc22/run_test_01_bootstrap.sh b/src/tests/ofc22/run_test_01_bootstrap.sh index 042e0a0a2f08b59074da2a6e185fc00f37b482c0..634fed02dd71464c6878f0c96fb67cf3067148e2 100755 --- a/src/tests/ofc22/run_test_01_bootstrap.sh +++ b/src/tests/ofc22/run_test_01_bootstrap.sh @@ -28,7 +28,9 @@ rm -f $COVERAGEFILE # Set the name of the Kubernetes namespace and hostname to use. K8S_NAMESPACE="ofc22" -K8S_HOSTNAME="kubernetes-master" +# K8S_HOSTNAME="kubernetes-master" +# dynamically gets the name of the K8s master node +K8S_HOSTNAME=`kubectl get nodes --selector=node-role.kubernetes.io/master | tr -s " " | cut -f1 -d" " | sed -n '2 p'` # Flush Context database kubectl --namespace $K8S_NAMESPACE exec -it deployment/contextservice --container redis -- redis-cli FLUSHALL diff --git a/src/tests/ofc22/run_test_02_create_service.sh b/src/tests/ofc22/run_test_02_create_service.sh index b212b687c2fd5be42239e3012d91d01b963c9c7f..5498f91f2a3186ca694443dfc047760464ad2663 100755 --- a/src/tests/ofc22/run_test_02_create_service.sh +++ b/src/tests/ofc22/run_test_02_create_service.sh @@ -22,7 +22,8 @@ COVERAGEFILE=$PROJECTDIR/coverage/.coverage # Set the name of the Kubernetes namespace and hostname to use. K8S_NAMESPACE="ofc22" -K8S_HOSTNAME="kubernetes-master" +# dynamically gets the name of the K8s master node +K8S_HOSTNAME=`kubectl get nodes --selector=node-role.kubernetes.io/master | tr -s " " | cut -f1 -d" " | sed -n '2 p'` export CONTEXTSERVICE_SERVICE_HOST=$(kubectl get node $K8S_HOSTNAME -o 'jsonpath={.status.addresses[?(@.type=="InternalIP")].address}') export CONTEXTSERVICE_SERVICE_PORT_GRPC=$(kubectl get service contextservice-public --namespace $K8S_NAMESPACE -o 'jsonpath={.spec.ports[?(@.port==1010)].nodePort}') diff --git a/src/tests/ofc22/run_test_03_delete_service.sh b/src/tests/ofc22/run_test_03_delete_service.sh index d0c3127ad7d2384285dde46c6fadefb4f6f8bdc6..7a8e3a662610042fc3aaf603f8944e48d5573dd2 100755 --- a/src/tests/ofc22/run_test_03_delete_service.sh +++ b/src/tests/ofc22/run_test_03_delete_service.sh @@ -22,7 +22,8 @@ COVERAGEFILE=$PROJECTDIR/coverage/.coverage # Set the name of the Kubernetes namespace and hostname to use. K8S_NAMESPACE="ofc22" -K8S_HOSTNAME="kubernetes-master" +# dynamically gets the name of the K8s master node +K8S_HOSTNAME=`kubectl get nodes --selector=node-role.kubernetes.io/master | tr -s " " | cut -f1 -d" " | sed -n '2 p'` export CONTEXTSERVICE_SERVICE_HOST=$(kubectl get node $K8S_HOSTNAME -o 'jsonpath={.status.addresses[?(@.type=="InternalIP")].address}') export CONTEXTSERVICE_SERVICE_PORT_GRPC=$(kubectl get service contextservice-public --namespace $K8S_NAMESPACE -o 'jsonpath={.spec.ports[?(@.port==1010)].nodePort}') diff --git a/src/tests/ofc22/run_test_04_cleanup.sh b/src/tests/ofc22/run_test_04_cleanup.sh index c31774523dd9937f82e17a7c90fbf41c7b3594f4..5995a804f84db1d18f7e1ed18676bc575af7e80b 100755 --- a/src/tests/ofc22/run_test_04_cleanup.sh +++ b/src/tests/ofc22/run_test_04_cleanup.sh @@ -22,7 +22,8 @@ COVERAGEFILE=$PROJECTDIR/coverage/.coverage # Set the name of the Kubernetes namespace and hostname to use. K8S_NAMESPACE="ofc22" -K8S_HOSTNAME="kubernetes-master" +# dynamically gets the name of the K8s master node +K8S_HOSTNAME=`kubectl get nodes --selector=node-role.kubernetes.io/master | tr -s " " | cut -f1 -d" " | sed -n '2 p'` export CONTEXTSERVICE_SERVICE_HOST=$(kubectl get node $K8S_HOSTNAME -o 'jsonpath={.status.addresses[?(@.type=="InternalIP")].address}') export CONTEXTSERVICE_SERVICE_PORT_GRPC=$(kubectl get service contextservice-public --namespace $K8S_NAMESPACE -o 'jsonpath={.spec.ports[?(@.port==1010)].nodePort}') diff --git a/src/tests/ofc22/tests/Objects.py b/src/tests/ofc22/tests/Objects.py index 6205b5e4ada67749f8230e99badca048a2372c2b..a47ba7c16d841ca51c9889f83a0796d8540bb621 100644 --- a/src/tests/ofc22/tests/Objects.py +++ b/src/tests/ofc22/tests/Objects.py @@ -61,7 +61,7 @@ except ImportError: DEVICE_O1_ADDRESS = '0.0.0.0' DEVICE_O1_PORT = 4900 -#USE_REAL_DEVICES = False # Uncomment to force to use emulated devices +# USE_REAL_DEVICES = False # Uncomment to force to use emulated devices def json_endpoint_ids(device_id : Dict, endpoint_descriptors : List[Tuple[str, str, List[int]]]): return [ diff --git a/src/webui/service/device/routes.py b/src/webui/service/device/routes.py index 8a0e1cc0a8448a91b7dcaec1b9cc0d7308c65821..f4e58d3b0f92ef4e002c086ccc6092c9d5d397ef 100644 --- a/src/webui/service/device/routes.py +++ b/src/webui/service/device/routes.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from flask import render_template, Blueprint, flash, session, redirect +from flask import render_template, Blueprint, flash, session, redirect, url_for from device.client.DeviceClient import DeviceClient from context.client.ContextClient import ContextClient from webui.Config import (CONTEXT_SERVICE_ADDRESS, CONTEXT_SERVICE_PORT, @@ -28,6 +28,10 @@ device_client: DeviceClient = DeviceClient(DEVICE_SERVICE_ADDRESS, DEVICE_SERVIC @device.get('/') def home(): + context_uuid = session.get('context_uuid', '-') + if context_uuid == "-": + flash("Please select a context!", "warning") + return redirect(url_for("main.home")) request: ContextId = ContextId() request.context_uuid.uuid = session.get('context_uuid', '-') context_client.connect() diff --git a/src/webui/service/main/routes.py b/src/webui/service/main/routes.py index 78247b3ca66b41801bf12a7cb3be25e2adf93ad4..6a74b6f53fdcdd1c46128c695e78a4dab81cf491 100644 --- a/src/webui/service/main/routes.py +++ b/src/webui/service/main/routes.py @@ -14,7 +14,7 @@ import logging import sys -from flask import render_template, Blueprint, flash, session +from flask import redirect, render_template, Blueprint, flash, session, url_for from webui.Config import CONTEXT_SERVICE_ADDRESS, CONTEXT_SERVICE_PORT from context.client.ContextClient import ContextClient from webui.proto.context_pb2 import Empty @@ -49,3 +49,9 @@ def home(): @main.get('/about') def about(): return render_template('main/about.html') + + +@main.get('/resetsession') +def reset_session(): + session.clear() + return redirect(url_for("main.home")) diff --git a/src/webui/service/service/routes.py b/src/webui/service/service/routes.py index e41be7c4c526efcb3dae32edf0a355044530ef34..d16dccdf8c3a321c47200c4098fda28057a1d079 100644 --- a/src/webui/service/service/routes.py +++ b/src/webui/service/service/routes.py @@ -13,7 +13,7 @@ # limitations under the License. import grpc -from flask import render_template, Blueprint, flash, session +from flask import redirect, render_template, Blueprint, flash, session, url_for 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 @@ -29,6 +29,9 @@ def home(): # flash('This is a danger message', 'danger') context_uuid = session.get('context_uuid', '-') + if context_uuid == "-": + flash("Please select a context!", "warning") + return redirect(url_for("main.home")) request: ContextId = ContextId() request.context_uuid.uuid = context_uuid context_client.connect() @@ -44,7 +47,8 @@ def home(): context_not_found = True context_client.close() - return render_template('service/home.html', services=services, context_not_found=context_not_found, + return render_template('service/home.html', services=services, + context_not_found=context_not_found, ste=ServiceTypeEnum, sse=ServiceStatusEnum) diff --git a/src/webui/service/templates/base.html b/src/webui/service/templates/base.html index fcc8c0a8de658d50766cff3ab582dfd50e06769b..3fdc5e8753a27f5ac73868fd9515bf05aa4561d5 100644 --- a/src/webui/service/templates/base.html +++ b/src/webui/service/templates/base.html @@ -55,21 +55,22 @@ {% 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> + {% 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('service.home') }}">Service</a> + <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"> - {% if '/device/' in request.path %} - <a class="nav-link active" aria-current="page" href="{{ url_for('device.home') }}">Device</a> + {% 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('device.home') }}">Device</a> + <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"> <a class="nav-link" href="#">Compute</a> </li> @@ -114,7 +115,7 @@ </div> </main> - <footer class="footer" style="background-color: darkgrey;"> + <footer class="footer" style="background-color: darkgrey; margin-top: 30px;"> <div class="row"> <div class="col-md-12"> <p class="text-muted text-center" style="color: white;">© 2021-2023</p> diff --git a/src/webui/service/templates/device/add.html b/src/webui/service/templates/device/add.html index aada90f389e52f47f46a81fcbd4fd9f3990cad26..fe1ba31f26579fcf681ccf4da64a7906cae9cff5 100644 --- a/src/webui/service/templates/device/add.html +++ b/src/webui/service/templates/device/add.html @@ -101,9 +101,16 @@ 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> + <div class="d-grid gap-2 d-md-flex justify-content-md-start"> + <button type="submit" class="btn btn-primary"> + <i class="bi bi-plus-circle-fill"></i> + {{ submit_text }} + </button> + <button type="button" class="btn btn-block btn-secondary" onclick="javascript: history.back()"> + <i class="bi bi-box-arrow-in-left"></i> + Cancel + </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 index a8c635808ce9fb9b7b3a4da4310dc160b962f347..af82ede821afb3f576196bbd3561a6dea2a13eae 100644 --- a/src/webui/service/templates/device/detail.html +++ b/src/webui/service/templates/device/detail.html @@ -21,10 +21,16 @@ <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> + <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> + <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> --> @@ -47,21 +53,21 @@ </div> </div> <div class="row mb-3"> - <b>Configurations:</b> + <b>Endpoints:</b> <div class="col-sm-10"> <ul> - {% for config in device.device_config.config_rules %} - <li>{{ config.resource_key }}: {{ config.resource_value }}</li> + {% for endpoint in device.device_endpoints %} + <li>{{ endpoint.endpoint_id.endpoint_uuid.uuid }}: {{ endpoint.endpoint_type }}</li> {% endfor %} </ul> </div> </div> <div class="row mb-3"> - <b>Endpoints:</b> + <b>Configurations:</b> <div class="col-sm-10"> <ul> - {% for endpoint in device.device_endpoints %} - <li>{{ endpoint.endpoint_id.endpoint_uuid.uuid }}: {{ endpoint.endpoint_type }}</li> + {% for config in device.device_config.config_rules %} + <li>{{ config.resource_key }}: {{ config.resource_value }}</li> {% endfor %} </ul> </div> diff --git a/src/webui/service/templates/device/home.html b/src/webui/service/templates/device/home.html index 9f31906695da59be23260179bd540029f5ee1333..a05cac8b99bf1135f80add68d4280ccfba021220 100644 --- a/src/webui/service/templates/device/home.html +++ b/src/webui/service/templates/device/home.html @@ -47,7 +47,7 @@ <th scope="col">Endpoints</th> <th scope="col">Drivers</th> <th scope="col">Status</th> - <th scope="col">Configuration</th> + <!-- <th scope="col">Configuration</th> --> <th scope="col"></th> </tr> </thead> @@ -78,7 +78,7 @@ </ul> </td> <td>{{ dose.Name(device.device_operational_status).replace('DEVICEOPERATIONALSTATUS_', '') }}</td> - <td> + <!-- <td> <ul> {% for config in device.device_config.config_rules %} <li> @@ -87,7 +87,7 @@ </li> {% endfor %} </ul> - </td> + </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"> diff --git a/src/webui/service/templates/service/home.html b/src/webui/service/templates/service/home.html index 8f6a99dc3ab54dacaa9741f70dc6ba08d0714fa6..13fad6625a69a958aacd94929df9ac61295a718b 100644 --- a/src/webui/service/templates/service/home.html +++ b/src/webui/service/templates/service/home.html @@ -20,7 +20,6 @@ <h1>Services</h1> <div class="row"> - {% if context_found %} <!-- <div class="col"> <a href="{{ url_for('service.add') }}" class="btn btn-primary" style="margin-bottom: 10px;"> <i class="bi bi-plus"></i> @@ -38,11 +37,6 @@ </div> </form> </div> --> - {% else %} - <div class="col"> - Context <i>{{ session['context_uuid'] }}</i> not found. - </div> - {% endif %} </div> @@ -54,7 +48,7 @@ <th scope="col">End points</th> <th scope="col">Constraints</th> <th scope="col">Status</th> - <th scope="col">Configuration</th> + <!-- <th scope="col">Configuration</th> --> <!-- <th scope="col"></th> --> </tr> </thead> @@ -85,7 +79,7 @@ </ul> </td> <td>{{ sse.Name(service.service_status.service_status).replace('SERVICESTATUS_', '') }}</td> - <td> + <!-- <td> <ul> {% for rule in service.service_config.config_rules %} <li> @@ -95,7 +89,7 @@ </li> {% endfor %} </ul> - </td> + </td> --> <!-- <td> <a href="{{ url_for('service.detail', service_uuid=service.service_id.service_uuid.uuid.replace('/', '_')) }}"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eye" viewBox="0 0 16 16">