summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlistair Coles <alistairncoles@gmail.com>2018-04-19 18:58:44 +0100
committerAlistair Coles <alistairncoles@gmail.com>2018-04-23 14:44:20 +0100
commitf47daf1131e8e45e736b693c635a7b10805c00d1 (patch)
tree9d9b66a2eb427134cd7d76f3c1d0c0f07dd70aa5
parentc0ffbd5eee04bc94a4fdeb8bbdeccf1e7338867d (diff)
downloadswift-f47daf1131e8e45e736b693c635a7b10805c00d1.tar.gz
Make first GET to root return objects or shard ranges as appropriate
Before the first backend container GET request was always for objects. The proxy then deduced the container's sharding state from the response headers and if appropriate made a second request for shard ranges. This was inefficient. With this patch the first backend container GET request has X-Backend-Record-Type set to 'auto' which causes the container server to return shard ranges if it is sharding or sharded, or objects otherwise. The proxy can deduce which record type it has received from the response header X-Backend-Record-Type and behave accordingly. Change-Id: If507d5b5d3e315007bf78f38ebdda8580cbc45cc
-rw-r--r--swift/container/server.py6
-rw-r--r--swift/proxy/controllers/container.py44
-rw-r--r--test/probe/test_sharder.py22
-rw-r--r--test/unit/container/test_server.py140
-rw-r--r--test/unit/proxy/controllers/test_container.py324
-rw-r--r--test/unit/proxy/test_server.py4
6 files changed, 320 insertions, 220 deletions
diff --git a/swift/container/server.py b/swift/container/server.py
index b75b79ba2..bcb7cd602 100644
--- a/swift/container/server.py
+++ b/swift/container/server.py
@@ -25,7 +25,8 @@ from eventlet import Timeout
import swift.common.db
from swift.container.sync_store import ContainerSyncStore
from swift.container.backend import ContainerBroker, DATADIR, \
- RECORD_TYPE_SHARD_NODE, UNSHARDED, SHARD_UPDATE_STATES, db_state_text
+ RECORD_TYPE_SHARD_NODE, UNSHARDED, SHARD_UPDATE_STATES, db_state_text, \
+ SHARDING, SHARDED
from swift.container.replicator import ContainerReplicatorRpc
from swift.common.db import DatabaseAlreadyExists
from swift.common.container_sync_realms import ContainerSyncRealms
@@ -584,6 +585,9 @@ class ContainerController(BaseStorageServer):
record_type = req.headers.get('x-backend-record-type', '').lower()
include_deleted = config_true_value(
req.headers.get('x-backend-include-deleted', False))
+ if record_type == 'auto' and info.get('db_state') in (SHARDING,
+ SHARDED):
+ record_type = 'shard'
if record_type == 'shard':
resp_headers = gen_resp_headers(info)
override_deleted = config_true_value(
diff --git a/swift/proxy/controllers/container.py b/swift/proxy/controllers/container.py
index acec6b878..d3e3fad7b 100644
--- a/swift/proxy/controllers/container.py
+++ b/swift/proxy/controllers/container.py
@@ -18,7 +18,7 @@ import json
from six.moves.urllib.parse import unquote
from swift.common.utils import public, csv_append, Timestamp, \
- config_true_value
+ config_true_value, ShardRange
from swift.common.constraints import check_metadata, CONTAINER_LISTING_LIMIT
from swift.common.http import HTTP_ACCEPTED, is_success
from swift.common.request_helpers import get_sys_meta_prefix
@@ -106,30 +106,26 @@ class ContainerController(Controller):
node_iter = self.app.iter_nodes(self.app.container_ring, part)
params = req.params
params['format'] = 'json'
+ record_type = req.headers.get('X-Backend-Record-Type', '').lower()
+ if not record_type:
+ record_type = 'auto'
+ req.headers['X-Backend-Record-Type'] = 'auto'
+ params['states'] = 'listing'
req.params = params
- # TODO: if cached container info tells us container is sharded then
- # skip straight to _get_sharded
resp = self.GETorHEAD_base(
req, _('Container'), node_iter, part,
req.swift_entity_path, concurrency)
- sharding_state = resp.headers.get(
- 'X-Backend-Sharding-State', 'unsharded')
- record_type = req.headers.get('X-Backend-Record-Type', '').lower()
- self.app.logger.debug('GET for container in state %s' % sharding_state)
- if all([req.method == "GET",
- sharding_state in ('sharding', 'sharded'),
- record_type not in ('object', 'shard')]):
+ resp_record_type = resp.headers.get('X-Backend-Record-Type', '')
+ if all((req.method == "GET", record_type == 'auto',
+ resp_record_type.lower() == 'shard')):
resp = self._get_from_shards(req, resp)
# Cache this. We just made a request to a storage node and got
# up-to-date information for the container.
resp.headers['X-Backend-Recheck-Container-Existence'] = str(
self.app.recheck_container_existence)
- # TODO: seems like a good idea to not set cache for shard/all
- # requests, but revisit this at some point
- if record_type != 'shard':
- set_info_cache(self.app, req.environ, self.account_name,
- self.container_name, resp)
+ set_info_cache(self.app, req.environ, self.account_name,
+ self.container_name, resp)
if 'swift.authorize' in req.environ:
req.acl = resp.headers.get('x-container-read')
aresp = req.environ['swift.authorize'](req)
@@ -149,11 +145,12 @@ class ContainerController(Controller):
return resp
def _get_from_shards(self, req, resp):
- # get the list of ShardRanges that contain the requested listing range
- # by using original request params
- ranges = self._get_shard_ranges(
- req, self.account_name, self.container_name, states='listing')
- if not ranges:
+ # construct listing using shards described by the response body
+ shard_ranges = [ShardRange.from_dict(data)
+ for data in json.loads(resp.body)]
+ self.app.logger.debug('GET listing from %s shards for: %s',
+ len(shard_ranges), req.path_qs)
+ if not shard_ranges:
# can't find ranges or there was a problem getting the ranges. So
# return what we have.
return resp
@@ -161,12 +158,14 @@ class ContainerController(Controller):
objects = []
req_limit = int(req.params.get('limit', CONTAINER_LISTING_LIMIT))
params = req.params.copy()
+ params.pop('states', None)
+ req.headers.pop('X-Backend-Record-Type', None)
reverse = config_true_value(params.get('reverse'))
marker = params.get('marker')
end_marker = params.get('end_marker')
limit = req_limit
- for shard_range in ranges:
+ for shard_range in shard_ranges:
params['limit'] = limit
# Always set marker to ensure that object names less than or equal
# to those already in the listing are not fetched
@@ -194,9 +193,12 @@ class ContainerController(Controller):
if (shard_range.account == self.account_name and
shard_range.container == self.container_name):
+ # directed back to same container - force GET of objects
headers = {'X-Backend-Record-Type': 'object'}
else:
headers = None
+ self.app.logger.debug('Getting from %s %s with %s',
+ shard_range, shard_range.name, headers)
objs, shard_resp = self._get_container_listing(
req, shard_range.account, shard_range.container,
headers=headers, params=params)
diff --git a/test/probe/test_sharder.py b/test/probe/test_sharder.py
index a78e2a35f..0aeb9dcf2 100644
--- a/test/probe/test_sharder.py
+++ b/test/probe/test_sharder.py
@@ -608,9 +608,9 @@ class TestContainerSharding(ReplProbeTest):
self.run_sharders(shard_1)
self.assert_container_object_count(len(more_obj_names + obj_names))
- # we've added objects enough that we need to shard *again* into three
- # new shards, but nothing happens until the root leader identifies
- # shard candidate...
+ # we've added objects enough that we need to shard the first shard
+ # *again* into three new sub-shards, but nothing happens until the root
+ # leader identifies shard candidate...
root_shard_ranges = self.direct_get_container_shard_ranges()
for node, (hdrs, root_shards) in root_shard_ranges.items():
self.assertLengthEqual(root_shards, 2)
@@ -628,7 +628,7 @@ class TestContainerSharding(ReplProbeTest):
self.sharders.once(number=self.brain.node_numbers[0],
additional_args='--partitions=%s' % self.brain.part)
- # ... so third shard replica state is not moved to sharding
+ # ... so third replica of first shard state is not moved to sharding
found_for_shard = self.categorize_container_dir_content(
shard_1.account, shard_1.container)
self.assertLengthEqual(found_for_shard['normal_dbs'], 3)
@@ -637,15 +637,15 @@ class TestContainerSharding(ReplProbeTest):
[ContainerBroker(db_file).get_own_shard_range().state
for db_file in found_for_shard['normal_dbs']])
- # ...then run first cycle of shard sharders in order, leader first, to
- # get to predictable state where all nodes have cleaved 2 out of 3
- # ranges...starting with first two nodes
+ # ...then run first cycle of first shard sharders in order, leader
+ # first, to get to predictable state where all nodes have cleaved 2 out
+ # of 3 ranges...starting with first two nodes
for node_number in shard_1_nodes[:2]:
self.sharders.once(
number=node_number,
additional_args='--partitions=%s' % shard_1_part)
- # ... first two replicas start sharding
+ # ... first two replicas start sharding to sub-shards
found_for_shard = self.categorize_container_dir_content(
shard_1.account, shard_1.container)
self.assertLengthEqual(found_for_shard['shard_dbs'], 2)
@@ -682,7 +682,7 @@ class TestContainerSharding(ReplProbeTest):
number=shard_1_nodes[2],
additional_args='--partitions=%s' % shard_1_part)
- # third replica is sharding but has no shard ranges yet...
+ # third replica is sharding but has no sub-shard ranges yet...
found_for_shard = self.categorize_container_dir_content(
shard_1.account, shard_1.container)
self.assertLengthEqual(found_for_shard['shard_dbs'], 2)
@@ -693,7 +693,7 @@ class TestContainerSharding(ReplProbeTest):
ShardRange.SHARDING, broker.get_own_shard_range().state)
self.assertFalse(broker.get_shard_ranges())
- # ...until shard ranges are replicated from another shard replica;
+ # ...until sub-shard ranges are replicated from another shard replica;
# there may also be a sub-shard replica missing so run replicators on
# all nodes to fix that if necessary
self.brain.servers.start(number=shard_1_nodes[2])
@@ -704,7 +704,7 @@ class TestContainerSharding(ReplProbeTest):
number=shard_1_nodes[2],
additional_args='--partitions=%s' % shard_1_part)
- # check original first shard range state and shards - all replicas
+ # check original first shard range state and sub-shards - all replicas
# should now be in consistent state
found_for_shard = self.categorize_container_dir_content(
shard_1.account, shard_1.container)
diff --git a/test/unit/container/test_server.py b/test/unit/container/test_server.py
index e8014b43e..ef3136fe2 100644
--- a/test/unit/container/test_server.py
+++ b/test/unit/container/test_server.py
@@ -2783,6 +2783,146 @@ class TestContainerController(unittest.TestCase):
do_test(False, [])
do_test(True, shard_ranges)
+ def test_GET_auto_record_type(self):
+ # make a container
+ ts_iter = make_timestamp_iter()
+ ts_now = Timestamp.now() # used when mocking Timestamp.now()
+ headers = {'X-Timestamp': next(ts_iter).normal}
+ req = Request.blank('/sda1/p/a/c', method='PUT', headers=headers)
+ self.assertEqual(201, req.get_response(self.controller).status_int)
+ # PUT some objects
+ objects = [{'name': 'obj_%d' % i,
+ 'x-timestamp': next(ts_iter).normal,
+ 'x-content-type': 'text/plain',
+ 'x-etag': 'etag_%d' % i,
+ 'x-size': 1024 * i
+ } for i in range(2)]
+ for obj in objects:
+ req = Request.blank('/sda1/p/a/c/%s' % obj['name'], method='PUT',
+ headers=obj)
+ self._update_object_put_headers(req)
+ resp = req.get_response(self.controller)
+ self.assertEqual(201, resp.status_int)
+ # PUT some shard ranges
+ shard_bounds = [('', 'm', ShardRange.CLEAVED),
+ ('m', '', ShardRange.CREATED)]
+ shard_ranges = [
+ ShardRange('.sharded_a/_%s' % upper, next(ts_iter),
+ lower, upper,
+ i * 100, i * 1000, meta_timestamp=next(ts_iter),
+ state=state, state_timestamp=next(ts_iter))
+ for i, (lower, upper, state) in enumerate(shard_bounds)]
+ for shard_range in shard_ranges:
+ self._put_shard_range(shard_range)
+
+ broker = self.controller._get_container_broker('sda1', 'p', 'a', 'c')
+
+ def assert_GET_objects(req, expected_objects):
+ resp = req.get_response(self.controller)
+ self.assertEqual(resp.status_int, 200)
+ self.assertEqual(resp.content_type, 'application/json')
+ expected = [
+ dict(hash=obj['x-etag'], bytes=obj['x-size'],
+ content_type=obj['x-content-type'],
+ last_modified=Timestamp(obj['x-timestamp']).isoformat,
+ name=obj['name']) for obj in expected_objects]
+ self.assertEqual(expected, json.loads(resp.body))
+ self.assertIn('X-Backend-Record-Type', resp.headers)
+ self.assertEqual(
+ 'object', resp.headers.pop('X-Backend-Record-Type'))
+ resp.headers.pop('Content-Length')
+ return resp
+
+ def assert_GET_shard_ranges(req, expected_shard_ranges):
+ with mock.patch('swift.common.utils.Timestamp.now',
+ classmethod(lambda ts_cls: ts_now)):
+ resp = req.get_response(self.controller)
+ self.assertEqual(resp.status_int, 200)
+ self.assertEqual(resp.content_type, 'application/json')
+ expected = [
+ dict(sr, last_modified=Timestamp(sr.timestamp).isoformat)
+ for sr in expected_shard_ranges]
+ self.assertEqual(expected, json.loads(resp.body))
+ self.assertIn('X-Backend-Record-Type', resp.headers)
+ self.assertEqual(
+ 'shard', resp.headers.pop('X-Backend-Record-Type'))
+ resp.headers.pop('Content-Length')
+ return resp
+
+ # unsharded
+ req = Request.blank('/sda1/p/a/c?format=json', method='GET',
+ headers={'X-Backend-Record-Type': 'auto'})
+ resp = assert_GET_objects(req, objects)
+ headers = resp.headers
+ req = Request.blank('/sda1/p/a/c?format=json', method='GET',
+ headers={'X-Backend-Record-Type': 'shard'})
+ resp = assert_GET_shard_ranges(req, shard_ranges)
+ self.assertEqual(headers, resp.headers)
+ req = Request.blank('/sda1/p/a/c?format=json', method='GET',
+ headers={'X-Backend-Record-Type': 'object'})
+ resp = assert_GET_objects(req, objects)
+ self.assertEqual(headers, resp.headers)
+ req = Request.blank('/sda1/p/a/c?format=json', method='GET')
+ resp = assert_GET_objects(req, objects)
+ self.assertEqual(headers, resp.headers)
+
+ # move to sharding state
+ own_sr = broker.get_own_shard_range()
+ own_sr.update_state(ShardRange.SHARDING, state_timestamp=next(ts_iter))
+ own_sr.epoch = next(ts_iter)
+ broker.merge_shard_ranges(own_sr)
+ self.assertTrue(broker.set_sharding_state())
+ req = Request.blank('/sda1/p/a/c?format=json', method='GET',
+ headers={'X-Backend-Record-Type': 'auto'})
+ resp = assert_GET_shard_ranges(req, shard_ranges)
+ headers = resp.headers
+ req = Request.blank('/sda1/p/a/c?format=json', method='GET',
+ headers={'X-Backend-Record-Type': 'shard'})
+ resp = assert_GET_shard_ranges(req, shard_ranges)
+ self.assertEqual(headers, resp.headers)
+ req = Request.blank('/sda1/p/a/c?format=json', method='GET',
+ headers={'X-Backend-Record-Type': 'object'})
+ resp = assert_GET_objects(req, objects)
+ self.assertEqual(headers, resp.headers)
+ req = Request.blank('/sda1/p/a/c?format=json', method='GET')
+ resp = assert_GET_objects(req, objects)
+ self.assertEqual(headers, resp.headers)
+
+ # limit is applied to objects but not shard ranges
+ req = Request.blank('/sda1/p/a/c?format=json&limit=1', method='GET',
+ headers={'X-Backend-Record-Type': 'auto'})
+ resp = assert_GET_shard_ranges(req, shard_ranges)
+ headers = resp.headers
+ req = Request.blank('/sda1/p/a/c?format=json&limit=1', method='GET',
+ headers={'X-Backend-Record-Type': 'shard'})
+ resp = assert_GET_shard_ranges(req, shard_ranges)
+ self.assertEqual(headers, resp.headers)
+ req = Request.blank('/sda1/p/a/c?format=json&limit=1', method='GET',
+ headers={'X-Backend-Record-Type': 'object'})
+ resp = assert_GET_objects(req, objects[:1])
+ self.assertEqual(headers, resp.headers)
+ req = Request.blank('/sda1/p/a/c?format=json&limit=1', method='GET')
+ resp = assert_GET_objects(req, objects[:1])
+ self.assertEqual(headers, resp.headers)
+
+ # move to sharded state
+ self.assertTrue(broker.set_sharded_state())
+ req = Request.blank('/sda1/p/a/c?format=json', method='GET',
+ headers={'X-Backend-Record-Type': 'auto'})
+ resp = assert_GET_shard_ranges(req, shard_ranges)
+ headers = resp.headers
+ req = Request.blank('/sda1/p/a/c?format=json', method='GET',
+ headers={'X-Backend-Record-Type': 'shard'})
+ resp = assert_GET_shard_ranges(req, shard_ranges)
+ self.assertEqual(headers, resp.headers)
+ req = Request.blank('/sda1/p/a/c?format=json', method='GET',
+ headers={'X-Backend-Record-Type': 'object'})
+ resp = assert_GET_objects(req, [])
+ self.assertEqual(headers, resp.headers)
+ req = Request.blank('/sda1/p/a/c?format=json', method='GET')
+ resp = assert_GET_objects(req, [])
+ self.assertEqual(headers, resp.headers)
+
def test_PUT_GET_to_sharding_container(self):
broker = self.controller._get_container_broker('sda1', 'p', 'a', 'c')
ts_iter = make_timestamp_iter()
diff --git a/test/unit/proxy/controllers/test_container.py b/test/unit/proxy/controllers/test_container.py
index 33af90d2d..ff84f7b57 100644
--- a/test/unit/proxy/controllers/test_container.py
+++ b/test/unit/proxy/controllers/test_container.py
@@ -498,8 +498,9 @@ class TestContainerController(TestRingBase):
def test_GET_sharded_container(self):
shard_bounds = (('', 'ham'), ('ham', 'pie'), ('pie', ''))
- shard_ranges = [ShardRange('a/c', Timestamp.now(), lower, upper)
- for lower, upper in shard_bounds]
+ shard_ranges = [
+ ShardRange('.shards_a/c_%s' % upper, Timestamp.now(), lower, upper)
+ for lower, upper in shard_bounds]
sr_dicts = [dict(sr) for sr in shard_ranges]
sr_objs = [self._make_shard_objects(sr) for sr in shard_ranges]
shard_resp_hdrs = [
@@ -532,8 +533,6 @@ class TestContainerController(TestRingBase):
mock_responses = [
# status, body, headers
(404, '', {}),
- (200, {}, root_resp_hdrs),
- (404, '', {}),
(200, sr_dicts, root_shard_resp_hdrs),
(200, sr_objs[0], shard_resp_hdrs[0]),
(200, sr_objs[1], shard_resp_hdrs[1]),
@@ -541,19 +540,18 @@ class TestContainerController(TestRingBase):
]
expected_requests = [
# path, headers, params
- ('a/c', {}, {}), # 404
- ('a/c', {}, {}), # 200
- ('a/c', {'X-Backend-Record-Type': 'shard'},
+ ('a/c', {'X-Backend-Record-Type': 'auto'},
dict(states='listing')), # 404
- ('a/c', {'X-Backend-Record-Type': 'shard'},
+ ('a/c', {'X-Backend-Record-Type': 'auto'},
dict(states='listing')), # 200
- (shard_ranges[0].name, {},
- dict(marker='', end_marker='ham\x00', limit=str(limit))), # 200
- (shard_ranges[1].name, {},
- dict(marker='h', end_marker='pie\x00',
+ (shard_ranges[0].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='', end_marker='ham\x00', limit=str(limit),
+ states='listing')), # 200
+ (shard_ranges[1].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='h', end_marker='pie\x00', states='listing',
limit=str(limit - len(sr_objs[0])))), # 200
- (shard_ranges[2].name, {},
- dict(marker='p', end_marker='',
+ (shard_ranges[2].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='p', end_marker='', states='listing',
limit=str(limit - len(sr_objs[0] + sr_objs[1])))) # 200
]
@@ -567,7 +565,6 @@ class TestContainerController(TestRingBase):
root_range = ShardRange('a/c', Timestamp.now(), 'pie', '')
mock_responses = [
# status, body, headers
- (200, {}, root_resp_hdrs),
(200, sr_dicts[:2] + [dict(root_range)], root_shard_resp_hdrs),
(200, sr_objs[0], shard_resp_hdrs[0]),
(200, sr_objs[1], shard_resp_hdrs[1]),
@@ -575,13 +572,13 @@ class TestContainerController(TestRingBase):
]
expected_requests = [
# path, headers, params
- ('a/c', {}, {}), # 200
- ('a/c', {'X-Backend-Record-Type': 'shard'},
+ ('a/c', {'X-Backend-Record-Type': 'auto'},
dict(states='listing')), # 200
- (shard_ranges[0].name, {},
- dict(marker='', end_marker='ham\x00', limit=str(limit))), # 200
- (shard_ranges[1].name, {},
- dict(marker='h', end_marker='pie\x00',
+ (shard_ranges[0].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='', end_marker='ham\x00', limit=str(limit),
+ states='listing')), # 200
+ (shard_ranges[1].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='h', end_marker='pie\x00', states='listing',
limit=str(limit - len(sr_objs[0])))), # 200
(root_range.name, {'X-Backend-Record-Type': 'object'},
dict(marker='p', end_marker='',
@@ -597,7 +594,6 @@ class TestContainerController(TestRingBase):
# GET all objects in reverse
mock_responses = [
# status, body, headers
- (200, {}, root_resp_hdrs),
(200, list(reversed(sr_dicts)), root_shard_resp_hdrs),
(200, list(reversed(sr_objs[2])), shard_resp_hdrs[2]),
(200, list(reversed(sr_objs[1])), shard_resp_hdrs[1]),
@@ -605,18 +601,16 @@ class TestContainerController(TestRingBase):
]
expected_requests = [
# path, headers, params
- ('a/c', {}, dict(reverse='true')), # 200
- ('a/c', {'X-Backend-Record-Type': 'shard'},
- dict(states='listing', reverse='true')), # 404
- (shard_ranges[2].name, {},
+ ('a/c', {'X-Backend-Record-Type': 'auto'},
+ dict(states='listing', reverse='true')),
+ (shard_ranges[2].name, {'X-Backend-Record-Type': 'auto'},
dict(marker='', end_marker='pie', reverse='true',
- limit=str(limit))), # 200
- (shard_ranges[1].name, {},
- dict(marker='q', end_marker='ham',
+ limit=str(limit), states='listing')), # 200
+ (shard_ranges[1].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='q', end_marker='ham', states='listing',
reverse='true', limit=str(limit - len(sr_objs[2])))), # 200
- (shard_ranges[0].name, {},
- dict(marker='i', end_marker='',
- reverse='true',
+ (shard_ranges[0].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='i', end_marker='', states='listing', reverse='true',
limit=str(limit - len(sr_objs[2] + sr_objs[1])))), # 200
]
@@ -632,28 +626,24 @@ class TestContainerController(TestRingBase):
expected_objects = all_objects[:limit]
mock_responses = [
(404, '', {}),
- (200, {}, root_resp_hdrs),
- (404, '', {}),
(200, sr_dicts, root_shard_resp_hdrs),
(200, sr_objs[0], shard_resp_hdrs[0]),
(200, sr_objs[1], shard_resp_hdrs[1]),
(200, sr_objs[2][:1], shard_resp_hdrs[2])
]
expected_requests = [
- ('a/c', {}, dict(limit=str(limit))), # 404
- ('a/c', {}, dict(limit=str(limit))), # 200
- ('a/c', {'X-Backend-Record-Type': 'shard'},
- dict(states='listing')), # 404
- ('a/c', {'X-Backend-Record-Type': 'shard'},
- dict(states='listing')), # 200
- (shard_ranges[0].name, {}, # 200
- dict(marker='', end_marker='ham\x00',
+ ('a/c', {'X-Backend-Record-Type': 'auto'},
+ dict(limit=str(limit), states='listing')), # 404
+ ('a/c', {'X-Backend-Record-Type': 'auto'},
+ dict(limit=str(limit), states='listing')), # 200
+ (shard_ranges[0].name, {'X-Backend-Record-Type': 'auto'}, # 200
+ dict(marker='', end_marker='ham\x00', states='listing',
limit=str(limit))),
- (shard_ranges[1].name, {}, # 200
- dict(marker='h', end_marker='pie\x00',
+ (shard_ranges[1].name, {'X-Backend-Record-Type': 'auto'}, # 200
+ dict(marker='h', end_marker='pie\x00', states='listing',
limit=str(limit - len(sr_objs[0])))),
- (shard_ranges[2].name, {}, # 200
- dict(marker='p', end_marker='',
+ (shard_ranges[2].name, {'X-Backend-Record-Type': 'auto'}, # 200
+ dict(marker='p', end_marker='', states='listing',
limit=str(limit - len(sr_objs[0] + sr_objs[1]))))
]
resp = self._check_GET_shard_listing(
@@ -668,25 +658,24 @@ class TestContainerController(TestRingBase):
expected_objects = all_objects[first_included:]
mock_responses = [
(404, '', {}),
- (200, {}, root_resp_hdrs),
(200, sr_dicts[1:], root_shard_resp_hdrs),
(404, '', {}),
(200, sr_objs[1][2:], shard_resp_hdrs[1]),
(200, sr_objs[2], shard_resp_hdrs[2])
]
expected_requests = [
- ('a/c', {}, dict(marker=marker)), # 404
- ('a/c', {}, dict(marker=marker)), # 200
- ('a/c', {'X-Backend-Record-Type': 'shard'},
+ ('a/c', {'X-Backend-Record-Type': 'auto'},
+ dict(marker=marker, states='listing')), # 404
+ ('a/c', {'X-Backend-Record-Type': 'auto'},
dict(marker=marker, states='listing')), # 200
- (shard_ranges[1].name, {}, # 404
- dict(marker=marker, end_marker='pie\x00',
+ (shard_ranges[1].name, {'X-Backend-Record-Type': 'auto'}, # 404
+ dict(marker=marker, end_marker='pie\x00', states='listing',
limit=str(limit))),
- (shard_ranges[1].name, {}, # 200
- dict(marker=marker, end_marker='pie\x00',
+ (shard_ranges[1].name, {'X-Backend-Record-Type': 'auto'}, # 200
+ dict(marker=marker, end_marker='pie\x00', states='listing',
limit=str(limit))),
- (shard_ranges[2].name, {}, # 200
- dict(marker='p', end_marker='',
+ (shard_ranges[2].name, {'X-Backend-Record-Type': 'auto'}, # 200
+ dict(marker='p', end_marker='', states='listing',
limit=str(limit - len(sr_objs[1][2:])))),
]
resp = self._check_GET_shard_listing(
@@ -700,25 +689,24 @@ class TestContainerController(TestRingBase):
expected_objects = all_objects[:first_excluded]
mock_responses = [
(404, '', {}),
- (200, {}, root_resp_hdrs),
(200, sr_dicts[:2], root_shard_resp_hdrs),
(200, sr_objs[0], shard_resp_hdrs[0]),
(404, '', {}),
(200, sr_objs[1][:6], shard_resp_hdrs[1])
]
expected_requests = [
- ('a/c', {}, dict(end_marker=end_marker)), # 404
- ('a/c', {}, dict(end_marker=end_marker)), # 200
- ('a/c', {'X-Backend-Record-Type': 'shard'},
+ ('a/c', {'X-Backend-Record-Type': 'auto'},
+ dict(end_marker=end_marker, states='listing')), # 404
+ ('a/c', {'X-Backend-Record-Type': 'auto'},
dict(end_marker=end_marker, states='listing')), # 200
- (shard_ranges[0].name, {}, # 200
- dict(marker='', end_marker='ham\x00',
+ (shard_ranges[0].name, {'X-Backend-Record-Type': 'auto'}, # 200
+ dict(marker='', end_marker='ham\x00', states='listing',
limit=str(limit))),
- (shard_ranges[1].name, {}, # 404
- dict(marker='h', end_marker=end_marker,
+ (shard_ranges[1].name, {'X-Backend-Record-Type': 'auto'}, # 404
+ dict(marker='h', end_marker=end_marker, states='listing',
limit=str(limit - len(sr_objs[0])))),
- (shard_ranges[1].name, {}, # 200
- dict(marker='h', end_marker=end_marker,
+ (shard_ranges[1].name, {'X-Backend-Record-Type': 'auto'}, # 200
+ dict(marker='h', end_marker=end_marker, states='listing',
limit=str(limit - len(sr_objs[0])))),
]
resp = self._check_GET_shard_listing(
@@ -730,27 +718,15 @@ class TestContainerController(TestRingBase):
limit = 2
expected_objects = all_objects[first_included:first_excluded]
mock_responses = [
- (404, '', {}),
- (200, {}, root_resp_hdrs),
- (404, '', {}),
(200, sr_dicts[1:2], root_shard_resp_hdrs),
(200, sr_objs[1][2:6], shard_resp_hdrs[1])
]
expected_requests = [
- ('a/c', {},
- dict(marker=marker, end_marker=end_marker,
- limit=str(limit))), # 404
- ('a/c', {},
- dict(marker=marker, end_marker=end_marker,
- limit=str(limit))), # 200
- ('a/c', {'X-Backend-Record-Type': 'shard'},
- dict(states='listing',
- marker=marker, end_marker=end_marker)), # 404
- ('a/c', {'X-Backend-Record-Type': 'shard'},
- dict(states='listing',
+ ('a/c', {'X-Backend-Record-Type': 'auto'},
+ dict(states='listing', limit=str(limit),
marker=marker, end_marker=end_marker)), # 200
- (shard_ranges[1].name, {}, # 200
- dict(marker=marker, end_marker=end_marker,
+ (shard_ranges[1].name, {'X-Backend-Record-Type': 'auto'}, # 200
+ dict(marker=marker, end_marker=end_marker, states='listing',
limit=str(limit))),
]
resp = self._check_GET_shard_listing(
@@ -762,27 +738,15 @@ class TestContainerController(TestRingBase):
# reverse with marker, end_marker
expected_objects.reverse()
mock_responses = [
- (404, '', {}),
- (200, {}, root_resp_hdrs),
- (404, '', {}),
(200, sr_dicts[1:2], root_shard_resp_hdrs),
(200, list(reversed(sr_objs[1][2:6])), shard_resp_hdrs[1])
]
expected_requests = [
- ('a/c', {},
+ ('a/c', {'X-Backend-Record-Type': 'auto'},
dict(marker=end_marker, reverse='true', end_marker=marker,
- limit=str(limit))), # 404
- ('a/c', {},
- dict(marker=end_marker, reverse='true', end_marker=marker,
- limit=str(limit))), # 200
- ('a/c', {'X-Backend-Record-Type': 'shard'},
- dict(states='listing', marker=end_marker,
- end_marker=marker, reverse='true')), # 404
- ('a/c', {'X-Backend-Record-Type': 'shard'},
- dict(states='listing', marker=end_marker,
- end_marker=marker, reverse='true')), # 200
- (shard_ranges[1].name, {}, # 200
- dict(marker=end_marker, end_marker=marker,
+ limit=str(limit), states='listing',)), # 200
+ (shard_ranges[1].name, {'X-Backend-Record-Type': 'auto'}, # 200
+ dict(marker=end_marker, end_marker=marker, states='listing',
limit=str(limit), reverse='true')),
]
self._check_GET_shard_listing(
@@ -802,7 +766,8 @@ class TestContainerController(TestRingBase):
('', 'pie', ShardRange.ACTIVE),
('lemon', '', ShardRange.ACTIVE))
shard_ranges = [
- ShardRange('a/c', Timestamp.now(), lower, upper, state=state)
+ ShardRange('.shards_a/c_' + upper, Timestamp.now(), lower, upper,
+ state=state)
for lower, upper, state in shard_bounds]
sr_dicts = [dict(sr) for sr in shard_ranges]
sr_objs = [self._make_shard_objects(sr) for sr in shard_ranges]
@@ -838,7 +803,6 @@ class TestContainerController(TestRingBase):
objs_2 = [o for o in sr_objs[2] if o['name'] > sr_objs[1][-1]['name']]
mock_responses = [
# status, body, headers
- (200, {}, root_resp_hdrs),
(200, sr_dicts, root_shard_resp_hdrs),
(200, sr_objs[0], shard_resp_hdrs[0]),
(200, objs_1, shard_resp_hdrs[1]),
@@ -847,16 +811,16 @@ class TestContainerController(TestRingBase):
# NB marker always advances to last object name
expected_requests = [
# path, headers, params
- ('a/c', {}, {}), # 200
- ('a/c', {'X-Backend-Record-Type': 'shard'},
+ ('a/c', {'X-Backend-Record-Type': 'auto'},
dict(states='listing')), # 200
- (shard_ranges[0].name, {},
- dict(marker='', end_marker='ham\x00', limit=str(limit))), # 200
- (shard_ranges[1].name, {},
- dict(marker='h', end_marker='pie\x00',
+ (shard_ranges[0].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='', end_marker='ham\x00', states='listing',
+ limit=str(limit))), # 200
+ (shard_ranges[1].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='h', end_marker='pie\x00', states='listing',
limit=str(limit - len(sr_objs[0])))), # 200
- (shard_ranges[2].name, {},
- dict(marker='p', end_marker='',
+ (shard_ranges[2].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='p', end_marker='', states='listing',
limit=str(limit - len(sr_objs[0] + objs_1)))) # 200
]
@@ -875,7 +839,6 @@ class TestContainerController(TestRingBase):
objs_1 = [o for o in sr_objs[1] if o['name'] < sr_objs[2][0]['name']]
mock_responses = [
# status, body, headers
- (200, {}, root_resp_hdrs),
(200, list(reversed(sr_dicts)), root_shard_resp_hdrs),
(200, list(reversed(sr_objs[2])), shard_resp_hdrs[2]),
(200, list(reversed(objs_1)), shard_resp_hdrs[1]),
@@ -884,17 +847,17 @@ class TestContainerController(TestRingBase):
# NB marker always advances to last object name
expected_requests = [
# path, headers, params
- ('a/c', {}, dict(reverse='true')), # 200
- ('a/c', {'X-Backend-Record-Type': 'shard'},
+ ('a/c', {'X-Backend-Record-Type': 'auto'},
dict(states='listing', reverse='true')), # 200
- (shard_ranges[2].name, {},
- dict(marker='', end_marker='lemon', limit=str(limit),
+ (shard_ranges[2].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='', end_marker='lemon', states='listing',
+ limit=str(limit),
reverse='true')), # 200
- (shard_ranges[1].name, {},
- dict(marker='m', end_marker='', reverse='true',
+ (shard_ranges[1].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='m', end_marker='', reverse='true', states='listing',
limit=str(limit - len(sr_objs[2])))), # 200
- (shard_ranges[0].name, {},
- dict(marker='A', end_marker='', reverse='true',
+ (shard_ranges[0].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='A', end_marker='', reverse='true', states='listing',
limit=str(limit - len(sr_objs[2] + objs_1)))) # 200
]
@@ -909,8 +872,9 @@ class TestContainerController(TestRingBase):
def test_GET_sharded_container_gap_in_shards(self):
# verify ordered listing even if unexpected gap between shard ranges
shard_bounds = (('', 'ham'), ('onion', 'pie'), ('rhubarb', ''))
- shard_ranges = [ShardRange('a/c', Timestamp.now(), lower, upper)
- for lower, upper in shard_bounds]
+ shard_ranges = [
+ ShardRange('.shards_a/c_' + upper, Timestamp.now(), lower, upper)
+ for lower, upper in shard_bounds]
sr_dicts = [dict(sr) for sr in shard_ranges]
sr_objs = [self._make_shard_objects(sr) for sr in shard_ranges]
shard_resp_hdrs = [
@@ -938,7 +902,6 @@ class TestContainerController(TestRingBase):
mock_responses = [
# status, body, headers
- (200, {}, root_resp_hdrs),
(200, sr_dicts, root_shard_resp_hdrs),
(200, sr_objs[0], shard_resp_hdrs[0]),
(200, sr_objs[1], shard_resp_hdrs[1]),
@@ -947,16 +910,16 @@ class TestContainerController(TestRingBase):
# NB marker always advances to last object name
expected_requests = [
# path, headers, params
- ('a/c', {}, {}), # 200
- ('a/c', {'X-Backend-Record-Type': 'shard'},
+ ('a/c', {'X-Backend-Record-Type': 'auto'},
dict(states='listing')), # 200
- (shard_ranges[0].name, {},
- dict(marker='', end_marker='ham\x00', limit=str(limit))), # 200
- (shard_ranges[1].name, {},
- dict(marker='h', end_marker='pie\x00',
+ (shard_ranges[0].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='', end_marker='ham\x00', states='listing',
+ limit=str(limit))), # 200
+ (shard_ranges[1].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='h', end_marker='pie\x00', states='listing',
limit=str(limit - len(sr_objs[0])))), # 200
- (shard_ranges[2].name, {},
- dict(marker='p', end_marker='',
+ (shard_ranges[2].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='p', end_marker='', states='listing',
limit=str(limit - len(sr_objs[0] + sr_objs[1])))) # 200
]
@@ -968,8 +931,9 @@ class TestContainerController(TestRingBase):
def test_GET_sharded_container_empty_shard(self):
# verify ordered listing when a shard is empty
shard_bounds = (('', 'ham'), ('ham', 'pie'), ('lemon', ''))
- shard_ranges = [ShardRange('a/c', Timestamp.now(), lower, upper)
- for lower, upper in shard_bounds]
+ shard_ranges = [
+ ShardRange('.shards_a/c_%s' % upper, Timestamp.now(), lower, upper)
+ for lower, upper in shard_bounds]
sr_dicts = [dict(sr) for sr in shard_ranges]
sr_objs = [self._make_shard_objects(sr) for sr in shard_ranges]
# empty second shard range
@@ -999,7 +963,6 @@ class TestContainerController(TestRingBase):
mock_responses = [
# status, body, headers
- (200, {}, root_resp_hdrs),
(200, sr_dicts, root_shard_resp_hdrs),
(200, sr_objs[0], shard_resp_hdrs[0]),
(200, sr_objs[1], shard_resp_hdrs[1]),
@@ -1008,16 +971,16 @@ class TestContainerController(TestRingBase):
# NB marker always advances to last object name
expected_requests = [
# path, headers, params
- ('a/c', {}, {}), # 200
- ('a/c', {'X-Backend-Record-Type': 'shard'},
+ ('a/c', {'X-Backend-Record-Type': 'auto'},
dict(states='listing')), # 200
- (shard_ranges[0].name, {},
- dict(marker='', end_marker='ham\x00', limit=str(limit))), # 200
- (shard_ranges[1].name, {},
- dict(marker='h', end_marker='pie\x00',
+ (shard_ranges[0].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='', end_marker='ham\x00', states='listing',
+ limit=str(limit))), # 200
+ (shard_ranges[1].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='h', end_marker='pie\x00', states='listing',
limit=str(limit - len(sr_objs[0])))), # 200
- (shard_ranges[2].name, {},
- dict(marker='h', end_marker='',
+ (shard_ranges[2].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='h', end_marker='', states='listing',
limit=str(limit - len(sr_objs[0] + sr_objs[1])))) # 200
]
@@ -1029,7 +992,6 @@ class TestContainerController(TestRingBase):
# marker in empty second range
mock_responses = [
# status, body, headers
- (200, {}, root_resp_hdrs),
(200, sr_dicts[1:], root_shard_resp_hdrs),
(200, sr_objs[1], shard_resp_hdrs[1]),
(200, sr_objs[2], shard_resp_hdrs[2])
@@ -1037,14 +999,14 @@ class TestContainerController(TestRingBase):
# NB marker unchanged when getting from third range
expected_requests = [
# path, headers, params
- ('a/c', {}, dict(marker='koolaid')), # 200
- ('a/c', {'X-Backend-Record-Type': 'shard'},
+ ('a/c', {'X-Backend-Record-Type': 'auto'},
dict(states='listing', marker='koolaid')), # 200
- (shard_ranges[1].name, {},
- dict(marker='koolaid', end_marker='pie\x00',
+ (shard_ranges[1].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='koolaid', end_marker='pie\x00', states='listing',
limit=str(limit))), # 200
- (shard_ranges[2].name, {},
- dict(marker='koolaid', end_marker='', limit=str(limit))) # 200
+ (shard_ranges[2].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='koolaid', end_marker='', states='listing',
+ limit=str(limit))) # 200
]
resp = self._check_GET_shard_listing(
@@ -1056,7 +1018,6 @@ class TestContainerController(TestRingBase):
# marker in empty second range, reverse
mock_responses = [
# status, body, headers
- (200, {}, root_resp_hdrs),
(200, list(reversed(sr_dicts[:2])), root_shard_resp_hdrs),
(200, list(reversed(sr_objs[1])), shard_resp_hdrs[1]),
(200, list(reversed(sr_objs[0])), shard_resp_hdrs[2])
@@ -1064,15 +1025,14 @@ class TestContainerController(TestRingBase):
# NB marker unchanged when getting from first range
expected_requests = [
# path, headers, params
- ('a/c', {}, dict(marker='koolaid', reverse='true')), # 200
- ('a/c', {'X-Backend-Record-Type': 'shard'},
+ ('a/c', {'X-Backend-Record-Type': 'auto'},
dict(states='listing', marker='koolaid', reverse='true')), # 200
- (shard_ranges[1].name, {},
+ (shard_ranges[1].name, {'X-Backend-Record-Type': 'auto'},
dict(marker='koolaid', end_marker='ham', reverse='true',
- limit=str(limit))), # 200
- (shard_ranges[0].name, {},
+ states='listing', limit=str(limit))), # 200
+ (shard_ranges[0].name, {'X-Backend-Record-Type': 'auto'},
dict(marker='koolaid', end_marker='', reverse='true',
- limit=str(limit))) # 200
+ states='listing', limit=str(limit))) # 200
]
resp = self._check_GET_shard_listing(
@@ -1084,8 +1044,9 @@ class TestContainerController(TestRingBase):
def _check_GET_sharded_container_shard_error(self, error):
# verify ordered listing when a shard is empty
shard_bounds = (('', 'ham'), ('ham', 'pie'), ('lemon', ''))
- shard_ranges = [ShardRange('a/c', Timestamp.now(), lower, upper)
- for lower, upper in shard_bounds]
+ shard_ranges = [
+ ShardRange('.shards_a/c_%s' % upper, Timestamp.now(), lower, upper)
+ for lower, upper in shard_bounds]
sr_dicts = [dict(sr) for sr in shard_ranges]
sr_objs = [self._make_shard_objects(sr) for sr in shard_ranges]
# empty second shard range
@@ -1115,7 +1076,6 @@ class TestContainerController(TestRingBase):
mock_responses = [
# status, body, headers
- (200, {}, root_resp_hdrs),
(200, sr_dicts, root_shard_resp_hdrs),
(200, sr_objs[0], shard_resp_hdrs[0])] + \
[(error, [], {})] * 2 * self.CONTAINER_REPLICAS + \
@@ -1124,17 +1084,17 @@ class TestContainerController(TestRingBase):
# NB marker always advances to last object name
expected_requests = [
# path, headers, params
- ('a/c', {}, {}), # 200
- ('a/c', {'X-Backend-Record-Type': 'shard'},
+ ('a/c', {'X-Backend-Record-Type': 'auto'},
dict(states='listing')), # 200
- (shard_ranges[0].name, {},
- dict(marker='', end_marker='ham\x00', limit=str(limit)))] \
- + [(shard_ranges[1].name, {},
- dict(marker='h', end_marker='pie\x00',
+ (shard_ranges[0].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='', end_marker='ham\x00', states='listing',
+ limit=str(limit)))] \
+ + [(shard_ranges[1].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='h', end_marker='pie\x00', states='listing',
limit=str(limit - len(sr_objs[0]))))
] * 2 * self.CONTAINER_REPLICAS \
- + [(shard_ranges[2].name, {},
- dict(marker='h', end_marker='',
+ + [(shard_ranges[2].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='h', end_marker='', states='listing',
limit=str(limit - len(sr_objs[0] + sr_objs[1]))))]
resp = self._check_GET_shard_listing(
@@ -1150,7 +1110,7 @@ class TestContainerController(TestRingBase):
# one shard is in process of sharding
shard_bounds = (('', 'ham'), ('ham', 'pie'), ('pie', ''))
shard_ranges = [
- ShardRange('a/c_' + upper, Timestamp.now(), lower, upper)
+ ShardRange('.shards_a/c_' + upper, Timestamp.now(), lower, upper)
for lower, upper in shard_bounds]
sr_dicts = [dict(sr) for sr in shard_ranges]
sr_objs = [self._make_shard_objects(sr) for sr in shard_ranges]
@@ -1198,10 +1158,8 @@ class TestContainerController(TestRingBase):
mock_responses = [
# status, body, headers
- (200, {}, root_resp_hdrs),
(200, sr_dicts, root_shard_resp_hdrs),
(200, sr_objs[0], shard_resp_hdrs[0]),
- (200, {}, shard_resp_hdrs[1]),
(200, sub_sr_dicts + [sr_dicts[1]], shard_1_shard_resp_hdrs),
(200, sub_sr_objs[0], sub_shard_resp_hdrs[0]),
(200, sub_sr_objs[1], sub_shard_resp_hdrs[1]),
@@ -1211,37 +1169,33 @@ class TestContainerController(TestRingBase):
]
# NB marker always advances to last object name
expected_requests = [
- # path, headers, params
- ('a/c', {}, {}),
# get root shard ranges
- ('a/c', {'X-Backend-Record-Type': 'shard'},
+ ('a/c', {'X-Backend-Record-Type': 'auto'},
dict(states='listing')), # 200
# get first shard objects
- (shard_ranges[0].name, {},
- dict(marker='', end_marker='ham\x00', limit=str(limit))), # 200
- # get second shard
- (shard_ranges[1].name, {},
- dict(marker='h', end_marker='pie\x00',
- limit=str(limit - len(sr_objs[0])))), # 200
+ (shard_ranges[0].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='', end_marker='ham\x00', states='listing',
+ limit=str(limit))), # 200
# get second shard sub-shard ranges
- (shard_ranges[1].name, {'X-Backend-Record-Type': 'shard'},
- dict(marker='h', end_marker='pie\x00', states='listing')),
+ (shard_ranges[1].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='h', end_marker='pie\x00', states='listing',
+ limit=str(limit - len(sr_objs[0])))),
# get first sub-shard objects
- (sub_shard_ranges[0].name, {},
- dict(marker='h', end_marker='juice\x00',
+ (sub_shard_ranges[0].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='h', end_marker='juice\x00', states='listing',
limit=str(limit - len(sr_objs[0])))),
# get second sub-shard objects
- (sub_shard_ranges[1].name, {},
- dict(marker='j', end_marker='lemon\x00',
+ (sub_shard_ranges[1].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='j', end_marker='lemon\x00', states='listing',
limit=str(limit - len(sr_objs[0] + sub_sr_objs[0])))),
# get remainder of first shard objects
- (shard_ranges[1].name, {},
+ (shard_ranges[1].name, {'X-Backend-Record-Type': 'object'},
dict(marker='l', end_marker='pie\x00',
limit=str(limit - len(sr_objs[0] + sub_sr_objs[0] +
sub_sr_objs[1])))), # 200
# get third shard objects
- (shard_ranges[2].name, {},
- dict(marker='p', end_marker='',
+ (shard_ranges[2].name, {'X-Backend-Record-Type': 'auto'},
+ dict(marker='p', end_marker='', states='listing',
limit=str(limit - len(sr_objs[0] + sr_objs[1])))) # 200
]
expected_objects = (
diff --git a/test/unit/proxy/test_server.py b/test/unit/proxy/test_server.py
index 758ad7d54..743ad6b18 100644
--- a/test/unit/proxy/test_server.py
+++ b/test/unit/proxy/test_server.py
@@ -3346,7 +3346,7 @@ class TestReplicatedObjectController(
'x-backend-sharding-state': sharding_state,
'X-Backend-Record-Type': 'shard'}
shard_range = utils.ShardRange(
- '.sharded_a/c_shard', utils.Timestamp.now(), 'l', 'u')
+ '.shards_a/c_shard', utils.Timestamp.now(), 'l', 'u')
body = json.dumps([dict(shard_range)])
with mocked_http_conn(*status_codes, headers=resp_headers,
body=body) as fake_conn:
@@ -3398,7 +3398,7 @@ class TestReplicatedObjectController(
'Host': 'localhost:80',
'Referer': '%s http://localhost/v1/a/c/o' % method,
'X-Backend-Storage-Policy-Index': '1',
- 'X-Backend-Container-Path': '.sharded_a/c_shard'
+ 'X-Backend-Container-Path': shard_range.name
},
}
check_request(request, **expectations)