diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index b0a143ac83..4ea430efa9 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -134,12 +134,16 @@ from nova.virt.libvirt.volume import volume from nova.virt import netutils from nova.volume import cinder -libvirt: ty.Any = None +try: + # This is optional for unit testing but required at runtime. We check for + # it during driver init. + import libvirt +except ImportError: + libvirt = None uefi_logged = False LOG = logging.getLogger(__name__) - CONF = nova.conf.CONF MAX_CONSOLE_BYTES = 100 * units.Ki @@ -396,6 +400,12 @@ class AsyncDeviceEventsHandler: class LibvirtDriver(driver.ComputeDriver): def __init__(self, virtapi, read_only=False): + if libvirt is None: + # the libvirt driver is "customer 0" of the libvirt API: if we + # haven't been able to import it, fail early by attempting to + # import again + __import__('libvirt') + # NOTE(aspiers) Some of these are dynamic, so putting # capabilities on the instance rather than on the class. # This prevents the risk of one test setting a capability @@ -443,17 +453,12 @@ class LibvirtDriver(driver.ComputeDriver): "supports_ephemeral_encryption_luks": self.image_backend.backend().SUPPORTS_LUKS, } - super(LibvirtDriver, self).__init__(virtapi) + super().__init__(virtapi) if not sys.platform.startswith('linux'): raise exception.InternalError( _('The libvirt driver only works on Linux')) - global libvirt - if libvirt is None: - libvirt = importutils.import_module('libvirt') - libvirt_migrate.libvirt = libvirt - self._host = host.Host(self._uri(), read_only, lifecycle_event_handler=self.emit_event, conn_event_handler=self._handle_conn_event) diff --git a/nova/virt/libvirt/guest.py b/nova/virt/libvirt/guest.py index e6c60d29d1..cac2710a29 100644 --- a/nova/virt/libvirt/guest.py +++ b/nova/virt/libvirt/guest.py @@ -34,7 +34,6 @@ from lxml import etree from oslo_log import log as logging from oslo_utils import encodeutils from oslo_utils import excutils -from oslo_utils import importutils from nova.compute import power_state from nova import exception @@ -42,10 +41,11 @@ from nova.i18n import _ from nova.virt import hardware from nova.virt.libvirt import config as vconfig - -if ty.TYPE_CHECKING: +try: + # This is optional for unit testing but required at runtime. We check for + # it during driver init. import libvirt -else: +except ImportError: libvirt = None try: @@ -103,14 +103,9 @@ LIBVIRT_BLOCK_JOB_TYPE = { } -class Guest(object): +class Guest: def __init__(self, domain): - - global libvirt - if libvirt is None: - libvirt = importutils.import_module('libvirt') - self._domain = domain def __repr__(self): diff --git a/nova/virt/libvirt/host.py b/nova/virt/libvirt/host.py index 8634080819..eaeee8a8d6 100644 --- a/nova/virt/libvirt/host.py +++ b/nova/virt/libvirt/host.py @@ -31,7 +31,6 @@ from collections import defaultdict import fnmatch import glob import inspect -from lxml import etree import operator import os import queue @@ -41,10 +40,10 @@ import typing as ty from eventlet import greenio from eventlet import greenthread from eventlet import patcher +from lxml import etree from oslo_log import log as logging from oslo_serialization import jsonutils from oslo_utils import excutils -from oslo_utils import importutils from oslo_utils import strutils from oslo_utils import units from oslo_utils import versionutils @@ -67,20 +66,20 @@ from nova.virt.libvirt import migration as libvirt_migrate from nova.virt.libvirt import utils as libvirt_utils import nova.virt.node # noqa -if ty.TYPE_CHECKING: +try: + # This is optional for unit testing but required at runtime. We check for + # it during driver init. import libvirt -else: +except ImportError: libvirt = None +CONF = nova.conf.CONF LOG = logging.getLogger(__name__) native_socket = patcher.original('socket') native_threading = patcher.original("threading") native_Queue = patcher.original("queue") -CONF = nova.conf.CONF - - # This list is for libvirt hypervisor drivers that need special handling. # This is *not* the complete list of supported hypervisor drivers. HV_DRIVER_QEMU = "QEMU" @@ -125,11 +124,6 @@ class Host(object): def __init__(self, uri, read_only=False, conn_event_handler=None, lifecycle_event_handler=None): - - global libvirt - if libvirt is None: - libvirt = importutils.import_module('libvirt') - self._uri = uri self._read_only = read_only self._initial_connection = True diff --git a/nova/virt/libvirt/migration.py b/nova/virt/libvirt/migration.py index 53d148b555..80f3f77302 100644 --- a/nova/virt/libvirt/migration.py +++ b/nova/virt/libvirt/migration.py @@ -12,10 +12,8 @@ # License for the specific language governing permissions and limitations # under the License. +"""Utility methods to manage guests migration.""" -"""Utility methods to manage guests migration - -""" from collections import deque from lxml import etree @@ -28,15 +26,16 @@ from nova import objects from nova.virt import hardware from nova.virt.libvirt import config as vconfig +try: + # This is optional for unit testing but required at runtime. We check for + # it during driver init. + import libvirt +except ImportError: + libvirt = None + LOG = logging.getLogger(__name__) - CONF = nova.conf.CONF -# TODO(berrange): hack to avoid a "import libvirt" in this file. -# Remove this and similar hacks in guest.py, driver.py, host.py -# etc in Ocata. -libvirt = None - def graphics_listen_addrs(migrate_data): """Returns listen addresses of vnc/spice from a LibvirtLiveMigrateData"""