def test_upload_tarball_by_url_https_failed_retry_v1(self):
fake_conn = mock.Mock()
mock_HTTPSConn = self.mock_patch_object(
self.glance, '_create_connection', fake_conn)
mock_validate_image = self.mock_patch_object(
self.glance, 'validate_image_status_before_upload_v1')
mock_create_tarball = self.mock_patch_object(
self.glance.utils, 'create_tarball')
mock_check_resp_status = self.mock_patch_object(
self.glance, 'check_resp_status_and_retry')
self.glance._create_connection().getresponse = mock.Mock()
self.glance._create_connection().getresponse().status = \
httplib.REQUEST_TIMEOUT
fake_extra_headers = {}
fake_properties = {}
fake_endpoint = 'https://fake_netloc/fake_path'
expected_url = "%(glance_endpoint)s/v1/images/%(image_id)s" % {
'glance_endpoint': fake_endpoint,
'image_id': 'fake_image_id'}
self.glance._upload_tarball_by_url_v1(
'fake_staging_path', 'fake_image_id', fake_endpoint,
fake_extra_headers, fake_properties)
self.assertTrue(mock_HTTPSConn.called)
mock_validate_image.assert_called_with(fake_conn,
expected_url,
fake_extra_headers)
self.assertTrue(mock_create_tarball.called)
self.assertTrue(
mock_HTTPSConn.return_value.getresponse.called)
self.assertTrue(mock_check_resp_status.called)
python类REQUEST_TIMEOUT的实例源码
def _should_retry(resp):
"""Given a urlfetch response, decide whether to retry that request."""
return (resp.status_code == httplib.REQUEST_TIMEOUT or
(resp.status_code >= 500 and
resp.status_code < 600))
def _should_retry(resp):
"""Given a urlfetch response, decide whether to retry that request."""
return (resp.status_code == httplib.REQUEST_TIMEOUT or
(resp.status_code >= 500 and
resp.status_code < 600))
def check_resp_status_and_retry(resp, image_id, url):
# Note(Jesse): This branch sorts errors into those that are permanent,
# those that are ephemeral, and those that are unexpected.
if resp.status in (httplib.BAD_REQUEST, # 400
httplib.UNAUTHORIZED, # 401
httplib.PAYMENT_REQUIRED, # 402
httplib.FORBIDDEN, # 403
httplib.METHOD_NOT_ALLOWED, # 405
httplib.NOT_ACCEPTABLE, # 406
httplib.PROXY_AUTHENTICATION_REQUIRED, # 407
httplib.CONFLICT, # 409
httplib.GONE, # 410
httplib.LENGTH_REQUIRED, # 411
httplib.PRECONDITION_FAILED, # 412
httplib.REQUEST_ENTITY_TOO_LARGE, # 413
httplib.REQUEST_URI_TOO_LONG, # 414
httplib.UNSUPPORTED_MEDIA_TYPE, # 415
httplib.REQUESTED_RANGE_NOT_SATISFIABLE, # 416
httplib.EXPECTATION_FAILED, # 417
httplib.UNPROCESSABLE_ENTITY, # 422
httplib.LOCKED, # 423
httplib.FAILED_DEPENDENCY, # 424
httplib.UPGRADE_REQUIRED, # 426
httplib.NOT_IMPLEMENTED, # 501
httplib.HTTP_VERSION_NOT_SUPPORTED, # 505
httplib.NOT_EXTENDED, # 510
):
raise PluginError("Got Permanent Error response [%i] while "
"uploading image [%s] to glance [%s]"
% (resp.status, image_id, url))
# Nova service would process the exception
elif resp.status == httplib.NOT_FOUND: # 404
exc = XenAPI.Failure('ImageNotFound')
raise exc
# NOTE(nikhil): Only a sub-set of the 500 errors are retryable. We
# optimistically retry on 500 errors below.
elif resp.status in (httplib.REQUEST_TIMEOUT, # 408
httplib.INTERNAL_SERVER_ERROR, # 500
httplib.BAD_GATEWAY, # 502
httplib.SERVICE_UNAVAILABLE, # 503
httplib.GATEWAY_TIMEOUT, # 504
httplib.INSUFFICIENT_STORAGE, # 507
):
raise RetryableError("Got Ephemeral Error response [%i] while "
"uploading image [%s] to glance [%s]"
% (resp.status, image_id, url))
else:
# Note(Jesse): Assume unexpected errors are retryable. If you are
# seeing this error message, the error should probably be added
# to either the ephemeral or permanent error list.
raise RetryableError("Got Unexpected Error response [%i] while "
"uploading image [%s] to glance [%s]"
% (resp.status, image_id, url))
def test_upload_tarball_by_url_https_failed_retry_v2(self):
fake_conn = mock.Mock()
mock_HTTPSConn = self.mock_patch_object(
self.glance, '_create_connection', fake_conn)
mock_validate_image = self.mock_patch_object(
self.glance, 'validate_image_status_before_upload_v2')
mock_create_tarball = self.mock_patch_object(
self.glance.utils, 'create_tarball')
mock_check_resp_status = self.mock_patch_object(
self.glance, 'check_resp_status_and_retry')
mock_update_image_meta = self.mock_patch_object(
self.glance, '_update_image_meta_v2')
self.glance._create_connection().getresponse = mock.Mock()
self.glance._create_connection().getresponse().status = \
httplib.REQUEST_TIMEOUT
fake_extra_headers = {}
fake_properties = {}
fake_endpoint = 'https://fake_netloc/fake_path'
fake_image_id = 'fake_image_id'
expected_url = "%(glance_endpoint)s/v2/images/%(image_id)s/file" % {
'glance_endpoint': fake_endpoint,
'image_id': fake_image_id}
expected_wsgi_path = '/fake_path/v2/images/%s' % fake_image_id
expected_mgt_url = "%(glance_endpoint)s/v2/images/%(image_id)s" % {
'glance_endpoint': fake_endpoint,
'image_id': fake_image_id}
expect_url_parts = urlparse(expected_url)
fake_mgt_parts = urlparse(expected_mgt_url)
fake_mgt_path = fake_mgt_parts[2]
self.glance._upload_tarball_by_url_v2(
'fake_staging_path', fake_image_id, fake_endpoint,
fake_extra_headers, fake_properties)
mock_update_image_meta.assert_called_with(fake_conn,
fake_extra_headers,
fake_properties,
fake_mgt_path)
mock_HTTPSConn.assert_called_with(expect_url_parts[0],
expect_url_parts[1])
mock_validate_image.assert_called_with(fake_conn,
expected_url,
fake_extra_headers,
expected_wsgi_path)
self.assertTrue(mock_create_tarball.called)
self.assertTrue(
mock_HTTPSConn.return_value.getresponse.called)
self.assertTrue(mock_check_resp_status.called)
def check_status(status, expected, path, headers=None,
resp_headers=None, body=None, extras=None):
"""Check HTTP response status is expected.
Args:
status: HTTP response status. int.
expected: a list of expected statuses. A list of ints.
path: filename or a path prefix.
headers: HTTP request headers.
resp_headers: HTTP response headers.
body: HTTP response body.
extras: extra info to be logged verbatim if error occurs.
Raises:
AuthorizationError: if authorization failed.
NotFoundError: if an object that's expected to exist doesn't.
TimeoutError: if HTTP request timed out.
ServerError: if server experienced some errors.
FatalError: if any other unexpected errors occurred.
"""
if status in expected:
return
msg = ('Expect status %r from Google Storage. But got status %d.\n'
'Path: %r.\n'
'Request headers: %r.\n'
'Response headers: %r.\n'
'Body: %r.\n'
'Extra info: %r.\n' %
(expected, status, path, headers, resp_headers, body, extras))
if status == httplib.UNAUTHORIZED:
raise AuthorizationError(msg)
elif status == httplib.FORBIDDEN:
raise ForbiddenError(msg)
elif status == httplib.NOT_FOUND:
raise NotFoundError(msg)
elif status == httplib.REQUEST_TIMEOUT:
raise TimeoutError(msg)
elif status == httplib.REQUESTED_RANGE_NOT_SATISFIABLE:
raise InvalidRange(msg)
elif (status == httplib.OK and 308 in expected and
httplib.OK not in expected):
raise FileClosedError(msg)
elif status >= 500:
raise ServerError(msg)
else:
raise FatalError(msg)
def check_status(status, expected, path, headers=None,
resp_headers=None, body=None, extras=None):
"""Check HTTP response status is expected.
Args:
status: HTTP response status. int.
expected: a list of expected statuses. A list of ints.
path: filename or a path prefix.
headers: HTTP request headers.
resp_headers: HTTP response headers.
body: HTTP response body.
extras: extra info to be logged verbatim if error occurs.
Raises:
AuthorizationError: if authorization failed.
NotFoundError: if an object that's expected to exist doesn't.
TimeoutError: if HTTP request timed out.
ServerError: if server experienced some errors.
FatalError: if any other unexpected errors occurred.
"""
if status in expected:
return
msg = ('Expect status %r from Google Storage. But got status %d.\n'
'Path: %r.\n'
'Request headers: %r.\n'
'Response headers: %r.\n'
'Body: %r.\n'
'Extra info: %r.\n' %
(expected, status, path, headers, resp_headers, body, extras))
if status == httplib.UNAUTHORIZED:
raise AuthorizationError(msg)
elif status == httplib.FORBIDDEN:
raise ForbiddenError(msg)
elif status == httplib.NOT_FOUND:
raise NotFoundError(msg)
elif status == httplib.REQUEST_TIMEOUT:
raise TimeoutError(msg)
elif status == httplib.REQUESTED_RANGE_NOT_SATISFIABLE:
raise InvalidRange(msg)
elif (status == httplib.OK and 308 in expected and
httplib.OK not in expected):
raise FileClosedError(msg)
elif status >= 500:
raise ServerError(msg)
else:
raise FatalError(msg)