Delete ports when nova fails to boot VM

This patch adds some code to the exception handler in the instance
manager's boot method to cleanup any created ports if nova fails to boot
the instance.

Change-Id: I459ccd82a367fcd41d4a894b7231c797dc5100e9
Closes-Bug: #1516152
(cherry picked from commit 7de346fd49)
This commit is contained in:
James King 2015-11-18 11:53:22 -05:00 committed by Adam Gandelman
parent 7211574959
commit 53e0266387
6 changed files with 31 additions and 3 deletions

View File

@ -110,6 +110,13 @@ class BaseDriver(object):
return _make_ports
def delete_ports(self, worker_context):
"""Delete all created ports.
:param worker_context:
:returns: None
"""
@staticmethod
def pre_populate_hook():
"""called in populate.py durring driver loading loop.
@ -120,7 +127,7 @@ class BaseDriver(object):
"""pre-plug hook
:param worker_context:
:returs: None
:returns: None
"""
@staticmethod

View File

@ -202,6 +202,16 @@ class Router(BaseDriver):
return _make_ports
def delete_ports(self, worker_context):
"""Delete all ports.
:param worker_context:
:returns: None
"""
worker_context.neutron.delete_vrrp_port(self.id)
worker_context.neutron.delete_vrrp_port(self.id, label='MGT')
@staticmethod
def pre_populate_hook():
"""Fetch the existing routers from neutrom then and returns list back

View File

@ -246,7 +246,7 @@ class InstanceManager(object):
return
except:
self.log.exception(_LE('Instance failed to start boot'))
return
self.driver.delete_ports(worker_context)
else:
# We have successfully started a (re)boot attempt so
# record the timestamp so we can report how long it takes.

View File

@ -151,6 +151,15 @@ class RouterDriverTest(base.RugTestBase):
]
self.assertEqual(res, ('fake_mgt_port', expected_instance_ports))
def test_delete_ports(self):
rtr = self._init_driver()
fake_router_obj = fakes.fake_router()
rtr._router = fake_router_obj
rtr.delete_ports(self.ctx)
expected_ports = [mock.call(rtr.id),
mock.call(rtr.id, label='MGT')]
self.ctx.neutron.delete_vrrp_port.assert_has_calls(expected_ports)
@mock.patch('akanda.rug.api.neutron.Neutron')
def test_pre_populate_retry_loop(self, mocked_neutron_api):
neutron_client = mock.Mock()

View File

@ -119,6 +119,7 @@ def fake_driver(resource_id=None):
fake_driver.name = 'ak-FakeDriver-fake_resource_id'
fake_driver.image_uuid = 'fake_image_uuid'
fake_driver.make_ports.return_value = 'fake_ports_callback'
fake_driver.delete_ports.return_value = 'fake_delete_ports_callback'
return fake_driver

View File

@ -360,6 +360,7 @@ class TestInstanceManager(base.RugTestBase):
instance = mock.sentinel.instance
self.ctx.neutron.get_router_detail.return_value = rtr
self.ctx.nova_client.get_instance.return_value = instance
self.ctx.nova_client.boot_instance.side_effect = RuntimeError
rtr.id = 'ROUTER1'
instance.id = 'INSTANCE1'
rtr.management_port = management_port
@ -368,7 +369,6 @@ class TestInstanceManager(base.RugTestBase):
rtr.ports.__iter__.return_value = [management_port, external_port,
internal_port]
self.instance_mgr.boot(self.ctx)
self.assertEqual(self.instance_mgr.state, states.BOOTING)
self.ctx.nova_client.boot_instance.assert_called_once_with(
resource_type=self.fake_driver.RESOURCE_NAME,
prev_instance_info=self.INSTANCE_INFO,
@ -376,6 +376,7 @@ class TestInstanceManager(base.RugTestBase):
image_uuid=self.fake_driver.image_uuid,
flavor=self.fake_driver.flavor,
make_ports_callback='fake_ports_callback')
self.instance_mgr.driver.delete_ports.assert_called_once_with(self.ctx)
def test_boot_check_up(self):
with mock.patch.object(