Make DirectClientException report correct ip and port
When direct_client.direct_get_suffix_hashes raises a DirectClientException the exception message and variables should report the replication_ip and replication_port, as opposed to the ip and port values reported for all other case when the exception is raised. Add option to override ip and port reported in DirectClientException. Also adds unit tests to verify both cases. Related-Bug: 1566395 Change-Id: If3d952847c7199f4e9f6164858085367266386d2
This commit is contained in:
parent
950b601a9c
commit
5d56f40f04
|
@ -39,13 +39,16 @@ from swift.common.utils import quote
|
|||
|
||||
class DirectClientException(ClientException):
|
||||
|
||||
def __init__(self, stype, method, node, part, path, resp):
|
||||
def __init__(self, stype, method, node, part, path, resp, host=None):
|
||||
# host can be used to override the node ip and port reported in
|
||||
# the exception
|
||||
host = host if host is not None else node
|
||||
full_path = quote('/%s/%s%s' % (node['device'], part, path))
|
||||
msg = '%s server %s:%s direct %s %r gave status %s' % (
|
||||
stype, node['ip'], node['port'], method, full_path, resp.status)
|
||||
stype, host['ip'], host['port'], method, full_path, resp.status)
|
||||
headers = HeaderKeyDict(resp.getheaders())
|
||||
super(DirectClientException, self).__init__(
|
||||
msg, http_host=node['ip'], http_port=node['port'],
|
||||
msg, http_host=host['ip'], http_port=host['port'],
|
||||
http_device=node['device'], http_status=resp.status,
|
||||
http_reason=resp.reason, http_headers=headers)
|
||||
|
||||
|
@ -489,7 +492,10 @@ def direct_get_suffix_hashes(node, part, suffixes, conn_timeout=5,
|
|||
resp = conn.getresponse()
|
||||
if not is_success(resp.status):
|
||||
raise DirectClientException('Object', 'REPLICATE',
|
||||
node, part, path, resp)
|
||||
node, part, path, resp,
|
||||
host={'ip': node['replication_ip'],
|
||||
'port': node['replication_port']}
|
||||
)
|
||||
return pickle.loads(resp.read())
|
||||
|
||||
|
||||
|
|
|
@ -26,9 +26,10 @@ import six
|
|||
from six.moves import urllib
|
||||
|
||||
from swift.common import direct_client
|
||||
from swift.common.direct_client import DirectClientException
|
||||
from swift.common.exceptions import ClientException
|
||||
from swift.common.header_key_dict import HeaderKeyDict
|
||||
from swift.common.utils import Timestamp
|
||||
from swift.common.utils import Timestamp, quote
|
||||
from swift.common.swob import RESPONSE_REASONS
|
||||
from swift.common.storage_policy import POLICIES
|
||||
from six.moves.http_client import HTTPException
|
||||
|
@ -631,6 +632,28 @@ class TestDirectClient(unittest.TestCase):
|
|||
self.assertEqual(conn.port, '7000')
|
||||
self.assertEqual(data, resp)
|
||||
|
||||
def _test_direct_get_suffix_hashes_fail(self, status_code):
|
||||
with mocked_http_conn(status_code):
|
||||
with self.assertRaises(DirectClientException) as cm:
|
||||
direct_client.direct_get_suffix_hashes(
|
||||
self.node, self.part, ['a83', 'b52'])
|
||||
self.assertIn('REPLICATE', cm.exception.message)
|
||||
self.assertIn(quote('/%s/%s/a83-b52'
|
||||
% (self.node['device'], self.part)),
|
||||
cm.exception.message)
|
||||
self.assertIn(self.node['replication_ip'], cm.exception.message)
|
||||
self.assertIn(self.node['replication_port'], cm.exception.message)
|
||||
self.assertEqual(self.node['replication_ip'], cm.exception.http_host)
|
||||
self.assertEqual(self.node['replication_port'], cm.exception.http_port)
|
||||
self.assertEqual(self.node['device'], cm.exception.http_device)
|
||||
self.assertEqual(status_code, cm.exception.http_status)
|
||||
|
||||
def test_direct_get_suffix_hashes_503(self):
|
||||
self._test_direct_get_suffix_hashes_fail(503)
|
||||
|
||||
def test_direct_get_suffix_hashes_507(self):
|
||||
self._test_direct_get_suffix_hashes_fail(507)
|
||||
|
||||
def test_direct_put_object_with_content_length(self):
|
||||
contents = six.StringIO('123456')
|
||||
|
||||
|
@ -720,6 +743,17 @@ class TestDirectClient(unittest.TestCase):
|
|||
retries=2, error_log=logger.error)
|
||||
self.assertEqual('DELETE', conn.method)
|
||||
self.assertEqual(err_ctx.exception.http_status, 500)
|
||||
self.assertIn('DELETE', err_ctx.exception.message)
|
||||
self.assertIn(quote('/%s/%s/%s/%s/%s'
|
||||
% (self.node['device'], self.part, self.account,
|
||||
self.container, self.obj)),
|
||||
err_ctx.exception.message)
|
||||
self.assertIn(self.node['ip'], err_ctx.exception.message)
|
||||
self.assertIn(self.node['port'], err_ctx.exception.message)
|
||||
self.assertEqual(self.node['ip'], err_ctx.exception.http_host)
|
||||
self.assertEqual(self.node['port'], err_ctx.exception.http_port)
|
||||
self.assertEqual(self.node['device'], err_ctx.exception.http_device)
|
||||
self.assertEqual(500, err_ctx.exception.http_status)
|
||||
self.assertEqual([mock.call(1), mock.call(2)],
|
||||
mock_sleep.call_args_list)
|
||||
error_lines = logger.get_lines_for_level('error')
|
||||
|
|
Loading…
Reference in New Issue