Beispiel #1
0
def set_device_data(device, data, save_priority=SAVE_PRIORITY, warnings=[]):
    """
    Go through the submitted data, and update the Device object
    in accordance with the meaning of the particular fields.
    """

    keys = {
        'sn': 'serial_number',
        'name': 'hostname',
        'dc': 'data_center',
        'rack': 'rack',
        'barcode': 'barcode',
        'chassis_position': 'chassis_position',
    }
    can_edit_position = check_if_can_edit_position(data)
    for field_name, key_name in keys.iteritems():
        if key_name in data:
            if all((
                    not can_edit_position,
                    field_name in ('dc', 'rack', 'chassis_position'),
            )):
                warnings.append(
                    'You can not set data for `{}` here - skipped. Use assets '
                    'module.'.format(key_name), )
                continue
            setattr(device, field_name, data[key_name])
    if 'model_name' in data and (data['model_name'] or '').strip():
        try:
            model_type = get_choice_by_name(DeviceType,
                                            data.get('type', 'unknown'))
        except ValueError:
            model_type = DeviceType.unknown
        try:
            # Don't use get_or_create, because we are in transaction
            device.model = DeviceModel.objects.get(
                name=data['model_name'],
                type=model_type,
            )
        except DeviceModel.DoesNotExist:
            model = DeviceModel(
                name=data['model_name'],
                type=model_type,
            )
            try:
                model.save()
            except IntegrityError:
                if model_type != DeviceType.unknown:
                    try:
                        device.model = DeviceModel.objects.get(
                            name='%s (%s)' %
                            (data['model_name'], model_type.raw),
                            type=model_type,
                        )
                    except DeviceModel.DoesNotExist:
                        model = DeviceModel(
                            type=model_type,
                            name='%s (%s)' %
                            (data['model_name'], model_type.raw),
                        )
                        try:
                            model.save()
                        except IntegrityError:
                            pass
                        else:
                            device.model = model
            else:
                device.model = model
    if 'disks' in data:
        _update_component_data(
            device,
            data['disks'],
            Storage,
            {
                'sn': 'serial_number',
                'device': 'device',
                'size': 'size',
                'speed': 'speed',
                'mount_point': 'mount_point',
                'label': 'label',
                'family': 'family',
                'model_name': 'model_name',
            },
            [
                ('sn', ),
                ('device', 'mount_point'),
            ],
            ComponentType.disk,
            {'name'},
            save_priority=save_priority,
        )
    if 'processors' in data:
        for index, processor in enumerate(data['processors']):
            processor['index'] = index
        _update_component_data(
            device,
            data['processors'],
            Processor,
            {
                'device': 'device',
                'label': 'label',
                'speed': 'speed',
                'cores': 'cores',
                'family': 'family',
                'index': 'index',
                'model_name': 'model_name',
            },
            [
                ('device', 'index'),
            ],
            ComponentType.processor,
            save_priority=save_priority,
        )
    if 'memory' in data:
        for index, memory in enumerate(data['memory']):
            memory['index'] = index
            memory['speed'] = memory.get('speed', None) or None
        _update_component_data(
            device,
            data['memory'],
            Memory,
            {
                'device': 'device',
                'label': 'label',
                'speed': 'speed',
                'size': 'size',
                'index': 'index',
            },
            [
                ('device', 'index'),
            ],
            ComponentType.memory,
            {'name'},
            save_priority=save_priority,
        )
    if 'mac_addresses' in data:
        _update_component_data(
            device,
            [{
                'mac': mac
            } for mac in data['mac_addresses']],
            Ethernet,
            {
                'mac': 'mac',
                'device': 'device',
            },
            [('mac', )],
            None,
            save_priority=save_priority,
        )
    if 'management_ip_addresses' in data:
        if not data.get('asset'):
            _update_addresses(device, data['management_ip_addresses'], True)
        else:
            warnings.append(
                'Management IP addresses ({}) have been ignored. To change '
                'them, please use the Assets module.'.format(
                    ', '.join(data['management_ip_addresses']), ), )
    if 'system_ip_addresses' in data:
        _update_addresses(device, data['system_ip_addresses'], False)
    if 'management' in data:
        if not data.get('asset'):
            device.management, created = IPAddress.concurrent_get_or_create(
                address=data['management'],
                defaults={'is_management': True},
            )
        else:
            warnings.append(
                'Management IP address ({}) has been ignored. To change '
                'them, please use the Assets module.'.format(
                    data['management'], ), )
    if 'fibrechannel_cards' in data:
        _update_component_data(
            device,
            data['fibrechannel_cards'],
            FibreChannel,
            {
                'device': 'device',
                'label': 'label',
                'model_name': 'model_name',
                'physical_id': 'physical_id',
            },
            [
                ('physical_id', 'device'),
            ],
            ComponentType.fibre,
            save_priority=save_priority,
        )
    if 'parts' in data:
        _update_component_data(
            device,
            data['parts'],
            GenericComponent,
            {
                'device': 'device',
                'label': 'label',
                'model_name': 'model_name',
                'sn': 'serial_number',
                'type': 'type',
            },
            [
                ('sn', ),
            ],
            save_priority=save_priority,
        )
    if 'disk_exports' in data:
        _update_component_data(
            device,
            data['disk_exports'],
            DiskShare,
            {
                'device': 'device',
                'label': 'label',
                'wwn': 'serial_number',
                'size': 'size',
                'full': 'full',
                'snapshot_size': 'snapshot_size',
                'share_id': 'share_id',
                'model_name': 'model_name',
            },
            [
                ('wwn', ),
            ],
            ComponentType.share,
            save_priority=save_priority,
        )
    if 'disk_shares' in data:
        shares = []
        for share in data['disk_shares']:
            if share.get('server'):
                servers = find_devices({
                    'server': share['server'],
                })
                if len(servers) > 1:
                    raise ValueError(
                        "Multiple servers found for share mount %r" % share, )
                elif len(servers) <= 0:
                    raise ValueError(
                        "No server found for share mount %r" % share, )
                share['server'] = servers[0]
            else:
                share['server'] = None
            try:
                share['share'] = DiskShare.objects.get(
                    wwn=share['serial_number'])
            except DiskShare.DoesNotExist:
                warnings.append('No share found for share mount: %r' % share)
                continue
            if share.get('address'):
                try:
                    share['address'] = IPAddress.objects.get(
                        address=share['address'], )
                except IPAddress.DoesNotExist:
                    warnings.append('No IP address found for share mount: %r' %
                                    share)
                    continue
            elif 'address' in share:
                del share['address']
            shares.append(share)
        _update_component_data(
            device,
            shares,
            DiskShareMount,
            {
                'share': 'share',
                'size': 'size',
                'address': 'address',
                'is_virtual': 'is_virtual',
                'volume': 'volume',
                'server': 'server',
                'device': 'device',
            },
            [
                ('device', 'share'),
            ],
            save_priority=save_priority,
        )
    if 'installed_software' in data:
        _update_component_data(
            device,
            data['installed_software'],
            Software,
            {
                'device': 'device',
                'path': 'path',
                'label': 'label',
                'version': 'version',
                'model_name': 'model_name',
                'sn': 'serial_number',
            },
            [
                ('device', 'path'),
            ],
            ComponentType.software,
            save_priority=save_priority,
        )
    if ('system_label' in data or 'system_memory' in data
            or 'system_storage' in data or 'system_cores_count' in data
            or 'system_family' in data or 'system_model_name' in data):
        _update_component_data(
            device,
            [data],
            OperatingSystem,
            {
                'device': 'device',
                'memory': 'system_memory',
                'storage': 'system_storage',
                'cores_count': 'system_cores_count',
                'family': 'system_family',
                'label': 'system_label',
                'model_name': 'system_model_name',
            },
            [
                ('device', ),
            ],
            ComponentType.os,
            save_priority=save_priority,
        )
    if 'subdevices' in data:
        subdevice_ids = []
        for subdevice_data in data['subdevices']:
            subdevice = device_from_data(subdevice_data,
                                         save_priority=save_priority,
                                         warnings=warnings)
            if has_logical_children(device):
                subdevice.logical_parent = device
                if subdevice.parent and subdevice.parent.id == device.id:
                    subdevice.parent = None
            else:
                subdevice.parent = device
            subdevice.save(priority=save_priority)
            subdevice_ids.append(subdevice.id)
        set_, parent_attr = ((device.logicalchild_set, 'logical_parent')
                             if has_logical_children(device) else
                             (device.child_set, 'parent'))
        for subdevice in set_.exclude(id__in=subdevice_ids):
            setattr(subdevice, parent_attr, None)
            subdevice.save(priority=save_priority)
    if 'connections' in data:
        parsed_connections = set()
        for connection_data in data['connections']:
            connection = connection_from_data(device, connection_data)
            if connection.connection_type == ConnectionType.network:
                connetion_details = connection_data.get('details', {})
                if connetion_details:
                    outbound_port = connetion_details.get('outbound_port')
                    inbound_port = connetion_details.get('inbound_port')
                    try:
                        details = NetworkConnection.objects.get(
                            connection=connection)
                    except NetworkConnection.DoesNotExist:
                        details = NetworkConnection(connection=connection)
                    if outbound_port:
                        details.outbound_port = outbound_port
                    if inbound_port:
                        details.inbound_port = inbound_port
                    details.save()
            parsed_connections.add(connection.pk)
        device.outbound_connections.exclude(pk__in=parsed_connections).delete()
    if 'asset' in data and 'ralph_assets' in settings.INSTALLED_APPS:
        from ralph_assets.api_ralph import assign_asset
        asset = data['asset']
        if asset and not isinstance(asset, Asset):
            asset = get_asset_by_name(asset)
        if asset:
            assign_asset(device.id, asset.id)
Beispiel #2
0
def set_device_data(device, data, save_priority=SAVE_PRIORITY, warnings=[]):
    """
    Go through the submitted data, and update the Device object
    in accordance with the meaning of the particular fields.
    """

    keys = {
        'sn': 'serial_number',
        'name': 'hostname',
        'dc': 'data_center',
        'rack': 'rack',
        'barcode': 'barcode',
        'chassis_position': 'chassis_position',
    }
    for field_name, key_name in keys.iteritems():
        if key_name in data:
            setattr(device, field_name, data[key_name])
    if 'model_name' in data and (data['model_name'] or '').strip():
        try:
            model_type = _get_choice_by_name(
                DeviceType,
                data.get('type', 'unknown')
            )
        except ValueError:
            model_type = DeviceType.unknown
        try:
            # Don't use get_or_create, because we are in transaction
            device.model = DeviceModel.objects.get(
                name=data['model_name'],
                type=model_type,
            )
        except DeviceModel.DoesNotExist:
            model = DeviceModel(
                name=data['model_name'],
                type=model_type,
            )
            try:
                model.save()
            except IntegrityError:
                if model_type != DeviceType.unknown:
                    try:
                        device.model = DeviceModel.objects.get(
                            name='%s (%s)' % (
                                data['model_name'], model_type.raw
                            ),
                            type=model_type,
                        )
                    except DeviceModel.DoesNotExist:
                        model = DeviceModel(
                            type=model_type,
                            name='%s (%s)' % (
                                data['model_name'], model_type.raw
                            ),
                        )
                        try:
                            model.save()
                        except IntegrityError:
                            pass
                        else:
                            device.model = model
            else:
                device.model = model
    if 'disks' in data:
        _update_component_data(
            device,
            data['disks'],
            Storage,
            {
                'sn': 'serial_number',
                'device': 'device',
                'size': 'size',
                'speed': 'speed',
                'mount_point': 'mount_point',
                'label': 'label',
                'family': 'family',
                'model_name': 'model_name',
            },
            [
                ('sn',),
                ('device', 'mount_point'),
            ],
            ComponentType.disk,
            {'name'},
            save_priority=save_priority,
        )
    if 'processors' in data:
        for index, processor in enumerate(data['processors']):
            processor['index'] = index
        _update_component_data(
            device,
            data['processors'],
            Processor,
            {
                'device': 'device',
                'label': 'label',
                'speed': 'speed',
                'cores': 'cores',
                'family': 'family',
                'index': 'index',
                'model_name': 'model_name',
            },
            [
                ('device', 'index'),
            ],
            ComponentType.processor,
            save_priority=save_priority,
        )
    if 'memory' in data:
        for index, memory in enumerate(data['memory']):
            memory['index'] = index
            memory['speed'] = memory.get('speed', None) or None
        _update_component_data(
            device,
            data['memory'],
            Memory,
            {
                'device': 'device',
                'label': 'label',
                'speed': 'speed',
                'size': 'size',
                'index': 'index',
            },
            [
                ('device', 'index'),
            ],
            ComponentType.memory,
            {'name'},
            save_priority=save_priority,
        )
    if 'mac_addresses' in data:
        _update_component_data(
            device,
            [{'mac': mac} for mac in data['mac_addresses']],
            Ethernet,
            {
                'mac': 'mac',
                'device': 'device',
            },
            [('mac',)],
            None,
            save_priority=save_priority,
        )
    if 'management_ip_addresses' in data:
        _update_addresses(device, data['management_ip_addresses'], True)
    if 'system_ip_addresses' in data:
        _update_addresses(device, data['system_ip_addresses'], False)
    if 'management' in data:
        device.management, created = IPAddress.concurrent_get_or_create(
            address=data['management']
        )
    if 'fibrechannel_cards' in data:
        _update_component_data(
            device,
            data['fibrechannel_cards'],
            FibreChannel,
            {
                'device': 'device',
                'label': 'label',
                'model_name': 'model_name',
                'physical_id': 'physical_id',
            },
            [
                ('physical_id', 'device'),
            ],
            ComponentType.fibre,
            save_priority=save_priority,
        )
    if 'parts' in data:
        _update_component_data(
            device,
            data['parts'],
            GenericComponent,
            {
                'device': 'device',
                'label': 'label',
                'model_name': 'model_name',
                'sn': 'serial_number',
                'type': 'type',
            },
            [
                ('sn',),
            ],
            save_priority=save_priority,
        )
    if 'disk_exports' in data:
        _update_component_data(
            device,
            data['disk_exports'],
            DiskShare,
            {
                'device': 'device',
                'label': 'label',
                'wwn': 'serial_number',
                'size': 'size',
                'full': 'full',
                'snapshot_size': 'snapshot_size',
                'share_id': 'share_id',
                'model_name': 'model_name',
            },
            [
                ('wwn',),
            ],
            ComponentType.share,
            save_priority=save_priority,
        )
    if 'disk_shares' in data:
        shares = []
        for share in data['disk_shares']:
            if share.get('server'):
                servers = find_devices({
                    'server': share['server'],
                })
                if len(servers) > 1:
                    raise ValueError(
                        "Multiple servers found for share mount %r" % share,
                    )
                elif len(servers) <= 0:
                    raise ValueError(
                        "No server found for share mount %r" % share,
                    )
                share['server'] = servers[0]
            else:
                share['server'] = None
            try:
                share['share'] = DiskShare.objects.get(
                    wwn=share['serial_number']
                )
            except DiskShare.DoesNotExist:
                warnings.append(
                    'No share found for share mount: %r' % share
                )
                continue
            if share.get('address'):
                try:
                    share['address'] = IPAddress.objects.get(
                        address=share['address'],
                    )
                except IPAddress.DoesNotExist:
                    warnings.append(
                        'No IP address found for share mount: %r' % share
                    )
                    continue
            elif 'address' in share:
                del share['address']
            shares.append(share)
        _update_component_data(
            device,
            shares,
            DiskShareMount,
            {
                'share': 'share',
                'size': 'size',
                'address': 'address',
                'is_virtual': 'is_virtual',
                'volume': 'volume',
                'server': 'server',
                'device': 'device',
            },
            [
                ('device', 'share'),
            ],
            save_priority=save_priority,
        )
    if 'installed_software' in data:
        _update_component_data(
            device,
            data['installed_software'],
            Software,
            {
                'device': 'device',
                'path': 'path',
                'label': 'label',
                'version': 'version',
                'model_name': 'model_name',
                'sn': 'serial_number',
            },
            [
                ('device', 'path'),
            ],
            ComponentType.software,
            save_priority=save_priority,
        )
    if (
        'system_label' in data or
        'system_memory' in data or
        'system_storage' in data or
        'system_cores_count' in data or
        'system_family' in data or
        'system_model_name' in data
    ):
        _update_component_data(
            device,
            [data],
            OperatingSystem,
            {
                'device': 'device',
                'memory': 'system_memory',
                'storage': 'system_storage',
                'cores_count': 'system_cores_count',
                'family': 'system_family',
                'label': 'system_label',
                'model_name': 'system_model_name',
            },
            [
                ('device',),
            ],
            ComponentType.os,
            save_priority=save_priority,
        )
    if 'subdevices' in data:
        subdevice_ids = []
        for subdevice_data in data['subdevices']:
            subdevice = device_from_data(
                subdevice_data,
                save_priority=save_priority,
                warnings=warnings
            )
            if (
                device.model and
                device.model.type in (DeviceType.switch_stack,)
            ):
                subdevice.logical_parent = device
                if subdevice.parent and subdevice.parent.id == device.id:
                    subdevice.parent = None
            else:
                subdevice.parent = device
            subdevice.save(priority=save_priority)
            subdevice_ids.append(subdevice.id)
        for subdevice in device.child_set.exclude(id__in=subdevice_ids):
            subdevice.parent = None
            subdevice.save(priority=save_priority)
    if 'asset' in data and 'ralph_assets' in settings.INSTALLED_APPS:
        from ralph_assets.api_ralph import assign_asset
        if data['asset']:
            try:
                asset_id = data['asset'].id
            except AttributeError:
                pass
            else:
                assign_asset(device.id, asset_id)
Beispiel #3
0
def set_device_data(device, data, save_priority=SAVE_PRIORITY, warnings=[]):
    """
    Go through the submitted data, and update the Device object
    in accordance with the meaning of the particular fields.
    """

    keys = {
        'sn': 'serial_number',
        'name': 'hostname',
        'dc': 'data_center',
        'rack': 'rack',
        'barcode': 'barcode',
        'chassis_position': 'chassis_position',
    }
    can_edit_position = check_if_can_edit_position(data)
    for field_name, key_name in keys.iteritems():
        if key_name in data:
            if all((
                not can_edit_position,
                field_name in ('dc', 'rack', 'chassis_position'),
            )):
                warnings.append(
                    'You can not set data for `{}` here - skipped. Use assets '
                    'module.'.format(key_name),
                )
                continue
            setattr(device, field_name, data[key_name])
    if 'model_name' in data and (data['model_name'] or '').strip():
        try:
            model_type = get_choice_by_name(
                DeviceType,
                data.get('type', 'unknown')
            )
        except ValueError:
            model_type = DeviceType.unknown
        try:
            # Don't use get_or_create, because we are in transaction
            device.model = DeviceModel.objects.get(
                name=data['model_name'],
                type=model_type,
            )
        except DeviceModel.DoesNotExist:
            model = DeviceModel(
                name=data['model_name'],
                type=model_type,
            )
            try:
                model.save()
            except IntegrityError:
                if model_type != DeviceType.unknown:
                    try:
                        device.model = DeviceModel.objects.get(
                            name='%s (%s)' % (
                                data['model_name'], model_type.raw
                            ),
                            type=model_type,
                        )
                    except DeviceModel.DoesNotExist:
                        model = DeviceModel(
                            type=model_type,
                            name='%s (%s)' % (
                                data['model_name'], model_type.raw
                            ),
                        )
                        try:
                            model.save()
                        except IntegrityError:
                            pass
                        else:
                            device.model = model
            else:
                device.model = model
    if 'disks' in data:
        _update_component_data(
            device,
            data['disks'],
            Storage,
            {
                'sn': 'serial_number',
                'device': 'device',
                'size': 'size',
                'speed': 'speed',
                'mount_point': 'mount_point',
                'label': 'label',
                'family': 'family',
                'model_name': 'model_name',
            },
            [
                ('sn',),
                ('device', 'mount_point'),
            ],
            ComponentType.disk,
            {'name'},
            save_priority=save_priority,
        )
    if 'processors' in data:
        for index, processor in enumerate(data['processors']):
            processor['index'] = index
        _update_component_data(
            device,
            data['processors'],
            Processor,
            {
                'device': 'device',
                'label': 'label',
                'speed': 'speed',
                'cores': 'cores',
                'family': 'family',
                'index': 'index',
                'model_name': 'model_name',
            },
            [
                ('device', 'index'),
            ],
            ComponentType.processor,
            save_priority=save_priority,
        )
    if 'memory' in data:
        for index, memory in enumerate(data['memory']):
            memory['index'] = index
            memory['speed'] = memory.get('speed', None) or None
        _update_component_data(
            device,
            data['memory'],
            Memory,
            {
                'device': 'device',
                'label': 'label',
                'speed': 'speed',
                'size': 'size',
                'index': 'index',
            },
            [
                ('device', 'index'),
            ],
            ComponentType.memory,
            {'name'},
            save_priority=save_priority,
        )
    if 'mac_addresses' in data:
        _update_component_data(
            device,
            [{'mac': mac} for mac in data['mac_addresses']],
            Ethernet,
            {
                'mac': 'mac',
                'device': 'device',
            },
            [('mac',)],
            None,
            save_priority=save_priority,
        )
    if 'management_ip_addresses' in data:
        if not data.get('asset'):
            _update_addresses(device, data['management_ip_addresses'], True)
        else:
            warnings.append(
                'Management IP addresses ({}) have been ignored. To change '
                'them, please use the Assets module.'.format(
                    ', '.join(data['management_ip_addresses']),
                ),
            )
    if 'system_ip_addresses' in data:
        _update_addresses(device, data['system_ip_addresses'], False)
    if 'management' in data:
        if not data.get('asset'):
            device.management, created = IPAddress.concurrent_get_or_create(
                address=data['management'], defaults={'is_management': True},
            )
        else:
            warnings.append(
                'Management IP address ({}) has been ignored. To change '
                'them, please use the Assets module.'.format(
                    data['management'],
                ),
            )
    if 'fibrechannel_cards' in data:
        _update_component_data(
            device,
            data['fibrechannel_cards'],
            FibreChannel,
            {
                'device': 'device',
                'label': 'label',
                'model_name': 'model_name',
                'physical_id': 'physical_id',
            },
            [
                ('physical_id', 'device'),
            ],
            ComponentType.fibre,
            save_priority=save_priority,
        )
    if 'parts' in data:
        _update_component_data(
            device,
            data['parts'],
            GenericComponent,
            {
                'device': 'device',
                'label': 'label',
                'model_name': 'model_name',
                'sn': 'serial_number',
                'type': 'type',
            },
            [
                ('sn',),
            ],
            save_priority=save_priority,
        )
    if 'disk_exports' in data:
        _update_component_data(
            device,
            data['disk_exports'],
            DiskShare,
            {
                'device': 'device',
                'label': 'label',
                'wwn': 'serial_number',
                'size': 'size',
                'full': 'full',
                'snapshot_size': 'snapshot_size',
                'share_id': 'share_id',
                'model_name': 'model_name',
            },
            [
                ('wwn',),
            ],
            ComponentType.share,
            save_priority=save_priority,
        )
    if 'disk_shares' in data:
        shares = []
        for share in data['disk_shares']:
            if share.get('server'):
                servers = find_devices({
                    'server': share['server'],
                })
                if len(servers) > 1:
                    raise ValueError(
                        "Multiple servers found for share mount %r" % share,
                    )
                elif len(servers) <= 0:
                    raise ValueError(
                        "No server found for share mount %r" % share,
                    )
                share['server'] = servers[0]
            else:
                share['server'] = None
            try:
                share['share'] = DiskShare.objects.get(
                    wwn=share['serial_number']
                )
            except DiskShare.DoesNotExist:
                warnings.append(
                    'No share found for share mount: %r' % share
                )
                continue
            if share.get('address'):
                try:
                    share['address'] = IPAddress.objects.get(
                        address=share['address'],
                    )
                except IPAddress.DoesNotExist:
                    warnings.append(
                        'No IP address found for share mount: %r' % share
                    )
                    continue
            elif 'address' in share:
                del share['address']
            shares.append(share)
        _update_component_data(
            device,
            shares,
            DiskShareMount,
            {
                'share': 'share',
                'size': 'size',
                'address': 'address',
                'is_virtual': 'is_virtual',
                'volume': 'volume',
                'server': 'server',
                'device': 'device',
            },
            [
                ('device', 'share'),
            ],
            save_priority=save_priority,
        )
    if 'installed_software' in data:
        _update_component_data(
            device,
            data['installed_software'],
            Software,
            {
                'device': 'device',
                'path': 'path',
                'label': 'label',
                'version': 'version',
                'model_name': 'model_name',
                'sn': 'serial_number',
            },
            [
                ('device', 'path'),
            ],
            ComponentType.software,
            save_priority=save_priority,
        )
    if (
        'system_label' in data or
        'system_memory' in data or
        'system_storage' in data or
        'system_cores_count' in data or
        'system_family' in data or
        'system_model_name' in data
    ):
        _update_component_data(
            device,
            [data],
            OperatingSystem,
            {
                'device': 'device',
                'memory': 'system_memory',
                'storage': 'system_storage',
                'cores_count': 'system_cores_count',
                'family': 'system_family',
                'label': 'system_label',
                'model_name': 'system_model_name',
            },
            [
                ('device',),
            ],
            ComponentType.os,
            save_priority=save_priority,
        )
    if 'subdevices' in data:
        subdevice_ids = []
        for subdevice_data in data['subdevices']:
            subdevice = device_from_data(
                subdevice_data,
                save_priority=save_priority,
                warnings=warnings
            )
            if has_logical_children(device):
                subdevice.logical_parent = device
                if subdevice.parent and subdevice.parent.id == device.id:
                    subdevice.parent = None
            else:
                subdevice.parent = device
            subdevice.save(priority=save_priority)
            subdevice_ids.append(subdevice.id)
        set_, parent_attr = (
            (device.logicalchild_set, 'logical_parent')
            if has_logical_children(device)
            else (device.child_set, 'parent')
        )
        for subdevice in set_.exclude(id__in=subdevice_ids):
            setattr(subdevice, parent_attr, None)
            subdevice.save(priority=save_priority)
    if 'connections' in data:
        parsed_connections = set()
        for connection_data in data['connections']:
            connection = connection_from_data(device, connection_data)
            if connection.connection_type == ConnectionType.network:
                connetion_details = connection_data.get('details', {})
                if connetion_details:
                    outbound_port = connetion_details.get('outbound_port')
                    inbound_port = connetion_details.get('inbound_port')
                    try:
                        details = NetworkConnection.objects.get(
                            connection=connection
                        )
                    except NetworkConnection.DoesNotExist:
                        details = NetworkConnection(connection=connection)
                    if outbound_port:
                        details.outbound_port = outbound_port
                    if inbound_port:
                        details.inbound_port = inbound_port
                    details.save()
            parsed_connections.add(connection.pk)
        device.outbound_connections.exclude(
            pk__in=parsed_connections
        ).delete()
    if 'asset' in data and 'ralph_assets' in settings.INSTALLED_APPS:
        from ralph_assets.api_ralph import assign_asset
        asset = data['asset']
        if asset and not isinstance(asset, Asset):
            asset = get_asset_by_name(asset)
        if asset:
            assign_asset(device.id, asset.id)