Specify pickle protocol in REPLICATE()

The default pickle protocol in python3 is version 3. This is not
readable by a python2 interpreter.

Force the use of version 2 in the object server REPLICATE() function,
for compatibility with python 2.

Change-Id: I19d23570ff3a084d288de1308e059cfd8134d6ad
This commit is contained in:
Alexandre Lécuyer 2019-05-16 18:08:03 +02:00 committed by Tim Burke
parent b4c8cf192a
commit 4927b1f29c
2 changed files with 30 additions and 1 deletions

View File

@ -1256,7 +1256,8 @@ class ObjectController(BaseStorageServer):
except DiskFileDeviceUnavailable:
resp = HTTPInsufficientStorage(drive=device, request=request)
else:
resp = Response(body=pickle.dumps(hashes))
# force pickle protocol for compatibility with py2 nodes
resp = Response(body=pickle.dumps(hashes, protocol=2))
return resp
@public

View File

@ -6812,6 +6812,34 @@ class TestObjectController(unittest.TestCase):
tpool.execute = was_tpool_exe
diskfile.DiskFileManager._get_hashes = was_get_hashes
def test_REPLICATE_pickle_protocol(self):
def fake_get_hashes(*args, **kwargs):
return 0, {1: 2}
def my_tpool_execute(func, *args, **kwargs):
return func(*args, **kwargs)
was_get_hashes = diskfile.DiskFileManager._get_hashes
was_tpool_exe = tpool.execute
try:
diskfile.DiskFileManager._get_hashes = fake_get_hashes
tpool.execute = my_tpool_execute
req = Request.blank('/sda1/p/suff',
environ={'REQUEST_METHOD': 'REPLICATE'},
headers={})
with mock.patch('swift.obj.server.pickle.dumps') as fake_pickle:
fake_pickle.return_value = b''
req.get_response(self.object_controller)
# This is the key assertion: starting in Python 3.0, the
# default protocol version is 3, but such pickles can't be read
# on Python 2. As long as we may need to talk to a Python 2
# process, we need to cap our protocol version.
fake_pickle.assert_called_once_with({1: 2}, protocol=2)
finally:
tpool.execute = was_tpool_exe
diskfile.DiskFileManager._get_hashes = was_get_hashes
def test_REPLICATE_timeout(self):
def fake_get_hashes(*args, **kwargs):