diff --git a/nova/compute/resource_tracker.py b/nova/compute/resource_tracker.py index 39297a860f94..b1af3ffe5bc3 100644 --- a/nova/compute/resource_tracker.py +++ b/nova/compute/resource_tracker.py @@ -616,10 +616,31 @@ class ResourceTracker(object): stats.digest_stats(resources.get('stats')) compute_node.stats = stats - # update the allocation ratios for the related ComputeNode object - compute_node.ram_allocation_ratio = self.ram_allocation_ratio - compute_node.cpu_allocation_ratio = self.cpu_allocation_ratio - compute_node.disk_allocation_ratio = self.disk_allocation_ratio + # Update the allocation ratios for the related ComputeNode object + # but only if the configured values are not the default 0.0; the + # ComputeNode._from_db_object method takes care of providing default + # allocation ratios when the config is left at the 0.0 default, so + # we'll really end up with something like a + # ComputeNode.cpu_allocation_ratio of 16.0, not 0.0. We want to avoid + # resetting the ComputeNode fields to 0.0 because that will make + # the _resource_change method think something changed when really it + # didn't. + # TODO(mriedem): Will this break any scenarios where an operator is + # trying to *reset* the allocation ratios by changing config from + # non-0.0 back to 0.0? Maybe we should only do this if the fields on + # the ComputeNode object are not already set. For example, let's say + # the cpu_allocation_ratio config was 1.0 and then the operator wants + # to get back to the default (16.0 via the facade), and to do that they + # change the config back to 0.0 (or just unset the config option). + # Should we support that or treat these config options as "sticky" in + # that once you start setting them, you can't go back to the implied + # defaults by unsetting or resetting to 0.0? Sort of like how + # per-tenant quota is sticky once you change it in the API. + for res in ('cpu', 'disk', 'ram'): + attr = '%s_allocation_ratio' % res + conf_alloc_ratio = getattr(self, attr) + if conf_alloc_ratio != 0.0: + setattr(compute_node, attr, conf_alloc_ratio) # now copy rest to compute_node compute_node.update_from_virt_driver(resources) diff --git a/nova/tests/unit/compute/test_resource_tracker.py b/nova/tests/unit/compute/test_resource_tracker.py index be6e3be4f0ed..9d5530a078a8 100644 --- a/nova/tests/unit/compute/test_resource_tracker.py +++ b/nova/tests/unit/compute/test_resource_tracker.py @@ -1333,6 +1333,41 @@ class TestUpdateComputeNode(BaseTestCase): self.assertRaises(exc.ComputeHostNotFound, self.rt.get_node_uuid, 'foo') + def test_copy_resources_no_update_allocation_ratios(self): + """Tests that a ComputeNode object's allocation ratio fields are + not set if the configured allocation ratio values are default 0.0. + """ + self._setup_rt() + compute = _COMPUTE_NODE_FIXTURES[0].obj_clone() + compute.obj_reset_changes() # make sure we start clean + self.rt._copy_resources( + compute, self.driver_mock.get_available_resource.return_value) + # Assert that the ComputeNode fields were not changed. + changes = compute.obj_get_changes() + for res in ('cpu', 'disk', 'ram'): + attr_name = '%s_allocation_ratio' % res + self.assertNotIn(attr_name, changes) + + def test_copy_resources_update_allocation_ratios_from_config(self): + """Tests that a ComputeNode object's allocation ratio fields are + set if the configured allocation ratio values are not 0.0. + """ + # Set explicit ratio config values to 1.0 (the default is 0.0). + for res in ('cpu', 'disk', 'ram'): + opt_name = '%s_allocation_ratio' % res + CONF.set_override(opt_name, 1.0) + self._setup_rt() + compute = _COMPUTE_NODE_FIXTURES[0].obj_clone() + compute.obj_reset_changes() # make sure we start clean + self.rt._copy_resources( + compute, self.driver_mock.get_available_resource.return_value) + # Assert that the ComputeNode fields were changed. + changes = compute.obj_get_changes() + for res in ('cpu', 'disk', 'ram'): + attr_name = '%s_allocation_ratio' % res + self.assertIn(attr_name, changes) + self.assertEqual(1.0, changes[attr_name]) + class TestNormalizatInventoryFromComputeNode(test.NoDBTestCase): def test_normalize_libvirt(self):