swift 2.23.2__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 (208) 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.2.data/scripts/swift-account-audit → swift/cli/account_audit.py +23 -13
  9. swift-2.23.2.data/scripts/swift-config → swift/cli/config.py +2 -2
  10. swift/cli/container_deleter.py +5 -11
  11. swift-2.23.2.data/scripts/swift-dispersion-populate → swift/cli/dispersion_populate.py +8 -7
  12. swift/cli/dispersion_report.py +10 -9
  13. swift-2.23.2.data/scripts/swift-drive-audit → swift/cli/drive_audit.py +63 -21
  14. swift/cli/form_signature.py +3 -7
  15. swift-2.23.2.data/scripts/swift-get-nodes → swift/cli/get_nodes.py +8 -2
  16. swift/cli/info.py +183 -29
  17. swift/cli/manage_shard_ranges.py +708 -37
  18. swift-2.23.2.data/scripts/swift-oldies → swift/cli/oldies.py +25 -14
  19. swift-2.23.2.data/scripts/swift-orphans → swift/cli/orphans.py +7 -3
  20. swift/cli/recon.py +196 -67
  21. swift-2.23.2.data/scripts/swift-recon-cron → swift/cli/recon_cron.py +17 -20
  22. swift-2.23.2.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 +198 -127
  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 +396 -147
  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 -81
  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 +52 -19
  102. swift/common/middleware/tempauth.py +76 -58
  103. swift/common/middleware/tempurl.py +192 -174
  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.2.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} +2191 -2762
  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 +555 -536
  130. swift/container/auditor.py +14 -100
  131. swift/container/backend.py +552 -227
  132. swift/container/reconciler.py +126 -37
  133. swift/container/replicator.py +96 -22
  134. swift/container/server.py +397 -176
  135. swift/container/sharder.py +1580 -639
  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 +213 -122
  146. swift/obj/ssync_receiver.py +145 -85
  147. swift/obj/ssync_sender.py +113 -54
  148. swift/obj/updater.py +653 -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 +452 -86
  154. swift/proxy/controllers/info.py +3 -2
  155. swift/proxy/controllers/obj.py +1009 -490
  156. swift/proxy/server.py +185 -112
  157. swift-2.35.0.dist-info/AUTHORS +501 -0
  158. swift-2.35.0.dist-info/LICENSE +202 -0
  159. {swift-2.23.2.dist-info → swift-2.35.0.dist-info}/METADATA +52 -61
  160. swift-2.35.0.dist-info/RECORD +201 -0
  161. {swift-2.23.2.dist-info → swift-2.35.0.dist-info}/WHEEL +1 -1
  162. {swift-2.23.2.dist-info → swift-2.35.0.dist-info}/entry_points.txt +43 -0
  163. swift-2.35.0.dist-info/pbr.json +1 -0
  164. swift/locale/de/LC_MESSAGES/swift.po +0 -1216
  165. swift/locale/en_GB/LC_MESSAGES/swift.po +0 -1207
  166. swift/locale/es/LC_MESSAGES/swift.po +0 -1085
  167. swift/locale/fr/LC_MESSAGES/swift.po +0 -909
  168. swift/locale/it/LC_MESSAGES/swift.po +0 -894
  169. swift/locale/ja/LC_MESSAGES/swift.po +0 -965
  170. swift/locale/ko_KR/LC_MESSAGES/swift.po +0 -964
  171. swift/locale/pt_BR/LC_MESSAGES/swift.po +0 -881
  172. swift/locale/ru/LC_MESSAGES/swift.po +0 -891
  173. swift/locale/tr_TR/LC_MESSAGES/swift.po +0 -832
  174. swift/locale/zh_CN/LC_MESSAGES/swift.po +0 -833
  175. swift/locale/zh_TW/LC_MESSAGES/swift.po +0 -838
  176. swift-2.23.2.data/scripts/swift-account-auditor +0 -23
  177. swift-2.23.2.data/scripts/swift-account-info +0 -51
  178. swift-2.23.2.data/scripts/swift-account-reaper +0 -23
  179. swift-2.23.2.data/scripts/swift-account-replicator +0 -34
  180. swift-2.23.2.data/scripts/swift-account-server +0 -23
  181. swift-2.23.2.data/scripts/swift-container-auditor +0 -23
  182. swift-2.23.2.data/scripts/swift-container-info +0 -51
  183. swift-2.23.2.data/scripts/swift-container-reconciler +0 -21
  184. swift-2.23.2.data/scripts/swift-container-replicator +0 -34
  185. swift-2.23.2.data/scripts/swift-container-sharder +0 -33
  186. swift-2.23.2.data/scripts/swift-container-sync +0 -23
  187. swift-2.23.2.data/scripts/swift-container-updater +0 -23
  188. swift-2.23.2.data/scripts/swift-dispersion-report +0 -24
  189. swift-2.23.2.data/scripts/swift-form-signature +0 -20
  190. swift-2.23.2.data/scripts/swift-init +0 -119
  191. swift-2.23.2.data/scripts/swift-object-auditor +0 -29
  192. swift-2.23.2.data/scripts/swift-object-expirer +0 -33
  193. swift-2.23.2.data/scripts/swift-object-info +0 -60
  194. swift-2.23.2.data/scripts/swift-object-reconstructor +0 -33
  195. swift-2.23.2.data/scripts/swift-object-relinker +0 -41
  196. swift-2.23.2.data/scripts/swift-object-replicator +0 -37
  197. swift-2.23.2.data/scripts/swift-object-server +0 -27
  198. swift-2.23.2.data/scripts/swift-object-updater +0 -23
  199. swift-2.23.2.data/scripts/swift-proxy-server +0 -23
  200. swift-2.23.2.data/scripts/swift-recon +0 -24
  201. swift-2.23.2.data/scripts/swift-ring-builder +0 -24
  202. swift-2.23.2.data/scripts/swift-ring-builder-analyzer +0 -22
  203. swift-2.23.2.data/scripts/swift-ring-composer +0 -22
  204. swift-2.23.2.dist-info/DESCRIPTION.rst +0 -166
  205. swift-2.23.2.dist-info/RECORD +0 -220
  206. swift-2.23.2.dist-info/metadata.json +0 -1
  207. swift-2.23.2.dist-info/pbr.json +0 -1
  208. {swift-2.23.2.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,15 +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
21
+ from collections import defaultdict
19
22
 
20
- from six.moves import urllib
23
+ import urllib
21
24
 
25
+ from swift.common.exceptions import LockTimeout
22
26
  from swift.common.utils import hash_path, storage_directory, \
23
27
  Timestamp, is_valid_ipv6
24
28
  from swift.common.ring import Ring
@@ -29,8 +33,10 @@ from swift.account.backend import AccountBroker, DATADIR as ABDATADIR
29
33
  from swift.container.backend import ContainerBroker, DATADIR as CBDATADIR
30
34
  from swift.obj.diskfile import get_data_dir, read_metadata, DATADIR_BASE, \
31
35
  extract_policy
32
- 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
33
38
  from swift.common.middleware.crypto.crypto_utils import load_crypto_meta
39
+ from swift.common.utils import md5, set_swift_dir
34
40
 
35
41
 
36
42
  class InfoSystemExit(Exception):
@@ -57,6 +63,8 @@ def parse_get_node_args(options, args):
57
63
  else:
58
64
  raise InfoSystemExit('Ring file does not exist')
59
65
 
66
+ if options.quoted:
67
+ args = [urllib.parse.unquote(arg) for arg in args]
60
68
  if len(args) == 1:
61
69
  args = args[0].strip('/').split('/', 2)
62
70
 
@@ -95,6 +103,7 @@ def curl_head_command(ip, port, device, part, target, policy_index):
95
103
  if policy_index is not None:
96
104
  cmd += ' -H "%s: %s"' % ('X-Backend-Storage-Policy-Index',
97
105
  policy_index)
106
+ cmd += ' --path-as-is'
98
107
  return cmd
99
108
 
100
109
 
@@ -193,7 +202,30 @@ def print_ring_locations(ring, datadir, account, container=None, obj=None,
193
202
  'real value is set in the config file on each storage node.')
194
203
 
195
204
 
196
- def print_db_info_metadata(db_type, info, metadata, drop_prefixes=False):
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
+
227
+ def print_db_info_metadata(db_type, info, metadata, drop_prefixes=False,
228
+ verbose=False):
197
229
  """
198
230
  print out data base info/metadata based on its type
199
231
 
@@ -227,6 +259,7 @@ def print_db_info_metadata(db_type, info, metadata, drop_prefixes=False):
227
259
  if db_type == 'container':
228
260
  print(' Container: %s' % container)
229
261
 
262
+ print(' Deleted: %s' % info['is_deleted'])
230
263
  path_hash = hash_path(account, container)
231
264
  if db_type == 'container':
232
265
  print(' Container Hash: %s' % path_hash)
@@ -291,12 +324,16 @@ def print_db_info_metadata(db_type, info, metadata, drop_prefixes=False):
291
324
  title = key.replace('_', '-').title()
292
325
  print(' %s: %s' % (title, value))
293
326
  if sys_metadata:
294
- print(' System Metadata: %s' % sys_metadata)
327
+ print(' System Metadata:')
328
+ for key, value in sys_metadata.items():
329
+ print(' %s: %s' % (key, value))
295
330
  else:
296
331
  print('No system metadata found in db file')
297
332
 
298
333
  if user_metadata:
299
- print(' User Metadata: %s' % user_metadata)
334
+ print(' User Metadata:')
335
+ for key, value in user_metadata.items():
336
+ print(' %s: %s' % (key, value))
300
337
  else:
301
338
  print('No user metadata found in db file')
302
339
 
@@ -306,20 +343,31 @@ def print_db_info_metadata(db_type, info, metadata, drop_prefixes=False):
306
343
  print(' Type: %s' % shard_type)
307
344
  print(' State: %s' % info['db_state'])
308
345
  if info.get('shard_ranges'):
309
- print('Shard Ranges (%d):' % len(info['shard_ranges']))
346
+ num_shards = len(info['shard_ranges'])
347
+ print('Shard Ranges (%d):' % num_shards)
348
+ count_by_state = defaultdict(int)
310
349
  for srange in info['shard_ranges']:
311
- srange = dict(srange, state_text=srange.state_text)
312
- print(' Name: %(name)s' % srange)
313
- print(' lower: %(lower)r, upper: %(upper)r' % srange)
314
- print(' Object Count: %(object_count)d, Bytes Used: '
315
- '%(bytes_used)d, State: %(state_text)s (%(state)d)'
316
- % srange)
317
- print(' Created at: %s (%s)'
318
- % (Timestamp(srange['timestamp']).isoformat,
319
- srange['timestamp']))
320
- print(' Meta Timestamp: %s (%s)'
321
- % (Timestamp(srange['meta_timestamp']).isoformat,
322
- srange['meta_timestamp']))
350
+ count_by_state[(srange.state, srange.state_text)] += 1
351
+ print(' States:')
352
+ for key_state, count in sorted(count_by_state.items()):
353
+ key, state = key_state
354
+ print(' %9s: %s' % (state, count))
355
+ if verbose:
356
+ for srange in info['shard_ranges']:
357
+ srange = dict(srange, state_text=srange.state_text)
358
+ print(' Name: %(name)s' % srange)
359
+ print(' lower: %(lower)r, upper: %(upper)r' % srange)
360
+ print(' Object Count: %(object_count)d, Bytes Used: '
361
+ '%(bytes_used)d, State: %(state_text)s (%(state)d)'
362
+ % srange)
363
+ print(' Created at: %s (%s)'
364
+ % (Timestamp(srange['timestamp']).isoformat,
365
+ srange['timestamp']))
366
+ print(' Meta Timestamp: %s (%s)'
367
+ % (Timestamp(srange['meta_timestamp']).isoformat,
368
+ srange['meta_timestamp']))
369
+ else:
370
+ print('(Use -v/--verbose to show more Shard Ranges details)')
323
371
 
324
372
 
325
373
  def print_obj_metadata(metadata, drop_prefixes=False):
@@ -417,7 +465,7 @@ def print_obj_metadata(metadata, drop_prefixes=False):
417
465
 
418
466
 
419
467
  def print_info(db_type, db_file, swift_dir='/etc/swift', stale_reads_ok=False,
420
- drop_prefixes=False):
468
+ drop_prefixes=False, verbose=False, sync=False):
421
469
  if db_type not in ('account', 'container'):
422
470
  print("Unrecognized DB type: internal error")
423
471
  raise InfoSystemExit()
@@ -442,13 +490,20 @@ def print_info(db_type, db_file, swift_dir='/etc/swift', stale_reads_ok=False,
442
490
  raise
443
491
  account = info['account']
444
492
  container = None
493
+ info['is_deleted'] = broker.is_deleted()
445
494
  if db_type == 'container':
446
495
  container = info['container']
447
496
  info['is_root'] = broker.is_root_container()
448
497
  sranges = broker.get_shard_ranges()
449
498
  if sranges:
450
499
  info['shard_ranges'] = sranges
451
- print_db_info_metadata(db_type, info, broker.metadata, drop_prefixes)
500
+ print_db_info_metadata(
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))
452
507
  try:
453
508
  ring = Ring(swift_dir, ring_name=db_type)
454
509
  except Exception:
@@ -518,6 +573,8 @@ def print_obj(datafile, check_etag=True, swift_dir='/etc/swift',
518
573
  except EOFError:
519
574
  print("Invalid metadata")
520
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()}
521
578
 
522
579
  etag = metadata.pop('ETag', '')
523
580
  length = metadata.pop('Content-Length', '')
@@ -527,7 +584,7 @@ def print_obj(datafile, check_etag=True, swift_dir='/etc/swift',
527
584
  # Optional integrity check; it's useful, but slow.
528
585
  file_len = None
529
586
  if check_etag:
530
- h = md5()
587
+ h = md5(usedforsecurity=False)
531
588
  file_len = 0
532
589
  while True:
533
590
  data = fp.read(64 * 1024)
@@ -612,15 +669,15 @@ def print_item_locations(ring, ring_name=None, account=None, container=None,
612
669
  ring = POLICIES.get_object_ring(policy_index, swift_dir)
613
670
  ring_name = (POLICIES.get_by_name(policy_name)).ring_name
614
671
 
615
- if account is None and (container is not None or obj is not None):
672
+ if (container or obj) and not account:
616
673
  print('No account specified')
617
674
  raise InfoSystemExit()
618
675
 
619
- if container is None and obj is not None:
676
+ if obj and not container:
620
677
  print('No container specified')
621
678
  raise InfoSystemExit()
622
679
 
623
- if account is None and part is None:
680
+ if not account and not part:
624
681
  print('No target specified')
625
682
  raise InfoSystemExit()
626
683
 
@@ -652,8 +709,105 @@ def print_item_locations(ring, ring_name=None, account=None, container=None,
652
709
  print('Warning: account specified ' +
653
710
  'but ring not named "account"')
654
711
 
655
- print('\nAccount \t%s' % account)
656
- print('Container\t%s' % container)
657
- 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))
658
718
  print_ring_locations(ring, loc, account, container, obj, part, all_nodes,
659
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))