If an ESX guest has a snapshot, the path the libvirt driver gives us will look
like:
[yellow:storage1] RHEL4-X/RHEL4-X-000003.vmdk
instead of:
[yellow:storage1] RHEL4-X/RHEL4-X.vmdk
The current path mangling code does take this into account.
This change makes it use the current mechanism first, but try again after
removing a '-\d+' suffix if it gets a 404. Trying twice should make it continue
to work in the event that a local naming scheme matches the suffix used for
snapshots. Ideally we would be able to get this information from the libvirt
driver, but it's not implemented yet.
---
lib/Sys/VirtV2V/Transfer/ESX.pm | 52 +++++++++++++++++++++++++++++++-------
1 files changed, 42 insertions(+), 10 deletions(-)
diff --git a/lib/Sys/VirtV2V/Transfer/ESX.pm b/lib/Sys/VirtV2V/Transfer/ESX.pm
index 5d6b586..faf872d 100644
--- a/lib/Sys/VirtV2V/Transfer/ESX.pm
+++ b/lib/Sys/VirtV2V/Transfer/ESX.pm
@@ -102,9 +102,7 @@ sub get_volume
my $datastore = $1;
my $vmdk = $2;
- my $url = URI->new("https://".$self->{_v2v_server});
- $url->path("/folder/$vmdk-flat.vmdk");
- $url->query_form(dcPath => "ha-datacenter", dsName =>
$datastore);
+ my $url = _get_vol_url($self->{_v2v_server}, $vmdk, $datastore);
# Replace / with _ so the vmdk name can be used as a volume name
my $volname = $vmdk;
@@ -125,16 +123,39 @@ sub get_volume
# We could do this with a single GET request. The problem with this is that
# you have to create the volume before writing to it. If the volume creation
# takes a very long time, the transfer may fail in the mean time.
- my $r = $self->head($url);
- if ($r->is_success) {
- $self->verify_certificate($r) unless ($self->{_v2v_noverify});
- $self->create_volume($r);
- } else {
- $self->report_error($r);
+ my $retried = 0;
+ SIZE: for(;;) {
+ my $r = $self->head($url);
+ if ($r->is_success) {
+ $self->verify_certificate($r) unless ($self->{_v2v_noverify});
+ $self->create_volume($r);
+ last SIZE;
+ }
+
+ # If a disk is actually a snapshot image it will have '-00000n'
+ # appended to its name, e.g.:
+ # [yellow:storage1] RHEL4-X/RHEL4-X-000003.vmdk
+ # The flat storage is still called RHEL4-X-flat, however.
+ # If we got a 404 and the vmdk name looks like it might be a snapshot,
+ # try again without the snapshot suffix.
+ # XXX: We're in flaky heuristic territory here. When the libvirt ESX
+ # driver implements the volume apis we should look for this information
+ # there instead.
+ elsif ($r->code == 404 && $retried == 0) {
+ $retried = 1;
+ if ($vmdk =~ /^(.*)-\d+$/) {
+ $vmdk = $1;
+ $url = _get_vol_url($self->{_v2v_server}, $vmdk, $datastore);
+ }
+ }
+
+ else {
+ $self->report_error($r);
+ }
}
$self->{_v2v_received} = 0;
- $r = $self->get($url,
+ my $r = $self->get($url,
':content_cb' => sub { $self->handle_data(@_); },
':read_size_hint' => 64 * 1024);
@@ -160,6 +181,17 @@ sub get_volume
$self->report_error($r);
}
+sub _get_vol_url
+{
+ my ($server, $vmdk, $datastore) = @_;
+
+ my $url = URI->new("https://".$server);
+ $url->path("/folder/$vmdk-flat.vmdk");
+ $url->query_form(dcPath => "ha-datacenter", dsName =>
$datastore);
+
+ return $url;
+}
+
sub report_error
{
my $self = shift;
--
1.7.0.1