From ba00d60b95c44a57505926aa4b7698922a847736 Mon Sep 17 00:00:00 2001 From: Dan Smith Date: Wed, 12 Mar 2025 11:40:55 -0700 Subject: [PATCH] Extend invalidate_rp to only invalidate cache This makes invalidate_resource_provider() have a cacheonly flag that only invalidates our cache, but does not remove the provider from the tree for efficiency. Related to blueprint one-time-use-devices Change-Id: I04dd5e984c5671d866804c258422e4230fce37b7 --- nova/scheduler/client/report.py | 13 ++++---- .../unit/scheduler/client/test_report.py | 30 +++++++++++++++++++ 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/nova/scheduler/client/report.py b/nova/scheduler/client/report.py index 8f9abb9c93..dfa371baae 100644 --- a/nova/scheduler/client/report.py +++ b/nova/scheduler/client/report.py @@ -2389,15 +2389,18 @@ class SchedulerReportClient(object): # left a no-op for backward compatibility. pass - def invalidate_resource_provider(self, name_or_uuid): + def invalidate_resource_provider(self, name_or_uuid, cacheonly=False): """Invalidate the cache for a resource provider. :param name_or_uuid: Name or UUID of the resource provider to look up. + :param cacheonly: Only reset the cache but do not remove the provider + from the tree """ - try: - self._provider_tree.remove(name_or_uuid) - except ValueError: - pass + if not cacheonly: + try: + self._provider_tree.remove(name_or_uuid) + except ValueError: + pass self._association_refresh_time.pop(name_or_uuid, None) def get_provider_by_name(self, context, name): diff --git a/nova/tests/unit/scheduler/client/test_report.py b/nova/tests/unit/scheduler/client/test_report.py index ed43b7843d..41dcd34d59 100644 --- a/nova/tests/unit/scheduler/client/test_report.py +++ b/nova/tests/unit/scheduler/client/test_report.py @@ -2811,6 +2811,36 @@ class TestProviderOperations(SchedulerReportClientTestCase): self.client.get_resource_provider_name, self.context, uuids.rp) + def test_invalidate_full(self): + self._init_provider_tree() + rp_uuid = self.compute_node.uuid + self.client._association_refresh_time[rp_uuid] = time.time() + + # Initially, cache is not stale and our provider exists + self.assertFalse(self.client._associations_stale(rp_uuid)) + self.assertTrue(self.client._provider_tree.exists(rp_uuid)) + + # A full invalidation means our cache is stale (i.e. needs update) + # and our provider is gone from the tree + self.client.invalidate_resource_provider(rp_uuid) + self.assertTrue(self.client._associations_stale(rp_uuid)) + self.assertFalse(self.client._provider_tree.exists(rp_uuid)) + + def test_invalidate_cache_only(self): + self._init_provider_tree() + rp_uuid = self.compute_node.uuid + self.client._association_refresh_time[rp_uuid] = time.time() + + # Initially, cache is not stale and our provider exists + self.assertFalse(self.client._associations_stale(rp_uuid)) + self.assertTrue(self.client._provider_tree.exists(rp_uuid)) + + # After a cache-only validation, our cache is stale (i.e. needs update) + # but the provider still exists in our tree + self.client.invalidate_resource_provider(rp_uuid, cacheonly=True) + self.assertTrue(self.client._associations_stale(rp_uuid)) + self.assertTrue(self.client._provider_tree.exists(rp_uuid)) + class TestAggregates(SchedulerReportClientTestCase): def test_get_provider_aggregates_found(self):