diff --git a/bin/nova-dhcpbridge b/bin/nova-dhcpbridge index a3cbe168c..2f1ef6cec 100755 --- a/bin/nova-dhcpbridge +++ b/bin/nova-dhcpbridge @@ -40,6 +40,7 @@ from nova import db from nova import flags from nova import log as logging from nova.network import linux_net +from nova.openstack.common import importutils from nova import rpc from nova import utils @@ -52,7 +53,7 @@ def add_lease(mac, ip_address): """Set the IP that was assigned by the DHCP server.""" if FLAGS.fake_rabbit: LOG.debug(_("leasing ip")) - network_manager = utils.import_object(FLAGS.network_manager) + network_manager = importutils.import_object(FLAGS.network_manager) network_manager.lease_fixed_ip(context.get_admin_context(), ip_address) else: @@ -74,7 +75,7 @@ def del_lease(mac, ip_address): """Called when a lease expires.""" if FLAGS.fake_rabbit: LOG.debug(_("releasing ip")) - network_manager = utils.import_object(FLAGS.network_manager) + network_manager = importutils.import_object(FLAGS.network_manager) network_manager.release_fixed_ip(context.get_admin_context(), ip_address) else: @@ -88,7 +89,7 @@ def init_leases(network_id): """Get the list of hosts for a network.""" ctxt = context.get_admin_context() network_ref = db.network_get(ctxt, network_id) - network_manager = utils.import_object(FLAGS.network_manager) + network_manager = importutils.import_object(FLAGS.network_manager) return network_manager.get_dhcp_leases(ctxt, network_ref) diff --git a/bin/nova-manage b/bin/nova-manage index dbb22d794..7b33fa4d3 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -76,21 +76,22 @@ if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'nova', '__init__.py')): gettext.install('nova', unicode=1) +from nova.api.ec2 import ec2utils +from nova.auth import manager from nova.compat import flagfile +from nova.compute import instance_types from nova import context from nova import crypto from nova import db +from nova.db import migration from nova import exception from nova import flags from nova import log as logging +from nova.openstack.common import importutils from nova import quota from nova import rpc from nova import utils from nova import version -from nova.api.ec2 import ec2utils -from nova.auth import manager -from nova.compute import instance_types -from nova.db import migration from nova.volume import volume_types FLAGS = flags.FLAGS @@ -794,7 +795,7 @@ class NetworkCommands(object): fixed_cidr = netaddr.IPNetwork(fixed_cidr) # create the network - net_manager = utils.import_object(FLAGS.network_manager) + net_manager = importutils.import_object(FLAGS.network_manager) net_manager.create_networks(context.get_admin_context(), label=label, cidr=fixed_range_v4, @@ -863,7 +864,7 @@ class NetworkCommands(object): if fixed_range is None and uuid is None: raise Exception("Please specify either fixed_range or uuid") - net_manager = utils.import_object(FLAGS.network_manager) + net_manager = importutils.import_object(FLAGS.network_manager) if "QuantumManager" in FLAGS.network_manager: if uuid is None: raise Exception("UUID is required to delete Quantum Networks") diff --git a/nova/auth/manager.py b/nova/auth/manager.py index f03e453b8..4f3787591 100644 --- a/nova/auth/manager.py +++ b/nova/auth/manager.py @@ -35,6 +35,7 @@ from nova import exception from nova import flags from nova import log as logging from nova.openstack.common import cfg +from nova.openstack.common import importutils from nova import utils from nova.auth import signer @@ -247,9 +248,9 @@ class AuthManager(object): __init__ is run every time AuthManager() is called, so we only reset the driver if it is not set or a new driver is specified. """ - self.network_manager = utils.import_object(FLAGS.network_manager) + self.network_manager = importutils.import_object(FLAGS.network_manager) if driver or not getattr(self, 'driver', None): - self.driver = utils.import_class(driver or FLAGS.auth_driver) + self.driver = importutils.import_class(driver or FLAGS.auth_driver) if AuthManager.mc is None: AuthManager.mc = memcache.Client(FLAGS.memcached_servers, debug=0) diff --git a/nova/notifier/api.py b/nova/notifier/api.py index 5af16cbac..4eff31bc4 100644 --- a/nova/notifier/api.py +++ b/nova/notifier/api.py @@ -19,6 +19,7 @@ from nova import flags from nova import utils from nova import log as logging from nova.openstack.common import cfg +from nova.openstack.common import importutils LOG = logging.getLogger(__name__) @@ -117,7 +118,7 @@ def notify(publisher_id, event_type, priority, payload): # Ensure everything is JSON serializable. payload = utils.to_primitive(payload, convert_instances=True) - driver = utils.import_object(FLAGS.notification_driver) + driver = importutils.import_module(FLAGS.notification_driver) msg = dict(message_id=str(uuid.uuid4()), publisher_id=publisher_id, event_type=event_type, diff --git a/nova/notifier/list_notifier.py b/nova/notifier/list_notifier.py index 9fb8a55e7..c3f27fd0e 100644 --- a/nova/notifier/list_notifier.py +++ b/nova/notifier/list_notifier.py @@ -13,11 +13,11 @@ # License for the specific language governing permissions and limitations # under the License. -from nova import exception from nova import flags from nova import log as logging from nova.openstack.common import cfg -from nova import utils +from nova.openstack.common import exception as common_exception +from nova.openstack.common import importutils list_notifier_drivers_opt = cfg.MultiStrOpt('list_notifier_drivers', @@ -49,8 +49,8 @@ def _get_drivers(): drivers = [] for notification_driver in FLAGS.list_notifier_drivers: try: - drivers.append(utils.import_object(notification_driver)) - except exception.ClassNotFound as e: + drivers.append(importutils.import_module(notification_driver)) + except ImportError as e: drivers.append(ImportFailureNotifier(e)) return drivers diff --git a/nova/openstack/common/exception.py b/nova/openstack/common/exception.py new file mode 100644 index 000000000..ba32da550 --- /dev/null +++ b/nova/openstack/common/exception.py @@ -0,0 +1,147 @@ +# 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. + +""" +Exceptions common to OpenStack projects +""" + +import logging + + +class ProcessExecutionError(IOError): + def __init__(self, stdout=None, stderr=None, exit_code=None, cmd=None, + description=None): + if description is None: + description = "Unexpected error while running command." + if exit_code is None: + exit_code = '-' + message = "%s\nCommand: %s\nExit code: %s\nStdout: %r\nStderr: %r" % ( + description, cmd, exit_code, stdout, stderr) + IOError.__init__(self, message) + + +class Error(Exception): + def __init__(self, message=None): + super(Error, self).__init__(message) + + +class ApiError(Error): + def __init__(self, message='Unknown', code='Unknown'): + self.message = message + self.code = code + super(ApiError, self).__init__('%s: %s' % (code, message)) + + +class NotFound(Error): + pass + + +class UnknownScheme(Error): + + msg = "Unknown scheme '%s' found in URI" + + def __init__(self, scheme): + msg = self.__class__.msg % scheme + super(UnknownScheme, self).__init__(msg) + + +class BadStoreUri(Error): + + msg = "The Store URI %s was malformed. Reason: %s" + + def __init__(self, uri, reason): + msg = self.__class__.msg % (uri, reason) + super(BadStoreUri, self).__init__(msg) + + +class Duplicate(Error): + pass + + +class NotAuthorized(Error): + pass + + +class NotEmpty(Error): + pass + + +class Invalid(Error): + pass + + +class BadInputError(Exception): + """Error resulting from a client sending bad input to a server""" + pass + + +class MissingArgumentError(Error): + pass + + +class DatabaseMigrationError(Error): + pass + + +class ClientConnectionError(Exception): + """Error resulting from a client connecting to a server""" + pass + + +def wrap_exception(f): + def _wrap(*args, **kw): + try: + return f(*args, **kw) + except Exception, e: + if not isinstance(e, Error): + #exc_type, exc_value, exc_traceback = sys.exc_info() + logging.exception('Uncaught exception') + #logging.error(traceback.extract_stack(exc_traceback)) + raise Error(str(e)) + raise + _wrap.func_name = f.func_name + return _wrap + + +class OpenstackException(Exception): + """ + Base Exception + + To correctly use this class, inherit from it and define + a 'message' property. That message will get printf'd + with the keyword arguments provided to the constructor. + """ + message = "An unknown exception occurred" + + def __init__(self, **kwargs): + try: + self._error_string = self.message % kwargs + + except Exception: + # at least get the core message out if something happened + self._error_string = self.message + + def __str__(self): + return self._error_string + + +class MalformedRequestBody(OpenstackException): + message = "Malformed message body: %(reason)s" + + +class InvalidContentType(OpenstackException): + message = "Invalid content type %(content_type)s" diff --git a/nova/openstack/common/importutils.py b/nova/openstack/common/importutils.py new file mode 100644 index 000000000..2d8bc09a9 --- /dev/null +++ b/nova/openstack/common/importutils.py @@ -0,0 +1,45 @@ +# 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 + +from nova.openstack.common import exception + + +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): + raise exception.NotFound('Class %s cannot be found' % class_str) + + +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/nova/rpc/__init__.py b/nova/rpc/__init__.py index 45d8c00b2..f5b9fa8da 100644 --- a/nova/rpc/__init__.py +++ b/nova/rpc/__init__.py @@ -18,7 +18,7 @@ # under the License. from nova.openstack.common import cfg -from nova import utils +from nova.openstack.common import importutils rpc_opts = [ @@ -219,5 +219,5 @@ def _get_impl(): """Delay import of rpc_backend until configuration is loaded.""" global _RPCIMPL if _RPCIMPL is None: - _RPCIMPL = utils.import_object(_CONF.rpc_backend) + _RPCIMPL = importutils.import_module(_CONF.rpc_backend) return _RPCIMPL diff --git a/nova/rpc/common.py b/nova/rpc/common.py index 0b9eebf0f..33aea9bc3 100644 --- a/nova/rpc/common.py +++ b/nova/rpc/common.py @@ -24,6 +24,7 @@ import traceback from nova import exception from nova import log as logging from nova.openstack.common import cfg +from nova.openstack.common import importutils from nova import utils @@ -192,8 +193,7 @@ def deserialize_remote_exception(conf, data): return RemoteError(name, failure.get('message'), trace) try: - __import__(module) - mod = sys.modules[module] + mod = importutils.import_module(module) klass = getattr(mod, name) if not issubclass(klass, Exception): raise TypeError("Can only deserialize Exceptions") diff --git a/nova/scheduler/driver.py b/nova/scheduler/driver.py index d4ba58d6f..bae33aa12 100644 --- a/nova/scheduler/driver.py +++ b/nova/scheduler/driver.py @@ -29,6 +29,7 @@ from nova import exception from nova import flags from nova import log as logging from nova.openstack.common import cfg +from nova.openstack.common import importutils from nova import rpc from nova.rpc import common as rpc_common from nova import utils @@ -131,7 +132,7 @@ class Scheduler(object): """The base class that all Scheduler classes should inherit from.""" def __init__(self): - self.host_manager = utils.import_object( + self.host_manager = importutils.import_object( FLAGS.scheduler_host_manager) self.compute_api = compute_api.API() diff --git a/nova/scheduler/filter_scheduler.py b/nova/scheduler/filter_scheduler.py index 4894c8563..ce7ba420b 100644 --- a/nova/scheduler/filter_scheduler.py +++ b/nova/scheduler/filter_scheduler.py @@ -25,10 +25,11 @@ from nova import exception from nova import flags from nova import log as logging from nova.notifier import api as notifier +from nova.openstack.common import exception as common_exception +from nova.openstack.common import importutils from nova.scheduler import driver from nova.scheduler import least_cost from nova.scheduler import scheduler_options -from nova import utils FLAGS = flags.FLAGS @@ -243,8 +244,8 @@ class FilterScheduler(driver.Scheduler): # NOTE: import_class is somewhat misnamed since # the weighing function can be any non-class callable # (i.e., no 'self') - cost_fn = utils.import_class(cost_fn_str) - except exception.ClassNotFound: + cost_fn = importutils.import_class(cost_fn_str) + except common_exception.NotFound: raise exception.SchedulerCostFunctionNotFound( cost_fn_str=cost_fn_str) diff --git a/nova/scheduler/filters/__init__.py b/nova/scheduler/filters/__init__.py index ccc29a7db..e8e81c601 100644 --- a/nova/scheduler/filters/__init__.py +++ b/nova/scheduler/filters/__init__.py @@ -21,7 +21,7 @@ import os import types from nova import exception -from nova import utils +from nova.openstack.common import importutils class BaseHostFilter(object): @@ -43,7 +43,7 @@ def _is_filter_class(cls): def _get_filter_classes_from_module(module_name): """Get all filter classes from a module.""" classes = [] - module = utils.import_object(module_name) + module = importutils.import_module(module_name) for obj_name in dir(module): itm = getattr(module, obj_name) if _is_filter_class(itm): @@ -75,7 +75,7 @@ def get_filter_classes(filter_class_names): """Get filter classes from class names.""" classes = [] for cls_name in filter_class_names: - obj = utils.import_class(cls_name) + obj = importutils.import_class(cls_name) if _is_filter_class(obj): classes.append(obj) elif type(obj) is types.FunctionType: diff --git a/nova/scheduler/manager.py b/nova/scheduler/manager.py index 045663855..959c91583 100644 --- a/nova/scheduler/manager.py +++ b/nova/scheduler/manager.py @@ -31,6 +31,7 @@ from nova import log as logging from nova import manager from nova.notifier import api as notifier from nova.openstack.common import cfg +from nova.openstack.common import importutils from nova import utils @@ -50,7 +51,7 @@ class SchedulerManager(manager.Manager): def __init__(self, scheduler_driver=None, *args, **kwargs): if not scheduler_driver: scheduler_driver = FLAGS.scheduler_driver - self.driver = utils.import_object(scheduler_driver) + self.driver = importutils.import_object(scheduler_driver) super(SchedulerManager, self).__init__(*args, **kwargs) def __getattr__(self, key): diff --git a/nova/scheduler/multi.py b/nova/scheduler/multi.py index b58a23fe7..6063f03b5 100644 --- a/nova/scheduler/multi.py +++ b/nova/scheduler/multi.py @@ -23,8 +23,8 @@ Scheduler that allows routing some calls to one driver and others to another. from nova import flags from nova.openstack.common import cfg +from nova.openstack.common import importutils from nova.scheduler import driver -from nova import utils multi_scheduler_opts = [ @@ -56,8 +56,10 @@ class MultiScheduler(driver.Scheduler): def __init__(self): super(MultiScheduler, self).__init__() - compute_driver = utils.import_object(FLAGS.compute_scheduler_driver) - volume_driver = utils.import_object(FLAGS.volume_scheduler_driver) + compute_driver = importutils.import_object( + FLAGS.compute_scheduler_driver) + volume_driver = importutils.import_object( + FLAGS.volume_scheduler_driver) self.drivers = {'compute': compute_driver, 'volume': volume_driver} diff --git a/nova/service.py b/nova/service.py index c9817bbe8..d4c9cf683 100644 --- a/nova/service.py +++ b/nova/service.py @@ -33,6 +33,7 @@ from nova import exception from nova import flags from nova import log as logging from nova.openstack.common import cfg +from nova.openstack.common import importutils from nova import rpc from nova import utils from nova import version @@ -163,7 +164,7 @@ class Service(object): self.binary = binary self.topic = topic self.manager_class_name = manager - manager_class = utils.import_class(self.manager_class_name) + manager_class = importutils.import_class(self.manager_class_name) self.manager = manager_class(host=self.host, *args, **kwargs) self.report_interval = report_interval self.periodic_interval = periodic_interval @@ -381,7 +382,7 @@ class WSGIService(object): if not manager_class_name: return None - manager_class = utils.import_class(manager_class_name) + manager_class = importutils.import_class(manager_class_name) return manager_class() def start(self): diff --git a/nova/tests/scheduler/test_host_filters.py b/nova/tests/scheduler/test_host_filters.py index f56a14565..1d61d0fe9 100644 --- a/nova/tests/scheduler/test_host_filters.py +++ b/nova/tests/scheduler/test_host_filters.py @@ -20,6 +20,7 @@ import json from nova import context from nova import exception from nova import flags +from nova.openstack.common import exception as common_exception from nova.scheduler import filters from nova import test from nova.tests.scheduler import fakes @@ -64,7 +65,7 @@ class HostFiltersTestCase(test.TestCase): self.assertEqual(len(classes), 1 + len(self.class_map)) def test_get_filter_classes_raises_on_invalid_classes(self): - self.assertRaises(exception.ClassNotFound, + self.assertRaises(common_exception.NotFound, filters.get_filter_classes, ['nova.tests.scheduler.test_host_filters.NoExist']) self.assertRaises(exception.ClassNotFound, diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index 75544746b..0fae2d48f 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -42,6 +42,7 @@ from nova import flags from nova.image import fake as fake_image from nova import log as logging from nova.notifier import test_notifier +from nova.openstack.common import importutils import nova.policy from nova import rpc from nova.rpc import common as rpc_common @@ -104,7 +105,7 @@ class BaseTestCase(test.TestCase): stub_network=True, notification_driver='nova.notifier.test_notifier', network_manager='nova.network.manager.FlatManager') - self.compute = utils.import_object(FLAGS.compute_manager) + self.compute = importutils.import_object(FLAGS.compute_manager) self.user_id = 'fake' self.project_id = 'fake' diff --git a/nova/tests/test_compute_utils.py b/nova/tests/test_compute_utils.py index bd047dae1..d3c7c73e2 100644 --- a/nova/tests/test_compute_utils.py +++ b/nova/tests/test_compute_utils.py @@ -27,6 +27,7 @@ import nova.image.fake from nova.compute import utils as compute_utils from nova.compute import instance_types from nova.notifier import test_notifier +from nova.openstack.common import importutils from nova.tests import fake_network @@ -51,7 +52,7 @@ class UsageInfoTestCase(test.TestCase): stub_network=True, notification_driver='nova.notifier.test_notifier', network_manager='nova.network.manager.FlatManager') - self.compute = utils.import_object(FLAGS.compute_manager) + self.compute = importutils.import_object(FLAGS.compute_manager) self.user_id = 'fake' self.project_id = 'fake' self.context = context.RequestContext(self.user_id, self.project_id) diff --git a/nova/tests/test_console.py b/nova/tests/test_console.py index 0aab49946..c65d3c126 100644 --- a/nova/tests/test_console.py +++ b/nova/tests/test_console.py @@ -22,8 +22,8 @@ from nova import context from nova import db from nova import exception from nova import flags +from nova.openstack.common import importutils from nova import test -from nova import utils FLAGS = flags.FLAGS flags.DECLARE('console_driver', 'nova.console.manager') @@ -35,7 +35,7 @@ class ConsoleTestCase(test.TestCase): super(ConsoleTestCase, self).setUp() self.flags(console_driver='nova.console.fake.FakeConsoleProxy', stub_compute=True) - self.console = utils.import_object(FLAGS.console_manager) + self.console = importutils.import_object(FLAGS.console_manager) self.user_id = 'fake' self.project_id = 'fake' self.context = context.RequestContext(self.user_id, self.project_id) diff --git a/nova/tests/test_consoleauth.py b/nova/tests/test_consoleauth.py index 6370a4ff4..ba336ccd5 100644 --- a/nova/tests/test_consoleauth.py +++ b/nova/tests/test_consoleauth.py @@ -22,13 +22,14 @@ Tests for Consoleauth Code. import time +from nova.consoleauth import manager from nova import context from nova import db from nova import flags from nova import log as logging +from nova.openstack.common import importutils from nova import test from nova import utils -from nova.consoleauth import manager FLAGS = flags.FLAGS @@ -40,7 +41,7 @@ class ConsoleauthTestCase(test.TestCase): def setUp(self): super(ConsoleauthTestCase, self).setUp() - self.manager = utils.import_object(FLAGS.consoleauth_manager) + self.manager = importutils.import_object(FLAGS.consoleauth_manager) self.context = context.get_admin_context() def test_tokens_expire(self): diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py index 5a7ac8b80..cf871801d 100644 --- a/nova/tests/test_libvirt.py +++ b/nova/tests/test_libvirt.py @@ -27,18 +27,21 @@ import tempfile from xml.etree import ElementTree from xml.dom import minidom -from nova import context -from nova import db -from nova import exception -from nova import flags -from nova import log as logging -from nova import test -from nova import utils from nova.api.ec2 import cloud from nova.compute import instance_types from nova.compute import power_state from nova.compute import utils as compute_utils from nova.compute import vm_states +from nova import context +from nova import db +from nova import exception +from nova import flags +from nova import log as logging +from nova.openstack.common import importutils +from nova import test +from nova.tests import fake_network +from nova.tests import fake_libvirt_utils +from nova import utils from nova.virt import images from nova.virt import driver from nova.virt import firewall as base_firewall @@ -48,8 +51,6 @@ from nova.virt.libvirt import firewall from nova.virt.libvirt import volume from nova.volume import driver as volume_driver from nova.virt.libvirt import utils as libvirt_utils -from nova.tests import fake_network -from nova.tests import fake_libvirt_utils try: @@ -693,7 +694,7 @@ class LibvirtConnTestCase(test.TestCase): self.flags(image_service='nova.image.fake.FakeImageService') # Start test - image_service = utils.import_object(FLAGS.image_service) + image_service = importutils.import_object(FLAGS.image_service) # Assign different image_ref from nova/images/fakes for testing ami test_instance = copy.deepcopy(self.test_instance) @@ -731,7 +732,7 @@ class LibvirtConnTestCase(test.TestCase): self.flags(image_service='nova.image.fake.FakeImageService') # Start test - image_service = utils.import_object(FLAGS.image_service) + image_service = importutils.import_object(FLAGS.image_service) # Assuming that base image already exists in image_service instance_ref = db.instance_create(self.context, self.test_instance) @@ -766,7 +767,7 @@ class LibvirtConnTestCase(test.TestCase): self.flags(snapshot_image_format='qcow2') # Start test - image_service = utils.import_object(FLAGS.image_service) + image_service = importutils.import_object(FLAGS.image_service) # Assuming that base image already exists in image_service instance_ref = db.instance_create(self.context, self.test_instance) @@ -800,7 +801,7 @@ class LibvirtConnTestCase(test.TestCase): self.flags(image_service='nova.image.fake.FakeImageService') # Start test - image_service = utils.import_object(FLAGS.image_service) + image_service = importutils.import_object(FLAGS.image_service) # Assign different image_ref from nova/images/fakes for # testing different base image @@ -838,7 +839,7 @@ class LibvirtConnTestCase(test.TestCase): self.flags(image_service='nova.image.fake.FakeImageService') # Start test - image_service = utils.import_object(FLAGS.image_service) + image_service = importutils.import_object(FLAGS.image_service) # Assign a non-existent image test_instance = copy.deepcopy(self.test_instance) @@ -1166,8 +1167,8 @@ class LibvirtConnTestCase(test.TestCase): fake_timer = FakeTime() # _fake_network_info must be called before create_fake_libvirt_mock(), - # as _fake_network_info calls utils.import_class() and - # create_fake_libvirt_mock() mocks utils.import_class(). + # as _fake_network_info calls importutils.import_class() and + # create_fake_libvirt_mock() mocks importutils.import_class(). network_info = _fake_network_info(self.stubs, 1) self.create_fake_libvirt_mock() instance_ref = db.instance_create(self.context, self.test_instance) @@ -1201,7 +1202,7 @@ class LibvirtConnTestCase(test.TestCase): def test_live_migration_raises_exception(self): """Confirms recover method is called when exceptions are raised.""" # Preparing data - self.compute = utils.import_object(FLAGS.compute_manager) + self.compute = importutils.import_object(FLAGS.compute_manager) instance_dict = {'host': 'fake', 'power_state': power_state.RUNNING, 'vm_state': vm_states.ACTIVE} @@ -1362,8 +1363,8 @@ class LibvirtConnTestCase(test.TestCase): return # _fake_network_info must be called before create_fake_libvirt_mock(), - # as _fake_network_info calls utils.import_class() and - # create_fake_libvirt_mock() mocks utils.import_class(). + # as _fake_network_info calls importutils.import_class() and + # create_fake_libvirt_mock() mocks importutils.import_class(). network_info = _fake_network_info(self.stubs, 1) self.create_fake_libvirt_mock() diff --git a/nova/tests/test_linux_net.py b/nova/tests/test_linux_net.py index 1571a8bee..1e7d3e0ff 100644 --- a/nova/tests/test_linux_net.py +++ b/nova/tests/test_linux_net.py @@ -23,6 +23,7 @@ from nova import context from nova import db from nova import flags from nova import log as logging +from nova.openstack.common import importutils from nova import test from nova import utils from nova.network import linux_net @@ -211,7 +212,7 @@ class LinuxNetworkTestCase(test.TestCase): def setUp(self): super(LinuxNetworkTestCase, self).setUp() network_driver = FLAGS.network_driver - self.driver = utils.import_object(network_driver) + self.driver = importutils.import_module(network_driver) self.driver.db = db self.context = context.RequestContext('testuser', 'testproject', is_admin=True) diff --git a/nova/tests/test_volume.py b/nova/tests/test_volume.py index fca593c7c..af3ba9f64 100644 --- a/nova/tests/test_volume.py +++ b/nova/tests/test_volume.py @@ -29,10 +29,10 @@ from nova import exception from nova import db from nova import flags from nova import log as logging +from nova.openstack.common import importutils import nova.policy from nova import rpc from nova import test -from nova import utils import nova.volume.api FLAGS = flags.FLAGS @@ -44,9 +44,9 @@ class VolumeTestCase(test.TestCase): def setUp(self): super(VolumeTestCase, self).setUp() - self.compute = utils.import_object(FLAGS.compute_manager) + self.compute = importutils.import_object(FLAGS.compute_manager) self.flags(connection_type='fake') - self.volume = utils.import_object(FLAGS.volume_manager) + self.volume = importutils.import_object(FLAGS.volume_manager) self.context = context.get_admin_context() self.instance_id = db.instance_create(self.context, {})['id'] @@ -354,7 +354,7 @@ class DriverTestCase(test.TestCase): super(DriverTestCase, self).setUp() self.flags(volume_driver=self.driver_name, logging_default_format_string="%(message)s") - self.volume = utils.import_object(FLAGS.volume_manager) + self.volume = importutils.import_object(FLAGS.volume_manager) self.context = context.get_admin_context() self.output = "" diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index e513ca0fb..310ad06c8 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -36,13 +36,13 @@ from nova import db from nova import exception from nova import flags from nova import log as logging +from nova.openstack.common import importutils from nova import test from nova.tests.db import fakes as db_fakes from nova.tests.xenapi import stubs from nova.tests.glance import stubs as glance_stubs from nova.tests import fake_network from nova.tests import fake_utils -from nova import utils from nova.virt.xenapi import connection as xenapi_conn from nova.virt.xenapi import fake as xenapi_fake from nova.virt.xenapi import volume_utils @@ -215,7 +215,7 @@ class XenAPIVMTestCase(test.TestCase): """Unit tests for VM operations.""" def setUp(self): super(XenAPIVMTestCase, self).setUp() - self.network = utils.import_object(FLAGS.network_manager) + self.network = importutils.import_object(FLAGS.network_manager) self.flags(xenapi_connection_url='test_url', xenapi_connection_password='test_pass', instance_name_template='%d', @@ -1546,7 +1546,7 @@ class XenAPIDom0IptablesFirewallTestCase(test.TestCase): stubs.stubout_session(self.stubs, stubs.FakeSessionForFirewallTests, test_case=self) self.context = context.RequestContext(self.user_id, self.project_id) - self.network = utils.import_object(FLAGS.network_manager) + self.network = importutils.import_object(FLAGS.network_manager) self.conn = xenapi_conn.get_connection(False) self.fw = self.conn._vmops.firewall_driver diff --git a/nova/utils.py b/nova/utils.py index 309863bd5..71e734e8b 100644 --- a/nova/utils.py +++ b/nova/utils.py @@ -57,6 +57,7 @@ from nova import exception from nova import flags from nova import log as logging from nova.openstack.common import cfg +from nova.openstack.common import importutils LOG = logging.getLogger(__name__) @@ -69,27 +70,6 @@ FLAGS.register_opt( help='Whether to disable inter-process locks')) -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: - LOG.debug(_('Inner Exception: %s'), exc) - raise exception.ClassNotFound(class_name=class_str, exception=exc) - - -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 find_config(config_path): """Find a configuration file using the given hint. @@ -1229,20 +1209,20 @@ def monkey_patch(): for module_and_decorator in FLAGS.monkey_patch_modules: module, decorator_name = module_and_decorator.split(':') # import decorator function - decorator = import_class(decorator_name) + decorator = importutils.import_class(decorator_name) __import__(module) # Retrieve module information using pyclbr module_data = pyclbr.readmodule_ex(module) for key in module_data.keys(): # set the decorator for the class methods if isinstance(module_data[key], pyclbr.Class): - clz = import_class("%s.%s" % (module, key)) + clz = importutils.import_class("%s.%s" % (module, key)) for method, func in inspect.getmembers(clz, inspect.ismethod): setattr(clz, method, decorator("%s.%s.%s" % (module, key, method), func)) # set the decorator for the function if isinstance(module_data[key], pyclbr.Function): - func = import_class("%s.%s" % (module, key)) + func = importutils.import_class("%s.%s" % (module, key)) setattr(sys.modules[module], key, decorator("%s.%s" % (module, key), func)) diff --git a/openstack-common.conf b/openstack-common.conf index 854e80b14..d32dec4e6 100644 --- a/openstack-common.conf +++ b/openstack-common.conf @@ -1,7 +1,7 @@ [DEFAULT] # The list of modules to copy from openstack-common -modules=cfg,local,iniparser +modules=cfg,exception,local,importutils,iniparser # The base module to hold the copy of openstack.common base=nova