From 8df82a3fe9e8fd13e86b52f569397da7523f8d28 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 24 Oct 2012 16:14:36 -0700 Subject: [PATCH] libvirt: persist volume attachments into config When you attach a volume to a running instance, only the running xml is updated in libvirt. This is due to the usage of the VIRT_DOMAIN_AFFECT_CURRENT flag passed to attach device. What we really want is to affect both the config and the running xml. There is no combination of flags that works in all states, so we explicitly set the right combination of flags depending on the running state of the vm. Includes a test to test_virt_drivers to ensure the flags are passed correctly. Fixes bug 1071069 Change-Id: I1992748b08daf99cf03dfeb0937ad42457fff1a3 --- nova/tests/fakelibvirt.py | 7 ++++++- nova/tests/test_virt_drivers.py | 12 ++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/nova/tests/fakelibvirt.py b/nova/tests/fakelibvirt.py index b933b004..7c9d5b23 100644 --- a/nova/tests/fakelibvirt.py +++ b/nova/tests/fakelibvirt.py @@ -73,6 +73,8 @@ VIR_DOMAIN_XML_SECURE = 1 VIR_DOMAIN_UNDEFINE_MANAGED_SAVE = 1 VIR_DOMAIN_AFFECT_CURRENT = 0 +VIR_DOMAIN_AFFECT_LIVE = 1 +VIR_DOMAIN_AFFECT_CONFIG = 2 VIR_CPU_COMPARE_ERROR = -1 VIR_CPU_COMPARE_INCOMPATIBLE = 0 @@ -337,7 +339,10 @@ class Domain(object): self._def['devices']['disks'] += [disk_info] return True - def attachDeviceFlags(self, xml, _flags): + def attachDeviceFlags(self, xml, flags): + if (flags & VIR_DOMAIN_AFFECT_LIVE and + self._state != VIR_DOMAIN_RUNNING): + raise libvirtError("AFFECT_LIVE only allowed for running domains!") self.attachDevice(xml) def detachDevice(self, xml): diff --git a/nova/tests/test_virt_drivers.py b/nova/tests/test_virt_drivers.py index d5a2203f..5508ab9b 100644 --- a/nova/tests/test_virt_drivers.py +++ b/nova/tests/test_virt_drivers.py @@ -360,6 +360,18 @@ class _VirtDriverTestCase(_FakeDriverBackendTestCase): instance_ref['name'], '/mnt/nova/something') + @catch_notimplementederror + def test_attach_detach_different_power_states(self): + instance_ref, network_info = self._get_running_instance() + self.connection.power_off(instance_ref) + self.connection.attach_volume({'driver_volume_type': 'fake'}, + instance_ref['name'], + '/mnt/nova/something') + self.connection.power_on(instance_ref) + self.connection.detach_volume({'driver_volume_type': 'fake'}, + instance_ref['name'], + '/mnt/nova/something') + @catch_notimplementederror def test_get_info(self): instance_ref, network_info = self._get_running_instance()