From dca2e7d22310f19f94f7c637fa74791b85b0550b Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Wed, 21 Sep 2016 16:22:28 -0400 Subject: [PATCH] Cleanup after container start fails If the container.start method fails then trap the exception and clean up after itself as well. Change-Id: I2e8b80da40c09a2e45df96e2f871ab5e083a6398 Signed-off-by: Chuck Short --- nova/tests/unit/virt/lxd/test_driver.py | 36 +++++++++++++++++++++++++ nova/virt/lxd/driver.py | 7 ++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/nova/tests/unit/virt/lxd/test_driver.py b/nova/tests/unit/virt/lxd/test_driver.py index aba4c0e2..e5ecb82d 100644 --- a/nova/tests/unit/virt/lxd/test_driver.py +++ b/nova/tests/unit/virt/lxd/test_driver.py @@ -323,6 +323,42 @@ class LXDDriverTest(test.NoDBTestCase): lxd_driver.cleanup.assert_called_once_with( ctx, instance, network_info, block_device_info) + def test_spawn_container_start_fail(self): + def container_get(*args, **kwargs): + raise lxdcore_exceptions.LXDAPIException(MockResponse(404)) + + def side_effect(*args, **kwargs): + raise lxdcore_exceptions.LXDAPIException(MockResponse(200)) + + self.client.containers.get.side_effect = container_get + container = mock.Mock() + ctx = context.get_admin_context() + instance = fake_instance.fake_instance_obj(ctx, name='test') + image_meta = mock.Mock() + injected_files = mock.Mock() + admin_password = mock.Mock() + network_info = [mock.Mock()] + block_device_info = mock.Mock() + + lxd_driver = driver.LXDDriver(None) + lxd_driver.init_host(None) + lxd_driver.setup_image = mock.Mock() + lxd_driver.vif_driver = mock.Mock() + lxd_driver.cleanup = mock.Mock() + lxd_driver.create_profile = mock.Mock(return_value={ + 'name': instance.name, 'config': {}, 'devices': {}}) + lxd_driver.client.containers.create = mock.Mock( + side_effect=side_effect) + container.start.side_effect = side_effect + + self.assertRaises( + lxdcore_exceptions.LXDAPIException, + lxd_driver.spawn, + ctx, instance, image_meta, injected_files, admin_password, + network_info, block_device_info) + lxd_driver.cleanup.assert_called_once_with( + ctx, instance, network_info, block_device_info) + @mock.patch('nova.virt.lxd.driver.container_utils.get_container_storage') @mock.patch.object(driver.utils, 'execute') @mock.patch('nova.virt.driver.block_device_info_get_ephemerals') diff --git a/nova/virt/lxd/driver.py b/nova/virt/lxd/driver.py index 90f6de8b..9a1dd52f 100644 --- a/nova/virt/lxd/driver.py +++ b/nova/virt/lxd/driver.py @@ -332,7 +332,12 @@ class LXDDriver(driver.ComputeDriver): profile.devices.update(config_drive) profile.save() - container.start() + try: + container.start() + except lxd_exceptions.LXDAPIException as e: + with excutils.save_and_reraise_exception(): + self.cleanup( + context, instance, network_info, block_device_info) def destroy(self, context, instance, network_info, block_device_info=None, destroy_disks=True, migrate_data=None):