libvirt: allow querying devices from the persistent domain
This patch adds from_persistent_config kwargs to get_interface_by_cfg() and get_disk() so that the caller can specify which domain config the devices is read from. Currently, if there was both a live domain and a persistent domain then nova only reads from the live domain. In a later patch during device detach these calls will be used to detach from the persistent domain separately from the live domain. Change-Id: I86153d31b02e6b74b42d53a6800297cbd0e5cbb4 Related-Bug: #1882521
This commit is contained in:
parent
f5cd6e2dea
commit
a634103b15
|
@ -24034,6 +24034,41 @@ class LibvirtDriverTestCase(test.NoDBTestCase, TraitsComparisonMixin):
|
||||||
|
|
||||||
self.assertIsNone(guest.get_disk('vdc'))
|
self.assertIsNone(guest.get_disk('vdc'))
|
||||||
|
|
||||||
|
dom.XMLDesc.assert_has_calls([mock.call(0)] * 3)
|
||||||
|
|
||||||
|
def test_get_disk_xml_from_persistent_config(self):
|
||||||
|
dom_xml = """
|
||||||
|
<domain type="kvm">
|
||||||
|
<devices>
|
||||||
|
<disk type="file">
|
||||||
|
<source file="disk1_file"/>
|
||||||
|
<target dev="vda" bus="virtio"/>
|
||||||
|
<serial>0e38683e-f0af-418f-a3f1-6b67ea0f919d</serial>
|
||||||
|
</disk>
|
||||||
|
<disk type="block">
|
||||||
|
<source dev="/path/to/dev/1"/>
|
||||||
|
<target dev="vdb" bus="virtio" serial="1234"/>
|
||||||
|
</disk>
|
||||||
|
</devices>
|
||||||
|
</domain>
|
||||||
|
"""
|
||||||
|
|
||||||
|
diska_xml = """<disk type="file" device="disk">
|
||||||
|
<source file="disk1_file"/>
|
||||||
|
<target bus="virtio" dev="vda"/>
|
||||||
|
<serial>0e38683e-f0af-418f-a3f1-6b67ea0f919d</serial>
|
||||||
|
</disk>"""
|
||||||
|
|
||||||
|
dom = mock.MagicMock()
|
||||||
|
dom.XMLDesc.return_value = dom_xml
|
||||||
|
guest = libvirt_guest.Guest(dom)
|
||||||
|
|
||||||
|
actual_diska_xml = guest.get_disk(
|
||||||
|
'vda', from_persistent_config=True).to_xml()
|
||||||
|
self.assertXmlEqual(diska_xml, actual_diska_xml)
|
||||||
|
dom.XMLDesc.assert_called_once_with(
|
||||||
|
fakelibvirt.VIR_DOMAIN_XML_INACTIVE)
|
||||||
|
|
||||||
def test_vcpu_model_from_config(self):
|
def test_vcpu_model_from_config(self):
|
||||||
drv = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
|
drv = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
|
||||||
vcpu_model = drv._cpu_config_to_vcpu_model(None, None)
|
vcpu_model = drv._cpu_config_to_vcpu_model(None, None)
|
||||||
|
|
|
@ -540,6 +540,49 @@ class GuestTestCase(test.NoDBTestCase):
|
||||||
self.assertIsNotNone(
|
self.assertIsNotNone(
|
||||||
self.guest.get_interface_by_cfg(cfg))
|
self.guest.get_interface_by_cfg(cfg))
|
||||||
self.assertIsNone(self.guest.get_interface_by_cfg(None))
|
self.assertIsNone(self.guest.get_interface_by_cfg(None))
|
||||||
|
self.domain.XMLDesc.assert_has_calls([mock.call(0)] * 6)
|
||||||
|
|
||||||
|
# now check if the persistent config can be queried too
|
||||||
|
self.domain.XMLDesc.reset_mock()
|
||||||
|
devs = self.guest.get_all_devices(
|
||||||
|
devtype=None, from_persistent_config=True)
|
||||||
|
self.domain.XMLDesc.assert_called_once_with(
|
||||||
|
fakelibvirt.VIR_DOMAIN_XML_INACTIVE)
|
||||||
|
|
||||||
|
def test_get_interface_by_cfg_persistent_domain(self):
|
||||||
|
self.domain.XMLDesc.return_value = """<domain>
|
||||||
|
<devices>
|
||||||
|
<interface type="bridge">
|
||||||
|
<mac address="fa:16:3e:f9:af:ae"/>
|
||||||
|
<model type="virtio"/>
|
||||||
|
<driver name="qemu"/>
|
||||||
|
<source bridge="qbr84008d03-11"/>
|
||||||
|
<target dev="tap84008d03-11"/>
|
||||||
|
</interface>
|
||||||
|
</devices>
|
||||||
|
</domain>"""
|
||||||
|
cfg = vconfig.LibvirtConfigGuestInterface()
|
||||||
|
cfg.parse_str("""
|
||||||
|
<interface type="bridge">
|
||||||
|
<mac address="fa:16:3e:f9:af:ae"/>
|
||||||
|
<model type="virtio"/>
|
||||||
|
<driver name="qemu"/>
|
||||||
|
<source bridge="qbr84008d03-11"/>
|
||||||
|
<target dev="tap84008d03-11"/>
|
||||||
|
</interface>""")
|
||||||
|
self.assertIsNotNone(
|
||||||
|
self.guest.get_interface_by_cfg(
|
||||||
|
cfg, from_persistent_config=True))
|
||||||
|
self.assertIsNone(
|
||||||
|
self.guest.get_interface_by_cfg(
|
||||||
|
vconfig.LibvirtConfigGuestInterface(),
|
||||||
|
from_persistent_config=True))
|
||||||
|
self.domain.XMLDesc.assert_has_calls(
|
||||||
|
[
|
||||||
|
mock.call(fakelibvirt.VIR_DOMAIN_XML_INACTIVE),
|
||||||
|
mock.call(fakelibvirt.VIR_DOMAIN_XML_INACTIVE),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
def test_get_interface_by_cfg_vhostuser(self):
|
def test_get_interface_by_cfg_vhostuser(self):
|
||||||
self.domain.XMLDesc.return_value = """<domain>
|
self.domain.XMLDesc.return_value = """<domain>
|
||||||
|
|
|
@ -227,19 +227,22 @@ class Guest(object):
|
||||||
|
|
||||||
return interfaces
|
return interfaces
|
||||||
|
|
||||||
def get_interface_by_cfg(self, cfg):
|
def get_interface_by_cfg(self, cfg, from_persistent_config=False):
|
||||||
"""Lookup a full LibvirtConfigGuestDevice with
|
"""Lookup a full LibvirtConfigGuestDevice with
|
||||||
LibvirtConfigGuesDevice generated
|
LibvirtConfigGuesDevice generated
|
||||||
by nova.virt.libvirt.vif.get_config.
|
by nova.virt.libvirt.vif.get_config.
|
||||||
|
|
||||||
:param cfg: config object that represents the guest interface.
|
:param cfg: config object that represents the guest interface.
|
||||||
:type cfg: a subtype of LibvirtConfigGuestDevice object
|
:type cfg: a subtype of LibvirtConfigGuestDevice object
|
||||||
|
:param from_persistent_config: query the device from the persistent
|
||||||
|
domain instead of the live domain configuration
|
||||||
:returns: nova.virt.libvirt.config.LibvirtConfigGuestDevice instance
|
:returns: nova.virt.libvirt.config.LibvirtConfigGuestDevice instance
|
||||||
if found, else None
|
if found, else None
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if cfg:
|
if cfg:
|
||||||
interfaces = self.get_all_devices(type(cfg))
|
interfaces = self.get_all_devices(
|
||||||
|
type(cfg), from_persistent_config)
|
||||||
for interface in interfaces:
|
for interface in interfaces:
|
||||||
# NOTE(leehom) LibvirtConfigGuest get from domain and
|
# NOTE(leehom) LibvirtConfigGuest get from domain and
|
||||||
# LibvirtConfigGuest generated by
|
# LibvirtConfigGuest generated by
|
||||||
|
@ -312,13 +315,16 @@ class Guest(object):
|
||||||
config.parse_str(self._domain.XMLDesc(0))
|
config.parse_str(self._domain.XMLDesc(0))
|
||||||
return config
|
return config
|
||||||
|
|
||||||
def get_disk(self, device):
|
def get_disk(self, device, from_persistent_config=False):
|
||||||
"""Returns the disk mounted at device
|
"""Returns the disk mounted at device
|
||||||
|
|
||||||
:returns LivirtConfigGuestDisk: mounted at device or None
|
:returns LivirtConfigGuestDisk: mounted at device or None
|
||||||
"""
|
"""
|
||||||
|
flags = 0
|
||||||
|
if from_persistent_config:
|
||||||
|
flags |= libvirt.VIR_DOMAIN_XML_INACTIVE
|
||||||
try:
|
try:
|
||||||
doc = etree.fromstring(self._domain.XMLDesc(0))
|
doc = etree.fromstring(self._domain.XMLDesc(flags))
|
||||||
except Exception:
|
except Exception:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -343,18 +349,24 @@ class Guest(object):
|
||||||
|
|
||||||
return self.get_all_devices(vconfig.LibvirtConfigGuestDisk)
|
return self.get_all_devices(vconfig.LibvirtConfigGuestDisk)
|
||||||
|
|
||||||
def get_all_devices(self, devtype=None):
|
def get_all_devices(self, devtype=None, from_persistent_config=False):
|
||||||
"""Returns all devices for a guest
|
"""Returns all devices for a guest
|
||||||
|
|
||||||
:param devtype: a LibvirtConfigGuestDevice subclass class
|
:param devtype: a LibvirtConfigGuestDevice subclass class
|
||||||
|
:param from_persistent_config: query the device from the persistent
|
||||||
|
domain (i.e. inactive XML configuration that'll be used on next
|
||||||
|
start of the domain) instead of the live domain configuration
|
||||||
:returns: a list of LibvirtConfigGuestDevice instances
|
:returns: a list of LibvirtConfigGuestDevice instances
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
flags = 0
|
||||||
|
if from_persistent_config:
|
||||||
|
flags |= libvirt.VIR_DOMAIN_XML_INACTIVE
|
||||||
|
|
||||||
try:
|
try:
|
||||||
config = vconfig.LibvirtConfigGuest()
|
config = vconfig.LibvirtConfigGuest()
|
||||||
config.parse_str(
|
config.parse_str(
|
||||||
self._domain.XMLDesc(0))
|
self._domain.XMLDesc(flags))
|
||||||
except Exception:
|
except Exception:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue