From 5edd805fe2395f35ecdfe5b589a51dc00565852f Mon Sep 17 00:00:00 2001 From: Sean Mooney Date: Thu, 22 Jun 2023 19:29:32 +0100 Subject: [PATCH] Remove deprecated AZ filter. This change remvoes the az filter and always enabled the placement pre-filter. As part of this removal the config option to control enabling the pre-filter is removed as it is now mandatory. The AZ filter docs and tests are also removed and an upgrade release note is added. Depends-On: https://review.opendev.org/c/openstack/devstack/+/886972 Change-Id: Icc8580835beb2b4d40341f81c25eb1f024e70ade --- doc/source/admin/availability-zones.rst | 16 +--- doc/source/admin/scheduling.rst | 20 +---- .../contributor/testing/libvirt-numa.rst | 2 +- nova/conf/scheduler.py | 38 --------- nova/objects/selection.py | 1 - .../filters/availability_zone_filter.py | 78 ------------------- nova/scheduler/request_filter.py | 2 - .../api_sample_tests/api_sample_base.py | 16 +--- nova/tests/functional/test_aggregates.py | 21 ----- nova/tests/functional/test_cross_az_attach.py | 3 +- .../filters/test_availability_zone_filters.py | 50 ------------ .../unit/scheduler/test_request_filter.py | 10 --- .../az-filter-removal-587f7337040b6216.yaml | 11 +++ 13 files changed, 20 insertions(+), 248 deletions(-) delete mode 100644 nova/scheduler/filters/availability_zone_filter.py delete mode 100644 nova/tests/unit/scheduler/filters/test_availability_zone_filters.py create mode 100644 releasenotes/notes/az-filter-removal-587f7337040b6216.yaml diff --git a/doc/source/admin/availability-zones.rst b/doc/source/admin/availability-zones.rst index e368c9011f2a..282e8fc9b324 100644 --- a/doc/source/admin/availability-zones.rst +++ b/doc/source/admin/availability-zones.rst @@ -69,10 +69,9 @@ Availability Zones with Placement In order to use placement to honor availability zone requests, there must be placement aggregates that match the membership and UUID of nova host aggregates -that you assign as availability zones. The same key in aggregate metadata used -by the `AvailabilityZoneFilter` filter controls this function, and is enabled by -setting :oslo.config:option:`scheduler.query_placement_for_availability_zone` -to ``True``. As of 24.0.0 (Xena), this is the default. +that you assign as availability zones. An aggregate metadata key is used +to controls this function. As of 28.0.0 (Bobcat), this is the only way to +schedule instances to availability-zones. .. code-block:: console @@ -107,12 +106,6 @@ to ``True``. As of 24.0.0 (Xena), this is the default. $ openstack aggregate set --property availability_zone=az002 myaz - $ openstack --os-placement-api-version=1.2 resource provider aggregate set --aggregate 019e2189-31b3-49e1-aff2-b220ebd91c24 815a5634-86fb-4e1e-8824-8a631fee3e06 - -Without the above configuration, the `AvailabilityZoneFilter` filter must be -enabled in :oslo.config:option:`filter_scheduler.enabled_filters` to retain -proper behavior. - Implications for moving servers ------------------------------- @@ -183,8 +176,7 @@ With respect to availability zones, a server is restricted to a zone if: for details. If the server was not created in a specific zone then it is free to be moved -to other zones, i.e. the :ref:`AvailabilityZoneFilter ` -is a no-op. +to other zones. Resource affinity ~~~~~~~~~~~~~~~~~ diff --git a/doc/source/admin/scheduling.rst b/doc/source/admin/scheduling.rst index 353514ab5543..7c4b2e0bcaea 100644 --- a/doc/source/admin/scheduling.rst +++ b/doc/source/admin/scheduling.rst @@ -10,7 +10,8 @@ a variety of options. In the default configuration, this scheduler considers hosts that meet all the following criteria: -* Are in the requested :term:`Availability Zone` (``AvailabilityZoneFilter``). +* Are in the requested :term:`Availability Zone` + (``map_az_to_placement_aggregate``) placement pre filter. * Can service the request meaning the nova-compute service handling the target node is available and not disabled (``ComputeFilter``). @@ -166,9 +167,6 @@ possible to avoid unnecessary costs. We can sort items by their costs in reverse order. For example, ``ComputeFilter`` is better before any resource calculating filters like ``NUMATopologyFilter``. -In medium/large environments having AvailabilityZoneFilter before any -capability or resource calculating filters can be useful. - .. _AggregateImagePropertiesIsolation: ``AggregateImagePropertiesIsolation`` @@ -349,20 +347,6 @@ Refer to :doc:`/admin/aggregates` for more information. This is a no-op filter. It does not eliminate any of the available hosts. -.. _AvailabilityZoneFilter: - -``AvailabilityZoneFilter`` -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Filters hosts by availability zone. It passes hosts matching the availability -zone specified in the instance properties. Use a comma to specify multiple -zones. The filter will then ensure it matches any zone specified. - -You must enable this filter for the scheduler to respect availability zones in -requests. - -Refer to :doc:`/admin/availability-zones` for more information. - .. _ComputeCapabilitiesFilter: ``ComputeCapabilitiesFilter`` diff --git a/doc/source/contributor/testing/libvirt-numa.rst b/doc/source/contributor/testing/libvirt-numa.rst index 589532373bde..cf738b45a991 100644 --- a/doc/source/contributor/testing/libvirt-numa.rst +++ b/doc/source/contributor/testing/libvirt-numa.rst @@ -134,7 +134,7 @@ For example: [[post-config|$NOVA_CONF]] [filter_scheduler] - enabled_filters=ComputeFilter,AvailabilityZoneFilter,ComputeCapabilitiesFilter,ImagePropertiesFilter,PciPassthroughFilter,NUMATopologyFilter + enabled_filters=ComputeFilter,ComputeCapabilitiesFilter,ImagePropertiesFilter,PciPassthroughFilter,NUMATopologyFilter EOF $ FORCE=yes ./stack.sh diff --git a/nova/conf/scheduler.py b/nova/conf/scheduler.py index c7aa2ad76d43..eb982f4485b6 100644 --- a/nova/conf/scheduler.py +++ b/nova/conf/scheduler.py @@ -146,44 +146,6 @@ Possible values: Related options: - ``[scheduler] placement_aggregate_required_for_tenants`` -"""), - cfg.BoolOpt("query_placement_for_availability_zone", - default=True, - deprecated_for_removal=True, - deprecated_since='24.0.0', - deprecated_reason=""" -Since the introduction of placement pre-filters in 18.0.0 (Rocky), we have -supported tracking Availability Zones either natively in placement or using the -legacy ``AvailabilityZoneFilter`` scheduler filter. In 24.0.0 (Xena), the -filter-based approach has been deprecated for removal in favor of the -placement-based approach. As a result, this config option has also been -deprecated and will be removed when the ``AvailabilityZoneFilter`` filter is -removed. -""", - help=""" -Use placement to determine availability zones. - -This setting causes the scheduler to look up a host aggregate with the -metadata key of `availability_zone` set to the value provided by an -incoming request, and request results from placement be limited to that -aggregate. - -The matching aggregate UUID must be mirrored in placement for proper -operation. If no host aggregate with the `availability_zone` key is -found, or that aggregate does not match one in placement, the result will -be the same as not finding any suitable hosts. - -Note that if you disable this flag, you **must** enable the (less efficient) -``AvailabilityZoneFilter`` in the scheduler in order to availability zones to -work correctly. - -Possible values: - -- A boolean value. - -Related options: - -- ``[filter_scheduler] enabled_filters`` """), cfg.BoolOpt("query_placement_for_image_type_support", default=False, diff --git a/nova/objects/selection.py b/nova/objects/selection.py index e13f22600f5a..a5ba5c27341e 100644 --- a/nova/objects/selection.py +++ b/nova/objects/selection.py @@ -72,7 +72,6 @@ class Selection(base.NovaObject, ovo_base.ComparableVersionedObject): """ allocation_request_json = jsonutils.dumps(allocation_request) limits = objects.SchedulerLimits.from_dict(host_state.limits) - # Note that the AZ logic here is similar to the AvailabilityZoneFilter. metadata = filter_utils.aggregate_metadata_get_by_host( host_state, key='availability_zone') availability_zone = metadata.get('availability_zone') diff --git a/nova/scheduler/filters/availability_zone_filter.py b/nova/scheduler/filters/availability_zone_filter.py deleted file mode 100644 index a0f4a669b00c..000000000000 --- a/nova/scheduler/filters/availability_zone_filter.py +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright (c) 2011-2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_log import log as logging - -import nova.conf -from nova.scheduler import filters -from nova.scheduler.filters import utils - -LOG = logging.getLogger(__name__) - -CONF = nova.conf.CONF - - -class AvailabilityZoneFilter(filters.BaseHostFilter): - """Filters Hosts by availability zone. - - Works with aggregate metadata availability zones, using the key - 'availability_zone' - Note: in theory a compute node can be part of multiple availability_zones - """ - - # Availability zones do not change within a request - run_filter_once_per_request = True - - RUN_ON_REBUILD = False - - def __init__(self): - super().__init__() - if CONF.scheduler.query_placement_for_availability_zone: - LOG.warning( - "The 'AvailabilityZoneFilter' is deprecated since the 24.0.0 " - "(Xena) release. Since the 18.0.0 (Rocky) release, nova " - "has supported mapping AZs to placement aggregates. " - "The feature is enabled by the " - "'query_placement_for_availability_zone' config option and " - "is now enabled by default. As such, the " - "'AvailabilityZoneFilter' is no longer required. Nova is " - "currently configured to use both placement and the " - "AvailabilityZoneFilter for AZ enforcement." - ) - - def host_passes(self, host_state, spec_obj): - availability_zone = spec_obj.availability_zone - - if not availability_zone: - return True - - metadata = utils.aggregate_metadata_get_by_host( - host_state, key='availability_zone') - - if 'availability_zone' in metadata: - hosts_passes = availability_zone in metadata['availability_zone'] - host_az = metadata['availability_zone'] - else: - hosts_passes = availability_zone == CONF.default_availability_zone - host_az = CONF.default_availability_zone - - if not hosts_passes: - LOG.debug("Availability Zone '%(az)s' requested. " - "%(host_state)s has AZs: %(host_az)s", - {'host_state': host_state, - 'az': availability_zone, - 'host_az': host_az}) - - return hosts_passes diff --git a/nova/scheduler/request_filter.py b/nova/scheduler/request_filter.py index bf5c32f37201..31b7f2c0ac88 100644 --- a/nova/scheduler/request_filter.py +++ b/nova/scheduler/request_filter.py @@ -142,8 +142,6 @@ def map_az_to_placement_aggregate(ctxt, request_spec): This will modify request_spec to request hosts in an aggregate that matches the desired AZ of the user's request. """ - if not CONF.scheduler.query_placement_for_availability_zone: - return False az_hint = request_spec.availability_zone if not az_hint: diff --git a/nova/tests/functional/api_sample_tests/api_sample_base.py b/nova/tests/functional/api_sample_tests/api_sample_base.py index be8e07a94119..f722d1efc0be 100644 --- a/nova/tests/functional/api_sample_tests/api_sample_base.py +++ b/nova/tests/functional/api_sample_tests/api_sample_base.py @@ -67,7 +67,7 @@ class ApiSampleTestBaseV21(testscenarios.WithScenarios, # correctly constructed. USE_PROJECT_ID = True # Availability zones for the API samples tests. Can be overridden by - # sub-classes. If set, the AvailabilityZoneFilter is not used. + # sub-classes. availability_zones = ['us-west'] scenarios = [ @@ -122,17 +122,3 @@ class ApiSampleTestBaseV21(testscenarios.WithScenarios, def _setup_services(self): pass - - def _setup_scheduler_service(self): - """Overrides _IntegratedTestBase._setup_scheduler_service to filter - out the AvailabilityZoneFilter prior to starting the scheduler. - """ - if self.availability_zones: - # The test is using fake zones so disable the - # AvailabilityZoneFilter which is otherwise enabled by default. - enabled_filters = CONF.filter_scheduler.enabled_filters - if 'AvailabilityZoneFilter' in enabled_filters: - enabled_filters.remove('AvailabilityZoneFilter') - self.flags(enabled_filters=enabled_filters, - group='filter_scheduler') - return super(ApiSampleTestBaseV21, self)._setup_scheduler_service() diff --git a/nova/tests/functional/test_aggregates.py b/nova/tests/functional/test_aggregates.py index 1ffa3ada92cc..6bbbf3cfdf46 100644 --- a/nova/tests/functional/test_aggregates.py +++ b/nova/tests/functional/test_aggregates.py @@ -544,25 +544,6 @@ class TenantAggregateFilterTest(AggregateRequestFiltersTest): self.assertEqual('host2', self._get_instance_host(server)) -class AvailabilityZoneFilterTest(AggregateRequestFiltersTest): - def setUp(self): - # Default to enabling the filter - self.flags(query_placement_for_availability_zone=True, - group='scheduler') - - # Use custom weigher to make sure that we have a predictable - # scheduling sort order. - self.useFixture(nova_fixtures.HostNameWeigherFixture()) - super(AvailabilityZoneFilterTest, self).setUp() - - def test_filter_with_az(self): - self._set_az_aggregate('only-host2', 'myaz') - server1 = self._boot_server(az='myaz') - server2 = self._boot_server(az='myaz') - hosts = [self._get_instance_host(s) for s in (server1, server2)] - self.assertEqual(['host2', 'host2'], hosts) - - class IsolateAggregateFilterTest(AggregateRequestFiltersTest): def setUp(self): # Default to enabling the filter @@ -848,8 +829,6 @@ class TestAggregateFiltersTogether(AggregateRequestFiltersTest): group='scheduler') self.flags(placement_aggregate_required_for_tenants=True, group='scheduler') - self.flags(query_placement_for_availability_zone=True, - group='scheduler') self.flags(enable_isolated_aggregate_filtering=True, group='scheduler') # setting traits to flavors diff --git a/nova/tests/functional/test_cross_az_attach.py b/nova/tests/functional/test_cross_az_attach.py index 0987e6737621..26a08f518f77 100644 --- a/nova/tests/functional/test_cross_az_attach.py +++ b/nova/tests/functional/test_cross_az_attach.py @@ -42,8 +42,7 @@ class CrossAZAttachTestCase(test.TestCase, api_version='v2.1')).admin_api self.start_service('conductor') self.start_service('scheduler') - # Start two compute services and add them to the AZ. This allows us to - # get past the AvailabilityZoneFilter and build a server. + # Start two compute service and add it to the AZ. self.start_service('compute', host='host1') self.start_service('compute', host='host2') agg_id = self.api.post_aggregate({'aggregate': { diff --git a/nova/tests/unit/scheduler/filters/test_availability_zone_filters.py b/nova/tests/unit/scheduler/filters/test_availability_zone_filters.py deleted file mode 100644 index 38a75452ba7e..000000000000 --- a/nova/tests/unit/scheduler/filters/test_availability_zone_filters.py +++ /dev/null @@ -1,50 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from unittest import mock - -from nova import objects -from nova.scheduler.filters import availability_zone_filter -from nova import test -from nova.tests.unit.scheduler import fakes - - -@mock.patch('nova.scheduler.filters.utils.aggregate_metadata_get_by_host') -class TestAvailabilityZoneFilter(test.NoDBTestCase): - - def setUp(self): - super(TestAvailabilityZoneFilter, self).setUp() - self.filt_cls = availability_zone_filter.AvailabilityZoneFilter() - - @staticmethod - def _make_zone_request(zone): - return objects.RequestSpec( - context=mock.sentinel.ctx, - availability_zone=zone) - - def test_availability_zone_filter_same(self, agg_mock): - agg_mock.return_value = {'availability_zone': set(['nova'])} - request = self._make_zone_request('nova') - host = fakes.FakeHostState('host1', 'node1', {}) - self.assertTrue(self.filt_cls.host_passes(host, request)) - - def test_availability_zone_filter_same_comma(self, agg_mock): - agg_mock.return_value = {'availability_zone': set(['nova', 'nova2'])} - request = self._make_zone_request('nova') - host = fakes.FakeHostState('host1', 'node1', {}) - self.assertTrue(self.filt_cls.host_passes(host, request)) - - def test_availability_zone_filter_different(self, agg_mock): - agg_mock.return_value = {'availability_zone': set(['nova'])} - request = self._make_zone_request('bad') - host = fakes.FakeHostState('host1', 'node1', {}) - self.assertFalse(self.filt_cls.host_passes(host, request)) diff --git a/nova/tests/unit/scheduler/test_request_filter.py b/nova/tests/unit/scheduler/test_request_filter.py index 77e538006a8f..cedfd5066499 100644 --- a/nova/tests/unit/scheduler/test_request_filter.py +++ b/nova/tests/unit/scheduler/test_request_filter.py @@ -32,8 +32,6 @@ class TestRequestFilter(test.NoDBTestCase): project_id=uuids.project) self.flags(limit_tenants_to_placement_aggregate=True, group='scheduler') - self.flags(query_placement_for_availability_zone=True, - group='scheduler') self.flags(enable_isolated_aggregate_filtering=True, group='scheduler') self.flags(query_placement_for_routed_network_aggregates=True, @@ -260,14 +258,6 @@ class TestRequestFilter(test.NoDBTestCase): getmd.assert_called_once_with(self.context, key='availability_zone', value='fooaz') - @mock.patch('nova.objects.AggregateList.get_by_metadata') - def test_map_az_disabled(self, getmd): - self.flags(query_placement_for_availability_zone=False, - group='scheduler') - reqspec = objects.RequestSpec(availability_zone='fooaz') - request_filter.map_az_to_placement_aggregate(self.context, reqspec) - getmd.assert_not_called() - @mock.patch('nova.objects.aggregate.AggregateList.' 'get_non_matching_by_metadata_keys') @mock.patch('nova.objects.AggregateList.get_by_metadata') diff --git a/releasenotes/notes/az-filter-removal-587f7337040b6216.yaml b/releasenotes/notes/az-filter-removal-587f7337040b6216.yaml new file mode 100644 index 000000000000..2072d39640ee --- /dev/null +++ b/releasenotes/notes/az-filter-removal-587f7337040b6216.yaml @@ -0,0 +1,11 @@ +--- +upgrade: + - | + The ``AvailabilityZoneFilter`` was deprecated for removal + in 24.0.0 (Xena) and has now been removed. + The functionality of the``AvailabilityZoneFilter`` has been + replaced by the``map_az_to_placement_aggregate`` pre-filter. + The pre-filter was introduced in 18.0.0 (Rocky) and enabled + by default in 24.0.0 (Xena). This pre-filter is now always + enabled and the ``[scheduler] query_placement_for_availability_zone`` + config option has been removed.