From 24330771af0b77bb1042e280af5db3c51e8b883b Mon Sep 17 00:00:00 2001 From: Thiago da Silva Date: Mon, 8 Dec 2014 21:29:30 -0500 Subject: [PATCH] fix dlo manifest file getting versioned According to documentation dlo manifest files should not be versioned. This patch fixes this issue and adds some unit and functional for this scenario. Change-Id: Ib5b29a19e1d577026deb50fc9d26064a8da81cd7 Signed-off-by: Thiago da Silva --- swift/proxy/controllers/obj.py | 4 +++- test/functional/tests.py | 28 ++++++++++++++++++++++++++++ test/unit/proxy/test_server.py | 28 ++++++++++++++++------------ 3 files changed, 47 insertions(+), 13 deletions(-) diff --git a/swift/proxy/controllers/obj.py b/swift/proxy/controllers/obj.py index e322c41205..3327f926a2 100644 --- a/swift/proxy/controllers/obj.py +++ b/swift/proxy/controllers/obj.py @@ -515,7 +515,9 @@ class ObjectController(Controller): req.headers['X-Timestamp'] = Timestamp(time.time()).internal if object_versions and not req.environ.get('swift_versioned_copy'): - if hresp.status_int != HTTP_NOT_FOUND: + is_manifest = 'X-Object-Manifest' in req.headers or \ + 'X-Object-Manifest' in hresp.headers + if hresp.status_int != HTTP_NOT_FOUND and not is_manifest: # This is a version manifest and needs to be handled # differently. First copy the existing data to a new object, # then write the data from this request to the version manifest diff --git a/test/functional/tests.py b/test/functional/tests.py index d6b0b70f9a..546e578352 100644 --- a/test/functional/tests.py +++ b/test/functional/tests.py @@ -2515,6 +2515,34 @@ class TestObjectVersioning(Base): versioned_obj.delete() self.assertRaises(ResponseError, versioned_obj.read) + def test_versioning_dlo(self): + container = self.env.container + versions_container = self.env.versions_container + obj_name = Utils.create_name() + + for i in ('1', '2', '3'): + time.sleep(.01) # guarantee that the timestamp changes + obj_name_seg = obj_name + '/' + i + versioned_obj = container.file(obj_name_seg) + versioned_obj.write(i) + versioned_obj.write(i + i) + + self.assertEqual(3, versions_container.info()['object_count']) + + man_file = container.file(obj_name) + man_file.write('', hdrs={"X-Object-Manifest": "%s/%s/" % + (self.env.container.name, obj_name)}) + + # guarantee that the timestamp changes + time.sleep(.01) + + # write manifest file again + man_file.write('', hdrs={"X-Object-Manifest": "%s/%s/" % + (self.env.container.name, obj_name)}) + + self.assertEqual(3, versions_container.info()['object_count']) + self.assertEqual("112233", man_file.read()) + class TestObjectVersioningUTF8(Base2, TestObjectVersioning): set_up = False diff --git a/test/unit/proxy/test_server.py b/test/unit/proxy/test_server.py index 95b44aff88..e0e02c0cc9 100644 --- a/test/unit/proxy/test_server.py +++ b/test/unit/proxy/test_server.py @@ -4249,18 +4249,22 @@ class TestObjectController(unittest.TestCase): exp = 'HTTP/1.1 404' self.assertEquals(headers[:len(exp)], exp) - # make sure manifest files don't get versioned - sock = connect_tcp(('localhost', prolis.getsockname()[1])) - fd = sock.makefile() - fd.write('PUT /v1/a/%s/%s HTTP/1.1\r\nHost: ' - 'localhost\r\nConnection: close\r\nX-Storage-Token: ' - 't\r\nContent-Length: 0\r\nContent-Type: text/jibberish0\r\n' - 'Foo: barbaz\r\nX-Object-Manifest: %s/foo_\r\n\r\n' - % (oc, vc, o)) - fd.flush() - headers = readuntil2crlfs(fd) - exp = 'HTTP/1.1 201' - self.assertEquals(headers[:len(exp)], exp) + # make sure dlo manifest files don't get versioned + for _junk in xrange(1, versions_to_create): + sleep(.01) # guarantee that the timestamp changes + sock = connect_tcp(('localhost', prolis.getsockname()[1])) + fd = sock.makefile() + fd.write('PUT /v1/a/%s/%s HTTP/1.1\r\nHost: ' + 'localhost\r\nConnection: close\r\nX-Storage-Token: ' + 't\r\nContent-Length: 0\r\n' + 'Content-Type: text/jibberish0\r\n' + 'Foo: barbaz\r\nX-Object-Manifest: %s/%s/\r\n\r\n' + % (oc, o, oc, o)) + fd.flush() + headers = readuntil2crlfs(fd) + exp = 'HTTP/1.1 201' + self.assertEquals(headers[:len(exp)], exp) + # Ensure we have no saved versions sock = connect_tcp(('localhost', prolis.getsockname()[1])) fd = sock.makefile()