This refactors useful VCenter functions out of the large
'input_libvirt_vcenter_https.ml' file.
---
po/POTFILES-ml | 1 +
v2v/Makefile.am | 2 +
v2v/input_libvirt_vcenter_https.ml | 144 +--------------------------------
v2v/vCenter.ml | 160 +++++++++++++++++++++++++++++++++++++
v2v/vCenter.mli | 40 ++++++++++
5 files changed, 205 insertions(+), 142 deletions(-)
create mode 100644 v2v/vCenter.ml
create mode 100644 v2v/vCenter.mli
diff --git a/po/POTFILES-ml b/po/POTFILES-ml
index 239e586..f794f1d 100644
--- a/po/POTFILES-ml
+++ b/po/POTFILES-ml
@@ -126,4 +126,5 @@ v2v/types.ml
v2v/utils.ml
v2v/v2v.ml
v2v/v2v_unit_tests.ml
+v2v/vCenter.ml
v2v/xml.ml
diff --git a/v2v/Makefile.am b/v2v/Makefile.am
index 6bfdb62..da31aaf 100644
--- a/v2v/Makefile.am
+++ b/v2v/Makefile.am
@@ -69,6 +69,7 @@ SOURCES_MLI = \
OVF.mli \
stringMap.mli \
types.mli \
+ vCenter.mli \
xml.mli
SOURCES_ML = \
@@ -77,6 +78,7 @@ SOURCES_ML = \
xml.ml \
utils.ml \
curl.ml \
+ vCenter.ml \
domainxml.ml \
DOM.ml \
kvmuid.ml \
diff --git a/v2v/input_libvirt_vcenter_https.ml b/v2v/input_libvirt_vcenter_https.ml
index 13108c7..0f1a648 100644
--- a/v2v/input_libvirt_vcenter_https.ml
+++ b/v2v/input_libvirt_vcenter_https.ml
@@ -33,146 +33,6 @@ open Printf
let readahead_for_conversion = None
let readahead_for_copying = Some (64 * 1024 * 1024)
-(* Return the session cookie. It is memoized, so you can call this
- * as often as required.
- *)
-let get_session_cookie =
- let session_cookie = ref "" in
- fun password scheme uri sslverify url ->
- if !session_cookie <> "" then
- Some !session_cookie
- else (
- let curl_args = [
- "head", None;
- "silent", None;
- "url", Some url;
- ] in
- let curl_args =
- match uri.uri_user, password with
- | None, None -> curl_args
- | None, Some _ ->
- warning (f_"--password-file parameter ignored because 'user@' was
not given in the URL");
- curl_args
- | Some user, None ->
- ("user", Some user) :: curl_args
- | Some user, Some password ->
- ("user", Some (user ^ ":" ^ password)) :: curl_args in
- let curl_args =
- if not sslverify then ("insecure", None) :: curl_args else curl_args
in
-
- let lines = Curl.run curl_args in
-
- let dump_response chan =
- Curl.print_curl_command chan curl_args;
-
- (* Dump out the output of the command. *)
- List.iter (fun x -> fprintf chan "%s\n" x) lines;
- flush chan
- in
-
- if verbose () then dump_response stdout;
-
- (* Look for the last HTTP/x.y NNN status code in the output. *)
- let status = ref "" in
- List.iter (
- fun line ->
- let len = String.length line in
- if len >= 12 && String.sub line 0 5 = "HTTP/" then
- status := String.sub line 9 3
- ) lines;
- let status = !status in
- if status = "" then (
- dump_response stderr;
- error (f_"vcenter: no status code in output of 'curl' command. Is
'curl' installed?")
- );
-
- if status = "401" then (
- dump_response stderr;
- if uri.uri_user <> None then
- error (f_"vcenter: incorrect username or password")
- else
- error (f_"vcenter: incorrect username or password. You might need to
specify the username in the URI like this: %s://USERNAME@[etc]")
- scheme
- );
-
- if status = "404" then (
- dump_response stderr;
- error (f_"vcenter: URL not found: %s\n\nThe '--dcpath' parameter may
be useful. See the explanation in the virt-v2v(1) man page OPTIONS section.") url
- );
-
- if status <> "200" then (
- dump_response stderr;
- error (f_"vcenter: invalid response from server")
- );
-
- (* Get the cookie. *)
- List.iter (
- fun line ->
- let len = String.length line in
- if len >= 12 && String.sub line 0 12 = "Set-Cookie: " then
(
- let line = String.sub line 12 (len-12) in
- let cookie, _ = String.split ";" line in
- session_cookie := cookie
- )
- ) lines;
- if !session_cookie = "" then (
- dump_response stderr;
- warning (f_"vcenter: could not read session cookie from the vCenter Server,
conversion may consume all sessions on the server and fail part way through");
- None
- )
- else
- Some !session_cookie
- )
-
-let multiple_slash = Str.regexp "/+"
-
-(* Helper function to extract the dcPath from a URI. *)
-let get_dcPath uri scheme =
- let default_dc = "ha-datacenter" in
- match scheme with
- | "vpx" ->
- (match uri.uri_path with
- | None ->
- warning (f_"vcenter: URI (-ic parameter) contains no path, so we cannot
determine the dcPath (datacenter name)");
- default_dc
- | Some path ->
- (* vCenter: URIs are *usually* '/Folder/Datacenter/esxi' so we can
- * just chop off the first '/' and final '/esxi' to get the
dcPath.
- *
- * The libvirt driver allows things like '/DC///esxi////' so we also
- * have to handle trailing slashes and collapse multiple slashes into
- * single (RHBZ#1258342).
- *
- * However if there is a cluster involved then the URI may be
- * /Folder/Datacenter/Cluster/esxi but dcPath=Folder/Datacenter/Cluster
- * won't work. In this case the user has to adjust the path to
- * remove the Cluster name (which still works in libvirt). There
- * should be a way to ask the libvirt vpx driver for the correct
- * path, but there isn't. XXX See also RHBZ#1256823.
- *)
- (* Collapse multiple slashes to single slash. *)
- let path = Str.global_replace multiple_slash "/" path in
- (* Chop off the first and trailing '/' (if found). *)
- let path =
- let len = String.length path in
- if len > 0 && path.[0] = '/' then
- String.sub path 1 (len-1)
- else path in
- let path =
- let len = String.length path in
- if len > 0 && path.[len-1] = '/' then
- String.sub path 0 (len-1)
- else path in
- (* Chop off the final element (ESXi hostname). *)
- let len =
- try String.rindex path '/' with Not_found -> String.length path in
- String.sub path 0 len
- );
- | "esx" -> (* Connecting to an ESXi hypervisor directly, so it's
fixed. *)
- default_dc
- | _ -> (* Don't know, so guess. *)
- default_dc
-
(* Map the <source/> string to a qemu URI using the cURL driver
* in qemu. The 'path' will be something like
*
@@ -200,7 +60,7 @@ let map_source_to_uri ?readahead dcPath password uri scheme server path
=
let dcPath =
match dcPath with
| None ->
- let dcPath = get_dcPath uri scheme in
+ let dcPath = VCenter.guess_dcPath uri scheme in
if verbose () then
printf "vcenter: calculated dcPath as: %s\n" dcPath;
dcPath
@@ -233,7 +93,7 @@ let map_source_to_uri ?readahead dcPath password uri scheme server path
=
(* Now we have to query the server to get the session cookie. *)
let session_cookie =
- get_session_cookie password scheme uri sslverify url in
+ VCenter.get_session_cookie password scheme uri sslverify url in
(* Construct the JSON parameters. *)
let json_params = [
diff --git a/v2v/vCenter.ml b/v2v/vCenter.ml
new file mode 100644
index 0000000..20dd964
--- /dev/null
+++ b/v2v/vCenter.ml
@@ -0,0 +1,160 @@
+(* virt-v2v
+ * Copyright (C) 2009-2015 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_utils
+open Common_gettext.Gettext
+
+open Xml
+
+(* Memoized session cookie. *)
+let session_cookie = ref ""
+
+let get_session_cookie password scheme uri sslverify url =
+ if !session_cookie <> "" then
+ Some !session_cookie
+ else (
+ let curl_args = [
+ "head", None;
+ "silent", None;
+ "url", Some url;
+ ] in
+ let curl_args =
+ match uri.uri_user, password with
+ | None, None -> curl_args
+ | None, Some _ ->
+ warning (f_"--password-file parameter ignored because 'user@' was
not given in the URL");
+ curl_args
+ | Some user, None ->
+ ("user", Some user) :: curl_args
+ | Some user, Some password ->
+ ("user", Some (user ^ ":" ^ password)) :: curl_args in
+ let curl_args =
+ if not sslverify then ("insecure", None) :: curl_args else curl_args in
+
+ let lines = Curl.run curl_args in
+
+ let dump_response chan =
+ Curl.print_curl_command chan curl_args;
+
+ (* Dump out the output of the command. *)
+ List.iter (fun x -> fprintf chan "%s\n" x) lines;
+ flush chan
+ in
+
+ if verbose () then dump_response stdout;
+
+ (* Look for the last HTTP/x.y NNN status code in the output. *)
+ let status = ref "" in
+ List.iter (
+ fun line ->
+ let len = String.length line in
+ if len >= 12 && String.sub line 0 5 = "HTTP/" then
+ status := String.sub line 9 3
+ ) lines;
+ let status = !status in
+ if status = "" then (
+ dump_response stderr;
+ error (f_"vcenter: no status code in output of 'curl' command. Is
'curl' installed?")
+ );
+
+ if status = "401" then (
+ dump_response stderr;
+ if uri.uri_user <> None then
+ error (f_"vcenter: incorrect username or password")
+ else
+ error (f_"vcenter: incorrect username or password. You might need to
specify the username in the URI like this: %s://USERNAME@[etc]")
+ scheme
+ );
+
+ if status = "404" then (
+ dump_response stderr;
+ error (f_"vcenter: URL not found: %s\n\nThe '--dcpath' parameter may
be useful. See the explanation in the virt-v2v(1) man page OPTIONS section.") url
+ );
+
+ if status <> "200" then (
+ dump_response stderr;
+ error (f_"vcenter: invalid response from server")
+ );
+
+ (* Get the cookie. *)
+ List.iter (
+ fun line ->
+ let len = String.length line in
+ if len >= 12 && String.sub line 0 12 = "Set-Cookie: " then
(
+ let line = String.sub line 12 (len-12) in
+ let cookie, _ = String.split ";" line in
+ session_cookie := cookie
+ )
+ ) lines;
+ if !session_cookie = "" then (
+ dump_response stderr;
+ warning (f_"vcenter: could not read session cookie from the vCenter Server,
conversion may consume all sessions on the server and fail part way through");
+ None
+ )
+ else
+ Some !session_cookie
+ )
+
+let multiple_slash = Str.regexp "/+"
+let default_dc = "ha-datacenter"
+
+let guess_dcPath uri = function
+ | "vpx" ->
+ (match uri.uri_path with
+ | None ->
+ warning (f_"vcenter: URI (-ic parameter) contains no path, so we cannot
determine the dcPath (datacenter name)");
+ default_dc
+ | Some path ->
+ (* vCenter: URIs are *usually* '/Folder/Datacenter/esxi' so we can
+ * just chop off the first '/' and final '/esxi' to get the
dcPath.
+ *
+ * The libvirt driver allows things like '/DC///esxi////' so we also
+ * have to handle trailing slashes and collapse multiple slashes into
+ * single (RHBZ#1258342).
+ *
+ * However if there is a cluster involved then the URI may be
+ * /Folder/Datacenter/Cluster/esxi but dcPath=Folder/Datacenter/Cluster
+ * won't work. In this case the user has to adjust the path to
+ * remove the Cluster name (which still works in libvirt). There
+ * should be a way to ask the libvirt vpx driver for the correct
+ * path, but there isn't. XXX See also RHBZ#1256823.
+ *)
+ (* Collapse multiple slashes to single slash. *)
+ let path = Str.global_replace multiple_slash "/" path in
+ (* Chop off the first and trailing '/' (if found). *)
+ let path =
+ let len = String.length path in
+ if len > 0 && path.[0] = '/' then
+ String.sub path 1 (len-1)
+ else path in
+ let path =
+ let len = String.length path in
+ if len > 0 && path.[len-1] = '/' then
+ String.sub path 0 (len-1)
+ else path in
+ (* Chop off the final element (ESXi hostname). *)
+ let len =
+ try String.rindex path '/' with Not_found -> String.length path in
+ String.sub path 0 len
+ );
+ | "esx" -> (* Connecting to an ESXi hypervisor directly, so it's
fixed. *)
+ default_dc
+ | _ -> (* Don't know, so guess. *)
+ default_dc
diff --git a/v2v/vCenter.mli b/v2v/vCenter.mli
new file mode 100644
index 0000000..10a9657
--- /dev/null
+++ b/v2v/vCenter.mli
@@ -0,0 +1,40 @@
+(* virt-v2v
+ * Copyright (C) 2009-2015 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.
+ *)
+
+(** Functions for dealing with VMware vCenter. *)
+
+val get_session_cookie : string option -> string -> Xml.uri -> bool -> string
-> string option
+(** [get_session_cookie password scheme uri sslverify url]
+ contacts the vCenter server, logs in, and gets the session cookie,
+ which can later be passed back to the server instead of having to
+ log in each time (this is also more efficient since it avoids
+ vCenter running out of authentication sessions).
+
+ Returns [None] if the session cookie could not be read (but
+ authentication was successful). You can proceed without the
+ session cookie in this case, but there is an unavoidable
+ danger of running out of authentication sessions. If the
+ session cookie could not be read, this function prints a
+ warning.
+
+ The session cookie is memoized so you can call this function as
+ often as you want, and only a single log in is made. *)
+
+val guess_dcPath : Xml.uri -> string -> string
+(** Try to guess the dcPath parameter from a URI. The mapping is
+ not precise. *)
--
2.5.0