mrc0mmand / rpms / libguestfs

Forked from rpms/libguestfs 3 years ago
Clone

Blame SOURCES/0164-dib-rework-run-of-extra-data.d-hooks-RHBZ-1362354.patch

e76f14
From 89edc42bc6e62851dffc32276b0c24f2a4bf8cf6 Mon Sep 17 00:00:00 2001
e76f14
From: Pino Toscano <ptoscano@redhat.com>
e76f14
Date: Wed, 3 Aug 2016 16:40:20 +0200
e76f14
Subject: [PATCH] dib: rework run of extra-data.d hooks (RHBZ#1362354)
e76f14
e76f14
Instead of running them before lanching the appliance with the disks and
e76f14
then uploading the result after root.d hooks run, mount the root in the
e76f14
local temporary directory using FUSE and then run the hooks on the
e76f14
guest.  Other than being closer to what diskimage-builder does, it also
e76f14
avoids issues with the extra-data.d scripts assuming to find things
e76f14
already, and we don't error out while trying to unpack files on the
e76f14
guest.
e76f14
e76f14
Since virt-dib requires FUSE now, build it only if FUSE is supported.
e76f14
e76f14
(cherry picked from commit d12be6625a74b4a088c75da5ae3a968678d814fd)
e76f14
---
e76f14
 Makefile.am      |   4 +-
e76f14
 dib/Makefile.am  |   4 +-
e76f14
 dib/dib.ml       | 123 +++++++++++++++++++++++++++++++------------------------
e76f14
 dib/virt-dib.pod |  23 -----------
e76f14
 4 files changed, 76 insertions(+), 78 deletions(-)
e76f14
e76f14
diff --git a/Makefile.am b/Makefile.am
e76f14
index ce20058..0945993 100644
e76f14
--- a/Makefile.am
e76f14
+++ b/Makefile.am
e76f14
@@ -145,7 +145,6 @@ SUBDIRS += \
e76f14
 	mllib \
e76f14
 	customize \
e76f14
 	builder builder/website \
e76f14
-	dib \
e76f14
 	get-kernel \
e76f14
 	resize \
e76f14
 	sparsify \
e76f14
@@ -154,6 +153,9 @@ SUBDIRS += \
e76f14
 if HAVE_OCAML_PKG_LIBVIRT
e76f14
 SUBDIRS += v2v/test-harness
e76f14
 endif
e76f14
+if HAVE_FUSE
e76f14
+SUBDIRS += dib
e76f14
+endif
e76f14
 endif
e76f14
 
e76f14
 # Perl tools.
e76f14
diff --git a/dib/Makefile.am b/dib/Makefile.am
e76f14
index ff6a933..ac0af26 100644
e76f14
--- a/dib/Makefile.am
e76f14
+++ b/dib/Makefile.am
e76f14
@@ -34,7 +34,8 @@ SOURCES_ML = \
e76f14
 
e76f14
 SOURCES_C = \
e76f14
 	../mllib/dev_t-c.c \
e76f14
-	../mllib/mkdtemp-c.c
e76f14
+	../mllib/mkdtemp-c.c \
e76f14
+	../mllib/exit-c.c
e76f14
 
e76f14
 bin_PROGRAMS =
e76f14
 
e76f14
@@ -62,6 +63,7 @@ BOBJECTS = \
e76f14
 	$(top_builddir)/mllib/stringMap.cmo \
e76f14
 	$(top_builddir)/mllib/common_utils.cmo \
e76f14
 	$(top_builddir)/mllib/mkdtemp.cmo \
e76f14
+	$(top_builddir)/mllib/exit.cmo \
e76f14
 	$(SOURCES_ML:.ml=.cmo)
e76f14
 XOBJECTS = $(BOBJECTS:.cmo=.cmx)
e76f14
 
e76f14
diff --git a/dib/dib.ml b/dib/dib.ml
e76f14
index 87af4eb..17775d8 100644
e76f14
--- a/dib/dib.ml
e76f14
+++ b/dib/dib.ml
e76f14
@@ -69,13 +69,15 @@ let envvars_string l =
e76f14
 
e76f14
 let prepare_external ~envvars ~dib_args ~dib_vars ~out_name ~root_label
e76f14
   ~rootfs_uuid ~image_cache ~arch ~network ~debug
e76f14
-  destdir libdir hooksdir tmpdir fakebindir all_elements element_paths =
e76f14
+  destdir libdir hooksdir fakebindir all_elements element_paths =
e76f14
   let network_string = if network then "" else "1" in
e76f14
 
e76f14
   let run_extra = sprintf "\
e76f14
 #!/bin/bash
e76f14
 set -e
e76f14
 %s
e76f14
+mount_dir=$1
e76f14
+shift
e76f14
 target_dir=$1
e76f14
 shift
e76f14
 script=$1
e76f14
@@ -87,7 +89,7 @@ shift
e76f14
 export PATH=%s:$PATH
e76f14
 
e76f14
 # d-i-b variables
e76f14
-export TMP_MOUNT_PATH=%s
e76f14
+export TMP_MOUNT_PATH=\"$mount_dir\"
e76f14
 export DIB_OFFLINE=%s
e76f14
 export IMAGE_NAME=\"%s\"
e76f14
 export DIB_ROOT_LABEL=\"%s\"
e76f14
@@ -120,7 +122,6 @@ $target_dir/$script
e76f14
     (if debug >= 1 then "set -x\n" else "")
e76f14
     (envvars_string envvars)
e76f14
     fakebindir
e76f14
-    (quote tmpdir)
e76f14
     network_string
e76f14
     out_name
e76f14
     root_label
e76f14
@@ -134,10 +135,7 @@ $target_dir/$script
e76f14
     (String.concat ":" element_paths)
e76f14
     (quote dib_vars)
e76f14
     debug in
e76f14
-  write_script (destdir // "run-part-extra.sh") run_extra;
e76f14
-
e76f14
-  (* Needed as TMPDIR for the extra-data hooks *)
e76f14
-  do_mkdir (tmpdir // "tmp")
e76f14
+  write_script (destdir // "run-part-extra.sh") run_extra
e76f14
 
e76f14
 let prepare_aux ~envvars ~dib_args ~dib_vars ~log_file ~out_name ~rootfs_uuid
e76f14
   ~arch ~network ~root_label ~install_type ~debug ~extra_packages
e76f14
@@ -392,26 +390,61 @@ let run_parts ~debug ~sysroot ~blockdev ~log_file ?(new_wd = "")
e76f14
   flush_all ();
e76f14
   Buffer.contents outbuf
e76f14
 
e76f14
-let run_parts_host ~debug hooks_dir hook_name scripts run_script =
e76f14
+let run_parts_host ~debug (g : Guestfs.guestfs) hooks_dir hook_name base_mount_dir scripts run_script =
e76f14
   let hook_dir = hooks_dir // hook_name in
e76f14
   let scripts = List.sort digit_prefix_compare scripts in
e76f14
-  let timings = Hashtbl.create 13 in
e76f14
-  List.iter (
e76f14
-    fun x ->
e76f14
-      message (f_"Running: %s/%s") hook_name x;
e76f14
-      let cmd = [ run_script; hook_dir; x ] in
e76f14
-      let run () =
e76f14
-        run_command cmd in
e76f14
-      let delta_t = timed_run run in
e76f14
-      if debug >= 1 then (
e76f14
-        printf "\n";
e76f14
-        printf "%s completed after %.3f s\n" x delta_t
e76f14
-      );
e76f14
-      Hashtbl.add timings x delta_t;
e76f14
-  ) scripts;
e76f14
-  if debug >= 1 then (
e76f14
-    print_string (timing_output ~target_name:hook_name scripts timings)
e76f14
+  let mount_dir = base_mount_dir // hook_name in
e76f14
+  do_mkdir mount_dir;
e76f14
+
e76f14
+  let rec fork_and_run () =
e76f14
+    let pid = Unix.fork () in
e76f14
+    if pid = 0 then ( (* child *)
e76f14
+      let retcode = run_scripts () in
e76f14
+      flush_all ();
e76f14
+      let cmd = [ "guestunmount"; mount_dir ] in
e76f14
+      ignore (run_command cmd);
e76f14
+      Exit._exit retcode
e76f14
+    );
e76f14
+    pid
e76f14
+  and run_scripts () =
e76f14
+    let timings = Hashtbl.create 13 in
e76f14
+    let rec loop = function
e76f14
+      | x :: xs ->
e76f14
+        message (f_"Running: %s/%s") hook_name x;
e76f14
+        let cmd = [ run_script; mount_dir; hook_dir; x ] in
e76f14
+        let retcode = ref 0 in
e76f14
+        let run () =
e76f14
+          retcode := run_command cmd in
e76f14
+        let delta_t = timed_run run in
e76f14
+        if debug >= 1 then (
e76f14
+          printf "\n";
e76f14
+          printf "%s completed after %.3f s\n" x delta_t
e76f14
+        );
e76f14
+        Hashtbl.add timings x delta_t;
e76f14
+        let retcode = !retcode in
e76f14
+        if retcode <> 0 then retcode
e76f14
+        else loop xs
e76f14
+      | [] -> 0
e76f14
+    in
e76f14
+    let retcode = loop scripts in
e76f14
+    if debug >= 1 then (
e76f14
+      print_string (timing_output ~target_name:hook_name scripts timings)
e76f14
+    );
e76f14
+    retcode
e76f14
+  in
e76f14
+
e76f14
+  g#mount_local mount_dir;
e76f14
+  let pid = fork_and_run () in
e76f14
+  g#mount_local_run ();
e76f14
+
e76f14
+  (match snd (Unix.waitpid [] pid) with
e76f14
+  | Unix.WEXITED 0 -> ()
e76f14
+  | Unix.WEXITED i -> exit i
e76f14
+  | Unix.WSIGNALED i
e76f14
+  | Unix.WSTOPPED i ->
e76f14
+    error (f_"sub-process killed by signal (%d)") i
e76f14
   );
e76f14
+
e76f14
   flush_all ()
e76f14
 
e76f14
 let run_install_packages ~debug ~blockdev ~log_file
e76f14
@@ -455,8 +488,6 @@ let main () =
e76f14
   do_mkdir auxtmpdir;
e76f14
   let hookstmpdir = auxtmpdir // "hooks" in
e76f14
   do_mkdir (hookstmpdir // "environment.d");    (* Just like d-i-b does. *)
e76f14
-  let extradatatmpdir = tmpdir // "extra-data" in
e76f14
-  do_mkdir extradatatmpdir;
e76f14
   do_mkdir (auxtmpdir // "out" // image_basename_d);
e76f14
   let elements =
e76f14
     if cmdline.use_base then ["base"] @ cmdline.elements
e76f14
@@ -575,20 +606,11 @@ let main () =
e76f14
   prepare_external ~envvars ~dib_args ~dib_vars ~out_name:image_basename
e76f14
                    ~root_label ~rootfs_uuid ~image_cache ~arch
e76f14
                    ~network:cmdline.network ~debug
e76f14
-                   tmpdir cmdline.basepath hookstmpdir extradatatmpdir
e76f14
+                   tmpdir cmdline.basepath hookstmpdir
e76f14
                    (auxtmpdir // "fake-bin")
e76f14
                    all_elements cmdline.element_paths;
e76f14
 
e76f14
-  let run_hook_host hook =
e76f14
-    try
e76f14
-      let scripts = Hashtbl.find final_hooks hook in
e76f14
-      if debug >= 1 then (
e76f14
-        printf "Running hooks for %s...\n%!" hook;
e76f14
-      );
e76f14
-      run_parts_host ~debug hookstmpdir hook scripts
e76f14
-        (tmpdir // "run-part-extra.sh")
e76f14
-    with Not_found -> ()
e76f14
-  and run_hook ~blockdev ~sysroot ?(new_wd = "") (g : Guestfs.guestfs) hook =
e76f14
+  let run_hook ~blockdev ~sysroot ?(new_wd = "") (g : Guestfs.guestfs) hook =
e76f14
     try
e76f14
       let scripts = Hashtbl.find final_hooks hook in
e76f14
       if debug >= 1 then (
e76f14
@@ -597,8 +619,6 @@ let main () =
e76f14
       run_parts ~debug ~sysroot ~blockdev ~log_file ~new_wd g hook scripts
e76f14
     with Not_found -> "" in
e76f14
 
e76f14
-  run_hook_host "extra-data.d";
e76f14
-
e76f14
   let copy_in (g : Guestfs.guestfs) srcdir destdir =
e76f14
     let desttar = Filename.temp_file ~temp_dir:tmpdir "virt-dib." ".tar.gz" in
e76f14
     let cmd = [ "tar"; "czf"; desttar; "-C"; srcdir; "--owner=root";
e76f14
@@ -608,18 +628,6 @@ let main () =
e76f14
     g#tar_in ~compress:"gzip" desttar destdir;
e76f14
     Sys.remove desttar in
e76f14
 
e76f14
-  let copy_preserve_in (g : Guestfs.guestfs) srcdir destdir =
e76f14
-    let desttar = Filename.temp_file ~temp_dir:tmpdir "virt-dib." ".tar.gz" in
e76f14
-    let remotetar = "/tmp/aux/" ^ (Filename.basename desttar) in
e76f14
-    let cmd = [ "tar"; "czf"; desttar; "-C"; srcdir; "--owner=root";
e76f14
-                "--group=root"; "." ] in
e76f14
-    if run_command cmd <> 0 then exit 1;
e76f14
-    g#upload desttar remotetar;
e76f14
-    let verbose_flag = if debug > 0 then "v" else "" in
e76f14
-    ignore (g#debug "sh" [| "tar"; "-C"; "/sysroot" ^ destdir; "--no-overwrite-dir"; "-x" ^ verbose_flag ^ "zf"; "/sysroot" ^ remotetar |]);
e76f14
-    Sys.remove desttar;
e76f14
-    g#rm remotetar in
e76f14
-
e76f14
   if debug >= 1 then
e76f14
     ignore (run_command [ "tree"; "-ps"; tmpdir ]);
e76f14
 
e76f14
@@ -747,7 +755,16 @@ let main () =
e76f14
   and run_hook_subroot hook =
e76f14
     do_run_hooks_noout ~sysroot:Subroot hook
e76f14
   and do_run_hooks_noout ~sysroot ?(new_wd = "") hook =
e76f14
-    ignore (run_hook ~sysroot ~blockdev ~new_wd g hook) in
e76f14
+    ignore (run_hook ~sysroot ~blockdev ~new_wd g hook)
e76f14
+  and run_hook_host hook =
e76f14
+    try
e76f14
+      let scripts = Hashtbl.find final_hooks hook in
e76f14
+      if debug >= 1 then (
e76f14
+        printf "Running hooks for %s...\n%!" hook;
e76f14
+      );
e76f14
+      run_parts_host ~debug g hookstmpdir hook tmpdir scripts
e76f14
+        (tmpdir // "run-part-extra.sh")
e76f14
+    with Not_found -> () in
e76f14
 
e76f14
   g#sync ();
e76f14
   checked_umount_all ();
e76f14
@@ -799,7 +816,7 @@ let main () =
e76f14
   mount_aux ();
e76f14
   g#ln_s "aux/hooks" "/tmp/in_target.d";
e76f14
 
e76f14
-  copy_preserve_in g extradatatmpdir "/";
e76f14
+  run_hook_host "extra-data.d";
e76f14
 
e76f14
   run_hook_in "pre-install.d";
e76f14
 
e76f14
diff --git a/dib/virt-dib.pod b/dib/virt-dib.pod
e76f14
index 8ccb9f5..41e7ec7 100644
e76f14
--- a/dib/virt-dib.pod
e76f14
+++ b/dib/virt-dib.pod
e76f14
@@ -577,29 +577,6 @@ arguments
e76f14
 
e76f14
 =item
e76f14
 
e76f14
-C<extra-data.d> scripts run in the host environment, before all the
e76f14
-other ones (even C<root.d>); this means that, depending on the
e76f14
-configuration for the elements, some of them may fail due to missing
e76f14
-content (usually directories) in C<TMP_HOOKS_PATH>.
e76f14
-
e76f14
-Workarounds for this may be either:
e76f14
-
e76f14
-=over 4
e76f14
-
e76f14
-=item
e76f14
-
e76f14
-fix the C<extra-data.d> scripts to create the missing directories
e76f14
-
e76f14
-=item
e76f14
-
e76f14
-create (and use) a simple element with a C<extra-data.d> script
e76f14
-named e.g. F<00-create-missing-dirs> to create the missing
e76f14
-directories
e76f14
-
e76f14
-=back
e76f14
-
e76f14
-=item
e76f14
-
e76f14
 extra tools needed on some out-of-chroot phases need to be available
e76f14
 in the appliance, see L</EXTRA DEPENDENCIES>.
e76f14
 
e76f14
-- 
aa0300
2.7.4
e76f14