mirror of
https://github.com/virt-manager/virt-manager.git
synced 2025-02-25 18:55:27 -06:00
xmlbuilder: Add replace_child
This will be used for UI XML editing of devices
This commit is contained in:
64
tests/xmlparse-xml/replace-child-build.xml
Normal file
64
tests/xmlparse-xml/replace-child-build.xml
Normal file
@@ -0,0 +1,64 @@
|
||||
<domain type="test">
|
||||
<uuid>00000000-1111-2222-3333-444444444444</uuid>
|
||||
<vcpu>1</vcpu>
|
||||
<os>
|
||||
<type arch="i686">hvm</type>
|
||||
</os>
|
||||
<features>
|
||||
<pae/>
|
||||
<vmport state="off"/>
|
||||
</features>
|
||||
<clock offset="utc"/>
|
||||
<pm>
|
||||
<suspend-to-mem enabled="no"/>
|
||||
<suspend-to-disk enabled="no"/>
|
||||
</pm>
|
||||
<devices>
|
||||
<emulator>/usr/bin/test-hv</emulator>
|
||||
<disk type="file" device="cdrom">
|
||||
<target dev="sda" bus="scsi"/>
|
||||
<readonly/>
|
||||
</disk>
|
||||
<disk type="file" device="cdrom">
|
||||
<target dev="sdb" bus="scsi"/>
|
||||
<readonly/>
|
||||
</disk>
|
||||
<disk type="file" device="cdrom">
|
||||
<target dev="sdz" bus="scsi"/>
|
||||
<readonly/>
|
||||
</disk>
|
||||
<disk type="file" device="cdrom">
|
||||
<target dev="sdd" bus="scsi"/>
|
||||
<readonly/>
|
||||
</disk>
|
||||
<disk type="file" device="cdrom">
|
||||
<target dev="sde" bus="scsi"/>
|
||||
<readonly/>
|
||||
</disk>
|
||||
<disk type="file" device="cdrom">
|
||||
<target dev="sdf" bus="scsi"/>
|
||||
<readonly/>
|
||||
</disk>
|
||||
<controller type="usb" index="0" model="ich9-ehci1"/>
|
||||
<controller type="usb" index="0" model="ich9-uhci1">
|
||||
<master startport="0"/>
|
||||
</controller>
|
||||
<controller type="usb" index="0" model="ich9-uhci2">
|
||||
<master startport="2"/>
|
||||
</controller>
|
||||
<controller type="usb" index="0" model="ich9-uhci3">
|
||||
<master startport="4"/>
|
||||
</controller>
|
||||
<console type="pty"/>
|
||||
<input type="tablet" bus="usb"/>
|
||||
<graphics type="spice" port="-1" tlsPort="-1" autoport="yes">
|
||||
<image compression="off"/>
|
||||
</graphics>
|
||||
<sound model="ich6"/>
|
||||
<video>
|
||||
<model type="qxl"/>
|
||||
</video>
|
||||
<redirdev bus="usb" type="spicevmc"/>
|
||||
<redirdev bus="usb" type="spicevmc"/>
|
||||
</devices>
|
||||
</domain>
|
||||
63
tests/xmlparse-xml/replace-child-parse.xml
Normal file
63
tests/xmlparse-xml/replace-child-parse.xml
Normal file
@@ -0,0 +1,63 @@
|
||||
<domain type="test">
|
||||
<uuid>00000000-1111-2222-3333-444444444444</uuid>
|
||||
<vcpu>1</vcpu>
|
||||
<os>
|
||||
<type arch="i686">hvm</type>
|
||||
</os>
|
||||
<features>
|
||||
<pae/>
|
||||
<vmport state="off"/>
|
||||
</features>
|
||||
<clock offset="utc"/>
|
||||
<pm>
|
||||
<suspend-to-mem enabled="no"/>
|
||||
<suspend-to-disk enabled="no"/>
|
||||
</pm>
|
||||
<devices>
|
||||
<emulator>/usr/bin/test-hv</emulator>
|
||||
<disk type="file" device="cdrom">
|
||||
<target dev="sda" bus="scsi"/>
|
||||
<readonly/>
|
||||
</disk>
|
||||
<disk type="file" device="cdrom">
|
||||
<target dev="sdb" bus="scsi"/>
|
||||
<readonly/>
|
||||
</disk>
|
||||
<disk type="file" device="cdrom">
|
||||
<target dev="sdz" bus="scsi"/>
|
||||
<readonly/>
|
||||
</disk>
|
||||
<disk type="file" device="cdrom">
|
||||
<target dev="sdd" bus="scsi"/>
|
||||
<readonly/>
|
||||
</disk>
|
||||
<disk device="cdrom">
|
||||
<target dev="sdw" bus="scsi"/>
|
||||
</disk>
|
||||
<disk type="file" device="cdrom">
|
||||
<target dev="sdf" bus="scsi"/>
|
||||
<readonly/>
|
||||
</disk>
|
||||
<controller type="usb" index="0" model="ich9-ehci1"/>
|
||||
<controller type="usb" index="0" model="ich9-uhci1">
|
||||
<master startport="0"/>
|
||||
</controller>
|
||||
<controller type="usb" index="0" model="ich9-uhci2">
|
||||
<master startport="2"/>
|
||||
</controller>
|
||||
<controller type="usb" index="0" model="ich9-uhci3">
|
||||
<master startport="4"/>
|
||||
</controller>
|
||||
<console type="pty"/>
|
||||
<input type="tablet" bus="usb"/>
|
||||
<graphics type="spice" port="-1" tlsPort="-1" autoport="yes">
|
||||
<image compression="off"/>
|
||||
</graphics>
|
||||
<sound model="ich6"/>
|
||||
<video>
|
||||
<model type="qxl"/>
|
||||
</video>
|
||||
<redirdev bus="usb" type="spicevmc"/>
|
||||
<redirdev bus="usb" type="spicevmc"/>
|
||||
</devices>
|
||||
</domain>
|
||||
@@ -1451,3 +1451,31 @@ class XMLParseTest(unittest.TestCase):
|
||||
raise AssertionError("Expected parse failure")
|
||||
except RuntimeError as e:
|
||||
self.assertTrue("'foo'" in str(e))
|
||||
|
||||
def testReplaceChildParse(self):
|
||||
buildfile = "tests/xmlparse-xml/replace-child-build.xml"
|
||||
parsefile = "tests/xmlparse-xml/replace-child-parse.xml"
|
||||
|
||||
def mkdisk(target):
|
||||
disk = virtinst.DeviceDisk(self.conn)
|
||||
disk.device = "cdrom"
|
||||
disk.bus = "scsi"
|
||||
disk.target = target
|
||||
return disk
|
||||
|
||||
guest = virtinst.Guest(self.conn)
|
||||
guest.add_device(mkdisk("sda"))
|
||||
guest.add_device(mkdisk("sdb"))
|
||||
guest.add_device(mkdisk("sdc"))
|
||||
guest.add_device(mkdisk("sdd"))
|
||||
guest.add_device(mkdisk("sde"))
|
||||
guest.add_device(mkdisk("sdf"))
|
||||
guest.devices.replace_child(guest.devices.disk[2], mkdisk("sdz"))
|
||||
guest.set_defaults(guest)
|
||||
utils.diff_compare(guest.get_xml(), buildfile)
|
||||
|
||||
guest = virtinst.Guest(self.conn, parsexml=guest.get_xml())
|
||||
newdisk = virtinst.DeviceDisk(self.conn,
|
||||
parsexml=mkdisk("sdw").get_xml())
|
||||
guest.devices.replace_child(guest.devices.disk[4], newdisk)
|
||||
utils.diff_compare(guest.get_xml(), parsefile)
|
||||
|
||||
@@ -109,6 +109,8 @@ class _XMLBase(object):
|
||||
raise NotImplementedError()
|
||||
def _node_remove_child(self, parentnode, childnode):
|
||||
raise NotImplementedError()
|
||||
def _node_replace_child(self, xpath, newnode):
|
||||
raise NotImplementedError()
|
||||
def _node_from_xml(self, xml):
|
||||
raise NotImplementedError()
|
||||
def _node_has_content(self, node):
|
||||
@@ -160,6 +162,13 @@ class _XMLBase(object):
|
||||
parentnode = self._node_make_stub(xpath)
|
||||
self._node_add_child(xpath, parentnode, newnode)
|
||||
|
||||
def node_replace_xml(self, xpath, xml):
|
||||
"""
|
||||
Replace the node at xpath with the passed in xml
|
||||
"""
|
||||
newnode = self._node_from_xml(xml)
|
||||
self._node_replace_child(xpath, newnode)
|
||||
|
||||
def node_force_remove(self, fullxpath):
|
||||
"""
|
||||
Remove the element referenced at the passed xpath, regardless
|
||||
@@ -390,5 +399,9 @@ class _Libxml2API(_XMLBase):
|
||||
parentnode.addChild(newnode)
|
||||
parentnode.addChild(libxml2.newText(endtext))
|
||||
|
||||
def _node_replace_child(self, xpath, newnode):
|
||||
oldnode = self._find(xpath)
|
||||
oldnode.replaceNode(newnode)
|
||||
|
||||
|
||||
XMLAPI = _Libxml2API
|
||||
|
||||
@@ -709,6 +709,24 @@ class XMLBuilder(object):
|
||||
self._xmlstate.xmlapi.node_force_remove(xpath)
|
||||
self._set_child_xpaths()
|
||||
|
||||
def replace_child(self, origobj, newobj):
|
||||
"""
|
||||
Replace the origobj child with the newobj. For is_build, this
|
||||
replaces the objects, but for !is_build this only replaces the
|
||||
XML and keeps the object references in place. This is hacky and
|
||||
it's fixable but at time or writing it doesn't matter for
|
||||
our usecases.
|
||||
"""
|
||||
if not self._xmlstate.is_build:
|
||||
xpath = origobj.get_xml_id()
|
||||
indent = 2 * xpath.count("/")
|
||||
xml = util.xml_indent(newobj.get_xml(), indent).strip()
|
||||
self._xmlstate.xmlapi.node_replace_xml(xpath, xml)
|
||||
else:
|
||||
origidx = origobj.get_xml_idx()
|
||||
self.remove_child(origobj)
|
||||
self.add_child(newobj, idx=origidx)
|
||||
|
||||
def _prop_is_unset(self, propname):
|
||||
"""
|
||||
Return True if the property name has never had a value set
|
||||
|
||||
Reference in New Issue
Block a user