Bug 1474753

Summary: Having both an empty floppy and an empty cdrom makes VDSM generate invalid internal device config
Product: [oVirt] vdsm Reporter: Sergio Lopez <slopezpa>
Component: CoreAssignee: Dan Kenigsberg <danken>
Status: CLOSED INSUFFICIENT_DATA QA Contact: Raz Tamir <ratamir>
Severity: high Docs Contact:
Priority: unspecified    
Version: 4.18.24CC: bugs, gveitmic, tjelinek
Target Milestone: ---   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of:
: 1475042 (view as bug list) Environment:
Last Closed: 2017-08-01 10:04:06 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: Virt RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 1475042    

Description Sergio Lopez 2017-07-25 10:32:44 UTC
Having an empty cdrom and an empty floppy means the device path for both is the same (""). This confuses VDSM, overriding the configuration of the second device with the first one:

<snip from "vdsm/vdsm/virt/vmdevices/storage.py:127">
            # Update vm's conf with address for known disk devices
            knownDev = False
            for dev in vm.conf['devices']:
                # See comment in previous loop. This part is used to update
                # the vm configuration as well.
                if ('alias' in dev and dev['alias'] == alias
                        and dev['path'] != devPath):
                    vm.log.warning('updating drive %s config path from %s '
                                   'to %s', dev['alias'], dev['path'],
                                   devPath)
                    dev['path'] = devPath
                if (dev['type'] == hwclass.DISK and
                        dev['path'] == devPath):
                    dev['name'] = name
                    dev['address'] = address
                    dev['alias'] = alias
                    dev['readonly'] = str(readonly)
                    if bootOrder:
                        dev['bootOrder'] = bootOrder
                    vm.log.debug('Matched %s', mergeDicts(deviceDict, dev))
                    knownDev = True
</snip>

As a consequence, the cdrom device is getting "fdc0-0-0" as alias:

engine=# select type,device,alias from vm_device where vm_id='REDACTED' and device='cdrom';
-[ RECORD 1 ]----
type   | disk
device | cdrom
alias  | fdc0-0-0

Additionally, as the actual alias of the cdrom in the XML definition ("ide0-1-0") has not been added to the configuration, VDSM treats it as an unknown device:

<snip from ""vdsm/vdsm/virt/vmdevices/common.py:31"
def _update_unknown_device_info(vm):
    """
    Obtain info about unknown devices from libvirt domain and update the
    corresponding device structures.  Unknown device is a device that has an
    address but wasn't passed during VM creation request.

    :param vm: VM for which the device info should be updated
    :type vm: `class:Vm` instance

    """
    def isKnownDevice(alias):
        for dev in vm.conf['devices']:
            if dev.get('alias') == alias:
                return True
        return False

    for x in vm.domain.devices.childNodes:
        # Ignore empty nodes and devices without address
        if (x.nodeName == '#text' or
                not x.getElementsByTagName('address')):
            continue

        alias = x.getElementsByTagName('alias')[0].getAttribute('name')
        if not isKnownDevice(alias):
            address = vmxml.device_address(x)
            # I general case we assume that device has attribute 'type',
            # if it hasn't getAttribute returns ''.
            device = x.getAttribute('type')
            newDev = {'type': x.nodeName,
                      'alias': alias,
                      'device': device,
                      'address': address}
            vm.conf['devices'].append(newDev)
</snip>

This causes the addition of a non-existent and invalid disk with "device=file":

engine=# select * from vm_device where device='file';
-[ RECORD 1 ]-------------+----------------------------------------------------
device_id                 | a20e43e3-8e80-447d-b0f2-a3bcc1c1567f
vm_id                     | f902a348-df69-44a0-9e11-3c4658fb1684
type                      | disk
device                    | file
address                   | {bus=1, controller=0, type=drive, target=0, unit=0}
boot_order                | 0
spec_params               | { }
is_managed                | f
is_plugged                | t
is_readonly               | f
_create_date              | 2017-07-24 10:50:07.767036-04
_update_date              | 
alias                     | ide0-1-0
custom_properties         | 
snapshot_id               | 
logical_name              | 
is_using_scsi_reservation | f
host_device               | 

In addition to being wrong, this is known to cause a failure when trying to migrate an affected VM to another Host.