diff --git a/bin/swift-init b/bin/swift-init index 08dcb7582e..1037ce8eed 100755 --- a/bin/swift-init +++ b/bin/swift-init @@ -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() diff --git a/doc/manpages/swift-init.1 b/doc/manpages/swift-init.1 index 5a24787bfc..3a0e112659 100644 --- a/doc/manpages/swift-init.1 +++ b/doc/manpages/swift-init.1 @@ -109,6 +109,8 @@ allows one to use the keywords such as "all", "main" and "rest" for the .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 diff --git a/swift/common/manager.py b/swift/common/manager.py index ca1bc3ca26..03eb0479e9 100644 --- a/swift/common/manager.py +++ b/swift/common/manager.py @@ -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: diff --git a/test/unit/common/test_manager.py b/test/unit/common/test_manager.py index d408e84262..e62870b5e0 100644 --- a/test/unit/common/test_manager.py +++ b/test/unit/common/test_manager.py @@ -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: