end of day
This commit is contained in:
		
							
								
								
									
										75
									
								
								nova/scheduler/host_filter.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								nova/scheduler/host_filter.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,75 @@ | |||||||
|  | # 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. | ||||||
|  |  | ||||||
|  | """ | ||||||
|  | The Host Filter classes are a way to ensure that only hosts that are | ||||||
|  | appropriate are considered when creating a new instance. Hosts that are | ||||||
|  | either incompatible or insufficient to accept a newly-requested instance | ||||||
|  | are removed by Host Filter classes from consideration. Those that pass | ||||||
|  | the filter are then passed on for weighting or other process for ordering. | ||||||
|  |  | ||||||
|  | Three filters are included: AllHosts, Flavor & JSON. AllHosts just | ||||||
|  | returns the full, unfiltered list of hosts. Flavor is a hard coded | ||||||
|  | matching mechanism based on flavor criteria and 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 Flavors and/or InstanceTypes are used for | ||||||
|  | specifing the type of instance desired. Specific Nova users have | ||||||
|  | noted a need for a more expressive way of specifying instances. | ||||||
|  | Since we don't want to get into building full DSL this 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 FlavorFilter. | ||||||
|  | """ | ||||||
|  |  | ||||||
|  | import json | ||||||
|  | import types | ||||||
|  |  | ||||||
|  | from nova import exception | ||||||
|  | from nova import flags | ||||||
|  | from nova import log as logging | ||||||
|  |  | ||||||
|  | import nova.scheduler | ||||||
|  |  | ||||||
|  |  | ||||||
|  | LOG = logging.getLogger('nova.scheduler.host_filter') | ||||||
|  | FLAGS = flags.FLAGS | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def _get_filters(): | ||||||
|  |     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)] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def choose_host_filter(filter_name=None): | ||||||
|  |     """Since the caller may specify which filter to use we need | ||||||
|  |     to have an authoritative list of what is permissible. This | ||||||
|  |     function checks the filter name against a predefined set | ||||||
|  |     of acceptable filters. | ||||||
|  |     """ | ||||||
|  |     if not filter_name: | ||||||
|  |         filter_name = FLAGS.default_host_filter | ||||||
|  |     for filter_class in _get_filters(): | ||||||
|  |         host_match = "%s.%s" % (filter_class.__module__, filter_class.__name__) | ||||||
|  |         if (host_match.startswith("nova.scheduler.filters") and | ||||||
|  |                 (host_match.split(".")[-1] == filter_name)): | ||||||
|  |             return filter_class() | ||||||
|  |     raise exception.SchedulerHostFilterNotFound(filter_name=filter_name) | ||||||
| @@ -20,6 +20,7 @@ import json | |||||||
|  |  | ||||||
| from nova import exception | from nova import exception | ||||||
| from nova import test | from nova import test | ||||||
|  | from nova.scheduler import host_filter | ||||||
| from nova.scheduler import filters | from nova.scheduler import filters | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -55,7 +56,7 @@ class HostFilterTestCase(test.TestCase): | |||||||
|  |  | ||||||
|     def setUp(self): |     def setUp(self): | ||||||
|         super(HostFilterTestCase, self).setUp() |         super(HostFilterTestCase, self).setUp() | ||||||
|         default_host_filter = 'nova.scheduler.filteris.AllHostsFilter' |         default_host_filter = 'AllHostsFilter' | ||||||
|         self.flags(default_host_filter=default_host_filter) |         self.flags(default_host_filter=default_host_filter) | ||||||
|         self.instance_type = dict(name='tiny', |         self.instance_type = dict(name='tiny', | ||||||
|                 memory_mb=50, |                 memory_mb=50, | ||||||
| @@ -98,13 +99,10 @@ class HostFilterTestCase(test.TestCase): | |||||||
|     def test_choose_filter(self): |     def test_choose_filter(self): | ||||||
|         # Test default filter ... |         # Test default filter ... | ||||||
|         hf = host_filter.choose_host_filter() |         hf = host_filter.choose_host_filter() | ||||||
|         self.assertEquals(hf._full_name(), |         self.assertEquals(hf._full_name().split(".")[-1], 'AllHostsFilter') | ||||||
|                         'nova.scheduler.host_filter.AllHostsFilter') |  | ||||||
|         # Test valid filter ... |         # Test valid filter ... | ||||||
|         hf = host_filter.choose_host_filter( |         hf = host_filter.choose_host_filter('InstanceTypeFilter') | ||||||
|                         'nova.scheduler.host_filter.InstanceTypeFilter') |         self.assertEquals(hf._full_name().split(".")[-1], 'InstanceTypeFilter') | ||||||
|         self.assertEquals(hf._full_name(), |  | ||||||
|                         'nova.scheduler.host_filter.InstanceTypeFilter') |  | ||||||
|         # Test invalid filter ... |         # Test invalid filter ... | ||||||
|         try: |         try: | ||||||
|             host_filter.choose_host_filter('does not exist') |             host_filter.choose_host_filter('does not exist') | ||||||
| @@ -113,7 +111,7 @@ class HostFilterTestCase(test.TestCase): | |||||||
|             pass |             pass | ||||||
|  |  | ||||||
|     def test_all_host_filter(self): |     def test_all_host_filter(self): | ||||||
|         hf = host_filter.AllHostsFilter() |         hf = filters.AllHostsFilter() | ||||||
|         cooked = hf.instance_type_to_filter(self.instance_type) |         cooked = hf.instance_type_to_filter(self.instance_type) | ||||||
|         hosts = hf.filter_hosts(self.zone_manager, cooked) |         hosts = hf.filter_hosts(self.zone_manager, cooked) | ||||||
|         self.assertEquals(10, len(hosts)) |         self.assertEquals(10, len(hosts)) | ||||||
| @@ -121,11 +119,10 @@ class HostFilterTestCase(test.TestCase): | |||||||
|             self.assertTrue(host.startswith('host')) |             self.assertTrue(host.startswith('host')) | ||||||
|  |  | ||||||
|     def test_instance_type_filter(self): |     def test_instance_type_filter(self): | ||||||
|         hf = host_filter.InstanceTypeFilter() |         hf = filters.InstanceTypeFilter() | ||||||
|         # filter all hosts that can support 50 ram and 500 disk |         # filter all hosts that can support 50 ram and 500 disk | ||||||
|         name, cooked = hf.instance_type_to_filter(self.instance_type) |         name, cooked = hf.instance_type_to_filter(self.instance_type) | ||||||
|         self.assertEquals('nova.scheduler.host_filter.InstanceTypeFilter', |         self.assertEquals(name.split(".")[-1], 'InstanceTypeFilter') | ||||||
|                           name) |  | ||||||
|         hosts = hf.filter_hosts(self.zone_manager, cooked) |         hosts = hf.filter_hosts(self.zone_manager, cooked) | ||||||
|         self.assertEquals(6, len(hosts)) |         self.assertEquals(6, len(hosts)) | ||||||
|         just_hosts = [host for host, caps in hosts] |         just_hosts = [host for host, caps in hosts] | ||||||
| @@ -134,21 +131,20 @@ class HostFilterTestCase(test.TestCase): | |||||||
|         self.assertEquals('host10', just_hosts[5]) |         self.assertEquals('host10', just_hosts[5]) | ||||||
|  |  | ||||||
|     def test_instance_type_filter_extra_specs(self): |     def test_instance_type_filter_extra_specs(self): | ||||||
|         hf = host_filter.InstanceTypeFilter() |         hf = filters.InstanceTypeFilter() | ||||||
|         # filter all hosts that can support 50 ram and 500 disk |         # filter all hosts that can support 50 ram and 500 disk | ||||||
|         name, cooked = hf.instance_type_to_filter(self.gpu_instance_type) |         name, cooked = hf.instance_type_to_filter(self.gpu_instance_type) | ||||||
|         self.assertEquals('nova.scheduler.host_filter.InstanceTypeFilter', |         self.assertEquals(name.split(".")[-1], 'InstanceTypeFilter') | ||||||
|                           name) |  | ||||||
|         hosts = hf.filter_hosts(self.zone_manager, cooked) |         hosts = hf.filter_hosts(self.zone_manager, cooked) | ||||||
|         self.assertEquals(1, len(hosts)) |         self.assertEquals(1, len(hosts)) | ||||||
|         just_hosts = [host for host, caps in hosts] |         just_hosts = [host for host, caps in hosts] | ||||||
|         self.assertEquals('host07', just_hosts[0]) |         self.assertEquals('host07', just_hosts[0]) | ||||||
|  |  | ||||||
|     def test_json_filter(self): |     def test_json_filter(self): | ||||||
|         hf = host_filter.JsonFilter() |         hf = filters.JsonFilter() | ||||||
|         # filter all hosts that can support 50 ram and 500 disk |         # filter all hosts that can support 50 ram and 500 disk | ||||||
|         name, cooked = hf.instance_type_to_filter(self.instance_type) |         name, cooked = hf.instance_type_to_filter(self.instance_type) | ||||||
|         self.assertEquals('nova.scheduler.host_filter.JsonFilter', name) |         self.assertEquals(name.split(".")[-1], 'JsonFilter') | ||||||
|         hosts = hf.filter_hosts(self.zone_manager, cooked) |         hosts = hf.filter_hosts(self.zone_manager, cooked) | ||||||
|         self.assertEquals(6, len(hosts)) |         self.assertEquals(6, len(hosts)) | ||||||
|         just_hosts = [host for host, caps in hosts] |         just_hosts = [host for host, caps in hosts] | ||||||
| @@ -191,6 +187,12 @@ class HostFilterTestCase(test.TestCase): | |||||||
|  |  | ||||||
|         raw = ['in', '$compute.host_memory_free', 20, 40, 60, 80, 100] |         raw = ['in', '$compute.host_memory_free', 20, 40, 60, 80, 100] | ||||||
|         cooked = json.dumps(raw) |         cooked = json.dumps(raw) | ||||||
|  |         def debug(*args): | ||||||
|  |             with file("/tmp/debug", "a") as dbg: | ||||||
|  |                 msg = " ".join([str(arg) for arg in args]) | ||||||
|  |                 dbg.write("%s\n" % msg) | ||||||
|  |  | ||||||
|  |         debug("cooked", cooked, type(cooked)) | ||||||
|         hosts = hf.filter_hosts(self.zone_manager, cooked) |         hosts = hf.filter_hosts(self.zone_manager, cooked) | ||||||
|  |  | ||||||
|         self.assertEquals(5, len(hosts)) |         self.assertEquals(5, len(hosts)) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Ed Leafe
					Ed Leafe