From e252506b51ed5b40a757e46bd98b47a383a5a40f Mon Sep 17 00:00:00 2001 From: Russell Bryant Date: Fri, 27 Apr 2012 14:14:18 -0400 Subject: [PATCH] Use openstack.common.importutils. Use import_class(), import_object(), and import_module() from openstack-common's importutils module. The equivalent functions have been removed from nova.utils. A few modules had import order cleaned up in passing, as well. My initial motivation for this was to remove some more usage of nova bits from nova.rpc as another step towards being able to move nova.rpc import openstack-common. Since I was pulling importutils into nova, I went ahead and converted the whole thing. Change-Id: I7c7786cf0001bcd06db52b9a99ff4284a3f6c6fa --- bin/nova-dhcpbridge | 7 +- bin/nova-manage | 13 +- nova/auth/manager.py | 5 +- nova/notifier/api.py | 3 +- nova/notifier/list_notifier.py | 8 +- nova/openstack/common/exception.py | 147 ++++++++++++++++++++++ nova/openstack/common/importutils.py | 45 +++++++ nova/rpc/__init__.py | 4 +- nova/rpc/common.py | 4 +- nova/scheduler/driver.py | 3 +- nova/scheduler/filter_scheduler.py | 7 +- nova/scheduler/filters/__init__.py | 6 +- nova/scheduler/manager.py | 3 +- nova/scheduler/multi.py | 8 +- nova/service.py | 5 +- nova/tests/scheduler/test_host_filters.py | 3 +- nova/tests/test_compute.py | 3 +- nova/tests/test_compute_utils.py | 3 +- nova/tests/test_console.py | 4 +- nova/tests/test_consoleauth.py | 5 +- nova/tests/test_libvirt.py | 39 +++--- nova/tests/test_linux_net.py | 3 +- nova/tests/test_volume.py | 8 +- nova/tests/test_xenapi.py | 6 +- nova/utils.py | 28 +---- openstack-common.conf | 2 +- 26 files changed, 280 insertions(+), 92 deletions(-) create mode 100644 nova/openstack/common/exception.py create mode 100644 nova/openstack/common/importutils.py 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