|
|
d0ea73 |
From c2ed35e2bc17bcacf333626b21cd6796d4d8d6cf Mon Sep 17 00:00:00 2001
|
|
|
d0ea73 |
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
|
d0ea73 |
Date: Tue, 5 Jun 2018 13:27:43 +0100
|
|
|
d0ea73 |
Subject: [PATCH] v2v: -o rhv-upload: Log full imageio response on failure.
|
|
|
d0ea73 |
|
|
|
d0ea73 |
Thanks: Nir Soffer
|
|
|
d0ea73 |
(cherry picked from commit 831a75cd11c5a87e40fccdadcb62353f6a4d5a72)
|
|
|
d0ea73 |
---
|
|
|
d0ea73 |
v2v/rhv-upload-plugin.py | 69 ++++++++++++++++++++++++----------------
|
|
|
d0ea73 |
1 file changed, 42 insertions(+), 27 deletions(-)
|
|
|
d0ea73 |
|
|
|
d0ea73 |
diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py
|
|
|
d0ea73 |
index 9ad354b84..7c5084efd 100644
|
|
|
d0ea73 |
--- a/v2v/rhv-upload-plugin.py
|
|
|
d0ea73 |
+++ b/v2v/rhv-upload-plugin.py
|
|
|
d0ea73 |
@@ -227,6 +227,32 @@ def can_flush(h):
|
|
|
d0ea73 |
def get_size(h):
|
|
|
d0ea73 |
return params['disk_size']
|
|
|
d0ea73 |
|
|
|
d0ea73 |
+# Any unexpected HTTP response status from the server will end up
|
|
|
d0ea73 |
+# calling this function which logs the full error, pauses the
|
|
|
d0ea73 |
+# transfer, sets the failed state, and raises a RuntimeError
|
|
|
d0ea73 |
+# exception.
|
|
|
d0ea73 |
+def request_failed(h, r, msg):
|
|
|
d0ea73 |
+ # Setting the failed flag in the handle causes the disk to be
|
|
|
d0ea73 |
+ # cleaned up on close.
|
|
|
d0ea73 |
+ h['failed'] = True
|
|
|
d0ea73 |
+ h['transfer_service'].pause()
|
|
|
d0ea73 |
+
|
|
|
d0ea73 |
+ status = r.status
|
|
|
d0ea73 |
+ reason = r.reason
|
|
|
d0ea73 |
+ try:
|
|
|
d0ea73 |
+ body = r.read()
|
|
|
d0ea73 |
+ except EnvironmentError as e:
|
|
|
d0ea73 |
+ body = "(Unable to read response body: %s)" % e
|
|
|
d0ea73 |
+
|
|
|
d0ea73 |
+ # Log the full error if we're verbose.
|
|
|
d0ea73 |
+ debug("unexpected response from imageio server:")
|
|
|
d0ea73 |
+ debug(msg)
|
|
|
d0ea73 |
+ debug("%d: %s" % (status, reason))
|
|
|
d0ea73 |
+ debug(body)
|
|
|
d0ea73 |
+
|
|
|
d0ea73 |
+ # Only a short error is included in the exception.
|
|
|
d0ea73 |
+ raise RuntimeError("%s: %d %s: %r", msg, status, reason, body[:200])
|
|
|
d0ea73 |
+
|
|
|
d0ea73 |
# For documentation see:
|
|
|
d0ea73 |
# https://github.com/oVirt/ovirt-imageio/blob/master/docs/random-io.md
|
|
|
d0ea73 |
# For examples of working code to read/write from the server, see:
|
|
|
d0ea73 |
@@ -247,16 +273,14 @@ def pread(h, count, offset):
|
|
|
d0ea73 |
r = http.getresponse()
|
|
|
d0ea73 |
# 206 = HTTP Partial Content.
|
|
|
d0ea73 |
if r.status != 206:
|
|
|
d0ea73 |
- h['transfer_service'].pause()
|
|
|
d0ea73 |
- h['failed'] = True
|
|
|
d0ea73 |
- raise RuntimeError("could not read sector (%d, %d): %d: %s" %
|
|
|
d0ea73 |
- (offset, count, r.status, r.reason))
|
|
|
d0ea73 |
+ request_failed(h, r,
|
|
|
d0ea73 |
+ "could not read sector offset %d size %d" %
|
|
|
d0ea73 |
+ (offset, count))
|
|
|
d0ea73 |
return r.read()
|
|
|
d0ea73 |
|
|
|
d0ea73 |
def pwrite(h, buf, offset):
|
|
|
d0ea73 |
http = h['http']
|
|
|
d0ea73 |
transfer = h['transfer']
|
|
|
d0ea73 |
- transfer_service = h['transfer_service']
|
|
|
d0ea73 |
|
|
|
d0ea73 |
count = len(buf)
|
|
|
d0ea73 |
h['highestwrite'] = max(h['highestwrite'], offset+count)
|
|
|
d0ea73 |
@@ -274,15 +298,13 @@ def pwrite(h, buf, offset):
|
|
|
d0ea73 |
|
|
|
d0ea73 |
r = http.getresponse()
|
|
|
d0ea73 |
if r.status != 200:
|
|
|
d0ea73 |
- transfer_service.pause()
|
|
|
d0ea73 |
- h['failed'] = True
|
|
|
d0ea73 |
- raise RuntimeError("could not write sector (%d, %d): %d: %s" %
|
|
|
d0ea73 |
- (offset, count, r.status, r.reason))
|
|
|
d0ea73 |
+ request_failed(h, r,
|
|
|
d0ea73 |
+ "could not write sector offset %d size %d" %
|
|
|
d0ea73 |
+ (offset, count))
|
|
|
d0ea73 |
|
|
|
d0ea73 |
def zero(h, count, offset, may_trim):
|
|
|
d0ea73 |
http = h['http']
|
|
|
d0ea73 |
transfer = h['transfer']
|
|
|
d0ea73 |
- transfer_service = h['transfer_service']
|
|
|
d0ea73 |
|
|
|
d0ea73 |
# Unlike the trim and flush calls, there is no 'can_zero' method
|
|
|
d0ea73 |
# so nbdkit could call this even if the server doesn't support
|
|
|
d0ea73 |
@@ -304,10 +326,9 @@ def zero(h, count, offset, may_trim):
|
|
|
d0ea73 |
|
|
|
d0ea73 |
r = http.getresponse()
|
|
|
d0ea73 |
if r.status != 200:
|
|
|
d0ea73 |
- transfer_service.pause()
|
|
|
d0ea73 |
- h['failed'] = True
|
|
|
d0ea73 |
- raise RuntimeError("could not zero sector (%d, %d): %d: %s" %
|
|
|
d0ea73 |
- (offset, count, r.status, r.reason))
|
|
|
d0ea73 |
+ request_failed(h, r,
|
|
|
d0ea73 |
+ "could not zero sector offset %d size %d" %
|
|
|
d0ea73 |
+ (offset, count))
|
|
|
d0ea73 |
|
|
|
d0ea73 |
def emulate_zero(h, count, offset):
|
|
|
d0ea73 |
# qemu-img convert starts by trying to zero/trim the whole device.
|
|
|
d0ea73 |
@@ -332,15 +353,13 @@ def emulate_zero(h, count, offset):
|
|
|
d0ea73 |
|
|
|
d0ea73 |
r = http.getresponse()
|
|
|
d0ea73 |
if r.status != 200:
|
|
|
d0ea73 |
- transfer_service.pause()
|
|
|
d0ea73 |
- h['failed'] = True
|
|
|
d0ea73 |
- raise RuntimeError("could not write zeroes (%d, %d): %d: %s" %
|
|
|
d0ea73 |
- (offset, count, r.status, r.reason))
|
|
|
d0ea73 |
+ request_failed(h, r,
|
|
|
d0ea73 |
+ "could not write zeroes offset %d size %d" %
|
|
|
d0ea73 |
+ (offset, count))
|
|
|
d0ea73 |
|
|
|
d0ea73 |
def trim(h, count, offset):
|
|
|
d0ea73 |
http = h['http']
|
|
|
d0ea73 |
transfer = h['transfer']
|
|
|
d0ea73 |
- transfer_service = h['transfer_service']
|
|
|
d0ea73 |
|
|
|
d0ea73 |
# Construct the JSON request for trimming.
|
|
|
d0ea73 |
buf = json.dumps({'op': "trim",
|
|
|
d0ea73 |
@@ -355,15 +374,13 @@ def trim(h, count, offset):
|
|
|
d0ea73 |
|
|
|
d0ea73 |
r = http.getresponse()
|
|
|
d0ea73 |
if r.status != 200:
|
|
|
d0ea73 |
- transfer_service.pause()
|
|
|
d0ea73 |
- h['failed'] = True
|
|
|
d0ea73 |
- raise RuntimeError("could not trim sector (%d, %d): %d: %s" %
|
|
|
d0ea73 |
- (offset, count, r.status, r.reason))
|
|
|
d0ea73 |
+ request_failed(h, r,
|
|
|
d0ea73 |
+ "could not trim sector offset %d size %d" %
|
|
|
d0ea73 |
+ (offset, count))
|
|
|
d0ea73 |
|
|
|
d0ea73 |
def flush(h):
|
|
|
d0ea73 |
http = h['http']
|
|
|
d0ea73 |
transfer = h['transfer']
|
|
|
d0ea73 |
- transfer_service = h['transfer_service']
|
|
|
d0ea73 |
|
|
|
d0ea73 |
# Construct the JSON request for flushing.
|
|
|
d0ea73 |
buf = json.dumps({'op': "flush"}).encode()
|
|
|
d0ea73 |
@@ -375,9 +392,7 @@ def flush(h):
|
|
|
d0ea73 |
|
|
|
d0ea73 |
r = http.getresponse()
|
|
|
d0ea73 |
if r.status != 200:
|
|
|
d0ea73 |
- transfer_service.pause()
|
|
|
d0ea73 |
- h['failed'] = True
|
|
|
d0ea73 |
- raise RuntimeError("could not flush: %d: %s" % (r.status, r.reason))
|
|
|
d0ea73 |
+ request_failed(h, r, "could not flush")
|
|
|
d0ea73 |
|
|
|
d0ea73 |
def delete_disk_on_failure(h):
|
|
|
d0ea73 |
disk_service = h['disk_service']
|
|
|
d0ea73 |
--
|
|
|
d0ea73 |
2.20.1
|
|
|
d0ea73 |
|