[Libguestfs] [PATCH 2/6] dib: add --checksum

Pino Toscano ptoscano at redhat.com
Thu Feb 2 13:43:21 UTC 2017


Add a new option to create files with the MD5 and SHA512 checksums of
all the disk image types produced.

This was implemented in diskimage-builder upstream as
commit 2ea5feca5c4b64867ac327736edfb20408f8840e and
commit 22952b7ea0543bb4f446752976d1d8ba232b021a.
---
 dib/cmdline.ml   |  7 +++++-
 dib/cmdline.mli  |  1 +
 dib/dib.ml       | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
 dib/virt-dib.pod | 13 +++++++++++
 4 files changed, 85 insertions(+), 5 deletions(-)

diff --git a/dib/cmdline.ml b/dib/cmdline.ml
index 144e5a7..418dbbd 100644
--- a/dib/cmdline.ml
+++ b/dib/cmdline.ml
@@ -56,6 +56,7 @@ type cmdline = {
   arch : string;
   envvars : string list;
   docker_target : string option;
+  checksum : bool;
 }
 
 let parse_cmdline () =
@@ -158,6 +159,8 @@ read the man page virt-dib(1).
   let docker_target = ref None in
   let set_docker_target arg = docker_target := Some arg in
 
+  let checksum = ref false in
+
   let argspec = [
     [ S 'p'; L"element-path" ],           Getopt.String ("path", append_element_path),  s_"Add new a elements location";
     [ L"exclude-element" ], Getopt.String ("element", append_excluded_element),
@@ -177,6 +180,7 @@ read the man page virt-dib(1).
     [ L"extra-packages" ], Getopt.String ("pkg,...", append_extra_packages),
       s_"Add extra packages to install";
     [ L"docker-target" ], Getopt.String ("target", set_docker_target), s_"Repo and tag for docker";
+    [ L"checksum" ],   Getopt.Set checksum,          s_"Generate MD5 and SHA256 checksum files";
 
     [ L"ramdisk" ],    Getopt.Set is_ramdisk,        "Switch to a ramdisk build";
     [ L"ramdisk-element" ], Getopt.Set_string ("name", ramdisk_element), s_"Main element for building ramdisks";
@@ -234,6 +238,7 @@ read the man page virt-dib(1).
   let machine_readable = !machine_readable in
   let extra_packages = List.rev !extra_packages in
   let docker_target = !docker_target in
+  let checksum = !checksum in
 
   (* No elements and machine-readable mode?  Print some facts. *)
   if elements = [] && machine_readable then (
@@ -266,5 +271,5 @@ read the man page virt-dib(1).
     extra_packages = extra_packages; memsize = memsize; network = network;
     smp = smp; delete_on_failure = delete_on_failure;
     formats = formats; arch = arch; envvars = envvars;
-    docker_target = docker_target;
+    docker_target = docker_target; checksum = checksum;
   }
diff --git a/dib/cmdline.mli b/dib/cmdline.mli
index 79364fb..2e004a0 100644
--- a/dib/cmdline.mli
+++ b/dib/cmdline.mli
@@ -48,6 +48,7 @@ type cmdline = {
   arch : string;
   envvars : string list;
   docker_target : string option;
+  checksum : bool;
 }
 
 val parse_cmdline : unit -> cmdline
diff --git a/dib/dib.ml b/dib/dib.ml
index 9505c52..7f05870 100644
--- a/dib/dib.ml
+++ b/dib/dib.ml
@@ -27,6 +27,10 @@ open Printf
 
 module G = Guestfs
 
+let checksums = [ "md5"; "sha512" ]
+and tool_of_checksum csum =
+  csum ^ "sum"
+
 let exclude_elements elements = function
   | [] ->
     (* No elements to filter out, so just don't bother iterating through
@@ -68,9 +72,10 @@ let envvars_string l =
   String.concat "\n" l
 
 let prepare_external ~envvars ~dib_args ~dib_vars ~out_name ~root_label
-  ~rootfs_uuid ~image_cache ~arch ~network ~debug ~fs_type
+  ~rootfs_uuid ~image_cache ~arch ~network ~debug ~fs_type ~checksum
   destdir libdir hooksdir fakebindir all_elements element_paths =
   let network_string = if network then "" else "1" in
+  let checksum_string = if checksum then "1" else "" in
 
   let run_extra = sprintf "\
 #!/bin/bash
@@ -106,6 +111,7 @@ export TMPDIR=\"${TMP_MOUNT_PATH}/tmp\"
 export TMP_DIR=\"${TMPDIR}\"
 export DIB_DEBUG_TRACE=%d
 export FS_TYPE=%s
+export DIB_CHECKSUM=%s
 
 ENVIRONMENT_D_DIR=$target_dir/../environment.d
 
@@ -136,13 +142,15 @@ $target_dir/$script
     (String.concat ":" element_paths)
     (quote dib_vars)
     debug
-    fs_type in
+    fs_type
+    checksum_string in
   write_script (destdir // "run-part-extra.sh") run_extra
 
 let prepare_aux ~envvars ~dib_args ~dib_vars ~log_file ~out_name ~rootfs_uuid
   ~arch ~network ~root_label ~install_type ~debug ~extra_packages ~fs_type
-  destdir all_elements =
+  ~checksum destdir all_elements =
   let network_string = if network then "" else "1" in
+  let checksum_string = if checksum then "1" else "" in
 
   let script_run_part = sprintf "\
 #!/bin/bash
@@ -191,6 +199,7 @@ export DIB_ENV=%s
 export DIB_DEBUG_TRACE=%d
 export DIB_NO_TMPFS=1
 export FS_TYPE=%s
+export DIB_CHECKSUM=%s
 
 export TMP_BUILD_DIR=$mysysroot/tmp/aux
 export TMP_IMAGE_DIR=$mysysroot/tmp/aux
@@ -229,7 +238,8 @@ $target_dir/$script
     (String.concat " " (StringSet.elements all_elements))
     (quote dib_vars)
     debug
-    fs_type in
+    fs_type
+    checksum_string in
   write_script (destdir // "run-part.sh") script_run_part;
   let script_run_and_log = "\
 #!/bin/bash
@@ -487,6 +497,8 @@ let main () =
     require_tool "qemu-img";
   if List.mem "vhd" cmdline.formats then
     require_tool "vhd-util";
+  if cmdline.checksum then
+    List.iter (fun x -> require_tool (tool_of_checksum x)) checksums;
 
   let image_basename = Filename.basename cmdline.image_name in
   let image_basename_d = image_basename ^ ".d" in
@@ -600,6 +612,7 @@ let main () =
               ~install_type:cmdline.install_type ~debug
               ~extra_packages:cmdline.extra_packages
               ~fs_type:cmdline.fs_type
+              ~checksum:cmdline.checksum
               auxtmpdir all_elements;
 
   let delete_output_file = ref cmdline.delete_on_failure in
@@ -617,6 +630,7 @@ let main () =
                    ~root_label ~rootfs_uuid ~image_cache ~arch
                    ~network:cmdline.network ~debug
                    ~fs_type:cmdline.fs_type
+                   ~checksum:cmdline.checksum
                    tmpdir cmdline.basepath hookstmpdir
                    (auxtmpdir // "fake-bin")
                    all_elements cmdline.element_paths;
@@ -939,6 +953,53 @@ let main () =
     ) formats_img_nonraw;
   );
 
+  if not is_ramdisk_build && cmdline.checksum then (
+    let file_flags = [ Unix.O_WRONLY; Unix.O_CREAT; Unix.O_TRUNC; Unix.O_CLOEXEC; ] in
+    List.iter (
+      fun fmt ->
+        let fn = output_filename cmdline.image_name fmt in
+        message (f_"Generating checksums for %s") fn;
+        let pids =
+          List.map (
+            fun csum ->
+              let csum_fn = fn ^ "." ^ csum in
+              let csum_tool = tool_of_checksum csum in
+              let outfd = Unix.openfile csum_fn file_flags 0o640 in
+              let args = [| csum_tool; fn; |] in
+              Common_utils.debug "%s" (stringify_args (Array.to_list args));
+              let pid = Unix.create_process csum_tool args Unix.stdin
+                          outfd Unix.stderr in
+              (pid, csum_tool, outfd)
+          ) checksums in
+        let pids = ref pids in
+        while !pids <> [] do
+          let pid, stat = Unix.waitpid [] 0 in
+          let matching_pair, new_pids =
+            List.partition (
+              fun (p, tool, outfd) ->
+                pid = p
+            ) !pids in
+          if matching_pair <> [] then (
+            let matching_pair = List.hd matching_pair in
+            let _, csum_tool, outfd = matching_pair in
+            Unix.close outfd;
+            pids := new_pids;
+            match stat with
+            | Unix.WEXITED 0 -> ()
+            | Unix.WEXITED i ->
+              error (f_"external command '%s' exited with error %d")
+                csum_tool i
+            | Unix.WSIGNALED i ->
+              error (f_"external command '%s' killed by signal %d")
+                csum_tool i
+            | Unix.WSTOPPED i ->
+              error (f_"external command '%s' stopped by signal %d")
+                csum_tool i
+          );
+        done;
+    ) formats_img;
+  );
+
   message (f_"Done")
 
 let () = run_main_and_handle_errors main
diff --git a/dib/virt-dib.pod b/dib/virt-dib.pod
index eca3768..09251c7 100644
--- a/dib/virt-dib.pod
+++ b/dib/virt-dib.pod
@@ -72,6 +72,11 @@ Right now this option does nothing more than setting the C<ARCH>
 environment variable for the elements, and it's up to them to
 produce an image for the requested architecture.
 
+=item B<--checksum>
+
+Generate checksum files for the generated image.  The supported
+checksums are MD5, and SHA256.
+
 =item B<--colors>
 
 =item B<--colours>
@@ -320,6 +325,14 @@ A directory containing any files created by the elements, for example
 F<dib-manifests> directory (created by the C<manifests> element),
 ramdisks and kernels in ramdisk mode, and so on.
 
+=item F<$NAME.ext.checksum>
+
+When I<--checksum> is specified, there will be files for each
+supported checksum type; for example: F<$NAME.ext.md5>,
+F<$NAME.ext.sha256>, etc.
+
+Not applicable in ramdisk mode, see L</RAMDISK BUILDING>.
+
 =back
 
 =item B<--no-delete-on-failure>
-- 
2.9.3




More information about the Libguestfs mailing list