From a79d3d546bbf679fdc7d337824dbe1a26451fbaa Mon Sep 17 00:00:00 2001 From: Eric Fried Date: Wed, 16 Oct 2019 11:57:34 -0500 Subject: [PATCH] Always trait the compute node RP with COMPUTE_NODE We have at least one use case [1] for identifying resource providers which represent compute nodes. There are a few ways we could do that hackishly (e.g. [2], [3]) but the clean way is to have nova-compute mark the provider with a trait, since nova-compute knows which one it is anyway. This commit uses the COMPUTE_NODE trait for this purpose, and bumps the os-traits requirement to 1.1.0 where it is introduced. Arguably this is a no-op until something starts using it, but a release note is added anyway warning that all compute nodes should be upgraded to ussuri (or the trait added manually) for the trait to be useful. [1] https://review.opendev.org/#/c/670112/7/nova/cmd/manage.py@2921 [2] Assume a provider with a certain resource class, like MEMORY_MB, is always a compute node. This is not necessarily future-proof (maybe all MEMORY_MB will someday reside on NUMA node providers; similar for other resource classes) and isn't necessarily true in all cases today anyway (ironic nodes don't have MEMORY_MB inventory) and there's also currently no easy way to query for that (GET /resource_providers?MEMORY_MB:1 won't return "full" providers, and you can't ask for :0). [3] Assume a root provider without the MISC_SHARES_VIA_AGGREGATE trait is a compute node. This assumes you're only using placement for nova-ish things. Change-Id: I4cb9cbe1e02c3f6c6148f73a38d10e8db7e61b1a --- lower-constraints.txt | 2 +- nova/compute/resource_tracker.py | 5 +++++ .../functional/libvirt/test_report_cpu_traits.py | 7 +++++-- .../tests/functional/test_servers_provider_tree.py | 14 ++++++++++---- nova/tests/unit/compute/test_resource_tracker.py | 12 +++++++----- .../new-COMPUTE_NODE-trait-06701d03b17d179f.yaml | 12 ++++++++++++ requirements.txt | 2 +- 7 files changed, 41 insertions(+), 13 deletions(-) create mode 100644 releasenotes/notes/new-COMPUTE_NODE-trait-06701d03b17d179f.yaml diff --git a/lower-constraints.txt b/lower-constraints.txt index ae2a119bdfa2..b3a59698432e 100644 --- a/lower-constraints.txt +++ b/lower-constraints.txt @@ -68,7 +68,7 @@ os-brick==2.6.2 os-client-config==1.29.0 os-resource-classes==0.4.0 os-service-types==1.7.0 -os-traits==0.16.0 +os-traits==1.1.0 os-vif==1.14.0 os-win==3.0.0 os-xenapi==0.3.3 diff --git a/nova/compute/resource_tracker.py b/nova/compute/resource_tracker.py index 034f4f00854e..124b095ab9fe 100644 --- a/nova/compute/resource_tracker.py +++ b/nova/compute/resource_tracker.py @@ -1120,6 +1120,11 @@ class ResourceTracker(object): elif trait in traits: traits.remove(trait) + # Always mark the compute node. This lets other processes (possibly + # unrelated to nova or even OpenStack) find and distinguish these + # providers easily. + traits.add(os_traits.COMPUTE_NODE) + self._sync_compute_service_disabled_trait(context, traits) return list(traits) diff --git a/nova/tests/functional/libvirt/test_report_cpu_traits.py b/nova/tests/functional/libvirt/test_report_cpu_traits.py index 44be4391433a..4a2103b5cec4 100644 --- a/nova/tests/functional/libvirt/test_report_cpu_traits.py +++ b/nova/tests/functional/libvirt/test_report_cpu_traits.py @@ -57,8 +57,9 @@ class LibvirtReportTraitsTests(LibvirtReportTraitsTestBase): # Test CPU traits reported on initial node startup, these specific # trait values are coming from fakelibvirt's baselineCPU result. + # COMPUTE_NODE is always set on the compute node provider. traits = self._get_provider_traits(self.host_uuid) - for trait in ('HW_CPU_X86_VMX', 'HW_CPU_X86_AESNI'): + for trait in ('HW_CPU_X86_VMX', 'HW_CPU_X86_AESNI', 'COMPUTE_NODE'): self.assertIn(trait, traits) self._create_trait('CUSTOM_TRAITS') @@ -73,7 +74,9 @@ class LibvirtReportTraitsTests(LibvirtReportTraitsTestBase): # and it's not in the baseline for the host. traits = set(self._get_provider_traits(self.host_uuid)) expected_traits = self.expected_libvirt_driver_capability_traits.union( - [u'HW_CPU_X86_VMX', u'HW_CPU_X86_AESNI', u'CUSTOM_TRAITS'] + [u'HW_CPU_X86_VMX', u'HW_CPU_X86_AESNI', u'CUSTOM_TRAITS', + # The periodic restored the COMPUTE_NODE trait. + u'COMPUTE_NODE'] ) self.assertItemsEqual(expected_traits, traits) diff --git a/nova/tests/functional/test_servers_provider_tree.py b/nova/tests/functional/test_servers_provider_tree.py index e499b5d65408..6bf60449a094 100644 --- a/nova/tests/functional/test_servers_provider_tree.py +++ b/nova/tests/functional/test_servers_provider_tree.py @@ -81,7 +81,11 @@ class ProviderTreeTests(integrated_helpers.ProviderUsageBaseTestCase): 'step_size': 1, }, }, self._get_provider_inventory(self.host_uuid)) - self.assertItemsEqual(self.expected_fake_driver_capability_traits, + self.expected_compute_node_traits = ( + self.expected_fake_driver_capability_traits.union( + # The COMPUTE_NODE trait is always added + [os_traits.COMPUTE_NODE])) + self.assertItemsEqual(self.expected_compute_node_traits, self._get_provider_traits(self.host_uuid)) def _run_update_available_resource(self, startup): @@ -148,7 +152,7 @@ class ProviderTreeTests(integrated_helpers.ProviderUsageBaseTestCase): self.assertIn('CUSTOM_GOLD', self._get_all_traits()) self.assertEqual(inv, self._get_provider_inventory(self.host_uuid)) self.assertItemsEqual( - traits.union(self.expected_fake_driver_capability_traits), + traits.union(self.expected_compute_node_traits), self._get_provider_traits(self.host_uuid) ) self.assertEqual(aggs, @@ -369,7 +373,7 @@ class ProviderTreeTests(integrated_helpers.ProviderUsageBaseTestCase): self._get_provider_inventory(uuids.pf2_2)['SRIOV_NET_VF']['total']) # Compute don't have any extra traits - self.assertItemsEqual(self.expected_fake_driver_capability_traits, + self.assertItemsEqual(self.expected_compute_node_traits, self._get_provider_traits(self.host_uuid)) # NUMAs don't have any traits @@ -591,6 +595,7 @@ class TraitsTrackingTests(integrated_helpers.ProviderUsageBaseTestCase): self.assertNotIn(custom_trait, global_traits) self.assertIn(os_traits.COMPUTE_NET_ATTACH_INTERFACE, global_traits) self.assertIn(os_traits.COMPUTE_DEVICE_TAGGING, global_traits) + self.assertIn(os_traits.COMPUTE_NODE, global_traits) self.assertEqual([], self._get_all_providers()) self._mock_upt(ptree_traits, []) @@ -599,7 +604,8 @@ class TraitsTrackingTests(integrated_helpers.ProviderUsageBaseTestCase): rp_uuid = self._get_provider_uuid_by_host('host1') expected_traits = set( - ptree_traits + [os_traits.COMPUTE_NET_ATTACH_INTERFACE] + ptree_traits + + [os_traits.COMPUTE_NET_ATTACH_INTERFACE, os_traits.COMPUTE_NODE] ) self.assertItemsEqual(expected_traits, self._get_provider_traits(rp_uuid)) diff --git a/nova/tests/unit/compute/test_resource_tracker.py b/nova/tests/unit/compute/test_resource_tracker.py index 0b401b5f3598..10ea3f882d1c 100644 --- a/nova/tests/unit/compute/test_resource_tracker.py +++ b/nova/tests/unit/compute/test_resource_tracker.py @@ -41,6 +41,7 @@ from nova import test from nova.tests.unit import fake_instance from nova.tests.unit import fake_notifier from nova.tests.unit.objects import test_pci_device as fake_pci_device +from nova.tests.unit import utils from nova.virt import driver _HOSTNAME = 'fake-host' @@ -1599,12 +1600,13 @@ class TestUpdateComputeNode(BaseTestCase): self.rt._update(mock.sentinel.ctx, new_compute) self.driver_mock.capabilities_as_traits.assert_called_once() + # We always decorate with COMPUTE_NODE + exp_traits = {mock.sentinel.trait, os_traits.COMPUTE_NODE} + # Can't predict the order of the traits list, so use ItemsMatcher ptree.update_traits.assert_called_once_with( - new_compute.hypervisor_hostname, - [mock.sentinel.trait] - ) + new_compute.hypervisor_hostname, utils.ItemsMatcher(exp_traits)) mock_sync_disabled.assert_called_once_with( - mock.sentinel.ctx, {mock.sentinel.trait}) + mock.sentinel.ctx, exp_traits) @mock.patch('nova.compute.resource_tracker.ResourceTracker.' '_sync_compute_service_disabled_trait') @@ -1681,7 +1683,7 @@ class TestUpdateComputeNode(BaseTestCase): self.driver_mock.get_inventory.assert_not_called() ptree.update_traits.assert_called_once_with( new_compute.hypervisor_hostname, - [] + [os_traits.COMPUTE_NODE] ) exp_inv = copy.deepcopy(fake_inv) # These ratios and reserved amounts come from fake_upt diff --git a/releasenotes/notes/new-COMPUTE_NODE-trait-06701d03b17d179f.yaml b/releasenotes/notes/new-COMPUTE_NODE-trait-06701d03b17d179f.yaml new file mode 100644 index 000000000000..1160877eba4b --- /dev/null +++ b/releasenotes/notes/new-COMPUTE_NODE-trait-06701d03b17d179f.yaml @@ -0,0 +1,12 @@ +--- +upgrade: + - | + Starting in the Ussuri release, compute node resource providers are + automatically marked with the ``COMPUTE_NODE`` trait. This allows them to + be distinguished easily from other providers, including sharing and nested + providers, as well as other non-compute-related providers in a deployment. + To make effective use of this trait (e.g. for scheduling purposes), all + compute nodes must be upgrade to Ussuri. Alternatively, you can manually + add the trait to pre-Ussuri compute node providers via `openstack resource + provider trait set + `_ diff --git a/requirements.txt b/requirements.txt index 57e45ceba487..6902d2940c5e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -56,7 +56,7 @@ psutil>=3.2.2 # BSD oslo.versionedobjects>=1.35.0 # Apache-2.0 os-brick>=2.6.2 # Apache-2.0 os-resource-classes>=0.4.0 # Apache-2.0 -os-traits>=0.16.0 # Apache-2.0 +os-traits>=1.1.0 # Apache-2.0 os-vif>=1.14.0 # Apache-2.0 os-win>=3.0.0 # Apache-2.0 castellan>=0.16.0 # Apache-2.0