Commit 1ec240fd authored by Lluis Gifre Renom's avatar Lluis Gifre Renom
Browse files

Merge branch 'feat/301-cttc-dscm-pluggables' of...

Merge branch 'feat/301-cttc-dscm-pluggables' of ssh://gifrerenom_labs.etsi.org/tfs/controller into feat/306-cttc-enhanced-restconf-based-openconfig-nbi-for-dscm-pluggables
parents e68f69e4 44f8098e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ include:
  - local: '/src/ztp_server/.gitlab-ci.yml'
  - local: '/src/osm_client/.gitlab-ci.yml'
  - local: '/src/simap_connector/.gitlab-ci.yml'
  - local: '/src/pluggables/.gitlab-ci.yml'

  # This should be last one: end-to-end integration tests
  - local: '/src/tests/.gitlab-ci.yml'
+3 −3
Original line number Diff line number Diff line
@@ -28,9 +28,9 @@ ENV PYTHONUNBUFFERED=0
#     chmod +x /bin/grpc_health_probe

# Get generic Python packages
RUN python3 -m pip install --upgrade pip
RUN python3 -m pip install --upgrade setuptools wheel
RUN python3 -m pip install --upgrade pip-tools
RUN python3 -m pip install --upgrade 'pip==25.2'
RUN python3 -m pip install --upgrade 'setuptools==79.0.0' 'wheel==0.45.1'
RUN python3 -m pip install --upgrade 'pip-tools==7.3.0'

# Get common Python packages
# Note: this step enables sharing the previous Docker build steps among all the Python components
+8 −8
Original line number Diff line number Diff line
@@ -28,9 +28,9 @@ RUN GRPC_HEALTH_PROBE_VERSION=v0.2.0 && \
    chmod +x /bin/grpc_health_probe

# Get generic Python packages
RUN python3 -m pip install --upgrade pip
RUN python3 -m pip install --upgrade setuptools wheel
RUN python3 -m pip install --upgrade pip-tools
RUN python3 -m pip install --upgrade 'pip==25.2'
RUN python3 -m pip install --upgrade 'setuptools==79.0.0' 'wheel==0.45.1'
RUN python3 -m pip install --upgrade 'pip-tools==7.3.0'

# Get common Python packages
# Note: this step enables sharing the previous Docker build steps among all the Python components
@@ -54,15 +54,15 @@ RUN rm *.proto
RUN find . -type f -exec sed -i -E 's/^(import\ .*)_pb2/from . \1_pb2/g' {} \;

# Create component sub-folders, get specific Python packages
RUN mkdir -p /var/teraflow/dscm
WORKDIR /var/teraflow/dscm
COPY src/dscm/requirements.in requirements.in
RUN mkdir -p /var/teraflow/pluggables
WORKDIR /var/teraflow/pluggables
COPY src/pluggables/requirements.in requirements.in
RUN pip-compile --quiet --output-file=requirements.txt requirements.in
RUN python3 -m pip install -r requirements.txt

# Add component files into working directory
WORKDIR /var/teraflow
COPY src/dscm/. dscm/
COPY src/pluggables/. pluggables/

# # Start the service
ENTRYPOINT [ "python", "-m", "dscm.service" ]
ENTRYPOINT [ "python", "-m", "pluggables.service" ]
+17 −18
Original line number Diff line number Diff line
@@ -12,14 +12,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import copy, logging, os, pytest
import logging, os, pytest
from typing import Union
from common.Constants import ServiceNameEnum
from common.Settings import (
    ENVVAR_SUFIX_SERVICE_HOST, ENVVAR_SUFIX_SERVICE_PORT_GRPC,
    get_env_var_name, get_service_port_grpc
)
from common.proto.context_pb2 import Device, DeviceId, Topology, Context
from common.proto.context_pb2 import DeviceId, Topology, Context
from common.tools.service.GenericGrpcService import GenericGrpcService
from common.tests.MockServicerImpl_Context import MockServicerImpl_Context
from common.proto.context_pb2_grpc import add_ContextServiceServicer_to_server
@@ -37,7 +37,7 @@ from pluggables.tests.CommonObjects import (
    CONTEXT_ID, CONTEXT, TOPOLOGY_ID, TOPOLOGY,
    get_device_hub_with_connect_rules, get_device_leaf_with_connect_rules
)
from common.tools.object_factory.Topology import json_topology


LOGGER = logging.getLogger(__name__)

@@ -47,14 +47,14 @@ MOCKSERVICE_PORT = 10000
# Configure service endpoints
CONTEXT_SERVICE_PORT = MOCKSERVICE_PORT + get_service_port_grpc(ServiceNameEnum.CONTEXT)
DEVICE_SERVICE_PORT = MOCKSERVICE_PORT + get_service_port_grpc(ServiceNameEnum.DEVICE)
DSCMPLUGGABLE_SERVICE_PORT = get_service_port_grpc(ServiceNameEnum.PLUGGABLES)
PLUGGABLE_SERVICE_PORT = get_service_port_grpc(ServiceNameEnum.PLUGGABLES)

os.environ[get_env_var_name(ServiceNameEnum.CONTEXT, ENVVAR_SUFIX_SERVICE_HOST)]         = str(LOCAL_HOST)
os.environ[get_env_var_name(ServiceNameEnum.CONTEXT, ENVVAR_SUFIX_SERVICE_PORT_GRPC)]    = str(CONTEXT_SERVICE_PORT)
os.environ[get_env_var_name(ServiceNameEnum.DEVICE, ENVVAR_SUFIX_SERVICE_HOST)]          = str(LOCAL_HOST)
os.environ[get_env_var_name(ServiceNameEnum.DEVICE, ENVVAR_SUFIX_SERVICE_PORT_GRPC)]     = str(DEVICE_SERVICE_PORT)
os.environ[get_env_var_name(ServiceNameEnum.PLUGGABLES, ENVVAR_SUFIX_SERVICE_HOST)]      = str(LOCAL_HOST)
os.environ[get_env_var_name(ServiceNameEnum.PLUGGABLES, ENVVAR_SUFIX_SERVICE_PORT_GRPC)] = str(DSCMPLUGGABLE_SERVICE_PORT)
os.environ[get_env_var_name(ServiceNameEnum.PLUGGABLES, ENVVAR_SUFIX_SERVICE_PORT_GRPC)] = str(PLUGGABLE_SERVICE_PORT)


class MockContextService(GenericGrpcService):
@@ -167,4 +167,3 @@ def test_prepare_environment(
    assert leaf_device_retrieved is not None
    assert leaf_device_retrieved.device_id.device_uuid.uuid == DEVICE_LEAF_UUID
    LOGGER.info(f'Verified Leaf device: {leaf_device_retrieved.name}')
+32 −31
Original line number Diff line number Diff line
@@ -25,16 +25,17 @@ from common.Settings import (
    get_env_var_name, get_service_port_grpc)
from common.tests.MockServicerImpl_Context import MockServicerImpl_Context
from common.proto.context_pb2_grpc import add_ContextServiceServicer_to_server

from common.proto.pluggables_pb2 import (PluggableId, Pluggable, 
    CreatePluggableRequest, ListPluggablesRequest, ListPluggablesResponse, View)
from common.proto.pluggables_pb2 import (
    PluggableId, Pluggable, ListPluggablesResponse, View
)
from common.tools.service.GenericGrpcService import GenericGrpcService

from pluggables.client.PluggablesClient import PluggablesClient
from pluggables.service.PluggablesService import PluggablesService
from pluggables.tests.testmessages import (create_pluggable_request,
    create_list_pluggables_request,  create_get_pluggable_request,
    create_delete_pluggable_request, create_configure_pluggable_request)
from pluggables.tests.testmessages import (
    create_pluggable_request, create_list_pluggables_request,
    create_get_pluggable_request, create_delete_pluggable_request,
    create_configure_pluggable_request,
)


###########################
@@ -63,21 +64,21 @@ class MockContextService(GenericGrpcService):
# This fixture will be requested by test cases and last during testing session
@pytest.fixture(scope='session')
def pluggables_service():
    LOGGER.info('Initializing DscmPluggableService...')
    LOGGER.info('Initializing PluggableService...')
    _service = PluggablesService()
    _service.start()

    # yield the server, when test finishes, execution will resume to stop it
    LOGGER.info('Yielding DscmPluggableService...')
    LOGGER.info('Yielding PluggableService...')
    yield _service

    LOGGER.info('Terminating DscmPluggableService...')
    LOGGER.info('Terminating PluggableService...')
    _service.stop()

    LOGGER.info('Terminated DscmPluggableService...')
    LOGGER.info('Terminated PluggableService...')

@pytest.fixture(scope='function')
def dscm_pluggable_client(pluggables_service : PluggablesService):
def pluggable_client(pluggables_service : PluggablesService):
    LOGGER.info('Creating PluggablesClient...')
    _client = PluggablesClient()

@@ -104,10 +105,10 @@ def log_all_methods(request):
###########################

# CreatePluggable Test without configuration
def test_CreatePluggable(dscm_pluggable_client : PluggablesClient):
def test_CreatePluggable(pluggable_client : PluggablesClient):
    LOGGER.info('Creating Pluggable for test...')
    _pluggable_request = create_pluggable_request(preferred_pluggable_index=-1)
    _pluggable         = dscm_pluggable_client.CreatePluggable(_pluggable_request)
    _pluggable         = pluggable_client.CreatePluggable(_pluggable_request)
    LOGGER.info('Created Pluggable for test: %s', _pluggable)
    assert isinstance(_pluggable, Pluggable)
    assert _pluggable.id.pluggable_index         == _pluggable_request.preferred_pluggable_index
@@ -115,13 +116,13 @@ def test_CreatePluggable(dscm_pluggable_client : PluggablesClient):


# CreatePluggable Test with configuration
def test_CreatePluggable_with_config(dscm_pluggable_client : PluggablesClient):
def test_CreatePluggable_with_config(pluggable_client : PluggablesClient):
    LOGGER.info('Creating Pluggable with initial configuration for test...')
    _pluggable_request = create_pluggable_request(
                            device_uuid               = "9bbf1937-db9e-45bc-b2c6-3214a9d42157",
                            preferred_pluggable_index = -1,
                            with_initial_config       = True)
    _pluggable         = dscm_pluggable_client.CreatePluggable(_pluggable_request)
    _pluggable         = pluggable_client.CreatePluggable(_pluggable_request)
    LOGGER.info('Created Pluggable with initial configuration for test: %s', _pluggable)
    assert isinstance(_pluggable, Pluggable)
    assert _pluggable.id.pluggable_index         == _pluggable_request.preferred_pluggable_index
@@ -133,26 +134,26 @@ def test_CreatePluggable_with_config(dscm_pluggable_client : PluggablesClient):
    assert len(dsc_group.subcarriers) == 2

# create pluggable request with pluggable key already exists error
def test_CreatePluggable_already_exists(dscm_pluggable_client : PluggablesClient):
def test_CreatePluggable_already_exists(pluggable_client : PluggablesClient):
    LOGGER.info('Creating Pluggable for test...')
    _pluggable_request = create_pluggable_request(preferred_pluggable_index=5)
    _pluggable         = dscm_pluggable_client.CreatePluggable(_pluggable_request)
    _pluggable         = pluggable_client.CreatePluggable(_pluggable_request)
    LOGGER.info('Created Pluggable for test: %s', _pluggable)
    assert isinstance(_pluggable, Pluggable)
    assert _pluggable.id.pluggable_index         == _pluggable_request.preferred_pluggable_index
    assert _pluggable.id.device.device_uuid.uuid == _pluggable_request.device.device_uuid.uuid
    # Try to create the same pluggable again, should raise ALREADY_EXISTS
    with pytest.raises(grpc.RpcError) as e:
        dscm_pluggable_client.CreatePluggable(_pluggable_request)
        pluggable_client.CreatePluggable(_pluggable_request)
    assert e.value.code() == grpc.StatusCode.ALREADY_EXISTS

# ListPluggables Test
def test_ListPluggables(dscm_pluggable_client : PluggablesClient):
def test_ListPluggables(pluggable_client : PluggablesClient):
    LOGGER.info('Listing Pluggables for test...')
    _list_request = create_list_pluggables_request(
                        view_level = View.VIEW_CONFIG       # View.VIEW_STATE
    )
    _pluggables   = dscm_pluggable_client.ListPluggables(_list_request)
    _pluggables   = pluggable_client.ListPluggables(_list_request)
    LOGGER.info('Listed Pluggables for test: %s', _pluggables)
    assert isinstance(_pluggables, ListPluggablesResponse)
    if len(_pluggables.pluggables) != 0:
@@ -164,12 +165,12 @@ def test_ListPluggables(dscm_pluggable_client : PluggablesClient):
        assert len(_pluggables.pluggables) == 0

# GetPluggable Test
def test_GetPluggable(dscm_pluggable_client : PluggablesClient):
def test_GetPluggable(pluggable_client : PluggablesClient):
    LOGGER.info('Starting GetPluggable test...')
    LOGGER.info('Getting Pluggable for test...')
    # First create a pluggable to get it later
    _pluggable_request = create_pluggable_request(preferred_pluggable_index=1)
    _created_pluggable = dscm_pluggable_client.CreatePluggable(_pluggable_request)
    _created_pluggable = pluggable_client.CreatePluggable(_pluggable_request)
    LOGGER.info('Created Pluggable for GetPluggable test: %s', _created_pluggable)

    _get_request = create_get_pluggable_request(
@@ -177,7 +178,7 @@ def test_GetPluggable(dscm_pluggable_client : PluggablesClient):
                        pluggable_index   = _created_pluggable.id.pluggable_index,
                        view_level        = View.VIEW_FULL
    )
    _pluggable   = dscm_pluggable_client.GetPluggable(_get_request)
    _pluggable   = pluggable_client.GetPluggable(_get_request)
    LOGGER.info('Got Pluggable for test: %s', _pluggable)
    assert isinstance(_pluggable, Pluggable)
    assert _pluggable.id.pluggable_index         == _created_pluggable.id.pluggable_index
@@ -185,26 +186,26 @@ def test_GetPluggable(dscm_pluggable_client : PluggablesClient):


# DeletePluggable Test
def test_DeletePluggable(dscm_pluggable_client : PluggablesClient):
def test_DeletePluggable(pluggable_client : PluggablesClient):
    LOGGER.info('Starting DeletePluggable test...')
    LOGGER.info('Creating Pluggable to delete for test...')

    # First create a pluggable to delete it later
    _pluggable_request = create_pluggable_request(preferred_pluggable_index=2)
    _created_pluggable = dscm_pluggable_client.CreatePluggable(_pluggable_request)
    _created_pluggable = pluggable_client.CreatePluggable(_pluggable_request)
    LOGGER.info('Created Pluggable to delete for test: %s', _created_pluggable)

    _delete_request = create_delete_pluggable_request(
                        device_uuid       = _created_pluggable.id.device.device_uuid.uuid,
                        pluggable_index   = _created_pluggable.id.pluggable_index
    )
    _response       = dscm_pluggable_client.DeletePluggable(_delete_request)
    _response       = pluggable_client.DeletePluggable(_delete_request)
    LOGGER.info('Deleted Pluggable for test, response: %s', _response)
    assert isinstance(_response, Empty)

    # Try to get the deleted pluggable, should raise NOT_FOUND
    with pytest.raises(grpc.RpcError) as e:
        dscm_pluggable_client.GetPluggable(
        pluggable_client.GetPluggable(
            create_get_pluggable_request(
                device_uuid     = _created_pluggable.id.device.device_uuid.uuid,
                pluggable_index = _created_pluggable.id.pluggable_index
@@ -213,20 +214,20 @@ def test_DeletePluggable(dscm_pluggable_client : PluggablesClient):
    assert e.value.code() == grpc.StatusCode.NOT_FOUND

# ConfigurePluggable Test
def test_ConfigurePluggable(dscm_pluggable_client : PluggablesClient):
def test_ConfigurePluggable(pluggable_client : PluggablesClient):
    LOGGER.info('Starting ConfigurePluggable test...')
    LOGGER.info('Creating Pluggable to configure for test...')

    # First create a pluggable to configure it later
    _pluggable_request = create_pluggable_request(preferred_pluggable_index=3)
    _created_pluggable = dscm_pluggable_client.CreatePluggable(_pluggable_request)
    _created_pluggable = pluggable_client.CreatePluggable(_pluggable_request)
    LOGGER.info('Created Pluggable to configure for test: %s', _created_pluggable)

    _configure_request = create_configure_pluggable_request(
                            device_uuid       = _created_pluggable.id.device.device_uuid.uuid,
                            pluggable_index   = _created_pluggable.id.pluggable_index,
    )
    _pluggable         = dscm_pluggable_client.ConfigurePluggable(_configure_request)
    _pluggable         = pluggable_client.ConfigurePluggable(_configure_request)
    LOGGER.info('Configured Pluggable for test: %s', _pluggable)
    assert isinstance(_pluggable, Pluggable)
    assert _pluggable.config is not None
Loading