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
swift/obj/auditor.py CHANGED
@@ -18,26 +18,32 @@ import os
18
18
  import sys
19
19
  import time
20
20
  import signal
21
+ from optparse import OptionParser
21
22
  from os.path import basename, dirname, join
22
23
  from random import shuffle
23
- from swift import gettext_ as _
24
24
  from contextlib import closing
25
25
  from eventlet import Timeout
26
26
 
27
27
  from swift.obj import diskfile, replicator
28
- from swift.common.utils import (
29
- get_logger, ratelimit_sleep, dump_recon_cache, list_from_csv, listdir,
30
- unlink_paths_older_than, readconf, config_auto_int_value, round_robin_iter)
31
- from swift.common.exceptions import DiskFileQuarantined, DiskFileNotExist,\
32
- DiskFileDeleted, DiskFileExpired
33
- from swift.common.daemon import Daemon
28
+ from swift.common.exceptions import DiskFileQuarantined, DiskFileNotExist, \
29
+ DiskFileDeleted, DiskFileExpired, QuarantineRequest
30
+ from swift.common.daemon import Daemon, run_daemon
34
31
  from swift.common.storage_policy import POLICIES
32
+ from swift.common.utils import (
33
+ config_auto_int_value, dump_recon_cache, get_logger, list_from_csv,
34
+ listdir, load_pkg_resource, parse_prefixed_conf, EventletRateLimiter,
35
+ readconf, round_robin_iter, unlink_paths_older_than, parse_options,
36
+ get_prefixed_logger)
37
+ from swift.common.recon import RECON_OBJECT_FILE, DEFAULT_RECON_CACHE_PATH
35
38
 
36
39
 
37
40
  class AuditorWorker(object):
38
41
  """Walk through file system to audit objects"""
39
42
 
40
- def __init__(self, conf, logger, rcache, devices, zero_byte_only_at_fps=0):
43
+ def __init__(self, conf, logger, rcache, devices, zero_byte_only_at_fps=0,
44
+ watcher_defs=None):
45
+ if watcher_defs is None:
46
+ watcher_defs = {}
41
47
  self.conf = conf
42
48
  self.logger = logger
43
49
  self.devices = devices
@@ -81,8 +87,10 @@ class AuditorWorker(object):
81
87
  self.auditor_type = 'ZBF'
82
88
  self.log_time = int(conf.get('log_time', 3600))
83
89
  self.last_logged = 0
84
- self.files_running_time = 0
85
- self.bytes_running_time = 0
90
+ self.files_rate_limiter = EventletRateLimiter(
91
+ self.max_files_per_second)
92
+ self.bytes_rate_limiter = EventletRateLimiter(
93
+ self.max_bytes_per_second)
86
94
  self.bytes_processed = 0
87
95
  self.total_bytes_processed = 0
88
96
  self.total_files_processed = 0
@@ -95,6 +103,11 @@ class AuditorWorker(object):
95
103
  self.stats_buckets = dict(
96
104
  [(s, 0) for s in self.stats_sizes + ['OVER']])
97
105
 
106
+ self.watchers = [
107
+ WatcherWrapper(wdef['klass'], name, wdef['conf'], logger)
108
+ for name, wdef in watcher_defs.items()]
109
+ logger.debug("%d audit watcher(s) loaded", len(self.watchers))
110
+
98
111
  def create_recon_nested_dict(self, top_level_key, device_list, item):
99
112
  if device_list:
100
113
  device_key = ''.join(sorted(device_list))
@@ -107,13 +120,15 @@ class AuditorWorker(object):
107
120
  if device_dirs:
108
121
  device_dir_str = ','.join(sorted(device_dirs))
109
122
  if self.auditor_type == 'ALL':
110
- description = _(' - parallel, %s') % device_dir_str
123
+ description = ' - parallel, %s' % device_dir_str
111
124
  else:
112
- description = _(' - %s') % device_dir_str
113
- self.logger.info(_('Begin object audit "%(mode)s" mode (%(audi_type)s'
114
- '%(description)s)') %
125
+ description = ' - %s' % device_dir_str
126
+ self.logger.info('Begin object audit "%(mode)s" mode (%(audi_type)s'
127
+ '%(description)s)',
115
128
  {'mode': mode, 'audi_type': self.auditor_type,
116
129
  'description': description})
130
+ for watcher in self.watchers:
131
+ watcher.start(self.auditor_type)
117
132
  begin = reported = time.time()
118
133
  self.total_bytes_processed = 0
119
134
  self.total_files_processed = 0
@@ -135,18 +150,17 @@ class AuditorWorker(object):
135
150
  loop_time = time.time()
136
151
  self.failsafe_object_audit(location)
137
152
  self.logger.timing_since('timing', loop_time)
138
- self.files_running_time = ratelimit_sleep(
139
- self.files_running_time, self.max_files_per_second)
153
+ self.files_rate_limiter.wait()
140
154
  self.total_files_processed += 1
141
155
  now = time.time()
142
156
  if now - self.last_logged >= self.log_time:
143
- self.logger.info(_(
157
+ self.logger.info(
144
158
  'Object audit (%(type)s). '
145
159
  'Since %(start_time)s: Locally: %(passes)d passed, '
146
160
  '%(quars)d quarantined, %(errors)d errors, '
147
161
  'files/sec: %(frate).2f, bytes/sec: %(brate).2f, '
148
162
  'Total time: %(total).2f, Auditing time: %(audit).2f, '
149
- 'Rate: %(audit_rate).2f') % {
163
+ 'Rate: %(audit_rate).2f', {
150
164
  'type': '%s%s' % (self.auditor_type, description),
151
165
  'start_time': time.ctime(reported),
152
166
  'passes': self.passes, 'quars': self.quarantines,
@@ -174,12 +188,12 @@ class AuditorWorker(object):
174
188
  time_auditing += (now - loop_time)
175
189
  # Avoid divide by zero during very short runs
176
190
  elapsed = (time.time() - begin) or 0.000001
177
- self.logger.info(_(
191
+ self.logger.info(
178
192
  'Object audit (%(type)s) "%(mode)s" mode '
179
193
  'completed: %(elapsed).02fs. Total quarantined: %(quars)d, '
180
194
  'Total errors: %(errors)d, Total files/sec: %(frate).2f, '
181
195
  'Total bytes/sec: %(brate).2f, Auditing time: %(audit).2f, '
182
- 'Rate: %(audit_rate).2f') % {
196
+ 'Rate: %(audit_rate).2f', {
183
197
  'type': '%s%s' % (self.auditor_type, description),
184
198
  'mode': mode, 'elapsed': elapsed,
185
199
  'quars': total_quarantines + self.quarantines,
@@ -187,9 +201,11 @@ class AuditorWorker(object):
187
201
  'frate': self.total_files_processed / elapsed,
188
202
  'brate': self.total_bytes_processed / elapsed,
189
203
  'audit': time_auditing, 'audit_rate': time_auditing / elapsed})
204
+ for watcher in self.watchers:
205
+ watcher.end()
190
206
  if self.stats_sizes:
191
207
  self.logger.info(
192
- _('Object audit stats: %s') % json.dumps(self.stats_buckets))
208
+ 'Object audit stats: %s', json.dumps(self.stats_buckets))
193
209
 
194
210
  for policy in POLICIES:
195
211
  # Unset remaining partitions to not skip them in the next run
@@ -223,7 +239,7 @@ class AuditorWorker(object):
223
239
  except (Exception, Timeout):
224
240
  self.logger.increment('errors')
225
241
  self.errors += 1
226
- self.logger.exception(_('ERROR Trying to audit %s'), location)
242
+ self.logger.exception('ERROR Trying to audit %s', location)
227
243
 
228
244
  def object_audit(self, location):
229
245
  """
@@ -244,6 +260,10 @@ class AuditorWorker(object):
244
260
  try:
245
261
  with df.open(modernize=True):
246
262
  metadata = df.get_metadata()
263
+ if not df.validate_metadata():
264
+ df._quarantine(
265
+ df._data_file,
266
+ "Metadata failed validation")
247
267
  obj_size = int(metadata['Content-Length'])
248
268
  if self.stats_sizes:
249
269
  self.record_stats(obj_size)
@@ -253,16 +273,22 @@ class AuditorWorker(object):
253
273
  with closing(reader):
254
274
  for chunk in reader:
255
275
  chunk_len = len(chunk)
256
- self.bytes_running_time = ratelimit_sleep(
257
- self.bytes_running_time,
258
- self.max_bytes_per_second,
259
- incr_by=chunk_len)
276
+ self.bytes_rate_limiter.wait(incr_by=chunk_len)
260
277
  self.bytes_processed += chunk_len
261
278
  self.total_bytes_processed += chunk_len
279
+ for watcher in self.watchers:
280
+ try:
281
+ watcher.see_object(
282
+ metadata,
283
+ df._ondisk_info['data_file'])
284
+ except QuarantineRequest:
285
+ raise df._quarantine(
286
+ df._data_file,
287
+ "Requested by %s" % watcher.watcher_name)
262
288
  except DiskFileQuarantined as err:
263
289
  self.quarantines += 1
264
- self.logger.error(_('ERROR Object %(obj)s failed audit and was'
265
- ' quarantined: %(err)s'),
290
+ self.logger.error('ERROR Object %(obj)s failed audit and was'
291
+ ' quarantined: %(err)s',
266
292
  {'obj': location, 'err': err})
267
293
  except DiskFileExpired:
268
294
  pass # ignore expired objects
@@ -299,9 +325,23 @@ class ObjectAuditor(Daemon):
299
325
  self.conf_zero_byte_fps = int(
300
326
  conf.get('zero_byte_files_per_second', 50))
301
327
  self.recon_cache_path = conf.get('recon_cache_path',
302
- '/var/cache/swift')
303
- self.rcache = join(self.recon_cache_path, "object.recon")
304
- self.interval = int(conf.get('interval', 30))
328
+ DEFAULT_RECON_CACHE_PATH)
329
+ self.rcache = join(self.recon_cache_path, RECON_OBJECT_FILE)
330
+ self.interval = float(conf.get('interval', 30))
331
+
332
+ watcher_names = set(list_from_csv(conf.get('watchers', '')))
333
+ # Normally '__file__' is always in config, but tests neglect it often.
334
+ watcher_configs = \
335
+ parse_prefixed_conf(conf['__file__'], 'object-auditor:watcher:') \
336
+ if '__file__' in conf else {}
337
+ self.watcher_defs = {}
338
+ for name in watcher_names:
339
+ self.logger.debug("Loading entry point '%s'", name)
340
+ wconf = dict(conf)
341
+ wconf.update(watcher_configs.get(name, {}))
342
+ self.watcher_defs[name] = {
343
+ 'conf': wconf,
344
+ 'klass': load_pkg_resource("swift.object_audit_watcher", name)}
305
345
 
306
346
  def _sleep(self):
307
347
  time.sleep(self.interval)
@@ -318,7 +358,8 @@ class ObjectAuditor(Daemon):
318
358
  device_dirs = kwargs.get('device_dirs')
319
359
  worker = AuditorWorker(self.conf, self.logger, self.rcache,
320
360
  self.devices,
321
- zero_byte_only_at_fps=zero_byte_only_at_fps)
361
+ zero_byte_only_at_fps=zero_byte_only_at_fps,
362
+ watcher_defs=self.watcher_defs)
322
363
  worker.audit_all_objects(mode=mode, device_dirs=device_dirs)
323
364
 
324
365
  def fork_child(self, zero_byte_fps=False, sleep_between_zbf_scanner=False,
@@ -329,6 +370,7 @@ class ObjectAuditor(Daemon):
329
370
  return pid
330
371
  else:
331
372
  signal.signal(signal.SIGTERM, signal.SIG_DFL)
373
+ os.environ.pop('NOTIFY_SOCKET', None)
332
374
  if zero_byte_fps:
333
375
  kwargs['zero_byte_fps'] = self.conf_zero_byte_fps
334
376
  if sleep_between_zbf_scanner:
@@ -337,7 +379,7 @@ class ObjectAuditor(Daemon):
337
379
  self.run_audit(**kwargs)
338
380
  except Exception as e:
339
381
  self.logger.exception(
340
- _("ERROR: Unable to run auditing: %s") % e)
382
+ "ERROR: Unable to run auditing: %s", e)
341
383
  finally:
342
384
  sys.exit()
343
385
 
@@ -416,7 +458,7 @@ class ObjectAuditor(Daemon):
416
458
  try:
417
459
  self.audit_loop(parent, zbo_fps, **kwargs)
418
460
  except (Exception, Timeout) as err:
419
- self.logger.exception(_('ERROR auditing: %s'), err)
461
+ self.logger.exception('ERROR auditing: %s', err)
420
462
  self._sleep()
421
463
 
422
464
  def run_once(self, *args, **kwargs):
@@ -437,4 +479,80 @@ class ObjectAuditor(Daemon):
437
479
  self.audit_loop(parent, zbo_fps, override_devices=override_devices,
438
480
  **kwargs)
439
481
  except (Exception, Timeout) as err:
440
- self.logger.exception(_('ERROR auditing: %s'), err)
482
+ self.logger.exception('ERROR auditing: %s', err)
483
+
484
+
485
+ class WatcherWrapper(object):
486
+ """
487
+ Run the user-supplied watcher.
488
+
489
+ Simple and gets the job done. Note that we aren't doing anything
490
+ to isolate ourselves from hangs or file descriptor leaks
491
+ in the plugins.
492
+
493
+ :param logger: an instance of ``SwiftLogAdapter``.
494
+
495
+ """
496
+
497
+ def __init__(self, watcher_class, watcher_name, conf, logger):
498
+ self.watcher_name = watcher_name
499
+ self.watcher_in_error = False
500
+ self.logger = get_prefixed_logger(
501
+ logger, '[audit-watcher %s] ' % watcher_name)
502
+
503
+ try:
504
+ self.watcher = watcher_class(conf, self.logger)
505
+ except (Exception, Timeout):
506
+ self.logger.exception('Error intializing watcher')
507
+ self.watcher_in_error = True
508
+
509
+ def start(self, audit_type):
510
+ if self.watcher_in_error:
511
+ return # can't trust the state of the thing; bail
512
+ try:
513
+ self.watcher.start(audit_type=audit_type)
514
+ except (Exception, Timeout):
515
+ self.logger.exception('Error starting watcher')
516
+ self.watcher_in_error = True
517
+
518
+ def see_object(self, meta, data_file_path):
519
+ if self.watcher_in_error:
520
+ return # can't trust the state of the thing; bail
521
+ kwargs = {'object_metadata': meta,
522
+ 'data_file_path': data_file_path}
523
+ try:
524
+ self.watcher.see_object(**kwargs)
525
+ except QuarantineRequest:
526
+ # Avoid extra logging.
527
+ raise
528
+ except (Exception, Timeout):
529
+ self.logger.exception(
530
+ 'Error in see_object(meta=%r, data_file_path=%r)',
531
+ meta, data_file_path)
532
+ # Do *not* flag watcher as being in an error state; a failure
533
+ # to process one object shouldn't impact the ability to process
534
+ # others.
535
+
536
+ def end(self):
537
+ if self.watcher_in_error:
538
+ return # can't trust the state of the thing; bail
539
+ kwargs = {}
540
+ try:
541
+ self.watcher.end(**kwargs)
542
+ except (Exception, Timeout):
543
+ self.logger.exception('Error ending watcher')
544
+ self.watcher_in_error = True
545
+
546
+
547
+ def main():
548
+ parser = OptionParser("%prog CONFIG [options]")
549
+ parser.add_option('-z', '--zero_byte_fps',
550
+ help='Audit only zero byte files at specified files/sec')
551
+ parser.add_option('-d', '--devices',
552
+ help='Audit only given devices. Comma-separated list')
553
+ conf_file, options = parse_options(parser=parser, once=True)
554
+ run_daemon(ObjectAuditor, conf_file, **options)
555
+
556
+
557
+ if __name__ == '__main__':
558
+ main()