From 09a7545649e6cac0de2c4421cb64b659164174ee Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Fri, 26 Aug 2011 22:34:49 +0100 Subject: [PATCH] resize: Add --machine-readable option for machine friendly output. --- resize/progress.ml | 32 +++++++++++++++------------- resize/progress.mli | 2 +- resize/progress_c.c | 10 ++++++--- resize/resize.ml | 30 ++++++++++++++++++++++---- resize/virt-resize.pod | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 109 insertions(+), 23 deletions(-) diff --git a/resize/progress.ml b/resize/progress.ml index 0018172..0ae72a3 100644 --- a/resize/progress.ml +++ b/resize/progress.ml @@ -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]) diff --git a/resize/progress.mli b/resize/progress.mli index 31deb09..cd20e21 100644 --- a/resize/progress.mli +++ b/resize/progress.mli @@ -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 diff --git a/resize/progress_c.c b/resize/progress_c.c index dddf787..52e653b 100644 --- a/resize/progress_c.c +++ b/resize/progress_c.c @@ -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 (); diff --git a/resize/resize.ml b/resize/resize.ml index d4455eb..1bd9632 100644 --- a/resize/resize.ml +++ b/resize/resize.ml @@ -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. *) diff --git a/resize/virt-resize.pod b/resize/virt-resize.pod index 3a6af18..d03906c 100644 --- a/resize/virt-resize.pod +++ b/resize/virt-resize.pod @@ -349,6 +349,12 @@ You can give this option multiple times, I 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 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." -- 1.8.3.1