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.
- swift/__init__.py +29 -50
- swift/account/auditor.py +21 -118
- swift/account/backend.py +33 -28
- swift/account/reaper.py +37 -28
- swift/account/replicator.py +22 -0
- swift/account/server.py +60 -26
- swift/account/utils.py +28 -11
- swift-2.23.3.data/scripts/swift-account-audit → swift/cli/account_audit.py +23 -13
- swift-2.23.3.data/scripts/swift-config → swift/cli/config.py +2 -2
- swift/cli/container_deleter.py +5 -11
- swift-2.23.3.data/scripts/swift-dispersion-populate → swift/cli/dispersion_populate.py +8 -7
- swift/cli/dispersion_report.py +10 -9
- swift-2.23.3.data/scripts/swift-drive-audit → swift/cli/drive_audit.py +63 -21
- swift/cli/form_signature.py +3 -7
- swift-2.23.3.data/scripts/swift-get-nodes → swift/cli/get_nodes.py +8 -2
- swift/cli/info.py +154 -14
- swift/cli/manage_shard_ranges.py +705 -37
- swift-2.23.3.data/scripts/swift-oldies → swift/cli/oldies.py +25 -14
- swift-2.23.3.data/scripts/swift-orphans → swift/cli/orphans.py +7 -3
- swift/cli/recon.py +196 -67
- swift-2.23.3.data/scripts/swift-recon-cron → swift/cli/recon_cron.py +17 -20
- swift-2.23.3.data/scripts/swift-reconciler-enqueue → swift/cli/reconciler_enqueue.py +2 -3
- swift/cli/relinker.py +807 -126
- swift/cli/reload.py +135 -0
- swift/cli/ringbuilder.py +217 -20
- swift/cli/ringcomposer.py +0 -1
- swift/cli/shard-info.py +4 -3
- swift/common/base_storage_server.py +9 -20
- swift/common/bufferedhttp.py +48 -74
- swift/common/constraints.py +20 -15
- swift/common/container_sync_realms.py +9 -11
- swift/common/daemon.py +25 -8
- swift/common/db.py +195 -128
- swift/common/db_auditor.py +168 -0
- swift/common/db_replicator.py +95 -55
- swift/common/digest.py +141 -0
- swift/common/direct_client.py +144 -33
- swift/common/error_limiter.py +93 -0
- swift/common/exceptions.py +25 -1
- swift/common/header_key_dict.py +2 -9
- swift/common/http_protocol.py +373 -0
- swift/common/internal_client.py +129 -59
- swift/common/linkat.py +3 -4
- swift/common/manager.py +284 -67
- swift/common/memcached.py +390 -145
- swift/common/middleware/__init__.py +4 -0
- swift/common/middleware/account_quotas.py +211 -46
- swift/common/middleware/acl.py +3 -8
- swift/common/middleware/backend_ratelimit.py +230 -0
- swift/common/middleware/bulk.py +22 -34
- swift/common/middleware/catch_errors.py +1 -3
- swift/common/middleware/cname_lookup.py +6 -11
- swift/common/middleware/container_quotas.py +1 -1
- swift/common/middleware/container_sync.py +39 -17
- swift/common/middleware/copy.py +12 -0
- swift/common/middleware/crossdomain.py +22 -9
- swift/common/middleware/crypto/__init__.py +2 -1
- swift/common/middleware/crypto/crypto_utils.py +11 -15
- swift/common/middleware/crypto/decrypter.py +28 -11
- swift/common/middleware/crypto/encrypter.py +12 -17
- swift/common/middleware/crypto/keymaster.py +8 -15
- swift/common/middleware/crypto/kms_keymaster.py +2 -1
- swift/common/middleware/dlo.py +15 -11
- swift/common/middleware/domain_remap.py +5 -4
- swift/common/middleware/etag_quoter.py +128 -0
- swift/common/middleware/formpost.py +73 -70
- swift/common/middleware/gatekeeper.py +8 -1
- swift/common/middleware/keystoneauth.py +33 -3
- swift/common/middleware/list_endpoints.py +4 -4
- swift/common/middleware/listing_formats.py +85 -49
- swift/common/middleware/memcache.py +4 -95
- swift/common/middleware/name_check.py +3 -2
- swift/common/middleware/proxy_logging.py +160 -92
- swift/common/middleware/ratelimit.py +17 -10
- swift/common/middleware/read_only.py +6 -4
- swift/common/middleware/recon.py +59 -22
- swift/common/middleware/s3api/acl_handlers.py +25 -3
- swift/common/middleware/s3api/acl_utils.py +6 -1
- swift/common/middleware/s3api/controllers/__init__.py +6 -0
- swift/common/middleware/s3api/controllers/acl.py +3 -2
- swift/common/middleware/s3api/controllers/bucket.py +242 -137
- swift/common/middleware/s3api/controllers/logging.py +2 -2
- swift/common/middleware/s3api/controllers/multi_delete.py +43 -20
- swift/common/middleware/s3api/controllers/multi_upload.py +219 -133
- swift/common/middleware/s3api/controllers/obj.py +112 -8
- swift/common/middleware/s3api/controllers/object_lock.py +44 -0
- swift/common/middleware/s3api/controllers/s3_acl.py +2 -2
- swift/common/middleware/s3api/controllers/tagging.py +57 -0
- swift/common/middleware/s3api/controllers/versioning.py +36 -7
- swift/common/middleware/s3api/etree.py +22 -9
- swift/common/middleware/s3api/exception.py +0 -4
- swift/common/middleware/s3api/s3api.py +113 -41
- swift/common/middleware/s3api/s3request.py +384 -218
- swift/common/middleware/s3api/s3response.py +126 -23
- swift/common/middleware/s3api/s3token.py +16 -17
- swift/common/middleware/s3api/schema/delete.rng +1 -1
- swift/common/middleware/s3api/subresource.py +7 -10
- swift/common/middleware/s3api/utils.py +27 -10
- swift/common/middleware/slo.py +665 -358
- swift/common/middleware/staticweb.py +64 -37
- swift/common/middleware/symlink.py +51 -18
- swift/common/middleware/tempauth.py +76 -58
- swift/common/middleware/tempurl.py +191 -173
- swift/common/middleware/versioned_writes/__init__.py +51 -0
- swift/common/middleware/{versioned_writes.py → versioned_writes/legacy.py} +27 -26
- swift/common/middleware/versioned_writes/object_versioning.py +1482 -0
- swift/common/middleware/x_profile/exceptions.py +1 -4
- swift/common/middleware/x_profile/html_viewer.py +18 -19
- swift/common/middleware/x_profile/profile_model.py +1 -2
- swift/common/middleware/xprofile.py +10 -10
- swift-2.23.3.data/scripts/swift-container-server → swift/common/recon.py +13 -8
- swift/common/registry.py +147 -0
- swift/common/request_helpers.py +324 -57
- swift/common/ring/builder.py +67 -25
- swift/common/ring/composite_builder.py +1 -1
- swift/common/ring/ring.py +177 -51
- swift/common/ring/utils.py +1 -1
- swift/common/splice.py +10 -6
- swift/common/statsd_client.py +205 -0
- swift/common/storage_policy.py +49 -44
- swift/common/swob.py +86 -102
- swift/common/{utils.py → utils/__init__.py} +2163 -2772
- swift/common/utils/base.py +131 -0
- swift/common/utils/config.py +433 -0
- swift/common/utils/ipaddrs.py +256 -0
- swift/common/utils/libc.py +345 -0
- swift/common/utils/logs.py +859 -0
- swift/common/utils/timestamp.py +412 -0
- swift/common/wsgi.py +553 -535
- swift/container/auditor.py +14 -100
- swift/container/backend.py +490 -231
- swift/container/reconciler.py +126 -37
- swift/container/replicator.py +96 -22
- swift/container/server.py +358 -165
- swift/container/sharder.py +1540 -684
- swift/container/sync.py +94 -88
- swift/container/updater.py +53 -32
- swift/obj/auditor.py +153 -35
- swift/obj/diskfile.py +466 -217
- swift/obj/expirer.py +406 -124
- swift/obj/mem_diskfile.py +7 -4
- swift/obj/mem_server.py +1 -0
- swift/obj/reconstructor.py +523 -262
- swift/obj/replicator.py +249 -188
- swift/obj/server.py +207 -122
- swift/obj/ssync_receiver.py +145 -85
- swift/obj/ssync_sender.py +113 -54
- swift/obj/updater.py +652 -139
- swift/obj/watchers/__init__.py +0 -0
- swift/obj/watchers/dark_data.py +213 -0
- swift/proxy/controllers/account.py +11 -11
- swift/proxy/controllers/base.py +848 -604
- swift/proxy/controllers/container.py +433 -92
- swift/proxy/controllers/info.py +3 -2
- swift/proxy/controllers/obj.py +1000 -489
- swift/proxy/server.py +185 -112
- {swift-2.23.3.dist-info → swift-2.35.0.dist-info}/AUTHORS +58 -11
- {swift-2.23.3.dist-info → swift-2.35.0.dist-info}/METADATA +51 -56
- swift-2.35.0.dist-info/RECORD +201 -0
- {swift-2.23.3.dist-info → swift-2.35.0.dist-info}/WHEEL +1 -1
- {swift-2.23.3.dist-info → swift-2.35.0.dist-info}/entry_points.txt +43 -0
- swift-2.35.0.dist-info/pbr.json +1 -0
- swift/locale/de/LC_MESSAGES/swift.po +0 -1216
- swift/locale/en_GB/LC_MESSAGES/swift.po +0 -1207
- swift/locale/es/LC_MESSAGES/swift.po +0 -1085
- swift/locale/fr/LC_MESSAGES/swift.po +0 -909
- swift/locale/it/LC_MESSAGES/swift.po +0 -894
- swift/locale/ja/LC_MESSAGES/swift.po +0 -965
- swift/locale/ko_KR/LC_MESSAGES/swift.po +0 -964
- swift/locale/pt_BR/LC_MESSAGES/swift.po +0 -881
- swift/locale/ru/LC_MESSAGES/swift.po +0 -891
- swift/locale/tr_TR/LC_MESSAGES/swift.po +0 -832
- swift/locale/zh_CN/LC_MESSAGES/swift.po +0 -833
- swift/locale/zh_TW/LC_MESSAGES/swift.po +0 -838
- swift-2.23.3.data/scripts/swift-account-auditor +0 -23
- swift-2.23.3.data/scripts/swift-account-info +0 -51
- swift-2.23.3.data/scripts/swift-account-reaper +0 -23
- swift-2.23.3.data/scripts/swift-account-replicator +0 -34
- swift-2.23.3.data/scripts/swift-account-server +0 -23
- swift-2.23.3.data/scripts/swift-container-auditor +0 -23
- swift-2.23.3.data/scripts/swift-container-info +0 -55
- swift-2.23.3.data/scripts/swift-container-reconciler +0 -21
- swift-2.23.3.data/scripts/swift-container-replicator +0 -34
- swift-2.23.3.data/scripts/swift-container-sharder +0 -37
- swift-2.23.3.data/scripts/swift-container-sync +0 -23
- swift-2.23.3.data/scripts/swift-container-updater +0 -23
- swift-2.23.3.data/scripts/swift-dispersion-report +0 -24
- swift-2.23.3.data/scripts/swift-form-signature +0 -20
- swift-2.23.3.data/scripts/swift-init +0 -119
- swift-2.23.3.data/scripts/swift-object-auditor +0 -29
- swift-2.23.3.data/scripts/swift-object-expirer +0 -33
- swift-2.23.3.data/scripts/swift-object-info +0 -60
- swift-2.23.3.data/scripts/swift-object-reconstructor +0 -33
- swift-2.23.3.data/scripts/swift-object-relinker +0 -41
- swift-2.23.3.data/scripts/swift-object-replicator +0 -37
- swift-2.23.3.data/scripts/swift-object-server +0 -27
- swift-2.23.3.data/scripts/swift-object-updater +0 -23
- swift-2.23.3.data/scripts/swift-proxy-server +0 -23
- swift-2.23.3.data/scripts/swift-recon +0 -24
- swift-2.23.3.data/scripts/swift-ring-builder +0 -24
- swift-2.23.3.data/scripts/swift-ring-builder-analyzer +0 -22
- swift-2.23.3.data/scripts/swift-ring-composer +0 -22
- swift-2.23.3.dist-info/RECORD +0 -220
- swift-2.23.3.dist-info/pbr.json +0 -1
- {swift-2.23.3.dist-info → swift-2.35.0.dist-info}/LICENSE +0 -0
- {swift-2.23.3.dist-info → swift-2.35.0.dist-info}/top_level.txt +0 -0
swift/__init__.py
CHANGED
@@ -13,20 +13,32 @@
|
|
13
13
|
# See the License for the specific language governing permissions and
|
14
14
|
# limitations under the License.
|
15
15
|
|
16
|
-
import
|
17
|
-
import sys
|
18
|
-
import gettext
|
16
|
+
import warnings
|
19
17
|
|
20
|
-
|
18
|
+
__version__ = None
|
21
19
|
|
20
|
+
# First, try to get our version out of PKG-INFO. If we're installed,
|
21
|
+
# this'll let us find our version without pulling in pbr. After all, if
|
22
|
+
# we're installed on a system, we're not in a Git-managed source tree, so
|
23
|
+
# pbr doesn't really buy us anything.
|
22
24
|
try:
|
23
|
-
|
24
|
-
|
25
|
-
#
|
26
|
-
|
27
|
-
|
28
|
-
pkg_resources.
|
29
|
-
|
25
|
+
import importlib.metadata
|
26
|
+
except ImportError:
|
27
|
+
# python < 3.8
|
28
|
+
import pkg_resources
|
29
|
+
try:
|
30
|
+
__version__ = __canonical_version__ = pkg_resources.get_provider(
|
31
|
+
pkg_resources.Requirement.parse('swift')).version
|
32
|
+
except pkg_resources.DistributionNotFound:
|
33
|
+
pass
|
34
|
+
else:
|
35
|
+
try:
|
36
|
+
__version__ = __canonical_version__ = importlib.metadata.distribution(
|
37
|
+
'swift').version
|
38
|
+
except importlib.metadata.PackageNotFoundError:
|
39
|
+
pass
|
40
|
+
|
41
|
+
if __version__ is None:
|
30
42
|
# No PKG-INFO? We're probably running from a checkout, then. Let pbr do
|
31
43
|
# its thing to figure out a version number.
|
32
44
|
import pbr.version
|
@@ -34,43 +46,10 @@ except pkg_resources.DistributionNotFound:
|
|
34
46
|
__version__ = _version_info.release_string()
|
35
47
|
__canonical_version__ = _version_info.version_string()
|
36
48
|
|
37
|
-
_localedir = os.environ.get('SWIFT_LOCALEDIR')
|
38
|
-
_t = gettext.translation('swift', localedir=_localedir, fallback=True)
|
39
49
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
# In the development of py3, json.loads() stopped accepting byte strings
|
47
|
-
# for a while. https://bugs.python.org/issue17909 got fixed for py36, but
|
48
|
-
# since it was termed an enhancement and not a regression, we don't expect
|
49
|
-
# any backports. At the same time, it'd be better if we could avoid
|
50
|
-
# leaving a whole bunch of json.loads(resp.body.decode(...)) scars in the
|
51
|
-
# code that'd probably persist even *after* we drop support for 3.5 and
|
52
|
-
# earlier. So, monkey patch stdlib.
|
53
|
-
import json
|
54
|
-
if not getattr(json.loads, 'patched_to_decode', False):
|
55
|
-
class JsonLoadsPatcher(object):
|
56
|
-
def __init__(self, orig):
|
57
|
-
self._orig = orig
|
58
|
-
|
59
|
-
def __call__(self, s, **kw):
|
60
|
-
if isinstance(s, bytes):
|
61
|
-
# No fancy byte-order mark detection for us; just assume
|
62
|
-
# UTF-8 and raise a UnicodeDecodeError if appropriate.
|
63
|
-
s = s.decode('utf8')
|
64
|
-
return self._orig(s, **kw)
|
65
|
-
|
66
|
-
def __getattribute__(self, attr):
|
67
|
-
if attr == 'patched_to_decode':
|
68
|
-
return True
|
69
|
-
if attr == '_orig':
|
70
|
-
return super().__getattribute__(attr)
|
71
|
-
# Pass through all other attrs to the original; among other
|
72
|
-
# things, this preserves doc strings, etc.
|
73
|
-
return getattr(self._orig, attr)
|
74
|
-
|
75
|
-
json.loads = JsonLoadsPatcher(json.loads)
|
76
|
-
del JsonLoadsPatcher
|
50
|
+
warnings.filterwarnings('ignore', module='cryptography|OpenSSL', message=(
|
51
|
+
'Python 2 is no longer supported by the Python core team. '
|
52
|
+
'Support for it is now deprecated in cryptography'))
|
53
|
+
warnings.filterwarnings('ignore', message=(
|
54
|
+
'Python 3.6 is no longer supported by the Python core team. '
|
55
|
+
'Therefore, support for it is deprecated in cryptography'))
|
swift/account/auditor.py
CHANGED
@@ -13,100 +13,22 @@
|
|
13
13
|
# See the License for the specific language governing permissions and
|
14
14
|
# limitations under the License.
|
15
15
|
|
16
|
-
import os
|
17
|
-
import time
|
18
|
-
from swift import gettext_ as _
|
19
|
-
from random import random
|
20
16
|
|
21
|
-
|
22
|
-
from swift.account.backend import AccountBroker, DATADIR
|
17
|
+
from swift.account.backend import AccountBroker
|
23
18
|
from swift.common.exceptions import InvalidAccountInfo
|
24
|
-
from swift.common.
|
25
|
-
|
26
|
-
from swift.common.
|
19
|
+
from swift.common.daemon import run_daemon
|
20
|
+
from swift.common.db_auditor import DatabaseAuditor
|
21
|
+
from swift.common.utils import parse_options
|
27
22
|
|
28
|
-
from eventlet import Timeout
|
29
23
|
|
30
|
-
|
31
|
-
class AccountAuditor(Daemon):
|
24
|
+
class AccountAuditor(DatabaseAuditor):
|
32
25
|
"""Audit accounts."""
|
33
26
|
|
34
|
-
|
35
|
-
|
36
|
-
self.logger = logger or get_logger(conf, log_route='account-auditor')
|
37
|
-
self.devices = conf.get('devices', '/srv/node')
|
38
|
-
self.mount_check = config_true_value(conf.get('mount_check', 'true'))
|
39
|
-
self.interval = int(conf.get('interval', 1800))
|
40
|
-
self.logging_interval = 3600 # once an hour
|
41
|
-
self.account_passes = 0
|
42
|
-
self.account_failures = 0
|
43
|
-
self.accounts_running_time = 0
|
44
|
-
self.max_accounts_per_second = \
|
45
|
-
float(conf.get('accounts_per_second', 200))
|
46
|
-
swift.common.db.DB_PREALLOCATION = \
|
47
|
-
config_true_value(conf.get('db_preallocation', 'f'))
|
48
|
-
self.recon_cache_path = conf.get('recon_cache_path',
|
49
|
-
'/var/cache/swift')
|
50
|
-
self.rcache = os.path.join(self.recon_cache_path, "account.recon")
|
51
|
-
|
52
|
-
def _one_audit_pass(self, reported):
|
53
|
-
all_locs = audit_location_generator(self.devices, DATADIR, '.db',
|
54
|
-
mount_check=self.mount_check,
|
55
|
-
logger=self.logger)
|
56
|
-
for path, device, partition in all_locs:
|
57
|
-
self.account_audit(path)
|
58
|
-
if time.time() - reported >= self.logging_interval:
|
59
|
-
self.logger.info(_('Since %(time)s: Account audits: '
|
60
|
-
'%(passed)s passed audit,'
|
61
|
-
'%(failed)s failed audit'),
|
62
|
-
{'time': time.ctime(reported),
|
63
|
-
'passed': self.account_passes,
|
64
|
-
'failed': self.account_failures})
|
65
|
-
dump_recon_cache({'account_audits_since': reported,
|
66
|
-
'account_audits_passed': self.account_passes,
|
67
|
-
'account_audits_failed':
|
68
|
-
self.account_failures},
|
69
|
-
self.rcache, self.logger)
|
70
|
-
reported = time.time()
|
71
|
-
self.account_passes = 0
|
72
|
-
self.account_failures = 0
|
73
|
-
self.accounts_running_time = ratelimit_sleep(
|
74
|
-
self.accounts_running_time, self.max_accounts_per_second)
|
75
|
-
return reported
|
76
|
-
|
77
|
-
def run_forever(self, *args, **kwargs):
|
78
|
-
"""Run the account audit until stopped."""
|
79
|
-
reported = time.time()
|
80
|
-
time.sleep(random() * self.interval)
|
81
|
-
while True:
|
82
|
-
self.logger.info(_('Begin account audit pass.'))
|
83
|
-
begin = time.time()
|
84
|
-
try:
|
85
|
-
reported = self._one_audit_pass(reported)
|
86
|
-
except (Exception, Timeout):
|
87
|
-
self.logger.increment('errors')
|
88
|
-
self.logger.exception(_('ERROR auditing'))
|
89
|
-
elapsed = time.time() - begin
|
90
|
-
if elapsed < self.interval:
|
91
|
-
time.sleep(self.interval - elapsed)
|
92
|
-
self.logger.info(
|
93
|
-
_('Account audit pass completed: %.02fs'), elapsed)
|
94
|
-
dump_recon_cache({'account_auditor_pass_completed': elapsed},
|
95
|
-
self.rcache, self.logger)
|
27
|
+
server_type = "account"
|
28
|
+
broker_class = AccountBroker
|
96
29
|
|
97
|
-
def
|
98
|
-
|
99
|
-
self.logger.info(_('Begin account audit "once" mode'))
|
100
|
-
begin = reported = time.time()
|
101
|
-
self._one_audit_pass(reported)
|
102
|
-
elapsed = time.time() - begin
|
103
|
-
self.logger.info(
|
104
|
-
_('Account audit "once" mode completed: %.02fs'), elapsed)
|
105
|
-
dump_recon_cache({'account_auditor_pass_completed': elapsed},
|
106
|
-
self.rcache, self.logger)
|
107
|
-
|
108
|
-
def validate_per_policy_counts(self, broker):
|
109
|
-
info = broker.get_info()
|
30
|
+
def _audit(self, info, broker):
|
31
|
+
# Validate per policy counts
|
110
32
|
policy_stats = broker.get_policy_stats(do_migrations=True)
|
111
33
|
policy_totals = {
|
112
34
|
'container_count': 0,
|
@@ -120,36 +42,17 @@ class AccountAuditor(Daemon):
|
|
120
42
|
for key in policy_totals:
|
121
43
|
if policy_totals[key] == info[key]:
|
122
44
|
continue
|
123
|
-
|
124
|
-
'The total %(key)s for the
|
125
|
-
'match the sum of %(key)s across policies (%(sum)s)'
|
126
|
-
% {'key': key,
|
127
|
-
'total': info[key],
|
128
|
-
|
45
|
+
return InvalidAccountInfo(
|
46
|
+
'The total %(key)s for the account %(account)s (%(total)s) '
|
47
|
+
'does not match the sum of %(key)s across policies (%(sum)s)'
|
48
|
+
% {'key': key, 'account': info.get('account'),
|
49
|
+
'total': info[key], 'sum': policy_totals[key]})
|
50
|
+
|
51
|
+
|
52
|
+
def main():
|
53
|
+
conf_file, options = parse_options(once=True)
|
54
|
+
run_daemon(AccountAuditor, conf_file, **options)
|
129
55
|
|
130
|
-
def account_audit(self, path):
|
131
|
-
"""
|
132
|
-
Audits the given account path
|
133
56
|
|
134
|
-
|
135
|
-
|
136
|
-
start_time = time.time()
|
137
|
-
try:
|
138
|
-
broker = AccountBroker(path, logger=self.logger)
|
139
|
-
if not broker.is_deleted():
|
140
|
-
self.validate_per_policy_counts(broker)
|
141
|
-
self.logger.increment('passes')
|
142
|
-
self.account_passes += 1
|
143
|
-
self.logger.debug(_('Audit passed for %s'), broker)
|
144
|
-
except InvalidAccountInfo as e:
|
145
|
-
self.logger.increment('failures')
|
146
|
-
self.account_failures += 1
|
147
|
-
self.logger.error(
|
148
|
-
_('Audit Failed for %(path)s: %(err)s'),
|
149
|
-
{'path': path, 'err': str(e)})
|
150
|
-
except (Exception, Timeout):
|
151
|
-
self.logger.increment('failures')
|
152
|
-
self.account_failures += 1
|
153
|
-
self.logger.exception(_('ERROR Could not get account info %s'),
|
154
|
-
path)
|
155
|
-
self.logger.timing_since('timing', start_time)
|
57
|
+
if __name__ == '__main__':
|
58
|
+
main()
|
swift/account/backend.py
CHANGED
@@ -16,14 +16,11 @@
|
|
16
16
|
Pluggable Back-end for Account Server
|
17
17
|
"""
|
18
18
|
|
19
|
-
from uuid import uuid4
|
20
19
|
|
21
20
|
import sqlite3
|
22
21
|
|
23
|
-
import
|
24
|
-
|
25
|
-
from swift.common.utils import Timestamp
|
26
|
-
from swift.common.db import DatabaseBroker, utf8encode, zero_like
|
22
|
+
from swift.common.utils import Timestamp, RESERVED_BYTE
|
23
|
+
from swift.common.db import DatabaseBroker, zero_like
|
27
24
|
|
28
25
|
DATADIR = 'accounts'
|
29
26
|
|
@@ -154,7 +151,7 @@ class AccountBroker(DatabaseBroker):
|
|
154
151
|
conn.execute('''
|
155
152
|
UPDATE account_stat SET account = ?, created_at = ?, id = ?,
|
156
153
|
put_timestamp = ?, status_changed_at = ?
|
157
|
-
''', (self.account, Timestamp.now().internal,
|
154
|
+
''', (self.account, Timestamp.now().internal, self._new_db_id(),
|
158
155
|
put_timestamp, put_timestamp))
|
159
156
|
|
160
157
|
def create_policy_stat_table(self, conn):
|
@@ -189,20 +186,6 @@ class AccountBroker(DatabaseBroker):
|
|
189
186
|
self._db_version = 1
|
190
187
|
return self._db_version
|
191
188
|
|
192
|
-
def _delete_db(self, conn, timestamp, force=False):
|
193
|
-
"""
|
194
|
-
Mark the DB as deleted.
|
195
|
-
|
196
|
-
:param conn: DB connection object
|
197
|
-
:param timestamp: timestamp to mark as deleted
|
198
|
-
"""
|
199
|
-
conn.execute("""
|
200
|
-
UPDATE account_stat
|
201
|
-
SET delete_timestamp = ?,
|
202
|
-
status = 'DELETED',
|
203
|
-
status_changed_at = ?
|
204
|
-
WHERE delete_timestamp < ? """, (timestamp, timestamp, timestamp))
|
205
|
-
|
206
189
|
def _commit_puts_load(self, item_list, entry):
|
207
190
|
"""See :func:`swift.common.db.DatabaseBroker._commit_puts_load`"""
|
208
191
|
# check to see if the update includes policy_index or not
|
@@ -369,7 +352,7 @@ class AccountBroker(DatabaseBroker):
|
|
369
352
|
''').fetchone())
|
370
353
|
|
371
354
|
def list_containers_iter(self, limit, marker, end_marker, prefix,
|
372
|
-
delimiter, reverse=False):
|
355
|
+
delimiter, reverse=False, allow_reserved=False):
|
373
356
|
"""
|
374
357
|
Get a list of containers sorted by name starting at marker onward, up
|
375
358
|
to limit entries. Entries will begin with the prefix and will not have
|
@@ -381,14 +364,12 @@ class AccountBroker(DatabaseBroker):
|
|
381
364
|
:param prefix: prefix query
|
382
365
|
:param delimiter: delimiter for query
|
383
366
|
:param reverse: reverse the result order.
|
367
|
+
:param allow_reserved: exclude names with reserved-byte by default
|
384
368
|
|
385
369
|
:returns: list of tuples of (name, object_count, bytes_used,
|
386
|
-
put_timestamp,
|
370
|
+
put_timestamp, storage_policy_index, is_subdir)
|
387
371
|
"""
|
388
372
|
delim_force_gte = False
|
389
|
-
if six.PY2:
|
390
|
-
(marker, end_marker, prefix, delimiter) = utf8encode(
|
391
|
-
marker, end_marker, prefix, delimiter)
|
392
373
|
if reverse:
|
393
374
|
# Reverse the markers if we are reversing the listing.
|
394
375
|
marker, end_marker = end_marker, marker
|
@@ -402,7 +383,8 @@ class AccountBroker(DatabaseBroker):
|
|
402
383
|
results = []
|
403
384
|
while len(results) < limit:
|
404
385
|
query = """
|
405
|
-
SELECT name, object_count, bytes_used, put_timestamp,
|
386
|
+
SELECT name, object_count, bytes_used, put_timestamp,
|
387
|
+
{storage_policy_index}, 0
|
406
388
|
FROM container
|
407
389
|
WHERE """
|
408
390
|
query_args = []
|
@@ -424,6 +406,9 @@ class AccountBroker(DatabaseBroker):
|
|
424
406
|
elif prefix:
|
425
407
|
query += ' name >= ? AND'
|
426
408
|
query_args.append(prefix)
|
409
|
+
if not allow_reserved:
|
410
|
+
query += ' name >= ? AND'
|
411
|
+
query_args.append(chr(ord(RESERVED_BYTE) + 1))
|
427
412
|
if self.get_db_version(conn) < 1:
|
428
413
|
query += ' +deleted = 0'
|
429
414
|
else:
|
@@ -431,7 +416,27 @@ class AccountBroker(DatabaseBroker):
|
|
431
416
|
query += ' ORDER BY name %s LIMIT ?' % \
|
432
417
|
('DESC' if reverse else '')
|
433
418
|
query_args.append(limit - len(results))
|
434
|
-
|
419
|
+
try:
|
420
|
+
# First, try querying with the storage policy index.
|
421
|
+
curs = conn.execute(
|
422
|
+
query.format(
|
423
|
+
storage_policy_index="storage_policy_index"),
|
424
|
+
query_args)
|
425
|
+
except sqlite3.OperationalError as err:
|
426
|
+
# If the storage policy column is not available,
|
427
|
+
# the database has not been migrated to the new schema
|
428
|
+
# with storage_policy_index. Re-run the query with
|
429
|
+
# storage_policy_index set to 0, which is what
|
430
|
+
# would be set once the database is migrated.
|
431
|
+
# TODO(callumdickinson): If support for migrating
|
432
|
+
# pre-storage policy versions of Swift is dropped,
|
433
|
+
# then this special handling can be removed.
|
434
|
+
if "no such column: storage_policy_index" in str(err):
|
435
|
+
curs = conn.execute(
|
436
|
+
query.format(storage_policy_index="0"),
|
437
|
+
query_args)
|
438
|
+
else:
|
439
|
+
raise
|
435
440
|
curs.row_factory = None
|
436
441
|
|
437
442
|
# Delimiters without a prefix is ignored, further if there
|
@@ -468,7 +473,7 @@ class AccountBroker(DatabaseBroker):
|
|
468
473
|
delim_force_gte = True
|
469
474
|
dir_name = name[:end + len(delimiter)]
|
470
475
|
if dir_name != orig_marker:
|
471
|
-
results.append([dir_name, 0, 0, '0', 1])
|
476
|
+
results.append([dir_name, 0, 0, '0', -1, 1])
|
472
477
|
curs.close()
|
473
478
|
break
|
474
479
|
results.append(row)
|
swift/account/reaper.py
CHANGED
@@ -19,22 +19,22 @@ import socket
|
|
19
19
|
from logging import DEBUG
|
20
20
|
from math import sqrt
|
21
21
|
from time import time
|
22
|
-
from hashlib import md5
|
23
22
|
import itertools
|
24
23
|
|
25
24
|
from eventlet import GreenPool, sleep, Timeout
|
26
|
-
import six
|
27
25
|
|
28
26
|
import swift.common.db
|
29
27
|
from swift.account.backend import AccountBroker, DATADIR
|
30
28
|
from swift.common.constraints import check_drive
|
29
|
+
from swift.common.daemon import run_daemon
|
31
30
|
from swift.common.direct_client import direct_delete_container, \
|
32
31
|
direct_delete_object, direct_get_container
|
33
32
|
from swift.common.exceptions import ClientException
|
33
|
+
from swift.common.request_helpers import USE_REPLICATION_NETWORK_HEADER
|
34
34
|
from swift.common.ring import Ring
|
35
35
|
from swift.common.ring.utils import is_local_device
|
36
36
|
from swift.common.utils import get_logger, whataremyips, config_true_value, \
|
37
|
-
Timestamp
|
37
|
+
Timestamp, md5, node_to_string, parse_options
|
38
38
|
from swift.common.daemon import Daemon
|
39
39
|
from swift.common.storage_policy import POLICIES, PolicyError
|
40
40
|
|
@@ -65,7 +65,7 @@ class AccountReaper(Daemon):
|
|
65
65
|
self.logger = logger or get_logger(conf, log_route='account-reaper')
|
66
66
|
self.devices = conf.get('devices', '/srv/node')
|
67
67
|
self.mount_check = config_true_value(conf.get('mount_check', 'true'))
|
68
|
-
self.interval =
|
68
|
+
self.interval = float(conf.get('interval', 3600))
|
69
69
|
self.swift_dir = conf.get('swift_dir', '/etc/swift')
|
70
70
|
self.account_ring = None
|
71
71
|
self.container_ring = None
|
@@ -262,16 +262,15 @@ class AccountReaper(Daemon):
|
|
262
262
|
container_limit *= len(nodes)
|
263
263
|
try:
|
264
264
|
containers = list(broker.list_containers_iter(
|
265
|
-
container_limit, '', None, None, None))
|
265
|
+
container_limit, '', None, None, None, allow_reserved=True))
|
266
266
|
while containers:
|
267
267
|
try:
|
268
|
-
for
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
len(nodes)
|
268
|
+
for row in containers:
|
269
|
+
container = row[0]
|
270
|
+
this_shard = (
|
271
|
+
int(md5(container.encode('utf-8'),
|
272
|
+
usedforsecurity=False)
|
273
|
+
.hexdigest(), 16) % len(nodes))
|
275
274
|
if container_shard not in (this_shard, None):
|
276
275
|
continue
|
277
276
|
|
@@ -282,7 +281,8 @@ class AccountReaper(Daemon):
|
|
282
281
|
self.logger.exception(
|
283
282
|
'Exception with containers for account %s', account)
|
284
283
|
containers = list(broker.list_containers_iter(
|
285
|
-
container_limit, containers[-1][0], None, None, None
|
284
|
+
container_limit, containers[-1][0], None, None, None,
|
285
|
+
allow_reserved=True))
|
286
286
|
log_buf = ['Completed pass on account %s' % account]
|
287
287
|
except (Exception, Timeout):
|
288
288
|
self.logger.exception('Exception with account %s', account)
|
@@ -369,22 +369,22 @@ class AccountReaper(Daemon):
|
|
369
369
|
node, part, account, container,
|
370
370
|
marker=marker,
|
371
371
|
conn_timeout=self.conn_timeout,
|
372
|
-
response_timeout=self.node_timeout
|
372
|
+
response_timeout=self.node_timeout,
|
373
|
+
headers={USE_REPLICATION_NETWORK_HEADER: 'true'})
|
373
374
|
self.stats_return_codes[2] = \
|
374
375
|
self.stats_return_codes.get(2, 0) + 1
|
375
376
|
self.logger.increment('return_codes.2')
|
376
377
|
except ClientException as err:
|
377
378
|
if self.logger.getEffectiveLevel() <= DEBUG:
|
378
379
|
self.logger.exception(
|
379
|
-
'Exception with %
|
380
|
+
'Exception with %s', node_to_string(node))
|
380
381
|
self.stats_return_codes[err.http_status // 100] = \
|
381
382
|
self.stats_return_codes.get(err.http_status // 100, 0) + 1
|
382
383
|
self.logger.increment(
|
383
384
|
'return_codes.%d' % (err.http_status // 100,))
|
384
|
-
except (Timeout, socket.error)
|
385
|
+
except (Timeout, socket.error):
|
385
386
|
self.logger.error(
|
386
|
-
'Timeout Exception with %
|
387
|
-
node)
|
387
|
+
'Timeout Exception with %s', node_to_string(node))
|
388
388
|
if not objects:
|
389
389
|
break
|
390
390
|
try:
|
@@ -417,7 +417,8 @@ class AccountReaper(Daemon):
|
|
417
417
|
'X-Account-Partition': str(account_partition),
|
418
418
|
'X-Account-Device': anode['device'],
|
419
419
|
'X-Account-Override-Deleted': 'yes',
|
420
|
-
'X-Timestamp': timestamp.internal
|
420
|
+
'X-Timestamp': timestamp.internal,
|
421
|
+
USE_REPLICATION_NETWORK_HEADER: 'true'})
|
421
422
|
successes += 1
|
422
423
|
self.stats_return_codes[2] = \
|
423
424
|
self.stats_return_codes.get(2, 0) + 1
|
@@ -425,17 +426,16 @@ class AccountReaper(Daemon):
|
|
425
426
|
except ClientException as err:
|
426
427
|
if self.logger.getEffectiveLevel() <= DEBUG:
|
427
428
|
self.logger.exception(
|
428
|
-
'Exception with %
|
429
|
+
'Exception with %s', node_to_string(node))
|
429
430
|
failures += 1
|
430
431
|
self.logger.increment('containers_failures')
|
431
432
|
self.stats_return_codes[err.http_status // 100] = \
|
432
433
|
self.stats_return_codes.get(err.http_status // 100, 0) + 1
|
433
434
|
self.logger.increment(
|
434
435
|
'return_codes.%d' % (err.http_status // 100,))
|
435
|
-
except (Timeout, socket.error)
|
436
|
+
except (Timeout, socket.error):
|
436
437
|
self.logger.error(
|
437
|
-
'Timeout Exception with %
|
438
|
-
node)
|
438
|
+
'Timeout Exception with %s', node_to_string(node))
|
439
439
|
failures += 1
|
440
440
|
self.logger.increment('containers_failures')
|
441
441
|
if successes > failures:
|
@@ -493,7 +493,8 @@ class AccountReaper(Daemon):
|
|
493
493
|
'X-Container-Partition': str(container_partition),
|
494
494
|
'X-Container-Device': cnode['device'],
|
495
495
|
'X-Backend-Storage-Policy-Index': policy_index,
|
496
|
-
'X-Timestamp': timestamp.internal
|
496
|
+
'X-Timestamp': timestamp.internal,
|
497
|
+
USE_REPLICATION_NETWORK_HEADER: 'true'})
|
497
498
|
successes += 1
|
498
499
|
self.stats_return_codes[2] = \
|
499
500
|
self.stats_return_codes.get(2, 0) + 1
|
@@ -501,19 +502,18 @@ class AccountReaper(Daemon):
|
|
501
502
|
except ClientException as err:
|
502
503
|
if self.logger.getEffectiveLevel() <= DEBUG:
|
503
504
|
self.logger.exception(
|
504
|
-
'Exception with %
|
505
|
+
'Exception with %s', node_to_string(node))
|
505
506
|
failures += 1
|
506
507
|
self.logger.increment('objects_failures')
|
507
508
|
self.stats_return_codes[err.http_status // 100] = \
|
508
509
|
self.stats_return_codes.get(err.http_status // 100, 0) + 1
|
509
510
|
self.logger.increment(
|
510
511
|
'return_codes.%d' % (err.http_status // 100,))
|
511
|
-
except (Timeout, socket.error)
|
512
|
+
except (Timeout, socket.error):
|
512
513
|
failures += 1
|
513
514
|
self.logger.increment('objects_failures')
|
514
515
|
self.logger.error(
|
515
|
-
'Timeout Exception with %
|
516
|
-
node)
|
516
|
+
'Timeout Exception with %s', node_to_string(node))
|
517
517
|
if successes > failures:
|
518
518
|
self.stats_objects_deleted += 1
|
519
519
|
self.logger.increment('objects_deleted')
|
@@ -523,3 +523,12 @@ class AccountReaper(Daemon):
|
|
523
523
|
else:
|
524
524
|
self.stats_objects_possibly_remaining += 1
|
525
525
|
self.logger.increment('objects_possibly_remaining')
|
526
|
+
|
527
|
+
|
528
|
+
def main():
|
529
|
+
conf_file, options = parse_options(once=True)
|
530
|
+
run_daemon(AccountReaper, conf_file, **options)
|
531
|
+
|
532
|
+
|
533
|
+
if __name__ == '__main__':
|
534
|
+
main()
|
swift/account/replicator.py
CHANGED
@@ -13,8 +13,12 @@
|
|
13
13
|
# See the License for the specific language governing permissions and
|
14
14
|
# limitations under the License.
|
15
15
|
|
16
|
+
import optparse
|
17
|
+
|
16
18
|
from swift.account.backend import AccountBroker, DATADIR
|
17
19
|
from swift.common import db_replicator
|
20
|
+
from swift.common.daemon import run_daemon
|
21
|
+
from swift.common.utils import parse_options
|
18
22
|
|
19
23
|
|
20
24
|
class AccountReplicator(db_replicator.Replicator):
|
@@ -22,3 +26,21 @@ class AccountReplicator(db_replicator.Replicator):
|
|
22
26
|
brokerclass = AccountBroker
|
23
27
|
datadir = DATADIR
|
24
28
|
default_port = 6202
|
29
|
+
|
30
|
+
|
31
|
+
def main():
|
32
|
+
parser = optparse.OptionParser("%prog CONFIG [options]")
|
33
|
+
parser.add_option('-d', '--devices',
|
34
|
+
help=('Replicate only given devices. '
|
35
|
+
'Comma-separated list. '
|
36
|
+
'Only has effect if --once is used.'))
|
37
|
+
parser.add_option('-p', '--partitions',
|
38
|
+
help=('Replicate only given partitions. '
|
39
|
+
'Comma-separated list. '
|
40
|
+
'Only has effect if --once is used.'))
|
41
|
+
conf_file, options = parse_options(parser=parser, once=True)
|
42
|
+
run_daemon(AccountReplicator, conf_file, **options)
|
43
|
+
|
44
|
+
|
45
|
+
if __name__ == '__main__':
|
46
|
+
main()
|