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

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. 

15 

16""" 

17Filter support 

18""" 

19from oslo_log import log 

20 

21from manila.scheduler import base_handler 

22 

23LOG = log.getLogger(__name__) 

24 

25 

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. 

30 

31 Return True if it passes the filter, False otherwise. 

32 Override this in a subclass. 

33 """ 

34 return True 

35 

36 def filter_all(self, filter_obj_list, filter_properties): 

37 """Yield objects that pass the filter. 

38 

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 

46 

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 

50 

51 def run_filter_for_index(self, index): 

52 """Check if filter needs to be run for the "index-th" instance. 

53 

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) 

59 

60 

61class BaseFilterHandler(base_handler.BaseHandler): 

62 """Base class to handle loading filter classes. 

63 

64 This class should be subclassed where one needs to use filters. 

65 """ 

66 

67 def get_filtered_objects(self, filter_classes, objs, 

68 filter_properties, index=0): 

69 """Get objects after filter 

70 

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

84 

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)