[Libguestfs] [PATCH v2 1/2] v2v: Abstract the target file so it could be a QEMU URI.

Richard W.M. Jones rjones at redhat.com
Fri Dec 8 08:39:34 UTC 2017


This complicated bit of refactoring abstracts the target file so it is
allowed to be either a filename or a QEMU URI.
---
 v2v/create_libvirt_xml.ml |  9 +++--
 v2v/output_glance.ml      | 10 ++++--
 v2v/output_libvirt.ml     |  5 +--
 v2v/output_local.ml       |  5 +--
 v2v/output_null.ml        |  2 +-
 v2v/output_qemu.ml        | 17 ++++++---
 v2v/output_rhv.ml         |  7 +++-
 v2v/output_vdsm.ml        |  6 +++-
 v2v/types.ml              |  9 +++--
 v2v/types.mli             |  6 +++-
 v2v/v2v.ml                | 90 ++++++++++++++++++++++++++++++-----------------
 11 files changed, 116 insertions(+), 50 deletions(-)

diff --git a/v2v/create_libvirt_xml.ml b/v2v/create_libvirt_xml.ml
index ecf0d14c5..c6b47538e 100644
--- a/v2v/create_libvirt_xml.ml
+++ b/v2v/create_libvirt_xml.ml
@@ -178,6 +178,11 @@ let create_libvirt_xml ?pool source target_buses guestcaps
     | BusSlotEmpty -> Comment (sprintf "%s slot %d is empty" bus_name i)
 
     | BusSlotTarget t ->
+       let target_file =
+         match t.target_file with
+         | TargetFile s -> s
+         | TargetURI _ -> assert false in
+
         e "disk" [
           "type", if pool = None then "file" else "volume";
           "device", "disk"
@@ -190,12 +195,12 @@ let create_libvirt_xml ?pool source target_buses guestcaps
           (match pool with
           | None ->
             e "source" [
-              "file", absolute_path t.target_file;
+              "file", absolute_path target_file;
             ] []
           | Some pool ->
             e "source" [
               "pool", pool;
-              "volume", Filename.basename t.target_file;
+              "volume", Filename.basename target_file;
             ] []
           );
           e "target" [
diff --git a/v2v/output_glance.ml b/v2v/output_glance.ml
index d00011eb5..6f9defc3e 100644
--- a/v2v/output_glance.ml
+++ b/v2v/output_glance.ml
@@ -63,8 +63,8 @@ object
     (* Write targets to a temporary local file - see above for reason. *)
     List.map (
       fun t ->
-        let target_file = tmpdir // t.target_overlay.ov_sd in
-        { t with target_file = target_file }
+        let target_file = TargetFile (tmpdir // t.target_overlay.ov_sd) in
+        { t with target_file }
     ) targets
 
   method create_metadata source targets _ guestcaps inspect target_firmware =
@@ -157,6 +157,12 @@ object
               fun (k, v) -> [ "--property"; sprintf "%s=%s" k v ]
             ) common_properties
           ) in
+
+        let target_file =
+          match target_file with
+          | TargetFile s -> s
+          | TargetURI _ -> assert false in
+
         let cmd = [ "glance"; "image-create"; "--name"; name;
                     "--disk-format=" ^ target_format;
                     "--container-format=bare"; "--file"; target_file;
diff --git a/v2v/output_libvirt.ml b/v2v/output_libvirt.ml
index 729f8b67a..ffa3e43c3 100644
--- a/v2v/output_libvirt.ml
+++ b/v2v/output_libvirt.ml
@@ -128,8 +128,9 @@ class output_libvirt oc output_pool = object
     List.map (
       fun t ->
         let target_file =
-          target_path // source.s_name ^ "-" ^ t.target_overlay.ov_sd in
-        { t with target_file = target_file }
+          TargetFile (target_path // source.s_name ^ "-" ^
+                      t.target_overlay.ov_sd) in
+        { t with target_file }
     ) targets
 
   method supported_firmware = [ TargetBIOS; TargetUEFI ]
diff --git a/v2v/output_local.ml b/v2v/output_local.ml
index 97ad8dddd..a6836be2f 100644
--- a/v2v/output_local.ml
+++ b/v2v/output_local.ml
@@ -34,8 +34,9 @@ class output_local dir = object
   method prepare_targets source targets =
     List.map (
       fun t ->
-        let target_file = dir // source.s_name ^ "-" ^ t.target_overlay.ov_sd in
-        { t with target_file = target_file }
+        let target_file =
+          TargetFile (dir // source.s_name ^ "-" ^ t.target_overlay.ov_sd) in
+        { t with target_file }
     ) targets
 
   method supported_firmware = [ TargetBIOS; TargetUEFI ]
diff --git a/v2v/output_null.ml b/v2v/output_null.ml
index d01f45654..65861a597 100644
--- a/v2v/output_null.ml
+++ b/v2v/output_null.ml
@@ -47,7 +47,7 @@ object
     List.map (
       fun t ->
         let target_file = tmpdir // t.target_overlay.ov_sd in
-        { t with target_file = target_file }
+        { t with target_file = TargetFile target_file }
     ) targets
 
   method create_metadata _ _ _ _ _ _ = ()
diff --git a/v2v/output_qemu.ml b/v2v/output_qemu.ml
index f61d698d6..f4c6b8b80 100644
--- a/v2v/output_qemu.ml
+++ b/v2v/output_qemu.ml
@@ -35,8 +35,9 @@ object
   method prepare_targets source targets =
     List.map (
       fun t ->
-        let target_file = dir // source.s_name ^ "-" ^ t.target_overlay.ov_sd in
-        { t with target_file = target_file }
+        let target_file =
+          TargetFile (dir // source.s_name ^ "-" ^ t.target_overlay.ov_sd) in
+        { t with target_file }
     ) targets
 
   method supported_firmware = [ TargetBIOS; TargetUEFI ]
@@ -122,7 +123,11 @@ object
     | BusSlotEmpty -> ()
 
     | BusSlotTarget t ->
-       arg_list "-drive" ["file=" ^ t.target_file; "format=" ^ t.target_format;
+       let target_file =
+         match t.target_file with
+         | TargetFile s -> s
+         | TargetURI _ -> assert false in
+       arg_list "-drive" ["file=" ^ target_file; "format=" ^ t.target_format;
                           "if=" ^ if_name; "index=" ^ string_of_int i;
                           "media=disk"]
 
@@ -141,7 +146,11 @@ object
     | BusSlotEmpty -> ()
 
     | BusSlotTarget t ->
-       arg_list "-drive" ["file=" ^ t.target_file; "format=" ^ t.target_format;
+       let target_file =
+         match t.target_file with
+         | TargetFile s -> s
+         | TargetURI _ -> assert false in
+       arg_list "-drive" ["file=" ^ target_file; "format=" ^ t.target_format;
                           "if=scsi"; "bus=0"; "unit=" ^ string_of_int i;
                           "media=disk"]
 
diff --git a/v2v/output_rhv.ml b/v2v/output_rhv.ml
index 2bcd988c1..58e084a5c 100644
--- a/v2v/output_rhv.ml
+++ b/v2v/output_rhv.ml
@@ -230,9 +230,10 @@ object
         fun ({ target_overlay = ov } as t, image_uuid, vol_uuid) ->
           let ov_sd = ov.ov_sd in
           let target_file = images_dir // image_uuid // vol_uuid in
+
           debug "RHV: will export %s to %s" ov_sd target_file;
 
-          { t with target_file = target_file }
+          { t with target_file = TargetFile target_file }
       ) (List.combine3 targets image_uuids vol_uuids) in
 
     (* Generate the .meta file associated with each volume. *)
@@ -241,6 +242,10 @@ object
         targets in
     List.iter (
       fun ({ target_file }, meta) ->
+        let target_file =
+          match target_file with
+          | TargetFile s -> s
+          | TargetURI _ -> assert false in
         let meta_filename = target_file ^ ".meta" in
         Changeuid.make_file changeuid_t meta_filename meta
     ) (List.combine targets metas);
diff --git a/v2v/output_vdsm.ml b/v2v/output_vdsm.ml
index d5911e80e..993261882 100644
--- a/v2v/output_vdsm.ml
+++ b/v2v/output_vdsm.ml
@@ -134,7 +134,7 @@ object
 
           debug "VDSM: will export %s to %s" ov_sd target_file;
 
-          { t with target_file = target_file }
+          { t with target_file = TargetFile target_file }
       ) (List.combine3 targets vdsm_params.image_uuids vdsm_params.vol_uuids) in
 
     (* Generate the .meta files associated with each volume. *)
@@ -143,6 +143,10 @@ object
         vdsm_params.image_uuids targets in
     List.iter (
       fun ({ target_file }, meta) ->
+        let target_file =
+          match target_file with
+          | TargetFile s -> s
+          | TargetURI _ -> assert false in
         let meta_filename = target_file ^ ".meta" in
         with_open_out meta_filename (fun chan -> output_string chan meta)
     ) (List.combine targets metas);
diff --git a/v2v/types.ml b/v2v/types.ml
index 1ffb09440..be86f1b3b 100644
--- a/v2v/types.ml
+++ b/v2v/types.ml
@@ -293,12 +293,15 @@ ov_source = %s
     ov.ov_source.s_qemu_uri
 
 type target = {
-  target_file : string;
+  target_file : target_file;
   target_format : string;
   target_estimated_size : int64 option;
   target_actual_size : int64 option;
   target_overlay : overlay;
 }
+and target_file =
+  | TargetFile of string
+  | TargetURI of string
 
 let string_of_target t =
   sprintf "\
@@ -308,7 +311,9 @@ target_estimated_size = %s
 target_overlay = %s
 target_overlay.ov_source = %s
 "
-    t.target_file
+    (match t.target_file with
+     | TargetFile s -> "[file] " ^ s
+     | TargetURI s -> "[qemu] " ^ s)
     t.target_format
     (match t.target_estimated_size with
     | None -> "None" | Some i -> Int64.to_string i)
diff --git a/v2v/types.mli b/v2v/types.mli
index 9e2f8ceb4..95d890638 100644
--- a/v2v/types.mli
+++ b/v2v/types.mli
@@ -189,7 +189,7 @@ val string_of_overlay : overlay -> string
 (** {2 Target disks} *)
 
 type target = {
-  target_file : string;      (** Destination file. *)
+  target_file : target_file; (** Destination file or QEMU URI. *)
   target_format : string;    (** Destination format (eg. -of option). *)
 
   (* Note that the estimate is filled in by core v2v.ml code before
@@ -203,6 +203,10 @@ type target = {
 }
 (** Target disk. *)
 
+and target_file =
+  | TargetFile of string     (** Target is a file. *)
+  | TargetURI of string      (** Target is a QEMU URI. *)
+
 val string_of_target : target -> string
 
 (** {2 Guest firmware} *)
diff --git a/v2v/v2v.ml b/v2v/v2v.ml
index 9edc080ff..94146b596 100644
--- a/v2v/v2v.ml
+++ b/v2v/v2v.ml
@@ -362,7 +362,7 @@ and init_targets cmdline output source overlays =
          * estimate_target_size will fill in the target_estimated_size field.
          * actual_target_size will fill in the target_actual_size field.
          *)
-        { target_file = ""; target_format = format;
+        { target_file = TargetFile ""; target_format = format;
           target_estimated_size = None;
           target_actual_size = None;
           target_overlay = ov }
@@ -665,15 +665,24 @@ and copy_targets cmdline targets input output =
   at_exit (fun () ->
     if !delete_target_on_exit then (
       List.iter (
-        fun t -> try unlink t.target_file with _ -> ()
+        fun t ->
+          match t.target_file with
+          | TargetURI _ -> ()
+          | TargetFile s -> try unlink s with _ -> ()
       ) targets
     )
   );
   let nr_disks = List.length targets in
   List.mapi (
     fun i t ->
-      message (f_"Copying disk %d/%d to %s (%s)")
-        (i+1) nr_disks t.target_file t.target_format;
+      (match t.target_file with
+       | TargetFile s ->
+          message (f_"Copying disk %d/%d to %s (%s)")
+                  (i+1) nr_disks s t.target_format;
+       | TargetURI s ->
+          message (f_"Copying disk %d/%d to qemu URI %s (%s)")
+                  (i+1) nr_disks s t.target_format
+      );
       debug "%s" (string_of_target t);
 
       (* We noticed that qemu sometimes corrupts the qcow2 file on
@@ -693,33 +702,47 @@ and copy_targets cmdline targets input output =
        *)
       input#adjust_overlay_parameters t.target_overlay;
 
-      (* It turns out that libguestfs's disk creation code is
-       * considerably more flexible and easier to use than
-       * qemu-img, so create the disk explicitly using libguestfs
-       * then pass the 'qemu-img convert -n' option so qemu reuses
-       * the disk.
-       *
-       * Also we allow the output mode to actually create the disk
-       * image.  This lets the output mode set ownership and
-       * permissions correctly if required.
-       *)
-      (* What output preallocation mode should we use? *)
-      let preallocation =
-        match t.target_format, cmdline.output_alloc with
-        | ("raw"|"qcow2"), Sparse -> Some "sparse"
-        | ("raw"|"qcow2"), Preallocated -> Some "full"
-        | _ -> None (* ignore -oa flag for other formats *) in
-      let compat =
-        match t.target_format with "qcow2" -> Some "1.1" | _ -> None in
-      output#disk_create
-        t.target_file t.target_format t.target_overlay.ov_virtual_size
-        ?preallocation ?compat;
+      (match t.target_file with
+       | TargetFile filename ->
+          (* It turns out that libguestfs's disk creation code is
+           * considerably more flexible and easier to use than
+           * qemu-img, so create the disk explicitly using libguestfs
+           * then pass the 'qemu-img convert -n' option so qemu reuses
+           * the disk.
+           *
+           * Also we allow the output mode to actually create the disk
+           * image.  This lets the output mode set ownership and
+           * permissions correctly if required.
+           *)
+          (* What output preallocation mode should we use? *)
+          let preallocation =
+            match t.target_format, cmdline.output_alloc with
+            | ("raw"|"qcow2"), Sparse -> Some "sparse"
+            | ("raw"|"qcow2"), Preallocated -> Some "full"
+            | _ -> None (* ignore -oa flag for other formats *) in
+          let compat =
+            match t.target_format with "qcow2" -> Some "1.1" | _ -> None in
+          output#disk_create filename t.target_format
+                             t.target_overlay.ov_virtual_size
+                             ?preallocation ?compat
 
-      let cmd = [ Guestfs_config.qemu_img; "convert" ] @
+       | TargetURI _ ->
+          (* XXX For the moment we assume that qemu URI outputs
+           * need no special work.  We can change this in future.
+           *)
+          ()
+      );
+
+      let cmd =
+        let filename =
+          match t.target_file with
+          | TargetFile filename -> "file:" ^ filename
+          | TargetURI uri -> uri in
+        [ Guestfs_config.qemu_img; "convert" ] @
         (if not (quiet ()) then [ "-p" ] else []) @
         [ "-n"; "-f"; "qcow2"; "-O"; t.target_format ] @
         (if cmdline.compressed then [ "-c" ] else []) @
-        [ overlay_file; t.target_file ] in
+        [ overlay_file; filename ] in
       let start_time = gettimeofday () in
       if run_command cmd <> 0 then
         error (f_"qemu-img command failed, see earlier errors");
@@ -772,11 +795,14 @@ and copy_targets cmdline targets input output =
 
 (* Update the target_actual_size field in the target structure. *)
 and actual_target_size target =
-  let size =
-    (* Ignore errors because we want to avoid failures after copying. *)
-    try Some (du target.target_file)
-    with Failure _ | Invalid_argument _ -> None in
-  { target with target_actual_size = size }
+  match target.target_file with
+  | TargetFile filename ->
+     let size =
+       (* Ignore errors because we want to avoid failures after copying. *)
+       try Some (du filename)
+       with Failure _ | Invalid_argument _ -> None in
+     { target with target_actual_size = size }
+  | TargetURI _ -> target
 
 (* Save overlays if --debug-overlays option was used. *)
 and preserve_overlays overlays src_name =
-- 
2.13.2




More information about the Libguestfs mailing list