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