Add flag to make IsolatedHostsFilter less restrictive

This patch allows to run 'isolated' and 'non isolated'
images on isolated hosts by adding a flag
'restrict_isolated_hosts_to_isolated_images'.

If the flag is set to True then 'non isolated' images
can't be run on isolated hosts (same behaviour as the
current filter) otherwise they can be run on isolated
hosts.

DocImpact

blueprint improve-isolatedhostsfilter

Change-Id: I8c092caf32c05be88a547a7e8cb0530cc4925080
This commit is contained in:
Yassine Lamgarchal 2013-08-02 16:44:54 +02:00
parent c6d5325ef6
commit 35925e5d28
4 changed files with 50 additions and 10 deletions

View File

@ -79,8 +79,8 @@ There are some standard filter classes to use (:mod:`nova.scheduler.filters`):
fall back to the global default ``cpu_allocation_ratio``. If more than one value
is found for a host (meaning the host is in two differenet aggregate with
different ratio settings), the minimum value will be used.
* |IsolatedHostsFilter| - filter based on ``image_isolated`` and ``host_isolated``
flags.
* |IsolatedHostsFilter| - filter based on ``image_isolated``, ``host_isolated``
and ``restrict_isolated_hosts_to_isolated_images`` flags.
* |JsonFilter| - allows simple JSON-based grammar for selecting hosts.
* |RamFilter| - filters hosts by their RAM. Only hosts with sufficient RAM
to host the instance are passed.
@ -166,7 +166,8 @@ Now we are going to |IsolatedHostsFilter|. There can be some special hosts
reserved for specific images. These hosts are called **isolated**. So the
images to run on the isolated hosts are also called isolated. This Scheduler
checks if ``image_isolated`` flag named in instance specifications is the same
that the host has.
that the host has. Isolated hosts can run non isolated images if the flag
``restrict_isolated_hosts_to_isolated_images`` is set to false.
|DifferentHostFilter| - its method ``host_passes`` returns ``True`` if host to
place instance on is different from all the hosts used by set of instances.

View File

@ -1714,6 +1714,10 @@
# Host reserved for specific images (list value)
#isolated_hosts=
# Whether to force isolated hosts to run only isolated images
# (boolean value)
#restrict_isolated_hosts_to_isolated_images=true
#
# Options defined in nova.scheduler.filters.num_instances_filter

View File

@ -24,6 +24,10 @@ isolated_opts = [
cfg.ListOpt('isolated_hosts',
default=[],
help='Host reserved for specific images'),
cfg.BoolOpt('restrict_isolated_hosts_to_isolated_images',
default=True,
help='Whether to force isolated hosts to run only isolated '
'images'),
]
CONF = cfg.CONF
CONF.register_opts(isolated_opts)
@ -37,26 +41,42 @@ class IsolatedHostsFilter(filters.BaseHostFilter):
def host_passes(self, host_state, filter_properties):
"""
Result Matrix:
Result Matrix with 'restrict_isolated_hosts_to_isolated_images' set
to True:
| isolated_image | non_isolated_image
-------------+----------------+-------------------
iso_host | True | False
non_iso_host | False | True
Result Matrix with 'restrict_isolated_hosts_to_isolated_images' set
to False:
| isolated_image | non_isolated_image
-------------+----------------+-------------------
iso_host | True | True
non_iso_host | False | True
"""
# If the configuration does not list any hosts, the filter will always
# return True, assuming a configuration error, so letting all hosts
# through.
isolated_hosts = CONF.isolated_hosts
isolated_images = CONF.isolated_images
restrict_isolated_hosts_to_isolated_images = (CONF.
restrict_isolated_hosts_to_isolated_images)
if not isolated_images:
# As there are no images to match, return False if the host is in
# the isolation list
return host_state.host not in isolated_hosts
# As there are no images to match, return True if the filter is
# not restrictive otherwise return False if the host is in the
# isolation list.
return ((not restrict_isolated_hosts_to_isolated_images) or
(host_state.host not in isolated_hosts))
spec = filter_properties.get('request_spec', {})
props = spec.get('instance_properties', {})
image_ref = props.get('image_ref')
image_isolated = image_ref in isolated_images
host_isolated = host_state.host in isolated_hosts
return image_isolated == host_isolated
if restrict_isolated_hosts_to_isolated_images:
return (image_isolated == host_isolated)
else:
return (not image_isolated) or host_isolated

View File

@ -896,10 +896,13 @@ class HostFiltersTestCase(test.NoDBTestCase):
passes=False)
def _do_test_isolated_hosts(self, host_in_list, image_in_list,
set_flags=True):
set_flags=True,
restrict_isolated_hosts_to_isolated_images=True):
if set_flags:
self.flags(isolated_images=['isolated_image'],
isolated_hosts=['isolated_host'])
isolated_hosts=['isolated_host'],
restrict_isolated_hosts_to_isolated_images=
restrict_isolated_hosts_to_isolated_images)
host_name = 'isolated_host' if host_in_list else 'free_host'
image_ref = 'isolated_image' if image_in_list else 'free_image'
filter_properties = {
@ -949,6 +952,18 @@ class HostFiltersTestCase(test.NoDBTestCase):
self.assertFalse(self._do_test_isolated_hosts(True, True, False))
self.assertTrue(self._do_test_isolated_hosts(False, False, False))
def test_isolated_hosts_less_restrictive(self):
# If there are isolated hosts and non isolated images
self.assertTrue(self._do_test_isolated_hosts(True, False, True, False))
# If there are isolated hosts and isolated images
self.assertTrue(self._do_test_isolated_hosts(True, True, True, False))
# If there are non isolated hosts and non isolated images
self.assertTrue(self._do_test_isolated_hosts(False, False, True,
False))
# If there are non isolated hosts and isolated images
self.assertFalse(self._do_test_isolated_hosts(False, True, True,
False))
def test_json_filter_passes(self):
filt_cls = self.class_map['JsonFilter']()
filter_properties = {'instance_type': {'memory_mb': 1024,