Coverage for manila/scheduler/filters/base.py: 100%
32 statements
« prev ^ index » next coverage.py v7.11.0, created at 2026-02-18 22:19 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2026-02-18 22:19 +0000
1# Copyright (c) 2011-2012 OpenStack Foundation.
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
16"""
17Filter support
18"""
19from oslo_log import log
21from manila.scheduler import base_handler
23LOG = log.getLogger(__name__)
26class BaseFilter(object):
27 """Base class for all filter classes."""
28 def _filter_one(self, obj, filter_properties):
29 """Check if an object passes a filter.
31 Return True if it passes the filter, False otherwise.
32 Override this in a subclass.
33 """
34 return True
36 def filter_all(self, filter_obj_list, filter_properties):
37 """Yield objects that pass the filter.
39 Can be overridden in a subclass, if you need to base filtering
40 decisions on all objects. Otherwise, one can just override
41 _filter_one() to filter a single object.
42 """
43 for obj in filter_obj_list:
44 if self._filter_one(obj, filter_properties):
45 yield obj
47 # Set to true in a subclass if a filter only needs to be run once
48 # for each request rather than for each instance
49 run_filter_once_per_request = False
51 def run_filter_for_index(self, index):
52 """Check if filter needs to be run for the "index-th" instance.
54 Return True if the filter needs to be run for the "index-th"
55 instance in a request. Only need to override this if a filter
56 needs anything other than "first only" or "all" behaviour.
57 """
58 return not (self.run_filter_once_per_request and index > 0)
61class BaseFilterHandler(base_handler.BaseHandler):
62 """Base class to handle loading filter classes.
64 This class should be subclassed where one needs to use filters.
65 """
67 def get_filtered_objects(self, filter_classes, objs,
68 filter_properties, index=0):
69 """Get objects after filter
71 :param filter_classes: filters that will be used to filter the
72 objects
73 :param objs: objects that will be filtered
74 :param filter_properties: client filter properties
75 :param index: This value needs to be increased in the caller
76 function of get_filtered_objects when handling
77 each resource.
78 """
79 list_objs = list(objs)
80 LOG.debug("Starting with %d host(s)", len(list_objs))
81 for filter_cls in filter_classes:
82 cls_name = filter_cls.__name__
83 filter_class = filter_cls()
85 if filter_class.run_filter_for_index(index):
86 objs = filter_class.filter_all(list_objs, filter_properties)
87 if objs is None:
88 LOG.debug("Filter %(cls_name)s says to stop filtering",
89 {'cls_name': cls_name})
90 return (None, cls_name)
91 list_objs = list(objs)
92 msg = ("Filter %(cls_name)s returned %(obj_len)d host(s)"
93 % {'cls_name': cls_name, 'obj_len': len(list_objs)})
94 if not list_objs:
95 LOG.info(msg)
96 break
97 LOG.debug(msg)
98 return (list_objs, cls_name)