From b90319814d0b7f957478c78b0b50215e0ac2405f Mon Sep 17 00:00:00 2001 From: Lluis Gifre Date: Wed, 20 Oct 2021 19:52:24 +0200 Subject: [PATCH] Several changes: Common: - added ORM helper function get_related_instances - minor modifications in ORM framework Proto: - field/message/enum renamings in context.proto to normalize notation Context: - Expanded service/database/Models.py into separate models to facilitate coding - Completed implementation of Get/Set/List/Remove methods for Context, Topology, Device, Link, and EndPoint; also completed for relation models between topology and device/link, and ConfigModels - Implemented test units for Get/Set/List/Remove methods for Context, Topology, Device, Link, and EndPoint - Implemented skeleton for Get/Set/List/Remove methods for Service. - Added Tools.py with helper methods to fimplify handling of enums between ORM and gRPC messages. --- proto/context.proto | 35 +- src/common/orm/backend/Tools.py | 4 +- src/common/orm/model/Model.py | 17 +- src/context/proto/context_pb2.py | 236 +++---- src/context/service/database/ConfigModel.py | 56 ++ src/context/service/database/ContextModel.py | 30 + src/context/service/database/DeviceModel.py | 75 +++ src/context/service/database/EndPointModel.py | 33 + src/context/service/database/LinkModel.py | 24 + src/context/service/database/Models.py | 95 --- .../service/database/RelationModels.py | 18 + src/context/service/database/ServiceModel.py | 65 ++ src/context/service/database/Tools.py | 33 + src/context/service/database/TopologyModel.py | 39 ++ .../grpc_server/ContextServiceServicerImpl.py | 321 +++++++++- src/context/tests/test_unitary.py | 606 ++++++++++++------ 16 files changed, 1221 insertions(+), 466 deletions(-) create mode 100644 src/context/service/database/ConfigModel.py create mode 100644 src/context/service/database/ContextModel.py create mode 100644 src/context/service/database/DeviceModel.py create mode 100644 src/context/service/database/EndPointModel.py create mode 100644 src/context/service/database/LinkModel.py delete mode 100644 src/context/service/database/Models.py create mode 100644 src/context/service/database/RelationModels.py create mode 100644 src/context/service/database/ServiceModel.py create mode 100644 src/context/service/database/Tools.py create mode 100644 src/context/service/database/TopologyModel.py diff --git a/proto/context.proto b/proto/context.proto index fd7580e52..251326c80 100644 --- a/proto/context.proto +++ b/proto/context.proto @@ -118,9 +118,9 @@ message Device { DeviceId device_id = 1; string device_type = 2; DeviceConfig device_config = 3; - DeviceOperationalStatus devive_operational_status = 4; + DeviceOperationalStatusEnum device_operational_status = 4; repeated DeviceDriverEnum device_drivers = 5; - repeated EndPoint endpoints = 6; + repeated EndPoint device_endpoints = 6; } message DeviceConfig { @@ -136,10 +136,10 @@ enum DeviceDriverEnum { DEVICEDRIVER_ONF_TR_352 = 5; } -enum DeviceOperationalStatus { - UNDEFINED = 0; - DISABLED = 1; - ENABLED = 2; +enum DeviceOperationalStatusEnum { + DEVICEOPERATIONALSTATUS_UNDEFINED = 0; + DEVICEOPERATIONALSTATUS_DISABLED = 1; + DEVICEOPERATIONALSTATUS_ENABLED = 2; } message DeviceIdList { @@ -163,7 +163,7 @@ message LinkId { message Link { LinkId link_id = 1; - repeated EndPointId endpoint_ids = 2; + repeated EndPointId link_endpoint_ids = 2; } message LinkIdList { @@ -189,9 +189,9 @@ message ServiceId { message Service { ServiceId service_id = 1; ServiceTypeEnum service_type = 2; - repeated EndPointId endpoint_ids = 3; - repeated Constraint constraints = 4; - ServiceState service_state = 5; + repeated EndPointId service_endpoint_ids = 3; + repeated Constraint service_constraints = 4; + ServiceStatus service_status = 5; ServiceConfig service_config = 6; } @@ -202,14 +202,15 @@ enum ServiceTypeEnum { SERVICETYPE_TAPI_CONNECTIVITY_SERVICE = 3; } -enum ServiceStateEnum { - SERVICESTATUS_PLANNED = 0; - SERVICESTATUS_ACTIVE = 1; - SERVICESTATUS_PENDING_REMOVAL = 2; +enum ServiceStatusEnum { + SERVICESTATUS_UNDEFINED = 0; + SERVICESTATUS_PLANNED = 1; + SERVICESTATUS_ACTIVE = 2; + SERVICESTATUS_PENDING_REMOVAL = 3; } -message ServiceState { - ServiceStateEnum service_state = 1; +message ServiceStatus { + ServiceStatusEnum service_status = 1; } message ServiceConfig { @@ -239,7 +240,7 @@ message EndPointId { message EndPoint { EndPointId endpoint_id = 1; - string port_type = 2; + string endpoint_type = 2; } diff --git a/src/common/orm/backend/Tools.py b/src/common/orm/backend/Tools.py index bc24bbf36..8152e1a76 100644 --- a/src/common/orm/backend/Tools.py +++ b/src/common/orm/backend/Tools.py @@ -1,5 +1,5 @@ from typing import List, Union -def key_to_str(key : Union[str, List[str]]) -> str: +def key_to_str(key : Union[str, List[str]], separator : str = '/') -> str: if isinstance(key, str): return key - return '/'.join(map(str, key)) + return separator.join(map(str, key)) diff --git a/src/common/orm/model/Model.py b/src/common/orm/model/Model.py index 65ae9dc67..396e9e524 100644 --- a/src/common/orm/model/Model.py +++ b/src/common/orm/model/Model.py @@ -4,7 +4,6 @@ from typing import Any, Dict, List, Mapping, Optional, Set, Tuple, Union from common.orm.Database import Database from common.orm.backend.Tools import key_to_str from common.orm.fields.ForeignKeyField import ForeignKeyField -from common.type_checkers.Checkers import chk_issubclass from ..Exceptions import ConstraintException, MutexException from ..fields.Field import Field from ..fields.PrimaryKeyField import PrimaryKeyField @@ -291,3 +290,19 @@ class Model(metaclass=MetaModel): for name in self._field_names_list # pylint: disable=no-member ) return '{:s}({:s})'.format(self._class_name, arguments) + +def get_related_instances( + source_instance : Model, relation_model_class : MetaModel, relation_field_name : str) -> Set[Model]: + navigation_fk_field : ForeignKeyField = getattr(relation_model_class, relation_field_name, None) + if navigation_fk_field is None or not isinstance(navigation_fk_field, ForeignKeyField): + msg = 'relation_field_name({:s}) must be a ForeignKeyField in relation_model_class({:s})' + raise AttributeError(msg.format(relation_field_name, relation_model_class.__name__)) + target_model_class = navigation_fk_field.foreign_model + database = source_instance.database + db_target_instances = set() + for db_relation_pk,_ in source_instance.references(relation_model_class): + db_relation = relation_model_class(database, db_relation_pk) + target_fk_field = getattr(db_relation, relation_field_name, None) + if target_fk_field is None: continue + db_target_instances.add(target_model_class(database, target_fk_field)) + return db_target_instances diff --git a/src/context/proto/context_pb2.py b/src/context/proto/context_pb2.py index 7a0b096c5..8b4848bc3 100644 --- a/src/context/proto/context_pb2.py +++ b/src/context/proto/context_pb2.py @@ -20,7 +20,7 @@ DESCRIPTOR = _descriptor.FileDescriptor( 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\"\x8f\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\x12\x43\n\x19\x64\x65vive_operational_status\x18\x04 \x01(\x0e\x32 .context.DeviceOperationalStatus\x12\x31\n\x0e\x64\x65vice_drivers\x18\x05 \x03(\x0e\x32\x19.context.DeviceDriverEnum\x12$\n\tendpoints\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\"S\n\x04Link\x12 \n\x07link_id\x18\x01 \x01(\x0b\x32\x0f.context.LinkId\x12)\n\x0c\x65ndpoint_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\"\x94\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)\n\x0c\x65ndpoint_ids\x18\x03 \x03(\x0b\x32\x13.context.EndPointId\x12(\n\x0b\x63onstraints\x18\x04 \x03(\x0b\x32\x13.context.Constraint\x12,\n\rservice_state\x18\x05 \x01(\x0b\x32\x15.context.ServiceState\x12.\n\x0eservice_config\x18\x06 \x01(\x0b\x32\x16.context.ServiceConfig\"@\n\x0cServiceState\x12\x30\n\rservice_state\x18\x01 \x01(\x0e\x32\x19.context.ServiceStateEnum\":\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\"G\n\x08\x45ndPoint\x12(\n\x0b\x65ndpoint_id\x18\x01 \x01(\x0b\x32\x13.context.EndPointId\x12\x11\n\tport_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*C\n\x17\x44\x65viceOperationalStatus\x12\r\n\tUNDEFINED\x10\x00\x12\x0c\n\x08\x44ISABLED\x10\x01\x12\x0b\n\x07\x45NABLED\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*j\n\x10ServiceStateEnum\x12\x19\n\x15SERVICESTATUS_PLANNED\x10\x00\x12\x18\n\x14SERVICESTATUS_ACTIVE\x10\x01\x12!\n\x1dSERVICESTATUS_PENDING_REMOVAL\x10\x02*]\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' + 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( @@ -53,8 +53,8 @@ _EVENTTYPEENUM = _descriptor.EnumDescriptor( ], containing_type=None, serialized_options=None, - serialized_start=3427, - serialized_end=3533, + serialized_start=3468, + serialized_end=3574, ) _sym_db.RegisterEnumDescriptor(_EVENTTYPEENUM) @@ -99,43 +99,43 @@ _DEVICEDRIVERENUM = _descriptor.EnumDescriptor( ], containing_type=None, serialized_options=None, - serialized_start=3536, - serialized_end=3733, + serialized_start=3577, + serialized_end=3774, ) _sym_db.RegisterEnumDescriptor(_DEVICEDRIVERENUM) DeviceDriverEnum = enum_type_wrapper.EnumTypeWrapper(_DEVICEDRIVERENUM) -_DEVICEOPERATIONALSTATUS = _descriptor.EnumDescriptor( - name='DeviceOperationalStatus', - full_name='context.DeviceOperationalStatus', +_DEVICEOPERATIONALSTATUSENUM = _descriptor.EnumDescriptor( + name='DeviceOperationalStatusEnum', + full_name='context.DeviceOperationalStatusEnum', filename=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key, values=[ _descriptor.EnumValueDescriptor( - name='UNDEFINED', index=0, number=0, + name='DEVICEOPERATIONALSTATUS_UNDEFINED', index=0, number=0, serialized_options=None, type=None, create_key=_descriptor._internal_create_key), _descriptor.EnumValueDescriptor( - name='DISABLED', index=1, number=1, + name='DEVICEOPERATIONALSTATUS_DISABLED', index=1, number=1, serialized_options=None, type=None, create_key=_descriptor._internal_create_key), _descriptor.EnumValueDescriptor( - name='ENABLED', index=2, number=2, + 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=3735, - serialized_end=3802, + serialized_start=3777, + serialized_end=3920, ) -_sym_db.RegisterEnumDescriptor(_DEVICEOPERATIONALSTATUS) +_sym_db.RegisterEnumDescriptor(_DEVICEOPERATIONALSTATUSENUM) -DeviceOperationalStatus = enum_type_wrapper.EnumTypeWrapper(_DEVICEOPERATIONALSTATUS) +DeviceOperationalStatusEnum = enum_type_wrapper.EnumTypeWrapper(_DEVICEOPERATIONALSTATUSENUM) _SERVICETYPEENUM = _descriptor.EnumDescriptor( name='ServiceTypeEnum', full_name='context.ServiceTypeEnum', @@ -166,43 +166,48 @@ _SERVICETYPEENUM = _descriptor.EnumDescriptor( ], containing_type=None, serialized_options=None, - serialized_start=3805, - serialized_end=3934, + serialized_start=3923, + serialized_end=4052, ) _sym_db.RegisterEnumDescriptor(_SERVICETYPEENUM) ServiceTypeEnum = enum_type_wrapper.EnumTypeWrapper(_SERVICETYPEENUM) -_SERVICESTATEENUM = _descriptor.EnumDescriptor( - name='ServiceStateEnum', - full_name='context.ServiceStateEnum', +_SERVICESTATUSENUM = _descriptor.EnumDescriptor( + name='ServiceStatusEnum', + full_name='context.ServiceStatusEnum', filename=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key, values=[ _descriptor.EnumValueDescriptor( - name='SERVICESTATUS_PLANNED', index=0, number=0, + name='SERVICESTATUS_UNDEFINED', index=0, number=0, serialized_options=None, type=None, create_key=_descriptor._internal_create_key), _descriptor.EnumValueDescriptor( - name='SERVICESTATUS_ACTIVE', index=1, number=1, + name='SERVICESTATUS_PLANNED', index=1, number=1, serialized_options=None, type=None, create_key=_descriptor._internal_create_key), _descriptor.EnumValueDescriptor( - name='SERVICESTATUS_PENDING_REMOVAL', index=2, number=2, + 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=3936, - serialized_end=4042, + serialized_start=4055, + serialized_end=4191, ) -_sym_db.RegisterEnumDescriptor(_SERVICESTATEENUM) +_sym_db.RegisterEnumDescriptor(_SERVICESTATUSENUM) -ServiceStateEnum = enum_type_wrapper.EnumTypeWrapper(_SERVICESTATEENUM) +ServiceStatusEnum = enum_type_wrapper.EnumTypeWrapper(_SERVICESTATUSENUM) _CONFIGACTIONENUM = _descriptor.EnumDescriptor( name='ConfigActionEnum', full_name='context.ConfigActionEnum', @@ -228,8 +233,8 @@ _CONFIGACTIONENUM = _descriptor.EnumDescriptor( ], containing_type=None, serialized_options=None, - serialized_start=4044, - serialized_end=4137, + serialized_start=4193, + serialized_end=4286, ) _sym_db.RegisterEnumDescriptor(_CONFIGACTIONENUM) @@ -244,16 +249,17 @@ DEVICEDRIVER_TRANSPORT_API = 2 DEVICEDRIVER_P4 = 3 DEVICEDRIVER_IETF_NETWORK_TOPOLOGY = 4 DEVICEDRIVER_ONF_TR_352 = 5 -UNDEFINED = 0 -DISABLED = 1 -ENABLED = 2 +DEVICEOPERATIONALSTATUS_UNDEFINED = 0 +DEVICEOPERATIONALSTATUS_DISABLED = 1 +DEVICEOPERATIONALSTATUS_ENABLED = 2 SERVICETYPE_UNKNOWN = 0 SERVICETYPE_L3NM = 1 SERVICETYPE_L2NM = 2 SERVICETYPE_TAPI_CONNECTIVITY_SERVICE = 3 -SERVICESTATUS_PLANNED = 0 -SERVICESTATUS_ACTIVE = 1 -SERVICESTATUS_PENDING_REMOVAL = 2 +SERVICESTATUS_UNDEFINED = 0 +SERVICESTATUS_PLANNED = 1 +SERVICESTATUS_ACTIVE = 2 +SERVICESTATUS_PENDING_REMOVAL = 3 CONFIGACTION_UNDEFINED = 0 CONFIGACTION_SET = 1 CONFIGACTION_DELETE = 2 @@ -794,7 +800,7 @@ _DEVICE = _descriptor.Descriptor( is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='devive_operational_status', full_name='context.Device.devive_operational_status', index=3, + 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, @@ -808,7 +814,7 @@ _DEVICE = _descriptor.Descriptor( is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='endpoints', full_name='context.Device.endpoints', index=5, + 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, @@ -827,7 +833,7 @@ _DEVICE = _descriptor.Descriptor( oneofs=[ ], serialized_start=1035, - serialized_end=1306, + serialized_end=1317, ) @@ -858,8 +864,8 @@ _DEVICECONFIG = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=1308, - serialized_end=1365, + serialized_start=1319, + serialized_end=1376, ) @@ -890,8 +896,8 @@ _DEVICEIDLIST = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=1367, - serialized_end=1420, + serialized_start=1378, + serialized_end=1431, ) @@ -922,8 +928,8 @@ _DEVICELIST = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=1422, - serialized_end=1468, + serialized_start=1433, + serialized_end=1479, ) @@ -961,8 +967,8 @@ _DEVICEEVENT = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=1470, - serialized_end=1552, + serialized_start=1481, + serialized_end=1563, ) @@ -993,8 +999,8 @@ _LINKID = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=1554, - serialized_end=1596, + serialized_start=1565, + serialized_end=1607, ) @@ -1014,7 +1020,7 @@ _LINK = _descriptor.Descriptor( is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='endpoint_ids', full_name='context.Link.endpoint_ids', index=1, + 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, @@ -1032,8 +1038,8 @@ _LINK = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=1598, - serialized_end=1681, + serialized_start=1609, + serialized_end=1697, ) @@ -1064,8 +1070,8 @@ _LINKIDLIST = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=1683, - serialized_end=1730, + serialized_start=1699, + serialized_end=1746, ) @@ -1096,8 +1102,8 @@ _LINKLIST = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=1732, - serialized_end=1772, + serialized_start=1748, + serialized_end=1788, ) @@ -1135,8 +1141,8 @@ _LINKEVENT = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=1774, - serialized_end=1850, + serialized_start=1790, + serialized_end=1866, ) @@ -1174,8 +1180,8 @@ _SERVICEID = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=1852, - serialized_end=1940, + serialized_start=1868, + serialized_end=1956, ) @@ -1202,21 +1208,21 @@ _SERVICE = _descriptor.Descriptor( is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='endpoint_ids', full_name='context.Service.endpoint_ids', index=2, + 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='constraints', full_name='context.Service.constraints', index=3, + 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_state', full_name='context.Service.service_state', index=4, + 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, @@ -1241,21 +1247,21 @@ _SERVICE = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=1943, - serialized_end=2219, + serialized_start=1959, + serialized_end=2253, ) -_SERVICESTATE = _descriptor.Descriptor( - name='ServiceState', - full_name='context.ServiceState', +_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_state', full_name='context.ServiceState.service_state', index=0, + 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, @@ -1273,8 +1279,8 @@ _SERVICESTATE = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=2221, - serialized_end=2285, + serialized_start=2255, + serialized_end=2322, ) @@ -1305,8 +1311,8 @@ _SERVICECONFIG = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=2287, - serialized_end=2345, + serialized_start=2324, + serialized_end=2382, ) @@ -1337,8 +1343,8 @@ _SERVICEIDLIST = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=2347, - serialized_end=2403, + serialized_start=2384, + serialized_end=2440, ) @@ -1369,8 +1375,8 @@ _SERVICELIST = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=2405, - serialized_end=2454, + serialized_start=2442, + serialized_end=2491, ) @@ -1408,8 +1414,8 @@ _SERVICEEVENT = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=2456, - serialized_end=2541, + serialized_start=2493, + serialized_end=2578, ) @@ -1454,8 +1460,8 @@ _ENDPOINTID = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=2544, - serialized_end=2674, + serialized_start=2581, + serialized_end=2711, ) @@ -1475,7 +1481,7 @@ _ENDPOINT = _descriptor.Descriptor( is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='port_type', full_name='context.EndPoint.port_type', index=1, + 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, @@ -1493,8 +1499,8 @@ _ENDPOINT = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=2676, - serialized_end=2747, + serialized_start=2713, + serialized_end=2788, ) @@ -1539,8 +1545,8 @@ _CONFIGRULE = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=2749, - serialized_end=2850, + serialized_start=2790, + serialized_end=2891, ) @@ -1578,8 +1584,8 @@ _CONSTRAINT = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=2852, - serialized_end=2915, + serialized_start=2893, + serialized_end=2956, ) @@ -1610,8 +1616,8 @@ _CONNECTIONID = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=2917, - serialized_end=2971, + serialized_start=2958, + serialized_end=3012, ) @@ -1656,8 +1662,8 @@ _CONNECTION = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=2974, - serialized_end=3115, + serialized_start=3015, + serialized_end=3156, ) @@ -1688,8 +1694,8 @@ _CONNECTIONIDLIST = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=3117, - serialized_end=3182, + serialized_start=3158, + serialized_end=3223, ) @@ -1720,8 +1726,8 @@ _CONNECTIONLIST = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=3184, - serialized_end=3242, + serialized_start=3225, + serialized_end=3283, ) @@ -1766,8 +1772,8 @@ _TERAFLOWCONTROLLER = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=3244, - serialized_end=3338, + serialized_start=3285, + serialized_end=3379, ) @@ -1805,8 +1811,8 @@ _AUTHENTICATIONRESULT = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=3340, - serialized_end=3425, + serialized_start=3381, + serialized_end=3466, ) _EVENT.fields_by_name['event_type'].enum_type = _EVENTTYPEENUM @@ -1831,9 +1837,9 @@ _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['devive_operational_status'].enum_type = _DEVICEOPERATIONALSTATUS +_DEVICE.fields_by_name['device_operational_status'].enum_type = _DEVICEOPERATIONALSTATUSENUM _DEVICE.fields_by_name['device_drivers'].enum_type = _DEVICEDRIVERENUM -_DEVICE.fields_by_name['endpoints'].message_type = _ENDPOINT +_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 @@ -1841,7 +1847,7 @@ _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['endpoint_ids'].message_type = _ENDPOINTID +_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 @@ -1850,11 +1856,11 @@ _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['endpoint_ids'].message_type = _ENDPOINTID -_SERVICE.fields_by_name['constraints'].message_type = _CONSTRAINT -_SERVICE.fields_by_name['service_state'].message_type = _SERVICESTATE +_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 -_SERVICESTATE.fields_by_name['service_state'].enum_type = _SERVICESTATEENUM +_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 @@ -1899,7 +1905,7 @@ 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['ServiceState'] = _SERVICESTATE +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 @@ -1916,9 +1922,9 @@ 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['DeviceOperationalStatus'] = _DEVICEOPERATIONALSTATUS +DESCRIPTOR.enum_types_by_name['DeviceOperationalStatusEnum'] = _DEVICEOPERATIONALSTATUSENUM DESCRIPTOR.enum_types_by_name['ServiceTypeEnum'] = _SERVICETYPEENUM -DESCRIPTOR.enum_types_by_name['ServiceStateEnum'] = _SERVICESTATEENUM +DESCRIPTOR.enum_types_by_name['ServiceStatusEnum'] = _SERVICESTATUSENUM DESCRIPTOR.enum_types_by_name['ConfigActionEnum'] = _CONFIGACTIONENUM _sym_db.RegisterFileDescriptor(DESCRIPTOR) @@ -2104,12 +2110,12 @@ Service = _reflection.GeneratedProtocolMessageType('Service', (_message.Message, }) _sym_db.RegisterMessage(Service) -ServiceState = _reflection.GeneratedProtocolMessageType('ServiceState', (_message.Message,), { - 'DESCRIPTOR' : _SERVICESTATE, +ServiceStatus = _reflection.GeneratedProtocolMessageType('ServiceStatus', (_message.Message,), { + 'DESCRIPTOR' : _SERVICESTATUS, '__module__' : 'context_pb2' - # @@protoc_insertion_point(class_scope:context.ServiceState) + # @@protoc_insertion_point(class_scope:context.ServiceStatus) }) -_sym_db.RegisterMessage(ServiceState) +_sym_db.RegisterMessage(ServiceStatus) ServiceConfig = _reflection.GeneratedProtocolMessageType('ServiceConfig', (_message.Message,), { 'DESCRIPTOR' : _SERVICECONFIG, @@ -2218,8 +2224,8 @@ _CONTEXTSERVICE = _descriptor.ServiceDescriptor( index=0, serialized_options=None, create_key=_descriptor._internal_create_key, - serialized_start=4140, - serialized_end=5841, + serialized_start=4289, + serialized_end=5990, methods=[ _descriptor.MethodDescriptor( name='ListContextIds', diff --git a/src/context/service/database/ConfigModel.py b/src/context/service/database/ConfigModel.py new file mode 100644 index 000000000..783d1cf17 --- /dev/null +++ b/src/context/service/database/ConfigModel.py @@ -0,0 +1,56 @@ +import functools, hashlib, logging, operator +from enum import Enum +from typing import Dict, List +from common.orm.fields.EnumeratedField import EnumeratedField +from common.orm.fields.ForeignKeyField import ForeignKeyField +from common.orm.fields.IntegerField import IntegerField +from common.orm.fields.PrimaryKeyField import PrimaryKeyField +from common.orm.fields.StringField import StringField +from common.orm.model.Model import Model +from context.proto.context_pb2 import ConfigActionEnum +from context.service.database.Tools import grpc_to_enum + +LOGGER = logging.getLogger(__name__) + +class ORM_ConfigActionEnum(Enum): + UNDEFINED = ConfigActionEnum.CONFIGACTION_UNDEFINED + SET = ConfigActionEnum.CONFIGACTION_SET + DELETE = ConfigActionEnum.CONFIGACTION_DELETE + +grpc_to_enum__config_action = functools.partial( + grpc_to_enum, ConfigActionEnum, ORM_ConfigActionEnum) + +def remove_dict_key(dictionary : Dict, key : str): + dictionary.pop(key, None) + return dictionary + +def config_key_hasher(resource_key : str, digest_size : int = 8): + hasher = hashlib.blake2b(digest_size=digest_size) + hasher.update(resource_key.encode('UTF-8')) + return hasher.hexdigest() + +class ConfigModel(Model): + pk = PrimaryKeyField() + + def dump(self) -> List[Dict]: + db_config_rule_pks = self.references(ConfigRuleModel) + config_rules = [ConfigRuleModel(self.database, pk).dump(include_position=True) for pk,_ in db_config_rule_pks] + config_rules = sorted(config_rules, key=operator.itemgetter('position')) + return [remove_dict_key(config_rule, 'position') for config_rule in config_rules] + +class ConfigRuleModel(Model): + pk = PrimaryKeyField() + config_fk = ForeignKeyField(ConfigModel) + position = IntegerField(min_value=0, required=True) + action = EnumeratedField(ORM_ConfigActionEnum, required=True) + key = StringField(required=True, allow_empty=False) + value = StringField(required=True, allow_empty=False) + + def dump(self, include_position=True) -> Dict: # pylint: disable=arguments-differ + result = { + 'action': self.action.value, + 'resource_key': self.key, + 'resource_value': self.value, + } + if include_position: result['position'] = self.position + return result diff --git a/src/context/service/database/ContextModel.py b/src/context/service/database/ContextModel.py new file mode 100644 index 000000000..bab5e285a --- /dev/null +++ b/src/context/service/database/ContextModel.py @@ -0,0 +1,30 @@ +import logging +from typing import Dict, List +from common.orm.fields.PrimaryKeyField import PrimaryKeyField +from common.orm.fields.StringField import StringField +from common.orm.model.Model import Model + +LOGGER = logging.getLogger(__name__) + +class ContextModel(Model): + pk = PrimaryKeyField() + context_uuid = StringField(required=True, allow_empty=False) + + def dump_id(self) -> Dict: + return {'context_uuid': {'uuid': self.context_uuid}} + + def dump_service_ids(self) -> List[Dict]: + from .ServiceModel import ServiceModel + db_service_pks = self.references(ServiceModel) + return [ServiceModel(self.database, pk).dump_id() for pk in db_service_pks] + + def dump_topology_ids(self) -> List[Dict]: + from .TopologyModel import TopologyModel + db_topology_pks = self.references(TopologyModel) + return [TopologyModel(self.database, pk).dump_id() for pk in db_topology_pks] + + def dump(self, include_services=True, include_topologies=True) -> Dict: # pylint: disable=arguments-differ + result = {'context_id': self.dump_id()} + if include_services: result['service_ids'] = self.dump_service_ids() + if include_topologies: result['topology_ids'] = self.dump_topology_ids() + return result diff --git a/src/context/service/database/DeviceModel.py b/src/context/service/database/DeviceModel.py new file mode 100644 index 000000000..5c70b877c --- /dev/null +++ b/src/context/service/database/DeviceModel.py @@ -0,0 +1,75 @@ +import functools, logging +from enum import Enum +from typing import Dict, List +from common.orm.fields.EnumeratedField import EnumeratedField +from common.orm.fields.ForeignKeyField import ForeignKeyField +from common.orm.fields.PrimaryKeyField import PrimaryKeyField +from common.orm.fields.StringField import StringField +from common.orm.model.Model import Model +from context.proto.context_pb2 import DeviceDriverEnum, DeviceOperationalStatusEnum +from .ConfigModel import ConfigModel +from .Tools import grpc_to_enum + +LOGGER = logging.getLogger(__name__) + +class ORM_DeviceDriverEnum(Enum): + UNDEFINED = DeviceDriverEnum.DEVICEDRIVER_UNDEFINED + OPENCONFIG = DeviceDriverEnum.DEVICEDRIVER_OPENCONFIG + TRANSPORT_API = DeviceDriverEnum.DEVICEDRIVER_TRANSPORT_API + P4 = DeviceDriverEnum.DEVICEDRIVER_P4 + IETF_NETWORK_TOPOLOGY = DeviceDriverEnum.DEVICEDRIVER_IETF_NETWORK_TOPOLOGY + ONF_TR_352 = DeviceDriverEnum.DEVICEDRIVER_ONF_TR_352 + +grpc_to_enum__device_driver = functools.partial( + grpc_to_enum, DeviceDriverEnum, ORM_DeviceDriverEnum) + +class ORM_DeviceOperationalStatusEnum(Enum): + UNDEFINED = DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_UNDEFINED + DISABLED = DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_DISABLED + ENABLED = DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_ENABLED + +grpc_to_enum__device_operational_status = functools.partial( + grpc_to_enum, DeviceOperationalStatusEnum, ORM_DeviceOperationalStatusEnum) + +class DeviceModel(Model): + pk = PrimaryKeyField() + device_uuid = StringField(required=True, allow_empty=False) + device_type = StringField() + device_config_fk = ForeignKeyField(ConfigModel) + device_operational_status = EnumeratedField(ORM_DeviceOperationalStatusEnum, required=True) + + def dump_id(self) -> Dict: + return {'device_uuid': {'uuid': self.device_uuid}} + + def dump_config(self) -> Dict: + return ConfigModel(self.database, self.device_config_fk).dump() + + def dump_drivers(self) -> List[int]: + db_driver_pks = self.references(DriverModel) + return [DriverModel(self.database, pk).dump() for pk,_ in db_driver_pks] + + def dump_endpoints(self) -> List[Dict]: + from .EndPointModel import EndPointModel + db_endpoints_pks = self.references(EndPointModel) + return [EndPointModel(self.database, pk).dump() for pk,_ in db_endpoints_pks] + + def dump( # pylint: disable=arguments-differ + self, include_config_rules=True, include_drivers=True, include_endpoints=True + ) -> Dict: + result = { + 'device_id': self.dump_id(), + 'device_type': self.device_type, + 'device_operational_status': self.device_operational_status.value, + } + if include_config_rules: result.setdefault('device_config', {})['config_rules'] = self.dump_config() + if include_drivers: result['device_drivers'] = self.dump_drivers() + if include_endpoints: result['device_endpoints'] = self.dump_endpoints() + return result + +class DriverModel(Model): + pk = PrimaryKeyField() + device_fk = ForeignKeyField(DeviceModel) + driver = EnumeratedField(ORM_DeviceDriverEnum, required=True) + + def dump(self) -> Dict: + return self.driver.value diff --git a/src/context/service/database/EndPointModel.py b/src/context/service/database/EndPointModel.py new file mode 100644 index 000000000..b7c220a00 --- /dev/null +++ b/src/context/service/database/EndPointModel.py @@ -0,0 +1,33 @@ +import logging +from typing import Dict +from common.orm.fields.ForeignKeyField import ForeignKeyField +from common.orm.fields.PrimaryKeyField import PrimaryKeyField +from common.orm.fields.StringField import StringField +from common.orm.model.Model import Model +from context.service.database.DeviceModel import DeviceModel +from context.service.database.TopologyModel import TopologyModel + +LOGGER = logging.getLogger(__name__) + +class EndPointModel(Model): + pk = PrimaryKeyField() + topology_fk = ForeignKeyField(TopologyModel, required=False) + device_fk = ForeignKeyField(DeviceModel) + endpoint_uuid = StringField(required=True, allow_empty=False) + endpoint_type = StringField() + + def dump_id(self) -> Dict: + device_id = DeviceModel(self.database, self.device_fk).dump_id() + result = { + 'device_id': device_id, + 'endpoint_uuid': {'uuid': self.endpoint_uuid}, + } + if self.topology_fk is not None: + result['topology_id'] = TopologyModel(self.database, self.topology_fk).dump_id() + return result + + def dump(self) -> Dict: + return { + 'endpoint_id': self.dump_id(), + 'endpoint_type': self.endpoint_type, + } diff --git a/src/context/service/database/LinkModel.py b/src/context/service/database/LinkModel.py new file mode 100644 index 000000000..551a628d5 --- /dev/null +++ b/src/context/service/database/LinkModel.py @@ -0,0 +1,24 @@ +import logging +from typing import Dict +from common.orm.fields.PrimaryKeyField import PrimaryKeyField +from common.orm.fields.StringField import StringField +from common.orm.model.Model import Model + +LOGGER = logging.getLogger(__name__) + +class LinkModel(Model): + pk = PrimaryKeyField() + link_uuid = StringField(required=True, allow_empty=False) + + def dump_id(self) -> Dict: + return {'link_uuid': {'uuid': self.link_uuid}} + + #def dump_topology_ids(self) -> List[Dict]: + # db_topology_pks = self.references(TopologyModel) + # return [TopologyModel(self.database, pk).dump_id() for pk in db_topology_pks] + + def dump(self) -> Dict: + return { + 'link_id': self.dump_id(), + #'link_endpoint_ids': self.dump_endpoints(), + } diff --git a/src/context/service/database/Models.py b/src/context/service/database/Models.py deleted file mode 100644 index e20327ed7..000000000 --- a/src/context/service/database/Models.py +++ /dev/null @@ -1,95 +0,0 @@ -from typing import Dict, List -from common.orm.fields.IntegerField import IntegerField -from common.orm.fields.StringField import StringField -from common.orm.model.Model import Model -from common.orm.fields.ForeignKeyField import ForeignKeyField -from common.orm.fields.PrimaryKeyField import PrimaryKeyField - -class ContextModel(Model): - pk = PrimaryKeyField() - - def dump_id(self) -> Dict: - return {'context_uuid': {'uuid': self.pk}} - - def dump_service_ids(self) -> List[Dict]: - db_service_pks = self.references(ServiceModel) - return [ServiceModel(self.database, pk, auto_load=False).dump_id() for pk in db_service_pks] - - def dump_topology_ids(self) -> List[Dict]: - db_topology_pks = self.references(TopologyModel) - return [TopologyModel(self.database, pk, auto_load=False).dump_id() for pk in db_topology_pks] - - def dump(self, include_services=True, include_topologies=True) -> Dict: # pylint: disable=arguments-differ - result = {'context_id': self.dump_id()} - if include_services: result['service_ids'] = self.dump_service_ids() - if include_topologies: result['topology_ids'] = self.dump_topology_ids() - return result - -class TopologyModel(Model): - pk = PrimaryKeyField() - context_fk = ForeignKeyField(ContextModel) - - def dump_id(self) -> Dict: - context_id = ContextModel(self.database, self.context_fk, auto_load=False).dump_id() - return { - 'context_id': context_id, - 'topology_uuid': {'uuid': self.pk.split('/')[-1]}, - } - - def dump_device_ids(self) -> List[Dict]: - db_device_pks = self.references(DeviceModel) - return [DeviceModel(self.database, pk, auto_load=False).dump_id() for pk in db_device_pks] - - def dump_link_ids(self) -> List[Dict]: - db_link_pks = self.references(LinkModel) - return [LinkModel(self.database, pk, auto_load=False).dump_id() for pk in db_link_pks] - - def dump(self, include_devices=True, include_links=True) -> Dict: # pylint: disable=arguments-differ - result = {'topology_id': self.dump_id()} - if include_devices: result['device_ids'] = self.dump_device_ids() - if include_links: result['link_ids'] = self.dump_link_ids() - return result - -class DeviceModel(Model): - pk = PrimaryKeyField() - device_type = StringField() - -class TopologyDeviceModel(Model): - pk = PrimaryKeyField() - topology_fk = ForeignKeyField(TopologyModel) - device_fk = ForeignKeyField(DeviceModel) - -class DeviceConfigModel(Model): - pk = PrimaryKeyField() - device_fk = ForeignKeyField(DeviceModel) - -class DeviceConfigRuleModel(Model): - pk = PrimaryKeyField() - device_config_fk = ForeignKeyField(DeviceConfigModel) - position = IntegerField(min_value=0, required=True) - key = StringField(required=True) - value = StringField(required=True) - -#message Device { -# DeviceConfig device_config = 3; -# DeviceOperationalStatus devive_operational_status = 4; -# repeated DeviceDriverEnum device_drivers = 5; -# repeated EndPoint endpoints = 6; -#} - -class LinkModel(Model): - link_uuid = PrimaryKeyField() - -class TopologyLinkModel(Model): - topology_fk = ForeignKeyField(TopologyModel) - link_fk = ForeignKeyField(LinkModel) - -class EndPointModel(Model): - endpoint_uuid = PrimaryKeyField() - -class ServiceModel(Model): - endpoint_uuid = PrimaryKeyField() - - -# TODO: implement query methods to find, for instance, topologies belonging to a context -# from Context instance, retrieve references of a specific Model type diff --git a/src/context/service/database/RelationModels.py b/src/context/service/database/RelationModels.py new file mode 100644 index 000000000..ae7198ff5 --- /dev/null +++ b/src/context/service/database/RelationModels.py @@ -0,0 +1,18 @@ +import logging +from common.orm.fields.ForeignKeyField import ForeignKeyField +from common.orm.fields.PrimaryKeyField import PrimaryKeyField +from common.orm.model.Model import Model +from .DeviceModel import DeviceModel +from .LinkModel import LinkModel +from .TopologyModel import TopologyModel + +LOGGER = logging.getLogger(__name__) + +class TopologyDeviceModel(Model): + pk = PrimaryKeyField() + topology_fk = ForeignKeyField(TopologyModel) + device_fk = ForeignKeyField(DeviceModel) + +class TopologyLinkModel(Model): + topology_fk = ForeignKeyField(TopologyModel) + link_fk = ForeignKeyField(LinkModel) diff --git a/src/context/service/database/ServiceModel.py b/src/context/service/database/ServiceModel.py new file mode 100644 index 000000000..f89d1098d --- /dev/null +++ b/src/context/service/database/ServiceModel.py @@ -0,0 +1,65 @@ +import functools, logging +from enum import Enum +from typing import Dict +#from common.orm.fields.EnumeratedField import EnumeratedField +from common.orm.fields.ForeignKeyField import ForeignKeyField +from common.orm.fields.PrimaryKeyField import PrimaryKeyField +from common.orm.fields.StringField import StringField +from common.orm.model.Model import Model, get_related_instances +from context.proto.context_pb2 import ServiceStatusEnum, ServiceTypeEnum +from context.service.database.Tools import grpc_to_enum +from .ContextModel import ContextModel + +LOGGER = logging.getLogger(__name__) + +class ORM_ServiceTypeEnum(Enum): + UNKNOWN = ServiceTypeEnum.SERVICETYPE_UNKNOWN + L3NM = ServiceTypeEnum.SERVICETYPE_L3NM + L2NM = ServiceTypeEnum.SERVICETYPE_L2NM + TAPI_CONNECTIVITY_SERVICE = ServiceTypeEnum.SERVICETYPE_TAPI_CONNECTIVITY_SERVICE + +grpc_to_enum__service_type = functools.partial( + grpc_to_enum, ServiceTypeEnum, ORM_ServiceTypeEnum) + +class ORM_ServiceStatusEnum(Enum): + UNDEFINED = ServiceStatusEnum.SERVICESTATUS_UNDEFINED + PLANNED = ServiceStatusEnum.SERVICESTATUS_PLANNED + ACTIVE = ServiceStatusEnum.SERVICESTATUS_ACTIVE + PENDING_REMOVAL = ServiceStatusEnum.SERVICESTATUS_PENDING_REMOVAL + +grpc_to_enum__service_status = functools.partial( + grpc_to_enum, ServiceStatusEnum, ORM_ServiceStatusEnum) + +class ServiceModel(Model): + pk = PrimaryKeyField() + context_fk = ForeignKeyField(ContextModel) + service_uuid = StringField(required=True, allow_empty=False) + + def dump_id(self) -> Dict: + context_id = ContextModel(self.database, self.context_fk).dump_id() + return { + 'context_id': context_id, + 'service_uuid': {'uuid': self.service_uuid}, + } + + #def dump_device_ids(self) -> List[Dict]: + # db_device_pks = self.references(DeviceModel) + # return [DeviceModel(self.database, pk).dump_id() for pk in db_device_pks] + + #def dump_link_ids(self) -> List[Dict]: + # db_link_pks = self.references(LinkModel) + # return [LinkModel(self.database, pk).dump_id() for pk in db_link_pks] + + def dump( # pylint: disable=arguments-differ + self, include_endpoint_ids=True, include_constraints=True, include_config_rules=True + ) -> Dict: + result = { + 'service_id': self.dump_id(), + 'service_type': ServiceTypeEnum.Value('SERVICETYPE_UNKNOWN'), + 'service_status': ServiceStatusEnum.Value('SERVICESTATUS_UNDEFINED'), + 'service_config': {}, + } + #if include_endpoint_ids: result['service_endpoint_ids'] = self.dump_endpoint_ids() + #if include_constraints: result['service_constraints'] = self.dump_constraints() + #if include_config_rules: result['service_config']['config_rules'] = self.dump_config_rules() + return result diff --git a/src/context/service/database/Tools.py b/src/context/service/database/Tools.py new file mode 100644 index 000000000..f9197807a --- /dev/null +++ b/src/context/service/database/Tools.py @@ -0,0 +1,33 @@ +import logging, re +from enum import Enum + +# Enumeration classes are redundant with gRPC classes, but gRPC does not provide a programmatical method to retrieve +# the values it expects from strings containing the desired value symbol or its integer value, so a kind of mapping is +# required. Besides, ORM Models expect Enum classes in EnumeratedFields; we create specific and conveniently defined +# Enum classes to serve both purposes. + +LOGGER = logging.getLogger(__name__) + +def grpc_to_enum(grpc_enum_class, orm_enum_class : Enum, grpc_enum_value): + #LOGGER.info('grpc_enum_class={:s}'.format(str(grpc_enum_class))) + #LOGGER.info('orm_enum_class={:s}'.format(str(orm_enum_class))) + #LOGGER.info('grpc_enum_value={:s}'.format(str(grpc_enum_value))) + + grpc_enum_name = grpc_enum_class.Name(grpc_enum_value) + #LOGGER.info('grpc_enum_name={:s}'.format(str(grpc_enum_name))) + + grpc_enum_prefix = orm_enum_class.__name__.upper() + #LOGGER.info('grpc_enum_prefix={:s}'.format(str(grpc_enum_prefix))) + grpc_enum_prefix = re.sub(r'^ORM_(.+)$', r'\1', grpc_enum_prefix) + #LOGGER.info('grpc_enum_prefix={:s}'.format(str(grpc_enum_prefix))) + grpc_enum_prefix = re.sub(r'^(.+)ENUM$', r'\1', grpc_enum_prefix) + #LOGGER.info('grpc_enum_prefix={:s}'.format(str(grpc_enum_prefix))) + grpc_enum_prefix = grpc_enum_prefix + '_' + + orm_enum_name = grpc_enum_name.replace(grpc_enum_prefix, '') + #LOGGER.info('orm_enum_name={:s}'.format(str(orm_enum_name))) + + orm_enum_value = orm_enum_class._member_map_.get(orm_enum_name) # pylint: disable=protected-access + #LOGGER.info('orm_enum_value={:s}'.format(str(orm_enum_value))) + + return orm_enum_value diff --git a/src/context/service/database/TopologyModel.py b/src/context/service/database/TopologyModel.py new file mode 100644 index 000000000..871dd2e8f --- /dev/null +++ b/src/context/service/database/TopologyModel.py @@ -0,0 +1,39 @@ +import logging, operator +from typing import Dict, List +from common.orm.fields.ForeignKeyField import ForeignKeyField +from common.orm.fields.PrimaryKeyField import PrimaryKeyField +from common.orm.fields.StringField import StringField +from common.orm.model.Model import Model, get_related_instances +from .ContextModel import ContextModel + +LOGGER = logging.getLogger(__name__) + +class TopologyModel(Model): + pk = PrimaryKeyField() + context_fk = ForeignKeyField(ContextModel) + topology_uuid = StringField(required=True, allow_empty=False) + + def dump_id(self) -> Dict: + context_id = ContextModel(self.database, self.context_fk).dump_id() + return { + 'context_id': context_id, + 'topology_uuid': {'uuid': self.topology_uuid}, + } + + def dump_device_ids(self) -> List[Dict]: + from .RelationModels import TopologyDeviceModel + db_devices = get_related_instances(self, TopologyDeviceModel, 'device_fk') + return [db_device.dump_id() for db_device in sorted(db_devices, key=operator.attrgetter('pk'))] + + def dump_link_ids(self) -> List[Dict]: + from .RelationModels import TopologyLinkModel + db_links = get_related_instances(self, TopologyLinkModel, 'link_fk') + return [db_link.dump_id() for db_link in sorted(db_links, key=operator.attrgetter('pk'))] + + def dump( # pylint: disable=arguments-differ + self, include_devices=True, include_links=True + ) -> Dict: + result = {'topology_id': self.dump_id()} + if include_devices: result['device_ids'] = self.dump_device_ids() + if include_links: result['link_ids'] = self.dump_link_ids() + return result diff --git a/src/context/service/grpc_server/ContextServiceServicerImpl.py b/src/context/service/grpc_server/ContextServiceServicerImpl.py index c765eb28c..d628fb5e5 100644 --- a/src/context/service/grpc_server/ContextServiceServicerImpl.py +++ b/src/context/service/grpc_server/ContextServiceServicerImpl.py @@ -1,19 +1,25 @@ import grpc, logging, operator from typing import Iterator -from common.Constants import DEFAULT_CONTEXT_UUID, DEFAULT_TOPOLOGY_UUID #from common.exceptions.ServiceException import ServiceException from common.metrics.Metrics import create_metrics, safe_and_metered_rpc_method from common.orm.Database import Database from common.orm.backend.Tools import key_to_str -from context.proto.context_pb2 import \ - Context, ContextEvent, ContextId, ContextIdList, ContextList, \ - Device, DeviceEvent, DeviceId, DeviceIdList, DeviceList, \ - Empty, \ - Link, LinkEvent, LinkId, LinkIdList, LinkList, \ - Service, ServiceEvent, ServiceId, ServiceIdList, ServiceList, \ - Topology, TopologyEvent, TopologyId, TopologyIdList, TopologyList +from context.proto.context_pb2 import ( + Context, ContextEvent, ContextId, ContextIdList, ContextList, Device, DeviceEvent, DeviceId, DeviceIdList, + DeviceList, DeviceOperationalStatusEnum, Empty, Link, LinkEvent, LinkId, LinkIdList, LinkList, Service, ServiceEvent, ServiceId, ServiceIdList, + ServiceList, Topology, TopologyEvent, TopologyId, TopologyIdList, TopologyList) from context.proto.context_pb2_grpc import ContextServiceServicer -from context.service.database.Models import ContextModel, TopologyModel +from context.service.database.ConfigModel import ( + ConfigModel, ConfigRuleModel, config_key_hasher, grpc_to_enum__config_action) +from context.service.database.ContextModel import ContextModel +from context.service.database.DeviceModel import ( + DeviceModel, DriverModel, grpc_to_enum__device_driver, grpc_to_enum__device_operational_status) +from context.service.database.EndPointModel import EndPointModel +from context.service.database.LinkModel import LinkModel +from context.service.database.ServiceModel import ServiceModel +from context.service.database.TopologyModel import TopologyModel +from context.service.database.RelationModels import TopologyDeviceModel, TopologyLinkModel + #from .Tools import check_link_id_request, check_link_request LOGGER = logging.getLogger(__name__) @@ -50,14 +56,44 @@ class ContextServiceServicerImpl(ContextServiceServicer): db_context = ContextModel(self.database, str_key, auto_load=False) found = db_context.load() if not found: return Context() - return Context(**db_context.dump(include_services=True, include_topologies=True)) + return Context(**db_context.dump( + include_services=True, include_topologies=True)) @safe_and_metered_rpc_method(METRICS, LOGGER) def SetContext(self, request: Context, context : grpc.ServicerContext) -> ContextId: - str_key = key_to_str(request.context_id.context_uuid.uuid) - db_context = ContextModel(self.database, str_key) + str_context_key = key_to_str(request.context_id.context_uuid.uuid) + db_context = ContextModel(self.database, str_context_key) + db_context.context_uuid = request.context_id.context_uuid.uuid db_context.save() - # TODO: add topologies and services + + for i,topology_id in enumerate(request.topology_ids): + if topology_id.context_id.context_uuid.uuid != db_context.context_uuid: + msg = '{:s}({:s}) != {:s}({:s})' + raise ValueError(msg.format( + 'request.context_id.context_uuid.uuid', + request.context_id.context_uuid.uuid, + 'request.topology_ids[{:d}].context_id.context_uuid.uuid'.format(i), + topology_id.context_id.context_uuid.uuid)) + str_topology_key = key_to_str([str_context_key, topology_id.topology_uuid.uuid]) + db_topology = TopologyModel(self.database, str_topology_key) + db_topology.context_fk = db_context + db_topology.topology_uuid = topology_id.topology_uuid.uuid + db_topology.save() + + for i,service_id in enumerate(request.service_ids): + if service_id.context_id.context_uuid.uuid != db_context.context_uuid: + msg = '{:s}({:s}) != {:s}({:s})' + raise ValueError(msg.format( + 'request.context_id.context_uuid.uuid', + request.context_id.context_uuid.uuid, + 'request.service_ids[{:d}].context_id.context_uuid.uuid'.format(i), + service_id.context_id.context_uuid.uuid)) + str_service_key = key_to_str([str_context_key, service_id.service_uuid.uuid]) + db_service = ServiceModel(self.database, str_service_key) + db_service.context_fk = db_context + db_service.service_uuid = service_id.service_uuid.uuid + db_service.save() + return ContextId(**db_context.dump_id()) @safe_and_metered_rpc_method(METRICS, LOGGER) @@ -76,17 +112,14 @@ class ContextServiceServicerImpl(ContextServiceServicer): db_context = ContextModel(self.database, request.context_uuid.uuid) db_topology_pks = db_context.references(TopologyModel) db_topology_pks = sorted(map(operator.itemgetter(0), db_topology_pks)) - topology_ids = [TopologyModel(self.database, pk).dump_id() for pk in db_topology_pks] - return TopologyIdList(topology_ids=topology_ids) + return TopologyIdList(topology_ids=[TopologyModel(self.database, pk).dump_id() for pk in db_topology_pks]) @safe_and_metered_rpc_method(METRICS, LOGGER) def ListTopologies(self, request: ContextId, context : grpc.ServicerContext) -> TopologyList: db_context = ContextModel(self.database, request.context_uuid.uuid) db_topology_pks = db_context.references(TopologyModel) db_topology_pks = sorted(map(operator.itemgetter(0), db_topology_pks)) - print('db_topology_pks', db_topology_pks) - topologies = [TopologyModel(self.database, pk).dump() for pk in db_topology_pks] - return TopologyList(topologies=topologies) + return TopologyList(topologies=[TopologyModel(self.database, pk).dump() for pk in db_topology_pks]) @safe_and_metered_rpc_method(METRICS, LOGGER) def GetTopology(self, request: TopologyId, context : grpc.ServicerContext) -> Topology: @@ -94,7 +127,8 @@ class ContextServiceServicerImpl(ContextServiceServicer): db_topology = TopologyModel(self.database, str_key, auto_load=False) found = db_topology.load() if not found: return Topology() - return Topology(**db_topology.dump(include_devices=True, include_links=True)) + return Topology(**db_topology.dump( + include_devices=True, include_links=True)) @safe_and_metered_rpc_method(METRICS, LOGGER) def SetTopology(self, request: Topology, context : grpc.ServicerContext) -> TopologyId: @@ -103,8 +137,33 @@ class ContextServiceServicerImpl(ContextServiceServicer): db_context = ContextModel(self.database, str_context_key) db_topology = TopologyModel(self.database, str_topology_key) db_topology.context_fk = db_context + db_topology.topology_uuid = request.topology_id.topology_uuid.uuid db_topology.save() - # TODO: add devices and links + + for device_id in request.device_ids: + str_device_key = key_to_str(device_id.device_uuid.uuid) + db_device = DeviceModel(self.database, str_device_key) + db_device.device_uuid = device_id.device_uuid.uuid + db_device.save() + + str_topology_device_key = key_to_str([str_topology_key, str_device_key], separator='--') + db_topology_device = TopologyDeviceModel(self.database, str_topology_device_key) + db_topology_device.topology_fk = db_topology + db_topology_device.device_fk = db_device + db_topology_device.save() + + for link_id in request.link_ids: + str_link_key = key_to_str(link_id.link_uuid.uuid) + db_link = LinkModel(self.database, str_link_key) + db_link.link_uuid = link_id.link_uuid.uuid + db_link.save() + + str_topology_link_key = key_to_str([str_topology_key, str_link_key], separator='--') + db_topology_link = TopologyLinkModel(self.database, str_topology_link_key) + db_topology_link.topology_fk = db_topology + db_topology_link.link_fk = db_link + db_topology_link.save() + return TopologyId(**db_topology.dump_id()) @safe_and_metered_rpc_method(METRICS, LOGGER) @@ -120,23 +179,125 @@ class ContextServiceServicerImpl(ContextServiceServicer): @safe_and_metered_rpc_method(METRICS, LOGGER) def ListDeviceIds(self, request: Empty, context : grpc.ServicerContext) -> DeviceIdList: - pass + db_device_pks = sorted(list(DeviceModel.get_primary_keys(self.database))) + return DeviceIdList(device_ids=[DeviceModel(self.database, pk).dump_id() for pk in db_device_pks]) @safe_and_metered_rpc_method(METRICS, LOGGER) def ListDevices(self, request: Empty, context : grpc.ServicerContext) -> DeviceList: - pass + db_device_pks = sorted(list(DeviceModel.get_primary_keys(self.database))) + return DeviceList(devices=[DeviceModel(self.database, pk).dump() for pk in db_device_pks]) @safe_and_metered_rpc_method(METRICS, LOGGER) def GetDevice(self, request: DeviceId, context : grpc.ServicerContext) -> Device: - pass + str_key = key_to_str(request.device_uuid.uuid) + db_device = DeviceModel(self.database, str_key, auto_load=False) + found = db_device.load() + if not found: return Device() + return Device(**db_device.dump( + include_config_rules=True, include_drivers=True, include_endpoints=True)) @safe_and_metered_rpc_method(METRICS, LOGGER) def SetDevice(self, request: Device, context : grpc.ServicerContext) -> DeviceId: - pass + device_uuid = request.device_id.device_uuid.uuid + str_device_key = key_to_str(device_uuid) + + str_config_key = key_to_str([str_device_key, 'running'], separator=':') + db_running_config = ConfigModel(self.database, str_config_key) + db_running_config.save() + + db_device = DeviceModel(self.database, str_device_key) + db_device.device_uuid = device_uuid + db_device.device_type = request.device_type + db_device.device_operational_status = grpc_to_enum__device_operational_status(request.device_operational_status) + db_device.device_config_fk = db_running_config + db_device.save() + + for i,config_rule in enumerate(request.device_config.config_rules): + str_rule_key_hash = config_key_hasher(config_rule.resource_key) + str_device_config_rule_key = key_to_str([str_config_key, str_rule_key_hash], separator=':') + db_device_config_rule = ConfigRuleModel(self.database, str_device_config_rule_key) + db_device_config_rule.config_fk = db_running_config + db_device_config_rule.position = i + db_device_config_rule.action = grpc_to_enum__config_action(config_rule.action) + db_device_config_rule.key = config_rule.resource_key + db_device_config_rule.value = config_rule.resource_value + db_device_config_rule.save() + + for i,driver in enumerate(request.device_drivers): + orm_driver = grpc_to_enum__device_driver(driver) + str_device_driver_key = key_to_str([str_device_key, orm_driver.name]) + db_device_driver = DriverModel(self.database, str_device_driver_key) + db_device_driver.device_fk = db_device + db_device_driver.driver = orm_driver + db_device_driver.save() + + for i,endpoint in enumerate(request.device_endpoints): + endpoint_uuid = endpoint.endpoint_id.endpoint_uuid.uuid + endpoint_device_uuid = endpoint.endpoint_id.device_id.device_uuid.uuid + if len(endpoint_device_uuid) == 0: endpoint_device_uuid = device_uuid + if device_uuid != endpoint_device_uuid: + msg = '{:s}({:s}) != {:s}({:s})' + raise ValueError(msg.format( + 'request.device_id.device_uuid.uuid', + device_uuid, + 'request.device_endpoints[{:d}].endpoint_id.device_id.device_uuid.uuid'.format(i), + endpoint_device_uuid)) + + db_topology = None + endpoint_topology_context_uuid = endpoint.endpoint_id.topology_id.context_id.context_uuid.uuid + endpoint_topology_uuid = endpoint.endpoint_id.topology_id.topology_uuid.uuid + if len(endpoint_topology_context_uuid) > 0 and len(endpoint_topology_uuid) > 0: + str_context_key = key_to_str([endpoint_topology_context_uuid]) + db_context = ContextModel(self.database, str_context_key) + db_context.context_uuid = endpoint_topology_context_uuid + db_context.save() + + str_topology_key = key_to_str([endpoint_topology_context_uuid, endpoint_topology_uuid]) + db_topology = TopologyModel(self.database, str_topology_key) + db_topology.context_fk = db_context + db_topology.topology_uuid = endpoint_topology_uuid + db_topology.save() + + str_topology_device_key = key_to_str([str_topology_key, str_device_key], separator='--') + db_topology_device = TopologyDeviceModel(self.database, str_topology_device_key) + db_topology_device.topology_fk = db_topology + db_topology_device.device_fk = db_device + db_topology_device.save() + + str_device_endpoint_key = key_to_str([str_device_key, endpoint_uuid]) + if db_topology is not None: + str_device_endpoint_key = key_to_str([str_device_endpoint_key, str_topology_key], separator=':') + db_device_endpoint = EndPointModel(self.database, str_device_endpoint_key) + db_device_endpoint.device_fk = db_device + db_device_endpoint.endpoint_uuid = endpoint_uuid + db_device_endpoint.endpoint_type = endpoint.endpoint_type + if db_topology is not None: db_device_endpoint.topology_fk = db_topology + db_device_endpoint.save() + + return DeviceId(**db_device.dump_id()) @safe_and_metered_rpc_method(METRICS, LOGGER) def RemoveDevice(self, request: DeviceId, context : grpc.ServicerContext) -> Empty: - pass + str_key = key_to_str(request.device_uuid.uuid) + db_device = DeviceModel(self.database, str_key) + + for db_endpoint_pk,_ in db_device.references(EndPointModel): + EndPointModel(self.database, db_endpoint_pk).delete() + + for db_topology_device_pk,_ in db_device.references(TopologyDeviceModel): + TopologyDeviceModel(self.database, db_topology_device_pk).delete() + + for db_driver_pk,_ in db_device.references(DriverModel): + DriverModel(self.database, db_driver_pk).delete() + + db_config = ConfigModel(self.database, db_device.device_config_fk) + for db_config_rule_pk,_ in db_config.references(ConfigRuleModel): + ConfigRuleModel(self.database, db_config_rule_pk).delete() + + db_device.delete() + db_config.delete() + + return Empty() @safe_and_metered_rpc_method(METRICS, LOGGER) def GetDeviceEvents(self, request: Empty, context : grpc.ServicerContext) -> Iterator[DeviceEvent]: @@ -144,23 +305,89 @@ class ContextServiceServicerImpl(ContextServiceServicer): @safe_and_metered_rpc_method(METRICS, LOGGER) def ListLinkIds(self, request: Empty, context : grpc.ServicerContext) -> LinkIdList: - pass + db_link_pks = sorted(list(LinkModel.get_primary_keys(self.database))) + return LinkIdList(link_ids=[LinkModel(self.database, pk).dump_id() for pk in db_link_pks]) @safe_and_metered_rpc_method(METRICS, LOGGER) def ListLinks(self, request: Empty, context : grpc.ServicerContext) -> LinkList: - pass + db_link_pks = sorted(list(LinkModel.get_primary_keys(self.database))) + return LinkList(links=[LinkModel(self.database, pk).dump() for pk in db_link_pks]) @safe_and_metered_rpc_method(METRICS, LOGGER) def GetLink(self, request: LinkId, context : grpc.ServicerContext) -> Link: - pass + str_key = key_to_str(request.link_uuid.uuid) + db_link = LinkModel(self.database, str_key, auto_load=False) + found = db_link.load() + if not found: return Link() + return Link(**db_link.dump()) @safe_and_metered_rpc_method(METRICS, LOGGER) def SetLink(self, request: Link, context : grpc.ServicerContext) -> LinkId: - pass + str_key = key_to_str(request.link_id.link_uuid.uuid) + db_link = LinkModel(self.database, str_key) + db_link.link_uuid = request.link_id.link_uuid.uuid + db_link.save() + + for i,endpoint_id in enumerate(request.link_endpoint_ids): + endpoint_uuid = endpoint_id.endpoint_uuid.uuid + endpoint_device_uuid = endpoint_id.device_id.device_uuid.uuid + + str_device_key = key_to_str(endpoint_device_uuid) + str_config_key = key_to_str([str_device_key, 'running'], separator=':') + db_running_config = ConfigModel(self.database, str_config_key) + db_running_config.save() + + db_device = DeviceModel(self.database, str_device_key) + db_device.device_uuid = endpoint_device_uuid + db_device.device_operational_status = grpc_to_enum__device_operational_status( + DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_UNDEFINED) + db_device.device_config_fk = db_running_config + db_device.save() + + db_topology = None + endpoint_topology_context_uuid = endpoint_id.topology_id.context_id.context_uuid.uuid + endpoint_topology_uuid = endpoint_id.topology_id.topology_uuid.uuid + if len(endpoint_topology_context_uuid) > 0 and len(endpoint_topology_uuid) > 0: + str_context_key = key_to_str([endpoint_topology_context_uuid]) + db_context = ContextModel(self.database, str_context_key) + db_context.context_uuid = endpoint_topology_context_uuid + db_context.save() + + str_topology_key = key_to_str([endpoint_topology_context_uuid, endpoint_topology_uuid]) + db_topology = TopologyModel(self.database, str_topology_key) + db_topology.context_fk = db_context + db_topology.topology_uuid = endpoint_topology_uuid + db_topology.save() + + str_topology_device_key = key_to_str([str_topology_key, str_device_key], separator='--') + db_topology_device = TopologyDeviceModel(self.database, str_topology_device_key) + db_topology_device.topology_fk = db_topology + db_topology_device.device_fk = db_device + db_topology_device.save() + + str_device_endpoint_key = key_to_str([str_device_key, endpoint_uuid]) + if db_topology is not None: + str_device_endpoint_key = key_to_str([str_device_endpoint_key, str_topology_key], separator=':') + db_device_endpoint = EndPointModel(self.database, str_device_endpoint_key) + db_device_endpoint.device_fk = db_device + db_device_endpoint.endpoint_uuid = endpoint_uuid + if db_topology is not None: db_device_endpoint.topology_fk = db_topology + db_device_endpoint.save() + + return LinkId(**db_link.dump_id()) @safe_and_metered_rpc_method(METRICS, LOGGER) def RemoveLink(self, request: LinkId, context : grpc.ServicerContext) -> Empty: - pass + str_key = key_to_str(request.link_uuid.uuid) + db_link = LinkModel(self.database, str_key) + + db_topology_link_pks = db_link.references(TopologyLinkModel) + for db_topology_link_pk,_ in db_topology_link_pks: + db_topology_link = TopologyLinkModel(self.database, db_topology_link_pk) + db_topology_link.delete() + + db_link.delete() + return Empty() @safe_and_metered_rpc_method(METRICS, LOGGER) def GetLinkEvents(self, request: Empty, context : grpc.ServicerContext) -> Iterator[LinkEvent]: @@ -168,23 +395,47 @@ class ContextServiceServicerImpl(ContextServiceServicer): @safe_and_metered_rpc_method(METRICS, LOGGER) def ListServiceIds(self, request: ContextId, context : grpc.ServicerContext) -> ServiceIdList: - pass + db_context = ContextModel(self.database, request.context_uuid.uuid) + db_service_pks = db_context.references(ServiceModel) + db_service_pks = sorted(map(operator.itemgetter(0), db_service_pks)) + return ServiceIdList(service_ids=[ServiceModel(self.database, pk).dump_id() for pk in db_service_pks]) @safe_and_metered_rpc_method(METRICS, LOGGER) def ListServices(self, request: ContextId, context : grpc.ServicerContext) -> ServiceList: - pass + db_context = ContextModel(self.database, request.context_uuid.uuid) + db_service_pks = db_context.references(ServiceModel) + db_service_pks = sorted(map(operator.itemgetter(0), db_service_pks)) + services = [ServiceModel(self.database, pk).dump() for pk in db_service_pks] + LOGGER.info('[ListServices] services={:s}'.format(str(services))) + return ServiceList(services=services) @safe_and_metered_rpc_method(METRICS, LOGGER) def GetService(self, request: ServiceId, context : grpc.ServicerContext) -> Service: - pass + str_key = key_to_str([request.context_id.context_uuid.uuid, request.service_uuid.uuid]) + db_service = ServiceModel(self.database, str_key, auto_load=False) + found = db_service.load() + if not found: return Service() + return Service(**db_service.dump( + include_endpoint_ids=True, include_constraints=True, include_config_rules=True)) @safe_and_metered_rpc_method(METRICS, LOGGER) def SetService(self, request: Service, context : grpc.ServicerContext) -> ServiceId: - pass + str_context_key = key_to_str([request.service_id.context_id.context_uuid.uuid]) + str_service_key = key_to_str([str_context_key, request.service_id.service_uuid.uuid]) + db_context = ContextModel(self.database, str_context_key) + db_service = ServiceModel(self.database, str_service_key) + db_service.context_fk = db_context + db_service.service_uuid = request.service_id.service_uuid.uuid + db_service.save() + # TODO: add endpoint_ids, constraints, and config_rules + return ServiceId(**db_service.dump_id()) @safe_and_metered_rpc_method(METRICS, LOGGER) def RemoveService(self, request: ServiceId, context : grpc.ServicerContext) -> Empty: - pass + str_key = key_to_str([request.context_id.context_uuid.uuid, request.service_uuid.uuid]) + db_service = ServiceModel(self.database, str_key) + db_service.delete() + return Empty() @safe_and_metered_rpc_method(METRICS, LOGGER) def GetServiceEvents(self, request: Empty, context : grpc.ServicerContext) -> Iterator[ServiceEvent]: diff --git a/src/context/tests/test_unitary.py b/src/context/tests/test_unitary.py index 15ec1ebad..a9e285e90 100644 --- a/src/context/tests/test_unitary.py +++ b/src/context/tests/test_unitary.py @@ -1,19 +1,9 @@ import copy, logging, pytest -#import grpc, requests, time -#from google.protobuf.json_format import MessageToDict from common.Constants import DEFAULT_CONTEXT_UUID, DEFAULT_TOPOLOGY_UUID from common.orm.Database import Database from common.orm.Factory import get_database_backend, BackendEnum -#from common.tests.Assertions import validate_empty, validate_link_id, validate_topology, validate_topology_has_devices,\ -# validate_topology_has_links, validate_topology_is_empty from context.client.ContextClient import ContextClient -from context.proto.context_pb2 import \ - Context, ContextEvent, ContextId, ContextIdList, ContextList, \ - Device, DeviceEvent, DeviceId, DeviceIdList, DeviceList, \ - Empty, \ - Link, LinkEvent, LinkId, LinkIdList, LinkList, \ - Service, ServiceEvent, ServiceId, ServiceIdList, ServiceList, \ - Topology, TopologyEvent, TopologyId, TopologyIdList, TopologyList +from context.proto.context_pb2 import ConfigActionEnum, Context, ContextId, Device, DeviceDriverEnum, DeviceId, DeviceOperationalStatusEnum, Empty, Link, LinkId, Service, ServiceId, ServiceStatusEnum, ServiceTypeEnum, Topology, TopologyId from context.service.grpc_server.ContextService import ContextService from context.Config import GRPC_SERVICE_PORT, GRPC_MAX_WORKERS, GRPC_GRACE_PERIOD #, RESTAPI_SERVICE_PORT, \ # RESTAPI_BASE_URL @@ -30,16 +20,138 @@ LOGGER.setLevel(logging.DEBUG) ## use "copy.deepcopy" to prevent propagating forced changes during tests CONTEXT_ID = {'context_uuid': {'uuid': DEFAULT_CONTEXT_UUID}} CONTEXT = {'context_id': copy.deepcopy(CONTEXT_ID)} -TOPOLOGY_ID = {'context_id': copy.deepcopy(CONTEXT_ID), 'topology_uuid': {'uuid': DEFAULT_TOPOLOGY_UUID}} -TOPOLOGY = {'topology_id': copy.deepcopy(TOPOLOGY_ID)} -#LINK_ID = {'link_id': {'uuid': 'DEV1/EP2 ==> DEV2/EP1'}} -#LINK = { -# 'link_id': {'link_id': {'uuid': 'DEV1/EP2 ==> DEV2/EP1'}}, -# 'endpointList' : [ -# {'topoId': copy.deepcopy(TOPOLOGY_ID), 'dev_id': {'device_id': {'uuid': 'DEV1'}}, 'port_id': {'uuid' : 'EP2'}}, -# {'topoId': copy.deepcopy(TOPOLOGY_ID), 'dev_id': {'device_id': {'uuid': 'DEV2'}}, 'port_id': {'uuid' : 'EP1'}}, -# ] -#} + +TOPOLOGY_ID = { + 'context_id': copy.deepcopy(CONTEXT_ID), + 'topology_uuid': {'uuid': DEFAULT_TOPOLOGY_UUID}, +} +TOPOLOGY = { + 'topology_id': copy.deepcopy(TOPOLOGY_ID), + 'device_ids': [], + 'link_ids': [], +} + +DEVICE1_UUID = 'DEV1' +DEVICE1_ID = {'device_uuid': {'uuid': DEVICE1_UUID}} +DEVICE1 = { + 'device_id': copy.deepcopy(DEVICE1_ID), + 'device_type': 'packet-router', + 'device_config': {'config_rules': [ + {'action': ConfigActionEnum.CONFIGACTION_SET, + 'resource_key': 'device/resource-1/value', + 'resource_value': 'value1'}, + {'action': ConfigActionEnum.CONFIGACTION_SET, + 'resource_key': 'device/resource-2/value', + 'resource_value': 'value2'}, + {'action': ConfigActionEnum.CONFIGACTION_SET, + 'resource_key': 'device/resource-3/value', + 'resource_value': 'value3'}, + ]}, + 'device_operational_status': DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_ENABLED, + 'device_drivers': [DeviceDriverEnum.DEVICEDRIVER_OPENCONFIG, DeviceDriverEnum.DEVICEDRIVER_P4], + 'device_endpoints': [ + {'endpoint_id': { + 'topology_id': copy.deepcopy(TOPOLOGY_ID), + 'device_id': copy.deepcopy(DEVICE1_ID), + 'endpoint_uuid': {'uuid': 'EP1'}, + }, 'endpoint_type': 'port-packet-100G'}, + {'endpoint_id': { + 'topology_id': copy.deepcopy(TOPOLOGY_ID), + 'device_id': copy.deepcopy(DEVICE1_ID), + 'endpoint_uuid': {'uuid': 'EP2'}, + }, 'endpoint_type': 'port-packet-100G'}, + {'endpoint_id': { + 'topology_id': copy.deepcopy(TOPOLOGY_ID), + 'device_id': copy.deepcopy(DEVICE1_ID), + 'endpoint_uuid': {'uuid': 'EP3'}, + }, 'endpoint_type': 'port-packet-100G'}, + ], +} + +DEVICE2_UUID = 'DEV2' +DEVICE2_ID = {'device_uuid': {'uuid': DEVICE2_UUID}} +DEVICE2 = { + 'device_id': copy.deepcopy(DEVICE2_ID), + 'device_type': 'packet-router', + 'device_config': {'config_rules': [ + {'action': ConfigActionEnum.CONFIGACTION_SET, + 'resource_key': 'device/resource-1/value', + 'resource_value': 'value4'}, + {'action': ConfigActionEnum.CONFIGACTION_SET, + 'resource_key': 'device/resource-2/value', + 'resource_value': 'value5'}, + {'action': ConfigActionEnum.CONFIGACTION_SET, + 'resource_key': 'device/resource-3/value', + 'resource_value': 'value6'}, + ]}, + 'device_operational_status': DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_ENABLED, + 'device_drivers': [DeviceDriverEnum.DEVICEDRIVER_OPENCONFIG, DeviceDriverEnum.DEVICEDRIVER_P4], + 'device_endpoints': [ + {'endpoint_id': { + 'topology_id': copy.deepcopy(TOPOLOGY_ID), + 'device_id': copy.deepcopy(DEVICE2_ID), + 'endpoint_uuid': {'uuid': 'EP1'}, + }, 'endpoint_type': 'port-packet-100G'}, + {'endpoint_id': { + 'topology_id': copy.deepcopy(TOPOLOGY_ID), + 'device_id': copy.deepcopy(DEVICE2_ID), + 'endpoint_uuid': {'uuid': 'EP2'}, + }, 'endpoint_type': 'port-packet-100G'}, + {'endpoint_id': { + 'topology_id': copy.deepcopy(TOPOLOGY_ID), + 'device_id': copy.deepcopy(DEVICE2_ID), + 'endpoint_uuid': {'uuid': 'EP3'}, + }, 'endpoint_type': 'port-packet-100G'}, + ], +} + +LINK_UUID = 'DEV1/EP2 ==> DEV2/EP1' +LINK_ID = {'link_uuid': {'uuid': LINK_UUID}} +LINK = { + 'link_id': copy.deepcopy(LINK_ID), + 'link_endpoint_ids' : [ + {'topology_id': copy.deepcopy(TOPOLOGY_ID), + 'device_id': copy.deepcopy(DEVICE1_ID), + 'endpoint_uuid': {'uuid' : 'EP2'}}, + {'topology_id': copy.deepcopy(TOPOLOGY_ID), + 'device_id': copy.deepcopy(DEVICE2_ID), + 'endpoint_uuid': {'uuid' : 'EP1'}}, + ] +} + +SERVICE_UUID = 'SVC:DEV1/EP2-DEV2/EP1' +SERVICE_ID = { + 'context_id': copy.deepcopy(CONTEXT_ID), + 'service_uuid': {'uuid': SERVICE_UUID}, +} +SERVICE = { + 'service_id': copy.deepcopy(SERVICE_ID), + 'service_type': ServiceTypeEnum.SERVICETYPE_L3NM, + 'service_endpoint_ids' : [ + {'topology_id': copy.deepcopy(TOPOLOGY_ID), + 'device_id': copy.deepcopy(DEVICE1_ID), + 'endpoint_uuid': {'uuid' : 'EP2'}}, + {'topology_id': copy.deepcopy(TOPOLOGY_ID), + 'device_id': copy.deepcopy(DEVICE2_ID), + 'endpoint_uuid': {'uuid' : 'EP1'}}, + ], + 'service_constraints': [ + {'constraint_type': 'latency_ms', 'constraint_value': '15.2'}, + {'constraint_type': 'jitter_us', 'constraint_value': '1.2'}, + ], + 'service_status': {'service_status': ServiceStatusEnum.SERVICESTATUS_ACTIVE}, + 'service_config': {'config_rules': [ + {'action': ConfigActionEnum.CONFIGACTION_SET, + 'resource_key': 'service/resource-1/value', + 'resource_value': 'value7'}, + {'action': ConfigActionEnum.CONFIGACTION_SET, + 'resource_key': 'service/resource-2/value', + 'resource_value': 'value8'}, + {'action': ConfigActionEnum.CONFIGACTION_SET, + 'resource_key': 'service/resource-3/value', + 'resource_value': 'value9'}, + ]}, +} @pytest.fixture(scope='session') def context_database(): @@ -55,16 +167,6 @@ def context_service(context_database : Database): # pylint: disable=redefined-ou yield _service _service.stop() -#@pytest.fixture(scope='session') -#def context_service_rest(context_database : Database): -# _rest_server = Server(port=restapi_port, base_url=RESTAPI_BASE_URL) -# _rest_server.add_resource(Context, '/context', endpoint='api.context', resource_class_args=(context_database,)) -# _rest_server.start() -# time.sleep(1) # bring time for the server to start -# yield _rest_server -# _rest_server.shutdown() -# _rest_server.join() - @pytest.fixture(scope='session') def context_client(context_service : ContextService): # pylint: disable=redefined-outer-name _client = ContextClient(address='127.0.0.1', port=grpc_port) @@ -155,6 +257,7 @@ def test_topology_instances( assert len(db_entries) == 2 response = context_client.SetTopology(Topology(**TOPOLOGY)) + LOGGER.info('response={:s}'.format(str(response))) assert response.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID assert response.topology_uuid.uuid == DEFAULT_TOPOLOGY_UUID @@ -177,6 +280,12 @@ def test_topology_instances( assert len(response.topologies[0].device_ids) == 0 assert len(response.topologies[0].link_ids) == 0 + response = context_client.GetTopology(TopologyId(**TOPOLOGY_ID)) + assert response.topology_id.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID + assert response.topology_id.topology_uuid.uuid == DEFAULT_TOPOLOGY_UUID + assert len(response.device_ids) == 0 + assert len(response.link_ids) == 0 + context_client.RemoveTopology(TopologyId(**TOPOLOGY_ID)) context_client.RemoveContext(ContextId(**CONTEXT_ID)) @@ -187,177 +296,272 @@ def test_topology_instances( LOGGER.info('-----------------------------------------------------------') assert len(db_entries) == 0 +def test_device_instances( + context_client : ContextClient, context_database : Database): # pylint: disable=redefined-outer-name -#def test_get_topology_empty(context_client : ContextClient, context_database : Database): -# # should work -# context_database.clear_all() -# validate_topology_is_empty(MessageToDict( -# context_client.GetTopology(Empty()), -# including_default_value_fields=True, preserving_proto_field_name=True, -# use_integers_for_enums=False)) -# -#def test_get_topology_completed(context_client : ContextClient, context_database : Database): -# # should work -# populate_example(context_database, add_services=False) -# topology = MessageToDict( -# context_client.GetTopology(Empty()), -# including_default_value_fields=True, preserving_proto_field_name=True, -# use_integers_for_enums=False) -# validate_topology(topology) -# validate_topology_has_devices(topology) -# validate_topology_has_links(topology) -# -#def test_delete_link_empty_uuid(context_client : ContextClient): -# # should fail with link not found -# with pytest.raises(grpc._channel._InactiveRpcError) as e: -# copy_link_id = copy.deepcopy(LINK_ID) -# copy_link_id['link_id']['uuid'] = '' -# context_client.DeleteLink(LinkId(**copy_link_id)) -# assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT -# msg = 'link_id.link_id.uuid() is out of range: '\ -# 'allow_empty(False) min_length(None) max_length(None) allowed_lengths(None).' -# assert e.value.details() == msg -# -#def test_add_link_already_exists(context_client : ContextClient): -# # should fail with link already exists -# with pytest.raises(grpc._channel._InactiveRpcError) as e: -# context_client.AddLink(Link(**LINK)) -# assert e.value.code() == grpc.StatusCode.ALREADY_EXISTS -# msg = 'Context(admin)/Topology(admin)/Link(DEV1/EP2 ==> DEV2/EP1) already exists in the database.' -# assert e.value.details() == msg -# -#def test_delete_link(context_client : ContextClient): -# # should work -# validate_empty(MessageToDict( -# context_client.DeleteLink(LinkId(**LINK_ID)), -# including_default_value_fields=True, preserving_proto_field_name=True, -# use_integers_for_enums=False)) -# -#def test_delete_link_not_existing(context_client : ContextClient): -# # should fail with link not found -# with pytest.raises(grpc._channel._InactiveRpcError) as e: -# context_client.DeleteLink(LinkId(**LINK_ID)) -# assert e.value.code() == grpc.StatusCode.NOT_FOUND -# msg = 'Context(admin)/Topology(admin)/Link(DEV1/EP2 ==> DEV2/EP1) does not exist in the database.' -# assert e.value.details() == msg -# -#def test_add_link_uuid_empty(context_client : ContextClient): -# # should fail with link uuid empty -# with pytest.raises(grpc._channel._InactiveRpcError) as e: -# copy_link = copy.deepcopy(LINK) -# copy_link['link_id']['link_id']['uuid'] = '' -# context_client.AddLink(Link(**copy_link)) -# assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT -# msg = 'link.link_id.link_id.uuid() is out of range: '\ -# 'allow_empty(False) min_length(None) max_length(None) allowed_lengths(None).' -# assert e.value.details() == msg -# -#def test_add_link_wrong_endpoint(context_client : ContextClient): -# # should fail with wrong endpoint context -# with pytest.raises(grpc._channel._InactiveRpcError) as e: -# copy_link = copy.deepcopy(LINK) -# copy_link['endpointList'][0]['topoId']['contextId']['contextUuid']['uuid'] = 'wrong-context' -# context_client.AddLink(Link(**copy_link)) -# assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT -# msg = 'Context(wrong-context) in Endpoint(#0) of '\ -# 'Context(admin)/Topology(admin)/Link(DEV1/EP2 ==> DEV2/EP1) mismatches acceptable Contexts({\'admin\'}). '\ -# 'Optionally, leave field empty to use predefined Context(admin).' -# assert e.value.details() == msg -# -# # should fail with wrong endpoint topology -# with pytest.raises(grpc._channel._InactiveRpcError) as e: -# copy_link = copy.deepcopy(LINK) -# copy_link['endpointList'][0]['topoId']['topoId']['uuid'] = 'wrong-topo' -# context_client.AddLink(Link(**copy_link)) -# assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT -# msg = 'Context(admin)/Topology(wrong-topo) in Endpoint(#0) of '\ -# 'Context(admin)/Topology(admin)/Link(DEV1/EP2 ==> DEV2/EP1) mismatches acceptable Topologies({\'admin\'}). '\ -# 'Optionally, leave field empty to use predefined Topology(admin).' -# assert e.value.details() == msg -# -# # should fail with device uuid is empty -# with pytest.raises(grpc._channel._InactiveRpcError) as e: -# copy_link = copy.deepcopy(LINK) -# copy_link['endpointList'][0]['dev_id']['device_id']['uuid'] = '' -# context_client.AddLink(Link(**copy_link)) -# assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT -# msg = 'endpoint_id[#0].dev_id.device_id.uuid() is out of range: '\ -# 'allow_empty(False) min_length(None) max_length(None) allowed_lengths(None).' -# assert e.value.details() == msg -# -# # should fail with wrong endpoint device -# with pytest.raises(grpc._channel._InactiveRpcError) as e: -# copy_link = copy.deepcopy(LINK) -# copy_link['endpointList'][0]['dev_id']['device_id']['uuid'] = 'wrong-device' -# context_client.AddLink(Link(**copy_link)) -# assert e.value.code() == grpc.StatusCode.NOT_FOUND -# msg = 'Context(admin)/Topology(admin)/Device(wrong-device) in Endpoint(#0) of '\ -# 'Context(admin)/Topology(admin)/Link(DEV1/EP2 ==> DEV2/EP1) does not exist in the database.' -# assert e.value.details() == msg -# -# # should fail with endpoint uuid is empty -# with pytest.raises(grpc._channel._InactiveRpcError) as e: -# copy_link = copy.deepcopy(LINK) -# copy_link['endpointList'][0]['port_id']['uuid'] = '' -# context_client.AddLink(Link(**copy_link)) -# assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT -# msg = 'endpoint_id[#0].port_id.uuid() is out of range: '\ -# 'allow_empty(False) min_length(None) max_length(None) allowed_lengths(None).' -# assert e.value.details() == msg -# -# # should fail with wrong endpoint port -# with pytest.raises(grpc._channel._InactiveRpcError) as e: -# copy_link = copy.deepcopy(LINK) -# copy_link['endpointList'][0]['port_id']['uuid'] = 'wrong-port' -# context_client.AddLink(Link(**copy_link)) -# assert e.value.code() == grpc.StatusCode.NOT_FOUND -# msg = 'Context(admin)/Topology(admin)/Device(DEV1)/Port(wrong-port) in Endpoint(#0) of '\ -# 'Context(admin)/Topology(admin)/Link(DEV1/EP2 ==> DEV2/EP1) does not exist in the database.' -# assert e.value.details() == msg -# -# # should fail with endpoint device duplicated -# with pytest.raises(grpc._channel._InactiveRpcError) as e: -# copy_link = copy.deepcopy(LINK) -# copy_link['endpointList'][1]['dev_id']['device_id']['uuid'] = 'DEV1' -# context_client.AddLink(Link(**copy_link)) -# assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT -# msg = 'Duplicated Context(admin)/Topology(admin)/Device(DEV1) in Endpoint(#1) of '\ -# 'Context(admin)/Topology(admin)/Link(DEV1/EP2 ==> DEV2/EP1).' -# assert e.value.details() == msg -# -#def test_add_link(context_client : ContextClient): -# # should work -# validate_link_id(MessageToDict( -# context_client.AddLink(Link(**LINK)), -# including_default_value_fields=True, preserving_proto_field_name=True, -# use_integers_for_enums=False)) -# -#def test_delete_link_2(context_client : ContextClient): -# # should work -# validate_empty(MessageToDict( -# context_client.DeleteLink(LinkId(**LINK_ID)), -# including_default_value_fields=True, preserving_proto_field_name=True, -# use_integers_for_enums=False)) -# -#def test_add_link_default_endpoint_context_topology(context_client : ContextClient): -# # should work -# copy_link = copy.deepcopy(LINK) -# copy_link['endpointList'][0]['topoId']['contextId']['contextUuid']['uuid'] = '' -# copy_link['endpointList'][0]['topoId']['topoId']['uuid'] = '' -# validate_link_id(MessageToDict( -# context_client.AddLink(Link(**copy_link)), -# including_default_value_fields=True, preserving_proto_field_name=True, -# use_integers_for_enums=False)) -# -#def test_get_topology_completed_2(context_client : ContextClient): -# # should work -# topology = MessageToDict( -# context_client.GetTopology(Empty()), -# including_default_value_fields=True, preserving_proto_field_name=True, -# use_integers_for_enums=False) -# validate_topology(topology) -# validate_topology_has_devices(topology) -# validate_topology_has_links(topology) + context_database.clear_all() + + response = context_client.SetContext(Context(**CONTEXT)) + assert response.context_uuid.uuid == DEFAULT_CONTEXT_UUID + + response = context_client.SetTopology(Topology(**TOPOLOGY)) + assert response.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID + assert response.topology_uuid.uuid == DEFAULT_TOPOLOGY_UUID + + response = context_client.ListDeviceIds(Empty()) + assert len(response.device_ids) == 0 + + response = context_client.ListDevices(Empty()) + assert len(response.devices) == 0 + + response = context_client.GetDevice(DeviceId(**DEVICE1_ID)) + assert len(response.device_id.device_uuid.uuid) == 0 + assert len(response.device_type) == 0 + assert len(response.device_config.config_rules) == 0 + assert response.device_operational_status == DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_UNDEFINED + assert len(response.device_drivers) == 0 + assert len(response.device_endpoints) == 0 + + db_entries = context_database.dump() + LOGGER.info('----- Database Dump [{:3d} entries] -------------------------'.format(len(db_entries))) + for db_entry in db_entries: + LOGGER.info(' [{:>4s}] {:40s} :: {:s}'.format(*db_entry)) + LOGGER.info('-----------------------------------------------------------') + assert len(db_entries) == 5 + + response = context_client.SetDevice(Device(**DEVICE1)) + assert response.device_uuid.uuid == DEVICE1_UUID + + db_entries = context_database.dump() + LOGGER.info('----- Database Dump [{:3d} entries] -------------------------'.format(len(db_entries))) + for db_entry in db_entries: + LOGGER.info(' [{:>4s}] {:40s} :: {:s}'.format(*db_entry)) + LOGGER.info('-----------------------------------------------------------') + assert len(db_entries) == 25 + + response = context_client.ListDeviceIds(Empty()) + assert len(response.device_ids) == 1 + assert response.device_ids[0].device_uuid.uuid == DEVICE1_UUID + + response = context_client.ListDevices(Empty()) + assert len(response.devices) == 1 + assert response.devices[0].device_id.device_uuid.uuid == DEVICE1_UUID + assert response.devices[0].device_type == 'packet-router' + assert len(response.devices[0].device_config.config_rules) == 3 + assert response.devices[0].device_operational_status == DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_ENABLED + assert len(response.devices[0].device_drivers) == 2 + assert len(response.devices[0].device_endpoints) == 3 + + response = context_client.GetDevice(DeviceId(**DEVICE1_ID)) + assert response.device_id.device_uuid.uuid == DEVICE1_UUID + assert response.device_type == 'packet-router' + assert len(response.device_config.config_rules) == 3 + assert response.device_operational_status == DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_ENABLED + assert len(response.device_drivers) == 2 + assert len(response.device_endpoints) == 3 + + TOPOLOGY_WITH_DEVICE = copy.deepcopy(TOPOLOGY) + TOPOLOGY_WITH_DEVICE['device_ids'].append(DEVICE1_ID) + response = context_client.SetTopology(Topology(**TOPOLOGY_WITH_DEVICE)) + assert response.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID + assert response.topology_uuid.uuid == DEFAULT_TOPOLOGY_UUID + + response = context_client.GetTopology(TopologyId(**TOPOLOGY_ID)) + assert response.topology_id.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID + assert response.topology_id.topology_uuid.uuid == DEFAULT_TOPOLOGY_UUID + assert len(response.device_ids) == 1 + assert response.device_ids[0].device_uuid.uuid == DEVICE1_UUID + assert len(response.link_ids) == 0 + + db_entries = context_database.dump() + LOGGER.info('----- Database Dump [{:3d} entries] -------------------------'.format(len(db_entries))) + for db_entry in db_entries: + LOGGER.info(' [{:>4s}] {:40s} :: {:s}'.format(*db_entry)) # pragma: no cover + LOGGER.info('-----------------------------------------------------------') + assert len(db_entries) == 25 + + context_client.RemoveDevice(DeviceId(**DEVICE1_ID)) + context_client.RemoveTopology(TopologyId(**TOPOLOGY_ID)) + context_client.RemoveContext(ContextId(**CONTEXT_ID)) + + db_entries = context_database.dump() + LOGGER.info('----- Database Dump [{:3d} entries] -------------------------'.format(len(db_entries))) + for db_entry in db_entries: + LOGGER.info(' [{:>4s}] {:40s} :: {:s}'.format(*db_entry)) # pragma: no cover + LOGGER.info('-----------------------------------------------------------') + assert len(db_entries) == 0 + +def test_link_instances( + context_client : ContextClient, context_database : Database): # pylint: disable=redefined-outer-name + + context_database.clear_all() + + response = context_client.SetContext(Context(**CONTEXT)) + assert response.context_uuid.uuid == DEFAULT_CONTEXT_UUID + + response = context_client.SetTopology(Topology(**TOPOLOGY)) + assert response.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID + assert response.topology_uuid.uuid == DEFAULT_TOPOLOGY_UUID + + response = context_client.ListLinkIds(Empty()) + assert len(response.link_ids) == 0 + + response = context_client.ListLinks(Empty()) + assert len(response.links) == 0 + + response = context_client.GetLink(LinkId(**LINK_ID)) + assert len(response.link_id.link_uuid.uuid) == 0 + assert len(response.link_endpoint_ids) == 0 + + db_entries = context_database.dump() + LOGGER.info('----- Database Dump [{:3d} entries] -------------------------'.format(len(db_entries))) + for db_entry in db_entries: + LOGGER.info(' [{:>4s}] {:40s} :: {:s}'.format(*db_entry)) + LOGGER.info('-----------------------------------------------------------') + assert len(db_entries) == 5 + + response = context_client.SetLink(Link(**LINK)) + assert response.link_uuid.uuid == LINK_UUID + + db_entries = context_database.dump() + LOGGER.info('----- Database Dump [{:3d} entries] -------------------------'.format(len(db_entries))) + for db_entry in db_entries: + LOGGER.info(' [{:>4s}] {:40s} :: {:s}'.format(*db_entry)) + LOGGER.info('-----------------------------------------------------------') + assert len(db_entries) == 24 + + response = context_client.ListLinkIds(Empty()) + assert len(response.link_ids) == 1 + assert response.link_ids[0].link_uuid.uuid == LINK_UUID + + response = context_client.ListLinks(Empty()) + assert len(response.links) == 1 + assert response.links[0].link_id.link_uuid.uuid == LINK_UUID + assert len(response.links[0].link_endpoint_ids) == 0 + + response = context_client.GetLink(LinkId(**LINK_ID)) + assert response.link_id.link_uuid.uuid == LINK_UUID + assert len(response.link_endpoint_ids) == 0 + + TOPOLOGY_WITH_LINK = copy.deepcopy(TOPOLOGY) + TOPOLOGY_WITH_LINK['link_ids'].append(LINK_ID) + response = context_client.SetTopology(Topology(**TOPOLOGY_WITH_LINK)) + assert response.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID + assert response.topology_uuid.uuid == DEFAULT_TOPOLOGY_UUID + + response = context_client.GetTopology(TopologyId(**TOPOLOGY_ID)) + assert response.topology_id.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID + assert response.topology_id.topology_uuid.uuid == DEFAULT_TOPOLOGY_UUID + assert len(response.device_ids) == 2 + assert response.device_ids[0].device_uuid.uuid == DEVICE1_UUID + assert response.device_ids[1].device_uuid.uuid == DEVICE2_UUID + assert len(response.link_ids) == 1 + assert response.link_ids[0].link_uuid.uuid == LINK_UUID + + db_entries = context_database.dump() + LOGGER.info('----- Database Dump [{:3d} entries] -------------------------'.format(len(db_entries))) + for db_entry in db_entries: + LOGGER.info(' [{:>4s}] {:40s} :: {:s}'.format(*db_entry)) # pragma: no cover + LOGGER.info('-----------------------------------------------------------') + assert len(db_entries) == 27 + + context_client.RemoveLink(LinkId(**LINK_ID)) + context_client.RemoveDevice(DeviceId(**DEVICE1_ID)) + context_client.RemoveDevice(DeviceId(**DEVICE2_ID)) + context_client.RemoveTopology(TopologyId(**TOPOLOGY_ID)) + context_client.RemoveContext(ContextId(**CONTEXT_ID)) + + db_entries = context_database.dump() + LOGGER.info('----- Database Dump [{:3d} entries] -------------------------'.format(len(db_entries))) + for db_entry in db_entries: + LOGGER.info(' [{:>4s}] {:40s} :: {:s}'.format(*db_entry)) # pragma: no cover + LOGGER.info('-----------------------------------------------------------') + assert len(db_entries) == 0 + +def t_e_s_t_service_instances( + context_client : ContextClient, context_database : Database): # pylint: disable=redefined-outer-name + + context_database.clear_all() + + response = context_client.SetContext(Context(**CONTEXT)) + assert response.context_uuid.uuid == DEFAULT_CONTEXT_UUID + + response = context_client.ListServiceIds(ContextId(**CONTEXT_ID)) + assert len(response.service_ids) == 0 + + response = context_client.ListServices(ContextId(**CONTEXT_ID)) + assert len(response.services) == 0 + + response = context_client.GetService(ServiceId(**SERVICE_ID)) + assert len(response.service_id.service_uuid.uuid) == 0 + assert len(response.service_id.context_id.context_uuid.uuid) == 0 + assert response.service_type == ServiceTypeEnum.SERVICETYPE_UNKNOWN + assert len(response.service_endpoint_ids) == 0 + assert len(response.service_constraints) == 0 + assert response.service_status.service_status == ServiceStatusEnum.SERVICESTATUS_UNDEFINED + assert len(response.service_config.config_rules) == 0 + + db_entries = context_database.dump() + LOGGER.info('----- Database Dump [{:3d} entries] -------------------------'.format(len(db_entries))) + for db_entry in db_entries: + LOGGER.info(' [{:>4s}] {:40s} :: {:s}'.format(*db_entry)) + LOGGER.info('-----------------------------------------------------------') + assert len(db_entries) == 2 + + response = context_client.SetService(Service(**SERVICE)) + assert response.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID + assert response.service_uuid.uuid == SERVICE_UUID + + db_entries = context_database.dump() + LOGGER.info('----- Database Dump [{:3d} entries] -------------------------'.format(len(db_entries))) + for db_entry in db_entries: + LOGGER.info(' [{:>4s}] {:40s} :: {:s}'.format(*db_entry)) + LOGGER.info('-----------------------------------------------------------') + assert len(db_entries) == 5 + + response = context_client.ListServiceIds(ContextId(**CONTEXT_ID)) + assert len(response.service_ids) == 1 + assert response.service_ids[0].context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID + assert response.service_ids[0].service_uuid.uuid == SERVICE_UUID + + response = context_client.ListServices(ContextId(**CONTEXT_ID)) + assert len(response.services) == 1 + assert response.services[0].service_id.context_id.context_uuid.uuid == DEFAULT_CONTEXT_UUID + assert response.services[0].service_id.service_uuid.uuid == SERVICE_UUID + assert response.services[0].service_type == ServiceTypeEnum.SERVICETYPE_L3NM + assert len(response.services[0].service_endpoint_ids) == 0 + assert len(response.services[0].service_constraints) == 0 + assert response.services[0].service_status.service_status == ServiceStatusEnum.SERVICESTATUS_ACTIVE + assert len(response.services[0].service_config.config_rules) == 0 + + response = context_client.GetService(ServiceId(**SERVICE_ID)) + assert len(response.service_id.service_uuid.uuid) == 0 + assert len(response.service_id.context_id.context_uuid.uuid) == 0 + assert len(response.service_type) == 0 + assert len(response.service_endpoint_ids) == 0 + assert len(response.service_constraints) == 0 + assert response.service_status.service_status == ServiceStatusEnum.SERVICESTATUS_ACTIVE + assert len(response.service_config.config_rules) == 0 + + context_client.RemoveService(ServiceId(**SERVICE_ID)) + context_client.RemoveContext(ContextId(**CONTEXT_ID)) + + db_entries = context_database.dump() + LOGGER.info('----- Database Dump [{:3d} entries] -------------------------'.format(len(db_entries))) + for db_entry in db_entries: + LOGGER.info(' [{:>4s}] {:40s} :: {:s}'.format(*db_entry)) # pragma: no cover + LOGGER.info('-----------------------------------------------------------') + assert len(db_entries) == 0 + +#@pytest.fixture(scope='session') +#def context_service_rest(context_database : Database): +# _rest_server = Server(port=restapi_port, base_url=RESTAPI_BASE_URL) +# _rest_server.add_resource(Context, '/context', endpoint='api.context', resource_class_args=(context_database,)) +# _rest_server.start() +# time.sleep(1) # bring time for the server to start +# yield _rest_server +# _rest_server.shutdown() +# _rest_server.join() # #def test_get_topology_completed_rest_api(context_service_rest : Server): # # should work -- GitLab