[Libguestfs] translating CD-ROM device paths from i440fx to Q35 in virt-v2v (was: test-v2v-cdrom: update the CD-ROM's bus to SATA in the converted domain)

Daniel P. Berrangé berrange at redhat.com
Thu Sep 30 11:54:21 UTC 2021


On Thu, Sep 30, 2021 at 01:12:39PM +0200, Laszlo Ersek wrote:
> On 09/29/21 21:22, Richard W.M. Jones wrote:
> Please correct me if I'm wrong: at the moment, I believe virt-v2v parses
> and manipulates the following elements and attributes in the domain XML:
> 
>       <target dev='hda' bus='ide'/>
>       <target dev='hdb' bus='ide'/>
>       <target dev='hdc' bus='ide'/>
>       <target dev='hdd' bus='ide'/>
>               ^^^       ^^^
> 
> My understanding is however that the target/@dev attribute is mostly
> irrelevant:
> 
> https://libvirt.org/formatdomain.html#hard-drives-floppy-disks-cdroms
> 
>     The dev attribute indicates the "logical" device name. The actual
>     device name specified is not guaranteed to map to the device name in
>     the guest OS. Treat it as a device ordering hint. [...]

I won't say it is irrelevant.  Functionally @dev is absolutely still
important, as it influences how the disk is attached to the VM.

Rather I would say that the @dev attribute is misleading to users,
because they mistakenly think it provides a guarantee that the disk
will appear with this name inside the guest.

> What actually matters is the target/@bus attribute, in combination with
> the sibling element <address>. Such as:
> 
>       <target dev='hda' bus='ide'/>
>                              ^^^
>       <address type='drive' controller='0' bus='0' target='0' unit='0'/>
>                                         ^       ^                   ^
> 
>       <target dev='hdb' bus='ide'/>
>                              ^^^
>       <address type='drive' controller='0' bus='0' target='0' unit='1'/>
>                                         ^       ^                   ^
> 
>       <target dev='hdc' bus='ide'/>
>                              ^^^
>       <address type='drive' controller='0' bus='1' target='0' unit='0'/>
>                                         ^       ^                   ^
> 
>       <target dev='hdd' bus='ide'/>
>                              ^^^
>       <address type='drive' controller='0' bus='1' target='0' unit='1'/>
>                                         ^       ^                   ^
> 
> So, target/@dev should be mostly ignored; what matters is the following
> tuple:
> 
>   (target/@bus, address/@controller, address/@bus, address/@unit)

Yes, the <address/> is what libvirt internally drivers all configuration
off, but in practice application developers almost never use the <address>
element directly.  They will just give target/@dev and libvirt will use
that to automatically populate an <address/> element, in order to reliably
fixate the guest ABI thereafter.

> 
> Extracting just the tuples:
> 
>   (ide, 0, 0, 0)
>   (ide, 0, 0, 1)
>   (ide, 0, 1, 0)
>   (ide, 0, 1, 1)
> 
> The first two components of each tuple -- i.e., (ide, 0) -- refer to the
> following IDE controller:
> 
>     <controller type='ide' index='0'>
>                 ^^^^^^^^^^ ^^^^^^^^^
>       <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
>     </controller>
> 
> and then the rest of the components, such as (0, 0), (0, 1), (1, 0), (1,
> 1), identify the disk on that IDE controller.

Yes, that's correct for IDE.

> (Side comment: the PCI location of the (first) IDE controller is fixed
> in QEMU; if one tries to change it, libvirt complains: "Primary IDE
> controller must have PCI address 0:0:1.1".)

Yep, its defined by the QEMU machine type and we just have to accept
that for IDE/SATA.

> Inside the guest, /dev/hd* nodes don't even exist, so it's unlikely that
> /etc/fstab would refer to them. /etc/fstab can however refer to symlinks
> under "/dev/disk/by-id" (for example):
> 
>   lrwxrwxrwx. 1 root root  9 Sep 30 11:54 ata-QEMU_DVD-ROM_QM00001 -> ../../sr0
>   lrwxrwxrwx. 1 root root  9 Sep 30 11:54 ata-QEMU_DVD-ROM_QM00002 -> ../../sr1
>   lrwxrwxrwx. 1 root root  9 Sep 30 11:54 ata-QEMU_DVD-ROM_QM00003 -> ../../sr2
>   lrwxrwxrwx. 1 root root  9 Sep 30 11:54 ata-QEMU_DVD-ROM_QM00004 -> ../../sr3
> 
> Furthermore, we have pseudo-files (directories) such as:
> 
>   /sys/devices/pci0000:00/0000:00:01.1/ata1/host0/target0:0:0/0:0:0:0/block/sr0
>   /sys/devices/pci0000:00/0000:00:01.1/ata1/host0/target0:0:1/0:0:1:0/block/sr1
>   /sys/devices/pci0000:00/0000:00:01.1/ata2/host1/target1:0:0/1:0:0:0/block/sr2
>   /sys/devices/pci0000:00/0000:00:01.1/ata2/host1/target1:0:1/1:0:1:0/block/sr3
>                                                               ^   ^
> 
> So in order to map a device path from the original guest's "/etc/fstab",
> such as "/dev/disk/by-id/ata-QEMU_DVD-ROM_QM00003", to the original
> domain XML's <disk> element, we have to do the following in the "source"
> appliance:
> 
> NODE=$(realpath /dev/disk/by-id/ata-QEMU_DVD-ROM_QM00003)
> # -> /dev/sr2
> NODE=${NODE#/dev/}
> # -> sr2
> DEVPATH=$(ls -d /sys/devices/pci0000:00/0000:00:01.1/ata?/host?/target?:0:?/?:0:?:0/block/$NODE)
> # -> /sys/devices/pci0000:00/0000:00:01.1/ata2/host1/target1:0:0/1:0:0:0/block/sr2
> 
> And then map the "1:0:0:0" pathname component from $DEVPATH to:
> 
>       <target dev='hdc' bus='ide'/>
>       <address type='drive' controller='0' bus='1' target='0' unit='0'/>
>                                            ^^^^^^^            ^^^^^^^^
>                                            [1]:0:0:0          1:0:[0]:0
> 
> in the original domain XML. This tells us under what device node the
> original guest sees the host-side file (<source> element).

Yes, to map from the guest to the libvirt XML, you need to be working
in terms of the hardware buses/addresses.


> So, assuming we mapped the original (i440fx)
> "/dev/disk/by-id/ata-QEMU_DVD-ROM_QM00003" guest device path to some
> <source> element (= host-side file) in the original domain XML, and
> assuming virt-v2v assigned the same <source> element to the following
> element on the Q35 board:
> 
>       <target dev='sd*' bus='sata'/>
>       <address type='drive' controller='0' bus='0' target='0' unit='4'/>
>                                                               ^^^^^^^^
> 
> we find the device node in the destination appliance as follows:
> 
> NODE=$(basename /sys/devices/pci0000:00/0000:00:1f.2/ata?/host?/target?:0:0/4:0:0:0/block/*)
>                                                                             ^
>                                                                             unit='4'
> # -> sr4
> 
> and then replace "/dev/disk/by-id/ata-QEMU_DVD-ROM_QM00003" with
> "/dev/sr4" in "/etc/fstab".

I wouldn't recommend using any of the /dev/* devices, as those are
all unstable when faced with changed guest configuration over time.
/etc/fstab should really use a stable /dev/disk/ symlink, so it can
be directly associated with the desired device based on the hardware
topology, rather than guest OS device probe order.

> /dev/disk/by-label and /dev/disk/by-uuid are based on media contents,
> and multiple CD-ROMs may (read-only) map the same host-side file, so
> those are not good for mapping either, I think. Also does not cover
> CD-ROM devices that are empty (have no medium) at the time of
> conversion, but "/etc/fstab" still refers to them (potentially with
> "noauto"). So I think the only reliable ID is the hardware device path.

Yep, the symlink based on hardware  topology is the only thing that
can be stable and unique.


Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|




More information about the Libguestfs mailing list