From c083743062e2044ff9af0b7d7ccb19a935b448e2 Mon Sep 17 00:00:00 2001 From: Nikola Dipanov Date: Thu, 2 Apr 2015 12:28:16 +0100 Subject: [PATCH] virt: Make sure block device info is persisted There are several methods that we wrap with a @update_db decorator, which is to say that we want the data that changed on the object to be persisted once the method has done it's work. However in case of exceptions, we would do some local cleanup and propagate the exception to through the stack, which would cause the db save to not happen (due to the way the 'update_db' decorator was written). This is not ideal since some of those methods such as 'attach()' do several interaction (with the Cinder API and libvirt for example), and making sure that results of successfull ones are persisted in case of a non immediate failure is important for later cleanup, and keeping the system in a consistent state. This patch makes sure that we persist data to the DB at all times. Change-Id: Icf8dbe4e3b7fd65b3c7a5eb479d6be15ee504253 Closes-bug: #1439282 --- nova/tests/unit/virt/test_block_device.py | 5 ++++- nova/virt/block_device.py | 6 ++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/nova/tests/unit/virt/test_block_device.py b/nova/tests/unit/virt/test_block_device.py index b9f8411a2782..287c7f9a4ead 100644 --- a/nova/tests/unit/virt/test_block_device.py +++ b/nova/tests/unit/virt/test_block_device.py @@ -356,6 +356,7 @@ class TestDriverBlockDevice(test.NoDBTestCase): self.volume_api.check_attach(self.context, fake_volume, instance=instance).AndRaise( test.TestingException) + driver_bdm._bdm_obj.save().AndReturn(None) return instance, expected_conn_info self.virt_driver.get_volume_connector(instance).AndReturn(connector) @@ -383,9 +384,11 @@ class TestDriverBlockDevice(test.NoDBTestCase): self.volume_api.terminate_connection( elevated_context, fake_volume['id'], connector).AndReturn(None) + driver_bdm._bdm_obj.save().AndReturn(None) return instance, expected_conn_info if volume_attach: + driver_bdm._bdm_obj.save().AndReturn(None) if not fail_volume_attach: self.volume_api.attach(elevated_context, fake_volume['id'], 'fake_uuid', bdm_dict['device_name'], @@ -395,7 +398,7 @@ class TestDriverBlockDevice(test.NoDBTestCase): 'fake_uuid', bdm_dict['device_name'], mode=access_mode).AndRaise( test.TestingException) - driver_bdm._bdm_obj.save().MultipleTimes().AndReturn(None) + driver_bdm._bdm_obj.save().AndReturn(None) return instance, expected_conn_info def test_volume_attach(self): diff --git a/nova/virt/block_device.py b/nova/virt/block_device.py index 362475108737..a9760b668c3d 100644 --- a/nova/virt/block_device.py +++ b/nova/virt/block_device.py @@ -45,8 +45,10 @@ class _NoLegacy(Exception): def update_db(method): @functools.wraps(method) def wrapped(obj, context, *args, **kwargs): - ret_val = method(obj, context, *args, **kwargs) - obj.save() + try: + ret_val = method(obj, context, *args, **kwargs) + finally: + obj.save() return ret_val return wrapped