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
This commit is contained in:
Sean Mooney 2023-06-22 19:29:32 +01:00
parent e02c5f0e7a
commit 5edd805fe2
13 changed files with 20 additions and 248 deletions

View File

@ -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 <AvailabilityZoneFilter>`
is a no-op.
to other zones.
Resource affinity
~~~~~~~~~~~~~~~~~

View File

@ -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``

View File

@ -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

View File

@ -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,

View File

@ -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')

View File

@ -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

View File

@ -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:

View File

@ -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()

View File

@ -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

View File

@ -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': {

View File

@ -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))

View File

@ -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')

View File

@ -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.