Also changes command line parsing to require a pool to be specified when using
libvirt output, meaning storage will always be copied.
---
MANIFEST | 1 +
lib/Sys/VirtV2V/Connection.pm | 74 +++++++++---------
lib/Sys/VirtV2V/Connection/LibVirt.pm | 18 +++--
lib/Sys/VirtV2V/Connection/LibVirtXML.pm | 11 ++-
lib/Sys/VirtV2V/Target/LibVirt.pm | 18 ++---
lib/Sys/VirtV2V/Transfer/ESX.pm | 7 +-
lib/Sys/VirtV2V/Transfer/LocalCopy.pm | 121 ++++++++++++++++++++++++++++++
v2v/virt-v2v.pl | 7 ++-
8 files changed, 193 insertions(+), 64 deletions(-)
create mode 100644 lib/Sys/VirtV2V/Transfer/LocalCopy.pm
diff --git a/MANIFEST b/MANIFEST
index 1bc6018..d5debe1 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -15,6 +15,7 @@ lib/Sys/VirtV2V/UserMessage.pm
lib/Sys/VirtV2V/Target/LibVirt.pm
lib/Sys/VirtV2V/Target/RHEV.pm
lib/Sys/VirtV2V/Transfer/ESX.pm
+lib/Sys/VirtV2V/Transfer/LocalCopy.pm
MANIFEST This list of files
MANIFEST.SKIP
META.yml
diff --git a/lib/Sys/VirtV2V/Connection.pm b/lib/Sys/VirtV2V/Connection.pm
index 5ecc7e3..5b4ed8d 100644
--- a/lib/Sys/VirtV2V/Connection.pm
+++ b/lib/Sys/VirtV2V/Connection.pm
@@ -22,10 +22,12 @@ use warnings;
use Sys::Virt;
-use Locale::TextDomain 'virt-v2v';
-
+use Sys::VirtV2V::Transfer::ESX;
+use Sys::VirtV2V::Transfer::LocalCopy;
use Sys::VirtV2V::UserMessage qw(user_message);
+use Locale::TextDomain 'virt-v2v';
+
=pod
=head1 NAME
@@ -134,41 +136,39 @@ sub _storage_iterate
else {
my $path = $source->getValue();
- if (defined($transfer)) {
- # Die if transfer required and no output target
- die (user_message(__"No output target was specified"))
- unless (defined($target));
-
- # Fetch the remote storage
- my $vol = $transfer->transfer($self, $path, $target);
-
- # Export the new path
- $path = $vol->get_path();
-
- # Find any existing driver element.
- my ($driver) = $disk->findnodes('driver');
-
- # Create a new driver element if none exists
- unless (defined($driver)) {
- $driver =
-
$disk->getOwnerDocument()->createElement("driver");
- $disk->appendChild($driver);
- }
- $driver->setAttribute('name', 'qemu');
- $driver->setAttribute('type', $vol->get_format());
-
- # Remove the @file or @dev attribute before adding a new one
- $source_e->removeAttributeNode($source);
-
- # Set @file or @dev as appropriate
- if ($vol->is_block())
- {
- $disk->setAttribute('type', 'block');
- $source_e->setAttribute('dev', $path);
- } else {
- $disk->setAttribute('type', 'file');
- $source_e->setAttribute('file', $path);
- }
+ # Die if transfer required and no output target
+ die (user_message(__"No output target was specified"))
+ unless (defined($target));
+
+ # Fetch the remote storage
+ my $vol = $transfer->transfer($self, $path, $target);
+
+ # Export the new path
+ $path = $vol->get_path();
+
+ # Find any existing driver element.
+ my ($driver) = $disk->findnodes('driver');
+
+ # Create a new driver element if none exists
+ unless (defined($driver)) {
+ $driver =
+ $disk->getOwnerDocument()->createElement("driver");
+ $disk->appendChild($driver);
+ }
+ $driver->setAttribute('name', 'qemu');
+ $driver->setAttribute('type', $vol->get_format());
+
+ # Remove the @file or @dev attribute before adding a new one
+ $source_e->removeAttributeNode($source);
+
+ # Set @file or @dev as appropriate
+ if ($vol->is_block())
+ {
+ $disk->setAttribute('type', 'block');
+ $source_e->setAttribute('dev', $path);
+ } else {
+ $disk->setAttribute('type', 'file');
+ $source_e->setAttribute('file', $path);
}
push(@paths, $path);
diff --git a/lib/Sys/VirtV2V/Connection/LibVirt.pm
b/lib/Sys/VirtV2V/Connection/LibVirt.pm
index 2c289b9..43fe624 100644
--- a/lib/Sys/VirtV2V/Connection/LibVirt.pm
+++ b/lib/Sys/VirtV2V/Connection/LibVirt.pm
@@ -30,7 +30,6 @@ use XML::DOM;
use Sys::Virt;
use Sys::VirtV2V;
-use Sys::VirtV2V::Transfer::ESX;
use Sys::VirtV2V::UserMessage qw(user_message);
use Locale::TextDomain 'virt-v2v';
@@ -46,7 +45,7 @@ Sys::VirtV2V::Connection::LibVirt - Read libvirt metadata from libvirtd
use Sys::VirtV2V::Connection::LibVirt;
$conn = Sys::VirtV2V::Connection::LibVirt->new
- ("xen+ssh://xenserver.example.com/", $name, $pool);
+ ("xen+ssh://xenserver.example.com/", $name, $target);
$dom = $conn->get_dom();
=head1 DESCRIPTION
@@ -59,11 +58,10 @@ libvirt connection.
=over
-=item new(uri, name, pool)
+=item new(uri, name, target)
Create a new Sys::VirtV2V::Connection::LibVirt. Domain I<name> will be
-obtained from I<uri>. Remote storage will be copied to a new volume, which
-will be created in I<pool>.
+obtained from I<uri>. Remote storage will be create on I<target>.
=cut
@@ -71,7 +69,7 @@ sub new
{
my $class = shift;
- my ($uri, $name, $pool) = @_;
+ my ($uri, $name, $target) = @_;
my $self = {};
@@ -151,7 +149,13 @@ sub new
$transfer = "Sys::VirtV2V::Transfer::ESX";
}
- $self->_storage_iterate($transfer, $pool);
+ # Default to LocalCopy
+ # XXX: Need transfer methods for remote libvirt connections, e.g. scp
+ else {
+ $transfer = "Sys::VirtV2V::Transfer::LocalCopy";
+ }
+
+ $self->_storage_iterate($transfer, $target);
return $self;
}
diff --git a/lib/Sys/VirtV2V/Connection/LibVirtXML.pm
b/lib/Sys/VirtV2V/Connection/LibVirtXML.pm
index 03b85b1..0ce07fd 100644
--- a/lib/Sys/VirtV2V/Connection/LibVirtXML.pm
+++ b/lib/Sys/VirtV2V/Connection/LibVirtXML.pm
@@ -39,7 +39,7 @@ Sys::VirtV2V::Connection::LibVirtXML - Read libvirt XML from a file
use Sys::VirtV2V::Connection::LibVirtXML;
- $conn = Sys::VirtV2V::Connection::LibVirtXML->new($path);
+ $conn = Sys::VirtV2V::Connection::LibVirtXML->new($path, $target);
$dom = $conn->get_dom();
=head1 DESCRIPTION
@@ -52,9 +52,10 @@ file.
=over
-=item new(path)
+=item new(path, target)
Create a new LibVirtXML connection. The metadata itself is read from I<path>.
+Storage will be copied to I<target>.
=cut
@@ -62,7 +63,7 @@ sub new
{
my $class = shift;
- my ($path) = @_;
+ my ($path, $target) = @_;
my $self = {};
$self->{path} = $path;
@@ -71,8 +72,8 @@ sub new
$self->_get_dom($path);
- # No transfer methods defined yet
- $self->_storage_iterate(undef, undef);
+ # Only support LocalCopy for libvirtxml
+ $self->_storage_iterate("Sys::VirtV2V::Transfer::LocalCopy", $target);
return $self;
}
diff --git a/lib/Sys/VirtV2V/Target/LibVirt.pm b/lib/Sys/VirtV2V/Target/LibVirt.pm
index 96ed513..ab95fb7 100644
--- a/lib/Sys/VirtV2V/Target/LibVirt.pm
+++ b/lib/Sys/VirtV2V/Target/LibVirt.pm
@@ -186,16 +186,14 @@ sub new
$self->{vmm} = Sys::Virt->new(auth => 1, uri => $uri);
- if (defined($poolname)) {
- eval {
- $self->{pool} = $self->{vmm}->get_storage_pool_by_name($poolname);
- };
-
- if ($@) {
- die(user_message(__x("Output pool {poolname} is not a valid ".
- "storage pool",
- poolname => $poolname)));
- }
+ eval {
+ $self->{pool} = $self->{vmm}->get_storage_pool_by_name($poolname);
+ };
+
+ if ($@) {
+ die(user_message(__x("Output pool {poolname} is not a valid ".
+ "storage pool",
+ poolname => $poolname)));
}
return $self;
diff --git a/lib/Sys/VirtV2V/Transfer/ESX.pm b/lib/Sys/VirtV2V/Transfer/ESX.pm
index 42b4326..9db28e0 100644
--- a/lib/Sys/VirtV2V/Transfer/ESX.pm
+++ b/lib/Sys/VirtV2V/Transfer/ESX.pm
@@ -120,10 +120,9 @@ sub get_volume
my $target = $self->{_v2v_target};
if ($target->volume_exists($volname)) {
print STDERR user_message(__x("WARNING: storage volume {name} ".
- "already exists in the target ".
- "pool. NOT fetching it again. ".
- "Delete the volume and retry to ".
- "download again.",
+ "already exists on the target. NOT ".
+ "fetching it again. Delete the volume ".
+ "and retry to download again.",
name => $volname));
return $target->get_volume($volname);
}
diff --git a/lib/Sys/VirtV2V/Transfer/LocalCopy.pm
b/lib/Sys/VirtV2V/Transfer/LocalCopy.pm
new file mode 100644
index 0000000..814bf4a
--- /dev/null
+++ b/lib/Sys/VirtV2V/Transfer/LocalCopy.pm
@@ -0,0 +1,121 @@
+# Sys::VirtV2V::Transfer::LocalCopy
+# Copyright (C) 2010 Red Hat Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+package Sys::VirtV2V::Transfer::LocalCopy;
+
+use File::Spec;
+use File::stat;
+
+use Sys::VirtV2V::UserMessage qw(user_message);
+
+use Locale::TextDomain 'virt-v2v';
+
+=pod
+
+=head1 NAME
+
+Sys::VirtV2V::Transfer::LocalCopy - Copy a guest's local storage
+
+=head1 SYNOPSIS
+
+ use Sys::VirtV2V::Transfer::LocalCopy;
+
+ $vol = Sys::VirtV2V::Transfer::LocalCopy->transfer($conn, $path, $target);
+
+=head1 DESCRIPTION
+
+Sys::VirtV2V::Transfer::LocalCopy retrieves guest storage devices from local
+storage.
+
+=head1 METHODS
+
+=over
+
+=item transfer(conn, path, target)
+
+Transfer <path> from local storage. Storage will be created using <target>.
+
+=cut
+
+sub transfer
+{
+ my $class = shift;
+
+ my ($conn, $path, $target) = @_;
+
+ my (undef, undef, $name) = File::Spec->splitpath($path);
+
+ if ($target->volume_exists($name)) {
+ print STDERR user_message(__x("WARNING: storage volume {name} ".
+ "already exists on the target. NOT ".
+ "copying it again. Delete the volume ".
+ "and retry to copy again.",
+ name => $name));
+ return $target->get_volume($name);
+ }
+
+ my $fh;
+ open($fh, '<', $path)
+ or die(user_message(__x("Unable to open {path} for reading: {error}",
+ path => $path,
+ error => $!)));
+
+ my $st = stat($fh)
+ or die(user_message(__x("Unable to stat {path}: {error}",
+ path => $path,
+ error => $!)));
+
+ my $vol = $target->create_volume($name, $st->size);
+ $vol->open();
+
+ for (;;) {
+ my $buffer;
+ # Transfer in block chunks
+ my $in = sysread($fh, $buffer, $st->blksize);
+ die(user_message(__x("Error reading data from {path}: {error}",
+ path => $path,
+ error => $!))) if (!defined($in));
+
+ last if ($in == 0);
+
+ $vol->write($buffer);
+ }
+
+ $vol->close();
+
+ return $vol;
+}
+
+=back
+
+=head1 COPYRIGHT
+
+Copyright (C) 2010 Red Hat Inc.
+
+=head1 LICENSE
+
+Please see the file COPYING.LIB for the full license.
+
+=head1 SEE ALSO
+
+L<Sys::VirtV2V::Converter(3pm)>,
+L<virt-v2v(1)>,
+L<http://libguestfs.org/>.
+
+=cut
+
+1;
diff --git a/v2v/virt-v2v.pl b/v2v/virt-v2v.pl
index 351caf1..c1a4728 100755
--- a/v2v/virt-v2v.pl
+++ b/v2v/virt-v2v.pl
@@ -225,6 +225,11 @@ if(defined($config_file)) {
my $target;
if ($output_method eq "libvirt") {
+ pod2usage({ -message => __("You must specify an output storage pool ".
+ "when using the libvirt output method"),
+ -exitval => 1 })
+ unless (defined($output_pool));
+
$target = new Sys::VirtV2V::Target::LibVirt($output_uri, $output_pool);
}
@@ -257,7 +262,7 @@ eval {
modulename => 'libvirtxml'));
}
- $conn = Sys::VirtV2V::Connection::LibVirtXML->new($path);
+ $conn = Sys::VirtV2V::Connection::LibVirtXML->new($path, $target);
}
elsif ($input_method eq "libvirt") {
--
1.6.6.1