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.
- 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.2.data/scripts/swift-account-audit → swift/cli/account_audit.py +23 -13
- swift-2.23.2.data/scripts/swift-config → swift/cli/config.py +2 -2
- swift/cli/container_deleter.py +5 -11
- swift-2.23.2.data/scripts/swift-dispersion-populate → swift/cli/dispersion_populate.py +8 -7
- swift/cli/dispersion_report.py +10 -9
- swift-2.23.2.data/scripts/swift-drive-audit → swift/cli/drive_audit.py +63 -21
- swift/cli/form_signature.py +3 -7
- swift-2.23.2.data/scripts/swift-get-nodes → swift/cli/get_nodes.py +8 -2
- swift/cli/info.py +183 -29
- swift/cli/manage_shard_ranges.py +708 -37
- swift-2.23.2.data/scripts/swift-oldies → swift/cli/oldies.py +25 -14
- swift-2.23.2.data/scripts/swift-orphans → swift/cli/orphans.py +7 -3
- swift/cli/recon.py +196 -67
- swift-2.23.2.data/scripts/swift-recon-cron → swift/cli/recon_cron.py +17 -20
- swift-2.23.2.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 +198 -127
- 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 +396 -147
- 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 -81
- 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 +52 -19
- swift/common/middleware/tempauth.py +76 -58
- swift/common/middleware/tempurl.py +192 -174
- 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.2.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} +2191 -2762
- 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 +555 -536
- swift/container/auditor.py +14 -100
- swift/container/backend.py +552 -227
- swift/container/reconciler.py +126 -37
- swift/container/replicator.py +96 -22
- swift/container/server.py +397 -176
- swift/container/sharder.py +1580 -639
- 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 +213 -122
- swift/obj/ssync_receiver.py +145 -85
- swift/obj/ssync_sender.py +113 -54
- swift/obj/updater.py +653 -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 +452 -86
- swift/proxy/controllers/info.py +3 -2
- swift/proxy/controllers/obj.py +1009 -490
- swift/proxy/server.py +185 -112
- swift-2.35.0.dist-info/AUTHORS +501 -0
- swift-2.35.0.dist-info/LICENSE +202 -0
- {swift-2.23.2.dist-info → swift-2.35.0.dist-info}/METADATA +52 -61
- swift-2.35.0.dist-info/RECORD +201 -0
- {swift-2.23.2.dist-info → swift-2.35.0.dist-info}/WHEEL +1 -1
- {swift-2.23.2.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.2.data/scripts/swift-account-auditor +0 -23
- swift-2.23.2.data/scripts/swift-account-info +0 -51
- swift-2.23.2.data/scripts/swift-account-reaper +0 -23
- swift-2.23.2.data/scripts/swift-account-replicator +0 -34
- swift-2.23.2.data/scripts/swift-account-server +0 -23
- swift-2.23.2.data/scripts/swift-container-auditor +0 -23
- swift-2.23.2.data/scripts/swift-container-info +0 -51
- swift-2.23.2.data/scripts/swift-container-reconciler +0 -21
- swift-2.23.2.data/scripts/swift-container-replicator +0 -34
- swift-2.23.2.data/scripts/swift-container-sharder +0 -33
- swift-2.23.2.data/scripts/swift-container-sync +0 -23
- swift-2.23.2.data/scripts/swift-container-updater +0 -23
- swift-2.23.2.data/scripts/swift-dispersion-report +0 -24
- swift-2.23.2.data/scripts/swift-form-signature +0 -20
- swift-2.23.2.data/scripts/swift-init +0 -119
- swift-2.23.2.data/scripts/swift-object-auditor +0 -29
- swift-2.23.2.data/scripts/swift-object-expirer +0 -33
- swift-2.23.2.data/scripts/swift-object-info +0 -60
- swift-2.23.2.data/scripts/swift-object-reconstructor +0 -33
- swift-2.23.2.data/scripts/swift-object-relinker +0 -41
- swift-2.23.2.data/scripts/swift-object-replicator +0 -37
- swift-2.23.2.data/scripts/swift-object-server +0 -27
- swift-2.23.2.data/scripts/swift-object-updater +0 -23
- swift-2.23.2.data/scripts/swift-proxy-server +0 -23
- swift-2.23.2.data/scripts/swift-recon +0 -24
- swift-2.23.2.data/scripts/swift-ring-builder +0 -24
- swift-2.23.2.data/scripts/swift-ring-builder-analyzer +0 -22
- swift-2.23.2.data/scripts/swift-ring-composer +0 -22
- swift-2.23.2.dist-info/DESCRIPTION.rst +0 -166
- swift-2.23.2.dist-info/RECORD +0 -220
- swift-2.23.2.dist-info/metadata.json +0 -1
- swift-2.23.2.dist-info/pbr.json +0 -1
- {swift-2.23.2.dist-info → swift-2.35.0.dist-info}/top_level.txt +0 -0
swift/common/manager.py
CHANGED
@@ -13,18 +13,19 @@
|
|
13
13
|
# See the License for the specific language governing permissions and
|
14
14
|
# limitations under the License.
|
15
15
|
|
16
|
-
|
16
|
+
|
17
17
|
import functools
|
18
18
|
import errno
|
19
|
+
from optparse import OptionParser
|
19
20
|
import os
|
20
21
|
import resource
|
21
22
|
import signal
|
22
23
|
import time
|
23
24
|
import subprocess
|
24
25
|
import re
|
25
|
-
import
|
26
|
-
from swift import gettext_ as _
|
26
|
+
import sys
|
27
27
|
import tempfile
|
28
|
+
from shutil import which
|
28
29
|
|
29
30
|
from swift.common.utils import search_tree, remove_file, write_file, readconf
|
30
31
|
from swift.common.exceptions import InvalidPidFileException
|
@@ -46,6 +47,7 @@ REST_SERVERS = [s for s in ALL_SERVERS if s not in MAIN_SERVERS]
|
|
46
47
|
# aliases mapping
|
47
48
|
ALIASES = {'all': ALL_SERVERS, 'main': MAIN_SERVERS, 'rest': REST_SERVERS}
|
48
49
|
GRACEFUL_SHUTDOWN_SERVERS = MAIN_SERVERS
|
50
|
+
SEAMLESS_SHUTDOWN_SERVERS = MAIN_SERVERS
|
49
51
|
START_ONCE_SERVERS = REST_SERVERS
|
50
52
|
# These are servers that match a type (account-*, container-*, object-*) but
|
51
53
|
# don't use that type-server.conf file and instead use their own.
|
@@ -66,22 +68,22 @@ def setup_env():
|
|
66
68
|
resource.setrlimit(resource.RLIMIT_NOFILE,
|
67
69
|
(MAX_DESCRIPTORS, MAX_DESCRIPTORS))
|
68
70
|
except ValueError:
|
69
|
-
print(
|
70
|
-
|
71
|
+
print("WARNING: Unable to modify file descriptor limit. "
|
72
|
+
"Running as non-root?")
|
71
73
|
|
72
74
|
try:
|
73
75
|
resource.setrlimit(resource.RLIMIT_DATA,
|
74
76
|
(MAX_MEMORY, MAX_MEMORY))
|
75
77
|
except ValueError:
|
76
|
-
print(
|
77
|
-
|
78
|
+
print("WARNING: Unable to modify memory limit. "
|
79
|
+
"Running as non-root?")
|
78
80
|
|
79
81
|
try:
|
80
82
|
resource.setrlimit(resource.RLIMIT_NPROC,
|
81
83
|
(MAX_PROCS, MAX_PROCS))
|
82
84
|
except ValueError:
|
83
|
-
print(
|
84
|
-
|
85
|
+
print("WARNING: Unable to modify max process limit. "
|
86
|
+
"Running as non-root?")
|
85
87
|
|
86
88
|
# Set PYTHON_EGG_CACHE if it isn't already set
|
87
89
|
os.environ.setdefault('PYTHON_EGG_CACHE', tempfile.gettempdir())
|
@@ -97,8 +99,10 @@ def command(func):
|
|
97
99
|
func.publicly_accessible = True
|
98
100
|
|
99
101
|
@functools.wraps(func)
|
100
|
-
def wrapped(*a, **kw):
|
101
|
-
rv = func(*a, **kw)
|
102
|
+
def wrapped(self, *a, **kw):
|
103
|
+
rv = func(self, *a, **kw)
|
104
|
+
if len(self.servers) == 0:
|
105
|
+
return 1
|
102
106
|
return 1 if rv else 0
|
103
107
|
return wrapped
|
104
108
|
|
@@ -173,6 +177,50 @@ def kill_group(pid, sig):
|
|
173
177
|
os.kill(-pid, sig)
|
174
178
|
|
175
179
|
|
180
|
+
def get_child_pids(pid):
|
181
|
+
"""
|
182
|
+
Get the current set of all child PIDs for a PID.
|
183
|
+
|
184
|
+
:param pid: process id
|
185
|
+
"""
|
186
|
+
output = subprocess.check_output(
|
187
|
+
["ps", "--ppid", str(pid), "--no-headers", "-o", "pid"])
|
188
|
+
return {int(pid) for pid in output.split()}
|
189
|
+
|
190
|
+
|
191
|
+
def format_server_name(servername):
|
192
|
+
"""
|
193
|
+
Formats server name as swift compatible server names
|
194
|
+
E.g. swift-object-server
|
195
|
+
|
196
|
+
:param servername: server name
|
197
|
+
:returns: swift compatible server name and its binary name
|
198
|
+
"""
|
199
|
+
if '.' in servername:
|
200
|
+
servername = servername.split('.', 1)[0]
|
201
|
+
if '-' not in servername:
|
202
|
+
servername = '%s-server' % servername
|
203
|
+
cmd = 'swift-%s' % servername
|
204
|
+
return servername, cmd
|
205
|
+
|
206
|
+
|
207
|
+
def verify_server(server):
|
208
|
+
"""
|
209
|
+
Check whether the server is among swift servers or not, and also
|
210
|
+
checks whether the server's binaries are installed or not.
|
211
|
+
|
212
|
+
:param server: name of the server
|
213
|
+
:returns: True, when the server name is valid and its binaries are found.
|
214
|
+
False, otherwise.
|
215
|
+
"""
|
216
|
+
if not server:
|
217
|
+
return False
|
218
|
+
_, cmd = format_server_name(server)
|
219
|
+
if which(cmd) is None:
|
220
|
+
return False
|
221
|
+
return True
|
222
|
+
|
223
|
+
|
176
224
|
class UnknownCommandError(Exception):
|
177
225
|
pass
|
178
226
|
|
@@ -202,7 +250,8 @@ class Manager(object):
|
|
202
250
|
|
203
251
|
self.servers = set()
|
204
252
|
for name in self.server_names:
|
205
|
-
|
253
|
+
if verify_server(name):
|
254
|
+
self.servers.add(Server(name, run_dir))
|
206
255
|
|
207
256
|
def __iter__(self):
|
208
257
|
return iter(self.servers)
|
@@ -239,7 +288,7 @@ class Manager(object):
|
|
239
288
|
try:
|
240
289
|
status += server.interact(**kwargs)
|
241
290
|
except KeyboardInterrupt:
|
242
|
-
print(
|
291
|
+
print('\nuser quit')
|
243
292
|
self.stop(**kwargs)
|
244
293
|
break
|
245
294
|
elif kwargs.get('wait', True):
|
@@ -276,7 +325,7 @@ class Manager(object):
|
|
276
325
|
for server in self.servers:
|
277
326
|
signaled_pids = server.stop(**kwargs)
|
278
327
|
if not signaled_pids:
|
279
|
-
print(
|
328
|
+
print('No %s running' % server)
|
280
329
|
else:
|
281
330
|
server_pids[server] = signaled_pids
|
282
331
|
|
@@ -289,7 +338,7 @@ class Manager(object):
|
|
289
338
|
for server, killed_pid in watch_server_pids(server_pids,
|
290
339
|
interval=kill_wait,
|
291
340
|
**kwargs):
|
292
|
-
print(
|
341
|
+
print("%(server)s (%(pid)s) appears to have stopped" %
|
293
342
|
{'server': server, 'pid': killed_pid})
|
294
343
|
killed_pids.add(killed_pid)
|
295
344
|
if not killed_pids.symmetric_difference(signaled_pids):
|
@@ -302,15 +351,15 @@ class Manager(object):
|
|
302
351
|
if not killed_pids.issuperset(pids):
|
303
352
|
# some pids of this server were not killed
|
304
353
|
if kill_after_timeout:
|
305
|
-
print(
|
306
|
-
|
354
|
+
print('Waited %(kill_wait)s seconds for %(server)s '
|
355
|
+
'to die; killing' %
|
307
356
|
{'kill_wait': kill_wait, 'server': server})
|
308
357
|
# Send SIGKILL to all remaining pids
|
309
358
|
for pid in set(pids.keys()) - killed_pids:
|
310
|
-
print(
|
311
|
-
|
312
|
-
|
313
|
-
|
359
|
+
print('Signal %(server)s pid: %(pid)s signal: '
|
360
|
+
'%(signal)s' % {'server': server,
|
361
|
+
'pid': pid,
|
362
|
+
'signal': signal.SIGKILL})
|
314
363
|
# Send SIGKILL to process group
|
315
364
|
try:
|
316
365
|
kill_group(pid, signal.SIGKILL)
|
@@ -319,8 +368,8 @@ class Manager(object):
|
|
319
368
|
if e.errno != errno.ESRCH:
|
320
369
|
raise
|
321
370
|
else:
|
322
|
-
print(
|
323
|
-
|
371
|
+
print('Waited %(kill_wait)s seconds for %(server)s '
|
372
|
+
'to die; giving up' %
|
324
373
|
{'kill_wait': kill_wait, 'server': server})
|
325
374
|
return 1
|
326
375
|
|
@@ -365,6 +414,31 @@ class Manager(object):
|
|
365
414
|
status += m.start(**kwargs)
|
366
415
|
return status
|
367
416
|
|
417
|
+
@command
|
418
|
+
def reload_seamless(self, **kwargs):
|
419
|
+
"""seamlessly re-exec, then shutdown of old listen sockets on
|
420
|
+
supporting servers
|
421
|
+
"""
|
422
|
+
kwargs.pop('graceful', None)
|
423
|
+
kwargs['seamless'] = True
|
424
|
+
status = 0
|
425
|
+
for server in self.servers:
|
426
|
+
signaled_pids = server.stop(**kwargs)
|
427
|
+
if not signaled_pids:
|
428
|
+
print('No %s running' % server)
|
429
|
+
status += 1
|
430
|
+
return status
|
431
|
+
|
432
|
+
def kill_child_pids(self, **kwargs):
|
433
|
+
"""kill child pids, optionally servicing accepted connections"""
|
434
|
+
status = 0
|
435
|
+
for server in self.servers:
|
436
|
+
signaled_pids = server.kill_child_pids(**kwargs)
|
437
|
+
if not signaled_pids:
|
438
|
+
print('No %s running' % server)
|
439
|
+
status += 1
|
440
|
+
return status
|
441
|
+
|
368
442
|
@command
|
369
443
|
def force_reload(self, **kwargs):
|
370
444
|
"""alias for reload
|
@@ -420,10 +494,8 @@ class Server(object):
|
|
420
494
|
self.server, self.conf = self.server.rsplit('.', 1)
|
421
495
|
else:
|
422
496
|
self.conf = None
|
423
|
-
|
424
|
-
self.server = '%s-server' % self.server
|
497
|
+
self.server, self.cmd = format_server_name(self.server)
|
425
498
|
self.type = self.server.rsplit('-', 1)[0]
|
426
|
-
self.cmd = 'swift-%s' % self.server
|
427
499
|
self.procs = []
|
428
500
|
self.run_dir = run_dir
|
429
501
|
|
@@ -523,7 +595,7 @@ class Server(object):
|
|
523
595
|
|
524
596
|
def dump_found_configs():
|
525
597
|
if found_conf_files:
|
526
|
-
print(
|
598
|
+
print('Found configs:')
|
527
599
|
for i, conf_file in enumerate(found_conf_files):
|
528
600
|
print(' %d) %s' % (i + 1, conf_file))
|
529
601
|
|
@@ -531,18 +603,18 @@ class Server(object):
|
|
531
603
|
# maybe there's a config file(s) out there, but I couldn't find it!
|
532
604
|
if not kwargs.get('quiet'):
|
533
605
|
if number:
|
534
|
-
print(
|
535
|
-
|
606
|
+
print('Unable to locate config number %(number)s for'
|
607
|
+
' %(server)s' %
|
536
608
|
{'number': number, 'server': self.server})
|
537
609
|
else:
|
538
|
-
print(
|
610
|
+
print('Unable to locate config for %s' % self.server)
|
539
611
|
if kwargs.get('verbose') and not kwargs.get('quiet'):
|
540
612
|
dump_found_configs()
|
541
613
|
elif any(["object-expirer" in name for name in conf_files]) and \
|
542
614
|
not kwargs.get('quiet'):
|
543
|
-
print(
|
544
|
-
|
545
|
-
|
615
|
+
print("WARNING: object-expirer.conf is deprecated. "
|
616
|
+
"Move object-expirers' configuration into "
|
617
|
+
"object-server.conf.")
|
546
618
|
if kwargs.get('verbose'):
|
547
619
|
dump_found_configs()
|
548
620
|
|
@@ -578,6 +650,32 @@ class Server(object):
|
|
578
650
|
pid = None
|
579
651
|
yield pid_file, pid
|
580
652
|
|
653
|
+
def _signal_pid(self, sig, pid, pid_file, verbose):
|
654
|
+
try:
|
655
|
+
if sig != signal.SIG_DFL:
|
656
|
+
print('Signal %(server)s pid: %(pid)s signal: '
|
657
|
+
'%(signal)s' %
|
658
|
+
{'server': self.server, 'pid': pid, 'signal': sig})
|
659
|
+
safe_kill(pid, sig, 'swift-%s' % self.server)
|
660
|
+
except InvalidPidFileException:
|
661
|
+
if verbose:
|
662
|
+
print('Removing pid file %(pid_file)s with wrong pid '
|
663
|
+
'%(pid)d' % {'pid_file': pid_file, 'pid': pid})
|
664
|
+
remove_file(pid_file)
|
665
|
+
return False
|
666
|
+
except OSError as e:
|
667
|
+
if e.errno == errno.ESRCH:
|
668
|
+
# pid does not exist
|
669
|
+
if verbose:
|
670
|
+
print("Removing stale pid file %s" % pid_file)
|
671
|
+
remove_file(pid_file)
|
672
|
+
elif e.errno == errno.EPERM:
|
673
|
+
print("No permission to signal PID %d" % pid)
|
674
|
+
return False
|
675
|
+
else:
|
676
|
+
# process exists
|
677
|
+
return True
|
678
|
+
|
581
679
|
def signal_pids(self, sig, **kwargs):
|
582
680
|
"""Send a signal to pids for this server
|
583
681
|
|
@@ -589,33 +687,32 @@ class Server(object):
|
|
589
687
|
pids = {}
|
590
688
|
for pid_file, pid in self.iter_pid_files(**kwargs):
|
591
689
|
if not pid: # Catches None and 0
|
592
|
-
print(
|
690
|
+
print('Removing pid file %s with invalid pid' % pid_file)
|
593
691
|
remove_file(pid_file)
|
594
692
|
continue
|
595
|
-
|
596
|
-
if sig != signal.SIG_DFL:
|
597
|
-
print(_('Signal %(server)s pid: %(pid)s signal: '
|
598
|
-
'%(signal)s') %
|
599
|
-
{'server': self.server, 'pid': pid, 'signal': sig})
|
600
|
-
safe_kill(pid, sig, 'swift-%s' % self.server)
|
601
|
-
except InvalidPidFileException as e:
|
602
|
-
if kwargs.get('verbose'):
|
603
|
-
print(_('Removing pid file %(pid_file)s with wrong pid '
|
604
|
-
'%(pid)d') % {'pid_file': pid_file, 'pid': pid})
|
605
|
-
remove_file(pid_file)
|
606
|
-
except OSError as e:
|
607
|
-
if e.errno == errno.ESRCH:
|
608
|
-
# pid does not exist
|
609
|
-
if kwargs.get('verbose'):
|
610
|
-
print(_("Removing stale pid file %s") % pid_file)
|
611
|
-
remove_file(pid_file)
|
612
|
-
elif e.errno == errno.EPERM:
|
613
|
-
print(_("No permission to signal PID %d") % pid)
|
614
|
-
else:
|
615
|
-
# process exists
|
693
|
+
if self._signal_pid(sig, pid, pid_file, kwargs.get('verbose')):
|
616
694
|
pids[pid] = pid_file
|
617
695
|
return pids
|
618
696
|
|
697
|
+
def signal_children(self, sig, **kwargs):
|
698
|
+
"""Send a signal to child pids for this server
|
699
|
+
|
700
|
+
:param sig: signal to send
|
701
|
+
|
702
|
+
:returns: a dict mapping pids (ints) to pid_files (paths)
|
703
|
+
|
704
|
+
"""
|
705
|
+
pids = {}
|
706
|
+
for pid_file, pid in self.iter_pid_files(**kwargs):
|
707
|
+
if not pid: # Catches None and 0
|
708
|
+
print('Removing pid file %s with invalid pid' % pid_file)
|
709
|
+
remove_file(pid_file)
|
710
|
+
continue
|
711
|
+
for pid in get_child_pids(pid):
|
712
|
+
if self._signal_pid(sig, pid, pid_file, kwargs.get('verbose')):
|
713
|
+
pids[pid] = pid_file
|
714
|
+
return pids
|
715
|
+
|
619
716
|
def get_running_pids(self, **kwargs):
|
620
717
|
"""Get running pids
|
621
718
|
|
@@ -628,17 +725,40 @@ class Server(object):
|
|
628
725
|
"""Kill running pids
|
629
726
|
|
630
727
|
:param graceful: if True, attempt SIGHUP on supporting servers
|
728
|
+
:param seamless: if True, attempt SIGUSR1 on supporting servers
|
631
729
|
|
632
730
|
:returns: a dict mapping pids (ints) to pid_files (paths)
|
633
731
|
|
634
732
|
"""
|
635
733
|
graceful = kwargs.get('graceful')
|
734
|
+
seamless = kwargs.get('seamless')
|
636
735
|
if graceful and self.server in GRACEFUL_SHUTDOWN_SERVERS:
|
637
736
|
sig = signal.SIGHUP
|
737
|
+
elif seamless and self.server in SEAMLESS_SHUTDOWN_SERVERS:
|
738
|
+
sig = signal.SIGUSR1
|
638
739
|
else:
|
639
740
|
sig = signal.SIGTERM
|
640
741
|
return self.signal_pids(sig, **kwargs)
|
641
742
|
|
743
|
+
def kill_child_pids(self, **kwargs):
|
744
|
+
"""Kill child pids, leaving server overseer to respawn them
|
745
|
+
|
746
|
+
:param graceful: if True, attempt SIGHUP on supporting servers
|
747
|
+
:param seamless: if True, attempt SIGUSR1 on supporting servers
|
748
|
+
|
749
|
+
:returns: a dict mapping pids (ints) to pid_files (paths)
|
750
|
+
|
751
|
+
"""
|
752
|
+
graceful = kwargs.get('graceful')
|
753
|
+
seamless = kwargs.get('seamless')
|
754
|
+
if graceful and self.server in GRACEFUL_SHUTDOWN_SERVERS:
|
755
|
+
sig = signal.SIGHUP
|
756
|
+
elif seamless and self.server in SEAMLESS_SHUTDOWN_SERVERS:
|
757
|
+
sig = signal.SIGUSR1
|
758
|
+
else:
|
759
|
+
sig = signal.SIGTERM
|
760
|
+
return self.signal_children(sig, **kwargs)
|
761
|
+
|
642
762
|
def status(self, pids=None, **kwargs):
|
643
763
|
"""Display status of server
|
644
764
|
|
@@ -655,15 +775,15 @@ class Server(object):
|
|
655
775
|
kwargs['quiet'] = True
|
656
776
|
conf_files = self.conf_files(**kwargs)
|
657
777
|
if conf_files:
|
658
|
-
print(
|
778
|
+
print("%(server)s #%(number)d not running (%(conf)s)" %
|
659
779
|
{'server': self.server, 'number': number,
|
660
780
|
'conf': conf_files[0]})
|
661
781
|
else:
|
662
|
-
print(
|
782
|
+
print("No %s running" % self.server)
|
663
783
|
return 1
|
664
784
|
for pid, pid_file in pids.items():
|
665
785
|
conf_file = self.get_conf_file_name(pid_file)
|
666
|
-
print(
|
786
|
+
print("%(server)s running (%(pid)s - %(conf)s)" %
|
667
787
|
{'server': self.server, 'pid': pid, 'conf': conf_file})
|
668
788
|
return 0
|
669
789
|
|
@@ -719,10 +839,8 @@ class Server(object):
|
|
719
839
|
if proc.stdout.closed:
|
720
840
|
output = ''
|
721
841
|
else:
|
722
|
-
output = proc.stdout.read()
|
842
|
+
output = proc.stdout.read().decode('utf8', 'backslashreplace')
|
723
843
|
proc.stdout.close()
|
724
|
-
if not six.PY2:
|
725
|
-
output = output.decode('utf8', 'backslashreplace')
|
726
844
|
|
727
845
|
if kwargs.get('once', False):
|
728
846
|
# if you don't want once to wait you can send it to the
|
@@ -771,16 +889,16 @@ class Server(object):
|
|
771
889
|
# any unstarted instances
|
772
890
|
if conf_file in conf_files:
|
773
891
|
already_started = True
|
774
|
-
print(
|
892
|
+
print("%(server)s running (%(pid)s - %(conf)s)" %
|
775
893
|
{'server': self.server, 'pid': pid, 'conf': conf_file})
|
776
894
|
elif not kwargs.get('number', 0):
|
777
895
|
already_started = True
|
778
|
-
print(
|
896
|
+
print("%(server)s running (%(pid)s - %(pid_file)s)" %
|
779
897
|
{'server': self.server, 'pid': pid,
|
780
898
|
'pid_file': pid_file})
|
781
899
|
|
782
900
|
if already_started:
|
783
|
-
print(
|
901
|
+
print("%s already started..." % self.server)
|
784
902
|
return {}
|
785
903
|
|
786
904
|
if self.server not in START_ONCE_SERVERS:
|
@@ -789,16 +907,16 @@ class Server(object):
|
|
789
907
|
pids = {}
|
790
908
|
for conf_file in conf_files:
|
791
909
|
if kwargs.get('once'):
|
792
|
-
msg =
|
910
|
+
msg = 'Running %s once' % self.server
|
793
911
|
else:
|
794
|
-
msg =
|
912
|
+
msg = 'Starting %s' % self.server
|
795
913
|
print('%s...(%s)' % (msg, conf_file))
|
796
914
|
try:
|
797
915
|
pid = self.spawn(conf_file, **kwargs)
|
798
916
|
except OSError as e:
|
799
917
|
if e.errno == errno.ENOENT:
|
800
918
|
# TODO(clayg): should I check if self.cmd exists earlier?
|
801
|
-
print(
|
919
|
+
print("%s does not exist" % self.cmd)
|
802
920
|
break
|
803
921
|
else:
|
804
922
|
raise
|
@@ -813,3 +931,102 @@ class Server(object):
|
|
813
931
|
|
814
932
|
"""
|
815
933
|
return self.kill_running_pids(**kwargs)
|
934
|
+
|
935
|
+
|
936
|
+
USAGE = \
|
937
|
+
"""%prog <server>[.<config>] [<server>[.<config>] ...] <command> [options]
|
938
|
+
|
939
|
+
where:
|
940
|
+
<server> is the name of a swift service e.g. proxy-server.
|
941
|
+
The '-server' part of the name may be omitted.
|
942
|
+
'all', 'main' and 'rest' are reserved words that represent a
|
943
|
+
group of services.
|
944
|
+
all: Expands to all swift daemons.
|
945
|
+
main: Expands to main swift daemons.
|
946
|
+
(proxy, container, account, object)
|
947
|
+
rest: Expands to all remaining background daemons (beyond
|
948
|
+
"main").
|
949
|
+
(updater, replicator, auditor, etc)
|
950
|
+
<config> is an explicit configuration filename without the
|
951
|
+
.conf extension. If <config> is specified then <server> should
|
952
|
+
refer to a directory containing the configuration file, e.g.:
|
953
|
+
|
954
|
+
swift-init object.1 start
|
955
|
+
|
956
|
+
will start an object-server using the configuration file
|
957
|
+
/etc/swift/object-server/1.conf
|
958
|
+
<command> is a command from the list below.
|
959
|
+
|
960
|
+
Commands:
|
961
|
+
""" + '\n'.join(["%16s: %s" % x for x in Manager.list_commands()])
|
962
|
+
|
963
|
+
|
964
|
+
def main():
|
965
|
+
parser = OptionParser(USAGE)
|
966
|
+
parser.add_option('-v', '--verbose', action="store_true",
|
967
|
+
default=False, help="display verbose output")
|
968
|
+
parser.add_option('-w', '--no-wait', action="store_false", dest="wait",
|
969
|
+
default=True, help="won't wait for server to start "
|
970
|
+
"before returning")
|
971
|
+
parser.add_option('-o', '--once', action="store_true",
|
972
|
+
default=False, help="only run one pass of daemon")
|
973
|
+
# this is a negative option, default is options.daemon = True
|
974
|
+
parser.add_option('-n', '--no-daemon', action="store_false", dest="daemon",
|
975
|
+
default=True, help="start server interactively")
|
976
|
+
parser.add_option('-g', '--graceful', action="store_true",
|
977
|
+
default=False, help="send SIGHUP to supporting servers")
|
978
|
+
parser.add_option('-c', '--config-num', metavar="N", type="int",
|
979
|
+
dest="number", default=0,
|
980
|
+
help="send command to the Nth server only")
|
981
|
+
parser.add_option('-k', '--kill-wait', metavar="N", type="int",
|
982
|
+
dest="kill_wait", default=KILL_WAIT,
|
983
|
+
help="wait N seconds for processes to die (default 15)")
|
984
|
+
parser.add_option('-r', '--run-dir', type="str",
|
985
|
+
dest="run_dir", default=RUN_DIR,
|
986
|
+
help="alternative directory to store running pid files "
|
987
|
+
"default: %s" % RUN_DIR)
|
988
|
+
# Changing behaviour if missing config
|
989
|
+
parser.add_option('--strict', dest='strict', action='store_true',
|
990
|
+
help="Return non-zero status code if some config is "
|
991
|
+
"missing. Default mode if all servers are "
|
992
|
+
"explicitly named.")
|
993
|
+
# a negative option for strict
|
994
|
+
parser.add_option('--non-strict', dest='strict', action='store_false',
|
995
|
+
help="Return zero status code even if some config is "
|
996
|
+
"missing. Default mode if any server is a glob or "
|
997
|
+
"one of aliases `all`, `main` or `rest`.")
|
998
|
+
# SIGKILL daemon after kill_wait period
|
999
|
+
parser.add_option('--kill-after-timeout', dest='kill_after_timeout',
|
1000
|
+
action='store_true',
|
1001
|
+
help="Kill daemon and all children after kill-wait "
|
1002
|
+
"period.")
|
1003
|
+
|
1004
|
+
options, args = parser.parse_args()
|
1005
|
+
|
1006
|
+
if len(args) < 2:
|
1007
|
+
parser.print_help()
|
1008
|
+
print('ERROR: specify server(s) and command')
|
1009
|
+
return 1
|
1010
|
+
|
1011
|
+
command = args[-1]
|
1012
|
+
servers = args[:-1]
|
1013
|
+
|
1014
|
+
# this is just a silly swap for me cause I always try to "start main"
|
1015
|
+
commands = dict(Manager.list_commands()).keys()
|
1016
|
+
if command not in commands and servers[0] in commands:
|
1017
|
+
servers.append(command)
|
1018
|
+
command = servers.pop(0)
|
1019
|
+
|
1020
|
+
manager = Manager(servers, run_dir=options.run_dir)
|
1021
|
+
try:
|
1022
|
+
status = manager.run_command(command, **options.__dict__)
|
1023
|
+
except UnknownCommandError:
|
1024
|
+
parser.print_help()
|
1025
|
+
print('ERROR: unknown command, %s' % command)
|
1026
|
+
status = 1
|
1027
|
+
|
1028
|
+
return 1 if status else 0
|
1029
|
+
|
1030
|
+
|
1031
|
+
if __name__ == "__main__":
|
1032
|
+
sys.exit(main())
|