Pino Toscano
2018-May-22 09:09 UTC
[Libguestfs] [PATCH v2] v2v: linux: fix kernel detection when split in different packages
The current detection code for Linux kernels assumes that a kernel package contains everything in it, i.e. the kernel itself, its modules, and its configuration. However, since recent Ubuntu versions (e.g. starting from 18.04) modules & config (with few more files) are split in an own package, thus not detecting the modpath from installed vmlinuz files. To overcome this situation, rework this detection a bit: 1) find the vmlinuz file as before, but then immediately make sure it exists by stat'ing it 2) find the modules path from the package as before: 2a) if found, extract the version in the same step 2b) if not found, get the kernel version from the vmlinuz filename, and use it to detect the modules path 3) check that the modules path exists The detection done in (2b) is based on the current packaging scheme found in the most important Linux distributions (Fedora, RHEL, CentOS, Debian, Ubuntu, openSUSE, AltLinux, and possibly more). The notable exception is Arch Linux. As additional change, do not assume the config file is in the same package as vmlinuz, but directly look into the filesystem using the version we already have. --- v2v/linux_kernels.ml | 47 +++++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/v2v/linux_kernels.ml b/v2v/linux_kernels.ml index c047d6deb..24f61429d 100644 --- a/v2v/linux_kernels.ml +++ b/v2v/linux_kernels.ml @@ -103,27 +103,42 @@ let detect_kernels (g : G.guestfs) inspect family bootloader None ) else ( - (* Which of these is the kernel itself? *) + (* Which of these is the kernel itself? Also, make sure to check + * it exists by stat'ing it. + *) let vmlinuz = List.find ( fun filename -> String.is_prefix filename "/boot/vmlinuz-" ) files in - (* Which of these is the modpath? *) - let modpath = List.find ( - fun filename -> - String.length filename >= 14 && - String.is_prefix filename "/lib/modules/" - ) files in - - (* Check vmlinuz & modpath exist. *) - if not (g#is_dir ~followsymlinks:true modpath) then - raise Not_found; let vmlinuz_stat try g#statns vmlinuz with G.Error _ -> raise Not_found in - (* Get/construct the version. XXX Read this from kernel file. *) - let version - let prefix_len = String.length "/lib/modules/" in - String.sub modpath prefix_len (String.length modpath - prefix_len) in + (* Determine the modpath from the package, falling back to the + * version in the vmlinuz file name. + *) + let modpath, version + let prefix = "/lib/modules/" in + try + let prefix_len = String.length prefix in + List.find_map ( + fun filename -> + let filename_len = String.length filename in + if filename_len > prefix_len && + String.is_prefix filename prefix then ( + let version = String.sub filename prefix_len + (filename_len - prefix_len) in + Some (filename, version) + ) else + None + ) files + with Not_found -> + let version + String.sub vmlinuz 14 (String.length vmlinuz - 14) in + let modpath = prefix ^ version in + modpath, version in + + (* Check that the modpath exists. *) + if not (g#is_dir ~followsymlinks:true modpath) then + raise Not_found; (* Find the initramfs which corresponds to the kernel. * Since the initramfs is built at runtime, and doesn't have @@ -188,7 +203,7 @@ let detect_kernels (g : G.guestfs) inspect family bootloader let config_file let cfg = "/boot/config-" ^ version in - if List.mem cfg files then Some cfg + if g#is_file ~followsymlinks:true cfg then Some cfg else None in let kernel_supports what kconf -- 2.17.0
Richard W.M. Jones
2018-May-22 10:41 UTC
Re: [Libguestfs] [PATCH v2] v2v: linux: fix kernel detection when split in different packages
On Tue, May 22, 2018 at 11:09:22AM +0200, Pino Toscano wrote:> The current detection code for Linux kernels assumes that a kernel > package contains everything in it, i.e. the kernel itself, its modules, > and its configuration. However, since recent Ubuntu versions (e.g. > starting from 18.04) modules & config (with few more files) are split in > an own package, thus not detecting the modpath from installed vmlinuz > files. > > To overcome this situation, rework this detection a bit: > 1) find the vmlinuz file as before, but then immediately make sure it > exists by stat'ing it > 2) find the modules path from the package as before: > 2a) if found, extract the version in the same step > 2b) if not found, get the kernel version from the vmlinuz filename, > and use it to detect the modules path > 3) check that the modules path exists > > The detection done in (2b) is based on the current packaging scheme > found in the most important Linux distributions (Fedora, RHEL, CentOS, > Debian, Ubuntu, openSUSE, AltLinux, and possibly more). The notable > exception is Arch Linux. > > As additional change, do not assume the config file is in the same > package as vmlinuz, but directly look into the filesystem using the > version we already have. > --- > v2v/linux_kernels.ml | 47 +++++++++++++++++++++++++++++--------------- > 1 file changed, 31 insertions(+), 16 deletions(-) > > diff --git a/v2v/linux_kernels.ml b/v2v/linux_kernels.ml > index c047d6deb..24f61429d 100644 > --- a/v2v/linux_kernels.ml > +++ b/v2v/linux_kernels.ml > @@ -103,27 +103,42 @@ let detect_kernels (g : G.guestfs) inspect family bootloader > None > ) > else ( > - (* Which of these is the kernel itself? *) > + (* Which of these is the kernel itself? Also, make sure to check > + * it exists by stat'ing it. > + *) > let vmlinuz = List.find ( > fun filename -> String.is_prefix filename "/boot/vmlinuz-" > ) files in > - (* Which of these is the modpath? *) > - let modpath = List.find ( > - fun filename -> > - String.length filename >= 14 && > - String.is_prefix filename "/lib/modules/" > - ) files in > - > - (* Check vmlinuz & modpath exist. *) > - if not (g#is_dir ~followsymlinks:true modpath) then > - raise Not_found; > let vmlinuz_stat > try g#statns vmlinuz with G.Error _ -> raise Not_found in > > - (* Get/construct the version. XXX Read this from kernel file. *) > - let version > - let prefix_len = String.length "/lib/modules/" in > - String.sub modpath prefix_len (String.length modpath - prefix_len) in > + (* Determine the modpath from the package, falling back to the > + * version in the vmlinuz file name. > + *) > + let modpath, version > + let prefix = "/lib/modules/" in > + try > + let prefix_len = String.length prefix in > + List.find_map ( > + fun filename -> > + let filename_len = String.length filename in > + if filename_len > prefix_len &&Strictly speaking this test is not needed, since String.is_prefix implies it. Anyway, the patch is good, ACK. Rich.> + String.is_prefix filename prefix then ( > + let version = String.sub filename prefix_len > + (filename_len - prefix_len) in > + Some (filename, version) > + ) else > + None > + ) files > + with Not_found -> > + let version > + String.sub vmlinuz 14 (String.length vmlinuz - 14) in > + let modpath = prefix ^ version in > + modpath, version in > + > + (* Check that the modpath exists. *) > + if not (g#is_dir ~followsymlinks:true modpath) then > + raise Not_found; > > (* Find the initramfs which corresponds to the kernel. > * Since the initramfs is built at runtime, and doesn't have > @@ -188,7 +203,7 @@ let detect_kernels (g : G.guestfs) inspect family bootloader > > let config_file > let cfg = "/boot/config-" ^ version in > - if List.mem cfg files then Some cfg > + if g#is_file ~followsymlinks:true cfg then Some cfg > else None in > > let kernel_supports what kconf > -- > 2.17.0 > > _______________________________________________ > Libguestfs mailing list > Libguestfs@redhat.com > https://www.redhat.com/mailman/listinfo/libguestfs-- 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
Apparently Analagous Threads
- [v2v PATCH 1/3] linux: remove warning for packages with no files
- [PATCH] v2v: linux: fix kernel detection when split in different packages
- [v2v PATCH 3/3] linux: remove special handling of packages with no files
- [libguestfs-common PATCH 0/2] detect_kernels: deal with RHEL's kernel-core / kernel-modules-core split
- [rhel-9.2 v2v PATCH 0/2] detect_kernels: deal with RHEL's kernel-core / kernel-modules-core split