Drop compat for non-update_provider_tree code paths
In Train [1] we deprecated support for compute drivers that did not implement the update_provider_tree method. That compat code is now removed along with the get_inventory method definition and (most) references to it. As a result there are more things we can remove but those will come in separate changes. [1] I1eae47bce08f6292d38e893a2122289bcd6f4b58 Change-Id: Ib62ac0b692eb92a2ed364ec9f486ded05def39ad
This commit is contained in:
		@@ -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:
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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.
 | 
			
		||||
 
 | 
			
		||||
@@ -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,
 | 
			
		||||
            []
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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()
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
		Reference in New Issue
	
	Block a user