From e80a87352431ee6f05729be32296e90b2d9c13c7 Mon Sep 17 00:00:00 2001 From: Dan Smith Date: Fri, 22 Apr 2016 14:22:08 -0700 Subject: [PATCH] Fail to start nova-api if no APIs were able to be started This helps to make it clear that either you specified no API services, or you specified all bad ones, or that you fat-fingered the thing entirely. If we can't start any, we shouldn't start the process acting like we did and then wait for you to figure out the hard way that we aren't actually listening for any requests. Change-Id: I864486a58cf3fde35647ae3b8d2ad917c809ea54 Related-Bug: #1572495 (cherry picked from commit 9b2329d10021a7fa5f43b9fd8be3c833dd7212d0) --- nova/cmd/api.py | 9 ++++++++- nova/tests/unit/cmd/test_nova_api.py | 22 ++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) 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)