From bf3e123e1f7c09c64beecf0ff092c7e6b84590b4 Mon Sep 17 00:00:00 2001 From: Sahid Orentino Ferdjaoui Date: Mon, 17 Dec 2018 09:54:48 -0500 Subject: [PATCH] fix error on delete interface when destroying instance An instance may be destroyed prior nova-compute receives a vif-delete-event. detach_interface() will so try to get the lxd profile related to the instance which does not exist anymore, the process will fail with a NotFound exception raised by lxclib. In this commit we solve the issue by handling the exception and so avoiding on updatating the lxc profile. We still continue the process of vif_driver.un_plug() to ensure all got cleaned. Change-Id: If7fd5dd17323ec625df3518311dfb012302b2711 Closes-Bug: #1808819 Signed-off-by: Sahid Orentino Ferdjaoui --- nova/tests/unit/virt/lxd/test_driver.py | 22 ++++++++++++ nova/virt/lxd/driver.py | 45 +++++++++++++++---------- 2 files changed, 49 insertions(+), 18 deletions(-) diff --git a/nova/tests/unit/virt/lxd/test_driver.py b/nova/tests/unit/virt/lxd/test_driver.py index 10fa5b88..223c4179 100644 --- a/nova/tests/unit/virt/lxd/test_driver.py +++ b/nova/tests/unit/virt/lxd/test_driver.py @@ -796,6 +796,28 @@ class LXDDriverTest(test.NoDBTestCase): self.assertEqual(['root'], sorted(profile.devices.keys())) profile.save.assert_called_once_with(wait=True) + def test_detach_interface_not_found(self): + self.client.profiles.get.side_effect = lxdcore_exceptions.NotFound( + "404") + + ctx = context.get_admin_context() + instance = fake_instance.fake_instance_obj( + ctx, name='test', memory_mb=0) + vif = { + 'id': '0123456789abcdef', + 'type': network_model.VIF_TYPE_OVS, + 'address': '00:11:22:33:44:55', + 'network': { + 'bridge': 'fakebr'}} + + lxd_driver = driver.LXDDriver(None) + lxd_driver.init_host(None) + + lxd_driver.detach_interface(ctx, instance, vif) + + self.vif_driver.unplug.assert_called_once_with( + instance, vif) + def test_migrate_disk_and_power_off(self): container = mock.Mock() self.client.containers.get.return_value = container diff --git a/nova/virt/lxd/driver.py b/nova/virt/lxd/driver.py index 73b65cc3..8bd7939d 100644 --- a/nova/virt/lxd/driver.py +++ b/nova/virt/lxd/driver.py @@ -800,25 +800,34 @@ class LXDDriver(driver.ComputeDriver): profile.save(wait=True) def detach_interface(self, context, instance, vif): - profile = self.client.profiles.get(instance.name) - devname = lxd_vif.get_vif_devname(vif) + try: + profile = self.client.profiles.get(instance.name) + devname = lxd_vif.get_vif_devname(vif) - # NOTE(jamespage): Attempt to remove device using - # new style tap naming - if devname in profile.devices: - del profile.devices[devname] - profile.save(wait=True) - else: - # NOTE(jamespage): For upgrades, scan devices - # and attempt to identify - # using mac address as the - # device will *not* have a - # consistent name - for key, val in profile.devices.items(): - if val.get('hwaddr') == vif['address']: - del profile.devices[key] - profile.save(wait=True) - break + # NOTE(jamespage): Attempt to remove device using + # new style tap naming + if devname in profile.devices: + del profile.devices[devname] + profile.save(wait=True) + else: + # NOTE(jamespage): For upgrades, scan devices + # and attempt to identify + # using mac address as the + # device will *not* have a + # consistent name + for key, val in profile.devices.items(): + if val.get('hwaddr') == vif['address']: + del profile.devices[key] + profile.save(wait=True) + break + except lxd_exceptions.NotFound: + # This method is called when an instance get destroyed. It + # could happen that Nova to receive an event + # "vif-delete-event" after the instance is destroyed which + # result the lxd profile not exist. + LOG.debug("lxd profile for instance {instance} does not exist. " + "The instance probably got destroyed before this method " + "got called.".format(instance=instance.name)) self.vif_driver.unplug(instance, vif)