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 \