Guest: Convert to new style XML prop, drop a bunch of XML infrastructure

Now every XML property is new style, without explicit local get/set
handlers. Drop a bunch of XML infrastructure that was helping with the
transition.
This commit is contained in:
Cole Robinson 2013-07-17 17:58:24 -04:00
parent 4e4ce6d395
commit 2ba3ec2684
82 changed files with 611 additions and 774 deletions

View File

@ -20,9 +20,9 @@
<devices>
<emulator>/usr/lib/xen/bin/qemu-dm</emulator>
<disk type="block" device="floppy">
<driver type="vmdk"/>
<target dev="fda" bus="fdc"/>
<address type="drive" controller="0" bus="0" target="0" unit="0"/>
<driver type="vmdk"/>
<source dev="/disk-pool/diskvol1-clone"/>
</disk>
<disk type="block" device="disk">

View File

@ -9,7 +9,9 @@
<boot dev="network"/>
</os>
<features>
<acpi/><apic/><pae/>
<acpi/>
<apic/>
<pae/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>
@ -35,7 +37,9 @@
<boot dev="network"/>
</os>
<features>
<acpi/><apic/><pae/>
<acpi/>
<apic/>
<pae/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -9,7 +9,9 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/><pae/>
<acpi/>
<apic/>
<pae/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -11,7 +11,9 @@
<cmdline>method=tests/cli-test-xml/faketree console=ttyS0</cmdline>
</os>
<features>
<acpi/><apic/><pae/>
<acpi/>
<apic/>
<pae/>
</features>
<cpu mode="custom" match="exact">
<model>core2duo</model>
@ -65,7 +67,9 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/><pae/>
<acpi/>
<apic/>
<pae/>
</features>
<cpu mode="custom" match="exact">
<model>core2duo</model>

View File

@ -9,7 +9,9 @@
<boot dev="fd"/>
</os>
<features>
<acpi/><apic/><pae/>
<acpi/>
<apic/>
<pae/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -10,7 +10,9 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/><pae/>
<acpi/>
<apic/>
<pae/>
</features>
<clock offset="localtime"/>
<on_poweroff>destroy</on_poweroff>
@ -53,7 +55,9 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/><pae/>
<acpi/>
<apic/>
<pae/>
</features>
<clock offset="localtime"/>
<on_poweroff>destroy</on_poweroff>
@ -96,7 +100,9 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/><pae/>
<acpi/>
<apic/>
<pae/>
</features>
<clock offset="localtime"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -6,7 +6,8 @@
<vcpu>1</vcpu>
<bootloader>/usr/bin/pygrub</bootloader>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>

View File

@ -14,7 +14,9 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/><pae/>
<acpi/>
<apic/>
<pae/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>
@ -100,7 +102,9 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/><pae/>
<acpi/>
<apic/>
<pae/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -9,7 +9,9 @@
<boot dev="network"/>
</os>
<features>
<acpi/><apic/><pae/>
<acpi/>
<apic/>
<pae/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -9,7 +9,9 @@
<boot dev="cdrom"/>
</os>
<features>
<acpi/><apic/><pae/>
<acpi/>
<apic/>
<pae/>
</features>
<cpu mode="custom" match="exact">
<model>Penryn</model>

View File

@ -9,7 +9,9 @@
<boot dev="fd"/>
</os>
<features>
<acpi/><apic/><pae/>
<acpi/>
<apic/>
<pae/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -9,7 +9,9 @@
<boot dev="network"/>
</os>
<features>
<acpi/><apic/><pae/>
<acpi/>
<apic/>
<pae/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>
@ -35,7 +37,9 @@
<boot dev="network"/>
</os>
<features>
<acpi/><apic/><pae/>
<acpi/>
<apic/>
<pae/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -10,7 +10,9 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/><pae/>
<acpi/>
<apic/>
<pae/>
</features>
<cpu>
<topology sockets="1" cores="4" threads="1"/>
@ -48,7 +50,9 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/><pae/>
<acpi/>
<apic/>
<pae/>
</features>
<cpu>
<topology sockets="1" cores="4" threads="1"/>
@ -86,7 +90,9 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/><pae/>
<acpi/>
<apic/>
<pae/>
</features>
<cpu>
<topology sockets="1" cores="4" threads="1"/>

View File

@ -6,7 +6,8 @@
<vcpu>1</vcpu>
<bootloader>/usr/bin/pygrub</bootloader>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>

View File

@ -11,7 +11,9 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/><pae/>
<acpi/>
<apic/>
<pae/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -6,7 +6,8 @@
<vcpu>1</vcpu>
<bootloader>/usr/bin/pygrub</bootloader>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>

View File

@ -12,7 +12,8 @@
<cmdline>method=tests/cli-test-xml/faketree</cmdline>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>
@ -48,7 +49,8 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -11,7 +11,8 @@
<cmdline>method=tests/cli-test-xml/faketree</cmdline>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<on_poweroff>destroy</on_poweroff>
<on_reboot>destroy</on_reboot>
@ -40,7 +41,8 @@
<vcpu>1</vcpu>
<bootloader>/usr/bin/pygrub</bootloader>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>

View File

@ -11,7 +11,8 @@
<cmdline>method=tests/cli-test-xml/faketree</cmdline>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<on_poweroff>destroy</on_poweroff>
<on_reboot>destroy</on_reboot>
@ -40,7 +41,8 @@
<vcpu>1</vcpu>
<bootloader>/usr/bin/pygrub</bootloader>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>

View File

@ -9,7 +9,8 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -9,7 +9,9 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/><pae/>
<acpi/>
<apic/>
<pae/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -3,14 +3,15 @@
<uuid>12345678-1234-1234-1234-123456789012</uuid>
<memory>409600</memory>
<currentMemory>204800</currentMemory>
<vcpu cpuset="0,1,2,3,4,5,6,7" current="5">7</vcpu>
<vcpu cpuset="0,1,2,3,4,5,6,7">7</vcpu>
<os>
<type arch="i686">hvm</type>
<loader>/usr/lib/xen/boot/hvmloader</loader>
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<cpu match="minimum" mode="custom">
<model>footest</model>

View File

@ -1,38 +0,0 @@
<domain type="xen">
<name>TestGuest</name>
<uuid>12345678-1234-1234-1234-123456789012</uuid>
<memory>409600</memory>
<currentMemory>204800</currentMemory>
<vcpu>5</vcpu>
<os>
<type arch="i686">hvm</type>
<loader>/usr/lib/xen/boot/hvmloader</loader>
<boot dev="network"/>
</os>
<features>
<acpi/><apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>restart</on_crash>
<devices>
<emulator>/usr/lib/xen/bin/qemu-dm</emulator>
<interface type="bridge">
<source bridge="br0"/>
<mac address="22:22:33:44:55:66"/>
</interface>
<interface type="bridge">
<mac address="22:22:33:44:55:67"/>
<source bridge="foobr0"/>
</interface>
<interface type="bridge">
<mac address="22:22:33:44:55:68"/>
</interface>
<input type="mouse" bus="ps2"/>
<graphics type="sdl" display=":3.4" xauth="/tmp/.Xauthority"/>
<console type="pty"/>
</devices>
</domain>

View File

@ -10,7 +10,8 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -10,7 +10,8 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -11,7 +11,8 @@
<bootmenu enable="yes"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -10,7 +10,8 @@
<boot dev="network"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -10,7 +10,8 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -10,7 +10,8 @@
<boot dev="network"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -14,7 +14,8 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="localtime"/>
<on_poweroff>destroy</on_poweroff>
@ -40,11 +41,11 @@
<target dev="sdb" bus="scsi"/>
<address type="spapr-vio"/>
</disk>
<controller type="ide" index="3"/>
<controller type="virtio-serial" index="0" ports="32" vectors="17"/>
<controller type="scsi" index="0">
<address type="spapr-vio"/>
</controller>
<controller type="ide" index="3"/>
<controller type="virtio-serial" index="0" ports="32" vectors="17"/>
<interface type="network">
<source network="default"/>
<mac address="22:22:33:44:55:66"/>

View File

@ -10,7 +10,8 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -10,7 +10,8 @@
<boot dev="network"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -10,7 +10,8 @@
<boot dev="network"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -10,7 +10,8 @@
<boot dev="network"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -10,7 +10,8 @@
<boot dev="network"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -10,7 +10,8 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -9,7 +9,8 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -9,7 +9,8 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -9,7 +9,8 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -9,7 +9,8 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -10,7 +10,8 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -9,7 +9,8 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -11,7 +11,8 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -11,7 +11,8 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -12,7 +12,8 @@
<cmdline>my kernel args</cmdline>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -14,7 +14,8 @@
<bootmenu enable="no"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -10,7 +10,8 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -10,7 +10,8 @@
<boot dev="cdrom"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -10,7 +10,8 @@
<boot dev="network"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -11,7 +11,8 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -11,7 +11,8 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="localtime"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -11,7 +11,8 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -11,7 +11,8 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -11,7 +11,8 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -11,7 +11,8 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -14,7 +14,8 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -11,7 +11,8 @@
<cmdline>method=tests/cli-test-xml/fakerhel6tree</cmdline>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -9,7 +9,8 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="utc"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -10,7 +10,8 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="localtime"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -9,7 +9,8 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="localtime"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -9,7 +9,8 @@
<boot dev="hd"/>
</os>
<features>
<acpi/><apic/>
<acpi/>
<apic/>
</features>
<clock offset="localtime"/>
<on_poweroff>destroy</on_poweroff>

View File

@ -877,7 +877,7 @@ class TestXMLConfig(unittest.TestCase):
# Cpuset
cpustr = g.generate_cpuset(g.conn, g.memory)
g.cpuset = cpustr
g.maxvcpus = 7
g.vcpus = 7
g.cpu.model = "footest"
g.cpu.vendor = "Intel"
@ -920,7 +920,8 @@ class TestXMLConfig(unittest.TestCase):
i = utils.make_pxe_installer()
g = utils.get_basic_fullyvirt_guest(installer=i)
g.add_usb_ich9_controllers()
for dev in virtinst.VirtualController.get_usb2_controllers(g.conn):
g.add_device(dev)
self._compare(g, "boot-usb2", False)
@ -969,35 +970,41 @@ class TestXMLConfig(unittest.TestCase):
origfunc = None
util = None
try:
i = utils.make_pxe_installer()
g = utils.get_basic_fullyvirt_guest(installer=i)
util = getattr(virtinst, "util")
origfunc = util.default_bridge
def newbridge(ignore_conn):
return ["bridge", "br0"]
return ["bridge", "bzz0"]
util.default_bridge = newbridge
dev1 = virtinst.VirtualNetworkInterface(g.conn)
dev1 = virtinst.VirtualNetworkInterface(utils.get_conn())
dev1.macaddr = "22:22:33:44:55:66"
g.add_device(dev1)
dev2 = virtinst.VirtualNetworkInterface(g.conn,
parsexml=dev1.get_xml_config().strip("\n"))
dev2 = virtinst.VirtualNetworkInterface(utils.get_conn(),
parsexml=dev1.get_xml_config())
dev2.source = None
dev2.source = "foobr0"
dev2.macaddr = "22:22:33:44:55:67"
g.add_device(dev2)
dev3 = virtinst.VirtualNetworkInterface(g.conn,
parsexml=dev1.get_xml_config().strip("\n"))
dev3 = virtinst.VirtualNetworkInterface(utils.get_conn(),
parsexml=dev1.get_xml_config())
dev3.source = None
dev3.macaddr = "22:22:33:44:55:68"
g.add_device(dev3)
self._compare(g, "boot-default-bridge", False, do_create=False)
dev3.type = dev3.TYPE_USER
self._compare(g, None, False)
utils.diff_compare(dev1.get_xml_config(), None,
" <interface type=\"bridge\">\n"
" <source bridge=\"bzz0\"/>\n"
" <mac address=\"22:22:33:44:55:66\"/>\n"
" </interface>")
utils.diff_compare(dev2.get_xml_config(), None,
"<interface type=\"bridge\">\n"
" <mac address=\"22:22:33:44:55:67\"/>\n"
" <source bridge=\"foobr0\"/>\n"
" </interface>\n")
utils.diff_compare(dev3.get_xml_config(), None,
"<interface type=\"bridge\">\n"
" <mac address=\"22:22:33:44:55:68\"/>\n"
" </interface>\n")
finally:
if util and origfunc:
util.default_bridge = origfunc

View File

@ -24,9 +24,9 @@
<feature name="addfeature" policy="require"/>
</cpu>
<clock offset="localtime"/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>restart</on_crash>
<on_poweroff>restart</on_poweroff>
<on_reboot>destroy</on_reboot>
<on_crash>destroy</on_crash>
<vcpu cpuset="1-5,15" current="10">12</vcpu>
<devices>
<emulator>/usr/binnnn/fooemu</emulator>

View File

@ -103,8 +103,8 @@ class XMLParseTest(unittest.TestCase):
check = self._make_checker(guest)
check("name", "TestGuest", "change_name")
check("description", None, "Hey desc changed&")
check("maxvcpus", 5, 12)
check("vcpus", 12, 10)
check("vcpus", 5, 12)
check("curvcpus", None, 10)
check("cpuset", "1-3", "1-8,^6", "1-5,15")
check("maxmemory", 409600, 512000)
check("memory", 204800, 1024000)
@ -115,6 +115,9 @@ class XMLParseTest(unittest.TestCase):
check("hugepage", False, True)
check("type", "kvm", "test")
check("bootloader", None, "pygrub")
check("on_poweroff", "destroy", "restart")
check("on_reboot", "restart", "destroy")
check("on_crash", "restart", "destroy")
check = self._make_checker(guest.clock)
check("offset", "utc", "localtime")

View File

@ -480,8 +480,8 @@ class vmmDomain(vmmLibvirtObject):
# CPU define methods
def define_vcpus(self, vcpus, maxvcpus):
def change(guest):
guest.vcpus = int(vcpus)
guest.maxvcpus = int(maxvcpus)
guest.curvcpus = int(vcpus)
guest.vcpus = int(maxvcpus)
return self._redefine_guest(change)
def define_cpuset(self, cpuset):
def change(guest):
@ -813,7 +813,9 @@ class vmmDomain(vmmLibvirtObject):
guest.remove_device(dev)
if newmodel == "ich9-ehci1":
guest.add_usb_ich9_controllers()
for dev in virtinst.VirtualController.get_usb2_controllers(
guest.conn):
guest.add_device(dev)
return self._redefine_device(change, devobj)
@ -986,9 +988,9 @@ class vmmDomain(vmmLibvirtObject):
return int(self._get_guest().vcpus)
def vcpu_max_count(self):
guest = self._get_guest()
has_xml_max = (guest.vcpus != guest.maxvcpus)
has_xml_max = (guest.curvcpus != guest.vcpus)
if has_xml_max or not self.is_active():
return guest.maxvcpus
return guest.vcpus
if self._startup_vcpus is None:
self._startup_vcpus = int(self.vcpu_count())

View File

@ -19,8 +19,6 @@
from virtinst.xmlbuilder import XMLBuilder, XMLProperty
import libxml2
class CPUFeature(XMLBuilder):
"""
@ -31,7 +29,6 @@ class CPUFeature(XMLBuilder):
_XML_PROP_ORDER = ["_xmlname", "policy"]
_XML_ROOT_NAME = "cpu"
_XML_XPATH_RELATIVE = True
_XML_INDENT = 4
def __init__(self, conn, name, parsexml=None, parsexmlnode=None):
@ -47,13 +44,13 @@ class CPUFeature(XMLBuilder):
def _name_xpath(self):
return "./cpu/feature[@name='%s']/@name" % self._name
_xmlname = XMLProperty(name="feature name",
xml_get_xpath=_name_xpath,
xml_set_xpath=_name_xpath)
make_getter_xpath_cb=_name_xpath,
make_setter_xpath_cb=_name_xpath)
def _policy_xpath(self):
return "./cpu/feature[@name='%s']/@policy" % self._name
policy = XMLProperty(name="feature policy",
xml_get_xpath=_policy_xpath,
xml_set_xpath=_policy_xpath)
make_getter_xpath_cb=_policy_xpath,
make_setter_xpath_cb=_policy_xpath)
def clear(self):
self.policy = None
@ -70,13 +67,11 @@ class CPU(XMLBuilder):
_dumpxml_xpath = "/domain/cpu"
_XML_ROOT_NAME = "cpu"
_XML_INDENT = 2
_XML_XPATH_RELATIVE = True
_XML_PROP_ORDER = ["mode", "match", "model", "vendor",
"sockets", "cores", "threads"]
"sockets", "cores", "threads", "_features"]
def __init__(self, conn, parsexml=None, parsexmlnode=None):
self._features = []
self._XML_SUB_ELEMENTS = self._XML_SUB_ELEMENTS + ["_features"]
XMLBuilder.__init__(self, conn, parsexml, parsexmlnode)
def _parsexml(self, xml, node):

View File

@ -24,6 +24,5 @@ class Clock(XMLBuilder):
_dumpxml_xpath = "/domain/clock"
_XML_INDENT = 2
_XML_ROOT_NAME = "clock"
_XML_XPATH_RELATIVE = True
offset = XMLProperty(xpath="./clock/@offset")

View File

@ -101,7 +101,7 @@ class Cloner(object):
return self._clone_name
def set_clone_name(self, name):
try:
self._valid_guest.set_name(name)
self._valid_guest.name = name
except ValueError, e:
raise ValueError(_("Invalid name for new guest: %s") % e)
@ -111,7 +111,7 @@ class Cloner(object):
def set_clone_uuid(self, uuid):
try:
self._valid_guest.set_uuid(uuid)
self._valid_guest.uuid = uuid
except ValueError, e:
raise ValueError(_("Invalid uuid for new guest: %s") % e)

View File

@ -286,7 +286,7 @@ class DistroInstaller(Installer.Installer):
guest.os.os_type)
(kernelfn, initrdfn, args) = media
if guest.get_os_autodetect():
if guest.os_autodetect:
if os_type:
logging.debug("Auto detected OS type as: %s", os_type)
guest.os_type = os_type

View File

@ -27,7 +27,6 @@ class DomainFeatures(XMLBuilder):
_dumpxml_xpath = "/domain/features"
_XML_ROOT_NAME = "features"
_XML_INDENT = 2
_XML_XPATH_RELATIVE = True
_XML_PROP_ORDER = ["acpi", "apic", "pae"]
acpi = XMLProperty(xpath="./features/acpi", is_tri=True)
@ -40,9 +39,3 @@ class DomainFeatures(XMLBuilder):
return getattr(self, attr)
def __delitem__(self, attr):
return setattr(self, attr, None)
def _cleanup_xml(self, xml):
# Format it in the old style
xml = xml.replace("\n ", "")
xml = xml.replace("<features>", "<features>\n ")
return xml

View File

@ -98,7 +98,6 @@ class DomainNumatune(XMLBuilder):
_dumpxml_xpath = "/domain/numatune"
_XML_ROOT_NAME = "numatune"
_XML_INDENT = 2
_XML_XPATH_RELATIVE = True
_XML_PROP_ORDER = ["memory_mode", "memory_nodeset"]
memory_nodeset = XMLProperty(xpath="./numatune/memory/@nodeset")

View File

@ -35,8 +35,6 @@ from virtinst.osxml import OSXML
from virtinst.xmlbuilder import XMLBuilder, XMLProperty
from virtinst.VirtualDevice import VirtualDevice
from virtinst.VirtualDisk import VirtualDisk
from virtinst.VirtualInputDevice import VirtualInputDevice
from virtinst.VirtualController import VirtualController
from virtinst.Clock import Clock
from virtinst.Seclabel import Seclabel
from virtinst.CPU import CPU
@ -163,27 +161,22 @@ class Guest(XMLBuilder):
return cpustr
_XML_ROOT_NAME = "domain"
_XML_INDENT = 0
_XML_PROP_ORDER = ["type", "name", "uuid", "description",
"maxmemory", "memory", "hugepage", "vcpus", "curvcpus",
"numatune", "bootloader", "os", "features", "cpu", "clock",
"on_poweroff", "on_reboot", "on_crash", "emulator", "all_devices",
"seclabel"]
def __init__(self, conn, parsexml=None, parsexmlnode=None):
self._name = None
self._uuid = None
self._memory = None
self._maxmemory = None
self._hugepage = None
self._vcpus = 1
self._maxvcpus = 1
self._cpuset = None
self._autostart = False
self._clock = None
self._seclabel = None
self._description = None
self._features = None
self._replace = None
self._emulator = None
self._type = None
self.autostart = False
self.replace = False
self.os_autodetect = False
self._os_type = None
self._os_variant = None
self._os_autodetect = False
self.installer = None
@ -204,8 +197,6 @@ class Guest(XMLBuilder):
self.installer = virtinst.DistroInstaller(conn)
self._type = "xen"
# Need to do this after all parameter init
self.os = OSXML(self.conn, parsexml, parsexmlnode)
self.features = DomainFeatures(self.conn)
@ -219,123 +210,73 @@ class Guest(XMLBuilder):
# Property accessors #
######################
# Domain name of the guest
def get_name(self):
return self._name
def set_name(self, val):
def _validate_name(self, val):
if val == self.name:
return
util.validate_name(_("Guest"), val, lencheck=True)
if self.replace:
return
do_fail = False
if self.replace is not True:
try:
self.conn.lookupByName(val)
do_fail = True
except:
# Name not found
pass
try:
self.conn.lookupByName(val)
except:
return
raise ValueError(_("Guest name '%s' is already in use.") % val)
name = XMLProperty(xpath="./name", validate_cb=_validate_name)
if do_fail:
raise ValueError(_("Guest name '%s' is already in use.") % val)
self._name = val
name = XMLProperty(get_name, set_name,
xpath="./name")
# Memory allocated to the guest. Should be given in MB
def get_memory(self):
return self._memory
def set_memory(self, val):
self._memory = val
def _set_memory(self, val):
if val is None:
return None
if self.maxmemory is None or self.maxmemory < val:
self.maxmemory = val
memory = XMLProperty(get_memory, set_memory, is_int=True,
xpath="./currentMemory")
# Memory allocated to the guest. Should be given in MB
def get_maxmemory(self):
return self._maxmemory
def set_maxmemory(self, val):
self._maxmemory = val
maxmemory = XMLProperty(get_maxmemory, set_maxmemory, is_int=True,
xpath="./memory")
def get_hugepage(self):
return self._hugepage
def set_hugepage(self, val):
if val is None:
return val
self._hugepage = bool(val)
hugepage = XMLProperty(get_hugepage, set_hugepage,
xpath="./memoryBacking/hugepages", is_bool=True)
# UUID for the guest
def get_uuid(self):
return self._uuid
def set_uuid(self, val):
val = util.validate_uuid(val)
self._uuid = val
uuid = XMLProperty(get_uuid, set_uuid,
xpath="./uuid")
def __validate_cpus(self, val):
val = int(val)
if val < 1:
raise ValueError(_("Number of vcpus must be a positive integer."))
return val
memory = XMLProperty(xpath="./currentMemory", is_int=True,
default_cb=lambda s: 1,
set_converter=_set_memory)
maxmemory = XMLProperty(xpath="./memory", is_int=True)
# number of vcpus for the guest
def get_vcpus(self):
return self._vcpus
def set_vcpus(self, val):
val = self.__validate_cpus(val)
self._vcpus = val
def _set_vcpus(self, val):
if val is None:
return None
# Don't force set maxvcpus unless already specified
if self.maxvcpus is not None and self.maxvcpus < val:
self.maxvcpus = val
def _vcpus_get_converter(self, val):
# If no current VCPUs, return maxvcpus
if not val:
val = self.maxvcpus
return int(val)
vcpus = XMLProperty(get_vcpus, set_vcpus,
xpath="./vcpu/@current",
get_converter=_vcpus_get_converter)
def _get_maxvcpus(self):
return self._maxvcpus
def _set_maxvcpus(self, val):
val = self.__validate_cpus(val)
self._maxvcpus = val
maxvcpus = XMLProperty(_get_maxvcpus, _set_maxvcpus,
xpath="./vcpu", is_int=True)
# set phy-cpus for the guest
def get_cpuset(self):
return self._cpuset
def set_cpuset(self, val):
if val is None or val == "":
self._cpuset = None
return
# Don't force set curvcpus unless already specified
if self.curvcpus is not None and self.curvcpus > val:
self.curvcpus = val
return val
vcpus = XMLProperty(xpath="./vcpu", is_int=True,
set_converter=_set_vcpus,
default_cb=lambda s: 1)
curvcpus = XMLProperty(xpath="./vcpu/@current", is_int=True)
def _validate_cpuset(self, val):
DomainNumatune.validate_cpuset(self.conn, val)
self._cpuset = val
cpuset = XMLProperty(get_cpuset, set_cpuset,
xpath="./vcpu/@cpuset")
cpuset = XMLProperty(xpath="./vcpu/@cpuset",
validate_cb=_validate_cpuset)
type = XMLProperty(xpath="./@type", default_cb=lambda s: "xen")
hugepage = XMLProperty(xpath="./memoryBacking/hugepages", is_bool=True)
uuid = XMLProperty(xpath="./uuid",
validate_cb=lambda s, v: util.validate_uuid(v))
bootloader = XMLProperty(xpath="./bootloader")
description = XMLProperty(xpath="./description")
emulator = XMLProperty(xpath="./devices/emulator")
on_poweroff = XMLProperty(xpath="./on_poweroff",
default_cb=lambda s: "destroy")
on_reboot = XMLProperty(xpath="./on_reboot")
on_crash = XMLProperty(xpath="./on_crash")
###############################
# Distro detection properties #
###############################
# GAH! - installer.os_type = "hvm" or "xen" (aka xen paravirt)
# guest.os_type = "Solaris", "Windows", "Linux"
# FIXME: We should really rename this property to something else,
# change it throughout the codebase for readability sake, but
# maintain back compat.
def get_os_type(self):
return self._os_type
def set_os_type(self, val):
if type(val) is not str:
raise ValueError(_("OS type must be a string."))
val = val.lower()
if val in self._OS_TYPES:
if self._os_type != val:
# Invalidate variant, since it may not apply to the new os type
@ -344,14 +285,11 @@ class Guest(XMLBuilder):
else:
raise ValueError(_("OS type '%s' does not exist in our "
"dictionary") % val)
os_type = property(get_os_type, set_os_type)
def get_os_variant(self):
return self._os_variant
def set_os_variant(self, val):
if type(val) is not str:
raise ValueError(_("OS variant must be a string."))
val = val.lower()
if self.os_type:
@ -374,49 +312,12 @@ class Guest(XMLBuilder):
if not found:
raise ValueError(_("Unknown OS variant '%s'" % val))
os_variant = property(get_os_variant, set_os_variant)
def set_os_autodetect(self, val):
self._os_autodetect = bool(val)
def get_os_autodetect(self):
return self._os_autodetect
os_autodetect = property(get_os_autodetect, set_os_autodetect)
# Get the current variants 'distro' tag: 'rhel', 'fedora', etc.
def get_os_distro(self):
return self._lookup_osdict_key("distro")
os_distro = property(get_os_distro)
def get_autostart(self):
return self._autostart
def set_autostart(self, val):
self._autostart = bool(val)
autostart = property(get_autostart, set_autostart,
doc="Have domain autostart when the host boots.")
def _get_description(self):
return self._description
def _set_description(self, val):
self._description = val
description = XMLProperty(_get_description, _set_description,
xpath="./description")
def _get_emulator(self):
return self._emulator
def _set_emulator(self, val):
self._emulator = val
emulator = XMLProperty(_get_emulator, _set_emulator,
xpath="./devices/emulator")
def _get_replace(self):
return self._replace
def _set_replace(self, val):
self._replace = bool(val)
replace = property(_get_replace, _set_replace,
doc=_("Whether we should overwrite an existing guest "
"with the same name."))
########################################
# Device Add/Remove Public API methods #
@ -450,15 +351,10 @@ class Guest(XMLBuilder):
self._track_device(dev)
if set_defaults:
def list_one_dev(devtype):
if dev.virtual_device_type == devtype:
return [dev][:]
else:
return []
origdev = self._devices
try:
self._devices = [dev]
self._set_defaults(self.features)
self._set_device_defaults()
except:
self._devices = origdev
@ -511,13 +407,6 @@ class Guest(XMLBuilder):
if xpath:
self._remove_child_xpath(xpath)
bootloader = XMLProperty(xpath="./bootloader")
type = XMLProperty(xpath="./@type", default_cb=lambda s: "xen")
def _cleanup_xml(self, xml):
if not xml.endswith("\n"):
xml += "\n"
return xml
################################
# Private xml building methods #
@ -575,7 +464,7 @@ class Guest(XMLBuilder):
def add_default_input_device(self):
if self.os.is_container():
return
self.add_device(VirtualInputDevice(self.conn))
self.add_device(virtinst.VirtualInputDevice(self.conn))
def add_default_console_device(self):
if self.os.is_xenpv():
@ -584,151 +473,6 @@ class Guest(XMLBuilder):
dev.type = dev.TYPE_PTY
self.add_device(dev)
def _get_device_xml(self, devs, install=True):
def do_remove_media(d):
# Keep cdrom around, but with no media attached,
# But only if we are a distro that doesn't have a multi
# stage install (aka not Windows)
return (d.virtual_device_type == VirtualDevice.VIRTUAL_DEV_DISK and
d.device == VirtualDisk.DEVICE_CDROM
and d.transient
and not install and
not self.get_continue_inst())
def do_skip_disk(d):
# Skip transient labeled non-media disks
return (d.virtual_device_type == VirtualDevice.VIRTUAL_DEV_DISK and
d.device == VirtualDisk.DEVICE_DISK
and d.transient
and not install)
# Wrapper for building disk XML, handling transient CDROMs
def get_dev_xml(dev):
origpath = None
try:
if do_skip_disk(dev):
return ""
if do_remove_media(dev):
origpath = dev.path
dev.path = None
return dev.get_xml_config()
finally:
if origpath:
dev.path = origpath
def get_vscsi_ctrl_xml():
ctrl = virtinst.VirtualController(self.conn)
ctrl.type = "scsi"
ctrl.address.set_addrstr("spapr-vio")
return ctrl.get_xml_config()
xml = self._get_emulator_xml()
# Build XML
for dev in devs:
xml = util.xml_append(xml, get_dev_xml(dev))
if (dev.address.type == "spapr-vio" and
dev.virtual_device_type == VirtualDevice.VIRTUAL_DEV_DISK):
xml = util.xml_append(xml, get_vscsi_ctrl_xml())
return xml
def _get_emulator_xml(self):
emulator = self.emulator
if self.os.is_xenpv():
return ""
if (not self.emulator and
self.os.is_hvm() and
self.type == "xen"):
if self.conn.caps.host.arch in ("x86_64"):
emulator = "/usr/lib64/xen/bin/qemu-dm"
else:
emulator = "/usr/lib/xen/bin/qemu-dm"
emu_xml = ""
if emulator is not None:
emu_xml = " <emulator>%s</emulator>" % emulator
return emu_xml
def _get_features_xml(self, features):
"""
Return features (pae, acpi, apic) xml
"""
if self.os.is_container():
return ""
return features.get_xml_config()
def _get_cpu_xml(self):
"""
Return <cpu> XML
"""
self.cpu.set_topology_defaults(self.vcpus)
return self.cpu.get_xml_config()
def _get_clock_xml(self):
"""
Return <clock/> xml
"""
return self.clock.get_xml_config()
def _get_seclabel_xml(self):
"""
Return <seclabel> XML
"""
xml = ""
if self.seclabel:
xml = self.seclabel.get_xml_config()
return xml
def _get_default_init(self):
for fs in self.get_devices("filesystem"):
if fs.target == "/":
return "/sbin/init"
return "/bin/sh"
def _get_osblob(self, install):
"""
Return os, features, and clock xml (Implemented in subclass)
"""
oscopy = self.os.copy()
self.installer.alter_bootconfig(self, install, oscopy)
if oscopy.is_container() and not oscopy.init:
oscopy.init = self._get_default_init()
if not oscopy.loader and oscopy.is_hvm() and self.type == "xen":
oscopy.loader = "/usr/lib/xen/boot/hvmloader"
if oscopy.os_type == "xen" and self.type == "xen":
# Use older libvirt 'linux' value for back compat
oscopy.os_type = "linux"
if oscopy.kernel or oscopy.init:
oscopy.bootorder = []
return oscopy.get_xml_config() or None
def _get_osblob_helper(self, guest, isinstall,
bootconfig, endbootconfig):
return self.get_xml_config()
def _get_vcpu_xml(self):
curvcpus_supported = self.conn.check_conn_support(
self.conn.SUPPORT_CONN_MAXVCPUS_XML)
cpuset = ""
if self.cpuset is not None:
cpuset = " cpuset='%s'" % self.cpuset
maxv = self.maxvcpus
curv = self.vcpus
curxml = ""
if maxv != curv and curvcpus_supported:
curxml = " current='%s'" % curv
else:
maxv = curv
return " <vcpu%s%s>%s</vcpu>" % (cpuset, curxml, maxv)
############################
# Install Helper functions #
@ -756,23 +500,42 @@ class Guest(XMLBuilder):
for dev in self.get_all_devices():
dev.setup(progresscb)
all_devices = property(lambda s: s.get_all_devices())
##############
# Public API #
##############
def _get_xml_config(self, *args, **kwargs):
def _prepare_get_xml(self):
# We do a shallow copy of the device list here, and set the defaults.
# This way, default changes aren't persistent, and we don't need
# to worry about when to call set_defaults
origdevs = self._devices
data = (self._devices, self.features, self.os)
try:
self._devices = [dev.copy() for dev in self._devices]
return self._do_get_xml_config(*args, **kwargs)
finally:
self._devices = origdevs
self.features = self.features.copy()
self.os = self.os.copy()
except:
self._finish_get_xml(data)
raise
return data
def _finish_get_xml(self, data):
self._devices, self.features, self.os = data
def _do_get_xml_config(self, install=True, disk_boot=False):
def _cleanup_xml(self, xml):
lines = xml.splitlines()
newlines = []
for line in lines:
newlines.append(line)
xml = "\n".join(newlines)
if not xml.endswith("\n"):
xml += "\n"
return xml
def _get_xml_config(self, install=True, disk_boot=False):
"""
Return the full Guest xml configuration.
@ -790,67 +553,36 @@ class Guest(XMLBuilder):
"""
# pylint: disable=W0221
# Argument number differs from overridden method
tmpfeat = self.features.copy()
self._set_defaults(tmpfeat)
action = install and "destroy" or "restart"
osblob_install = install and not disk_boot
if osblob_install and not self.installer.has_install_phase():
return None
self.installer.alter_bootconfig(self, osblob_install, self.os)
self.set_defaults()
self._set_transient_device_defaults(install)
action = install and "destroy" or "restart"
self.on_reboot = action
self.on_crash = action
self.bootloader = None
if (not install and
self.os.is_xenpv() and
not self.os.kernel):
osblob = " <bootloader>/usr/bin/pygrub</bootloader>"
else:
osblob = self._get_osblob(osblob_install)
self.bootloader = "/usr/bin/pygrub"
self.os.clear()
desc_xml = ""
if self.description is not None:
desc = str(self.description)
desc_xml = (" <description>%s</description>" %
util.xml_escape(desc))
count = {}
for dev in self.get_all_devices():
devtype = dev.virtual_device_type
if devtype not in count:
count[devtype] = 1
newpath = "./devices/%s[%d]" % (devtype, count[devtype])
setattr(dev, "_XML_NEW_ROOT_PATH", newpath)
count[devtype] += 1
xml = ""
add = lambda x: util.xml_append(xml, x)
xml = add("<domain type='%s'>" % self.type)
xml = add(" <name>%s</name>" % self.name)
xml = add(" <uuid>%s</uuid>" % self.uuid)
xml = add(desc_xml)
xml = add(" <memory>%s</memory>" % self.maxmemory)
xml = add(" <currentMemory>%s</currentMemory>" % self.memory)
# <blkiotune>
# <memtune>
if self.hugepage is True:
xml = add(" <memoryBacking>")
xml = add(" <hugepages/>")
xml = add(" </memoryBacking>")
xml = add(self._get_vcpu_xml())
# <cputune>
xml = add(self.numatune.get_xml_config())
# <sysinfo>
xml = add(osblob)
xml = add(self._get_features_xml(tmpfeat))
xml = add(self._get_cpu_xml())
xml = add(self._get_clock_xml())
xml = add(" <on_poweroff>destroy</on_poweroff>")
xml = add(" <on_reboot>%s</on_reboot>" % action)
xml = add(" <on_crash>%s</on_crash>" % action)
xml = add(" <devices>")
xml = add(self._get_device_xml(self.get_all_devices(), install))
xml = add(" </devices>")
xml = add(self._get_seclabel_xml())
xml = add("</domain>\n")
def cb(doc, ctx):
ignore = ctx
return doc.serialize()
xml = util.xml_parse_wrapper(xml, cb)
return "\n".join(xml.splitlines()[1:]) + "\n"
return self._make_xml_stub()
def get_continue_inst(self):
"""
@ -987,7 +719,6 @@ class Guest(XMLBuilder):
self.domain = self._create_guest(consolecb, meter, wait,
start_xml, final_xml, is_initial,
noboot)
# Set domain autostart flag if requested
self._flag_autostart()
@ -1139,6 +870,31 @@ class Guest(XMLBuilder):
# Device defaults #
###################
def _set_transient_device_defaults(self, install):
def do_remove_media(d):
# Keep cdrom around, but with no media attached,
# But only if we are a distro that doesn't have a multi
# stage install (aka not Windows)
return (d.virtual_device_type == VirtualDevice.VIRTUAL_DEV_DISK and
d.device == VirtualDisk.DEVICE_CDROM
and d.transient
and not install and
not self.get_continue_inst())
def do_skip_disk(d):
# Skip transient labeled non-media disks
return (d.virtual_device_type == VirtualDevice.VIRTUAL_DEV_DISK and
d.device == VirtualDisk.DEVICE_DISK
and d.transient
and not install)
for dev in self.get_all_devices():
if do_skip_disk(dev):
self.remove_device(dev)
continue
if do_remove_media(dev):
dev.path = None
def set_defaults(self):
"""
Public function to set guest defaults. Things like preferred
@ -1146,9 +902,46 @@ class Guest(XMLBuilder):
The install process will call a non-persistent version, so calling
this manually isn't required.
"""
self._set_defaults(self.features)
self._set_osxml_defaults()
self._set_feature_defaults()
self._set_device_defaults()
self._set_emulator_defaults()
self._set_cpu_defaults()
def _set_hvm_defaults(self, features):
def _set_cpu_defaults(self):
self.cpu.set_topology_defaults(self.vcpus)
def _set_emulator_defaults(self):
if self.os.is_xenpv():
self.emulator = None
return
if self.emulator:
return
if self.os.is_hvm() and self.type == "xen":
if self.conn.caps.host.arch == "x86_64":
self.emulator = "/usr/lib64/xen/bin/qemu-dm"
else:
self.emulator = "/usr/lib/xen/bin/qemu-dm"
def _set_osxml_defaults(self):
if self.os.is_container() and not self.os.init:
for fs in self.get_devices("filesystem"):
if fs.target == "/":
self.os.init = "/sbin/init"
break
self.os.init = self.os.init or "/bin/sh"
if not self.os.loader and self.os.is_hvm() and self.type == "xen":
self.os.loader = "/usr/lib/xen/boot/hvmloader"
if self.os.os_type == "xen" and self.type == "xen":
# Use older libvirt 'linux' value for back compat
self.os.os_type = "linux"
if self.os.kernel or self.os.init:
self.os.bootorder = []
def _set_hvm_defaults(self):
disktype = VirtualDevice.VIRTUAL_DEV_DISK
nettype = VirtualDevice.VIRTUAL_DEV_NET
disk_bus = self._lookup_device_param(disktype, "bus")
@ -1167,13 +960,6 @@ class Guest(XMLBuilder):
if self.clock.offset is None:
self.clock.offset = self._lookup_osdict_key("clock")
if features["acpi"] is None:
features["acpi"] = self._lookup_osdict_key("acpi")
if features["apic"] is None:
features["apic"] = self._lookup_osdict_key("apic")
if features["pae"] is None:
features["pae"] = self.conn.caps.support_pae()
if (self.os.machine is None and
self.conn.caps.host.arch == "ppc64"):
self.os.machine = "pseries"
@ -1192,36 +978,40 @@ class Guest(XMLBuilder):
if d.bus == d.BUS_DEFAULT:
d.bus = d.BUS_XEN
def add_usb_ich9_controllers(self):
ctrl = VirtualController(self.conn)
ctrl.type = "usb"
ctrl.model = "ich9-ehci1"
self.add_device(ctrl)
def _set_feature_defaults(self):
if self.os.is_container():
self.features.acpi = None
self.features.apic = None
self.features.pae = None
return
ctrl = VirtualController(self.conn)
ctrl.type = "usb"
ctrl.model = "ich9-uhci1"
ctrl.master_startport = 0
self.add_device(ctrl)
if not self.os.is_hvm():
return
ctrl = VirtualController(self.conn)
ctrl.type = "usb"
ctrl.model = "ich9-uhci2"
ctrl.master_startport = 2
self.add_device(ctrl)
if self.features["acpi"] is None:
self.features["acpi"] = self._lookup_osdict_key("acpi")
if self.features["apic"] is None:
self.features["apic"] = self._lookup_osdict_key("apic")
if self.features["pae"] is None:
self.features["pae"] = self.conn.caps.support_pae()
ctrl = VirtualController(self.conn)
ctrl.type = "usb"
ctrl.model = "ich9-uhci3"
ctrl.master_startport = 4
self.add_device(ctrl)
def _set_defaults(self, features):
def _set_device_defaults(self):
for dev in self.get_devices("all"):
dev.set_defaults()
# Add spapr-vio controller if needed
if (dev.address.type == "spapr-vio" and
dev.virtual_device_type == VirtualDevice.VIRTUAL_DEV_DISK and
not any([cont.address.type == "spapr-vio" for cont in
self.get_devices("controller")])):
ctrl = virtinst.VirtualController(self.conn)
ctrl.type = "scsi"
ctrl.address.set_addrstr("spapr-vio")
self.add_device(ctrl)
if self.os.is_hvm():
self._set_hvm_defaults(features)
self._set_hvm_defaults()
if self.os.is_xenpv():
self._set_pv_defaults()

View File

@ -41,7 +41,6 @@ class Seclabel(XMLBuilder):
_dumpxml_xpath = "/domain/seclabel"
_XML_ROOT_NAME = "seclabel"
_XML_INDENT = 2
_XML_XPATH_RELATIVE = True
_XML_PROP_ORDER = ["type", "model", "relabel", "label", "imagelabel"]
def _guess_secmodel(self):

View File

@ -151,7 +151,7 @@ class _VirtualCharDevice(VirtualDevice):
def _sourcepath_get_xpath(self):
return "./source/@path | ./@tty"
source_path = XMLProperty(xml_get_xpath=_sourcepath_get_xpath,
source_path = XMLProperty(make_getter_xpath_cb=_sourcepath_get_xpath,
doc=_("Host input path to attach to the guest."),
xpath="./source/@path")
@ -167,8 +167,8 @@ class _VirtualCharDevice(VirtualDevice):
return "./source/@mode"
source_mode = XMLProperty(name="char sourcemode",
doc=_("Target connect/listen mode."),
xml_get_xpath=_sourcemode_xpath,
xml_set_xpath=_sourcemode_xpath,
make_getter_xpath_cb=_sourcemode_xpath,
make_setter_xpath_cb=_sourcemode_xpath,
default_cb=_get_default_source_mode)
def _get_default_sourcehost(self):
@ -188,8 +188,8 @@ class _VirtualCharDevice(VirtualDevice):
return "./source[@mode='%s']/@host" % mode
source_host = XMLProperty(name="char sourcehost",
doc=_("Address to connect/listen to."),
xml_get_xpath=_sourcehost_xpath,
xml_set_xpath=_sourcehost_xpath,
make_getter_xpath_cb=_sourcehost_xpath,
make_setter_xpath_cb=_sourcehost_xpath,
default_cb=_get_default_sourcehost,
set_converter=_set_source_validate)
@ -197,8 +197,8 @@ class _VirtualCharDevice(VirtualDevice):
return "./source[@mode='%s']/@service" % self.source_mode
source_port = XMLProperty(name="char sourceport",
doc=_("Port on target host to connect/listen to."),
xml_get_xpath=_sourceport_xpath,
xml_set_xpath=_sourceport_xpath,
make_getter_xpath_cb=_sourceport_xpath,
make_setter_xpath_cb=_sourceport_xpath,
set_converter=_set_source_validate, is_int=True)
_has_mode_connect = XMLProperty(xpath="./source[@mode='connect']/@mode")

View File

@ -54,7 +54,35 @@ class VirtualController(VirtualDevice):
return ctype
return pretty_mappings[ctype]
_XML_PROP_ORDER = ["type", "index", "model"]
@staticmethod
def get_usb2_controllers(conn):
ret = []
ctrl = VirtualController(conn)
ctrl.type = "usb"
ctrl.model = "ich9-ehci1"
ret.append(ctrl)
ctrl = VirtualController(conn)
ctrl.type = "usb"
ctrl.model = "ich9-uhci1"
ctrl.master_startport = 0
ret.append(ctrl)
ctrl = VirtualController(conn)
ctrl.type = "usb"
ctrl.model = "ich9-uhci2"
ctrl.master_startport = 2
ret.append(ctrl)
ctrl = VirtualController(conn)
ctrl.type = "usb"
ctrl.model = "ich9-uhci3"
ctrl.master_startport = 4
ret.append(ctrl)
return ret
_XML_PROP_ORDER = ["type", "index", "model", "master_startport"]
type = XMLProperty(xpath="./@type")
model = XMLProperty(xpath="./@model")

View File

@ -82,7 +82,7 @@ class VirtualDevice(XMLBuilder):
self.alias = VirtualDeviceAlias(conn, parsexmlnode=parsexmlnode)
self.address = VirtualDeviceAddress(conn, parsexmlnode=parsexmlnode)
self._XML_SUB_ELEMENTS = ["alias", "address"]
self._XML_PROP_ORDER = self._XML_PROP_ORDER + ["alias", "address"]
if not self.virtual_device_type:
raise ValueError(_("Virtual device type must be set in subclass."))
@ -132,7 +132,6 @@ class VirtualDeviceAddress(XMLBuilder):
_XML_ROOT_NAME = "address"
_XML_INDENT = 0
#_XML_XPATH_RELATIVE = True
_XML_PROP_ORDER = ["type", "domain", "bus", "slot", "function"]
def set_addrstr(self, addrstr):

View File

@ -452,6 +452,8 @@ class VirtualDisk(VirtualDevice):
return self._storage_backend.get_dev_type()
def _get_default_driver_name(self):
if not self.path:
return None
if self.conn.is_qemu():
return self.DRIVER_QEMU
return None
@ -480,7 +482,7 @@ class VirtualDisk(VirtualDevice):
# XML properties #
##################
def _xml_get_xpath(self):
def _make_getter_xpath_cb(self):
xpath = None
ret = "./source/@file"
for prop in _TARGET_PROPS:
@ -489,11 +491,11 @@ class VirtualDisk(VirtualDevice):
ret = xpath
break
return ret
def _xml_set_xpath(self):
def _make_setter_xpath_cb(self):
return "./source/@" + self.disk_type_to_target_prop(self.type)
_xmlpath = XMLProperty(name="disk path",
xml_get_xpath=_xml_get_xpath,
xml_set_xpath=_xml_set_xpath,
make_getter_xpath_cb=_make_getter_xpath_cb,
make_setter_xpath_cb=_make_setter_xpath_cb,
clear_first=["./source/@" + target for target in
_TARGET_PROPS])
@ -591,9 +593,21 @@ class VirtualDisk(VirtualDevice):
self._storage_backend = backend
def _refresh_backend_settings(self):
self._refresh_xml_prop("type")
self._refresh_xml_prop("driver_name")
self._refresh_xml_prop("driver_type")
def refresh_prop_xml(propname):
# When parsing, we can pull info from _propstore or the
# backing XML. The problem is that disk XML has several
# interdependent properties that we need to update if
# one or the other changes.
#
# This will update the XML value with the newly determined
# default value, but it won't edit propstore. This means
prop = self.all_xml_props()[propname]
val = getattr(prop, "_default_cb")(self)
prop.setter(self, val, call_fset=False)
refresh_prop_xml("type")
refresh_prop_xml("driver_name")
refresh_prop_xml("driver_type")
self._xmlpath = self.path
def __managed_storage(self):
@ -709,14 +723,6 @@ class VirtualDisk(VirtualDevice):
self.type == self.TYPE_BLOCK):
self.driver_io = self.IO_MODE_NATIVE
def _cleanup_xml(self, xml):
# Remove <driver> block if path is None. Might not be strictly
# requires but it's what we've always done
if not self.path and "<driver" in xml:
xml = "\n".join([l for l in xml.splitlines()
if "<driver" not in l])
return xml
def is_size_conflict(self):
"""
reports if disk size conflicts with available space

View File

@ -99,8 +99,8 @@ class VirtualFilesystem(VirtualDevice):
ret = "./source/@" + self.type_to_source_prop(self.type)
return ret
source = XMLProperty(name="filesystem source",
xml_get_xpath=_xml_get_source_xpath,
xml_set_xpath=_xml_set_source_xpath)
make_getter_xpath_cb=_xml_get_source_xpath,
make_setter_xpath_cb=_xml_set_source_xpath)
def _validate_set_target(self, val):
# In case of qemu for default fs type (mount) target is not

View File

@ -54,10 +54,8 @@ def _random_mac(conn):
class VirtualPort(XMLBuilder):
type = XMLProperty(xpath="./virtualport/@type")
managerid = XMLProperty(xpath="./virtualport/parameters/@managerid",
is_int=True)
typeid = XMLProperty(xpath="./virtualport/parameters/@typeid", is_int=True)
typeidversion = XMLProperty(
xpath="./virtualport/parameters/@typeidversion", is_int=True)
@ -65,7 +63,6 @@ class VirtualPort(XMLBuilder):
class VirtualNetworkInterface(VirtualDevice):
virtual_device_type = VirtualDevice.VIRTUAL_DEV_NET
TYPE_BRIDGE = "bridge"
@ -138,7 +135,6 @@ class VirtualNetworkInterface(VirtualDevice):
VirtualDevice.__init__(self, conn, parsexml, parsexmlnode)
self.virtualport = VirtualPort(conn, parsexml, parsexmlnode)
self._XML_SUB_ELEMENTS.append("virtualport")
self._random_mac = None
self._default_bridge = None
@ -200,7 +196,7 @@ class VirtualNetworkInterface(VirtualDevice):
_XML_PROP_ORDER = [
"bridge", "network", "source_dev", "source_mode",
"macaddr", "target_dev", "model"]
"macaddr", "target_dev", "model", "virtualport"]
type = XMLProperty(xpath="./@type",
default_cb=lambda s: s.TYPE_BRIDGE)

View File

@ -754,7 +754,7 @@ def get_networks(guest, networks, macs):
def set_os_variant(guest, distro_type, distro_variant):
if not distro_type and not distro_variant:
# Default to distro autodetection
guest.set_os_autodetect(True)
guest.os_autodetect = True
return
if (distro_type and str(distro_type).lower() != "none"):
@ -798,7 +798,7 @@ def digest_graphics(guest, options, default_override=None):
elif "DISPLAY" in os.environ.keys():
logging.debug("DISPLAY is set: looking for pre-configured graphics")
if cliconfig.default_graphics in ["spice", "vnc", "sdl"]:
logging.debug("Defaulting graphics to pre-configured %s" %
logging.debug("Defaulting graphics to pre-configured %s",
cliconfig.default_graphics.upper())
return [cliconfig.default_graphics]
logging.debug("No valid pre-configured graphics "
@ -1189,10 +1189,11 @@ def parse_vcpu(guest, optstring, default_vcpus=None):
set_param = _build_set_param(guest, opts)
set_cpu_param = _build_set_param(guest.cpu, opts)
has_vcpus = ("vcpus" in opts or (vcpus is not None))
has_max = ("maxvcpus" in opts)
has_vcpus = ("vcpus" in opts) or has_max
set_param("vcpus", "vcpus")
set_param("maxvcpus", "maxvcpus")
set_param(has_max and "curvcpus" or "vcpus", "vcpus")
set_param("vcpus", "maxvcpus")
set_cpu_param("sockets", "sockets")
set_cpu_param("cores", "cores")
@ -1637,7 +1638,8 @@ def parse_controller(guest, optstring, dev=None):
return None
if optstring == "usb2":
guest.add_usb_ich9_controllers()
for dev in virtinst.VirtualController.get_usb2_controllers(guest.conn):
guest.add_device(dev)
return None
# Peel the mode off the front

View File

@ -42,7 +42,6 @@ class OSXML(XMLBuilder):
_dumpxml_xpath = "/domain/os"
_XML_ROOT_NAME = "os"
_XML_INDENT = 2
_XML_XPATH_RELATIVE = True
_XML_PROP_ORDER = ["arch", "os_type", "loader",
"kernel", "initrd", "kernel_args",
"bootorder"]

View File

@ -52,6 +52,15 @@ class _CtxCleanupWrapper(object):
return getattr(self._ctx, attrname)
def _indent(xmlstr, level):
xml = ""
if not xmlstr:
return xml
if not level:
return xmlstr
return "\n".join((" " * level + l) for l in xmlstr.splitlines())
def _tuplify_lists(*args):
"""
Similar to zip(), but use None if lists aren't long enough, and
@ -232,9 +241,9 @@ def _remove_xpath_node(ctx, xpath, dofree=True, root_name=None):
class XMLProperty(property):
def __init__(self, fget=None, fset=None, doc=None, xpath=None, name=None,
get_converter=None, set_converter=None,
xml_get_xpath=None, xml_set_xpath=None,
def __init__(self, doc=None, xpath=None, name=None,
set_converter=None, validate_cb=None,
make_getter_xpath_cb=None, make_setter_xpath_cb=None,
is_bool=False, is_tri=False, is_int=False,
is_multi=False, is_yesno=False,
clear_first=None, default_cb=None, default_name=None):
@ -249,23 +258,22 @@ class XMLProperty(property):
use the xpath value to map the name property to the underlying XML
definition.
@param fget: typical getter function for the property
@param fset: typical setter function for the property
@param doc: option doc string for the property
@param xpath: xpath string which maps to the associated property
in a typical XML document
@param name: Just a string to print for debugging, only needed
if xpath isn't specified.
@param get_converter:
@param set_converter: optional function for converting the property
value from the virtinst API to the guest XML. For example,
the Guest.memory API was once in MB, but the libvirt domain
memory API is in KB. So, if xpath is specified, on a 'get'
operation we convert the XML value with int(val) / 1024.
@param xml_get_xpath:
@param xml_set_xpath: Not all props map cleanly to a static xpath.
This allows passing functions which generate an xpath for getting
or setting.
@param validate_cb: Called once when value is set, should
raise a RuntimeError if the value is not proper.
@param make_getter_xpath_cb:
@param make_setter_xpath_cb: Not all props map cleanly to a
static xpath. This allows passing functions which generate
an xpath for getting or setting.
@param is_bool: Whether this is a boolean property in the XML
@param is_tri: Boolean XML property, but return None if there's
no value set.
@ -294,10 +302,10 @@ class XMLProperty(property):
self._is_multi = is_multi
self._is_yesno = is_yesno
self._xpath_for_getter_cb = xml_get_xpath
self._xpath_for_setter_cb = xml_set_xpath
self._xpath_for_getter_cb = make_getter_xpath_cb
self._xpath_for_setter_cb = make_setter_xpath_cb
self._convert_value_for_getter_cb = get_converter
self._validate_cb = validate_cb
self._convert_value_for_setter_cb = set_converter
self._setter_clear_these_first = clear_first or []
self._default_cb = default_cb
@ -310,43 +318,21 @@ class XMLProperty(property):
if self._default_name and not self._default_cb:
raise RuntimeError("default_name requires default_cb.")
self._fget = fget
self._fset = fset
if _trackprops:
_allprops.append(self)
if self._is_new_style_prop():
if _trackprops:
_allprops.append(self)
else:
if self._default_cb:
raise RuntimeError("Can't set default_cb for old style XML "
"prop.")
property.__init__(self, fget=self.new_getter, fset=self.new_setter)
property.__init__(self, fget=self.getter, fset=self.setter)
self.__doc__ = doc
##################
# Public-ish API #
##################
def __repr__(self):
return "<XMLProperty %s %s>" % (str(self._name), id(self))
def has_default_value(self):
return bool(self._default_cb)
####################
# Internal helpers #
####################
def _is_new_style_prop(self):
"""
True if this is a prop without an explicitly passed in fget/fset
pair.
"""
return not bool(self._fget)
def _findpropname(self, xmlbuilder):
"""
Map the raw property() instance to the param name it's exposed
@ -372,14 +358,9 @@ class XMLProperty(property):
raise RuntimeError("%s: didn't generate any setter xpath." % self)
return self._xpath_fix_relative(xmlbuilder, ret)
def _xpath_fix_relative(self, xmlbuilder, xpath):
if not getattr(xmlbuilder, "_xml_fixup_relative_xpath"):
if not xmlbuilder._XML_NEW_ROOT_PATH:
return xpath
root = "./%s" % getattr(xmlbuilder, "_XML_ROOT_NAME")
if not xpath.startswith(root):
raise RuntimeError("%s: xpath did not start with root=%s" %
(str(self), root))
ret = "." + xpath[len(root):]
return ret
return "./%s%s" % (xmlbuilder._XML_NEW_ROOT_PATH, xpath.strip("."))
def _xpath_list_for_setter(self, xpath, setval, nodelist):
@ -401,7 +382,7 @@ class XMLProperty(property):
def _convert_value_for_setter(self, xmlbuilder):
# Convert from API value to XML value
val = self._orig_fget(xmlbuilder)
val = self._nonxml_fget(xmlbuilder)
if self._default_name and val == self._default_name:
val = self._default_cb(xmlbuilder)
elif self._is_yesno:
@ -440,12 +421,7 @@ class XMLProperty(property):
return clear_nodes
def _convert_get_value(self, xmlbuilder, val, initial=False):
if self._fget and initial:
# If user passed in an fget impl, we expect them to put things
# in the form they want.
return val
def _convert_get_value(self, val, initial=False):
if self._is_bool:
if initial and self._is_tri and val is None:
ret = None
@ -462,38 +438,36 @@ class XMLProperty(property):
ret = []
else:
ret = val
if self._convert_value_for_getter_cb:
ret = self._convert_value_for_getter_cb(xmlbuilder, ret)
return ret
def _orig_fget(self, xmlbuilder):
# Returns (is unset, fget value)
if self._fget:
# For the passed in fget callback, we have any way to
# tell if the value is unset or not.
return self._fget(xmlbuilder)
# The flip side to default_orig_fset, fetch the value from
# XMLBuilder._propstore
def _prop_is_unset(self, xmlbuilder):
propstore = getattr(xmlbuilder, "_propstore")
propname = self._findpropname(xmlbuilder)
unset = (propname not in propstore)
if unset and self._default_cb:
if self._default_name:
return self._default_name
return self._default_cb(xmlbuilder)
return propstore.get(propname, None)
return (propname not in propstore)
def _orig_fset(self, xmlbuilder, val):
def _set_default(self, xmlbuilder):
"""
If no fset specified, this stores the value in XMLBuilder._propstore
Encode the property default into the XML and propstore, but
only if a default is registered, and only if the property was
not already explicitly set by the API user.
This is called during the get_xml_config process and shouldn't
be called from outside this file.
"""
if not self._prop_is_unset(xmlbuilder):
return
if not self._default_cb:
return
if self._default_cb(xmlbuilder) is None:
return
self.setter(xmlbuilder, self.getter(xmlbuilder), validate=False)
def _nonxml_fset(self, xmlbuilder, val):
"""
This stores the value in XMLBuilder._propstore
dict as propname->value. This saves us from having to explicitly
track every variable.
"""
if self._fset:
return self._fset(xmlbuilder, val)
propstore = getattr(xmlbuilder, "_propstore")
proporder = getattr(xmlbuilder, "_proporder")
@ -506,31 +480,50 @@ class XMLProperty(property):
proporder.remove(propname)
proporder.append(propname)
def _nonxml_fget(self, xmlbuilder):
"""
The flip side to nonxml_fset, fetch the value from
XMLBuilder._propstore
"""
propstore = getattr(xmlbuilder, "_propstore")
propname = self._findpropname(xmlbuilder)
unset = (propname not in propstore)
if unset and self._default_cb:
if self._default_name:
return self._default_name
return self._default_cb(xmlbuilder)
return propstore.get(propname, None)
def _clear(self, xmlbuilder):
val = None
if self._is_multi:
val = []
self.setter(xmlbuilder, val)
##################################
# The actual getter/setter impls #
##################################
def new_getter(self, xmlbuilder):
fgetval = self._orig_fget(xmlbuilder)
def getter(self, xmlbuilder):
fgetval = self._nonxml_fget(xmlbuilder)
root_node = getattr(xmlbuilder, "_xml_node")
if root_node is None:
return self._convert_get_value(xmlbuilder, fgetval, initial=True)
return self._convert_get_value(fgetval, initial=True)
xpath = self._xpath_for_getter(xmlbuilder)
nodelist = self._build_node_list(xmlbuilder, xpath)
if not nodelist:
return self._convert_get_value(xmlbuilder, None)
return self._convert_get_value(None)
ret = []
for node in nodelist:
content = node.content
if self._is_bool:
content = True
val = self._convert_get_value(xmlbuilder, content)
val = self._convert_get_value(content)
if not self._is_multi:
return val
# If user is querying multiple nodes, return a list of results
@ -538,9 +531,11 @@ class XMLProperty(property):
return ret
def new_setter(self, xmlbuilder, val, call_fset=True):
def setter(self, xmlbuilder, val, call_fset=True, validate=True):
if call_fset:
self._orig_fset(xmlbuilder, val)
if validate and self._validate_cb:
self._validate_cb(xmlbuilder, val)
self._nonxml_fset(xmlbuilder, val)
root_node = getattr(xmlbuilder, "_xml_node")
if root_node is None:
@ -574,45 +569,11 @@ class XMLProperty(property):
continue
node.setContent(util.xml_escape(str(val)))
def _prop_is_unset(self, xmlbuilder):
propstore = getattr(xmlbuilder, "_propstore")
propname = self._findpropname(xmlbuilder)
return (propname not in propstore)
def refresh_xml(self, xmlbuilder, force_call_fset=False):
call_fset = True
if not self._is_new_style_prop():
call_fset = False
elif getattr(xmlbuilder, "_is_parse")():
call_fset = False
elif self._prop_is_unset(xmlbuilder) and self._default_cb:
call_fset = False
if force_call_fset:
call_fset = True
self.fset(xmlbuilder, self.fget(xmlbuilder), call_fset=call_fset)
def set_default(self, xmlbuilder):
if not self._prop_is_unset(xmlbuilder) or not self._default_cb:
return
if self._default_cb(xmlbuilder) is None:
return
self.refresh_xml(xmlbuilder, force_call_fset=True)
class XMLBuilder(object):
"""
Base for all classes which build or parse domain XML
"""
@staticmethod
def indent(xmlstr, level):
xml = ""
if not xmlstr:
return xml
if not level:
return xmlstr
return "\n".join((" " * level + l) for l in xmlstr.splitlines())
# Order that we should apply values to the XML. Keeps XML generation
# consistent with what the test suite expects.
_XML_PROP_ORDER = []
@ -624,16 +585,11 @@ class XMLBuilder(object):
# Integer indentation level for generated XML.
_XML_INDENT = None
# If XML xpaths are relative to a different element, like
# device addresses.
_XML_XPATH_RELATIVE = False
# List of property names that point to a manually tracked
# XMLBuilder that alters our device xml, like self.address for
# VirtualDevice
_XML_SUB_ELEMENTS = []
# This is only used to make device XML work for guest XML generating
_XML_NEW_ROOT_PATH = ""
_dumpxml_xpath = "."
def __init__(self, conn, parsexml=None, parsexmlnode=None):
"""
Initialize state
@ -649,7 +605,6 @@ class XMLBuilder(object):
self._xml_node = None
self._xml_ctx = None
self._xml_root_doc = None
self._xml_fixup_relative_xpath = False
self._propstore = {}
self._proporder = []
@ -679,7 +634,7 @@ class XMLBuilder(object):
return self._xml_node.nodePath()
return None
def get_xml_config(self, *args, **kwargs):
def _do_get_xml_config(self, dumpxml_xpath, clean, *args, **kwargs):
"""
Construct and return object xml
@ -687,11 +642,7 @@ class XMLBuilder(object):
@rtype: str
"""
if self._xml_ctx:
dumpxml_path = self._dumpxml_xpath
if self._xml_fixup_relative_xpath:
dumpxml_path = "."
node = _get_xpath_node(self._xml_ctx, dumpxml_path)
node = _get_xpath_node(self._xml_ctx, dumpxml_xpath)
if not node:
ret = ""
else:
@ -701,16 +652,26 @@ class XMLBuilder(object):
ret = self._get_xml_config(*args, **kwargs)
if ret is None:
return None
ret = self._add_parse_bits(ret)
for propname in self._XML_SUB_ELEMENTS:
for prop in util.listify(getattr(self, propname)):
ret = prop._add_parse_bits(ret)
ret = self._add_parse_bits(ret, clean=False)
if ret == xmlstub:
ret = ""
return self._cleanup_xml(ret)
if clean:
ret = self._cleanup_xml(ret)
return ret
def get_xml_config(self, *args, **kwargs):
data = self._prepare_get_xml()
try:
return self._do_get_xml_config(self._dumpxml_xpath, True,
*args, **kwargs)
finally:
self._finish_get_xml(data)
def clear(self):
for prop in self.all_xml_props().values():
prop._clear(self)
#######################
@ -720,13 +681,6 @@ class XMLBuilder(object):
def _is_parse(self):
return bool(self._xml_node or self._xml_ctx)
def _refresh_xml_prop(self, propname):
"""
Refresh the XML for the passed class propname. Used to adjust
the XML when an interdependent property changes.
"""
self.all_xml_props()[propname].refresh_xml(self)
###################
# Child overrides #
@ -738,6 +692,11 @@ class XMLBuilder(object):
def validate(self):
pass
def _prepare_get_xml(self):
return None
def _finish_get_xml(self, data):
ignore = data
def _get_xml_config(self):
"""
Internal XML building function. Must be overwritten by subclass
@ -766,8 +725,7 @@ class XMLBuilder(object):
raise RuntimeError("Must specify _XML_INDENT.")
if self._XML_ROOT_NAME == "":
return ""
return self.indent("<%s/>" % (self._XML_ROOT_NAME), self._XML_INDENT)
return _indent("<%s/>" % (self._XML_ROOT_NAME), self._XML_INDENT)
def _add_child_node(self, parent_xpath, newnode):
ret = _build_xpath_node(self._xml_ctx, parent_xpath, newnode)
@ -802,12 +760,11 @@ class XMLBuilder(object):
ret[key] = val
return ret
def _do_add_parse_bits(self, xml):
# Find all properties that have default callbacks
def _do_add_parse_bits(self, xml, node, clean):
# Set all defaults if the properties have one registered
xmlprops = self.all_xml_props()
defaultprops = [v for v in xmlprops.values() if v.has_default_value()]
for prop in defaultprops:
prop.set_default(self)
for prop in xmlprops.values():
prop._set_default(self)
# Default props alter our _propstore. But at this point _propstore
# is empty, there's nothing for us to do, so exit early
@ -816,15 +773,16 @@ class XMLBuilder(object):
# Unindent XML
indent = 0
for c in xml:
if c != " ":
break
indent += 1
xml = "\n".join([l[indent:] for l in xml.splitlines()])
if xml:
for c in xml:
if c != " ":
break
indent += 1
xml = "\n".join([l[indent:] for l in xml.splitlines()])
# Parse the XML into our internal state. Use the raw
# _parsexml so we don't hit Guest parsing into its internal state
XMLBuilder._parsexml(self, xml, None)
XMLBuilder._parsexml(self, xml, node)
# Set up preferred XML ordering
do_order = self._proporder[:]
@ -832,13 +790,24 @@ class XMLBuilder(object):
if key in do_order:
do_order.remove(key)
do_order.insert(0, key)
elif key not in xmlprops:
do_order.insert(0, key)
# Alter the XML
for key in do_order:
setattr(self, key, self._propstore[key])
return self.indent(self.get_xml_config().strip("\n"), indent)
if key in xmlprops:
xmlprops[key].setter(self, self._propstore[key],
validate=False)
else:
for obj in util.listify(getattr(self, key)):
if self._XML_NEW_ROOT_PATH and not obj._XML_NEW_ROOT_PATH:
obj._XML_NEW_ROOT_PATH = self._XML_NEW_ROOT_PATH
obj._add_parse_bits(xml=None, node=self._xml_node)
def _add_parse_bits(self, xml):
xml = self._do_get_xml_config(".", clean).strip("\n")
return _indent(xml, indent)
def _add_parse_bits(self, xml, node=None, clean=True):
"""
Callback that adds the implicitly tracked XML properties to
the manually generated xml. This should only exist until all
@ -850,12 +819,10 @@ class XMLBuilder(object):
origproporder = self._proporder[:]
origpropstore = self._propstore.copy()
try:
self._xml_fixup_relative_xpath = self._XML_XPATH_RELATIVE
return self._do_add_parse_bits(xml)
return self._do_add_parse_bits(xml, node, clean)
finally:
self._xml_root_doc = None
self._xml_node = None
self._xml_ctx = None
self._proporder = origproporder
self._propstore = origpropstore
self._xml_fixup_relative_xpath = False