e9bfca
From 320ba554d11f75c4c2753968505a1d3308b64dda Mon Sep 17 00:00:00 2001
e9bfca
From: Nir Soffer <nirsof@gmail.com>
e9bfca
Date: Mon, 25 Jun 2018 19:22:13 +0300
e9bfca
Subject: [PATCH] v2v: rvh-upload-plugin: Always read the response
e9bfca
e9bfca
Python manual warns[1]:
e9bfca
e9bfca
    Note that you must have read the whole response before you can send
e9bfca
    a new request to the server.
e9bfca
e9bfca
The reason for this warning is exposed only when the server is using
e9bfca
keep alive connections. When the response is not read, sending a new
e9bfca
request will fail with:
e9bfca
e9bfca
    httplib.ResponseNotReady
e9bfca
e9bfca
Even if Content-Length was 0 or the request has no content. The failure
e9bfca
looks like this when using --verbose:
e9bfca
e9bfca
nbdkit: python[1]: debug: zero count=33554432 offset=0 may_trim=1 fua=0
e9bfca
nbdkit: python[1]: debug: zero count=33554432 offset=33554432 may_trim=1 fua=0
e9bfca
nbdkit: python[1]: error: /home/nsoffer/src/libguestfs/tmp/rhvupload.Au2B5I/rhv-upload-plugin.py: zero: error: Request-sent
e9bfca
nbdkit: python[1]: debug: sending error reply: Input/output error
e9bfca
qemu-img: error writing zeroes at offset 0: Input/output error
e9bfca
e9bfca
Change all requests to read the whole response.
e9bfca
e9bfca
Tested with imageio patch supporting keep alive connections:
e9bfca
https://gerrit.ovirt.org/#/c/92296/
e9bfca
e9bfca
[1] https://docs.python.org/3.8/library/http.client.html#http.client.HTTPConnection.getresponse
e9bfca
e9bfca
(cherry picked from commit f4e0a8342dbeb2c779c76e1807a37b24a0c96feb)
e9bfca
---
e9bfca
 v2v/rhv-upload-plugin.py | 15 ++++++++++++++-
e9bfca
 1 file changed, 14 insertions(+), 1 deletion(-)
e9bfca
e9bfca
diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py
e9bfca
index 7c5084efd..2eec375f7 100644
e9bfca
--- a/v2v/rhv-upload-plugin.py
e9bfca
+++ b/v2v/rhv-upload-plugin.py
e9bfca
@@ -197,11 +197,13 @@ def get_options(h):
e9bfca
     http.endheaders()
e9bfca
 
e9bfca
     r = http.getresponse()
e9bfca
+    data = r.read()
e9bfca
+
e9bfca
     if r.status == 200:
e9bfca
         # New imageio never needs authentication.
e9bfca
         h['needs_auth'] = False
e9bfca
 
e9bfca
-        j = json.loads(r.read())
e9bfca
+        j = json.loads(data)
e9bfca
         h['can_zero'] = "zero" in j['features']
e9bfca
         h['can_trim'] = "trim" in j['features']
e9bfca
         h['can_flush'] = "flush" in j['features']
e9bfca
@@ -276,6 +278,7 @@ def pread(h, count, offset):
e9bfca
         request_failed(h, r,
e9bfca
                        "could not read sector offset %d size %d" %
e9bfca
                        (offset, count))
e9bfca
+
e9bfca
     return r.read()
e9bfca
 
e9bfca
 def pwrite(h, buf, offset):
e9bfca
@@ -302,6 +305,8 @@ def pwrite(h, buf, offset):
e9bfca
                        "could not write sector offset %d size %d" %
e9bfca
                        (offset, count))
e9bfca
 
e9bfca
+    r.read()
e9bfca
+
e9bfca
 def zero(h, count, offset, may_trim):
e9bfca
     http = h['http']
e9bfca
     transfer = h['transfer']
e9bfca
@@ -330,6 +335,8 @@ def zero(h, count, offset, may_trim):
e9bfca
                        "could not zero sector offset %d size %d" %
e9bfca
                        (offset, count))
e9bfca
 
e9bfca
+    r.read()
e9bfca
+
e9bfca
 def emulate_zero(h, count, offset):
e9bfca
     # qemu-img convert starts by trying to zero/trim the whole device.
e9bfca
     # Since we've just created a new disk it's safe to ignore these
e9bfca
@@ -357,6 +364,8 @@ def emulate_zero(h, count, offset):
e9bfca
                            "could not write zeroes offset %d size %d" %
e9bfca
                            (offset, count))
e9bfca
 
e9bfca
+        r.read()
e9bfca
+
e9bfca
 def trim(h, count, offset):
e9bfca
     http = h['http']
e9bfca
     transfer = h['transfer']
e9bfca
@@ -378,6 +387,8 @@ def trim(h, count, offset):
e9bfca
                        "could not trim sector offset %d size %d" %
e9bfca
                        (offset, count))
e9bfca
 
e9bfca
+    r.read()
e9bfca
+
e9bfca
 def flush(h):
e9bfca
     http = h['http']
e9bfca
     transfer = h['transfer']
e9bfca
@@ -394,6 +405,8 @@ def flush(h):
e9bfca
     if r.status != 200:
e9bfca
         request_failed(h, r, "could not flush")
e9bfca
 
e9bfca
+    r.read()
e9bfca
+
e9bfca
 def delete_disk_on_failure(h):
e9bfca
     disk_service = h['disk_service']
e9bfca
     disk_service.remove()
e9bfca
-- 
8ff76f
2.20.1
e9bfca