Commit 2844313e authored by Lluis Gifre Renom's avatar Lluis Gifre Renom
Browse files

NBI component - IETF Network plugin:

- Implemented skeleton of plugin
- Added test scenario
- Added new requirements
- Extended MockContext to properly link/unlink topologies, services and slices to contexts
parent daed600d
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -20,5 +20,8 @@ cd $PROJECTDIR/src
RCFILE=$PROJECTDIR/coverage/.coveragerc

# Run unitary tests and analyze coverage of code at same time
#coverage run --rcfile=$RCFILE --append -m pytest --log-level=INFO --verbose \
#    nbi/tests/test_unitary.py

coverage run --rcfile=$RCFILE --append -m pytest --log-level=INFO --verbose \
    nbi/tests/test_unitary.py
    nbi/tests/test_ietf_network.py
+57 −6
Original line number Diff line number Diff line
@@ -143,17 +143,34 @@ class MockServicerImpl_Context(ContextServiceServicer):

    def SetTopology(self, request: Topology, context : grpc.ServicerContext) -> TopologyId:
        LOGGER.debug('[SetTopology] request={:s}'.format(grpc_message_to_json_string(request)))
        container_name = 'topology[{:s}]'.format(str(request.topology_id.context_id.context_uuid.uuid))
        context_uuid = str(request.topology_id.context_id.context_uuid.uuid)
        container_name = 'topology[{:s}]'.format(context_uuid)
        topology_uuid = request.topology_id.topology_uuid.uuid
        reply,_ = self._set(request, container_name, topology_uuid, 'topology_id', TOPIC_TOPOLOGY)

        context_ = self.obj_db.get_entry('context', context_uuid, context)
        for _topology_id in context_.topology_ids:
            if _topology_id.topology_uuid.uuid == topology_uuid: break
        else:
            # topology not found, add it
            context_.topology_ids.add().topology_uuid.uuid = topology_uuid

        LOGGER.debug('[SetTopology] reply={:s}'.format(grpc_message_to_json_string(reply)))
        return reply

    def RemoveTopology(self, request: TopologyId, context : grpc.ServicerContext) -> Empty:
        LOGGER.debug('[RemoveTopology] request={:s}'.format(grpc_message_to_json_string(request)))
        container_name = 'topology[{:s}]'.format(str(request.context_id.context_uuid.uuid))
        context_uuid = str(request.context_id.context_uuid.uuid)
        container_name = 'topology[{:s}]'.format(context_uuid)
        topology_uuid = request.topology_uuid.uuid
        reply = self._del(request, container_name, topology_uuid, 'topology_id', TOPIC_TOPOLOGY, context)

        context_ = self.obj_db.get_entry('context', context_uuid, context)
        for _topology_id in context_.topology_ids:
            if _topology_id.topology_uuid.uuid == topology_uuid:
                context_.topology_ids.remove(_topology_id)
                break

        LOGGER.debug('[RemoveTopology] reply={:s}'.format(grpc_message_to_json_string(reply)))
        return reply

@@ -368,17 +385,34 @@ class MockServicerImpl_Context(ContextServiceServicer):

    def SetSlice(self, request: Slice, context : grpc.ServicerContext) -> SliceId:
        LOGGER.debug('[SetSlice] request={:s}'.format(grpc_message_to_json_string(request)))
        container_name = 'slice[{:s}]'.format(str(request.slice_id.context_id.context_uuid.uuid))
        context_uuid = str(request.slice_id.context_id.context_uuid.uuid)
        container_name = 'slice[{:s}]'.format(context_uuid)
        slice_uuid = request.slice_id.slice_uuid.uuid
        reply,_ = self._set(request, container_name, slice_uuid, 'slice_id', TOPIC_SLICE)

        context_ = self.obj_db.get_entry('context', context_uuid, context)
        for _slice_id in context_.slice_ids:
            if _slice_id.slice_uuid.uuid == slice_uuid: break
        else:
            # slice not found, add it
            context_.slice_ids.add().slice_uuid.uuid = slice_uuid

        LOGGER.debug('[SetSlice] reply={:s}'.format(grpc_message_to_json_string(reply)))
        return reply

    def RemoveSlice(self, request: SliceId, context : grpc.ServicerContext) -> Empty:
        LOGGER.debug('[RemoveSlice] request={:s}'.format(grpc_message_to_json_string(request)))
        container_name = 'slice[{:s}]'.format(str(request.context_id.context_uuid.uuid))
        context_uuid = str(request.slice_id.context_id.context_uuid.uuid)
        container_name = 'slice[{:s}]'.format(context_uuid)
        slice_uuid = request.slice_uuid.uuid
        reply = self._del(request, container_name, slice_uuid, 'slice_id', TOPIC_SLICE, context)

        context_ = self.obj_db.get_entry('context', context_uuid, context)
        for _slice_id in context_.slice_ids:
            if _slice_id.slice_uuid.uuid == slice_uuid:
                context_.slice_ids.remove(_slice_id)
                break

        LOGGER.debug('[RemoveSlice] reply={:s}'.format(grpc_message_to_json_string(reply)))
        return reply

@@ -443,17 +477,34 @@ class MockServicerImpl_Context(ContextServiceServicer):

    def SetService(self, request: Service, context : grpc.ServicerContext) -> ServiceId:
        LOGGER.debug('[SetService] request={:s}'.format(grpc_message_to_json_string(request)))
        container_name = 'service[{:s}]'.format(str(request.service_id.context_id.context_uuid.uuid))
        context_uuid = str(request.service_id.context_id.context_uuid.uuid)
        container_name = 'service[{:s}]'.format(context_uuid)
        service_uuid = request.service_id.service_uuid.uuid
        reply,_ = self._set(request, container_name, service_uuid, 'service_id', TOPIC_SERVICE)

        context_ = self.obj_db.get_entry('context', context_uuid, context)
        for _service_id in context_.service_ids:
            if _service_id.service_uuid.uuid == service_uuid: break
        else:
            # service not found, add it
            context_.service_ids.add().service_uuid.uuid = service_uuid

        LOGGER.debug('[SetService] reply={:s}'.format(grpc_message_to_json_string(reply)))
        return reply

    def RemoveService(self, request: ServiceId, context : grpc.ServicerContext) -> Empty:
        LOGGER.debug('[RemoveService] request={:s}'.format(grpc_message_to_json_string(request)))
        container_name = 'service[{:s}]'.format(str(request.context_id.context_uuid.uuid))
        context_uuid = str(request.service_id.context_id.context_uuid.uuid)
        container_name = 'service[{:s}]'.format(context_uuid)
        service_uuid = request.service_uuid.uuid
        reply = self._del(request, container_name, service_uuid, 'service_id', TOPIC_SERVICE, context)

        context_ = self.obj_db.get_entry('context', context_uuid, context)
        for _service_id in context_.service_ids:
            if _service_id.service_uuid.uuid == service_uuid:
                context_.service_ids.remove(_service_id)
                break

        LOGGER.debug('[RemoveService] reply={:s}'.format(grpc_message_to_json_string(reply)))
        return reply

+1 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

deepdiff==6.7.*
Flask==2.1.3
Flask-HTTPAuth==4.5.0
Flask-RESTful==0.3.9
+2 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ from .rest_server.RestServer import RestServer
from .rest_server.nbi_plugins.debug_api import register_debug_api
from .rest_server.nbi_plugins.etsi_bwm import register_etsi_bwm_api
from .rest_server.nbi_plugins.ietf_l2vpn import register_ietf_l2vpn
from .rest_server.nbi_plugins.ietf_network import register_ietf_network
from .rest_server.nbi_plugins.ietf_network_slice import register_ietf_nss

terminate = threading.Event()
@@ -63,6 +64,7 @@ def main():
    register_debug_api(rest_server)
    register_etsi_bwm_api(rest_server)
    register_ietf_l2vpn(rest_server)  # Registering L2VPN entrypoint
    register_ietf_network(rest_server)
    register_ietf_nss(rest_server)  # Registering NSS entrypoint
    rest_server.start()

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

PROVIDER_ID = 10
CLIENT_ID = 0
Loading