201 lines
7.6 KiB
Python
201 lines
7.6 KiB
Python
# Copyright 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.
|
|
"""
|
|
Tests For Scheduler Host Filters.
|
|
"""
|
|
|
|
import json
|
|
|
|
from nova import exception
|
|
from nova import test
|
|
from nova.scheduler import host_filter
|
|
|
|
|
|
class FakeZoneManager:
|
|
pass
|
|
|
|
|
|
class HostFilterTestCase(test.TestCase):
|
|
"""Test case for host filters."""
|
|
|
|
def _host_caps(self, multiplier):
|
|
# Returns host capabilities in the following way:
|
|
# host1 = memory:free 10 (100max)
|
|
# disk:available 100 (1000max)
|
|
# hostN = memory:free 10 + 10N
|
|
# disk:available 100 + 100N
|
|
# in other words: hostN has more resources than host0
|
|
# which means ... don't go above 10 hosts.
|
|
return {'host_name-description': 'XenServer %s' % multiplier,
|
|
'host_hostname': 'xs-%s' % multiplier,
|
|
'host_memory_total': 100,
|
|
'host_memory_overhead': 10,
|
|
'host_memory_free': 10 + multiplier * 10,
|
|
'host_memory_free-computed': 10 + multiplier * 10,
|
|
'host_other-config': {},
|
|
'host_ip_address': '192.168.1.%d' % (100 + multiplier),
|
|
'host_cpu_info': {},
|
|
'disk_available': 100 + multiplier * 100,
|
|
'disk_total': 1000,
|
|
'disk_used': 0,
|
|
'host_uuid': 'xxx-%d' % multiplier,
|
|
'host_name-label': 'xs-%s' % multiplier}
|
|
|
|
def setUp(self):
|
|
super(HostFilterTestCase, self).setUp()
|
|
default_host_filter = 'nova.scheduler.host_filter.AllHostsFilter'
|
|
self.flags(default_host_filter=default_host_filter)
|
|
self.instance_type = dict(name='tiny',
|
|
memory_mb=50,
|
|
vcpus=10,
|
|
local_gb=500,
|
|
flavorid=1,
|
|
swap=500,
|
|
rxtx_quota=30000,
|
|
rxtx_cap=200,
|
|
extra_specs={})
|
|
|
|
self.zone_manager = FakeZoneManager()
|
|
states = {}
|
|
for x in xrange(10):
|
|
states['host%02d' % (x + 1)] = {'compute': self._host_caps(x)}
|
|
self.zone_manager.service_states = states
|
|
|
|
def test_choose_filter(self):
|
|
# Test default filter ...
|
|
hf = host_filter.choose_host_filter()
|
|
self.assertEquals(hf._full_name(),
|
|
'nova.scheduler.host_filter.AllHostsFilter')
|
|
# Test valid filter ...
|
|
hf = host_filter.choose_host_filter(
|
|
'nova.scheduler.host_filter.InstanceTypeFilter')
|
|
self.assertEquals(hf._full_name(),
|
|
'nova.scheduler.host_filter.InstanceTypeFilter')
|
|
# Test invalid filter ...
|
|
try:
|
|
host_filter.choose_host_filter('does not exist')
|
|
self.fail("Should not find host filter.")
|
|
except exception.SchedulerHostFilterNotFound:
|
|
pass
|
|
|
|
def test_all_host_filter(self):
|
|
hf = host_filter.AllHostsFilter()
|
|
cooked = hf.instance_type_to_filter(self.instance_type)
|
|
hosts = hf.filter_hosts(self.zone_manager, cooked)
|
|
self.assertEquals(10, len(hosts))
|
|
for host, capabilities in hosts:
|
|
self.assertTrue(host.startswith('host'))
|
|
|
|
def test_instance_type_filter(self):
|
|
hf = host_filter.InstanceTypeFilter()
|
|
# filter all hosts that can support 50 ram and 500 disk
|
|
name, cooked = hf.instance_type_to_filter(self.instance_type)
|
|
self.assertEquals('nova.scheduler.host_filter.InstanceTypeFilter',
|
|
name)
|
|
hosts = hf.filter_hosts(self.zone_manager, cooked)
|
|
self.assertEquals(6, len(hosts))
|
|
just_hosts = [host for host, caps in hosts]
|
|
just_hosts.sort()
|
|
self.assertEquals('host05', just_hosts[0])
|
|
self.assertEquals('host10', just_hosts[5])
|
|
|
|
def test_json_filter(self):
|
|
hf = host_filter.JsonFilter()
|
|
# filter all hosts that can support 50 ram and 500 disk
|
|
name, cooked = hf.instance_type_to_filter(self.instance_type)
|
|
self.assertEquals('nova.scheduler.host_filter.JsonFilter', name)
|
|
hosts = hf.filter_hosts(self.zone_manager, cooked)
|
|
self.assertEquals(6, len(hosts))
|
|
just_hosts = [host for host, caps in hosts]
|
|
just_hosts.sort()
|
|
self.assertEquals('host05', just_hosts[0])
|
|
self.assertEquals('host10', just_hosts[5])
|
|
|
|
# Try some custom queries
|
|
|
|
raw = ['or',
|
|
['and',
|
|
['<', '$compute.host_memory_free', 30],
|
|
['<', '$compute.disk_available', 300],
|
|
],
|
|
['and',
|
|
['>', '$compute.host_memory_free', 70],
|
|
['>', '$compute.disk_available', 700],
|
|
],
|
|
]
|
|
|
|
cooked = json.dumps(raw)
|
|
hosts = hf.filter_hosts(self.zone_manager, cooked)
|
|
|
|
self.assertEquals(5, len(hosts))
|
|
just_hosts = [host for host, caps in hosts]
|
|
just_hosts.sort()
|
|
for index, host in zip([1, 2, 8, 9, 10], just_hosts):
|
|
self.assertEquals('host%02d' % index, host)
|
|
|
|
raw = ['not',
|
|
['=', '$compute.host_memory_free', 30],
|
|
]
|
|
cooked = json.dumps(raw)
|
|
hosts = hf.filter_hosts(self.zone_manager, cooked)
|
|
|
|
self.assertEquals(9, len(hosts))
|
|
just_hosts = [host for host, caps in hosts]
|
|
just_hosts.sort()
|
|
for index, host in zip([1, 2, 4, 5, 6, 7, 8, 9, 10], just_hosts):
|
|
self.assertEquals('host%02d' % index, host)
|
|
|
|
raw = ['in', '$compute.host_memory_free', 20, 40, 60, 80, 100]
|
|
cooked = json.dumps(raw)
|
|
hosts = hf.filter_hosts(self.zone_manager, cooked)
|
|
|
|
self.assertEquals(5, len(hosts))
|
|
just_hosts = [host for host, caps in hosts]
|
|
just_hosts.sort()
|
|
for index, host in zip([2, 4, 6, 8, 10], just_hosts):
|
|
self.assertEquals('host%02d' % index, host)
|
|
|
|
# Try some bogus input ...
|
|
raw = ['unknown command', ]
|
|
cooked = json.dumps(raw)
|
|
try:
|
|
hf.filter_hosts(self.zone_manager, cooked)
|
|
self.fail("Should give KeyError")
|
|
except KeyError, e:
|
|
pass
|
|
|
|
self.assertTrue(hf.filter_hosts(self.zone_manager, json.dumps([])))
|
|
self.assertTrue(hf.filter_hosts(self.zone_manager, json.dumps({})))
|
|
self.assertTrue(hf.filter_hosts(self.zone_manager, json.dumps(
|
|
['not', True, False, True, False])))
|
|
|
|
try:
|
|
hf.filter_hosts(self.zone_manager, json.dumps(
|
|
'not', True, False, True, False))
|
|
self.fail("Should give KeyError")
|
|
except KeyError, e:
|
|
pass
|
|
|
|
self.assertFalse(hf.filter_hosts(self.zone_manager,
|
|
json.dumps(['=', '$foo', 100])))
|
|
self.assertFalse(hf.filter_hosts(self.zone_manager,
|
|
json.dumps(['=', '$.....', 100])))
|
|
self.assertFalse(hf.filter_hosts(self.zone_manager,
|
|
json.dumps(
|
|
['>', ['and', ['or', ['not', ['<', ['>=', ['<=', ['in', ]]]]]]]])))
|
|
|
|
self.assertFalse(hf.filter_hosts(self.zone_manager,
|
|
json.dumps(['=', {}, ['>', '$missing....foo']])))
|