[Libguestfs] [PATCH 1/2] v2v: rhv-upload-plugin: Handle send send failures

Nir Soffer
2018-08-20T22:15:02Z

The oVirt server may fail a PUT request before reading all request body.
However before closing the connection, it writes a detailed error
response, that will make debugging issues like expired tickets much
easier to handle. If we don't get the response and log the error, the
error may be lost when the daemon log is rotated.

Change pwrite() and emulate_zero() to get the response after EPIPE,
failing with the error response from the oVirt server.

Here is an example error log when a ticket expires during import:

nbdkit: python[1]: error:
/home/nsoffer/src/libguestfs/tmp/v2v.pRoyXm/rhv-upload-plugin.py:
pwrite: error: ('%s: %d %s: %r', 'could not write sector offset
1841154048 size 1024', 403,
'Forbidden', b'{"explanation": "Access was denied to
this resource.", "code": 403, "detail":
"Ticket u\'6071e16f-ec60-4ff9-a594-10b0faae3617\' expired",
"title": "Forbidden"}')
---
 v2v/rhv-upload-plugin.py | 22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py
index 2d686c2da..7327ea4c5 100644
--- a/v2v/rhv-upload-plugin.py
+++ b/v2v/rhv-upload-plugin.py
@@ -17,6 +17,7 @@
 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

 import builtins
+import errno
 import json
 import logging
 import socket
@@ -357,7 +358,12 @@ def pwrite(h, buf, offset):
     http.putheader("Content-Range", "bytes %d-%d/*" %
(offset, offset+count-1))
     http.putheader("Content-Length", str(count))
     http.endheaders()
-    http.send(buf)
+
+    try:
+        http.send(buf)
+    except socket.error as e:
+        if e[0] != errno.EPIPE:
+            raise

     r = http.getresponse()
     if r.status != 200:
@@ -413,11 +419,15 @@ def emulate_zero(h, count, offset):
         http.putheader("Content-Length", str(count))
         http.endheaders()

-        buf = bytearray(128*1024)
-        while count > len(buf):
-            http.send(buf)
-            count -= len(buf)
-        http.send(buffer(buf, 0, count))
+        try:
+            buf = bytearray(128*1024)
+            while count > len(buf):
+                http.send(buf)
+                count -= len(buf)
+            http.send(buffer(buf, 0, count))
+        except socket.error as e:
+            if e[0] != errno.EPIPE:
+                raise

         r = http.getresponse()
         if r.status != 200:
--
2.17.1