X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=resize%2Fresize.ml;h=b4af80911c0a206bc7a0b758424f06d22273784a;hb=3f54bd02fcf540f9b4b6edc93f3b6b9c7ba136bd;hp=8e7057c6bde7e4d6b8d69dbe4a2037ae8e6a6a85;hpb=d31de200b82ef66d7e87b32dd5345c053997cc35;p=libguestfs.git diff --git a/resize/resize.ml b/resize/resize.ml index 8e7057c..b4af809 100644 --- a/resize/resize.ml +++ b/resize/resize.ml @@ -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 @@ -144,8 +166,9 @@ read the man page virt-resize(1). lv_expands, 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 () = @@ -163,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 @@ -215,7 +239,6 @@ let () = (* Build a data structure describing the source disk's partition layout. *) type partition = { p_name : string; (* Device name, like /dev/sda1. *) - p_size : int64; (* Current size of this partition. *) p_part : G.partition; (* Partition data from libguestfs. *) p_bootable : bool; (* Is it bootable? *) p_mbr_id : int option; (* MBR ID, if it has one. *) @@ -296,7 +319,7 @@ let partitions : partition list = with G.Error _ -> None in let typ = get_partition_content name in - { p_name = name; p_size = part.G.part_size; p_part = part; + { p_name = name; p_part = part; p_bootable = bootable; p_mbr_id = mbr_id; p_type = typ; p_operation = OpCopy; p_target_partnum = 0 } ) parts in @@ -312,11 +335,13 @@ let partitions : partition list = *) List.iter ( function - | { p_name = name; p_size = size; p_type = ContentPV pv_size } + | { p_name = name; p_part = { G.part_size = size }; + p_type = ContentPV pv_size } when size < pv_size -> error "%s: partition size %Ld < physical volume size %Ld" name size pv_size - | { p_name = name; p_size = size; p_type = ContentFS (_, fs_size) } + | { p_name = name; p_part = { G.part_size = size }; + p_type = ContentFS (_, fs_size) } when size < fs_size -> error "%s: partition size %Ld < filesystem size %Ld" name size fs_size @@ -373,12 +398,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 @@ -387,6 +414,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 @@ -398,6 +426,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 @@ -457,7 +486,7 @@ let () = *) let mark_partition_for_resize ~option ?(force = false) p newsize = let name = p.p_name in - let oldsize = p.p_size in + let oldsize = p.p_part.G.part_size in (match p.p_operation with | OpResize _ -> @@ -511,7 +540,7 @@ let () = let p = find_partition ~option dev in (* Parse the size field. *) - let oldsize = p.p_size in + let oldsize = p.p_part.G.part_size in let newsize = parse_size oldsize sizefield in if newsize <= 0L then @@ -543,7 +572,7 @@ let calculate_surplus () = fun total p -> let newsize = match p.p_operation with - | OpCopy | OpIgnore -> p.p_size + | OpCopy | OpIgnore -> p.p_part.G.part_size | OpDelete -> 0L | OpResize newsize -> newsize in total +^ newsize @@ -571,7 +600,7 @@ let () = let option = "--expand" in let p = find_partition ~option dev in - let oldsize = p.p_size in + let oldsize = p.p_part.G.part_size in mark_partition_for_resize ~option p (oldsize +^ surplus) ); (match shrink with @@ -582,7 +611,7 @@ let () = let option = "--shrink" in let p = find_partition ~option dev in - let oldsize = p.p_size in + let oldsize = p.p_part.G.part_size in mark_partition_for_resize ~option p (oldsize +^ surplus) ) ) @@ -625,7 +654,7 @@ let () = printf "Summary of changes:\n\n"; List.iter ( - fun ({ p_name = name; p_size = oldsize } as p) -> + fun ({ p_name = name; p_part = { G.part_size = oldsize }} as p) -> let text = match p.p_operation with | OpCopy -> @@ -785,7 +814,7 @@ let () = | OpDelete -> None (* do nothing *) | OpIgnore | OpCopy -> (* new partition, same size *) (* Size in sectors. *) - let size = (p.p_size +^ sectsize -^ 1L) /^ sectsize in + let size = (p.p_part.G.part_size +^ sectsize -^ 1L) /^ sectsize in Some (add_partition size) | OpResize newsize -> (* new partition, resized *) (* Size in sectors. *) @@ -855,7 +884,7 @@ let () = | ({ p_name = source; p_target_partnum = target_partnum; p_operation = (OpCopy | OpResize _) } as p) :: ps when target_partnum > 0 -> - let oldsize = p.p_size in + let oldsize = p.p_part.G.part_size in let newsize = match p.p_operation with OpResize s -> s | _ -> oldsize in @@ -920,6 +949,14 @@ let () = g#e2fsck_f target; g#resize2fs 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. *)