Skip to content

Commit a634103

Browse files
author
Balazs Gibizer
committed
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
1 parent f5cd6e2 commit a634103

File tree

3 files changed

+97
-7
lines changed

3 files changed

+97
-7
lines changed

nova/tests/unit/virt/libvirt/test_driver.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24034,6 +24034,41 @@ def test_get_disk_xml(self):
2403424034

2403524035
self.assertIsNone(guest.get_disk('vdc'))
2403624036

24037+
dom.XMLDesc.assert_has_calls([mock.call(0)] * 3)
24038+
24039+
def test_get_disk_xml_from_persistent_config(self):
24040+
dom_xml = """
24041+
<domain type="kvm">
24042+
<devices>
24043+
<disk type="file">
24044+
<source file="disk1_file"/>
24045+
<target dev="vda" bus="virtio"/>
24046+
<serial>0e38683e-f0af-418f-a3f1-6b67ea0f919d</serial>
24047+
</disk>
24048+
<disk type="block">
24049+
<source dev="/path/to/dev/1"/>
24050+
<target dev="vdb" bus="virtio" serial="1234"/>
24051+
</disk>
24052+
</devices>
24053+
</domain>
24054+
"""
24055+
24056+
diska_xml = """<disk type="file" device="disk">
24057+
<source file="disk1_file"/>
24058+
<target bus="virtio" dev="vda"/>
24059+
<serial>0e38683e-f0af-418f-a3f1-6b67ea0f919d</serial>
24060+
</disk>"""
24061+
24062+
dom = mock.MagicMock()
24063+
dom.XMLDesc.return_value = dom_xml
24064+
guest = libvirt_guest.Guest(dom)
24065+
24066+
actual_diska_xml = guest.get_disk(
24067+
'vda', from_persistent_config=True).to_xml()
24068+
self.assertXmlEqual(diska_xml, actual_diska_xml)
24069+
dom.XMLDesc.assert_called_once_with(
24070+
fakelibvirt.VIR_DOMAIN_XML_INACTIVE)
24071+
2403724072
def test_vcpu_model_from_config(self):
2403824073
drv = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
2403924074
vcpu_model = drv._cpu_config_to_vcpu_model(None, None)

nova/tests/unit/virt/libvirt/test_guest.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,49 @@ def test_get_devices(self):
540540
self.assertIsNotNone(
541541
self.guest.get_interface_by_cfg(cfg))
542542
self.assertIsNone(self.guest.get_interface_by_cfg(None))
543+
self.domain.XMLDesc.assert_has_calls([mock.call(0)] * 6)
544+
545+
# now check if the persistent config can be queried too
546+
self.domain.XMLDesc.reset_mock()
547+
devs = self.guest.get_all_devices(
548+
devtype=None, from_persistent_config=True)
549+
self.domain.XMLDesc.assert_called_once_with(
550+
fakelibvirt.VIR_DOMAIN_XML_INACTIVE)
551+
552+
def test_get_interface_by_cfg_persistent_domain(self):
553+
self.domain.XMLDesc.return_value = """<domain>
554+
<devices>
555+
<interface type="bridge">
556+
<mac address="fa:16:3e:f9:af:ae"/>
557+
<model type="virtio"/>
558+
<driver name="qemu"/>
559+
<source bridge="qbr84008d03-11"/>
560+
<target dev="tap84008d03-11"/>
561+
</interface>
562+
</devices>
563+
</domain>"""
564+
cfg = vconfig.LibvirtConfigGuestInterface()
565+
cfg.parse_str("""
566+
<interface type="bridge">
567+
<mac address="fa:16:3e:f9:af:ae"/>
568+
<model type="virtio"/>
569+
<driver name="qemu"/>
570+
<source bridge="qbr84008d03-11"/>
571+
<target dev="tap84008d03-11"/>
572+
</interface>""")
573+
self.assertIsNotNone(
574+
self.guest.get_interface_by_cfg(
575+
cfg, from_persistent_config=True))
576+
self.assertIsNone(
577+
self.guest.get_interface_by_cfg(
578+
vconfig.LibvirtConfigGuestInterface(),
579+
from_persistent_config=True))
580+
self.domain.XMLDesc.assert_has_calls(
581+
[
582+
mock.call(fakelibvirt.VIR_DOMAIN_XML_INACTIVE),
583+
mock.call(fakelibvirt.VIR_DOMAIN_XML_INACTIVE),
584+
]
585+
)
543586

544587
def test_get_interface_by_cfg_vhostuser(self):
545588
self.domain.XMLDesc.return_value = """<domain>

nova/virt/libvirt/guest.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -227,19 +227,22 @@ def get_interfaces(self):
227227

228228
return interfaces
229229

230-
def get_interface_by_cfg(self, cfg):
230+
def get_interface_by_cfg(self, cfg, from_persistent_config=False):
231231
"""Lookup a full LibvirtConfigGuestDevice with
232232
LibvirtConfigGuesDevice generated
233233
by nova.virt.libvirt.vif.get_config.
234234
235235
:param cfg: config object that represents the guest interface.
236236
:type cfg: a subtype of LibvirtConfigGuestDevice object
237+
:param from_persistent_config: query the device from the persistent
238+
domain instead of the live domain configuration
237239
:returns: nova.virt.libvirt.config.LibvirtConfigGuestDevice instance
238240
if found, else None
239241
"""
240242

241243
if cfg:
242-
interfaces = self.get_all_devices(type(cfg))
244+
interfaces = self.get_all_devices(
245+
type(cfg), from_persistent_config)
243246
for interface in interfaces:
244247
# NOTE(leehom) LibvirtConfigGuest get from domain and
245248
# LibvirtConfigGuest generated by
@@ -312,13 +315,16 @@ def get_config(self):
312315
config.parse_str(self._domain.XMLDesc(0))
313316
return config
314317

315-
def get_disk(self, device):
318+
def get_disk(self, device, from_persistent_config=False):
316319
"""Returns the disk mounted at device
317320
318321
:returns LivirtConfigGuestDisk: mounted at device or None
319322
"""
323+
flags = 0
324+
if from_persistent_config:
325+
flags |= libvirt.VIR_DOMAIN_XML_INACTIVE
320326
try:
321-
doc = etree.fromstring(self._domain.XMLDesc(0))
327+
doc = etree.fromstring(self._domain.XMLDesc(flags))
322328
except Exception:
323329
return None
324330

@@ -343,18 +349,24 @@ def get_all_disks(self):
343349

344350
return self.get_all_devices(vconfig.LibvirtConfigGuestDisk)
345351

346-
def get_all_devices(self, devtype=None):
352+
def get_all_devices(self, devtype=None, from_persistent_config=False):
347353
"""Returns all devices for a guest
348354
349355
:param devtype: a LibvirtConfigGuestDevice subclass class
350-
356+
:param from_persistent_config: query the device from the persistent
357+
domain (i.e. inactive XML configuration that'll be used on next
358+
start of the domain) instead of the live domain configuration
351359
:returns: a list of LibvirtConfigGuestDevice instances
352360
"""
353361

362+
flags = 0
363+
if from_persistent_config:
364+
flags |= libvirt.VIR_DOMAIN_XML_INACTIVE
365+
354366
try:
355367
config = vconfig.LibvirtConfigGuest()
356368
config.parse_str(
357-
self._domain.XMLDesc(0))
369+
self._domain.XMLDesc(flags))
358370
except Exception:
359371
return []
360372

0 commit comments

Comments
 (0)