From 3bc265281fd7cdaa9656f5c4c5f9325c4d1a37e1 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Fri, 16 Nov 2012 14:27:00 -0800 Subject: [PATCH] Refactor where store drivers are initialized The call to create_stores was happening in the v1 and v2 API controllers. This moves that call and the verification that the default_store exists into the necessary binaries. Fixes bug 1039727. Change-Id: I36542fd9b1d536d6266898766317abe110bb71a2 --- bin/glance-api | 4 +++ bin/glance-cache-prefetcher | 6 ++++- bin/glance-scrubber | 27 ++++++++++++-------- glance/api/v1/images.py | 35 +++----------------------- glance/api/v2/image_data.py | 1 - glance/api/v2/images.py | 1 - glance/image_cache/prefetcher.py | 10 ++------ glance/store/__init__.py | 15 +++++++++++ glance/store/scrubber.py | 2 -- glance/tests/functional/v1/test_api.py | 2 +- glance/tests/unit/base.py | 3 --- glance/tests/unit/test_http_store.py | 1 - 12 files changed, 46 insertions(+), 61 deletions(-) diff --git a/bin/glance-api b/bin/glance-api index 071bf908f2..97599c6559 100755 --- a/bin/glance-api +++ b/bin/glance-api @@ -40,6 +40,7 @@ from glance.common import config from glance.common import wsgi from glance.common import exception from glance.openstack.common import log +import glance.store def fail(returncode, e): @@ -52,6 +53,9 @@ if __name__ == '__main__': config.parse_args() log.setup('glance') + glance.store.create_stores() + glance.store.verify_default_store() + server = wsgi.Server() server.start(config.load_paste_app, default_port=9292) server.wait() diff --git a/bin/glance-cache-prefetcher b/bin/glance-cache-prefetcher index 7948ae9407..9986c928a3 100755 --- a/bin/glance-cache-prefetcher +++ b/bin/glance-cache-prefetcher @@ -1,7 +1,7 @@ #!/usr/bin/env python # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011-2012 OpenStack LLC. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -40,6 +40,7 @@ gettext.install('glance', unicode=1) from glance.common import config from glance.image_cache import prefetcher from glance.openstack.common import cfg +import glance.store CONF = cfg.CONF @@ -49,6 +50,9 @@ if __name__ == '__main__': config.parse_cache_args() config.setup_logging() + glance.store.create_stores() + glance.store.verify_default_store() + app = prefetcher.Prefetcher() app.run() except RuntimeError, e: diff --git a/bin/glance-scrubber b/bin/glance-scrubber index 365ead9faf..55a97ed793 100755 --- a/bin/glance-scrubber +++ b/bin/glance-scrubber @@ -1,7 +1,7 @@ #!/usr/bin/env python # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011-2012 OpenStack LLC. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -36,27 +36,32 @@ gettext.install('glance', unicode=1) from glance.common import config from glance.openstack.common import cfg +import glance.store from glance.store import scrubber CONF = cfg.CONF if __name__ == '__main__': + CONF.register_cli_opt( + cfg.BoolOpt('daemon', + short='D', + default=False, + help='Run as a long-running process. When not ' + 'specified (the default) run the scrub operation ' + 'once and then exits. When specified do not exit ' + 'and run scrub on wakeup_time interval as ' + 'specified in the config.')) + CONF.register_opt(cfg.IntOpt('wakeup_time', default=300)) + try: - CONF.register_cli_opt( - cfg.BoolOpt('daemon', - short='D', - default=False, - help='Run as a long-running process. When not ' - 'specified (the default) run the scrub operation ' - 'once and then exits. When specified do not exit ' - 'and run scrub on wakeup_time interval as ' - 'specified in the config.')) - CONF.register_opt(cfg.IntOpt('wakeup_time', default=300)) config.parse_args() config.setup_logging() + glance.store.create_stores() + glance.store.verify_default_store() + app = scrubber.Scrubber() if CONF.daemon: diff --git a/glance/api/v1/images.py b/glance/api/v1/images.py index cd3cf35cfd..d80c2b5fdf 100644 --- a/glance/api/v1/images.py +++ b/glance/api/v1/images.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010 OpenStack LLC. +# Copyright 2010-2012 OpenStack LLC. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -19,7 +19,6 @@ /images endpoint for Glance v1 API """ -import sys import traceback import eventlet @@ -34,7 +33,6 @@ from webob.exc import (HTTPError, from glance.api import common from glance.api import policy import glance.api.v1 -from glance import context from glance.api.v1 import controller from glance.api.v1 import filters from glance.common import exception @@ -44,8 +42,7 @@ from glance import notifier from glance.openstack.common import cfg import glance.openstack.common.log as logging from glance import registry -from glance.store import (create_stores, - get_from_backend, +from glance.store import (get_from_backend, get_size_from_backend, safe_delete_from_backend, schedule_delayed_delete_from_backend, @@ -53,6 +50,7 @@ from glance.store import (create_stores, get_store_from_scheme) +CONF = cfg.CONF LOG = logging.getLogger(__name__) SUPPORTED_PARAMS = glance.api.v1.SUPPORTED_PARAMS SUPPORTED_FILTERS = glance.api.v1.SUPPORTED_FILTERS @@ -61,14 +59,6 @@ DISK_FORMATS = ['ami', 'ari', 'aki', 'vhd', 'vmdk', 'raw', 'qcow2', 'vdi', 'iso'] -# Defined at module level due to _is_opt_registered -# identity check (not equality). -default_store_opt = cfg.StrOpt('default_store', default='file') - -CONF = cfg.CONF -CONF.register_opt(default_store_opt) - - def validate_image_meta(req, values): name = values.get('name') @@ -126,8 +116,6 @@ class Controller(controller.BaseController): """ def __init__(self): - create_stores() - self.verify_scheme_or_exit(CONF.default_store) self.notifier = notifier.Notifier() registry.configure_registry_client() self.policy = policy.Enforcer() @@ -885,23 +873,6 @@ class Controller(controller.BaseController): request=request, content_type='text/plain') - def verify_scheme_or_exit(self, scheme): - """ - Verifies availability of the storage backend for the - given scheme or exits - - :param scheme: The backend store scheme - """ - try: - get_store_from_scheme(context.RequestContext(), scheme) - except exception.UnknownScheme: - msg = _("Store for scheme %s not found") - LOG.error(msg % scheme) - # message on stderr will only be visible if started directly via - # bin/glance-api, as opposed to being daemonized by glance-control - sys.stderr.write(msg % scheme) - sys.exit(255) - class ImageDeserializer(wsgi.JSONRequestDeserializer): """Handles deserialization of specific controller method requests.""" diff --git a/glance/api/v2/image_data.py b/glance/api/v2/image_data.py index e9083f4088..18b5bb59c8 100644 --- a/glance/api/v2/image_data.py +++ b/glance/api/v2/image_data.py @@ -35,7 +35,6 @@ class ImageDataController(object): self.db_api = db_api or glance.db.get_api() self.db_api.configure_db() self.store_api = store_api or glance.store - self.store_api.create_stores() self.policy = policy_enforcer or policy.Enforcer() self.notifier = notifier or glance.notifier.Notifier() diff --git a/glance/api/v2/images.py b/glance/api/v2/images.py index cac9ce25a1..4887f05143 100644 --- a/glance/api/v2/images.py +++ b/glance/api/v2/images.py @@ -48,7 +48,6 @@ class ImagesController(object): self.policy = policy_enforcer or policy.Enforcer() self.notifier = notifier or glance.notifier.Notifier() self.store_api = store_api or glance.store - self.store_api.create_stores() def _enforce(self, req, action): """Authorize an action against our policies""" diff --git a/glance/image_cache/prefetcher.py b/glance/image_cache/prefetcher.py index dd9081e9c3..3f48ff7cb4 100644 --- a/glance/image_cache/prefetcher.py +++ b/glance/image_cache/prefetcher.py @@ -27,12 +27,6 @@ from glance.image_cache import base import glance.openstack.common.log as logging from glance import registry import glance.store -import glance.store.filesystem -from glance.store import get_from_backend -import glance.store.http -import glance.store.rbd -import glance.store.s3 -import glance.store.swift LOG = logging.getLogger(__name__) @@ -41,7 +35,6 @@ LOG = logging.getLogger(__name__) class Prefetcher(base.CacheApp): def __init__(self): - glance.store.create_stores() super(Prefetcher, self).__init__() registry.configure_registry_client() registry.configure_registry_admin_creds() @@ -60,7 +53,8 @@ class Prefetcher(base.CacheApp): LOG.warn(_("No metadata found for image '%s'"), image_id) return False - image_data, image_size = get_from_backend(ctx, image_meta['location']) + location = image_meta['location'] + image_data, image_size = glance.store.get_from_backend(ctx, location) LOG.debug(_("Caching image '%s'"), image_id) self.cache.cache_image_iter(image_id, image_data) return True diff --git a/glance/store/__init__.py b/glance/store/__init__.py index 2f1828ac30..ff4dd5666a 100644 --- a/glance/store/__init__.py +++ b/glance/store/__init__.py @@ -21,6 +21,7 @@ import time from glance.common import exception from glance.common import utils +import glance.context from glance.openstack.common import cfg from glance.openstack.common import importutils import glance.openstack.common.log as logging @@ -37,6 +38,10 @@ store_opts = [ 'glance.store.s3.Store', 'glance.store.swift.Store', ]), + cfg.StrOpt('default_store', default='file', + help=_("Default scheme to use to store image data. The " + "scheme must be registered by one of the stores " + "defined by the 'known_stores' config option.")), cfg.StrOpt('scrubber_datadir', default='/var/lib/glance/scrubber'), cfg.BoolOpt('delayed_delete', default=False), @@ -168,6 +173,16 @@ def create_stores(): return store_count +def verify_default_store(): + scheme = cfg.CONF.default_store + context = glance.context.RequestContext() + try: + get_store_from_scheme(context, scheme) + except exception.UnknownScheme: + msg = _("Store for scheme %s not found") % scheme + raise RuntimeError(msg) + + def get_store_from_scheme(context, scheme): """ Given a scheme, return the appropriate store object diff --git a/glance/store/scrubber.py b/glance/store/scrubber.py index 4d9755176d..a07e6ae387 100644 --- a/glance/store/scrubber.py +++ b/glance/store/scrubber.py @@ -92,8 +92,6 @@ class Scrubber(object): utils.safe_mkdirs(self.datadir) - store.create_stores() - def run(self, pool, event=None): now = time.time() diff --git a/glance/tests/functional/v1/test_api.py b/glance/tests/functional/v1/test_api.py index 02eac4e1ec..ca890b777d 100644 --- a/glance/tests/functional/v1/test_api.py +++ b/glance/tests/functional/v1/test_api.py @@ -1240,7 +1240,7 @@ class TestApi(functional.FunctionalTest): # ensure that the API server fails to launch self.start_server(self.api_server, expect_launch=False, - expected_exitcode=255, + expected_exitcode=1, **self.__dict__.copy()) def _do_test_post_image_content_bad_format(self, format): diff --git a/glance/tests/unit/base.py b/glance/tests/unit/base.py index 6d2a9ff115..abc0981932 100644 --- a/glance/tests/unit/base.py +++ b/glance/tests/unit/base.py @@ -23,9 +23,6 @@ import stubout from glance.openstack.common import cfg from glance import store -# NOTE(ameade): this import is necessary. Since we override a cfg opt it -# registers we must have that opt loaded. -from glance.store import filesystem from glance.store import location from glance.tests import stubs from glance.tests import utils as test_utils diff --git a/glance/tests/unit/test_http_store.py b/glance/tests/unit/test_http_store.py index 25b356de58..43ea833f52 100644 --- a/glance/tests/unit/test_http_store.py +++ b/glance/tests/unit/test_http_store.py @@ -17,7 +17,6 @@ import stubout -from glance.common import config from glance.common import exception from glance import context from glance.db.sqlalchemy import api as db_api