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
This commit is contained in:
parent
86b91474d1
commit
814e7f8c82
@ -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):
|
||||
|
@ -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()
|
||||
|
@ -646,7 +646,13 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
self._conn.defineXML(domxml)
|
||||
else:
|
||||
try:
|
||||
flags = (libvirt.VIR_DOMAIN_AFFECT_CURRENT)
|
||||
# NOTE(vish): We can always affect config because our
|
||||
# domains are persistent, but we should only
|
||||
# affect live if the domain is running.
|
||||
flags = libvirt.VIR_DOMAIN_AFFECT_CONFIG
|
||||
state = LIBVIRT_POWER_STATE[virt_dom.info()[0]]
|
||||
if state == power_state.RUNNING:
|
||||
flags |= libvirt.VIR_DOMAIN_AFFECT_LIVE
|
||||
virt_dom.attachDeviceFlags(conf.to_xml(), flags)
|
||||
except Exception, ex:
|
||||
if isinstance(ex, libvirt.libvirtError):
|
||||
@ -704,7 +710,13 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
domxml = virt_dom.XMLDesc(libvirt.VIR_DOMAIN_XML_SECURE)
|
||||
self._conn.defineXML(domxml)
|
||||
else:
|
||||
flags = (libvirt.VIR_DOMAIN_AFFECT_CURRENT)
|
||||
# NOTE(vish): We can always affect config because our
|
||||
# domains are persistent, but we should only
|
||||
# affect live if the domain is running.
|
||||
flags = libvirt.VIR_DOMAIN_AFFECT_CONFIG
|
||||
state = LIBVIRT_POWER_STATE[virt_dom.info()[0]]
|
||||
if state == power_state.RUNNING:
|
||||
flags |= libvirt.VIR_DOMAIN_AFFECT_LIVE
|
||||
virt_dom.detachDeviceFlags(xml, flags)
|
||||
except libvirt.libvirtError as ex:
|
||||
# NOTE(vish): This is called to cleanup volumes after live
|
||||
|
Loading…
Reference in New Issue
Block a user