swift-init return codes

Currently, swift-init returns zero if can't locate config on start.
Because of this problem, it is not possible to distinguish if managed
to start server.

Due to legacy two new complementary options are added. Default is context
dependent.
--strict returns non-zero if some config is missing (default mode
if explicitly named server)
--non-strict returns zero even if some config is missing (default mode
if alias is used)

As a side effect:
If some of demanded servers already running it does not try to start
unstarted and also returns non-zero (in strict mode). That is still sufficient
for the goal of patch.

For future improvements LSB status codes should be considered.

DocImpact
Change-Id: I7750abd4a94875b46f83f4aeee8509388d543c2b
This commit is contained in:
Lisak, Peter 2015-10-02 09:20:17 +02:00 committed by Peter Lisák
parent 166c34383a
commit 7b7c6c5249
4 changed files with 147 additions and 11 deletions

View File

@ -50,6 +50,16 @@ def main():
dest="run_dir", default=RUN_DIR,
help="alternative directory to store running pid files "
"default: %s" % RUN_DIR)
# Changing behaviour if missing config
parser.add_option('--strict', dest='strict', action='store_true',
help="Return non-zero status code if some config is "
"missing. Default mode if server is explicitly "
"named.")
# a negative option for strict
parser.add_option('--non-strict', dest='strict', action='store_false',
help="Return zero status code even if some config is "
"missing. Default mode if server is one of aliases "
"`all`, `main` or `rest`.")
options, args = parser.parse_args()

View File

@ -109,6 +109,8 @@ allows one to use the keywords such as "all", "main" and "rest" for the <server>
.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 "-r RUN_DIR, --run-dir=RUN_DIR directory where the pids will be stored (default /var/run/swift)
.IP "--strict return non-zero status code if some config is missing. Default mode if server is explicitly named."
.IP "--non-strict return zero status code even if some config is missing. Default mode if server is one of aliases `all`, `main` or `rest`."
.PD
.RE

View File

@ -42,6 +42,8 @@ ALL_SERVERS = ['account-auditor', 'account-server', 'container-auditor',
MAIN_SERVERS = ['proxy-server', 'account-server', 'container-server',
'object-server']
REST_SERVERS = [s for s in ALL_SERVERS if s not in MAIN_SERVERS]
# aliases mapping
ALIASES = {'all': ALL_SERVERS, 'main': MAIN_SERVERS, 'rest': REST_SERVERS}
GRACEFUL_SHUTDOWN_SERVERS = MAIN_SERVERS + ['auth-server']
START_ONCE_SERVERS = REST_SERVERS
# These are servers that match a type (account-*, container-*, object-*) but
@ -173,18 +175,17 @@ class Manager(object):
def __init__(self, servers, run_dir=RUN_DIR):
self.server_names = set()
self._default_strict = True
for server in servers:
if server == 'all':
self.server_names.update(ALL_SERVERS)
elif server == 'main':
self.server_names.update(MAIN_SERVERS)
elif server == 'rest':
self.server_names.update(REST_SERVERS)
if server in ALIASES:
self.server_names.update(ALIASES[server])
self._default_strict = False
elif '*' in server:
# convert glob to regex
self.server_names.update([
s for s in ALL_SERVERS if
re.match(server.replace('*', '.*'), s)])
self._default_strict = False
else:
self.server_names.add(server)
@ -211,8 +212,17 @@ class Manager(object):
setup_env()
status = 0
strict = kwargs.get('strict')
# if strict not set explicitly
if strict is None:
strict = self._default_strict
for server in self.servers:
server.launch(**kwargs)
status += 0 if server.launch(**kwargs) else 1
if not strict:
status = 0
if not kwargs.get('daemon', True):
for server in self.servers:
try:

View File

@ -1359,6 +1359,7 @@ class TestServer(unittest.TestCase):
pid_file = self.join_run_dir('proxy-server/2.pid')
self.assertTrue(pid_file in output)
self.assertTrue('already started' in output)
# no running pids
manager.os = MockOs([])
with temptree([], []) as proc_dir:
@ -1551,6 +1552,16 @@ class TestManager(unittest.TestCase):
for server in m:
self.assertTrue(server.server in manager.ALL_SERVERS)
def test_default_strict(self):
# test default strict
m = manager.Manager(['proxy'])
self.assertEqual(m._default_strict, True)
# aliases
m = manager.Manager(['main'])
self.assertEqual(m._default_strict, False)
m = manager.Manager(['proxy*'])
self.assertEqual(m._default_strict, False)
def test_status(self):
class MockServer(object):
@ -1595,7 +1606,12 @@ class TestManager(unittest.TestCase):
def launch(self, **kwargs):
self.called['launch'].append(kwargs)
return {}
if 'noconfig' in self.server:
return {}
elif 'somerunning' in self.server:
return {}
else:
return {1: self.server[0]}
def wait(self, **kwargs):
self.called['wait'].append(kwargs)
@ -1646,6 +1662,102 @@ class TestManager(unittest.TestCase):
kwargs = {'daemon': False}
status = m.start(**kwargs)
# test no config
m = manager.Manager(['proxy', 'noconfig'])
status = m.start()
self.assertEqual(status, 1)
for server in m.servers:
self.assertEqual(server.called['launch'], [{}])
self.assertEqual(server.called['wait'], [{}])
# test no config with --non-strict
m = manager.Manager(['proxy', 'noconfig'])
status = m.start(strict=False)
self.assertEqual(status, 0)
for server in m.servers:
self.assertEqual(server.called['launch'], [{'strict': False}])
self.assertEqual(server.called['wait'], [{'strict': False}])
# test no config --strict
m = manager.Manager(['proxy', 'noconfig'])
status = m.start(strict=True)
self.assertEqual(status, 1)
for server in m.servers:
self.assertEqual(server.called['launch'], [{'strict': True}])
self.assertEqual(server.called['wait'], [{'strict': True}])
# test no config with alias
m = manager.Manager(['main', 'noconfig'])
status = m.start()
self.assertEqual(status, 0)
for server in m.servers:
self.assertEqual(server.called['launch'], [{}])
self.assertEqual(server.called['wait'], [{}])
# test no config with alias and --non-strict
m = manager.Manager(['main', 'noconfig'])
status = m.start(strict=False)
self.assertEqual(status, 0)
for server in m.servers:
self.assertEqual(server.called['launch'], [{'strict': False}])
self.assertEqual(server.called['wait'], [{'strict': False}])
# test no config with alias and --strict
m = manager.Manager(['main', 'noconfig'])
status = m.start(strict=True)
self.assertEqual(status, 1)
for server in m.servers:
self.assertEqual(server.called['launch'], [{'strict': True}])
self.assertEqual(server.called['wait'], [{'strict': True}])
# test already all running
m = manager.Manager(['proxy', 'somerunning'])
status = m.start()
self.assertEqual(status, 1)
for server in m.servers:
self.assertEqual(server.called['launch'], [{}])
self.assertEqual(server.called['wait'], [{}])
# test already all running --non-strict
m = manager.Manager(['proxy', 'somerunning'])
status = m.start(strict=False)
self.assertEqual(status, 0)
for server in m.servers:
self.assertEqual(server.called['launch'], [{'strict': False}])
self.assertEqual(server.called['wait'], [{'strict': False}])
# test already all running --strict
m = manager.Manager(['proxy', 'somerunning'])
status = m.start(strict=True)
self.assertEqual(status, 1)
for server in m.servers:
self.assertEqual(server.called['launch'], [{'strict': True}])
self.assertEqual(server.called['wait'], [{'strict': True}])
# test already all running with alias
m = manager.Manager(['main', 'somerunning'])
status = m.start()
self.assertEqual(status, 0)
for server in m.servers:
self.assertEqual(server.called['launch'], [{}])
self.assertEqual(server.called['wait'], [{}])
# test already all running with alias and --non-strict
m = manager.Manager(['main', 'somerunning'])
status = m.start(strict=False)
self.assertEqual(status, 0)
for server in m.servers:
self.assertEqual(server.called['launch'], [{'strict': False}])
self.assertEqual(server.called['wait'], [{'strict': False}])
# test already all running with alias and --strict
m = manager.Manager(['main', 'somerunning'])
status = m.start(strict=True)
self.assertEqual(status, 1)
for server in m.servers:
self.assertEqual(server.called['launch'], [{'strict': True}])
self.assertEqual(server.called['wait'], [{'strict': True}])
finally:
manager.setup_env = old_setup_env
manager.Server = old_swift_server
@ -1658,7 +1770,8 @@ class TestManager(unittest.TestCase):
def launch(self, **kwargs):
self.called['launch'].append(kwargs)
return {}
# must return non-empty dict if launch succeeded
return {1: self.server[0]}
def wait(self, **kwargs):
self.called['wait'].append(kwargs)
@ -1710,7 +1823,8 @@ class TestManager(unittest.TestCase):
def launch(self, **kwargs):
self.called['launch'].append(kwargs)
return {}
# must return non-empty dict if launch succeeded
return {1: self.server[0]}
def interact(self, **kwargs):
self.called['interact'].append(kwargs)
@ -1753,7 +1867,7 @@ class TestManager(unittest.TestCase):
def launch(self, **kwargs):
self.called['launch'].append(kwargs)
return {}
return {1: 'account-reaper'}
orig_swift_server = manager.Server
try: