Loading proto/device.proto +1 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ service DeviceService { rpc GetInitialConfig (context.DeviceId ) returns (context.DeviceConfig ) {} rpc MonitorDeviceKpi (MonitoringSettings ) returns (context.Empty ) {} rpc SSETelemetrySubscribe(monitoring.SSEMonitoringSubscriptionConfig) returns (monitoring.SSEMonitoringSubscriptionResponse ) {} rpc UpdateDeviceInventory(context.DeviceId ) returns (context.Empty ) {} } message MonitoringSettings { Loading src/context/service/database/ConfigRule.py +3 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,9 @@ def compose_config_rules_data( dict_config_rules : List[Dict] = list() for position,config_rule in enumerate(config_rules): str_kind = config_rule.WhichOneof('config_rule') if device_uuid is not None and str_kind == 'custom': if '/inventory' in config_rule.custom.resource_key: continue kind = ConfigRuleKindEnum._member_map_.get(str_kind.upper()) # pylint: disable=no-member dict_config_rule = { 'position' : position, Loading src/context/service/database/Device.py +12 −1 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ from .models.DeviceModel import DeviceModel from .models.EndPointModel import EndPointModel from .models.ComponentModel import ComponentModel from .models.TopologyModel import TopologyDeviceModel, TopologyModel from .models.ConfigRuleModel import DeviceConfigRuleModel, ConfigRuleKindEnum from .models.enums.DeviceDriver import grpc_to_enum__device_driver from .models.enums.DeviceOperationalStatus import grpc_to_enum__device_operational_status from .models.enums.KpiSampleType import grpc_to_enum__kpi_sample_type Loading Loading @@ -243,6 +244,9 @@ def device_set(db_engine : Engine, messagebroker : MessageBroker, request : Devi device_topology_ids = [obj.dump_id() for obj in device_topologies] #LOGGER.warning('device_topology_ids={:s}'.format(str(device_topology_ids))) # Delete old components of the device to make sure they are fully updated session.query(ComponentModel).filter_by(device_uuid=device_uuid).delete() updated_components = False if len(components_data) > 0: Loading @@ -261,6 +265,13 @@ def device_set(db_engine : Engine, messagebroker : MessageBroker, request : Devi component_updates = session.execute(stmt).fetchall() updated_components = any([(updated_at > created_at) for created_at,updated_at in component_updates]) # Delete old /inventory config rules of the device to make sure they are fully updated session.query(DeviceConfigRuleModel).filter( DeviceConfigRuleModel.device_uuid == device_uuid, DeviceConfigRuleModel.kind == ConfigRuleKindEnum.CUSTOM, DeviceConfigRuleModel.data.contains('/inventory') ).delete(synchronize_session=False) changed_config_rules = upsert_config_rules(session, config_rules, device_uuid=device_uuid) return updated or updated_endpoints or updated_components or changed_config_rules, device_topology_ids Loading Loading @@ -332,7 +343,7 @@ def device_select(db_engine : Engine, request : DeviceFilter) -> DeviceList: query = session.query(DeviceModel) if request.include_endpoints : query = query.options(selectinload(DeviceModel.endpoints)) if request.include_config_rules: query = query.options(selectinload(DeviceModel.config_rules)) #if request.include_components : query = query.options(selectinload(DeviceModel.components)) if request.include_components : query = query.options(selectinload(DeviceModel.components)) obj_list : List[DeviceModel] = query.filter(DeviceModel.device_uuid.in_(device_uuids)).all() return [obj.dump(**dump_params) for obj in obj_list] devices = run_transaction(sessionmaker(bind=db_engine), callback) Loading src/device/client/DeviceClient.py +8 −0 Original line number Diff line number Diff line Loading @@ -113,3 +113,11 @@ class DeviceClient: response = self.stub.SSETelemetrySubscribe(request) LOGGER.debug('SSETelemetrySubscribe result: {:s}'.format(grpc_message_to_json_string(response))) return response @RETRY_DECORATOR def UpdateDeviceInventory(self, request : DeviceId) -> Empty: LOGGER.debug('UpdateDeviceInventory request: {:s}'.format(grpc_message_to_json_string(request))) response = self.stub.UpdateDeviceInventory(request) LOGGER.debug('UpdateDeviceInventory result: {:s}'.format(grpc_message_to_json_string(response))) return response src/device/service/DeviceServiceServicerImpl.py +60 −2 Original line number Diff line number Diff line Loading @@ -21,7 +21,7 @@ from common.method_wrappers.Decorator import MetricTypeEnum, MetricsPool, safe_a from common.method_wrappers.ServiceExceptions import NotFoundException, OperationFailedException from common.proto.context_pb2 import ( Device, DeviceConfig, DeviceDriverEnum, DeviceId, DeviceOperationalStatusEnum, Empty, Link, OpticalConfig, OpticalConfigId OpticalConfig, OpticalConfigId, ConfigActionEnum ) from common.proto.device_pb2 import MonitoringSettings from common.proto.device_pb2_grpc import DeviceServiceServicer Loading @@ -37,7 +37,7 @@ from .Tools import ( check_connect_rules, check_no_endpoints, compute_rules_to_add_delete, configure_rules, deconfigure_rules, get_device_controller_uuid, populate_config_rules, populate_endpoint_monitoring_resources, populate_endpoints, populate_initial_config_rules, subscribe_kpi, unsubscribe_kpi, update_endpoints, update_sap_id, subscribe_kpi, unsubscribe_kpi, update_endpoints, update_sap_id, _raw_config_rules_to_grpc ) LOGGER = logging.getLogger(__name__) Loading Loading @@ -445,3 +445,61 @@ class DeviceServiceServicerImpl(DeviceServiceServicer): ) return SSEMonitoringSubscriptionResponse() @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) def UpdateDeviceInventory(self, request : DeviceId, context : grpc.ServicerContext) -> Empty: device_uuid = request.device_uuid.uuid self.mutex_queues.wait_my_turn(device_uuid) try: context_client = ContextClient() device = get_device(context_client, device_uuid, rw_copy=True) if device is None: raise NotFoundException('Device', device_uuid) driver : _Driver = get_driver(self.driver_instance_cache, device) if driver is None: msg = ERROR_MISSING_DRIVER.format(device_uuid=str(device_uuid)) raise OperationFailedException('UpdateDeviceInventory', extra_details=msg) # Clear and populate endpoints again from the driver del device.device_endpoints[:] new_sub_devices = dict() new_sub_links = dict() sorted_sub_device_uuids = list() new_optical_configs = dict() errors = populate_endpoints( device, driver, self.monitoring_loops, new_sub_devices, sorted_sub_device_uuids, new_sub_links, new_optical_configs ) if len(errors) > 0: raise OperationFailedException('UpdateDeviceInventory', extra_details=errors) from device.service.driver_api._Driver import RESOURCE_INVENTORY results_getconfig = driver.GetConfig([RESOURCE_INVENTORY]) # Filter out existing /inventory rules to prevent duplicates or leftovers new_rules = [] for rule in device.device_config.config_rules: if rule.WhichOneof('config_rule') == 'custom': if '/inventory' in rule.custom.resource_key: continue new_rules.append(rule) del device.device_config.config_rules[:] device.device_config.config_rules.extend(new_rules) # Convert new inventory rules and update device config errors = _raw_config_rules_to_grpc( device_uuid, device.device_config, 'Error getting inventory resource {resource_key} on device {device_uuid}: {error}', ConfigActionEnum.CONFIGACTION_SET, results_getconfig ) if len(errors) > 0: raise OperationFailedException('UpdateDeviceInventory', extra_details=errors) context_client.SetDevice(device) context_client.close() return Empty() except Exception as e: LOGGER.exception('Error updating inventory of device {:s}'.format(str(device_uuid))) raise e Loading
proto/device.proto +1 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ service DeviceService { rpc GetInitialConfig (context.DeviceId ) returns (context.DeviceConfig ) {} rpc MonitorDeviceKpi (MonitoringSettings ) returns (context.Empty ) {} rpc SSETelemetrySubscribe(monitoring.SSEMonitoringSubscriptionConfig) returns (monitoring.SSEMonitoringSubscriptionResponse ) {} rpc UpdateDeviceInventory(context.DeviceId ) returns (context.Empty ) {} } message MonitoringSettings { Loading
src/context/service/database/ConfigRule.py +3 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,9 @@ def compose_config_rules_data( dict_config_rules : List[Dict] = list() for position,config_rule in enumerate(config_rules): str_kind = config_rule.WhichOneof('config_rule') if device_uuid is not None and str_kind == 'custom': if '/inventory' in config_rule.custom.resource_key: continue kind = ConfigRuleKindEnum._member_map_.get(str_kind.upper()) # pylint: disable=no-member dict_config_rule = { 'position' : position, Loading
src/context/service/database/Device.py +12 −1 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ from .models.DeviceModel import DeviceModel from .models.EndPointModel import EndPointModel from .models.ComponentModel import ComponentModel from .models.TopologyModel import TopologyDeviceModel, TopologyModel from .models.ConfigRuleModel import DeviceConfigRuleModel, ConfigRuleKindEnum from .models.enums.DeviceDriver import grpc_to_enum__device_driver from .models.enums.DeviceOperationalStatus import grpc_to_enum__device_operational_status from .models.enums.KpiSampleType import grpc_to_enum__kpi_sample_type Loading Loading @@ -243,6 +244,9 @@ def device_set(db_engine : Engine, messagebroker : MessageBroker, request : Devi device_topology_ids = [obj.dump_id() for obj in device_topologies] #LOGGER.warning('device_topology_ids={:s}'.format(str(device_topology_ids))) # Delete old components of the device to make sure they are fully updated session.query(ComponentModel).filter_by(device_uuid=device_uuid).delete() updated_components = False if len(components_data) > 0: Loading @@ -261,6 +265,13 @@ def device_set(db_engine : Engine, messagebroker : MessageBroker, request : Devi component_updates = session.execute(stmt).fetchall() updated_components = any([(updated_at > created_at) for created_at,updated_at in component_updates]) # Delete old /inventory config rules of the device to make sure they are fully updated session.query(DeviceConfigRuleModel).filter( DeviceConfigRuleModel.device_uuid == device_uuid, DeviceConfigRuleModel.kind == ConfigRuleKindEnum.CUSTOM, DeviceConfigRuleModel.data.contains('/inventory') ).delete(synchronize_session=False) changed_config_rules = upsert_config_rules(session, config_rules, device_uuid=device_uuid) return updated or updated_endpoints or updated_components or changed_config_rules, device_topology_ids Loading Loading @@ -332,7 +343,7 @@ def device_select(db_engine : Engine, request : DeviceFilter) -> DeviceList: query = session.query(DeviceModel) if request.include_endpoints : query = query.options(selectinload(DeviceModel.endpoints)) if request.include_config_rules: query = query.options(selectinload(DeviceModel.config_rules)) #if request.include_components : query = query.options(selectinload(DeviceModel.components)) if request.include_components : query = query.options(selectinload(DeviceModel.components)) obj_list : List[DeviceModel] = query.filter(DeviceModel.device_uuid.in_(device_uuids)).all() return [obj.dump(**dump_params) for obj in obj_list] devices = run_transaction(sessionmaker(bind=db_engine), callback) Loading
src/device/client/DeviceClient.py +8 −0 Original line number Diff line number Diff line Loading @@ -113,3 +113,11 @@ class DeviceClient: response = self.stub.SSETelemetrySubscribe(request) LOGGER.debug('SSETelemetrySubscribe result: {:s}'.format(grpc_message_to_json_string(response))) return response @RETRY_DECORATOR def UpdateDeviceInventory(self, request : DeviceId) -> Empty: LOGGER.debug('UpdateDeviceInventory request: {:s}'.format(grpc_message_to_json_string(request))) response = self.stub.UpdateDeviceInventory(request) LOGGER.debug('UpdateDeviceInventory result: {:s}'.format(grpc_message_to_json_string(response))) return response
src/device/service/DeviceServiceServicerImpl.py +60 −2 Original line number Diff line number Diff line Loading @@ -21,7 +21,7 @@ from common.method_wrappers.Decorator import MetricTypeEnum, MetricsPool, safe_a from common.method_wrappers.ServiceExceptions import NotFoundException, OperationFailedException from common.proto.context_pb2 import ( Device, DeviceConfig, DeviceDriverEnum, DeviceId, DeviceOperationalStatusEnum, Empty, Link, OpticalConfig, OpticalConfigId OpticalConfig, OpticalConfigId, ConfigActionEnum ) from common.proto.device_pb2 import MonitoringSettings from common.proto.device_pb2_grpc import DeviceServiceServicer Loading @@ -37,7 +37,7 @@ from .Tools import ( check_connect_rules, check_no_endpoints, compute_rules_to_add_delete, configure_rules, deconfigure_rules, get_device_controller_uuid, populate_config_rules, populate_endpoint_monitoring_resources, populate_endpoints, populate_initial_config_rules, subscribe_kpi, unsubscribe_kpi, update_endpoints, update_sap_id, subscribe_kpi, unsubscribe_kpi, update_endpoints, update_sap_id, _raw_config_rules_to_grpc ) LOGGER = logging.getLogger(__name__) Loading Loading @@ -445,3 +445,61 @@ class DeviceServiceServicerImpl(DeviceServiceServicer): ) return SSEMonitoringSubscriptionResponse() @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) def UpdateDeviceInventory(self, request : DeviceId, context : grpc.ServicerContext) -> Empty: device_uuid = request.device_uuid.uuid self.mutex_queues.wait_my_turn(device_uuid) try: context_client = ContextClient() device = get_device(context_client, device_uuid, rw_copy=True) if device is None: raise NotFoundException('Device', device_uuid) driver : _Driver = get_driver(self.driver_instance_cache, device) if driver is None: msg = ERROR_MISSING_DRIVER.format(device_uuid=str(device_uuid)) raise OperationFailedException('UpdateDeviceInventory', extra_details=msg) # Clear and populate endpoints again from the driver del device.device_endpoints[:] new_sub_devices = dict() new_sub_links = dict() sorted_sub_device_uuids = list() new_optical_configs = dict() errors = populate_endpoints( device, driver, self.monitoring_loops, new_sub_devices, sorted_sub_device_uuids, new_sub_links, new_optical_configs ) if len(errors) > 0: raise OperationFailedException('UpdateDeviceInventory', extra_details=errors) from device.service.driver_api._Driver import RESOURCE_INVENTORY results_getconfig = driver.GetConfig([RESOURCE_INVENTORY]) # Filter out existing /inventory rules to prevent duplicates or leftovers new_rules = [] for rule in device.device_config.config_rules: if rule.WhichOneof('config_rule') == 'custom': if '/inventory' in rule.custom.resource_key: continue new_rules.append(rule) del device.device_config.config_rules[:] device.device_config.config_rules.extend(new_rules) # Convert new inventory rules and update device config errors = _raw_config_rules_to_grpc( device_uuid, device.device_config, 'Error getting inventory resource {resource_key} on device {device_uuid}: {error}', ConfigActionEnum.CONFIGACTION_SET, results_getconfig ) if len(errors) > 0: raise OperationFailedException('UpdateDeviceInventory', extra_details=errors) context_client.SetDevice(device) context_client.close() return Empty() except Exception as e: LOGGER.exception('Error updating inventory of device {:s}'.format(str(device_uuid))) raise e