diff --git a/doc/source/reference/update-provider-tree.rst b/doc/source/reference/update-provider-tree.rst index e541556a3934..ab5419f8377c 100644 --- a/doc/source/reference/update-provider-tree.rst +++ b/doc/source/reference/update-provider-tree.rst @@ -23,13 +23,13 @@ Background ---------- In the movement towards using placement for scheduling and resource management, the virt driver method ``get_available_resource`` was initially superseded by -``get_inventory``, whereby the driver could specify its inventory in terms -understood by placement. In Queens, a ``get_traits`` driver method was added. -But ``get_inventory`` is limited to expressing only inventory (not traits or -aggregates). And both of these methods are limited to the resource provider -corresponding to the compute node. +``get_inventory`` (now gone), whereby the driver could specify its inventory in +terms understood by placement. In Queens, a ``get_traits`` driver method was +added. But ``get_inventory`` is limited to expressing only inventory (not +traits or aggregates). And both of these methods are limited to the resource +provider corresponding to the compute node. -Recent developments such as Nested Resource Providers necessitate the ability +Developments such as Nested Resource Providers necessitate the ability for the virt driver to have deeper control over what the resource tracker configures in placement on behalf of the compute node. This need is filled by the virt driver method ``update_provider_tree`` and its consumption by the @@ -130,9 +130,6 @@ aggregates, and traits associated with those resource providers. PF1 PF2 PF3 PF4------BW1 (root) agg2 -This method supersedes ``get_inventory`` and ``get_traits``: if this method is -implemented, neither ``get_inventory`` nor ``get_traits`` is used. - Driver implementations of ``update_provider_tree`` are expected to use public ``ProviderTree`` methods to effect changes to the provider tree passed in. Some of the methods which may be useful are as follows: diff --git a/nova/compute/resource_tracker.py b/nova/compute/resource_tracker.py index b2ba0145cf4d..413ae1c0e784 100644 --- a/nova/compute/resource_tracker.py +++ b/nova/compute/resource_tracker.py @@ -82,6 +82,7 @@ def _instance_is_live_migrating(instance): return False +# TODO(mriedem): Remove this now that get_inventory isn't being used anymore def _normalize_inventory_from_cn_obj(inv_data, cn): """Helper function that injects various information from a compute node object into the inventory dict returned from the virt driver's @@ -1153,59 +1154,38 @@ class ResourceTracker(object): # the inventory, traits, and aggregates throughout. allocs = None try: - try: - self.driver.update_provider_tree(prov_tree, nodename) - except exception.ReshapeNeeded: - if not startup: - # This isn't supposed to happen during periodic, so raise - # it up; the compute manager will treat it specially. - raise - LOG.info("Performing resource provider inventory and " - "allocation data migration during compute service " - "startup or fast-forward upgrade.") - allocs = self.reportclient.get_allocations_for_provider_tree( - context, nodename) - self.driver.update_provider_tree(prov_tree, nodename, - allocations=allocs) + self.driver.update_provider_tree(prov_tree, nodename) + except exception.ReshapeNeeded: + if not startup: + # This isn't supposed to happen during periodic, so raise + # it up; the compute manager will treat it specially. + raise + LOG.info("Performing resource provider inventory and " + "allocation data migration during compute service " + "startup or fast-forward upgrade.") + allocs = self.reportclient.get_allocations_for_provider_tree( + context, nodename) + self.driver.update_provider_tree(prov_tree, nodename, + allocations=allocs) - # Inject driver capabilities traits into the provider - # tree. We need to determine the traits that the virt - # driver owns - so those that come from the tree itself - # (via the virt driver) plus the compute capabilities - # traits, and then merge those with the traits set - # externally that the driver does not own - and remove any - # set on the provider externally that the virt owns but - # aren't in the current list of supported traits. For - # example, let's say we reported multiattach support as a - # trait at t1 and then at t2 it's not, so we need to - # remove it. But at both t1 and t2 there is a - # CUSTOM_VENDOR_TRAIT_X which we can't touch because it - # was set externally on the provider. - # We also want to sync the COMPUTE_STATUS_DISABLED trait based - # on the related nova-compute service's disabled status. - traits = self._get_traits( - context, nodename, provider_tree=prov_tree) - prov_tree.update_traits(nodename, traits) - except NotImplementedError: - # TODO(mriedem): Remove the compatibility code in the U release. - LOG.warning('Compute driver "%s" does not implement the ' - '"update_provider_tree" interface. Compatibility for ' - 'non-update_provider_tree interfaces will be removed ' - 'in a future release and result in an error to report ' - 'inventory for this compute service.', - CONF.compute_driver) - # update_provider_tree isn't implemented yet - try get_inventory - try: - inv_data = self.driver.get_inventory(nodename) - _normalize_inventory_from_cn_obj(inv_data, compute_node) - except NotImplementedError: - # Eventually all virt drivers will return an inventory dict in - # the format that the placement API expects and we'll be able - # to remove this code branch - inv_data = compute_utils.compute_node_to_inventory_dict( - compute_node) - - prov_tree.update_inventory(nodename, inv_data) + # Inject driver capabilities traits into the provider + # tree. We need to determine the traits that the virt + # driver owns - so those that come from the tree itself + # (via the virt driver) plus the compute capabilities + # traits, and then merge those with the traits set + # externally that the driver does not own - and remove any + # set on the provider externally that the virt owns but + # aren't in the current list of supported traits. For + # example, let's say we reported multiattach support as a + # trait at t1 and then at t2 it's not, so we need to + # remove it. But at both t1 and t2 there is a + # CUSTOM_VENDOR_TRAIT_X which we can't touch because it + # was set externally on the provider. + # We also want to sync the COMPUTE_STATUS_DISABLED trait based + # on the related nova-compute service's disabled status. + traits = self._get_traits( + context, nodename, provider_tree=prov_tree) + prov_tree.update_traits(nodename, traits) self.provider_tree = prov_tree diff --git a/nova/compute/utils.py b/nova/compute/utils.py index 7b14046613d9..e48da1aafbda 100644 --- a/nova/compute/utils.py +++ b/nova/compute/utils.py @@ -1463,6 +1463,8 @@ def notify_about_instance_delete(notifier, context, instance, phase=fields.NotificationPhase.END) +# TODO(mriedem): We should be able to remove this now that the ResourceTracker +# requires drivers to implement the update_provider_tree interface. def compute_node_to_inventory_dict(compute_node): """Given a supplied `objects.ComputeNode` object, return a dict, keyed by resource class, of various inventory information. diff --git a/nova/tests/unit/compute/test_resource_tracker.py b/nova/tests/unit/compute/test_resource_tracker.py index 37a3507b5818..a778a31eb3ce 100644 --- a/nova/tests/unit/compute/test_resource_tracker.py +++ b/nova/tests/unit/compute/test_resource_tracker.py @@ -449,7 +449,6 @@ def setup_rt(hostname, virt_resources=_VIRT_DRIVER_AVAIL_RESOURCES): # Make sure we don't change any global fixtures during tests virt_resources = copy.deepcopy(virt_resources) vd.get_available_resource.return_value = virt_resources - vd.get_inventory.side_effect = NotImplementedError def fake_upt(provider_tree, nodename, allocations=None): inventory = { @@ -1514,11 +1513,11 @@ class TestInitComputeNode(BaseTestCase): class TestUpdateComputeNode(BaseTestCase): - + @mock.patch('nova.compute.resource_tracker.ResourceTracker.' + '_sync_compute_service_disabled_trait', new=mock.Mock()) @mock.patch('nova.objects.ComputeNode.save') def test_existing_compute_node_updated_same_resources(self, save_mock): self._setup_rt() - self.driver_mock.update_provider_tree.side_effect = NotImplementedError # This is the same set of resources as the fixture, deliberately. We # are checking below to see that compute_node.save is not needlessly @@ -1531,8 +1530,9 @@ class TestUpdateComputeNode(BaseTestCase): self.rt._update(mock.sentinel.ctx, new_compute) self.assertFalse(save_mock.called) - # Even the compute node is not updated, get_inventory still got called. - self.driver_mock.get_inventory.assert_called_once_with(_NODENAME) + # Even the compute node is not updated, update_provider_tree + # still got called. + self.driver_mock.update_provider_tree.assert_called_once() @mock.patch('nova.compute.resource_tracker.ResourceTracker.' '_sync_compute_service_disabled_trait', new=mock.Mock()) @@ -1558,11 +1558,8 @@ class TestUpdateComputeNode(BaseTestCase): @mock.patch('nova.compute.resource_tracker.ResourceTracker.' '_sync_compute_service_disabled_trait', new=mock.Mock()) - @mock.patch('nova.compute.resource_tracker.' - '_normalize_inventory_from_cn_obj') @mock.patch('nova.objects.ComputeNode.save') - def test_existing_compute_node_updated_new_resources(self, save_mock, - norm_mock): + def test_existing_compute_node_updated_new_resources(self, save_mock): self._setup_rt() orig_compute = _COMPUTE_NODE_FIXTURES[0].obj_clone() @@ -1580,42 +1577,6 @@ class TestUpdateComputeNode(BaseTestCase): self.rt._update(mock.sentinel.ctx, new_compute) save_mock.assert_called_once_with() - # The get_inventory() is not implemented, it shouldn't call - # _normalize_inventory_from_cn_obj - norm_mock.assert_not_called() - - @mock.patch('nova.compute.resource_tracker.' - '_normalize_inventory_from_cn_obj') - @mock.patch('nova.objects.ComputeNode.save') - def test_existing_node_get_inventory_implemented(self, save_mock, - norm_mock): - """The get_inventory() virt driver method is only implemented for some - virt drivers. This method returns inventory information for a - node/provider in a way that the placement API better understands. - """ - self._setup_rt() - self.driver_mock.update_provider_tree.side_effect = NotImplementedError - - # Emulate a driver that has implemented the newish get_inventory() virt - # driver method - self.driver_mock.get_inventory.side_effect = [mock.sentinel.inv_data] - - orig_compute = _COMPUTE_NODE_FIXTURES[0].obj_clone() - self.rt.compute_nodes[_NODENAME] = orig_compute - self.rt.old_resources[_NODENAME] = orig_compute - - # Deliberately changing local_gb to trigger updating inventory - new_compute = orig_compute.obj_clone() - new_compute.local_gb = 210000 - - self.rt._update(mock.sentinel.ctx, new_compute) - save_mock.assert_called_once_with() - norm_mock.assert_called_once_with(mock.sentinel.inv_data, new_compute) - # Assert a warning was logged about using a virt driver that does not - # implement update_provider_tree. - self.assertIn('Compute driver "%s" does not implement the ' - '"update_provider_tree" interface.' % - CONF.compute_driver, self.stdlog.logger.output) @mock.patch('nova.compute.resource_tracker.ResourceTracker.' '_sync_compute_service_disabled_trait') @@ -1654,14 +1615,10 @@ class TestUpdateComputeNode(BaseTestCase): @mock.patch('nova.objects.ComputeNode.save') def test_existing_node_update_provider_tree_implemented( self, save_mock, mock_sync_disabled): - """The update_provider_tree() virt driver method is only implemented - for some virt drivers. This method returns inventory, trait, and + """The update_provider_tree() virt driver method must be implemented + by all virt drivers. This method returns inventory, trait, and aggregate information for resource providers in a tree associated with - the compute node. If this method doesn't raise a NotImplementedError, - it triggers _update() to try get_inventory() and then - compute_node_to_inventory_dict() to produce the inventory data with - which to call the update_from_provider_tree() method of the reporting - client instead. + the compute node. """ fake_inv = { orc.VCPU: { @@ -1721,7 +1678,6 @@ class TestUpdateComputeNode(BaseTestCase): ptree, new_compute.hypervisor_hostname) self.rt.reportclient.update_from_provider_tree.assert_called_once_with( mock.sentinel.ctx, ptree, allocations=None) - self.driver_mock.get_inventory.assert_not_called() ptree.update_traits.assert_called_once_with( new_compute.hypervisor_hostname, [] diff --git a/nova/virt/driver.py b/nova/virt/driver.py index 6cfdfefddeda..722ae9a0f58c 100644 --- a/nova/virt/driver.py +++ b/nova/virt/driver.py @@ -972,9 +972,6 @@ class ComputeDriver(object): node, as well as the inventory, aggregates, and traits associated with those resource providers. - 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``, @@ -1048,12 +1045,6 @@ class ComputeDriver(object): """ raise NotImplementedError() - def get_inventory(self, nodename): - """Return a dict, keyed by resource class, of inventory information for - the supplied node. - """ - raise NotImplementedError() - def capabilities_as_traits(self): """Returns this driver's capabilities dict where the keys are traits diff --git a/nova/virt/powervm/driver.py b/nova/virt/powervm/driver.py index 14a89b29eb50..dfa59f6d8b08 100644 --- a/nova/virt/powervm/driver.py +++ b/nova/virt/powervm/driver.py @@ -167,8 +167,6 @@ class PowerVMDriver(driver.ComputeDriver): this. :return: Dictionary describing resources. """ - # TODO(efried): Switch to get_inventory, per blueprint - # custom-resource-classes-pike # Do this here so it refreshes each time this method is called. self.host_wrapper = pvm_ms.System.get(self.adapter)[0] return self._get_available_resource() diff --git a/releasenotes/notes/ussuri-rm-non-upt-compat-b2847eb93bb609a9.yaml b/releasenotes/notes/ussuri-rm-non-upt-compat-b2847eb93bb609a9.yaml new file mode 100644 index 000000000000..83b285867162 --- /dev/null +++ b/releasenotes/notes/ussuri-rm-non-upt-compat-b2847eb93bb609a9.yaml @@ -0,0 +1,8 @@ +--- +upgrade: + - | + Compatibility code for compute drivers that do not implement the + `update_provider_tree`__ interface has been removed. All compute drivers + must now implement ``update_provider_tree``. + + __ https://docs.openstack.org/nova/latest/reference/update-provider-tree.html