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
(cherry picked from commit 814e7f8c82
)
This commit is contained in:
parent
15815057db
commit
ebabd029ac
|
@ -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):
|
||||
|
|
|
@ -389,6 +389,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()
|
||||
|
|
|
@ -648,7 +648,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):
|
||||
|
@ -709,7 +715,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)
|
||||
finally:
|
||||
self.volume_driver_method('disconnect_volume',
|
||||
|
|
Loading…
Reference in New Issue