mrc0mmand / rpms / libguestfs

Forked from rpms/libguestfs 3 years ago
Clone

Blame SOURCES/0219-v2v-Convert-xpath_to_-to-use-xpath-convenience-funct.patch

ffd6ed
From 200c392c36db4800e915e3c4de16ea6294dd4cd7 Mon Sep 17 00:00:00 2001
ffd6ed
From: "Richard W.M. Jones" <rjones@redhat.com>
ffd6ed
Date: Fri, 28 Aug 2015 13:53:24 +0100
ffd6ed
Subject: [PATCH] v2v: Convert xpath_to_* to use xpath convenience functions.
ffd6ed
ffd6ed
In -i libvirtxml, -i ova and -o libvirt drivers, replace the ad hoc
ffd6ed
xpath_to_* functions with use of the new xpath convenience functions
ffd6ed
introduced in the previous commit.
ffd6ed
ffd6ed
This is not entirely refactoring because I fixed a few bugs found by
ffd6ed
type safety.
ffd6ed
ffd6ed
(cherry picked from commit 261d05749fb75e60d56d3c2d92589de9dca7ca09)
ffd6ed
---
ffd6ed
 v2v/input_libvirtxml.ml | 281 ++++++++++++++++++++++--------------------------
ffd6ed
 v2v/input_ova.ml        |  85 +++++++--------
ffd6ed
 v2v/output_libvirt.ml   |  23 ++--
ffd6ed
 3 files changed, 180 insertions(+), 209 deletions(-)
ffd6ed
ffd6ed
diff --git a/v2v/input_libvirtxml.ml b/v2v/input_libvirtxml.ml
ffd6ed
index 16c34a6..be48a75 100644
ffd6ed
--- a/v2v/input_libvirtxml.ml
ffd6ed
+++ b/v2v/input_libvirtxml.ml
ffd6ed
@@ -39,37 +39,23 @@ let parse_libvirt_xml ?conn ~verbose xml =
ffd6ed
 
ffd6ed
   let doc = Xml.parse_memory xml in
ffd6ed
   let xpathctx = Xml.xpath_new_context doc in
ffd6ed
+  let xpath_string = xpath_string xpathctx
ffd6ed
+  and xpath_int = xpath_int xpathctx
ffd6ed
+  and xpath_int_default = xpath_int_default xpathctx in
ffd6ed
 
ffd6ed
-  let xpath_to_string expr default =
ffd6ed
-    let obj = Xml.xpath_eval_expression xpathctx expr in
ffd6ed
-    if Xml.xpathobj_nr_nodes obj < 1 then default
ffd6ed
-    else (
ffd6ed
-      let node = Xml.xpathobj_node obj 0 in
ffd6ed
-      Xml.node_as_string node
ffd6ed
-    )
ffd6ed
-  and xpath_to_int expr default =
ffd6ed
-    let obj = Xml.xpath_eval_expression xpathctx expr in
ffd6ed
-    if Xml.xpathobj_nr_nodes obj < 1 then default
ffd6ed
-    else (
ffd6ed
-      let node = Xml.xpathobj_node obj 0 in
ffd6ed
-      let str = Xml.node_as_string node in
ffd6ed
-      try int_of_string str
ffd6ed
-      with Failure "int_of_string" ->
ffd6ed
-        error (f_"expecting XML expression to return an integer (expression: %s)")
ffd6ed
-          expr
ffd6ed
-    )
ffd6ed
-  in
ffd6ed
-
ffd6ed
-  let dom_type = xpath_to_string "/domain/@type" "" in
ffd6ed
-  let name = xpath_to_string "/domain/name/text()" "" in
ffd6ed
-  let memory = xpath_to_int "/domain/memory/text()" (1024 * 1024) in
ffd6ed
+  let dom_type =
ffd6ed
+    match xpath_string "/domain/@type" with
ffd6ed
+    | None | Some "" ->
ffd6ed
+       error ~prog (f_"in the libvirt XML metadata, <domain type='...'> is missing or empty")
ffd6ed
+    | Some s -> s in
ffd6ed
+  let name =
ffd6ed
+    match xpath_string "/domain/name/text()" with
ffd6ed
+    | None | Some "" ->
ffd6ed
+       error ~prog (f_"in the libvirt XML metadata, <name> is missing or empty")
ffd6ed
+    | Some s -> s in
ffd6ed
+  let memory = xpath_int_default "/domain/memory/text()" (1024 * 1024) in
ffd6ed
   let memory = Int64.of_int memory *^ 1024L in
ffd6ed
-  let vcpu = xpath_to_int "/domain/vcpu/text()" 1 in
ffd6ed
-
ffd6ed
-  if dom_type = "" then
ffd6ed
-    error (f_"in the libvirt XML metadata, <domain type='...'> is missing or empty");
ffd6ed
-  if name = "" then
ffd6ed
-    error (f_"in the libvirt XML metadata, <name> is missing or empty");
ffd6ed
+  let vcpu = xpath_int_default "/domain/vcpu/text()" 1 in
ffd6ed
 
ffd6ed
   let features =
ffd6ed
     let features = ref [] in
ffd6ed
@@ -89,54 +75,53 @@ let parse_libvirt_xml ?conn ~verbose xml =
ffd6ed
       (* Ignore everything except the first <graphics> device. *)
ffd6ed
       let node = Xml.xpathobj_node obj 0 in
ffd6ed
       Xml.xpathctx_set_current_context xpathctx node;
ffd6ed
-      let keymap =
ffd6ed
-        match xpath_to_string "@keymap" "" with "" -> None | k -> Some k in
ffd6ed
-      let password =
ffd6ed
-        match xpath_to_string "@passwd" "" with "" -> None | pw -> Some pw in
ffd6ed
+      let keymap = xpath_string "@keymap" in
ffd6ed
+      let password = xpath_string "@passwd" in
ffd6ed
       let listen =
ffd6ed
         let obj = Xml.xpath_eval_expression xpathctx "listen" in
ffd6ed
         let nr_nodes = Xml.xpathobj_nr_nodes obj in
ffd6ed
         if nr_nodes < 1 then (
ffd6ed
-          match xpath_to_string "@listen" "" with "" -> LNone | a -> LAddress a
ffd6ed
+          match xpath_string "@listen" with
ffd6ed
+          | None -> LNone | Some a -> LAddress a
ffd6ed
         ) else (
ffd6ed
           (* Use only the first <listen> configuration. *)
ffd6ed
-          match xpath_to_string "listen[1]/@type" "" with
ffd6ed
-          | "" -> LNone
ffd6ed
-          | "address" ->
ffd6ed
-            (match xpath_to_string "listen[1]/@address" "" with
ffd6ed
-            | "" -> LNone
ffd6ed
-            | a -> LAddress a
ffd6ed
+          match xpath_string "listen[1]/@type" with
ffd6ed
+          | None -> LNone
ffd6ed
+          | Some "address" ->
ffd6ed
+            (match xpath_string "listen[1]/@address" with
ffd6ed
+            | None -> LNone
ffd6ed
+            | Some a -> LAddress a
ffd6ed
             )
ffd6ed
-          | "network" ->
ffd6ed
-            (match xpath_to_string "listen[1]/@network" "" with
ffd6ed
-            | "" -> LNone
ffd6ed
-            | n -> LNetwork n
ffd6ed
+          | Some "network" ->
ffd6ed
+            (match xpath_string "listen[1]/@network" with
ffd6ed
+            | None -> LNone
ffd6ed
+            | Some n -> LNetwork n
ffd6ed
             )
ffd6ed
-          | t ->
ffd6ed
+          | Some t ->
ffd6ed
             warning ~prog (f_"<listen type='%s'> in the input libvirt XML was ignored") t;
ffd6ed
             LNone
ffd6ed
         ) in
ffd6ed
       let port =
ffd6ed
-        match xpath_to_string "@autoport" "yes" with
ffd6ed
-        | "no" ->
ffd6ed
-          let port = xpath_to_int "@port" (-1) in
ffd6ed
-          if port >= 0 then Some port
ffd6ed
-          else None
ffd6ed
+        match xpath_string "@autoport" with
ffd6ed
+        | Some "no" ->
ffd6ed
+          (match xpath_int "@port" with
ffd6ed
+           | Some port when port > 0 -> Some port
ffd6ed
+           | Some _ | None -> None)
ffd6ed
         | _ -> None in
ffd6ed
-      match xpath_to_string "@type" "" with
ffd6ed
-      | "" -> None
ffd6ed
-      | "vnc" ->
ffd6ed
+      match xpath_string "@type" with
ffd6ed
+      | None -> None
ffd6ed
+      | Some "vnc" ->
ffd6ed
         Some { s_display_type = VNC;
ffd6ed
                s_keymap = keymap; s_password = password; s_listen = listen;
ffd6ed
                s_port = port }
ffd6ed
-      | "spice" ->
ffd6ed
+      | Some "spice" ->
ffd6ed
         Some { s_display_type = Spice;
ffd6ed
                s_keymap = keymap; s_password = password; s_listen = listen;
ffd6ed
                s_port = port }
ffd6ed
-      | "sdl"|"desktop" as t ->
ffd6ed
+      | Some ("sdl"|"desktop" as t) ->
ffd6ed
         warning ~prog (f_"virt-v2v does not support local displays, so <graphics type='%s'> in the input libvirt XML was ignored") t;
ffd6ed
         None
ffd6ed
-      | t ->
ffd6ed
+      | Some t ->
ffd6ed
         warning ~prog (f_"display <graphics type='%s'> in the input libvirt XML was ignored") t;
ffd6ed
         None
ffd6ed
     ) in
ffd6ed
@@ -151,16 +136,16 @@ let parse_libvirt_xml ?conn ~verbose xml =
ffd6ed
       let node = Xml.xpathobj_node obj 0 in
ffd6ed
 
ffd6ed
       Xml.xpathctx_set_current_context xpathctx node;
ffd6ed
-      match xpath_to_string "@model" "" with
ffd6ed
-      | "" -> None
ffd6ed
-      | "ac97"   -> Some { s_sound_model = AC97 }
ffd6ed
-      | "es1370" -> Some { s_sound_model = ES1370 }
ffd6ed
-      | "ich6"   -> Some { s_sound_model = ICH6 }
ffd6ed
-      | "ich9"   -> Some { s_sound_model = ICH9 }
ffd6ed
-      | "pcspk"  -> Some { s_sound_model = PCSpeaker }
ffd6ed
-      | "sb16"   -> Some { s_sound_model = SB16 }
ffd6ed
-      | "usb"    -> Some { s_sound_model = USBAudio }
ffd6ed
-      | model ->
ffd6ed
+      match xpath_string "@model" with
ffd6ed
+      | None -> None
ffd6ed
+      | Some "ac97"   -> Some { s_sound_model = AC97 }
ffd6ed
+      | Some "es1370" -> Some { s_sound_model = ES1370 }
ffd6ed
+      | Some "ich6"   -> Some { s_sound_model = ICH6 }
ffd6ed
+      | Some "ich9"   -> Some { s_sound_model = ICH9 }
ffd6ed
+      | Some "pcspk"  -> Some { s_sound_model = PCSpeaker }
ffd6ed
+      | Some "sb16"   -> Some { s_sound_model = SB16 }
ffd6ed
+      | Some "usb"    -> Some { s_sound_model = USBAudio }
ffd6ed
+      | Some model ->
ffd6ed
          warning ~prog (f_"unknown sound model %s ignored") model;
ffd6ed
          None
ffd6ed
     ) in
ffd6ed
@@ -191,84 +176,80 @@ let parse_libvirt_xml ?conn ~verbose xml =
ffd6ed
       Xml.xpathctx_set_current_context xpathctx node;
ffd6ed
 
ffd6ed
       let controller =
ffd6ed
-        let target_bus = xpath_to_string "target/@bus" "" in
ffd6ed
+        let target_bus = xpath_string "target/@bus" in
ffd6ed
         match target_bus with
ffd6ed
-        | "" -> None
ffd6ed
-        | "ide" -> Some Source_IDE
ffd6ed
-        | "scsi" -> Some Source_SCSI
ffd6ed
-        | "virtio" -> Some Source_virtio_blk
ffd6ed
-        | _ -> None in
ffd6ed
+        | None -> None
ffd6ed
+        | Some "ide" -> Some Source_IDE
ffd6ed
+        | Some "scsi" -> Some Source_SCSI
ffd6ed
+        | Some "virtio" -> Some Source_virtio_blk
ffd6ed
+        | Some _ -> None in
ffd6ed
 
ffd6ed
       let format =
ffd6ed
-        match xpath_to_string "driver/@type" "" with
ffd6ed
-        | "aio" -> Some "raw" (* Xen wierdness *)
ffd6ed
-        | "" -> None
ffd6ed
-        | format -> Some format in
ffd6ed
+        match xpath_string "driver/@type" with
ffd6ed
+        | Some "aio" -> Some "raw" (* Xen wierdness *)
ffd6ed
+        | None -> None
ffd6ed
+        | Some format -> Some format in
ffd6ed
 
ffd6ed
       (* The <disk type='...'> attribute may be 'block', 'file',
ffd6ed
        * 'network' or 'volume'.  We ignore any other types.
ffd6ed
        *)
ffd6ed
-      match xpath_to_string "@type" "" with
ffd6ed
-      | "block" ->
ffd6ed
-        let path = xpath_to_string "source/@dev" "" in
ffd6ed
-        if path <> "" then
ffd6ed
-          add_disk path format controller (P_source_dev path)
ffd6ed
-      | "file" ->
ffd6ed
-        let path = xpath_to_string "source/@file" "" in
ffd6ed
-        if path <> "" then
ffd6ed
-          add_disk path format controller (P_source_file path)
ffd6ed
-      | "network" ->
ffd6ed
+      match xpath_string "@type" with
ffd6ed
+      | None ->
ffd6ed
+         warning ~prog (f_"<disk> element with no type attribute ignored")
ffd6ed
+      | Some "block" ->
ffd6ed
+        (match xpath_string "source/@dev" with
ffd6ed
+         | Some path ->
ffd6ed
+            add_disk path format controller (P_source_dev path)
ffd6ed
+         | None -> ()
ffd6ed
+        );
ffd6ed
+      | Some "file" ->
ffd6ed
+        (match xpath_string "source/@file" with
ffd6ed
+         | Some path ->
ffd6ed
+            add_disk path format controller (P_source_file path)
ffd6ed
+         | None -> ()
ffd6ed
+        );
ffd6ed
+      | Some "network" ->
ffd6ed
         (* We only handle <source protocol="nbd"> here, and that is
ffd6ed
          * intended only for virt-p2v.  Any other network disk is
ffd6ed
          * currently ignored.
ffd6ed
          *)
ffd6ed
-        (match xpath_to_string "source/@protocol" "" with
ffd6ed
-        | "nbd" ->
ffd6ed
-          let host = xpath_to_string "source/host/@name" "" in
ffd6ed
-          let port = xpath_to_int "source/host/@port" 0 in
ffd6ed
-          if host <> "" && port > 0 then (
ffd6ed
-            (* Generate a qemu nbd URL.
ffd6ed
-             * XXX Quoting, although it's not needed for virt-p2v.
ffd6ed
-             *)
ffd6ed
-            let path = sprintf "nbd:%s:%d" host port in
ffd6ed
-            add_disk path format controller P_dont_rewrite
ffd6ed
-          )
ffd6ed
-        | "" -> ()
ffd6ed
-        | protocol ->
ffd6ed
-          warning ~prog (f_"network <disk> with <source protocol='%s'> was ignored")
ffd6ed
+        (match (xpath_string "source/@protocol",
ffd6ed
+                xpath_string "source/host/@name",
ffd6ed
+                xpath_int "source/host/@port") with
ffd6ed
+        | None, _, _ ->
ffd6ed
+          warning ~prog (f_"<disk type=network> was ignored")
ffd6ed
+        | Some "nbd", Some ("localhost" as host), Some port when port > 0 ->
ffd6ed
+          (* virt-p2v: Generate a qemu nbd URL. *)
ffd6ed
+          let path = sprintf "nbd:%s:%d" host port in
ffd6ed
+          add_disk path format controller P_dont_rewrite
ffd6ed
+        | Some protocol, _, _ ->
ffd6ed
+          warning ~prog (f_"<disk type='network'> with <source protocol='%s'> was ignored")
ffd6ed
             protocol
ffd6ed
         )
ffd6ed
-      | "volume" ->
ffd6ed
-        let pool = xpath_to_string "source/@pool" "" in
ffd6ed
-        let vol = xpath_to_string "source/@volume" "" in
ffd6ed
-        if pool <> "" && vol <> "" then (
ffd6ed
+      | Some "volume" ->
ffd6ed
+        (match xpath_string "source/@pool", xpath_string "source/@volume" with
ffd6ed
+        | None, None | Some _, None | None, Some _ -> ()
ffd6ed
+        | Some pool, Some vol ->
ffd6ed
           let xml = Domainxml.vol_dumpxml ?conn pool vol in
ffd6ed
           let doc = Xml.parse_memory xml in
ffd6ed
           let xpathctx = Xml.xpath_new_context doc in
ffd6ed
-
ffd6ed
-          let xpath_to_string expr default =
ffd6ed
-            let obj = Xml.xpath_eval_expression xpathctx expr in
ffd6ed
-            if Xml.xpathobj_nr_nodes obj < 1 then default
ffd6ed
-            else (
ffd6ed
-              let node = Xml.xpathobj_node obj 0 in
ffd6ed
-              Xml.node_as_string node
ffd6ed
-            ) in
ffd6ed
+          let xpath_string = Utils.xpath_string xpathctx in
ffd6ed
 
ffd6ed
           (* Use the format specified in the volume itself. *)
ffd6ed
-          let format =
ffd6ed
-            match xpath_to_string "/volume/target/format/@type" "" with
ffd6ed
-            | "" -> None
ffd6ed
-            | format -> Some format in
ffd6ed
+          let format = xpath_string "/volume/target/format/@type" in
ffd6ed
 
ffd6ed
-          match xpath_to_string "/volume/@type" "" with
ffd6ed
-          | "" | "file" ->
ffd6ed
-            let path = xpath_to_string "/volume/target/path/text()" "" in
ffd6ed
-            if path <> "" then
ffd6ed
-              add_disk path format controller (P_source_file path)
ffd6ed
-          | vol_type ->
ffd6ed
+          (match xpath_string "/volume/@type" with
ffd6ed
+          | None | Some "file" ->
ffd6ed
+            (match xpath_string "/volume/target/path/text()" with
ffd6ed
+             | Some path ->
ffd6ed
+                add_disk path format controller (P_source_file path)
ffd6ed
+             | None -> ()
ffd6ed
+            );
ffd6ed
+          | Some vol_type ->
ffd6ed
             warning ~prog (f_"<disk type='volume'> with <volume type='%s'> was ignored") vol_type
ffd6ed
+          )
ffd6ed
         )
ffd6ed
-      | disk_type ->
ffd6ed
+      | Some disk_type ->
ffd6ed
         warning ~prog (f_"<disk type='%s'> was ignored") disk_type
ffd6ed
     done;
ffd6ed
     get_disks () in
ffd6ed
@@ -285,18 +266,18 @@ let parse_libvirt_xml ?conn ~verbose xml =
ffd6ed
       Xml.xpathctx_set_current_context xpathctx node;
ffd6ed
 
ffd6ed
       let controller =
ffd6ed
-        let target_bus = xpath_to_string "target/@bus" "" in
ffd6ed
+        let target_bus = xpath_string "target/@bus" in
ffd6ed
         match target_bus with
ffd6ed
-        | "" -> None
ffd6ed
-        | "ide" -> Some Source_IDE
ffd6ed
-        | "scsi" -> Some Source_SCSI
ffd6ed
-        | "virtio" -> Some Source_virtio_blk
ffd6ed
-        | _ -> None in
ffd6ed
+        | None -> None
ffd6ed
+        | Some "ide" -> Some Source_IDE
ffd6ed
+        | Some "scsi" -> Some Source_SCSI
ffd6ed
+        | Some "virtio" -> Some Source_virtio_blk
ffd6ed
+        | Some _ -> None in
ffd6ed
 
ffd6ed
       let typ =
ffd6ed
-        match xpath_to_string "@device" "" with
ffd6ed
-        | "cdrom" -> CDROM
ffd6ed
-        | "floppy" -> Floppy
ffd6ed
+        match xpath_string "@device" with
ffd6ed
+        | Some "cdrom" -> CDROM
ffd6ed
+        | Some "floppy" -> Floppy
ffd6ed
         | _ -> assert false (* libxml2 error? *) in
ffd6ed
 
ffd6ed
       let disk =
ffd6ed
@@ -314,31 +295,31 @@ let parse_libvirt_xml ?conn ~verbose xml =
ffd6ed
       let node = Xml.xpathobj_node obj i in
ffd6ed
       Xml.xpathctx_set_current_context xpathctx node;
ffd6ed
 
ffd6ed
-      let mac = xpath_to_string "mac/@address" "" in
ffd6ed
+      let mac = xpath_string "mac/@address" in
ffd6ed
       let mac =
ffd6ed
         match mac with
ffd6ed
-        | ""
ffd6ed
-        | "00:00:00:00:00:00" (* thanks, VMware *) -> None
ffd6ed
-        | mac -> Some mac in
ffd6ed
+        | None
ffd6ed
+        | Some "00:00:00:00:00:00" (* thanks, VMware *) -> None
ffd6ed
+        | Some mac -> Some mac in
ffd6ed
 
ffd6ed
       let vnet_type =
ffd6ed
-        match xpath_to_string "@type" "" with
ffd6ed
-        | "network" -> Some Network
ffd6ed
-        | "bridge" -> Some Bridge
ffd6ed
-        | _ -> None in
ffd6ed
+        match xpath_string "@type" with
ffd6ed
+        | Some "network" -> Some Network
ffd6ed
+        | Some "bridge" -> Some Bridge
ffd6ed
+        | None | Some _ -> None in
ffd6ed
       match vnet_type with
ffd6ed
       | None -> ()
ffd6ed
       | Some vnet_type ->
ffd6ed
-        let vnet = xpath_to_string "source/@network | source/@bridge" "" in
ffd6ed
-        if vnet <> "" then (
ffd6ed
-          let nic = {
ffd6ed
-            s_mac = mac;
ffd6ed
-            s_vnet = vnet;
ffd6ed
-            s_vnet_orig = vnet;
ffd6ed
-            s_vnet_type = vnet_type
ffd6ed
-          } in
ffd6ed
-          nics := nic :: !nics
ffd6ed
-        )
ffd6ed
+        match xpath_string "source/@network | source/@bridge" with
ffd6ed
+        | None -> ()
ffd6ed
+        | Some vnet ->
ffd6ed
+           let nic = {
ffd6ed
+             s_mac = mac;
ffd6ed
+             s_vnet = vnet;
ffd6ed
+             s_vnet_orig = vnet;
ffd6ed
+             s_vnet_type = vnet_type
ffd6ed
+           } in
ffd6ed
+           nics := nic :: !nics
ffd6ed
     done;
ffd6ed
     List.rev !nics in
ffd6ed
 
ffd6ed
diff --git a/v2v/input_ova.ml b/v2v/input_ova.ml
ffd6ed
index ab8c27b..d1b7021 100644
ffd6ed
--- a/v2v/input_ova.ml
ffd6ed
+++ b/v2v/input_ova.ml
ffd6ed
@@ -180,41 +180,27 @@ object
ffd6ed
     Xml.xpath_register_ns xpathctx
ffd6ed
       "vssd" "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData";
ffd6ed
 
ffd6ed
-    let xpath_to_string expr default =
ffd6ed
-      let obj = Xml.xpath_eval_expression xpathctx expr in
ffd6ed
-      if Xml.xpathobj_nr_nodes obj < 1 then default
ffd6ed
-      else (
ffd6ed
-        let node = Xml.xpathobj_node obj 0 in
ffd6ed
-        Xml.node_as_string node
ffd6ed
-      )
ffd6ed
-    and xpath_to_int expr default =
ffd6ed
-      let obj = Xml.xpath_eval_expression xpathctx expr in
ffd6ed
-      if Xml.xpathobj_nr_nodes obj < 1 then default
ffd6ed
-      else (
ffd6ed
-        let node = Xml.xpathobj_node obj 0 in
ffd6ed
-        let str = Xml.node_as_string node in
ffd6ed
-        try int_of_string str
ffd6ed
-        with Failure "int_of_string" ->
ffd6ed
-          error (f_"expecting XML expression to return an integer (expression: %s)")
ffd6ed
-            expr
ffd6ed
-      )
ffd6ed
-    in
ffd6ed
+    let xpath_string = xpath_string xpathctx
ffd6ed
+    and xpath_int = xpath_int xpathctx
ffd6ed
+    and xpath_string_default = xpath_string_default xpathctx
ffd6ed
+    and xpath_int_default = xpath_int_default xpathctx in
ffd6ed
 
ffd6ed
     (* Search for vm name. *)
ffd6ed
     let name =
ffd6ed
-      xpath_to_string "/ovf:Envelope/ovf:VirtualSystem/ovf:Name/text()" "" in
ffd6ed
-    if name = "" then
ffd6ed
-      error (f_"could not parse ovf:Name from OVF document");
ffd6ed
+      match xpath_string "/ovf:Envelope/ovf:VirtualSystem/ovf:Name/text()" with
ffd6ed
+      | None | Some "" ->
ffd6ed
+        error (f_"could not parse ovf:Name from OVF document")
ffd6ed
+      | Some name -> name in
ffd6ed
 
ffd6ed
     (* Search for memory. *)
ffd6ed
-    let memory = xpath_to_int "/ovf:Envelope/ovf:VirtualSystem/ovf:VirtualHardwareSection/ovf:Item[rasd:ResourceType/text()=4]/rasd:VirtualQuantity/text()" (1024 * 1024) in
ffd6ed
+    let memory = xpath_int_default "/ovf:Envelope/ovf:VirtualSystem/ovf:VirtualHardwareSection/ovf:Item[rasd:ResourceType/text()=4]/rasd:VirtualQuantity/text()" (1024 * 1024) in
ffd6ed
     let memory = Int64.of_int (memory * 1024 * 1024) in
ffd6ed
 
ffd6ed
     (* Search for number of vCPUs. *)
ffd6ed
-    let vcpu = xpath_to_int "/ovf:Envelope/ovf:VirtualSystem/ovf:VirtualHardwareSection/ovf:Item[rasd:ResourceType/text()=3]/rasd:VirtualQuantity/text()" 1 in
ffd6ed
+    let vcpu = xpath_int_default "/ovf:Envelope/ovf:VirtualSystem/ovf:VirtualHardwareSection/ovf:Item[rasd:ResourceType/text()=3]/rasd:VirtualQuantity/text()" 1 in
ffd6ed
 
ffd6ed
     (* BIOS or EFI firmware? *)
ffd6ed
-    let firmware = xpath_to_string "/ovf:Envelope/ovf:VirtualSystem/ovf:VirtualHardwareSection/vmw:Config[@vmw:key=\"firmware\"]/@vmw:value" "bios" in
ffd6ed
+    let firmware = xpath_string_default "/ovf:Envelope/ovf:VirtualSystem/ovf:VirtualHardwareSection/vmw:Config[@vmw:key=\"firmware\"]/@vmw:value" "bios" in
ffd6ed
     let firmware =
ffd6ed
       match firmware with
ffd6ed
       | "bios" -> BIOS
ffd6ed
@@ -225,16 +211,16 @@ object
ffd6ed
     (* Helper function to return the parent controller of a disk. *)
ffd6ed
     let parent_controller id =
ffd6ed
       let expr = sprintf "/ovf:Envelope/ovf:VirtualSystem/ovf:VirtualHardwareSection/ovf:Item[rasd:InstanceID/text()=%d]/rasd:ResourceType/text()" id in
ffd6ed
-      let controller = xpath_to_int expr 0 in
ffd6ed
+      let controller = xpath_int expr in
ffd6ed
 
ffd6ed
       (* 6: iscsi controller, 5: ide *)
ffd6ed
       match controller with
ffd6ed
-      | 6 -> Some Source_SCSI
ffd6ed
-      | 5 -> Some Source_IDE
ffd6ed
-      | 0 ->
ffd6ed
+      | Some 6 -> Some Source_SCSI
ffd6ed
+      | Some 5 -> Some Source_IDE
ffd6ed
+      | None ->
ffd6ed
         warning ~prog (f_"ova disk has no parent controller, please report this as a bug supplying the *.ovf file extracted from the ova");
ffd6ed
         None
ffd6ed
-      | _ ->
ffd6ed
+      | Some controller ->
ffd6ed
         warning ~prog (f_"ova disk has an unknown VMware controller type (%d), please report this as a bug supplying the *.ovf file extracted from the ova")
ffd6ed
           controller;
ffd6ed
         None
ffd6ed
@@ -251,27 +237,32 @@ object
ffd6ed
         Xml.xpathctx_set_current_context xpathctx n;
ffd6ed
 
ffd6ed
         (* XXX We assume the OVF lists these in order.
ffd6ed
-        let address = xpath_to_int "rasd:AddressOnParent/text()" 0 in
ffd6ed
+        let address = xpath_int "rasd:AddressOnParent/text()" in
ffd6ed
         *)
ffd6ed
 
ffd6ed
         (* Find the parent controller. *)
ffd6ed
-        let parent_id = xpath_to_int "rasd:Parent/text()" 0 in
ffd6ed
+        let parent_id = xpath_int "rasd:Parent/text()" in
ffd6ed
         let controller =
ffd6ed
           match parent_id with
ffd6ed
-          | 0 -> None
ffd6ed
-          | id -> parent_controller id in
ffd6ed
+          | None -> None
ffd6ed
+          | Some id -> parent_controller id in
ffd6ed
 
ffd6ed
         Xml.xpathctx_set_current_context xpathctx n;
ffd6ed
-        let file_id = xpath_to_string "rasd:HostResource/text()" "" in
ffd6ed
+        let file_id = xpath_string_default "rasd:HostResource/text()" "" in
ffd6ed
         let rex = Str.regexp "^ovf:/disk/\\(.*\\)" in
ffd6ed
         if Str.string_match rex file_id 0 then (
ffd6ed
           (* Chase the references through to the actual file name. *)
ffd6ed
           let file_id = Str.matched_group 1 file_id in
ffd6ed
           let expr = sprintf "/ovf:Envelope/ovf:DiskSection/ovf:Disk[@ovf:diskId='%s']/@ovf:fileRef" file_id in
ffd6ed
-          let file_ref = xpath_to_string expr "" in
ffd6ed
-          if file_ref == "" then error (f_"error parsing disk fileRef");
ffd6ed
+          let file_ref =
ffd6ed
+            match xpath_string expr with
ffd6ed
+            | None -> error (f_"error parsing disk fileRef")
ffd6ed
+            | Some s -> s in
ffd6ed
           let expr = sprintf "/ovf:Envelope/ovf:References/ovf:File[@ovf:id='%s']/@ovf:href" file_ref in
ffd6ed
-          let filename = xpath_to_string expr "" in
ffd6ed
+          let filename =
ffd6ed
+            match xpath_string expr with
ffd6ed
+            | None -> error (f_"no href in ovf:File (id=%s)") file_ref
ffd6ed
+            | Some s -> s in
ffd6ed
 
ffd6ed
           (* Does the file exist and is it readable? *)
ffd6ed
           let filename = exploded // filename in
ffd6ed
@@ -318,19 +309,22 @@ object
ffd6ed
       for i = 0 to nr_nodes-1 do
ffd6ed
         let n = Xml.xpathobj_node obj i in
ffd6ed
         Xml.xpathctx_set_current_context xpathctx n;
ffd6ed
-        let id = xpath_to_int "rasd:ResourceType/text()" 0 in
ffd6ed
-        assert (id = 14 || id = 15 || id = 16);
ffd6ed
+        let id =
ffd6ed
+          match xpath_int "rasd:ResourceType/text()" with
ffd6ed
+          | None -> assert false
ffd6ed
+          | Some (14|15|16 as i) -> i
ffd6ed
+          | Some _ -> assert false in
ffd6ed
 
ffd6ed
         (* XXX We assume the OVF lists these in order.
ffd6ed
-        let address = xpath_to_int "rasd:AddressOnParent/text()" 0 in
ffd6ed
+        let address = xpath_int "rasd:AddressOnParent/text()" in
ffd6ed
         *)
ffd6ed
 
ffd6ed
         (* Find the parent controller. *)
ffd6ed
-        let parent_id = xpath_to_int "rasd:Parent/text()" 0 in
ffd6ed
+        let parent_id = xpath_int "rasd:Parent/text()" in
ffd6ed
         let controller =
ffd6ed
           match parent_id with
ffd6ed
-          | 0 -> None
ffd6ed
-          | id -> parent_controller id in
ffd6ed
+          | None -> None
ffd6ed
+          | Some id -> parent_controller id in
ffd6ed
 
ffd6ed
         let typ =
ffd6ed
           match id with
ffd6ed
@@ -352,7 +346,8 @@ object
ffd6ed
     for i = 0 to nr_nodes-1 do
ffd6ed
       let n = Xml.xpathobj_node obj i in
ffd6ed
       Xml.xpathctx_set_current_context xpathctx n;
ffd6ed
-      let vnet = xpath_to_string "rasd:ElementName/text()" (sprintf"eth%d" i) in
ffd6ed
+      let vnet =
ffd6ed
+        xpath_string_default "rasd:ElementName/text()" (sprintf"eth%d" i) in
ffd6ed
       let nic = {
ffd6ed
         s_mac = None;
ffd6ed
         s_vnet = vnet;
ffd6ed
diff --git a/v2v/output_libvirt.ml b/v2v/output_libvirt.ml
ffd6ed
index de4aeb4..16510d2 100644
ffd6ed
--- a/v2v/output_libvirt.ml
ffd6ed
+++ b/v2v/output_libvirt.ml
ffd6ed
@@ -350,23 +350,18 @@ class output_libvirt verbose oc output_pool = object
ffd6ed
     let xml = Domainxml.pool_dumpxml ?conn:oc output_pool in
ffd6ed
     let doc = Xml.parse_memory xml in
ffd6ed
     let xpathctx = Xml.xpath_new_context doc in
ffd6ed
-
ffd6ed
-    let xpath_to_string expr default =
ffd6ed
-      let obj = Xml.xpath_eval_expression xpathctx expr in
ffd6ed
-      if Xml.xpathobj_nr_nodes obj < 1 then default
ffd6ed
-      else (
ffd6ed
-        let node = Xml.xpathobj_node obj 0 in
ffd6ed
-        Xml.node_as_string node
ffd6ed
-      )
ffd6ed
-    in
ffd6ed
+    let xpath_string = xpath_string xpathctx in
ffd6ed
 
ffd6ed
     (* We can only output to a pool of type 'dir' (directory). *)
ffd6ed
-    let pool_type = xpath_to_string "/pool/@type" "" in
ffd6ed
-    if pool_type <> "dir" then
ffd6ed
+    if xpath_string "/pool/@type" <> Some "dir" then
ffd6ed
       error (f_"-o libvirt: output pool '%s' is not a directory (type='dir').  See virt-v2v(1) section \"OUTPUT TO LIBVIRT\"") output_pool;
ffd6ed
-    let target_path = xpath_to_string "/pool/target/path/text()" "" in
ffd6ed
-    if target_path = "" || not (is_directory target_path) then
ffd6ed
-      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;
ffd6ed
+    let target_path =
ffd6ed
+      match xpath_string "/pool/target/path/text()" with
ffd6ed
+      | None ->
ffd6ed
+         error (f_"-o libvirt: output pool '%s' does not have /pool/target/path element.  See virt-v2v(1) section \"OUTPUT TO LIBVIRT\"") output_pool
ffd6ed
+      | Some dir when not (is_directory dir) ->
ffd6ed
+         error (f_"-o libvirt: output pool '%s' has type='dir' but the /pool/target/path element is not a local directory.  See virt-v2v(1) section \"OUTPUT TO LIBVIRT\"") output_pool
ffd6ed
+      | Some dir -> dir in
ffd6ed
 
ffd6ed
     (* Set up the targets. *)
ffd6ed
     List.map (
ffd6ed
-- 
ffd6ed
1.8.3.1
ffd6ed