From 9f8ff3960cd8915af4017da64dbeaf3a74383074 Mon Sep 17 00:00:00 2001 From: Dan Smith Date: Wed, 1 Aug 2018 10:16:41 -0700 Subject: Hook resource_tracker to remove stale node information When we remove a node from a host due to rebalance or decommission, we need to tell the resource tracker so it stops keeping track of the details for that node. This adds a hook for doing that and calls it from the place in compute manager where we purge the record from the database. Change-Id: Ie6b6bb2a9e8a4ad33675fccb3827e8197fa16398 Closes-Bug: #1784874 (cherry picked from commit 99db9faae5c1e84e5aa8586c32ffcca7a61ae276) (cherry picked from commit 7302a625ee9af2c9dd88f8630f1e95fc5977a70a) (cherry picked from commit 4f112195b0ad99f07784a9fe8dbe32a25329151d) --- nova/compute/manager.py | 2 ++ nova/compute/resource_tracker.py | 10 ++++++++++ nova/tests/unit/compute/test_compute_mgr.py | 5 ++++- nova/tests/unit/compute/test_resource_tracker.py | 22 ++++++++++++++++++++++ 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index bc7c9eade6..2e82b90003 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -6663,6 +6663,7 @@ class ComputeManager(manager.Manager): for nodename in nodenames: self.update_available_resource_for_node(context, nodename) + rt = self._get_resource_tracker() # Delete orphan compute node not reported by driver but still in db for cn in compute_nodes_in_db: if cn.hypervisor_hostname not in nodenames: @@ -6672,6 +6673,7 @@ class ComputeManager(manager.Manager): {'id': cn.id, 'hh': cn.hypervisor_hostname, 'nodes': nodenames}) cn.destroy() + rt.remove_node(cn.hypervisor_hostname) # Delete the corresponding resource provider in placement, # along with any associated allocations and inventory. # TODO(cdent): Move use of reportclient into resource tracker. diff --git a/nova/compute/resource_tracker.py b/nova/compute/resource_tracker.py index 30ddaa6ddc..bd6125e041 100644 --- a/nova/compute/resource_tracker.py +++ b/nova/compute/resource_tracker.py @@ -542,6 +542,16 @@ class ResourceTracker(object): # now copy rest to compute_node compute_node.update_from_virt_driver(resources) + def remove_node(self, nodename): + """Handle node removal/rebalance. + + Clean up any stored data about a compute node no longer + managed by this host. + """ + self.stats.pop(nodename, None) + self.compute_nodes.pop(nodename, None) + self.old_resources.pop(nodename, None) + def _get_host_metrics(self, context, nodename): """Get the metrics from monitors and notify information to message bus. diff --git a/nova/tests/unit/compute/test_compute_mgr.py b/nova/tests/unit/compute/test_compute_mgr.py index 2d3d8bc7c4..f5b1df0664 100644 --- a/nova/tests/unit/compute/test_compute_mgr.py +++ b/nova/tests/unit/compute/test_compute_mgr.py @@ -212,6 +212,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase): self.assertTrue(log_mock.info.called) self.assertIsNone(self.compute._resource_tracker) + @mock.patch.object(manager.ComputeManager, '_get_resource_tracker') @mock.patch('nova.scheduler.client.report.SchedulerReportClient.' 'delete_resource_provider') @mock.patch.object(manager.ComputeManager, @@ -219,7 +220,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase): @mock.patch.object(fake_driver.FakeDriver, 'get_available_nodes') @mock.patch.object(manager.ComputeManager, '_get_compute_nodes_in_db') def test_update_available_resource(self, get_db_nodes, get_avail_nodes, - update_mock, del_rp_mock): + update_mock, del_rp_mock, mock_get_rt): db_nodes = [self._make_compute_node('node%s' % i, i) for i in range(1, 5)] avail_nodes = set(['node2', 'node3', 'node4', 'node5']) @@ -239,6 +240,8 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase): db_node.destroy.assert_called_once_with() del_rp_mock.assert_called_once_with(self.context, db_node, cascade=True) + mock_get_rt.return_value.remove_node.assert_called_once_with( + 'node1') else: self.assertFalse(db_node.destroy.called) diff --git a/nova/tests/unit/compute/test_resource_tracker.py b/nova/tests/unit/compute/test_resource_tracker.py index c26d69c903..52b451b763 100644 --- a/nova/tests/unit/compute/test_resource_tracker.py +++ b/nova/tests/unit/compute/test_resource_tracker.py @@ -1162,6 +1162,28 @@ class TestInitComputeNode(BaseTestCase): 42) self.assertTrue(self.sched_client_mock.update_resource_stats.called) + @mock.patch('nova.objects.ComputeNodeList.get_by_hypervisor') + @mock.patch('nova.objects.PciDeviceList.get_by_compute_node', + return_value=objects.PciDeviceList(objects=[])) + @mock.patch('nova.objects.ComputeNode.create') + @mock.patch('nova.objects.ComputeNode.get_by_host_and_nodename') + @mock.patch('nova.compute.resource_tracker.ResourceTracker.' + '_update') + def test_node_removed(self, update_mock, get_mock, + create_mock, pci_tracker_mock, + get_by_hypervisor_mock): + self._test_compute_node_created(update_mock, get_mock, create_mock, + pci_tracker_mock, + get_by_hypervisor_mock) + self.rt.old_resources[_NODENAME] = mock.sentinel.foo + self.assertIn(_NODENAME, self.rt.compute_nodes) + self.assertIn(_NODENAME, self.rt.stats) + self.assertIn(_NODENAME, self.rt.old_resources) + self.rt.remove_node(_NODENAME) + self.assertNotIn(_NODENAME, self.rt.compute_nodes) + self.assertNotIn(_NODENAME, self.rt.stats) + self.assertNotIn(_NODENAME, self.rt.old_resources) + class TestUpdateComputeNode(BaseTestCase): -- cgit v1.2.1