Richard W.M. Jones
2016-Aug-26 17:33 UTC
[Libguestfs] [PATCH 1/2] customize: Fix firstboot scripts on Debian 6 & 7 (RHBZ#1019388).
I have only verified the fix on Debian 7. The Debian 6 guest doesn't appear to boot, I'm not sure why. The second patch contains a test suite. Rich.
Richard W.M. Jones
2016-Aug-26 17:33 UTC
[Libguestfs] [PATCH 1/2] customize: Fix firstboot scripts on Debian 6 & 7 (RHBZ#1019388).
---
customize/firstboot.ml | 32 +++++++++++++++++++++++++++-----
1 file changed, 27 insertions(+), 5 deletions(-)
diff --git a/customize/firstboot.ml b/customize/firstboot.ml
index 706d63c..f7213bc 100644
--- a/customize/firstboot.ml
+++ b/customize/firstboot.ml
@@ -97,7 +97,7 @@ StandardError=inherit
WantedBy=default.target
" firstboot_dir
- let rec install_service (g : Guestfs.guestfs) distro + let rec
install_service (g : Guestfs.guestfs) root distro major g#mkdir_p
firstboot_dir;
g#mkdir_p (sprintf "%s/scripts" firstboot_dir);
g#write (sprintf "%s/firstboot.sh" firstboot_dir) firstboot_sh;
@@ -113,7 +113,7 @@ WantedBy=default.target
if g#is_dir "/etc/systemd/system" then
install_systemd_service g;
if g#is_dir "/etc/rc.d" || g#is_dir "/etc/init.d" then
- install_sysvinit_service g distro
+ install_sysvinit_service g root distro major
(* Install the systemd firstboot service, if not installed already. *)
and install_systemd_service g @@ -144,12 +144,16 @@ WantedBy=default.target
oldunitfile csum
)
- and install_sysvinit_service g = function
+ and install_sysvinit_service g root distro major + match distro with
|
"fedora"|"rhel"|"centos"|"scientificlinux"|"redhat-based"
->
install_sysvinit_redhat g
| "opensuse"|"sles"|"suse-based" ->
install_sysvinit_suse g
- | "debian"|"ubuntu" ->
+ | "debian" ->
+ install_sysvinit_debian g;
+ if major <= 7 then try_update_rc_d g root
+ | "ubuntu" ->
install_sysvinit_debian g
| distro ->
error (f_"guest type %s is not supported") distro
@@ -209,6 +213,23 @@ WantedBy=default.target
g#rm_f "/etc/rc2.d/S99virt-sysprep-firstboot";
g#rm_f "/etc/rc3.d/S99virt-sysprep-firstboot";
g#rm_f "/etc/rc5.d/S99virt-sysprep-firstboot"
+
+ (* On Debian 6 & 7 you have to run: update-rc.d guestfs-firstboot
defaults
+ * RHBZ#1019388.
+ *)
+ and try_update_rc_d g root + let guest_arch = g#inspect_get_arch root in
+ let guest_arch_compatible = guest_arch_compatible guest_arch in
+ let cmd = "update-rc.d guestfs-firstboot defaults" in
+ if guest_arch_compatible then
+ try ignore (g#sh cmd)
+ with Guestfs.Error msg ->
+ warning (f_"could not finish firstboot installation by running
'%s' because the command failed: %s")
+ cmd msg
+ else (
+ warning (f_"cannot finish firstboot installation by running
'%s' because host cpu (%s) and guest arch (%s) are not compatible. The
firstboot service may not run at boot.")
+ cmd Guestfs_config.host_cpu guest_arch
+ )
end
module Windows = struct
@@ -340,11 +361,12 @@ let script_count = ref 0
let add_firstboot_script (g : Guestfs.guestfs) root name content let typ =
g#inspect_get_type root in
let distro = g#inspect_get_distro root in
+ let major = g#inspect_get_major_version root in
incr script_count;
let filename = sprintf "%04d-%s" !script_count (sanitize_name name)
in
match typ, distro with
| "linux", _ ->
- Linux.install_service g distro;
+ Linux.install_service g root distro major;
let filename = Linux.firstboot_dir // "scripts" // filename in
g#write filename content;
g#chmod 0o755 filename
--
2.7.4
Richard W.M. Jones
2016-Aug-26 17:33 UTC
[Libguestfs] [PATCH 2/2] customize: Add a slow test that firstboot works on a variety of real guests.
---
.gitignore | 1 +
customize/Makefile.am | 41 ++++++++++++++-
customize/test-firstboot.sh | 119 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 160 insertions(+), 1 deletion(-)
create mode 100755 customize/test-firstboot.sh
diff --git a/.gitignore b/.gitignore
index a97fe11..0d98fcd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -128,6 +128,7 @@ Makefile.in
/customize/customize-options.pod
/customize/customize-synopsis.pod
/customize/stamp-virt-customize.pod
+/customize/test-firstboot-*.sh
/customize/virt-customize
/customize/virt-customize.1
/daemon/actions.h
diff --git a/customize/Makefile.am b/customize/Makefile.am
index a76b6c5..3a3e229 100644
--- a/customize/Makefile.am
+++ b/customize/Makefile.am
@@ -21,6 +21,7 @@ EXTRA_DIST = \
$(generator_built) \
$(SOURCES_MLI) $(SOURCES_ML) $(SOURCES_C) \
customize_main.ml \
+ test-firstboot.sh \
test-virt-customize.sh \
test-virt-customize-docs.sh \
virt-customize.pod
@@ -192,12 +193,50 @@ TESTS = \
if ENABLE_APPLIANCE
TESTS += \
- test-virt-customize.sh
+ test-virt-customize.sh \
+ $(SLOW_TESTS)
endif
check-valgrind:
$(MAKE) VG="$(top_builddir)/run @VG@" check
+# Slow tests of firstboot functionality in real guests.
+
+SLOW_TESTS = \
+ $(firstboot_test_scripts)
+
+check-slow:
+ $(MAKE) check TESTS="$(SLOW_TESTS)" SLOW=1
+
+firstboot_test_scripts := \
+ test-firstboot-rhel-4.9.sh \
+ test-firstboot-rhel-5.11.sh \
+ test-firstboot-rhel-6.8.sh \
+ test-firstboot-rhel-7.2.sh \
+ test-firstboot-debian-7.sh \
+ test-firstboot-debian-8.sh \
+ test-firstboot-fedora-24.sh \
+ test-firstboot-ubuntu-10.04.sh \
+ test-firstboot-ubuntu-12.04.sh \
+ test-firstboot-ubuntu-14.04.sh \
+ test-firstboot-ubuntu-16.04.sh
+# Firstboot is known-broken on RHEL 3:
+# test-firstboot-rhel-3.9.sh
+# Debian 6 does not work, but should do. The guest doesn't appear to
+# boot, so it may be a problem with the test-firstboot.sh test script.
+# test-firstboot-debian-6.sh
+
+test-firstboot-%.sh:
+ rm -f $@ $@-t
+ f=`echo "$@" | sed 's/test-firstboot-\(.*\).sh/\1/'`; \
+ echo 'exec $$srcdir/test-firstboot.sh' "$$f" > $@-t
+ chmod 0755 $@-t
+ mv $@-t $@
+
+CLEANFILES += \
+ $(firstboot_test_scripts) \
+ firstboot-*.img
+
# Dependencies.
depend: .depend
diff --git a/customize/test-firstboot.sh b/customize/test-firstboot.sh
new file mode 100755
index 0000000..168b4f3
--- /dev/null
+++ b/customize/test-firstboot.sh
@@ -0,0 +1,119 @@
+#!/bin/bash -
+# Test firstboot functionality.
+# Copyright (C) 2016 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 slow test checks that firstboot works.
+#
+# NB. 'test-firstboot.sh' runs the tests, but the various tests are
+# run via the 'test-firstboot-GUESTNAME.sh' wrappers.
+
+export LANG=C
+set -e
+
+if [ -z "$SLOW" ]; then
+ echo "$0: use 'make check-slow' to run this test"
+ exit 77
+fi
+
+if [ -n "$SKIP_TEST_FIRSTBOOT_SH" ]; then
+ echo "$0: test skipped because environment variable is set."
+ exit 77
+fi
+
+guestname="$1"
+if [ -z "$guestname" ]; then
+ echo "$0: guestname parameter not set, don't run this test
directly."
+ exit 1
+fi
+
+disk="firstboot-$guestname.img"
+rm -f "$disk"
+
+# If the guest doesn't exist in virt-builder, skip. This is because
+# we test some RHEL guests which most users won't have access to.
+if ! virt-builder -l "$guestname" >/dev/null 2>&1; then
+ echo "$0: test skipped because \"$guestname\" not known to
virt-builder."
+ exit 77
+fi
+
+# We can only run the tests on x86_64.
+if [ "$(uname -m)" != "x86_64" ]; then
+ echo "$0: test skipped because !x86_64."
+ exit 77
+fi
+
+# Check qemu is installed.
+qemu=qemu-system-x86_64
+if ! $qemu -help >/dev/null 2>&1; then
+ echo "$0: test skipped because $qemu not found."
+ exit 77
+fi
+
+# Some guests need special virt-builder parameters.
+# See virt-builder --notes "$guestname"
+declare -a extra
+case "$guestname" in
+ debian-6|debian-7)
+ extra[${#extra[*]}]='--edit'
+ extra[${#extra[*]}]='/etc/inittab:
+ s,^#([1-9].*respawn.*/sbin/getty.*),$1,'
+ ;;
+ fedora*|rhel*|centos*)
+ extra[${#extra[*]}]='--selinux-relabel'
+ ;;
+ *)
+ ;;
+esac
+
+# Build a guest (using virt-builder) with some firstboot commands.
+#
+# The script currently assumes a Linux guest. We should test Windows,
+# FreeBSD in future (XXX).
+virt-builder "$guestname" \
+ --quiet \
+ -o "$disk" \
+ --firstboot-command "mkdir /fb1; sleep 5" \
+ --firstboot-command "touch /fb1/fb2; sleep 5" \
+ --firstboot-command "poweroff" \
+ "${extra[@]}"
+
+# Boot the guest in qemu and wait for the firstboot scripts to run.
+#
+# Use IDE because some ancient guests don't support anything else.
+#
+# Adding a network device is not strictly necessary, but makes
+# the Debian 7 guest happier.
+timeout 300s \
+$qemu \
+ -nodefconfig \
+ -display none \
+ -machine accel=kvm:tcg \
+ -m 2048 \
+ -boot c \
+ -drive file="$disk",format=raw,if=ide \
+ -netdev user,id=usernet \
+ -device rtl8139,netdev=usernet \
+ -serial stdio ||:
+
+# Did the firstboot scripts run? And in the right order? We can tell
+# because the directory and file are created and so the 'stat'
+# commands should not fail in guestfish.
+guestfish --ro -a "$disk" -i \
+ statns /fb1 : \
+ statns /fb1/fb2
+
+rm "$disk"
--
2.7.4
Reasonably Related Threads
- [PATCH] sysprep: handle distro specific sysv scripts
- [PATCH v2 1/2] firstboot: rename systemd and sysvinit
- [PATCH 0/4] firstboot: assorted enhancements
- [PATCH 0/4] Add customization capabilities to virt-sysprep
- [PATCH] customize: Move virt-customize-related code to a separate