Init virt driver before use

The virt driver interface assumes that init_host is called before any
other query to the virt driver. The libvirt virt driver cannot fully
function otherwise. If any connection is made to the hypervisor before
driver.init_host then the libvirt lifecycle events will not function and
libvirt returns the warning:

  URI qemu:///system does not support events: internal error: could not
  initialize domain event timer: libvirt.libvirtError: internal error:
  could not initialize domain event timer

During the first startup of the nova-compute service
ComputeManager.init_host checks if the hypervisor has any instances to
detect if this is not really the first start of the compute service on
the host. But that code path happens before ComputeManager.init_host
initialize the virt driver via driver.init_host.

This patch reorders the calls to make sure the driver is initialized
before use.

Closes-Bug: #2130881
Change-Id: I814a2f3982d481a1f926fe13465a19955c4f48f2
Signed-off-by: Balazs Gibizer <gibi@redhat.com>
(cherry picked from commit 16abde56ee)
(cherry picked from commit 35b1f7731f)
(cherry picked from commit e178e62149)
This commit is contained in:
Balazs Gibizer
2025-11-07 15:48:54 +01:00
committed by Sylvain Bauza
parent 33f2229049
commit 8f1cdd250b
2 changed files with 13 additions and 22 deletions

View File

@@ -1595,16 +1595,6 @@ class ComputeManager(manager.Manager):
def init_host(self, service_ref):
"""Initialization for a standalone compute service."""
if service_ref:
# If we are an existing service, check to see if we need
# to record a locally-persistent node identity because
# we have upgraded from a previous version.
self._ensure_existing_node_identity(service_ref)
else:
# If we are a new service (in the database), make sure we have no
# instances on our hypervisor as we would expect.
self._sanity_check_new_host()
if CONF.pci.device_spec:
# Simply loading the PCI passthrough spec will do a bunch of
# validation that would otherwise wait until the PciDevTracker is
@@ -1635,6 +1625,16 @@ class ComputeManager(manager.Manager):
self.driver.init_host(host=self.host)
if service_ref:
# If we are an existing service, check to see if we need
# to record a locally-persistent node identity because
# we have upgraded from a previous version.
self._ensure_existing_node_identity(service_ref)
else:
# If we are a new service (in the database), make sure we have no
# instances on our hypervisor as we would expect.
self._sanity_check_new_host()
# NOTE(gibi): At this point the compute_nodes of the resource tracker
# has not been populated yet so we cannot rely on the resource tracker
# here.

View File

@@ -1044,21 +1044,12 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase,
test.MatchType(nova.context.RequestContext))
self.assertGreaterEqual(len(self.compute.driver.mock_calls), 2)
# This is bug https://bugs.launchpad.net/nova/+bug/2130881.
# The driver.init_host should have been called first
self.assertEqual(
mock.call.list_instance_uuids(),
self.compute.driver.mock_calls[0])
self.assertEqual(
mock.call.init_host(host='fake-mini'),
self.compute.driver.mock_calls[0])
self.assertEqual(
mock.call.list_instance_uuids(),
self.compute.driver.mock_calls[1])
# After the fix the following should pass
# self.assertEqual(
# mock.call.init_host(host='fake-mini'),
# self.compute.driver.mock_calls[0])
# self.assertEqual(
# mock.call.list_instance_uuids(),
# self.compute.driver.mock_calls[1])
def test_init_host_new_with_instances(self):
"""Tests the case where we start up without an existing service_ref,