summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2012-08-15 12:54:50 +0000
committerGerrit Code Review <review@openstack.org>2012-08-15 12:54:50 +0000
commit1ef3607239c4bce8a276e420f2b70137b1a1fe2f (patch)
treecef87ca4447c9922ff6e0b9ab8d251083e7a63d4
parentca950e7ea3909110fe05e3239975b7545423670a (diff)
parent90f77d71fe5815f08fe12e77e7645c6025ee0191 (diff)
downloadnova-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.py46
-rw-r--r--nova/tests/scheduler/test_host_filters.py384
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,