resize: Add --machine-readable option for machine friendly output.
[libguestfs.git] / resize / resize.ml
index 82fd765..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, 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,8 @@ 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
   let resizes = ref [] in
@@ -82,9 +84,11 @@ 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,            " -\"-";
+    "--ntfsresize-force", Arg.Set ntfsresize_force, " Force ntfsresize";
     "--output-format", Arg.Set_string format, "format Format of output disk";
     "-q",        Arg.Set quiet,             " Don't print the summary";
     "--quiet",   Arg.Set quiet,             " -\"-";
@@ -123,12 +127,33 @@ 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
   let resizes = List.rev !resizes in
   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
@@ -138,11 +163,12 @@ read the man page virt-resize(1).
 
   infile, outfile, copy_boot_loader, debug, deletes, dryrun,
   expand, expand_content, extra_partition, format, ignores,
-  lv_expands, output_format,
+  lv_expands, machine_readable, ntfsresize_force, output_format,
   quiet, resizes, resizes_force, shrink
 
-(* Default to true, since NTFS support is usually available. *)
+(* Default to true, since NTFS and btrfs support are usually available. *)
 let ntfs_available = ref true
+let btrfs_available = ref true
 
 (* Add in and out disks to the handle and launch. *)
 let connect_both_disks () =
@@ -150,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
@@ -160,6 +186,7 @@ let connect_both_disks () =
 
   (* Update features available in the daemon. *)
   ntfs_available := feature_available g [|"ntfsprogs"; "ntfs3g"|];
+  btrfs_available := feature_available g [|"btrfs"|];
 
   g
 
@@ -370,12 +397,14 @@ let lvs =
 (* These functions tell us if we know how to expand the content of
  * a particular partition or LV, and what method to use.
  *)
-type expand_content_method = PVResize | Resize2fs | NTFSResize
+type expand_content_method =
+  | PVResize | Resize2fs | NTFSResize | BtrfsFilesystemResize
 
 let string_of_expand_content_method = function
   | PVResize -> "pvresize"
   | Resize2fs -> "resize2fs"
   | NTFSResize -> "ntfsresize"
+  | BtrfsFilesystemResize -> "btrfs-filesystem-resize"
 
 let can_expand_content =
   if expand_content then
@@ -384,6 +413,7 @@ let can_expand_content =
     | ContentPV _ -> true
     | ContentFS (("ext2"|"ext3"|"ext4"), _) -> true
     | ContentFS (("ntfs"), _) when !ntfs_available -> true
+    | ContentFS (("btrfs"), _) when !btrfs_available -> true
     | ContentFS (_, _) -> false
   else
     fun _ -> false
@@ -395,6 +425,7 @@ let expand_content_method =
     | ContentPV _ -> PVResize
     | ContentFS (("ext2"|"ext3"|"ext4"), _) -> Resize2fs
     | ContentFS (("ntfs"), _) when !ntfs_available -> NTFSResize
+    | ContentFS (("btrfs"), _) when !btrfs_available -> BtrfsFilesystemResize
     | ContentFS (_, _) -> assert false
   else
     fun _ -> assert false
@@ -901,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. *)
@@ -916,7 +947,15 @@ let () =
       | Resize2fs ->
           g#e2fsck_f target;
           g#resize2fs target
-      | NTFSResize -> g#ntfsresize target
+      | NTFSResize -> g#ntfsresize_opts ~force:ntfsresize_force target
+      | BtrfsFilesystemResize ->
+          (* Complicated ...  Btrfs forces us to mount the filesystem
+           * in order to resize it.
+           *)
+          assert (Array.length (g#mounts ()) = 0);
+          g#mount_options "" target "/";
+          g#btrfs_filesystem_resize "/";
+          g#umount "/"
     in
 
     (* Expand partition content as required. *)