[Libguestfs] [PATCH v2] v2v: ova: Don't rely on qemu-img version, test "offset" and "size" features.

Richard W.M. Jones rjones at redhat.com
Mon Feb 6 20:21:05 UTC 2017


See:

https://www.redhat.com/archives/libguestfs/2017-February/msg00064.html
---
 v2v/input_ova.ml      |  5 ++---
 v2v/utils.ml          | 46 ++++++++++++++++++++++++++--------------------
 v2v/utils.mli         |  7 +++----
 v2v/v2v_unit_tests.ml |  7 +++++++
 4 files changed, 38 insertions(+), 27 deletions(-)

diff --git a/v2v/input_ova.ml b/v2v/input_ova.ml
index 3c11cd0..411e901 100644
--- a/v2v/input_ova.ml
+++ b/v2v/input_ova.ml
@@ -90,9 +90,8 @@ object
         match detect_file_type ova with
         | `Tar ->
           (* Normal ovas are tar file (not compressed). *)
-          let qmajor, qminor = qemu_img_version () in
-          if qmajor > 2 || (qmajor == 2 && qminor >= 8) then (
-            (* If QEMU is 2.8 or newer we don't have to extract everything.
+          if qemu_img_supports_offset_and_size () then (
+            (* In newer QEMU we don't have to extract everything.
              * We can access disks inside the tar archive directly.
              *)
             untar_metadata ova tmpdir;
diff --git a/v2v/utils.ml b/v2v/utils.ml
index 6a3074e..295134b 100644
--- a/v2v/utils.ml
+++ b/v2v/utils.ml
@@ -91,26 +91,32 @@ let du filename =
   | line::_ -> Int64.of_string line
   | [] -> invalid_arg filename
 
-let qemu_img_version () =
-  let lines = external_command "qemu-img --version" in
-  match lines with
-  | [] -> error (f_"'qemu-img --version' returned no output")
-  | line :: _ ->
-      let rex = Str.regexp
-        "qemu-img version \\([0-9]+\\)\\.\\([0-9]+\\)" in
-      if Str.string_match rex line 0 then (
-        try
-          int_of_string (Str.matched_group 1 line),
-          int_of_string (Str.matched_group 2 line)
-        with Failure _ ->
-          warning (f_"failed to parse qemu-img version(%S), assuming 0.9")
-            line;
-          0, 9
-      ) else (
-        warning (f_"failed to read qemu-img version(%S), assuming 0.9")
-          line;
-        0, 9
-      )
+let qemu_img_supports_offset_and_size () =
+  (* We actually attempt to create a qcow2 file with a raw backing
+   * file that has an offset and size.
+   *)
+  let tmp = Filename.temp_file "v2vqemuimgtst" ".img" in
+  Unix.truncate tmp 1024;
+
+  let json = [
+      "file", JSON.Dict [
+        "driver", JSON.String "raw";
+        "offset", JSON.Int 512;
+        "size", JSON.Int 512;
+        "file", JSON.Dict [
+          "filename", JSON.String tmp
+        ]
+      ]
+  ] in
+
+  let cmd =
+    sprintf "qemu-img info 'json:%s' >/dev/null%s"
+            (quote (JSON.string_of_doc ~fmt:JSON.Compact json))
+            (if verbose () then "" else " 2>&1") in
+  debug "%s" cmd;
+  let r = Sys.command cmd in
+  Unix.unlink tmp;
+  r = 0
 
 let find_file_in_tar tar filename =
   let lines = external_command (sprintf "tar tRvf %s" (Filename.quote tar)) in
diff --git a/v2v/utils.mli b/v2v/utils.mli
index eb47d03..b75baa7 100644
--- a/v2v/utils.mli
+++ b/v2v/utils.mli
@@ -51,10 +51,9 @@ val du : string -> int64
     This can raise either [Failure] or [Invalid_argument] in case
     of errors. *)
 
-val qemu_img_version : unit -> int * int
-(** Returns version of qemu-img as a tuple [(major, minor)].
-
-    In case of error [(0,9)] is returned. *)
+val qemu_img_supports_offset_and_size : unit -> bool
+(** Return true iff [qemu-img] supports the ["offset"] and ["size"]
+    parameters to open a subset of a file. *)
 
 val find_file_in_tar : string -> string -> int64 * int64
 (** [find_file_in_tar tar filename] looks up file in [tar] archive and returns
diff --git a/v2v/v2v_unit_tests.ml b/v2v/v2v_unit_tests.ml
index a89d8b0..1133d92 100644
--- a/v2v/v2v_unit_tests.ml
+++ b/v2v/v2v_unit_tests.ml
@@ -778,6 +778,12 @@ let test_shell_unquote ctx =
   assert_equal ~printer "i`" (Utils.shell_unquote "\"i\\`\"");
   assert_equal ~printer "j\"" (Utils.shell_unquote "\"j\\\"\"")
 
+let test_qemu_img_supports ctx =
+  (* No assertion here, we don't know if qemu-img supports the
+   * feature, so just run the code and make sure it doesn't crash.
+   *)
+  ignore (Utils.qemu_img_supports_offset_and_size ())
+
 (* Suites declaration. *)
 let suite =
   "virt-v2v" >:::
@@ -788,6 +794,7 @@ let suite =
       "Windows_virtio.virtio_iso_path_matches_guest_os" >::
         test_virtio_iso_path_matches_guest_os;
       "Utils.shell_unquote" >:: test_shell_unquote;
+      "Utils.qemu_img_supports" >:: test_qemu_img_supports;
     ]
 
 let () =
-- 
2.10.2




More information about the Libguestfs mailing list