[Pkg-libvirt-commits] [libguestfs] 110/266: v2v: Add -o libvirt target (creates guest directly in libvirt).

Hilko Bengen bengen at moszumanska.debian.org
Fri Oct 3 14:41:48 UTC 2014


This is an automated email from the git hooks/post-receive script.

bengen pushed a commit to annotated tag debian/1%1.27.35-1
in repository libguestfs.

commit e2fcc2304c160d20abfee1e5fe6c77f12979d2bf
Author: Richard W.M. Jones <rjones at redhat.com>
Date:   Fri Aug 15 13:19:53 2014 +0100

    v2v: Add -o libvirt target (creates guest directly in libvirt).
---
 v2v/cmdline.ml         |  6 ++--
 v2v/source_libvirt.ml  |  7 ++--
 v2v/target_libvirt.ml  | 93 ++++++++++++++++++++++++++++++++++++++++++++++----
 v2v/target_libvirt.mli |  8 ++---
 v2v/types.ml           |  2 +-
 v2v/types.mli          |  2 +-
 v2v/v2v.ml             |  6 ++--
 v2v/virt-v2v.pod       | 80 +++++++++++++++++++++++++++++++++++++++++--
 8 files changed, 181 insertions(+), 23 deletions(-)

diff --git a/v2v/cmdline.ml b/v2v/cmdline.ml
index c76b5bd..ea2c70c 100644
--- a/v2v/cmdline.ml
+++ b/v2v/cmdline.ml
@@ -201,13 +201,13 @@ read the man page virt-v2v(1).
   let output =
     match output_mode with
     | `Libvirt ->
-      if output_storage <> "" then
-        error (f_"-o libvirt: do not use the -os option");
+      let output_storage =
+        if output_storage = "" then "default" else output_storage in
       if vmtype <> None then
         error (f_"--vmtype option can only be used with '-o rhev'");
       if not do_copy then
         error (f_"--no-copy and '-o libvirt' cannot be used at the same time");
-      OutputLibvirt output_conn
+      OutputLibvirt (output_conn, output_storage)
 
     | `Local ->
       if output_storage = "" then
diff --git a/v2v/source_libvirt.ml b/v2v/source_libvirt.ml
index 91c6e1f..d787f42 100644
--- a/v2v/source_libvirt.ml
+++ b/v2v/source_libvirt.ml
@@ -51,8 +51,8 @@ let create_xml ?dir xml =
     else (
       let node = Xml.xpathobj_node doc obj 0 in
       Xml.node_as_string node
-    ) in
-  let xpath_to_int expr default =
+    )
+  and xpath_to_int expr default =
     let obj = Xml.xpath_eval_expression xpathctx expr in
     if Xml.xpathobj_nr_nodes obj < 1 then default
     else (
@@ -62,7 +62,8 @@ let create_xml ?dir xml =
       with Failure "int_of_string" ->
         error (f_"expecting XML expression to return an integer (expression: %s)")
           expr
-    ) in
+    )
+  in
 
   let dom_type = xpath_to_string "/domain/@type" "" in
   let name = xpath_to_string "/domain/name/text()" "" in
diff --git a/v2v/target_libvirt.ml b/v2v/target_libvirt.ml
index 5bc6ae9..6b1f280 100644
--- a/v2v/target_libvirt.ml
+++ b/v2v/target_libvirt.ml
@@ -25,7 +25,7 @@ open Types
 open Utils
 open DOM
 
-let create_libvirt_xml source overlays guestcaps =
+let create_libvirt_xml ?pool source overlays guestcaps =
   let memory_k = source.s_memory /^ 1024L in
 
   let features =
@@ -35,21 +35,31 @@ let create_libvirt_xml source overlays guestcaps =
         feature <> "acpi" || guestcaps.gcaps_acpi
     ) source.s_features in
 
-
   let disks =
     let block_prefix =
       if guestcaps.gcaps_block_bus = "virtio" then "vd" else "hd" in
     List.mapi (
       fun i ov ->
-        e "disk" ["type", "file"; "device", "disk"] [
+        e "disk" [
+          "type", if pool = None then "file" else "volume";
+          "device", "disk"
+        ] [
           e "driver" [
             "name", "qemu";
             "type", ov.ov_target_format;
             "cache", "none"
           ] [];
-          e "source" [
-            "file", ov.ov_target_file;
-          ] [];
+          (match pool with
+          | None ->
+            e "source" [
+              "file", ov.ov_target_file;
+            ] []
+          | Some pool ->
+            e "source" [
+              "pool", pool;
+              "volume", Filename.basename ov.ov_target_file;
+            ] []
+          );
           e "target" [
             "dev", block_prefix ^ (drive_name i);
             "bus", guestcaps.gcaps_block_bus;
@@ -92,3 +102,74 @@ let create_libvirt_xml source overlays guestcaps =
     ] (* /doc *) in
 
   doc
+
+let initialize oc output_pool source overlays =
+  (* Connect to output libvirt instance and check that the pool exists
+   * and dump out its XML.
+   *)
+  let cmd =
+    match oc with
+    | None -> sprintf "virsh pool-dumpxml %s" (quote output_pool)
+    | Some uri ->
+      sprintf "virsh -c %s dumpxml %s" (quote uri) (quote output_pool) in
+  let lines = external_command ~prog cmd in
+  let xml = String.concat "\n" lines in
+  let doc = Xml.parse_memory xml in
+  let xpathctx = Xml.xpath_new_context doc in
+
+  let xpath_to_string expr default =
+    let obj = Xml.xpath_eval_expression xpathctx expr in
+    if Xml.xpathobj_nr_nodes obj < 1 then default
+    else (
+      let node = Xml.xpathobj_node doc obj 0 in
+      Xml.node_as_string node
+    )
+  in
+
+  (* We can only output to a pool of type 'dir' (directory). *)
+  let pool_type = xpath_to_string "/pool/@type" "" in
+  if pool_type <> "dir" then
+    error (f_"-o libvirt: output pool '%s' is not a directory (type='dir').  See virt-v2v(1) section \"OUTPUT TO LIBVIRT\"") output_pool;
+  let target_path = xpath_to_string "/pool/target/path/text()" "" in
+  if target_path = "" || not (is_directory target_path) then
+    error (f_"-o libvirt: output pool '%s' has type='dir' but the /pool/target/path element either does not exist or is not a local directory.  See virt-v2v(1) section \"OUTPUT TO LIBVIRT\"") output_pool;
+
+  (* Set up the overlays. *)
+  List.map (
+    fun ov ->
+      let target_file = target_path // source.s_name ^ "-" ^ ov.ov_sd in
+      { ov with ov_target_file = target_file }
+  ) overlays
+
+let create_metadata oc output_pool source overlays guestcaps =
+  (* We copied directly into the final pool directory.  However we
+   * have to tell libvirt.
+   *)
+  let cmd =
+    match oc with
+    | None -> sprintf "virsh pool-refresh %s" (quote output_pool)
+    | Some uri ->
+      sprintf "virsh -c %s pool-refresh %s"
+        (quote uri) (quote output_pool) in
+  if Sys.command cmd <> 0 then
+    warning ~prog (f_"could not refresh libvirt pool %s") output_pool;
+
+  (* Create the metadata. *)
+  let doc = create_libvirt_xml ~pool:output_pool source overlays guestcaps in
+
+  let tmpfile, chan = Filename.open_temp_file "v2vlibvirt" ".xml" in
+  DOM.doc_to_chan chan doc;
+  close_out chan;
+
+  (* Define the domain in libvirt. *)
+  let cmd =
+    match oc with
+    | None -> sprintf "virsh define %s" (quote tmpfile)
+    | Some uri ->
+      sprintf "virsh -c %s define %s" (quote uri) (quote tmpfile) in
+  if Sys.command cmd = 0 then (
+    try Unix.unlink tmpfile with _ -> ()
+  ) else (
+    warning ~prog (f_"could not define libvirt domain.  The libvirt XML is still available in '%s'.  Try running 'virsh define %s' yourself instead.")
+      tmpfile tmpfile
+  );
diff --git a/v2v/target_libvirt.mli b/v2v/target_libvirt.mli
index de76a1f..f7a5669 100644
--- a/v2v/target_libvirt.mli
+++ b/v2v/target_libvirt.mli
@@ -16,10 +16,8 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *)
 
-(*
-val initialize : string -> Types.source -> Types.overlay list -> Types.overlay list
+val initialize : string option -> string -> Types.source -> Types.overlay list -> Types.overlay list
 
-val create_metadata : string -> Types.source -> Types.overlay list -> Types.guestcaps -> unit
-*)
+val create_metadata : string option -> string -> Types.source -> Types.overlay list -> Types.guestcaps -> unit
 
-val create_libvirt_xml : Types.source -> Types.overlay list -> Types.guestcaps -> DOM.doc
+val create_libvirt_xml : ?pool:string -> Types.source -> Types.overlay list -> Types.guestcaps -> DOM.doc
diff --git a/v2v/types.ml b/v2v/types.ml
index aeea221..4ccddd6 100644
--- a/v2v/types.ml
+++ b/v2v/types.ml
@@ -25,7 +25,7 @@ type input =
 | InputLibvirtXML of string
 
 type output =
-| OutputLibvirt of string option
+| OutputLibvirt of string option * string
 | OutputLocal of string
 | OutputRHEV of string * output_rhev_params
 
diff --git a/v2v/types.mli b/v2v/types.mli
index a772ce3..329bf6f 100644
--- a/v2v/types.mli
+++ b/v2v/types.mli
@@ -24,7 +24,7 @@ type input =
 (** The input arguments as specified on the command line. *)
 
 type output =
-| OutputLibvirt of string option    (* -o libvirt: -oc *)
+| OutputLibvirt of string option * string (* -o libvirt: -oc & -os *)
 | OutputLocal of string             (* -o local: directory *)
 | OutputRHEV of string * output_rhev_params (* -o rhev: output storage *)
 (** The output arguments as specified on the command line. *)
diff --git a/v2v/v2v.ml b/v2v/v2v.ml
index 1e12af7..27c6270 100644
--- a/v2v/v2v.ml
+++ b/v2v/v2v.ml
@@ -199,7 +199,8 @@ let rec main () =
       | None -> source
       | Some name -> { source with s_name = name } in
     match output with
-    | OutputLibvirt oc -> assert false
+    | OutputLibvirt (oc, os) ->
+      Target_libvirt.create_metadata oc os renamed_source overlays guestcaps
     | OutputLocal dir ->
       Target_local.create_metadata dir renamed_source overlays guestcaps
     | OutputRHEV (os, rhev_params) ->
@@ -252,7 +253,8 @@ and initialize_target ~verbose g
       | None -> source
       | Some name -> { source with s_name = name } in
     match output with
-    | OutputLibvirt oc -> assert false
+    | OutputLibvirt (oc, os) ->
+      Target_libvirt.initialize oc os renamed_source overlays
     | OutputLocal dir -> Target_local.initialize dir renamed_source overlays
     | OutputRHEV (os, rhev_params) ->
       Target_RHEV.initialize ~verbose
diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod
index 606831e..ae5502d 100644
--- a/v2v/virt-v2v.pod
+++ b/v2v/virt-v2v.pod
@@ -87,6 +87,8 @@ Set the output method to I<libvirt>.  This is the default.
 In this mode, the converted guest is created as a libvirt guest.  You
 may also specify a libvirt connection URI (see I<-oc>).
 
+See L</OUTPUT TO LIBVIRT> below.
+
 =item B<-o local>
 
 Set the output method to I<local>.
@@ -124,7 +126,7 @@ Set the output file allocation mode.  The default is C<sparse>.
 =item B<-oc> libvirtURI
 
 Specify a libvirt connection to use when writing the converted guest.
-This is only used when S<I<-o libvirt>>.
+This is only used when S<I<-o libvirt>>.  See L</OUTPUT TO LIBVIRT> below.
 
 Only local libvirt connections can be used.  Remote libvirt
 connections will not work.
@@ -144,7 +146,8 @@ the output name is the same as the input name.
 
 The location of the storage for the converted guest.
 
-For I<-o libvirt>, this is a libvirt pool (see S<C<virsh pool-list>>).
+For I<-o libvirt>, this is a libvirt directory pool
+(see S<C<virsh pool-list>>).
 
 For I<-o local>, this is a directory name.  The directory must exist.
 
@@ -398,6 +401,79 @@ code if there was a fatal error.
 Virt-v2v E<le> 0.9.1 did not support the I<--machine-readable>
 option at all.  The option was added when virt-v2v was rewritten in 2014.
 
+=head1 OUTPUT TO LIBVIRT
+
+The I<-o libvirt> option lets you upload the converted guest to
+a libvirt-managed host.  There are several limitations:
+
+=over 4
+
+=item *
+
+You can only use a local libvirt connection [see below for how to
+workaround this].
+
+=item *
+
+The I<-os pool> option must specify a directory pool, not anything
+more exotic such as iSCSI [but see below].
+
+=item *
+
+You can only upload to a KVM hypervisor.
+
+=back
+
+B<To output to a remote libvirt instance and/or a non-directory storage pool>
+you have to use the following workaround:
+
+=over 4
+
+=item 1.
+
+Use virt-v2v in I<-o local> mode to convert the guest disks and
+metadata into a local temporary directory:
+
+ virt-v2v [...] -o local -os /tmp
+
+This creates two (or more) files in C</tmp> called:
+
+ /tmp/NAME.xml     # the libvirt XML (metadata)
+ /tmp/NAME-sda     # the guest's first disk
+
+(for C<NAME> substitute the guest's name).
+
+=item 2.
+
+Upload the converted disk(s) into the storage pool called C<POOL>:
+
+ size=$(stat -c%s /tmp/NAME-sda)
+ virsh vol-create-as POOL NAME-sda $size --format raw
+ virsh vol-upload --pool POOL NAME-sda /tmp/NAME-sda
+
+=item 3.
+
+Edit C</tmp/NAME.xml> to change C</tmp/NAME-sda> to the pool name.
+In other words, locate the following bit of XML:
+
+ <disk type='file' device='disk'>
+   <driver name='qemu' type='raw' cache='none' />
+   <source file='/tmp/NAME-sda' />
+   <target dev='hda' bus='ide' />
+ </disk>
+
+and change I<only> the E<lt>sourceE<gt> element to:
+
+   <source pool='POOL' volume='NAME-sda' />
+
+=item 4.
+
+Define the final guest in libvirt:
+
+ virsh define /tmp/NAME.xml
+
+=back
+
 =head1 FILES
 
 =over 4

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-libvirt/libguestfs.git



More information about the Pkg-libvirt-commits mailing list