[Pkg-libvirt-commits] [libguestfs] 192/266: v2v: -i libvirt: Don't access remote -ic URIs during object creation.

Hilko Bengen bengen at moszumanska.debian.org
Fri Oct 3 14:42:00 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 4132680aea6b564c7fd668b859b262c58773a4dd
Author: Richard W.M. Jones <rjones at redhat.com>
Date:   Wed Aug 27 09:42:50 2014 +0100

    v2v: -i libvirt: Don't access remote -ic URIs during object creation.
    
    Previously if you used `-i libvirt -ic [a remote URI]' then the remote
    URI would be opened during object creation, which occurs during
    command line parsing.  The practical effect was that virt-v2v could
    appear to hang or give an error (eg if the remote URI is inaccessible)
    before printing any log messages.  This could be very confusing for
    the user.
    
    Split out -i libvirtxml into a separate module, containing the libvirt
    XML to source parsing code as a function called
    Input_libvirtxml.parse_libvirt_xml.
    
    Modify -i libvirt so it does all initialization and calls the helper
    function during the #source method, and not at object creation time.
---
 po/POTFILES-ml                                  |   1 +
 v2v/Makefile.am                                 |   2 +
 v2v/cmdline.ml                                  |   2 +-
 v2v/input_libvirt.ml                            | 321 +++---------------------
 v2v/input_libvirt.mli                           |   7 +-
 v2v/input_libvirtxml.ml                         | 268 ++++++++++++++++++++
 v2v/{input_libvirt.mli => input_libvirtxml.mli} |  16 +-
 7 files changed, 325 insertions(+), 292 deletions(-)

diff --git a/po/POTFILES-ml b/po/POTFILES-ml
index 7786569..ef677be 100644
--- a/po/POTFILES-ml
+++ b/po/POTFILES-ml
@@ -89,6 +89,7 @@ v2v/convert_windows.ml
 v2v/domainxml.ml
 v2v/input_disk.ml
 v2v/input_libvirt.ml
+v2v/input_libvirtxml.ml
 v2v/lib_esx.ml
 v2v/lib_linux.ml
 v2v/output_RHEV.ml
diff --git a/v2v/Makefile.am b/v2v/Makefile.am
index 049d9df..e3a000a 100644
--- a/v2v/Makefile.am
+++ b/v2v/Makefile.am
@@ -35,6 +35,7 @@ SOURCES_MLI = \
 	lib_linux.mli \
 	input_disk.mli \
 	input_libvirt.mli \
+	input_libvirtxml.mli \
 	output_libvirt.mli \
 	output_local.mli \
 	output_RHEV.mli \
@@ -51,6 +52,7 @@ SOURCES_ML = \
 	lib_esx.ml \
 	lib_linux.ml \
 	input_disk.ml \
+	input_libvirtxml.ml \
 	input_libvirt.ml \
 	convert_linux.ml \
 	convert_windows.ml \
diff --git a/v2v/cmdline.ml b/v2v/cmdline.ml
index a323829..62d9f6a 100644
--- a/v2v/cmdline.ml
+++ b/v2v/cmdline.ml
@@ -231,7 +231,7 @@ read the man page virt-v2v(1).
         | [filename] -> filename
         | _ ->
           error (f_"expecting a libvirt XML file name on the command line") in
-      Input_libvirt.input_libvirtxml verbose filename in
+      Input_libvirtxml.input_libvirtxml verbose filename in
 
   (* Parse the output mode. *)
   let output =
diff --git a/v2v/input_libvirt.ml b/v2v/input_libvirt.ml
index d409cd9..603e002 100644
--- a/v2v/input_libvirt.ml
+++ b/v2v/input_libvirt.ml
@@ -24,293 +24,54 @@ open Common_utils
 open Types
 open Utils
 
-let identity x = x
-
-class input_libvirt
-  verbose
-  options ?(map_source_file = identity) ?(map_source_dev = identity) xml =
+class input_libvirt verbose libvirt_uri guest =
 object
   inherit input verbose
 
-  method as_options = options
-
-  method source () =
-    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
-      )
-    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 (
-        let node = Xml.xpathobj_node doc obj 0 in
-        let str = Xml.node_as_string node in
-        try int_of_string str
-        with Failure "int_of_string" ->
-          error (f_"expecting XML expression to return an integer (expression: %s)")
-            expr
-      )
-    in
-
-    let dom_type = xpath_to_string "/domain/@type" "" in
-    let name = xpath_to_string "/domain/name/text()" "" in
-    let memory = xpath_to_int "/domain/memory/text()" (1024 * 1024) in
-    let memory = Int64.of_int memory *^ 1024L in
-    let vcpu = xpath_to_int "/domain/vcpu/text()" 1 in
-    let arch = xpath_to_string "/domain/os/type/@arch" "" in
-
-    let features =
-      let features = ref [] in
-      let obj = Xml.xpath_eval_expression xpathctx "/domain/features/*" in
-      let nr_nodes = Xml.xpathobj_nr_nodes obj in
-      for i = 0 to nr_nodes-1 do
-        let node = Xml.xpathobj_node doc obj i in
-        features := Xml.node_name node :: !features
-      done;
-      !features in
-
-    let display =
-      let obj = Xml.xpath_eval_expression xpathctx "/domain/devices/graphics" in
-      let nr_nodes = Xml.xpathobj_nr_nodes obj in
-      if nr_nodes < 1 then None
-      else (
-        (* Ignore everything except the first <graphics> device. *)
-        let node = Xml.xpathobj_node doc obj 0 in
-        Xml.xpathctx_set_current_context xpathctx node;
-        let keymap =
-          match xpath_to_string "@keymap" "" with "" -> None | k -> Some k in
-        let password =
-          match xpath_to_string "@passwd" "" with "" -> None | pw -> Some pw in
-        match xpath_to_string "@type" "" with
-        | "" -> None
-        | "vnc" ->
-          Some { s_display_type = `VNC;
-                 s_keymap = keymap; s_password = password }
-        | "spice" ->
-          Some { s_display_type = `Spice;
-                 s_keymap = keymap; s_password = password }
-        | t ->
-          warning ~prog (f_"display <graphics type='%s'> was ignored") t;
-          None
-      ) in
-
-    (* Non-removable disk devices. *)
-    let disks =
-      let get_disks, add_disk =
-        let disks = ref [] in
-        let get_disks () = List.rev !disks in
-        let add_disk qemu_uri format target_dev =
-          disks :=
-            { s_qemu_uri = qemu_uri; s_format = format;
-              s_target_dev = target_dev } :: !disks
-        in
-        get_disks, add_disk
-      in
-      let obj =
-        Xml.xpath_eval_expression xpathctx
-          "/domain/devices/disk[@device='disk']" in
-      let nr_nodes = Xml.xpathobj_nr_nodes obj in
-      if nr_nodes < 1 then
-        error (f_"this guest has no non-removable disks");
-      for i = 0 to nr_nodes-1 do
-        let node = Xml.xpathobj_node doc obj i in
-        Xml.xpathctx_set_current_context xpathctx node;
-
-        let target_dev =
-          let target_dev = xpath_to_string "target/@dev" "" in
-          if target_dev <> "" then Some target_dev else None in
-
-        let format =
-          let format = xpath_to_string "driver[@name='qemu']/@type" "" in
-          if format <> "" then Some format else None in
-
-        (* The <disk type='...'> attribute may be 'block', 'file' or
-         * 'network'.  We ignore any other types.
-         *)
-        match xpath_to_string "@type" "" with
-        | "block" ->
-          let path = xpath_to_string "source/@dev" "" in
-          if path <> "" then (
-            let path = map_source_dev path in
-            add_disk path format target_dev
-          )
-        | "file" ->
-          let path = xpath_to_string "source/@file" "" in
-          if path <> "" then (
-            let path = map_source_file path in
-            add_disk path format target_dev
-          )
-        | "network" ->
-          (* We only handle <source protocol="nbd"> here, and that is
-           * intended only for virt-p2v.  Any other network disk is
-           * currently ignored.
-           *)
-          (match xpath_to_string "source/@protocol" "" with
-          | "nbd" ->
-            let host = xpath_to_string "source/host/@name" "" in
-            let port = xpath_to_int "source/host/@port" 0 in
-            if host <> "" && port > 0 then (
-              (* Generate a qemu nbd URL.
-               * XXX Quoting, although it's not needed for virt-p2v.
-               *)
-              let path = sprintf "nbd:%s:%d" host port in
-              add_disk path format target_dev
-            )
-          | "" -> ()
-          | protocol ->
-            warning ~prog (f_"network <disk> with <source protocol='%s'> was ignored")
-              protocol
-          )
-        | disk_type ->
-          warning ~prog (f_"<disk type='%s'> was ignored") disk_type
-      done;
-      get_disks () in
-
-    (* Removable devices, CD-ROMs and floppy disks. *)
-    let removables =
-      let obj =
-        Xml.xpath_eval_expression xpathctx
-          "/domain/devices/disk[@device='cdrom' or @device='floppy']" in
-      let nr_nodes = Xml.xpathobj_nr_nodes obj in
-      let disks = ref [] in
-      for i = 0 to nr_nodes-1 do
-        let node = Xml.xpathobj_node doc obj i in
-        Xml.xpathctx_set_current_context xpathctx node;
-
-        let target_dev =
-          let target_dev = xpath_to_string "target/@dev" "" in
-          if target_dev <> "" then Some target_dev else None in
-
-        let typ =
-          match xpath_to_string "@device" "" with
-          | "cdrom" -> `CDROM
-          | "floppy" -> `Floppy
-          | _ -> assert false (* libxml2 error? *) in
-
-        let disk =
-          { s_removable_type = typ; s_removable_target_dev = target_dev } in
-        disks := disk :: !disks
-      done;
-      List.rev !disks in
-
-    (* Network interfaces. *)
-    let nics =
-      let obj = Xml.xpath_eval_expression xpathctx "/domain/devices/interface" in
-      let nr_nodes = Xml.xpathobj_nr_nodes obj in
-      let nics = ref [] in
-      for i = 0 to nr_nodes-1 do
-        let node = Xml.xpathobj_node doc obj i in
-        Xml.xpathctx_set_current_context xpathctx node;
-
-        let mac = xpath_to_string "mac/@address" "" in
-        let mac =
-          match mac with
-          | ""
-          | "00:00:00:00:00:00" (* thanks, VMware *) -> None
-          | mac -> Some mac in
-
-        let vnet_type =
-          match xpath_to_string "@type" "" with
-          | "network" -> Some Network
-          | "bridge" -> Some Bridge
-          | _ -> None in
-        match vnet_type with
-        | None -> ()
-        | Some vnet_type ->
-          let vnet = xpath_to_string "source/@network | source/@bridge" "" in
-          if vnet <> "" then (
-            let nic = {
-              s_mac = mac;
-              s_vnet = vnet;
-              s_vnet_orig = vnet;
-              s_vnet_type = vnet_type
-            } in
-            nics := nic :: !nics
-          )
-      done;
-      List.rev !nics in
-
-    {
-      s_dom_type = dom_type;
-      s_name = name; s_orig_name = name;
-      s_memory = memory;
-      s_vcpu = vcpu;
-      s_arch = arch;
-      s_features = features;
-      s_display = display;
-      s_disks = disks;
-      s_removables = removables;
-      s_nics = nics;
-    }
-end
-
-(* -i libvirtxml *)
-let input_libvirtxml verbose file =
-  let options = "-i libvirtxml " ^ file in
-
-  let xml = read_whole_file file in
-
-  (* When reading libvirt XML from a file (-i libvirtxml) we allow
-   * paths to disk images in the libvirt XML to be relative (to the XML
-   * file).  Relative paths are in fact not permitted in real libvirt
-   * XML, but they are very useful when dealing with test images or
-   * when writing the XML by hand.
-   *)
-  let dir = Filename.dirname (absolute_path file) in
-  let map_source_file path =
-    if not (Filename.is_relative path) then path else dir // path
-  in
-
-  new input_libvirt verbose options ~map_source_file xml
-
-(* -i libvirt [-ic libvirt_uri] *)
-let input_libvirt verbose libvirt_uri guest =
-  let options =
+  method as_options =
     sprintf "-i libvirt%s %s"
       (match libvirt_uri with
       | None -> ""
       | Some uri -> " -ic " ^ uri)
-      guest in
+      guest
 
-  (* Depending on the libvirt URI we may need to convert <source/>
-   * paths so we can access them remotely (if that is possible).  This
-   * is only true for remote, non-NULL URIs.  (We assume the user
-   * doesn't try setting $LIBVIRT_URI.  If they do that then all bets
-   * are off).
-   *)
-  let map_source_file, map_source_dev =
-    match libvirt_uri with
-    | None -> None, None
-    | Some orig_uri ->
-      let { Xml.uri_server = server; uri_scheme = scheme } as uri =
-        try Xml.parse_uri orig_uri
-        with Invalid_argument msg ->
-          error (f_"could not parse '-ic %s'.  Original error message was: %s")
-            orig_uri msg in
-      match server, scheme with
-      | None, _
-      | Some "", _ ->                   (* Not a remote URI. *)
-        None, None
-      | Some _, None                    (* No scheme? *)
-      | Some _, Some "" ->
-        None, None
-      | Some _, Some "esx" ->           (* esx://... *)
-        let f = Lib_esx.map_path_to_uri uri in Some f, Some f
-      (* XXX Missing: Look for qemu+ssh://, xen+ssh:// and use an ssh
-       * connection.  This was supported in old virt-v2v.
-       *)
-      | Some _, Some _ ->               (* Unknown remote scheme. *)
-        warning ~prog (f_"no support for remote libvirt connections to '-ic %s'.  The conversion may fail when it tries to read the source disks.")
-          orig_uri;
-        None, None in
+  method source () =
+    (* Depending on the libvirt URI we may need to convert <source/>
+     * paths so we can access them remotely (if that is possible).  This
+     * is only true for remote, non-NULL URIs.  (We assume the user
+     * doesn't try setting $LIBVIRT_URI.  If they do that then all bets
+     * are off).
+     *)
+    let map_source_file, map_source_dev =
+      match libvirt_uri with
+      | None -> None, None
+      | Some orig_uri ->
+        let { Xml.uri_server = server; uri_scheme = scheme } as uri =
+          try Xml.parse_uri orig_uri
+          with Invalid_argument msg ->
+            error (f_"could not parse '-ic %s'.  Original error message was: %s")
+              orig_uri msg in
+        match server, scheme with
+        | None, _
+        | Some "", _ ->                 (* Not a remote URI. *)
+          None, None
+        | Some _, None                  (* No scheme? *)
+        | Some _, Some "" ->
+          None, None
+        | Some _, Some "esx" ->         (* esx://... *)
+          let f = Lib_esx.map_path_to_uri uri in Some f, Some f
+        (* XXX Missing: Look for qemu+ssh://, xen+ssh:// and use an ssh
+         * connection.  This was supported in old virt-v2v.
+         *)
+        | Some _, Some _ ->             (* Unknown remote scheme. *)
+          warning ~prog (f_"no support for remote libvirt connections to '-ic %s'.  The conversion may fail when it tries to read the source disks.")
+            orig_uri;
+          None, None in
+
+    (* Get the libvirt XML. *)
+    let xml = Domainxml.dumpxml ?conn:libvirt_uri guest in
 
-  (* Get the libvirt XML. *)
-  let xml = Domainxml.dumpxml ?conn:libvirt_uri guest in
+    Input_libvirtxml.parse_libvirt_xml ?map_source_file ?map_source_dev xml
+end
 
-  new input_libvirt verbose options ?map_source_file ?map_source_dev xml
+let input_libvirt = new input_libvirt
diff --git a/v2v/input_libvirt.mli b/v2v/input_libvirt.mli
index 649fdc7..1ed704b 100644
--- a/v2v/input_libvirt.mli
+++ b/v2v/input_libvirt.mli
@@ -16,14 +16,9 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *)
 
-(** [-i libvirt] and [-i libvirtxml] sources. *)
+(** [-i libvirt] source. *)
 
 val input_libvirt : bool -> string option -> string -> Types.input
 (** [input_libvirt verbose libvirt_uri guest] creates and returns a
     new {!Types.input} object specialized for reading input from
     libvirt sources. *)
-
-val input_libvirtxml : bool -> string -> Types.input
-(** [input_libvirtxml verbose xml_file] creates and returns a new
-    {!Types.input} object specialized for reading input from local
-    libvirt XML files. *)
diff --git a/v2v/input_libvirtxml.ml b/v2v/input_libvirtxml.ml
new file mode 100644
index 0000000..6b9bfdf
--- /dev/null
+++ b/v2v/input_libvirtxml.ml
@@ -0,0 +1,268 @@
+(* virt-v2v
+ * Copyright (C) 2009-2014 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+open Printf
+
+open Common_gettext.Gettext
+open Common_utils
+
+open Types
+open Utils
+
+let identity x = x
+
+let parse_libvirt_xml ?(map_source_file = identity) ?(map_source_dev = identity)
+    xml =
+  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
+    )
+  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 (
+      let node = Xml.xpathobj_node doc obj 0 in
+      let str = Xml.node_as_string node in
+      try int_of_string str
+      with Failure "int_of_string" ->
+        error (f_"expecting XML expression to return an integer (expression: %s)")
+          expr
+    )
+  in
+
+  let dom_type = xpath_to_string "/domain/@type" "" in
+  let name = xpath_to_string "/domain/name/text()" "" in
+  let memory = xpath_to_int "/domain/memory/text()" (1024 * 1024) in
+  let memory = Int64.of_int memory *^ 1024L in
+  let vcpu = xpath_to_int "/domain/vcpu/text()" 1 in
+  let arch = xpath_to_string "/domain/os/type/@arch" "" in
+
+  let features =
+    let features = ref [] in
+    let obj = Xml.xpath_eval_expression xpathctx "/domain/features/*" in
+    let nr_nodes = Xml.xpathobj_nr_nodes obj in
+    for i = 0 to nr_nodes-1 do
+      let node = Xml.xpathobj_node doc obj i in
+      features := Xml.node_name node :: !features
+    done;
+    !features in
+
+  let display =
+    let obj = Xml.xpath_eval_expression xpathctx "/domain/devices/graphics" in
+    let nr_nodes = Xml.xpathobj_nr_nodes obj in
+    if nr_nodes < 1 then None
+    else (
+      (* Ignore everything except the first <graphics> device. *)
+      let node = Xml.xpathobj_node doc obj 0 in
+      Xml.xpathctx_set_current_context xpathctx node;
+      let keymap =
+        match xpath_to_string "@keymap" "" with "" -> None | k -> Some k in
+      let password =
+        match xpath_to_string "@passwd" "" with "" -> None | pw -> Some pw in
+      match xpath_to_string "@type" "" with
+      | "" -> None
+      | "vnc" ->
+        Some { s_display_type = `VNC;
+               s_keymap = keymap; s_password = password }
+      | "spice" ->
+        Some { s_display_type = `Spice;
+               s_keymap = keymap; s_password = password }
+      | t ->
+        warning ~prog (f_"display <graphics type='%s'> was ignored") t;
+        None
+    ) in
+
+  (* Non-removable disk devices. *)
+  let disks =
+    let get_disks, add_disk =
+      let disks = ref [] in
+      let get_disks () = List.rev !disks in
+      let add_disk qemu_uri format target_dev =
+        disks :=
+          { s_qemu_uri = qemu_uri; s_format = format;
+            s_target_dev = target_dev } :: !disks
+      in
+      get_disks, add_disk
+    in
+    let obj =
+      Xml.xpath_eval_expression xpathctx
+        "/domain/devices/disk[@device='disk']" in
+    let nr_nodes = Xml.xpathobj_nr_nodes obj in
+    if nr_nodes < 1 then
+      error (f_"this guest has no non-removable disks");
+    for i = 0 to nr_nodes-1 do
+      let node = Xml.xpathobj_node doc obj i in
+      Xml.xpathctx_set_current_context xpathctx node;
+
+      let target_dev =
+        let target_dev = xpath_to_string "target/@dev" "" in
+        if target_dev <> "" then Some target_dev else None in
+
+      let format =
+        let format = xpath_to_string "driver[@name='qemu']/@type" "" in
+        if format <> "" then Some format else None in
+
+      (* The <disk type='...'> attribute may be 'block', 'file' or
+       * 'network'.  We ignore any other types.
+       *)
+      match xpath_to_string "@type" "" with
+      | "block" ->
+        let path = xpath_to_string "source/@dev" "" in
+        if path <> "" then (
+          let path = map_source_dev path in
+          add_disk path format target_dev
+        )
+      | "file" ->
+        let path = xpath_to_string "source/@file" "" in
+        if path <> "" then (
+          let path = map_source_file path in
+          add_disk path format target_dev
+        )
+      | "network" ->
+        (* We only handle <source protocol="nbd"> here, and that is
+         * intended only for virt-p2v.  Any other network disk is
+         * currently ignored.
+         *)
+        (match xpath_to_string "source/@protocol" "" with
+        | "nbd" ->
+          let host = xpath_to_string "source/host/@name" "" in
+          let port = xpath_to_int "source/host/@port" 0 in
+          if host <> "" && port > 0 then (
+            (* Generate a qemu nbd URL.
+             * XXX Quoting, although it's not needed for virt-p2v.
+             *)
+            let path = sprintf "nbd:%s:%d" host port in
+            add_disk path format target_dev
+          )
+        | "" -> ()
+        | protocol ->
+          warning ~prog (f_"network <disk> with <source protocol='%s'> was ignored")
+            protocol
+        )
+      | disk_type ->
+        warning ~prog (f_"<disk type='%s'> was ignored") disk_type
+    done;
+    get_disks () in
+
+  (* Removable devices, CD-ROMs and floppy disks. *)
+  let removables =
+    let obj =
+      Xml.xpath_eval_expression xpathctx
+        "/domain/devices/disk[@device='cdrom' or @device='floppy']" in
+    let nr_nodes = Xml.xpathobj_nr_nodes obj in
+    let disks = ref [] in
+    for i = 0 to nr_nodes-1 do
+      let node = Xml.xpathobj_node doc obj i in
+      Xml.xpathctx_set_current_context xpathctx node;
+
+      let target_dev =
+        let target_dev = xpath_to_string "target/@dev" "" in
+        if target_dev <> "" then Some target_dev else None in
+
+      let typ =
+        match xpath_to_string "@device" "" with
+        | "cdrom" -> `CDROM
+        | "floppy" -> `Floppy
+        | _ -> assert false (* libxml2 error? *) in
+
+      let disk =
+        { s_removable_type = typ; s_removable_target_dev = target_dev } in
+      disks := disk :: !disks
+    done;
+    List.rev !disks in
+
+  (* Network interfaces. *)
+  let nics =
+    let obj = Xml.xpath_eval_expression xpathctx "/domain/devices/interface" in
+    let nr_nodes = Xml.xpathobj_nr_nodes obj in
+    let nics = ref [] in
+    for i = 0 to nr_nodes-1 do
+      let node = Xml.xpathobj_node doc obj i in
+      Xml.xpathctx_set_current_context xpathctx node;
+
+      let mac = xpath_to_string "mac/@address" "" in
+      let mac =
+        match mac with
+        | ""
+        | "00:00:00:00:00:00" (* thanks, VMware *) -> None
+        | mac -> Some mac in
+
+      let vnet_type =
+        match xpath_to_string "@type" "" with
+        | "network" -> Some Network
+        | "bridge" -> Some Bridge
+        | _ -> None in
+      match vnet_type with
+      | None -> ()
+      | Some vnet_type ->
+        let vnet = xpath_to_string "source/@network | source/@bridge" "" in
+        if vnet <> "" then (
+          let nic = {
+            s_mac = mac;
+            s_vnet = vnet;
+            s_vnet_orig = vnet;
+            s_vnet_type = vnet_type
+          } in
+          nics := nic :: !nics
+        )
+    done;
+    List.rev !nics in
+
+  {
+    s_dom_type = dom_type;
+    s_name = name; s_orig_name = name;
+    s_memory = memory;
+    s_vcpu = vcpu;
+    s_arch = arch;
+    s_features = features;
+    s_display = display;
+    s_disks = disks;
+    s_removables = removables;
+    s_nics = nics;
+  }
+
+class input_libvirtxml verbose file =
+object
+  inherit input verbose
+
+  method as_options = "-i libvirtxml " ^ file
+
+  method source () =
+    let xml = read_whole_file file in
+
+    (* When reading libvirt XML from a file (-i libvirtxml) we allow
+     * paths to disk images in the libvirt XML to be relative (to the XML
+     * file).  Relative paths are in fact not permitted in real libvirt
+     * XML, but they are very useful when dealing with test images or
+     * when writing the XML by hand.
+     *)
+    let dir = Filename.dirname (absolute_path file) in
+    let map_source_file path =
+      if not (Filename.is_relative path) then path else dir // path
+    in
+
+    parse_libvirt_xml ~map_source_file xml
+end
+
+let input_libvirtxml = new input_libvirtxml
diff --git a/v2v/input_libvirt.mli b/v2v/input_libvirtxml.mli
similarity index 65%
copy from v2v/input_libvirt.mli
copy to v2v/input_libvirtxml.mli
index 649fdc7..7faef35 100644
--- a/v2v/input_libvirt.mli
+++ b/v2v/input_libvirtxml.mli
@@ -16,12 +16,18 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *)
 
-(** [-i libvirt] and [-i libvirtxml] sources. *)
+(** [-i libvirtxml] source. *)
 
-val input_libvirt : bool -> string option -> string -> Types.input
-(** [input_libvirt verbose libvirt_uri guest] creates and returns a
-    new {!Types.input} object specialized for reading input from
-    libvirt sources. *)
+val parse_libvirt_xml : ?map_source_file:(string -> string) -> ?map_source_dev:(string -> string) -> string -> Types.source
+(** Take libvirt XML and parse it into a {!Types.source} structure.
+
+    The optional [?map_source_file] and [?map_source_dev] functions
+    are used to map [<source file="..."/>] and [<source dev="..."/>]
+    from the XML into QEMU URIs.  If not given, then an identity
+    mapping is used.
+
+    This function is also used by {!Input_libvirt}, hence it is
+    exported. *)
 
 val input_libvirtxml : bool -> string -> Types.input
 (** [input_libvirtxml verbose xml_file] creates and returns a new

-- 
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