diff --git a/nova/cmd/api.py b/nova/cmd/api.py index 36c23b6a2281..6964d77d240f 100644 --- a/nova/cmd/api.py +++ b/nova/cmd/api.py @@ -29,7 +29,7 @@ import six from nova import config from nova import exception -from nova.i18n import _LW +from nova.i18n import _LE, _LW from nova import objects from nova import service from nova import utils @@ -50,14 +50,21 @@ def main(): gmr.TextGuruMeditation.setup_autorun(version) launcher = service.process_launcher() + started = 0 for api in CONF.enabled_apis: should_use_ssl = api in CONF.enabled_ssl_apis try: server = service.WSGIService(api, use_ssl=should_use_ssl) launcher.launch_service(server, workers=server.workers or 1) + started += 1 except exception.PasteAppNotFound as ex: log.warning( _LW("%s. ``enabled_apis`` includes bad values. " "Fix to remove this warning."), six.text_type(ex)) + if started == 0: + log.error(_LE('No APIs were started. ' + 'Check the enabled_apis config option.')) + sys.exit(1) + launcher.wait() diff --git a/nova/tests/unit/cmd/test_nova_api.py b/nova/tests/unit/cmd/test_nova_api.py index 43c31c8c9c67..d9477afbb8e3 100644 --- a/nova/tests/unit/cmd/test_nova_api.py +++ b/nova/tests/unit/cmd/test_nova_api.py @@ -65,3 +65,25 @@ class TestNovaAPI(test.NoDBTestCase): launcher = mock_service.process_launcher.return_value launcher.launch_service.assert_called_once_with( fake_server, workers=123) + + @mock.patch('sys.exit') + def test_fails_if_none_started(self, mock_exit): + mock_exit.side_effect = test.TestingException + self.flags(enabled_apis=[]) + with mock.patch.object(api, 'service') as mock_service: + self.assertRaises(test.TestingException, api.main) + mock_exit.assert_called_once_with(1) + launcher = mock_service.process_launcher.return_value + self.assertFalse(launcher.wait.called) + + @mock.patch('sys.exit') + def test_fails_if_all_failed(self, mock_exit): + mock_exit.side_effect = test.TestingException + self.flags(enabled_apis=['foo', 'bar']) + with mock.patch.object(api, 'service') as mock_service: + mock_service.WSGIService.side_effect = exception.PasteAppNotFound( + name='foo', path='/') + self.assertRaises(test.TestingException, api.main) + mock_exit.assert_called_once_with(1) + launcher = mock_service.process_launcher.return_value + self.assertFalse(launcher.wait.called)