Blame SOURCES/0018-v2v-Inline-and-simplify-Xen-and-vCenter-input-method.patch

0d20ef
From 9583ab8900194694359cbefe403209f73fd08a47 Mon Sep 17 00:00:00 2001
0d20ef
From: "Richard W.M. Jones" <rjones@redhat.com>
0d20ef
Date: Mon, 20 Oct 2014 20:41:29 +0100
0d20ef
Subject: [PATCH] v2v: Inline and simplify Xen and vCenter input methods.
0d20ef
0d20ef
Take the opportunity presented by the refactoring in the previous
0d20ef
commit to inline and simplify functions in these input subclasses.
0d20ef
0d20ef
This finally removes the map_source* functions.
0d20ef
0d20ef
(cherry picked from commit b8f826b7ac1e7f90f670f474c3582b56063cdef6)
0d20ef
---
0d20ef
 v2v/input_libvirt_vcenter_https.ml | 249 +++++++++++++++++++------------------
0d20ef
 v2v/input_libvirt_xen_ssh.ml       |  93 +++++++-------
0d20ef
 2 files changed, 171 insertions(+), 171 deletions(-)
0d20ef
0d20ef
diff --git a/v2v/input_libvirt_vcenter_https.ml b/v2v/input_libvirt_vcenter_https.ml
0d20ef
index 7dde9be..5d98a86 100644
0d20ef
--- a/v2v/input_libvirt_vcenter_https.ml
0d20ef
+++ b/v2v/input_libvirt_vcenter_https.ml
0d20ef
@@ -28,11 +28,107 @@ open Input_libvirt_other
0d20ef
 
0d20ef
 open Printf
0d20ef
 
0d20ef
-let esx_re = Str.regexp "^\\[\\(.*\\)\\] \\(.*\\)\\.vmdk$"
0d20ef
+(* Return the session cookie.  It is memoized, so you can call this
0d20ef
+ * as often as required.
0d20ef
+ *)
0d20ef
+let get_session_cookie =
0d20ef
+  let session_cookie = ref "" in
0d20ef
+  fun verbose scheme uri sslverify url ->
0d20ef
+    if !session_cookie <> "" then
0d20ef
+      Some !session_cookie
0d20ef
+    else (
0d20ef
+      let cmd =
0d20ef
+        sprintf "curl -s%s%s%s -I %s ||:"
0d20ef
+          (if not sslverify then " --insecure" else "")
0d20ef
+          (match uri.uri_user with Some _ -> " -u" | None -> "")
0d20ef
+          (match uri.uri_user with Some user -> " " ^ quote user | None -> "")
0d20ef
+          (quote url) in
0d20ef
+      let lines = external_command ~prog cmd in
0d20ef
+
0d20ef
+      let dump_response chan =
0d20ef
+        fprintf chan "%s\n" cmd;
0d20ef
+        List.iter (fun x -> fprintf chan "%s\n" x) lines
0d20ef
+      in
0d20ef
+
0d20ef
+      if verbose then dump_response stdout;
0d20ef
+
0d20ef
+      (* Look for the last HTTP/x.y NNN status code in the output. *)
0d20ef
+      let status = ref "" in
0d20ef
+      List.iter (
0d20ef
+        fun line ->
0d20ef
+          let len = String.length line in
0d20ef
+          if len >= 12 && String.sub line 0 5 = "HTTP/" then
0d20ef
+            status := String.sub line 9 3
0d20ef
+      ) lines;
0d20ef
+      let status = !status in
0d20ef
+      if status = "" then (
0d20ef
+        dump_response stderr;
0d20ef
+        error (f_"esx: no status code in output of 'curl' command.  Is 'curl' installed?")
0d20ef
+      );
0d20ef
+
0d20ef
+      if status = "401" then (
0d20ef
+        dump_response stderr;
0d20ef
+        if uri.uri_user <> None then
0d20ef
+          error (f_"esx: incorrect username or password")
0d20ef
+        else
0d20ef
+          error (f_"esx: incorrect username or password.  You might need to specify the username in the URI like this: %s://USERNAME@[etc]")
0d20ef
+            scheme
0d20ef
+      );
0d20ef
+
0d20ef
+      if status = "404" then (
0d20ef
+        dump_response stderr;
0d20ef
+        error (f_"esx: URL not found: %s") url
0d20ef
+      );
0d20ef
+
0d20ef
+      if status <> "200" then (
0d20ef
+        dump_response stderr;
0d20ef
+        error (f_"esx: invalid response from server")
0d20ef
+      );
0d20ef
+
0d20ef
+      (* Get the cookie. *)
0d20ef
+      List.iter (
0d20ef
+        fun line ->
0d20ef
+          let len = String.length line in
0d20ef
+          if len >= 12 && String.sub line 0 12 = "Set-Cookie: " then (
0d20ef
+            let line = String.sub line 12 (len-12) in
0d20ef
+            let cookie, _ = string_split ";" line in
0d20ef
+            session_cookie := cookie
0d20ef
+          )
0d20ef
+      ) lines;
0d20ef
+      if !session_cookie = "" then (
0d20ef
+        dump_response stderr;
0d20ef
+        warning ~prog (f_"esx: could not read session cookie from the vCenter Server, conversion may consume all sessions on the server and fail part way through");
0d20ef
+        None
0d20ef
+      )
0d20ef
+      else
0d20ef
+        Some !session_cookie
0d20ef
+    )
0d20ef
 
0d20ef
-let session_cookie = ref ""
0d20ef
+(* Helper function to extract the datacenter from a URI. *)
0d20ef
+let get_datacenter uri scheme =
0d20ef
+  let default_dc = "ha-datacenter" in
0d20ef
+  match scheme with
0d20ef
+  | "vpx" ->           (* Hopefully the first part of the path. *)
0d20ef
+    (match uri.uri_path with
0d20ef
+    | None ->
0d20ef
+      warning ~prog (f_"esx: URI (-ic parameter) contains no path, so we cannot determine the datacenter name");
0d20ef
+      default_dc
0d20ef
+    | Some path ->
0d20ef
+      let path =
0d20ef
+        let len = String.length path in
0d20ef
+        if len > 0 && path.[0] = '/' then
0d20ef
+          String.sub path 1 (len-1)
0d20ef
+        else path in
0d20ef
+      let len =
0d20ef
+        try String.index path '/' with Not_found -> String.length path in
0d20ef
+      String.sub path 0 len
0d20ef
+    );
0d20ef
+  | "esx" -> (* Connecting to an ESXi hypervisor directly, so it's fixed. *)
0d20ef
+    default_dc
0d20ef
+  | _ ->                            (* Don't know, so guess. *)
0d20ef
+    default_dc
0d20ef
 
0d20ef
-(* Map an ESX <source/> to a qemu URI using the cURL driver
0d20ef
+(* Map the <source/> string to a qemu URI using the cURL driver
0d20ef
  * in qemu.  The 'path' will be something like
0d20ef
  *
0d20ef
  *   "[datastore1] Fedora 20/Fedora 20.vmdk"
0d20ef
@@ -46,9 +142,11 @@ let session_cookie = ref ""
0d20ef
  * XXX Need to handle templates.  The file is called "-delta.vmdk" in
0d20ef
  * place of "-flat.vmdk".
0d20ef
  *)
0d20ef
-let rec map_path_to_uri verbose uri scheme server ?readahead path format =
0d20ef
-  if not (Str.string_match esx_re path 0) then
0d20ef
-    path, format
0d20ef
+let source_re = Str.regexp "^\\[\\(.*\\)\\] \\(.*\\)\\.vmdk$"
0d20ef
+
0d20ef
+let map_source_to_uri ?readahead verbose uri scheme server path =
0d20ef
+  if not (Str.string_match source_re path 0) then
0d20ef
+    path
0d20ef
   else (
0d20ef
     let datastore = Str.matched_group 1 path
0d20ef
     and path = Str.matched_group 2 path in
0d20ef
@@ -111,105 +209,7 @@ let rec map_path_to_uri verbose uri scheme server ?readahead path format =
0d20ef
      *)
0d20ef
     let qemu_uri = "json: " ^ JSON.string_of_doc json_params in
0d20ef
 
0d20ef
-    (* The libvirt ESX driver doesn't normally specify a format, but
0d20ef
-     * the format of the -flat file is *always* raw, so force it here.
0d20ef
-     *)
0d20ef
-    qemu_uri, Some "raw"
0d20ef
-  )
0d20ef
-
0d20ef
-and get_datacenter uri scheme =
0d20ef
-  let default_dc = "ha-datacenter" in
0d20ef
-  match scheme with
0d20ef
-  | "vpx" ->           (* Hopefully the first part of the path. *)
0d20ef
-    (match uri.uri_path with
0d20ef
-    | None ->
0d20ef
-      warning ~prog (f_"esx: URI (-ic parameter) contains no path, so we cannot determine the datacenter name");
0d20ef
-      default_dc
0d20ef
-    | Some path ->
0d20ef
-      let path =
0d20ef
-        let len = String.length path in
0d20ef
-        if len > 0 && path.[0] = '/' then
0d20ef
-          String.sub path 1 (len-1)
0d20ef
-        else path in
0d20ef
-      let len =
0d20ef
-        try String.index path '/' with Not_found -> String.length path in
0d20ef
-      String.sub path 0 len
0d20ef
-    );
0d20ef
-  | "esx" -> (* Connecting to an ESXi hypervisor directly, so it's fixed. *)
0d20ef
-    default_dc
0d20ef
-  | _ ->                            (* Don't know, so guess. *)
0d20ef
-    default_dc
0d20ef
-
0d20ef
-and get_session_cookie verbose scheme uri sslverify url =
0d20ef
-  (* Memoize the session cookie. *)
0d20ef
-  if !session_cookie <> "" then
0d20ef
-    Some !session_cookie
0d20ef
-  else (
0d20ef
-    let cmd =
0d20ef
-      sprintf "curl -s%s%s%s -I %s ||:"
0d20ef
-        (if not sslverify then " --insecure" else "")
0d20ef
-        (match uri.uri_user with Some _ -> " -u" | None -> "")
0d20ef
-        (match uri.uri_user with Some user -> " " ^ quote user | None -> "")
0d20ef
-        (quote url) in
0d20ef
-    let lines = external_command ~prog cmd in
0d20ef
-
0d20ef
-    let dump_response chan =
0d20ef
-      fprintf chan "%s\n" cmd;
0d20ef
-      List.iter (fun x -> fprintf chan "%s\n" x) lines
0d20ef
-    in
0d20ef
-
0d20ef
-    if verbose then dump_response stdout;
0d20ef
-
0d20ef
-    (* Look for the last HTTP/x.y NNN status code in the output. *)
0d20ef
-    let status = ref "" in
0d20ef
-    List.iter (
0d20ef
-      fun line ->
0d20ef
-        let len = String.length line in
0d20ef
-        if len >= 12 && String.sub line 0 5 = "HTTP/" then
0d20ef
-          status := String.sub line 9 3
0d20ef
-    ) lines;
0d20ef
-    let status = !status in
0d20ef
-    if status = "" then (
0d20ef
-      dump_response stderr;
0d20ef
-      error (f_"esx: no status code in output of 'curl' command.  Is 'curl' installed?")
0d20ef
-    );
0d20ef
-
0d20ef
-    if status = "401" then (
0d20ef
-      dump_response stderr;
0d20ef
-      if uri.uri_user <> None then
0d20ef
-        error (f_"esx: incorrect username or password")
0d20ef
-      else
0d20ef
-        error (f_"esx: incorrect username or password.  You might need to specify the username in the URI like this: %s://USERNAME@[etc]")
0d20ef
-          scheme
0d20ef
-    );
0d20ef
-
0d20ef
-    if status = "404" then (
0d20ef
-      dump_response stderr;
0d20ef
-      error (f_"esx: URL not found: %s") url
0d20ef
-    );
0d20ef
-
0d20ef
-    if status <> "200" then (
0d20ef
-      dump_response stderr;
0d20ef
-      error (f_"esx: invalid response from server")
0d20ef
-    );
0d20ef
-
0d20ef
-    (* Get the cookie. *)
0d20ef
-    List.iter (
0d20ef
-      fun line ->
0d20ef
-        let len = String.length line in
0d20ef
-        if len >= 12 && String.sub line 0 12 = "Set-Cookie: " then (
0d20ef
-          let line = String.sub line 12 (len-12) in
0d20ef
-          let cookie, _ = string_split ";" line in
0d20ef
-          session_cookie := cookie
0d20ef
-        )
0d20ef
-    ) lines;
0d20ef
-    if !session_cookie = "" then (
0d20ef
-      dump_response stderr;
0d20ef
-      warning ~prog (f_"esx: could not read session cookie from the vCenter Server, conversion may consume all sessions on the server and fail part way through");
0d20ef
-      None
0d20ef
-    )
0d20ef
-    else
0d20ef
-      Some !session_cookie
0d20ef
+    qemu_uri
0d20ef
   )
0d20ef
 
0d20ef
 (* Subclass specialized for handling VMware vCenter over https. *)
0d20ef
@@ -218,11 +218,12 @@ class input_libvirt_vcenter_https
0d20ef
 object
0d20ef
   inherit input_libvirt verbose libvirt_uri guest
0d20ef
 
0d20ef
-  val mutable mapf = fun ?readahead uri format -> uri, format
0d20ef
-  val saved_uri = Hashtbl.create 13
0d20ef
+  val saved_source_paths = Hashtbl.create 13
0d20ef
 
0d20ef
   method source () =
0d20ef
-    if verbose then printf "input_libvirt_vcenter_https: source()\n%!";
0d20ef
+    if verbose then
0d20ef
+      printf "input_libvirt_vcenter_https: source: scheme %s server %s\n%!"
0d20ef
+        scheme server;
0d20ef
 
0d20ef
     error_if_libvirt_backend ();
0d20ef
 
0d20ef
@@ -233,38 +234,42 @@ object
0d20ef
     let { s_disks = disks } as source =
0d20ef
       Input_libvirtxml.parse_libvirt_xml ~verbose xml in
0d20ef
 
0d20ef
-    (* Save the mapf function and the original s_qemu_uri fields, so
0d20ef
-     * we can get them in the adjust_overlay_parameters method below.
0d20ef
+    (* Save the original source paths, so that we can remap them again
0d20ef
+     * in [#adjust_overlay_parameters].
0d20ef
      *)
0d20ef
-    mapf <- map_path_to_uri verbose parsed_uri scheme server;
0d20ef
     List.iter (
0d20ef
-      fun disk ->
0d20ef
-        Hashtbl.add saved_uri disk.s_disk_id (disk.s_qemu_uri, disk.s_format)
0d20ef
+      fun { s_disk_id = id; s_qemu_uri = path } ->
0d20ef
+        Hashtbl.add saved_source_paths id path
0d20ef
     ) disks;
0d20ef
 
0d20ef
     let disks = List.map (
0d20ef
-      fun ({ s_qemu_uri = uri; s_format = format } as disk) ->
0d20ef
-        let uri, format = mapf uri format in
0d20ef
-        { disk with s_qemu_uri = uri; s_format = format }
0d20ef
+      fun ({ s_qemu_uri = path } as disk) ->
0d20ef
+        let qemu_uri = map_source_to_uri verbose parsed_uri scheme server path in
0d20ef
+
0d20ef
+        (* The libvirt ESX driver doesn't normally specify a format, but
0d20ef
+         * the format of the -flat file is *always* raw, so force it here.
0d20ef
+         *)
0d20ef
+        { disk with s_qemu_uri = qemu_uri; s_format = Some "raw" }
0d20ef
     ) disks in
0d20ef
 
0d20ef
     { source with s_disks = disks }
0d20ef
 
0d20ef
   (* See RHBZ#1151033 and RHBZ#1153589 for why this is necessary. *)
0d20ef
   method adjust_overlay_parameters overlay =
0d20ef
-    let orig_uri, orig_format =
0d20ef
-      try Hashtbl.find saved_uri overlay.ov_source.s_disk_id
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_file, _ =
0d20ef
-      mapf ~readahead:(64 * 1024 * 1024) orig_uri orig_format in
0d20ef
+    let backing_qemu_uri =
0d20ef
+      map_source_to_uri ~readahead:(64 * 1024 * 1024)
0d20ef
+        verbose parsed_uri scheme server orig_path in
0d20ef
 
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_file) (quote overlay.ov_overlay_file) in
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, see earlier errors")
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 081317d..8b836a5 100644
0d20ef
--- a/v2v/input_libvirt_xen_ssh.ml
0d20ef
+++ b/v2v/input_libvirt_xen_ssh.ml
0d20ef
@@ -28,57 +28,15 @@ open Input_libvirt_other
0d20ef
 
0d20ef
 open Printf
0d20ef
 
0d20ef
-(* Map a Xen <source/> to a qemu URI using the SSH driver in qemu.
0d20ef
- * This code assumes (and the caller checks) that the Xen URI is
0d20ef
- * remotely accessible over ssh, so we can map the path to the qemu
0d20ef
- * URI:
0d20ef
- *
0d20ef
- * json: {
0d20ef
- *   "file.driver": "ssh",
0d20ef
- *   "file.user": "username",
0d20ef
- *   "file.host": "xen-host",
0d20ef
- *   "file.port": 123,
0d20ef
- *   "file.path": "path",
0d20ef
- *   "file.host_key_check": "no"
0d20ef
- * }
0d20ef
- *)
0d20ef
-let map_path_to_uri verbose uri scheme server path format =
0d20ef
-  (* Construct the JSON parameters. *)
0d20ef
-  let json_params = [
0d20ef
-    "file.driver", JSON.String "ssh";
0d20ef
-    "file.path", JSON.String path;
0d20ef
-    "file.host", JSON.String server;
0d20ef
-    "file.host_key_check", JSON.String "no";
0d20ef
-  ] in
0d20ef
-
0d20ef
-  let json_params =
0d20ef
-    match uri.uri_port with
0d20ef
-    | 0 | 22 -> json_params
0d20ef
-    (* qemu will actually assert-fail if you send the port number as a
0d20ef
-     * string ...
0d20ef
-     *)
0d20ef
-    | i -> ("file.port", JSON.Int i) :: json_params in
0d20ef
-
0d20ef
-  let json_params =
0d20ef
-    match uri.uri_user with
0d20ef
-    | None -> json_params
0d20ef
-    | Some user -> ("file.user", JSON.String user) :: json_params in
0d20ef
-
0d20ef
-  if verbose then
0d20ef
-    printf "ssh: json parameters: %s\n" (JSON.string_of_doc json_params);
0d20ef
-
0d20ef
-  (* Turn the JSON parameters into a 'json:' protocol string. *)
0d20ef
-  let qemu_uri = "json: " ^ JSON.string_of_doc json_params in
0d20ef
-
0d20ef
-  qemu_uri, format
0d20ef
-
0d20ef
 (* Subclass specialized for handling Xen over SSH. *)
0d20ef
 class input_libvirt_xen_ssh verbose libvirt_uri parsed_uri scheme server guest =
0d20ef
 object
0d20ef
   inherit input_libvirt verbose libvirt_uri guest
0d20ef
 
0d20ef
   method source () =
0d20ef
-    if verbose then printf "input_libvirt_xen_ssh: source()\n%!";
0d20ef
+    if verbose then
0d20ef
+      printf "input_libvirt_xen_ssh: source: scheme %s server %s\n%!"
0d20ef
+        scheme server;
0d20ef
 
0d20ef
     error_if_libvirt_backend ();
0d20ef
     error_if_no_ssh_agent ();
0d20ef
@@ -90,11 +48,48 @@ object
0d20ef
     let { s_disks = disks } as source =
0d20ef
       Input_libvirtxml.parse_libvirt_xml ~verbose xml in
0d20ef
 
0d20ef
-    let mapf = map_path_to_uri verbose parsed_uri scheme server in
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
+     * like this:
0d20ef
+     *
0d20ef
+     * json: {
0d20ef
+     *   "file.driver": "ssh",
0d20ef
+     *   "file.user": "username",
0d20ef
+     *   "file.host": "xen-host",
0d20ef
+     *   "file.port": 1022,
0d20ef
+     *   "file.path": "path",
0d20ef
+     *   "file.host_key_check": "no"
0d20ef
+     *)
0d20ef
     let disks = List.map (
0d20ef
-      fun ({ s_qemu_uri = uri; s_format = format } as disk) ->
0d20ef
-        let uri, format = mapf uri format in
0d20ef
-        { disk with s_qemu_uri = uri; s_format = format }
0d20ef
+      fun ({ s_qemu_uri = path } as disk) ->
0d20ef
+        (* Construct the JSON parameters. *)
0d20ef
+        let json_params = [
0d20ef
+          "file.driver", JSON.String "ssh";
0d20ef
+          "file.path", JSON.String path;
0d20ef
+          "file.host", JSON.String server;
0d20ef
+          "file.host_key_check", JSON.String "no";
0d20ef
+        ] in
0d20ef
+
0d20ef
+        let json_params =
0d20ef
+          match parsed_uri.uri_port with
0d20ef
+          | 0 | 22 -> json_params
0d20ef
+          (* qemu will actually assert-fail if you send the port
0d20ef
+           * number as a string ...
0d20ef
+           *)
0d20ef
+          | i -> ("file.port", JSON.Int i) :: json_params in
0d20ef
+
0d20ef
+        let json_params =
0d20ef
+          match parsed_uri.uri_user with
0d20ef
+          | None -> json_params
0d20ef
+          | Some user -> ("file.user", JSON.String user) :: json_params in
0d20ef
+
0d20ef
+        if verbose then
0d20ef
+          printf "ssh: json parameters: %s\n" (JSON.string_of_doc json_params);
0d20ef
+
0d20ef
+        (* Turn the JSON parameters into a 'json:' protocol string. *)
0d20ef
+        let qemu_uri = "json: " ^ JSON.string_of_doc json_params in
0d20ef
+
0d20ef
+        { disk with s_qemu_uri = qemu_uri }
0d20ef
     ) disks in
0d20ef
 
0d20ef
     { source with s_disks = disks }
0d20ef
-- 
0d20ef
1.8.3.1
0d20ef