Merge "container/test_server: cleanup Timestamp usage"
This commit is contained in:
@@ -35,7 +35,7 @@ from urllib.parse import quote
|
|||||||
from swift import __version__ as swift_version
|
from swift import __version__ as swift_version
|
||||||
from swift.common.header_key_dict import HeaderKeyDict
|
from swift.common.header_key_dict import HeaderKeyDict
|
||||||
from swift.common.swob import (Request, WsgiBytesIO, HTTPNoContent,
|
from swift.common.swob import (Request, WsgiBytesIO, HTTPNoContent,
|
||||||
bytes_to_wsgi, Response)
|
bytes_to_wsgi, Response, date_header_format)
|
||||||
import swift.container
|
import swift.container
|
||||||
from swift.container import server as container_server
|
from swift.container import server as container_server
|
||||||
from swift.common import constraints
|
from swift.common import constraints
|
||||||
@@ -208,7 +208,7 @@ class TestContainerController(unittest.TestCase):
|
|||||||
last_modified=put_timestamp.ceil()).headers['Last-Modified']
|
last_modified=put_timestamp.ceil()).headers['Last-Modified']
|
||||||
created_at_timestamp = next(self.ts)
|
created_at_timestamp = next(self.ts)
|
||||||
req = Request.blank('/sda1/p/a/c', method='PUT', headers={
|
req = Request.blank('/sda1/p/a/c', method='PUT', headers={
|
||||||
'x-timestamp': put_timestamp.normal})
|
'x-timestamp': put_timestamp.internal})
|
||||||
with mock.patch('swift.container.backend.Timestamp.now',
|
with mock.patch('swift.container.backend.Timestamp.now',
|
||||||
return_value=created_at_timestamp):
|
return_value=created_at_timestamp):
|
||||||
resp = req.get_response(self.controller)
|
resp = req.get_response(self.controller)
|
||||||
@@ -222,11 +222,11 @@ class TestContainerController(unittest.TestCase):
|
|||||||
'Content-Length': '0',
|
'Content-Length': '0',
|
||||||
'Last-Modified': expected_last_modified,
|
'Last-Modified': expected_last_modified,
|
||||||
'X-Backend-Delete-Timestamp': '0000000000.00000',
|
'X-Backend-Delete-Timestamp': '0000000000.00000',
|
||||||
'X-Backend-Put-Timestamp': put_timestamp.normal,
|
'X-Backend-Put-Timestamp': put_timestamp.internal,
|
||||||
'X-Backend-Sharding-State': 'unsharded',
|
'X-Backend-Sharding-State': 'unsharded',
|
||||||
'X-Backend-Status-Changed-At': put_timestamp.normal,
|
'X-Backend-Status-Changed-At': put_timestamp.internal,
|
||||||
'X-Backend-Storage-Policy-Index': str(int(POLICIES.default)),
|
'X-Backend-Storage-Policy-Index': str(int(POLICIES.default)),
|
||||||
'X-Backend-Timestamp': created_at_timestamp.normal,
|
'X-Backend-Timestamp': created_at_timestamp.internal,
|
||||||
'X-Container-Bytes-Used': '0',
|
'X-Container-Bytes-Used': '0',
|
||||||
'X-Container-Object-Count': '0',
|
'X-Container-Object-Count': '0',
|
||||||
'X-Put-Timestamp': put_timestamp.normal,
|
'X-Put-Timestamp': put_timestamp.normal,
|
||||||
@@ -234,7 +234,7 @@ class TestContainerController(unittest.TestCase):
|
|||||||
}, dict(headers))
|
}, dict(headers))
|
||||||
self.assertEqual(b'', b''.join(body_iter))
|
self.assertEqual(b'', b''.join(body_iter))
|
||||||
|
|
||||||
def _test_head(self, start, ts):
|
def _test_head(self, ts_start, ts):
|
||||||
req = Request.blank('/sda1/p/a/c', method='HEAD')
|
req = Request.blank('/sda1/p/a/c', method='HEAD')
|
||||||
response = req.get_response(self.controller)
|
response = req.get_response(self.controller)
|
||||||
self.assertEqual(response.status_int, 204)
|
self.assertEqual(response.status_int, 204)
|
||||||
@@ -242,7 +242,7 @@ class TestContainerController(unittest.TestCase):
|
|||||||
self.assertEqual(response.headers['x-container-object-count'], '0')
|
self.assertEqual(response.headers['x-container-object-count'], '0')
|
||||||
obj_put_request = Request.blank(
|
obj_put_request = Request.blank(
|
||||||
'/sda1/p/a/c/o', method='PUT', headers={
|
'/sda1/p/a/c/o', method='PUT', headers={
|
||||||
'x-timestamp': next(ts),
|
'x-timestamp': next(ts).internal,
|
||||||
'x-size': 42,
|
'x-size': 42,
|
||||||
'x-content-type': 'text/plain',
|
'x-content-type': 'text/plain',
|
||||||
'x-etag': 'x',
|
'x-etag': 'x',
|
||||||
@@ -256,45 +256,42 @@ class TestContainerController(unittest.TestCase):
|
|||||||
self.assertEqual(response.headers['x-container-bytes-used'], '42')
|
self.assertEqual(response.headers['x-container-bytes-used'], '42')
|
||||||
self.assertEqual(response.headers['x-container-object-count'], '1')
|
self.assertEqual(response.headers['x-container-object-count'], '1')
|
||||||
# created at time...
|
# created at time...
|
||||||
created_at_header = Timestamp(response.headers['x-timestamp'])
|
ts_created_at = Timestamp(response.headers['x-timestamp'])
|
||||||
self.assertEqual(response.headers['x-timestamp'],
|
self.assertEqual(response.headers['x-timestamp'],
|
||||||
created_at_header.normal)
|
ts_created_at.normal)
|
||||||
self.assertTrue(created_at_header >= start)
|
self.assertTrue(ts_created_at >= ts_start)
|
||||||
self.assertEqual(response.headers['x-put-timestamp'],
|
self.assertEqual(response.headers['x-put-timestamp'], ts_start.normal)
|
||||||
Timestamp(start).normal)
|
self.assertEqual(response.headers['last-modified'],
|
||||||
time_fmt = "%a, %d %b %Y %H:%M:%S GMT"
|
date_header_format(ts_start))
|
||||||
self.assertEqual(
|
|
||||||
response.last_modified.strftime(time_fmt),
|
|
||||||
time.strftime(time_fmt, time.gmtime(int(start))))
|
|
||||||
|
|
||||||
# backend headers
|
# backend headers
|
||||||
self.assertEqual(int(response.headers
|
self.assertEqual(int(response.headers
|
||||||
['X-Backend-Storage-Policy-Index']),
|
['X-Backend-Storage-Policy-Index']),
|
||||||
int(POLICIES.default))
|
int(POLICIES.default))
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
Timestamp(response.headers['x-backend-timestamp']) >= start)
|
Timestamp(response.headers['x-backend-timestamp']) >= ts_start)
|
||||||
self.assertEqual(response.headers['x-backend-put-timestamp'],
|
self.assertEqual(response.headers['x-backend-put-timestamp'],
|
||||||
Timestamp(start).internal)
|
ts_start.internal)
|
||||||
|
# the delete timestamp column defaults to the string '0'
|
||||||
self.assertEqual(response.headers['x-backend-delete-timestamp'],
|
self.assertEqual(response.headers['x-backend-delete-timestamp'],
|
||||||
Timestamp(0).internal)
|
Timestamp('0').internal)
|
||||||
self.assertEqual(response.headers['x-backend-status-changed-at'],
|
self.assertEqual(response.headers['x-backend-status-changed-at'],
|
||||||
Timestamp(start).internal)
|
ts_start.internal)
|
||||||
|
|
||||||
def test_HEAD(self):
|
def test_HEAD(self):
|
||||||
start = int(time.time())
|
ts_start = next(self.ts)
|
||||||
ts = (Timestamp(t).internal for t in itertools.count(start))
|
|
||||||
req = Request.blank('/sda1/p/a/c', method='PUT', headers={
|
req = Request.blank('/sda1/p/a/c', method='PUT', headers={
|
||||||
'x-timestamp': next(ts)})
|
'x-timestamp': ts_start.internal})
|
||||||
req.get_response(self.controller)
|
req.get_response(self.controller)
|
||||||
self._test_head(Timestamp(start), ts)
|
self._test_head(ts_start, self.ts)
|
||||||
|
|
||||||
def test_HEAD_timestamp_with_offset(self):
|
def test_HEAD_timestamp_with_offset(self):
|
||||||
start = int(time.time())
|
ts_iter = (Timestamp(ts, offset=1) for ts in self.ts)
|
||||||
ts = (Timestamp(t, offset=1).internal for t in itertools.count(start))
|
ts_start = next(ts_iter)
|
||||||
req = Request.blank('/sda1/p/a/c', method='PUT', headers={
|
req = Request.blank('/sda1/p/a/c', method='PUT', headers={
|
||||||
'x-timestamp': next(ts)})
|
'x-timestamp': ts_start.internal})
|
||||||
req.get_response(self.controller)
|
req.get_response(self.controller)
|
||||||
self._test_head(Timestamp(start, offset=1), ts)
|
self._test_head(ts_start, ts_iter)
|
||||||
|
|
||||||
def test_HEAD_not_found(self):
|
def test_HEAD_not_found(self):
|
||||||
req = Request.blank('/sda1/p/a/c', method='HEAD')
|
req = Request.blank('/sda1/p/a/c', method='HEAD')
|
||||||
@@ -303,13 +300,13 @@ class TestContainerController(unittest.TestCase):
|
|||||||
self.assertEqual(int(resp.headers['X-Backend-Storage-Policy-Index']),
|
self.assertEqual(int(resp.headers['X-Backend-Storage-Policy-Index']),
|
||||||
0)
|
0)
|
||||||
self.assertEqual(resp.headers['x-backend-timestamp'],
|
self.assertEqual(resp.headers['x-backend-timestamp'],
|
||||||
Timestamp(0).internal)
|
Timestamp.zero().internal)
|
||||||
self.assertEqual(resp.headers['x-backend-put-timestamp'],
|
self.assertEqual(resp.headers['x-backend-put-timestamp'],
|
||||||
Timestamp(0).internal)
|
Timestamp.zero().internal)
|
||||||
self.assertEqual(resp.headers['x-backend-status-changed-at'],
|
self.assertEqual(resp.headers['x-backend-status-changed-at'],
|
||||||
Timestamp(0).internal)
|
Timestamp.zero().internal)
|
||||||
self.assertEqual(resp.headers['x-backend-delete-timestamp'],
|
self.assertEqual(resp.headers['x-backend-delete-timestamp'],
|
||||||
Timestamp(0).internal)
|
Timestamp.zero().internal)
|
||||||
self.assertIsNone(resp.last_modified)
|
self.assertIsNone(resp.last_modified)
|
||||||
|
|
||||||
for header in ('x-container-object-count', 'x-container-bytes-used',
|
for header in ('x-container-object-count', 'x-container-bytes-used',
|
||||||
@@ -459,9 +456,9 @@ class TestContainerController(unittest.TestCase):
|
|||||||
self.assertEqual(resp.status_int, 202)
|
self.assertEqual(resp.status_int, 202)
|
||||||
|
|
||||||
def test_PUT_HEAD_put_timestamp_updates(self):
|
def test_PUT_HEAD_put_timestamp_updates(self):
|
||||||
put_ts = Timestamp(1)
|
ts = [next(self.ts) for _ in range(6)]
|
||||||
req = Request.blank('/sda1/p/a/c', environ={'REQUEST_METHOD': 'PUT'},
|
req = Request.blank('/sda1/p/a/c', environ={'REQUEST_METHOD': 'PUT'},
|
||||||
headers={'X-Timestamp': put_ts.internal})
|
headers={'X-Timestamp': ts[1].internal})
|
||||||
resp = req.get_response(self.controller)
|
resp = req.get_response(self.controller)
|
||||||
self.assertEqual(resp.status_int, 201)
|
self.assertEqual(resp.status_int, 201)
|
||||||
|
|
||||||
@@ -482,44 +479,40 @@ class TestContainerController(unittest.TestCase):
|
|||||||
return resp.headers
|
return resp.headers
|
||||||
|
|
||||||
# put timestamp is advanced on PUT with container path
|
# put timestamp is advanced on PUT with container path
|
||||||
put_ts = Timestamp(2)
|
resp_hdrs = do_put_head(ts[2], 'val1',
|
||||||
resp_hdrs = do_put_head(put_ts, 'val1',
|
|
||||||
{'x-backend-no-timestamp-update': 'false'})
|
{'x-backend-no-timestamp-update': 'false'})
|
||||||
self.assertEqual(resp_hdrs.get('x-container-meta-test'), 'val1')
|
self.assertEqual(resp_hdrs.get('x-container-meta-test'), 'val1')
|
||||||
self.assertEqual(resp_hdrs.get('x-backend-put-timestamp'),
|
self.assertEqual(resp_hdrs.get('x-backend-put-timestamp'),
|
||||||
put_ts.internal)
|
ts[2].internal)
|
||||||
self.assertEqual(resp_hdrs.get('x-put-timestamp'), put_ts.internal)
|
self.assertEqual(resp_hdrs.get('x-put-timestamp'), ts[2].normal)
|
||||||
|
|
||||||
put_ts = Timestamp(3)
|
resp_hdrs = do_put_head(ts[3], 'val2',
|
||||||
resp_hdrs = do_put_head(put_ts, 'val2',
|
|
||||||
{'x-backend-no-timestamp-update': 'true'})
|
{'x-backend-no-timestamp-update': 'true'})
|
||||||
self.assertEqual(resp_hdrs.get('x-container-meta-test'), 'val2')
|
self.assertEqual(resp_hdrs.get('x-container-meta-test'), 'val2')
|
||||||
self.assertEqual(resp_hdrs.get('x-backend-put-timestamp'),
|
self.assertEqual(resp_hdrs.get('x-backend-put-timestamp'),
|
||||||
put_ts.internal)
|
ts[3].internal)
|
||||||
self.assertEqual(resp_hdrs.get('x-put-timestamp'), put_ts.internal)
|
self.assertEqual(resp_hdrs.get('x-put-timestamp'), ts[3].normal)
|
||||||
|
|
||||||
# put timestamp is NOT updated if record type is shard
|
# put timestamp is NOT updated if record type is shard
|
||||||
put_ts = Timestamp(4)
|
|
||||||
resp_hdrs = do_put_head(
|
resp_hdrs = do_put_head(
|
||||||
put_ts, 'val3', {'x-backend-record-type': 'shard'},
|
ts[4], 'val3', {'x-backend-record-type': 'shard'},
|
||||||
body=json.dumps([dict(ShardRange('x/y', 123.4))]))
|
body=json.dumps([dict(ShardRange('x/y', 123.4))]))
|
||||||
self.assertEqual(resp_hdrs.get('x-container-meta-test'), 'val3')
|
self.assertEqual(resp_hdrs.get('x-container-meta-test'), 'val3')
|
||||||
self.assertEqual(resp_hdrs.get('x-backend-put-timestamp'),
|
self.assertEqual(resp_hdrs.get('x-backend-put-timestamp'),
|
||||||
Timestamp(3).internal)
|
ts[3].internal)
|
||||||
self.assertEqual(resp_hdrs.get('x-put-timestamp'),
|
self.assertEqual(resp_hdrs.get('x-put-timestamp'),
|
||||||
Timestamp(3).internal)
|
ts[3].normal)
|
||||||
|
|
||||||
# put timestamp and metadata are NOT updated for request with obj path
|
# put timestamp and metadata are NOT updated for request with obj path
|
||||||
put_ts = Timestamp(5)
|
|
||||||
resp_hdrs = do_put_head(
|
resp_hdrs = do_put_head(
|
||||||
put_ts, 'val4',
|
ts[5], 'val4',
|
||||||
{'x-content-type': 'plain/text', 'x-size': 0, 'x-etag': 'an-etag'},
|
{'x-content-type': 'plain/text', 'x-size': 0, 'x-etag': 'an-etag'},
|
||||||
path='a/c/o')
|
path='a/c/o')
|
||||||
self.assertEqual(resp_hdrs.get('x-container-meta-test'), 'val3')
|
self.assertEqual(resp_hdrs.get('x-container-meta-test'), 'val3')
|
||||||
self.assertEqual(resp_hdrs.get('x-backend-put-timestamp'),
|
self.assertEqual(resp_hdrs.get('x-backend-put-timestamp'),
|
||||||
Timestamp(3).internal)
|
ts[3].internal)
|
||||||
self.assertEqual(resp_hdrs.get('x-put-timestamp'),
|
self.assertEqual(resp_hdrs.get('x-put-timestamp'),
|
||||||
Timestamp(3).internal)
|
ts[3].normal)
|
||||||
|
|
||||||
def test_PUT_insufficient_space(self):
|
def test_PUT_insufficient_space(self):
|
||||||
conf = {'devices': self.testdir,
|
conf = {'devices': self.testdir,
|
||||||
@@ -1145,7 +1138,7 @@ class TestContainerController(unittest.TestCase):
|
|||||||
self.assertNotIn(key.lower(), resp.headers)
|
self.assertNotIn(key.lower(), resp.headers)
|
||||||
|
|
||||||
def test_POST_HEAD_no_timestamp_update(self):
|
def test_POST_HEAD_no_timestamp_update(self):
|
||||||
put_ts = Timestamp(1)
|
put_ts = next(self.ts)
|
||||||
req = Request.blank('/sda1/p/a/c', environ={'REQUEST_METHOD': 'PUT'},
|
req = Request.blank('/sda1/p/a/c', environ={'REQUEST_METHOD': 'PUT'},
|
||||||
headers={'X-Timestamp': put_ts.internal})
|
headers={'X-Timestamp': put_ts.internal})
|
||||||
resp = req.get_response(self.controller)
|
resp = req.get_response(self.controller)
|
||||||
@@ -1167,34 +1160,33 @@ class TestContainerController(unittest.TestCase):
|
|||||||
return resp.headers
|
return resp.headers
|
||||||
|
|
||||||
# verify timestamp IS advanced
|
# verify timestamp IS advanced
|
||||||
post_ts = Timestamp(2)
|
post_ts1 = next(self.ts)
|
||||||
resp_hdrs = do_post_head(post_ts, 'val1', {})
|
resp_hdrs = do_post_head(post_ts1, 'val1', {})
|
||||||
self.assertEqual(resp_hdrs.get('x-container-meta-test'), 'val1')
|
self.assertEqual(resp_hdrs.get('x-container-meta-test'), 'val1')
|
||||||
self.assertEqual(resp_hdrs.get('x-backend-put-timestamp'),
|
self.assertEqual(resp_hdrs.get('x-backend-put-timestamp'),
|
||||||
post_ts.internal)
|
post_ts1.internal)
|
||||||
|
|
||||||
post_ts = Timestamp(3)
|
post_ts2 = next(self.ts)
|
||||||
resp_hdrs = do_post_head(post_ts, 'val2',
|
resp_hdrs = do_post_head(post_ts2, 'val2',
|
||||||
{'x-backend-no-timestamp-update': 'false'})
|
{'x-backend-no-timestamp-update': 'false'})
|
||||||
self.assertEqual(resp_hdrs.get('x-container-meta-test'), 'val2')
|
self.assertEqual(resp_hdrs.get('x-container-meta-test'), 'val2')
|
||||||
self.assertEqual(resp_hdrs.get('x-backend-put-timestamp'),
|
self.assertEqual(resp_hdrs.get('x-backend-put-timestamp'),
|
||||||
post_ts.internal)
|
post_ts2.internal)
|
||||||
|
|
||||||
# verify timestamp IS NOT advanced, but metadata still updated
|
# verify timestamp IS NOT advanced, but metadata still updated
|
||||||
post_ts = Timestamp(4)
|
post_ts3 = next(self.ts)
|
||||||
resp_hdrs = do_post_head(post_ts, 'val3',
|
resp_hdrs = do_post_head(post_ts3, 'val3',
|
||||||
{'x-backend-No-timeStamp-update': 'true'})
|
{'x-backend-No-timeStamp-update': 'true'})
|
||||||
self.assertEqual(resp_hdrs.get('x-container-meta-test'), 'val3')
|
self.assertEqual(resp_hdrs.get('x-container-meta-test'), 'val3')
|
||||||
self.assertEqual(resp_hdrs.get('x-backend-put-timestamp'),
|
self.assertEqual(resp_hdrs.get('x-backend-put-timestamp'),
|
||||||
Timestamp(3).internal)
|
post_ts2.internal)
|
||||||
|
|
||||||
# verify timestamp will not go backwards
|
# verify timestamp will not go backwards
|
||||||
post_ts = Timestamp(2)
|
resp_hdrs = do_post_head(post_ts1, 'val4',
|
||||||
resp_hdrs = do_post_head(post_ts, 'val4',
|
|
||||||
{'x-backend-no-timestamp-update': 'true'})
|
{'x-backend-no-timestamp-update': 'true'})
|
||||||
self.assertEqual(resp_hdrs.get('x-container-meta-test'), 'val3')
|
self.assertEqual(resp_hdrs.get('x-container-meta-test'), 'val3')
|
||||||
self.assertEqual(resp_hdrs.get('x-backend-put-timestamp'),
|
self.assertEqual(resp_hdrs.get('x-backend-put-timestamp'),
|
||||||
Timestamp(3).internal)
|
post_ts2.internal)
|
||||||
|
|
||||||
def test_POST_invalid_partition(self):
|
def test_POST_invalid_partition(self):
|
||||||
req = Request.blank('/sda1/./a/c', environ={'REQUEST_METHOD': 'POST',
|
req = Request.blank('/sda1/./a/c', environ={'REQUEST_METHOD': 'POST',
|
||||||
@@ -1352,14 +1344,15 @@ class TestContainerController(unittest.TestCase):
|
|||||||
return err
|
return err
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
timestamps = [next(self.ts) for _ in range(5)]
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/sda1/p/a/c',
|
'/sda1/p/a/c',
|
||||||
environ={'REQUEST_METHOD': 'PUT'},
|
environ={'REQUEST_METHOD': 'PUT'},
|
||||||
headers={'X-Timestamp': Timestamp(1).internal,
|
headers={'X-Timestamp': timestamps[1].internal,
|
||||||
'X-Account-Host': '%s:%s' % bindsock.getsockname(),
|
'X-Account-Host': '%s:%s' % bindsock.getsockname(),
|
||||||
'X-Account-Partition': '123',
|
'X-Account-Partition': '123',
|
||||||
'X-Account-Device': 'sda1'})
|
'X-Account-Device': 'sda1'})
|
||||||
event = spawn(accept, 201, Timestamp(1).internal)
|
event = spawn(accept, 201, timestamps[1].internal)
|
||||||
try:
|
try:
|
||||||
with Timeout(3):
|
with Timeout(3):
|
||||||
resp = req.get_response(self.controller)
|
resp = req.get_response(self.controller)
|
||||||
@@ -1368,20 +1361,22 @@ class TestContainerController(unittest.TestCase):
|
|||||||
err = event.wait()
|
err = event.wait()
|
||||||
if err:
|
if err:
|
||||||
raise Exception(err)
|
raise Exception(err)
|
||||||
|
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/sda1/p/a/c',
|
'/sda1/p/a/c',
|
||||||
environ={'REQUEST_METHOD': 'DELETE'},
|
environ={'REQUEST_METHOD': 'DELETE'},
|
||||||
headers={'X-Timestamp': '2'})
|
headers={'X-Timestamp': timestamps[2].internal})
|
||||||
resp = req.get_response(self.controller)
|
resp = req.get_response(self.controller)
|
||||||
self.assertEqual(resp.status_int, 204)
|
self.assertEqual(resp.status_int, 204)
|
||||||
|
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/sda1/p/a/c',
|
'/sda1/p/a/c',
|
||||||
environ={'REQUEST_METHOD': 'PUT'},
|
environ={'REQUEST_METHOD': 'PUT'},
|
||||||
headers={'X-Timestamp': Timestamp(3).internal,
|
headers={'X-Timestamp': timestamps[3].internal,
|
||||||
'X-Account-Host': '%s:%s' % bindsock.getsockname(),
|
'X-Account-Host': '%s:%s' % bindsock.getsockname(),
|
||||||
'X-Account-Partition': '123',
|
'X-Account-Partition': '123',
|
||||||
'X-Account-Device': 'sda1'})
|
'X-Account-Device': 'sda1'})
|
||||||
event = spawn(accept, 404, Timestamp(3).internal)
|
event = spawn(accept, 404, timestamps[3].internal)
|
||||||
try:
|
try:
|
||||||
with Timeout(3):
|
with Timeout(3):
|
||||||
resp = req.get_response(self.controller)
|
resp = req.get_response(self.controller)
|
||||||
@@ -1390,14 +1385,15 @@ class TestContainerController(unittest.TestCase):
|
|||||||
err = event.wait()
|
err = event.wait()
|
||||||
if err:
|
if err:
|
||||||
raise Exception(err)
|
raise Exception(err)
|
||||||
|
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/sda1/p/a/c',
|
'/sda1/p/a/c',
|
||||||
environ={'REQUEST_METHOD': 'PUT'},
|
environ={'REQUEST_METHOD': 'PUT'},
|
||||||
headers={'X-Timestamp': Timestamp(5).internal,
|
headers={'X-Timestamp': timestamps[4].internal,
|
||||||
'X-Account-Host': '%s:%s' % bindsock.getsockname(),
|
'X-Account-Host': '%s:%s' % bindsock.getsockname(),
|
||||||
'X-Account-Partition': '123',
|
'X-Account-Partition': '123',
|
||||||
'X-Account-Device': 'sda1'})
|
'X-Account-Device': 'sda1'})
|
||||||
event = spawn(accept, 503, Timestamp(5).internal)
|
event = spawn(accept, 503, timestamps[4].internal)
|
||||||
got_exc = False
|
got_exc = False
|
||||||
try:
|
try:
|
||||||
with Timeout(3):
|
with Timeout(3):
|
||||||
@@ -1931,13 +1927,14 @@ class TestContainerController(unittest.TestCase):
|
|||||||
self.assertNotIn('X-Backend-Record-Type', resp.headers)
|
self.assertNotIn('X-Backend-Record-Type', resp.headers)
|
||||||
|
|
||||||
def test_DELETE_PUT_recreate(self):
|
def test_DELETE_PUT_recreate(self):
|
||||||
|
timestamps = [next(self.ts) for _ in range(5)]
|
||||||
path = '/sda1/p/a/c'
|
path = '/sda1/p/a/c'
|
||||||
req = Request.blank(path, method='PUT',
|
req = Request.blank(path, method='PUT',
|
||||||
headers={'X-Timestamp': '1'})
|
headers={'X-Timestamp': timestamps[1].internal})
|
||||||
resp = req.get_response(self.controller)
|
resp = req.get_response(self.controller)
|
||||||
self.assertEqual(resp.status_int, 201)
|
self.assertEqual(resp.status_int, 201)
|
||||||
req = Request.blank(path, method='DELETE',
|
req = Request.blank(path, method='DELETE',
|
||||||
headers={'X-Timestamp': '2'})
|
headers={'X-Timestamp': timestamps[2].internal})
|
||||||
resp = req.get_response(self.controller)
|
resp = req.get_response(self.controller)
|
||||||
self.assertEqual(resp.status_int, 204)
|
self.assertEqual(resp.status_int, 204)
|
||||||
req = Request.blank(path, method='GET')
|
req = Request.blank(path, method='GET')
|
||||||
@@ -1945,9 +1942,9 @@ class TestContainerController(unittest.TestCase):
|
|||||||
self.assertEqual(resp.status_int, 404) # sanity
|
self.assertEqual(resp.status_int, 404) # sanity
|
||||||
# backend headers
|
# backend headers
|
||||||
expectations = {
|
expectations = {
|
||||||
'x-backend-put-timestamp': Timestamp(1).internal,
|
'x-backend-put-timestamp': timestamps[1].internal,
|
||||||
'x-backend-delete-timestamp': Timestamp(2).internal,
|
'x-backend-delete-timestamp': timestamps[2].internal,
|
||||||
'x-backend-status-changed-at': Timestamp(2).internal,
|
'x-backend-status-changed-at': timestamps[2].internal,
|
||||||
}
|
}
|
||||||
for header, value in expectations.items():
|
for header, value in expectations.items():
|
||||||
self.assertEqual(resp.headers[header], value,
|
self.assertEqual(resp.headers[header], value,
|
||||||
@@ -1956,28 +1953,28 @@ class TestContainerController(unittest.TestCase):
|
|||||||
db = self.controller._get_container_broker('sda1', 'p', 'a', 'c')
|
db = self.controller._get_container_broker('sda1', 'p', 'a', 'c')
|
||||||
self.assertEqual(True, db.is_deleted())
|
self.assertEqual(True, db.is_deleted())
|
||||||
info = db.get_info()
|
info = db.get_info()
|
||||||
self.assertEqual(info['put_timestamp'], Timestamp('1').internal)
|
self.assertEqual(info['put_timestamp'], timestamps[1].internal)
|
||||||
self.assertEqual(info['delete_timestamp'], Timestamp('2').internal)
|
self.assertEqual(info['delete_timestamp'], timestamps[2].internal)
|
||||||
self.assertEqual(info['status_changed_at'], Timestamp('2').internal)
|
self.assertEqual(info['status_changed_at'], timestamps[2].internal)
|
||||||
# recreate
|
# recreate
|
||||||
req = Request.blank(path, method='PUT',
|
req = Request.blank(path, method='PUT',
|
||||||
headers={'X-Timestamp': '4'})
|
headers={'X-Timestamp': timestamps[4].internal})
|
||||||
resp = req.get_response(self.controller)
|
resp = req.get_response(self.controller)
|
||||||
self.assertEqual(resp.status_int, 201)
|
self.assertEqual(resp.status_int, 201)
|
||||||
db = self.controller._get_container_broker('sda1', 'p', 'a', 'c')
|
db = self.controller._get_container_broker('sda1', 'p', 'a', 'c')
|
||||||
self.assertEqual(False, db.is_deleted())
|
self.assertEqual(False, db.is_deleted())
|
||||||
info = db.get_info()
|
info = db.get_info()
|
||||||
self.assertEqual(info['put_timestamp'], Timestamp('4').internal)
|
self.assertEqual(info['put_timestamp'], timestamps[4].internal)
|
||||||
self.assertEqual(info['delete_timestamp'], Timestamp('2').internal)
|
self.assertEqual(info['delete_timestamp'], timestamps[2].internal)
|
||||||
self.assertEqual(info['status_changed_at'], Timestamp('4').internal)
|
self.assertEqual(info['status_changed_at'], timestamps[4].internal)
|
||||||
for method in ('GET', 'HEAD'):
|
for method in ('GET', 'HEAD'):
|
||||||
req = Request.blank(path)
|
req = Request.blank(path)
|
||||||
resp = req.get_response(self.controller)
|
resp = req.get_response(self.controller)
|
||||||
expectations = {
|
expectations = {
|
||||||
'x-put-timestamp': Timestamp(4).normal,
|
'x-put-timestamp': timestamps[4].normal,
|
||||||
'x-backend-put-timestamp': Timestamp(4).internal,
|
'x-backend-put-timestamp': timestamps[4].internal,
|
||||||
'x-backend-delete-timestamp': Timestamp(2).internal,
|
'x-backend-delete-timestamp': timestamps[2].internal,
|
||||||
'x-backend-status-changed-at': Timestamp(4).internal,
|
'x-backend-status-changed-at': timestamps[4].internal,
|
||||||
}
|
}
|
||||||
for header, expected in expectations.items():
|
for header, expected in expectations.items():
|
||||||
self.assertEqual(resp.headers[header], expected,
|
self.assertEqual(resp.headers[header], expected,
|
||||||
@@ -2125,7 +2122,7 @@ class TestContainerController(unittest.TestCase):
|
|||||||
self.assertEqual(resp.status_int, 201)
|
self.assertEqual(resp.status_int, 201)
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/sda1/p/a/c/o', method='PUT', headers={
|
'/sda1/p/a/c/o', method='PUT', headers={
|
||||||
'X-Timestamp': Timestamp(0).internal, 'X-Size': 1,
|
'X-Timestamp': Timestamp.zero().internal, 'X-Size': 1,
|
||||||
'X-Content-Type': 'text/plain', 'X-Etag': 'x'})
|
'X-Content-Type': 'text/plain', 'X-Etag': 'x'})
|
||||||
self._update_object_put_headers(req)
|
self._update_object_put_headers(req)
|
||||||
resp = req.get_response(self.controller)
|
resp = req.get_response(self.controller)
|
||||||
@@ -2151,11 +2148,9 @@ class TestContainerController(unittest.TestCase):
|
|||||||
self.assertEqual(resp.status_int, 404)
|
self.assertEqual(resp.status_int, 404)
|
||||||
|
|
||||||
def test_object_update_with_offset(self):
|
def test_object_update_with_offset(self):
|
||||||
ts = (Timestamp(t).internal for t in
|
|
||||||
itertools.count(int(time.time())))
|
|
||||||
# create container
|
# create container
|
||||||
req = Request.blank('/sda1/p/a/c', method='PUT', headers={
|
req = Request.blank('/sda1/p/a/c', method='PUT', headers={
|
||||||
'X-Timestamp': next(ts)})
|
'X-Timestamp': next(self.ts).internal})
|
||||||
resp = req.get_response(self.controller)
|
resp = req.get_response(self.controller)
|
||||||
self.assertEqual(resp.status_int, 201)
|
self.assertEqual(resp.status_int, 201)
|
||||||
# check status
|
# check status
|
||||||
@@ -2165,10 +2160,10 @@ class TestContainerController(unittest.TestCase):
|
|||||||
self.assertEqual(int(resp.headers['X-Backend-Storage-Policy-Index']),
|
self.assertEqual(int(resp.headers['X-Backend-Storage-Policy-Index']),
|
||||||
int(POLICIES.default))
|
int(POLICIES.default))
|
||||||
# create object
|
# create object
|
||||||
obj_timestamp = next(ts)
|
obj_timestamp = next(self.ts)
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/sda1/p/a/c/o', method='PUT', headers={
|
'/sda1/p/a/c/o', method='PUT', headers={
|
||||||
'X-Timestamp': obj_timestamp, 'X-Size': 1,
|
'X-Timestamp': obj_timestamp.internal, 'X-Size': 1,
|
||||||
'X-Content-Type': 'text/plain', 'X-Etag': 'x'})
|
'X-Content-Type': 'text/plain', 'X-Etag': 'x'})
|
||||||
self._update_object_put_headers(req)
|
self._update_object_put_headers(req)
|
||||||
resp = req.get_response(self.controller)
|
resp = req.get_response(self.controller)
|
||||||
@@ -2188,10 +2183,10 @@ class TestContainerController(unittest.TestCase):
|
|||||||
self.assertEqual(obj['hash'], 'x')
|
self.assertEqual(obj['hash'], 'x')
|
||||||
self.assertEqual(obj['content_type'], 'text/plain')
|
self.assertEqual(obj['content_type'], 'text/plain')
|
||||||
# send an update with an offset
|
# send an update with an offset
|
||||||
offset_timestamp = Timestamp(obj_timestamp, offset=1).internal
|
offset_timestamp = Timestamp(obj_timestamp, offset=1)
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/sda1/p/a/c/o', method='PUT', headers={
|
'/sda1/p/a/c/o', method='PUT', headers={
|
||||||
'X-Timestamp': offset_timestamp, 'X-Size': 2,
|
'X-Timestamp': offset_timestamp.internal, 'X-Size': 2,
|
||||||
'X-Content-Type': 'text/html', 'X-Etag': 'y'})
|
'X-Content-Type': 'text/html', 'X-Etag': 'y'})
|
||||||
self._update_object_put_headers(req)
|
self._update_object_put_headers(req)
|
||||||
resp = req.get_response(self.controller)
|
resp = req.get_response(self.controller)
|
||||||
@@ -2211,10 +2206,10 @@ class TestContainerController(unittest.TestCase):
|
|||||||
self.assertEqual(obj['hash'], 'y')
|
self.assertEqual(obj['hash'], 'y')
|
||||||
self.assertEqual(obj['content_type'], 'text/html')
|
self.assertEqual(obj['content_type'], 'text/html')
|
||||||
# now overwrite with a newer time
|
# now overwrite with a newer time
|
||||||
delete_timestamp = next(ts)
|
delete_timestamp = next(self.ts)
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/sda1/p/a/c/o', method='DELETE', headers={
|
'/sda1/p/a/c/o', method='DELETE', headers={
|
||||||
'X-Timestamp': delete_timestamp})
|
'X-Timestamp': delete_timestamp.internal})
|
||||||
self._update_object_put_headers(req)
|
self._update_object_put_headers(req)
|
||||||
resp = req.get_response(self.controller)
|
resp = req.get_response(self.controller)
|
||||||
self.assertEqual(resp.status_int, 204)
|
self.assertEqual(resp.status_int, 204)
|
||||||
@@ -2228,10 +2223,10 @@ class TestContainerController(unittest.TestCase):
|
|||||||
listing_data = json.loads(resp.body)
|
listing_data = json.loads(resp.body)
|
||||||
self.assertEqual(0, len(listing_data))
|
self.assertEqual(0, len(listing_data))
|
||||||
# recreate with an offset
|
# recreate with an offset
|
||||||
offset_timestamp = Timestamp(delete_timestamp, offset=1).internal
|
offset_timestamp = Timestamp(delete_timestamp, offset=1)
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/sda1/p/a/c/o', method='PUT', headers={
|
'/sda1/p/a/c/o', method='PUT', headers={
|
||||||
'X-Timestamp': offset_timestamp, 'X-Size': 3,
|
'X-Timestamp': offset_timestamp.internal, 'X-Size': 3,
|
||||||
'X-Content-Type': 'text/enriched', 'X-Etag': 'z'})
|
'X-Content-Type': 'text/enriched', 'X-Etag': 'z'})
|
||||||
self._update_object_put_headers(req)
|
self._update_object_put_headers(req)
|
||||||
resp = req.get_response(self.controller)
|
resp = req.get_response(self.controller)
|
||||||
@@ -2251,10 +2246,10 @@ class TestContainerController(unittest.TestCase):
|
|||||||
self.assertEqual(obj['hash'], 'z')
|
self.assertEqual(obj['hash'], 'z')
|
||||||
self.assertEqual(obj['content_type'], 'text/enriched')
|
self.assertEqual(obj['content_type'], 'text/enriched')
|
||||||
# delete offset with newer offset
|
# delete offset with newer offset
|
||||||
delete_timestamp = Timestamp(offset_timestamp, offset=1).internal
|
delete_timestamp = Timestamp(offset_timestamp, offset=1)
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/sda1/p/a/c/o', method='DELETE', headers={
|
'/sda1/p/a/c/o', method='DELETE', headers={
|
||||||
'X-Timestamp': delete_timestamp})
|
'X-Timestamp': delete_timestamp.internal})
|
||||||
self._update_object_put_headers(req)
|
self._update_object_put_headers(req)
|
||||||
resp = req.get_response(self.controller)
|
resp = req.get_response(self.controller)
|
||||||
self.assertEqual(resp.status_int, 204)
|
self.assertEqual(resp.status_int, 204)
|
||||||
@@ -2495,19 +2490,21 @@ class TestContainerController(unittest.TestCase):
|
|||||||
return err
|
return err
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
timestamps = [next(self.ts) for _ in range(6)]
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/sda1/p/a/c',
|
'/sda1/p/a/c',
|
||||||
environ={'REQUEST_METHOD': 'PUT'}, headers={'X-Timestamp': '1'})
|
environ={'REQUEST_METHOD': 'PUT'},
|
||||||
|
headers={'X-Timestamp': timestamps[1].internal})
|
||||||
resp = req.get_response(self.controller)
|
resp = req.get_response(self.controller)
|
||||||
self.assertEqual(resp.status_int, 201)
|
self.assertEqual(resp.status_int, 201)
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/sda1/p/a/c',
|
'/sda1/p/a/c',
|
||||||
environ={'REQUEST_METHOD': 'DELETE'},
|
environ={'REQUEST_METHOD': 'DELETE'},
|
||||||
headers={'X-Timestamp': Timestamp(2).internal,
|
headers={'X-Timestamp': timestamps[2].internal,
|
||||||
'X-Account-Host': '%s:%s' % bindsock.getsockname(),
|
'X-Account-Host': '%s:%s' % bindsock.getsockname(),
|
||||||
'X-Account-Partition': '123',
|
'X-Account-Partition': '123',
|
||||||
'X-Account-Device': 'sda1'})
|
'X-Account-Device': 'sda1'})
|
||||||
event = spawn(accept, 204, Timestamp(2).internal)
|
event = spawn(accept, 204, timestamps[2].internal)
|
||||||
try:
|
try:
|
||||||
with Timeout(3):
|
with Timeout(3):
|
||||||
resp = req.get_response(self.controller)
|
resp = req.get_response(self.controller)
|
||||||
@@ -2518,17 +2515,17 @@ class TestContainerController(unittest.TestCase):
|
|||||||
raise Exception(err)
|
raise Exception(err)
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/sda1/p/a/c', method='PUT', headers={
|
'/sda1/p/a/c', method='PUT', headers={
|
||||||
'X-Timestamp': Timestamp(2).internal})
|
'X-Timestamp': timestamps[2].internal})
|
||||||
resp = req.get_response(self.controller)
|
resp = req.get_response(self.controller)
|
||||||
self.assertEqual(resp.status_int, 201)
|
self.assertEqual(resp.status_int, 201)
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/sda1/p/a/c',
|
'/sda1/p/a/c',
|
||||||
environ={'REQUEST_METHOD': 'DELETE'},
|
environ={'REQUEST_METHOD': 'DELETE'},
|
||||||
headers={'X-Timestamp': Timestamp(3).internal,
|
headers={'X-Timestamp': timestamps[3].internal,
|
||||||
'X-Account-Host': '%s:%s' % bindsock.getsockname(),
|
'X-Account-Host': '%s:%s' % bindsock.getsockname(),
|
||||||
'X-Account-Partition': '123',
|
'X-Account-Partition': '123',
|
||||||
'X-Account-Device': 'sda1'})
|
'X-Account-Device': 'sda1'})
|
||||||
event = spawn(accept, 404, Timestamp(3).internal)
|
event = spawn(accept, 404, timestamps[3].internal)
|
||||||
try:
|
try:
|
||||||
with Timeout(3):
|
with Timeout(3):
|
||||||
resp = req.get_response(self.controller)
|
resp = req.get_response(self.controller)
|
||||||
@@ -2539,17 +2536,17 @@ class TestContainerController(unittest.TestCase):
|
|||||||
raise Exception(err)
|
raise Exception(err)
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/sda1/p/a/c', method='PUT', headers={
|
'/sda1/p/a/c', method='PUT', headers={
|
||||||
'X-Timestamp': Timestamp(4).internal})
|
'X-Timestamp': timestamps[4].internal})
|
||||||
resp = req.get_response(self.controller)
|
resp = req.get_response(self.controller)
|
||||||
self.assertEqual(resp.status_int, 201)
|
self.assertEqual(resp.status_int, 201)
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/sda1/p/a/c',
|
'/sda1/p/a/c',
|
||||||
environ={'REQUEST_METHOD': 'DELETE'},
|
environ={'REQUEST_METHOD': 'DELETE'},
|
||||||
headers={'X-Timestamp': Timestamp(5).internal,
|
headers={'X-Timestamp': timestamps[5].internal,
|
||||||
'X-Account-Host': '%s:%s' % bindsock.getsockname(),
|
'X-Account-Host': '%s:%s' % bindsock.getsockname(),
|
||||||
'X-Account-Partition': '123',
|
'X-Account-Partition': '123',
|
||||||
'X-Account-Device': 'sda1'})
|
'X-Account-Device': 'sda1'})
|
||||||
event = spawn(accept, 503, Timestamp(5).internal)
|
event = spawn(accept, 503, timestamps[5].internal)
|
||||||
got_exc = False
|
got_exc = False
|
||||||
try:
|
try:
|
||||||
with Timeout(3):
|
with Timeout(3):
|
||||||
@@ -4987,7 +4984,7 @@ class TestContainerController(unittest.TestCase):
|
|||||||
|
|
||||||
def test_GET_accept_not_valid(self):
|
def test_GET_accept_not_valid(self):
|
||||||
req = Request.blank('/sda1/p/a/c', method='PUT', headers={
|
req = Request.blank('/sda1/p/a/c', method='PUT', headers={
|
||||||
'X-Timestamp': Timestamp(0).internal})
|
'X-Timestamp': Timestamp.zero().internal})
|
||||||
resp = req.get_response(self.controller)
|
resp = req.get_response(self.controller)
|
||||||
self.assertEqual(resp.status_int, 201)
|
self.assertEqual(resp.status_int, 201)
|
||||||
req = Request.blank('/sda1/p/a/c', method='GET')
|
req = Request.blank('/sda1/p/a/c', method='GET')
|
||||||
@@ -5923,10 +5920,11 @@ class TestContainerController(unittest.TestCase):
|
|||||||
dict((k, v) for k, v in captured_args.items()
|
dict((k, v) for k, v in captured_args.items()
|
||||||
if v is not None))
|
if v is not None))
|
||||||
|
|
||||||
|
ts_put = next(self.ts)
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/sda1/p/a/c',
|
'/sda1/p/a/c',
|
||||||
environ={'REQUEST_METHOD': 'PUT'},
|
environ={'REQUEST_METHOD': 'PUT'},
|
||||||
headers={'X-Timestamp': '12345',
|
headers={'X-Timestamp': ts_put.internal,
|
||||||
'X-Account-Partition': '30',
|
'X-Account-Partition': '30',
|
||||||
'X-Account-Host': '1.2.3.4:5, 6.7.8.9:10',
|
'X-Account-Host': '1.2.3.4:5, 6.7.8.9:10',
|
||||||
'X-Account-Device': 'sdb1, sdf1'})
|
'X-Account-Device': 'sdb1, sdf1'})
|
||||||
@@ -5954,7 +5952,7 @@ class TestContainerController(unittest.TestCase):
|
|||||||
'x-bytes-used': 0,
|
'x-bytes-used': 0,
|
||||||
'x-delete-timestamp': '0',
|
'x-delete-timestamp': '0',
|
||||||
'x-object-count': 0,
|
'x-object-count': 0,
|
||||||
'x-put-timestamp': Timestamp(12345).internal,
|
'x-put-timestamp': ts_put.internal,
|
||||||
'X-Backend-Storage-Policy-Index': '%s' % POLICIES.default.idx,
|
'X-Backend-Storage-Policy-Index': '%s' % POLICIES.default.idx,
|
||||||
'referer': 'PUT http://localhost/sda1/p/a/c',
|
'referer': 'PUT http://localhost/sda1/p/a/c',
|
||||||
'user-agent': 'container-server %d' % os.getpid(),
|
'user-agent': 'container-server %d' % os.getpid(),
|
||||||
@@ -5972,7 +5970,7 @@ class TestContainerController(unittest.TestCase):
|
|||||||
'x-bytes-used': 0,
|
'x-bytes-used': 0,
|
||||||
'x-delete-timestamp': '0',
|
'x-delete-timestamp': '0',
|
||||||
'x-object-count': 0,
|
'x-object-count': 0,
|
||||||
'x-put-timestamp': Timestamp(12345).internal,
|
'x-put-timestamp': ts_put.internal,
|
||||||
'X-Backend-Storage-Policy-Index': '%s' % POLICIES.default.idx,
|
'X-Backend-Storage-Policy-Index': '%s' % POLICIES.default.idx,
|
||||||
'referer': 'PUT http://localhost/sda1/p/a/c',
|
'referer': 'PUT http://localhost/sda1/p/a/c',
|
||||||
'user-agent': 'container-server %d' % os.getpid(),
|
'user-agent': 'container-server %d' % os.getpid(),
|
||||||
|
|||||||
Reference in New Issue
Block a user