[Libguestfs] [PATCH 2/2] ESX: Get volume size in a separate HEAD request

Matthew Booth mbooth at redhat.com
Wed Apr 28 16:18:59 UTC 2010


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




More information about the Libguestfs mailing list