Resolve "(CTTC) Update NBI WebSocket endpoints to Flask-SocketIO and use gunicorn"

Closes #251 (closed)

Merge request reports

Loading
+25 −24
Changes for manifests/nbiservice.yaml: 25 added lines, 24 removed lines.
Original line number Diff line number Diff line
@@ -23,9 +23,6 @@ spec:
  replicas: 1
  template:
    metadata:
      annotations:
        config.linkerd.io/skip-inbound-ports: "8762"
        config.linkerd.io/skip-outbound-ports: "8762"
      labels:
        app: nbiservice
    spec:
@@ -36,22 +33,31 @@ spec:
          imagePullPolicy: Always
          ports:
            - containerPort: 8080
            - containerPort: 9090
            - containerPort: 9192
            - containerPort: 8761
            # Metrics disabled for now. No NBI endpoint uses it and
            # causes "address already in use" when deploying multiple
            # gunicorn workers.
            #- containerPort: 9192
          env:
            - name: LOG_LEVEL
              value: "INFO"
            - name: FLASK_ENV
              value: "production"  # change to "development" if developing
            - name: IETF_NETWORK_RENDERER
              value: "LIBYANG"
            - name: WS_IP_PORT
              value: "8761"
          readinessProbe:
            exec:
              command: ["/bin/grpc_health_probe", "-addr=:9090"]
            httpGet:
              path: /healthz
              port: 8080
            initialDelaySeconds: 5
            periodSeconds: 10
            failureThreshold: 3
          livenessProbe:
            exec:
              command: ["/bin/grpc_health_probe", "-addr=:9090"]
            httpGet:
              path: /healthz
              port: 8080
            initialDelaySeconds: 5
            periodSeconds: 10
            failureThreshold: 3
          resources:
            requests:
              cpu: 50m
@@ -75,15 +81,10 @@ spec:
      protocol: TCP
      port: 8080
      targetPort: 8080
    - name: grpc
      protocol: TCP
      port: 9090
      targetPort: 9090
    - name: metrics
      protocol: TCP
      port: 9192
      targetPort: 9192
    - name: websocket
      protocol: TCP
      port: 8761
      targetPort: 8761
    # Metrics disabled for now. No NBI endpoint uses it and
    # causes "address already in use" when deploying multiple
    # gunicorn workers.
    #- name: metrics
    #  protocol: TCP
    #  port: 9192
    #  targetPort: 9192

proto/nbi.proto

deleted100644 → 0
+0 −28
Changes for proto/nbi.proto: 0 added lines, 28 removed lines.
Original line number Diff line number Diff line
// Copyright 2022-2024 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";
package nbi;

import "context.proto";

service NbiService {
  rpc CheckCredentials                 (context.TeraFlowController) returns (context.AuthenticationResult) {}
  rpc GetConnectivityServiceStatus     (context.ServiceId         ) returns (context.ServiceStatus       ) {}
  rpc CreateConnectivityService        (context.Service           ) returns (context.ServiceId           ) {}
  rpc EditConnectivityService          (context.Service           ) returns (context.ServiceId           ) {}
  rpc DeleteConnectivityService        (context.Service           ) returns (context.Empty               ) {}
  rpc GetAllActiveConnectivityServices (context.Empty             ) returns (context.ServiceIdList       ) {}
  rpc ClearAllConnectivityServices     (context.Empty             ) returns (context.Empty               ) {}
}
+10 −8
Changes for scripts/run_tests_locally-nbi-core.sh: 10 added lines, 8 removed lines.
Original line number Diff line number Diff line
#!/bin/bash
# Copyright 2022-2024 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -12,12 +13,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from common.Constants import ServiceNameEnum
from common.Settings import get_service_baseurl_http, get_service_port_http
from common.tools.service.GenericRestServer import GenericRestServer

class RestServer(GenericRestServer):
    def __init__(self, cls_name: str = __name__) -> None:
        bind_port = get_service_port_http(ServiceNameEnum.NBI)
        base_url = get_service_baseurl_http(ServiceNameEnum.NBI)
        super().__init__(bind_port, base_url, cls_name=cls_name)
PROJECTDIR=`pwd`

cd $PROJECTDIR/src
RCFILE=$PROJECTDIR/coverage/.coveragerc

# Run unitary tests and analyze coverage of code at same time
# helpful pytest flags: --log-level=INFO -o log_cli=true --verbose --maxfail=1 --durations=0
coverage run --rcfile=$RCFILE --append -m pytest --log-level=INFO --verbose \
    nbi/tests/test_core.py
+8 −8
Changes for src/common/tests/InMemoryObjectDatabase.py: 8 added lines, 8 removed lines.
Original line number Diff line number Diff line
@@ -12,10 +12,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import grpc, logging
import grpc #, logging
from typing import Any, Dict, List, Set

LOGGER = logging.getLogger(__name__)
#LOGGER = logging.getLogger(__name__)

class InMemoryObjectDatabase:
    def __init__(self) -> None:
@@ -29,12 +29,12 @@ class InMemoryObjectDatabase:
        return [container[entry_uuid] for entry_uuid in sorted(container.keys())]

    def has_entry(self, container_name : str, entry_uuid : str) -> Any:
        LOGGER.debug('[has_entry] BEFORE database={:s}'.format(str(self._database)))
        #LOGGER.debug('[has_entry] BEFORE database={:s}'.format(str(self._database)))
        container = self._get_container(container_name)
        return entry_uuid in container

    def get_entry(self, container_name : str, entry_uuid : str, context : grpc.ServicerContext) -> Any:
        LOGGER.debug('[get_entry] BEFORE database={:s}'.format(str(self._database)))
        #LOGGER.debug('[get_entry] BEFORE database={:s}'.format(str(self._database)))
        container = self._get_container(container_name)
        if entry_uuid not in container:
            MSG = '{:s}({:s}) not found; available({:s})'
@@ -44,18 +44,18 @@ class InMemoryObjectDatabase:

    def set_entry(self, container_name : str, entry_uuid : str, entry : Any) -> Any:
        container = self._get_container(container_name)
        LOGGER.debug('[set_entry] BEFORE database={:s}'.format(str(self._database)))
        #LOGGER.debug('[set_entry] BEFORE database={:s}'.format(str(self._database)))
        container[entry_uuid] = entry
        LOGGER.debug('[set_entry] AFTER database={:s}'.format(str(self._database)))
        #LOGGER.debug('[set_entry] AFTER database={:s}'.format(str(self._database)))
        return entry

    def del_entry(self, container_name : str, entry_uuid : str, context : grpc.ServicerContext) -> None:
        container = self._get_container(container_name)
        LOGGER.debug('[del_entry] BEFORE database={:s}'.format(str(self._database)))
        #LOGGER.debug('[del_entry] BEFORE database={:s}'.format(str(self._database)))
        if entry_uuid not in container:
            context.abort(grpc.StatusCode.NOT_FOUND, str('{:s}({:s}) not found'.format(container_name, entry_uuid)))
        del container[entry_uuid]
        LOGGER.debug('[del_entry] AFTER database={:s}'.format(str(self._database)))
        #LOGGER.debug('[del_entry] AFTER database={:s}'.format(str(self._database)))

    def select_entries(self, container_name : str, entry_uuids : Set[str]) -> List[Any]:
        if len(entry_uuids) == 0: return self.get_entries(container_name)
+2 −0
Changes for src/common/tools/descriptor/Tools.py: 2 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ def get_descriptors_add_contexts(contexts : List[Dict]) -> List[Dict]:
    for context in contexts_add:
        context['topology_ids'] = []
        context['service_ids'] = []
        context['slice_ids'] = []
    return contexts_add

def get_descriptors_add_topologies(topologies : List[Dict]) -> List[Dict]:
@@ -29,6 +30,7 @@ def get_descriptors_add_topologies(topologies : List[Dict]) -> List[Dict]:
    for topology in topologies_add:
        topology['device_ids'] = []
        topology['link_ids'] = []
        topology['optical_link_ids'] = []
    return topologies_add

def get_descriptors_add_services(services : List[Dict]) -> List[Dict]:
Loading
Loading