mrc0mmand / rpms / libguestfs

Forked from rpms/libguestfs 3 years ago
Clone

Blame SOURCES/0021-v2v-i-libvirtxml-Fix-handling-of-nbd-sources-RHBZ-11.patch

0d20ef
From ab0f4d6925bfac4cb65c6d6e6e050d5366a8163b Mon Sep 17 00:00:00 2001
0d20ef
From: "Richard W.M. Jones" <rjones@redhat.com>
0d20ef
Date: Wed, 22 Oct 2014 12:00:36 +0100
0d20ef
Subject: [PATCH] v2v: -i libvirtxml: Fix handling of nbd sources
0d20ef
 (RHBZ#1153589).
0d20ef
0d20ef
Previously I modified the parse_libvirt_xml function to get rid of the
0d20ef
awkward 'map_source*' functions, and have the callers map over and
0d20ef
modify the source disks afterwards.  However this broke the case where
0d20ef
an "nbd:..." URL was returned by parse_libvirt_xml, since the callers
0d20ef
might try to map this URL (eg. turning it into an absolute path).
0d20ef
This broke virt-p2v specifically.
0d20ef
0d20ef
This commit changes parse_libvirt_xml to return a list of tuples
0d20ef
containing disk information, giving the callers more information with
0d20ef
which to do the mapping.
0d20ef
0d20ef
This fixes commit 3596165282ccf2c5896894ec4e9a71c6da788463.
0d20ef
0d20ef
(cherry picked from commit ad78d1492b02eaf5d810e2f9d012a5fed4f4124b)
0d20ef
---
0d20ef
 v2v/input_libvirt_other.ml         |  5 ++++-
ffd6ed
 v2v/input_libvirt_vcenter_https.ml | 44 ++++++++++++++++++++++++--------------
0d20ef
 v2v/input_libvirt_xen_ssh.ml       | 10 ++++++---
ffd6ed
 v2v/input_libvirtxml.ml            | 38 +++++++++++++++++++++-----------
ffd6ed
 v2v/input_libvirtxml.mli           | 17 +++++++++++++--
ffd6ed
 5 files changed, 80 insertions(+), 34 deletions(-)
0d20ef
0d20ef
diff --git a/v2v/input_libvirt_other.ml b/v2v/input_libvirt_other.ml
0d20ef
index a771aa1..9f3eedb 100644
0d20ef
--- a/v2v/input_libvirt_other.ml
0d20ef
+++ b/v2v/input_libvirt_other.ml
0d20ef
@@ -70,7 +70,10 @@ object
0d20ef
      *)
0d20ef
     let xml = Domainxml.dumpxml ?conn:libvirt_uri guest in
0d20ef
 
0d20ef
-    Input_libvirtxml.parse_libvirt_xml ~verbose xml
0d20ef
+    let source, disks = Input_libvirtxml.parse_libvirt_xml ~verbose xml in
0d20ef
+    let disks =
0d20ef
+      List.map (fun { Input_libvirtxml.p_source_disk = disk } -> disk) disks in
0d20ef
+    { source with s_disks = disks }
0d20ef
 end
0d20ef
 
0d20ef
 let input_libvirt_other = new input_libvirt_other
0d20ef
diff --git a/v2v/input_libvirt_vcenter_https.ml b/v2v/input_libvirt_vcenter_https.ml
0d20ef
index 71c2edd..56097e0 100644
0d20ef
--- a/v2v/input_libvirt_vcenter_https.ml
0d20ef
+++ b/v2v/input_libvirt_vcenter_https.ml
0d20ef
@@ -24,6 +24,7 @@ open Common_utils
0d20ef
 open Types
0d20ef
 open Xml
0d20ef
 open Utils
0d20ef
+open Input_libvirtxml
0d20ef
 open Input_libvirt_other
0d20ef
 
0d20ef
 open Printf
0d20ef
@@ -235,20 +236,28 @@ object
0d20ef
      * that the domain is not running.  (RHBZ#1138586)
0d20ef
      *)
0d20ef
     let xml = Domainxml.dumpxml ?conn:libvirt_uri guest in
0d20ef
-    let { s_disks = disks } as source =
0d20ef
-      Input_libvirtxml.parse_libvirt_xml ~verbose xml in
0d20ef
+    let source, disks = parse_libvirt_xml ~verbose xml in
0d20ef
 
0d20ef
     (* Save the original source paths, so that we can remap them again
0d20ef
      * in [#adjust_overlay_parameters].
0d20ef
      *)
0d20ef
     List.iter (
0d20ef
-      fun { s_disk_id = id; s_qemu_uri = path } ->
0d20ef
-        Hashtbl.add saved_source_paths id path
0d20ef
+      function
0d20ef
+      | { p_source = P_source_dev _ } ->
0d20ef
+        (* Should never happen ... *)
0d20ef
+        error (f_"source disk has <source dev=...> attribute in XML")
0d20ef
+      | { p_source_disk = { s_disk_id = id }; p_source = P_dont_rewrite } ->
0d20ef
+        Hashtbl.add saved_source_paths id None
0d20ef
+      | { p_source_disk = { s_disk_id = id }; p_source = P_source_file path } ->
0d20ef
+        Hashtbl.add saved_source_paths id (Some path)
0d20ef
     ) disks;
0d20ef
 
0d20ef
+    let readahead = readahead_for_conversion in
0d20ef
     let disks = List.map (
0d20ef
-      fun ({ s_qemu_uri = path } as disk) ->
0d20ef
-        let readahead = readahead_for_conversion in
0d20ef
+      function
0d20ef
+      | { p_source = P_source_dev _ } -> assert false
0d20ef
+      | { p_source_disk = disk; p_source = P_dont_rewrite } -> disk
0d20ef
+      | { p_source_disk = disk; p_source = P_source_file path } ->
0d20ef
         let qemu_uri = map_source_to_uri ?readahead
0d20ef
 	  verbose parsed_uri scheme server path in
0d20ef
 
0d20ef
@@ -265,18 +274,21 @@ object
0d20ef
     let orig_path =
0d20ef
       try Hashtbl.find saved_source_paths overlay.ov_source.s_disk_id
0d20ef
       with Not_found -> failwith "internal error in adjust_overlay_parameters" in
0d20ef
-    let backing_qemu_uri =
0d20ef
+    match orig_path with
0d20ef
+    | None -> ()
0d20ef
+    | Some orig_path ->
0d20ef
       let readahead = readahead_for_copying in
0d20ef
-      map_source_to_uri ?readahead
0d20ef
-        verbose parsed_uri scheme server orig_path in
ffd6ed
+      let backing_qemu_uri =
ffd6ed
+        map_source_to_uri ?readahead
ffd6ed
+          verbose parsed_uri scheme server orig_path in
ffd6ed
 
0d20ef
-    (* Rebase the qcow2 overlay to adjust the readahead parameter. *)
0d20ef
-    let cmd =
0d20ef
-      sprintf "qemu-img rebase -u -b %s %s"
0d20ef
-        (quote backing_qemu_uri) (quote overlay.ov_overlay_file) in
0d20ef
-    if verbose then printf "%s\n%!" cmd;
0d20ef
-    if Sys.command cmd <> 0 then
0d20ef
-      warning ~prog (f_"qemu-img rebase failed (ignored)")
0d20ef
+      (* Rebase the qcow2 overlay to adjust the readahead parameter. *)
0d20ef
+      let cmd =
0d20ef
+        sprintf "qemu-img rebase -u -b %s %s"
0d20ef
+          (quote backing_qemu_uri) (quote overlay.ov_overlay_file) in
0d20ef
+      if verbose then printf "%s\n%!" cmd;
0d20ef
+      if Sys.command cmd <> 0 then
0d20ef
+        warning ~prog (f_"qemu-img rebase failed (ignored)")
0d20ef
 end
0d20ef
 
0d20ef
 let input_libvirt_vcenter_https = new input_libvirt_vcenter_https
0d20ef
diff --git a/v2v/input_libvirt_xen_ssh.ml b/v2v/input_libvirt_xen_ssh.ml
0d20ef
index 8b836a5..e1600a0 100644
0d20ef
--- a/v2v/input_libvirt_xen_ssh.ml
0d20ef
+++ b/v2v/input_libvirt_xen_ssh.ml
0d20ef
@@ -24,6 +24,7 @@ open Common_utils
0d20ef
 open Types
0d20ef
 open Xml
0d20ef
 open Utils
0d20ef
+open Input_libvirtxml
0d20ef
 open Input_libvirt_other
0d20ef
 
0d20ef
 open Printf
0d20ef
@@ -45,8 +46,7 @@ object
0d20ef
      * that the domain is not running.  (RHBZ#1138586)
0d20ef
      *)
0d20ef
     let xml = Domainxml.dumpxml ?conn:libvirt_uri guest in
0d20ef
-    let { s_disks = disks } as source =
0d20ef
-      Input_libvirtxml.parse_libvirt_xml ~verbose xml in
0d20ef
+    let source, disks = parse_libvirt_xml ~verbose xml in
0d20ef
 
0d20ef
     (* Map the <source/> filename (which is relative to the remote
0d20ef
      * Xen server) to an ssh URI.  This is a JSON URI looking something
0d20ef
@@ -61,7 +61,11 @@ object
0d20ef
      *   "file.host_key_check": "no"
0d20ef
      *)
0d20ef
     let disks = List.map (
0d20ef
-      fun ({ s_qemu_uri = path } as disk) ->
0d20ef
+      function
0d20ef
+      | { p_source_disk = disk; p_source = P_dont_rewrite } ->
0d20ef
+        disk
0d20ef
+      | { p_source_disk = disk; p_source = P_source_dev path }
0d20ef
+      | { p_source_disk = disk; p_source = P_source_file path } ->
0d20ef
         (* Construct the JSON parameters. *)
0d20ef
         let json_params = [
0d20ef
           "file.driver", JSON.String "ssh";
0d20ef
diff --git a/v2v/input_libvirtxml.ml b/v2v/input_libvirtxml.ml
0d20ef
index 0cfd75c..c71260f 100644
0d20ef
--- a/v2v/input_libvirtxml.ml
0d20ef
+++ b/v2v/input_libvirtxml.ml
0d20ef
@@ -24,6 +24,15 @@ open Common_utils
0d20ef
 open Types
0d20ef
 open Utils
0d20ef
 
0d20ef
+type parsed_disk = {
0d20ef
+  p_source_disk : source_disk;
0d20ef
+  p_source : parsed_source;
0d20ef
+}
0d20ef
+and parsed_source =
0d20ef
+| P_source_dev of string
0d20ef
+| P_source_file of string
0d20ef
+| P_dont_rewrite
0d20ef
+
0d20ef
 let parse_libvirt_xml ~verbose xml =
0d20ef
   if verbose then
0d20ef
     printf "libvirt xml is:\n%s\n" xml;
0d20ef
@@ -105,12 +114,13 @@ let parse_libvirt_xml ~verbose xml =
0d20ef
     let get_disks, add_disk =
0d20ef
       let disks = ref [] and i = ref 0 in
0d20ef
       let get_disks () = List.rev !disks in
0d20ef
-      let add_disk qemu_uri format target_dev =
0d20ef
+      let add_disk qemu_uri format target_dev p_source =
0d20ef
         incr i;
0d20ef
         disks :=
0d20ef
-          { s_disk_id = !i;
0d20ef
-            s_qemu_uri = qemu_uri; s_format = format;
0d20ef
-            s_target_dev = target_dev } :: !disks
0d20ef
+          { p_source_disk = { s_disk_id = !i;
0d20ef
+                              s_qemu_uri = qemu_uri; s_format = format;
0d20ef
+                              s_target_dev = target_dev };
0d20ef
+            p_source = p_source } :: !disks
0d20ef
       in
0d20ef
       get_disks, add_disk
0d20ef
     in
0d20ef
@@ -141,11 +151,11 @@ let parse_libvirt_xml ~verbose xml =
0d20ef
       | "block" ->
0d20ef
         let path = xpath_to_string "source/@dev" "" in
0d20ef
         if path <> "" then
0d20ef
-          add_disk path format target_dev
0d20ef
+          add_disk path format target_dev (P_source_dev path)
0d20ef
       | "file" ->
0d20ef
         let path = xpath_to_string "source/@file" "" in
0d20ef
         if path <> "" then
0d20ef
-          add_disk path format target_dev
0d20ef
+          add_disk path format target_dev (P_source_file path)
0d20ef
       | "network" ->
0d20ef
         (* We only handle <source protocol="nbd"> here, and that is
0d20ef
          * intended only for virt-p2v.  Any other network disk is
0d20ef
@@ -160,7 +170,7 @@ let parse_libvirt_xml ~verbose xml =
0d20ef
              * XXX Quoting, although it's not needed for virt-p2v.
0d20ef
              *)
0d20ef
             let path = sprintf "nbd:%s:%d" host port in
0d20ef
-            add_disk path format target_dev
0d20ef
+            add_disk path format target_dev (P_dont_rewrite)
0d20ef
           )
0d20ef
         | "" -> ()
0d20ef
         | protocol ->
0d20ef
@@ -236,17 +246,18 @@ let parse_libvirt_xml ~verbose xml =
0d20ef
     done;
0d20ef
     List.rev !nics in
0d20ef
 
0d20ef
-  {
0d20ef
+  ({
0d20ef
     s_dom_type = dom_type;
0d20ef
     s_name = name; s_orig_name = name;
0d20ef
     s_memory = memory;
0d20ef
     s_vcpu = vcpu;
0d20ef
     s_features = features;
0d20ef
     s_display = display;
0d20ef
-    s_disks = disks;
0d20ef
+    s_disks = [];
0d20ef
     s_removables = removables;
0d20ef
     s_nics = nics;
0d20ef
-  }
0d20ef
+   },
0d20ef
+   disks)
0d20ef
 
0d20ef
 class input_libvirtxml verbose file =
0d20ef
 object
0d20ef
@@ -257,7 +268,7 @@ object
0d20ef
   method source () =
0d20ef
     let xml = read_whole_file file in
0d20ef
 
0d20ef
-    let { s_disks = disks } as source = parse_libvirt_xml ~verbose xml in
0d20ef
+    let source, disks = parse_libvirt_xml ~verbose xml in
0d20ef
 
0d20ef
     (* When reading libvirt XML from a file (-i libvirtxml) we allow
0d20ef
      * paths to disk images in the libvirt XML to be relative (to the XML
0d20ef
@@ -267,7 +278,10 @@ object
0d20ef
      *)
0d20ef
     let dir = Filename.dirname (absolute_path file) in
0d20ef
     let disks = List.map (
0d20ef
-      fun ({ s_qemu_uri = path } as disk) ->
0d20ef
+      function
0d20ef
+      | { p_source_disk = disk; p_source = P_dont_rewrite } -> disk
0d20ef
+      | { p_source_disk = disk; p_source = P_source_dev _ } -> disk
0d20ef
+      | { p_source_disk = disk; p_source = P_source_file path } ->
0d20ef
         let path =
0d20ef
           if not (Filename.is_relative path) then path else dir // path in
0d20ef
         { disk with s_qemu_uri = path }
0d20ef
diff --git a/v2v/input_libvirtxml.mli b/v2v/input_libvirtxml.mli
0d20ef
index 5c10df0..e450899 100644
0d20ef
--- a/v2v/input_libvirtxml.mli
0d20ef
+++ b/v2v/input_libvirtxml.mli
0d20ef
@@ -18,8 +18,21 @@
0d20ef
 
0d20ef
 (** [-i libvirtxml] source. *)
0d20ef
 
0d20ef
-val parse_libvirt_xml : verbose:bool -> string -> Types.source
0d20ef
-(** Take libvirt XML and parse it into a {!Types.source} structure.
0d20ef
+type parsed_disk = {
0d20ef
+  p_source_disk : Types.source_disk;    (** Source disk. *)
0d20ef
+  p_source : parsed_source;         (** <source dev|file attribute> *)
0d20ef
+}
0d20ef
+and parsed_source =
0d20ef
+| P_source_dev of string             (** <source dev> *)
0d20ef
+| P_source_file of string            (** <source file> *)
0d20ef
+| P_dont_rewrite                     (** s_qemu_uri is already set. *)
0d20ef
+
0d20ef
+val parse_libvirt_xml : verbose:bool -> string -> Types.source * parsed_disk list
0d20ef
+(** Take libvirt XML and parse it into a {!Types.source} structure and a
0d20ef
+    list of source disks.
0d20ef
+
0d20ef
+    {b Note} the [source.s_disks] field is an empty list.  The caller
0d20ef
+    must map over the parsed disks and update the [source.s_disks] field.
0d20ef
 
0d20ef
     This function is also used by {!Input_libvirt}, hence it is
0d20ef
     exported. *)
0d20ef
-- 
0d20ef
1.8.3.1
0d20ef