mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-22 07:03:38 +00:00
v2v: Implement input from nbdkit vddk plugin (RHBZ#1477912).
This commit is contained in:
@@ -36,6 +36,7 @@ SOURCES_MLI = \
|
||||
input_libvirt.mli \
|
||||
input_libvirt_other.mli \
|
||||
input_libvirt_vcenter_https.mli \
|
||||
input_libvirt_vddk.mli \
|
||||
input_libvirt_xen_ssh.mli \
|
||||
input_libvirtxml.mli \
|
||||
input_ova.mli \
|
||||
@@ -89,6 +90,7 @@ SOURCES_ML = \
|
||||
input_libvirtxml.ml \
|
||||
input_libvirt_other.ml \
|
||||
input_libvirt_vcenter_https.ml \
|
||||
input_libvirt_vddk.ml \
|
||||
input_libvirt_xen_ssh.ml \
|
||||
input_libvirt.ml \
|
||||
input_ova.ml \
|
||||
|
||||
@@ -64,6 +64,15 @@ let parse_cmdline () =
|
||||
let output_name = ref None in
|
||||
let output_storage = ref None in
|
||||
let password_file = ref None in
|
||||
let vddk = ref None in
|
||||
let vddk_config = ref None in
|
||||
let vddk_cookie = ref None in
|
||||
let vddk_nfchostport = ref None in
|
||||
let vddk_port = ref None in
|
||||
let vddk_snapshot = ref None in
|
||||
let vddk_thumbprint = ref None in
|
||||
let vddk_transports = ref None in
|
||||
let vddk_vimapiver = ref None in
|
||||
let vdsm_vm_uuid = ref None in
|
||||
let vdsm_ovf_output = ref None in (* default "." *)
|
||||
|
||||
@@ -203,6 +212,24 @@ let parse_cmdline () =
|
||||
[ L"print-source" ], Getopt.Set print_source, s_"Print source and stop";
|
||||
[ L"qemu-boot" ], Getopt.Set qemu_boot, s_"Boot in qemu (-o qemu only)";
|
||||
[ L"root" ], Getopt.String ("ask|... ", set_root_choice), s_"How to choose root filesystem";
|
||||
[ L"vddk" ], Getopt.String ("libpath", set_string_option_once "--vddk" vddk),
|
||||
s_"Use nbdkit VDDK plugin";
|
||||
[ L"vddk-config" ], Getopt.String ("filename", set_string_option_once "--vddk-config" vddk_config),
|
||||
s_"Set VDDK config file";
|
||||
[ L"vddk-cookie" ], Getopt.String ("cookie", set_string_option_once "--vddk-cookie" vddk_cookie),
|
||||
s_"Set VDDK cookie";
|
||||
[ L"vddk-nfchostport" ], Getopt.String ("nfchostport", set_string_option_once "--vddk-nfchostport" vddk_nfchostport),
|
||||
s_"Set VDDK nfchostport";
|
||||
[ L"vddk-port" ], Getopt.String ("port", set_string_option_once "--vddk-port" vddk_port),
|
||||
s_"Set VDDK port";
|
||||
[ L"vddk-snapshot" ], Getopt.String ("snapshot-moref", set_string_option_once "--vddk-snapshot" vddk_snapshot),
|
||||
s_"Set VDDK snapshot";
|
||||
[ L"vddk-thumbprint" ], Getopt.String ("thumbprint", set_string_option_once "--vddk-thumbprint" vddk_thumbprint),
|
||||
s_"Set VDDK thumbprint";
|
||||
[ L"vddk-transports" ], Getopt.String ("transports", set_string_option_once "--vddk-transports" vddk_transports),
|
||||
s_"Set VDDK transports";
|
||||
[ L"vddk-vimapiver" ], Getopt.String ("apiver", set_string_option_once "--vddk-vimapiver" vddk_vimapiver),
|
||||
s_"Set VDDK vimapiver";
|
||||
[ L"vdsm-compat" ], Getopt.Symbol ("0.10|1.1", ["0.10"; "1.1"], set_vdsm_compat), s_"Write qcow2 with compat=0.10|1.1";
|
||||
[ L"vdsm-image-uuid" ], Getopt.String ("uuid", add_vdsm_image_uuid), s_"Output image UUID(s)";
|
||||
[ L"vdsm-vol-uuid" ], Getopt.String ("uuid", add_vdsm_vol_uuid), s_"Output vol UUID(s)";
|
||||
@@ -265,6 +292,29 @@ read the man page virt-v2v(1).
|
||||
let print_source = !print_source in
|
||||
let qemu_boot = !qemu_boot in
|
||||
let root_choice = !root_choice in
|
||||
let vddk_options =
|
||||
match !vddk with
|
||||
| Some libdir ->
|
||||
Some { vddk_libdir = libdir;
|
||||
vddk_config = !vddk_config;
|
||||
vddk_cookie = !vddk_cookie;
|
||||
vddk_nfchostport = !vddk_nfchostport;
|
||||
vddk_port = !vddk_port;
|
||||
vddk_snapshot = !vddk_snapshot;
|
||||
vddk_thumbprint = !vddk_thumbprint;
|
||||
vddk_transports = !vddk_transports;
|
||||
vddk_vimapiver = !vddk_vimapiver }
|
||||
| None ->
|
||||
if !vddk_config <> None ||
|
||||
!vddk_cookie <> None ||
|
||||
!vddk_nfchostport <> None ||
|
||||
!vddk_port <> None ||
|
||||
!vddk_snapshot <> None ||
|
||||
!vddk_thumbprint <> None ||
|
||||
!vddk_transports <> None ||
|
||||
!vddk_vimapiver <> None then
|
||||
error (f_"‘--vddk-*’ options should only be used when conversion via the nbdkit VDDK plugin has been enabled, ie. using ‘--vddk’.");
|
||||
None in
|
||||
let vdsm_compat = !vdsm_compat in
|
||||
let vdsm_image_uuids = List.rev !vdsm_image_uuids in
|
||||
let vdsm_vol_uuids = List.rev !vdsm_vol_uuids in
|
||||
@@ -280,6 +330,7 @@ read the man page virt-v2v(1).
|
||||
printf "libguestfs-rewrite\n";
|
||||
printf "vcenter-https\n";
|
||||
printf "xen-ssh\n";
|
||||
printf "vddk\n";
|
||||
printf "colours-option\n";
|
||||
printf "vdsm-compat-option\n";
|
||||
List.iter (printf "input:%s\n") (Modules_list.input_modules ());
|
||||
@@ -318,7 +369,7 @@ read the man page virt-v2v(1).
|
||||
| [guest] -> guest
|
||||
| _ ->
|
||||
error (f_"expecting a libvirt guest name on the command line") in
|
||||
Input_libvirt.input_libvirt dcpath password input_conn guest
|
||||
Input_libvirt.input_libvirt dcpath vddk_options password input_conn guest
|
||||
|
||||
| `LibvirtXML ->
|
||||
(* -i libvirtxml: Expecting a filename (XML file). *)
|
||||
|
||||
@@ -27,7 +27,7 @@ open Types
|
||||
open Utils
|
||||
|
||||
(* Choose the right subclass based on the URI. *)
|
||||
let input_libvirt dcpath password libvirt_uri guest =
|
||||
let input_libvirt dcpath vddk_options password libvirt_uri guest =
|
||||
match libvirt_uri with
|
||||
| None ->
|
||||
Input_libvirt_other.input_libvirt_other password libvirt_uri guest
|
||||
@@ -47,10 +47,18 @@ let input_libvirt dcpath password libvirt_uri guest =
|
||||
| Some _, Some "" ->
|
||||
Input_libvirt_other.input_libvirt_other password libvirt_uri guest
|
||||
|
||||
(* vCenter over https *)
|
||||
(* vCenter over https, or
|
||||
* vCenter or ESXi using nbdkit vddk plugin
|
||||
*)
|
||||
| Some server, Some ("esx"|"gsx"|"vpx" as scheme) ->
|
||||
Input_libvirt_vcenter_https.input_libvirt_vcenter_https
|
||||
dcpath password libvirt_uri parsed_uri scheme server guest
|
||||
(match vddk_options with
|
||||
| None ->
|
||||
Input_libvirt_vcenter_https.input_libvirt_vcenter_https
|
||||
dcpath password libvirt_uri parsed_uri scheme server guest
|
||||
| Some vddk_options ->
|
||||
Input_libvirt_vddk.input_libvirt_vddk vddk_options password
|
||||
libvirt_uri parsed_uri guest
|
||||
)
|
||||
|
||||
(* Xen over SSH *)
|
||||
| Some server, Some ("xen+ssh" as scheme) ->
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
(** [-i libvirt] source. *)
|
||||
|
||||
val input_libvirt : string option -> string option -> string option -> string -> Types.input
|
||||
(** [input_libvirt dcpath password libvirt_uri guest] creates and returns a
|
||||
new {!Types.input} object specialized for reading input from
|
||||
libvirt sources. *)
|
||||
val input_libvirt : string option -> Types.vddk_options option -> string option -> string option -> string -> Types.input
|
||||
(** [input_libvirt dcpath vddk_options password libvirt_uri guest] creates
|
||||
and returns a new {!Types.input} object specialized for reading input
|
||||
from libvirt sources. *)
|
||||
|
||||
315
v2v/input_libvirt_vddk.ml
Normal file
315
v2v/input_libvirt_vddk.ml
Normal file
@@ -0,0 +1,315 @@
|
||||
(* virt-v2v
|
||||
* Copyright (C) 2009-2017 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.
|
||||
*)
|
||||
|
||||
(** [-i libvirt] when the source is VMware via nbdkit vddk plugin *)
|
||||
|
||||
open Unix
|
||||
|
||||
open Common_gettext.Gettext
|
||||
open Common_utils
|
||||
open Std_utils
|
||||
open Unix_utils
|
||||
|
||||
open Types
|
||||
open Utils
|
||||
open Input_libvirt_other
|
||||
open Parse_libvirt_xml
|
||||
open Xpath_helpers
|
||||
|
||||
open Printf
|
||||
|
||||
(* Subclass specialized for handling VMware via nbdkit vddk plugin. *)
|
||||
class input_libvirt_vddk vddk_options password libvirt_uri parsed_uri guest =
|
||||
|
||||
(* The VDDK path. *)
|
||||
let libdir = vddk_options.vddk_libdir in
|
||||
(* Compute the LD_LIBRARY_PATH that we must pass to nbdkit. *)
|
||||
let library_path = libdir // sprintf "lib%d" Sys.word_size in
|
||||
|
||||
(* Is SELinux enabled and enforcing on the host? *)
|
||||
let have_selinux =
|
||||
0 = Sys.command "getenforce 2>/dev/null | grep -isq Enforcing" in
|
||||
|
||||
(* Check that the VDDK path looks reasonable. *)
|
||||
let error_unless_vddk_libdir () =
|
||||
if not (is_directory libdir) then
|
||||
error (f_"‘--vddk %s’ does not point to a directory. See \"INPUT FROM VDDK\" in the virt-v2v(1) manual.") libdir;
|
||||
|
||||
if not (is_directory library_path) then
|
||||
error (f_"VDDK library path %s not found or not a directory. See \"INPUT FROM VDDK\" in the virt-v2v(1) manual.")
|
||||
library_path
|
||||
in
|
||||
|
||||
(* Check that nbdkit is available and new enough. *)
|
||||
let error_unless_nbdkit_working () =
|
||||
if 0 <> Sys.command "nbdkit --version >/dev/null" then
|
||||
error (f_"nbdkit is not installed or not working. It is required to use ‘--vddk’. See \"INPUT FROM VDDK\" in the virt-v2v(1) manual.");
|
||||
|
||||
(* Check it's a new enough version. The latest features we
|
||||
* require are ‘--exit-with-parent’ and ‘--selinux-label’, both
|
||||
* added in 1.1.14.
|
||||
*)
|
||||
let lines = external_command "nbdkit --help" in
|
||||
let lines = String.concat " " lines in
|
||||
if String.find lines "exit-with-parent" == -1 ||
|
||||
String.find lines "selinux-label" == -1 then
|
||||
error (f_"nbdkit is not new enough, you need to upgrade to nbdkit ≥ 1.1.14")
|
||||
in
|
||||
|
||||
(* Check that the VDDK plugin is installed and working *)
|
||||
let error_unless_nbdkit_vddk_working () =
|
||||
let cmd =
|
||||
sprintf "LD_LIBRARY_PATH=%s nbdkit vddk --dump-plugin >/dev/null"
|
||||
(quote library_path) in
|
||||
if Sys.command cmd <> 0 then (
|
||||
(* See if we can diagnose why ... *)
|
||||
let cmd =
|
||||
sprintf "LD_LIBRARY_PATH=%s LANG=C nbdkit vddk --dump-plugin 2>&1 | grep -sq libvixDiskLib.so"
|
||||
(quote library_path) in
|
||||
let needs_library = Sys.command cmd = 0 in
|
||||
if not needs_library then
|
||||
error (f_"nbdkit VDDK plugin is not installed or not working. It is required if you want to use VDDK.
|
||||
|
||||
The VDDK plugin is not enabled by default when you compile nbdkit. You have to read the instructions in the nbdkit sources under ‘plugins/vddk/README.VDDK’ to find out how to enable the VDDK plugin.
|
||||
|
||||
See also \"INPUT FROM VDDK\" in the virt-v2v(1) manual.")
|
||||
else
|
||||
error (f_"nbdkit VDDK plugin is not installed or not working. It is required if you want to use VDDK.
|
||||
|
||||
It looks like you did not set the right path in the ‘--vddk’ option, or your copy of the VDDK directory is incomplete. There should be a library called ’%s/libvixDiskLib.so.?’.
|
||||
|
||||
See also \"INPUT FROM VDDK\" in the virt-v2v(1) manual.") library_path
|
||||
)
|
||||
in
|
||||
|
||||
let error_unless_thumbprint () =
|
||||
if vddk_options.vddk_thumbprint = None then
|
||||
error (f_"You must pass the ‘--vddk-thumbprint’ option with the SSL thumbprint of the VMware server. To find the thumbprint, see the nbdkit-vddk-plugin(1) manual. See also \"INPUT FROM VDDK\" in the virt-v2v(1) manual.")
|
||||
in
|
||||
|
||||
object
|
||||
inherit input_libvirt password libvirt_uri guest
|
||||
|
||||
method source () =
|
||||
error_unless_vddk_libdir ();
|
||||
error_unless_nbdkit_working ();
|
||||
error_unless_nbdkit_vddk_working ();
|
||||
error_unless_thumbprint ();
|
||||
|
||||
(* Get the libvirt XML. This also checks (as a side-effect)
|
||||
* that the domain is not running. (RHBZ#1138586)
|
||||
*)
|
||||
let xml = Libvirt_utils.dumpxml ?password ?conn:libvirt_uri guest in
|
||||
let source, disks = parse_libvirt_xml ?conn:libvirt_uri xml in
|
||||
|
||||
(* Find the <vmware:moref> element from the XML. This was added
|
||||
* in libvirt >= 3.7 and is required.
|
||||
*)
|
||||
let moref =
|
||||
let doc = Xml.parse_memory xml in
|
||||
let xpathctx = Xml.xpath_new_context doc in
|
||||
Xml.xpath_register_ns xpathctx
|
||||
"vmware" "http://libvirt.org/schemas/domain/vmware/1.0";
|
||||
let xpath_string = xpath_string xpathctx in
|
||||
match xpath_string "/domain/vmware:moref" with
|
||||
| Some moref -> moref
|
||||
| None ->
|
||||
error (f_"<vmware:moref> was not found in the output of ‘virsh dumpxml \"%s\"’. The most likely reason is that libvirt is too old, try upgrading libvirt to ≥ 3.7.") guest in
|
||||
|
||||
(* Create a temporary directory where we place the sockets and
|
||||
* password file.
|
||||
*)
|
||||
let tmpdir =
|
||||
let base_dir = (open_guestfs ())#get_cachedir () in
|
||||
let t = Mkdtemp.temp_dir ~base_dir "vddk." in
|
||||
(* tmpdir must be readable (but not writable) by "other" so that
|
||||
* qemu can open the sockets. If we place a password file in
|
||||
* this directory then we'll chmod that to 0600 below.
|
||||
*)
|
||||
chmod t 0o755;
|
||||
rmdir_on_exit t;
|
||||
t in
|
||||
|
||||
(* Start constructing the parts of the incredibly long nbdkit
|
||||
* command line which don't change between disks.
|
||||
*)
|
||||
let args =
|
||||
let add_arg, get_args =
|
||||
let args = ref [] in
|
||||
let add_arg a = push_front a args in
|
||||
let get_args () = List.rev !args in
|
||||
add_arg, get_args in
|
||||
|
||||
(* It probably never happens that the server name can be missing
|
||||
* from the libvirt URI, but we need a server name to pass to
|
||||
* nbdkit, so ...
|
||||
*)
|
||||
let server =
|
||||
match parsed_uri.Xml.uri_server with
|
||||
| Some server -> server
|
||||
| None ->
|
||||
match libvirt_uri with
|
||||
| Some libvirt_uri ->
|
||||
error (f_"‘-ic %s’ URL does not contain a host name field")
|
||||
libvirt_uri
|
||||
| None ->
|
||||
error (f_"you must use the ‘-ic’ parameter. See \"INPUT FROM VDDK\" in the virt-v2v(1) manual.") in
|
||||
|
||||
(* Similar to above, we also need a username to pass. *)
|
||||
let user =
|
||||
match parsed_uri.Xml.uri_user with
|
||||
| Some user -> user
|
||||
| None -> "root" (* ? *) in
|
||||
|
||||
add_arg "nbdkit";
|
||||
if verbose () then add_arg "--verbose";
|
||||
add_arg "--readonly"; (* important! readonly mode *)
|
||||
add_arg "--foreground"; (* run in foreground *)
|
||||
add_arg "--exit-with-parent"; (* exit when virt-v2v exits *)
|
||||
add_arg "--newstyle"; (* use newstyle NBD protocol *)
|
||||
add_arg "--exportname"; add_arg "/";
|
||||
if have_selinux then ( (* label the socket so qemu can open it *)
|
||||
add_arg "--selinux-label"; add_arg "system_u:object_r:svirt_t:s0"
|
||||
);
|
||||
|
||||
(* Name of the plugin. Everything following is a plugin parameter. *)
|
||||
add_arg "vddk";
|
||||
|
||||
let password_param =
|
||||
match password with
|
||||
| None ->
|
||||
(* nbdkit asks for the password interactively *)
|
||||
"password=-"
|
||||
| Some password ->
|
||||
let password_file = tmpdir // "password" in
|
||||
let chan = open_out password_file in
|
||||
chmod password_file 0o600;
|
||||
output_string chan password;
|
||||
close_out chan;
|
||||
(* nbdkit reads the password from the file *)
|
||||
"password=+" ^ password_file in
|
||||
add_arg (sprintf "server=%s" server);
|
||||
add_arg (sprintf "user=%s" user);
|
||||
add_arg password_param;
|
||||
add_arg (sprintf "vm=moref=%s" moref);
|
||||
add_arg (sprintf "libdir=%s" libdir);
|
||||
|
||||
(* The passthrough parameters. *)
|
||||
let pt name = may (fun field -> add_arg (sprintf "%s=%s" name field)) in
|
||||
pt "config" vddk_options.vddk_config;
|
||||
pt "cookie" vddk_options.vddk_cookie;
|
||||
pt "nfchostport" vddk_options.vddk_nfchostport;
|
||||
pt "port" vddk_options.vddk_port;
|
||||
pt "snapshot" vddk_options.vddk_snapshot;
|
||||
pt "thumbprint" vddk_options.vddk_thumbprint;
|
||||
pt "transports" vddk_options.vddk_transports;
|
||||
pt "vimapiver" vddk_options.vddk_vimapiver;
|
||||
|
||||
get_args () in
|
||||
|
||||
(* Create an nbdkit instance for each disk and rewrite the source
|
||||
* paths to point to the NBD socket.
|
||||
*)
|
||||
let disks = List.map (
|
||||
function
|
||||
| { p_source_disk = disk; p_source = P_dont_rewrite } ->
|
||||
disk
|
||||
|
||||
| { p_source = P_source_dev _ } -> (* Should never happen. *)
|
||||
error (f_"source disk has <source dev=...> attribute in XML")
|
||||
|
||||
| { p_source_disk = disk; p_source = P_source_file path } ->
|
||||
(* The <source file=...> attribute returned by the libvirt
|
||||
* VMX driver looks like "[datastore] path". We can use it
|
||||
* directly as the nbdkit file= parameter, and it is passed
|
||||
* directly in this form to VDDK.
|
||||
*)
|
||||
|
||||
let sock = tmpdir // sprintf "nbdkit%d.sock" disk.s_disk_id in
|
||||
let qemu_uri = sprintf "nbd:unix:%s:exportname=/" sock in
|
||||
|
||||
let pidfile = tmpdir // sprintf "nbdkit%d.pid" disk.s_disk_id in
|
||||
|
||||
(* Construct the final command line with the "static" args
|
||||
* above plus the args which vary for each disk.
|
||||
*)
|
||||
let args =
|
||||
args @ [ "--pidfile"; pidfile;
|
||||
"--unix"; sock;
|
||||
sprintf "file=%s" path ] in
|
||||
let args = Array.of_list args in
|
||||
|
||||
(* Start an nbdkit instance in the background. By using
|
||||
* --exit-with-parent we don't have to worry about cleaning
|
||||
* it up, hopefully.
|
||||
*)
|
||||
let pid = fork () in
|
||||
if pid = 0 then (
|
||||
(* Child process (nbdkit). *)
|
||||
putenv "LD_LIBRARY_PATH" library_path;
|
||||
execvp "nbdkit" args
|
||||
);
|
||||
|
||||
(* Wait for the pidfile to appear so we know that nbdkit
|
||||
* is listening for requests.
|
||||
*)
|
||||
let rec loop i =
|
||||
if i = 0 then false
|
||||
else if Sys.file_exists pidfile then true
|
||||
else (
|
||||
sleep 1;
|
||||
loop (i-1)
|
||||
)
|
||||
in
|
||||
if not (loop 30) then (
|
||||
if verbose () then
|
||||
error (f_"nbdkit did not start up. See previous debugging messages for problems.")
|
||||
else
|
||||
error (f_"nbdkit did not start up. There may be errors printed by nbdkit above.
|
||||
|
||||
If the messages above are not sufficient to diagnose the problem then add the ‘virt-v2v -v -x’ options and examine the debugging output carefully.")
|
||||
);
|
||||
|
||||
if have_selinux then (
|
||||
(* Note that Unix domain sockets have both a file label and
|
||||
* a socket/process label. Using --selinux-label above
|
||||
* only set the socket label, but we must also set the file
|
||||
* label.
|
||||
*)
|
||||
ignore (
|
||||
run_command ["chcon"; "system_u:object_r:svirt_image_t:s0";
|
||||
sock]
|
||||
);
|
||||
);
|
||||
(* ... and the regular Unix permissions, in case qemu is
|
||||
* running as another user.
|
||||
*)
|
||||
chmod sock 0o777;
|
||||
|
||||
{ disk with s_qemu_uri = qemu_uri }
|
||||
) disks in
|
||||
|
||||
if verbose () then (
|
||||
eprintf "vddk: tmpdir %s:\n%!" tmpdir;
|
||||
ignore (Sys.command (sprintf "ls -laZ %s" (quote tmpdir)))
|
||||
);
|
||||
|
||||
{ source with s_disks = disks }
|
||||
end
|
||||
|
||||
let input_libvirt_vddk = new input_libvirt_vddk
|
||||
24
v2v/input_libvirt_vddk.mli
Normal file
24
v2v/input_libvirt_vddk.mli
Normal file
@@ -0,0 +1,24 @@
|
||||
(* virt-v2v
|
||||
* Copyright (C) 2017 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.
|
||||
*)
|
||||
|
||||
(** [-i libvirt] when the source is VMware via nbdkit vddk plugin *)
|
||||
|
||||
val input_libvirt_vddk : Types.vddk_options -> string option -> string option -> Xml.uri -> string -> Types.input
|
||||
(** [input_libvirt_vddk vddk_options password libvirt_uri parsed_uri guest]
|
||||
creates and returns a {!Types.input} object specialized for reading
|
||||
the guest disks using the nbdkit vddk plugin. *)
|
||||
12
v2v/types.ml
12
v2v/types.ml
@@ -488,6 +488,18 @@ type root_choice = AskRoot | SingleRoot | FirstRoot | RootDev of string
|
||||
|
||||
type output_allocation = Sparse | Preallocated
|
||||
|
||||
type vddk_options = {
|
||||
vddk_libdir : string;
|
||||
vddk_config : string option;
|
||||
vddk_cookie : string option;
|
||||
vddk_nfchostport : string option;
|
||||
vddk_port : string option;
|
||||
vddk_snapshot : string option;
|
||||
vddk_thumbprint : string option;
|
||||
vddk_transports : string option;
|
||||
vddk_vimapiver : string option;
|
||||
}
|
||||
|
||||
class virtual input = object
|
||||
method virtual as_options : string
|
||||
method virtual source : unit -> source
|
||||
|
||||
@@ -337,6 +337,19 @@ type root_choice = AskRoot | SingleRoot | FirstRoot | RootDev of string
|
||||
type output_allocation = Sparse | Preallocated
|
||||
(** Type of [-oa] (output allocation) option. *)
|
||||
|
||||
type vddk_options = {
|
||||
vddk_libdir : string;
|
||||
vddk_config : string option;
|
||||
vddk_cookie : string option;
|
||||
vddk_nfchostport : string option;
|
||||
vddk_port : string option;
|
||||
vddk_snapshot : string option;
|
||||
vddk_thumbprint : string option;
|
||||
vddk_transports : string option;
|
||||
vddk_vimapiver : string option;
|
||||
}
|
||||
(** Various options passed through to the nbdkit vddk plugin unmodified. *)
|
||||
|
||||
(** {2 Input object}
|
||||
|
||||
There is one of these used for the [-i] option. *)
|
||||
|
||||
158
v2v/virt-v2v.pod
158
v2v/virt-v2v.pod
@@ -161,8 +161,7 @@ qemu, do:
|
||||
|
||||
=item VMware ESXi
|
||||
|
||||
Must be managed by VMware vCenter E<ge> 5.0. Unmanaged, direct input
|
||||
from ESXi is not supported.
|
||||
Must be managed by VMware vCenter E<ge> 5.0 unless VDDK is available.
|
||||
|
||||
=item OVA exported from VMware
|
||||
|
||||
@@ -647,6 +646,35 @@ boot an operating system from the first virtio disk. Specifically,
|
||||
F</boot> must be on the first virtio disk, and it cannot chainload an
|
||||
OS which is not in the first virtio disk.
|
||||
|
||||
=item B<--vddk> LIBDIR
|
||||
|
||||
Enable VDDK input from VMware vCenter or ESXi. C<LIBDIR> is the top
|
||||
directory of the VDDK library. This directory should I<contain>
|
||||
subdirectories called F<include>, F<lib64> etc., but do not include
|
||||
F<lib64> actually in the parameter.
|
||||
|
||||
See L</INPUT FROM VDDK> below for details.
|
||||
|
||||
=item B<--vddk-config> FILENAME
|
||||
|
||||
=item B<--vddk-cookie> COOKIE
|
||||
|
||||
=item B<--vddk-nfchostport> PORT
|
||||
|
||||
=item B<--vddk-port> PORT
|
||||
|
||||
=item B<--vddk-snapshot> SNAPSHOT-MOREF
|
||||
|
||||
=item B<--vddk-thumbprint> xx:xx:xx:...
|
||||
|
||||
=item B<--vddk-transports> MODE:MODE:...
|
||||
|
||||
=item B<--vddk-vimapiver> APIVER
|
||||
|
||||
When using VDDK mode, these options are passed unmodified to the
|
||||
L<nbdkit(1)> VDDK plugin. Please refer to L<nbdkit-vddk-plugin(1)>.
|
||||
Only I<--vddk-thumbprint> is required, the others are optional.
|
||||
|
||||
=item B<--vdsm-compat=0.10>
|
||||
|
||||
=item B<--vdsm-compat=1.1>
|
||||
@@ -1402,6 +1430,130 @@ Perform the conversion of the guest using virt-v2v:
|
||||
|
||||
Remove the F<guest.xml> and F<guest-disk*> files.
|
||||
|
||||
=head1 INPUT FROM VDDK
|
||||
|
||||
Virt-v2v is able to import guests using VMware’s proprietary VDDK
|
||||
library (a.k.a. VixDiskLib).
|
||||
|
||||
=head2 VDDK: PREREQUISITES
|
||||
|
||||
=over 4
|
||||
|
||||
=item 1.
|
||||
|
||||
As the VDDK library is not open source, and the license of this
|
||||
library does not permit redistribution or commercial use, you must
|
||||
obtain VDDK yourself and satisfy yourself that your usage of the
|
||||
library is permitted by the license.
|
||||
|
||||
=item 2.
|
||||
|
||||
You must also compile nbdkit, enabling the VDDK plugin. At least
|
||||
nbdkit E<ge> 1.1.14 is required, but it is usually best to compile
|
||||
from the git tree.
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
L<https://github.com/libguestfs/nbdkit>
|
||||
|
||||
=item *
|
||||
|
||||
L<https://github.com/libguestfs/nbdkit/tree/master/plugins/vddk>
|
||||
|
||||
=back
|
||||
|
||||
=item 3.
|
||||
|
||||
You can run nbdkit from its source directory without needing to
|
||||
install it. Set C<$PATH> to include the nbdkit top build directory
|
||||
(the directory containing a shell script called F<nbdkit>):
|
||||
|
||||
export PATH=/path/to/nbdkit:$PATH
|
||||
|
||||
=item 4.
|
||||
|
||||
You must find the SSL "thumbprint" of your VMware server. How to do
|
||||
this is explained in L<nbdkit-vddk-plugin(1)>, also available at the
|
||||
link given in item 2 above.
|
||||
|
||||
=item 5.
|
||||
|
||||
VDDK imports require a feature added in libvirt E<ge> 3.7.
|
||||
|
||||
=back
|
||||
|
||||
=head2 VDDK: URI
|
||||
|
||||
Construct the correct C<vpx://> (for vCenter) or C<esx://> (for ESXi)
|
||||
URL. It will look something like these:
|
||||
|
||||
vpx://root@vcenter.example.com/Datacenter/esxi
|
||||
|
||||
esx://root@esxi.example.com
|
||||
|
||||
To verify that you have the correct URL, use the L<virsh(1)> command
|
||||
to list the guests on the server:
|
||||
|
||||
$ virsh -c 'vpx://root@vcenter.example.com/Datacenter/esxi' list --all
|
||||
Enter root's password for vcenter.example.com: ***
|
||||
|
||||
Id Name State
|
||||
----------------------------------------------------
|
||||
- Fedora 20 shut off
|
||||
- Windows 2003 shut off
|
||||
|
||||
If you get an error "Peer certificate cannot be authenticated with
|
||||
given CA certificates" or similar, then you can either import the
|
||||
vCenter host’s certificate, or bypass signature verification by adding
|
||||
the C<?no_verify=1> flag:
|
||||
|
||||
$ virsh -c 'vpx://root@vcenter.example.com/Datacenter/esxi?no_verify=1' list --all
|
||||
|
||||
You should also try dumping the metadata from any guest on your
|
||||
server, like this:
|
||||
|
||||
$ virsh -c 'vpx://root@vcenter.example.com/Datacenter/esxi' dumpxml "Windows 2003"
|
||||
<domain type='vmware'>
|
||||
<name>Windows 2003</name>
|
||||
[...]
|
||||
<vmware:moref>vm-123</vmware:moref>
|
||||
</domain>
|
||||
|
||||
If C<E<lt>vmware:morefE<gt>> does not appear in the metadata, then you
|
||||
need to upgrade libvirt.
|
||||
|
||||
B<If the above commands do not work, then virt-v2v is not going to
|
||||
work either>. Fix your URI and/or your VMware server before
|
||||
continuing.
|
||||
|
||||
=head2 VDDK: IMPORTING A GUEST
|
||||
|
||||
To import a particular guest from vCenter server or ESXi hypervisor,
|
||||
use a command like the following, substituting the URI, guest name and
|
||||
SSL thumbprint:
|
||||
|
||||
$ export PATH=/path/to/nbdkit:$PATH
|
||||
$ virt-v2v \
|
||||
-ic 'vpx://root@vcenter.example.com/Datacenter/esxi?no_verify=1' \
|
||||
--vddk /path/to/vmware-vix-disklib-distrib \
|
||||
--vddk-thumbprint xx:xx:xx:... \
|
||||
"Windows 2003" \
|
||||
-o local -os /var/tmp
|
||||
|
||||
Other options that you might need to add in rare circumstances include
|
||||
I<--vddk-config>, I<--vddk-cookie>, I<--vddk-nfchostport>,
|
||||
I<--vddk-port>, I<--vddk-snapshot>, I<--vddk-transports> and
|
||||
I<--vddk-vimapiver>, which are all explained in the
|
||||
L<nbdkit-vddk-plugin(1)> documentation.
|
||||
|
||||
=head2 VDDK: DEBUGGING VDDK FAILURES
|
||||
|
||||
The VDDK library can be operated in a verbose mode where it gives
|
||||
(very) verbose messages. Use ‘virt-v2v -v -x’ as usual to enable
|
||||
verbose messages.
|
||||
|
||||
=head1 INPUT FROM XEN
|
||||
|
||||
Virt-v2v is able to import Xen guests from RHEL 5 Xen or SLES and
|
||||
@@ -2207,6 +2359,8 @@ L<virt-v2v-copy-to-local(1)>,
|
||||
L<virt-v2v-test-harness(1)>,
|
||||
L<engine-image-uploader(8)>,
|
||||
L<import-to-ovirt.pl|http://git.annexia.org/?p=import-to-ovirt.git>,
|
||||
L<nbdkit(1)>,
|
||||
L<nbdkit-vddk-plugin(1)>,
|
||||
L<http://libguestfs.org/>.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Reference in New Issue
Block a user