Laszlo Ersek
2022-Aug-26 11:39 UTC
[Libguestfs] [p2v PATCH 0/4] improve the "virt-p2v in a VM" tests
"make run-virt-p2v-in-a-vm" and "make run-virt-p2v-in-an-nvme-vm" suffer from two problems: (a) possibly duplicate XFS UUIDs between the $PHYSICAL_MACHINE disk and the "virt-p2v.img" boot media, (b) slow guest (= fake "physical machine") boot. This series fixes these issues. Tested with actual conversions (libvirt output) and post-conversion booting. Laszlo Laszlo Ersek (4): Makefile.am: factor out "make-physical-machine.sh" make-physical-machine.sh: set root password to "p2v-phys" make-physical-machine.sh: regenerate filesystem UUIDs Makefile.am: speed up the boot phase of the "virt-p2v in a VM" tests Makefile.am | 9 +- .gitignore | 1 + make-physical-machine.sh | 117 ++++++++++++++++++++ 3 files changed, 124 insertions(+), 3 deletions(-) create mode 100755 make-physical-machine.sh
Laszlo Ersek
2022-Aug-26 11:39 UTC
[Libguestfs] [p2v PATCH 1/4] Makefile.am: factor out "make-physical-machine.sh"
Extract and somewhat generalize the recipe for the $(PHYSICAL_MACHINE)
target to a separate shell script. In preparation for the multiple steps
we're going to introduce later, redirect virt-builder to a temp file at
first (placed in the same directory as the finally expected disk image),
and rename that file upon success.
Signed-off-by: Laszlo Ersek <lersek at redhat.com>
---
Makefile.am | 5 ++-
.gitignore | 1 +
make-physical-machine.sh | 37 ++++++++++++++++++++
3 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/Makefile.am b/Makefile.am
index d94ac6fdaf94..f25de74b8690 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -41,6 +41,7 @@ EXTRA_DIST = \
kiwi-config.xml.in \
launch-virt-p2v \
libguestfs/README \
+ make-physical-machine.sh \
miniexpect/README \
p2v.ks.in \
p2v.service \
@@ -66,6 +67,7 @@ CLEANFILES += \
$(generated_sources) \
$(PHYSICAL_MACHINE) $(BLANK_DISK) \
about-authors.c \
+ physical-machine.tmp.* \
stamp-test-virt-p2v-pxe-data-files \
stamp-test-virt-p2v-pxe-kernel \
test-virt-p2v-pxe.authorized_keys \
@@ -255,6 +257,7 @@ if HAVE_LIBGUESTFS
check_DATA += \
$(PHYSICAL_MACHINE) \
$(BLANK_DISK)
+check_SCRIPTS = make-physical-machine.sh
endif HAVE_LIBGUESTFS
run-virt-p2v-directly: $(PHYSICAL_MACHINE)
@@ -317,7 +320,7 @@ run-virt-p2v-non-gui-conversion: $(PHYSICAL_MACHINE)
stamp-test-virt-p2v-pxe-dat
SLOW=1 $(top_builddir)/run ./test-virt-p2v-pxe.sh
$(PHYSICAL_MACHINE):
- $(top_builddir)/run virt-builder --format raw -o $@ fedora-35
+ $(top_builddir)/run ./make-physical-machine.sh $@
$(BLANK_DISK):
$(top_builddir)/run guestfish -N $@=part exit
diff --git a/.gitignore b/.gitignore
index a870e2b6186b..eea5128411c2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,6 +41,7 @@ Makefile.in
/m4/ltsugar.m4
/m4/ltversion.m4
/p2v-config.h
+/physical-machine.tmp.*
/podwrapper.pl
/run
/stamp-h1
diff --git a/make-physical-machine.sh b/make-physical-machine.sh
new file mode 100755
index 000000000000..fb42cda34fca
--- /dev/null
+++ b/make-physical-machine.sh
@@ -0,0 +1,37 @@
+#!/bin/bash -
+# Copyright (C) 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, see <https://www.gnu.org/licenses/>.
+
+set -e -u -C
+
+disk+
+cleanup()
+{
+ set +e
+ if test -n "$disk"; then
+ rm -f -- "$disk"
+ disk+ fi
+}
+
+trap cleanup EXIT
+
+output=$1
+outdir=$(dirname -- "$output")
+disk=$(mktemp -p "$outdir" physical-machine.tmp.XXXXXXXXXX)
+virt-builder --format raw -o "$disk" fedora-35
+mv -- "$disk" "$output"
+disk=
Laszlo Ersek
2022-Aug-26 11:39 UTC
[Libguestfs] [p2v PATCH 2/4] make-physical-machine.sh: set root password to "p2v-phys"
It helps with testing if we set the fake physical machine's password to a simple known string, rather than letting virt-builder generate a complex, random password. Signed-off-by: Laszlo Ersek <lersek at redhat.com> --- make-physical-machine.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make-physical-machine.sh b/make-physical-machine.sh index fb42cda34fca..ff6db4940b51 100755 --- a/make-physical-machine.sh +++ b/make-physical-machine.sh @@ -32,6 +32,6 @@ trap cleanup EXIT output=$1 outdir=$(dirname -- "$output") disk=$(mktemp -p "$outdir" physical-machine.tmp.XXXXXXXXXX) -virt-builder --format raw -o "$disk" fedora-35 +virt-builder --format raw -o "$disk" --root-password password:p2v-phys fedora-35 mv -- "$disk" "$output" disk=
Laszlo Ersek
2022-Aug-26 11:39 UTC
[Libguestfs] [p2v PATCH 3/4] make-physical-machine.sh: regenerate filesystem UUIDs
Some test targets in "Makefile.am", such as
"run-virt-p2v-in-a-vm" and
"run-virt-p2v-in-an-nvme-vm", use both the PHYSICAL_MACHINE disk (as
the
conversion subject) and "virt-p2v.img" (as boot media).
Unless the user overrides the PHYSICAL_MACHINE macro, we generate it with
virt-builder, using a distro that we open-code (currently: Fedora 35).
"virt-p2v.img" is also generated with virt-builder, but the distro
installed in it follows the user's host OS (therefore we have less control
over the distro choice in "virt-p2v.img").
The user's host OS may happen to match the OS we hardcode for
PHYSICAL_MACHINE (currently: Fedora 35), in which case we end up using the
same virt-builder template for both images. This is a problem: the
filesystems between both images will have identical UUIDs, which may cause
the kernel loaded from "virt-p2v.img" to mount the root filesystem
from
PHYSICAL_MACHINE.
Prevent this by regenerating the filesystem UUIDs in PHYSICAL_MACHINE
(whose distro we closely control, unless the user sets PHYSICAL_MACHINE
themselves). Instead of the virt-sysprep operation "fs-uuids", which
currently cannot update the filesystem UUID references in the guest's
config files (<https://libguestfs.org/virt-sysprep.1.html#fs-uuids>,
<https://bugzilla.redhat.com/show_bug.cgi?id=991641>), implement a
somewhat crude guest-side shell command for the same purpose. Such a
command would likely not be flexible / robust enough for "fs-uuids" in
virt-sysprep, but -- due to our tight control over the PHYSICAL_MACHINE
operating system in virt-p2v -- it should suffice for virt-p2v testing.
Signed-off-by: Laszlo Ersek <lersek at redhat.com>
---
make-physical-machine.sh | 82 +++++++++++++++++++-
1 file changed, 81 insertions(+), 1 deletion(-)
diff --git a/make-physical-machine.sh b/make-physical-machine.sh
index ff6db4940b51..946d59f0c30b 100755
--- a/make-physical-machine.sh
+++ b/make-physical-machine.sh
@@ -16,11 +16,16 @@
set -e -u -C
+GUESTFISH_PID disk
cleanup()
{
set +e
+ if test -n "$GUESTFISH_PID"; then
+ guestfish --remote -- exit >/dev/null 2>&1
+ GUESTFISH_PID+ fi
if test -n "$disk"; then
rm -f -- "$disk"
disk@@ -32,6 +37,81 @@ trap cleanup EXIT
output=$1
outdir=$(dirname -- "$output")
disk=$(mktemp -p "$outdir" physical-machine.tmp.XXXXXXXXXX)
-virt-builder --format raw -o "$disk" --root-password
password:p2v-phys fedora-35
+# Delay the SELinux relabeling.
+virt-builder --format raw -o "$disk" --root-password
password:p2v-phys \
+ --no-selinux-relabel fedora-35
+
+# Start a guestfish server on the disk image, so that each of the several
+# UUID-manipulation commands below not need a separate guestfish launch.
+guestfish_set_pid=$(guestfish --listen --format=raw --add "$disk")
+eval "$guestfish_set_pid"
+guestfish --remote -- run
+
+# The array below open-codes the partition:filesystem layout of the
virt-builder
+# disk template used above. Whenever you bump the Fedora version, update the
+# array below as needed.
+#
+# We cannot use inspection either before or after the filesystem UUID changes:
+#
+# - the UUID of a mounted filesystem cannot be changed (at least with XFS);
+#
+# - right after the UUID changes, inspection does not work correctly, as the
new
+# fs UUIDs are out of sync with the UUID references in those config files
that
+# inspection relies upon.
+#
+# Note that the order of entries is important too: the mount points must be
+# listed in dependency order (put the dependees first, the dependants last).
+fsdevs=(/dev/sda3:/ /dev/sda2:/boot)
+
+# For each filesystem:
+#
+# - regenerate the UUID,
+#
+# - produce a sed command (scriptlet) that performs the same UUID replacement
in
+# a text file,
+#
+# - mount the filesystem.
+#
+# Note that later we're going to rely on the fact that the generated sed
+# commands *require no quoting* on the shell command line.
+declare -a sed_script
+sed_idx=0
+for fsdev in "${fsdevs[@]}"; do
+ device=${fsdev%:*}
+ mountpoint=${fsdev#*:}
+
+ old_uuid=$(guestfish --remote -- get-uuid "$device")
+ guestfish --remote -- set-uuid-random "$device"
+ new_uuid=$(guestfish --remote -- get-uuid "$device")
+
+ sed_script[sed_idx++]=-e
+ sed_script[sed_idx++]=s/$old_uuid/$new_uuid/ig
+
+ guestfish --remote -- mount "$device" "$mountpoint"
+done
+
+# Prepare the UUID replacement shell command for the appliance.
+refresh_uuid_refs=(find /boot /etc -type f -print0 '|'
+ xargs -0 -r -- sed -i "${sed_script[@]}" --)
+
+# Passing the shell command to the appliance is where we rely on the fact that
+# the sed commands for replacing UUIDs require no quoting.
+guestfish --remote -- sh "${refresh_uuid_refs[*]}"
+
+# Tear down the guestfish server before we use virt-customize.
+waitpid=$GUESTFISH_PID
+guestfish --remote -- exit
+GUESTFISH_PID+while kill -s 0 -- "$waitpid" 2>/dev/null; do
+ sleep 1
+done
+
+# Reapply the SELinux labels now. Use virt-customize for this, rather than
+# guestfish's "selinux-relabel", as virt-customize contains some
heavy logic
+# related to "specfile". Inspection does work here, because the
config files are
+# in sync again with the filesystem UUIDs.
+virt-customize --format raw --add "$disk" --selinux-relabel
+
+# We're done; rename the temporary disk image to the expected output file.
mv -- "$disk" "$output"
disk=
Laszlo Ersek
2022-Aug-26 11:39 UTC
[Libguestfs] [p2v PATCH 4/4] Makefile.am: speed up the boot phase of the "virt-p2v in a VM" tests
The "piix3-usb-uhci" QEMU device emulates a USB1 controller. Not only does USB1 feature amazingly low transfer speeds -- which QEMU appears to emulate faithfully --, USB1 (and USB2 too) are distinctly virtualization-unfriendly, as the emulated controllers require constant polling. This is visible in two symptoms: (a) the "run-virt-p2v-in-a-vm" and "run-virt-p2v-in-an-nvme-vm" targets load data (such as the root filesystem) from the "virt-p2v.img" file very slowly, while the host CPU utilization of QEMU never exceeds ~30%, (b) once the virt-p2v application launches in the guest, and the cursor is blinking in the "Conversion server" text field, the host CPU utilization does not sink under ~12% (while "top" in the guest XTerm reports 99+% idleness). Fix this problem by using the qemu-xhci USB3 controller. USB3 both enables much higher transfer speeds and is event-driven, requiring no polling. Signed-off-by: Laszlo Ersek <lersek at redhat.com> --- Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index f25de74b8690..f2fe0e3efc99 100644 --- a/Makefile.am +++ b/Makefile.am @@ -270,7 +270,7 @@ run-virt-p2v-in-a-vm: virt-p2v.img $(PHYSICAL_MACHINE) -cpu host \ -m 2048 \ -drive id=hd0,file=$(PHYSICAL_MACHINE),format=raw,if=ide \ - -device piix3-usb-uhci \ + -device qemu-xhci \ -drive id=usb0,file=$<,format=raw,snapshot=on,if=none \ -device usb-storage,bootindex=1,drive=usb0 \ -boot menu=on \ @@ -294,7 +294,7 @@ run-virt-p2v-in-an-nvme-vm: virt-p2v.img $(PHYSICAL_MACHINE) $(BLANK_DISK) -device nvme,drive=phys,serial=01234567 \ \ -drive id=usb0,if=none,format=raw,file=$<,snapshot=on \ - -device piix3-usb-uhci,id=usb-bus \ + -device qemu-xhci,id=usb-bus \ -device usb-storage,drive=usb0,bootindex=1,bus=usb-bus.0 \ \ -drive id=blank1,if=none,format=raw,file=$(BLANK_DISK),snapshot=on \