We used to fetch the volume in a HEAD request. After receiving the header, which contains the content length, we created the target volume and opened it for writing before continuing to receive data. This created a problem if volume creation took long enough for the transfer to time out. To fix this, we get the size first with a HEAD request. Create the volume, then do a second GET request to receive the data. This fixes RHBZ#586816 --- lib/Sys/VirtV2V/Transfer/ESX.pm | 30 ++++++++++++++++++++++++------ 1 files changed, 24 insertions(+), 6 deletions(-) diff --git a/lib/Sys/VirtV2V/Transfer/ESX.pm b/lib/Sys/VirtV2V/Transfer/ESX.pm index fb0c6ea..f638149 100644 --- a/lib/Sys/VirtV2V/Transfer/ESX.pm +++ b/lib/Sys/VirtV2V/Transfer/ESX.pm @@ -121,10 +121,22 @@ sub get_volume return $target->get_volume($volname); } + # Head request to get the size and create the 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); + } + $self->{_v2v_received} = 0; - my $r = $self->SUPER::get($url, - ':content_cb' => sub { $self->handle_data(@_); }, - ':read_size_hint' => 64 * 1024); + $r = $self->get($url, + ':content_cb' => sub { $self->handle_data(@_); }, + ':read_size_hint' => 64 * 1024); if ($r->is_success) { # It reports success even if one of the callbacks died @@ -143,6 +155,13 @@ sub get_volume return $vol; } + $self->report_error($r); +} + +sub report_error +{ + my $self = shift; + my ($r) = @_; if ($r->code == 401) { die(user_message(__x("Authentication error connecting to ". @@ -173,10 +192,9 @@ sub handle_data my ($data, $response) = @_; - # Create the volume if it hasn't been created already - if (!defined($self->{_v2v_vol}) && $response->is_success) { + # Verify the certificate of the get request the first time we're called + if ($self->{_v2v_received} == 0) { $self->verify_certificate($response) unless ($self->{_v2v_noverify}); - $self->create_volume($response); } $self->{_v2v_received} += length($data); -- 1.6.6.1