Apply scheduler limits to Exact* filters
The DiskFilter, RamFilter and CoreFilter scheduler filters set the resource limit on the HostState object during filtering. This is later checked in compute during the claim, and used to enforce the allocation ratios in a safe manner. The Exact* filters do not set the resource limits, so scheduler race conditions can result in multiple bare metal instances claiming a single host. This change sets the resource limits on the HostState object in the ExactCoreFilter, ExactDiskFilter and ExactRamFilter, ensuring that only a single baremetal instance can claim a compute host. Change-Id: I31d0331afc4698046a4568935a95f70f30e335dd Partial-Bug: #1341420 Co-Authored-By: Will Miller <wmiller@cray.com>
This commit is contained in:
parent
c131f0e03e
commit
3471cc8b74
|
@ -44,4 +44,8 @@ class ExactCoreFilter(filters.BaseHostFilter):
|
|||
'usable_vcpus': usable_vcpus})
|
||||
return False
|
||||
|
||||
# NOTE(mgoddard): Setting the limit ensures that it is enforced in
|
||||
# compute. This ensures that if multiple instances are scheduled to a
|
||||
# single host, then all after the first will fail in the claim.
|
||||
host_state.limits['vcpu'] = host_state.vcpus_total
|
||||
return True
|
||||
|
|
|
@ -38,4 +38,8 @@ class ExactDiskFilter(filters.BaseHostFilter):
|
|||
'usable_disk_mb': host_state.free_disk_mb})
|
||||
return False
|
||||
|
||||
# NOTE(mgoddard): Setting the limit ensures that it is enforced in
|
||||
# compute. This ensures that if multiple instances are scheduled to a
|
||||
# single host, then all after the first will fail in the claim.
|
||||
host_state.limits['disk_gb'] = host_state.total_usable_disk_gb
|
||||
return True
|
||||
|
|
|
@ -35,4 +35,8 @@ class ExactRamFilter(filters.BaseHostFilter):
|
|||
'usable_ram': host_state.free_ram_mb})
|
||||
return False
|
||||
|
||||
# NOTE(mgoddard): Setting the limit ensures that it is enforced in
|
||||
# compute. This ensures that if multiple instances are scheduled to a
|
||||
# single host, then all after the first will fail in the claim.
|
||||
host_state.limits['memory_mb'] = host_state.total_usable_ram_mb
|
||||
return True
|
||||
|
|
|
@ -25,20 +25,24 @@ class TestExactCoreFilter(test.NoDBTestCase):
|
|||
def test_exact_core_filter_passes(self):
|
||||
spec_obj = objects.RequestSpec(
|
||||
flavor=objects.Flavor(vcpus=1))
|
||||
host = self._get_host({'vcpus_total': 3, 'vcpus_used': 2})
|
||||
vcpus = 3
|
||||
host = self._get_host({'vcpus_total': vcpus, 'vcpus_used': vcpus - 1})
|
||||
self.assertTrue(self.filt_cls.host_passes(host, spec_obj))
|
||||
self.assertEqual(host.limits.get('vcpu'), vcpus)
|
||||
|
||||
def test_exact_core_filter_fails(self):
|
||||
spec_obj = objects.RequestSpec(
|
||||
flavor=objects.Flavor(vcpus=2))
|
||||
host = self._get_host({'vcpus_total': 3, 'vcpus_used': 2})
|
||||
self.assertFalse(self.filt_cls.host_passes(host, spec_obj))
|
||||
self.assertNotIn('vcpu', host.limits)
|
||||
|
||||
def test_exact_core_filter_fails_host_vcpus_not_set(self):
|
||||
spec_obj = objects.RequestSpec(
|
||||
flavor=objects.Flavor(vcpus=1))
|
||||
host = self._get_host({})
|
||||
self.assertFalse(self.filt_cls.host_passes(host, spec_obj))
|
||||
self.assertNotIn('vcpu', host.limits)
|
||||
|
||||
def _get_host(self, host_attributes):
|
||||
return fakes.FakeHostState('host1', 'node1', host_attributes)
|
||||
|
|
|
@ -25,14 +25,18 @@ class TestExactDiskFilter(test.NoDBTestCase):
|
|||
def test_exact_disk_filter_passes(self):
|
||||
spec_obj = objects.RequestSpec(
|
||||
flavor=objects.Flavor(root_gb=1, ephemeral_gb=1, swap=1024))
|
||||
host = self._get_host({'free_disk_mb': 3 * 1024})
|
||||
disk_gb = 3
|
||||
host = self._get_host({'free_disk_mb': disk_gb * 1024,
|
||||
'total_usable_disk_gb': disk_gb})
|
||||
self.assertTrue(self.filt_cls.host_passes(host, spec_obj))
|
||||
self.assertEqual(host.limits.get('disk_gb'), disk_gb)
|
||||
|
||||
def test_exact_disk_filter_fails(self):
|
||||
spec_obj = objects.RequestSpec(
|
||||
flavor=objects.Flavor(root_gb=1, ephemeral_gb=1, swap=1024))
|
||||
host = self._get_host({'free_disk_mb': 2 * 1024})
|
||||
self.assertFalse(self.filt_cls.host_passes(host, spec_obj))
|
||||
self.assertNotIn('disk_gb', host.limits)
|
||||
|
||||
def _get_host(self, host_attributes):
|
||||
return fakes.FakeHostState('host1', 'node1', host_attributes)
|
||||
|
|
|
@ -25,14 +25,18 @@ class TestRamFilter(test.NoDBTestCase):
|
|||
def test_exact_ram_filter_passes(self):
|
||||
spec_obj = objects.RequestSpec(
|
||||
flavor=objects.Flavor(memory_mb=1024))
|
||||
host = self._get_host({'free_ram_mb': 1024})
|
||||
ram_mb = 1024
|
||||
host = self._get_host({'free_ram_mb': ram_mb,
|
||||
'total_usable_ram_mb': ram_mb})
|
||||
self.assertTrue(self.filt_cls.host_passes(host, spec_obj))
|
||||
self.assertEqual(host.limits.get('memory_mb'), ram_mb)
|
||||
|
||||
def test_exact_ram_filter_fails(self):
|
||||
spec_obj = objects.RequestSpec(
|
||||
flavor=objects.Flavor(memory_mb=512))
|
||||
host = self._get_host({'free_ram_mb': 1024})
|
||||
self.assertFalse(self.filt_cls.host_passes(host, spec_obj))
|
||||
self.assertNotIn('memory_mb', host.limits)
|
||||
|
||||
def _get_host(self, host_attributes):
|
||||
return fakes.FakeHostState('host1', 'node1', host_attributes)
|
||||
|
|
Loading…
Reference in New Issue