summaryrefslogtreecommitdiffstats
path: root/nova
diff options
context:
space:
mode:
authorChris Behrens <cbehrens@codestud.com>2012-02-24 00:01:57 +0000
committerChris Behrens <cbehrens@codestud.com>2012-02-27 23:41:06 +0000
commit3f42e11ca0dfedf07f50f4d5e1805914230e5edc (patch)
tree91a3cd6b9754a0dbe9b66a7b27551f525d2529be /nova
parentf01b9b8dd25d763e652259a0f99264d93661b29f (diff)
downloadnova-3f42e11ca0dfedf07f50f4d5e1805914230e5edc.tar.gz
nova-3f42e11ca0dfedf07f50f4d5e1805914230e5edc.tar.xz
nova-3f42e11ca0dfedf07f50f4d5e1805914230e5edc.zip
Make scheduler filters more pluggable
Filters are supposed to be pluggable, but they are not, since you have to modify __init__.py. This adds a --scheduler_availabile_filters setting which replaces the hardcoding in __init__.py. This setting is a MultiStr (a list, which you can specify more than once) containing the full paths to filter classes to make available to the scheduler. Using a value of 'nova.scheduler.filters.standard_filters' maps to all standard filters included in nova under nova.scheduler.filters. This is the default setting and matches what was in __init__.py before. Also renamed --default_host_filters to --scheduler_default_filters to make the flag a bit more clear. Change-Id: I10eb54e9982b6d42316adfb2cc2600b44a9c3bdf
Diffstat (limited to 'nova')
-rw-r--r--nova/scheduler/filters/__init__.py96
-rw-r--r--nova/scheduler/filters/abstract_filter.py25
-rw-r--r--nova/scheduler/filters/affinity_filter.py4
-rw-r--r--nova/scheduler/filters/all_hosts_filter.py4
-rw-r--r--nova/scheduler/filters/availability_zone_filter.py4
-rw-r--r--nova/scheduler/filters/compute_filter.py4
-rw-r--r--nova/scheduler/filters/core_filter.py4
-rw-r--r--nova/scheduler/filters/isolated_hosts_filter.py4
-rw-r--r--nova/scheduler/filters/json_filter.py4
-rw-r--r--nova/scheduler/filters/ram_filter.py4
-rw-r--r--nova/scheduler/host_manager.py32
-rw-r--r--nova/tests/scheduler/test_host_filters.py112
-rw-r--r--nova/tests/scheduler/test_host_manager.py5
13 files changed, 173 insertions, 129 deletions
diff --git a/nova/scheduler/filters/__init__.py b/nova/scheduler/filters/__init__.py
index a97897935..406a49119 100644
--- a/nova/scheduler/filters/__init__.py
+++ b/nova/scheduler/filters/__init__.py
@@ -14,30 +14,74 @@
# under the License.
"""
-There are three filters included: AllHosts, InstanceType & JSON.
-
-AllHosts just returns the full, unfiltered list of hosts.
-InstanceType is a hard coded matching mechanism based on flavor criteria.
-JSON is an ad-hoc filter grammar.
-
-Why JSON? The requests for instances may come in through the
-REST interface from a user or a parent Zone.
-Currently InstanceTypes are used for specifing the type of instance desired.
-Specific Nova users have noted a need for a more expressive way of specifying
-instance requirements. Since we don't want to get into building full DSL,
-this filter is a simple form as an example of how this could be done.
-In reality, most consumers will use the more rigid filters such as the
-InstanceType filter.
+Scheduler host filters
"""
-from nova.scheduler.filters.abstract_filter import AbstractHostFilter
-from nova.scheduler.filters.affinity_filter import DifferentHostFilter
-from nova.scheduler.filters.affinity_filter import SameHostFilter
-from nova.scheduler.filters.affinity_filter import SimpleCIDRAffinityFilter
-from nova.scheduler.filters.all_hosts_filter import AllHostsFilter
-from nova.scheduler.filters.availability_zone_filter \
- import AvailabilityZoneFilter
-from nova.scheduler.filters.isolated_hosts_filter import IsolatedHostsFilter
-from nova.scheduler.filters.compute_filter import ComputeFilter
-from nova.scheduler.filters.core_filter import CoreFilter
-from nova.scheduler.filters.json_filter import JsonFilter
-from nova.scheduler.filters.ram_filter import RamFilter
+
+import os
+import types
+
+from nova import exception
+from nova import utils
+
+
+class BaseHostFilter(object):
+ """Base class for host filters."""
+
+ def host_passes(self, host_state, filter_properties):
+ raise NotImplemented()
+
+ def _full_name(self):
+ """module.classname of the filter."""
+ return "%s.%s" % (self.__module__, self.__class__.__name__)
+
+
+def _is_filter_class(cls):
+ """Return whether a class is a valid Host Filter class."""
+ return type(cls) is types.TypeType and issubclass(cls, BaseHostFilter)
+
+
+def _get_filter_classes_from_module(module_name):
+ """Get all filter classes from a module."""
+ classes = []
+ module = utils.import_object(module_name)
+ for obj_name in dir(module):
+ itm = getattr(module, obj_name)
+ if _is_filter_class(itm):
+ classes.append(itm)
+ return classes
+
+
+def standard_filters():
+ """Return a list of filter classes found in this directory."""
+ classes = []
+ filters_dir = __path__[0]
+ for dirpath, dirnames, filenames in os.walk(filters_dir):
+ relpath = os.path.relpath(dirpath, filters_dir)
+ if relpath == '.':
+ relpkg = ''
+ else:
+ relpkg = '.%s' % '.'.join(relpath.split(os.sep))
+ for fname in filenames:
+ root, ext = os.path.splitext(fname)
+ if ext != '.py' or root == '__init__':
+ continue
+ module_name = "%s%s.%s" % (__package__, relpkg, root)
+ mod_classes = _get_filter_classes_from_module(module_name)
+ classes.extend(mod_classes)
+ return classes
+
+
+def get_filter_classes(filter_class_names):
+ """Get filter classes from class names."""
+ classes = []
+ for cls_name in filter_class_names:
+ obj = utils.import_class(cls_name)
+ if _is_filter_class(obj):
+ classes.append(obj)
+ elif type(obj) is types.FunctionType:
+ # Get list of classes from a function
+ classes.extend(obj())
+ else:
+ raise exception.ClassNotFound(class_name=cls_name,
+ exception='Not a valid scheduler filter')
+ return classes
diff --git a/nova/scheduler/filters/abstract_filter.py b/nova/scheduler/filters/abstract_filter.py
deleted file mode 100644
index 235eaa74b..000000000
--- a/nova/scheduler/filters/abstract_filter.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright (c) 2011 Openstack, LLC.
-# 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.
-
-
-class AbstractHostFilter(object):
- """Base class for host filters."""
-
- def host_passes(self, host_state, filter_properties):
- return True
-
- def _full_name(self):
- """module.classname of the filter."""
- return "%s.%s" % (self.__module__, self.__class__.__name__)
diff --git a/nova/scheduler/filters/affinity_filter.py b/nova/scheduler/filters/affinity_filter.py
index f6902e127..e6e7a116a 100644
--- a/nova/scheduler/filters/affinity_filter.py
+++ b/nova/scheduler/filters/affinity_filter.py
@@ -15,14 +15,14 @@
# limitations under the License.
-import abstract_filter
import netaddr
from nova.compute import api as compute
from nova import flags
+from nova.scheduler import filters
-class AffinityFilter(abstract_filter.AbstractHostFilter):
+class AffinityFilter(filters.BaseHostFilter):
def __init__(self):
self.compute_api = compute.API()
diff --git a/nova/scheduler/filters/all_hosts_filter.py b/nova/scheduler/filters/all_hosts_filter.py
index 1099e425d..d0bce5e56 100644
--- a/nova/scheduler/filters/all_hosts_filter.py
+++ b/nova/scheduler/filters/all_hosts_filter.py
@@ -14,10 +14,10 @@
# under the License.
-import abstract_filter
+from nova.scheduler import filters
-class AllHostsFilter(abstract_filter.AbstractHostFilter):
+class AllHostsFilter(filters.BaseHostFilter):
"""NOP host filter. Returns all hosts."""
def host_passes(self, host_state, filter_properties):
diff --git a/nova/scheduler/filters/availability_zone_filter.py b/nova/scheduler/filters/availability_zone_filter.py
index bd029d5db..4b6811a57 100644
--- a/nova/scheduler/filters/availability_zone_filter.py
+++ b/nova/scheduler/filters/availability_zone_filter.py
@@ -14,10 +14,10 @@
# under the License.
-import abstract_filter
+from nova.scheduler import filters
-class AvailabilityZoneFilter(abstract_filter.AbstractHostFilter):
+class AvailabilityZoneFilter(filters.BaseHostFilter):
"""Filters Hosts by availabilty zone."""
def host_passes(self, host_state, filter_properties):
diff --git a/nova/scheduler/filters/compute_filter.py b/nova/scheduler/filters/compute_filter.py
index ce2c3fb15..7e99344df 100644
--- a/nova/scheduler/filters/compute_filter.py
+++ b/nova/scheduler/filters/compute_filter.py
@@ -14,14 +14,14 @@
# under the License.
from nova import log as logging
-from nova.scheduler.filters import abstract_filter
+from nova.scheduler import filters
from nova import utils
LOG = logging.getLogger(__name__)
-class ComputeFilter(abstract_filter.AbstractHostFilter):
+class ComputeFilter(filters.BaseHostFilter):
"""HostFilter hard-coded to work with InstanceType records."""
def _satisfies_extra_specs(self, capabilities, instance_type):
diff --git a/nova/scheduler/filters/core_filter.py b/nova/scheduler/filters/core_filter.py
index f7333a661..fc8bab838 100644
--- a/nova/scheduler/filters/core_filter.py
+++ b/nova/scheduler/filters/core_filter.py
@@ -18,7 +18,7 @@
from nova import flags
from nova import log as logging
from nova.openstack.common import cfg
-from nova.scheduler.filters import abstract_filter
+from nova.scheduler import filters
LOG = logging.getLogger(__name__)
@@ -31,7 +31,7 @@ FLAGS = flags.FLAGS
FLAGS.register_opt(cpu_allocation_ratio_opt)
-class CoreFilter(abstract_filter.AbstractHostFilter):
+class CoreFilter(filters.BaseHostFilter):
"""CoreFilter filters based on CPU core utilization."""
def host_passes(self, host_state, filter_properties):
diff --git a/nova/scheduler/filters/isolated_hosts_filter.py b/nova/scheduler/filters/isolated_hosts_filter.py
index 82478ab7a..a857aee30 100644
--- a/nova/scheduler/filters/isolated_hosts_filter.py
+++ b/nova/scheduler/filters/isolated_hosts_filter.py
@@ -14,14 +14,14 @@
# under the License.
-import abstract_filter
from nova import flags
+from nova.scheduler import filters
FLAGS = flags.FLAGS
-class IsolatedHostsFilter(abstract_filter.AbstractHostFilter):
+class IsolatedHostsFilter(filters.BaseHostFilter):
"""Returns host."""
def host_passes(self, host_state, filter_properties):
diff --git a/nova/scheduler/filters/json_filter.py b/nova/scheduler/filters/json_filter.py
index af17322b2..35fdb6360 100644
--- a/nova/scheduler/filters/json_filter.py
+++ b/nova/scheduler/filters/json_filter.py
@@ -17,10 +17,10 @@
import json
import operator
-from nova.scheduler.filters import abstract_filter
+from nova.scheduler import filters
-class JsonFilter(abstract_filter.AbstractHostFilter):
+class JsonFilter(filters.BaseHostFilter):
"""Host Filter to allow simple JSON-based grammar for
selecting hosts.
"""
diff --git a/nova/scheduler/filters/ram_filter.py b/nova/scheduler/filters/ram_filter.py
index a2b5d2757..cda3fdfbd 100644
--- a/nova/scheduler/filters/ram_filter.py
+++ b/nova/scheduler/filters/ram_filter.py
@@ -17,7 +17,7 @@
from nova import flags
from nova import log as logging
from nova.openstack.common import cfg
-from nova.scheduler.filters import abstract_filter
+from nova.scheduler import filters
LOG = logging.getLogger(__name__)
@@ -29,7 +29,7 @@ FLAGS = flags.FLAGS
FLAGS.register_opt(ram_allocation_ratio_opt)
-class RamFilter(abstract_filter.AbstractHostFilter):
+class RamFilter(filters.BaseHostFilter):
"""Ram Filter with over subscription flag"""
def host_passes(self, host_state, filter_properties):
diff --git a/nova/scheduler/host_manager.py b/nova/scheduler/host_manager.py
index 090773aaf..0adda44e1 100644
--- a/nova/scheduler/host_manager.py
+++ b/nova/scheduler/host_manager.py
@@ -18,7 +18,6 @@ Manage hosts in the current zone.
"""
import datetime
-import types
import UserDict
from nova import db
@@ -26,6 +25,7 @@ from nova import exception
from nova import flags
from nova import log as logging
from nova.openstack.common import cfg
+from nova.scheduler import filters
from nova import utils
@@ -36,14 +36,20 @@ host_manager_opts = [
cfg.IntOpt('reserved_host_memory_mb',
default=512,
help='Amount of memory in MB to reserve for host/dom0'),
- cfg.ListOpt('default_host_filters',
+ cfg.MultiStrOpt('scheduler_available_filters',
+ default=['nova.scheduler.filters.standard_filters'],
+ help='Filter classes available to the scheduler which may '
+ 'be specified more than once. An entry of '
+ '"nova.scheduler.filters.standard_filters" '
+ 'maps to all filters included with nova.'),
+ cfg.ListOpt('scheduler_default_filters',
default=[
'AvailabilityZoneFilter',
'RamFilter',
'ComputeFilter'
],
- help='Which filters to use for filtering hosts when not '
- 'specified in the request.'),
+ help='Which filter class names to use for filtering hosts '
+ 'when not specified in the request.'),
]
FLAGS = flags.FLAGS
@@ -157,20 +163,8 @@ class HostManager(object):
def __init__(self):
self.service_states = {} # { <host> : { <service> : { cap k : v }}}
- self.filter_classes = self._get_filter_classes()
-
- def _get_filter_classes(self):
- """Get the list of possible filter classes"""
- # Imported here to avoid circular imports
- from nova.scheduler import filters
-
- def get_itm(nm):
- return getattr(filters, nm)
-
- return [get_itm(itm) for itm in dir(filters)
- if (type(get_itm(itm)) is types.TypeType)
- and issubclass(get_itm(itm), filters.AbstractHostFilter)
- and get_itm(itm) is not filters.AbstractHostFilter]
+ self.filter_classes = filters.get_filter_classes(
+ FLAGS.scheduler_available_filters)
def _choose_host_filters(self, filters):
"""Since the caller may specify which filters to use we need
@@ -179,7 +173,7 @@ class HostManager(object):
of acceptable filters.
"""
if filters is None:
- filters = FLAGS.default_host_filters
+ filters = FLAGS.scheduler_default_filters
if not isinstance(filters, (list, tuple)):
filters = [filters]
good_filters = []
diff --git a/nova/tests/scheduler/test_host_filters.py b/nova/tests/scheduler/test_host_filters.py
index d03d224d1..94f8e0be8 100644
--- a/nova/tests/scheduler/test_host_filters.py
+++ b/nova/tests/scheduler/test_host_filters.py
@@ -18,6 +18,7 @@ Tests For Scheduler Host Filters.
import json
from nova import context
+from nova import exception
from nova import flags
from nova.scheduler import filters
from nova import test
@@ -25,6 +26,15 @@ from nova.tests.scheduler import fakes
from nova import utils
+class TestFilter(filters.BaseHostFilter):
+ pass
+
+
+class TestBogusFilter(object):
+ """Class that doesn't inherit from BaseHostFilter"""
+ pass
+
+
class HostFiltersTestCase(test.TestCase):
"""Test case for host filters."""
@@ -34,9 +44,35 @@ class HostFiltersTestCase(test.TestCase):
self.json_query = json.dumps(
['and', ['>=', '$free_ram_mb', 1024],
['>=', '$free_disk_mb', 200 * 1024]])
+ # This has a side effect of testing 'get_filter_classes'
+ # when specifing a method (in this case, our standard filters)
+ classes = filters.get_filter_classes(
+ ['nova.scheduler.filters.standard_filters'])
+ self.class_map = {}
+ for cls in classes:
+ self.class_map[cls.__name__] = cls
+
+ def test_get_filter_classes(self):
+ classes = filters.get_filter_classes(
+ ['nova.tests.scheduler.test_host_filters.TestFilter'])
+ self.assertEqual(len(classes), 1)
+ self.assertEqual(classes[0].__name__, 'TestFilter')
+ # Test a specific class along with our standard filters
+ classes = filters.get_filter_classes(
+ ['nova.tests.scheduler.test_host_filters.TestFilter',
+ 'nova.scheduler.filters.standard_filters'])
+ self.assertEqual(len(classes), 1 + len(self.class_map))
+
+ def test_get_filter_classes_raises_on_invalid_classes(self):
+ self.assertRaises(exception.ClassNotFound,
+ filters.get_filter_classes,
+ ['nova.tests.scheduler.test_host_filters.NoExist'])
+ self.assertRaises(exception.ClassNotFound,
+ filters.get_filter_classes,
+ ['nova.tests.scheduler.test_host_filters.TestBogusFilter'])
def test_all_host_filter(self):
- filt_cls = filters.AllHostsFilter()
+ filt_cls = self.class_map['AllHostsFilter']()
host = fakes.FakeHostState('host1', 'compute', {})
self.assertTrue(filt_cls.host_passes(host, {}))
@@ -46,7 +82,7 @@ class HostFiltersTestCase(test.TestCase):
self.stubs.Set(utils, 'service_is_up', fake_service_is_up)
def test_affinity_different_filter_passes(self):
- filt_cls = filters.DifferentHostFilter()
+ filt_cls = self.class_map['DifferentHostFilter']()
host = fakes.FakeHostState('host1', 'compute', {})
instance = fakes.FakeInstance(context=self.context,
params={'host': 'host2'})
@@ -59,7 +95,7 @@ class HostFiltersTestCase(test.TestCase):
self.assertTrue(filt_cls.host_passes(host, filter_properties))
def test_affinity_different_filter_fails(self):
- filt_cls = filters.DifferentHostFilter()
+ filt_cls = self.class_map['DifferentHostFilter']()
host = fakes.FakeHostState('host1', 'compute', {})
instance = fakes.FakeInstance(context=self.context,
params={'host': 'host1'})
@@ -72,7 +108,7 @@ class HostFiltersTestCase(test.TestCase):
self.assertFalse(filt_cls.host_passes(host, filter_properties))
def test_affinity_same_filter_passes(self):
- filt_cls = filters.SameHostFilter()
+ filt_cls = self.class_map['SameHostFilter']()
host = fakes.FakeHostState('host1', 'compute', {})
instance = fakes.FakeInstance(context=self.context,
params={'host': 'host1'})
@@ -85,7 +121,7 @@ class HostFiltersTestCase(test.TestCase):
self.assertTrue(filt_cls.host_passes(host, filter_properties))
def test_affinity_same_filter_fails(self):
- filt_cls = filters.SameHostFilter()
+ filt_cls = self.class_map['SameHostFilter']()
host = fakes.FakeHostState('host1', 'compute', {})
instance = fakes.FakeInstance(context=self.context,
params={'host': 'host2'})
@@ -98,7 +134,7 @@ class HostFiltersTestCase(test.TestCase):
self.assertFalse(filt_cls.host_passes(host, filter_properties))
def test_affinity_simple_cidr_filter_passes(self):
- filt_cls = filters.SimpleCIDRAffinityFilter()
+ filt_cls = self.class_map['SimpleCIDRAffinityFilter']()
host = fakes.FakeHostState('host1', 'compute', {})
affinity_ip = flags.FLAGS.my_ip.split('.')[0:3]
@@ -113,7 +149,7 @@ class HostFiltersTestCase(test.TestCase):
self.assertTrue(filt_cls.host_passes(host, filter_properties))
def test_affinity_simple_cidr_filter_fails(self):
- filt_cls = filters.SimpleCIDRAffinityFilter()
+ filt_cls = self.class_map['SimpleCIDRAffinityFilter']()
host = fakes.FakeHostState('host1', 'compute', {})
affinity_ip = flags.FLAGS.my_ip.split('.')
@@ -129,7 +165,7 @@ class HostFiltersTestCase(test.TestCase):
def test_compute_filter_passes(self):
self._stub_service_is_up(True)
- filt_cls = filters.ComputeFilter()
+ filt_cls = self.class_map['ComputeFilter']()
filter_properties = {'instance_type': {'memory_mb': 1024}}
capabilities = {'enabled': True}
service = {'disabled': False}
@@ -140,7 +176,7 @@ class HostFiltersTestCase(test.TestCase):
def test_ram_filter_fails_on_memory(self):
self._stub_service_is_up(True)
- filt_cls = filters.RamFilter()
+ filt_cls = self.class_map['RamFilter']()
filter_properties = {'instance_type': {'memory_mb': 1024}}
capabilities = {'enabled': True}
service = {'disabled': False}
@@ -151,7 +187,7 @@ class HostFiltersTestCase(test.TestCase):
def test_compute_filter_fails_on_service_disabled(self):
self._stub_service_is_up(True)
- filt_cls = filters.ComputeFilter()
+ filt_cls = self.class_map['ComputeFilter']()
filter_properties = {'instance_type': {'memory_mb': 1024}}
capabilities = {'enabled': True}
service = {'disabled': True}
@@ -162,7 +198,7 @@ class HostFiltersTestCase(test.TestCase):
def test_compute_filter_fails_on_service_down(self):
self._stub_service_is_up(False)
- filt_cls = filters.ComputeFilter()
+ filt_cls = self.class_map['ComputeFilter']()
filter_properties = {'instance_type': {'memory_mb': 1024}}
capabilities = {'enabled': True}
service = {'disabled': False}
@@ -173,7 +209,7 @@ class HostFiltersTestCase(test.TestCase):
def test_compute_filter_passes_on_volume(self):
self._stub_service_is_up(True)
- filt_cls = filters.ComputeFilter()
+ filt_cls = self.class_map['ComputeFilter']()
filter_properties = {'instance_type': {'memory_mb': 1024}}
capabilities = {'enabled': False}
service = {'disabled': False}
@@ -184,7 +220,7 @@ class HostFiltersTestCase(test.TestCase):
def test_compute_filter_passes_on_no_instance_type(self):
self._stub_service_is_up(True)
- filt_cls = filters.ComputeFilter()
+ filt_cls = self.class_map['ComputeFilter']()
filter_properties = {}
capabilities = {'enabled': False}
service = {'disabled': False}
@@ -195,7 +231,7 @@ class HostFiltersTestCase(test.TestCase):
def test_compute_filter_passes_extra_specs(self):
self._stub_service_is_up(True)
- filt_cls = filters.ComputeFilter()
+ filt_cls = self.class_map['ComputeFilter']()
extra_specs = {'opt1': 1, 'opt2': 2}
capabilities = {'enabled': True, 'opt1': 1, 'opt2': 2}
service = {'disabled': False}
@@ -208,7 +244,7 @@ class HostFiltersTestCase(test.TestCase):
def test_compute_filter_fails_extra_specs(self):
self._stub_service_is_up(True)
- filt_cls = filters.ComputeFilter()
+ filt_cls = self.class_map['ComputeFilter']()
extra_specs = {'opt1': 1, 'opt2': 3}
capabilities = {'enabled': True, 'opt1': 1, 'opt2': 2}
service = {'disabled': False}
@@ -222,7 +258,7 @@ class HostFiltersTestCase(test.TestCase):
def test_isolated_hosts_fails_isolated_on_non_isolated(self):
self.flags(isolated_images=['isolated'], isolated_hosts=['isolated'])
- filt_cls = filters.IsolatedHostsFilter()
+ filt_cls = self.class_map['IsolatedHostsFilter']()
filter_properties = {
'request_spec': {
'instance_properties': {'image_ref': 'isolated'}
@@ -233,7 +269,7 @@ class HostFiltersTestCase(test.TestCase):
def test_isolated_hosts_fails_non_isolated_on_isolated(self):
self.flags(isolated_images=['isolated'], isolated_hosts=['isolated'])
- filt_cls = filters.IsolatedHostsFilter()
+ filt_cls = self.class_map['IsolatedHostsFilter']()
filter_properties = {
'request_spec': {
'instance_properties': {'image_ref': 'non-isolated'}
@@ -244,7 +280,7 @@ class HostFiltersTestCase(test.TestCase):
def test_isolated_hosts_passes_isolated_on_isolated(self):
self.flags(isolated_images=['isolated'], isolated_hosts=['isolated'])
- filt_cls = filters.IsolatedHostsFilter()
+ filt_cls = self.class_map['IsolatedHostsFilter']()
filter_properties = {
'request_spec': {
'instance_properties': {'image_ref': 'isolated'}
@@ -255,7 +291,7 @@ class HostFiltersTestCase(test.TestCase):
def test_isolated_hosts_passes_non_isolated_on_non_isolated(self):
self.flags(isolated_images=['isolated'], isolated_hosts=['isolated'])
- filt_cls = filters.IsolatedHostsFilter()
+ filt_cls = self.class_map['IsolatedHostsFilter']()
filter_properties = {
'request_spec': {
'instance_properties': {'image_ref': 'non-isolated'}
@@ -265,7 +301,7 @@ class HostFiltersTestCase(test.TestCase):
self.assertTrue(filt_cls.host_passes(host, filter_properties))
def test_json_filter_passes(self):
- filt_cls = filters.JsonFilter()
+ filt_cls = self.class_map['JsonFilter']()
filter_properties = {'instance_type': {'memory_mb': 1024,
'root_gb': 200,
'ephemeral_gb': 0},
@@ -278,7 +314,7 @@ class HostFiltersTestCase(test.TestCase):
self.assertTrue(filt_cls.host_passes(host, filter_properties))
def test_json_filter_passes_with_no_query(self):
- filt_cls = filters.JsonFilter()
+ filt_cls = self.class_map['JsonFilter']()
filter_properties = {'instance_type': {'memory_mb': 1024,
'root_gb': 200,
'ephemeral_gb': 0}}
@@ -290,7 +326,7 @@ class HostFiltersTestCase(test.TestCase):
self.assertTrue(filt_cls.host_passes(host, filter_properties))
def test_json_filter_fails_on_memory(self):
- filt_cls = filters.JsonFilter()
+ filt_cls = self.class_map['JsonFilter']()
filter_properties = {'instance_type': {'memory_mb': 1024,
'root_gb': 200,
'ephemeral_gb': 0},
@@ -303,7 +339,7 @@ class HostFiltersTestCase(test.TestCase):
self.assertFalse(filt_cls.host_passes(host, filter_properties))
def test_json_filter_fails_on_disk(self):
- filt_cls = filters.JsonFilter()
+ filt_cls = self.class_map['JsonFilter']()
filter_properties = {'instance_type': {'memory_mb': 1024,
'root_gb': 200,
'ephemeral_gb': 0},
@@ -316,7 +352,7 @@ class HostFiltersTestCase(test.TestCase):
self.assertFalse(filt_cls.host_passes(host, filter_properties))
def test_json_filter_fails_on_caps_disabled(self):
- filt_cls = filters.JsonFilter()
+ filt_cls = self.class_map['JsonFilter']()
json_query = json.dumps(
['and', ['>=', '$free_ram_mb', 1024],
['>=', '$free_disk_mb', 200 * 1024],
@@ -333,7 +369,7 @@ class HostFiltersTestCase(test.TestCase):
self.assertFalse(filt_cls.host_passes(host, filter_properties))
def test_json_filter_fails_on_service_disabled(self):
- filt_cls = filters.JsonFilter()
+ filt_cls = self.class_map['JsonFilter']()
json_query = json.dumps(
['and', ['>=', '$free_ram_mb', 1024],
['>=', '$free_disk_mb', 200 * 1024],
@@ -351,7 +387,7 @@ class HostFiltersTestCase(test.TestCase):
def test_json_filter_happy_day(self):
"""Test json filter more thoroughly"""
- filt_cls = filters.JsonFilter()
+ filt_cls = self.class_map['JsonFilter']()
raw = ['and',
'$capabilities.enabled',
['=', '$capabilities.opt1', 'match'],
@@ -425,7 +461,7 @@ class HostFiltersTestCase(test.TestCase):
self.assertFalse(filt_cls.host_passes(host, filter_properties))
def test_json_filter_basic_operators(self):
- filt_cls = filters.JsonFilter()
+ filt_cls = self.class_map['JsonFilter']()
host = fakes.FakeHostState('host1', 'compute',
{'capabilities': {'enabled': True}})
# (operator, arguments, expected_result)
@@ -476,18 +512,16 @@ class HostFiltersTestCase(test.TestCase):
self.assertFalse(filt_cls.host_passes(host, filter_properties))
def test_json_filter_unknown_operator_raises(self):
- filt_cls = filters.JsonFilter()
+ filt_cls = self.class_map['JsonFilter']()
raw = ['!=', 1, 2]
filter_properties = {'query': json.dumps(raw)}
- capabilities = {'enabled': True, 'opt1': 'no-match'}
host = fakes.FakeHostState('host1', 'compute',
{'capabilities': {'enabled': True}})
self.assertRaises(KeyError,
filt_cls.host_passes, host, filter_properties)
def test_json_filter_empty_filters_pass(self):
- filt_cls = filters.JsonFilter()
- capabilities = {'enabled': True, 'opt1': 'no-match'}
+ filt_cls = self.class_map['JsonFilter']()
host = fakes.FakeHostState('host1', 'compute',
{'capabilities': {'enabled': True}})
@@ -499,8 +533,7 @@ class HostFiltersTestCase(test.TestCase):
self.assertTrue(filt_cls.host_passes(host, filter_properties))
def test_json_filter_invalid_num_arguments_fails(self):
- filt_cls = filters.JsonFilter()
- capabilities = {'enabled': True, 'opt1': 'no-match'}
+ filt_cls = self.class_map['JsonFilter']()
host = fakes.FakeHostState('host1', 'compute',
{'capabilities': {'enabled': True}})
@@ -513,8 +546,7 @@ class HostFiltersTestCase(test.TestCase):
self.assertFalse(filt_cls.host_passes(host, filter_properties))
def test_json_filter_unknown_variable_ignored(self):
- filt_cls = filters.JsonFilter()
- capabilities = {'enabled': True, 'opt1': 'no-match'}
+ filt_cls = self.class_map['JsonFilter']()
host = fakes.FakeHostState('host1', 'compute',
{'capabilities': {'enabled': True}})
@@ -527,7 +559,7 @@ class HostFiltersTestCase(test.TestCase):
self.assertTrue(filt_cls.host_passes(host, filter_properties))
def test_core_filter_passes(self):
- filt_cls = filters.CoreFilter()
+ filt_cls = self.class_map['CoreFilter']()
filter_properties = {'instance_type': {'vcpus': 1}}
self.flags(cpu_allocation_ratio=2)
host = fakes.FakeHostState('host1', 'compute',
@@ -535,13 +567,13 @@ class HostFiltersTestCase(test.TestCase):
self.assertTrue(filt_cls.host_passes(host, filter_properties))
def test_core_filter_fails_safe(self):
- filt_cls = filters.CoreFilter()
+ filt_cls = self.class_map['CoreFilter']()
filter_properties = {'instance_type': {'vcpus': 1}}
host = fakes.FakeHostState('host1', 'compute', {})
self.assertTrue(filt_cls.host_passes(host, filter_properties))
def test_core_filter_fails(self):
- filt_cls = filters.CoreFilter()
+ filt_cls = self.class_map['CoreFilter']()
filter_properties = {'instance_type': {'vcpus': 1}}
self.flags(cpu_allocation_ratio=2)
host = fakes.FakeHostState('host1', 'compute',
@@ -561,14 +593,14 @@ class HostFiltersTestCase(test.TestCase):
}
def test_availability_zone_filter_same(self):
- filt_cls = filters.AvailabilityZoneFilter()
+ filt_cls = self.class_map['AvailabilityZoneFilter']()
service = {'availability_zone': 'nova'}
request = self._make_zone_request('nova')
host = fakes.FakeHostState('host1', 'compute', {'service': service})
self.assertTrue(filt_cls.host_passes(host, request))
def test_availability_zone_filter_different(self):
- filt_cls = filters.AvailabilityZoneFilter()
+ filt_cls = self.class_map['AvailabilityZoneFilter']()
service = {'availability_zone': 'nova'}
request = self._make_zone_request('bad')
host = fakes.FakeHostState('host1', 'compute', {'service': service})
diff --git a/nova/tests/scheduler/test_host_manager.py b/nova/tests/scheduler/test_host_manager.py
index 0ee1d0470..ab0ed56c6 100644
--- a/nova/tests/scheduler/test_host_manager.py
+++ b/nova/tests/scheduler/test_host_manager.py
@@ -20,7 +20,6 @@ import datetime
from nova import db
from nova import exception
-from nova import log as logging
from nova.scheduler import host_manager
from nova import test
from nova.tests.scheduler import fakes
@@ -45,14 +44,14 @@ class HostManagerTestCase(test.TestCase):
self.host_manager = host_manager.HostManager()
def test_choose_host_filters_not_found(self):
- self.flags(default_host_filters='ComputeFilterClass3')
+ self.flags(scheduler_default_filters='ComputeFilterClass3')
self.host_manager.filter_classes = [ComputeFilterClass1,
ComputeFilterClass2]
self.assertRaises(exception.SchedulerHostFilterNotFound,
self.host_manager._choose_host_filters, None)
def test_choose_host_filters(self):
- self.flags(default_host_filters=['ComputeFilterClass2'])
+ self.flags(scheduler_default_filters=['ComputeFilterClass2'])
self.host_manager.filter_classes = [ComputeFilterClass1,
ComputeFilterClass2]