[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