Example #1
0
def _update_component_data(
    device,
    component_data,
    Component,
    field_map,
    unique_fields,
    model_type=None,
    forbidden_model_fields=set(),
):
    """
    Update components of a device based on the data from scan.

    This function is a little tricky, because we want to reuse the
    components as much as possible, instead of deleting everything and
    creating new ones every time.

    :param component_data: list of dicts describing the components
    :param Component: model to use to query and create components
    :param field_map: mapping from database fields to component_data keys
    :param unique_fields: list of tuples of fields that are unique together
    :param model_type: If provided, a 'model' field will be added
    :param forbidden_model_fields: If provided, model will be created
                                   without those fields
    """

    component_ids = []
    for index, data in enumerate(component_data):
        data['device'] = device
        data['index'] = index
        for group in unique_fields:
            # First try to find an existing component using unique fields
            fields = {
                field: data[field_map[field]]
                for field in group
                if data.get(field_map[field]) is not None
            }
            if len(group) != len(fields):
                continue
            try:
                component = Component.objects.get(**fields)
            except Component.DoesNotExist:
                continue
            break
        else:
            # No matching component found, create a new one
            if model_type is not None or 'type' in data:
                # If model_type is provided, create the model
                model = None
                if model_type is None:
                    try:
                        model_type = ComponentType.from_name(data['type'])
                    except ValueError:
                        model_type = None
                if model_type is not None:
                    model_fields = {
                        field: data[field_map[field]]
                        for field in field_map
                        if all((
                            data.get(field_map[field]),
                            field != 'type',
                            field not in forbidden_model_fields,
                        ))
                    }
                    if all((
                        'model_name' in data,
                        'name' not in forbidden_model_fields,
                    )):
                        model_fields['name'] = data['model_name']
                    model, created = ComponentModel.create(
                        model_type,
                        0,
                        **model_fields)
                if model is None:
                    raise ValueError('Unknown model')
                component = Component(model=model)
            else:
                component = Component()
        # Fill the component with values from the data dict
        for field, key in field_map.iteritems():
            if key in data:
                setattr(component, field, data[key])
        component.save(priority=100)
        component_ids.append(component.id)
    # Delete the components that are no longer current
    for component in Component.objects.filter(
        device=device,
    ).exclude(
        id__in=component_ids,
    ):
        component.delete()
Example #2
0
def get_device_data(device):
    """
    Generate a dict with all information that is stored in the database
    about this device, in a format compatible with that returned by the
    discovery plugins.
    """

    data = {
        'id': device.id,
        'system_ip_addresses': [
            ip.address for ip in
            device.ipaddress_set.filter(is_management=False)
        ],
        'management_ip_addresses': [
            ip.address for ip in
            device.ipaddress_set.filter(is_management=True)
        ],
        'mac_addresses': [
            eth.mac for eth in device.ethernet_set.all()
        ],
    }
    if device.name != 'unknown':
        data['hostname'] = device.name
    if device.model is not None:
        data['model_name'] = device.model.name
        data['type'] = DeviceType.from_id(device.model.type).raw
    if device.sn is not None:
        data['serial_number'] = device.sn
    if device.chassis_position:
        data['chassis_position'] = device.chassis_position
    if device.dc:
        data['data_center'] = device.dc
    if device.rack:
        data['rack'] = device.rack
    if device.management:
        data['management'] = device.management.address
    data['memory'] = [
        {
            'label': m.label,
            'size': m.size,
            'speed': m.speed,
            'index': m.index,
        } for m in device.memory_set.order_by('index')
    ]
    data['processors'] = [
        {
            'model_name': p.model.name if p.model else '',
            'speed': p.speed,
            'cores': p.get_cores(),
            'family': p.model.family if p.model else '',
            'label': p.label,
            'index': p.index,
        } for p in device.processor_set.order_by('index')
    ]
    disks = []
    for disk in device.storage_set.order_by('sn', 'mount_point'):
        disk_data = {
            'label': disk.label,
            'size': disk.size,
        }
        if disk.sn:
            disk_data['serial_number'] = disk.sn
        if disk.mount_point:
            disk_data['mount_point'] = disk.mount_point
        if disk.model:
            disk_data.update({
                'model_name': disk.model.name,
                'family': disk.model.family,
            })
        disks.append(disk_data)
    data['disks'] = disks
    data['disk_exports'] = [
        {
            'serial_number': share.wwn,
            'full': share.full,
            'size': share.size,
            'snapshot_size': share.snapshot_size,
            'label': share.label,
            'share_id': share.share_id,
            'model_name': share.model.name if share.model else '',
        } for share in device.diskshare_set.order_by('wwn')
    ]
    disk_shares = []
    for mount in device.disksharemount_set.order_by('volume', 'address'):
        mount_data = {
            'serial_number': mount.share.wwn if mount.share else '',
            'size': mount.size,
            'address': mount.address.address if mount.address else '',
            'is_virtual': mount.is_virtual,
            'volume': mount.volume,
        }
        if mount.server:
            mount_data['server'] = {
                'serial_number': mount.server.sn,
            }
        else:
            mount_data['server'] = None
        disk_shares.append(mount_data)
    data['disk_shares'] = disk_shares
    data['installed_software'] = [
        {
            'label': soft.label,
            'version': soft.version,
            'path': soft.path,
            'serial_number': soft.sn,
            'model_name': soft.model.name if soft.model else '',
        } for soft in device.software_set.order_by('label', 'version')
    ]
    data['fibrechannel_cards'] = [
        {
            'physical_id': fc.physical_id,
            'label': fc.label,
            'model_name': fc.model.name if fc.model else '',
        } for fc in device.fibrechannel_set.order_by('label')
    ]
    data['parts'] = [
        {
            'serial_number': part.sn,
            'label': part.label,
            'boot_firmware': part.boot_firmware,
            'hard_firmware': part.hard_firmware,
            'diag_firmware': part.diag_firmware,
            'mgmt_firmware': part.mgmt_firmware,
            'model_name': part.model.name if part.model else '',
            'type': ComponentType.from_id(
                part.model.type,
            ).raw if part.model else '',
        } for part in device.genericcomponent_set.order_by('sn')
    ]
    if device.model and device.model.type in (DeviceType.switch_stack,):
        data['subdevices'] = [
            get_device_data(dev)
            for dev in device.logicalchild_set.order_by('id')
        ]
    else:
        data['subdevices'] = [
            get_device_data(dev)
            for dev in device.child_set.order_by('id')
        ]
    if device.operatingsystem_set.exists():
        system = device.operatingsystem_set.all()[0]
        data['system_label'] = system.label
        data['system_memory'] = system.memory
        data['system_storage'] = system.storage
        data['system_cores_count'] = system.cores_count
        if system.model:
            data['system_family'] = system.model.family
    if 'ralph_assets' in settings.INSTALLED_APPS:
        from ralph_assets.api_ralph import get_asset
        asset = get_asset(device.id)
        if asset:
            data['asset'] = '{}, sn: {}'.format(asset['model'], asset['sn'])
        else:
            data['asset'] = None
    return data
Example #3
0
File: data.py Project: ar4s/ralph
def _update_component_data(
    device,
    component_data,
    Component,
    field_map,
    unique_fields,
    model_type=None,
    forbidden_model_fields=set(),
    save_priority=SAVE_PRIORITY,
):
    """
    Update components of a device based on the data from scan.

    This function is a little tricky, because we want to reuse the
    components as much as possible, instead of deleting everything and
    creating new ones every time.

    :param component_data: list of dicts describing the components
    :param Component: model to use to query and create components
    :param field_map: mapping from database fields to component_data keys
    :param unique_fields: list of tuples of fields that are unique together
    :param model_type: If provided, a 'model' field will be added
    :param forbidden_model_fields: If provided, model will be created
                                   without those fields
    :param save_priority: Save priority
    """

    component_ids = []
    for index, data in enumerate(component_data):
        model = None
        data['device'] = device
        data['index'] = index
        component = None
        for group in unique_fields:
            # First try to find an existing component using unique fields
            fields = {
                field: data[field_map[field]]
                for field in group
                if data.get(field_map[field]) is not None
            }
            if len(group) != len(fields):
                continue
            try:
                component_to_update = Component.objects.get(**fields)
            except Component.DoesNotExist:
                continue
            else:
                if not component:
                    component = component_to_update
                else:
                    if component.id != component_to_update.id:
                        component_to_update.delete()
        if not component:
            # No matching component found, create a new one
            if model_type is not None or 'type' in data:
                # If model_type is provided, create the model
                if model_type is None:
                    try:
                        model_type = ComponentType.from_name(data['type'])
                    except ValueError:
                        model_type = None
                if model_type is not None:
                    # family is required for disks
                    if model_type == ComponentType.disk:
                        if 'family' not in data or not data['family']:
                            data['family'] = 'Generic disk'
                    model = _get_or_create_model_for_component(
                        model_type,
                        data,
                        field_map,
                        forbidden_model_fields,
                        save_priority=save_priority,
                    )
                if model is None:
                    raise ValueError('Unknown model')
                component = Component(model=model)
            else:
                component = Component()
        # Fill the component with values from the data dict
        for field, key in field_map.iteritems():
            if key in data:
                setattr(component, field, data[key])
        if model_type is not None and model is None:
            try:
                model = _get_or_create_model_for_component(
                    model_type,
                    data,
                    field_map,
                    forbidden_model_fields,
                    save_priority=save_priority,
                )
            except AssertionError:
                pass
            else:
                if model:
                    component.model = model
        component.save(priority=save_priority)
        component_ids.append(component.id)
    # Delete the components that are no longer current
    for component in Component.objects.filter(
        device=device,
    ).exclude(
        id__in=component_ids,
    ):
        component.delete()