resize: Add --machine-readable option for machine friendly output.
authorRichard W.M. Jones <rjones@redhat.com>
Fri, 26 Aug 2011 21:34:49 +0000 (22:34 +0100)
committerRichard W.M. Jones <rjones@redhat.com>
Fri, 26 Aug 2011 21:34:49 +0000 (22:34 +0100)
resize/progress.ml
resize/progress.mli
resize/progress_c.c
resize/resize.ml
resize/virt-resize.pod

index 0018172..0ae72a3 100644 (file)
@@ -23,30 +23,32 @@ open Utils
 module G = Guestfs
 
 type progress_bar
-external progress_bar_init : unit -> progress_bar
+external progress_bar_init : machine_readable:bool -> progress_bar
   = "virt_resize_progress_bar_init"
 external progress_bar_reset : progress_bar -> unit
   = "virt_resize_progress_bar_reset"
 external progress_bar_set : progress_bar -> int64 -> int64 -> unit
   = "virt_resize_progress_bar_set"
 
-(* Initialize the C mini library. *)
-let bar = progress_bar_init ()
+let set_up_progress_bar ?(machine_readable = false) (g : Guestfs.guestfs) =
+  (* Initialize the C mini library. *)
+  let bar = progress_bar_init ~machine_readable in
 
-(* Reset the progress bar before every libguestfs function. *)
-let enter_callback g event evh buf array =
-  if event = G.EVENT_ENTER then
-    progress_bar_reset bar
+  (* Reset the progress bar before every libguestfs function. *)
+  let enter_callback g event evh buf array =
+    if event = G.EVENT_ENTER then
+      progress_bar_reset bar
+  in
 
-(* A progress event: move the progress bar. *)
-let progress_callback g event evh buf array =
-  if event = G.EVENT_PROGRESS && Array.length array >= 4 then (
-    let position = array.(2)
-    and total = array.(3) in
+  (* A progress event: move the progress bar. *)
+  let progress_callback g event evh buf array =
+    if event = G.EVENT_PROGRESS && Array.length array >= 4 then (
+      let position = array.(2)
+      and total = array.(3) in
 
-    progress_bar_set bar position total
-  )
+      progress_bar_set bar position total
+    )
+  in
 
-let set_up_progress_bar (g : Guestfs.guestfs) =
   ignore (g#set_event_callback enter_callback [G.EVENT_ENTER]);
   ignore (g#set_event_callback progress_callback [G.EVENT_PROGRESS])
index 31deb09..cd20e21 100644 (file)
@@ -16,4 +16,4 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *)
 
-val set_up_progress_bar : Guestfs.guestfs -> unit
+val set_up_progress_bar : ?machine_readable:bool -> Guestfs.guestfs -> unit
index dddf787..52e653b 100644 (file)
@@ -53,18 +53,22 @@ static struct custom_operations progress_bar_custom_operations = {
 };
 
 value
-virt_resize_progress_bar_init (value unitv)
+virt_resize_progress_bar_init (value machine_readablev)
 {
-  CAMLparam1 (unitv);
+  CAMLparam1 (machine_readablev);
   CAMLlocal1 (barv);
   struct progress_bar *bar;
+  int machine_readable = Bool_val (machine_readablev);
+  unsigned flags = 0;
 
   /* XXX Have to do this to get nl_langinfo to work properly.  However
    * we should really only call this from main.
    */
   setlocale (LC_ALL, "");
 
-  bar = progress_bar_init (0);
+  if (machine_readable)
+    flags |= PROGRESS_BAR_MACHINE_READABLE;
+  bar = progress_bar_init (flags);
   if (bar == NULL)
     caml_raise_out_of_memory ();
 
index d4455eb..1bd9632 100644 (file)
@@ -30,7 +30,7 @@ let prog = Filename.basename Sys.executable_name
 
 let infile, outfile, copy_boot_loader, debug, deletes, dryrun,
   expand, expand_content, extra_partition, format, ignores,
-  lv_expands, ntfsresize_force, output_format,
+  lv_expands, machine_readable, ntfsresize_force, output_format,
   quiet, resizes, resizes_force, shrink =
   let display_version () =
     let g = new G.guestfs () in
@@ -57,6 +57,7 @@ let infile, outfile, copy_boot_loader, debug, deletes, dryrun,
   let format = ref "" in
   let ignores = ref [] in
   let lv_expands = ref [] in
+  let machine_readable = ref false in
   let ntfsresize_force = ref false in
   let output_format = ref "" in
   let quiet = ref false in
@@ -83,6 +84,7 @@ let infile, outfile, copy_boot_loader, debug, deletes, dryrun,
     "--LV-expand", Arg.String (add lv_expands), "lv -\"-";
     "--lvexpand", Arg.String (add lv_expands), "lv -\"-";
     "--LVexpand", Arg.String (add lv_expands), "lv -\"-";
+    "--machine-readable", Arg.Set machine_readable, " Make output machine readable";
     "-n",        Arg.Set dryrun,            " Don't perform changes";
     "--dryrun",  Arg.Set dryrun,            " -\"-";
     "--dry-run", Arg.Set dryrun,            " -\"-";
@@ -125,6 +127,7 @@ read the man page virt-resize(1).
   let format = match !format with "" -> None | str -> Some str in
   let ignores = List.rev !ignores in
   let lv_expands = List.rev !lv_expands in
+  let machine_readable = !machine_readable in
   let ntfsresize_force = !ntfsresize_force in
   let output_format = match !output_format with "" -> None | str -> Some str in
   let quiet = !quiet in
@@ -132,6 +135,25 @@ read the man page virt-resize(1).
   let resizes_force = List.rev !resizes_force in
   let shrink = match !shrink with "" -> None | str -> Some str in
 
+  (* No arguments and machine-readable mode?  Print out some facts
+   * about what this binary supports.  We only need to print out new
+   * things added since this option, or things which depend on features
+   * of the appliance.
+   *)
+  if !disks = [] && machine_readable then (
+    printf "virt-resize\n";
+    printf "ntfsresize-force\n";
+    printf "32bitok\n";
+    let g = new G.guestfs () in
+    g#add_drive_opts "/dev/null";
+    g#launch ();
+    if feature_available g [| "ntfsprogs"; "ntfs3g" |] then
+      printf "ntfs\n";
+    if feature_available g [| "btrfs" |] then
+      printf "btrfs\n";
+    exit 0
+  );
+
   (* Verify we got exactly 2 disks. *)
   let infile, outfile =
     match List.rev !disks with
@@ -141,7 +163,7 @@ read the man page virt-resize(1).
 
   infile, outfile, copy_boot_loader, debug, deletes, dryrun,
   expand, expand_content, extra_partition, format, ignores,
-  lv_expands, ntfsresize_force, output_format,
+  lv_expands, machine_readable, ntfsresize_force, output_format,
   quiet, resizes, resizes_force, shrink
 
 (* Default to true, since NTFS and btrfs support are usually available. *)
@@ -154,7 +176,7 @@ let connect_both_disks () =
   if debug then g#set_trace true;
   g#add_drive_opts ?format ~readonly:true infile;
   g#add_drive_opts ?format:output_format ~readonly:false outfile;
-  if not quiet then Progress.set_up_progress_bar g;
+  if not quiet then Progress.set_up_progress_bar ~machine_readable g;
   g#launch ();
 
   (* Set the filter to /dev/sda, in case there are any rogue
@@ -910,7 +932,7 @@ let g =
     let g = new G.guestfs () in
     if debug then g#set_trace true;
     g#add_drive_opts ?format:output_format ~readonly:false outfile;
-    if not quiet then Progress.set_up_progress_bar g;
+    if not quiet then Progress.set_up_progress_bar ~machine_readable g;
     g#launch ();
 
     g (* Return new handle. *)
index 3a6af18..d03906c 100644 (file)
@@ -349,6 +349,12 @@ You can give this option multiple times, I<but> it doesn't
 make sense to do this unless the logical volumes you specify
 are all in different volume groups.
 
+=item B<--machine-readable>
+
+This option is used to make the output more machine friendly
+when being parsed by other programs.  See
+L</MACHINE READABLE OUTPUT> below.
+
 =item B<-n>
 
 =item B<--dryrun>
@@ -483,6 +489,58 @@ Display version number and exit.
 
 =back
 
+=head1 MACHINE READABLE OUTPUT
+
+The I<--machine-readable> option can be used to make the output more
+machine friendly, which is useful when calling virt-resize from other
+programs, GUIs etc.
+
+There are two ways to use this option.
+
+Firstly use the option on its own to query the capabilities of the
+virt-resize binary.  Typical output looks like this:
+
+ $ virt-resize --machine-readable
+ virt-resize
+ ntfsresize-force
+ 32bitok
+ ntfs
+ btrfs
+
+A list of features is printed, one per line, and the program exits
+with status 0.
+
+Secondly use the option in conjunction with other options to make the
+regular program output more machine friendly.
+
+At the moment this means:
+
+=over 4
+
+=item 1.
+
+Progress bar messages can be parsed from stdout by looking for this
+regular expression:
+
+ ^[0-9]+/[0-9]+$
+
+=item 2.
+
+The calling program should treat messages sent to stdout (except for
+progress bar messages) as status messages.  They can be logged and/or
+displayed to the user.
+
+=item 3.
+
+The calling program should treat messages sent to stderr as error
+messages.  In addition, virt-resize exits with a non-zero status code
+if there was a fatal error.
+
+=back
+
+Versions of the program prior to 1.13.9 did not support the
+I<--machine-readable> option and will return an error.
+
 =head1 NOTES
 
 =head2 "Partition 1 does not end on cylinder boundary."