Verify requested_destination in the scheduler

Now that the RequestSpec provides a field for a requested destination, we
can know if the admin user provided a destination to verify (and not force
it). In order to verify this destination, we want to run the filters for
only this host, so that if the filters are not okay for that possibility,
the scheduler should raise a NoValidHost exception.

For the moment, nothing is setting this field but the next patch will provide
an API-level modification for putting it if the provided destination exists
(and changing the behaviour if the admin provides the host field for evacuate
and live-migrate)

Change-Id: Ifb803c708e89b7101ded48571e1af49c33117758
Partially-Implements: blueprint check-destination-on-migrations
This commit is contained in:
Sylvain Bauza 2016-05-10 13:13:34 +02:00
parent 2358ebacd8
commit 7755b759b4
2 changed files with 57 additions and 0 deletions

View File

@ -505,10 +505,33 @@ class HostManager(object):
"'force_nodes' value of '%s'")
LOG.info(msg % forced_nodes_str)
def _get_hosts_matching_request(hosts, requested_destination):
(host, node) = (requested_destination.host,
requested_destination.node)
requested_nodes = [x for x in hosts
if x.host == host and x.nodename == node]
if requested_nodes:
LOG.info(_LI('Host filter only checking host %(host)s and '
'node %(node)s') % {'host': host, 'node': node})
else:
# NOTE(sbauza): The API level should prevent the user from
# providing a wrong destination but let's make sure a wrong
# destination doesn't trample the scheduler still.
LOG.info(_LI('No hosts matched due to not matching requested '
'destination (%(host)s, %(node)s)'
) % {'host': host, 'node': node})
return iter(requested_nodes)
ignore_hosts = spec_obj.ignore_hosts or []
force_hosts = spec_obj.force_hosts or []
force_nodes = spec_obj.force_nodes or []
requested_node = spec_obj.requested_destination
if requested_node is not None:
# NOTE(sbauza): Reduce a potentially long set of hosts as much as
# possible to any requested destination nodes before passing the
# list to the filters
hosts = _get_hosts_matching_request(hosts, requested_node)
if ignore_hosts or force_hosts or force_nodes:
# NOTE(deva): we can't assume "host" is unique because
# one host may have many nodes.

View File

@ -222,6 +222,40 @@ class HostManagerTestCase(test.NoDBTestCase):
fake_properties)
self._verify_result(info, result)
def test_get_filtered_hosts_with_requested_destination(self):
dest = objects.Destination(host='fake_host1', node='fake-node')
fake_properties = objects.RequestSpec(requested_destination=dest,
ignore_hosts=[],
instance_uuid='fake-uuid1',
force_hosts=[],
force_nodes=[])
info = {'expected_objs': [self.fake_hosts[0]],
'expected_fprops': fake_properties}
self._mock_get_filtered_hosts(info)
result = self.host_manager.get_filtered_hosts(self.fake_hosts,
fake_properties)
self._verify_result(info, result)
def test_get_filtered_hosts_with_wrong_requested_destination(self):
dest = objects.Destination(host='dummy', node='fake-node')
fake_properties = objects.RequestSpec(requested_destination=dest,
ignore_hosts=[],
instance_uuid='fake-uuid1',
force_hosts=[],
force_nodes=[])
info = {'expected_objs': [],
'expected_fprops': fake_properties}
self._mock_get_filtered_hosts(info)
result = self.host_manager.get_filtered_hosts(self.fake_hosts,
fake_properties)
self._verify_result(info, result)
def test_get_filtered_hosts_with_ignore(self):
fake_properties = objects.RequestSpec(
instance_uuid=uuids.instance,