Commit 6fa9f14f authored by Lluis Gifre Renom's avatar Lluis Gifre Renom
Browse files

Merge branch...

Merge branch 'feat/63-tid-add-support-to-update-device-inventory-manually-from-webui' into 'develop'

Resolve "(TID) Add support to update device inventory manually from WebUI"

See merge request !468
parents 3a4b412e f5a5c5df
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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 {
+11 −0
Original line number Diff line number Diff line
@@ -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
@@ -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:
@@ -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
+8 −0
Original line number Diff line number Diff line
@@ -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
+60 −2
Original line number Diff line number Diff line
@@ -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
@@ -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__)
@@ -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

+0 −1
Original line number Diff line number Diff line
@@ -66,7 +66,6 @@ end2end_test ecoc22:
    #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/deviceservice.yaml
    #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="frontend").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/pathcompservice.yaml
    #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/serviceservice.yaml
    #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/sliceservice.yaml
    #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/nbiservice.yaml

    - source src/tests/${TEST_NAME}/deploy_specs.sh
Loading