summaryrefslogtreecommitdiff
path: root/tests/unit/scheduler/test_host_filters.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/unit/scheduler/test_host_filters.py')
-rw-r--r--tests/unit/scheduler/test_host_filters.py704
1 files changed, 0 insertions, 704 deletions
diff --git a/tests/unit/scheduler/test_host_filters.py b/tests/unit/scheduler/test_host_filters.py
deleted file mode 100644
index ac6b5dcf..00000000
--- a/tests/unit/scheduler/test_host_filters.py
+++ /dev/null
@@ -1,704 +0,0 @@
-# Copyright 2011 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.
-
-"""
-Tests For Scheduler Host Filters.
-"""
-
-from oslo_context import context
-from oslo_serialization import jsonutils
-from oslotest import base as test_base
-
-from openstack.common.scheduler import filters
-from openstack.common.scheduler.filters import extra_specs_ops
-from tests.unit.scheduler import fake_hosts as fakes
-
-
-class TestFilter(filters.BaseHostFilter):
- pass
-
-
-class TestBogusFilter(object):
- """Class that doesn't inherit from BaseHostFilter."""
- pass
-
-
-class ExtraSpecsOpsTestCase(test_base.BaseTestCase):
- def _do_extra_specs_ops_test(self, value, req, matches):
- assertion = self.assertTrue if matches else self.assertFalse
- assertion(extra_specs_ops.match(value, req))
-
- def test_extra_specs_matches_simple(self):
- self._do_extra_specs_ops_test(
- value='1',
- req='1',
- matches=True)
-
- def test_extra_specs_fails_simple(self):
- self._do_extra_specs_ops_test(
- value='',
- req='1',
- matches=False)
-
- def test_extra_specs_fails_simple2(self):
- self._do_extra_specs_ops_test(
- value='3',
- req='1',
- matches=False)
-
- def test_extra_specs_fails_simple3(self):
- self._do_extra_specs_ops_test(
- value='222',
- req='2',
- matches=False)
-
- def test_extra_specs_fails_with_bogus_ops(self):
- self._do_extra_specs_ops_test(
- value='4',
- req='> 2',
- matches=False)
-
- def test_extra_specs_matches_with_op_eq(self):
- self._do_extra_specs_ops_test(
- value='123',
- req='= 123',
- matches=True)
-
- def test_extra_specs_matches_with_op_eq2(self):
- self._do_extra_specs_ops_test(
- value='124',
- req='= 123',
- matches=True)
-
- def test_extra_specs_fails_with_op_eq(self):
- self._do_extra_specs_ops_test(
- value='34',
- req='= 234',
- matches=False)
-
- def test_extra_specs_fails_with_op_eq3(self):
- self._do_extra_specs_ops_test(
- value='34',
- req='=',
- matches=False)
-
- def test_extra_specs_matches_with_op_seq(self):
- self._do_extra_specs_ops_test(
- value='123',
- req='s== 123',
- matches=True)
-
- def test_extra_specs_fails_with_op_seq(self):
- self._do_extra_specs_ops_test(
- value='1234',
- req='s== 123',
- matches=False)
-
- def test_extra_specs_matches_with_op_sneq(self):
- self._do_extra_specs_ops_test(
- value='1234',
- req='s!= 123',
- matches=True)
-
- def test_extra_specs_fails_with_op_sneq(self):
- self._do_extra_specs_ops_test(
- value='123',
- req='s!= 123',
- matches=False)
-
- def test_extra_specs_fails_with_op_sge(self):
- self._do_extra_specs_ops_test(
- value='1000',
- req='s>= 234',
- matches=False)
-
- def test_extra_specs_fails_with_op_sle(self):
- self._do_extra_specs_ops_test(
- value='1234',
- req='s<= 1000',
- matches=False)
-
- def test_extra_specs_fails_with_op_sl(self):
- self._do_extra_specs_ops_test(
- value='2',
- req='s< 12',
- matches=False)
-
- def test_extra_specs_fails_with_op_sg(self):
- self._do_extra_specs_ops_test(
- value='12',
- req='s> 2',
- matches=False)
-
- def test_extra_specs_matches_with_op_in(self):
- self._do_extra_specs_ops_test(
- value='12311321',
- req='<in> 11',
- matches=True)
-
- def test_extra_specs_matches_with_op_in2(self):
- self._do_extra_specs_ops_test(
- value='12311321',
- req='<in> 12311321',
- matches=True)
-
- def test_extra_specs_matches_with_op_in3(self):
- self._do_extra_specs_ops_test(
- value='12311321',
- req='<in> 12311321 <in>',
- matches=True)
-
- def test_extra_specs_fails_with_op_in(self):
- self._do_extra_specs_ops_test(
- value='12310321',
- req='<in> 11',
- matches=False)
-
- def test_extra_specs_fails_with_op_in2(self):
- self._do_extra_specs_ops_test(
- value='12310321',
- req='<in> 11 <in>',
- matches=False)
-
- def test_extra_specs_matches_with_op_is(self):
- self._do_extra_specs_ops_test(
- value=True,
- req='<is> True',
- matches=True)
-
- def test_extra_specs_matches_with_op_is2(self):
- self._do_extra_specs_ops_test(
- value=False,
- req='<is> False',
- matches=True)
-
- def test_extra_specs_matches_with_op_is3(self):
- self._do_extra_specs_ops_test(
- value=False,
- req='<is> Nonsense',
- matches=True)
-
- def test_extra_specs_fails_with_op_is(self):
- self._do_extra_specs_ops_test(
- value=True,
- req='<is> False',
- matches=False)
-
- def test_extra_specs_fails_with_op_is2(self):
- self._do_extra_specs_ops_test(
- value=False,
- req='<is> True',
- matches=False)
-
- def test_extra_specs_matches_with_op_or(self):
- self._do_extra_specs_ops_test(
- value='12',
- req='<or> 11 <or> 12',
- matches=True)
-
- def test_extra_specs_matches_with_op_or2(self):
- self._do_extra_specs_ops_test(
- value='12',
- req='<or> 11 <or> 12 <or>',
- matches=True)
-
- def test_extra_specs_fails_with_op_or(self):
- self._do_extra_specs_ops_test(
- value='13',
- req='<or> 11 <or> 12',
- matches=False)
-
- def test_extra_specs_fails_with_op_or2(self):
- self._do_extra_specs_ops_test(
- value='13',
- req='<or> 11 <or> 12 <or>',
- matches=False)
-
- def test_extra_specs_matches_with_op_le(self):
- self._do_extra_specs_ops_test(
- value='2',
- req='<= 10',
- matches=True)
-
- def test_extra_specs_fails_with_op_le(self):
- self._do_extra_specs_ops_test(
- value='3',
- req='<= 2',
- matches=False)
-
- def test_extra_specs_matches_with_op_ge(self):
- self._do_extra_specs_ops_test(
- value='3',
- req='>= 1',
- matches=True)
-
- def test_extra_specs_fails_with_op_ge(self):
- self._do_extra_specs_ops_test(
- value='2',
- req='>= 3',
- matches=False)
-
-
-class HostFiltersTestCase(test_base.BaseTestCase):
- """Test case for host filters."""
-
- def setUp(self):
- super(HostFiltersTestCase, self).setUp()
- self.context = context.RequestContext('fake', 'fake')
- self.json_query = jsonutils.dumps(
- ['and', ['>=', '$free_ram_mb', 1024],
- ['>=', '$free_disk_mb', 200 * 1024]])
- namespace = 'openstack.common.scheduler.filters'
- filter_handler = filters.HostFilterHandler(namespace)
- classes = filter_handler.get_all_classes()
- self.class_map = {}
- for cls in classes:
- self.class_map[cls.__name__] = cls
-
- def test_all_filters(self):
- # Double check at least a couple of known filters exist
- self.assertTrue('JsonFilter' in self.class_map)
- self.assertTrue('CapabilitiesFilter' in self.class_map)
- self.assertTrue('AvailabilityZoneFilter' in self.class_map)
- self.assertTrue('IgnoreAttemptedHostsFilter' in self.class_map)
-
- def _do_test_type_filter_extra_specs(self, ecaps, especs, passes):
- filt_cls = self.class_map['CapabilitiesFilter']()
- capabilities = {'enabled': True}
- capabilities.update(ecaps)
- service = {'disabled': False}
- filter_properties = {'resource_type': {'name': 'fake_type',
- 'extra_specs': especs}}
- host = fakes.FakeHostState('host1',
- {'free_capacity_gb': 1024,
- 'capabilities': capabilities,
- 'service': service})
- assertion = self.assertTrue if passes else self.assertFalse
- assertion(filt_cls.host_passes(host, filter_properties))
-
- def test_capability_filter_passes_extra_specs_simple(self):
- self._do_test_type_filter_extra_specs(
- ecaps={'opt1': '1', 'opt2': '2'},
- especs={'opt1': '1', 'opt2': '2'},
- passes=True)
-
- def test_capability_filter_fails_extra_specs_simple(self):
- self._do_test_type_filter_extra_specs(
- ecaps={'opt1': '1', 'opt2': '2'},
- especs={'opt1': '1', 'opt2': '222'},
- passes=False)
-
- def test_capability_filter_passes_extra_specs_complex(self):
- self._do_test_type_filter_extra_specs(
- ecaps={'opt1': 10, 'opt2': 5},
- especs={'opt1': '>= 2', 'opt2': '<= 8'},
- passes=True)
-
- def test_capability_filter_fails_extra_specs_complex(self):
- self._do_test_type_filter_extra_specs(
- ecaps={'opt1': 10, 'opt2': 5},
- especs={'opt1': '>= 2', 'opt2': '>= 8'},
- passes=False)
-
- def test_capability_filter_passes_scope_extra_specs(self):
- self._do_test_type_filter_extra_specs(
- ecaps={'scope_lv1': {'opt1': 10}},
- especs={'capabilities:scope_lv1:opt1': '>= 2'},
- passes=True)
-
- def test_capability_filter_passes_fakescope_extra_specs(self):
- self._do_test_type_filter_extra_specs(
- ecaps={'scope_lv1': {'opt1': 10}, 'opt2': 5},
- especs={'scope_lv1:opt1': '= 2', 'opt2': '>= 3'},
- passes=True)
-
- def test_capability_filter_fails_scope_extra_specs(self):
- self._do_test_type_filter_extra_specs(
- ecaps={'scope_lv1': {'opt1': 10}},
- especs={'capabilities:scope_lv1:opt1': '<= 2'},
- passes=False)
-
- def test_capability_filter_passes_multi_level_scope_extra_specs(self):
- self._do_test_type_filter_extra_specs(
- ecaps={'scope_lv0': {'scope_lv1':
- {'scope_lv2': {'opt1': 10}}}},
- especs={'capabilities:scope_lv0:scope_lv1:scope_lv2:opt1': '>= 2'},
- passes=True)
-
- def test_capability_filter_fails_wrong_scope_extra_specs(self):
- self._do_test_type_filter_extra_specs(
- ecaps={'scope_lv0': {'opt1': 10}},
- especs={'capabilities:scope_lv1:opt1': '>= 2'},
- passes=False)
-
- def test_json_filter_passes(self):
- filt_cls = self.class_map['JsonFilter']()
- filter_properties = {'resource_type': {'memory_mb': 1024,
- 'root_gb': 200,
- 'ephemeral_gb': 0},
- 'scheduler_hints': {'query': self.json_query}}
- capabilities = {'enabled': True}
- host = fakes.FakeHostState('host1',
- {'free_ram_mb': 1024,
- 'free_disk_mb': 200 * 1024,
- 'capabilities': capabilities})
- self.assertTrue(filt_cls.host_passes(host, filter_properties))
-
- def test_json_filter_passes_with_no_query(self):
- filt_cls = self.class_map['JsonFilter']()
- filter_properties = {'resource_type': {'memory_mb': 1024,
- 'root_gb': 200,
- 'ephemeral_gb': 0}}
- capabilities = {'enabled': True}
- host = fakes.FakeHostState('host1',
- {'free_ram_mb': 0,
- 'free_disk_mb': 0,
- 'capabilities': capabilities})
- self.assertTrue(filt_cls.host_passes(host, filter_properties))
-
- def test_json_filter_fails_on_memory(self):
- filt_cls = self.class_map['JsonFilter']()
- filter_properties = {'resource_type': {'memory_mb': 1024,
- 'root_gb': 200,
- 'ephemeral_gb': 0},
- 'scheduler_hints': {'query': self.json_query}}
- capabilities = {'enabled': True}
- host = fakes.FakeHostState('host1',
- {'free_ram_mb': 1023,
- 'free_disk_mb': 200 * 1024,
- 'capabilities': capabilities})
- self.assertFalse(filt_cls.host_passes(host, filter_properties))
-
- def test_json_filter_fails_on_disk(self):
- filt_cls = self.class_map['JsonFilter']()
- filter_properties = {'resource_type': {'memory_mb': 1024,
- 'root_gb': 200,
- 'ephemeral_gb': 0},
- 'scheduler_hints': {'query': self.json_query}}
- capabilities = {'enabled': True}
- host = fakes.FakeHostState('host1',
- {'free_ram_mb': 1024,
- 'free_disk_mb': (200 * 1024) - 1,
- 'capabilities': capabilities})
- self.assertFalse(filt_cls.host_passes(host, filter_properties))
-
- def test_json_filter_fails_on_caps_disabled(self):
- filt_cls = self.class_map['JsonFilter']()
- json_query = jsonutils.dumps(
- ['and', ['>=', '$free_ram_mb', 1024],
- ['>=', '$free_disk_mb', 200 * 1024],
- '$capabilities.enabled'])
- filter_properties = {'resource_type': {'memory_mb': 1024,
- 'root_gb': 200,
- 'ephemeral_gb': 0},
- 'scheduler_hints': {'query': json_query}}
- capabilities = {'enabled': False}
- host = fakes.FakeHostState('host1',
- {'free_ram_mb': 1024,
- 'free_disk_mb': 200 * 1024,
- 'capabilities': capabilities})
- self.assertFalse(filt_cls.host_passes(host, filter_properties))
-
- def test_json_filter_fails_on_service_disabled(self):
- filt_cls = self.class_map['JsonFilter']()
- json_query = jsonutils.dumps(
- ['and', ['>=', '$free_ram_mb', 1024],
- ['>=', '$free_disk_mb', 200 * 1024],
- ['not', '$service.disabled']])
- filter_properties = {'resource_type': {'memory_mb': 1024,
- 'local_gb': 200},
- 'scheduler_hints': {'query': json_query}}
- capabilities = {'enabled': True}
- host = fakes.FakeHostState('host1',
- {'free_ram_mb': 1024,
- 'free_disk_mb': 200 * 1024,
- 'capabilities': capabilities})
- self.assertFalse(filt_cls.host_passes(host, filter_properties))
-
- def test_json_filter_happy_day(self):
- """Test json filter more thoroughly."""
- filt_cls = self.class_map['JsonFilter']()
- raw = ['and',
- '$capabilities.enabled',
- ['=', '$capabilities.opt1', 'match'],
- ['or',
- ['and',
- ['<', '$free_ram_mb', 30],
- ['<', '$free_disk_mb', 300]],
- ['and',
- ['>', '$free_ram_mb', 30],
- ['>', '$free_disk_mb', 300]]]]
- filter_properties = {
- 'scheduler_hints': {
- 'query': jsonutils.dumps(raw),
- },
- }
-
- # Passes
- capabilities = {'enabled': True, 'opt1': 'match'}
- service = {'disabled': False}
- host = fakes.FakeHostState('host1',
- {'free_ram_mb': 10,
- 'free_disk_mb': 200,
- 'capabilities': capabilities,
- 'service': service})
- self.assertTrue(filt_cls.host_passes(host, filter_properties))
-
- # Passes
- capabilities = {'enabled': True, 'opt1': 'match'}
- service = {'disabled': False}
- host = fakes.FakeHostState('host1',
- {'free_ram_mb': 40,
- 'free_disk_mb': 400,
- 'capabilities': capabilities,
- 'service': service})
- self.assertTrue(filt_cls.host_passes(host, filter_properties))
-
- # Fails due to capabilities being disabled
- capabilities = {'enabled': False, 'opt1': 'match'}
- service = {'disabled': False}
- host = fakes.FakeHostState('host1',
- {'free_ram_mb': 40,
- 'free_disk_mb': 400,
- 'capabilities': capabilities,
- 'service': service})
- self.assertFalse(filt_cls.host_passes(host, filter_properties))
-
- # Fails due to being exact memory/disk we don't want
- capabilities = {'enabled': True, 'opt1': 'match'}
- service = {'disabled': False}
- host = fakes.FakeHostState('host1',
- {'free_ram_mb': 30,
- 'free_disk_mb': 300,
- 'capabilities': capabilities,
- 'service': service})
- self.assertFalse(filt_cls.host_passes(host, filter_properties))
-
- # Fails due to memory lower but disk higher
- capabilities = {'enabled': True, 'opt1': 'match'}
- service = {'disabled': False}
- host = fakes.FakeHostState('host1',
- {'free_ram_mb': 20,
- 'free_disk_mb': 400,
- 'capabilities': capabilities,
- 'service': service})
- self.assertFalse(filt_cls.host_passes(host, filter_properties))
-
- # Fails due to capabilities 'opt1' not equal
- capabilities = {'enabled': True, 'opt1': 'no-match'}
- service = {'enabled': True}
- host = fakes.FakeHostState('host1',
- {'free_ram_mb': 20,
- 'free_disk_mb': 400,
- 'capabilities': capabilities,
- 'service': service})
- self.assertFalse(filt_cls.host_passes(host, filter_properties))
-
- def test_json_filter_basic_operators(self):
- filt_cls = self.class_map['JsonFilter']()
- host = fakes.FakeHostState('host1',
- {'capabilities': {'enabled': True}})
- # (operator, arguments, expected_result)
- ops_to_test = [
- ['=', [1, 1], True],
- ['=', [1, 2], False],
- ['<', [1, 2], True],
- ['<', [1, 1], False],
- ['<', [2, 1], False],
- ['>', [2, 1], True],
- ['>', [2, 2], False],
- ['>', [2, 3], False],
- ['<=', [1, 2], True],
- ['<=', [1, 1], True],
- ['<=', [2, 1], False],
- ['>=', [2, 1], True],
- ['>=', [2, 2], True],
- ['>=', [2, 3], False],
- ['in', [1, 1], True],
- ['in', [1, 1, 2, 3], True],
- ['in', [4, 1, 2, 3], False],
- ['not', [True], False],
- ['not', [False], True],
- ['or', [True, False], True],
- ['or', [False, False], False],
- ['and', [True, True], True],
- ['and', [False, False], False],
- ['and', [True, False], False],
- # Nested ((True or False) and (2 > 1)) == Passes
- ['and', [['or', True, False], ['>', 2, 1]], True]]
-
- for (op, args, expected) in ops_to_test:
- raw = [op] + args
- filter_properties = {
- 'scheduler_hints': {
- 'query': jsonutils.dumps(raw),
- },
- }
- self.assertEqual(expected,
- filt_cls.host_passes(host, filter_properties))
-
- # This results in [False, True, False, True] and if any are True
- # then it passes...
- raw = ['not', True, False, True, False]
- filter_properties = {
- 'scheduler_hints': {
- 'query': jsonutils.dumps(raw),
- },
- }
- self.assertTrue(filt_cls.host_passes(host, filter_properties))
-
- # This results in [False, False, False] and if any are True
- # then it passes...which this doesn't
- raw = ['not', True, True, True]
- filter_properties = {
- 'scheduler_hints': {
- 'query': jsonutils.dumps(raw),
- },
- }
- self.assertFalse(filt_cls.host_passes(host, filter_properties))
-
- def test_json_filter_unknown_operator_raises(self):
- filt_cls = self.class_map['JsonFilter']()
- raw = ['!=', 1, 2]
- filter_properties = {
- 'scheduler_hints': {
- 'query': jsonutils.dumps(raw),
- },
- }
- host = fakes.FakeHostState('host1',
- {'capabilities': {'enabled': True}})
- self.assertRaises(KeyError,
- filt_cls.host_passes, host, filter_properties)
-
- def test_json_filter_empty_filters_pass(self):
- filt_cls = self.class_map['JsonFilter']()
- host = fakes.FakeHostState('host1',
- {'capabilities': {'enabled': True}})
-
- raw = []
- filter_properties = {
- 'scheduler_hints': {
- 'query': jsonutils.dumps(raw),
- },
- }
- self.assertTrue(filt_cls.host_passes(host, filter_properties))
- raw = {}
- filter_properties = {
- 'scheduler_hints': {
- 'query': jsonutils.dumps(raw),
- },
- }
- self.assertTrue(filt_cls.host_passes(host, filter_properties))
-
- def test_json_filter_invalid_num_arguments_fails(self):
- filt_cls = self.class_map['JsonFilter']()
- host = fakes.FakeHostState('host1',
- {'capabilities': {'enabled': True}})
-
- raw = ['>', ['and', ['or', ['not', ['<', ['>=', ['<=', ['in', ]]]]]]]]
- filter_properties = {
- 'scheduler_hints': {
- 'query': jsonutils.dumps(raw),
- },
- }
- self.assertFalse(filt_cls.host_passes(host, filter_properties))
-
- raw = ['>', 1]
- filter_properties = {
- 'scheduler_hints': {
- 'query': jsonutils.dumps(raw),
- },
- }
- self.assertFalse(filt_cls.host_passes(host, filter_properties))
-
- def test_json_filter_unknown_variable_ignored(self):
- filt_cls = self.class_map['JsonFilter']()
- host = fakes.FakeHostState('host1',
- {'capabilities': {'enabled': True}})
-
- raw = ['=', '$........', 1, 1]
- filter_properties = {
- 'scheduler_hints': {
- 'query': jsonutils.dumps(raw),
- },
- }
- self.assertTrue(filt_cls.host_passes(host, filter_properties))
-
- raw = ['=', '$foo', 2, 2]
- filter_properties = {
- 'scheduler_hints': {
- 'query': jsonutils.dumps(raw),
- },
- }
- self.assertTrue(filt_cls.host_passes(host, filter_properties))
-
- @staticmethod
- def _make_zone_request(zone, is_admin=False):
- ctxt = context.RequestContext('fake', 'fake', is_admin=is_admin)
- return {
- 'context': ctxt,
- 'request_spec': {
- 'resource_properties': {
- 'availability_zone': zone
- }
- }
- }
-
- def test_availability_zone_filter_same(self):
- filt_cls = self.class_map['AvailabilityZoneFilter']()
- service = {'availability_zone': 'nova'}
- request = self._make_zone_request('nova')
- host = fakes.FakeHostState('host1',
- {'service': service})
- self.assertTrue(filt_cls.host_passes(host, request))
-
- def test_availability_zone_filter_different(self):
- filt_cls = self.class_map['AvailabilityZoneFilter']()
- service = {'availability_zone': 'nova'}
- request = self._make_zone_request('bad')
- host = fakes.FakeHostState('host1',
- {'service': service})
- self.assertFalse(filt_cls.host_passes(host, request))
-
- def test_availability_zone_filter_empty(self):
- filt_cls = self.class_map['AvailabilityZoneFilter']()
- service = {'availability_zone': 'nova'}
- request = {}
- host = fakes.FakeHostState('host1',
- {'service': service})
- self.assertTrue(filt_cls.host_passes(host, request))
-
- def test_ignore_attempted_hosts_filter_disabled(self):
- # Test case where re-scheduling is disabled.
- filt_cls = self.class_map['IgnoreAttemptedHostsFilter']()
- host = fakes.FakeHostState('host1', {})
- filter_properties = {}
- self.assertTrue(filt_cls.host_passes(host, filter_properties))
-
- def test_ignore_attempted_hosts_filter_pass(self):
- # Node not previously tried.
- filt_cls = self.class_map['IgnoreAttemptedHostsFilter']()
- host = fakes.FakeHostState('host1', {})
- attempted = dict(num_attempts=2, hosts=['host2'])
- filter_properties = dict(retry=attempted)
- self.assertTrue(filt_cls.host_passes(host, filter_properties))
-
- def test_ignore_attempted_hosts_filter_fail(self):
- # Node was already tried.
- filt_cls = self.class_map['IgnoreAttemptedHostsFilter']()
- host = fakes.FakeHostState('host1', {})
- attempted = dict(num_attempts=2, hosts=['host1'])
- filter_properties = dict(retry=attempted)
- self.assertFalse(filt_cls.host_passes(host, filter_properties))