swift 2.32.0__py2.py3-none-any.whl → 2.34.0__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- swift/account/auditor.py +11 -0
- swift/account/reaper.py +11 -1
- swift/account/replicator.py +22 -0
- swift/account/server.py +13 -12
- swift-2.32.0.data/scripts/swift-account-audit → swift/cli/account_audit.py +6 -2
- swift-2.32.0.data/scripts/swift-config → swift/cli/config.py +1 -1
- swift-2.32.0.data/scripts/swift-dispersion-populate → swift/cli/dispersion_populate.py +6 -2
- swift-2.32.0.data/scripts/swift-drive-audit → swift/cli/drive_audit.py +12 -3
- swift-2.32.0.data/scripts/swift-get-nodes → swift/cli/get_nodes.py +6 -2
- swift/cli/info.py +131 -3
- swift-2.32.0.data/scripts/swift-oldies → swift/cli/oldies.py +6 -3
- swift-2.32.0.data/scripts/swift-orphans → swift/cli/orphans.py +7 -2
- swift-2.32.0.data/scripts/swift-recon-cron → swift/cli/recon_cron.py +9 -18
- swift-2.32.0.data/scripts/swift-reconciler-enqueue → swift/cli/reconciler_enqueue.py +2 -3
- swift/cli/relinker.py +1 -1
- swift/cli/reload.py +141 -0
- swift/cli/ringbuilder.py +24 -0
- swift/common/daemon.py +12 -2
- swift/common/db.py +14 -9
- swift/common/db_auditor.py +2 -2
- swift/common/db_replicator.py +6 -0
- swift/common/exceptions.py +12 -0
- swift/common/http_protocol.py +76 -3
- swift/common/manager.py +120 -5
- swift/common/memcached.py +24 -25
- swift/common/middleware/account_quotas.py +144 -43
- swift/common/middleware/backend_ratelimit.py +166 -24
- swift/common/middleware/catch_errors.py +1 -3
- swift/common/middleware/cname_lookup.py +3 -5
- swift/common/middleware/container_sync.py +6 -10
- swift/common/middleware/crypto/crypto_utils.py +4 -5
- swift/common/middleware/crypto/decrypter.py +4 -5
- swift/common/middleware/crypto/kms_keymaster.py +2 -1
- swift/common/middleware/proxy_logging.py +57 -43
- swift/common/middleware/ratelimit.py +6 -7
- swift/common/middleware/recon.py +6 -7
- swift/common/middleware/s3api/acl_handlers.py +10 -1
- swift/common/middleware/s3api/controllers/__init__.py +3 -0
- swift/common/middleware/s3api/controllers/acl.py +3 -2
- swift/common/middleware/s3api/controllers/logging.py +2 -2
- swift/common/middleware/s3api/controllers/multi_upload.py +31 -15
- swift/common/middleware/s3api/controllers/obj.py +20 -1
- swift/common/middleware/s3api/controllers/object_lock.py +44 -0
- swift/common/middleware/s3api/s3api.py +6 -0
- swift/common/middleware/s3api/s3request.py +190 -74
- swift/common/middleware/s3api/s3response.py +48 -8
- swift/common/middleware/s3api/s3token.py +2 -2
- swift/common/middleware/s3api/utils.py +2 -1
- swift/common/middleware/slo.py +508 -310
- swift/common/middleware/staticweb.py +45 -14
- swift/common/middleware/tempauth.py +6 -4
- swift/common/middleware/tempurl.py +134 -93
- swift/common/middleware/x_profile/exceptions.py +1 -4
- swift/common/middleware/x_profile/html_viewer.py +9 -10
- swift/common/middleware/x_profile/profile_model.py +1 -2
- swift/common/middleware/xprofile.py +1 -2
- swift/common/request_helpers.py +101 -8
- swift/common/statsd_client.py +207 -0
- swift/common/storage_policy.py +1 -1
- swift/common/swob.py +5 -2
- swift/common/utils/__init__.py +331 -1774
- swift/common/utils/base.py +138 -0
- swift/common/utils/config.py +443 -0
- swift/common/utils/logs.py +999 -0
- swift/common/utils/timestamp.py +23 -2
- swift/common/wsgi.py +19 -3
- swift/container/auditor.py +11 -0
- swift/container/backend.py +136 -31
- swift/container/reconciler.py +11 -2
- swift/container/replicator.py +64 -7
- swift/container/server.py +276 -146
- swift/container/sharder.py +86 -42
- swift/container/sync.py +11 -1
- swift/container/updater.py +12 -2
- swift/obj/auditor.py +20 -3
- swift/obj/diskfile.py +63 -25
- swift/obj/expirer.py +154 -47
- swift/obj/mem_diskfile.py +2 -1
- swift/obj/mem_server.py +1 -0
- swift/obj/reconstructor.py +28 -4
- swift/obj/replicator.py +63 -24
- swift/obj/server.py +76 -59
- swift/obj/updater.py +12 -2
- swift/obj/watchers/dark_data.py +72 -34
- swift/proxy/controllers/account.py +3 -2
- swift/proxy/controllers/base.py +254 -148
- swift/proxy/controllers/container.py +274 -289
- swift/proxy/controllers/obj.py +120 -166
- swift/proxy/server.py +17 -13
- {swift-2.32.0.dist-info → swift-2.34.0.dist-info}/AUTHORS +14 -4
- {swift-2.32.0.dist-info → swift-2.34.0.dist-info}/METADATA +9 -7
- {swift-2.32.0.dist-info → swift-2.34.0.dist-info}/RECORD +97 -120
- {swift-2.32.0.dist-info → swift-2.34.0.dist-info}/entry_points.txt +39 -0
- swift-2.34.0.dist-info/pbr.json +1 -0
- swift-2.32.0.data/scripts/swift-account-auditor +0 -23
- swift-2.32.0.data/scripts/swift-account-info +0 -52
- swift-2.32.0.data/scripts/swift-account-reaper +0 -23
- swift-2.32.0.data/scripts/swift-account-replicator +0 -34
- swift-2.32.0.data/scripts/swift-account-server +0 -23
- swift-2.32.0.data/scripts/swift-container-auditor +0 -23
- swift-2.32.0.data/scripts/swift-container-info +0 -56
- swift-2.32.0.data/scripts/swift-container-reconciler +0 -21
- swift-2.32.0.data/scripts/swift-container-replicator +0 -34
- swift-2.32.0.data/scripts/swift-container-server +0 -23
- swift-2.32.0.data/scripts/swift-container-sharder +0 -37
- swift-2.32.0.data/scripts/swift-container-sync +0 -23
- swift-2.32.0.data/scripts/swift-container-updater +0 -23
- swift-2.32.0.data/scripts/swift-dispersion-report +0 -24
- swift-2.32.0.data/scripts/swift-form-signature +0 -20
- swift-2.32.0.data/scripts/swift-init +0 -119
- swift-2.32.0.data/scripts/swift-object-auditor +0 -29
- swift-2.32.0.data/scripts/swift-object-expirer +0 -33
- swift-2.32.0.data/scripts/swift-object-info +0 -60
- swift-2.32.0.data/scripts/swift-object-reconstructor +0 -33
- swift-2.32.0.data/scripts/swift-object-relinker +0 -23
- swift-2.32.0.data/scripts/swift-object-replicator +0 -37
- swift-2.32.0.data/scripts/swift-object-server +0 -27
- swift-2.32.0.data/scripts/swift-object-updater +0 -23
- swift-2.32.0.data/scripts/swift-proxy-server +0 -23
- swift-2.32.0.data/scripts/swift-recon +0 -24
- swift-2.32.0.data/scripts/swift-ring-builder +0 -37
- swift-2.32.0.data/scripts/swift-ring-builder-analyzer +0 -22
- swift-2.32.0.data/scripts/swift-ring-composer +0 -22
- swift-2.32.0.dist-info/pbr.json +0 -1
- {swift-2.32.0.dist-info → swift-2.34.0.dist-info}/LICENSE +0 -0
- {swift-2.32.0.dist-info → swift-2.34.0.dist-info}/WHEEL +0 -0
- {swift-2.32.0.dist-info → swift-2.34.0.dist-info}/top_level.txt +0 -0
swift/container/server.py
CHANGED
@@ -15,6 +15,7 @@
|
|
15
15
|
|
16
16
|
import json
|
17
17
|
import os
|
18
|
+
import sys
|
18
19
|
import time
|
19
20
|
import traceback
|
20
21
|
|
@@ -38,7 +39,7 @@ from swift.common.utils import get_logger, hash_path, public, \
|
|
38
39
|
config_true_value, timing_stats, replication, \
|
39
40
|
override_bytes_from_content_type, get_log_line, \
|
40
41
|
config_fallocate_value, fs_has_free_space, list_from_csv, \
|
41
|
-
ShardRange
|
42
|
+
ShardRange, parse_options
|
42
43
|
from swift.common.constraints import valid_timestamp, check_utf8, \
|
43
44
|
check_drive, AUTO_CREATE_ACCOUNT_PREFIX
|
44
45
|
from swift.common.bufferedhttp import http_connect
|
@@ -53,6 +54,7 @@ from swift.common.swob import HTTPAccepted, HTTPBadRequest, HTTPConflict, \
|
|
53
54
|
HTTPPreconditionFailed, HTTPMethodNotAllowed, Request, Response, \
|
54
55
|
HTTPInsufficientStorage, HTTPException, HTTPMovedPermanently, \
|
55
56
|
wsgi_to_str, str_to_wsgi
|
57
|
+
from swift.common.wsgi import run_wsgi
|
56
58
|
|
57
59
|
|
58
60
|
def gen_resp_headers(info, is_deleted=False):
|
@@ -141,17 +143,7 @@ class ContainerController(BaseStorageServer):
|
|
141
143
|
self.replicator_rpc = ContainerReplicatorRpc(
|
142
144
|
self.root, DATADIR, ContainerBroker, self.mount_check,
|
143
145
|
logger=self.logger)
|
144
|
-
|
145
|
-
self.logger.warning('Option auto_create_account_prefix is '
|
146
|
-
'deprecated. Configure '
|
147
|
-
'auto_create_account_prefix under the '
|
148
|
-
'swift-constraints section of '
|
149
|
-
'swift.conf. This option will '
|
150
|
-
'be ignored in a future release.')
|
151
|
-
self.auto_create_account_prefix = \
|
152
|
-
conf['auto_create_account_prefix']
|
153
|
-
else:
|
154
|
-
self.auto_create_account_prefix = AUTO_CREATE_ACCOUNT_PREFIX
|
146
|
+
self.auto_create_account_prefix = AUTO_CREATE_ACCOUNT_PREFIX
|
155
147
|
self.shards_account_prefix = (
|
156
148
|
self.auto_create_account_prefix + 'shards_')
|
157
149
|
if config_true_value(conf.get('allow_versions', 'f')):
|
@@ -511,59 +503,42 @@ class ContainerController(BaseStorageServer):
|
|
511
503
|
return HTTPInsufficientStorage(drive=drive, request=req)
|
512
504
|
if not self.check_free_space(drive):
|
513
505
|
return HTTPInsufficientStorage(drive=drive, request=req)
|
514
|
-
requested_policy_index = self.get_and_validate_policy_index(req)
|
515
|
-
broker = self._get_container_broker(drive, part, account, container)
|
516
|
-
if obj: # put container object
|
517
|
-
# obj put expects the policy_index header, default is for
|
518
|
-
# legacy support during upgrade.
|
519
|
-
obj_policy_index = requested_policy_index or 0
|
520
|
-
self._maybe_autocreate(
|
521
|
-
broker, req_timestamp, account, obj_policy_index, req)
|
522
|
-
# redirect if a shard exists for this object name
|
523
|
-
response = self._redirect_to_shard(req, broker, obj)
|
524
|
-
if response:
|
525
|
-
return response
|
526
|
-
|
527
|
-
broker.put_object(obj, req_timestamp.internal,
|
528
|
-
int(req.headers['x-size']),
|
529
|
-
wsgi_to_str(req.headers['x-content-type']),
|
530
|
-
wsgi_to_str(req.headers['x-etag']), 0,
|
531
|
-
obj_policy_index,
|
532
|
-
wsgi_to_str(req.headers.get(
|
533
|
-
'x-content-type-timestamp')),
|
534
|
-
wsgi_to_str(req.headers.get('x-meta-timestamp')))
|
535
|
-
return HTTPCreated(request=req)
|
536
506
|
|
507
|
+
broker = self._get_container_broker(drive, part, account, container)
|
508
|
+
if obj:
|
509
|
+
return self.PUT_object(req, broker, account, obj, req_timestamp)
|
537
510
|
record_type = req.headers.get('x-backend-record-type', '').lower()
|
538
511
|
if record_type == RECORD_TYPE_SHARD:
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
512
|
+
return self.PUT_shard(req, broker, account, req_timestamp)
|
513
|
+
else:
|
514
|
+
return self.PUT_container(req, broker, account,
|
515
|
+
container, req_timestamp)
|
516
|
+
|
517
|
+
@timing_stats()
|
518
|
+
def PUT_object(self, req, broker, account, obj, req_timestamp):
|
519
|
+
"""Put object into container."""
|
520
|
+
# obj put expects the policy_index header, default is for
|
521
|
+
# legacy support during upgrade.
|
522
|
+
requested_policy_index = self.get_and_validate_policy_index(req)
|
523
|
+
obj_policy_index = requested_policy_index or 0
|
524
|
+
self._maybe_autocreate(
|
525
|
+
broker, req_timestamp, account, obj_policy_index, req)
|
526
|
+
# redirect if a shard exists for this object name
|
527
|
+
response = self._redirect_to_shard(req, broker, obj)
|
528
|
+
if response:
|
529
|
+
return response
|
530
|
+
|
531
|
+
broker.put_object(obj, req_timestamp.internal,
|
532
|
+
int(req.headers['x-size']),
|
533
|
+
wsgi_to_str(req.headers['x-content-type']),
|
534
|
+
wsgi_to_str(req.headers['x-etag']), 0,
|
535
|
+
obj_policy_index,
|
536
|
+
wsgi_to_str(req.headers.get(
|
537
|
+
'x-content-type-timestamp')),
|
538
|
+
wsgi_to_str(req.headers.get('x-meta-timestamp')))
|
539
|
+
return HTTPCreated(request=req)
|
540
|
+
|
541
|
+
def _create_ok_resp(self, req, broker, created):
|
567
542
|
if created:
|
568
543
|
return HTTPCreated(request=req,
|
569
544
|
headers={'x-backend-storage-policy-index':
|
@@ -573,6 +548,45 @@ class ContainerController(BaseStorageServer):
|
|
573
548
|
headers={'x-backend-storage-policy-index':
|
574
549
|
broker.storage_policy_index})
|
575
550
|
|
551
|
+
@timing_stats()
|
552
|
+
def PUT_shard(self, req, broker, account, req_timestamp):
|
553
|
+
"""Put shards into container."""
|
554
|
+
requested_policy_index = self.get_and_validate_policy_index(req)
|
555
|
+
try:
|
556
|
+
# validate incoming data...
|
557
|
+
shard_ranges = [ShardRange.from_dict(sr)
|
558
|
+
for sr in json.loads(req.body)]
|
559
|
+
except (ValueError, KeyError, TypeError) as err:
|
560
|
+
return HTTPBadRequest('Invalid body: %r' % err)
|
561
|
+
created = self._maybe_autocreate(
|
562
|
+
broker, req_timestamp, account, requested_policy_index, req)
|
563
|
+
self._update_metadata(req, broker, req_timestamp, 'PUT')
|
564
|
+
if shard_ranges:
|
565
|
+
# TODO: consider writing the shard ranges into the pending
|
566
|
+
# file, but if so ensure an all-or-none semantic for the write
|
567
|
+
broker.merge_shard_ranges(shard_ranges)
|
568
|
+
return self._create_ok_resp(req, broker, created)
|
569
|
+
|
570
|
+
@timing_stats()
|
571
|
+
def PUT_container(self, req, broker, account, container, req_timestamp):
|
572
|
+
"""Update or create container."""
|
573
|
+
requested_policy_index = self.get_and_validate_policy_index(req)
|
574
|
+
if requested_policy_index is None:
|
575
|
+
# use the default index sent by the proxy if available
|
576
|
+
new_container_policy = req.headers.get(
|
577
|
+
'X-Backend-Storage-Policy-Default', int(POLICIES.default))
|
578
|
+
else:
|
579
|
+
new_container_policy = requested_policy_index
|
580
|
+
created = self._update_or_create(req, broker,
|
581
|
+
req_timestamp.internal,
|
582
|
+
new_container_policy,
|
583
|
+
requested_policy_index)
|
584
|
+
self._update_metadata(req, broker, req_timestamp, 'PUT')
|
585
|
+
resp = self.account_update(req, account, container, broker)
|
586
|
+
if resp:
|
587
|
+
return resp
|
588
|
+
return self._create_ok_resp(req, broker, created)
|
589
|
+
|
576
590
|
@public
|
577
591
|
@timing_stats(sample_rate=0.1)
|
578
592
|
def HEAD(self, req):
|
@@ -600,29 +614,42 @@ class ContainerController(BaseStorageServer):
|
|
600
614
|
resp.last_modified = Timestamp(headers['X-PUT-Timestamp']).ceil()
|
601
615
|
return resp
|
602
616
|
|
603
|
-
def
|
617
|
+
def update_shard_record(self, record, shard_record_full=True):
|
618
|
+
"""
|
619
|
+
Return the shard_range database record as a dict, the keys will depend
|
620
|
+
on the database fields provided in the record.
|
621
|
+
|
622
|
+
:param record: shard entry record, either ShardRange or Namespace.
|
623
|
+
:param shard_record_full: boolean, when true the timestamp field is
|
624
|
+
added as "last_modified" in iso format.
|
625
|
+
:returns: dict suitable for listing responses
|
604
626
|
"""
|
605
|
-
|
606
|
-
|
627
|
+
response = dict(record)
|
628
|
+
if shard_record_full:
|
629
|
+
created = record.timestamp
|
630
|
+
response['last_modified'] = Timestamp(created).isoformat
|
631
|
+
return response
|
632
|
+
|
633
|
+
def update_object_record(self, record):
|
634
|
+
"""
|
635
|
+
Perform mutation to container listing records that are common to all
|
636
|
+
serialization formats, and returns it as a dict.
|
607
637
|
|
608
638
|
Converts created time to iso timestamp.
|
609
639
|
Replaces size with 'swift_bytes' content type parameter.
|
610
640
|
|
611
|
-
:
|
641
|
+
:param record: object entry record
|
612
642
|
:returns: modified record
|
613
643
|
"""
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
'bytes': size, 'hash': etag, 'name': name_,
|
624
|
-
'content_type': content_type}
|
625
|
-
override_bytes_from_content_type(response, logger=self.logger)
|
644
|
+
# record is object info
|
645
|
+
(name, created, size, content_type, etag) = record[:5]
|
646
|
+
name_ = name.decode('utf8') if six.PY2 else name
|
647
|
+
if content_type is None:
|
648
|
+
return {'subdir': name_}
|
649
|
+
response = {
|
650
|
+
'bytes': size, 'hash': etag, 'name': name_,
|
651
|
+
'content_type': content_type}
|
652
|
+
override_bytes_from_content_type(response, logger=self.logger)
|
626
653
|
response['last_modified'] = Timestamp(created).isoformat
|
627
654
|
return response
|
628
655
|
|
@@ -685,11 +712,11 @@ class ContainerController(BaseStorageServer):
|
|
685
712
|
either the string or integer representation of
|
686
713
|
:data:`~swift.common.utils.ShardRange.STATES`.
|
687
714
|
|
688
|
-
|
689
|
-
``listing`` will cause the listing to include all shard ranges
|
690
|
-
state suitable for contributing to an object listing
|
691
|
-
will cause the listing to include all shard ranges
|
692
|
-
suitable to accept an object update.
|
715
|
+
Alias values may be used in a ``states`` parameter value. The
|
716
|
+
``listing`` alias will cause the listing to include all shard ranges
|
717
|
+
in a state suitable for contributing to an object listing. The
|
718
|
+
``updating`` alias will cause the listing to include all shard ranges
|
719
|
+
in a state suitable to accept an object update.
|
693
720
|
|
694
721
|
If either of these aliases is used then the shard range listing will
|
695
722
|
if necessary be extended with a synthesised 'filler' range in order
|
@@ -698,6 +725,23 @@ class ContainerController(BaseStorageServer):
|
|
698
725
|
uncovered tail of the requested name range and will point back to the
|
699
726
|
same container.
|
700
727
|
|
728
|
+
The ``auditing`` alias will cause the listing to include all shard
|
729
|
+
ranges in a state useful to the sharder while auditing a shard
|
730
|
+
container. This alias will not cause a 'filler' range to be added,
|
731
|
+
but will cause the container's own shard range to be included in the
|
732
|
+
listing. For now, ``auditing`` is only supported when
|
733
|
+
'X-Backend-Record-Shard-Format' is 'full'.
|
734
|
+
|
735
|
+
* Shard range listings can be simplified to include only Namespace
|
736
|
+
only attributes (name, lower and upper) if the caller send the header
|
737
|
+
``X-Backend-Record-Shard-Format`` with value 'namespace' as a hint
|
738
|
+
that it would prefer namespaces. If this header doesn't exist or the
|
739
|
+
value is 'full', the listings will default to include all attributes
|
740
|
+
of shard ranges. But if params has includes/marker/end_marker then
|
741
|
+
the response will be full shard ranges, regardless the header of
|
742
|
+
``X-Backend-Record-Shard-Format``. The response header
|
743
|
+
``X-Backend-Record-Type`` will tell the user what type it gets back.
|
744
|
+
|
701
745
|
* Listings are not normally returned from a deleted container. However,
|
702
746
|
the ``X-Backend-Override-Deleted`` header may be used with a value in
|
703
747
|
:attr:`swift.common.utils.TRUE_VALUES` to force a shard range
|
@@ -709,13 +753,6 @@ class ContainerController(BaseStorageServer):
|
|
709
753
|
"""
|
710
754
|
drive, part, account, container, obj = get_obj_name_and_placement(req)
|
711
755
|
params = validate_container_params(req)
|
712
|
-
path = params.get('path')
|
713
|
-
prefix = params.get('prefix')
|
714
|
-
delimiter = params.get('delimiter')
|
715
|
-
marker = params.get('marker', '')
|
716
|
-
end_marker = params.get('end_marker')
|
717
|
-
limit = params['limit']
|
718
|
-
reverse = config_true_value(params.get('reverse'))
|
719
756
|
out_content_type = listing_formats.get_listing_content_type(req)
|
720
757
|
try:
|
721
758
|
check_drive(self.root, drive, self.mount_check)
|
@@ -730,70 +767,154 @@ class ContainerController(BaseStorageServer):
|
|
730
767
|
if record_type == 'auto' and db_state in (SHARDING, SHARDED):
|
731
768
|
record_type = 'shard'
|
732
769
|
if record_type == 'shard':
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
770
|
+
return self.GET_shard(req, broker, container, params, info,
|
771
|
+
is_deleted, out_content_type)
|
772
|
+
else:
|
773
|
+
return self.GET_object(req, broker, container, params, info,
|
774
|
+
is_deleted, out_content_type)
|
775
|
+
|
776
|
+
@timing_stats()
|
777
|
+
def GET_shard(self, req, broker, container, params, info,
|
778
|
+
is_deleted, out_content_type):
|
779
|
+
"""
|
780
|
+
Returns a list of persisted shard ranges or namespaces in response.
|
781
|
+
|
782
|
+
:param req: swob.Request object
|
783
|
+
:param broker: container DB broker object
|
784
|
+
:param container: container name
|
785
|
+
:param params: the request params.
|
786
|
+
:param info: the global info for the container
|
787
|
+
:param is_deleted: the is_deleted status for the container.
|
788
|
+
:param out_content_type: content type as a string.
|
789
|
+
:returns: an instance of :class:`swift.common.swob.Response`
|
790
|
+
"""
|
791
|
+
override_deleted = info and config_true_value(
|
792
|
+
req.headers.get('x-backend-override-deleted', False))
|
793
|
+
resp_headers = gen_resp_headers(
|
794
|
+
info, is_deleted=is_deleted and not override_deleted)
|
795
|
+
|
796
|
+
if is_deleted and not override_deleted:
|
797
|
+
return HTTPNotFound(request=req, headers=resp_headers)
|
798
|
+
|
799
|
+
marker = params.get('marker', '')
|
800
|
+
end_marker = params.get('end_marker')
|
801
|
+
reverse = config_true_value(params.get('reverse'))
|
802
|
+
states = params.get('states')
|
803
|
+
includes = params.get('includes')
|
804
|
+
include_deleted = config_true_value(
|
805
|
+
req.headers.get('x-backend-include-deleted', False))
|
806
|
+
|
807
|
+
resp_headers['X-Backend-Record-Type'] = 'shard'
|
808
|
+
override_filter_hdr = req.headers.get(
|
809
|
+
'x-backend-override-shard-name-filter', '').lower()
|
810
|
+
if override_filter_hdr == info.get('db_state') == 'sharded':
|
811
|
+
# respect the request to send back *all* ranges if the db is in
|
812
|
+
# sharded state
|
813
|
+
resp_headers['X-Backend-Override-Shard-Name-Filter'] = 'true'
|
814
|
+
marker = end_marker = includes = None
|
815
|
+
reverse = False
|
816
|
+
fill_gaps = include_own = False
|
817
|
+
if states:
|
818
|
+
states = list_from_csv(states)
|
819
|
+
fill_gaps = any(('listing' in states, 'updating' in states))
|
820
|
+
# The 'auditing' state alias is used by the sharder during
|
821
|
+
# shard audit; if the shard is shrinking then it needs to get
|
822
|
+
# acceptor shard ranges, which may be the root container
|
823
|
+
# itself, so use include_own.
|
824
|
+
include_own = 'auditing' in states
|
825
|
+
try:
|
826
|
+
states = broker.resolve_shard_range_states(states)
|
827
|
+
except ValueError:
|
828
|
+
return HTTPBadRequest(request=req, body='Bad state')
|
829
|
+
|
830
|
+
# For record type of 'shard', user can specify an additional header
|
831
|
+
# to ask for list of Namespaces instead of full ShardRanges.
|
832
|
+
# This will allow proxy server who is going to retrieve Namespace
|
833
|
+
# to talk to older version of container servers who don't support
|
834
|
+
# Namespace yet during upgrade.
|
835
|
+
shard_format = req.headers.get(
|
836
|
+
'x-backend-record-shard-format', 'full').lower()
|
837
|
+
if shard_format == 'namespace':
|
838
|
+
resp_headers['X-Backend-Record-Shard-Format'] = 'namespace'
|
839
|
+
# Namespace GET does not support all the options of Shard Range
|
840
|
+
# GET: 'x-backend-include-deleted' cannot be supported because
|
841
|
+
# there is no way for a Namespace to indicate the deleted state;
|
842
|
+
# the 'auditing' state query parameter is not supported because it
|
843
|
+
# is specific to the sharder which only requests full shard ranges.
|
844
|
+
if include_deleted:
|
845
|
+
return HTTPBadRequest(
|
846
|
+
request=req, body='No include_deleted for namespace GET')
|
847
|
+
if include_own:
|
848
|
+
return HTTPBadRequest(
|
849
|
+
request=req, body='No auditing state for namespace GET')
|
850
|
+
shard_format_full = False
|
851
|
+
container_list = broker.get_namespaces(
|
852
|
+
marker, end_marker, includes, reverse, states, fill_gaps)
|
853
|
+
else:
|
854
|
+
resp_headers['X-Backend-Record-Shard-Format'] = 'full'
|
855
|
+
shard_format_full = True
|
764
856
|
container_list = broker.get_shard_ranges(
|
765
857
|
marker, end_marker, includes, reverse, states=states,
|
766
858
|
include_deleted=include_deleted, fill_gaps=fill_gaps,
|
767
859
|
include_own=include_own)
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
860
|
+
listing = [self.update_shard_record(record, shard_format_full)
|
861
|
+
for record in container_list]
|
862
|
+
return self._create_GET_response(req, out_content_type, info,
|
863
|
+
resp_headers, broker.metadata,
|
864
|
+
container, listing)
|
865
|
+
|
866
|
+
@timing_stats()
|
867
|
+
def GET_object(self, req, broker, container, params, info,
|
868
|
+
is_deleted, out_content_type):
|
869
|
+
"""
|
870
|
+
Returns a list of objects in response.
|
871
|
+
|
872
|
+
:param req: swob.Request object
|
873
|
+
:param broker: container DB broker object
|
874
|
+
:param container: container name
|
875
|
+
:param params: the request params.
|
876
|
+
:param info: the global info for the container
|
877
|
+
:param is_deleted: the is_deleted status for the container.
|
878
|
+
:param out_content_type: content type as a string.
|
879
|
+
:returns: an instance of :class:`swift.common.swob.Response`
|
880
|
+
"""
|
881
|
+
marker = params.get('marker', '')
|
882
|
+
end_marker = params.get('end_marker')
|
883
|
+
reverse = config_true_value(params.get('reverse'))
|
884
|
+
path = params.get('path')
|
885
|
+
prefix = params.get('prefix')
|
886
|
+
delimiter = params.get('delimiter')
|
887
|
+
limit = params['limit']
|
888
|
+
requested_policy_index = self.get_and_validate_policy_index(req)
|
889
|
+
resp_headers = gen_resp_headers(info, is_deleted=is_deleted)
|
890
|
+
if is_deleted:
|
891
|
+
return HTTPNotFound(request=req, headers=resp_headers)
|
892
|
+
resp_headers['X-Backend-Record-Type'] = 'object'
|
893
|
+
storage_policy_index = (
|
894
|
+
requested_policy_index if requested_policy_index is not None
|
895
|
+
else info['storage_policy_index'])
|
896
|
+
resp_headers['X-Backend-Record-Storage-Policy-Index'] = \
|
897
|
+
storage_policy_index
|
898
|
+
# Use the retired db while container is in process of sharding,
|
899
|
+
# otherwise use current db
|
900
|
+
src_broker = broker.get_brokers()[0]
|
901
|
+
container_list = src_broker.list_objects_iter(
|
902
|
+
limit, marker, end_marker, prefix, delimiter, path,
|
903
|
+
storage_policy_index=storage_policy_index,
|
904
|
+
reverse=reverse, allow_reserved=req.allow_reserved_names)
|
905
|
+
listing = [self.update_object_record(record)
|
906
|
+
for record in container_list]
|
907
|
+
return self._create_GET_response(req, out_content_type, info,
|
908
|
+
resp_headers, broker.metadata,
|
909
|
+
container, listing)
|
910
|
+
|
911
|
+
def _create_GET_response(self, req, out_content_type, info, resp_headers,
|
912
|
+
metadata, container, listing):
|
791
913
|
for key, (value, _timestamp) in metadata.items():
|
792
914
|
if value and (key.lower() in self.save_headers or
|
793
915
|
is_sys_or_user_meta('container', key)):
|
794
916
|
resp_headers[str_to_wsgi(key)] = str_to_wsgi(value)
|
795
|
-
|
796
|
-
for record in container_list]
|
917
|
+
|
797
918
|
if out_content_type.endswith('/xml'):
|
798
919
|
body = listing_formats.container_to_xml(listing, container)
|
799
920
|
elif out_content_type.endswith('/json'):
|
@@ -929,3 +1050,12 @@ def app_factory(global_conf, **local_conf):
|
|
929
1050
|
conf = global_conf.copy()
|
930
1051
|
conf.update(local_conf)
|
931
1052
|
return ContainerController(conf)
|
1053
|
+
|
1054
|
+
|
1055
|
+
def main():
|
1056
|
+
conf_file, options = parse_options(test_config=True)
|
1057
|
+
sys.exit(run_wsgi(conf_file, 'container-server', **options))
|
1058
|
+
|
1059
|
+
|
1060
|
+
if __name__ == '__main__':
|
1061
|
+
main()
|