Merge "Make ComputeFilter verify compute-related instance properties"
This commit is contained in:
@@ -22,10 +22,59 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ComputeFilter(filters.BaseHostFilter):
|
||||
"""Filter on active Compute nodes"""
|
||||
"""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
|
||||
|
||||
def host_passes(self, host_state, filter_properties):
|
||||
"""Returns True for only active compute nodes"""
|
||||
"""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', {})
|
||||
instance_type = filter_properties.get('instance_type')
|
||||
if host_state.topic != 'compute' or not instance_type:
|
||||
return True
|
||||
@@ -40,4 +89,8 @@ 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
|
||||
|
||||
@@ -394,6 +394,106 @@ class HostFiltersTestCase(test.TestCase):
|
||||
'service': service})
|
||||
self.assertTrue(filt_cls.host_passes(host, filter_properties))
|
||||
|
||||
def test_compute_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}
|
||||
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})
|
||||
self.assertTrue(filt_cls.host_passes(host, filter_properties))
|
||||
|
||||
def test_compute_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}
|
||||
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})
|
||||
self.assertFalse(filt_cls.host_passes(host, filter_properties))
|
||||
|
||||
def test_compute_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}
|
||||
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})
|
||||
self.assertTrue(filt_cls.host_passes(host, filter_properties))
|
||||
|
||||
def test_compute_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}
|
||||
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})
|
||||
self.assertFalse(filt_cls.host_passes(host, filter_properties))
|
||||
|
||||
def test_compute_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': {}}
|
||||
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})
|
||||
self.assertTrue(filt_cls.host_passes(host, filter_properties))
|
||||
|
||||
def test_compute_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}
|
||||
capabilities = {'enabled': True}
|
||||
service = {'disabled': False}
|
||||
host = fakes.FakeHostState('host1', 'compute',
|
||||
{'free_ram_mb': 1024, 'capabilities': capabilities,
|
||||
'service': service})
|
||||
self.assertFalse(filt_cls.host_passes(host, filter_properties))
|
||||
|
||||
def test_compute_filter_passes_extra_specs_noop(self):
|
||||
self._stub_service_is_up(True)
|
||||
filt_cls = self.class_map['ComputeCapabilitiesFilter']()
|
||||
|
||||
Reference in New Issue
Block a user