diff --git a/glance/common/exception.py b/glance/common/exception.py index 597e54c9e1..9fa9b1a3e9 100644 --- a/glance/common/exception.py +++ b/glance/common/exception.py @@ -92,11 +92,6 @@ class StorageWriteDenied(GlanceException): message = _("Permission to write image storage media denied.") -class ImportFailure(GlanceException): - message = _("Failed to import requested object/class: '%(import_str)s'. " - "Reason: %(reason)s") - - class AuthBadRequest(GlanceException): message = _("Connect error/bad request to Auth service at URL %(url)s.") diff --git a/glance/common/utils.py b/glance/common/utils.py index 8263b651bb..c86ff9dfc0 100644 --- a/glance/common/utils.py +++ b/glance/common/utils.py @@ -149,27 +149,6 @@ def bool_from_string(subject): return False -def import_class(import_str): - """Returns a class from a string including module and class""" - mod_str, _sep, class_str = import_str.rpartition('.') - try: - __import__(mod_str) - return getattr(sys.modules[mod_str], class_str) - except (ImportError, ValueError, AttributeError), e: - raise exception.ImportFailure(import_str=import_str, - reason=e) - - -def import_object(import_str): - """Returns an object including a module or module and class""" - try: - __import__(import_str) - return sys.modules[import_str] - except ImportError: - cls = import_class(import_str) - return cls() - - def generate_uuid(): return str(uuid.uuid4()) diff --git a/glance/common/wsgi.py b/glance/common/wsgi.py index 0e83ecd433..7e58edaf6c 100644 --- a/glance/common/wsgi.py +++ b/glance/common/wsgi.py @@ -43,6 +43,7 @@ import webob.exc from glance.common import exception from glance.common import utils from glance.openstack.common import cfg +from glance.openstack.common import importutils bind_opts = [ @@ -564,7 +565,7 @@ class BasePasteFactory(object): we strip() the value before using it. """ class_name = local_conf[self.KEY].replace(':', '.').strip() - return utils.import_class(class_name) + return importutils.import_class(class_name) class AppFactory(BasePasteFactory): diff --git a/glance/image_cache/__init__.py b/glance/image_cache/__init__.py index 8202a32129..d63cd9581e 100644 --- a/glance/image_cache/__init__.py +++ b/glance/image_cache/__init__.py @@ -24,6 +24,7 @@ import logging from glance.common import exception from glance.common import utils from glance.openstack.common import cfg +from glance.openstack.common import importutils logger = logging.getLogger(__name__) DEFAULT_MAX_CACHE_SIZE = 10 * 1024 * 1024 * 1024 # 10 GB @@ -52,17 +53,17 @@ class ImageCache(object): driver_name = self.conf.image_cache_driver driver_module = (__name__ + '.drivers.' + driver_name + '.Driver') try: - self.driver_class = utils.import_class(driver_module) + self.driver_class = importutils.import_class(driver_module) logger.info(_("Image cache loaded driver '%s'.") % driver_name) - except exception.ImportFailure, import_err: + except ImportError, import_err: logger.warn(_("Image cache driver " "'%(driver_name)s' failed to load. " "Got error: '%(import_err)s.") % locals()) driver_module = __name__ + '.drivers.sqlite.Driver' logger.info(_("Defaulting to SQLite driver.")) - self.driver_class = utils.import_class(driver_module) + self.driver_class = importutils.import_class(driver_module) self.configure_driver() def configure_driver(self): @@ -80,7 +81,7 @@ class ImageCache(object): "Got error: '%(config_err)s") % locals()) logger.info(_("Defaulting to SQLite driver.")) default_module = __name__ + '.drivers.sqlite.Driver' - self.driver_class = utils.import_class(default_module) + self.driver_class = importutils.import_class(default_module) self.driver = self.driver_class(self.conf) self.driver.configure() diff --git a/glance/notifier/__init__.py b/glance/notifier/__init__.py index 14efb3c117..16b7b3224a 100644 --- a/glance/notifier/__init__.py +++ b/glance/notifier/__init__.py @@ -21,8 +21,8 @@ import socket import uuid from glance.common import exception -from glance.common import utils from glance.openstack.common import cfg +from glance.openstack.common import importutils _STRATEGIES = { @@ -45,7 +45,8 @@ class Notifier(object): conf.register_opts(self.opts) strategy = conf.notifier_strategy try: - self.strategy = utils.import_class(_STRATEGIES[strategy])(conf) + strategy_cls = _STRATEGIES[strategy] + self.strategy = importutils.import_class(strategy_cls)(conf) except (KeyError, ImportError): raise exception.InvalidNotifierStrategy(strategy=strategy) diff --git a/glance/openstack/common/importutils.py b/glance/openstack/common/importutils.py new file mode 100644 index 0000000000..7654af5b95 --- /dev/null +++ b/glance/openstack/common/importutils.py @@ -0,0 +1,44 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 OpenStack LLC. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +""" +Import related utilities and helper functions. +""" + +import sys + + +def import_class(import_str): + """Returns a class from a string including module and class""" + mod_str, _sep, class_str = import_str.rpartition('.') + try: + __import__(mod_str) + return getattr(sys.modules[mod_str], class_str) + except (ImportError, ValueError, AttributeError), exc: + raise ImportError('Class %s cannot be found (%s)' % + (class_str, str(exc))) + + +def import_object(import_str, *args, **kwargs): + """Import a class and return an instance of it.""" + return import_class(import_str)(*args, **kwargs) + + +def import_module(import_str): + """Import a module.""" + __import__(import_str) + return sys.modules[import_str] diff --git a/glance/store/__init__.py b/glance/store/__init__.py index 4a8e6e24d1..38d150d065 100644 --- a/glance/store/__init__.py +++ b/glance/store/__init__.py @@ -23,6 +23,7 @@ import time from glance.common import exception from glance.common import utils from glance.openstack.common import cfg +from glance.openstack.common import importutils from glance import registry from glance.store import location @@ -129,7 +130,7 @@ def _get_store_class(store_entry): store_cls = None try: logger.debug("Attempting to import store %s", store_entry) - store_cls = utils.import_class(store_entry) + store_cls = importutils.import_class(store_entry) except exception.NotFound: raise BackendException('Unable to load store. ' 'Could not find a class named %s.' diff --git a/glance/store/base.py b/glance/store/base.py index 1bb80bd303..ff03a74600 100644 --- a/glance/store/base.py +++ b/glance/store/base.py @@ -20,7 +20,7 @@ import logging from glance.common import exception -from glance.common import utils +from glance.openstack.common import importutils logger = logging.getLogger('glance.store.base') @@ -68,7 +68,7 @@ class Store(object): if not self.store_location_class: class_name = "%s.StoreLocation" % (self.__module__) logger.debug("Late loading location class %s", class_name) - self.store_location_class = utils.import_class(class_name) + self.store_location_class = importutils.import_class(class_name) return self.store_location_class def configure_add(self): diff --git a/glance/tests/unit/test_misc.py b/glance/tests/unit/test_misc.py index 3364a0797a..41ce66cd49 100644 --- a/glance/tests/unit/test_misc.py +++ b/glance/tests/unit/test_misc.py @@ -23,6 +23,7 @@ import re from glance.common import crypt from glance.common import exception from glance.common import utils +from glance.openstack.common import importutils from glance.tests import utils as test_utils @@ -45,36 +46,6 @@ class UtilsTestCase(test_utils.BaseTestCase): self.assertFalse(utils.bool_from_string(value), "Got True for value: %r" % value) - def test_import_class_or_object(self): - # Test that import_class raises a descriptive error when the - # class to import could not be found. - self.assertRaises(exception.ImportFailure, utils.import_class, - 'nomodule') - - self.assertRaises(exception.ImportFailure, utils.import_class, - 'mymodule.nonexistingclass') - - self.assertRaises(exception.ImportFailure, utils.import_class, - 'sys.nonexistingclass') - - self.assertRaises(exception.ImportFailure, utils.import_object, - 'os.path.NONEXISTINGOBJECT') - - store_class = utils.import_class('glance.store.s3.Store') - - self.assertTrue(store_class.__name__ == 'Store') - - # Try importing an object by supplying a class and - # verify the object's class name is the same as that supplied - ex_obj = utils.import_object('glance.common.exception.GlanceException') - - self.assertTrue(ex_obj.__class__.__name__ == 'GlanceException') - - # Try importing a module itself - module_obj = utils.import_object('glance.registry') - - self.assertEqual('glance.registry', module_obj.__package__) - def test_isotime(self): dt1 = datetime.datetime(2001, 11, 10, 1, 2, 3) self.assertEqual('2001-11-10T01:02:03Z', utils.isotime(dt1)) diff --git a/glance/tests/unit/test_notifier.py b/glance/tests/unit/test_notifier.py index dee1361551..c6c1f36372 100644 --- a/glance/tests/unit/test_notifier.py +++ b/glance/tests/unit/test_notifier.py @@ -28,9 +28,9 @@ except ImportError: import stubout from glance.common import exception -from glance.common import utils as common_utils from glance import notifier import glance.notifier.notify_kombu +from glance.openstack.common import importutils from glance.tests import utils @@ -105,8 +105,8 @@ class TestRabbitNotifier(utils.BaseTestCase): rabbit_self.connection = 'fake_connection' return None - self.notify_kombu = common_utils.import_object( - "glance.notifier.notify_kombu") + self.notify_kombu = importutils.import_module("glance.notifier." + "notify_kombu") self.notify_kombu.RabbitStrategy._send_message = self._send_message self.notify_kombu.RabbitStrategy._connect = _fake_connect self.called = False @@ -302,8 +302,8 @@ class TestQpidNotifier(utils.BaseTestCase): qpid.messaging.Sender = lambda *_x, **_y: self.mock_sender qpid.messaging.Receiver = lambda *_x, **_y: self.mock_receiver - self.notify_qpid = common_utils.import_object( - "glance.notifier.notify_qpid") + self.notify_qpid = importutils.import_module("glance.notifier." + "notify_qpid") def tearDown(self): super(TestQpidNotifier, self).tearDown() diff --git a/openstack-common.conf b/openstack-common.conf index b018c97264..cf0f3e284e 100644 --- a/openstack-common.conf +++ b/openstack-common.conf @@ -1,7 +1,7 @@ [DEFAULT] # The list of modules to copy from openstack-common -modules=iniparser,cfg,setup +modules=cfg,importutils,iniparser,setup # The base module to hold the copy of openstack.common base=glance