From 0caf24f308e754884b53b244f5b6228c9c2e4147 Mon Sep 17 00:00:00 2001 From: Dan Smith Date: Thu, 3 Nov 2022 13:00:46 -0700 Subject: [PATCH] Add get_available_node_uuids() to virt driver This adds a get_available_node_uuids() method to the virt driver interface. This aims to eventually replace the nodename-based interface, but currently provides an implementation that will work for most drivers. Any driver that does not override this method will get the locally-persistent UUID from nova.virt.node. Ironic obviously needs to override this (which is easy), as well as the fake driver because it supports multiple nodes for testing. The libvirt driver overrides it only because we test multiple libvirt driver instances on a single host and we need each instantiation of it to "capture" the UUID we have mocked out at the time it is started. Change-Id: Ibe14d2b223c737d82c217a74bc94e41603271a9d --- nova/test.py | 1 + nova/tests/functional/compute/test_resource_tracker.py | 1 + nova/tests/functional/libvirt/base.py | 5 ++++- nova/tests/functional/libvirt/test_evacuate.py | 4 +++- nova/tests/functional/libvirt/test_vpmem.py | 6 +++++- nova/virt/driver.py | 4 ++++ nova/virt/fake.py | 10 +++++++--- nova/virt/ironic/driver.py | 3 +++ nova/virt/libvirt/driver.py | 3 +++ nova/virt/libvirt/host.py | 8 ++++++++ 10 files changed, 39 insertions(+), 6 deletions(-) diff --git a/nova/test.py b/nova/test.py index f050dde3f958..4f3554d6826b 100644 --- a/nova/test.py +++ b/nova/test.py @@ -693,6 +693,7 @@ class SubclassSignatureTestCase(testtools.TestCase, metaclass=abc.ABCMeta): raise NotImplementedError() def setUp(self): + self.useFixture(nova_fixtures.ConfFixture(CONF)) self.base = self._get_base_class() super(SubclassSignatureTestCase, self).setUp() diff --git a/nova/tests/functional/compute/test_resource_tracker.py b/nova/tests/functional/compute/test_resource_tracker.py index fff08697ae69..139fb5e6acdc 100644 --- a/nova/tests/functional/compute/test_resource_tracker.py +++ b/nova/tests/functional/compute/test_resource_tracker.py @@ -248,6 +248,7 @@ class IronicResourceTrackerTest(test.TestCase): 'numa_topology': None, 'resource_class': None, # Act like admin hasn't set yet... 'stats': stats, + 'uuid': str(getattr(uuids, nodename)), } self.rt.update_available_resource(self.ctx, nodename) diff --git a/nova/tests/functional/libvirt/base.py b/nova/tests/functional/libvirt/base.py index 47a8bbe81c95..89fb0e51a5fa 100644 --- a/nova/tests/functional/libvirt/base.py +++ b/nova/tests/functional/libvirt/base.py @@ -18,6 +18,7 @@ import io from unittest import mock import fixtures +from oslo_utils.fixture import uuidsentinel as uuids from nova import conf from nova.tests import fixtures as nova_fixtures @@ -177,7 +178,9 @@ class ServersTestBase(integrated_helpers._IntegratedTestBase): self.assertNotIn(hostname, self.computes) self.assertNotIn(hostname, self.compute_rp_uuids) - self.computes[hostname] = _start_compute(hostname, host_info) + with mock.patch('nova.virt.node.get_local_node_uuid') as m: + m.return_value = str(getattr(uuids, 'node_%s' % hostname)) + self.computes[hostname] = _start_compute(hostname, host_info) self.compute_rp_uuids[hostname] = self.placement.get( '/resource_providers?name=%s' % hostname).body[ diff --git a/nova/tests/functional/libvirt/test_evacuate.py b/nova/tests/functional/libvirt/test_evacuate.py index 9d3deec99dbf..92d7ffba2979 100644 --- a/nova/tests/functional/libvirt/test_evacuate.py +++ b/nova/tests/functional/libvirt/test_evacuate.py @@ -415,7 +415,9 @@ class _LibvirtEvacuateTest(integrated_helpers.InstanceHelperMixin): with mock.patch.object(fakelibvirt.Connection, 'getHostname', return_value=name): - compute = self.start_service('compute', host=name) + with mock.patch('nova.virt.node.get_local_node_uuid') as m: + m.return_value = str(getattr(uuids, 'node_%s' % name)) + compute = self.start_service('compute', host=name) compute.driver._host.get_connection().getHostname = lambda: name return compute diff --git a/nova/tests/functional/libvirt/test_vpmem.py b/nova/tests/functional/libvirt/test_vpmem.py index d1cad0e376c7..1200f80357ee 100644 --- a/nova/tests/functional/libvirt/test_vpmem.py +++ b/nova/tests/functional/libvirt/test_vpmem.py @@ -12,9 +12,11 @@ # under the License. import fixtures +from unittest import mock from oslo_config import cfg from oslo_log import log as logging +from oslo_utils.fixture import uuidsentinel as uuids from nova import objects from nova.tests import fixtures as nova_fixtures @@ -99,7 +101,9 @@ class VPMEMTestBase(integrated_helpers.LibvirtProviderUsageBaseTestCase): cpu_cores=2, cpu_threads=2), hostname=hostname) self.mock_conn.return_value = fake_connection - compute = self._start_compute(host=hostname) + with mock.patch('nova.virt.node.get_local_node_uuid') as m: + m.return_value = str(getattr(uuids, 'node_%s' % hostname)) + compute = self._start_compute(host=hostname) # Ensure populating the existing pmems correctly. vpmems = compute.driver._vpmems_by_name diff --git a/nova/virt/driver.py b/nova/virt/driver.py index 532ed1fa5091..b6297bb7858e 100644 --- a/nova/virt/driver.py +++ b/nova/virt/driver.py @@ -34,6 +34,7 @@ from nova import context as nova_context from nova.i18n import _ from nova import objects from nova.virt import event as virtevent +import nova.virt.node CONF = nova.conf.CONF LOG = logging.getLogger(__name__) @@ -1595,6 +1596,9 @@ class ComputeDriver(object): """ raise NotImplementedError() + def get_available_node_uuids(self, refresh=False): + return [nova.virt.node.get_local_node_uuid()] + def node_is_available(self, nodename): """Return whether this compute service manages a particular node.""" if nodename in self.get_available_nodes(): diff --git a/nova/virt/fake.py b/nova/virt/fake.py index 362bf8997309..af59c6c02782 100644 --- a/nova/virt/fake.py +++ b/nova/virt/fake.py @@ -32,6 +32,7 @@ import fixtures import os_resource_classes as orc from oslo_log import log as logging from oslo_serialization import jsonutils +from oslo_utils.fixture import uuidsentinel as uuids from oslo_utils import versionutils from nova.compute import power_state @@ -160,8 +161,8 @@ class FakeDriver(driver.ComputeDriver): self._host = host # NOTE(gibi): this is unnecessary complex and fragile but this is # how many current functional sample tests expect the node name. - self._nodes = (['fake-mini'] if self._host == 'compute' - else [self._host]) + self._set_nodes(['fake-mini'] if self._host == 'compute' + else [self._host]) def _set_nodes(self, nodes): # NOTE(gibi): this is not part of the driver interface but used @@ -646,6 +647,9 @@ class FakeDriver(driver.ComputeDriver): def get_available_nodes(self, refresh=False): return self._nodes + def get_available_node_uuids(self, refresh=False): + return [str(getattr(uuids, n)) for n in self.get_available_nodes()] + def instance_on_disk(self, instance): return False @@ -764,7 +768,7 @@ class PredictableNodeUUIDDriver(SmallFakeDriver): PredictableNodeUUIDDriver, self).get_available_resource(nodename) # This is used in ComputeNode.update_from_virt_driver which is called # from the ResourceTracker when creating a ComputeNode. - resources['uuid'] = uuid.uuid5(uuid.NAMESPACE_DNS, nodename) + resources['uuid'] = str(uuid.uuid5(uuid.NAMESPACE_DNS, nodename)) return resources diff --git a/nova/virt/ironic/driver.py b/nova/virt/ironic/driver.py index 117294ff897e..b437b4a9594d 100644 --- a/nova/virt/ironic/driver.py +++ b/nova/virt/ironic/driver.py @@ -839,6 +839,9 @@ class IronicDriver(virt_driver.ComputeDriver): return node_uuids + def get_available_node_uuids(self, refresh=False): + return self.get_available_nodes(refresh=refresh) + def update_provider_tree(self, provider_tree, nodename, allocations=None): """Update a ProviderTree object with current resource provider and inventory information. diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index dbc9bc3f1e9e..e4c997c17196 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -11317,6 +11317,9 @@ class LibvirtDriver(driver.ComputeDriver): def get_available_nodes(self, refresh=False): return [self._host.get_hostname()] + def get_available_node_uuids(self, refresh=False): + return [self._host.get_node_uuid()] + def get_host_cpu_stats(self): """Return the current CPU state of the host.""" return self._host.get_cpu_stats() diff --git a/nova/virt/libvirt/host.py b/nova/virt/libvirt/host.py index 46435a9a7fd8..4a8bf6f2ac0b 100644 --- a/nova/virt/libvirt/host.py +++ b/nova/virt/libvirt/host.py @@ -66,6 +66,7 @@ from nova.virt.libvirt import event as libvirtevent from nova.virt.libvirt import guest as libvirt_guest 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: import libvirt @@ -138,6 +139,7 @@ class Host(object): self._caps = None self._domain_caps = None self._hostname = None + self._node_uuid = None self._wrapped_conn = None self._wrapped_conn_lock = threading.Lock() @@ -1059,6 +1061,12 @@ class Host(object): {'old': self._hostname, 'new': hostname}) return self._hostname + def get_node_uuid(self): + """Returns the UUID of this node.""" + if not self._node_uuid: + self._node_uuid = nova.virt.node.get_local_node_uuid() + return self._node_uuid + def find_secret(self, usage_type, usage_id): """Find a secret.