[Libguestfs] [PATCH 3/3] Add --include-packagelist

Pino Toscano ptoscano at redhat.com
Wed Dec 2 18:11:36 UTC 2015


Introduce a new option, mainly used for debugging, to add in the
root of the appliance a file containing the list of all the packages
used to build it.
---
 src/build.ml     | 42 ++++++++++++++++++++++++++++++++++--------
 src/chroot.ml    | 19 ++++++++++++++++++-
 src/ext2.ml      | 18 +++++++++++++++++-
 src/prepare.ml   |  3 ++-
 src/supermin.ml  |  9 +++++++--
 src/supermin.pod | 11 +++++++++++
 6 files changed, 89 insertions(+), 13 deletions(-)

diff --git a/src/build.ml b/src/build.ml
index fb2e6d3..4675454 100644
--- a/src/build.ml
+++ b/src/build.ml
@@ -59,7 +59,8 @@ and string_of_file_content = function
 
 let rec build debug
     (copy_kernel, dtb_wildcard, format, host_cpu,
-     packager_config, tmpdir, use_installed, size)
+     packager_config, tmpdir, use_installed, size,
+     include_packagelist)
     inputs outputdir =
   if debug >= 1 then
     printf "supermin: build: %s\n%!" (String.concat " " inputs);
@@ -101,14 +102,22 @@ let rec build debug
     let packages = package_set_of_list packages in
     get_all_requires packages in
 
+  (* Get the list of packages only if we need to, i.e. when creating
+   * /packagelist in the appliance, when printing all the packages
+   * for debug, or in both cases.
+   *)
+  let pretty_packages =
+    if include_packagelist || debug >= 2 then (
+      let pkg_names = PackageSet.elements packages in
+      let pkg_names = List.map ph.ph_package_to_string pkg_names in
+      List.sort compare pkg_names
+    ) else [] in
+
   if debug >= 1 then (
     printf "supermin: build: %d packages, including dependencies\n%!"
       (PackageSet.cardinal packages);
     if debug >= 2 then (
-      let pkg_names = PackageSet.elements packages in
-      let pkg_names = List.map ph.ph_package_to_string pkg_names in
-      let pkg_names = List.sort compare pkg_names in
-      List.iter (printf "  - %s\n") pkg_names;
+      List.iter (printf "  - %s\n") pretty_packages;
       flush Pervasives.stdout
     )
   );
@@ -197,11 +206,21 @@ let rec build debug
     )
   );
 
+  (* Create a temporary file for packagelist, if requested. *)
+  let packagelist_file =
+    if include_packagelist then (
+      let filename, chan = Filename.open_temp_file "packagelist." "" in
+      List.iter (fprintf chan "%s\n") pretty_packages;
+      flush chan;
+      close_out chan;
+      Some filename
+    ) else None in
+
   (* Depending on the format, we build the appliance in different ways. *)
-  match format with
+  (match format with
   | Chroot ->
     (* chroot doesn't need an external kernel or initrd *)
-    Chroot.build_chroot debug files outputdir
+    Chroot.build_chroot debug files outputdir packagelist_file
 
   | Ext2 ->
     let kernel = outputdir // "kernel"
@@ -210,8 +229,15 @@ let rec build debug
     and initrd = outputdir // "initrd" in
     let kernel_version, modpath =
       Kernel.build_kernel debug host_cpu dtb_wildcard copy_kernel kernel dtb in
-    Ext2.build_ext2 debug basedir files modpath kernel_version appliance size;
+    Ext2.build_ext2 debug basedir files modpath kernel_version appliance size
+      packagelist_file;
     Ext2_initrd.build_initrd debug tmpdir modpath initrd
+  );
+
+  (match packagelist_file with
+  | None -> ()
+  | Some filename -> Sys.remove filename
+  )
 
 and read_appliance debug basedir appliance = function
   | [] -> appliance
diff --git a/src/chroot.ml b/src/chroot.ml
index b9c1dc2..346c24b 100644
--- a/src/chroot.ml
+++ b/src/chroot.ml
@@ -22,7 +22,7 @@ open Printf
 open Utils
 open Package_handler
 
-let build_chroot debug files outputdir =
+let build_chroot debug files outputdir packagelist_file =
   let do_copy src dest =
     if debug >= 2 then printf "supermin: chroot: copy %s\n%!" dest;
     let cmd = sprintf "cp -p %s %s" (quote src) (quote dest) in
@@ -69,6 +69,23 @@ let build_chroot debug files outputdir =
       with Unix_error _ -> ()
   ) files;
 
+  (* Add packagelist file, if requested. *)
+  (match packagelist_file with
+  | None -> ()
+  | Some filename ->
+    if debug >= 1 then
+      printf "supermin: chroot: creating /packagelist\n%!";
+
+    let opath = outputdir // "packagelist" in
+
+    do_copy filename opath;
+    (* Change the permissions of the file to be sure it is readable
+     * by everyone.  Unfortunately we cannot change the ownership,
+     * as non-root users cannot give away files to other users.
+     *)
+    chmod opath 0o644
+  );
+
   (* Second pass: fix up directory permissions in reverse. *)
   let dirs = filter_map (
     fun file ->
diff --git a/src/ext2.ml b/src/ext2.ml
index 79539a3..6348c29 100644
--- a/src/ext2.ml
+++ b/src/ext2.ml
@@ -34,7 +34,8 @@ open Package_handler
  *)
 let default_appliance_size = 4L *^ 1024L *^ 1024L *^ 1024L
 
-let build_ext2 debug basedir files modpath kernel_version appliance size =
+let build_ext2 debug basedir files modpath kernel_version appliance size
+    packagelist_file =
   if debug >= 1 then
     printf "supermin: ext2: creating empty ext2 filesystem '%s'\n%!" appliance;
 
@@ -74,6 +75,21 @@ let build_ext2 debug basedir files modpath kernel_version appliance size =
       ext2fs_copy_file_from_host fs src file.ft_path
   ) files;
 
+  (* Add packagelist file, if requested. *)
+  (match packagelist_file with
+  | None -> ()
+  | Some filename ->
+    if debug >= 1 then
+      printf "supermin: ext2: creating /packagelist\n%!";
+
+    ext2fs_copy_file_from_host fs filename "/packagelist";
+    (* Change the permissions and ownership of the file, to be sure
+     * it is root-owned, and readable by everyone.
+     *)
+    ext2fs_chmod fs "/packagelist" 0o644;
+    ext2fs_chown fs "/packagelist" 0 0
+  );
+
   if debug >= 1 then
     printf "supermin: ext2: copying kernel modules\n%!";
 
diff --git a/src/prepare.ml b/src/prepare.ml
index 7e522e9..8193f36 100644
--- a/src/prepare.ml
+++ b/src/prepare.ml
@@ -22,7 +22,8 @@ open Package_handler
 open Utils
 
 let prepare debug (copy_kernel, dtb_wildcard, format, host_cpu,
-             packager_config, tmpdir, use_installed, size)
+             packager_config, tmpdir, use_installed, size,
+             include_packagelist)
     inputs outputdir =
   if debug >= 1 then
     printf "supermin: prepare: %s\n%!" (String.concat " " inputs);
diff --git a/src/supermin.ml b/src/supermin.ml
index 3070b6b..bbb1dba 100644
--- a/src/supermin.ml
+++ b/src/supermin.ml
@@ -95,6 +95,7 @@ let main () =
     let packager_config = ref "" in
     let use_installed = ref false in
     let size = ref None in
+    let include_packagelist = ref false in
 
     let set_debug () = incr debug in
 
@@ -140,6 +141,8 @@ let main () =
       "--format",  Arg.String set_format,     ditto;
       "--host-cpu", Arg.Set_string host_cpu,  "ARCH Set host CPU architecture";
       "--if-newer", Arg.Set if_newer,             " Only build if needed";
+      "--include-packagelist", Arg.Set include_packagelist,
+                                              " Add a file with the list of packages";
       "--list-drivers", Arg.Unit display_drivers, " Display list of drivers and exit";
       "--lock",    Arg.Set_string lockfile,   "LOCKFILE Use a lock file";
       "--names",   Arg.Unit error_supermin_5, " Give an error for people needing supermin 4";
@@ -170,6 +173,7 @@ let main () =
       match !packager_config with "" -> None | s -> Some s in
     let use_installed = !use_installed in
     let size = !size in
+    let include_packagelist = !include_packagelist in
 
     let format =
       match mode, !format with
@@ -194,7 +198,8 @@ let main () =
 
     debug, mode, if_newer, inputs, lockfile, outputdir,
     (copy_kernel, dtb_wildcard, format, host_cpu,
-     packager_config, tmpdir, use_installed, size) in
+     packager_config, tmpdir, use_installed, size,
+     include_packagelist) in
 
   if debug >= 1 then printf "supermin: version: %s\n" Config.package_version;
 
@@ -202,7 +207,7 @@ let main () =
    * This fails with an error if one could not be located.
    *)
   let () =
-    let (_, _, _, _, packager_config, tmpdir, _, _) = args in
+    let (_, _, _, _, packager_config, tmpdir, _, _, _) = args in
     let settings = {
       debug = debug;
       tmpdir = tmpdir;
diff --git a/src/supermin.pod b/src/supermin.pod
index 53d1b11..298247c 100644
--- a/src/supermin.pod
+++ b/src/supermin.pod
@@ -217,6 +217,17 @@ directory.
 
 See also I<--lock> below.
 
+=item B<"--include-packagelist>
+
+(I<--build> mode only)
+
+Add a F</packagelist> file inside the generated chroot or ext2
+filesystem, containing a sorted list of all the packages used to
+build the appliance.
+
+Mostly useful for debugging, as it makes it easier to find out e.g.
+which version of a package was copied in the appliance.
+
 =item B<--list-drivers>
 
 List the package manager drivers compiled into supermin, and whether
-- 
2.1.0




More information about the Libguestfs mailing list