swift 2.23.3__py3-none-any.whl → 2.35.0__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 (206) hide show
  1. swift/__init__.py +29 -50
  2. swift/account/auditor.py +21 -118
  3. swift/account/backend.py +33 -28
  4. swift/account/reaper.py +37 -28
  5. swift/account/replicator.py +22 -0
  6. swift/account/server.py +60 -26
  7. swift/account/utils.py +28 -11
  8. swift-2.23.3.data/scripts/swift-account-audit → swift/cli/account_audit.py +23 -13
  9. swift-2.23.3.data/scripts/swift-config → swift/cli/config.py +2 -2
  10. swift/cli/container_deleter.py +5 -11
  11. swift-2.23.3.data/scripts/swift-dispersion-populate → swift/cli/dispersion_populate.py +8 -7
  12. swift/cli/dispersion_report.py +10 -9
  13. swift-2.23.3.data/scripts/swift-drive-audit → swift/cli/drive_audit.py +63 -21
  14. swift/cli/form_signature.py +3 -7
  15. swift-2.23.3.data/scripts/swift-get-nodes → swift/cli/get_nodes.py +8 -2
  16. swift/cli/info.py +154 -14
  17. swift/cli/manage_shard_ranges.py +705 -37
  18. swift-2.23.3.data/scripts/swift-oldies → swift/cli/oldies.py +25 -14
  19. swift-2.23.3.data/scripts/swift-orphans → swift/cli/orphans.py +7 -3
  20. swift/cli/recon.py +196 -67
  21. swift-2.23.3.data/scripts/swift-recon-cron → swift/cli/recon_cron.py +17 -20
  22. swift-2.23.3.data/scripts/swift-reconciler-enqueue → swift/cli/reconciler_enqueue.py +2 -3
  23. swift/cli/relinker.py +807 -126
  24. swift/cli/reload.py +135 -0
  25. swift/cli/ringbuilder.py +217 -20
  26. swift/cli/ringcomposer.py +0 -1
  27. swift/cli/shard-info.py +4 -3
  28. swift/common/base_storage_server.py +9 -20
  29. swift/common/bufferedhttp.py +48 -74
  30. swift/common/constraints.py +20 -15
  31. swift/common/container_sync_realms.py +9 -11
  32. swift/common/daemon.py +25 -8
  33. swift/common/db.py +195 -128
  34. swift/common/db_auditor.py +168 -0
  35. swift/common/db_replicator.py +95 -55
  36. swift/common/digest.py +141 -0
  37. swift/common/direct_client.py +144 -33
  38. swift/common/error_limiter.py +93 -0
  39. swift/common/exceptions.py +25 -1
  40. swift/common/header_key_dict.py +2 -9
  41. swift/common/http_protocol.py +373 -0
  42. swift/common/internal_client.py +129 -59
  43. swift/common/linkat.py +3 -4
  44. swift/common/manager.py +284 -67
  45. swift/common/memcached.py +390 -145
  46. swift/common/middleware/__init__.py +4 -0
  47. swift/common/middleware/account_quotas.py +211 -46
  48. swift/common/middleware/acl.py +3 -8
  49. swift/common/middleware/backend_ratelimit.py +230 -0
  50. swift/common/middleware/bulk.py +22 -34
  51. swift/common/middleware/catch_errors.py +1 -3
  52. swift/common/middleware/cname_lookup.py +6 -11
  53. swift/common/middleware/container_quotas.py +1 -1
  54. swift/common/middleware/container_sync.py +39 -17
  55. swift/common/middleware/copy.py +12 -0
  56. swift/common/middleware/crossdomain.py +22 -9
  57. swift/common/middleware/crypto/__init__.py +2 -1
  58. swift/common/middleware/crypto/crypto_utils.py +11 -15
  59. swift/common/middleware/crypto/decrypter.py +28 -11
  60. swift/common/middleware/crypto/encrypter.py +12 -17
  61. swift/common/middleware/crypto/keymaster.py +8 -15
  62. swift/common/middleware/crypto/kms_keymaster.py +2 -1
  63. swift/common/middleware/dlo.py +15 -11
  64. swift/common/middleware/domain_remap.py +5 -4
  65. swift/common/middleware/etag_quoter.py +128 -0
  66. swift/common/middleware/formpost.py +73 -70
  67. swift/common/middleware/gatekeeper.py +8 -1
  68. swift/common/middleware/keystoneauth.py +33 -3
  69. swift/common/middleware/list_endpoints.py +4 -4
  70. swift/common/middleware/listing_formats.py +85 -49
  71. swift/common/middleware/memcache.py +4 -95
  72. swift/common/middleware/name_check.py +3 -2
  73. swift/common/middleware/proxy_logging.py +160 -92
  74. swift/common/middleware/ratelimit.py +17 -10
  75. swift/common/middleware/read_only.py +6 -4
  76. swift/common/middleware/recon.py +59 -22
  77. swift/common/middleware/s3api/acl_handlers.py +25 -3
  78. swift/common/middleware/s3api/acl_utils.py +6 -1
  79. swift/common/middleware/s3api/controllers/__init__.py +6 -0
  80. swift/common/middleware/s3api/controllers/acl.py +3 -2
  81. swift/common/middleware/s3api/controllers/bucket.py +242 -137
  82. swift/common/middleware/s3api/controllers/logging.py +2 -2
  83. swift/common/middleware/s3api/controllers/multi_delete.py +43 -20
  84. swift/common/middleware/s3api/controllers/multi_upload.py +219 -133
  85. swift/common/middleware/s3api/controllers/obj.py +112 -8
  86. swift/common/middleware/s3api/controllers/object_lock.py +44 -0
  87. swift/common/middleware/s3api/controllers/s3_acl.py +2 -2
  88. swift/common/middleware/s3api/controllers/tagging.py +57 -0
  89. swift/common/middleware/s3api/controllers/versioning.py +36 -7
  90. swift/common/middleware/s3api/etree.py +22 -9
  91. swift/common/middleware/s3api/exception.py +0 -4
  92. swift/common/middleware/s3api/s3api.py +113 -41
  93. swift/common/middleware/s3api/s3request.py +384 -218
  94. swift/common/middleware/s3api/s3response.py +126 -23
  95. swift/common/middleware/s3api/s3token.py +16 -17
  96. swift/common/middleware/s3api/schema/delete.rng +1 -1
  97. swift/common/middleware/s3api/subresource.py +7 -10
  98. swift/common/middleware/s3api/utils.py +27 -10
  99. swift/common/middleware/slo.py +665 -358
  100. swift/common/middleware/staticweb.py +64 -37
  101. swift/common/middleware/symlink.py +51 -18
  102. swift/common/middleware/tempauth.py +76 -58
  103. swift/common/middleware/tempurl.py +191 -173
  104. swift/common/middleware/versioned_writes/__init__.py +51 -0
  105. swift/common/middleware/{versioned_writes.py → versioned_writes/legacy.py} +27 -26
  106. swift/common/middleware/versioned_writes/object_versioning.py +1482 -0
  107. swift/common/middleware/x_profile/exceptions.py +1 -4
  108. swift/common/middleware/x_profile/html_viewer.py +18 -19
  109. swift/common/middleware/x_profile/profile_model.py +1 -2
  110. swift/common/middleware/xprofile.py +10 -10
  111. swift-2.23.3.data/scripts/swift-container-server → swift/common/recon.py +13 -8
  112. swift/common/registry.py +147 -0
  113. swift/common/request_helpers.py +324 -57
  114. swift/common/ring/builder.py +67 -25
  115. swift/common/ring/composite_builder.py +1 -1
  116. swift/common/ring/ring.py +177 -51
  117. swift/common/ring/utils.py +1 -1
  118. swift/common/splice.py +10 -6
  119. swift/common/statsd_client.py +205 -0
  120. swift/common/storage_policy.py +49 -44
  121. swift/common/swob.py +86 -102
  122. swift/common/{utils.py → utils/__init__.py} +2163 -2772
  123. swift/common/utils/base.py +131 -0
  124. swift/common/utils/config.py +433 -0
  125. swift/common/utils/ipaddrs.py +256 -0
  126. swift/common/utils/libc.py +345 -0
  127. swift/common/utils/logs.py +859 -0
  128. swift/common/utils/timestamp.py +412 -0
  129. swift/common/wsgi.py +553 -535
  130. swift/container/auditor.py +14 -100
  131. swift/container/backend.py +490 -231
  132. swift/container/reconciler.py +126 -37
  133. swift/container/replicator.py +96 -22
  134. swift/container/server.py +358 -165
  135. swift/container/sharder.py +1540 -684
  136. swift/container/sync.py +94 -88
  137. swift/container/updater.py +53 -32
  138. swift/obj/auditor.py +153 -35
  139. swift/obj/diskfile.py +466 -217
  140. swift/obj/expirer.py +406 -124
  141. swift/obj/mem_diskfile.py +7 -4
  142. swift/obj/mem_server.py +1 -0
  143. swift/obj/reconstructor.py +523 -262
  144. swift/obj/replicator.py +249 -188
  145. swift/obj/server.py +207 -122
  146. swift/obj/ssync_receiver.py +145 -85
  147. swift/obj/ssync_sender.py +113 -54
  148. swift/obj/updater.py +652 -139
  149. swift/obj/watchers/__init__.py +0 -0
  150. swift/obj/watchers/dark_data.py +213 -0
  151. swift/proxy/controllers/account.py +11 -11
  152. swift/proxy/controllers/base.py +848 -604
  153. swift/proxy/controllers/container.py +433 -92
  154. swift/proxy/controllers/info.py +3 -2
  155. swift/proxy/controllers/obj.py +1000 -489
  156. swift/proxy/server.py +185 -112
  157. {swift-2.23.3.dist-info → swift-2.35.0.dist-info}/AUTHORS +58 -11
  158. {swift-2.23.3.dist-info → swift-2.35.0.dist-info}/METADATA +51 -56
  159. swift-2.35.0.dist-info/RECORD +201 -0
  160. {swift-2.23.3.dist-info → swift-2.35.0.dist-info}/WHEEL +1 -1
  161. {swift-2.23.3.dist-info → swift-2.35.0.dist-info}/entry_points.txt +43 -0
  162. swift-2.35.0.dist-info/pbr.json +1 -0
  163. swift/locale/de/LC_MESSAGES/swift.po +0 -1216
  164. swift/locale/en_GB/LC_MESSAGES/swift.po +0 -1207
  165. swift/locale/es/LC_MESSAGES/swift.po +0 -1085
  166. swift/locale/fr/LC_MESSAGES/swift.po +0 -909
  167. swift/locale/it/LC_MESSAGES/swift.po +0 -894
  168. swift/locale/ja/LC_MESSAGES/swift.po +0 -965
  169. swift/locale/ko_KR/LC_MESSAGES/swift.po +0 -964
  170. swift/locale/pt_BR/LC_MESSAGES/swift.po +0 -881
  171. swift/locale/ru/LC_MESSAGES/swift.po +0 -891
  172. swift/locale/tr_TR/LC_MESSAGES/swift.po +0 -832
  173. swift/locale/zh_CN/LC_MESSAGES/swift.po +0 -833
  174. swift/locale/zh_TW/LC_MESSAGES/swift.po +0 -838
  175. swift-2.23.3.data/scripts/swift-account-auditor +0 -23
  176. swift-2.23.3.data/scripts/swift-account-info +0 -51
  177. swift-2.23.3.data/scripts/swift-account-reaper +0 -23
  178. swift-2.23.3.data/scripts/swift-account-replicator +0 -34
  179. swift-2.23.3.data/scripts/swift-account-server +0 -23
  180. swift-2.23.3.data/scripts/swift-container-auditor +0 -23
  181. swift-2.23.3.data/scripts/swift-container-info +0 -55
  182. swift-2.23.3.data/scripts/swift-container-reconciler +0 -21
  183. swift-2.23.3.data/scripts/swift-container-replicator +0 -34
  184. swift-2.23.3.data/scripts/swift-container-sharder +0 -37
  185. swift-2.23.3.data/scripts/swift-container-sync +0 -23
  186. swift-2.23.3.data/scripts/swift-container-updater +0 -23
  187. swift-2.23.3.data/scripts/swift-dispersion-report +0 -24
  188. swift-2.23.3.data/scripts/swift-form-signature +0 -20
  189. swift-2.23.3.data/scripts/swift-init +0 -119
  190. swift-2.23.3.data/scripts/swift-object-auditor +0 -29
  191. swift-2.23.3.data/scripts/swift-object-expirer +0 -33
  192. swift-2.23.3.data/scripts/swift-object-info +0 -60
  193. swift-2.23.3.data/scripts/swift-object-reconstructor +0 -33
  194. swift-2.23.3.data/scripts/swift-object-relinker +0 -41
  195. swift-2.23.3.data/scripts/swift-object-replicator +0 -37
  196. swift-2.23.3.data/scripts/swift-object-server +0 -27
  197. swift-2.23.3.data/scripts/swift-object-updater +0 -23
  198. swift-2.23.3.data/scripts/swift-proxy-server +0 -23
  199. swift-2.23.3.data/scripts/swift-recon +0 -24
  200. swift-2.23.3.data/scripts/swift-ring-builder +0 -24
  201. swift-2.23.3.data/scripts/swift-ring-builder-analyzer +0 -22
  202. swift-2.23.3.data/scripts/swift-ring-composer +0 -22
  203. swift-2.23.3.dist-info/RECORD +0 -220
  204. swift-2.23.3.dist-info/pbr.json +0 -1
  205. {swift-2.23.3.dist-info → swift-2.35.0.dist-info}/LICENSE +0 -0
  206. {swift-2.23.3.dist-info → swift-2.35.0.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,4 @@
1
- #!python
1
+ #!/usr/bin/env python
2
2
  # Copyright (c) 2010-2012 OpenStack Foundation
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,13 +18,13 @@ import datetime
18
18
  import glob
19
19
  import locale
20
20
  import os
21
+ import os.path
21
22
  import re
22
23
  import subprocess
23
24
  import sys
24
25
 
25
26
 
26
- import six
27
- from six.moves.configparser import ConfigParser
27
+ from configparser import ConfigParser
28
28
 
29
29
  from swift.common.utils import backward, get_logger, dump_recon_cache, \
30
30
  config_true_value
@@ -32,6 +32,27 @@ from swift.common.utils import backward, get_logger, dump_recon_cache, \
32
32
 
33
33
  def get_devices(device_dir, logger):
34
34
  devices = []
35
+ majmin_devices = {}
36
+
37
+ # List /dev/block
38
+ # Using os.scandir on recent versions of python, else os.listdir
39
+ if 'scandir' in dir(os):
40
+ with os.scandir("/dev/block") as it:
41
+ for ent in it:
42
+ if ent.is_symlink():
43
+ dev_name = os.path.basename(os.readlink(ent.path))
44
+ majmin = os.path.basename(ent.path).split(':')
45
+ majmin_devices[dev_name] = {'major': majmin[0],
46
+ 'minor': majmin[1]}
47
+ else:
48
+ for ent in os.listdir("/dev/block"):
49
+ ent_path = os.path.join("/dev/block", ent)
50
+ if os.path.is_symlink(ent_path):
51
+ dev_name = os.path.basename(os.readlink(ent_path))
52
+ majmin = os.path.basename(ent_path).split(':')
53
+ majmin_devices[dev_name] = {'major': majmin[0],
54
+ 'minor': majmin[1]}
55
+
35
56
  for line in open('/proc/mounts').readlines():
36
57
  data = line.strip().split()
37
58
  block_device = data[0]
@@ -40,15 +61,25 @@ def get_devices(device_dir, logger):
40
61
  device = {}
41
62
  device['mount_point'] = mount_point
42
63
  device['block_device'] = block_device
43
- try:
44
- device_num = os.stat(block_device).st_rdev
45
- except OSError:
46
- # If we can't stat the device, then something weird is going on
47
- logger.error("Error: Could not stat %s!" %
48
- block_device)
49
- continue
50
- device['major'] = str(os.major(device_num))
51
- device['minor'] = str(os.minor(device_num))
64
+ dev_name = os.path.basename(block_device)
65
+ if dev_name in majmin_devices:
66
+ # If symlink is in /dev/block
67
+ device['major'] = majmin_devices[dev_name]['major']
68
+ device['minor'] = majmin_devices[dev_name]['minor']
69
+ else:
70
+ # Else we try to stat block_device
71
+ try:
72
+ device_num = os.stat(block_device).st_rdev
73
+ except OSError:
74
+ # If we can't stat the device,
75
+ # then something weird is going on
76
+ logger.error(
77
+ 'Could not determine major:minor numbers for %s '
78
+ '(mounted at %s)! Skipping...',
79
+ block_device, mount_point)
80
+ continue
81
+ device['major'] = str(os.major(device_num))
82
+ device['minor'] = str(os.minor(device_num))
52
83
  devices.append(device)
53
84
  for line in open('/proc/partitions').readlines()[2:]:
54
85
  major, minor, blocks, kernel_device = line.strip().split()
@@ -84,7 +115,7 @@ def get_errors(error_re, log_file_pattern, minutes, logger,
84
115
  # track of the year and month in case the year recently
85
116
  # ticked over
86
117
  year = now_time.year
87
- prev_entry_month = now_time.month
118
+ prev_ent_month = now_time.strftime('%b')
88
119
  errors = {}
89
120
 
90
121
  reached_old_logs = False
@@ -96,8 +127,7 @@ def get_errors(error_re, log_file_pattern, minutes, logger,
96
127
  print("Unable to open " + path)
97
128
  sys.exit(1)
98
129
  for line in backward(f):
99
- if not six.PY2:
100
- line = line.decode(log_file_encoding, 'surrogateescape')
130
+ line = line.decode(log_file_encoding, 'surrogateescape')
101
131
  if '[ 0.000000]' in line \
102
132
  or 'KERNEL supported cpus:' in line \
103
133
  or 'BIOS-provided physical RAM map:' in line:
@@ -106,16 +136,21 @@ def get_errors(error_re, log_file_pattern, minutes, logger,
106
136
  break
107
137
  # Solves the problem with year change - kern.log does not
108
138
  # keep track of the year.
109
- log_time_entry = line.split()[:3]
110
- if log_time_entry[0] == 'Dec' and prev_entry_month == 'Jan':
139
+ log_time_ent = line.split()[:3]
140
+ if log_time_ent[0] == 'Dec' and prev_ent_month == 'Jan':
111
141
  year -= 1
112
- prev_entry_month = log_time_entry[0]
113
- log_time_string = '%d %s' % (year, ' '.join(log_time_entry))
142
+ prev_ent_month = log_time_ent[0]
143
+ log_time_string = '%d %s' % (year, ' '.join(log_time_ent))
114
144
  try:
115
145
  log_time = datetime.datetime.strptime(
116
146
  log_time_string, '%Y %b %d %H:%M:%S')
117
147
  except ValueError:
118
- continue
148
+ # Some versions use ISO timestamps instead
149
+ try:
150
+ log_time = datetime.datetime.strptime(
151
+ line[0:19], '%Y-%m-%dT%H:%M:%S')
152
+ except ValueError:
153
+ continue
119
154
  if log_time > end_time:
120
155
  for err in error_re:
121
156
  for device in err.findall(line):
@@ -142,7 +177,7 @@ def comment_fstab(mount_point):
142
177
  os.rename('/etc/fstab.new', '/etc/fstab')
143
178
 
144
179
 
145
- if __name__ == '__main__':
180
+ def main():
146
181
  c = ConfigParser()
147
182
  try:
148
183
  conf_path = sys.argv[1]
@@ -222,3 +257,10 @@ if __name__ == '__main__':
222
257
 
223
258
  if unmounts == 0:
224
259
  logger.info("No drives were unmounted")
260
+ elif os.path.isdir("/run/systemd/system"):
261
+ logger.debug("fstab updated, calling systemctl daemon-reload")
262
+ subprocess.call(["/usr/bin/systemctl", "daemon-reload"])
263
+
264
+
265
+ if __name__ == '__main__':
266
+ main()
@@ -15,9 +15,7 @@
15
15
  """
16
16
  Script for generating a form signature for use with FormPost middleware.
17
17
  """
18
- from __future__ import print_function
19
18
  import hmac
20
- import six
21
19
  from hashlib import sha1
22
20
  from os.path import basename
23
21
  from time import time
@@ -95,11 +93,9 @@ def main(argv):
95
93
  return 1
96
94
  data = '%s\n%s\n%s\n%s\n%s' % (path, redirect, max_file_size,
97
95
  max_file_count, expires)
98
- if six.PY3:
99
- data = data if isinstance(data, six.binary_type) else \
100
- data.encode('utf8')
101
- key = key if isinstance(key, six.binary_type) else \
102
- key.encode('utf8')
96
+ data = data.encode('utf8')
97
+ key = key if isinstance(key, bytes) else \
98
+ key.encode('utf8')
103
99
  sig = hmac.new(key, data,
104
100
  sha1).hexdigest()
105
101
  print(' Expires:', expires)
@@ -1,4 +1,4 @@
1
- #!python
1
+ #!/usr/bin/env python
2
2
  # Copyright (c) 2010-2012 OpenStack Foundation
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -25,7 +25,7 @@ from swift.cli.info import (parse_get_node_args, print_item_locations,
25
25
  InfoSystemExit)
26
26
 
27
27
 
28
- if __name__ == '__main__':
28
+ def main():
29
29
 
30
30
  usage = '''
31
31
  Shows the nodes responsible for the item specified.
@@ -52,6 +52,8 @@ if __name__ == '__main__':
52
52
  help='Specify which policy to use')
53
53
  parser.add_option('-d', '--swift-dir', default='/etc/swift',
54
54
  dest='swift_dir', help='Path to swift directory')
55
+ parser.add_option('-Q', '--quoted', action='store_true',
56
+ help='Assume swift paths are quoted')
55
57
  options, args = parser.parse_args()
56
58
 
57
59
  if set_swift_dir(options.swift_dir):
@@ -72,3 +74,7 @@ if __name__ == '__main__':
72
74
  print_item_locations(ring, ring_name, *args, **vars(options))
73
75
  except InfoSystemExit:
74
76
  sys.exit(1)
77
+
78
+
79
+ if __name__ == '__main__':
80
+ main()
swift/cli/info.py CHANGED
@@ -10,16 +10,19 @@
10
10
  # License for the specific language governing permissions and limitations
11
11
  # under the License.
12
12
 
13
- from __future__ import print_function
13
+
14
+ import codecs
14
15
  import itertools
15
16
  import json
17
+ from optparse import OptionParser
16
18
  import os
17
19
  import sqlite3
18
- from hashlib import md5
20
+ import sys
19
21
  from collections import defaultdict
20
22
 
21
- from six.moves import urllib
23
+ import urllib
22
24
 
25
+ from swift.common.exceptions import LockTimeout
23
26
  from swift.common.utils import hash_path, storage_directory, \
24
27
  Timestamp, is_valid_ipv6
25
28
  from swift.common.ring import Ring
@@ -30,8 +33,10 @@ from swift.account.backend import AccountBroker, DATADIR as ABDATADIR
30
33
  from swift.container.backend import ContainerBroker, DATADIR as CBDATADIR
31
34
  from swift.obj.diskfile import get_data_dir, read_metadata, DATADIR_BASE, \
32
35
  extract_policy
33
- from swift.common.storage_policy import POLICIES
36
+ from swift.common.storage_policy import POLICIES, reload_storage_policies
37
+ from swift.common.swob import wsgi_to_str
34
38
  from swift.common.middleware.crypto.crypto_utils import load_crypto_meta
39
+ from swift.common.utils import md5, set_swift_dir
35
40
 
36
41
 
37
42
  class InfoSystemExit(Exception):
@@ -58,6 +63,8 @@ def parse_get_node_args(options, args):
58
63
  else:
59
64
  raise InfoSystemExit('Ring file does not exist')
60
65
 
66
+ if options.quoted:
67
+ args = [urllib.parse.unquote(arg) for arg in args]
61
68
  if len(args) == 1:
62
69
  args = args[0].strip('/').split('/', 2)
63
70
 
@@ -96,6 +103,7 @@ def curl_head_command(ip, port, device, part, target, policy_index):
96
103
  if policy_index is not None:
97
104
  cmd += ' -H "%s: %s"' % ('X-Backend-Storage-Policy-Index',
98
105
  policy_index)
106
+ cmd += ' --path-as-is'
99
107
  return cmd
100
108
 
101
109
 
@@ -194,6 +202,28 @@ def print_ring_locations(ring, datadir, account, container=None, obj=None,
194
202
  'real value is set in the config file on each storage node.')
195
203
 
196
204
 
205
+ def get_max_len_sync_item(syncs, item, title):
206
+ def map_func(element):
207
+ return str(element[item])
208
+ return max(list(map(len, map(map_func, syncs))) + [len(title)])
209
+
210
+
211
+ def print_db_syncs(incoming, syncs):
212
+ max_sync_point_len = get_max_len_sync_item(syncs, 'sync_point',
213
+ "Sync Point")
214
+ max_remote_len = get_max_len_sync_item(syncs, 'remote_id', "Remote ID")
215
+ print('%s Syncs:' % ('Incoming' if incoming else 'Outgoing'))
216
+ print(' %s\t%s\t%s' % ("Sync Point".ljust(max_sync_point_len),
217
+ "Remote ID".ljust(max_remote_len),
218
+ "Updated At"))
219
+ for sync in syncs:
220
+ print(' %s\t%s\t%s (%s)' % (
221
+ str(sync['sync_point']).ljust(max_sync_point_len),
222
+ sync['remote_id'].ljust(max_remote_len),
223
+ Timestamp(sync['updated_at']).isoformat,
224
+ sync['updated_at']))
225
+
226
+
197
227
  def print_db_info_metadata(db_type, info, metadata, drop_prefixes=False,
198
228
  verbose=False):
199
229
  """
@@ -229,6 +259,7 @@ def print_db_info_metadata(db_type, info, metadata, drop_prefixes=False,
229
259
  if db_type == 'container':
230
260
  print(' Container: %s' % container)
231
261
 
262
+ print(' Deleted: %s' % info['is_deleted'])
232
263
  path_hash = hash_path(account, container)
233
264
  if db_type == 'container':
234
265
  print(' Container Hash: %s' % path_hash)
@@ -293,12 +324,16 @@ def print_db_info_metadata(db_type, info, metadata, drop_prefixes=False,
293
324
  title = key.replace('_', '-').title()
294
325
  print(' %s: %s' % (title, value))
295
326
  if sys_metadata:
296
- print(' System Metadata: %s' % sys_metadata)
327
+ print(' System Metadata:')
328
+ for key, value in sys_metadata.items():
329
+ print(' %s: %s' % (key, value))
297
330
  else:
298
331
  print('No system metadata found in db file')
299
332
 
300
333
  if user_metadata:
301
- print(' User Metadata: %s' % user_metadata)
334
+ print(' User Metadata:')
335
+ for key, value in user_metadata.items():
336
+ print(' %s: %s' % (key, value))
302
337
  else:
303
338
  print('No user metadata found in db file')
304
339
 
@@ -430,7 +465,7 @@ def print_obj_metadata(metadata, drop_prefixes=False):
430
465
 
431
466
 
432
467
  def print_info(db_type, db_file, swift_dir='/etc/swift', stale_reads_ok=False,
433
- drop_prefixes=False, verbose=False):
468
+ drop_prefixes=False, verbose=False, sync=False):
434
469
  if db_type not in ('account', 'container'):
435
470
  print("Unrecognized DB type: internal error")
436
471
  raise InfoSystemExit()
@@ -455,6 +490,7 @@ def print_info(db_type, db_file, swift_dir='/etc/swift', stale_reads_ok=False,
455
490
  raise
456
491
  account = info['account']
457
492
  container = None
493
+ info['is_deleted'] = broker.is_deleted()
458
494
  if db_type == 'container':
459
495
  container = info['container']
460
496
  info['is_root'] = broker.is_root_container()
@@ -463,6 +499,11 @@ def print_info(db_type, db_file, swift_dir='/etc/swift', stale_reads_ok=False,
463
499
  info['shard_ranges'] = sranges
464
500
  print_db_info_metadata(
465
501
  db_type, info, broker.metadata, drop_prefixes, verbose)
502
+ if sync:
503
+ # Print incoming / outgoing sync tables.
504
+ for incoming in (True, False):
505
+ print_db_syncs(incoming, broker.get_syncs(incoming,
506
+ include_timestamp=True))
466
507
  try:
467
508
  ring = Ring(swift_dir, ring_name=db_type)
468
509
  except Exception:
@@ -532,6 +573,8 @@ def print_obj(datafile, check_etag=True, swift_dir='/etc/swift',
532
573
  except EOFError:
533
574
  print("Invalid metadata")
534
575
  raise InfoSystemExit()
576
+ metadata = {wsgi_to_str(k): v if k == 'name' else wsgi_to_str(v)
577
+ for k, v in metadata.items()}
535
578
 
536
579
  etag = metadata.pop('ETag', '')
537
580
  length = metadata.pop('Content-Length', '')
@@ -541,7 +584,7 @@ def print_obj(datafile, check_etag=True, swift_dir='/etc/swift',
541
584
  # Optional integrity check; it's useful, but slow.
542
585
  file_len = None
543
586
  if check_etag:
544
- h = md5()
587
+ h = md5(usedforsecurity=False)
545
588
  file_len = 0
546
589
  while True:
547
590
  data = fp.read(64 * 1024)
@@ -626,15 +669,15 @@ def print_item_locations(ring, ring_name=None, account=None, container=None,
626
669
  ring = POLICIES.get_object_ring(policy_index, swift_dir)
627
670
  ring_name = (POLICIES.get_by_name(policy_name)).ring_name
628
671
 
629
- if account is None and (container is not None or obj is not None):
672
+ if (container or obj) and not account:
630
673
  print('No account specified')
631
674
  raise InfoSystemExit()
632
675
 
633
- if container is None and obj is not None:
676
+ if obj and not container:
634
677
  print('No container specified')
635
678
  raise InfoSystemExit()
636
679
 
637
- if account is None and part is None:
680
+ if not account and not part:
638
681
  print('No target specified')
639
682
  raise InfoSystemExit()
640
683
 
@@ -666,8 +709,105 @@ def print_item_locations(ring, ring_name=None, account=None, container=None,
666
709
  print('Warning: account specified ' +
667
710
  'but ring not named "account"')
668
711
 
669
- print('\nAccount \t%s' % account)
670
- print('Container\t%s' % container)
671
- print('Object \t%s\n\n' % obj)
712
+ if account:
713
+ print('\nAccount \t%s' % urllib.parse.quote(account))
714
+ if container:
715
+ print('Container\t%s' % urllib.parse.quote(container))
716
+ if obj:
717
+ print('Object \t%s\n\n' % urllib.parse.quote(obj))
672
718
  print_ring_locations(ring, loc, account, container, obj, part, all_nodes,
673
719
  policy_index=policy_index)
720
+
721
+
722
+ def obj_main():
723
+ # Make stdout able to write escaped bytes
724
+ sys.stdout = codecs.getwriter("utf-8")(
725
+ sys.stdout.detach(), errors='surrogateescape')
726
+
727
+ parser = OptionParser('%prog [options] OBJECT_FILE')
728
+ parser.add_option(
729
+ '-n', '--no-check-etag', default=True,
730
+ action="store_false", dest="check_etag",
731
+ help="Don't verify file contents against stored etag")
732
+ parser.add_option(
733
+ '-d', '--swift-dir', default='/etc/swift', dest='swift_dir',
734
+ help="Pass location of swift directory")
735
+ parser.add_option(
736
+ '--drop-prefixes', default=False, action="store_true",
737
+ help="When outputting metadata, drop the per-section common prefixes")
738
+ parser.add_option(
739
+ '-P', '--policy-name', dest='policy_name',
740
+ help="Specify storage policy name")
741
+
742
+ options, args = parser.parse_args()
743
+
744
+ if len(args) != 1:
745
+ sys.exit(parser.print_help())
746
+
747
+ if set_swift_dir(options.swift_dir):
748
+ reload_storage_policies()
749
+
750
+ try:
751
+ print_obj(*args, **vars(options))
752
+ except InfoSystemExit:
753
+ sys.exit(1)
754
+
755
+
756
+ def run_print_info(db_type, args, opts):
757
+ try:
758
+ print_info(db_type, *args, **opts)
759
+ except InfoSystemExit:
760
+ sys.exit(1)
761
+ except (sqlite3.OperationalError, LockTimeout) as e:
762
+ if not opts.get('stale_reads_ok'):
763
+ opts['stale_reads_ok'] = True
764
+ print('Warning: Possibly Stale Data')
765
+ run_print_info(db_type, args, opts)
766
+ sys.exit(2)
767
+ else:
768
+ print('%s info failed: %s' % (db_type.title(), e))
769
+ sys.exit(1)
770
+
771
+
772
+ def container_main():
773
+ parser = OptionParser('%prog [options] CONTAINER_DB_FILE')
774
+ parser.add_option(
775
+ '-d', '--swift-dir', default='/etc/swift',
776
+ help="Pass location of swift directory")
777
+ parser.add_option(
778
+ '--drop-prefixes', default=False, action="store_true",
779
+ help="When outputting metadata, drop the per-section common prefixes")
780
+ parser.add_option(
781
+ '-v', '--verbose', default=False, action="store_true",
782
+ help="Show all shard ranges. By default, only the number of shard "
783
+ "ranges is displayed if there are many shards.")
784
+ parser.add_option(
785
+ '--sync', '-s', default=False, action="store_true",
786
+ help="Output the contents of the incoming/outging sync tables")
787
+
788
+ options, args = parser.parse_args()
789
+
790
+ if len(args) != 1:
791
+ sys.exit(parser.print_help())
792
+
793
+ run_print_info('container', args, vars(options))
794
+
795
+
796
+ def account_main():
797
+ parser = OptionParser('%prog [options] ACCOUNT_DB_FILE')
798
+ parser.add_option(
799
+ '-d', '--swift-dir', default='/etc/swift',
800
+ help="Pass location of swift directory")
801
+ parser.add_option(
802
+ '--drop-prefixes', default=False, action="store_true",
803
+ help="When outputting metadata, drop the per-section common prefixes")
804
+ parser.add_option(
805
+ '--sync', '-s', default=False, action="store_true",
806
+ help="Output the contents of the incoming/outging sync tables")
807
+
808
+ options, args = parser.parse_args()
809
+
810
+ if len(args) != 1:
811
+ sys.exit(parser.print_help())
812
+
813
+ run_print_info('account', args, vars(options))