nova/nova/tests/unit/scheduler/test_chance_scheduler.py
Ed Leafe e7152eef7b Modify select_destinations() to return objects and alts
This changes select_destinations() on the scheduler side to optionally
return Selection objects and alternates. The RPC signature doesn't
change in this patch, though, so everything on the conductor side
remains unchanged. The next patch in the series will make the actual RPC
change.

Blueprint: return-alternate-hosts

Change-Id: I03b95a2106624c2ea24835814ca38e954ec7a997
2017-12-07 15:01:13 +00:00

159 lines
6.6 KiB
Python

# 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 Chance Scheduler.
"""
import mock
from nova import exception
from nova import objects
from nova.scheduler import chance
from nova.scheduler import host_manager
from nova.tests.unit.scheduler import test_scheduler
from nova.tests import uuidsentinel as uuids
def _generate_fake_hosts(num):
hosts = []
for i in range(num):
fake_host_state = host_manager.HostState("host%s" % i, "fake_node",
uuids.cell)
fake_host_state.uuid = getattr(uuids, "host%s" % i)
fake_host_state.limits = {}
hosts.append(fake_host_state)
return hosts
class ChanceSchedulerTestCase(test_scheduler.SchedulerTestCase):
"""Test case for Chance Scheduler."""
driver_cls = chance.ChanceScheduler
def test_filter_hosts_avoid(self):
"""Test to make sure _filter_hosts() filters original hosts if
avoid_original_host is True.
"""
hosts = ['host1', 'host2', 'host3']
spec_obj = objects.RequestSpec(ignore_hosts=['host2'])
filtered = self.driver._filter_hosts(hosts, spec_obj=spec_obj)
self.assertEqual(filtered, ['host1', 'host3'])
def test_filter_hosts_no_avoid(self):
"""Test to make sure _filter_hosts() does not filter original
hosts if avoid_original_host is False.
"""
hosts = ['host1', 'host2', 'host3']
spec_obj = objects.RequestSpec(ignore_hosts=[])
filtered = self.driver._filter_hosts(hosts, spec_obj=spec_obj)
self.assertEqual(filtered, hosts)
@mock.patch("nova.scheduler.chance.ChanceScheduler.hosts_up")
def test_select_destinations(self, mock_hosts_up):
mock_hosts_up.return_value = _generate_fake_hosts(4)
spec_obj = objects.RequestSpec(num_instances=2, ignore_hosts=None)
dests = self.driver.select_destinations(self.context, spec_obj,
[uuids.instance1, uuids.instance2], {},
mock.sentinel.provider_summaries)
self.assertEqual(2, len(dests))
# Test that different hosts were returned
self.assertIsNot(dests[0], dests[1])
@mock.patch("nova.scheduler.chance.ChanceScheduler._filter_hosts")
@mock.patch("nova.scheduler.chance.ChanceScheduler.hosts_up")
def test_select_destinations_no_valid_host(self, mock_hosts_up,
mock_filter):
mock_hosts_up.return_value = _generate_fake_hosts(4)
mock_filter.return_value = []
spec_obj = objects.RequestSpec(num_instances=1)
spec_obj.instance_uuid = uuids.instance
self.assertRaises(exception.NoValidHost,
self.driver.select_destinations, self.context,
spec_obj, [spec_obj.instance_uuid], {},
mock.sentinel.provider_summaries)
@mock.patch("nova.scheduler.chance.ChanceScheduler.hosts_up")
def test_schedule_success_single_instance(self, mock_hosts_up):
hosts = _generate_fake_hosts(20)
mock_hosts_up.return_value = hosts
spec_obj = objects.RequestSpec(num_instances=1, ignore_hosts=None)
spec_obj.instance_uuid = uuids.instance
# Set the max_attempts to 2
attempts = 2
expected = attempts
self.flags(max_attempts=attempts, group="scheduler")
selected_hosts = self.driver._schedule(self.context, "compute",
spec_obj, [spec_obj.instance_uuid], return_alternates=True)
self.assertEqual(1, len(selected_hosts))
for host_list in selected_hosts:
self.assertEqual(expected, len(host_list))
# Now set max_attempts to a number larger than the available hosts. It
# should return a host_list containing only as many hosts as there are
# to choose from.
attempts = len(hosts) + 1
expected = len(hosts)
self.flags(max_attempts=attempts, group="scheduler")
selected_hosts = self.driver._schedule(self.context, "compute",
spec_obj, [spec_obj.instance_uuid], return_alternates=True)
self.assertEqual(1, len(selected_hosts))
for host_list in selected_hosts:
self.assertEqual(expected, len(host_list))
# Now verify that if we pass False for return_alternates, that we only
# get one host in the host_list.
attempts = 5
expected = 1
self.flags(max_attempts=attempts, group="scheduler")
selected_hosts = self.driver._schedule(self.context, "compute",
spec_obj, [spec_obj.instance_uuid], return_alternates=False)
self.assertEqual(1, len(selected_hosts))
for host_list in selected_hosts:
self.assertEqual(expected, len(host_list))
@mock.patch("nova.scheduler.chance.ChanceScheduler.hosts_up")
def test_schedule_success_multiple_instances(self, mock_hosts_up):
hosts = _generate_fake_hosts(20)
mock_hosts_up.return_value = hosts
num_instances = 4
spec_obj = objects.RequestSpec(num_instances=num_instances,
ignore_hosts=None)
instance_uuids = [getattr(uuids, "inst%s" % i)
for i in range(num_instances)]
spec_obj.instance_uuid = instance_uuids[0]
# Set the max_attempts to 2
attempts = 2
self.flags(max_attempts=attempts, group="scheduler")
selected_hosts = self.driver._schedule(self.context, "compute",
spec_obj, instance_uuids, return_alternates=True)
self.assertEqual(num_instances, len(selected_hosts))
for host_list in selected_hosts:
self.assertEqual(attempts, len(host_list))
# Verify that none of the selected hosts appear as alternates
# Set the max_attempts to 5 to get 4 alternates per instance
attempts = 4
self.flags(max_attempts=attempts, group="scheduler")
result = self.driver._schedule(self.context, "compute", spec_obj,
instance_uuids)
selected = [host_list[0] for host_list in result]
for host_list in result:
for sel in selected:
self.assertNotIn(sel, host_list[1:])