psss / rpms / libguestfs

Forked from rpms/libguestfs 5 years ago
Clone
Blob Blame History Raw
From 1745a756c962ec90a6418203098666bb5823ce3b Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 7 Jan 2014 17:32:04 +0000
Subject: [PATCH] builder: Fix handling of --size parameter.

It now matches the documentation:

  "Select the size of the output disk, [...]

  Virt-builder will resize filesystems inside the disk image
  automatically.

  If the size is not specified, then one of two things happens.  If
  the output is a file, then the size is the same as the template.  If
  the output is a device, partition, etc then the size of that device
  is used."

This also adds checks to make sure that users don't try to shrink a
disk (which is not possible), and they don't try to resize larger than
the output block device.

(cherry picked from commit 06f7bea14883c4903c58077757179341c0e1471a)
---
 builder/builder.ml | 43 ++++++++++++++++++++++++++++++++++---------
 1 file changed, 34 insertions(+), 9 deletions(-)

diff --git a/builder/builder.ml b/builder/builder.ml
index 1cd007f..0c1f1e0 100644
--- a/builder/builder.ml
+++ b/builder/builder.ml
@@ -263,9 +263,6 @@ let main () =
       format_tag @ compression_tag in
 
   (* Planner: Goal. *)
-  let output_size =
-    let { Index_parser.size = default_size } = entry in
-    match size with None -> default_size | Some size -> size in
   let output_filename, output_format =
     match output, format with
     | None, None -> sprintf "%s.img" arg, "raw"
@@ -273,18 +270,46 @@ let main () =
     | None, Some format -> sprintf "%s.%s" arg format, format
     | Some output, None -> output, "raw"
     | Some output, Some format -> output, format in
-  let output_is_block_dev = is_block_device output_filename in
-
-  if output_is_block_dev && size <> None then (
-    eprintf (f_"%s: you cannot use --size option with block devices\n") prog;
-    exit 1
-  );
 
   if is_char_device output_filename then (
     eprintf (f_"%s: cannot output to a character device or /dev/null\n") prog;
     exit 1
   );
 
+  let blockdev_getsize64 dev =
+    let cmd = sprintf "blockdev --getsize64 %s" (quote dev) in
+    let lines = external_command ~prog cmd in
+    assert (List.length lines >= 1);
+    Int64.of_string (List.hd lines)
+  in
+  let output_is_block_dev, blockdev_size =
+    let b = is_block_device output_filename in
+    let sz = if b then blockdev_getsize64 output_filename else 0L in
+    b, sz in
+
+  let output_size =
+    let { Index_parser.size = original_image_size } = entry in
+
+    let size =
+      match size with
+      | Some size -> size
+      (* --size parameter missing, output to file: use original image size *)
+      | None when not output_is_block_dev -> original_image_size
+      (* --size parameter missing, block device: use block device size *)
+      | None -> blockdev_size in
+
+    if size < original_image_size then (
+      eprintf (f_"%s: images cannot be shrunk, the output size is too small for this image.  Requested size = %s, minimum size = %s\n")
+        prog (human_size size) (human_size original_image_size);
+      exit 1
+    )
+    else if output_is_block_dev && output_format = "raw" && size > blockdev_size then (
+      eprintf (f_"%s: output size is too large for this block device.  Requested size = %s, output block device = %s, output block device size = %s\n")
+        prog (human_size size) output_filename (human_size blockdev_size);
+      exit 1
+    );
+    size in
+
   let goal =
     (* MUST *)
     let goal_must = [
-- 
1.8.5.3