v2v: Add a new tool virt-v2v-copy-to-local.

This allows certain guests which virt-v2v cannot access to be copied
off the remote hypervisor and converted.  Essentially this just
automates the process of copying the guest's disks and adjusting the
libvirt XML.

This also adds a test of the new tool.
This commit is contained in:
Richard W.M. Jones
2015-11-19 14:26:43 +00:00
parent 05a80e6088
commit 87adc30163
7 changed files with 693 additions and 53 deletions

3
.gitignore vendored
View File

@@ -562,6 +562,7 @@ Makefile.in
/v2v/rhel-6.5.img
/v2v/rhel-7.0.img
/v2v/stamp-virt-v2v.pod
/v2v/stamp-virt-v2v-copy-to-local.pod
/v2v/test-harness/.depend
/v2v/test-harness/META
/v2v/test-harness/dllv2v_test_harness.so
@@ -570,6 +571,8 @@ Makefile.in
/v2v/v2v_unit_tests
/v2v/virt-v2v
/v2v/virt-v2v.1
/v2v/virt-v2v-copy-to-local
/v2v/virt-v2v-copy-to-local.1
/website/*.html
/website/README.txt
/website/TODO.txt

View File

@@ -101,6 +101,7 @@ v2v/changeuid.ml
v2v/cmdline.ml
v2v/convert_linux.ml
v2v/convert_windows.ml
v2v/copy_to_local.ml
v2v/curl.ml
v2v/domainxml.ml
v2v/input_disk.ml

View File

@@ -19,6 +19,7 @@ include $(top_srcdir)/subdir-rules.mk
EXTRA_DIST = \
$(SOURCES_MLI) $(SOURCES_ML) $(SOURCES_C) \
copy_to_local.ml \
v2v_unit_tests.ml \
$(TESTS) $(SLOW_TESTS) \
HACKING \
@@ -35,7 +36,8 @@ EXTRA_DIST = \
test-v2v-networks-and-bridges-expected.xml \
test-v2v-networks-and-bridges.xml \
test-v2v-sound.xml \
virt-v2v.pod
virt-v2v.pod \
virt-v2v-copy-to-local.pod
CLEANFILES = *~ *.annot *.cmi *.cmo *.cmx *.cmxa *.o virt-v2v
@@ -113,7 +115,7 @@ SOURCES_C = \
if HAVE_OCAML
bin_PROGRAMS = virt-v2v
bin_PROGRAMS = virt-v2v virt-v2v-copy-to-local
virt_v2v_SOURCES = $(SOURCES_C)
virt_v2v_CPPFLAGS = \
@@ -177,6 +179,46 @@ virt_v2v_LINK = \
$(OCAMLFIND) $(BEST) $(OCAMLFLAGS) $(OCAMLPACKAGES) $(OCAMLLINKFLAGS) \
$(OBJECTS) -o $@
virt_v2v_copy_to_local_SOURCES = \
domainxml-c.c \
utils-c.c \
xml-c.c
virt_v2v_copy_to_local_CPPFLAGS = \
-I. \
-I$(top_builddir) \
-I$(shell $(OCAMLC) -where) \
-I$(top_srcdir)/src
virt_v2v_copy_to_local_CFLAGS = \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
$(LIBXML2_CFLAGS) \
$(LIBVIRT_CFLAGS)
COPY_TO_LOCAL_BOBJECTS = \
$(top_builddir)/mllib/guestfs_config.cmo \
$(top_builddir)/mllib/common_gettext.cmo \
$(top_builddir)/mllib/common_utils.cmo \
$(top_builddir)/mllib/JSON.cmo \
xml.cmo \
utils.cmo \
curl.cmo \
vCenter.cmo \
domainxml.cmo \
copy_to_local.cmo
COPY_TO_LOCAL_XOBJECTS = $(COPY_TO_LOCAL_BOBJECTS:.cmo=.cmx)
if !HAVE_OCAMLOPT
COPY_TO_LOCAL_OBJECTS = $(COPY_TO_LOCAL_BOBJECTS)
else
COPY_TO_LOCAL_OBJECTS = $(COPY_TO_LOCAL_XOBJECTS)
endif
virt_v2v_copy_to_local_DEPENDENCIES = \
$(COPY_TO_LOCAL_OBJECTS) $(top_srcdir)/ocaml-link.sh
virt_v2v_copy_to_local_LINK = \
$(top_srcdir)/ocaml-link.sh -cclib '$(OCAMLCLIBS)' -- \
$(OCAMLFIND) $(BEST) $(OCAMLFLAGS) $(OCAMLPACKAGES) $(OCAMLLINKFLAGS) \
$(COPY_TO_LOCAL_OBJECTS) -o $@
.mli.cmi:
$(OCAMLFIND) ocamlc $(OCAMLFLAGS) $(OCAMLPACKAGES) -c $< -o $@
.ml.cmo:
@@ -192,9 +234,11 @@ virttoolsdatadir = $(datadir)/virt-tools
# Manual pages and HTML files for the website.
man_MANS = virt-v2v.1
man_MANS = virt-v2v.1 virt-v2v-copy-to-local.1
noinst_DATA = $(top_builddir)/website/virt-v2v.1.html
noinst_DATA = \
$(top_builddir)/website/virt-v2v.1.html \
$(top_builddir)/website/virt-v2v-copy-to-local.1.html
virt-v2v.1 $(top_builddir)/website/virt-v2v.1.html: stamp-virt-v2v.pod
@@ -206,9 +250,21 @@ stamp-virt-v2v.pod: virt-v2v.pod
$<
touch $@
virt-v2v-copy-to-local.1 $(top_builddir)/website/virt-v2v-copy-to-local.1.html: stamp-virt-v2v-copy-to-local.pod
stamp-virt-v2v-copy-to-local.pod: virt-v2v-copy-to-local.pod
$(PODWRAPPER) \
--man virt-v2v-copy-to-local.1 \
--html $(top_builddir)/website/virt-v2v-copy-to-local.1.html \
--license GPLv2+ \
$<
touch $@
CLEANFILES += \
stamp-virt-v2v.pod \
virt-v2v.1
stamp-virt-v2v-copy-to-local.pod \
virt-v2v.1 \
virt-v2v-copy-to-local.1
# Tests.
@@ -231,7 +287,8 @@ TESTS_ENVIRONMENT = $(top_builddir)/run --test
TESTS = \
test-v2v-i-ova-formats.sh \
test-v2v-i-ova-gz.sh \
test-v2v-i-ova-two-disks.sh
test-v2v-i-ova-two-disks.sh \
test-v2v-copy-to-local.sh
if HAVE_OCAML_PKG_OUNIT
TESTS += v2v_unit_tests

332
v2v/copy_to_local.ml Normal file
View File

@@ -0,0 +1,332 @@
(* 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.
*)
(* The separate virt-v2v-copy-to-local tool. *)
open Printf
open Common_gettext.Gettext
open Common_utils
open Utils
type source_t = Xen_ssh of string | ESXi of string | Test
let rec main () =
let input_conn = ref None in
let password_file = ref None in
let set_string_option_once optname optref arg =
match !optref with
| Some _ ->
error (f_"%s option used more than once on the command line") optname
| None ->
optref := Some arg
in
(* Handle the command line. *)
let argspec = [
"-ic", Arg.String (set_string_option_once "-ic" input_conn),
"uri " ^ s_"Libvirt URI";
"--password-file", Arg.String (set_string_option_once "--password-file" password_file),
"file " ^ s_"Use password from file";
] in
let argspec = set_standard_options argspec in
let args = ref [] in
let anon_fun s = args := s :: !args in
let usage_msg =
sprintf (f_"\
%s: copy a remote guest to the local machine
Copy the remote guest:
virt-v2v-copy-to-local -ic xen+ssh://root@xen.example.com guest
virt-v2v-copy-to-local -ic esx://esxi.example.com guest
Then perform the conversion step:
virt-v2v -i libvirtxml guest.xml -o local -os /var/tmp
To clean up:
rm guest.xml guest-disk*
A short summary of the options is given below. For detailed help please
read the man page virt-v2v-copy-to-local(1).
")
prog in
Arg.parse argspec anon_fun usage_msg;
let args = !args in
let input_conn = !input_conn in
let password_file = !password_file in
let input_conn =
match input_conn with
| None ->
error (f_"the -ic parameter is required") (* at the moment *)
| Some ic -> ic in
(* Parse out the password from the password file. *)
let password =
match password_file with
| None -> None
| Some filename ->
let password = read_first_line_from_file filename in
Some password in
(* Check this is a libvirt URI we can understand. *)
let parsed_uri =
try Xml.parse_uri input_conn
with Invalid_argument msg ->
error (f_"could not parse '-ic %s'. Original error message was: %s")
input_conn msg in
let source =
match parsed_uri.Xml.uri_server, parsed_uri.Xml.uri_scheme with
| Some server, Some "xen+ssh" -> (* Xen over SSH *)
Xen_ssh server
| Some server, Some "esx" -> (* esxi over https *)
ESXi server
(* This is just for testing, and is not documented. *)
| None, Some "test" ->
Test
(* We can probably extend this list in future. *)
| _ ->
error (f_"only copies from VMware ESXi or Xen over SSH are supported. See the virt-v2v-copy-to-local(1) manual page.") in
(* We expect a single extra argument, which is the guest name. *)
let guest_name =
match args with
| [] ->
error (f_"missing guest name. See the virt-v2v-copy-to-local(1) manual page.")
| [arg] -> arg
| _ ->
error (f_"too many command line parameters. See the virt-v2v-copy-to-local(1) manual page.") in
(* Print the version, easier than asking users to tell us. *)
if verbose () then
printf "%s: %s %s (%s)\n%!"
prog Guestfs_config.package_name Guestfs_config.package_version Guestfs_config.host_cpu;
(* Get the remote libvirt XML. *)
message (f_"Fetching the remote libvirt XML metadata ...");
let xml = Domainxml.dumpxml ?password ~conn:input_conn guest_name in
if verbose () then
printf "libvirt XML from remote server:\n%s\n" xml;
(* Get the disk remote paths from the XML. *)
message (f_"Parsing the remote libvirt XML metadata ...");
let disks, dcpath, xml = parse_libvirt_xml guest_name xml in
if verbose () then
printf "libvirt XML after modifying for local disks:\n%s\n" xml;
(* For VMware ESXi source, we have to massage the disk path. *)
let disks =
match source with
| ESXi server ->
List.map (
fun (remote_disk, local_disk) ->
let url, sslverify =
VCenter.map_source_to_https dcpath parsed_uri
server remote_disk in
if verbose () then
printf "esxi: source disk %s (sslverify=%b)\n" url sslverify;
let cookie =
VCenter.get_session_cookie password "esx"
parsed_uri sslverify url in
(url, local_disk, sslverify, cookie)
) disks
| Test | Xen_ssh _ ->
List.map (fun (remote_disk, local_disk) ->
(remote_disk, local_disk, false, None)) disks in
(* Delete the disks on exit, unless we finish everything OK. *)
let delete_on_exit = ref true in
at_exit (
fun () ->
if !delete_on_exit then (
List.iter (
fun (_, local_disk, _, _) ->
try Unix.unlink local_disk with _ -> ()
) disks
)
);
(* Copy the disks. *)
let n = List.length disks in
iteri (
fun i (remote_disk, local_disk, sslverify, cookie) ->
message (f_"Copying remote disk %d/%d to %s")
(i+1) n local_disk;
(* How we copy it depends on the source. *)
match source with
| Xen_ssh server ->
let { Xml.uri_user = user; uri_port = port } = parsed_uri in
let cmd =
sprintf "set -o pipefail; ssh%s %s%s dd bs=1M if=%s | dd%s conv=sparse bs=1M of=%s"
(match port with
| n when n >= 1 -> sprintf " -p %d" n
| _ -> "")
(match user with
| None -> ""
| Some u -> sprintf "%s@" (quote u))
server
(quote remote_disk)
(if quiet () then ""
else " status=progress")
(quote local_disk) in
if verbose () then
printf "%s\n%!" cmd;
if Sys.command cmd <> 0 then
error (f_"ssh copy command failed, see earlier errors");
| ESXi _ ->
let curl_args = [
"url", Some remote_disk;
"output", Some local_disk;
] in
let curl_args =
if sslverify then curl_args
else ("insecure", None) :: curl_args in
let curl_args =
match cookie with
| None -> curl_args
| Some cookie -> ("cookie", Some cookie) :: curl_args in
let curl_args =
if quiet () then ("silent", None) :: curl_args
else curl_args in
if verbose () then
Curl.print_curl_command stdout curl_args;
ignore (Curl.run curl_args)
| Test ->
let cmd = sprintf "cp %s %s" (quote remote_disk) (quote local_disk) in
if verbose () then
printf "%s\n%!" cmd;
if Sys.command cmd <> 0 then
error (f_"copy command failed, see earlier errors");
) disks;
let guest_xml = guest_name ^ ".xml" in
message (f_"Writing libvirt XML metadata to %s ...") guest_xml;
let chan = open_out guest_xml in
output_string chan xml;
close_out chan;
(* Finished, so don't delete the disks on exit. *)
message (f_"Finishing off");
delete_on_exit := false
(* This is a greatly simplified version of the parsing function
* in virt-v2v input_libvirtxml.ml:parse_libvirt_xml
* It also modifies the XML <disk> elements to point to local disks.
*)
and parse_libvirt_xml guest_name xml =
(* Parse the XML. *)
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
and xpath_string_default = xpath_string_default xpathctx in
(* Get the dcpath, only present for libvirt >= 1.2.20 so use a
* sensible default for older versions.
*)
let dcpath =
xpath_string_default "/domain/vmware:datacenterpath" "ha-datacenter" in
(* Parse the disks. *)
let get_disks, add_disk =
let disks = ref [] and i = ref 0 in
let get_disks () = List.rev !disks in
let add_disk remote_disk =
(* Generate a unique name for each output disk. *)
incr i;
let local_disk = sprintf "%s-disk%d" guest_name !i in
disks := (remote_disk, local_disk) :: !disks;
local_disk
in
get_disks, add_disk
in
(* node is a <disk> node, containing a <source> element. Update the
* node to point to a local file.
*)
let update_disk_node node local_disk =
Xml.set_prop node "type" "file";
let obj = Xml.xpath_eval_expression xpathctx "source" in
let nr_nodes = Xml.xpathobj_nr_nodes obj in
assert (nr_nodes >= 1);
for i = 0 to nr_nodes-1 do
let source_node = Xml.xpathobj_node obj i in
ignore (Xml.unset_prop source_node "dev");
Xml.set_prop source_node "file" local_disk
done
in
let obj =
Xml.xpath_eval_expression xpathctx
"/domain/devices/disk[@device='disk']" in
let nr_nodes = Xml.xpathobj_nr_nodes obj in
if nr_nodes < 1 then
error (f_"this guest has no non-removable disks");
for i = 0 to nr_nodes-1 do
let node = Xml.xpathobj_node obj i in
Xml.xpathctx_set_current_context xpathctx node;
(* The <disk type='...'> attribute may be 'block' or 'file'.
* We ignore any other types.
*)
match xpath_string "@type" with
| None ->
warning (f_"<disk> element with no type attribute ignored")
| Some "block" ->
(match xpath_string "source/@dev" with
| Some path ->
let local_disk = add_disk path in
update_disk_node node local_disk
| None -> ()
);
| Some "file" ->
(match xpath_string "source/@file" with
| Some path ->
let local_disk = add_disk path in
update_disk_node node local_disk
| None -> ()
);
| Some disk_type ->
warning (f_"<disk type='%s'> was ignored") disk_type
done;
let xml = Xml.to_string doc ~format:true in
get_disks (), dcpath, xml
let () = run_main_and_handle_errors main

53
v2v/test-v2v-copy-to-local.sh Executable file
View File

@@ -0,0 +1,53 @@
#!/bin/bash -
# libguestfs virt-v2v test script
# Copyright (C) 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.
# Test virt-v2v-copy-to-local command.
unset CDPATH
export LANG=C
set -e
if [ -n "$SKIP_TEST_V2V_COPY_TO_LOCAL_SH" ]; then
echo "$0: test skipped because environment variable is set"
exit 77
fi
abs_top_builddir="$(cd ..; pwd)"
libvirt_uri="test://$abs_top_builddir/test-data/phony-guests/guests.xml"
f=../test-data/phony-guests/fedora.img
if ! test -f $f || ! test -s $f; then
echo "$0: test skipped because phony Fedora image was not created"
exit 77
fi
d=test-v2v-copy-to-local.d
rm -rf $d
mkdir $d
pushd $d
$VG virt-v2v-copy-to-local --debug-gc -ic "$libvirt_uri" fedora
popd
# Test the libvirt XML metadata was created.
test -f $d/fedora.xml
# Test the disk was created.
test -f $d/fedora-disk1
rm -r $d

View File

@@ -0,0 +1,216 @@
=head1 NAME
virt-v2v-copy-to-local - Copy a remote guest to the local machine
=head1 SYNOPSIS
virt-v2v-copy-to-local -ic LIBVIRT_URI GUEST
virt-v2v-copy-to-local -ic xen+ssh://root@xen.example.com xen_guest
virt-v2v-copy-to-local -ic esx://root@esxi.example.com vmware_guest
=head1 DESCRIPTION
C<virt-v2v-copy-to-local> copies a guest from a remote hypervisor to
the local machine, in preparation for conversion by L<virt-v2v(1)>.
Note this tool alone B<does not> do the virt-v2v conversion.
=head2 When to use this tool
This tool is not usually necessary, but there are a few special cases
(see list below) where you might need it.
If your case does not fit one of these special cases, then ignore this
tool and read L<virt-v2v(1)> instead. The virt-v2v-copy-to-local
process is slower than using virt-v2v directly, because it has to copy
unused parts of the guest disk.
=over 4
=item *
You have a Xen guest using host block devices. Virt-v2v cannot
convert such guests directly.
See L<virt-v2v(1)/XEN OR SSH CONVERSIONS FROM BLOCK DEVICES>.
=item *
You have VMware ESXi hypervisors, and are not using VMware vCenter to
manage them. Virt-v2v cannot directly access ESXi hypervisor, so you
either have to export the guest as an OVA (eg. using VMware's
C<ovftool>); or you can use this tool to copy the guest to a local
file on the conversion server, from where virt-v2v will be able to
access it.
=back
=head2 How this tool works
This tool uses libvirt to get the libvirt XML (metadata) of the remote
guest, essentially equivalent to running C<virsh dumpxml guest>.
It then uses the XML to locate the remote guest disks, which are
copied over using a hypervisor-specific method. It uses ssh for
remote Xen hypervisors, and HTTPS (curl) for remote ESXi hypervisors.
It then modifies the libvirt XML so that it points at the local copies
of the guest disks.
The libvirt XML is output to a file called F<guest.xml> (where
I<guest> is the name of the guest). The disk(s) are output to file(s)
called F<guest-disk1>, F<guest-disk2> and so on.
After copying the guest locally, you can convert it using:
virt-v2v -i libvirtxml guest.xml [-o options ...]
Virt-v2v finds the local copies of the disks by looking in the XML.
=head1 EXAMPLES
=head2 Copy and convert from Xen hypervisor that uses host block devices
virt-v2v-copy-to-local -ic xen+ssh://root@xen.example.com xen_guest
virt-v2v -i libvirtxml xen_guest.xml -o local -os /var/tmp
rm xen_guest.xml xen_guest-disk*
=head2 Copy and convert from ESXi hypervisor
virt-v2v-copy-to-local -ic esx://root@esxi.example.com?no_verify=1 vmware_guest
virt-v2v -i libvirtxml vmware_guest.xml -o local -os /var/tmp
rm vmware_guest.xml vmware_guest-disk*
=head1 COPYING FROM XEN HYPERVISOR
=head2 XEN: LIBVIRT URI
The libvirt URI for remote Xen hosts will look something like this:
xen+ssh://root@xen.example.com
The remote Xen server must allow root logins over ssh.
To test it and list the remote guests available, use L<virsh(1)>:
$ virsh -c xen+ssh://root@xen.example.com list --all
Id Name State
----------------------------------------------------
0 Domain-0 running
- guest shut off
=head2 XEN: COPY THE GUEST
Using the libvirt URI as the I<-ic> option, copy one of the guests to
the local machine:
$ virt-v2v-copy-to-local -ic xen+ssh://root@xen.example.com guest
This creates F<guest.xml>, F<guest-disk1>, ...
=head2 XEN: DO THE CONVERSION
Perform the conversion of the guest using virt-v2v:
$ virt-v2v -i libvirtxml guest.xml -o local -os /var/tmp
=head2 XEN: CLEAN UP
Remove the F<guest.xml> and F<guest-disk*> files.
=head1 COPYING FROM VMware ESXi HYPERVISOR
=head2 ESXi: LIBVIRT URI
The libvirt URI for VMware ESXi hypervisors will look something like this:
esx://root@esxi.example.com?no_verify=1
The C<?no_verify=1> parameter disables TLS certificate checking.
To test it and list the remote guests available, use L<virsh(1)>:
$ virsh -c esx://root@esxi.example.com?no_verify=1 list --all
Enter root's password for esxi.example.com: ***
Id Name State
----------------------------------------------------
- guest shut off
=head2 ESXi: COPY THE GUEST
Using the libvirt URI as the I<-ic> option, copy one of the guests to
the local machine:
$ virt-v2v-copy-to-local -ic esx://root@esxi.example.com?no_verify=1 guest
This creates F<guest.xml>, F<guest-disk1>, ...
=head2 ESXi: DO THE CONVERSION
Perform the conversion of the guest using virt-v2v:
$ virt-v2v -i libvirtxml guest.xml -o local -os /var/tmp
=head2 ESXi: CLEAN UP
Remove the F<guest.xml> and F<guest-disk*> files.
=head1 OPTIONS
=over 4
=item B<--help>
Display help.
=item B<-ic> libvirtURI
Specify a libvirt connection URI
=item B<--password-file> file
Instead of asking for password(s) interactively, pass the password
through a file. Note the file should contain the whole password,
B<without any trailing newline>, and for security the file should have
mode C<0600> so that others cannot read it.
Currently this option does not have any effect on xen+ssh transfers,
but that is a bug.
=item B<-q>
=item B<--quiet>
This disables progress bars and other unnecessary output.
=item B<-v>
=item B<--verbose>
Enable verbose messages for debugging.
=item B<-V>
=item B<--version>
Display version number and exit.
=back
=head1 SEE ALSO
L<virt-v2v(1)>,
L<virsh(1)>,
L<http://libguestfs.org/>,
L<https://libvirt.org/uri.html>,
L<https://libvirt.org/remote.html>,
L<https://libvirt.org/drvesx.html>.
=head1 AUTHORS
Richard W.M. Jones L<http://people.redhat.com/~rjones/>
=head1 COPYRIGHT
Copyright (C) 2009-2015 Red Hat Inc.

View File

@@ -1177,6 +1177,19 @@ directory containing the files:
$ virt-v2v -i ova /path/to/files -o local -os /var/tmp
=head1 INPUT FROM VMWARE ESXi HYPERVISOR
Virt-v2v cannot access an ESXi hypervisor directly.
However you can use the L<virt-v2v-copy-to-local(1)> tool to copy the
guest off the hypervisor into a local file, and then convert it:
virt-v2v-copy-to-local -ic esx://esxi.example.com vmware_guest
virt-v2v -i libvirtxml vmware_guest.xml [-o options ...]
rm vmware_guest.xml vmware_guest-disk*
See L<virt-v2v-copy-to-local(1)> for further information.
=head1 INPUT FROM RHEL 5 XEN
Virt-v2v is able to import Xen guests from RHEL 5 Xen hosts.
@@ -1269,53 +1282,9 @@ The workaround is to copy the guest over to the conversion server.
You will need sufficient space on the conversion server to store a
full copy of the guest.
=over 4
=item 1.
From the conversion host, dump the guest XML to a local file:
virsh -c xen+ssh://root@xen.example.com dumpxml guest > guest.xml
=item 2.
From the conversion host, copy the guest disk(s) over. You may need
to read the C<E<lt>diskE<gt>> sections from the guest XML to find the
names of the guest disks.
ssh root@xen.example.com 'dd if=/dev/VG/guest' | dd conv=sparse of=guest-disk1
Notice C<conv=sparse> which adds sparseness, so the copied disk will
use as little space as possible.
=item 3.
Edit the guest XML file, replacing C<E<lt>diskE<gt>> section(s) that
refer to the remote disks with references to the local copies.
Three changes have to be made. Firstly in:
<disk type='block' device='disk'>
the C<type> must be changed to C<file>:
<disk type='file' device='disk'>
The last two changes are in the C<E<lt>sourceE<gt>> line where:
<source dev='/dev/VG/guest'/>
C<source dev=> becomes C<source file=> pointing at the local file:
<source file='guest-disk1'/>
=item 4.
Convert the guest using C<virt-v2v -i libvirtxml> mode like this:
virt-v2v -i libvirtxml guest.xml [-o options as usual ...]
=back
virt-v2v-copy-to-local -ic xen+ssh://root@xen.example.com guest
virt-v2v -i libvirtxml guest.xml [-o options ...]
rm guest.xml guest-disk*
=head1 OUTPUT TO LIBVIRT
@@ -1786,6 +1755,14 @@ For other environment variables, see L<guestfs(3)/ENVIRONMENT VARIABLES>.
=over 4
=item L<virt-v2v-copy-to-local(1)>
There are some special cases where virt-v2v cannot directly access the
remote hypervisor. In that case you have to use
L<virt-v2v-copy-to-local(1)> to make a local copy of the guest first,
followed by running C<virt-v2v -i libvirtxml> to perform the
conversion.
=item L<engine-image-uploader(8)>
Variously called C<engine-image-uploader>, C<ovirt-image-uploader> or
@@ -1816,6 +1793,7 @@ L<guestfs(3)>,
L<guestfish(1)>,
L<qemu-img(1)>,
L<fstrim(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>,