[PATCH v2] launch: add support for autodetection of appliance image format
by Pavel Butsykin
This feature allows you to use different image formats for the fixed
appliance. The raw format is used by default.
Signed-off-by: Pavel Butsykin <pbutsykin(a)virtuozzo.com>
---
lib/launch-direct.c | 2 ++
lib/launch-libvirt.c | 19 ++++++++++++-------
m4/guestfs_appliance.m4 | 11 +++++++++++
3 files changed, 25 insertions(+), 7 deletions(-)
diff --git a/lib/launch-direct.c b/lib/launch-direct.c
index 0be662e25..b9b54857a 100644
--- a/lib/launch-direct.c
+++ b/lib/launch-direct.c
@@ -592,7 +592,9 @@ launch_direct (guestfs_h *g, void *datav, const char *arg)
append_list ("id=appliance");
append_list ("cache=unsafe");
append_list ("if=none");
+#ifndef APPLIANCE_FMT_AUTO
append_list ("format=raw");
+#endif
} end_list ();
start_list ("-device") {
append_list ("scsi-hd");
diff --git a/lib/launch-libvirt.c b/lib/launch-libvirt.c
index 4adb2cfb3..030ea6911 100644
--- a/lib/launch-libvirt.c
+++ b/lib/launch-libvirt.c
@@ -212,9 +212,10 @@ get_source_format_or_autodetect (guestfs_h *g, struct drive *drv)
/**
* Create a qcow2 format overlay, with the given C<backing_drive>
- * (file). The C<format> parameter, which must be non-NULL, is the
- * backing file format. This is used to create the appliance overlay,
- * and also for read-only drives.
+ * (file). The C<format> parameter is the backing file format.
+ * The C<format> parameter can be NULL, in this case the backing
+ * format will be determined automatically. This is used to create
+ * the appliance overlay, and also for read-only drives.
*/
static char *
make_qcow2_overlay (guestfs_h *g, const char *backing_drive,
@@ -223,8 +224,6 @@ make_qcow2_overlay (guestfs_h *g, const char *backing_drive,
char *overlay;
struct guestfs_disk_create_argv optargs;
- assert (format != NULL);
-
if (guestfs_int_lazy_make_tmpdir (g) == -1)
return NULL;
@@ -232,8 +231,10 @@ make_qcow2_overlay (guestfs_h *g, const char *backing_drive,
optargs.bitmask = GUESTFS_DISK_CREATE_BACKINGFILE_BITMASK;
optargs.backingfile = backing_drive;
- optargs.bitmask |= GUESTFS_DISK_CREATE_BACKINGFORMAT_BITMASK;
- optargs.backingformat = format;
+ if (format) {
+ optargs.bitmask |= GUESTFS_DISK_CREATE_BACKINGFORMAT_BITMASK;
+ optargs.backingformat = format;
+ }
if (guestfs_disk_create_argv (g, overlay, "qcow2", -1, &optargs) == -1) {
free (overlay);
@@ -461,7 +462,11 @@ launch_libvirt (guestfs_h *g, void *datav, const char *libvirt_uri)
/* Note that appliance can be NULL if using the old-style appliance. */
if (appliance) {
+#ifdef APPLIANCE_FMT_AUTO
+ params.appliance_overlay = make_qcow2_overlay (g, appliance, NULL);
+#else
params.appliance_overlay = make_qcow2_overlay (g, appliance, "raw");
+#endif
if (!params.appliance_overlay)
goto cleanup;
}
diff --git a/m4/guestfs_appliance.m4 b/m4/guestfs_appliance.m4
index 81c43879f..4e1ec8135 100644
--- a/m4/guestfs_appliance.m4
+++ b/m4/guestfs_appliance.m4
@@ -139,3 +139,14 @@ AC_SUBST([GUESTFS_DEFAULT_PATH])
AC_DEFINE_UNQUOTED([GUESTFS_DEFAULT_PATH], ["$GUESTFS_DEFAULT_PATH"],
[Define guestfs default path.])
+
+AC_ARG_ENABLE([appliance-fmt-auto],
+ [AS_HELP_STRING([--enable-appliance-fmt-auto],
+ [enable autodetection of appliance image format @<:@default=no@:>@])],
+ [ENABLE_APPLIANCE_FMT_AUTO="$enableval"],
+ [ENABLE_APPLIANCE_FMT_AUTO=no])
+
+if test "x$ENABLE_APPLIANCE_FMT_AUTO" = "xyes"; then
+ AC_DEFINE([APPLIANCE_FMT_AUTO], [1],
+ [Define to 1 if enabled autodetection of appliance image format.])
+fi
--
2.13.0
4 years, 9 months
1.39 proposal: Let's split up the libguestfs git repo and tarballs
by Richard W.M. Jones
My contention is that the libguestfs git repository is too large and
unwieldy. There are too many separate, unrelated projects and as a
result of that the source has too many dependencies and takes too long
to build and test.
The project divides (sort of) naturally into layers -- the library,
the bindings, the various virt tools -- and could be split along those
lines into separate projects which can then be released and evolve at
their own pace.
My suggested split would be something like this:
* libguestfs: The library, daemon and appliance. That would include
the following directories in a single project:
appliance
bash
contrib
daemon
docs
examples
gnulib
lib
logo
test-tool
tmp
utils
website
* 1 project for each language binding:
csharp
erlang
gobject
golang
haskell
java
lua
ocaml
php
perl
python
ruby
* virt-customize and related tools, we'd probably call this subproject
"virt-builder". It would include virt-builder, virt-customize and
virt-sysprep, since they share a lot of common code.
* 1 project for each of the following items:
small tools written in C
(virt-cat, virt-filesystems, virt-log, virt-ls, virt-tail,
virt-diff, virt-edit, virt-format, guestmount, virt-inspector,
virt-make-fs, virt-rescue)
guestfish
virt-alignment-scan and virt-df
virt-dib
virt-get-kernel
virt-resize
virt-sparsify
virt-v2v and virt-p2v
virt-win-reg
* I'd be inclined to drop the legacy Perl tools virt-tar,
virt-list-filesystems, virt-list-partitions unless someone
especially wished to step forward to maintain them.
* common code and generator: Off to the side we'd somehow need to
package up the common code and the generator for use by all of the
above projects. It wouldn't be a separate project for downstream
packagers, but instead the code would be included (ie. duplicated)
in tarballs and upstream available as a side git repo that you'd
need to include when building (git submodule?). This is somewhat
unspecified.
M4, PO, and tests would be split between the projects as appropriate.
My proposal would be to do this incrementally, rather than all at
once, moving the easier things out first.
Thoughts?
Rich.
--
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
libguestfs lets you edit virtual machines. Supports shell scripting,
bindings from many languages. http://libguestfs.org
4 years, 11 months
virt-builder download issues
by Alex Buchanan
I'm having trouble downloading templates (ubuntu-18.04, among others) using virt-builder. The downloads get to about 50% (or 13, or 62) and then stall. wget easily downloads the files quickly.
I'd be happy with working around this by manually placing the images in the cache directory, but I can't seem to figure out the appropriate placement. virt-builder doesn't find the cached file.
Please send help,
Thanks!
6 years, 5 months
[PATCH v2] daemon: Move lvmetad to early in the appliance boot process.
by Richard W.M. Jones
When the daemon starts up it creates a fresh (empty) LVM configuration
and starts up lvmetad (which depends on the LVM configuration).
However this appears to cause problems: Some types of PV seem to
require lvmetad and don't work without it
(https://bugzilla.redhat.com/show_bug.cgi?id=1581810). If we don't
start lvmetad earlier, the device nodes are not created.
Therefore move the whole initialization step into appliance/init.
Two further changes had to be made:
Now we are using lvmetad all the time, using vgchange is incorrect.
With lvmetad activated early we must use ‘pvscan --cache --activate ay’
to scan all disks for PVs and activate any VGs on them (although the
documentation is complex, confusing and contradictory so I'm not
completely sure about this).
The ‘lvm_system_dir’ local variable in ‘daemon/lvm-filter.c’
previously contained the path of the directory above $LVM_SYSTEM_DIR
(eg. $LVM_SYSTEM_DIR = "/etc/lvm", lvm_system_dir = "/etc"). As this
was highly confusing, I have changed it so the local variable and the
environment variable have identical contents. This involved removing
the ‘lvm/’ component from a couple of paths since it is now included
in the local variable.
---
appliance/init | 11 +++++++-
daemon/daemon.h | 4 ---
daemon/guestfsd.c | 8 ------
daemon/lvm-filter.c | 75 +++++++++--------------------------------------------
4 files changed, 22 insertions(+), 76 deletions(-)
diff --git a/appliance/init b/appliance/init
index 6a61a8d6e..4f2b55822 100755
--- a/appliance/init
+++ b/appliance/init
@@ -133,9 +133,17 @@ fi
# Scan for MDs but don't run arrays unless all expected drives are present
mdadm -As --auto=yes --no-degraded
+# Set up a clean LVM environment.
+# Empty LVM configuration file means "all defaults".
+mkdir -p /tmp/lvm
+touch /tmp/lvm/lvm.conf
+LVM_SYSTEM_DIR=/tmp/lvm
+export LVM_SYSTEM_DIR
+lvmetad
+
# Scan for LVM.
modprobe dm_mod ||:
-lvm vgchange -aay --sysinit
+lvm pvscan --cache --activate ay
# Scan for MDs and run all found arrays even they are in degraded state
mdadm -As --auto=yes --run
@@ -149,6 +157,7 @@ if test "$guestfs_verbose" = 1 && test "$guestfs_boot_analysis" != 1; then
ls -lR /dev
cat /proc/mounts
cat /proc/mdstat
+ lvm config
lvm pvs
lvm vgs
lvm lvs
diff --git a/daemon/daemon.h b/daemon/daemon.h
index 7958ba781..faaf1237e 100644
--- a/daemon/daemon.h
+++ b/daemon/daemon.h
@@ -249,10 +249,6 @@ extern char *get_blkid_tag (const char *device, const char *tag);
/* lvm.c */
extern int lv_canonical (const char *device, char **ret);
-/* lvm-filter.c */
-extern void clean_lvm_config (void);
-extern void start_lvmetad (void);
-
/* zero.c */
extern void wipe_device_before_mkfs (const char *device);
diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c
index 68d3de2ec..ae428e573 100644
--- a/daemon/guestfsd.c
+++ b/daemon/guestfsd.c
@@ -233,14 +233,6 @@ main (int argc, char *argv[])
_umask (0);
#endif
- /* Make a private copy of /etc/lvm so we can change the config (see
- * daemon/lvm-filter.c).
- */
- if (!test_mode) {
- clean_lvm_config ();
- start_lvmetad ();
- }
-
/* Connect to virtio-serial channel. */
if (!channel)
channel = VIRTIO_SERIAL_CHANNEL;
diff --git a/daemon/lvm-filter.c b/daemon/lvm-filter.c
index ad85a7cc4..1ea5ad8ab 100644
--- a/daemon/lvm-filter.c
+++ b/daemon/lvm-filter.c
@@ -36,71 +36,20 @@
#include "daemon.h"
#include "actions.h"
-/* This runs during daemon start up and creates a fresh LVM
- * configuration which we can modify as we desire. LVM allows
- * configuration to be completely empty (meaning "all defaults").
- *
- * The final directory layout is:
- *
- * /tmp/lvmXXXXXX (lvm_system_dir set to this)
- * /tmp/lvmXXXXXX/lvm ($LVM_SYSTEM_DIR set to this)
- * /tmp/lvmXXXXXX/lvm/lvm.conf (configuration file - initially empty)
- */
-static char lvm_system_dir[] = "/tmp/lvmXXXXXX";
-
-static void rm_lvm_system_dir (void);
static void debug_lvm_config (void);
-void
-clean_lvm_config (void)
-{
- char env[64], conf[64];
- FILE *fp;
-
- if (mkdtemp (lvm_system_dir) == NULL)
- error (EXIT_FAILURE, errno, "mkdtemp: %s", lvm_system_dir);
-
- snprintf (env, sizeof env, "%s/lvm", lvm_system_dir);
- mkdir (env, 0755);
- snprintf (conf, sizeof conf, "%s/lvm/lvm.conf", lvm_system_dir);
- fp = fopen (conf, "w");
- if (fp == NULL) {
- perror ("clean_lvm_config: cannot create empty lvm.conf");
- exit (EXIT_FAILURE);
- }
- fclose (fp);
-
- /* Set environment variable so we use the clean configuration. */
- setenv ("LVM_SYSTEM_DIR", env, 1);
-
- /* Set a handler to remove the temporary directory at exit. */
- atexit (rm_lvm_system_dir);
-
- debug_lvm_config ();
-}
-
-/* Try to run lvmetad, without failing if it couldn't. */
-void
-start_lvmetad (void)
-{
- int r;
-
- if (verbose)
- printf ("%s\n", "lvmetad");
- r = system ("lvmetad");
- if (r == -1)
- perror ("system/lvmetad");
- else if (!WIFEXITED (r) || WEXITSTATUS (r) != 0)
- fprintf (stderr, "warning: lvmetad command failed\n");
-}
-
+/* Read LVM_SYSTEM_DIR environment variable, or set it to a default
+ * value if the environment variable is not set.
+ */
+static const char *lvm_system_dir;
+static void get_lvm_system_dir (void) __attribute__((constructor));
static void
-rm_lvm_system_dir (void)
+get_lvm_system_dir (void)
{
- char cmd[64];
-
- snprintf (cmd, sizeof cmd, "rm -rf %s", lvm_system_dir);
- ignore_value (system (cmd));
+ lvm_system_dir = getenv ("LVM_SYSTEM_DIR");
+ if (!lvm_system_dir)
+ lvm_system_dir = "/etc/lvm";
+ fprintf (stderr, "lvm_system_dir = %s\n", lvm_system_dir);
}
/* Rewrite the 'filter = [ ... ]' line in lvm.conf. */
@@ -112,7 +61,7 @@ set_filter (char *const *filters)
FILE *fp;
size_t i, j;
- if (asprintf (&conf, "%s/lvm/lvm.conf", lvm_system_dir) == -1) {
+ if (asprintf (&conf, "%s/lvm.conf", lvm_system_dir) == -1) {
reply_with_perror ("asprintf");
return -1;
}
@@ -177,7 +126,7 @@ static int
rescan (void)
{
char lvm_cache[64];
- snprintf (lvm_cache, sizeof lvm_cache, "%s/lvm/cache/.cache", lvm_system_dir);
+ snprintf (lvm_cache, sizeof lvm_cache, "%s/cache/.cache", lvm_system_dir);
unlink (lvm_cache);
--
2.16.2
6 years, 5 months
[PATCH] RFC: v2v: use RHV Setup Tools ISO if available
by Pino Toscano
If the RHV Setup Tools ISO is installed, open it, and copy RHEV APT from
there, instead of using (if available) the executable located in the
virt-tools data directory.
This way, RHV conversion hosts with the RHV Setup Tools ISO installed
will always install the latest version when convering Windows guests,
no matter which version is (eventually) shipped as virt-tools.
---
v2v/convert_windows.ml | 57 ++++++++++++++++++++++++++++++++++++------
v2v/virt-v2v.pod | 18 +++++++++++++
2 files changed, 67 insertions(+), 8 deletions(-)
diff --git a/v2v/convert_windows.ml b/v2v/convert_windows.ml
index 163319545..21dafe4f4 100644
--- a/v2v/convert_windows.ml
+++ b/v2v/convert_windows.ml
@@ -27,6 +27,10 @@ open Types
module G = Guestfs
+type tool_location =
+ | Local_path of string (* path of file *)
+ | ISO of string * string (* path of ISO, path to look for inside the ISO *)
+
(* Convert Windows guests.
*
* This only does a "pre-conversion", the steps needed to get the
@@ -239,12 +243,15 @@ let convert (g : G.guestfs) inspect source output rcaps =
(* Install RHEV-APT only if appropriate for the output hypervisor. *)
if output#install_rhev_apt then (
- let tool_path = virt_tools_data_dir () // "rhev-apt.exe" in
- if Sys.file_exists tool_path then
- configure_rhev_apt tool_path
- else
- warning (f_"%s is missing, but the output hypervisor is oVirt or RHV. Installing RHEV-APT in the guest would mean the guest is automatically updated with new drivers etc. You may wish to install RHEV-APT manually after conversion.")
- tool_path
+ let rhev_apt =
+ let iso = virt_tools_data_dir () // "rhv-guest-tools-iso" // "rhv-tools-setup.iso" in
+ if is_regular_file iso then
+ ISO (iso, "/RHEV-Application Provisioning Tool.exe")
+ else
+ Local_path (virt_tools_data_dir () // "rhev-apt.exe") in
+
+ if copy_rhev_apt rhev_apt then
+ configure_rhev_apt ()
);
(* Install VMDP unconditionally, if available, but don't
@@ -330,12 +337,46 @@ echo Wait for PnP to complete
(* add_firstboot_script has created the path already. *)
g#upload tool_path (g#case_sensitive_path pnp_wait_path)
- and configure_rhev_apt tool_path =
+ and copy_rhev_apt tool_location =
(* Configure RHEV-APT (the RHV guest agent). However if it doesn't
* exist just warn about it and continue.
*)
- g#upload tool_path "/rhev-apt.exe"; (* XXX *)
+ let ret = ref false in
+ let target = "/rhev-apt.exe" (* XXX *) in
+ (match tool_location with
+ | Local_path path ->
+ debug "windows: copy_rhev_apt: source file %s" path;
+ if Sys.file_exists path then (
+ g#upload path target;
+ ret := true
+ )
+ else
+ warning (f_"%s is missing, but the output hypervisor is oVirt or RHV. Installing RHEV-APT in the guest would mean the guest is automatically updated with new drivers etc. You may wish to install RHEV-APT manually after conversion.")
+ path
+ | ISO (iso, path) ->
+ debug "windows: copy_rhev_apt: source ISO %s, path %s" iso path;
+ try
+ let g2 = open_guestfs ~identifier:"rhev_apt" () in
+ g2#add_drive_opts iso ~readonly:true;
+ g2#launch ();
+ g2#mount_ro "/dev/sda" "/";
+ if g2#is_file path ~followsymlinks:true then (
+ debug "copying rhev-apt: '%s:%s' -> '%s'"
+ iso path target;
+ g#write target (g2#read_file path);
+ ret := true
+ )
+ else
+ warning (f_"%s is missing in %s, but the output hypervisor is oVirt or RHV. Installing RHEV-APT in the guest would mean the guest is automatically updated with new drivers etc. You may wish to install RHEV-APT manually after conversion.")
+ path iso;
+ g2#close()
+ with Guestfs.Error msg ->
+ error (f_"%s: cannot open RHEV Tools ISO file: %s") iso msg
+ );
+ !ret
+
+ and configure_rhev_apt () =
let fb_script = "\
@echo off
diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod
index 859d68fc5..3d153f1b3 100644
--- a/v2v/virt-v2v.pod
+++ b/v2v/virt-v2v.pod
@@ -2464,6 +2464,20 @@ option at all. The option was added when virt-v2v was rewritten in 2014.
=over 4
+=item F</usr/share/rhv-guest-tools-iso/rhv-tools-setup.iso>
+
+(Optional)
+
+If this file is present, then virt-v2v assumes that it is a RHV Tools
+ISO, containing F</RHEV-Application Provisioning Tool.exe> as the
+RHV Application Provisioning Tool (RHEV APT). The RHEV APT will be
+installed in the Windows guest during conversion. This tool is a
+guest agent which ensures that the virtio drivers remain up to date
+when the guest is running on Red Hat Virtualization (RHV).
+
+This ISO comes from Red Hat Virtualization (RHV), and is not
+distributed with virt-v2v.
+
=item F</usr/share/virtio-win>
(Optional)
@@ -2522,6 +2536,10 @@ conversion. This tool is a guest agent which ensures that the virtio
drivers remain up to date when the guest is running on Red Hat
Virtualization (RHV).
+Note this file is not used if
+F</usr/share/rhv-guest-tools-iso/rhv-tools-setup.iso> is already
+present.
+
This file comes from Red Hat Virtualization (RHV), and is not
distributed with virt-v2v.
--
2.17.0
6 years, 6 months
[PATCH] v2v: fix build rules for output_rhv_upload_*_source.ml files
by Pino Toscano
Use the $(srcdir) variable where needed, to make sure it builds also
with srcdir != builddir.
Furthermore, make sure that the OCaml dependencies calculation depend on
the generated output_rhv_upload_*_source.ml files, otherwise there will
be incomplete OCaml rules for them in the generated .depend.
Fixes commit cc04573927cca97de60d544d37467e67c25867a7.
---
v2v/Makefile.am | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/v2v/Makefile.am b/v2v/Makefile.am
index 34cad197b..88b31f86c 100644
--- a/v2v/Makefile.am
+++ b/v2v/Makefile.am
@@ -143,12 +143,12 @@ SOURCES_C = \
# These files are generated and contain rhv-upload-*.py embedded as an
# OCaml string.
-output_rhv_upload_createvm_source.ml: rhv-upload-createvm.py
- ./embed.sh code $^ $@
-output_rhv_upload_plugin_source.ml: rhv-upload-plugin.py
- ./embed.sh code $^ $@
-output_rhv_upload_precheck_source.ml: rhv-upload-precheck.py
- ./embed.sh code $^ $@
+output_rhv_upload_createvm_source.ml: $(srcdir)/rhv-upload-createvm.py
+ $(srcdir)/embed.sh code $^ $@
+output_rhv_upload_plugin_source.ml: $(srcdir)/rhv-upload-plugin.py
+ $(srcdir)/embed.sh code $^ $@
+output_rhv_upload_precheck_source.ml: $(srcdir)/rhv-upload-precheck.py
+ $(srcdir)/embed.sh code $^ $@
if HAVE_OCAML
@@ -578,7 +578,7 @@ v2v_unit_tests_LINK = \
$(v2v_unit_tests_THEOBJECTS) -o $@
# Dependencies.
-.depend: $(srcdir)/*.mli $(srcdir)/*.ml
+.depend: $(srcdir)/*.mli $(srcdir)/*.ml output_rhv_upload_createvm_source.ml output_rhv_upload_plugin_source.ml output_rhv_upload_precheck_source.ml
$(top_builddir)/ocaml-dep.sh $^
-include .depend
--
2.17.0
6 years, 6 months
vmx+ssh conversion failure -- read failed: would block
by Tomáš Golembiovský
Hi,
I noticed some issues with the ssh transport mode where the virt-v2v
would fail because of issue with libssh2. I see a lot of following
errors before the conversion terminates:
> commandrvf: /usr/sbin/update-initramfs -v -c -k 4.9.0-4-amd64
> read failed: would block (libssh2 error code: -37, sftp error code: 0)
> /usr/sbin/mkinitramfs: 265: /usr/sbin/mkinitramfs: dirname: Exec format error
Full log attached. The command used to run the conversion was:
> '/usr/bin/virt-v2v' '-v' '-x' 'ssh://root@x.x.x.x/vmfs/volumes/datastore/tg-mini/tg-mini.vmx' '-of' 'raw' '--bridge' 'ovirtmgmt' '-i' 'vmx' '-it' 'ssh' '-o' 'rhv-upload' '-oc' 'https://ovirt-engine42.kvm/ovirt-engine/api' '-os' 'data' '-op' '/tmp/tmpAEJ9LA.v2v' '-oo' 'rhv-cafile=/etc/pki/vdsm/certs/cacert.pem' '-oo' 'rhv-cluster=Default' '-oo' 'rhv-direct' '-oa' 'sparse' '--bridge' 'VM Network:ovirtmgmt' '--bridge' 'TG_Network:testnet'
Is this bug in qemu or are we simply using it wrong?
Tomas
--
Tomáš Golembiovský <tgolembi(a)redhat.com>
6 years, 6 months
[PATCH v2] v2v: linux: fix kernel detection when split in different packages
by Pino Toscano
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
6 years, 6 months