# Copyright 2011 OpenStack Foundation # 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 httplib from oslo.config import cfg import stubout from nova import context from nova import db from nova.openstack.common import jsonutils from nova.openstack.common import timeutils from nova.scheduler import filters from nova.scheduler.filters import extra_specs_ops from nova.scheduler.filters import trusted_filter from nova import servicegroup from nova import test from nova.tests.scheduler import fakes CONF = cfg.CONF CONF.import_opt('my_ip', 'nova.netconf') class TestFilter(filters.BaseHostFilter): pass class TestBogusFilter(object): """Class that doesn't inherit from BaseHostFilter.""" pass class ExtraSpecsOpsTestCase(test.TestCase): def _do_extra_specs_ops_test(self, value, req, matches): assertion = self.assertTrue if matches else self.assertFalse assertion(extra_specs_ops.match(value, req)) def test_extra_specs_matches_simple(self): self._do_extra_specs_ops_test( value='1', req='1', matches=True) def test_extra_specs_fails_simple(self): self._do_extra_specs_ops_test( value='', req='1', matches=False) def test_extra_specs_fails_simple2(self): self._do_extra_specs_ops_test( value='3', req='1', matches=False) def test_extra_specs_fails_simple3(self): self._do_extra_specs_ops_test( value='222', req='2', matches=False) def test_extra_specs_fails_with_bogus_ops(self): self._do_extra_specs_ops_test( value='4', req='> 2', matches=False) def test_extra_specs_matches_with_op_eq(self): self._do_extra_specs_ops_test( value='123', req='= 123', matches=True) def test_extra_specs_matches_with_op_eq2(self): self._do_extra_specs_ops_test( value='124', req='= 123', matches=True) def test_extra_specs_fails_with_op_eq(self): self._do_extra_specs_ops_test( value='34', req='= 234', matches=False) def test_extra_specs_fails_with_op_eq3(self): self._do_extra_specs_ops_test( value='34', req='=', matches=False) def test_extra_specs_matches_with_op_seq(self): self._do_extra_specs_ops_test( value='123', req='s== 123', matches=True) def test_extra_specs_fails_with_op_seq(self): self._do_extra_specs_ops_test( value='1234', req='s== 123', matches=False) def test_extra_specs_matches_with_op_sneq(self): self._do_extra_specs_ops_test( value='1234', req='s!= 123', matches=True) def test_extra_specs_fails_with_op_sneq(self): self._do_extra_specs_ops_test( value='123', req='s!= 123', matches=False) def test_extra_specs_fails_with_op_sge(self): self._do_extra_specs_ops_test( value='1000', req='s>= 234', matches=False) def test_extra_specs_fails_with_op_sle(self): self._do_extra_specs_ops_test( value='1234', req='s<= 1000', matches=False) def test_extra_specs_fails_with_op_sl(self): self._do_extra_specs_ops_test( value='2', req='s< 12', matches=False) def test_extra_specs_fails_with_op_sg(self): self._do_extra_specs_ops_test( value='12', req='s> 2', matches=False) def test_extra_specs_matches_with_op_in(self): self._do_extra_specs_ops_test( value='12311321', req=' 11', matches=True) def test_extra_specs_matches_with_op_in2(self): self._do_extra_specs_ops_test( value='12311321', req=' 12311321', matches=True) def test_extra_specs_matches_with_op_in3(self): self._do_extra_specs_ops_test( value='12311321', req=' 12311321 ', matches=True) def test_extra_specs_fails_with_op_in(self): self._do_extra_specs_ops_test( value='12310321', req=' 11', matches=False) def test_extra_specs_fails_with_op_in2(self): self._do_extra_specs_ops_test( value='12310321', req=' 11 ', matches=False) def test_extra_specs_matches_with_op_or(self): self._do_extra_specs_ops_test( value='12', req=' 11 12', matches=True) def test_extra_specs_matches_with_op_or2(self): self._do_extra_specs_ops_test( value='12', req=' 11 12 ', matches=True) def test_extra_specs_fails_with_op_or(self): self._do_extra_specs_ops_test( value='13', req=' 11 12', matches=False) def test_extra_specs_fails_with_op_or2(self): self._do_extra_specs_ops_test( value='13', req=' 11 12 ', matches=False) def test_extra_specs_matches_with_op_le(self): self._do_extra_specs_ops_test( value='2', req='<= 10', matches=True) def test_extra_specs_fails_with_op_le(self): self._do_extra_specs_ops_test( value='3', req='<= 2', matches=False) def test_extra_specs_matches_with_op_ge(self): self._do_extra_specs_ops_test( value='3', req='>= 1', matches=True) def test_extra_specs_fails_with_op_ge(self): self._do_extra_specs_ops_test( value='2', req='>= 3', matches=False) class HostFiltersTestCase(test.TestCase): """Test case for host filters.""" def fake_oat_request(self, *args, **kwargs): """Stubs out the response from OAT service.""" self.oat_attested = True return httplib.OK, self.oat_data def setUp(self): super(HostFiltersTestCase, self).setUp() self.oat_data = '' self.oat_attested = False self.stubs = stubout.StubOutForTesting() self.stubs.Set(trusted_filter.AttestationService, '_request', self.fake_oat_request) self.context = context.RequestContext('fake', 'fake') self.json_query = jsonutils.dumps( ['and', ['>=', '$free_ram_mb', 1024], ['>=', '$free_disk_mb', 200 * 1024]]) filter_handler = filters.HostFilterHandler() classes = filter_handler.get_matching_classes( ['nova.scheduler.filters.all_filters']) self.class_map = {} for cls in classes: self.class_map[cls.__name__] = cls def test_all_filters(self): # Double check at least a couple of known filters exist self.assertIn('AllHostsFilter', self.class_map) self.assertIn('ComputeFilter', self.class_map) def test_all_host_filter(self): filt_cls = self.class_map['AllHostsFilter']() host = fakes.FakeHostState('host1', 'node1', {}) self.assertTrue(filt_cls.host_passes(host, {})) def _stub_service_is_up(self, ret_value): def fake_service_is_up(self, service): return ret_value self.stubs.Set(servicegroup.API, 'service_is_up', fake_service_is_up) def test_affinity_different_filter_passes(self): filt_cls = self.class_map['DifferentHostFilter']() host = fakes.FakeHostState('host1', 'node1', {}) instance = fakes.FakeInstance(context=self.context, params={'host': 'host2'}) instance_uuid = instance.uuid filter_properties = {'context': self.context.elevated(), 'scheduler_hints': { 'different_host': [instance_uuid], }} self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_affinity_different_filter_no_list_passes(self): filt_cls = self.class_map['DifferentHostFilter']() host = fakes.FakeHostState('host1', 'node1', {}) instance = fakes.FakeInstance(context=self.context, params={'host': 'host2'}) instance_uuid = instance.uuid filter_properties = {'context': self.context.elevated(), 'scheduler_hints': { 'different_host': instance_uuid}} self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_affinity_different_filter_fails(self): filt_cls = self.class_map['DifferentHostFilter']() host = fakes.FakeHostState('host1', 'node1', {}) instance = fakes.FakeInstance(context=self.context, params={'host': 'host1'}) instance_uuid = instance.uuid filter_properties = {'context': self.context.elevated(), 'scheduler_hints': { 'different_host': [instance_uuid], }} self.assertFalse(filt_cls.host_passes(host, filter_properties)) def test_affinity_different_filter_handles_none(self): filt_cls = self.class_map['DifferentHostFilter']() host = fakes.FakeHostState('host1', 'node1', {}) instance = fakes.FakeInstance(context=self.context, params={'host': 'host2'}) instance_uuid = instance.uuid filter_properties = {'context': self.context.elevated(), 'scheduler_hints': None} self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_affinity_different_filter_handles_deleted_instance(self): filt_cls = self.class_map['DifferentHostFilter']() host = fakes.FakeHostState('host1', 'node1', {}) instance = fakes.FakeInstance(context=self.context, params={'host': 'host1'}) instance_uuid = instance.uuid db.instance_destroy(self.context, instance_uuid) filter_properties = {'context': self.context.elevated(), 'scheduler_hints': { 'different_host': [instance_uuid], }} self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_affinity_same_filter_no_list_passes(self): filt_cls = self.class_map['SameHostFilter']() host = fakes.FakeHostState('host1', 'node1', {}) instance = fakes.FakeInstance(context=self.context, params={'host': 'host1'}) instance_uuid = instance.uuid filter_properties = {'context': self.context.elevated(), 'scheduler_hints': { 'same_host': instance_uuid}} self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_affinity_same_filter_passes(self): filt_cls = self.class_map['SameHostFilter']() host = fakes.FakeHostState('host1', 'node1', {}) instance = fakes.FakeInstance(context=self.context, params={'host': 'host1'}) instance_uuid = instance.uuid filter_properties = {'context': self.context.elevated(), 'scheduler_hints': { 'same_host': [instance_uuid], }} self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_affinity_same_filter_fails(self): filt_cls = self.class_map['SameHostFilter']() host = fakes.FakeHostState('host1', 'node1', {}) instance = fakes.FakeInstance(context=self.context, params={'host': 'host2'}) instance_uuid = instance.uuid filter_properties = {'context': self.context.elevated(), 'scheduler_hints': { 'same_host': [instance_uuid], }} self.assertFalse(filt_cls.host_passes(host, filter_properties)) def test_affinity_same_filter_handles_none(self): filt_cls = self.class_map['SameHostFilter']() host = fakes.FakeHostState('host1', 'node1', {}) instance = fakes.FakeInstance(context=self.context, params={'host': 'host2'}) instance_uuid = instance.uuid filter_properties = {'context': self.context.elevated(), 'scheduler_hints': None} self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_affinity_same_filter_handles_deleted_instance(self): filt_cls = self.class_map['SameHostFilter']() host = fakes.FakeHostState('host1', 'node1', {}) instance = fakes.FakeInstance(context=self.context, params={'host': 'host1'}) instance_uuid = instance.uuid db.instance_destroy(self.context, instance_uuid) filter_properties = {'context': self.context.elevated(), 'scheduler_hints': { 'same_host': [instance_uuid], }} self.assertFalse(filt_cls.host_passes(host, filter_properties)) def test_affinity_simple_cidr_filter_passes(self): filt_cls = self.class_map['SimpleCIDRAffinityFilter']() host = fakes.FakeHostState('host1', 'node1', {}) host.capabilities = {'host_ip': '10.8.1.1'} affinity_ip = "10.8.1.100" filter_properties = {'context': self.context.elevated(), 'scheduler_hints': { 'cidr': '/24', 'build_near_host_ip': affinity_ip}} self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_affinity_simple_cidr_filter_fails(self): filt_cls = self.class_map['SimpleCIDRAffinityFilter']() host = fakes.FakeHostState('host1', 'node1', {}) host.capabilities = {'host_ip': '10.8.1.1'} affinity_ip = "10.8.1.100" filter_properties = {'context': self.context.elevated(), 'scheduler_hints': { 'cidr': '/32', 'build_near_host_ip': affinity_ip}} self.assertFalse(filt_cls.host_passes(host, filter_properties)) def test_affinity_simple_cidr_filter_handles_none(self): filt_cls = self.class_map['SimpleCIDRAffinityFilter']() host = fakes.FakeHostState('host1', 'node1', {}) affinity_ip = CONF.my_ip.split('.')[0:3] affinity_ip.append('100') affinity_ip = str.join('.', affinity_ip) filter_properties = {'context': self.context.elevated(), 'scheduler_hints': None} self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_compute_filter_passes(self): self._stub_service_is_up(True) filt_cls = self.class_map['ComputeFilter']() filter_properties = {'instance_type': {'memory_mb': 1024}} capabilities = {'enabled': True} service = {'disabled': False} host = fakes.FakeHostState('host1', 'node1', {'free_ram_mb': 1024, 'capabilities': capabilities, 'service': service}) self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_type_filter(self): self._stub_service_is_up(True) filt_cls = self.class_map['TypeAffinityFilter']() filter_properties = {'context': self.context, 'instance_type': {'id': 1}} filter2_properties = {'context': self.context, 'instance_type': {'id': 2}} capabilities = {'enabled': True} service = {'disabled': False} host = fakes.FakeHostState('fake_host', 'fake_node', {'capabilities': capabilities, 'service': service}) #True since empty self.assertTrue(filt_cls.host_passes(host, filter_properties)) fakes.FakeInstance(context=self.context, params={'host': 'fake_host', 'instance_type_id': 1}) #True since same type self.assertTrue(filt_cls.host_passes(host, filter_properties)) #False since different type self.assertFalse(filt_cls.host_passes(host, filter2_properties)) #False since node not homogeneous fakes.FakeInstance(context=self.context, params={'host': 'fake_host', 'instance_type_id': 2}) self.assertFalse(filt_cls.host_passes(host, filter_properties)) def test_aggregate_type_filter(self): self._stub_service_is_up(True) filt_cls = self.class_map['AggregateTypeAffinityFilter']() filter_properties = {'context': self.context, 'instance_type': {'name': 'fake1'}} filter2_properties = {'context': self.context, 'instance_type': {'name': 'fake2'}} capabilities = {'enabled': True} service = {'disabled': False} host = fakes.FakeHostState('fake_host', 'fake_node', {'capabilities': capabilities, 'service': service}) #True since no aggregates self.assertTrue(filt_cls.host_passes(host, filter_properties)) #True since type matches aggregate, metadata self._create_aggregate_with_host(name='fake_aggregate', hosts=['fake_host'], metadata={'instance_type': 'fake1'}) self.assertTrue(filt_cls.host_passes(host, filter_properties)) #False since type matches aggregate, metadata self.assertFalse(filt_cls.host_passes(host, filter2_properties)) def test_ram_filter_fails_on_memory(self): self._stub_service_is_up(True) filt_cls = self.class_map['RamFilter']() self.flags(ram_allocation_ratio=1.0) filter_properties = {'instance_type': {'memory_mb': 1024}} capabilities = {'enabled': True} service = {'disabled': False} host = fakes.FakeHostState('host1', 'node1', {'free_ram_mb': 1023, 'total_usable_ram_mb': 1024, 'capabilities': capabilities, 'service': service}) self.assertFalse(filt_cls.host_passes(host, filter_properties)) def test_ram_filter_passes(self): self._stub_service_is_up(True) filt_cls = self.class_map['RamFilter']() self.flags(ram_allocation_ratio=1.0) filter_properties = {'instance_type': {'memory_mb': 1024}} capabilities = {'enabled': True} service = {'disabled': False} host = fakes.FakeHostState('host1', 'node1', {'free_ram_mb': 1024, 'total_usable_ram_mb': 1024, 'capabilities': capabilities, 'service': service}) self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_ram_filter_oversubscribe(self): self._stub_service_is_up(True) filt_cls = self.class_map['RamFilter']() self.flags(ram_allocation_ratio=2.0) filter_properties = {'instance_type': {'memory_mb': 1024}} capabilities = {'enabled': True} service = {'disabled': False} host = fakes.FakeHostState('host1', 'node1', {'free_ram_mb': -1024, 'total_usable_ram_mb': 2048, 'capabilities': capabilities, 'service': service}) self.assertTrue(filt_cls.host_passes(host, filter_properties)) self.assertEqual(2048 * 2.0, host.limits['memory_mb']) def test_disk_filter_passes(self): self._stub_service_is_up(True) filt_cls = self.class_map['DiskFilter']() self.flags(disk_allocation_ratio=1.0) filter_properties = {'instance_type': {'root_gb': 1, 'ephemeral_gb': 1}} capabilities = {'enabled': True} service = {'disabled': False} host = fakes.FakeHostState('host1', 'node1', {'free_disk_mb': 11 * 1024, 'total_usable_disk_gb': 13, 'capabilities': capabilities, 'service': service}) self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_disk_filter_fails(self): self._stub_service_is_up(True) filt_cls = self.class_map['DiskFilter']() self.flags(disk_allocation_ratio=1.0) filter_properties = {'instance_type': {'root_gb': 11, 'ephemeral_gb': 1}} capabilities = {'enabled': True} service = {'disabled': False} host = fakes.FakeHostState('host1', 'node1', {'free_disk_mb': 11 * 1024, 'total_usable_disk_gb': 13, 'capabilities': capabilities, 'service': service}) self.assertFalse(filt_cls.host_passes(host, filter_properties)) def test_disk_filter_oversubscribe(self): self._stub_service_is_up(True) filt_cls = self.class_map['DiskFilter']() self.flags(disk_allocation_ratio=10.0) filter_properties = {'instance_type': {'root_gb': 100, 'ephemeral_gb': 19}} capabilities = {'enabled': True} service = {'disabled': False} # 1GB used... so 119GB allowed... host = fakes.FakeHostState('host1', 'node1', {'free_disk_mb': 11 * 1024, 'total_usable_disk_gb': 12, 'capabilities': capabilities, 'service': service}) self.assertTrue(filt_cls.host_passes(host, filter_properties)) self.assertEqual(12 * 10.0, host.limits['disk_gb']) def test_disk_filter_oversubscribe_fail(self): self._stub_service_is_up(True) filt_cls = self.class_map['DiskFilter']() self.flags(disk_allocation_ratio=10.0) filter_properties = {'instance_type': {'root_gb': 100, 'ephemeral_gb': 20}} capabilities = {'enabled': True} service = {'disabled': False} # 1GB used... so 119GB allowed... host = fakes.FakeHostState('host1', 'node1', {'free_disk_mb': 11 * 1024, 'total_usable_disk_gb': 12, 'capabilities': capabilities, 'service': service}) self.assertFalse(filt_cls.host_passes(host, filter_properties)) def test_compute_filter_fails_on_service_disabled(self): self._stub_service_is_up(True) filt_cls = self.class_map['ComputeFilter']() filter_properties = {'instance_type': {'memory_mb': 1024}} capabilities = {'enabled': True} service = {'disabled': True} host = fakes.FakeHostState('host1', 'node1', {'free_ram_mb': 1024, 'capabilities': capabilities, 'service': service}) self.assertFalse(filt_cls.host_passes(host, filter_properties)) def test_compute_filter_fails_on_service_down(self): self._stub_service_is_up(False) filt_cls = self.class_map['ComputeFilter']() filter_properties = {'instance_type': {'memory_mb': 1024}} capabilities = {'enabled': True} service = {'disabled': False} host = fakes.FakeHostState('host1', 'node1', {'free_ram_mb': 1024, 'capabilities': capabilities, 'service': service}) self.assertFalse(filt_cls.host_passes(host, filter_properties)) def test_compute_filter_fails_on_capability_disabled(self): self._stub_service_is_up(True) filt_cls = self.class_map['ComputeFilter']() filter_properties = {'instance_type': {'memory_mb': 1024}} capabilities = {'enabled': False} service = {'disabled': False} host = fakes.FakeHostState('host1', 'node1', {'free_ram_mb': 1024, 'capabilities': capabilities, 'service': service}) self.assertFalse(filt_cls.host_passes(host, filter_properties)) def test_image_properties_filter_passes_same_inst_props(self): self._stub_service_is_up(True) 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')]} host = fakes.FakeHostState('host1', 'node1', {'capabilities': capabilities}) self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_image_properties_filter_fails_different_inst_props(self): self._stub_service_is_up(True) 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')]} host = fakes.FakeHostState('host1', 'node1', {'capabilities': capabilities}) self.assertFalse(filt_cls.host_passes(host, filter_properties)) def test_image_properties_filter_passes_partial_inst_props(self): self._stub_service_is_up(True) 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')]} host = fakes.FakeHostState('host1', 'node1', {'capabilities': capabilities}) self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_image_properties_filter_fails_partial_inst_props(self): self._stub_service_is_up(True) 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')]} host = fakes.FakeHostState('host1', 'node1', {'capabilities': capabilities}) self.assertFalse(filt_cls.host_passes(host, filter_properties)) def test_image_properties_filter_passes_without_inst_props(self): self._stub_service_is_up(True) filt_cls = self.class_map['ImagePropertiesFilter']() filter_properties = {'request_spec': {}} capabilities = {'enabled': True, 'supported_instances': [ ('x86_64', 'kvm', 'hvm')]} host = fakes.FakeHostState('host1', 'node1', {'capabilities': capabilities}) self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_image_properties_filter_fails_without_host_props(self): self._stub_service_is_up(True) 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} host = fakes.FakeHostState('host1', 'node1', {'capabilities': capabilities}) self.assertFalse(filt_cls.host_passes(host, filter_properties)) def _do_test_compute_filter_extra_specs(self, ecaps, especs, passes): self._stub_service_is_up(True) filt_cls = self.class_map['ComputeCapabilitiesFilter']() capabilities = {'enabled': True} capabilities.update(ecaps) service = {'disabled': False} filter_properties = {'instance_type': {'memory_mb': 1024, 'extra_specs': especs}} host = fakes.FakeHostState('host1', 'node1', {'free_ram_mb': 1024, 'capabilities': capabilities, 'service': service}) assertion = self.assertTrue if passes else self.assertFalse assertion(filt_cls.host_passes(host, filter_properties)) def test_compute_filter_passes_extra_specs_simple(self): self._do_test_compute_filter_extra_specs( ecaps={'opt1': '1', 'opt2': '2'}, especs={'opt1': '1', 'opt2': '2', 'trust:trusted_host': 'true'}, passes=True) def test_compute_filter_fails_extra_specs_simple(self): self._do_test_compute_filter_extra_specs( ecaps={'opt1': '1', 'opt2': '2'}, especs={'opt1': '1', 'opt2': '222', 'trust:trusted_host': 'true'}, passes=False) def test_compute_filter_pass_extra_specs_simple_with_scope(self): self._do_test_compute_filter_extra_specs( ecaps={'opt1': '1', 'opt2': '2'}, especs={'capabilities:opt1': '1', 'trust:trusted_host': 'true'}, passes=True) def test_compute_filter_extra_specs_simple_with_wrong_scope(self): self._do_test_compute_filter_extra_specs( ecaps={'opt1': '1', 'opt2': '2'}, especs={'wrong_scope:opt1': '1', 'trust:trusted_host': 'true'}, passes=True) def test_compute_filter_extra_specs_pass_multi_level_with_scope(self): self._do_test_compute_filter_extra_specs( ecaps={'opt1': {'a': '1', 'b': {'aa': '2'}}, 'opt2': '2'}, especs={'opt1:a': '1', 'capabilities:opt1:b:aa': '2', 'trust:trusted_host': 'true'}, passes=True) def test_aggregate_filter_passes_no_extra_specs(self): self._stub_service_is_up(True) filt_cls = self.class_map['AggregateInstanceExtraSpecsFilter']() capabilities = {'enabled': True, 'opt1': 1, 'opt2': 2} filter_properties = {'context': self.context, 'instance_type': {'memory_mb': 1024}} host = fakes.FakeHostState('host1', 'node1', {'capabilities': capabilities}) self.assertTrue(filt_cls.host_passes(host, filter_properties)) def _create_aggregate_with_host(self, name='fake_aggregate', metadata=None, hosts=['host1']): values = {'name': name} if metadata: metadata['availability_zone'] = 'fake_avail_zone' else: metadata = {'availability_zone': 'fake_avail_zone'} result = db.aggregate_create(self.context.elevated(), values, metadata) for host in hosts: db.aggregate_host_add(self.context.elevated(), result['id'], host) return result def _do_test_aggregate_filter_extra_specs(self, emeta, especs, passes): self._stub_service_is_up(True) filt_cls = self.class_map['AggregateInstanceExtraSpecsFilter']() self._create_aggregate_with_host(name='fake2', metadata=emeta) filter_properties = {'context': self.context, 'instance_type': {'memory_mb': 1024, 'extra_specs': especs}} host = fakes.FakeHostState('host1', 'node1', {'free_ram_mb': 1024}) assertion = self.assertTrue if passes else self.assertFalse assertion(filt_cls.host_passes(host, filter_properties)) def test_aggregate_filter_fails_extra_specs_deleted_host(self): self._stub_service_is_up(True) filt_cls = self.class_map['AggregateInstanceExtraSpecsFilter']() extra_specs = {'opt1': 's== 1', 'opt2': 's== 2', 'trust:trusted_host': 'true'} self._create_aggregate_with_host(metadata={'opt1': '1'}) agg2 = self._create_aggregate_with_host(name='fake2', metadata={'opt2': '2'}) filter_properties = {'context': self.context, 'instance_type': {'memory_mb': 1024, 'extra_specs': extra_specs}} host = fakes.FakeHostState('host1', 'node1', {'free_ram_mb': 1024}) db.aggregate_host_delete(self.context.elevated(), agg2['id'], 'host1') self.assertFalse(filt_cls.host_passes(host, filter_properties)) def test_aggregate_filter_passes_extra_specs_simple(self): self._do_test_aggregate_filter_extra_specs( emeta={'opt1': '1', 'opt2': '2'}, especs={'opt1': '1', 'opt2': '2', 'trust:trusted_host': 'true'}, passes=True) def test_aggregate_filter_fails_extra_specs_simple(self): self._do_test_aggregate_filter_extra_specs( emeta={'opt1': '1', 'opt2': '2'}, especs={'opt1': '1', 'opt2': '222', 'trust:trusted_host': 'true'}, passes=False) def _do_test_isolated_hosts(self, host_in_list, image_in_list, set_flags=True): if set_flags: self.flags(isolated_images=['isolated_image'], isolated_hosts=['isolated_host']) host_name = 'isolated_host' if host_in_list else 'free_host' image_ref = 'isolated_image' if image_in_list else 'free_image' filter_properties = { 'request_spec': { 'instance_properties': {'image_ref': image_ref} } } filt_cls = self.class_map['IsolatedHostsFilter']() host = fakes.FakeHostState(host_name, 'node', {}) return filt_cls.host_passes(host, filter_properties) def test_isolated_hosts_fails_isolated_on_non_isolated(self): self.assertFalse(self._do_test_isolated_hosts(False, True)) def test_isolated_hosts_fails_non_isolated_on_isolated(self): self.assertFalse(self._do_test_isolated_hosts(True, False)) def test_isolated_hosts_passes_isolated_on_isolated(self): self.assertTrue(self._do_test_isolated_hosts(True, True)) def test_isolated_hosts_passes_non_isolated_on_non_isolated(self): self.assertTrue(self._do_test_isolated_hosts(False, False)) def test_isolated_hosts_no_config(self): # If there are no hosts nor isolated images in the config, it should # not filter at all. This is the default config. self.assertTrue(self._do_test_isolated_hosts(False, True, False)) self.assertTrue(self._do_test_isolated_hosts(True, False, False)) self.assertTrue(self._do_test_isolated_hosts(True, True, False)) self.assertTrue(self._do_test_isolated_hosts(False, False, False)) def test_isolated_hosts_no_hosts_config(self): self.flags(isolated_images=['isolated_image']) # If there are no hosts in the config, it should only filter out # images that are listed self.assertFalse(self._do_test_isolated_hosts(False, True, False)) self.assertTrue(self._do_test_isolated_hosts(True, False, False)) self.assertFalse(self._do_test_isolated_hosts(True, True, False)) self.assertTrue(self._do_test_isolated_hosts(False, False, False)) def test_isolated_hosts_no_images_config(self): self.flags(isolated_hosts=['isolated_host']) # If there are no images in the config, it should only filter out # isolated_hosts self.assertTrue(self._do_test_isolated_hosts(False, True, False)) self.assertFalse(self._do_test_isolated_hosts(True, False, False)) self.assertFalse(self._do_test_isolated_hosts(True, True, False)) self.assertTrue(self._do_test_isolated_hosts(False, False, False)) def test_json_filter_passes(self): filt_cls = self.class_map['JsonFilter']() filter_properties = {'instance_type': {'memory_mb': 1024, 'root_gb': 200, 'ephemeral_gb': 0}, 'scheduler_hints': {'query': self.json_query}} capabilities = {'enabled': True} host = fakes.FakeHostState('host1', 'node1', {'free_ram_mb': 1024, 'free_disk_mb': 200 * 1024, 'capabilities': capabilities}) self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_json_filter_passes_with_no_query(self): filt_cls = self.class_map['JsonFilter']() filter_properties = {'instance_type': {'memory_mb': 1024, 'root_gb': 200, 'ephemeral_gb': 0}} capabilities = {'enabled': True} host = fakes.FakeHostState('host1', 'node1', {'free_ram_mb': 0, 'free_disk_mb': 0, 'capabilities': capabilities}) self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_json_filter_fails_on_memory(self): filt_cls = self.class_map['JsonFilter']() filter_properties = {'instance_type': {'memory_mb': 1024, 'root_gb': 200, 'ephemeral_gb': 0}, 'scheduler_hints': {'query': self.json_query}} capabilities = {'enabled': True} host = fakes.FakeHostState('host1', 'node1', {'free_ram_mb': 1023, 'free_disk_mb': 200 * 1024, 'capabilities': capabilities}) self.assertFalse(filt_cls.host_passes(host, filter_properties)) def test_json_filter_fails_on_disk(self): filt_cls = self.class_map['JsonFilter']() filter_properties = {'instance_type': {'memory_mb': 1024, 'root_gb': 200, 'ephemeral_gb': 0}, 'scheduler_hints': {'query': self.json_query}} capabilities = {'enabled': True} host = fakes.FakeHostState('host1', 'node1', {'free_ram_mb': 1024, 'free_disk_mb': (200 * 1024) - 1, 'capabilities': capabilities}) self.assertFalse(filt_cls.host_passes(host, filter_properties)) def test_json_filter_fails_on_caps_disabled(self): filt_cls = self.class_map['JsonFilter']() json_query = jsonutils.dumps( ['and', ['>=', '$free_ram_mb', 1024], ['>=', '$free_disk_mb', 200 * 1024], '$capabilities.enabled']) filter_properties = {'instance_type': {'memory_mb': 1024, 'root_gb': 200, 'ephemeral_gb': 0}, 'scheduler_hints': {'query': json_query}} capabilities = {'enabled': False} host = fakes.FakeHostState('host1', 'node1', {'free_ram_mb': 1024, 'free_disk_mb': 200 * 1024, 'capabilities': capabilities}) self.assertFalse(filt_cls.host_passes(host, filter_properties)) def test_json_filter_fails_on_service_disabled(self): filt_cls = self.class_map['JsonFilter']() json_query = jsonutils.dumps( ['and', ['>=', '$free_ram_mb', 1024], ['>=', '$free_disk_mb', 200 * 1024], ['not', '$service.disabled']]) filter_properties = {'instance_type': {'memory_mb': 1024, 'local_gb': 200}, 'scheduler_hints': {'query': json_query}} capabilities = {'enabled': True} service = {'disabled': True} host = fakes.FakeHostState('host1', 'node1', {'free_ram_mb': 1024, 'free_disk_mb': 200 * 1024, 'capabilities': capabilities}) self.assertFalse(filt_cls.host_passes(host, filter_properties)) def test_json_filter_happy_day(self): # Test json filter more thoroughly. filt_cls = self.class_map['JsonFilter']() raw = ['and', '$capabilities.enabled', ['=', '$capabilities.opt1', 'match'], ['or', ['and', ['<', '$free_ram_mb', 30], ['<', '$free_disk_mb', 300]], ['and', ['>', '$free_ram_mb', 30], ['>', '$free_disk_mb', 300]]]] filter_properties = { 'scheduler_hints': { 'query': jsonutils.dumps(raw), }, } # Passes capabilities = {'enabled': True, 'opt1': 'match'} service = {'disabled': False} host = fakes.FakeHostState('host1', 'node1', {'free_ram_mb': 10, 'free_disk_mb': 200, 'capabilities': capabilities, 'service': service}) self.assertTrue(filt_cls.host_passes(host, filter_properties)) # Passes capabilities = {'enabled': True, 'opt1': 'match'} service = {'disabled': False} host = fakes.FakeHostState('host1', 'node1', {'free_ram_mb': 40, 'free_disk_mb': 400, 'capabilities': capabilities, 'service': service}) self.assertTrue(filt_cls.host_passes(host, filter_properties)) # Fails due to capabilities being disabled capabilities = {'enabled': False, 'opt1': 'match'} service = {'disabled': False} host = fakes.FakeHostState('host1', 'node1', {'free_ram_mb': 40, 'free_disk_mb': 400, 'capabilities': capabilities, 'service': service}) self.assertFalse(filt_cls.host_passes(host, filter_properties)) # Fails due to being exact memory/disk we don't want capabilities = {'enabled': True, 'opt1': 'match'} service = {'disabled': False} host = fakes.FakeHostState('host1', 'node1', {'free_ram_mb': 30, 'free_disk_mb': 300, 'capabilities': capabilities, 'service': service}) self.assertFalse(filt_cls.host_passes(host, filter_properties)) # Fails due to memory lower but disk higher capabilities = {'enabled': True, 'opt1': 'match'} service = {'disabled': False} host = fakes.FakeHostState('host1', 'node1', {'free_ram_mb': 20, 'free_disk_mb': 400, 'capabilities': capabilities, 'service': service}) self.assertFalse(filt_cls.host_passes(host, filter_properties)) # Fails due to capabilities 'opt1' not equal capabilities = {'enabled': True, 'opt1': 'no-match'} service = {'enabled': True} host = fakes.FakeHostState('host1', 'node1', {'free_ram_mb': 20, 'free_disk_mb': 400, 'capabilities': capabilities, 'service': service}) self.assertFalse(filt_cls.host_passes(host, filter_properties)) def test_json_filter_basic_operators(self): filt_cls = self.class_map['JsonFilter']() host = fakes.FakeHostState('host1', 'node1', {'capabilities': {'enabled': True}}) # (operator, arguments, expected_result) ops_to_test = [ ['=', [1, 1], True], ['=', [1, 2], False], ['<', [1, 2], True], ['<', [1, 1], False], ['<', [2, 1], False], ['>', [2, 1], True], ['>', [2, 2], False], ['>', [2, 3], False], ['<=', [1, 2], True], ['<=', [1, 1], True], ['<=', [2, 1], False], ['>=', [2, 1], True], ['>=', [2, 2], True], ['>=', [2, 3], False], ['in', [1, 1], True], ['in', [1, 1, 2, 3], True], ['in', [4, 1, 2, 3], False], ['not', [True], False], ['not', [False], True], ['or', [True, False], True], ['or', [False, False], False], ['and', [True, True], True], ['and', [False, False], False], ['and', [True, False], False], # Nested ((True or False) and (2 > 1)) == Passes ['and', [['or', True, False], ['>', 2, 1]], True]] for (op, args, expected) in ops_to_test: raw = [op] + args filter_properties = { 'scheduler_hints': { 'query': jsonutils.dumps(raw), }, } self.assertEqual(expected, filt_cls.host_passes(host, filter_properties)) # This results in [False, True, False, True] and if any are True # then it passes... raw = ['not', True, False, True, False] filter_properties = { 'scheduler_hints': { 'query': jsonutils.dumps(raw), }, } self.assertTrue(filt_cls.host_passes(host, filter_properties)) # This results in [False, False, False] and if any are True # then it passes...which this doesn't raw = ['not', True, True, True] filter_properties = { 'scheduler_hints': { 'query': jsonutils.dumps(raw), }, } self.assertFalse(filt_cls.host_passes(host, filter_properties)) def test_json_filter_unknown_operator_raises(self): filt_cls = self.class_map['JsonFilter']() raw = ['!=', 1, 2] filter_properties = { 'scheduler_hints': { 'query': jsonutils.dumps(raw), }, } host = fakes.FakeHostState('host1', 'node1', {'capabilities': {'enabled': True}}) self.assertRaises(KeyError, filt_cls.host_passes, host, filter_properties) def test_json_filter_empty_filters_pass(self): filt_cls = self.class_map['JsonFilter']() host = fakes.FakeHostState('host1', 'node1', {'capabilities': {'enabled': True}}) raw = [] filter_properties = { 'scheduler_hints': { 'query': jsonutils.dumps(raw), }, } self.assertTrue(filt_cls.host_passes(host, filter_properties)) raw = {} filter_properties = { 'scheduler_hints': { 'query': jsonutils.dumps(raw), }, } self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_json_filter_invalid_num_arguments_fails(self): filt_cls = self.class_map['JsonFilter']() host = fakes.FakeHostState('host1', 'node1', {'capabilities': {'enabled': True}}) raw = ['>', ['and', ['or', ['not', ['<', ['>=', ['<=', ['in', ]]]]]]]] filter_properties = { 'scheduler_hints': { 'query': jsonutils.dumps(raw), }, } self.assertFalse(filt_cls.host_passes(host, filter_properties)) raw = ['>', 1] filter_properties = { 'scheduler_hints': { 'query': jsonutils.dumps(raw), }, } self.assertFalse(filt_cls.host_passes(host, filter_properties)) def test_json_filter_unknown_variable_ignored(self): filt_cls = self.class_map['JsonFilter']() host = fakes.FakeHostState('host1', 'node1', {'capabilities': {'enabled': True}}) raw = ['=', '$........', 1, 1] filter_properties = { 'scheduler_hints': { 'query': jsonutils.dumps(raw), }, } self.assertTrue(filt_cls.host_passes(host, filter_properties)) raw = ['=', '$foo', 2, 2] filter_properties = { 'scheduler_hints': { 'query': jsonutils.dumps(raw), }, } self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_trusted_filter_default_passes(self): self._stub_service_is_up(True) filt_cls = self.class_map['TrustedFilter']() filter_properties = {'context': self.context.elevated(), 'instance_type': {'memory_mb': 1024}} host = fakes.FakeHostState('host1', 'node1', {}) self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_trusted_filter_trusted_and_trusted_passes(self): self.oat_data = {"hosts": [{"host_name": "host1", "trust_lvl": "trusted", "vtime": timeutils.isotime()}]} self._stub_service_is_up(True) filt_cls = self.class_map['TrustedFilter']() extra_specs = {'trust:trusted_host': 'trusted'} filter_properties = {'context': self.context.elevated(), 'instance_type': {'memory_mb': 1024, 'extra_specs': extra_specs}} host = fakes.FakeHostState('host1', 'node1', {}) self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_trusted_filter_trusted_and_untrusted_fails(self): self.oat_data = {"hosts": [{"host_name": "host1", "trust_lvl": "untrusted", "vtime": timeutils.isotime()}]} self._stub_service_is_up(True) filt_cls = self.class_map['TrustedFilter']() extra_specs = {'trust:trusted_host': 'trusted'} filter_properties = {'context': self.context.elevated(), 'instance_type': {'memory_mb': 1024, 'extra_specs': extra_specs}} host = fakes.FakeHostState('host1', 'node1', {}) self.assertFalse(filt_cls.host_passes(host, filter_properties)) def test_trusted_filter_untrusted_and_trusted_fails(self): self.oat_data = {"hosts": [{"host_name": "host1", "trust_lvl": "trusted", "vtime": timeutils.isotime()}]} self._stub_service_is_up(True) filt_cls = self.class_map['TrustedFilter']() extra_specs = {'trust:trusted_host': 'untrusted'} filter_properties = {'context': self.context.elevated(), 'instance_type': {'memory_mb': 1024, 'extra_specs': extra_specs}} host = fakes.FakeHostState('host1', 'node1', {}) self.assertFalse(filt_cls.host_passes(host, filter_properties)) def test_trusted_filter_untrusted_and_untrusted_passes(self): self.oat_data = {"hosts": [{"host_name": "host1", "trust_lvl": "untrusted", "vtime": timeutils.isotime()}]} self._stub_service_is_up(True) filt_cls = self.class_map['TrustedFilter']() extra_specs = {'trust:trusted_host': 'untrusted'} filter_properties = {'context': self.context.elevated(), 'instance_type': {'memory_mb': 1024, 'extra_specs': extra_specs}} host = fakes.FakeHostState('host1', 'node1', {}) self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_trusted_filter_update_cache(self): self.oat_data = {"hosts": [{"host_name": "host1", "trust_lvl": "untrusted", "vtime": timeutils.isotime()}]} filt_cls = self.class_map['TrustedFilter']() extra_specs = {'trust:trusted_host': 'untrusted'} filter_properties = {'context': self.context.elevated(), 'instance_type': {'memory_mb': 1024, 'extra_specs': extra_specs}} host = fakes.FakeHostState('host1', 'node1', {}) filt_cls.host_passes(host, filter_properties) # Fill the caches self.oat_attested = False filt_cls.host_passes(host, filter_properties) self.assertFalse(self.oat_attested) self.oat_attested = False timeutils.set_time_override(timeutils.utcnow()) timeutils.advance_time_seconds( CONF.trusted_computing.attestation_auth_timeout + 80) filt_cls.host_passes(host, filter_properties) self.assertTrue(self.oat_attested) timeutils.clear_time_override() def test_trusted_filter_update_cache_timezone(self): self.oat_data = {"hosts": [{"host_name": "host1", "trust_lvl": "untrusted", "vtime": "2012-09-09T05:10:40-04:00"}]} filt_cls = self.class_map['TrustedFilter']() extra_specs = {'trust:trusted_host': 'untrusted'} filter_properties = {'context': self.context.elevated(), 'instance_type': {'memory_mb': 1024, 'extra_specs': extra_specs}} host = fakes.FakeHostState('host1', 'node1', {}) timeutils.set_time_override( timeutils.normalize_time( timeutils.parse_isotime("2012-09-09T09:10:40Z"))) filt_cls.host_passes(host, filter_properties) # Fill the caches self.oat_attested = False filt_cls.host_passes(host, filter_properties) self.assertFalse(self.oat_attested) self.oat_attested = False timeutils.advance_time_seconds( CONF.trusted_computing.attestation_auth_timeout - 10) filt_cls.host_passes(host, filter_properties) self.assertFalse(self.oat_attested) timeutils.clear_time_override() def test_core_filter_passes(self): filt_cls = self.class_map['CoreFilter']() filter_properties = {'instance_type': {'vcpus': 1}} self.flags(cpu_allocation_ratio=2) host = fakes.FakeHostState('host1', 'node1', {'vcpus_total': 4, 'vcpus_used': 7}) self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_core_filter_fails_safe(self): filt_cls = self.class_map['CoreFilter']() filter_properties = {'instance_type': {'vcpus': 1}} host = fakes.FakeHostState('host1', 'node1', {}) self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_core_filter_fails(self): filt_cls = self.class_map['CoreFilter']() filter_properties = {'instance_type': {'vcpus': 1}} self.flags(cpu_allocation_ratio=2) host = fakes.FakeHostState('host1', 'node1', {'vcpus_total': 4, 'vcpus_used': 8}) self.assertFalse(filt_cls.host_passes(host, filter_properties)) @staticmethod def _make_zone_request(zone, is_admin=False): ctxt = context.RequestContext('fake', 'fake', is_admin=is_admin) return { 'context': ctxt, 'request_spec': { 'instance_properties': { 'availability_zone': zone } } } def test_availability_zone_filter_same(self): filt_cls = self.class_map['AvailabilityZoneFilter']() service = {'availability_zone': 'nova'} request = self._make_zone_request('nova') host = fakes.FakeHostState('host1', 'node1', {'service': service}) self.assertTrue(filt_cls.host_passes(host, request)) def test_availability_zone_filter_different(self): filt_cls = self.class_map['AvailabilityZoneFilter']() service = {'availability_zone': 'nova'} request = self._make_zone_request('bad') host = fakes.FakeHostState('host1', 'node1', {'service': service}) self.assertFalse(filt_cls.host_passes(host, request)) def test_retry_filter_disabled(self): # Test case where retry/re-scheduling is disabled. filt_cls = self.class_map['RetryFilter']() host = fakes.FakeHostState('host1', 'node1', {}) filter_properties = {} self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_retry_filter_pass(self): # Node not previously tried. filt_cls = self.class_map['RetryFilter']() host = fakes.FakeHostState('host1', 'nodeX', {}) retry = dict(num_attempts=2, hosts=[['host1', 'node1'], # same host, different node ['host2', 'node2'], # different host and node ]) filter_properties = dict(retry=retry) self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_retry_filter_fail(self): # Node was already tried. filt_cls = self.class_map['RetryFilter']() host = fakes.FakeHostState('host1', 'node1', {}) retry = dict(num_attempts=1, hosts=[['host1', 'node1']]) filter_properties = dict(retry=retry) self.assertFalse(filt_cls.host_passes(host, filter_properties)) def test_filter_num_iops_passes(self): self.flags(max_io_ops_per_host=8) filt_cls = self.class_map['IoOpsFilter']() host = fakes.FakeHostState('host1', 'node1', {'num_io_ops': 7}) filter_properties = {} self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_filter_num_iops_fails(self): self.flags(max_io_ops_per_host=8) filt_cls = self.class_map['IoOpsFilter']() host = fakes.FakeHostState('host1', 'node1', {'num_io_ops': 8}) def test_filter_num_instances_passes(self): self.flags(max_instances_per_host=5) filt_cls = self.class_map['NumInstancesFilter']() host = fakes.FakeHostState('host1', 'node1', {'num_instances': 4}) filter_properties = {} self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_filter_num_instances_fails(self): self.flags(max_instances_per_host=5) filt_cls = self.class_map['NumInstancesFilter']() host = fakes.FakeHostState('host1', 'node1', {'num_instances': 5}) filter_properties = {} self.assertFalse(filt_cls.host_passes(host, filter_properties)) def test_group_anti_affinity_filter_passes(self): filt_cls = self.class_map['GroupAntiAffinityFilter']() host = fakes.FakeHostState('host1', 'node1', {}) filter_properties = {'group_hosts': []} self.assertTrue(filt_cls.host_passes(host, filter_properties)) filter_properties = {'group_hosts': ['host2']} self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_group_anti_affinity_filter_fails(self): filt_cls = self.class_map['GroupAntiAffinityFilter']() host = fakes.FakeHostState('host1', 'node1', {}) filter_properties = {'group_hosts': ['host1']} self.assertFalse(filt_cls.host_passes(host, filter_properties)) def test_aggregate_multi_tenancy_isolation_with_meta_passes(self): self._stub_service_is_up(True) filt_cls = self.class_map['AggregateMultiTenancyIsolation']() aggr_meta = {'filter_tenant_id': 'my_tenantid'} self._create_aggregate_with_host(name='fake1', metadata=aggr_meta, hosts=['host1']) filter_properties = {'context': self.context, 'request_spec': { 'instance_properties': { 'project_id': 'my_tenantid'}}} host = fakes.FakeHostState('host1', 'compute', {}) self.assertTrue(filt_cls.host_passes(host, filter_properties)) def test_aggregate_multi_tenancy_isolation_fails(self): self._stub_service_is_up(True) filt_cls = self.class_map['AggregateMultiTenancyIsolation']() aggr_meta = {'filter_tenant_id': 'other_tenantid'} self._create_aggregate_with_host(name='fake1', metadata=aggr_meta, hosts=['host1']) filter_properties = {'context': self.context, 'request_spec': { 'instance_properties': { 'project_id': 'my_tenantid'}}} host = fakes.FakeHostState('host1', 'compute', {}) self.assertFalse(filt_cls.host_passes(host, filter_properties)) def test_aggregate_multi_tenancy_isolation_no_meta_passes(self): self._stub_service_is_up(True) filt_cls = self.class_map['AggregateMultiTenancyIsolation']() aggr_meta = {} self._create_aggregate_with_host(name='fake1', metadata=aggr_meta, hosts=['host1']) filter_properties = {'context': self.context, 'request_spec': { 'instance_properties': { 'project_id': 'my_tenantid'}}} host = fakes.FakeHostState('host1', 'compute', {}) self.assertTrue(filt_cls.host_passes(host, filter_properties))