Fix CVE-2022-2211 Denial of Service in --key parameter

resolves: rhbz#2102719
Add -oo compressed support
resolves: rhbz#2047660
Install qemu-ga package during conversion (2028764)
Limit the maximum of disks per guest
resolves: rhbz#2051564
Add support for LUKS encrypted guests using Clevis & Tang
resolves: rhbz#1809453
This commit is contained in:
Richard W.M. Jones 2022-07-05 12:05:05 +01:00
parent 05ecc1e30a
commit b6cf325d1f
20 changed files with 36182 additions and 4 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,44 @@
From ef6e9a2fbe5c294837a019533a38a42ffb5770d7 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 8 Jun 2022 16:10:56 +0100
Subject: [PATCH] test-data/phony-guests: Increase size of root filesystem
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Avoid this error in virt-v2v when trying to convert the phony Fedora
guest image:
[ 8.1] Checking for sufficient free disk space in the guest
virt-v2v: error: not enough free space for conversion on filesystem
/. 21.6 MB free < 100 MB needed
(cherry picked from commit fd7cd0c0fd2259506f6ec1c248c11c1158656665)
---
test-data/phony-guests/make-fedora-img.pl | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/test-data/phony-guests/make-fedora-img.pl b/test-data/phony-guests/make-fedora-img.pl
index 90492b81..f340f4d7 100755
--- a/test-data/phony-guests/make-fedora-img.pl
+++ b/test-data/phony-guests/make-fedora-img.pl
@@ -1,6 +1,6 @@
#!/usr/bin/env perl
# libguestfs
-# Copyright (C) 2010-2020 Red Hat Inc.
+# Copyright (C) 2010-2022 Red Hat Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -210,7 +210,7 @@ sub init_lvm_root {
$g->pvcreate ($rootdev);
$g->vgcreate ('VG', [$rootdev]);
- $g->lvcreate ('Root', 'VG', 32);
+ $g->lvcreate ('Root', 'VG', 256);
$g->lvcreate ('LV1', 'VG', 32);
$g->lvcreate ('LV2', 'VG', 32);
$g->lvcreate ('LV3', 'VG', 64);
--
2.31.1

View File

@ -0,0 +1,220 @@
From 3c8d2e517491edd9241542f21f1203f098e29677 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 8 Jun 2022 16:24:18 +0100
Subject: [PATCH] test-data/phony-guests: Allow virt-v2v to work against phony
Fedora
We didn't use the phony Fedora guest before with virt-v2v (only the
phony Windows image). This commit makes miscellaneous changes so that
it can be used for testing:
- Add dummy rpm and dracut commands.
- Add dummy kernel, initramfs and modules directory.
- Add dummy grub configuration pointing to the kernel.
(cherry picked from commit 1e75569aa074a50e96867d1021651ca2f75bcc16)
---
.gitignore | 1 +
test-data/phony-guests/Makefile.am | 19 +++++--
test-data/phony-guests/fedora.c | 66 +++++++++++++++++++++++
test-data/phony-guests/make-fedora-img.pl | 26 ++++++++-
4 files changed, 107 insertions(+), 5 deletions(-)
create mode 100644 test-data/phony-guests/fedora.c
diff --git a/.gitignore b/.gitignore
index 5a48ee58..dcafa39c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -119,6 +119,7 @@ Makefile.in
/test-data/phony-guests/fedora-luks.img
/test-data/phony-guests/fedora-md1.img
/test-data/phony-guests/fedora-md2.img
+/test-data/phony-guests/fedora-static-bin
/test-data/phony-guests/fedora.db
/test-data/phony-guests/guests.xml
/test-data/phony-guests/guests-all-good.xml
diff --git a/test-data/phony-guests/Makefile.am b/test-data/phony-guests/Makefile.am
index 60313548..c45ddc11 100644
--- a/test-data/phony-guests/Makefile.am
+++ b/test-data/phony-guests/Makefile.am
@@ -76,7 +76,8 @@ blank-%.img:
# Make a (dummy) Fedora image.
fedora.img: make-fedora-img.pl \
fedora-journal.tar.xz \
- fedora.db
+ fedora.db \
+ fedora-static-bin
SRCDIR=$(srcdir) LAYOUT=partitions $(top_builddir)/run --test ./$<
# Make a (dummy) Fedora image using md devices
@@ -84,7 +85,8 @@ fedora-md1.img fedora-md2.img: stamp-fedora-md.img
stamp-fedora-md.img: make-fedora-img.pl \
fedora-journal.tar.xz \
- fedora.db
+ fedora.db \
+ fedora-static-bin
rm -f $@
SRCDIR=$(srcdir) LAYOUT=partitions-md $(top_builddir)/run --test ./$<
touch $@
@@ -93,13 +95,15 @@ stamp-fedora-md.img: make-fedora-img.pl \
# for root and home.
fedora-btrfs.img: make-fedora-img.pl \
fedora-journal.tar.xz \
- fedora.db
+ fedora.db \
+ fedora-static-bin
SRCDIR=$(srcdir) LAYOUT=btrfs $(top_builddir)/run --test ./$<
# Make a (dummy) Fedora image with LVM encrypted with LUKS.
fedora-luks.img: make-fedora-img.pl \
fedora-journal.tar.xz \
- fedora.db
+ fedora.db \
+ fedora-static-bin
SRCDIR=$(srcdir) LAYOUT=lvm-luks $(top_builddir)/run --test ./$<
# Make a (dummy) Debian image.
@@ -137,6 +141,13 @@ fedora.db: fedora-db.sql.xz
xzcat $< | $(SQLITE3) $@-t
mv $@-t $@
+# This is included in the phony Fedora image to act as a phony "rpm"
+# and "dracut" command. For the use of -all-static here, see
+# libguestfs/tests/Makefile.am
+check_PROGRAMS = fedora-static-bin
+fedora_static_bin_SOURCES = fedora.c
+fedora_static_bin_LDFLAGS = -all-static
+
windows-software: windows-software.reg
rm -f $@ $@-t
cp $(srcdir)/minimal-hive $@-t
diff --git a/test-data/phony-guests/fedora.c b/test-data/phony-guests/fedora.c
new file mode 100644
index 00000000..c74976d6
--- /dev/null
+++ b/test-data/phony-guests/fedora.c
@@ -0,0 +1,66 @@
+/* libguestfs test images
+ * Copyright (C) 2009-2020 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/* This is "just enough" of a binary to look like RPM and dracut, as
+ * far as virt-v2v is concerned.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* NB: This is also defined in make-fedora-img.pl */
+#define KVER "5.19.0-0.rc1.14.fc37.x86_64"
+
+static const char *
+get_basename (const char *str)
+{
+ const char *ret = strrchr (str, '/');
+ return ret == NULL ? str : ret + 1;
+}
+
+int
+main (int argc, char *argv[])
+{
+ if (argc == 3 &&
+ strcmp (get_basename (argv[0]), "rpm") == 0 &&
+ strcmp (argv[1], "-ql") == 0 &&
+ strncmp (argv[2], "kernel-", 7) == 0) {
+ /* XXX These files and directories actually exist. It would be
+ * better to list files in /boot and /lib/modules matching a
+ * pattern rather than hard-coding the list here, which duplicates
+ * information in make-fedora-img.pl.
+ */
+ printf ("/boot/vmlinuz-" KVER "\n");
+ printf ("/lib/modules/" KVER "\n");
+ printf ("/lib/modules/" KVER "/kernel\n");
+ printf ("/lib/modules/" KVER "/kernel/drivers\n");
+ printf ("/lib/modules/" KVER "/kernel/drivers/block\n");
+ printf ("/lib/modules/" KVER "/kernel/drivers/block/virtio_blk.ko\n");
+ }
+ else if (argc >= 1 &&
+ strcmp (get_basename (argv[0]), "dracut") == 0) {
+ // do nothing, pretend to rebuild the initramfs
+ }
+ else {
+ fprintf (stderr, "phony Fedora: unknown command\n");
+ exit (1);
+ }
+
+ exit (0);
+}
diff --git a/test-data/phony-guests/make-fedora-img.pl b/test-data/phony-guests/make-fedora-img.pl
index f340f4d7..ad30960f 100755
--- a/test-data/phony-guests/make-fedora-img.pl
+++ b/test-data/phony-guests/make-fedora-img.pl
@@ -240,6 +240,7 @@ $g->mount ($bootdev, '/boot');
$g->mkdir ('/bin');
$g->mkdir ('/etc');
$g->mkdir ('/etc/sysconfig');
+$g->mkdir ('/sbin');
$g->mkdir ('/usr');
$g->mkdir ('/usr/share');
$g->mkdir ('/usr/share/zoneinfo');
@@ -276,8 +277,17 @@ $g->upload ($ENV{SRCDIR}.'/../binaries/bin-x86_64-dynamic', '/bin/ls');
$g->tar_in ($ENV{SRCDIR}.'/fedora-journal.tar.xz', '/var/log/journal', compress => "xz");
+# NB: This is also defined in fedora.c
+my $kver = "5.19.0-0.rc1.14.fc37.x86_64";
$g->mkdir ('/boot/grub');
-$g->touch ('/boot/grub/grub.conf');
+$g->write ('/boot/grub/grub.conf', <<EOF);
+title Fedora
+ root (hd0,0)
+ kernel /vmlinuz-$kver
+ initrd /initramfs-$kver.img
+EOF
+
+$g->touch ('/etc/modprobe.conf');
# Test files.
$g->write ('/etc/test1', 'abcdefg');
@@ -300,6 +310,20 @@ $g->ln_s ('/bin/test1', '/bin/test5');
$g->mkfifo (0777, '/bin/test6');
$g->mknod (0777, 10, 10, '/bin/test7');
+# Virt-v2v needs an RPM command, or at least something which acts
+# similarly, and also a dracut command.
+$g->upload ('fedora-static-bin', '/bin/rpm');
+$g->chmod (0777, '/bin/rpm');
+$g->upload ('fedora-static-bin', '/sbin/dracut');
+$g->chmod (0777, '/sbin/dracut');
+
+# Virt-v2v also needs a kernel, initrd and modules path.
+$g->touch ("/boot/vmlinuz-$kver");
+$g->touch ("/boot/initramfs-$kver.img");
+$g->mkdir_p ("/lib/modules/$kver/kernel/drivers/block");
+$g->upload ($ENV{SRCDIR}.'/../binaries/bin-x86_64-dynamic',
+ "/lib/modules/$kver/kernel/drivers/block/virtio_blk.ko");
+
# Cleanup
$g->shutdown ();
$g->close ();
--
2.31.1

View File

@ -0,0 +1,202 @@
From 34e04554158afb85ee6b5baebe2a9b18e0b34c86 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 8 Jun 2022 17:31:24 +0100
Subject: [PATCH] tests: Add test cases for converting the phony Fedora images
As well as testing a full Fedora conversion which was not really
tested properly before, this also adds tests of conversions of Btrfs,
RAID and LUKS guests.
(cherry picked from commit 3600f81ec5b584cbdc3f1d33a7a42bbc014e2412)
---
tests/Makefile.am | 8 ++++++
tests/test-v2v-fedora-btrfs-conversion.sh | 31 +++++++++++++++++++++
tests/test-v2v-fedora-conversion.sh | 31 +++++++++++++++++++++
tests/test-v2v-fedora-luks-conversion.sh | 32 ++++++++++++++++++++++
tests/test-v2v-fedora-md-conversion.sh | 33 +++++++++++++++++++++++
5 files changed, 135 insertions(+)
create mode 100755 tests/test-v2v-fedora-btrfs-conversion.sh
create mode 100755 tests/test-v2v-fedora-conversion.sh
create mode 100755 tests/test-v2v-fedora-luks-conversion.sh
create mode 100755 tests/test-v2v-fedora-md-conversion.sh
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 549d39e1..eb2931c5 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -95,6 +95,10 @@ TESTS = \
test-v2v-print-source.sh \
test-v2v-sound.sh \
test-v2v-virtio-win-iso.sh \
+ test-v2v-fedora-conversion.sh \
+ test-v2v-fedora-btrfs-conversion.sh \
+ test-v2v-fedora-luks-conversion.sh \
+ test-v2v-fedora-md-conversion.sh \
test-v2v-windows-conversion.sh \
rhbz1232192.sh \
$(SLOW_TESTS) \
@@ -170,6 +174,10 @@ EXTRA_DIST += \
test-v2v-bad-networks-and-bridges.sh \
test-v2v-cdrom.expected \
test-v2v-cdrom.sh \
+ test-v2v-fedora-conversion.sh \
+ test-v2v-fedora-btrfs-conversion.sh \
+ test-v2v-fedora-luks-conversion.sh \
+ test-v2v-fedora-md-conversion.sh \
test-v2v-floppy.expected \
test-v2v-floppy.sh \
test-v2v-i-disk.sh \
diff --git a/tests/test-v2v-fedora-btrfs-conversion.sh b/tests/test-v2v-fedora-btrfs-conversion.sh
new file mode 100755
index 00000000..c78f8ae2
--- /dev/null
+++ b/tests/test-v2v-fedora-btrfs-conversion.sh
@@ -0,0 +1,31 @@
+#!/bin/bash -
+# libguestfs virt-v2v test script
+# Copyright (C) 2014-2022 Red Hat Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+# Test virt-v2v (Phony) Fedora conversion.
+
+set -e
+
+source ./functions.sh
+set -e
+set -x
+
+skip_if_skipped
+f=../test-data/phony-guests/fedora-btrfs.img
+requires test -f $f
+
+$VG virt-v2v --debug-gc -i disk $f -o null
diff --git a/tests/test-v2v-fedora-conversion.sh b/tests/test-v2v-fedora-conversion.sh
new file mode 100755
index 00000000..92f4bbe8
--- /dev/null
+++ b/tests/test-v2v-fedora-conversion.sh
@@ -0,0 +1,31 @@
+#!/bin/bash -
+# libguestfs virt-v2v test script
+# Copyright (C) 2014-2022 Red Hat Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+# Test virt-v2v (Phony) Fedora conversion.
+
+set -e
+
+source ./functions.sh
+set -e
+set -x
+
+skip_if_skipped
+f=../test-data/phony-guests/fedora.img
+requires test -f $f
+
+$VG virt-v2v --debug-gc -i disk $f -o null
diff --git a/tests/test-v2v-fedora-luks-conversion.sh b/tests/test-v2v-fedora-luks-conversion.sh
new file mode 100755
index 00000000..2922c31d
--- /dev/null
+++ b/tests/test-v2v-fedora-luks-conversion.sh
@@ -0,0 +1,32 @@
+#!/bin/bash -
+# libguestfs virt-v2v test script
+# Copyright (C) 2014-2022 Red Hat Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+# Test virt-v2v (Phony) Fedora conversion.
+
+set -e
+
+source ./functions.sh
+set -e
+set -x
+
+skip_if_skipped
+f=../test-data/phony-guests/fedora-luks.img
+requires test -f $f
+
+# The disk is encrypted with password "FEDORA".
+$VG virt-v2v --debug-gc -i disk $f -o null --key /dev/sda2:key:FEDORA
diff --git a/tests/test-v2v-fedora-md-conversion.sh b/tests/test-v2v-fedora-md-conversion.sh
new file mode 100755
index 00000000..669f2c01
--- /dev/null
+++ b/tests/test-v2v-fedora-md-conversion.sh
@@ -0,0 +1,33 @@
+#!/bin/bash -
+# libguestfs virt-v2v test script
+# Copyright (C) 2014-2022 Red Hat Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+# Test virt-v2v (Phony) Fedora conversion.
+
+set -e
+
+source ./functions.sh
+set -e
+set -x
+
+skip_if_skipped
+f1=../test-data/phony-guests/fedora-md1.img
+requires test -f $f1
+f2=../test-data/phony-guests/fedora-md2.img
+requires test -f $f2
+
+$VG virt-v2v --debug-gc -i disk $f1 $f2 -o null
--
2.31.1

View File

@ -0,0 +1,108 @@
From 6e5b4da53504a4b62d225fe103e5821ccbfd3c3a Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Mon, 13 Jun 2022 19:01:32 +0200
Subject: [PATCH] output/create_libvirt_xml: wire up the QEMU guest agent
The intent (even before RHBZ#2028764) has been to install the QEMU guest
agent in the converted domain unconditionally. Therefore, in order for the
GA to be actually accessible from the host side, augment the libvirt
output module with a "guest agent connection" also unconditionally.
For starters, the domain needs a virtio-serial device. Then there must be
a port on the device that (in the guest) the GA identifies by name, and
that (on the host) is exposed as a listening socket (usually in the unix
address family). The adress of that port (usually a pathname, i.e., for a
unix domain socket) is then passed to whatever host-side application wants
to talk to the GA.
The minimal domain XML fragment for that ("minimal" for our purposes) is
<controller type='virtio-serial' model='virtio'>
<channel type='unix'>
<target type='virtio' name='org.qemu.guest_agent.0'/>
</channel>
The "controller" element is needed because "controller/@model" is where we
regulate "virtio" vs. "virtio-transitional".
Everything else is filled in by libvirt. Notably, libvirt (a) creates and
binds the unix domain socket itself (usually
"/var/lib/libvirt/qemu/channel/target/DOMAIN/org.qemu.guest_agent.0"), (b)
passes the file descriptor to QEMU, and (c) figures out the socket
pathname for commands such as
virsh domfsinfo DOMAIN
virsh domhostname DOMAIN --source agent
virsh domifaddr DOMAIN --source agent
virsh guestinfo DOMAIN
For QEMU, the corresponding options would be
-chardev socket,id=agent,server=on,wait=off,path=/tmp/DOMAIN-agent \
-device virtio-serial-pci,id=vioserial \
-device virtserialport,bus=vioserial.0,nr=1,chardev=agent,name=org.qemu.guest_agent.0 \
Note the "path=/tmp/DOMAIN-agent" property of "-chardev"; virt-v2v would
have to generate that (in place of the "fd=nnnn" property that libvirt
passes to QEMU).
Omit extending the QEMU output module for now, as the QGA protocol is
based on JSON, and one needs "virsh" or "virt-manager" (or another
management application interface) anyway, for efficiently exchanging
messages with QGA. I don't know of end-user tools that directly connect to
"/tmp/DOMAIN-agent".
Don't modify the RHV and OpenStack outputs either; both of these
management products likely configure the virtio-serial device
automatically, for the agent access.
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2028764
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20220613170135.12557-2-lersek@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Tested-by: Richard W.M. Jones <rjones@redhat.com>
(cherry picked from commit 48c6ea27c5a7053e418622f7450e3f9ef05c923f)
---
output/create_libvirt_xml.ml | 11 +++++++++++
tests/test-v2v-i-ova.xml | 4 ++++
2 files changed, 15 insertions(+)
diff --git a/output/create_libvirt_xml.ml b/output/create_libvirt_xml.ml
index 68d0a909..531a4f75 100644
--- a/output/create_libvirt_xml.ml
+++ b/output/create_libvirt_xml.ml
@@ -524,6 +524,17 @@ let create_libvirt_xml ?pool source inspect
e "console" ["type", "pty"] [];
];
+ (* Given that we install the QEMU Guest Agent for both Linux and Windows
+ * guests unconditionally, create the virtio-serial device that's needed for
+ * communication between the host and the agent.
+ *)
+ List.push_back_list devices [
+ e "controller" ["type", "virtio-serial"; "model", virtio_model] [];
+ e "channel" ["type", "unix"] [
+ e "target" ["type", "virtio"; "name", "org.qemu.guest_agent.0"] []
+ ]
+ ];
+
List.push_back_list body [
e "devices" [] !devices;
];
diff --git a/tests/test-v2v-i-ova.xml b/tests/test-v2v-i-ova.xml
index 6b8cda62..da1db473 100644
--- a/tests/test-v2v-i-ova.xml
+++ b/tests/test-v2v-i-ova.xml
@@ -49,5 +49,9 @@
<input type='tablet' bus='usb'/>
<input type='mouse' bus='ps2'/>
<console type='pty'/>
+ <controller type='virtio-serial' model='virtio'/>
+ <channel type='unix'>
+ <target type='virtio' name='org.qemu.guest_agent.0'/>
+ </channel>
</devices>
</domain>
--
2.31.1

View File

@ -0,0 +1,203 @@
From 2aa40ec1db2af2310a649bf6142f8de1ef0cd8e2 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Mon, 13 Jun 2022 19:01:33 +0200
Subject: [PATCH] windows_virtio: remove "install_linux_tools"
"Windows_virtio.install_linux_tools" has never really worked in practice;
we've never managed to get the right content into the right location on
the virtio-win ISO.
Later patches in this series will install the qemu guest agent in a
firstboot script, using the guest's own package manager. For now, for ease
of review, only remove "Windows_virtio.install_linux_tools", and its
dependencies that now become unused:
- Linux.architecture_string
- Linux.binary_package_extension
- Linux.install_local
Salvage the comment (at the outermost call site) that failure to install
QGA is not fatal. This will be relevant for exception handling in the
subsequent patches.
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2028764
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Acked-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20220613170135.12557-3-lersek@redhat.com>
(cherry picked from commit 52e9cd77a8ef7c1b7975d4f72056f8f6b45fb10b)
---
convert/convert_linux.ml | 4 +++-
convert/linux.ml | 35 -------------------------------
convert/linux.mli | 11 ----------
convert/windows_virtio.ml | 42 --------------------------------------
convert/windows_virtio.mli | 4 ----
5 files changed, 3 insertions(+), 93 deletions(-)
diff --git a/convert/convert_linux.ml b/convert/convert_linux.ml
index 56604949..79462aa1 100644
--- a/convert/convert_linux.ml
+++ b/convert/convert_linux.ml
@@ -538,13 +538,15 @@ let convert (g : G.guestfs) source inspect keep_serial_console _ =
)
and install_linux_tools () =
+ (* It is not fatal if we fail to install the QEMU guest agent. *)
let has_qemu_guest_agent =
List.exists (
fun { G.app2_name = name } ->
name = "qemu-guest-agent"
) inspect.i_apps in
if not has_qemu_guest_agent then
- Windows_virtio.install_linux_tools g inspect
+ (* FIXME -- install qemu-guest-agent here *)
+ ()
and configure_kernel () =
(* Previously this function would try to install kernels, but we
diff --git a/convert/linux.ml b/convert/linux.ml
index e2908d02..f9acd63f 100644
--- a/convert/linux.ml
+++ b/convert/linux.ml
@@ -33,20 +33,6 @@ let augeas_reload g =
g#aug_load ();
debug_augeas_errors g
-let rec install_local g { i_package_format = package_format } packages =
- if packages <> [] then (
- match package_format with
- | "rpm" ->
- let cmd = [ "rpm"; "--upgrade"; "-v" ] @ packages in
- let cmd = Array.of_list cmd in
- ignore (g#command cmd)
- | format ->
- error (f_"dont know how to install packages using %s: packages: %s")
- format (String.concat " " packages)
- (* Reload Augeas in case anything changed. *)
- augeas_reload g
- )
-
let rec remove g inspect packages =
if packages <> [] then (
do_remove g inspect packages;
@@ -187,24 +173,3 @@ let is_package_manager_save_file filename =
(* Recognized suffixes of package managers. *)
let suffixes = [ ".dpkg-old"; ".dpkg-new"; ".rpmsave"; ".rpmnew"; ] in
List.exists (Filename.check_suffix filename) suffixes
-
-let binary_package_extension { i_package_format = package_format } =
- match package_format with
- | "deb" -> "deb"
- | "rpm" -> "rpm"
- | format ->
- error (f_"dont know what is the extension of binary packages using %s")
- format
-
-let architecture_string { i_package_format = package_format; i_arch = arch;
- i_distro = distro } =
- match package_format, distro, arch with
- | "deb", _, "x86_64" -> "amd64"
- | "deb", _, a -> a
- | "rpm", ("sles"|"suse-based"|"opensuse"), "i386" -> "i586"
- | "rpm", ("sles"|"suse-based"|"opensuse"), a -> a
- | "rpm", _, "i386" -> "i686"
- | "rpm", _, a -> a
- | format, distro, arch ->
- error (f_"dont know what is the architecture string of %s using %s on %s")
- arch format distro
diff --git a/convert/linux.mli b/convert/linux.mli
index 856ffe3c..57898310 100644
--- a/convert/linux.mli
+++ b/convert/linux.mli
@@ -23,9 +23,6 @@ val augeas_reload : Guestfs.guestfs -> unit
additional debugging information about parsing problems
that augeas found. *)
-val install_local: Guestfs.guestfs -> Types.inspect -> string list -> unit
-(** Install package(s). *)
-
val remove : Guestfs.guestfs -> Types.inspect -> string list -> unit
(** Uninstall package(s). *)
@@ -38,11 +35,3 @@ val is_file_owned : Guestfs.guestfs -> Types.inspect -> string -> bool
val is_package_manager_save_file : string -> bool
(** Return true if the filename is something like [*.rpmsave], ie.
a package manager save-file. *)
-
-val binary_package_extension : Types.inspect -> string
-(** Return the extension typically used for binary packages in the
- specified package format. *)
-
-val architecture_string : Types.inspect -> string
-(** Return the architecture string typically used for binary packages
- in the specified package format, and for the specified distro. *)
diff --git a/convert/windows_virtio.ml b/convert/windows_virtio.ml
index 301f7544..183166b7 100644
--- a/convert/windows_virtio.ml
+++ b/convert/windows_virtio.ml
@@ -113,48 +113,6 @@ let rec install_drivers ((g, _) as reg) inspect =
virtio_rng_supported, virtio_ballon_supported, isa_pvpanic_supported, virtio_socket_supported)
)
-and install_linux_tools g inspect =
- let os =
- match inspect.i_distro with
- | "fedora" -> Some "fc28"
- | "rhel" | "centos" | "scientificlinux" | "redhat-based"
- | "oraclelinux" ->
- (* map 6 -> "el6" etc. *)
- if inspect.i_major_version >= 6 then
- Some (sprintf "el%d" inspect.i_major_version)
- else
- None
- | "sles" | "suse-based" | "opensuse" -> Some "lp151"
- | _ -> None in
-
- match os with
- | None -> ()
- | Some os ->
- let src_path = "linux" // os in
- let dst_path = "/var/tmp" in
- let pkg_arch = Linux.architecture_string inspect in
- let pkg_ext = Linux.binary_package_extension inspect in
- let package_suffixes = [
- sprintf ".%s.%s" pkg_arch pkg_ext;
- sprintf "_%s.%s" pkg_arch pkg_ext;
- ] in
- let package_filter path _ =
- List.exists (String.is_suffix path) package_suffixes
- in
- debug "locating packages in %s" src_path;
- let packages =
- copy_from_virtio_win g inspect src_path dst_path
- package_filter
- (fun () -> ()) in
- debug "done copying %d files" (List.length packages);
- let packages = List.map ((//) dst_path) packages in
- try
- Linux.install_local g inspect packages;
- if packages <> [] then
- info (f_"QEMU Guest Agent installed for this guest.");
- with G.Error msg ->
- warning (f_"failed to install QEMU Guest Agent: %s") msg
-
and add_guestor_to_registry ((g, root) as reg) inspect drv_name drv_pciid =
let ddb_node = g#hivex_node_get_child root "DriverDatabase" in
diff --git a/convert/windows_virtio.mli b/convert/windows_virtio.mli
index a92cc01d..73ec95c7 100644
--- a/convert/windows_virtio.mli
+++ b/convert/windows_virtio.mli
@@ -38,10 +38,6 @@ val install_drivers
reflecting what devices are now required by the guest, either virtio
devices if we managed to install those, or legacy devices if we didn't. *)
-val install_linux_tools : Guestfs.guestfs -> Types.inspect -> unit
-(** installs QEMU Guest Agent on Linux guest OS from the driver directory or
- driver ISO. It is not fatal if we fail to install the agent. *)
-
val copy_qemu_ga : Guestfs.guestfs -> Types.inspect -> string list
(** copy MSIs (idealy just one) with QEMU Guest Agent to Windows guest. The
MSIs are not installed by this function. *)
--
2.31.1

View File

@ -0,0 +1,85 @@
From bd1122439b4138952e6c14b834eac79405410a94 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Mon, 13 Jun 2022 19:01:34 +0200
Subject: [PATCH] convert_linux: extract qemu-guest-agent package name
In commit a30383e35d34 ("v2v: linux: do not install qemu-guest-agent if
already installed", 2019-09-20), the name of the package providing the
QEMU guest agent was hard-coded as "qemu-guest-agent", regardless of
distro family. Turns out this is actually correct (and may have been
intentional, only it was not specifically documented): in all OS families
currently recognized by our "family" function (`RHEL_family, `ALT_family,
`SUSE_family, `Debian_family), the *binary* package is indeed called
"qemu-guest-agent":
- https://brewweb.engineering.redhat.com/brew/packageinfo?packageID=47646
- http://rpmfind.net/linux/rpm2html/search.php?query=qemu-guest-agent&submit=Search+...&system=&arch=
- https://packages.altlinux.org/en/sisyphus/srpms/qemu/
- https://packages.debian.org/search?keywords=qemu-guest-agent&searchon=names&suite=all&section=all
As a way of documenting this, extract the mapping to a new helper function
named "qga_pkg_of_family".
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2028764
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Message-Id: <20220613170135.12557-4-lersek@redhat.com>
(cherry picked from commit f65e8e68fb4eb9b8d40ac0fe7bfc3122a13e5251)
---
convert/convert_linux.ml | 33 +++++++++++++++++++++++++--------
1 file changed, 25 insertions(+), 8 deletions(-)
diff --git a/convert/convert_linux.ml b/convert/convert_linux.ml
index 79462aa1..2ddbc07a 100644
--- a/convert/convert_linux.ml
+++ b/convert/convert_linux.ml
@@ -56,6 +56,16 @@ let convert (g : G.guestfs) source inspect keep_serial_console _ =
| "debian" | "ubuntu" | "linuxmint" | "kalilinux" -> `Debian_family
| _ -> assert false in
+ (* map the OS family name to the qemu-guest-agent package name *)
+ let qga_pkg_of_family =
+ function
+ | `RHEL_family
+ | `ALT_family
+ | `SUSE_family
+ | `Debian_family -> Some "qemu-guest-agent"
+ | _ -> None
+ in
+
assert (inspect.i_package_format = "rpm" || inspect.i_package_format = "deb");
(* Fail early if i_apps is empty. Certain steps such as kernel
@@ -539,14 +549,21 @@ let convert (g : G.guestfs) source inspect keep_serial_console _ =
and install_linux_tools () =
(* It is not fatal if we fail to install the QEMU guest agent. *)
- let has_qemu_guest_agent =
- List.exists (
- fun { G.app2_name = name } ->
- name = "qemu-guest-agent"
- ) inspect.i_apps in
- if not has_qemu_guest_agent then
- (* FIXME -- install qemu-guest-agent here *)
- ()
+ match qga_pkg_of_family family with
+ | None -> warning (f_"The name of the package that provides the QEMU Guest \
+ Agent for this guest OS is unknown. The guest agent \
+ will not be installed. Please consider reporting a \
+ bug according to the BUGS section of the virt-v2v(1) \
+ manual.")
+ | Some qga_pkg ->
+ let has_qemu_guest_agent =
+ List.exists (
+ fun { G.app2_name = name } ->
+ name = qga_pkg
+ ) inspect.i_apps in
+ if not has_qemu_guest_agent then
+ (* FIXME -- install qemu-guest-agent here *)
+ ()
and configure_kernel () =
(* Previously this function would try to install kernels, but we
--
2.31.1

View File

@ -0,0 +1,409 @@
From 21309da26e0647c00c16cfb374fa418991b432aa Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Mon, 13 Jun 2022 19:01:35 +0200
Subject: [PATCH] convert_linux: install the QEMU guest agent with a firstboot
script
Register a firstboot script, for installing the guest agent with the
guest's own package manager -- that is, "Guest_packages.install_command".
For installing the package, network connectivity is required. Check it
first with "nmcli" (also checking whether NetworkManager is running), then
with "systemd-networkd-wait-online" (dependent on systemd-networkd). Note
that NetworkManager and systemd-networkd are never supposed to be enabled
at the same time.
The source domain's SELinux policy may not allow our firstboot service to
execute the package's installation scripts (if any). For that reason,
temporarily disable SELinux around package installation.
After installation, register another script for launching the agent.
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2028764
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20220613170135.12557-5-lersek@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
(cherry picked from commit e64356896377af1ac75a03d6a4c6a4208910bbf4)
---
common | 2 +-
convert/convert_linux.ml | 78 ++++++++++++++++++++++++++++++++++++++--
2 files changed, 77 insertions(+), 3 deletions(-)
Submodule common 48527b87..9e990f3e:
diff --git a/common/mlcustomize/Makefile.am b/common/mlcustomize/Makefile.am
index cd7d8971..4e260647 100644
--- a/common/mlcustomize/Makefile.am
+++ b/common/mlcustomize/Makefile.am
@@ -38,10 +38,12 @@ generator_built = \
SOURCES_MLI = \
firstboot.mli \
+ guest_packages.mli \
SELinux_relabel.mli
SOURCES_ML = \
firstboot.ml \
+ guest_packages.ml \
SELinux_relabel.ml
if HAVE_OCAML
diff --git a/common/mlcustomize/customize-options.pod b/common/mlcustomize/customize-options.pod
index a83c80a5..8aafacde 100644
--- a/common/mlcustomize/customize-options.pod
+++ b/common/mlcustomize/customize-options.pod
@@ -310,6 +310,10 @@ It cannot delete directories, only regular files.
=back
+=item B<--selinux-relabel>
+
+This is a compatibility option that does nothing.
+
=item B<--sm-attach> SELECTOR
Attach to a pool using C<subscription-manager>.
diff --git a/common/mlcustomize/customize-synopsis.pod b/common/mlcustomize/customize-synopsis.pod
index 25208538..9e2c4b2b 100644
--- a/common/mlcustomize/customize-synopsis.pod
+++ b/common/mlcustomize/customize-synopsis.pod
@@ -13,4 +13,4 @@
[--uninstall PKG,PKG..] [--update] [--upload FILE:DEST]
[--write FILE:CONTENT] [--no-logfile]
[--password-crypto md5|sha256|sha512] [--no-selinux-relabel]
- [--sm-credentials SELECTOR]
+ [--selinux-relabel] [--sm-credentials SELECTOR]
diff --git a/common/mlcustomize/customize_cmdline.ml b/common/mlcustomize/customize_cmdline.ml
index 5d404e84..a17bed40 100644
--- a/common/mlcustomize/customize_cmdline.ml
+++ b/common/mlcustomize/customize_cmdline.ml
@@ -111,6 +111,8 @@ and flags = {
(* --password-crypto md5|sha256|sha512 *)
no_selinux_relabel : bool;
(* --no-selinux-relabel *)
+ selinux_relabel_ignored : bool;
+ (* --selinux-relabel *)
sm_credentials : Subscription_manager.sm_credentials option;
(* --sm-credentials SELECTOR *)
}
@@ -122,6 +124,7 @@ let rec argspec () =
let scrub_logfile = ref false in
let password_crypto = ref None in
let no_selinux_relabel = ref false in
+ let selinux_relabel_ignored = ref false in
let sm_credentials = ref None in
let rec get_ops () = {
@@ -132,6 +135,7 @@ let rec argspec () =
scrub_logfile = !scrub_logfile;
password_crypto = !password_crypto;
no_selinux_relabel = !no_selinux_relabel;
+ selinux_relabel_ignored = !selinux_relabel_ignored;
sm_credentials = !sm_credentials;
}
in
@@ -464,6 +468,12 @@ let rec argspec () =
s_"Do not relabel files with correct SELinux labels"
),
None, "Do not attempt to correct the SELinux labels of files in the guest.\n\nIn such guests that support SELinux, customization automatically\nrelabels files so that they have the correct SELinux label. (The\nrelabeling is performed immediately, but if the operation fails,\ncustomization will instead touch F</.autorelabel> on the image to\nschedule a relabel operation for the next time the image boots.) This\noption disables the automatic relabeling.\n\nThe option is a no-op for guests that do not support SELinux.";
+ (
+ [ L"selinux-relabel" ],
+ Getopt.Set selinux_relabel_ignored,
+ s_"Compatibility option doing nothing"
+ ),
+ None, "This is a compatibility option that does nothing.";
(
[ L"sm-credentials" ],
Getopt.String (
diff --git a/common/mlcustomize/customize_cmdline.mli b/common/mlcustomize/customize_cmdline.mli
index 7ee882a6..7d14e782 100644
--- a/common/mlcustomize/customize_cmdline.mli
+++ b/common/mlcustomize/customize_cmdline.mli
@@ -103,6 +103,8 @@ and flags = {
(* --password-crypto md5|sha256|sha512 *)
no_selinux_relabel : bool;
(* --no-selinux-relabel *)
+ selinux_relabel_ignored : bool;
+ (* --selinux-relabel *)
sm_credentials : Subscription_manager.sm_credentials option;
(* --sm-credentials SELECTOR *)
}
diff --git a/common/mlcustomize/guest_packages.ml b/common/mlcustomize/guest_packages.ml
new file mode 100644
index 00000000..4c3c34ed
--- /dev/null
+++ b/common/mlcustomize/guest_packages.ml
@@ -0,0 +1,132 @@
+(* virt-customize
+ * Copyright (C) 2012-2021 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+open Printf
+
+open Common_gettext.Gettext
+open Std_utils
+
+exception Unknown_package_manager of string
+exception Unimplemented_package_manager of string
+
+(* Windows has package_management == "unknown". *)
+let error_unknown_package_manager flag =
+ let msg = sprintf (f_"cannot use %s because no package manager has been \
+ detected for this guest OS.\n\nIf this guest OS is a \
+ common one with ordinary package management then this \
+ may have been caused by a failure of libguestfs \
+ inspection.\n\nFor OSes such as Windows that lack \
+ package management, this is not possible. Try using \
+ one of the --firstboot* flags instead (described in \
+ the virt-customize(1) manual).") flag in
+ raise (Unknown_package_manager msg)
+
+let error_unimplemented_package_manager flag pm =
+ let msg = sprintf (f_"sorry, %s with the %s package manager has not \
+ been implemented yet.\n\nYou can work around this by \
+ using one of the --run* or --firstboot* options \
+ instead (described in the virt-customize(1) manual).")
+ flag pm in
+ raise (Unimplemented_package_manager msg)
+
+(* http://distrowatch.com/dwres.php?resource=package-management *)
+let install_command packages package_management =
+ let quoted_args = String.concat " " (List.map quote packages) in
+ match package_management with
+ | "apk" ->
+ sprintf "
+ apk update
+ apk add %s
+ " quoted_args
+ | "apt" ->
+ (* http://unix.stackexchange.com/questions/22820 *)
+ sprintf "
+ export DEBIAN_FRONTEND=noninteractive
+ apt_opts='-q -y -o Dpkg::Options::=--force-confnew'
+ apt-get $apt_opts update
+ apt-get $apt_opts install %s
+ " quoted_args
+ | "dnf" ->
+ sprintf "dnf%s -y install %s"
+ (if verbose () then " --verbose" else "")
+ quoted_args
+ | "pisi" -> sprintf "pisi it %s" quoted_args
+ | "pacman" -> sprintf "pacman -S --noconfirm %s" quoted_args
+ | "urpmi" -> sprintf "urpmi %s" quoted_args
+ | "xbps" -> sprintf "xbps-install -Sy %s" quoted_args
+ | "yum" -> sprintf "yum -y install %s" quoted_args
+ | "zypper" -> sprintf "zypper -n in -l %s" quoted_args
+
+ | "unknown" ->
+ error_unknown_package_manager (s_"--install")
+ | pm ->
+ error_unimplemented_package_manager (s_"--install") pm
+
+let update_command package_management =
+ match package_management with
+ | "apk" ->
+ "
+ apk update
+ apk upgrade
+ "
+ | "apt" ->
+ (* http://unix.stackexchange.com/questions/22820 *)
+ "
+ export DEBIAN_FRONTEND=noninteractive
+ apt_opts='-q -y -o Dpkg::Options::=--force-confnew'
+ apt-get $apt_opts update
+ apt-get $apt_opts upgrade
+ "
+ | "dnf" ->
+ sprintf "dnf%s -y --best upgrade"
+ (if verbose () then " --verbose" else "")
+ | "pisi" -> "pisi upgrade"
+ | "pacman" -> "pacman -Su"
+ | "urpmi" -> "urpmi --auto-select"
+ | "xbps" -> "xbps-install -Suy"
+ | "yum" -> "yum -y update"
+ | "zypper" -> "zypper -n update -l"
+
+ | "unknown" ->
+ error_unknown_package_manager (s_"--update")
+ | pm ->
+ error_unimplemented_package_manager (s_"--update") pm
+
+let uninstall_command packages package_management =
+ let quoted_args = String.concat " " (List.map quote packages) in
+ match package_management with
+ | "apk" -> sprintf "apk del %s" quoted_args
+ | "apt" ->
+ (* http://unix.stackexchange.com/questions/22820 *)
+ sprintf "
+ export DEBIAN_FRONTEND=noninteractive
+ apt_opts='-q -y -o Dpkg::Options::=--force-confnew'
+ apt-get $apt_opts remove %s
+ " quoted_args
+ | "dnf" -> sprintf "dnf -y remove %s" quoted_args
+ | "pisi" -> sprintf "pisi rm %s" quoted_args
+ | "pacman" -> sprintf "pacman -R %s" quoted_args
+ | "urpmi" -> sprintf "urpme %s" quoted_args
+ | "xbps" -> sprintf "xbps-remove -Sy %s" quoted_args
+ | "yum" -> sprintf "yum -y remove %s" quoted_args
+ | "zypper" -> sprintf "zypper -n rm %s" quoted_args
+
+ | "unknown" ->
+ error_unknown_package_manager (s_"--uninstall")
+ | pm ->
+ error_unimplemented_package_manager (s_"--uninstall") pm
diff --git a/common/mlcustomize/guest_packages.mli b/common/mlcustomize/guest_packages.mli
new file mode 100644
index 00000000..7504a6ab
--- /dev/null
+++ b/common/mlcustomize/guest_packages.mli
@@ -0,0 +1,44 @@
+(* virt-customize
+ * Copyright (C) 2012-2021 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+exception Unknown_package_manager of string
+exception Unimplemented_package_manager of string
+(** For all three functions below, [package_management] determines the package
+ management system in use by the guest; commonly it should be filled in from
+ [Guestfs.inspect_get_package_management], or the equivalent guestfs object
+ method.
+
+ If [package_management] is unknown or unimplemented, the functions raise
+ [Unknown_package_manager "error message"] or [Unimplemented_package_manager
+ "error message"], correspondingly. *)
+
+val install_command : string list -> string -> string
+(** [install_command packages package_management] produces a properly quoted
+ shell command string suitable for execution in the guest (directly or via a
+ Firstboot script) for installing the OS packages listed in [packages]. *)
+
+val update_command : string -> string
+(** [update_command package_management] produces a properly quoted shell command
+ string suitable for execution in the guest (directly or via a Firstboot
+ script) for updating the OS packages that are currently installed in the
+ guest. *)
+
+val uninstall_command : string list -> string -> string
+(** [uninstall_command packages package_management] produces a properly quoted
+ shell command string suitable for execution in the guest (directly or via a
+ Firstboot script) for uninstalling the OS packages listed in [packages]. *)
diff --git a/convert/convert_linux.ml b/convert/convert_linux.ml
index 2ddbc07a..59d143bd 100644
--- a/convert/convert_linux.ml
+++ b/convert/convert_linux.ml
@@ -562,8 +562,82 @@ let convert (g : G.guestfs) source inspect keep_serial_console _ =
name = qga_pkg
) inspect.i_apps in
if not has_qemu_guest_agent then
- (* FIXME -- install qemu-guest-agent here *)
- ()
+ try
+ let inst_cmd = Guest_packages.install_command [qga_pkg]
+ inspect.i_package_management in
+
+ (* Use only the portable filename character set in this. *)
+ let selinux_enforcing = "/root/virt-v2v-fb-selinux-enforcing"
+ and timeout = 30 in
+ let fbs =
+ Firstboot.add_firstboot_script g inspect.i_root
+ in
+ info (f_"The QEMU Guest Agent will be installed for this guest at \
+ first boot.");
+
+ (* Wait for the network to come online in the guest (best effort).
+ *)
+ fbs "wait online"
+ (sprintf "#!/bin/sh\n\
+ if conn=$(nmcli networking connectivity); then\n\
+ \ \ tries=0\n\
+ \ \ while\n\
+ \ \ \ \ test $tries -lt %d &&\n\
+ \ \ \ \ test full != \"$conn\"\n\
+ \ \ do\n\
+ \ \ \ \ sleep 1\n\
+ \ \ \ \ tries=$((tries + 1))\n\
+ \ \ \ \ conn=$(nmcli networking connectivity)\n\
+ \ \ done\n\
+ elif systemctl -q is-active systemd-networkd; then\n\
+ \ \ /usr/lib/systemd/systemd-networkd-wait-online \\\n\
+ \ \ \ \ -q --timeout=%d\n\
+ fi\n" timeout timeout);
+
+ (* Disable SELinux temporarily around package installation. Refer to
+ * <https://bugzilla.redhat.com/show_bug.cgi?id=2028764#c7> and
+ * <https://bugzilla.redhat.com/show_bug.cgi?id=2028764#c8>.
+ *)
+ fbs "setenforce 0"
+ (sprintf "#!/bin/sh\n\
+ rm -f %s\n\
+ if command -v getenforce >/dev/null &&\n\
+ \ \ test Enforcing = \"$(getenforce)\"\n\
+ then\n\
+ \ \ touch %s\n\
+ \ \ setenforce 0\n\
+ fi\n" selinux_enforcing selinux_enforcing);
+ fbs "install qga" inst_cmd;
+ fbs "setenforce restore"
+ (sprintf "#!/bin/sh\n\
+ if test -f %s; then\n\
+ \ \ setenforce 1\n\
+ \ \ rm -f %s\n\
+ fi\n" selinux_enforcing selinux_enforcing);
+
+ (* Start the agent now and at subsequent boots. The following
+ * commands should work on both sysvinit distros / distro versions
+ * (regardless of "/etc/rc.d/" vs. "/etc/init.d/" being the scheme
+ * in use) and systemd distros (via redirection to systemctl).
+ *
+ * On distros where the chkconfig command is redirected to
+ * systemctl, the chkconfig command is likely superfluous. That's
+ * because on systemd distros, the QGA package comes with such
+ * runtime dependencies / triggers that the presence of the
+ * virtio-serial port named "org.qemu.guest_agent.0" automatically
+ * starts the agent during (second and later) boots. However, even
+ * on such distros, the chkconfig command should do no harm.
+ *)
+ fbs "start qga"
+ (sprintf "#!/bin/sh\n\
+ service %s start\n\
+ chkconfig %s on\n" qga_pkg qga_pkg)
+ with
+ | Guest_packages.Unknown_package_manager msg
+ | Guest_packages.Unimplemented_package_manager msg ->
+ warning (f_"The QEMU Guest Agent will not be installed. The \
+ install command for package %s could not be created: \
+ %s.") qga_pkg msg
and configure_kernel () =
(* Previously this function would try to install kernels, but we
--
2.31.1

View File

@ -0,0 +1,35 @@
From 55ae823b5a98667483ef6c9bf1f70011f2f60268 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 14 Jun 2022 13:27:07 +0200
Subject: [PATCH] test-data: Replace deprecated luks_open with cryptsetup_open.
The two calls are identical, so this simply avoids a deprecation
warning.
(Picked from guestfs-tools commit 9a27f19269f5 ("test-data: Replace
deprecated luks_open with cryptsetup_open.", 2022-02-28).)
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20220614112709.12210-2-lersek@redhat.com>
Acked-by: Richard W.M. Jones <rjones@redhat.com>
(cherry picked from commit 88e237da4c4d065e445659e2fdf34892cb99bdb9)
---
test-data/phony-guests/make-fedora-img.pl | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test-data/phony-guests/make-fedora-img.pl b/test-data/phony-guests/make-fedora-img.pl
index ad30960f..488a7d89 100755
--- a/test-data/phony-guests/make-fedora-img.pl
+++ b/test-data/phony-guests/make-fedora-img.pl
@@ -195,7 +195,7 @@ EOF
# Put LUKS on the second partition.
$g->luks_format ('/dev/sda2', 'FEDORA', 0);
- $g->luks_open ('/dev/sda2', 'FEDORA', 'luks');
+ $g->cryptsetup_open ('/dev/sda2', 'FEDORA', 'luks');
init_lvm_root ('/dev/mapper/luks');
}
--
2.31.1

View File

@ -0,0 +1,158 @@
From b01ebfd510a841341c653d709ed94ad4ff4b7637 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Tue, 14 Jun 2022 13:27:08 +0200
Subject: [PATCH] tests: rename "luks" to "lvm-on-luks"
Clarify that our current usage of "luks" stands for "lvm-on-luks" (IOW,
that the decrypted LUKS devices are Physical Volumes for LVM).
(This is a port of libguestfs patch 'tests: rename "luks" to
"lvm-on-luks"' -- commit 39a5bb6fda4d. See also guestfs-tools commit
8f2bbc3d50d8 -- 'inspector: rename "luks" to "lvm-on-luks"', 2022-02-28.)
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20220614112709.12210-3-lersek@redhat.com>
Acked-by: Richard W.M. Jones <rjones@redhat.com>
(cherry picked from commit a2ff864d9332686cb7c27ccffe82783622c5d73d)
---
.gitignore | 2 +-
test-data/phony-guests/Makefile.am | 8 ++++----
test-data/phony-guests/guests.xml.in | 4 ++--
test-data/phony-guests/make-fedora-img.pl | 8 ++++----
tests/Makefile.am | 4 ++--
...rsion.sh => test-v2v-fedora-lvm-on-luks-conversion.sh} | 2 +-
6 files changed, 14 insertions(+), 14 deletions(-)
rename tests/{test-v2v-fedora-luks-conversion.sh => test-v2v-fedora-lvm-on-luks-conversion.sh} (95%)
diff --git a/.gitignore b/.gitignore
index dcafa39c..0256b89d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -116,7 +116,7 @@ Makefile.in
/test-data/phony-guests/debian.img
/test-data/phony-guests/fedora.img
/test-data/phony-guests/fedora-btrfs.img
-/test-data/phony-guests/fedora-luks.img
+/test-data/phony-guests/fedora-lvm-on-luks.img
/test-data/phony-guests/fedora-md1.img
/test-data/phony-guests/fedora-md2.img
/test-data/phony-guests/fedora-static-bin
diff --git a/test-data/phony-guests/Makefile.am b/test-data/phony-guests/Makefile.am
index c45ddc11..6d7db3da 100644
--- a/test-data/phony-guests/Makefile.am
+++ b/test-data/phony-guests/Makefile.am
@@ -49,7 +49,7 @@ disk_images = \
fedora-md1.img \
fedora-md2.img \
fedora-btrfs.img \
- fedora-luks.img \
+ fedora-lvm-on-luks.img \
ubuntu.img \
archlinux.img \
coreos.img \
@@ -99,12 +99,12 @@ fedora-btrfs.img: make-fedora-img.pl \
fedora-static-bin
SRCDIR=$(srcdir) LAYOUT=btrfs $(top_builddir)/run --test ./$<
-# Make a (dummy) Fedora image with LVM encrypted with LUKS.
-fedora-luks.img: make-fedora-img.pl \
+# Make a (dummy) Fedora image with LVM-on-LUKS.
+fedora-lvm-on-luks.img: make-fedora-img.pl \
fedora-journal.tar.xz \
fedora.db \
fedora-static-bin
- SRCDIR=$(srcdir) LAYOUT=lvm-luks $(top_builddir)/run --test ./$<
+ SRCDIR=$(srcdir) LAYOUT=lvm-on-luks $(top_builddir)/run --test ./$<
# Make a (dummy) Debian image.
debian.img: make-debian-img.sh
diff --git a/test-data/phony-guests/guests.xml.in b/test-data/phony-guests/guests.xml.in
index 9f64c35c..339a6f7d 100644
--- a/test-data/phony-guests/guests.xml.in
+++ b/test-data/phony-guests/guests.xml.in
@@ -185,7 +185,7 @@
<!-- LUKS password is 'FEDORA' -->
<domain type='test'>
- <name>fedora-luks</name>
+ <name>fedora-lvm-on-luks</name>
<memory>1048576</memory>
<os>
<type>hvm</type>
@@ -194,7 +194,7 @@
<devices>
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
- <source file='@abs_builddir@/fedora-luks.img'/>
+ <source file='@abs_builddir@/fedora-lvm-on-luks.img'/>
<target dev='vda' bus='virtio'/>
</disk>
</devices>
diff --git a/test-data/phony-guests/make-fedora-img.pl b/test-data/phony-guests/make-fedora-img.pl
index 488a7d89..0d886bdf 100755
--- a/test-data/phony-guests/make-fedora-img.pl
+++ b/test-data/phony-guests/make-fedora-img.pl
@@ -171,8 +171,8 @@ EOF
}
}
-elsif ($ENV{LAYOUT} eq 'lvm-luks') {
- push (@images, "fedora-luks.img-t");
+elsif ($ENV{LAYOUT} eq 'lvm-on-luks') {
+ push (@images, "fedora-lvm-on-luks.img-t");
open (my $fstab, '>', "fedora.fstab") or die;
print $fstab <<EOF;
@@ -183,9 +183,9 @@ EOF
$bootdev = '/dev/sda1';
- $g->disk_create ("fedora-luks.img-t", "raw", $IMAGE_SIZE);
+ $g->disk_create ("fedora-lvm-on-luks.img-t", "raw", $IMAGE_SIZE);
- $g->add_drive ("fedora-luks.img-t", format => "raw");
+ $g->add_drive ("fedora-lvm-on-luks.img-t", format => "raw");
$g->launch ();
$g->part_init ('/dev/sda', 'mbr');
diff --git a/tests/Makefile.am b/tests/Makefile.am
index eb2931c5..46e53a58 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -97,7 +97,7 @@ TESTS = \
test-v2v-virtio-win-iso.sh \
test-v2v-fedora-conversion.sh \
test-v2v-fedora-btrfs-conversion.sh \
- test-v2v-fedora-luks-conversion.sh \
+ test-v2v-fedora-lvm-on-luks-conversion.sh \
test-v2v-fedora-md-conversion.sh \
test-v2v-windows-conversion.sh \
rhbz1232192.sh \
@@ -176,7 +176,7 @@ EXTRA_DIST += \
test-v2v-cdrom.sh \
test-v2v-fedora-conversion.sh \
test-v2v-fedora-btrfs-conversion.sh \
- test-v2v-fedora-luks-conversion.sh \
+ test-v2v-fedora-lvm-on-luks-conversion.sh \
test-v2v-fedora-md-conversion.sh \
test-v2v-floppy.expected \
test-v2v-floppy.sh \
diff --git a/tests/test-v2v-fedora-luks-conversion.sh b/tests/test-v2v-fedora-lvm-on-luks-conversion.sh
similarity index 95%
rename from tests/test-v2v-fedora-luks-conversion.sh
rename to tests/test-v2v-fedora-lvm-on-luks-conversion.sh
index 2922c31d..e3e70e8c 100755
--- a/tests/test-v2v-fedora-luks-conversion.sh
+++ b/tests/test-v2v-fedora-lvm-on-luks-conversion.sh
@@ -25,7 +25,7 @@ set -e
set -x
skip_if_skipped
-f=../test-data/phony-guests/fedora-luks.img
+f=../test-data/phony-guests/fedora-lvm-on-luks.img
requires test -f $f
# The disk is encrypted with password "FEDORA".
--
2.31.1

View File

@ -0,0 +1,220 @@
From 308f585fa1e98fc07aad7a4e9299af47416d604f Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Tue, 14 Jun 2022 13:27:09 +0200
Subject: [PATCH] tests: add LUKS-on-LVM test
Port guestfs-tools commit 27da4b0c4991 ("inspector: add LUKS-on-LVM test",
2022-02-28) to virt-v2v. While at it, account for virt-v2v commit
fd7cd0c0fd22 ("test-data/phony-guests: Increase size of root filesystem",
2022-06-08).
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20220614112709.12210-4-lersek@redhat.com>
Acked-by: Richard W.M. Jones <rjones@redhat.com>
(cherry picked from commit e4efe4b7d240b66b1d53fbe5a127f4f5966f6903)
---
.gitignore | 1 +
test-data/phony-guests/Makefile.am | 7 +++
test-data/phony-guests/guests.xml.in | 18 +++++++
test-data/phony-guests/make-fedora-img.pl | 54 +++++++++++++++++++
tests/Makefile.am | 2 +
.../test-v2v-fedora-luks-on-lvm-conversion.sh | 36 +++++++++++++
6 files changed, 118 insertions(+)
create mode 100755 tests/test-v2v-fedora-luks-on-lvm-conversion.sh
diff --git a/.gitignore b/.gitignore
index 0256b89d..46345e3b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -116,6 +116,7 @@ Makefile.in
/test-data/phony-guests/debian.img
/test-data/phony-guests/fedora.img
/test-data/phony-guests/fedora-btrfs.img
+/test-data/phony-guests/fedora-luks-on-lvm.img
/test-data/phony-guests/fedora-lvm-on-luks.img
/test-data/phony-guests/fedora-md1.img
/test-data/phony-guests/fedora-md2.img
diff --git a/test-data/phony-guests/Makefile.am b/test-data/phony-guests/Makefile.am
index 6d7db3da..29dbd4d0 100644
--- a/test-data/phony-guests/Makefile.am
+++ b/test-data/phony-guests/Makefile.am
@@ -49,6 +49,7 @@ disk_images = \
fedora-md1.img \
fedora-md2.img \
fedora-btrfs.img \
+ fedora-luks-on-lvm.img \
fedora-lvm-on-luks.img \
ubuntu.img \
archlinux.img \
@@ -99,6 +100,12 @@ fedora-btrfs.img: make-fedora-img.pl \
fedora-static-bin
SRCDIR=$(srcdir) LAYOUT=btrfs $(top_builddir)/run --test ./$<
+# Make a (dummy) Fedora image with LUKS-on-LVM.
+fedora-luks-on-lvm.img: make-fedora-img.pl \
+ fedora-journal.tar.xz \
+ fedora.db
+ SRCDIR=$(srcdir) LAYOUT=luks-on-lvm $(top_builddir)/run --test ./$<
+
# Make a (dummy) Fedora image with LVM-on-LUKS.
fedora-lvm-on-luks.img: make-fedora-img.pl \
fedora-journal.tar.xz \
diff --git a/test-data/phony-guests/guests.xml.in b/test-data/phony-guests/guests.xml.in
index 339a6f7d..4391c9b4 100644
--- a/test-data/phony-guests/guests.xml.in
+++ b/test-data/phony-guests/guests.xml.in
@@ -183,6 +183,24 @@
</devices>
</domain>
+ <!-- LUKS passwords are 'FEDORA-Root', 'FEDORA-LV1', 'FEDORA-LV2',
+ 'FEDORA-LV3' -->
+ <domain type='test'>
+ <name>fedora-luks-on-lvm</name>
+ <memory>1048576</memory>
+ <os>
+ <type>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <devices>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='raw'/>
+ <source file='@abs_builddir@/fedora-luks-on-lvm.img'/>
+ <target dev='vda' bus='virtio'/>
+ </disk>
+ </devices>
+ </domain>
+
<!-- LUKS password is 'FEDORA' -->
<domain type='test'>
<name>fedora-lvm-on-luks</name>
diff --git a/test-data/phony-guests/make-fedora-img.pl b/test-data/phony-guests/make-fedora-img.pl
index 0d886bdf..c30c0b53 100755
--- a/test-data/phony-guests/make-fedora-img.pl
+++ b/test-data/phony-guests/make-fedora-img.pl
@@ -200,6 +200,60 @@ EOF
init_lvm_root ('/dev/mapper/luks');
}
+elsif ($ENV{LAYOUT} eq 'luks-on-lvm') {
+ push (@images, "fedora-luks-on-lvm.img-t");
+
+ open (my $fstab, '>', "fedora.fstab") or die;
+ print $fstab <<EOF;
+LABEL=BOOT /boot ext2 default 0 0
+LABEL=ROOT / ext2 default 0 0
+EOF
+ close ($fstab) or die;
+
+ $bootdev = '/dev/sda1';
+
+ $g->disk_create ("fedora-luks-on-lvm.img-t", "raw", $IMAGE_SIZE);
+
+ $g->add_drive ("fedora-luks-on-lvm.img-t", format => "raw");
+ $g->launch ();
+
+ $g->part_init ('/dev/sda', 'mbr');
+ foreach my $p (@PARTITIONS) {
+ $g->part_add('/dev/sda', @$p);
+ }
+
+ # Create the Volume Group on /dev/sda2.
+ $g->pvcreate ('/dev/sda2');
+ $g->vgcreate ('VG', ['/dev/sda2']);
+ $g->lvcreate ('Root', 'VG', 256);
+ $g->lvcreate ('LV1', 'VG', 32);
+ $g->lvcreate ('LV2', 'VG', 32);
+ $g->lvcreate ('LV3', 'VG', 64);
+
+ # Format each Logical Group as a LUKS device, with a different password.
+ $g->luks_format ('/dev/VG/Root', 'FEDORA-Root', 0);
+ $g->luks_format ('/dev/VG/LV1', 'FEDORA-LV1', 0);
+ $g->luks_format ('/dev/VG/LV2', 'FEDORA-LV2', 0);
+ $g->luks_format ('/dev/VG/LV3', 'FEDORA-LV3', 0);
+
+ # Open the LUKS devices. This creates nodes like /dev/mapper/*-luks.
+ $g->cryptsetup_open ('/dev/VG/Root', 'FEDORA-Root', 'Root-luks');
+ $g->cryptsetup_open ('/dev/VG/LV1', 'FEDORA-LV1', 'LV1-luks');
+ $g->cryptsetup_open ('/dev/VG/LV2', 'FEDORA-LV2', 'LV2-luks');
+ $g->cryptsetup_open ('/dev/VG/LV3', 'FEDORA-LV3', 'LV3-luks');
+
+ # Phony root filesystem.
+ $g->mkfs ('ext2', '/dev/mapper/Root-luks', blocksize => 4096, label => 'ROOT');
+ $g->set_uuid ('/dev/mapper/Root-luks', '01234567-0123-0123-0123-012345678902');
+
+ # Other filesystems, just for testing findfs-label.
+ $g->mkfs ('ext2', '/dev/mapper/LV1-luks', blocksize => 4096, label => 'LV1');
+ $g->mkfs ('ext2', '/dev/mapper/LV2-luks', blocksize => 1024, label => 'LV2');
+ $g->mkfs ('ext2', '/dev/mapper/LV3-luks', blocksize => 2048, label => 'LV3');
+
+ $g->mount ('/dev/mapper/Root-luks', '/');
+}
+
else {
print STDERR "$0: Unknown LAYOUT: ",$ENV{LAYOUT},"\n";
exit 1;
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 46e53a58..e787a86c 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -97,6 +97,7 @@ TESTS = \
test-v2v-virtio-win-iso.sh \
test-v2v-fedora-conversion.sh \
test-v2v-fedora-btrfs-conversion.sh \
+ test-v2v-fedora-luks-on-lvm-conversion.sh \
test-v2v-fedora-lvm-on-luks-conversion.sh \
test-v2v-fedora-md-conversion.sh \
test-v2v-windows-conversion.sh \
@@ -176,6 +177,7 @@ EXTRA_DIST += \
test-v2v-cdrom.sh \
test-v2v-fedora-conversion.sh \
test-v2v-fedora-btrfs-conversion.sh \
+ test-v2v-fedora-luks-on-lvm-conversion.sh \
test-v2v-fedora-lvm-on-luks-conversion.sh \
test-v2v-fedora-md-conversion.sh \
test-v2v-floppy.expected \
diff --git a/tests/test-v2v-fedora-luks-on-lvm-conversion.sh b/tests/test-v2v-fedora-luks-on-lvm-conversion.sh
new file mode 100755
index 00000000..1a4068cf
--- /dev/null
+++ b/tests/test-v2v-fedora-luks-on-lvm-conversion.sh
@@ -0,0 +1,36 @@
+#!/bin/bash -
+# libguestfs virt-v2v test script
+# Copyright (C) 2014-2022 Red Hat Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+# Test virt-v2v (Phony) Fedora conversion.
+
+set -e
+
+source ./functions.sh
+set -e
+set -x
+
+skip_if_skipped
+f=../test-data/phony-guests/fedora-luks-on-lvm.img
+requires test -f $f
+
+keys=(--key /dev/VG/Root:key:FEDORA-Root
+ --key /dev/VG/LV1:key:FEDORA-LV1
+ --key /dev/VG/LV2:key:FEDORA-LV2
+ --key /dev/VG/LV3:key:FEDORA-LV3)
+
+$VG virt-v2v --debug-gc -i disk $f -o null "${keys[@]}"
--
2.31.1

View File

@ -0,0 +1,125 @@
From 1477040f818e86723b1f1f0c424e70380c33b892 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Fri, 17 Jun 2022 11:53:37 +0200
Subject: [PATCH] RHV outputs: limit copied disk count to 23
We currently support virtio-blk (commonly) or IDE (unusually) for exposing
disks to the converted guest; refer to "guestcaps.gcaps_block_bus" in
"lib/create_ovf.ml". When using virtio-blk (i.e., in the common case), RHV
can deal with at most 23 disks, as it plugs each virtio-blk device in a
separate slot on the PCI(e) root bus; and the other slots are reserved for
various purposes. When a domain has too many disks, the problem only
becomes apparent once the copying finishes and an import is attempted.
Modify the RHV outputs to fail relatively early when a domain has more
than 23 disks that need to be copied.
Notes:
- With IDE, the theoretical limit may even be as low as 4. However, in the
"Output_module.setup" function, we don't have access to
"guestcaps.gcaps_block_bus", and in practice the IDE limitation has not
caused surprises. So for now stick with 23, assuming virtio-blk.
Modifying the "Output_module.setup" parameter list just for this seems
overkill.
- We could move the new check to an even earlier step, namely
"Output_module.parse_options", due to the v2v directory deliberately
existing (and having been populated with input sockets) at that time.
However, even discounting the fact that "parse_options" is not a good
name for including this kind of step, "parse_options" does not have
access to the v2v directory name, and modifying the signature just for
this is (again) overkill.
- By adding the check to "Output_module.setup", we waste *some* effort
(namely, the conversion occurs between "parse_options" and "setup"),
but: (a) the "rhv-disk-uuid" count check (against the disk count) is
already being done in the rhv-upload module's "setup" function, (b) in
practice the slowest step ought to be the copying, and placing the new
check in "setup" is early enough to prevent that.
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2051564
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20220617095337.9122-1-lersek@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
(cherry picked from commit e186cc2bea99a077990f192953e1bf6c9ba70e79)
---
output/output.ml | 5 +++++
output/output.mli | 7 +++++++
output/output_rhv.ml | 1 +
output/output_rhv_upload.ml | 1 +
output/output_vdsm.ml | 1 +
5 files changed, 15 insertions(+)
diff --git a/output/output.ml b/output/output.ml
index 10e685c4..5c6670b9 100644
--- a/output/output.ml
+++ b/output/output.ml
@@ -64,6 +64,11 @@ let get_disks dir =
in
loop [] 0
+let error_if_disk_count_gt dir n =
+ let socket = sprintf "%s/in%d" dir n in
+ if Sys.file_exists socket then
+ error (f_"this output module doesn't support copying more than %d disks") n
+
let output_to_local_file ?(changeuid = fun f -> f ())
output_alloc output_format filename size socket =
(* Check nbdkit is installed and has the required plugin. *)
diff --git a/output/output.mli b/output/output.mli
index 533a0c51..8d3d6865 100644
--- a/output/output.mli
+++ b/output/output.mli
@@ -76,6 +76,13 @@ val get_disks : string -> (int * int64) list
(** Examines the v2v directory and opens each input socket (in0 etc),
returning a list of input disk index and size. *)
+val error_if_disk_count_gt : string -> int -> unit
+(** This function lets an output module enforce a maximum disk count.
+ [error_if_disk_count_gt dir n] checks whether the domain has more than [n]
+ disks that need to be copied, by examining the existence of input NBD socket
+ "in[n]" in the v2v directory [dir]. If the socket exists, [error] is
+ called. *)
+
val output_to_local_file : ?changeuid:((unit -> unit) -> unit) ->
Types.output_allocation ->
string -> string -> int64 -> string ->
diff --git a/output/output_rhv.ml b/output/output_rhv.ml
index 119207fd..8571e07b 100644
--- a/output/output_rhv.ml
+++ b/output/output_rhv.ml
@@ -56,6 +56,7 @@ module RHV = struct
(options.output_alloc, options.output_format, output_name, output_storage)
let rec setup dir options source =
+ error_if_disk_count_gt dir 23;
let disks = get_disks dir in
let output_alloc, output_format, output_name, output_storage = options in
diff --git a/output/output_rhv_upload.ml b/output/output_rhv_upload.ml
index 828996b3..f2ced4f4 100644
--- a/output/output_rhv_upload.ml
+++ b/output/output_rhv_upload.ml
@@ -133,6 +133,7 @@ after their uploads (if you do, you must supply one for each disk):
else PCRE.matches (Lazy.force rex_uuid) uuid
let rec setup dir options source =
+ error_if_disk_count_gt dir 23;
let disks = get_disks dir in
let output_conn, output_format,
output_password, output_name, output_storage,
diff --git a/output/output_vdsm.ml b/output/output_vdsm.ml
index a1e8c246..23d1b9cd 100644
--- a/output/output_vdsm.ml
+++ b/output/output_vdsm.ml
@@ -119,6 +119,7 @@ For each disk you must supply one of each of these options:
compat, ovf_flavour)
let setup dir options source =
+ error_if_disk_count_gt dir 23;
let disks = get_disks dir in
let output_alloc, output_format,
output_name, output_storage,
--
2.31.1

View File

@ -0,0 +1,53 @@
From 5fa419748ef35851efadd1a249d55f42c5d0112b Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Wed, 29 Jun 2022 15:44:27 +0200
Subject: [PATCH] update common submodule for CVE-2022-2211 fix
$ git shortlog 9e990f3e4530..35467027f657
Laszlo Ersek (1):
options: fix buffer overflow in get_keys() [CVE-2022-2211]
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
(cherry picked from commit 795d5dfcef77fc54fec4d237bda28571454a6d4e)
---
common | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Submodule common 9e990f3e..35467027:
diff --git a/common/options/keys.c b/common/options/keys.c
index 798315c2..d27a7123 100644
--- a/common/options/keys.c
+++ b/common/options/keys.c
@@ -128,17 +128,23 @@ read_first_line_from_file (const char *filename)
char **
get_keys (struct key_store *ks, const char *device, const char *uuid)
{
- size_t i, j, len;
+ size_t i, j, nmemb;
char **r;
char *s;
/* We know the returned list must have at least one element and not
* more than ks->nr_keys.
*/
- len = 1;
- if (ks)
- len = MIN (1, ks->nr_keys);
- r = calloc (len+1, sizeof (char *));
+ nmemb = 1;
+ if (ks && ks->nr_keys > nmemb)
+ nmemb = ks->nr_keys;
+
+ /* make room for the terminating NULL */
+ if (nmemb == (size_t)-1)
+ error (EXIT_FAILURE, 0, _("size_t overflow"));
+ nmemb++;
+
+ r = calloc (nmemb, sizeof (char *));
if (r == NULL)
error (EXIT_FAILURE, errno, "calloc");
--
2.31.1

View File

@ -0,0 +1,586 @@
From 94b57f647d67d4713284af1f0580d1afedd6ebaa Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Fri, 1 Jul 2022 15:30:42 +0200
Subject: [PATCH] convert: document networking dependency of "--key ID:clevis"
Virt-v2v enables appliance networking already, for the sake of
"unconfigure_vmware". We now have a second use case for networking: "--key
ID:clevis". Update the comment in the code.
(Short log for libguestfs-common commit range 35467027f657..af6cb55bc58a:
Laszlo Ersek (12):
options: fix UUID comparison logic bug in get_keys()
mltools/tools_utils: remove unused function "key_store_to_cli"
mltools/tools_utils: allow multiple "--key" options for OCaml tools too
options: replace NULL-termination with number-of-elements in get_keys()
options: wrap each passphrase from get_keys() into a struct
options: add back-end for LUKS decryption with Clevis+Tang
options: introduce selector type "key_clevis"
options: generalize "--key" selector parsing for C-language utilities
mltools/tools_utils-c: handle internal type error with abort()
mltools/tools_utils: generalize "--key" selector parsing for OCaml utils
options, mltools/tools_utils: parse "--key ID:clevis" options
options, mltools/tools_utils: add helper for network dependency
).
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1809453
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20220628115856.5820-1-lersek@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
(cherry picked from commit 98fa5ab2685371c681282ce5de704877af27be74)
---
common | 2 +-
convert/convert.ml | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
Submodule common 35467027..af6cb55b:
diff --git a/common/mltools/tools_utils-c.c b/common/mltools/tools_utils-c.c
index 08146677..4ff42e5d 100644
--- a/common/mltools/tools_utils-c.c
+++ b/common/mltools/tools_utils-c.c
@@ -62,24 +62,31 @@ guestfs_int_mllib_inspect_decrypt (value gv, value gpv, value keysv)
caml_raise_out_of_memory ();
v = Field (elemv, 1);
- switch (Tag_val (v)) {
- case 0: /* KeyString of string */
- key.type = key_string;
- key.string.s = strdup (String_val (Field (v, 0)));
- if (!key.string.s)
- caml_raise_out_of_memory ();
- break;
- case 1: /* KeyFileName of string */
- key.type = key_file;
- key.file.name = strdup (String_val (Field (v, 0)));
- if (!key.file.name)
- caml_raise_out_of_memory ();
- break;
- default:
- error (EXIT_FAILURE, 0,
- "internal error: unhandled Tag_val (v) = %d",
- Tag_val (v));
- }
+ if (Is_block (v))
+ switch (Tag_val (v)) {
+ case 0: /* KeyString of string */
+ key.type = key_string;
+ key.string.s = strdup (String_val (Field (v, 0)));
+ if (!key.string.s)
+ caml_raise_out_of_memory ();
+ break;
+ case 1: /* KeyFileName of string */
+ key.type = key_file;
+ key.file.name = strdup (String_val (Field (v, 0)));
+ if (!key.file.name)
+ caml_raise_out_of_memory ();
+ break;
+ default:
+ abort ();
+ }
+ else
+ switch (Int_val (v)) {
+ case 0: /* KeyClevis */
+ key.type = key_clevis;
+ break;
+ default:
+ abort ();
+ }
ks = key_store_import_key (ks, &key);
diff --git a/common/mltools/tools_utils.ml b/common/mltools/tools_utils.ml
index 695fda7e..562bfadc 100644
--- a/common/mltools/tools_utils.ml
+++ b/common/mltools/tools_utils.ml
@@ -29,11 +29,12 @@ open Getopt.OptionName
let prog = ref prog
type key_store = {
- keys : (string, key_store_key) Hashtbl.t;
+ keys : (string * key_store_key) list ref;
}
and key_store_key =
| KeyString of string
| KeyFileName of string
+ | KeyClevis
external c_inspect_decrypt : Guestfs.t -> int64 -> (string * key_store_key) list -> unit = "guestfs_int_mllib_inspect_decrypt"
external c_set_echo_keys : unit -> unit = "guestfs_int_mllib_set_echo_keys" [@@noalloc]
@@ -376,7 +377,7 @@ let create_standard_options argspec ?anon_fun ?(key_opts = false)
)
in
let ks = {
- keys = Hashtbl.create 13;
+ keys = ref [];
} in
let argspec = ref argspec in
let add_argspec = List.push_back argspec in
@@ -392,14 +393,28 @@ let create_standard_options argspec ?anon_fun ?(key_opts = false)
if key_opts then (
let parse_key_selector arg =
- let parts = String.nsplit ~max:3 ":" arg in
+ let parts = String.nsplit ":" arg in
match parts with
+ | [] ->
+ error (f_"selector '%s': missing ID") arg
+ | [ _ ] ->
+ error (f_"selector '%s': missing TYPE") arg
+ | [ _; "key" ]
+ | _ :: "key" :: _ :: _ :: _ ->
+ error (f_"selector '%s': missing KEY_STRING, or too many fields") arg
| [ device; "key"; key ] ->
- Hashtbl.replace ks.keys device (KeyString key)
+ List.push_back ks.keys (device, KeyString key)
+ | [ _; "file" ]
+ | _ :: "file" :: _ :: _ :: _ ->
+ error (f_"selector '%s': missing FILENAME, or too many fields") arg
| [ device; "file"; file ] ->
- Hashtbl.replace ks.keys device (KeyFileName file)
+ List.push_back ks.keys (device, KeyFileName file)
+ | _ :: "clevis" :: _ :: _ ->
+ error (f_"selector '%s': too many fields") arg
+ | [ device; "clevis" ] ->
+ List.push_back ks.keys (device, KeyClevis)
| _ ->
- error (f_"invalid selector string for --key: %s") arg
+ error (f_"selector '%s': invalid TYPE") arg
in
add_argspec ([ L"echo-keys" ], Getopt.Unit c_set_echo_keys, s_"Dont turn off echo for passphrases");
@@ -420,16 +435,6 @@ let create_standard_options argspec ?anon_fun ?(key_opts = false)
let getopt = Getopt.create argspec ?anon_fun usage_msg in
{ getopt; ks; debug_gc }
-let key_store_to_cli { keys } =
- Hashtbl.fold (
- fun k v acc ->
- let arg =
- match v with
- | KeyString s -> sprintf "%s:key:%s" k s
- | KeyFileName f -> sprintf "%s:file:%s" k f in
- "--key" :: arg :: acc
- ) keys []
-
(* Run an external command, slurp up the output as a list of lines. *)
let external_command ?(echo_cmd = true) cmd =
if echo_cmd then
@@ -691,21 +696,19 @@ let is_btrfs_subvolume g fs =
if g#last_errno () = Guestfs.Errno.errno_EINVAL then false
else raise exn
+let key_store_requires_network ks =
+ List.exists (function
+ | _, KeyClevis -> true
+ | _ -> false) !(ks.keys)
+
let inspect_decrypt g ks =
- (* Turn the keys in the key_store into a simpler struct, so it is possible
- * to read it using the C API.
- *)
- let keys_as_list = Hashtbl.fold (
- fun k v acc ->
- (k, v) :: acc
- ) ks.keys [] in
(* Note we pass original 'g' even though it is not used by the
* callee. This is so that 'g' is kept as a root on the stack, and
* so cannot be garbage collected while we are in the c_inspect_decrypt
* function.
*)
c_inspect_decrypt g#ocaml_handle (Guestfs.c_pointer g#ocaml_handle)
- keys_as_list
+ !(ks.keys)
let with_timeout op timeout ?(sleep = 2) fn =
let start_t = Unix.gettimeofday () in
diff --git a/common/mltools/tools_utils.mli b/common/mltools/tools_utils.mli
index 50183006..ec900e63 100644
--- a/common/mltools/tools_utils.mli
+++ b/common/mltools/tools_utils.mli
@@ -103,14 +103,6 @@ val create_standard_options : Getopt.speclist -> ?anon_fun:Getopt.anon_fun -> ?k
Returns a new {!cmdline_options} structure. *)
-val key_store_to_cli : key_store -> string list
-(** Convert a {!key_store} object back to a list of command line
- options, essentially undoing the effect of Getopt parsing.
- This is used in virt-v2v to pass the keystore to helpers.
- It is not particularly secure, especially if you use the
- [:key:] selector, although not any less secure than passing
- them via the command line in the first place. *)
-
val external_command : ?echo_cmd:bool -> string -> string list
(** Run an external command, slurp up the output as a list of lines.
@@ -204,6 +196,10 @@ val inspect_mount_root_ro : Guestfs.guestfs -> string -> unit
val is_btrfs_subvolume : Guestfs.guestfs -> string -> bool
(** Checks if a filesystem is a btrfs subvolume. *)
+val key_store_requires_network : key_store -> bool
+(** [key_store_requires_network ks] returns [true] iff [ks] contains at least
+ one "ID:clevis" selector. *)
+
val inspect_decrypt : Guestfs.guestfs -> key_store -> unit
(** Simple implementation of decryption: look for any encrypted
partitions and decrypt them, then rescan for VGs. *)
diff --git a/common/options/decrypt.c b/common/options/decrypt.c
index 1cd7b627..97c8b88d 100644
--- a/common/options/decrypt.c
+++ b/common/options/decrypt.c
@@ -124,10 +124,10 @@ decrypt_mountables (guestfs_h *g, const char * const *mountables,
while ((mountable = *mnt_scan++) != NULL) {
CLEANUP_FREE char *type = NULL;
CLEANUP_FREE char *uuid = NULL;
- CLEANUP_FREE_STRING_LIST char **keys = NULL;
+ struct matching_key *keys;
+ size_t nr_matches;
CLEANUP_FREE char *mapname = NULL;
- const char * const *key_scan;
- const char *key;
+ size_t scan;
type = guestfs_vfs_type (g, mountable);
if (type == NULL)
@@ -144,33 +144,45 @@ decrypt_mountables (guestfs_h *g, const char * const *mountables,
/* Grab the keys that we should try with this device, based on device name,
* or UUID (if any).
*/
- keys = get_keys (ks, mountable, uuid);
- assert (keys[0] != NULL);
+ keys = get_keys (ks, mountable, uuid, &nr_matches);
+ assert (nr_matches > 0);
/* Generate a node name for the plaintext (decrypted) device node. */
if (uuid == NULL || asprintf (&mapname, "luks-%s", uuid) == -1)
mapname = make_mapname (mountable);
/* Try each key in turn. */
- key_scan = (const char * const *)keys;
- while ((key = *key_scan++) != NULL) {
+ for (scan = 0; scan < nr_matches; ++scan) {
+ struct matching_key *key = keys + scan;
int r;
guestfs_push_error_handler (g, NULL, NULL);
- r = guestfs_cryptsetup_open (g, mountable, key, mapname, -1);
+ assert (key->clevis == (key->passphrase == NULL));
+ if (key->clevis)
+#ifdef GUESTFS_HAVE_CLEVIS_LUKS_UNLOCK
+ r = guestfs_clevis_luks_unlock (g, mountable, mapname);
+#else
+ error (EXIT_FAILURE, 0,
+ _("'clevis_luks_unlock', needed for decrypting %s, is "
+ "unavailable in this libguestfs version"), mountable);
+#endif
+ else
+ r = guestfs_cryptsetup_open (g, mountable, key->passphrase, mapname,
+ -1);
guestfs_pop_error_handler (g);
if (r == 0)
break;
}
- if (key == NULL)
+ if (scan == nr_matches)
error (EXIT_FAILURE, 0,
_("could not find key to open LUKS encrypted %s.\n\n"
"Try using --key on the command line.\n\n"
"Original error: %s (%d)"),
mountable, guestfs_last_error (g), guestfs_last_errno (g));
+ free_keys (keys, nr_matches);
decrypted_some = true;
}
diff --git a/common/options/key-option.pod b/common/options/key-option.pod
index 90a3b15c..6bc04df1 100644
--- a/common/options/key-option.pod
+++ b/common/options/key-option.pod
@@ -14,4 +14,13 @@ Use the specified C<KEY_STRING> as passphrase.
Read the passphrase from F<FILENAME>.
+=item B<--key> C<ID>:clevis
+
+Attempt passphrase-less unlocking for C<ID> with Clevis, over the
+network. Please refer to L<guestfs(3)/ENCRYPTED DISKS> for more
+information on network-bound disk encryption (NBDE).
+
+Note that if any such option is present on the command line, QEMU user
+networking will be automatically enabled for the libguestfs appliance.
+
=back
diff --git a/common/options/keys.c b/common/options/keys.c
index d27a7123..d987ae56 100644
--- a/common/options/keys.c
+++ b/common/options/keys.c
@@ -125,11 +125,12 @@ read_first_line_from_file (const char *filename)
* keystore. There may be multiple. If none are read from the
* keystore, ask the user.
*/
-char **
-get_keys (struct key_store *ks, const char *device, const char *uuid)
+struct matching_key *
+get_keys (struct key_store *ks, const char *device, const char *uuid,
+ size_t *nr_matches)
{
- size_t i, j, nmemb;
- char **r;
+ size_t i, nmemb;
+ struct matching_key *r, *match;
char *s;
/* We know the returned list must have at least one element and not
@@ -139,22 +140,20 @@ get_keys (struct key_store *ks, const char *device, const char *uuid)
if (ks && ks->nr_keys > nmemb)
nmemb = ks->nr_keys;
- /* make room for the terminating NULL */
- if (nmemb == (size_t)-1)
+ if (nmemb > (size_t)-1 / sizeof *r)
error (EXIT_FAILURE, 0, _("size_t overflow"));
- nmemb++;
- r = calloc (nmemb, sizeof (char *));
+ r = malloc (nmemb * sizeof *r);
if (r == NULL)
- error (EXIT_FAILURE, errno, "calloc");
+ error (EXIT_FAILURE, errno, "malloc");
- j = 0;
+ match = r;
if (ks) {
for (i = 0; i < ks->nr_keys; ++i) {
struct key_store_key *key = &ks->keys[i];
- if (STRNEQ (key->id, device) && (uuid && STRNEQ (key->id, uuid)))
+ if (STRNEQ (key->id, device) && (!uuid || STRNEQ (key->id, uuid)))
continue;
switch (key->type) {
@@ -162,68 +161,101 @@ get_keys (struct key_store *ks, const char *device, const char *uuid)
s = strdup (key->string.s);
if (!s)
error (EXIT_FAILURE, errno, "strdup");
- r[j++] = s;
+ match->clevis = false;
+ match->passphrase = s;
+ ++match;
break;
case key_file:
s = read_first_line_from_file (key->file.name);
- r[j++] = s;
+ match->clevis = false;
+ match->passphrase = s;
+ ++match;
+ break;
+ case key_clevis:
+ match->clevis = true;
+ match->passphrase = NULL;
+ ++match;
break;
}
}
}
- if (j == 0) {
+ if (match == r) {
/* Key not found in the key store, ask the user for it. */
s = read_key (device);
if (!s)
error (EXIT_FAILURE, 0, _("could not read key from user"));
- r[0] = s;
+ match->clevis = false;
+ match->passphrase = s;
+ ++match;
}
+ *nr_matches = (size_t)(match - r);
return r;
}
+void
+free_keys (struct matching_key *keys, size_t nr_matches)
+{
+ size_t i;
+
+ for (i = 0; i < nr_matches; ++i) {
+ struct matching_key *key = keys + i;
+
+ assert (key->clevis == (key->passphrase == NULL));
+ if (!key->clevis)
+ free (key->passphrase);
+ }
+ free (keys);
+}
+
struct key_store *
key_store_add_from_selector (struct key_store *ks, const char *selector)
{
- CLEANUP_FREE_STRING_LIST char **fields =
- guestfs_int_split_string (':', selector);
+ CLEANUP_FREE_STRING_LIST char **fields = NULL;
+ size_t field_count;
struct key_store_key key;
+ fields = guestfs_int_split_string (':', selector);
if (!fields)
error (EXIT_FAILURE, errno, "guestfs_int_split_string");
+ field_count = guestfs_int_count_strings (fields);
- if (guestfs_int_count_strings (fields) != 3) {
- invalid_selector:
- error (EXIT_FAILURE, 0, "invalid selector for --key: %s", selector);
- }
-
- /* 1: device */
+ /* field#0: ID */
+ if (field_count < 1)
+ error (EXIT_FAILURE, 0, _("selector '%s': missing ID"), selector);
key.id = strdup (fields[0]);
if (!key.id)
error (EXIT_FAILURE, errno, "strdup");
- /* 2: key type */
- if (STREQ (fields[1], "key"))
+ /* field#1...: TYPE, and TYPE-specific properties */
+ if (field_count < 2)
+ error (EXIT_FAILURE, 0, _("selector '%s': missing TYPE"), selector);
+
+ if (STREQ (fields[1], "key")) {
key.type = key_string;
- else if (STREQ (fields[1], "file"))
- key.type = key_file;
- else
- goto invalid_selector;
-
- /* 3: actual key */
- switch (key.type) {
- case key_string:
+ if (field_count != 3)
+ error (EXIT_FAILURE, 0,
+ _("selector '%s': missing KEY_STRING, or too many fields"),
+ selector);
key.string.s = strdup (fields[2]);
if (!key.string.s)
error (EXIT_FAILURE, errno, "strdup");
- break;
- case key_file:
+ } else if (STREQ (fields[1], "file")) {
+ key.type = key_file;
+ if (field_count != 3)
+ error (EXIT_FAILURE, 0,
+ _("selector '%s': missing FILENAME, or too many fields"),
+ selector);
key.file.name = strdup (fields[2]);
if (!key.file.name)
error (EXIT_FAILURE, errno, "strdup");
- break;
- }
+ } else if (STREQ (fields[1], "clevis")) {
+ key.type = key_clevis;
+ if (field_count != 2)
+ error (EXIT_FAILURE, 0, _("selector '%s': too many fields"), selector);
+ } else
+ error (EXIT_FAILURE, 0, _("selector '%s': invalid TYPE"), selector);
return key_store_import_key (ks, &key);
}
@@ -252,6 +284,21 @@ key_store_import_key (struct key_store *ks, const struct key_store_key *key)
return ks;
}
+bool
+key_store_requires_network (const struct key_store *ks)
+{
+ size_t i;
+
+ if (ks == NULL)
+ return false;
+
+ for (i = 0; i < ks->nr_keys; ++i)
+ if (ks->keys[i].type == key_clevis)
+ return true;
+
+ return false;
+}
+
void
free_key_store (struct key_store *ks)
{
@@ -270,6 +317,9 @@ free_key_store (struct key_store *ks)
case key_file:
free (key->file.name);
break;
+ case key_clevis:
+ /* nothing */
+ break;
}
free (key->id);
}
diff --git a/common/options/options.h b/common/options/options.h
index 80df91a8..60d5d806 100644
--- a/common/options/options.h
+++ b/common/options/options.h
@@ -115,6 +115,7 @@ struct key_store_key {
enum {
key_string, /* key specified as string */
key_file, /* key stored in a file */
+ key_clevis, /* key reconstructed with Clevis+Tang */
} type;
union {
struct {
@@ -134,6 +135,19 @@ struct key_store {
size_t nr_keys;
};
+/* A key matching a particular ID (pathname of the libguestfs device node that
+ * stands for the encrypted block device, or LUKS UUID).
+ */
+struct matching_key {
+ /* True iff the passphrase should be reconstructed using Clevis, talking to
+ * Tang servers over the network.
+ */
+ bool clevis;
+
+ /* Explicit passphrase, otherwise. */
+ char *passphrase;
+};
+
/* in config.c */
extern void parse_config (void);
@@ -151,9 +165,12 @@ extern void print_inspect_prompt (void);
/* in key.c */
extern char *read_key (const char *param);
-extern char **get_keys (struct key_store *ks, const char *device, const char *uuid);
+extern struct matching_key *get_keys (struct key_store *ks, const char *device,
+ const char *uuid, size_t *nr_matches);
+extern void free_keys (struct matching_key *keys, size_t nr_matches);
extern struct key_store *key_store_add_from_selector (struct key_store *ks, const char *selector);
extern struct key_store *key_store_import_key (struct key_store *ks, const struct key_store_key *key);
+extern bool key_store_requires_network (const struct key_store *ks);
extern void free_key_store (struct key_store *ks);
/* in options.c */
diff --git a/convert/convert.ml b/convert/convert.ml
index 5e0e6c2b..b678dc92 100644
--- a/convert/convert.ml
+++ b/convert/convert.ml
@@ -57,7 +57,8 @@ let rec convert dir options source =
* sure this is not too large because each vCPU consumes guest RAM.
*)
g#set_smp (min 8 (Sysconf.nr_processors_online ()));
- (* The network is only used by the unconfigure_vmware () function. *)
+ (* The network is used by the unconfigure_vmware () function, and the "--key
+ * ID:clevis" command line options (if any). *)
g#set_network true;
List.iter (
fun { s_disk_id = i } ->
--
2.31.1

View File

@ -0,0 +1,145 @@
From a2d58a7f879c2fd3ac6ff1ddd92db0e455b906f3 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Fri, 28 Jan 2022 09:30:29 +0000
Subject: [PATCH] qemu-nbd: Implement output compression for qcow2 files
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
(cherry picked from commit 71c4301909cb307def02ebcd0e89beee4138e7f2)
---
lib/qemuNBD.ml | 11 +++++++++--
lib/qemuNBD.mli | 5 +++++
output/output.ml | 39 ++++++++++++++++++++++++++++++++++++---
output/output.mli | 1 +
4 files changed, 51 insertions(+), 5 deletions(-)
diff --git a/lib/qemuNBD.ml b/lib/qemuNBD.ml
index ae21b17c..bbb65f41 100644
--- a/lib/qemuNBD.ml
+++ b/lib/qemuNBD.ml
@@ -55,14 +55,16 @@ type cmd = {
disk : string;
mutable snapshot : bool;
mutable format : string option;
+ mutable imgopts : bool;
}
-let create disk = { disk; snapshot = false; format = None }
+let create disk = { disk; snapshot = false; format = None; imgopts = false }
let set_snapshot cmd snap = cmd.snapshot <- snap
let set_format cmd format = cmd.format <- format
+let set_image_opts cmd imgopts = cmd.imgopts <- imgopts
-let run_unix socket { disk; snapshot; format } =
+let run_unix socket { disk; snapshot; format; imgopts } =
assert (disk <> "");
(* Create a temporary directory where we place the PID file. *)
@@ -85,6 +87,11 @@ let run_unix socket { disk; snapshot; format } =
(* -s adds a protective overlay. *)
if snapshot then List.push_back args "-s";
+ (* --image-opts reinterprets the filename parameter as a set of
+ * image options.
+ *)
+ if imgopts then List.push_back args "--image-opts";
+
if have_selinux && qemu_nbd_has_selinux_label_option () then (
List.push_back args "--selinux-label";
List.push_back args "system_u:object_r:svirt_socket_t:s0"
diff --git a/lib/qemuNBD.mli b/lib/qemuNBD.mli
index e10d3106..afe9d944 100644
--- a/lib/qemuNBD.mli
+++ b/lib/qemuNBD.mli
@@ -43,6 +43,11 @@ val set_snapshot : cmd -> bool -> unit
val set_format : cmd -> string option -> unit
(** Set the format [--format] parameter. *)
+val set_image_opts : cmd -> bool -> unit
+(** Set whether the [--image-opts] parameter is used. This changes
+ the meaning of the [filename] parameter to a set of image options.
+ Consult the qemu-nbd man page for more details. *)
+
val run_unix : string -> cmd -> string * int
(** Start qemu-nbd command listening on a Unix domain socket,
waiting for the process to start up.
diff --git a/output/output.ml b/output/output.ml
index 5c6670b9..23c3932d 100644
--- a/output/output.ml
+++ b/output/output.ml
@@ -69,7 +69,7 @@ let error_if_disk_count_gt dir n =
if Sys.file_exists socket then
error (f_"this output module doesn't support copying more than %d disks") n
-let output_to_local_file ?(changeuid = fun f -> f ())
+let output_to_local_file ?(changeuid = fun f -> f ()) ?(compressed = false)
output_alloc output_format filename size socket =
(* Check nbdkit is installed and has the required plugin. *)
if not (Nbdkit.is_installed ()) then
@@ -78,6 +78,24 @@ let output_to_local_file ?(changeuid = fun f -> f ())
error (f_"nbdkit-file-plugin is not installed or not working");
let nbdkit_config = Nbdkit.config () in
+ if compressed then (
+ (* Only allow compressed with -of qcow2. *)
+ if output_format <> "qcow2" then
+ error (f_"-oo compressed is only allowed when the output format \
+ is a local qcow2-format file, i.e. -of qcow2");
+
+ (* Check nbdcopy is new enough. This assumes that the version of
+ * libnbd is the same as the version of nbdcopy, but parsing this
+ * is easier. We can remove this check when we build-depend on
+ * libnbd >= 1.14.
+ *)
+ let version =
+ NBD.create () |> NBD.get_version |>
+ String.nsplit "." |> List.map int_of_string in
+ if version < [1; 13; 5] then
+ error (f_"-oo compressed option requires nbdcopy >= 1.13.5")
+ );
+
let g = open_guestfs () in
let preallocation =
match output_alloc with
@@ -103,9 +121,24 @@ let output_to_local_file ?(changeuid = fun f -> f ())
On_exit.kill pid
| "qcow2" ->
- let cmd = QemuNBD.create filename in
+ let cmd =
+ if compressed then (
+ let qemu_quote str = String.replace str "," ",," in
+ let image_opts = [ "driver=compress";
+ "file.driver=qcow2";
+ "file.file.driver=file";
+ "file.file.filename=" ^ qemu_quote filename ] in
+ let image_opts = String.concat "," image_opts in
+ let cmd = QemuNBD.create image_opts in
+ QemuNBD.set_image_opts cmd true;
+ cmd
+ )
+ else (* not compressed *) (
+ let cmd = QemuNBD.create filename in
+ QemuNBD.set_format cmd (Some "qcow2");
+ cmd
+ ) in
QemuNBD.set_snapshot cmd false;
- QemuNBD.set_format cmd (Some "qcow2");
let _, pid = QemuNBD.run_unix socket cmd in
On_exit.kill pid
diff --git a/output/output.mli b/output/output.mli
index 8d3d6865..c1f0f53d 100644
--- a/output/output.mli
+++ b/output/output.mli
@@ -84,6 +84,7 @@ val error_if_disk_count_gt : string -> int -> unit
called. *)
val output_to_local_file : ?changeuid:((unit -> unit) -> unit) ->
+ ?compressed:bool ->
Types.output_allocation ->
string -> string -> int64 -> string ->
unit
--
2.31.1

View File

@ -0,0 +1,275 @@
From b4b48b88c3fadbceedaf8ba03e788bff27b0ad4d Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Fri, 28 Jan 2022 09:30:58 +0000
Subject: [PATCH] -o disk, -o libvirt, -o qemu: Implement -of qcow2 -oo
compressed
For various output modes, implement -oo compressed which can be used
to generate compressed qcow2 files. This option was dropped when
modularizing virt-v2v, and required changes to nbdcopy which are
finally upstream in libnbd >= 1.13.5.
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2047660
Fixes: commit 255722cbf39afc0b012e2ac00d16fa6ba2f8c21f
Reported-by: Xiaodai Wang
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
(cherry picked from commit 53690a0c602a4286fdb9408fdf6a01cc352697ec)
---
TODO | 14 --------------
output/output_disk.ml | 29 +++++++++++++++++++++--------
output/output_libvirt.ml | 31 ++++++++++++++++++++++---------
output/output_qemu.ml | 38 +++++++++++++++++++++-----------------
4 files changed, 64 insertions(+), 48 deletions(-)
diff --git a/TODO b/TODO
index f578d506..04b1dd20 100644
--- a/TODO
+++ b/TODO
@@ -1,17 +1,3 @@
-virt-v2v -o disk|qemu -oo compressed
-------------------------------------
-
-This was temporarily dropped when I modularized virt-v2v. It would
-not be too difficult to add it back. The following is the qemu-nbd
-command required (to be run as the output helper) which creates a
-compressed qcow2 disk image:
-
-$ qemu-nbd --image-opts driver=compress,file.driver=qcow2,file.file.driver=file,file.file.filename=new.qcow2
-
-Note this requires fixes in nbdcopy so it obeys the advertised block
-alignment:
-https://lists.gnu.org/archive/html/qemu-block/2022-01/threads.html#00729
-
virt-v2v -o rhv-upload
----------------------
diff --git a/output/output_disk.ml b/output/output_disk.ml
index bc5b4e1c..abcfcdc0 100644
--- a/output/output_disk.ml
+++ b/output/output_disk.ml
@@ -30,7 +30,7 @@ open Create_libvirt_xml
open Output
module Disk = struct
- type poptions = Types.output_allocation * string * string * string
+ type poptions = bool * Types.output_allocation * string * string * string
type t = unit
@@ -41,11 +41,21 @@ module Disk = struct
| None -> ""
let query_output_options () =
- printf (f_"No output options can be used in this mode.\n")
+ printf (f_"Output options that can be used with -o disk:
+
+ -oo compressed Compress the output file (used only with -of qcow2)
+")
let parse_options options source =
- if options.output_options <> [] then
- error (f_"no -oo (output options) are allowed here");
+ let compressed = ref false in
+ List.iter (
+ function
+ | "compressed", "" -> compressed := true
+ | "compressed", v -> compressed := bool_of_string v
+ | k, _ ->
+ error (f_"-o disk: unknown output option -oo %s") k
+ ) options.output_options;
+
if options.output_password <> None then
error_option_cannot_be_used_in_output_mode "local" "-op";
@@ -60,11 +70,13 @@ module Disk = struct
let output_name = Option.default source.s_name options.output_name in
- options.output_alloc, options.output_format, output_name, output_storage
+ !compressed, options.output_alloc, options.output_format,
+ output_name, output_storage
let setup dir options source =
let disks = get_disks dir in
- let output_alloc, output_format, output_name, output_storage = options in
+ let compressed, output_alloc, output_format, output_name, output_storage =
+ options in
List.iter (
fun (i, size) ->
@@ -73,11 +85,12 @@ module Disk = struct
(* Create the actual output disk. *)
let outdisk = disk_path output_storage output_name i in
- output_to_local_file output_alloc output_format outdisk size socket
+ output_to_local_file ~compressed output_alloc output_format
+ outdisk size socket
) disks
let finalize dir options () source inspect target_meta =
- let output_alloc, output_format, output_name, output_storage = options in
+ let _, output_alloc, output_format, output_name, output_storage = options in
(* Convert metadata to libvirt XML. *)
(match target_meta.target_firmware with
diff --git a/output/output_libvirt.ml b/output/output_libvirt.ml
index e0d3432d..04b4c5f8 100644
--- a/output/output_libvirt.ml
+++ b/output/output_libvirt.ml
@@ -32,7 +32,7 @@ open Create_libvirt_xml
open Output
module Libvirt_ = struct
- type poptions = Libvirt.rw Libvirt.Connect.t Lazy.t *
+ type poptions = Libvirt.rw Libvirt.Connect.t Lazy.t * bool *
Types.output_allocation * string * string * string
type t = string * string
@@ -44,11 +44,21 @@ module Libvirt_ = struct
| None -> ""
let query_output_options () =
- printf (f_"No output options can be used in this mode.\n")
+ printf (f_"Output options that can be used with -o libvirt:
+
+ -oo compressed Compress the output file (used only with -of qcow2)
+")
let parse_options options source =
- if options.output_options <> [] then
- error (f_"no -oo (output options) are allowed here");
+ let compressed = ref false in
+ List.iter (
+ function
+ | "compressed", "" -> compressed := true
+ | "compressed", v -> compressed := bool_of_string v
+ | k, _ ->
+ error (f_"-o disk: unknown output option -oo %s") k
+ ) options.output_options;
+
if options.output_password <> None then
error_option_cannot_be_used_in_output_mode "libvirt" "-op";
@@ -59,12 +69,13 @@ module Libvirt_ = struct
let output_name = Option.default source.s_name options.output_name in
- (conn, options.output_alloc, options.output_format, output_name,
- output_pool)
+ (conn, !compressed, options.output_alloc, options.output_format,
+ output_name, output_pool)
let setup dir options source =
let disks = get_disks dir in
- let conn, output_alloc, output_format, output_name, output_pool = options in
+ let conn, compressed, output_alloc, output_format,
+ output_name, output_pool = options in
let conn = Lazy.force conn in
(* Get the capabilities from libvirt. *)
@@ -119,13 +130,15 @@ module Libvirt_ = struct
(* Create the actual output disk. *)
let outdisk = target_path // output_name ^ "-sd" ^ (drive_name i) in
- output_to_local_file output_alloc output_format outdisk size socket
+ output_to_local_file ~compressed output_alloc output_format
+ outdisk size socket
) disks;
(capabilities_xml, pool_name)
let rec finalize dir options t source inspect target_meta =
- let conn, output_alloc, output_format, output_name, output_pool = options in
+ let conn, _, output_alloc, output_format, output_name, output_pool =
+ options in
let capabilities_xml, pool_name = t in
(match target_meta.target_firmware with
diff --git a/output/output_qemu.ml b/output/output_qemu.ml
index 527d3c5e..e7efbb73 100644
--- a/output/output_qemu.ml
+++ b/output/output_qemu.ml
@@ -29,7 +29,8 @@ open Utils
open Output
module QEMU = struct
- type poptions = bool * Types.output_allocation * string * string * string
+ type poptions = bool * bool *
+ Types.output_allocation * string * string * string
type t = unit
@@ -42,6 +43,7 @@ module QEMU = struct
let query_output_options () =
printf (f_"Output options (-oo) which can be used with -o qemu:
+ -oo compressed Compress the output file (used only with -of qcow2)
-oo qemu-boot Boot the guest in qemu after conversion
")
@@ -49,19 +51,19 @@ module QEMU = struct
if options.output_password <> None then
error_option_cannot_be_used_in_output_mode "qemu" "-op";
- let qemu_boot = ref false in
+ let compressed = ref false
+ and qemu_boot = ref false in
List.iter (
- fun (k, v) ->
- match k with
- | "qemu-boot" ->
- if v = "" || v = "true" then qemu_boot := true
- else if v = "false" then qemu_boot := false
- else
- error (f_"-o qemu: use -oo qemu-boot[=true|false]")
- | k ->
- error (f_"-o qemu: unknown output option -oo %s") k
- ) options.output_options;
- let qemu_boot = !qemu_boot in
+ function
+ | "compressed", "" -> compressed := true
+ | "compressed", v -> compressed := bool_of_string v
+ | "qemu-boot", "" -> qemu_boot := true
+ | "qemu-boot", v -> qemu_boot := bool_of_string v
+ | k, _ ->
+ error (f_"-o qemu: unknown output option -oo %s") k
+ ) options.output_options;
+ let compressed = !compressed
+ and qemu_boot = !qemu_boot in
if qemu_boot then
error (f_"-o qemu: the -oo qemu-boot option cannot be used in RHEL");
@@ -77,12 +79,13 @@ module QEMU = struct
let output_name = Option.default source.s_name options.output_name in
- (qemu_boot, options.output_alloc, options.output_format,
+ (compressed, qemu_boot, options.output_alloc, options.output_format,
output_name, output_storage)
let setup dir options source =
let disks = get_disks dir in
- let _, output_alloc, output_format, output_name, output_storage = options in
+ let compressed, _, output_alloc, output_format,
+ output_name, output_storage = options in
List.iter (
fun (i, size) ->
@@ -91,11 +94,12 @@ module QEMU = struct
(* Create the actual output disk. *)
let outdisk = disk_path output_storage output_name i in
- output_to_local_file output_alloc output_format outdisk size socket
+ output_to_local_file ~compressed output_alloc output_format
+ outdisk size socket
) disks
let finalize dir options () source inspect target_meta =
- let qemu_boot, output_alloc, output_format,
+ let _, qemu_boot, output_alloc, output_format,
output_name, output_storage = options in
let { guestcaps; target_buses; target_firmware } = target_meta in
--
2.31.1

View File

@ -0,0 +1,117 @@
From f87296160b1c1e213d86a077ab2e764c2977bc1e Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Fri, 1 Jul 2022 11:18:53 +0100
Subject: [PATCH] tests: Add a simple test of -o local -of qcow2 -oo compressed
This only tests that it doesn't completely fail, which it did before
we fixed nbdcopy. I checked the file sizes manually and with
compression the resulting file is about half the size.
This test is a clone of tests/test-v2v-of-option.sh. In order to
compare the sizes across the two tests, and to keep the tests fairly
similar I added an ls -l command to the original test.
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
(cherry picked from commit 7505750972b49e1a448c519a27998bd5f20be60a)
---
tests/Makefile.am | 2 +
tests/test-v2v-o-local-qcow2-compressed.sh | 53 ++++++++++++++++++++++
tests/test-v2v-of-option.sh | 2 +
3 files changed, 57 insertions(+)
create mode 100755 tests/test-v2v-o-local-qcow2-compressed.sh
diff --git a/tests/Makefile.am b/tests/Makefile.am
index e787a86c..a26ecf7a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -82,6 +82,7 @@ TESTS = \
test-v2v-networks-and-bridges.sh \
test-v2v-o-glance.sh \
test-v2v-o-libvirt.sh \
+ test-v2v-o-local-qcow2-compressed.sh \
test-v2v-o-null.sh \
test-v2v-o-openstack.sh \
test-v2v-o-qemu.sh \
@@ -241,6 +242,7 @@ EXTRA_DIST += \
test-v2v-networks-and-bridges-expected.xml \
test-v2v-o-glance.sh \
test-v2v-o-libvirt.sh \
+ test-v2v-o-local-qcow2-compressed.sh \
test-v2v-o-null.sh \
test-v2v-o-openstack.sh \
test-v2v-o-qemu.sh \
diff --git a/tests/test-v2v-o-local-qcow2-compressed.sh b/tests/test-v2v-o-local-qcow2-compressed.sh
new file mode 100755
index 00000000..32c9ebbe
--- /dev/null
+++ b/tests/test-v2v-o-local-qcow2-compressed.sh
@@ -0,0 +1,53 @@
+#!/bin/bash -
+# libguestfs virt-v2v test script
+# Copyright (C) 2014-2022 Red Hat Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+# Test -o local -of qcow2 -oo compressed.
+
+set -e
+
+source ./functions.sh
+set -e
+set -x
+
+skip_if_skipped
+requires test -f ../test-data/phony-guests/windows.img
+
+# This requires fixed nbdcopy >= 1.13.5.
+requires nbdcopy --version
+nbdcopy --version | {
+ IFS=' .' read name major minor release
+ requires test \( "$major" -gt 1 \) -o \
+ \( "$major" -eq 1 -a "$minor" -gt 13 \) -o \
+ \( "$major" -eq 1 -a "$minor" -eq 13 -a "$release" -ge 5 \)
+}
+
+export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
+
+d=test-v2v-o-local-qcow2-compressed.d
+rm -rf $d
+cleanup_fn rm -rf $d
+mkdir $d
+
+$VG virt-v2v --debug-gc \
+ -i disk ../test-data/phony-guests/windows.img \
+ -o local -of qcow2 -oo compressed -os $d
+
+# Test the libvirt XML metadata and a disk was created.
+ls -l $d
+test -f $d/windows.xml
+test -f $d/windows-sda
diff --git a/tests/test-v2v-of-option.sh b/tests/test-v2v-of-option.sh
index bdfd3418..6c5f5938 100755
--- a/tests/test-v2v-of-option.sh
+++ b/tests/test-v2v-of-option.sh
@@ -42,6 +42,8 @@ $VG virt-v2v --debug-gc \
-i libvirt -ic "$libvirt_uri" windows \
-o local -os $d -of qcow2
+ls -l $d
+
# Test the disk is qcow2 format.
if [ "$(guestfish disk-format $d/windows-sda)" != qcow2 ]; then
echo "$0: test failed: output is not qcow2"
--
2.31.1

View File

@ -0,0 +1,50 @@
From 8bc838bd9b12c658bd7c6f1d5d22dfc0375ca57b Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 5 Jul 2022 11:56:54 +0100
Subject: [PATCH] RHEL 9: -oo compressed: Remove nbdcopy version check and test
In RHEL 9 nbdcopy 1.12.4-2 will be sufficient (vs nbdcopy 1.13.5
upstream). We will enforce this through RPM dependencies and test it
separately. Thus remove the version check and test.
---
output/output.ml | 11 -----------
tests/Makefile.am | 1 -
2 files changed, 12 deletions(-)
diff --git a/output/output.ml b/output/output.ml
index 23c3932d..496c32b6 100644
--- a/output/output.ml
+++ b/output/output.ml
@@ -83,17 +83,6 @@ let output_to_local_file ?(changeuid = fun f -> f ()) ?(compressed = false)
if output_format <> "qcow2" then
error (f_"-oo compressed is only allowed when the output format \
is a local qcow2-format file, i.e. -of qcow2");
-
- (* Check nbdcopy is new enough. This assumes that the version of
- * libnbd is the same as the version of nbdcopy, but parsing this
- * is easier. We can remove this check when we build-depend on
- * libnbd >= 1.14.
- *)
- let version =
- NBD.create () |> NBD.get_version |>
- String.nsplit "." |> List.map int_of_string in
- if version < [1; 13; 5] then
- error (f_"-oo compressed option requires nbdcopy >= 1.13.5")
);
let g = open_guestfs () in
diff --git a/tests/Makefile.am b/tests/Makefile.am
index a26ecf7a..47e5f10d 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -82,7 +82,6 @@ TESTS = \
test-v2v-networks-and-bridges.sh \
test-v2v-o-glance.sh \
test-v2v-o-libvirt.sh \
- test-v2v-o-local-qcow2-compressed.sh \
test-v2v-o-null.sh \
test-v2v-o-openstack.sh \
test-v2v-o-qemu.sh \
--
2.31.1

View File

@ -0,0 +1,25 @@
From 2408250d7cbf6c32a0a9a9de072fdb93d583519d Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 5 Jul 2022 11:58:09 +0100
Subject: [PATCH] RHEL 9: tests: Remove btrfs test
RHEL does not have btrfs so this test always fails.
---
tests/Makefile.am | 1 -
1 file changed, 1 deletion(-)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 47e5f10d..9560cc77 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -96,7 +96,6 @@ TESTS = \
test-v2v-sound.sh \
test-v2v-virtio-win-iso.sh \
test-v2v-fedora-conversion.sh \
- test-v2v-fedora-btrfs-conversion.sh \
test-v2v-fedora-luks-on-lvm-conversion.sh \
test-v2v-fedora-lvm-on-luks-conversion.sh \
test-v2v-fedora-md-conversion.sh \
--
2.31.1

View File

@ -16,7 +16,7 @@
Name: virt-v2v
Epoch: 1
Version: 2.0.6
Release: 2%{?dist}
Release: 3%{?dist}
Summary: Convert a virtual machine to run on KVM
License: GPLv2+
@ -45,6 +45,25 @@ Patch0009: 0009-RHEL-Remove-the-in-place-option.patch
Patch0010: 0010-output-Remove-o-json-mode.patch
Patch0011: 0011-output-Remove-unused-dummy.c.patch
Patch0012: 0012-adopt-inversion-of-SELinux-relabeling-in-virt-custom.patch
Patch0013: 0013-test-data-phony-guests-Upgrade-Fedora-RPM-database-a.patch
Patch0014: 0014-test-data-phony-guests-Increase-size-of-root-filesys.patch
Patch0015: 0015-test-data-phony-guests-Allow-virt-v2v-to-work-agains.patch
Patch0016: 0016-tests-Add-test-cases-for-converting-the-phony-Fedora.patch
Patch0017: 0017-output-create_libvirt_xml-wire-up-the-QEMU-guest-age.patch
Patch0018: 0018-windows_virtio-remove-install_linux_tools.patch
Patch0019: 0019-convert_linux-extract-qemu-guest-agent-package-name.patch
Patch0020: 0020-convert_linux-install-the-QEMU-guest-agent-with-a-fi.patch
Patch0021: 0021-test-data-Replace-deprecated-luks_open-with-cryptset.patch
Patch0022: 0022-tests-rename-luks-to-lvm-on-luks.patch
Patch0023: 0023-tests-add-LUKS-on-LVM-test.patch
Patch0024: 0024-RHV-outputs-limit-copied-disk-count-to-23.patch
Patch0025: 0025-update-common-submodule-for-CVE-2022-2211-fix.patch
Patch0026: 0026-convert-document-networking-dependency-of-key-ID-cle.patch
Patch0027: 0027-qemu-nbd-Implement-output-compression-for-qcow2-file.patch
Patch0028: 0028-o-disk-o-libvirt-o-qemu-Implement-of-qcow2-oo-compre.patch
Patch0029: 0029-tests-Add-a-simple-test-of-o-local-of-qcow2-oo-compr.patch
Patch0030: 0030-RHEL-9-oo-compressed-Remove-nbdcopy-version-check-an.patch
Patch0031: 0031-RHEL-9-tests-Remove-btrfs-test.patch
%if !0%{?rhel}
# libguestfs hasn't been built on i686 for a while since there is no
@ -67,6 +86,7 @@ ExclusiveArch: x86_64
BuildRequires: autoconf, automake, libtool
%endif
BuildRequires: git
BuildRequires: make
BuildRequires: /usr/bin/pod2man
BuildRequires: gcc
@ -136,7 +156,7 @@ Requires: python3
%else
Requires: platform-python
%endif
Requires: libnbd >= 1.10
Requires: libnbd >= 1.12.4-2.el9
Requires: %{_bindir}/qemu-nbd
Requires: %{_bindir}/nbdcopy
Requires: %{_bindir}/nbdinfo
@ -212,7 +232,7 @@ for %{name}.
%if 0%{verify_tarball_signature}
%{gpgverify} --keyring='%{SOURCE2}' --signature='%{SOURCE1}' --data='%{SOURCE0}'
%endif
%autosetup -p1
%autosetup -p1 -S git
%if 0%{patches_touch_autotools}
autoreconf -i
@ -322,7 +342,7 @@ rm $RPM_BUILD_ROOT%{_mandir}/man1/virt-v2v-in-place.1*
%changelog
* Thu Jun 08 2022 Richard W.M. Jones <rjones@redhat.com> - 1:2.0.6-2
* Tue Jul 05 2022 Richard W.M. Jones <rjones@redhat.com> - 1:2.0.6-3
- Rebase to stable branch version 2.0.6
resolves: rhbz#2059287, rhbz#1658126, rhbz#1788823, rhbz#1854275
- Fix openssh-clients dependency
@ -362,6 +382,15 @@ rm $RPM_BUILD_ROOT%{_mandir}/man1/virt-v2v-in-place.1*
resolves: rhbz#2003503
- Add Requires python3 / platform-python
resolves: rhbz#2094779
- Fix CVE-2022-2211 Denial of Service in --key parameter
resolves: rhbz#2102719
- Add -oo compressed support
resolves: rhbz#2047660
- Install qemu-ga package during conversion (2028764)
- Limit the maximum of disks per guest
resolves: rhbz#2051564
- Add support for LUKS encrypted guests using Clevis & Tang
resolves: rhbz#1809453
* Tue Feb 15 2022 Richard W.M. Jones <rjones@redhat.com> - 1:1.45.99-1
- Rebase to upstream 1.45.99.