diff options
| author | Jenkins <jenkins@review.openstack.org> | 2012-08-22 07:02:45 +0000 |
|---|---|---|
| committer | Gerrit Code Review <review@openstack.org> | 2012-08-22 07:02:45 +0000 |
| commit | b090bdd0887317bb4f1f2a8ecec577b16fb94363 (patch) | |
| tree | eddf432cbc8beb1873d27c698424013f9aa9501c /nova | |
| parent | 962efab370f168bb077447eeb15d43063c8b2272 (diff) | |
| parent | 5ea7db9b7195132df4d8efea0a8e41e4f994b23c (diff) | |
| download | nova-b090bdd0887317bb4f1f2a8ecec577b16fb94363.tar.gz nova-b090bdd0887317bb4f1f2a8ecec577b16fb94363.tar.xz nova-b090bdd0887317bb4f1f2a8ecec577b16fb94363.zip | |
Merge "Introduce ImagePropertiesFilter scheduler filter"
Diffstat (limited to 'nova')
| -rw-r--r-- | nova/scheduler/filters/arch_filter.py | 44 | ||||
| -rw-r--r-- | nova/scheduler/filters/compute_filter.py | 57 | ||||
| -rw-r--r-- | nova/scheduler/filters/image_props_filter.py | 86 | ||||
| -rw-r--r-- | nova/scheduler/host_manager.py | 3 | ||||
| -rw-r--r-- | nova/tests/scheduler/test_host_filters.py | 151 |
5 files changed, 127 insertions, 214 deletions
diff --git a/nova/scheduler/filters/arch_filter.py b/nova/scheduler/filters/arch_filter.py deleted file mode 100644 index 625ce2909..000000000 --- a/nova/scheduler/filters/arch_filter.py +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2011-2012 OpenStack, LLC -# Copyright (c) 2012 Canonical Ltd -# 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. - - -from nova.openstack.common import log as logging -from nova.scheduler import filters -from nova import utils - - -LOG = logging.getLogger(__name__) - - -class ArchFilter(filters.BaseHostFilter): - """Filter out hosts that can not support the guest architecture. - Note: This is supported for libvirt only now. - """ - - def host_passes(self, host_state, filter_properties): - spec = filter_properties.get('request_spec', {}) - props = spec.get('instance_properties', {}) - - cpu_info = host_state.capabilities.get('cpu_info') - permitted_instances = cpu_info.get('permitted_instance_types', None) - - instance_arch = utils.sys_platform_translate(props.get('architecture')) - - if permitted_instances and instance_arch in permitted_instances: - return True - - LOG.warn(_('%(host_state)s fails permitted_instance_types'), locals()) - return False diff --git a/nova/scheduler/filters/compute_filter.py b/nova/scheduler/filters/compute_filter.py index c0ee98762..2d7c898d6 100644 --- a/nova/scheduler/filters/compute_filter.py +++ b/nova/scheduler/filters/compute_filter.py @@ -22,59 +22,10 @@ LOG = logging.getLogger(__name__) class ComputeFilter(filters.BaseHostFilter): - """Filter on active Compute nodes that satisfy the instance properties""" - - def _instance_supported(self, capabilities, instance_meta): - """Check if the instance is supported by the hypervisor. - - The instance may specify an architecture, hypervisor, and - vm_mode, e.g. (x86_64, kvm, hvm). - """ - inst_arch = instance_meta.get('image_architecture', None) - inst_h_type = instance_meta.get('image_hypervisor_type', None) - inst_vm_mode = instance_meta.get('image_vm_mode', None) - inst_props_req = (inst_arch, inst_h_type, inst_vm_mode) - - # Supported if no compute-related instance properties are specified - if not any(inst_props_req): - return True - - supp_instances = capabilities.get('supported_instances', None) - # Not supported if an instance property is requested but nothing - # advertised by the host. - if not supp_instances: - LOG.debug(_("Instance contains properties %(instance_meta)s, " - "but no corresponding capabilities are advertised " - "by the compute node"), locals()) - return False - - def _compare_props(props, other_props): - for i in props: - if i and i not in other_props: - return False - return True - - for supp_inst in supp_instances: - if _compare_props(inst_props_req, supp_inst): - LOG.debug(_("Instance properties %(instance_meta)s " - "are satisfied by compute host capabilities " - "%(capabilities)s"), locals()) - return True - - LOG.debug(_("Instance contains properties %(instance_meta)s " - "that are not provided by the compute node " - "capabilities %(capabilities)s"), locals()) - return False + """Filter on active Compute nodes""" def host_passes(self, host_state, filter_properties): - """Check if host passes instance compute properties. - - Returns True for active compute nodes that satisfy - the compute properties specified in the instance. - """ - spec = filter_properties.get('request_spec', {}) - instance_props = spec.get('instance_properties', {}) - instance_meta = instance_props.get('system_metadata', {}) + """Returns True for only active compute nodes""" instance_type = filter_properties.get('instance_type') if host_state.topic != 'compute' or not instance_type: return True @@ -89,8 +40,4 @@ class ComputeFilter(filters.BaseHostFilter): LOG.debug(_("%(host_state)s is disabled via capabilities"), locals()) return False - if not self._instance_supported(capabilities, instance_meta): - LOG.debug(_("%(host_state)s does not support requested " - "instance_properties"), locals()) - return False return True diff --git a/nova/scheduler/filters/image_props_filter.py b/nova/scheduler/filters/image_props_filter.py new file mode 100644 index 000000000..5eb710882 --- /dev/null +++ b/nova/scheduler/filters/image_props_filter.py @@ -0,0 +1,86 @@ +# Copyright (c) 2011-2012 OpenStack, LLC +# Copyright (c) 2012 Canonical Ltd +# Copyright (c) 2012 SUSE LINUX Products GmbH +# 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. + +from nova.openstack.common import log as logging +from nova.scheduler import filters +from nova import utils + + +LOG = logging.getLogger(__name__) + + +class ImagePropertiesFilter(filters.BaseHostFilter): + """Filter compute nodes that satisfy instance image properties. + + The ImagePropertiesFilter filters compute nodes that satisfy + any architecture, hpervisor type, or virtual machine mode properties + specified on the instance's image properties. Image properties are + contained in the image dictionary in the request_spec. + """ + + def _instance_supported(self, capabilities, image_props): + img_arch = image_props.get('architecture', None) + img_h_type = image_props.get('hypervisor_type', None) + img_vm_mode = image_props.get('vm_mode', None) + checked_img_props = (img_arch, img_h_type, img_vm_mode) + + # Supported if no compute-related instance properties are specified + if not any(checked_img_props): + return True + + supp_instances = capabilities.get('supported_instances', None) + # Not supported if an instance property is requested but nothing + # advertised by the host. + if not supp_instances: + LOG.debug(_("Instance contains properties %(image_props)s, " + "but no corresponding capabilities are advertised " + "by the compute node"), locals()) + return False + + def _compare_props(props, other_props): + for i in props: + if i and i not in other_props: + return False + return True + + for supp_inst in supp_instances: + if _compare_props(checked_img_props, supp_inst): + LOG.debug(_("Instance properties %(image_props)s " + "are satisfied by compute host capabilities " + "%(capabilities)s"), locals()) + return True + + LOG.debug(_("Instance contains properties %(image_props)s " + "that are not provided by the compute node " + "capabilities %(capabilities)s"), locals()) + return False + + def host_passes(self, host_state, filter_properties): + """Check if host passes specified image properties. + + Returns True for compute nodes that satisfy image properties + contained in the request_spec. + """ + spec = filter_properties.get('request_spec', {}) + image_props = spec.get('image', {}).get('properties', {}) + capabilities = host_state.capabilities + + if not self._instance_supported(capabilities, image_props): + LOG.debug(_("%(host_state)s does not support requested " + "instance_properties"), locals()) + return False + return True diff --git a/nova/scheduler/host_manager.py b/nova/scheduler/host_manager.py index f373a2ef3..33ba2c160 100644 --- a/nova/scheduler/host_manager.py +++ b/nova/scheduler/host_manager.py @@ -47,7 +47,8 @@ host_manager_opts = [ 'AvailabilityZoneFilter', 'RamFilter', 'ComputeFilter', - 'ComputeCapabilitiesFilter' + 'ComputeCapabilitiesFilter', + 'ImagePropertiesFilter' ], help='Which filter class names to use for filtering hosts ' 'when not specified in the request.'), diff --git a/nova/tests/scheduler/test_host_filters.py b/nova/tests/scheduler/test_host_filters.py index 5e42fed6f..49486162a 100644 --- a/nova/tests/scheduler/test_host_filters.py +++ b/nova/tests/scheduler/test_host_filters.py @@ -412,104 +412,81 @@ class HostFiltersTestCase(test.TestCase): 'service': service}) self.assertTrue(filt_cls.host_passes(host, filter_properties)) - def test_compute_filter_passes_same_inst_props(self): + def test_image_properties_filter_passes_same_inst_props(self): self._stub_service_is_up(True) - filt_cls = self.class_map['ComputeFilter']() - inst_meta = {'system_metadata': {'image_architecture': 'x86_64', - 'image_hypervisor_type': 'kvm', - 'image_vm_mode': 'hvm'}} - req_spec = {'instance_properties': inst_meta} - filter_properties = {'instance_type': {'memory_mb': 1024}, - 'request_spec': req_spec} + filt_cls = self.class_map['ImagePropertiesFilter']() + img_props = {'properties': {'_architecture': 'x86_64', + 'hypervisor_type': 'kvm', + 'vm_mode': 'hvm'}} + filter_properties = {'request_spec': {'image': img_props}} capabilities = {'enabled': True, 'supported_instances': [ ('x86_64', 'kvm', 'hvm')]} - service = {'disabled': False} host = fakes.FakeHostState('host1', 'compute', - {'free_ram_mb': 1024, 'capabilities': capabilities, - 'service': service}) + {'capabilities': capabilities}) self.assertTrue(filt_cls.host_passes(host, filter_properties)) - def test_compute_filter_fails_different_inst_props(self): + def test_image_properties_filter_fails_different_inst_props(self): self._stub_service_is_up(True) - filt_cls = self.class_map['ComputeFilter']() - inst_meta = {'system_metadata': {'image_architecture': 'arm', - 'image_hypervisor_type': 'qemu', - 'image_vm_mode': 'hvm'}} - req_spec = {'instance_properties': inst_meta} - filter_properties = {'instance_type': {'memory_mb': 1024}, - 'request_spec': req_spec} + filt_cls = self.class_map['ImagePropertiesFilter']() + img_props = {'properties': {'architecture': 'arm', + 'hypervisor_type': 'qemu', + 'vm_mode': 'hvm'}} + filter_properties = {'request_spec': {'image': img_props}} capabilities = {'enabled': True, 'supported_instances': [ ('x86_64', 'kvm', 'hvm')]} - service = {'disabled': False} host = fakes.FakeHostState('host1', 'compute', - {'free_ram_mb': 1024, 'capabilities': capabilities, - 'service': service}) + {'capabilities': capabilities}) self.assertFalse(filt_cls.host_passes(host, filter_properties)) - def test_compute_filter_passes_partial_inst_props(self): + def test_image_properties_filter_passes_partial_inst_props(self): self._stub_service_is_up(True) - filt_cls = self.class_map['ComputeFilter']() - inst_meta = {'system_metadata': {'image_architecture': 'x86_64', - 'image_vm_mode': 'hvm'}} - req_spec = {'instance_properties': inst_meta} - filter_properties = {'instance_type': {'memory_mb': 1024}, - 'request_spec': req_spec} + filt_cls = self.class_map['ImagePropertiesFilter']() + img_props = {'properties': {'architecture': 'x86_64', + 'vm_mode': 'hvm'}} + filter_properties = {'request_spec': {'image': img_props}} capabilities = {'enabled': True, 'supported_instances': [ ('x86_64', 'kvm', 'hvm')]} - service = {'disabled': False} host = fakes.FakeHostState('host1', 'compute', - {'free_ram_mb': 1024, 'capabilities': capabilities, - 'service': service}) + {'capabilities': capabilities}) self.assertTrue(filt_cls.host_passes(host, filter_properties)) - def test_compute_filter_fails_partial_inst_props(self): + def test_image_properties_filter_fails_partial_inst_props(self): self._stub_service_is_up(True) - filt_cls = self.class_map['ComputeFilter']() - inst_meta = {'system_metadata': {'image_architecture': 'x86_64', - 'image_vm_mode': 'hvm'}} - req_spec = {'instance_properties': inst_meta} - filter_properties = {'instance_type': {'memory_mb': 1024}, - 'request_spec': req_spec} + filt_cls = self.class_map['ImagePropertiesFilter']() + img_props = {'properties': {'architecture': 'x86_64', + 'vm_mode': 'hvm'}} + filter_properties = {'request_spec': {'image': img_props}} capabilities = {'enabled': True, 'supported_instances': [ ('x86_64', 'xen', 'xen')]} - service = {'disabled': False} host = fakes.FakeHostState('host1', 'compute', - {'free_ram_mb': 1024, 'capabilities': capabilities, - 'service': service}) + {'capabilities': capabilities}) self.assertFalse(filt_cls.host_passes(host, filter_properties)) - def test_compute_filter_passes_without_inst_props(self): + def test_image_properties_filter_passes_without_inst_props(self): self._stub_service_is_up(True) - filt_cls = self.class_map['ComputeFilter']() - filter_properties = {'instance_type': {'memory_mb': 1024}, - 'request_spec': {}} + filt_cls = self.class_map['ImagePropertiesFilter']() + filter_properties = {'request_spec': {}} capabilities = {'enabled': True, 'supported_instances': [ ('x86_64', 'kvm', 'hvm')]} - service = {'disabled': False} host = fakes.FakeHostState('host1', 'compute', - {'free_ram_mb': 1024, 'capabilities': capabilities, - 'service': service}) + {'capabilities': capabilities}) self.assertTrue(filt_cls.host_passes(host, filter_properties)) - def test_compute_filter_fails_without_host_props(self): + def test_image_properties_filter_fails_without_host_props(self): self._stub_service_is_up(True) - filt_cls = self.class_map['ComputeFilter']() - inst_meta = {'system_metadata': {'image_architecture': 'x86_64', - 'image_hypervisor_type': 'kvm', - 'image_vm_mode': 'hvm'}} - req_spec = {'instance_properties': inst_meta} - filter_properties = {'instance_type': {'memory_mb': 1024}, - 'request_spec': req_spec} + filt_cls = self.class_map['ImagePropertiesFilter']() + img_props = {'properties': {'architecture': 'x86_64', + 'hypervisor_type': 'kvm', + 'vm_mode': 'hvm'}} + filter_properties = {'request_spec': {'image': img_props}} capabilities = {'enabled': True} - service = {'disabled': False} host = fakes.FakeHostState('host1', 'compute', - {'free_ram_mb': 1024, 'capabilities': capabilities, - 'service': service}) + {'capabilities': capabilities}) self.assertFalse(filt_cls.host_passes(host, filter_properties)) def _do_test_compute_filter_extra_specs(self, ecaps, especs, passes): @@ -1256,60 +1233,6 @@ class HostFiltersTestCase(test.TestCase): host = fakes.FakeHostState('host1', 'compute', {'service': service}) self.assertFalse(filt_cls.host_passes(host, request)) - def test_arch_filter_same(self): - permitted_instances = ['x86_64'] - filt_cls = self.class_map['ArchFilter']() - filter_properties = { - 'request_spec': { - 'instance_properties': {'architecture': 'x86_64'} - } - } - capabilities = {'enabled': True, - 'cpu_info': { - 'permitted_instance_types': permitted_instances - } - } - service = {'disabled': False} - host = fakes.FakeHostState('host1', 'compute', - {'capabilities': capabilities, 'service': service}) - self.assertTrue(filt_cls.host_passes(host, filter_properties)) - - def test_arch_filter_different(self): - permitted_instances = ['arm'] - filt_cls = self.class_map['ArchFilter']() - filter_properties = { - 'request_spec': { - 'instance_properties': {'architecture': 'x86_64'} - } - } - capabilities = {'enabled': True, - 'cpu_info': { - 'permitted_instance_types': permitted_instances - } - } - service = {'disabled': False} - host = fakes.FakeHostState('host1', 'compute', - {'capabilities': capabilities, 'service': service}) - self.assertFalse(filt_cls.host_passes(host, filter_properties)) - - def test_arch_filter_without_permitted_instances(self): - permitted_instances = [] - filt_cls = self.class_map['ArchFilter']() - filter_properties = { - 'request_spec': { - 'instance_properties': {'architecture': 'x86_64'} - } - } - capabilities = {'enabled': True, - 'cpu_info': { - 'permitted_instance_types': permitted_instances - } - } - service = {'disabled': False} - host = fakes.FakeHostState('host1', 'compute', - {'capabilities': capabilities, 'service': service}) - self.assertFalse(filt_cls.host_passes(host, filter_properties)) - def test_retry_filter_disabled(self): """Test case where retry/re-scheduling is disabled""" filt_cls = self.class_map['RetryFilter']() |
