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