diff --git a/src/context/service/Database.py b/src/context/service/Database.py index 8fae9f652eab73f577bd383def6d88bbd19418ed..bf970b356a61df10474d024554839b94b57cc610 100644 --- a/src/context/service/Database.py +++ b/src/context/service/Database.py @@ -1,7 +1,7 @@ from typing import Tuple, List from sqlalchemy import MetaData -from sqlalchemy.orm import Session +from sqlalchemy.orm import Session, joinedload from context.service.database.Base import Base import logging from common.orm.backend.Tools import key_to_str @@ -27,8 +27,11 @@ class Database(Session): def create_or_update(self, model): with self.session() as session: att = getattr(model, model.main_pk_name()) + obj = self.get_object(type(model), att) + filt = {model.main_pk_name(): att} - found = session.query(type(model)).filter_by(**filt).one_or_none() + t_model = type(model) + found = session.query(t_model).filter_by(**filt).one_or_none() if found: found = True else: @@ -36,6 +39,9 @@ class Database(Session): session.merge(model) session.commit() + + obj = self.get_object(t_model, att) + return model, found def create(self, model): @@ -93,11 +99,11 @@ class Database(Session): raise NotFoundException(model_class.__name__.replace('Model', ''), main_key) return get - def get_or_create(self, model_class: Base, key_parts: List[str] - ) -> Tuple[Base, bool]: + def get_or_create(self, model_class: Base, key_parts: List[str], filt=None) -> Tuple[Base, bool]: str_key = key_to_str(key_parts) - filt = {model_class.main_pk_name(): key_parts} + if not filt: + filt = {model_class.main_pk_name(): key_parts} with self.session() as session: get = session.query(model_class).filter_by(**filt).one_or_none() if get: @@ -105,7 +111,6 @@ class Database(Session): else: obj = model_class() setattr(obj, model_class.main_pk_name(), str_key) - LOGGER.info(obj.dump()) session.add(obj) session.commit() return obj, True diff --git a/src/context/service/database/ConfigModel.py b/src/context/service/database/ConfigModel.py index 4dcd50c2cc6d010af1f2a745ad4e22c96eb226ed..40069185fc2c7ce43d584fe8b1b0704a22d88e84 100644 --- a/src/context/service/database/ConfigModel.py +++ b/src/context/service/database/ConfigModel.py @@ -40,7 +40,7 @@ class ConfigModel(Base): # pylint: disable=abstract-method config_uuid = Column(UUID(as_uuid=False), primary_key=True) # Relationships - config_rule = relationship("ConfigRuleModel", back_populates="config", lazy="dynamic") + config_rule = relationship("ConfigRuleModel", back_populates="config", lazy='joined') def delete(self) -> None: @@ -48,7 +48,7 @@ class ConfigModel(Base): # pylint: disable=abstract-method for pk,_ in db_config_rule_pks: ConfigRuleModel(self.database, pk).delete() super().delete() - def dump(self): # -> List[Dict]: + def dump(self) -> List[Dict]: config_rules = [] for a in self.config_rule: asdf = a.dump() @@ -62,7 +62,7 @@ class ConfigModel(Base): # pylint: disable=abstract-method class ConfigRuleModel(Base): # pylint: disable=abstract-method __tablename__ = 'ConfigRule' config_rule_uuid = Column(UUID(as_uuid=False), primary_key=True) - config_uuid = Column(UUID(as_uuid=False), ForeignKey("Config.config_uuid"), primary_key=True) + config_uuid = Column(UUID(as_uuid=False), ForeignKey("Config.config_uuid", ondelete='CASCADE'), primary_key=True) action = Column(Enum(ORM_ConfigActionEnum, create_constraint=True, native_enum=True), nullable=False) position = Column(INTEGER, nullable=False) diff --git a/src/context/service/database/ContextModel.py b/src/context/service/database/ContextModel.py index ef1d485bed9937929160ca700d08ed191bc8e7b1..cde774fe49430bf9d4c347533747315562dcdccc 100644 --- a/src/context/service/database/ContextModel.py +++ b/src/context/service/database/ContextModel.py @@ -33,7 +33,8 @@ class ContextModel(Base): def dump_id(self) -> Dict: return {'context_uuid': {'uuid': self.context_uuid}} - def main_pk_name(self): + @staticmethod + def main_pk_name(): return 'context_uuid' """ diff --git a/src/context/service/database/DeviceModel.py b/src/context/service/database/DeviceModel.py index bf8f73c79a6c595eb427e108e0ca610e1f966f76..122da50afbad1f894b03d9caeac8c096ed822cac 100644 --- a/src/context/service/database/DeviceModel.py +++ b/src/context/service/database/DeviceModel.py @@ -49,14 +49,16 @@ class DeviceModel(Base): __tablename__ = 'Device' device_uuid = Column(UUID(as_uuid=False), primary_key=True) device_type = Column(String) - device_config_uuid = Column(UUID(as_uuid=False), ForeignKey("Config.config_uuid")) + device_config_uuid = Column(UUID(as_uuid=False), ForeignKey("Config.config_uuid", ondelete='CASCADE')) device_operational_status = Column(Enum(ORM_DeviceOperationalStatusEnum, create_constraint=False, native_enum=False)) # Relationships - device_config = relationship("ConfigModel", lazy="joined") - driver = relationship("DriverModel", lazy="joined") - endpoints = relationship("EndPointModel", lazy="joined") + device_config = relationship("ConfigModel", passive_deletes="all, delete", lazy="joined") + driver = relationship("DriverModel", passive_deletes=True, back_populates="device") + endpoints = relationship("EndPointModel", passive_deletes=True, back_populates="device") + + # topology = relationship("TopologyModel", lazy="joined") # def delete(self) -> None: # # pylint: disable=import-outside-toplevel @@ -83,13 +85,25 @@ class DeviceModel(Base): return self.device_config.dump() def dump_drivers(self) -> List[int]: - return self.driver.dump() + response = [] + + for a in self.driver: + LOGGER.info('DUMPPPPPPPPPPPPPPPPPPPPPIIIIIIIIIIIIIIIIIIIIIIINNNNNNNNNNNNNNNGGGGGGGGGGGGGGGGGGg') + LOGGER.info('aasdfadsf: {}'.format(a.dump())) + response.append(a.dump()) + + return response def dump_endpoints(self) -> List[Dict]: - return self.endpoints.dump() + response = [] + + for a in self.endpoints: + response.append(a.dump()) + + return response def dump( # pylint: disable=arguments-differ - self, include_config_rules=True, include_drivers=False, include_endpoints=False + self, include_config_rules=True, include_drivers=True, include_endpoints=True ) -> Dict: result = { 'device_id': self.dump_id(), @@ -101,24 +115,26 @@ class DeviceModel(Base): if include_endpoints: result['device_endpoints'] = self.dump_endpoints() return result - def main_pk_name(self): + @staticmethod + def main_pk_name(): return 'device_uuid' class DriverModel(Base): # pylint: disable=abstract-method __tablename__ = 'Driver' - driver_uuid = Column(UUID(as_uuid=False), primary_key=True) - device_uuid = Column(UUID(as_uuid=False), ForeignKey("Device.device_uuid"), primary_key=True) + # driver_uuid = Column(UUID(as_uuid=False), primary_key=True) + device_uuid = Column(UUID(as_uuid=False), ForeignKey("Device.device_uuid", ondelete='CASCADE'), primary_key=True) driver = Column(Enum(ORM_DeviceDriverEnum, create_constraint=False, native_enum=False)) # Relationships - device = relationship("DeviceModel") + device = relationship("DeviceModel", back_populates="driver") def dump(self) -> Dict: return self.driver.value - def main_pk_name(self): - return 'driver_uuid' + @staticmethod + def main_pk_name(): + return 'device_uuid' def set_drivers(database : Database, db_device : DeviceModel, grpc_device_drivers): db_device_pk = db_device.device_uuid diff --git a/src/context/service/database/EndPointModel.py b/src/context/service/database/EndPointModel.py index 669b590e3a8e2b56d8b8efcdf8deb9e99ead23ab..a4381a2e307127dacfb27136c67ab5baa7f2101b 100644 --- a/src/context/service/database/EndPointModel.py +++ b/src/context/service/database/EndPointModel.py @@ -27,14 +27,17 @@ LOGGER = logging.getLogger(__name__) class EndPointModel(Base): __tablename__ = 'EndPoint' - endpoint_uuid = Column(UUID(as_uuid=False), primary_key=True, unique=True) topology_uuid = Column(UUID(as_uuid=False), ForeignKey("Topology.topology_uuid"), primary_key=True) - device_uuid = Column(UUID(as_uuid=False), ForeignKey("Device.device_uuid"), primary_key=True) + device_uuid = Column(UUID(as_uuid=False), ForeignKey("Device.device_uuid", ondelete='CASCADE'), primary_key=True) + endpoint_uuid = Column(UUID(as_uuid=False), primary_key=True, unique=True) endpoint_type = Column(String) # Relationships + kpi_sample_types = relationship("KpiSampleTypeModel", passive_deletes=True, back_populates="EndPoint") + device = relationship("DeviceModel", back_populates="endpoints") - def main_pk_name(self): + @staticmethod + def main_pk_name(): return 'endpoint_uuid' def delete(self) -> None: @@ -44,32 +47,41 @@ class EndPointModel(Base): def dump_id(self) -> Dict: result = { - 'device_uuid': self.device_uuid, + 'device_id': self.device.dump_id(), 'endpoint_uuid': {'uuid': self.endpoint_uuid}, } return result def dump_kpi_sample_types(self) -> List[int]: - db_kpi_sample_type_pks = self.references(KpiSampleTypeModel) - return [KpiSampleTypeModel(self.database, pk).dump() for pk,_ in db_kpi_sample_type_pks] + # db_kpi_sample_type_pks = self.references(KpiSampleTypeModel) + # return [KpiSampleTypeModel(self.database, pk).dump() for pk,_ in db_kpi_sample_type_pks] + response = [] + for a in self.kpi_sample_types: + response.append(a.dump()) + return response def dump( # pylint: disable=arguments-differ self, include_kpi_sample_types=True ) -> Dict: result = { - 'endpoint_uuid': self.dump_id(), + 'endpoint_id': self.dump_id(), 'endpoint_type': self.endpoint_type, } if include_kpi_sample_types: result['kpi_sample_types'] = self.dump_kpi_sample_types() return result + class KpiSampleTypeModel(Base): # pylint: disable=abstract-method __tablename__ = 'KpiSampleType' kpi_uuid = Column(UUID(as_uuid=False), primary_key=True) - endpoint_uuid = Column(UUID(as_uuid=False), ForeignKey("EndPoint.endpoint_uuid")) + endpoint_uuid = Column(UUID(as_uuid=False), ForeignKey("EndPoint.endpoint_uuid", ondelete='CASCADE')) kpi_sample_type = Column(Enum(ORM_KpiSampleTypeEnum, create_constraint=False, native_enum=False)) # __table_args__ = (ForeignKeyConstraint([endpoint_uuid], [EndPointModel.endpoint_uuid]), {}) + + # Relationships + EndPoint = relationship("EndPointModel", passive_deletes=True, back_populates="kpi_sample_types") + def dump(self) -> Dict: return self.kpi_sample_type.value diff --git a/src/context/service/grpc_server/ContextServiceServicerImpl.py b/src/context/service/grpc_server/ContextServiceServicerImpl.py index d104d556772f8691ea001673d1b7133ce7161282..108ab9950e494cc5069de3140c4a5ed29c731161 100644 --- a/src/context/service/grpc_server/ContextServiceServicerImpl.py +++ b/src/context/service/grpc_server/ContextServiceServicerImpl.py @@ -46,7 +46,6 @@ from context.service.database.ConnectionModel import ConnectionModel, set_path from context.service.database.ConstraintModel import set_constraints from context.service.database.EndPointModel import EndPointModel, set_kpi_sample_types from context.service.database.Events import notify_event -from context.service.database.LinkModel import LinkModel from context.service.database.RelationModels import ( ConnectionSubServiceModel, LinkEndPointModel, ServiceEndPointModel, SliceEndPointModel, SliceServiceModel, SliceSubSliceModel, TopologyDeviceModel, TopologyLinkModel) @@ -60,6 +59,7 @@ from context.service.database.TopologyModel import TopologyModel from context.service.database.Events import notify_event from context.service.database.EndPointModel import EndPointModel from context.service.database.EndPointModel import KpiSampleTypeModel +from context.service.database.LinkModel import LinkModel from .Constants import ( CONSUME_TIMEOUT, TOPIC_CONNECTION, TOPIC_CONTEXT, TOPIC_DEVICE, TOPIC_LINK, TOPIC_SERVICE, TOPIC_SLICE, @@ -268,7 +268,7 @@ class ContextServiceServicerImpl(ContextServiceServicer): def ListDevices(self, request: Empty, context : grpc.ServicerContext) -> DeviceList: with self.session() as session: result = session.query(DeviceModel).all() - return DeviceList(devices=[device.dump_id() for device in result]) + return DeviceList(devices=[device.dump() for device in result]) @safe_and_metered_rpc_method(METRICS, LOGGER) def GetDevice(self, request: DeviceId, context : grpc.ServicerContext) -> Device: @@ -278,72 +278,76 @@ class ContextServiceServicerImpl(ContextServiceServicer): if not result: raise NotFoundException(DeviceModel.__name__.replace('Model', ''), device_uuid) - rd = result.dump() + rd = result.dump(include_config_rules=True, include_drivers=True, include_endpoints=True) + rt = Device(**rd) return rt @safe_and_metered_rpc_method(METRICS, LOGGER) def SetDevice(self, request: Device, context : grpc.ServicerContext) -> DeviceId: - device_uuid = request.device_id.device_uuid.uuid + with self.session() as session: + device_uuid = request.device_id.device_uuid.uuid - for i,endpoint in enumerate(request.device_endpoints): - 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: - raise InvalidArgumentException( - 'request.device_endpoints[{:d}].device_id.device_uuid.uuid'.format(i), endpoint_device_uuid, - ['should be == {:s}({:s})'.format('request.device_id.device_uuid.uuid', device_uuid)]) - - config_rules = grpc_config_rules_to_raw(request.device_config.config_rules) - running_config_result = self.update_config(device_uuid, 'running', config_rules) - db_running_config = running_config_result[0][0] - config_uuid = db_running_config.config_uuid - - new_obj = DeviceModel(**{ - 'device_uuid' : device_uuid, - 'device_type' : request.device_type, - 'device_operational_status' : grpc_to_enum__device_operational_status(request.device_operational_status), - 'device_config_uuid' : config_uuid, - }) - result: Tuple[DeviceModel, bool] = self.database.create_or_update(new_obj) - db_device, updated = result + for i,endpoint in enumerate(request.device_endpoints): + 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: + raise InvalidArgumentException( + 'request.device_endpoints[{:d}].device_id.device_uuid.uuid'.format(i), endpoint_device_uuid, + ['should be == {:s}({:s})'.format('request.device_id.device_uuid.uuid', device_uuid)]) - self.set_drivers(db_device, request.device_drivers) + config_rules = grpc_config_rules_to_raw(request.device_config.config_rules) + running_config_result = self.update_config(session, device_uuid, 'running', config_rules) + db_running_config = running_config_result[0][0] + config_uuid = db_running_config.config_uuid - 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 + new_obj = DeviceModel(**{ + 'device_uuid' : device_uuid, + 'device_type' : request.device_type, + 'device_operational_status' : grpc_to_enum__device_operational_status(request.device_operational_status), + 'device_config_uuid' : config_uuid, + }) + result: Tuple[DeviceModel, bool] = self.database.create_or_update(new_obj) + db_device, updated = result - str_endpoint_key = key_to_str([device_uuid, endpoint_uuid]) - endpoint_attributes = { - 'device_uuid' : db_device.device_uuid, - 'endpoint_uuid': endpoint_uuid, - 'endpoint_type': endpoint.endpoint_type, - } + self.set_drivers(db_device, request.device_drivers) - 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_topology_key = key_to_str([endpoint_topology_context_uuid, endpoint_topology_uuid]) + 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 + + str_endpoint_key = key_to_str([device_uuid, endpoint_uuid]) + endpoint_attributes = { + 'device_uuid' : db_device.device_uuid, + 'endpoint_uuid': endpoint_uuid, + 'endpoint_type': endpoint.endpoint_type, + } + + 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_topology_key = key_to_str([endpoint_topology_context_uuid, endpoint_topology_uuid]) - db_topology : TopologyModel = self.database.get_object(TopologyModel, endpoint_topology_uuid) + db_topology: TopologyModel = self.database.get_object(TopologyModel, endpoint_topology_uuid) + new_topo = TopologyModel(context_uuid=db_topology.context_uuid, topology_uuid=db_topology.topology_uuid, device_uuids=db_device.device_uuid) - str_endpoint_key = key_to_str([str_endpoint_key, str_topology_key], separator=':') - endpoint_attributes['topology_uuid'] = db_topology.topology_uuid + self.database.create_or_update(new_topo) - new_endpoint = EndPointModel(**endpoint_attributes) - result : Tuple[EndPointModel, bool] = self.database.create_or_update(new_endpoint) - db_endpoint, updated = result + endpoint_attributes['topology_uuid'] = db_topology.topology_uuid - self.set_kpi_sample_types(db_endpoint, endpoint.kpi_sample_types) + new_endpoint = EndPointModel(**endpoint_attributes) + result : Tuple[EndPointModel, bool] = self.database.create_or_update(new_endpoint) + db_endpoint, updated = result - # event_type = EventTypeEnum.EVENTTYPE_UPDATE if updated else EventTypeEnum.EVENTTYPE_CREATE - dict_device_id = db_device.dump_id() - # notify_event(self.messagebroker, TOPIC_DEVICE, event_type, {'device_id': dict_device_id}) + self.set_kpi_sample_types(db_endpoint, endpoint.kpi_sample_types) - return DeviceId(**dict_device_id) + # event_type = EventTypeEnum.EVENTTYPE_UPDATE if updated else EventTypeEnum.EVENTTYPE_CREATE + dict_device_id = db_device.dump_id() + # notify_event(self.messagebroker, TOPIC_DEVICE, event_type, {'device_id': dict_device_id}) + + return DeviceId(**dict_device_id) def set_kpi_sample_types(self, db_endpoint: EndPointModel, grpc_endpoint_kpi_sample_types): db_endpoint_pk = db_endpoint.endpoint_uuid @@ -362,7 +366,7 @@ class ContextServiceServicerImpl(ContextServiceServicer): orm_driver = grpc_to_enum__device_driver(driver) str_device_driver_key = key_to_str([db_device_pk, orm_driver.name]) driver_config = { - "driver_uuid": str(uuid.uuid4()), + # "driver_uuid": str(uuid.uuid4()), "device_uuid": db_device_pk, "driver": orm_driver.name } @@ -373,13 +377,19 @@ class ContextServiceServicerImpl(ContextServiceServicer): self.database.create_or_update(db_device_driver) def update_config( - self, db_parent_pk: str, config_name: str, + self, session, db_parent_pk: str, config_name: str, raw_config_rules: List[Tuple[ORM_ConfigActionEnum, str, str]] ) -> List[Tuple[Union[ConfigModel, ConfigRuleModel], bool]]: - str_config_key = key_to_str([db_parent_pk, config_name], separator=':') - result = self.database.get_or_create(ConfigModel, db_parent_pk) - db_config, created = result + created = False + + db_config = session.query(ConfigModel).filter_by(**{ConfigModel.main_pk_name(): db_parent_pk}).one_or_none() + if not db_config: + db_config = ConfigModel() + setattr(db_config, ConfigModel.main_pk_name(), db_parent_pk) + session.add(db_config) + session.commit() + created = True LOGGER.info('UPDATED-CONFIG: {}'.format(db_config.dump())) @@ -452,15 +462,16 @@ class ContextServiceServicerImpl(ContextServiceServicer): @safe_and_metered_rpc_method(METRICS, LOGGER) def RemoveDevice(self, request: DeviceId, context : grpc.ServicerContext) -> Empty: - with self.lock: - device_uuid = request.device_uuid.uuid - db_device = DeviceModel(self.database, device_uuid, auto_load=False) - found = db_device.load() - if not found: return Empty() + device_uuid = request.device_uuid.uuid - dict_device_id = db_device.dump_id() - db_device.delete() + with self.session() as session: + result = session.query(DeviceModel).filter_by(device_uuid=device_uuid).one_or_none() + if not result: + return Empty() + dict_device_id = result.dump_id() + session.query(DeviceModel).filter_by(device_uuid=device_uuid).delete() + session.commit() event_type = EventTypeEnum.EVENTTYPE_REMOVE notify_event(self.messagebroker, TOPIC_DEVICE, event_type, {'device_id': dict_device_id}) return Empty() @@ -472,75 +483,86 @@ class ContextServiceServicerImpl(ContextServiceServicer): - """ # ----- Link ------------------------------------------------------------------------------------------------------- @safe_and_metered_rpc_method(METRICS, LOGGER) def ListLinkIds(self, request: Empty, context : grpc.ServicerContext) -> LinkIdList: - with self.lock: - db_links : List[LinkModel] = get_all_objects(self.database, LinkModel) - db_links = sorted(db_links, key=operator.attrgetter('pk')) - return LinkIdList(link_ids=[db_link.dump_id() for db_link in db_links]) + with self.session() as session: + result = session.query(LinkModel).all() + return LinkIdList(link_ids=[db_link.dump_id() for db_link in result]) + @safe_and_metered_rpc_method(METRICS, LOGGER) def ListLinks(self, request: Empty, context : grpc.ServicerContext) -> LinkList: - with self.lock: - db_links : List[LinkModel] = get_all_objects(self.database, LinkModel) - db_links = sorted(db_links, key=operator.attrgetter('pk')) - return LinkList(links=[db_link.dump() for db_link in db_links]) + with self.session() as session: + result = session.query(DeviceModel).all() + return LinkList(links=[db_link.dump() for db_link in result]) @safe_and_metered_rpc_method(METRICS, LOGGER) def GetLink(self, request: LinkId, context : grpc.ServicerContext) -> Link: - with self.lock: - link_uuid = request.link_uuid.uuid - db_link : LinkModel = get_object(self.database, LinkModel, link_uuid) - return Link(**db_link.dump()) + link_uuid = request.link_uuid.uuid + with self.session() as session: + result = session.query(LinkModel).filter(LinkModel.device_uuid == link_uuid).one_or_none() + if not result: + raise NotFoundException(DeviceModel.__name__.replace('Model', ''), link_uuid) - @safe_and_metered_rpc_method(METRICS, LOGGER) - def SetLink(self, request: Link, context : grpc.ServicerContext) -> LinkId: - with self.lock: - link_uuid = request.link_id.link_uuid.uuid - result : Tuple[LinkModel, bool] = update_or_create_object( - self.database, LinkModel, link_uuid, {'link_uuid': link_uuid}) - db_link, updated = result + rd = result.dump() - for endpoint_id in request.link_endpoint_ids: - endpoint_uuid = endpoint_id.endpoint_uuid.uuid - endpoint_device_uuid = endpoint_id.device_id.device_uuid.uuid - endpoint_topology_uuid = endpoint_id.topology_id.topology_uuid.uuid - endpoint_topology_context_uuid = endpoint_id.topology_id.context_id.context_uuid.uuid + rt = Link(**rd) - str_endpoint_key = key_to_str([endpoint_device_uuid, endpoint_uuid]) + return rt - db_topology = None - if len(endpoint_topology_context_uuid) > 0 and len(endpoint_topology_uuid) > 0: - str_topology_key = key_to_str([endpoint_topology_context_uuid, endpoint_topology_uuid]) - db_topology : TopologyModel = get_object(self.database, TopologyModel, str_topology_key) - str_topology_device_key = key_to_str([str_topology_key, endpoint_device_uuid], separator='--') - # check device is in topology - get_object(self.database, TopologyDeviceModel, str_topology_device_key) - str_endpoint_key = key_to_str([str_endpoint_key, str_topology_key], separator=':') - db_endpoint : EndPointModel = get_object(self.database, EndPointModel, str_endpoint_key) - str_link_endpoint_key = key_to_str([link_uuid, endpoint_device_uuid], separator='--') - result : Tuple[LinkEndPointModel, bool] = get_or_create_object( - self.database, LinkEndPointModel, str_link_endpoint_key, { - 'link_fk': db_link, 'endpoint_fk': db_endpoint}) - #db_link_endpoint, link_endpoint_created = result + @safe_and_metered_rpc_method(METRICS, LOGGER) + def SetLink(self, request: Link, context : grpc.ServicerContext) -> LinkId: + link_uuid = request.link_id.link_uuid.uuid - if db_topology is not None: - str_topology_link_key = key_to_str([str_topology_key, link_uuid], separator='--') - result : Tuple[TopologyLinkModel, bool] = get_or_create_object( - self.database, TopologyLinkModel, str_topology_link_key, { - 'topology_fk': db_topology, 'link_fk': db_link}) - #db_topology_link, topology_link_created = result + new_link = LinkModel(**{ + 'lin_uuid': link_uuid + }) + result: Tuple[LinkModel, bool] = self.database.create_or_update(new_link) + db_link, updated = result - event_type = EventTypeEnum.EVENTTYPE_UPDATE if updated else EventTypeEnum.EVENTTYPE_CREATE - dict_link_id = db_link.dump_id() - notify_event(self.messagebroker, TOPIC_LINK, event_type, {'link_id': dict_link_id}) - return LinkId(**dict_link_id) + for endpoint_id in request.link_endpoint_ids: + endpoint_uuid = endpoint_id.endpoint_uuid.uuid + endpoint_device_uuid = endpoint_id.device_id.device_uuid.uuid + endpoint_topology_uuid = endpoint_id.topology_id.topology_uuid.uuid + endpoint_topology_context_uuid = endpoint_id.topology_id.context_id.context_uuid.uuid + + str_endpoint_key = key_to_str([endpoint_device_uuid, endpoint_uuid]) + + if len(endpoint_topology_context_uuid) > 0 and len(endpoint_topology_uuid) > 0: + str_topology_key = key_to_str([endpoint_topology_context_uuid, endpoint_topology_uuid]) + # db_topology : TopologyModel = get_object(self.database, TopologyModel, str_topology_key) + db_topology : TopologyModel = self.database.get_object(TopologyModel, str_topology_key) + str_topology_device_key = key_to_str([str_topology_key, endpoint_device_uuid], separator='--') + # check device is in topology + # get_object(self.database, TopologyDeviceModel, str_topology_device_key) + # str_endpoint_key = key_to_str([str_endpoint_key, str_topology_key], separator=':') + + # db_endpoint : EndPointModel = get_object(self.database, EndPointModel, str_endpoint_key) + LOGGER.info('str_endpoint_key: {}'.format(str_endpoint_key)) + db_endpoint: EndPointModel = self.database.get_object(EndPointModel, str_endpoint_key) + + # str_link_endpoint_key = key_to_str([link_uuid, endpoint_device_uuid], separator='--') + # result : Tuple[LinkEndPointModel, bool] = get_or_create_object( + # self.database, LinkEndPointModel, str_link_endpoint_key, { + # 'link_fk': db_link, 'endpoint_fk': db_endpoint}) + #db_link_endpoint, link_endpoint_created = result + + # if db_topology is not None: + # str_topology_link_key = key_to_str([str_topology_key, link_uuid], separator='--') + # result : Tuple[TopologyLinkModel, bool] = get_or_create_object( + # self.database, TopologyLinkModel, str_topology_link_key, { + # 'topology_fk': db_topology, 'link_fk': db_link}) + # #db_topology_link, topology_link_created = result + + event_type = EventTypeEnum.EVENTTYPE_UPDATE if updated else EventTypeEnum.EVENTTYPE_CREATE + dict_link_id = db_link.dump_id() + notify_event(self.messagebroker, TOPIC_LINK, event_type, {'link_id': dict_link_id}) + return LinkId(**dict_link_id) @safe_and_metered_rpc_method(METRICS, LOGGER) def RemoveLink(self, request: LinkId, context : grpc.ServicerContext) -> Empty: @@ -562,6 +584,7 @@ class ContextServiceServicerImpl(ContextServiceServicer): for message in self.messagebroker.consume({TOPIC_LINK}, consume_timeout=CONSUME_TIMEOUT): yield LinkEvent(**json.loads(message.content)) + """ # ----- Service ----------------------------------------------------------------------------------------------------