diff options
-rw-r--r-- | glance/common/wsgi.py | 9 | ||||
-rw-r--r-- | glance/common/wsgi_app.py | 11 | ||||
-rw-r--r-- | glance/tests/unit/api/test_cmd.py | 11 | ||||
-rw-r--r-- | glance/tests/unit/common/test_wsgi.py | 24 | ||||
-rw-r--r-- | glance/tests/unit/common/test_wsgi_app.py | 25 |
5 files changed, 79 insertions, 1 deletions
diff --git a/glance/common/wsgi.py b/glance/common/wsgi.py index d9af2280f..452cb3232 100644 --- a/glance/common/wsgi.py +++ b/glance/common/wsgi.py @@ -456,6 +456,15 @@ class BaseServer(metaclass=abc.ABCMeta): self.configure() self.start_wsgi() + # NOTE(danms): This may raise GlanceException if the staging store is + # not configured properly, which will be caught and printed by + # cmd/api.py as an error message and abort startup. + staging = housekeeping.staging_store_path() + if not os.path.exists(staging) and CONF.enabled_import_methods: + LOG.warning(_LW('Import methods are enabled but staging directory ' + '%(path)s does not exist; Imports will fail!'), + {'path': staging}) + cleaner = housekeeping.StagingStoreCleaner(glance.db.get_api()) self.pool.spawn_n(cleaner.clean_orphaned_staging_residue) diff --git a/glance/common/wsgi_app.py b/glance/common/wsgi_app.py index ab1f12170..c2a0cba2a 100644 --- a/glance/common/wsgi_app.py +++ b/glance/common/wsgi_app.py @@ -24,7 +24,7 @@ import glance.async_ from glance.common import config from glance.common import store_utils from glance import housekeeping -from glance.i18n import _ +from glance.i18n import _, _LW from glance import notifier CONF = cfg.CONF @@ -141,6 +141,15 @@ def init_app(): glance_store.create_stores(CONF) glance_store.verify_default_store() + # NOTE(danms): This may raise GlanceException if the staging store is + # not configured properly, which will bubble up to the WSGI server, + # aborting application load as desired. + staging = housekeeping.staging_store_path() + if not os.path.exists(staging) and CONF.enabled_import_methods: + LOG.warning(_LW('Import methods are enabled but staging directory ' + '%(path)s does not exist; Imports will fail!'), + {'path': staging}) + run_staging_cleanup() _setup_os_profiler() diff --git a/glance/tests/unit/api/test_cmd.py b/glance/tests/unit/api/test_cmd.py index 49ec38b14..8038ecb61 100644 --- a/glance/tests/unit/api/test_cmd.py +++ b/glance/tests/unit/api/test_cmd.py @@ -83,6 +83,17 @@ class TestGlanceApiCmd(test_utils.BaseTestCase): exit = self.assertRaises(SystemExit, glance.cmd.api.main) self.assertEqual(2, exit.code) + @mock.patch('glance.async_.set_threadpool_model', new=mock.MagicMock()) + def test_cleaner_store_config_assertion(self): + failure = exc.GlanceException('This is what happens with http://') + self.config(node_staging_uri='http://good.luck') + self.mock_object(glance.common.wsgi.Server, 'start', + self._raise(failure)) + # Make sure that a failure to run the wsgi.Server will call our + # clean print-and-abort handler. + exit = self.assertRaises(SystemExit, glance.cmd.api.main) + self.assertEqual(99, exit.code) + @mock.patch.object(glance.common.config, 'parse_cache_args') @mock.patch.object(logging, 'setup') @mock.patch.object(glance.image_cache.ImageCache, 'init_driver') diff --git a/glance/tests/unit/common/test_wsgi.py b/glance/tests/unit/common/test_wsgi.py index 61b9e74cc..b7c6bedef 100644 --- a/glance/tests/unit/common/test_wsgi.py +++ b/glance/tests/unit/common/test_wsgi.py @@ -637,6 +637,30 @@ class ServerTest(test_utils.BaseTestCase): self.assertEqual(expected_workers, len(server.children)) + def test_invalid_staging_uri(self): + self.config(node_staging_uri='http://good.luck') + server = wsgi.Server() + with mock.patch.object(server, 'start_wsgi'): + # Make sure a stating URI with an bad scheme will abort startup + self.assertRaises(exception.GlanceException, + server.start, 'fake-application', 34567) + + @mock.patch('os.path.exists') + def test_missing_staging_dir(self, mock_exists): + mock_exists.return_value = False + server = wsgi.Server() + with mock.patch.object(server, 'start_wsgi'): + # Since we are mocking out start_wsgi, create a fake pool ourselves + server.pool = mock.MagicMock() + with mock.patch.object(wsgi, 'LOG') as mock_log: + server.start('fake-application', 34567) + mock_exists.assert_called_once_with('/tmp/staging/') + # Make sure a missing staging directory will log a warning. + mock_log.warning.assert_called_once_with( + 'Import methods are enabled but staging directory ' + '%(path)s does not exist; Imports will fail!', + {'path': '/tmp/staging/'}) + class TestHelpers(test_utils.BaseTestCase): diff --git a/glance/tests/unit/common/test_wsgi_app.py b/glance/tests/unit/common/test_wsgi_app.py index 87afc40d7..3de42cb77 100644 --- a/glance/tests/unit/common/test_wsgi_app.py +++ b/glance/tests/unit/common/test_wsgi_app.py @@ -19,6 +19,7 @@ from unittest import mock from glance.api import common from glance.api.v2 import cached_images import glance.async_ +from glance.common import exception from glance.common import wsgi_app from glance.tests import utils as test_utils @@ -114,3 +115,27 @@ class TestWsgiAppInit(test_utils.BaseTestCase): mock_conf.return_value = [] wsgi_app.init_app() mock_Timer.assert_not_called() + + @mock.patch('glance.common.wsgi_app._get_config_files') + @mock.patch('glance.async_._THREADPOOL_MODEL', new=None) + @mock.patch('glance.common.config.load_paste_app', new=mock.MagicMock()) + def test_staging_store_uri_assertion(self, mock_conf): + self.config(node_staging_uri='http://good.luck') + mock_conf.return_value = [] + # Make sure a staging URI with a bad scheme will abort startup + self.assertRaises(exception.GlanceException, wsgi_app.init_app) + + @mock.patch('glance.common.wsgi_app._get_config_files') + @mock.patch('glance.async_._THREADPOOL_MODEL', new=None) + @mock.patch('glance.common.config.load_paste_app', new=mock.MagicMock()) + @mock.patch('os.path.exists') + def test_staging_store_path_check(self, mock_exists, mock_conf): + mock_exists.return_value = False + mock_conf.return_value = [] + with mock.patch.object(wsgi_app, 'LOG') as mock_log: + wsgi_app.init_app() + # Make sure that a missing staging directory will log a warning. + mock_log.warning.assert_called_once_with( + 'Import methods are enabled but staging directory ' + '%(path)s does not exist; Imports will fail!', + {'path': '/tmp/staging/'}) |