summaryrefslogtreecommitdiffstats
path: root/nova
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2012-08-22 07:02:45 +0000
committerGerrit Code Review <review@openstack.org>2012-08-22 07:02:45 +0000
commitb090bdd0887317bb4f1f2a8ecec577b16fb94363 (patch)
treeeddf432cbc8beb1873d27c698424013f9aa9501c /nova
parent962efab370f168bb077447eeb15d43063c8b2272 (diff)
parent5ea7db9b7195132df4d8efea0a8e41e4f994b23c (diff)
downloadnova-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.py44
-rw-r--r--nova/scheduler/filters/compute_filter.py57
-rw-r--r--nova/scheduler/filters/image_props_filter.py86
-rw-r--r--nova/scheduler/host_manager.py3
-rw-r--r--nova/tests/scheduler/test_host_filters.py151
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']()