[Libguestfs] [PATCH v2 16/18] sparsify: Move copying-mode code to a separate file.

Richard W.M. Jones rjones at redhat.com
Tue Mar 11 23:13:59 UTC 2014


This is just code motion.
---
 po/POTFILES-ml       |   1 +
 sparsify/Makefile.am |   2 +
 sparsify/copying.ml  | 276 +++++++++++++++++++++++++++++++++++++++++++++++++++
 sparsify/sparsify.ml | 247 +--------------------------------------------
 4 files changed, 280 insertions(+), 246 deletions(-)
 create mode 100644 sparsify/copying.ml

diff --git a/po/POTFILES-ml b/po/POTFILES-ml
index ca29c25..fd2e886 100644
--- a/po/POTFILES-ml
+++ b/po/POTFILES-ml
@@ -32,6 +32,7 @@ mllib/uRI.ml
 mllib/urandom.ml
 resize/resize.ml
 sparsify/cmdline.ml
+sparsify/copying.ml
 sparsify/sparsify.ml
 sysprep/main.ml
 sysprep/sysprep_operation.ml
diff --git a/sparsify/Makefile.am b/sparsify/Makefile.am
index 3a6a011..2f32093 100644
--- a/sparsify/Makefile.am
+++ b/sparsify/Makefile.am
@@ -27,6 +27,7 @@ CLEANFILES = *~ *.cmi *.cmo *.cmx *.cmxa *.o virt-sparsify
 # Alphabetical order.
 SOURCES = \
 	cmdline.ml \
+	copying.ml \
 	sparsify.ml \
 	statvfs-c.c
 
@@ -44,6 +45,7 @@ deps = \
 	$(top_builddir)/mllib/config.cmx \
 	statvfs-c.o \
 	cmdline.cmx \
+	copying.cmx \
 	sparsify.cmx
 
 if HAVE_OCAMLOPT
diff --git a/sparsify/copying.ml b/sparsify/copying.ml
new file mode 100644
index 0000000..2765cf4
--- /dev/null
+++ b/sparsify/copying.ml
@@ -0,0 +1,276 @@
+(* virt-sparsify
+ * Copyright (C) 2011-2014 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+(* This is the traditional virt-sparsify mode: We copy from a
+ * source disk to a destination disk.
+ *)
+
+open Unix
+open Printf
+
+open Common_gettext.Gettext
+
+module G = Guestfs
+
+open Common_utils
+open Cmdline
+
+external statvfs_free_space : string -> int64 =
+  "virt_sparsify_statvfs_free_space"
+
+let run indisk outdisk check_tmpdir compress convert
+    format ignores machine_readable option quiet verbose trace zeroes =
+
+  (* Once we have got past argument parsing and start to create
+   * temporary files (including the potentially massive overlay file), we
+   * need to catch SIGINT (^C) and exit cleanly so the temporary file
+   * goes away.  Note that we don't delete temporaries in the signal
+   * handler.
+   *)
+  let do_sigint _ = exit 1 in
+  Sys.set_signal Sys.sigint (Sys.Signal_handle do_sigint);
+
+  (* What should the output format be?  If the user specified an
+   * input format, use that, else detect it from the source image.
+   *)
+  let output_format =
+    match convert with
+    | Some fmt -> fmt           (* user specified output conversion *)
+    | None ->
+      match format with
+      | Some fmt -> fmt    (* user specified input format, use that *)
+      | None ->
+        (* Don't know, so we must autodetect. *)
+        match (new G.guestfs ())#disk_format indisk  with
+        | "unknown" ->
+          error (f_"cannot detect input disk format; use the --format parameter")
+        | fmt -> fmt in
+
+  (* Compression is not supported by raw output (RHBZ#852194). *)
+  if output_format = "raw" && compress then
+    error (f_"--compress cannot be used for raw output.  Remove this option or use --convert qcow2.");
+
+  (* Get virtual size of the input disk. *)
+  let virtual_size = (new G.guestfs ())#disk_virtual_size indisk in
+  if not quiet then
+    printf (f_"Input disk virtual size = %Ld bytes (%s)\n%!")
+      virtual_size (human_size virtual_size);
+
+  (* Check there is enough space in $TMPDIR. *)
+  let tmpdir = Filename.temp_dir_name in
+
+  let print_warning () =
+    let free_space = statvfs_free_space tmpdir in
+    let extra_needed = virtual_size -^ free_space in
+    if extra_needed > 0L then (
+      eprintf (f_"\
+
+WARNING: There may not be enough free space on %s.
+You may need to set TMPDIR to point to a directory with more free space.
+
+Max needed: %s.  Free: %s.  May need another %s.
+
+Note this is an overestimate.  If the guest disk is full of data
+then not as much free space would be required.
+
+You can ignore this warning or change it to a hard failure using the
+--check-tmpdir=(ignore|continue|warn|fail) option.  See virt-sparsify(1).
+
+%!")
+        tmpdir (human_size virtual_size)
+        (human_size free_space) (human_size extra_needed);
+      true
+    ) else false
+  in
+
+  (match check_tmpdir with
+  | `Ignore -> ()
+  | `Continue -> ignore (print_warning ())
+  | `Warn ->
+    if print_warning () then (
+      eprintf "Press RETURN to continue or ^C to quit.\n%!";
+      ignore (read_line ())
+    );
+  | `Fail ->
+    if print_warning () then (
+      eprintf "Exiting because --check-tmpdir=fail was set.\n%!";
+      exit 2
+    )
+  );
+
+  if not quiet then
+    printf (f_"Create overlay file in %s to protect source disk ...\n%!") tmpdir;
+
+  (* Create the temporary overlay file. *)
+  let overlaydisk =
+    let tmp = Filename.temp_file "sparsify" ".qcow2" in
+    unlink_on_exit tmp;
+
+    (* Create it with the indisk as the backing file. *)
+    (* XXX Old code used to:
+     * - detect if compat=1.1 was supported
+     * - add lazy_refcounts option
+     *)
+    (new G.guestfs ())#disk_create
+      ~backingfile:indisk ?backingformat:format ~compat:"1.1"
+      tmp "qcow2" Int64.minus_one;
+
+    tmp in
+
+  if not quiet then
+    printf (f_"Examine source disk ...\n%!");
+
+  (* Connect to libguestfs. *)
+  let g =
+    let g = new G.guestfs () in
+    if trace then g#set_trace true;
+    if verbose then g#set_verbose true;
+
+    (* Note that the temporary overlay disk is always qcow2 format. *)
+    g#add_drive ~format:"qcow2" ~readonly:false ~cachemode:"unsafe" overlaydisk;
+
+    if not quiet then Progress.set_up_progress_bar ~machine_readable g;
+    g#launch ();
+
+    g in
+
+  (* Modify SIGINT handler (set first above) to cancel the handle. *)
+  let do_sigint _ =
+    g#user_cancel ();
+    exit 1
+  in
+  Sys.set_signal Sys.sigint (Sys.Signal_handle do_sigint);
+
+  (* Write zeroes for non-ignored filesystems that we are able to mount,
+   * and selected swap partitions.
+   *)
+  let filesystems = g#list_filesystems () in
+  let filesystems = List.map fst filesystems in
+  let filesystems = List.sort compare filesystems in
+
+  let is_ignored fs =
+    let fs = g#canonical_device_name fs in
+    List.exists (fun fs' -> fs = g#canonical_device_name fs') ignores
+  in
+
+  List.iter (
+    fun fs ->
+      if not (is_ignored fs) then (
+        if List.mem fs zeroes then (
+          if not quiet then
+            printf (f_"Zeroing %s ...\n%!") fs;
+
+          g#zero_device fs
+        ) else (
+          let mounted =
+            try g#mount fs "/"; true
+            with _ -> false in
+
+          if mounted then (
+            if not quiet then
+              printf (f_"Fill free space in %s with zero ...\n%!") fs;
+
+            g#zero_free_space "/"
+          ) else (
+            let is_linux_x86_swap =
+              (* Look for the signature for Linux swap on i386.
+               * Location depends on page size, so it definitely won't
+               * work on non-x86 architectures (eg. on PPC, page size is
+               * 64K).  Also this avoids hibernated swap space: in those,
+               * the signature is moved to a different location.
+               *)
+              try g#pread_device fs 10 4086L = "SWAPSPACE2"
+              with _ -> false in
+
+            if is_linux_x86_swap then (
+              if not quiet then
+                printf (f_"Clearing Linux swap on %s ...\n%!") fs;
+
+              (* Don't use mkswap.  Just preserve the header containing
+               * the label, UUID and swap format version (libguestfs
+               * mkswap may differ from guest's own).
+               *)
+              let header = g#pread_device fs 4096 0L in
+              g#zero_device fs;
+              if g#pwrite_device fs header 0L <> 4096 then
+                error (f_"pwrite: short write restoring swap partition header")
+            )
+          )
+        );
+
+        g#umount_all ()
+      )
+  ) filesystems;
+
+  (* Fill unused space in volume groups. *)
+  let vgs = g#vgs () in
+  let vgs = Array.to_list vgs in
+  let vgs = List.sort compare vgs in
+  List.iter (
+    fun vg ->
+      if not (List.mem vg ignores) then (
+        let lvname = string_random8 () in
+        let lvdev = "/dev/" ^ vg ^ "/" ^ lvname in
+
+        let created =
+          try g#lvcreate_free lvname vg 100; true
+          with _ -> false in
+
+        if created then (
+          if not quiet then
+            printf (f_"Fill free space in volgroup %s with zero ...\n%!") vg;
+
+          g#zero_device lvdev;
+          g#sync ();
+          g#lvremove lvdev
+        )
+      )
+  ) vgs;
+
+  (* Don't need libguestfs now. *)
+  g#shutdown ();
+  g#close ();
+
+  (* Modify SIGINT handler (set first above) to just exit. *)
+  let do_sigint _ = exit 1 in
+  Sys.set_signal Sys.sigint (Sys.Signal_handle do_sigint);
+
+  (* Now run qemu-img convert which copies the overlay to the
+   * destination and automatically does sparsification.
+   *)
+  if not quiet then
+    printf (f_"Copy to destination and make sparse ...\n%!");
+
+  let cmd =
+    sprintf "qemu-img convert -f qcow2 -O %s%s%s %s %s"
+      (Filename.quote output_format)
+      (if compress then " -c" else "")
+      (match option with
+      | None -> ""
+      | Some option -> " -o " ^ Filename.quote option)
+      (Filename.quote overlaydisk) (Filename.quote outdisk) in
+  if verbose then
+    printf "%s\n%!" cmd;
+  if Sys.command cmd <> 0 then
+    error (f_"external command failed: %s") cmd;
+
+  (* Finished. *)
+  if not quiet then (
+    print_newline ();
+    wrap (s_"Sparsify operation completed with no errors.  Before deleting the old disk, carefully check that the target disk boots and works correctly.\n");
+  )
diff --git a/sparsify/sparsify.ml b/sparsify/sparsify.ml
index 0091d95..faefb23 100644
--- a/sparsify/sparsify.ml
+++ b/sparsify/sparsify.ml
@@ -26,9 +26,6 @@ module G = Guestfs
 open Common_utils
 open Cmdline
 
-external statvfs_free_space : string -> int64 =
-  "virt_sparsify_statvfs_free_space"
-
 let () = Random.self_init ()
 
 let rec main () =
@@ -38,255 +35,13 @@ let rec main () =
 
   (match mode with
   | Mode_copying (outdisk, check_tmpdir, compress, convert, option) ->
-    copying indisk outdisk check_tmpdir compress convert
+    Copying.run indisk outdisk check_tmpdir compress convert
       format ignores machine_readable option quiet verbose trace zeroes
   );
 
   if debug_gc then
     Gc.compact ()
 
-and copying indisk outdisk check_tmpdir compress convert
-    format ignores machine_readable option quiet verbose trace zeroes =
-
-  (* Once we have got past argument parsing and start to create
-   * temporary files (including the potentially massive overlay file), we
-   * need to catch SIGINT (^C) and exit cleanly so the temporary file
-   * goes away.  Note that we don't delete temporaries in the signal
-   * handler.
-   *)
-  let do_sigint _ = exit 1 in
-  Sys.set_signal Sys.sigint (Sys.Signal_handle do_sigint);
-
-  (* What should the output format be?  If the user specified an
-   * input format, use that, else detect it from the source image.
-   *)
-  let output_format =
-    match convert with
-    | Some fmt -> fmt           (* user specified output conversion *)
-    | None ->
-      match format with
-      | Some fmt -> fmt    (* user specified input format, use that *)
-      | None ->
-        (* Don't know, so we must autodetect. *)
-        match (new G.guestfs ())#disk_format indisk  with
-        | "unknown" ->
-          error (f_"cannot detect input disk format; use the --format parameter")
-        | fmt -> fmt in
-
-  (* Compression is not supported by raw output (RHBZ#852194). *)
-  if output_format = "raw" && compress then
-    error (f_"--compress cannot be used for raw output.  Remove this option or use --convert qcow2.");
-
-  (* Get virtual size of the input disk. *)
-  let virtual_size = (new G.guestfs ())#disk_virtual_size indisk in
-  if not quiet then
-    printf (f_"Input disk virtual size = %Ld bytes (%s)\n%!")
-      virtual_size (human_size virtual_size);
-
-  (* Check there is enough space in $TMPDIR. *)
-  let tmpdir = Filename.temp_dir_name in
-
-  let print_warning () =
-    let free_space = statvfs_free_space tmpdir in
-    let extra_needed = virtual_size -^ free_space in
-    if extra_needed > 0L then (
-      eprintf (f_"\
-
-WARNING: There may not be enough free space on %s.
-You may need to set TMPDIR to point to a directory with more free space.
-
-Max needed: %s.  Free: %s.  May need another %s.
-
-Note this is an overestimate.  If the guest disk is full of data
-then not as much free space would be required.
-
-You can ignore this warning or change it to a hard failure using the
---check-tmpdir=(ignore|continue|warn|fail) option.  See virt-sparsify(1).
-
-%!")
-        tmpdir (human_size virtual_size)
-        (human_size free_space) (human_size extra_needed);
-      true
-    ) else false
-  in
-
-  (match check_tmpdir with
-  | `Ignore -> ()
-  | `Continue -> ignore (print_warning ())
-  | `Warn ->
-    if print_warning () then (
-      eprintf "Press RETURN to continue or ^C to quit.\n%!";
-      ignore (read_line ())
-    );
-  | `Fail ->
-    if print_warning () then (
-      eprintf "Exiting because --check-tmpdir=fail was set.\n%!";
-      exit 2
-    )
-  );
-
-  if not quiet then
-    printf (f_"Create overlay file in %s to protect source disk ...\n%!") tmpdir;
-
-  (* Create the temporary overlay file. *)
-  let overlaydisk =
-    let tmp = Filename.temp_file "sparsify" ".qcow2" in
-    unlink_on_exit tmp;
-
-    (* Create it with the indisk as the backing file. *)
-    (* XXX Old code used to:
-     * - detect if compat=1.1 was supported
-     * - add lazy_refcounts option
-     *)
-    (new G.guestfs ())#disk_create
-      ~backingfile:indisk ?backingformat:format ~compat:"1.1"
-      tmp "qcow2" Int64.minus_one;
-
-    tmp in
-
-  if not quiet then
-    printf (f_"Examine source disk ...\n%!");
-
-  (* Connect to libguestfs. *)
-  let g =
-    let g = new G.guestfs () in
-    if trace then g#set_trace true;
-    if verbose then g#set_verbose true;
-
-    (* Note that the temporary overlay disk is always qcow2 format. *)
-    g#add_drive ~format:"qcow2" ~readonly:false ~cachemode:"unsafe" overlaydisk;
-
-    if not quiet then Progress.set_up_progress_bar ~machine_readable g;
-    g#launch ();
-
-    g in
-
-  (* Modify SIGINT handler (set first above) to cancel the handle. *)
-  let do_sigint _ =
-    g#user_cancel ();
-    exit 1
-  in
-  Sys.set_signal Sys.sigint (Sys.Signal_handle do_sigint);
-
-  (* Write zeroes for non-ignored filesystems that we are able to mount,
-   * and selected swap partitions.
-   *)
-  let filesystems = g#list_filesystems () in
-  let filesystems = List.map fst filesystems in
-  let filesystems = List.sort compare filesystems in
-
-  let is_ignored fs =
-    let fs = g#canonical_device_name fs in
-    List.exists (fun fs' -> fs = g#canonical_device_name fs') ignores
-  in
-
-  List.iter (
-    fun fs ->
-      if not (is_ignored fs) then (
-        if List.mem fs zeroes then (
-          if not quiet then
-            printf (f_"Zeroing %s ...\n%!") fs;
-
-          g#zero_device fs
-        ) else (
-          let mounted =
-            try g#mount fs "/"; true
-            with _ -> false in
-
-          if mounted then (
-            if not quiet then
-              printf (f_"Fill free space in %s with zero ...\n%!") fs;
-
-            g#zero_free_space "/"
-          ) else (
-            let is_linux_x86_swap =
-              (* Look for the signature for Linux swap on i386.
-               * Location depends on page size, so it definitely won't
-               * work on non-x86 architectures (eg. on PPC, page size is
-               * 64K).  Also this avoids hibernated swap space: in those,
-               * the signature is moved to a different location.
-               *)
-              try g#pread_device fs 10 4086L = "SWAPSPACE2"
-              with _ -> false in
-
-            if is_linux_x86_swap then (
-              if not quiet then
-                printf (f_"Clearing Linux swap on %s ...\n%!") fs;
-
-              (* Don't use mkswap.  Just preserve the header containing
-               * the label, UUID and swap format version (libguestfs
-               * mkswap may differ from guest's own).
-               *)
-              let header = g#pread_device fs 4096 0L in
-              g#zero_device fs;
-              if g#pwrite_device fs header 0L <> 4096 then
-                error (f_"pwrite: short write restoring swap partition header")
-            )
-          )
-        );
-
-        g#umount_all ()
-      )
-  ) filesystems;
-
-  (* Fill unused space in volume groups. *)
-  let vgs = g#vgs () in
-  let vgs = Array.to_list vgs in
-  let vgs = List.sort compare vgs in
-  List.iter (
-    fun vg ->
-      if not (List.mem vg ignores) then (
-        let lvname = string_random8 () in
-        let lvdev = "/dev/" ^ vg ^ "/" ^ lvname in
-
-        let created =
-          try g#lvcreate_free lvname vg 100; true
-          with _ -> false in
-
-        if created then (
-          if not quiet then
-            printf (f_"Fill free space in volgroup %s with zero ...\n%!") vg;
-
-          g#zero_device lvdev;
-          g#sync ();
-          g#lvremove lvdev
-        )
-      )
-  ) vgs;
-
-  (* Don't need libguestfs now. *)
-  g#shutdown ();
-  g#close ();
-
-  (* Modify SIGINT handler (set first above) to just exit. *)
-  let do_sigint _ = exit 1 in
-  Sys.set_signal Sys.sigint (Sys.Signal_handle do_sigint);
-
-  (* Now run qemu-img convert which copies the overlay to the
-   * destination and automatically does sparsification.
-   *)
-  if not quiet then
-    printf (f_"Copy to destination and make sparse ...\n%!");
-
-  let cmd =
-    sprintf "qemu-img convert -f qcow2 -O %s%s%s %s %s"
-      (Filename.quote output_format)
-      (if compress then " -c" else "")
-      (match option with
-      | None -> ""
-      | Some option -> " -o " ^ Filename.quote option)
-      (Filename.quote overlaydisk) (Filename.quote outdisk) in
-  if verbose then
-    printf "%s\n%!" cmd;
-  if Sys.command cmd <> 0 then
-    error (f_"external command failed: %s") cmd;
-
-  (* Finished. *)
-  if not quiet then (
-    print_newline ();
-    wrap (s_"Sparsify operation completed with no errors.  Before deleting the old disk, carefully check that the target disk boots and works correctly.\n");
-  )
-
 let () =
   try main ()
   with
-- 
1.8.5.3




More information about the Libguestfs mailing list