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, dest="run_dir", default=RUN_DIR,
help="alternative directory to store running pid files " help="alternative directory to store running pid files "
"default: %s" % RUN_DIR) "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() 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 "-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) .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 .PD
.RE .RE

View File

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

View File

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