Prevent down nodes failing PUTs with non-ascii obj names
On an object PUT with a non-ascii name, if we hit some kind of exception speaking to only one object-server of the N we try to connect to, we try to log it -- but this causes an exception when interpolating the UTF-8 encoded path iff the message template is unicode. Since this is essentially an exception within an exception handler, this fails the entire request with a 500 error -- even though the other nodes may have been just fine. This occurs before it attempts a handoff node. The simplest way to reproduce this is by running func tests against a small cluster where one of the object nodes is not running N.B. The locale of the node does not matter because the message template is interpolated with node/device data from the Ring which is always unicode because of json. This includes an update to the FakeRing used by unittest infrastructure to ensure that the FakeRing devices make a round-trip through json to ensure consistent typing with real Rings. Change-Id: Icb7284eb5abc9869c1620ee6366817112d8e5587 Closes-bug: #1597210
This commit is contained in:
parent
79be80f126
commit
7568ea5dd9
@ -535,7 +535,7 @@ class Application(object):
|
|||||||
' re: %(info)s'),
|
' re: %(info)s'),
|
||||||
{'type': typ, 'ip': node['ip'],
|
{'type': typ, 'ip': node['ip'],
|
||||||
'port': node['port'], 'device': node['device'],
|
'port': node['port'], 'device': node['device'],
|
||||||
'info': additional_info},
|
'info': additional_info.decode('utf-8')},
|
||||||
**kwargs)
|
**kwargs)
|
||||||
|
|
||||||
def modify_wsgi_pipeline(self, pipe):
|
def modify_wsgi_pipeline(self, pipe):
|
||||||
|
@ -32,6 +32,7 @@ import eventlet
|
|||||||
from eventlet.green import socket
|
from eventlet.green import socket
|
||||||
from tempfile import mkdtemp
|
from tempfile import mkdtemp
|
||||||
from shutil import rmtree
|
from shutil import rmtree
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
from swift.common.utils import Timestamp, NOTICE
|
from swift.common.utils import Timestamp, NOTICE
|
||||||
@ -223,7 +224,8 @@ class FakeRing(Ring):
|
|||||||
for x in range(self.replicas):
|
for x in range(self.replicas):
|
||||||
ip = '10.0.0.%s' % x
|
ip = '10.0.0.%s' % x
|
||||||
port = self._base_port + x
|
port = self._base_port + x
|
||||||
self._devs.append({
|
# round trip through json to ensure unicode like real rings
|
||||||
|
self._devs.append(json.loads(json.dumps({
|
||||||
'ip': ip,
|
'ip': ip,
|
||||||
'replication_ip': ip,
|
'replication_ip': ip,
|
||||||
'port': port,
|
'port': port,
|
||||||
@ -232,7 +234,7 @@ class FakeRing(Ring):
|
|||||||
'zone': x % 3,
|
'zone': x % 3,
|
||||||
'region': x % 2,
|
'region': x % 2,
|
||||||
'id': x,
|
'id': x,
|
||||||
})
|
})))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def replica_count(self):
|
def replica_count(self):
|
||||||
|
@ -856,6 +856,20 @@ class TestReplicatedObjController(BaseObjectControllerMixin,
|
|||||||
node_error_count(self.app, object_ring.devs[1]),
|
node_error_count(self.app, object_ring.devs[1]),
|
||||||
self.app.error_suppression_limit + 1)
|
self.app.error_suppression_limit + 1)
|
||||||
|
|
||||||
|
def test_PUT_connect_exception_with_unicode_path_and_locale(self):
|
||||||
|
expected = 201
|
||||||
|
statuses = (
|
||||||
|
Exception('Connection refused: Please insert ten dollars'),
|
||||||
|
201, 201)
|
||||||
|
|
||||||
|
req = swob.Request.blank('/v1/AUTH_kilroy/%ED%88%8E/%E9%90%89',
|
||||||
|
method='PUT',
|
||||||
|
body='life is utf-gr8')
|
||||||
|
with set_http_connect(*statuses):
|
||||||
|
resp = req.get_response(self.app)
|
||||||
|
|
||||||
|
self.assertEqual(resp.status_int, expected)
|
||||||
|
|
||||||
def test_PUT_error_during_transfer_data(self):
|
def test_PUT_error_during_transfer_data(self):
|
||||||
class FakeReader(object):
|
class FakeReader(object):
|
||||||
def read(self, size):
|
def read(self, size):
|
||||||
|
Loading…
Reference in New Issue
Block a user