[Libguestfs] [PATCH 3/3] Shut down the appliance cleanly

Matthew Booth mbooth at redhat.com
Tue Aug 3 16:20:13 UTC 2010


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




More information about the Libguestfs mailing list