On Mon, Mar 11, 2024 at 07:32:30PM +0200, Andrey Drobyshev wrote:
> On 3/7/24 16:27, Richard W.M. Jones wrote:
> > On Thu, Feb 29, 2024 at 05:37:08PM +0200, Andrey Drobyshev wrote:
> >> I discovered that when a VM has an ISO attached via CD-ROM, libguestfs
> >> fails to read its partition table and therefore fails to perform basic
> >> operations on a VM, e.g. listing a directory or editing a file:
> >>
> >> # virsh domblklist rocky9-vm
> >> Target Source
> >> ---------------------------------------------------------------------------
> >>  sda   /vz/vmprivate/e827caad-b9e4-4858-b3dc-53ae6b8a5145/harddisk.hdd
> >>  sdb   /vzt/images/Rocky-9.3-x86_64-minimal.iso
> > 
> > [Download the ISO from here: https://rockylinux.org/download/]

We had a bit of a discussion here about this image, which we think is
a Hybrid ISO generated by either this exact tool or a similar one:
https://wiki.syslinux.org/wiki/index.php?title=Isohybrid

The image contains ISO with MBR + GPT partition table.  For some
reason sgdisk cannot seem to read the GPT partition table properly, so
either it's badly formatted or maybe there is a bug in sgdisk:

This hybrid ISO image:

  $ file /var/tmp/Rocky-9.3-x86_64-minimal.iso 
/var/tmp/Rocky-9.3-x86_64-minimal.iso: ISO 9660 CD-ROM filesystem data (DOS/MBR 
boot sector) 'Rocky-9-3-x86_64-dvd' (bootable)

Just some regular ISO:

  $ file /mnt/media/software/vmware/VMware-VCSA-all-7.0.0-15952498.iso 
  /mnt/media/software/vmware/VMware-VCSA-all-7.0.0-15952498.iso: ISO 9660 
CD-ROM filesystem data 'VMware VCSA'

Linux kernel and sfdisk can parse the MBR:

  $ virt-rescue --ro -a /var/tmp/Rocky-9.3-x86_64-minimal.iso 
  ><rescue> dmesg | grep sda:
  [    0.520088]  sda: sda1 sda2

  $ sfdisk -l /var/tmp/Rocky-9.3-x86_64-minimal.iso 
  Disk /var/tmp/Rocky-9.3-x86_64-minimal.iso: 1.57 GiB, 1686568960 bytes, 
3294080 sectors
  ...
  Device                                 Boot Start     End Sectors  Size Id 
Type
  /var/tmp/Rocky-9.3-x86_64-minimal.iso1 *        0 3293407 3293408  1.6G  0 
Empty
  /var/tmp/Rocky-9.3-x86_64-minimal.iso2        664   14851   14188  6.9M ef 
EFI (

But sgdisk cannot:

  $ sgdisk /var/tmp/Rocky-9.3-x86_64-minimal.iso -i 1
  Invalid partition data!

I just wonder if a better way to do this is to ignore partitions that
appear on a hybrid ISO by actually detecting hybrid ISO as a specific
format (rather than hard coding "iso9660" or "udf").

Your patch tries to modify list_filesystems, but this could also be
done in list_partitions.

Still thinking about this ...  Do we have a bug about it?

I think a key issue is why does sgdisk not recognise the
partition table.

Rich.


> >> # virt-ls -d rocky9-vm /
> >> libguestfs: error: inspect_os: sgdisk: Invalid partition data!
> >>
> >> # virt-edit -d rocky9-vm /etc/fstab
> >> libguestfs: error: inspect_os: sgdisk: Invalid partition data!
> >>
> >>
> >> Even virt-inspector can't give us proper output on an ISO9660 image:
> >>
> >> # virt-inspector /vzt/images/Rocky-9.3-x86_64-minimal.iso
> >> libguestfs: error: inspect_os: sgdisk: Invalid partition data!
> >> virt-inspector: no operating system could be detected inside this disk
> >> image.
> >> ...
> >>
> >>
> >> First I found a 3 years old topic where you suggested that sgdisk itself
> >> might be too old:
> >> https://listman.redhat.com/archives/libguestfs/2021-March/025939.html.
> >> However this doesn't seem to be it in this case:
> >> I've compiled the latest version from
> >> https://sourceforge.net/projects/gptfdisk -- no luck as well.  Seems
> >> that sgdisk isn't capable of recognizing ISO9660 images.
> >>
> >> Then I noticed 2 things:
> >>
> >> 1. libguestfs appliance is being created (with backend=libvirt) with ISO
> >> attached as device='disk' (not 'cdrom'):
> >>
> >>>     <disk type='file' device='disk'>                                      
> >>>       
> >>>       <driver name='qemu' type='qcow2' cache='unsafe'/>                   
> >>>       
> >>>       <source file='/tmp/libguestfsD7IHvF/overlay2.qcow2' index='2'/>     
> >>>       
> >>>       <backingStore type='file' index='5'>                                
> >>>       
> >>>         <format type='raw'/>                                              
> >>>                                                                           
> >>>            
> >>>         <source file='/vzt/images/Rocky-9.3-x86_64-minimal.iso'/>         
> >>>          
> >>>         <backingStore/>                                                   
> >>>          
> >>>       </backingStore>                                                     
> >>>          
> >>>       <target dev='sdb' bus='scsi'/>                                      
> >>>       
> >>>       <alias name='scsi0-0-1-0'/>                                         
> >>>       
> >>>       <address type='drive' controller='0' bus='0' target='1' unit='0'/>  
> >>>       
> >>>     </disk>
> >>
> >> That forces this disk to be supplied with "scsi-hd" driver in use, which
> >> in turn leads to the device being visible inside the guest as a regular
> >> SCSI hdd /dev/sdb.  Shouldn't we, for instance, make sure that for such
> >> images device='cdrom' and "scsi-cd" driver are being used?  In this case
> >> the guest will see it as /dev/sr0, and I suspect srX devices are being
> >> skipped by guestfs_inspect_os.
> > 
> > I think /dev/srX would not be ignored:
> > 
> > https://github.com/libguestfs/libguestfs/blob/729d6d55ea84494f0398d02450bd29c39c55f0bd/daemon/devsparts.ml#L52
> > 
> > But anyway I don't think that's the problem here.  We try to present
> > any disk image (even an ISO) as a regular disk to the libguestfs
> > appliance.  That's because we don't need or care about the special
> > features of /dev/srX like the ability to eject a disk.
> > 
> > I think the central problem is why libguestfs cannot inspect the ISO.
> > 
> >   $ virt-inspector -a Rocky-9.3-x86_64-minimal.iso 
> >   libguestfs: error: inspect_os: sgdisk: Invalid partition data!
> >   virt-inspector: no operating system could be detected inside this disk 
> > image.
> > 
> >   $ guestfish --ro -a Rocky-9.3-x86_64-minimal.iso -i
> >   libguestfs: error: inspect_os: sgdisk: Invalid partition data!
> > 
> > etc
> > 
> > Adding -vx options shows the problem is with sgdisk:
> > 
> >   command: sgdisk returned 2
> >   command: sgdisk: stderr:
> >   Invalid partition data!
> >   ocaml_exn: 'inspect_os' raised 'Failure' exception
> >   guestfsd: error: sgdisk: Invalid partition data!
> >   guestfsd: => inspect_os (0x1e0) took 0.13 secs
> > 
> > I believe this comes from:
> > 
> >   
> > https://github.com/libguestfs/libguestfs/blob/729d6d55ea84494f0398d02450bd29c39c55f0bd/daemon/parted.ml#L167
> > 
> > I modified the error message in this file to see what it's trying to
> > do and it comes from the call to 'part_get_gpt_type'.
> > 
> > I think it's a regression in commit b699111e04.
> >
> Just to be accurate here: commit b699111e04 ("daemon: list-filesystems:
> Filter out MBR extended partitions.") hasn't introduced the call to
> Parted.part_get_gpt_type, it was done by the commit 16192ad95 ("daemon:
> list-filesystems: Change the way we filter out LDM partitions.") coming
> from the same series.
> 
> > Do you want to try the attached patch?
> > 
> 
> Thank you, I've tried the patch and ignoring the sgdisk error does help
> to overcome the failure when working with domains having an ISO
> attached.  However I'm not convinced that simply ignoring the error is
> the right thing to do: what if there's an error on other than ISO, where
> we do indeed want to be aware of it?  I think we should rather make an
> exception for a CD/DVD images.
> 
> AFAIU ISO9660 images', as well as UDF images' structures aren't supposed
> to have partition tables.  Rather these formats fool tools like sgdisk,
> parted etc. into thinking there're actual partition tables.  If so, why
> don't we just skip listing separate partitions and look at the image as
> a whole when listing file systems.  What do you think of the attached patch?
> 
> > Note this still won't allow the ISO to be inspected, but it avoids the
> > "Invalid partition data!" error, and maybe will cure the original
> > problem above.
> > 
> 
> You're right, inspection still doesn't work properly (with my patch as
> well).  Now the commands fail further:
> 
> $ guestfish --ro -a /vzt/images/Rocky-9.3-x86_64-minimal.iso -i
> guestfish: no operating system was found on this disk
> 
> If using guestfish ‘-i’ option, remove this option and instead
> use the commands ‘run’ followed by ‘list-filesystems’.
> You can then mount filesystems you want by hand using the
> ‘mount’ or ‘mount-ro’ command.
> .....
> 
> $ virt-ls -a /vzt/images/Rocky-9.3-x86_64-minimal.iso /
> virt-ls: no operating system was found on this disk
> 
> If using guestfish ‘-i’ option, remove this option and instead
> use the commands ‘run’ followed by ‘list-filesystems’.
> You can then mount filesystems you want by hand using the
> ‘mount’ or ‘mount-ro’ command.
> .....
> 
> That seems to be because there's no <root> element in the inspection result:
> 
> $ virt-inspector -a /vzt/images/Rocky-9.3-x86_64-minimal.iso
> 
> <?xml version="1.0"?>
> <operatingsystems/>
> 
> Shouldn't we tweak inspect_get_roots() (from daemon/inspect.ml) to
> recognize ISO9660 as well?
> 
> >> 2. When trying to perform the same operation via guestfish, everything
> >> appears to be working:
> >>
> >> # guestfish -a /vzt/images/Rocky-9.3-x86_64-minimal.iso -m /dev/sda ls /
> >>> /dev/null && echo $?
> >> 0
> > 
> > I think this is just because we're avoiding inspection?
> > 
> >> File edit works as well.  From debug output I see that sgdisk isn't
> >> being invoked at all.  That means there's a code path for the same
> >> operations where sgdisk can be omitted.  Maybe we should follow that
> >> same code path when invoking other tools like virt-ls or virt-edit?
> >>
> >>
> >> Overall, what would be an appropriate fix in your opinion?  We should at
> >> least make sure that working with domains (with the "-d" option) works
> >> no matter what.
> >>
> >> Andrey
> > 
> > Rich.
> > 

> From 2a703ca4abb93fce76985afc34052e1372939ba0 Mon Sep 17 00:00:00 2001
> From: Andrey Drobyshev <andrey.drobys...@virtuozzo.com>
> Date: Mon, 11 Mar 2024 19:13:26 +0200
> Subject: [PATCH] daemon: listfs: Ignore partitions when dealing with ISO9660
>  or UDF
> 
> ISO9660 or UDF images (CD/DVD) don't really have partition table,
> however tools like sgdisk might think otherwise.  Currently when working
> with a domain having a cdrom attached, we get:
> 
>   $ virt-ls -d VM /
>   guestfsd: error: sgdisk: Invalid partition data!
> 
> Let's detect filesystem type of such a block device (with blkid) and
> treat it as a whole in case it has type "iso9660" or "udf", e.g.
> ignoring what appears to be separate partitions.
> 
> Signed-off-by: Andrey Drobyshev <andrey.drobys...@virtuozzo.com>
> ---
>  daemon/listfs.ml | 31 ++++++++++++++++++++++++++-----
>  1 file changed, 26 insertions(+), 5 deletions(-)
> 
> diff --git a/daemon/listfs.ml b/daemon/listfs.ml
> index 3c6e86fa5..15422be78 100644
> --- a/daemon/listfs.ml
> +++ b/daemon/listfs.ml
> @@ -43,8 +43,17 @@ let rec list_filesystems () =
>    let devices = List.filter is_not_partitioned_device devices in
>    List.iter (check_with_vfs_type ret) devices;
>  
> +  (* CD or DVD devices (ISO9660 or UDF).
> +   * We want to treat such devices as a whole, even if it appears
> +   * to have a partition table.
> +   *)
> +  let devices = Devsparts.list_devices () in
> +  let devices = List.filter is_device_cd_or_dvd devices in
> +  List.iter (check_with_vfs_type ret) devices;
> +
>    (* Partitions. *)
>    let partitions = Devsparts.list_partitions () in
> +  let partitions = List.filter is_not_fake_cd_or_dvd_partition partitions in
>    let partitions = List.filter is_partition_can_hold_filesystem partitions in
>    List.iter (check_with_vfs_type ret) partitions;
>  
> @@ -138,11 +147,7 @@ and is_mbr_extended parttype device partnum =
>  and is_mbr_bogus parttype device partnum =
>    parttype = "msdos" && partnum = 1 && Utils.has_bogus_mbr device
>  
> -(* Use vfs-type to check for a filesystem of some sort of [device].
> - * Appends (device, vfs_type) to the ret parameter (there may be
> - * multiple devices found in the case of btrfs).
> - *)
> -and check_with_vfs_type ret device =
> +and device_to_mountable_vfstype device =
>    let mountable = Mountable.of_device device in
>    let vfs_type =
>      try Blkid.vfs_type mountable
> @@ -151,6 +156,22 @@ and check_with_vfs_type ret device =
>           eprintf "check_with_vfs_type: %s: %s\n"
>                   device (Printexc.to_string exn);
>         "" in
> +  (mountable, vfs_type)
> +
> +and is_device_cd_or_dvd device =
> +  let mountable, vfs_type = device_to_mountable_vfstype device in
> +  vfs_type = "iso9660" || vfs_type = "udf"
> +
> +and is_not_fake_cd_or_dvd_partition partition =
> +  let device = Devsparts.part_to_dev partition in
> +  not (is_device_cd_or_dvd device)
> +
> +(* Use vfs-type to check for a filesystem of some sort of [device].
> + * Appends (device, vfs_type) to the ret parameter (there may be
> + * multiple devices found in the case of btrfs).
> + *)
> +and check_with_vfs_type ret device =
> +  let mountable, vfs_type = device_to_mountable_vfstype device in
>  
>    if vfs_type = "" then
>      List.push_back ret (mountable, "unknown")
> -- 
> 2.39.3
> 


-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-top is 'top' for virtual machines.  Tiny program with many
powerful monitoring features, net stats, disk stats, logging, etc.
http://people.redhat.com/~rjones/virt-top
_______________________________________________
Libguestfs mailing list -- guestfs@lists.libguestfs.org
To unsubscribe send an email to guestfs-le...@lists.libguestfs.org

Reply via email to