diff --git a/doc/source/reference/update-provider-tree.rst b/doc/source/reference/update-provider-tree.rst index e165f61104d5..bdaa29d20b7b 100644 --- a/doc/source/reference/update-provider-tree.rst +++ b/doc/source/reference/update-provider-tree.rst @@ -151,6 +151,13 @@ would become: } provider_tree.update_inventory(nodename, inv_data) +When reporting inventory for the standard resource classes ``VCPU``, +``MEMORY_MB`` and ``DISK_GB``, implementors of ``update_provider_tree`` may +need to set the ``allocation_ratio`` and ``reserved`` values in the +``inv_data`` dict based on configuration to reflect changes on the compute +for allocation ratios and reserved resource amounts back to the placement +service. + Porting from get_traits ~~~~~~~~~~~~~~~~~~~~~~~ To replace ``get_traits``, developers should use the diff --git a/nova/compute/resource_tracker.py b/nova/compute/resource_tracker.py index 70790395c225..e9a5ce06c40b 100644 --- a/nova/compute/resource_tracker.py +++ b/nova/compute/resource_tracker.py @@ -944,6 +944,10 @@ class ResourceTracker(object): # compute_node record if not set by the virt driver) because the # virt driver does not and will not have access to the compute_node inv_data = prov_tree.data(nodename).inventory + # TODO(mriedem): Stop calling _normalize_inventory_from_cn_obj when + # a virt driver implements update_provider_tree() since we expect + # the driver to manage the allocation ratios and reserved resource + # amounts. _normalize_inventory_from_cn_obj(inv_data, compute_node) prov_tree.update_inventory(nodename, inv_data) # Flush any changes. If we processed ReshapeNeeded above, allocs is diff --git a/nova/tests/functional/compute/test_resource_tracker.py b/nova/tests/functional/compute/test_resource_tracker.py index 4539dbfe1d0f..c4ef50d743bd 100644 --- a/nova/tests/functional/compute/test_resource_tracker.py +++ b/nova/tests/functional/compute/test_resource_tracker.py @@ -284,6 +284,14 @@ class TestUpdateComputeNodeReservedAndAllocationRatio( CONF.reserved_host_disk_mb) } + def _assert_reserved_inventory(self, inventories): + reserved = self._get_reserved_host_values_from_config() + for rc, res in reserved.items(): + self.assertIn('reserved', inventories[rc]) + self.assertEqual(res, inventories[rc]['reserved'], + 'Unexpected resource provider inventory ' + 'reserved value for %s' % rc) + def test_update_inventory_reserved_and_allocation_ratio_from_conf(self): # Start a compute service which should create a corresponding resource # provider in the placement service. @@ -310,11 +318,7 @@ class TestUpdateComputeNodeReservedAndAllocationRatio( self.assertIn('allocation_ratio', inventories[rc]) self.assertEqual(ratio, inventories[rc]['allocation_ratio'], 'Unexpected allocation ratio for %s' % rc) - reserved = self._get_reserved_host_values_from_config() - for rc, res in reserved.items(): - self.assertIn('reserved', inventories[rc]) - self.assertEqual(res, inventories[rc]['reserved'], - 'Unexpected reserved value for %s' % rc) + self._assert_reserved_inventory(inventories) # Now change the configuration values, restart the compute service, # and ensure the changes are reflected in the resource provider @@ -352,18 +356,9 @@ class TestUpdateComputeNodeReservedAndAllocationRatio( ratio, getattr(cn, '%s_allocation_ratio' % attr_map[rc]), 'Unexpected ComputeNode allocation ratio for %s' % rc) # Make sure the values in placement are updated. - # FIXME(mriedem): The config-driven allocation ratio overrides - # are not reflected in placement until bug 1799727 is fixed. - self.assertNotEqual(ratio, inventories[rc]['allocation_ratio'], - 'Unexpected resource provider inventory ' - 'allocation ratio for %s' % rc) + self.assertEqual(ratio, inventories[rc]['allocation_ratio'], + 'Unexpected resource provider inventory ' + 'allocation ratio for %s' % rc) # The reserved host values should also come from config. - reserved = self._get_reserved_host_values_from_config() - for rc, res in reserved.items(): - self.assertIn('reserved', inventories[rc]) - # FIXME(mriedem): The config-driven reserved overrides - # are not reflected in placement until bug 1799727 is fixed. - self.assertNotEqual(res, inventories[rc]['reserved'], - 'Unexpected resource provider inventory ' - 'reserved value for %s' % rc) + self._assert_reserved_inventory(inventories) diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py index b2774879a538..9685e9370c53 100644 --- a/nova/tests/unit/virt/libvirt/test_driver.py +++ b/nova/tests/unit/virt/libvirt/test_driver.py @@ -17962,18 +17962,24 @@ class TestUpdateProviderTree(test.NoDBTestCase): 'min_unit': 1, 'max_unit': self.vcpus, 'step_size': 1, + 'allocation_ratio': 16.0, + 'reserved': 0, }, rc_fields.ResourceClass.MEMORY_MB: { 'total': self.memory_mb, 'min_unit': 1, 'max_unit': self.memory_mb, 'step_size': 1, + 'allocation_ratio': 1.5, + 'reserved': 512, }, rc_fields.ResourceClass.DISK_GB: { 'total': self.disk_gb, 'min_unit': 1, 'max_unit': self.disk_gb, 'step_size': 1, + 'allocation_ratio': 1.0, + 'reserved': 0, }, } diff --git a/nova/virt/driver.py b/nova/virt/driver.py index 83b6eee52262..59340cbdaf2f 100644 --- a/nova/virt/driver.py +++ b/nova/virt/driver.py @@ -857,6 +857,11 @@ class ComputeDriver(object): """ raise NotImplementedError() + @staticmethod + def _get_reserved_host_disk_gb_from_config(): + import nova.compute.utils as compute_utils # avoid circular import + return compute_utils.convert_mb_to_ceil_gb(CONF.reserved_host_disk_mb) + def update_provider_tree(self, provider_tree, nodename, allocations=None): """Update a ProviderTree object with current resource provider and inventory information. @@ -869,6 +874,12 @@ class ComputeDriver(object): This method supersedes get_inventory(): if this method is implemented, get_inventory() is not used. + Implementors of this interface are expected to set ``allocation_ratio`` + and ``reserved`` values for inventory records, which may be based on + configuration options, e.g. ``[DEFAULT]/cpu_allocation_ratio``, + depending on the driver and resource class. If not provided, allocation + ratio defaults to 1.0 and reserved defaults to 0 in placement. + :note: Renaming the root provider (by deleting it from provider_tree and re-adding it with a different name) is not supported at this time. diff --git a/nova/virt/fake.py b/nova/virt/fake.py index 7010c6442db2..9b394f47f639 100644 --- a/nova/virt/fake.py +++ b/nova/virt/fake.py @@ -500,24 +500,34 @@ class FakeDriver(driver.ComputeDriver): return host_status def update_provider_tree(self, provider_tree, nodename, allocations=None): + # TODO(mriedem): The allocation_ratio config usage will change with + # blueprint initial-allocation-ratios. For now, the allocation ratio + # config values all default to 0.0 and the ComputeNode provides a + # facade for giving the real defaults, so we have to mimic that here. inventory = { 'VCPU': { 'total': self.vcpus, 'min_unit': 1, 'max_unit': self.vcpus, 'step_size': 1, + 'allocation_ratio': CONF.cpu_allocation_ratio or 16.0, + 'reserved': CONF.reserved_host_cpus, }, 'MEMORY_MB': { 'total': self.memory_mb, 'min_unit': 1, 'max_unit': self.memory_mb, 'step_size': 1, + 'allocation_ratio': CONF.ram_allocation_ratio or 1.5, + 'reserved': CONF.reserved_host_memory_mb, }, 'DISK_GB': { 'total': self.local_gb, 'min_unit': 1, 'max_unit': self.local_gb, 'step_size': 1, + 'allocation_ratio': CONF.disk_allocation_ratio or 1.0, + 'reserved': self._get_reserved_host_disk_gb_from_config(), }, } provider_tree.update_inventory(nodename, inventory) diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 6e60f3fe2351..0207e07650f9 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -6455,22 +6455,26 @@ class LibvirtDriver(driver.ComputeDriver): # TODO(sbauza): Use traits to make a better world. vgpus = self._get_vgpu_total() - # NOTE(jaypipes): We leave some fields like allocation_ratio and - # reserved out of the returned dicts here because, for now at least, - # the RT injects those values into the inventory dict based on the - # compute_nodes record values. + # TODO(mriedem): The allocation_ratio config usage will change with + # blueprint initial-allocation-ratios. For now, the allocation ratio + # config values all default to 0.0 and the ComputeNode provides a + # facade for giving the real defaults, so we have to mimic that here. result = { rc_fields.ResourceClass.VCPU: { 'total': vcpus, 'min_unit': 1, 'max_unit': vcpus, 'step_size': 1, + 'allocation_ratio': CONF.cpu_allocation_ratio or 16.0, + 'reserved': CONF.reserved_host_cpus, }, rc_fields.ResourceClass.MEMORY_MB: { 'total': memory_mb, 'min_unit': 1, 'max_unit': memory_mb, 'step_size': 1, + 'allocation_ratio': CONF.ram_allocation_ratio or 1.5, + 'reserved': CONF.reserved_host_memory_mb, }, } @@ -6486,6 +6490,8 @@ class LibvirtDriver(driver.ComputeDriver): 'min_unit': 1, 'max_unit': disk_gb, 'step_size': 1, + 'allocation_ratio': CONF.disk_allocation_ratio or 1.0, + 'reserved': self._get_reserved_host_disk_gb_from_config(), } if vgpus > 0: