Add --run-dir switch to swift-init

- Add ability to specify an alternative run_dir than the default
  /var/run/swift.
- DocImpact

Change-Id: I17677588f2c8da563b7fec2dc4fdc52da87126ed
This commit is contained in:
Chmouel Boudjnah 2013-01-10 15:08:10 +01:00 committed by Chmouel Boudjnah
parent b8626f9667
commit 3282e3885c
6 changed files with 78 additions and 43 deletions

View File

@ -17,8 +17,8 @@
import sys import sys
from optparse import OptionParser from optparse import OptionParser
from swift.common.manager import Server, Manager, UnknownCommandError, \ from swift.common.manager import Manager, UnknownCommandError, \
KILL_WAIT KILL_WAIT, RUN_DIR
USAGE = """%prog <server> [<server> ...] <command> [options] USAGE = """%prog <server> [<server> ...] <command> [options]
@ -46,6 +46,11 @@ def main():
parser.add_option('-k', '--kill-wait', metavar="N", type="int", parser.add_option('-k', '--kill-wait', metavar="N", type="int",
dest="kill_wait", default=KILL_WAIT, dest="kill_wait", default=KILL_WAIT,
help="wait N seconds for processes to die (default 15)") help="wait N seconds for processes to die (default 15)")
parser.add_option('-r', '--run-dir', type="str",
dest="run_dir", default=RUN_DIR,
help="alternative directory to store running pid files "
"default: %s" % RUN_DIR)
options, args = parser.parse_args() options, args = parser.parse_args()
if len(args) < 2: if len(args) < 2:
@ -62,7 +67,7 @@ def main():
servers.append(command) servers.append(command)
command = servers.pop(0) command = servers.pop(0)
manager = Manager(servers) manager = Manager(servers, run_dir=options.run_dir)
try: try:
status = manager.run_command(command, **options.__dict__) status = manager.run_command(command, **options.__dict__)
except UnknownCommandError: except UnknownCommandError:

View File

@ -6,6 +6,7 @@ import signal
import subprocess import subprocess
import sys import sys
from swift.common.manager import RUN_DIR
if __name__ == '__main__': if __name__ == '__main__':
parser = optparse.OptionParser(usage='''%prog [options] parser = optparse.OptionParser(usage='''%prog [options]
@ -28,10 +29,15 @@ Example (sends SIGTERM to all orphaned Swift processes older than two hours):
parser.add_option('-w', '--wide', dest='wide', default=False, parser.add_option('-w', '--wide', dest='wide', default=False,
action='store_true', action='store_true',
help="don't clip the listing at 80 characters") help="don't clip the listing at 80 characters")
parser.add_option('-r', '--run-dir', type="str",
dest="run_dir", default=RUN_DIR,
help="alternative directory to store running pid files "
"default: %s" % RUN_DIR)
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
pids = [] pids = []
for root, directories, files in os.walk('/var/run/swift'):
for root, directories, files in os.walk(options.run_dir):
for name in files: for name in files:
if name.endswith('.pid'): if name.endswith('.pid'):
pids.append(open(os.path.join(root, name)).read().strip()) pids.append(open(os.path.join(root, name)).read().strip())

View File

@ -108,6 +108,7 @@ allows one to use the keywords such as "all", "main" and "rest" for the <server>
.IP "-g, --graceful \t\t send SIGHUP to supporting servers .IP "-g, --graceful \t\t send SIGHUP to supporting servers
.IP "-c N, --config-num=N \t send command to the Nth server only .IP "-c N, --config-num=N \t send command to the Nth server only
.IP "-k N, --kill-wait=N \t wait N seconds for processes to die (default 15) .IP "-k N, --kill-wait=N \t wait N seconds for processes to die (default 15)
.IP "-r RUN_DIR, --run-dir=RUN_DIR directory where the pids will be stored (default /var/run/swift)
.PD .PD
.RE .RE

View File

@ -25,16 +25,17 @@
.SH SYNOPSIS .SH SYNOPSIS
.LP .LP
.B swift-orphans .B swift-orphans
[-h|--help] [-a|--age] [-k|--kill] [-w|--wide] [-h|--help] [-a|--age] [-k|--kill] [-w|--wide] [-r|--run-dir]
.SH DESCRIPTION .SH DESCRIPTION
.PP .PP
Lists and optionally kills orphaned Swift processes. This is done by scanning Lists and optionally kills orphaned Swift processes. This is done by scanning
/var/run/swift for .pid files and listing any processes that look like Swift /var/run/swift or the directory specified to the -r switch for .pid files and
processes but aren't associated with the pids in those .pid files. Any Swift listing any processes that look like Swift processes but aren't associated with
processes running with the 'once' parameter are ignored, as those are usually the pids in those .pid files. Any Swift processes running with the 'once'
for full-speed audit scans and such. parameter are ignored, as those are usually for full-speed audit scans and
such.
Example (sends SIGTERM to all orphaned Swift processes older than two hours): Example (sends SIGTERM to all orphaned Swift processes older than two hours):
swift-orphans -a 2 -k TERM swift-orphans -a 2 -k TERM

View File

@ -129,7 +129,7 @@ class Manager():
""" """
def __init__(self, servers): def __init__(self, servers, run_dir=RUN_DIR):
server_names = set() server_names = set()
for server in servers: for server in servers:
if server == 'all': if server == 'all':
@ -147,7 +147,7 @@ class Manager():
self.servers = set() self.servers = set()
for name in server_names: for name in server_names:
self.servers.add(Server(name)) self.servers.add(Server(name, run_dir))
@command @command
def status(self, **kwargs): def status(self, **kwargs):
@ -316,13 +316,14 @@ class Server():
:param server: name of server :param server: name of server
""" """
def __init__(self, server): def __init__(self, server, run_dir=RUN_DIR):
if '-' not in server: if '-' not in server:
server = '%s-server' % server server = '%s-server' % server
self.server = server.lower() self.server = server.lower()
self.type = server.rsplit('-', 1)[0] self.type = server.rsplit('-', 1)[0]
self.cmd = 'swift-%s' % server self.cmd = 'swift-%s' % server
self.procs = [] self.procs = []
self.run_dir = run_dir
def __str__(self): def __str__(self):
return self.server return self.server
@ -348,7 +349,7 @@ class Server():
""" """
return conf_file.replace( return conf_file.replace(
os.path.normpath(SWIFT_DIR), RUN_DIR, 1).replace( os.path.normpath(SWIFT_DIR), self.run_dir, 1).replace(
'%s-server' % self.type, self.server, 1).rsplit( '%s-server' % self.type, self.server, 1).rsplit(
'.conf', 1)[0] + '.pid' '.conf', 1)[0] + '.pid'
@ -362,11 +363,11 @@ class Server():
""" """
if self.server in STANDALONE_SERVERS: if self.server in STANDALONE_SERVERS:
return pid_file.replace( return pid_file.replace(
os.path.normpath(RUN_DIR), SWIFT_DIR, 1)\ os.path.normpath(self.run_dir), SWIFT_DIR, 1)\
.rsplit('.pid', 1)[0] + '.conf' .rsplit('.pid', 1)[0] + '.conf'
else: else:
return pid_file.replace( return pid_file.replace(
os.path.normpath(RUN_DIR), SWIFT_DIR, 1).replace( os.path.normpath(self.run_dir), SWIFT_DIR, 1).replace(
self.server, '%s-server' % self.type, 1).rsplit( self.server, '%s-server' % self.type, 1).rsplit(
'.pid', 1)[0] + '.conf' '.pid', 1)[0] + '.conf'
@ -411,7 +412,7 @@ class Server():
:returns: list of pid files :returns: list of pid files
""" """
pid_files = search_tree(RUN_DIR, '%s*' % self.server, '.pid') pid_files = search_tree(self.run_dir, '%s*' % self.server, '.pid')
if kwargs.get('number', 0): if kwargs.get('number', 0):
conf_files = self.conf_files(**kwargs) conf_files = self.conf_files(**kwargs)
# filter pid_files to match the index of numbered conf_file # filter pid_files to match the index of numbered conf_file

View File

@ -181,7 +181,7 @@ class TestManagerModule(unittest.TestCase):
class MockServer(): class MockServer():
def __init__(self, pids, zombie=0): def __init__(self, pids, run_dir=manager.RUN_DIR, zombie=0):
self.heartbeat = (pids for _ in range(zombie)) self.heartbeat = (pids for _ in range(zombie))
def get_running_pids(self): def get_running_pids(self):
@ -311,6 +311,24 @@ class TestServer(unittest.TestCase):
'container-auditor/1/container-auditor.pid') 'container-auditor/1/container-auditor.pid')
self.assertEquals(pid_file, server.get_pid_file_name(conf_file)) self.assertEquals(pid_file, server.get_pid_file_name(conf_file))
def test_get_custom_pid_file_name(self):
random_run_dir = "/random/dir"
get_random_run_dir = lambda x: os.path.join(random_run_dir, x)
server = manager.Server('proxy', run_dir=random_run_dir)
conf_file = self.join_swift_dir('proxy-server.conf')
pid_file = get_random_run_dir('proxy-server.pid')
self.assertEquals(pid_file, server.get_pid_file_name(conf_file))
server = manager.Server('object-replicator', run_dir=random_run_dir)
conf_file = self.join_swift_dir('object-server/1.conf')
pid_file = get_random_run_dir('object-replicator/1.pid')
self.assertEquals(pid_file, server.get_pid_file_name(conf_file))
server = manager.Server('container-auditor', run_dir=random_run_dir)
conf_file = self.join_swift_dir(
'container-server/1/container-auditor.conf')
pid_file = get_random_run_dir(
'container-auditor/1/container-auditor.pid')
self.assertEquals(pid_file, server.get_pid_file_name(conf_file))
def test_get_conf_file_name(self): def test_get_conf_file_name(self):
server = manager.Server('proxy') server = manager.Server('proxy')
conf_file = self.join_swift_dir('proxy-server.conf') conf_file = self.join_swift_dir('proxy-server.conf')
@ -450,7 +468,7 @@ class TestServer(unittest.TestCase):
files, contents = zip(*pid_files) files, contents = zip(*pid_files)
with temptree(files, contents) as t: with temptree(files, contents) as t:
manager.RUN_DIR = t manager.RUN_DIR = t
server = manager.Server('proxy') server = manager.Server('proxy', run_dir=t)
# test get one file # test get one file
iter = server.iter_pid_files() iter = server.iter_pid_files()
pid_file, pid = iter.next() pid_file, pid = iter.next()
@ -459,13 +477,13 @@ class TestServer(unittest.TestCase):
# ... and only one file # ... and only one file
self.assertRaises(StopIteration, iter.next) self.assertRaises(StopIteration, iter.next)
# test invalid value in pid file # test invalid value in pid file
server = manager.Server('auth') server = manager.Server('auth', run_dir=t)
self.assertRaises(ValueError, server.iter_pid_files().next) self.assertRaises(ValueError, server.iter_pid_files().next)
# test object-server doesn't steal pids from object-replicator # test object-server doesn't steal pids from object-replicator
server = manager.Server('object') server = manager.Server('object', run_dir=t)
self.assertRaises(StopIteration, server.iter_pid_files().next) self.assertRaises(StopIteration, server.iter_pid_files().next)
# test multi-pid iter # test multi-pid iter
server = manager.Server('object-replicator') server = manager.Server('object-replicator', run_dir=t)
real_map = { real_map = {
11: self.join_run_dir('object-replicator/1.pid'), 11: self.join_run_dir('object-replicator/1.pid'),
12: self.join_run_dir('object-replicator/2.pid'), 12: self.join_run_dir('object-replicator/2.pid'),
@ -494,7 +512,7 @@ class TestServer(unittest.TestCase):
files, pids = zip(*pid_files) files, pids = zip(*pid_files)
with temptree(files, pids) as t: with temptree(files, pids) as t:
manager.RUN_DIR = t manager.RUN_DIR = t
server = manager.Server('object') server = manager.Server('object', run_dir=t)
# test get all pid files # test get all pid files
real_map = { real_map = {
1: self.join_run_dir('object-server/1.pid'), 1: self.join_run_dir('object-server/1.pid'),
@ -530,7 +548,7 @@ class TestServer(unittest.TestCase):
manager.RUN_DIR = t manager.RUN_DIR = t
# mock os with both pids running # mock os with both pids running
manager.os = MockOs([1, 2]) manager.os = MockOs([1, 2])
server = manager.Server('proxy') server = manager.Server('proxy', run_dir=t)
pids = server.signal_pids(DUMMY_SIG) pids = server.signal_pids(DUMMY_SIG)
self.assertEquals(len(pids), 1) self.assertEquals(len(pids), 1)
self.assert_(1 in pids) self.assert_(1 in pids)
@ -562,7 +580,7 @@ class TestServer(unittest.TestCase):
self.join_run_dir('proxy-server.pid'))) self.join_run_dir('proxy-server.pid')))
# reset mock os with no running pids # reset mock os with no running pids
manager.os = MockOs([]) manager.os = MockOs([])
server = manager.Server('auth') server = manager.Server('auth', run_dir=t)
# test verbose warns on removing pid file # test verbose warns on removing pid file
pids = server.signal_pids(signal.SIG_DFL, verbose=True) pids = server.signal_pids(signal.SIG_DFL, verbose=True)
output = pop_stream(f) output = pop_stream(f)
@ -570,7 +588,7 @@ class TestServer(unittest.TestCase):
auth_pid = self.join_run_dir('auth-server.pid') auth_pid = self.join_run_dir('auth-server.pid')
self.assert_(auth_pid in output) self.assert_(auth_pid in output)
# test warning with insufficient permissions # test warning with insufficient permissions
server = manager.Server('object') server = manager.Server('object', run_dir=t)
pids = server.signal_pids(manager.os.RAISE_EPERM_SIG) pids = server.signal_pids(manager.os.RAISE_EPERM_SIG)
output = pop_stream(f) output = pop_stream(f)
self.assert_('no permission to signal pid 3' in self.assert_('no permission to signal pid 3' in
@ -586,7 +604,7 @@ class TestServer(unittest.TestCase):
) )
with temptree(*zip(*pid_files)) as t: with temptree(*zip(*pid_files)) as t:
manager.RUN_DIR = t manager.RUN_DIR = t
server = manager.Server('test-server') server = manager.Server('test-server', run_dir=t)
# mock os, only pid '1' is running # mock os, only pid '1' is running
manager.os = MockOs([1]) manager.os = MockOs([1])
running_pids = server.get_running_pids() running_pids = server.get_running_pids()
@ -620,7 +638,7 @@ class TestServer(unittest.TestCase):
manager.RUN_DIR = t manager.RUN_DIR = t
# all pids are running # all pids are running
manager.os = MockOs(pids) manager.os = MockOs(pids)
server = manager.Server('thing-doer') server = manager.Server('thing-doer', run_dir=t)
running_pids = server.get_running_pids() running_pids = server.get_running_pids()
# only thing-doer.pid, 1 # only thing-doer.pid, 1
self.assertEquals(len(running_pids), 1) self.assertEquals(len(running_pids), 1)
@ -636,7 +654,7 @@ class TestServer(unittest.TestCase):
self.assert_(os.path.exists, os.path.join(t, f)) self.assert_(os.path.exists, os.path.join(t, f))
# verify that servers are in fact not running # verify that servers are in fact not running
for server_name in ('thing-sayer', 'other-doer', 'other-sayer'): for server_name in ('thing-sayer', 'other-doer', 'other-sayer'):
server = manager.Server(server_name) server = manager.Server(server_name, run_dir=t)
running_pids = server.get_running_pids() running_pids = server.get_running_pids()
self.assertFalse(running_pids) self.assertFalse(running_pids)
# and now all OTHER pid files are cleaned out # and now all OTHER pid files are cleaned out
@ -653,7 +671,7 @@ class TestServer(unittest.TestCase):
files, running_pids = zip(*pid_files) files, running_pids = zip(*pid_files)
with temptree(files, running_pids) as t: with temptree(files, running_pids) as t:
manager.RUN_DIR = t manager.RUN_DIR = t
server = manager.Server('object') server = manager.Server('object', run_dir=t)
# test no servers running # test no servers running
manager.os = MockOs([]) manager.os = MockOs([])
pids = server.kill_running_pids() pids = server.kill_running_pids()
@ -661,8 +679,10 @@ class TestServer(unittest.TestCase):
files, running_pids = zip(*pid_files) files, running_pids = zip(*pid_files)
with temptree(files, running_pids) as t: with temptree(files, running_pids) as t:
manager.RUN_DIR = t manager.RUN_DIR = t
server.run_dir = t
# start up pid # start up pid
manager.os = MockOs([1]) manager.os = MockOs([1])
server = manager.Server('object', run_dir=t)
# test kill one pid # test kill one pid
pids = server.kill_running_pids() pids = server.kill_running_pids()
self.assertEquals(len(pids), 1) self.assertEquals(len(pids), 1)
@ -682,7 +702,7 @@ class TestServer(unittest.TestCase):
# test multi server kill & ignore graceful on unsupported server # test multi server kill & ignore graceful on unsupported server
self.assertFalse('object-replicator' in self.assertFalse('object-replicator' in
manager.GRACEFUL_SHUTDOWN_SERVERS) manager.GRACEFUL_SHUTDOWN_SERVERS)
server = manager.Server('object-replicator') server = manager.Server('object-replicator', run_dir=t)
pids = server.kill_running_pids(graceful=True) pids = server.kill_running_pids(graceful=True)
self.assertEquals(len(pids), 2) self.assertEquals(len(pids), 2)
for pid in (11, 12): for pid in (11, 12):
@ -713,7 +733,7 @@ class TestServer(unittest.TestCase):
with temptree(files, pids) as t: with temptree(files, pids) as t:
manager.RUN_DIR = t manager.RUN_DIR = t
# setup running servers # setup running servers
server = manager.Server('test') server = manager.Server('test', run_dir=t)
# capture stdio # capture stdio
old_stdout = sys.stdout old_stdout = sys.stdout
try: try:
@ -812,6 +832,7 @@ class TestServer(unittest.TestCase):
manager.SWIFT_DIR = swift_dir manager.SWIFT_DIR = swift_dir
with temptree([]) as t: with temptree([]) as t:
manager.RUN_DIR = t manager.RUN_DIR = t
server.run_dir = t
old_subprocess = manager.subprocess old_subprocess = manager.subprocess
try: try:
# test single server process calls spawn once # test single server process calls spawn once
@ -842,7 +863,7 @@ class TestServer(unittest.TestCase):
conf2 = self.join_swift_dir('test-server/2.conf') conf2 = self.join_swift_dir('test-server/2.conf')
conf3 = self.join_swift_dir('test-server/3.conf') conf3 = self.join_swift_dir('test-server/3.conf')
conf4 = self.join_swift_dir('test-server/4.conf') conf4 = self.join_swift_dir('test-server/4.conf')
server = manager.Server('test') server = manager.Server('test', run_dir=t)
# test server run once # test server run once
server.spawn(conf1, once=True) server.spawn(conf1, once=True)
self.assert_(server.procs) self.assert_(server.procs)
@ -1080,11 +1101,11 @@ class TestServer(unittest.TestCase):
with open(os.path.join(t, 'output'), 'w+') as f: with open(os.path.join(t, 'output'), 'w+') as f:
sys.stdout = f sys.stdout = f
# can't start server w/o an conf # can't start server w/o an conf
server = manager.Server('test') server = manager.Server('test', run_dir=t)
self.assertFalse(server.launch()) self.assertFalse(server.launch())
# start mock os running all pids # start mock os running all pids
manager.os = MockOs(pids) manager.os = MockOs(pids)
server = manager.Server('proxy') server = manager.Server('proxy', run_dir=t)
# can't start server if it's already running # can't start server if it's already running
self.assertFalse(server.launch()) self.assertFalse(server.launch())
output = pop_stream(f) output = pop_stream(f)
@ -1178,7 +1199,7 @@ class TestServer(unittest.TestCase):
manager.RUN_DIR = t manager.RUN_DIR = t
# start all pids in mock os # start all pids in mock os
manager.os = MockOs(pids) manager.os = MockOs(pids)
server = manager.Server('account-reaper') server = manager.Server('account-reaper', run_dir=t)
# test kill all running pids # test kill all running pids
pids = server.stop() pids = server.stop()
self.assertEquals(len(pids), 4) self.assertEquals(len(pids), 4)
@ -1269,7 +1290,7 @@ class TestManager(unittest.TestCase):
def test_status(self): def test_status(self):
class MockServer(): class MockServer():
def __init__(self, server): def __init__(self, server, run_dir=manager.RUN_DIR):
self.server = server self.server = server
self.called_kwargs = [] self.called_kwargs = []
@ -1304,7 +1325,7 @@ class TestManager(unittest.TestCase):
getattr(mock_setup_env, 'called', []).append(True) getattr(mock_setup_env, 'called', []).append(True)
class MockServer(): class MockServer():
def __init__(self, server): def __init__(self, server, run_dir=manager.RUN_DIR):
self.server = server self.server = server
self.called = defaultdict(list) self.called = defaultdict(list)
@ -1366,7 +1387,7 @@ class TestManager(unittest.TestCase):
def test_no_wait(self): def test_no_wait(self):
class MockServer(): class MockServer():
def __init__(self, server): def __init__(self, server, run_dir=manager.RUN_DIR):
self.server = server self.server = server
self.called = defaultdict(list) self.called = defaultdict(list)
@ -1417,7 +1438,7 @@ class TestManager(unittest.TestCase):
def test_no_daemon(self): def test_no_daemon(self):
class MockServer(): class MockServer():
def __init__(self, server): def __init__(self, server, run_dir=manager.RUN_DIR):
self.server = server self.server = server
self.called = defaultdict(list) self.called = defaultdict(list)
@ -1452,7 +1473,7 @@ class TestManager(unittest.TestCase):
def test_once(self): def test_once(self):
class MockServer(): class MockServer():
def __init__(self, server): def __init__(self, server, run_dir=manager.RUN_DIR):
self.server = server self.server = server
self.called = defaultdict(list) self.called = defaultdict(list)
@ -1489,16 +1510,16 @@ class TestManager(unittest.TestCase):
def test_stop(self): def test_stop(self):
class MockServerFactory(): class MockServerFactory():
class MockServer(): class MockServer():
def __init__(self, pids): def __init__(self, pids, run_dir=manager.RUN_DIR):
self.pids = pids self.pids = pids
def stop(self, **kwargs): def stop(self, **kwargs):
return self.pids return self.pids
def __init__(self, server_pids): def __init__(self, server_pids, run_dir=manager.RUN_DIR):
self.server_pids = server_pids self.server_pids = server_pids
def __call__(self, server): def __call__(self, server, run_dir=manager.RUN_DIR):
return MockServerFactory.MockServer(self.server_pids[server]) return MockServerFactory.MockServer(self.server_pids[server])
def mock_watch_server_pids(server_pids, **kwargs): def mock_watch_server_pids(server_pids, **kwargs):