diff options
| author | Jenkins <jenkins@review.openstack.org> | 2012-08-15 12:54:50 +0000 |
|---|---|---|
| committer | Gerrit Code Review <review@openstack.org> | 2012-08-15 12:54:50 +0000 |
| commit | 1ef3607239c4bce8a276e420f2b70137b1a1fe2f (patch) | |
| tree | cef87ca4447c9922ff6e0b9ab8d251083e7a63d4 | |
| parent | ca950e7ea3909110fe05e3239975b7545423670a (diff) | |
| parent | 90f77d71fe5815f08fe12e77e7645c6025ee0191 (diff) | |
| download | nova-1ef3607239c4bce8a276e420f2b70137b1a1fe2f.tar.gz nova-1ef3607239c4bce8a276e420f2b70137b1a1fe2f.tar.xz nova-1ef3607239c4bce8a276e420f2b70137b1a1fe2f.zip | |
Merge "Added several operators on instance_type_extra_specs."
| -rw-r--r-- | nova/scheduler/filters/compute_capabilities_filter.py | 46 | ||||
| -rw-r--r-- | nova/tests/scheduler/test_host_filters.py | 384 |
2 files changed, 419 insertions, 11 deletions
diff --git a/nova/scheduler/filters/compute_capabilities_filter.py b/nova/scheduler/filters/compute_capabilities_filter.py index 691b8f910..3d67ccf54 100644 --- a/nova/scheduler/filters/compute_capabilities_filter.py +++ b/nova/scheduler/filters/compute_capabilities_filter.py @@ -12,6 +12,7 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. +import operator from nova.openstack.common import log as logging from nova.scheduler import filters @@ -29,12 +30,45 @@ class ComputeCapabilitiesFilter(filters.BaseHostFilter): if 'extra_specs' not in instance_type: return True - # NOTE(lorinh): For now, we are just checking exact matching on the - # values. Later on, we want to handle numerical - # values so we can represent things like number of GPU cards - for key, value in instance_type['extra_specs'].iteritems(): - if capabilities.get(key, None) != value: - return False + # 1. The following operations are supported: + # =, s==, s!=, s>=, s>, s<=, s<, <in>, <or>, ==, !=, >=, <= + # 2. Note that <or> is handled in a different way below. + # 3. If the first word in the capability is not one of the operators, + # it is ignored. + op_methods = {'=': lambda x, y: float(x) >= float(y), + '<in>': lambda x, y: y in x, + '==': lambda x, y: float(x) == float(y), + '!=': lambda x, y: float(x) != float(y), + '>=': lambda x, y: float(x) >= float(y), + '<=': lambda x, y: float(x) <= float(y), + 's==': operator.eq, + 's!=': operator.ne, + 's<': operator.lt, + 's<=': operator.le, + 's>': operator.gt, + 's>=': operator.ge} + + for key, req in instance_type['extra_specs'].iteritems(): + words = req.split() + if words: + op = words[0] + method = op_methods.get(op) + + if (op == '<or>' or method): + cap = capabilities.get(key, None) + if cap is None: + return False + if op == '<or>': # Ex: <or> v1 <or> v2 <or> v3 + for idx in range(1, len(words), 2): + if words[idx] == cap: + break + else: + return False + else: # method + if len(words) == 1: + return False + if not method(cap, words[1]): + return False return True def host_passes(self, host_state, filter_properties): diff --git a/nova/tests/scheduler/test_host_filters.py b/nova/tests/scheduler/test_host_filters.py index 57827ac19..ca5ca5366 100644 --- a/nova/tests/scheduler/test_host_filters.py +++ b/nova/tests/scheduler/test_host_filters.py @@ -394,11 +394,11 @@ class HostFiltersTestCase(test.TestCase): 'service': service}) self.assertTrue(filt_cls.host_passes(host, filter_properties)) - def test_compute_filter_passes_extra_specs(self): + def test_compute_filter_passes_extra_specs_noop(self): self._stub_service_is_up(True) filt_cls = self.class_map['ComputeCapabilitiesFilter']() - extra_specs = {'opt1': 1, 'opt2': 2} - capabilities = {'enabled': True, 'opt1': 1, 'opt2': 2} + extra_specs = {'opt1': '1111', 'opt2': '222'} + capabilities = {'enabled': True, 'opt1': '1', 'opt2': '2'} service = {'disabled': False} filter_properties = {'instance_type': {'memory_mb': 1024, 'extra_specs': extra_specs}} @@ -407,10 +407,384 @@ class HostFiltersTestCase(test.TestCase): 'service': service}) self.assertTrue(filt_cls.host_passes(host, filter_properties)) - def test_compute_filter_fails_extra_specs(self): + def test_compute_filter_passes_extra_specs_noop2(self): self._stub_service_is_up(True) filt_cls = self.class_map['ComputeCapabilitiesFilter']() - extra_specs = {'opt1': 1, 'opt2': 3} + extra_specs = {'opt1': '1111', 'opt2': '222'} + capabilities = {'enabled': True, 'opt3': '1', 'opt4': '2'} + service = {'disabled': False} + filter_properties = {'instance_type': {'memory_mb': 1024, + 'extra_specs': extra_specs}} + 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_passes_extra_specs_noop3(self): + self._stub_service_is_up(True) + filt_cls = self.class_map['ComputeCapabilitiesFilter']() + extra_specs = {'opt1': '', 'opt2': ''} + capabilities = {'enabled': True, 'opt1': '1', 'opt2': '2'} + service = {'disabled': False} + filter_properties = {'instance_type': {'memory_mb': 1024, + 'extra_specs': extra_specs}} + 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_passes_extra_specs_noop4(self): + self._stub_service_is_up(True) + filt_cls = self.class_map['ComputeCapabilitiesFilter']() + extra_specs = {'opt1': '> 4', 'opt2': '< 3'} + capabilities = {'enabled': True, 'opt1': '2', 'opt2': '5'} + service = {'disabled': False} + filter_properties = {'instance_type': {'memory_mb': 1024, + 'extra_specs': extra_specs}} + 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_passes_extra_specs_with_op_eq(self): + self._stub_service_is_up(True) + filt_cls = self.class_map['ComputeCapabilitiesFilter']() + extra_specs = {'opt1': '= 123'} + capabilities = {'enabled': True, 'opt1': '123'} + service = {'disabled': False} + filter_properties = {'instance_type': {'memory_mb': 1024, + 'extra_specs': extra_specs}} + 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_passes_extra_specs_with_op_eq2(self): + self._stub_service_is_up(True) + filt_cls = self.class_map['ComputeCapabilitiesFilter']() + extra_specs = {'opt1': '= 123'} + capabilities = {'enabled': True, 'opt1': '124'} + service = {'disabled': False} + filter_properties = {'instance_type': {'memory_mb': 1024, + 'extra_specs': extra_specs}} + 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_passes_extra_specs_with_op_eq3(self): + self._stub_service_is_up(True) + filt_cls = self.class_map['ComputeCapabilitiesFilter']() + extra_specs = {'opt1': '= 123', 'opt2': '= 456'} + capabilities = {'enabled': True, 'opt1': '124', 'opt2': '456'} + service = {'disabled': False} + filter_properties = {'instance_type': {'memory_mb': 1024, + 'extra_specs': extra_specs}} + 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_extra_specs_with_op_eq(self): + self._stub_service_is_up(True) + filt_cls = self.class_map['ComputeCapabilitiesFilter']() + extra_specs = {'opt2': '= 234'} + capabilities = {'enabled': True, 'opt2': '34'} + service = {'disabled': False} + filter_properties = {'instance_type': {'memory_mb': 1024, + 'extra_specs': extra_specs}} + 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_fails_extra_specs_with_op_eq2(self): + self._stub_service_is_up(True) + filt_cls = self.class_map['ComputeCapabilitiesFilter']() + extra_specs = {'opt1': '= 123', 'opt2': '= 456'} + capabilities = {'enabled': True, 'opt1': '124', 'opt2': '4567'} + service = {'disabled': False} + filter_properties = {'instance_type': {'memory_mb': 1024, + 'extra_specs': extra_specs}} + 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_extra_specs_with_op_eq3(self): + self._stub_service_is_up(True) + filt_cls = self.class_map['ComputeCapabilitiesFilter']() + extra_specs = {'opt1': '='} + capabilities = {'enabled': True, 'opt1': '124'} + service = {'disabled': False} + filter_properties = {'instance_type': {'memory_mb': 1024, + 'extra_specs': extra_specs}} + 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_fails_extra_specs_with_op_eq4(self): + self._stub_service_is_up(True) + filt_cls = self.class_map['ComputeCapabilitiesFilter']() + extra_specs = {'opt11': '= 124', 'opt12': '= 456'} + capabilities = {'enabled': True, 'opt3': '124', 'opt4': '456'} + service = {'disabled': False} + filter_properties = {'instance_type': {'memory_mb': 1024, + 'extra_specs': extra_specs}} + 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_with_op_seq(self): + self._stub_service_is_up(True) + filt_cls = self.class_map['ComputeCapabilitiesFilter']() + extra_specs = {'opt1': 's== 123'} + capabilities = {'enabled': True, 'opt1': '123'} + service = {'disabled': False} + filter_properties = {'instance_type': {'memory_mb': 1024, + 'extra_specs': extra_specs}} + 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_extra_specs_with_op_seq(self): + self._stub_service_is_up(True) + filt_cls = self.class_map['ComputeCapabilitiesFilter']() + extra_specs = {'opt2': 's== 234'} + capabilities = {'enabled': True, 'opt2': '2345'} + service = {'disabled': False} + filter_properties = {'instance_type': {'memory_mb': 1024, + 'extra_specs': extra_specs}} + 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_with_op_sneq(self): + self._stub_service_is_up(True) + filt_cls = self.class_map['ComputeCapabilitiesFilter']() + extra_specs = {'opt1': 's!= 123'} + capabilities = {'enabled': True, 'opt1': '11'} + service = {'disabled': False} + filter_properties = {'instance_type': {'memory_mb': 1024, + 'extra_specs': extra_specs}} + 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_extra_specs_with_op_sneq(self): + self._stub_service_is_up(True) + filt_cls = self.class_map['ComputeCapabilitiesFilter']() + extra_specs = {'opt2': 's!= 234'} + capabilities = {'enabled': True, 'opt2': '234'} + service = {'disabled': False} + filter_properties = {'instance_type': {'memory_mb': 1024, + 'extra_specs': extra_specs}} + 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_with_op_sgle(self): + self._stub_service_is_up(True) + filt_cls = self.class_map['ComputeCapabilitiesFilter']() + extra_specs = {'opt1': 's<= 123', 'opt2': 's>= 43'} + capabilities = {'enabled': True, 'opt1': '11', 'opt2': '543'} + service = {'disabled': False} + filter_properties = {'instance_type': {'memory_mb': 1024, + 'extra_specs': extra_specs}} + 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_extra_specs_with_op_sge(self): + self._stub_service_is_up(True) + filt_cls = self.class_map['ComputeCapabilitiesFilter']() + extra_specs = {'opt2': 's>= 234'} + capabilities = {'enabled': True, 'opt2': '1000'} + service = {'disabled': False} + filter_properties = {'instance_type': {'memory_mb': 1024, + 'extra_specs': extra_specs}} + 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_fails_extra_specs_with_op_sle(self): + self._stub_service_is_up(True) + filt_cls = self.class_map['ComputeCapabilitiesFilter']() + extra_specs = {'opt2': 's<= 1000'} + capabilities = {'enabled': True, 'opt2': '234'} + service = {'disabled': False} + filter_properties = {'instance_type': {'memory_mb': 1024, + 'extra_specs': extra_specs}} + 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_with_op_sgl(self): + self._stub_service_is_up(True) + filt_cls = self.class_map['ComputeCapabilitiesFilter']() + extra_specs = {'opt1': 's< 123', 'opt2': 's> 43'} + capabilities = {'enabled': True, 'opt1': '11', 'opt2': '543'} + service = {'disabled': False} + filter_properties = {'instance_type': {'memory_mb': 1024, + 'extra_specs': extra_specs}} + 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_extra_specs_with_op_sl(self): + self._stub_service_is_up(True) + filt_cls = self.class_map['ComputeCapabilitiesFilter']() + extra_specs = {'opt2': 's< 12'} + capabilities = {'enabled': True, 'opt2': '2'} + service = {'disabled': False} + filter_properties = {'instance_type': {'memory_mb': 1024, + 'extra_specs': extra_specs}} + 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_fails_extra_specs_with_op_sg(self): + self._stub_service_is_up(True) + filt_cls = self.class_map['ComputeCapabilitiesFilter']() + extra_specs = {'opt2': 's> 2'} + capabilities = {'enabled': True, 'opt2': '12'} + service = {'disabled': False} + filter_properties = {'instance_type': {'memory_mb': 1024, + 'extra_specs': extra_specs}} + 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_with_op_in(self): + self._stub_service_is_up(True) + filt_cls = self.class_map['ComputeCapabilitiesFilter']() + extra_specs = {'opt1': '<in> 11'} + capabilities = {'enabled': True, 'opt1': '12311321'} + service = {'disabled': False} + filter_properties = {'instance_type': {'memory_mb': 1024, + 'extra_specs': extra_specs}} + 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_passes_extra_specs_with_op_in2(self): + self._stub_service_is_up(True) + filt_cls = self.class_map['ComputeCapabilitiesFilter']() + extra_specs = {'opt1': '<in> 12311321'} + capabilities = {'enabled': True, 'opt1': '12311321'} + service = {'disabled': False} + filter_properties = {'instance_type': {'memory_mb': 1024, + 'extra_specs': extra_specs}} + 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_extra_specs_with_op_in(self): + self._stub_service_is_up(True) + filt_cls = self.class_map['ComputeCapabilitiesFilter']() + extra_specs = {'opt1': '<in> 11'} + capabilities = {'enabled': True, 'opt1': '12310321'} + service = {'disabled': False} + filter_properties = {'instance_type': {'memory_mb': 1024, + 'extra_specs': extra_specs}} + 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_with_op_or(self): + self._stub_service_is_up(True) + filt_cls = self.class_map['ComputeCapabilitiesFilter']() + extra_specs = {'opt1': '<or> 11 <or> 12'} + capabilities = {'enabled': True, 'opt1': '12'} + service = {'disabled': False} + filter_properties = {'instance_type': {'memory_mb': 1024, + 'extra_specs': extra_specs}} + 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_extra_specs_with_op_or(self): + self._stub_service_is_up(True) + filt_cls = self.class_map['ComputeCapabilitiesFilter']() + extra_specs = {'opt1': '<or> 11 <or> 12'} + capabilities = {'enabled': True, 'opt1': '13'} + service = {'disabled': False} + filter_properties = {'instance_type': {'memory_mb': 1024, + 'extra_specs': extra_specs}} + 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_with_op_le(self): + self._stub_service_is_up(True) + filt_cls = self.class_map['ComputeCapabilitiesFilter']() + extra_specs = {'opt1': '<= 10', 'opt2': '<= 20'} + capabilities = {'enabled': True, 'opt1': 2, 'opt2': 2} + service = {'disabled': False} + filter_properties = {'instance_type': {'memory_mb': 1024, + 'extra_specs': extra_specs}} + 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_extra_specs_with_op_le(self): + self._stub_service_is_up(True) + filt_cls = self.class_map['ComputeCapabilitiesFilter']() + extra_specs = {'opt1': '<= 2', 'opt2': '<= 2'} + capabilities = {'enabled': True, 'opt1': 1, 'opt2': 3} + service = {'disabled': False} + filter_properties = {'instance_type': {'memory_mb': 1024, + 'extra_specs': extra_specs}} + 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_with_op_ge(self): + self._stub_service_is_up(True) + filt_cls = self.class_map['ComputeCapabilitiesFilter']() + extra_specs = {'opt1': '>= 1', 'opt2': '>= 2'} + capabilities = {'enabled': True, 'opt1': 2, 'opt2': 2} + service = {'disabled': False} + filter_properties = {'instance_type': {'memory_mb': 1024, + 'extra_specs': extra_specs}} + 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_extra_specs_with_op_ge(self): + self._stub_service_is_up(True) + filt_cls = self.class_map['ComputeCapabilitiesFilter']() + extra_specs = {'opt1': '>= 2', 'opt2': '>= 2'} capabilities = {'enabled': True, 'opt1': 1, 'opt2': 2} service = {'disabled': False} filter_properties = {'instance_type': {'memory_mb': 1024, |
