Delete preemptible instances on reservation start

Blueprint: blazar-preemptible-instances
Change-Id: Ic5fa07c4b1fffc763302b07e8a5f6fe0e15e019e
This commit is contained in:
Pierre Riteau 2022-02-03 21:50:28 +01:00
parent 4a2bb67fbf
commit 9264905508
2 changed files with 30 additions and 0 deletions

View File

@ -284,12 +284,15 @@ class ReservationPoolTestCase(tests.TestCase):
def test_add_computehost(self):
self._patch_get_aggregate_from_name_or_id()
terminate_preemptibles = self.patch(
self.pool, 'terminate_preemptibles')
self.pool.add_computehost('pool', 'host3')
check0 = self.nova.aggregates.add_host
check0.assert_any_call(self.fake_aggregate.id, 'host3')
check1 = self.nova.aggregates.remove_host
check1.assert_any_call(self.fake_freepool.id, 'host3')
terminate_preemptibles.assert_called_with('host3')
def test_add_computehost_with_host_id(self):
# NOTE(sbauza): Freepool.hosts only contains names of hosts, not UUIDs
@ -341,6 +344,8 @@ class ReservationPoolTestCase(tests.TestCase):
def test_add_computehost_revert(self):
self._patch_get_aggregate_from_name_or_id()
self.fake_freepool.hosts = ['host1', 'host2']
terminate_preemptibles = self.patch(
self.pool, 'terminate_preemptibles')
self.assertRaises(manager_exceptions.HostNotInFreePool,
self.pool.add_computehost,
'pool', ['host1', 'host2', 'host3'])
@ -355,6 +360,8 @@ class ReservationPoolTestCase(tests.TestCase):
mock.call(self.fake_freepool.id, 'host2'),
mock.call(self.fake_aggregate.id, 'host1'),
mock.call(self.fake_aggregate.id, 'host2')])
terminate_preemptibles.assert_has_calls([mock.call('host1'),
mock.call('host2')])
def test_remove_computehost_from_freepool(self):
self._patch_get_aggregate_from_name_or_id()

View File

@ -361,6 +361,15 @@ class ReservationPool(NovaClientWrapper):
except nova_exception.NotFound:
raise manager_exceptions.HostNotFound(host=host)
# When moving a host out of the freepool, we need to
# terminate preemptible instances before adding hosts to
# the reservation aggregate, which makes them available for
# scheduling.
#
# NOTE(priteau): Preemptibles should not be used with
# instance reservation yet.
self.terminate_preemptibles(host)
LOG.info("adding host '%(host)s' to aggregate %(id)s",
{'host': host, 'id': agg.id})
try:
@ -451,6 +460,20 @@ class ReservationPool(NovaClientWrapper):
metadata = {project_id: None}
return self.nova.aggregates.set_metadata(agg.id, metadata)
def terminate_preemptibles(self, host):
"""Terminate preemptible instances running on host"""
for server in self.nova.servers.list(
search_opts={"host": host, "all_tenants": 1}):
try:
LOG.info('Terminating preemptible instance %s (%s)',
server.name, server.id)
self.nova.servers.delete(server=server)
except nova_exception.NotFound:
LOG.info('Could not find server %s, may have been deleted '
'concurrently.', server)
except Exception as e:
LOG.exception('Failed to delete %s: %s.', server, str(e))
class NovaInventory(NovaClientWrapper):