When guestfsd exits, or the user exits the virt-rescue shell, the init script
exits which causes the kernel to panic. This is really a functional issue, as
all useful work is done by this point. However, it does cause virt-rescue to
display an unsightly error message.
This patch adds a new utility, guestfs_poweroff, to the appliance. This powers
off (reboots really: read the comment) the appliance, preventing init from
exiting, and therefore the kernel panic.
We also ignore errors returned by launch() in virt-rescue. launch() expects
guestfsd to start, which it never does in virt-rescue, so it always returns an
error about the appliance shutting down unexpectedly.
---
.gitignore | 1 +
appliance/Makefile.am | 6 ++++--
appliance/debian/modules/y0_install-guestfsd | 2 ++
appliance/guestfs_poweroff.c | 14 ++++++++++++++
appliance/init | 2 +-
appliance/update.sh.in | 4 ++++
tools/virt-rescue | 3 ++-
7 files changed, 28 insertions(+), 4 deletions(-)
create mode 100644 appliance/guestfs_poweroff.c
diff --git a/.gitignore b/.gitignore
index 094acb3..abd88bc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,7 @@ appliance/debian/debirf-libguestfs*.cgz
appliance/debian/root/
appliance/debian/vmlinuz-*
appliance/debian/debirf.conf
+appliance/guestfs_poweroff
appliance/initramfs.*.img
appliance/kmod.whitelist
appliance/make.sh
diff --git a/appliance/Makefile.am b/appliance/Makefile.am
index 2df8a2b..d30a071 100644
--- a/appliance/Makefile.am
+++ b/appliance/Makefile.am
@@ -46,6 +46,8 @@ superminfs_DATA = \
supermin.d/hostfiles
endif
+noinst_PROGRAMS = guestfs_poweroff
+
# Don't change these names - they must be the same as in '*.sh' scripts.
INITRAMFSIMG = initramfs.$(REPO).$(host_cpu).img
VMLINUZ = vmlinuz.$(REPO).$(host_cpu)
@@ -67,7 +69,7 @@ make.sh: make.sh.in
chmod +x $@-t
mv $@-t $@
-$(INITRAMFSIMG): $(top_builddir)/initramfs/fakeroot.log $(top_builddir)/daemon/guestfsd
init update.sh
+$(INITRAMFSIMG): $(top_builddir)/initramfs/fakeroot.log $(top_builddir)/daemon/guestfsd
init guestfs_poweroff update.sh
rm -f $@
bash update.sh
touch $@
@@ -99,7 +101,7 @@ supermin.d/daemon.img: $(INITRAMFSIMG)
mkdir -p supermin.d
rm -f $@ $@-t
(cd $(top_builddir)/initramfs && \
- echo -e "sbin\nsbin/guestfsd" | cpio --quiet -o -H newc ) > $@-t
+ echo -e "sbin\nsbin/guestfsd\nsbin/guestfs_poweroff" | cpio --quiet -o -H
newc ) > $@-t
mv $@-t $@
endif
diff --git a/appliance/debian/modules/y0_install-guestfsd
b/appliance/debian/modules/y0_install-guestfsd
index 2d895a0..c2b812a 100755
--- a/appliance/debian/modules/y0_install-guestfsd
+++ b/appliance/debian/modules/y0_install-guestfsd
@@ -37,4 +37,6 @@ rm -rf "$DEBIRF_ROOT"/usr/share/man/
# Install the actual appliance:
echo $PWD
install -o root -g root -m 0755 ../daemon/guestfsd
"$DEBIRF_ROOT"/sbin/guestfsd
+install -o root -g root -m 0755 ../appliance/guestfs_poweroff \
+ "$DEBIRF_ROOT"/sbin/guestfs_poweroff
install -o root -g root -m 0755 init "$DEBIRF_ROOT"/sbin/init
diff --git a/appliance/guestfs_poweroff.c b/appliance/guestfs_poweroff.c
new file mode 100644
index 0000000..7e18839
--- /dev/null
+++ b/appliance/guestfs_poweroff.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <sys/reboot.h>
+
+int main(int argc, char **argv)
+{
+ /* We actually hard reboot here rather than power off. For some reason
+ * reboot causes the qemu process to die, whereas poweroff doesn't.
+ *
+ * This should not return */
+ reboot(RB_AUTOBOOT);
+
+ perror("Power off failed");
+ return 1;
+}
diff --git a/appliance/init b/appliance/init
index ef6ad5c..f2daf69 100755
--- a/appliance/init
+++ b/appliance/init
@@ -108,10 +108,10 @@ else
bash -i
echo
echo "virt-rescue: Syncing the disk now before exiting ..."
- echo "(Don't worry if you see a 'Kernel panic' message below)"
echo
fi
sync
sleep 1
sync
+exec /sbin/guestfs_poweroff
diff --git a/appliance/update.sh.in b/appliance/update.sh.in
index 0222a75..9cb3450 100755
--- a/appliance/update.sh.in
+++ b/appliance/update.sh.in
@@ -33,6 +33,10 @@ if [ "@DIST@" = "REDHAT" ]; then
# Copy the daemon into the filesystem.
@FEBOOTSTRAP_INSTALL@ initramfs daemon/guestfsd /sbin/guestfsd 0755 root.root
+ # Copy guestfs_poweroff into the filesystem
+ febootstrap-install initramfs appliance/guestfs_poweroff \
+ /sbin/guestfs_poweroff 0755 root.root
+
# Generate final image.
@FEBOOTSTRAP_TO_INITRAMFS@ initramfs > $output-t
mv $output-t $output
diff --git a/tools/virt-rescue b/tools/virt-rescue
index 1f292f6..f466b43 100755
--- a/tools/virt-rescue
+++ b/tools/virt-rescue
@@ -214,7 +214,8 @@ $g->set_append ($str);
# Run the appliance. This won't return until the user quite the
# appliance.
-$g->launch ();
+# This will definitely return an error because we don't run the daemon
+eval { $g->launch (); };
exit 0;
--
1.7.2