VirtualCharDevice: Convert to new style XML props, rework API

This commit is contained in:
Cole Robinson 2013-07-16 09:14:37 -04:00
parent 9f37f58804
commit e802eae07b
28 changed files with 325 additions and 690 deletions

View File

@ -25,7 +25,8 @@ from virtinst import VirtualDisk
from virtinst import VirtualAudio from virtinst import VirtualAudio
from virtinst import VirtualNetworkInterface from virtinst import VirtualNetworkInterface
from virtinst import VirtualHostDevice from virtinst import VirtualHostDevice
from virtinst import VirtualCharDevice from virtinst import (VirtualChannelDevice, VirtualConsoleDevice,
VirtualParallelDevice, VirtualSerialDevice)
from virtinst import VirtualVideoDevice from virtinst import VirtualVideoDevice
from virtinst import VirtualController from virtinst import VirtualController
from virtinst import VirtualWatchdog from virtinst import VirtualWatchdog
@ -313,9 +314,8 @@ class TestXMLConfig(unittest.TestCase):
g.add_device(utils.get_filedisk()) g.add_device(utils.get_filedisk())
inp = VirtualInputDevice(g.conn) inp = VirtualInputDevice(g.conn)
cons = VirtualCharDevice.get_dev_instance(g.conn, cons = VirtualConsoleDevice(g.conn)
VirtualCharDevice.DEV_CONSOLE, cons.type = "pty"
VirtualCharDevice.CHAR_PTY)
g.add_device(inp) g.add_device(inp)
g.add_device(cons) g.add_device(cons)
@ -679,46 +679,38 @@ class TestXMLConfig(unittest.TestCase):
i = utils.make_pxe_installer() i = utils.make_pxe_installer()
g = utils.get_basic_fullyvirt_guest(installer=i) g = utils.get_basic_fullyvirt_guest(installer=i)
dev1 = VirtualCharDevice.get_dev_instance(g.conn, dev1 = VirtualSerialDevice(g.conn)
VirtualCharDevice.DEV_SERIAL, dev1.type = "null"
VirtualCharDevice.CHAR_NULL) dev2 = VirtualParallelDevice(g.conn)
dev2 = VirtualCharDevice.get_dev_instance(g.conn, dev2.type = "unix"
VirtualCharDevice.DEV_PARALLEL,
VirtualCharDevice.CHAR_UNIX)
dev2.source_path = "/tmp/foobar" dev2.source_path = "/tmp/foobar"
dev3 = VirtualCharDevice.get_dev_instance(g.conn, dev3 = VirtualSerialDevice(g.conn)
VirtualCharDevice.DEV_SERIAL, dev3.type = "tcp"
VirtualCharDevice.CHAR_TCP)
dev3.protocol = "telnet" dev3.protocol = "telnet"
dev3.source_host = "my.source.host" dev3.source_host = "my.source.host"
dev3.source_port = "1234" dev3.source_port = "1234"
dev4 = VirtualCharDevice.get_dev_instance(g.conn, dev4 = VirtualParallelDevice(g.conn)
VirtualCharDevice.DEV_PARALLEL, dev4.type = "udp"
VirtualCharDevice.CHAR_UDP)
dev4.bind_host = "my.bind.host" dev4.bind_host = "my.bind.host"
dev4.bind_port = "1111" dev4.bind_port = "1111"
dev4.source_host = "my.source.host" dev4.source_host = "my.source.host"
dev4.source_port = "2222" dev4.source_port = "2222"
dev5 = VirtualCharDevice.get_dev_instance(g.conn, dev5 = VirtualChannelDevice(g.conn)
VirtualCharDevice.DEV_CHANNEL, dev5.type = "pty"
VirtualCharDevice.CHAR_PTY) dev5.target_type = dev5.CHANNEL_TARGET_VIRTIO
dev5.target_type = dev5.CHAR_CHANNEL_TARGET_VIRTIO
dev5.target_name = "foo.bar.frob" dev5.target_name = "foo.bar.frob"
dev6 = VirtualCharDevice.get_dev_instance(g.conn, dev6 = VirtualConsoleDevice(g.conn)
VirtualCharDevice.DEV_CONSOLE, dev6.type = "pty"
VirtualCharDevice.CHAR_PTY)
dev7 = VirtualCharDevice.get_dev_instance(g.conn, dev7 = VirtualConsoleDevice(g.conn)
VirtualCharDevice.DEV_CONSOLE, dev7.type = "pty"
VirtualCharDevice.CHAR_PTY) dev7.target_type = dev7.CONSOLE_TARGET_VIRTIO
dev7.target_type = dev5.CHAR_CONSOLE_TARGET_VIRTIO
dev8 = VirtualCharDevice.get_dev_instance(g.conn, dev8 = VirtualChannelDevice(g.conn)
VirtualCharDevice.DEV_CHANNEL, dev8.type = "pty"
VirtualCharDevice.CHAR_PTY) dev8.target_type = dev8.CHANNEL_TARGET_GUESTFWD
dev8.target_type = dev5.CHAR_CHANNEL_TARGET_GUESTFWD
dev8.target_address = "1.2.3.4" dev8.target_address = "1.2.3.4"
dev8.target_port = "4567" dev8.target_port = "4567"
@ -811,16 +803,13 @@ class TestXMLConfig(unittest.TestCase):
g.add_device(net3) g.add_device(net3)
# Character devices # Character devices
cdev1 = VirtualCharDevice.get_dev_instance(g.conn, cdev1 = VirtualSerialDevice(g.conn)
VirtualCharDevice.DEV_SERIAL, cdev1.type = "null"
VirtualCharDevice.CHAR_NULL) cdev2 = VirtualParallelDevice(g.conn)
cdev2 = VirtualCharDevice.get_dev_instance(g.conn, cdev2.type = "unix"
VirtualCharDevice.DEV_PARALLEL,
VirtualCharDevice.CHAR_UNIX)
cdev2.source_path = "/tmp/foobar" cdev2.source_path = "/tmp/foobar"
cdev3 = VirtualCharDevice.get_dev_instance(g.conn, cdev3 = VirtualChannelDevice(g.conn)
VirtualCharDevice.DEV_CHANNEL, cdev3.type = "spicevmc"
VirtualCharDevice.CHAR_SPICEVMC)
g.add_device(cdev1) g.add_device(cdev1)
g.add_device(cdev2) g.add_device(cdev2)
g.add_device(cdev3) g.add_device(cdev3)

View File

@ -20,7 +20,10 @@
<emulator>/usr/lib/xen/bin/qemu-dm</emulator> <emulator>/usr/lib/xen/bin/qemu-dm</emulator>
<input type="mouse" bus="ps2"/> <input type="mouse" bus="ps2"/>
<graphics type="sdl" display=":3.4" xauth="/tmp/.Xauthority"/> <graphics type="sdl" display=":3.4" xauth="/tmp/.Xauthority"/>
<serial type="null"/> <serial type="udp">
<source mode="bind" host="example.com" service="66"/>
<source mode="connect" host="example.com.uk" service="77"/>
</serial>
<serial type="tcp"> <serial type="tcp">
<source mode="connect" host="my.source.host" service="1234"/> <source mode="connect" host="my.source.host" service="1234"/>
<protocol type="raw"/> <protocol type="raw"/>

View File

@ -312,46 +312,50 @@ class XMLParseTest(unittest.TestCase):
channel2 = guest.get_devices("channel")[1] channel2 = guest.get_devices("channel")[1]
check = self._make_checker(serial1) check = self._make_checker(serial1)
check("char_type", "null") check("type", "null", "udp")
check("bind_host", None, "example.com")
check("bind_port", None, 66)
check("source_host", None, "example.com.uk")
check("source_port", None, 77)
check = self._make_checker(serial2) check = self._make_checker(serial2)
check("char_type", "tcp") check("type", "tcp")
check("protocol", "telnet", "raw") check("protocol", "telnet", "raw")
check("source_mode", "bind", "connect") check("source_mode", "bind", "connect")
check = self._make_checker(parallel1) check = self._make_checker(parallel1)
check("source_mode", "bind") check("source_mode", "bind")
check("source_path", "/tmp/foobar", None) check("source_path", "/tmp/foobar", None)
check("char_type", "unix", "pty") check("type", "unix", "pty")
check = self._make_checker(parallel2) check = self._make_checker(parallel2)
check("char_type", "udp") check("type", "udp")
check("bind_port", "1111", "1357") check("bind_port", 1111, 1357)
check("bind_host", "my.bind.host", "my.foo.host") check("bind_host", "my.bind.host", "my.foo.host")
check("source_mode", "connect") check("source_mode", "connect")
check("source_port", "2222", "7777") check("source_port", 2222, 7777)
check("source_host", "my.source.host", "source.foo.host") check("source_host", "my.source.host", "source.foo.host")
check = self._make_checker(console1) check = self._make_checker(console1)
check("char_type", "pty") check("type", "pty")
check("target_type", None) check("target_type", None)
check = self._make_checker(console2) check = self._make_checker(console2)
check("char_type", "file") check("type", "file")
check("source_path", "/tmp/foo.img", None) check("source_path", "/tmp/foo.img", None)
check("source_path", None, "/root/foo") check("source_path", None, "/root/foo")
check("target_type", "virtio") check("target_type", "virtio")
check = self._make_checker(channel1) check = self._make_checker(channel1)
check("char_type", "pty") check("type", "pty")
check("target_type", "virtio") check("target_type", "virtio", "bar", "virtio")
check("target_name", "foo.bar.frob", "test.changed") check("target_name", "foo.bar.frob", "test.changed")
check = self._make_checker(channel2) check = self._make_checker(channel2)
check("char_type", "unix") check("type", "unix", "foo", "unix")
check("target_type", "guestfwd") check("target_type", "guestfwd")
check("target_address", "1.2.3.4", "5.6.7.8") check("target_address", "1.2.3.4", "5.6.7.8")
check("target_port", "4567", "1199") check("target_port", 4567, 1199)
self._alter_compare(guest.get_xml_config(), outfile) self._alter_compare(guest.get_xml_config(), outfile)

View File

@ -33,11 +33,9 @@ import urlgrabber.progress as progress
import virtinst import virtinst
import virtinst.cli as cli import virtinst.cli as cli
import virtinst.util as util import virtinst.util as util
from virtinst import VirtualCharDevice
from virtinst.cli import fail, print_stdout, print_stderr from virtinst.cli import fail, print_stdout, print_stderr
############################## ##############################
# Validation utility helpers # # Validation utility helpers #
############################## ##############################
@ -529,14 +527,10 @@ def build_guest_instance(conn, options):
get_watchdog(options.watchdog, guest) get_watchdog(options.watchdog, guest)
get_filesystems(options.filesystems, guest) get_filesystems(options.filesystems, guest)
cli.get_sound(options.sound, options.soundhw, guest) cli.get_sound(options.sound, options.soundhw, guest)
get_chardevs(VirtualCharDevice.VIRTUAL_DEV_SERIAL, options.serials, get_chardevs("serial", options.serials, guest, cli.parse_serial)
guest, cli.parse_serial) get_chardevs("parallel", options.parallels, guest, cli.parse_parallel)
get_chardevs(VirtualCharDevice.VIRTUAL_DEV_PARALLEL, options.parallels, get_chardevs("channel", options.channels, guest, cli.parse_channel)
guest, cli.parse_parallel) get_chardevs("console", options.consoles, guest, cli.parse_console)
get_chardevs(VirtualCharDevice.VIRTUAL_DEV_CHANNEL, options.channels,
guest, cli.parse_channel)
get_chardevs(VirtualCharDevice.VIRTUAL_DEV_CONSOLE, options.consoles,
guest, cli.parse_console)
cli.get_hostdevs(options.hostdevs, guest) cli.get_hostdevs(options.hostdevs, guest)
cli.get_smartcard(guest, options.smartcard) cli.get_smartcard(guest, options.smartcard)
cli.get_tpm(guest, options.tpm) cli.get_tpm(guest, options.tpm)

View File

@ -27,7 +27,8 @@ from gi.repository import Gdk
# pylint: enable=E0611 # pylint: enable=E0611
import virtinst import virtinst
from virtinst import (VirtualCharDevice, from virtinst import (VirtualChannelDevice, VirtualParallelDevice,
VirtualSerialDevice,
VirtualVideoDevice, VirtualWatchdog, VirtualVideoDevice, VirtualWatchdog,
VirtualFilesystem, VirtualSmartCardDevice, VirtualFilesystem, VirtualSmartCardDevice,
VirtualRedirDevice, VirtualTPMDevice) VirtualRedirDevice, VirtualTPMDevice)
@ -132,7 +133,7 @@ class vmmAddHardware(vmmGObjectUI):
self.widget("char-info").set_markup(doc) self.widget("char-info").set_markup(doc)
def update_doc_char_type(self, *ignore): def update_doc_char_type(self, *ignore):
return self._update_doc("char_type") return self._update_doc("type")
def update_doc_char_source_path(self, *ignore): def update_doc_char_source_path(self, *ignore):
return self._update_doc("source_path") return self._update_doc("source_path")
def update_doc_char_source_mode(self, *ignore): def update_doc_char_source_mode(self, *ignore):
@ -147,18 +148,17 @@ class vmmAddHardware(vmmGObjectUI):
return self._update_doc("target_name") return self._update_doc("target_name")
def _build_doc_str(self, param, docstr=None): def _build_doc_str(self, param, docstr=None):
doc = ""
doctmpl = "<i>%s</i>" doctmpl = "<i>%s</i>"
if docstr: if docstr:
doc = doctmpl % (docstr) return doctmpl % (docstr)
elif self._dev: elif not self._dev:
devclass = self._dev.__class__ return ""
paramdoc = getattr(devclass, param).__doc__
if paramdoc:
doc = doctmpl % paramdoc
return doc propdoc = getattr(self._dev.all_xml_props()[param], "__doc__")
if propdoc:
return doctmpl % propdoc
return ""
def show(self, parent): def show(self, parent):
logging.debug("Showing addhw") logging.debug("Showing addhw")
@ -303,8 +303,8 @@ class vmmAddHardware(vmmGObjectUI):
char_mode.pack_start(text, True) char_mode.pack_start(text, True)
char_mode.add_attribute(text, 'text', 1) char_mode.add_attribute(text, 'text', 1)
char_mode_model.set_sort_column_id(0, Gtk.SortType.ASCENDING) char_mode_model.set_sort_column_id(0, Gtk.SortType.ASCENDING)
for t in VirtualCharDevice.char_modes: for t in VirtualSerialDevice.MODES:
desc = VirtualCharDevice.get_char_mode_desc(t) desc = VirtualSerialDevice.pretty_mode(t)
char_mode_model.append([t, desc + " (%s)" % t]) char_mode_model.append([t, desc + " (%s)" % t])
self.widget("char-info-box").modify_bg(Gtk.StateType.NORMAL, self.widget("char-info-box").modify_bg(Gtk.StateType.NORMAL,
@ -833,7 +833,8 @@ class vmmAddHardware(vmmGObjectUI):
# Char device type # Char device type
char_devtype = self.widget("char-device-type") char_devtype = self.widget("char-device-type")
dev_type = self.get_char_type() char_class = self.get_char_type()
# Type name, desc # Type name, desc
char_devtype_model = Gtk.ListStore(str, str) char_devtype_model = Gtk.ListStore(str, str)
char_devtype.clear() char_devtype.clear()
@ -842,12 +843,12 @@ class vmmAddHardware(vmmGObjectUI):
char_devtype.pack_start(text, True) char_devtype.pack_start(text, True)
char_devtype.add_attribute(text, 'text', 1) char_devtype.add_attribute(text, 'text', 1)
for t in VirtualCharDevice.char_types_for_dev_type[dev_type]: for t in char_class.TYPES:
if (t in rhel6_blacklist and if (t in rhel6_blacklist and
not self.vm.rhel6_defaults()): not self.vm.rhel6_defaults()):
continue continue
desc = VirtualCharDevice.get_char_type_desc(t) desc = char_class.pretty_type(t)
row = [t, desc + " (%s)" % t] row = [t, desc + " (%s)" % t]
char_devtype_model.append(row) char_devtype_model.append(row)
char_devtype.set_active(0) char_devtype.set_active(0)
@ -988,10 +989,10 @@ class vmmAddHardware(vmmGObjectUI):
label = row[5] label = row[5]
if label == "parallel": if label == "parallel":
return VirtualCharDevice.VIRTUAL_DEV_PARALLEL return VirtualParallelDevice
elif label == "channel": elif label == "channel":
return VirtualCharDevice.VIRTUAL_DEV_CHANNEL return VirtualChannelDevice
return VirtualCharDevice.VIRTUAL_DEV_SERIAL return VirtualSerialDevice
def dev_to_title(self, page): def dev_to_title(self, page):
if page == PAGE_ERROR: if page == PAGE_ERROR:
@ -1020,7 +1021,8 @@ class vmmAddHardware(vmmGObjectUI):
return _("TPM") return _("TPM")
if page == PAGE_CHAR: if page == PAGE_CHAR:
return self.get_char_type().capitalize() + " Device" char_class = self.get_char_type()
return char_class.virtual_device_type.capitalize() + " Device"
if page == PAGE_HOSTDEV: if page == PAGE_HOSTDEV:
return self.get_config_host_device_type_info()[0] return self.get_config_host_device_type_info()[0]
@ -1056,16 +1058,17 @@ class vmmAddHardware(vmmGObjectUI):
self.widget("tpm-param-box").set_property("visible", show_something) self.widget("tpm-param-box").set_property("visible", show_something)
def change_char_device_type(self, src): def change_char_device_type(self, src):
self._update_doc("char_type") self._update_doc("type")
idx = src.get_active() idx = src.get_active()
if idx < 0: if idx < 0:
return return
chartype = self.get_char_type() char_class = self.get_char_type()
devtype = src.get_model()[src.get_active()][0] devtype = src.get_model()[src.get_active()][0]
conn = self.conn.get_backend() conn = self.conn.get_backend()
self._dev = VirtualCharDevice.get_dev_instance(conn, chartype, devtype) self._dev = char_class(conn)
self._dev.type = devtype
show_something = False show_something = False
for param_name, widget_name in char_widget_mappings.items(): for param_name, widget_name in char_widget_mappings.items():
@ -1472,13 +1475,14 @@ class vmmAddHardware(vmmGObjectUI):
return self.err.val_err(_("Host device parameter error"), e) return self.err.val_err(_("Host device parameter error"), e)
def validate_page_char(self): def validate_page_char(self):
chartype = self.get_char_type() charclass = self.get_char_type()
modebox = self.widget("char-mode") modebox = self.widget("char-mode")
devbox = self.widget("char-device-type") devbox = self.widget("char-device-type")
devtype = devbox.get_model()[devbox.get_active()][0] devtype = devbox.get_model()[devbox.get_active()][0]
conn = self.conn.get_backend() conn = self.conn.get_backend()
devclass = VirtualCharDevice.get_dev_instance(conn, chartype, devtype) devclass = charclass(conn)
devclass.type = devtype
source_path = self.widget("char-path").get_text() source_path = self.widget("char-path").get_text()
source_mode = modebox.get_model()[modebox.get_active()][0] source_mode = modebox.get_model()[modebox.get_active()][0]
@ -1489,9 +1493,9 @@ class vmmAddHardware(vmmGObjectUI):
target_name = self.widget("char-target-name").get_text() target_name = self.widget("char-target-name").get_text()
if self.widget("char-use-telnet").get_active(): if self.widget("char-use-telnet").get_active():
protocol = VirtualCharDevice.CHAR_PROTOCOL_TELNET protocol = VirtualSerialDevice.PROTOCOL_TELNET
else: else:
protocol = VirtualCharDevice.CHAR_PROTOCOL_RAW protocol = VirtualSerialDevice.PROTOCOL_RAW
value_mappings = { value_mappings = {
"source_path" : source_path, "source_path" : source_path,
@ -1514,8 +1518,9 @@ class vmmAddHardware(vmmGObjectUI):
# Dump XML for sanity checking # Dump XML for sanity checking
self._dev.get_xml_config() self._dev.get_xml_config()
except Exception, e: except Exception, e:
return self.err.val_err(_("%s device parameter error") % return self.err.val_err(
chartype.capitalize(), e) _("%s device parameter error") %
charclass.virtual_device_type.capitalize(), e)
def validate_page_video(self): def validate_page_video(self):
conn = self.conn.get_backend() conn = self.conn.get_backend()

View File

@ -2417,8 +2417,8 @@ class vmmDetails(vmmGObjectUI):
has_multi_spice = (len([d for d in self.vm.get_graphics_devices() if has_multi_spice = (len([d for d in self.vm.get_graphics_devices() if
d.type == d.TYPE_SPICE]) > 1) d.type == d.TYPE_SPICE]) > 1)
has_spicevmc = bool([d for d in self.vm.get_char_devices() if has_spicevmc = bool([d for d in self.vm.get_char_devices() if
(d.dev_type == d.DEV_CHANNEL and (d.virtual_device_type == "channel" and
d.char_type == d.CHAR_SPICEVMC)]) d.type == "spicevmc")])
fromspice = (gdev.type == "spice") fromspice = (gdev.type == "spice")
tospice = (newgtype == "spice") tospice = (newgtype == "spice")
@ -3234,8 +3234,8 @@ class vmmDetails(vmmGObjectUI):
if not chardev: if not chardev:
return return
show_target_type = not (chardev.dev_type in show_target_type = not (chardev.virtual_device_type in
[chardev.DEV_SERIAL, chardev.DEV_PARALLEL]) ["serial", "parallel"])
def show_ui(param, val=None): def show_ui(param, val=None):
widgetname = "char-" + param.replace("_", "-") widgetname = "char-" + param.replace("_", "-")
@ -3268,7 +3268,7 @@ class vmmDetails(vmmGObjectUI):
char_type = chardev.virtual_device_type.capitalize() char_type = chardev.virtual_device_type.capitalize()
target_port = chardev.target_port target_port = chardev.target_port
dev_type = chardev.char_type or "pty" dev_type = chardev.type or "pty"
primary = hasattr(chardev, "virtmanager_console_dup") primary = hasattr(chardev, "virtmanager_console_dup")
typelabel = "" typelabel = ""

View File

@ -28,7 +28,6 @@ import threading
import libvirt import libvirt
import virtinst import virtinst
from virtinst.VirtualCharDevice import VirtualCharSpicevmcDevice
from virtManager import util from virtManager import util
from virtManager.libvirtobject import vmmLibvirtObject from virtManager.libvirtobject import vmmLibvirtObject
@ -45,12 +44,12 @@ def compare_device(origdev, newdev, idx):
"hostdev" : ["type", "managed", "vmmindex", "hostdev" : ["type", "managed", "vmmindex",
"product", "vendor", "product", "vendor",
"function", "domain", "slot"], "function", "domain", "slot"],
"serial" : ["char_type", "target_port"], "serial" : ["type", "target_port"],
"parallel" : ["char_type", "target_port"], "parallel" : ["type", "target_port"],
"console" : ["char_type", "target_type", "target_port"], "console" : ["type", "target_type", "target_port"],
"graphics" : ["type", "vmmindex"], "graphics" : ["type", "vmmindex"],
"controller" : ["type", "index"], "controller" : ["type", "index"],
"channel" : ["char_type", "target_name"], "channel" : ["type", "target_name"],
"filesystem" : ["target" , "vmmindex"], "filesystem" : ["target" , "vmmindex"],
"smartcard" : ["mode" , "vmmindex"], "smartcard" : ["mode" , "vmmindex"],
"redirdev" : ["bus" , "type", "vmmindex"], "redirdev" : ["bus" , "type", "vmmindex"],
@ -740,12 +739,13 @@ class vmmDomain(vmmLibvirtObject):
is_spice = (newval == virtinst.VirtualGraphics.TYPE_SPICE) is_spice = (newval == virtinst.VirtualGraphics.TYPE_SPICE)
if is_spice: if is_spice:
guest.add_device(VirtualCharSpicevmcDevice(guest.conn)) dev = virtinst.VirtualChannelDevice(guest.conn)
dev.type = dev.TYPE_SPICEVMC
guest.add_device(dev)
else: else:
channels = guest.get_devices("channel") channels = guest.get_devices("channel")
channels = [x for x in channels if channels = [x for x in guest.get_devices("channel")
(x.char_type == if x.type == "spicevmc"]
virtinst.VirtualCharDevice.CHAR_SPICEVMC)]
for dev in channels: for dev in channels:
guest.remove_device(dev) guest.remove_device(dev)
@ -1109,7 +1109,7 @@ class vmmDomain(vmmLibvirtObject):
con = consoles[0] con = consoles[0]
ser = serials[0] ser = serials[0]
if (con.char_type == ser.char_type and if (con.type == ser.type and
con.target_type is None or con.target_type == "serial"): con.target_type is None or con.target_type == "serial"):
ser.virtmanager_console_dup = con ser.virtmanager_console_dup = con
devs.remove(con) devs.remove(con)

View File

@ -264,7 +264,7 @@ class vmmSerialConsole(vmmGObject):
""" """
usable_types = ["pty"] usable_types = ["pty"]
ctype = dev.char_type ctype = dev.type
path = dev.source_path path = dev.source_path
is_remote = vm.conn.is_remote() is_remote = vm.conn.is_remote()
support_tunnel = vmmSerialConsole.support_remote_console(vm) support_tunnel = vmmSerialConsole.support_remote_console(vm)

View File

@ -35,7 +35,6 @@ from virtinst.xmlbuilder import XMLBuilder, XMLProperty
from virtinst.VirtualDevice import VirtualDevice from virtinst.VirtualDevice import VirtualDevice
from virtinst.VirtualDisk import VirtualDisk from virtinst.VirtualDisk import VirtualDisk
from virtinst.VirtualInputDevice import VirtualInputDevice from virtinst.VirtualInputDevice import VirtualInputDevice
from virtinst.VirtualCharDevice import VirtualCharDevice
from virtinst.VirtualController import VirtualController from virtinst.VirtualController import VirtualController
from virtinst.Clock import Clock from virtinst.Clock import Clock
from virtinst.Seclabel import Seclabel from virtinst.Seclabel import Seclabel
@ -626,10 +625,10 @@ class Guest(XMLBuilder):
"sound" : virtinst.VirtualAudio, "sound" : virtinst.VirtualAudio,
"hostdev" : virtinst.VirtualHostDevice, "hostdev" : virtinst.VirtualHostDevice,
"input" : virtinst.VirtualInputDevice, "input" : virtinst.VirtualInputDevice,
"serial" : virtinst.VirtualCharDevice, "serial" : virtinst.VirtualSerialDevice,
"parallel" : virtinst.VirtualCharDevice, "parallel" : virtinst.VirtualParallelDevice,
"console" : virtinst.VirtualCharDevice, "console" : virtinst.VirtualConsoleDevice,
"channel" : virtinst.VirtualCharDevice, "channel" : virtinst.VirtualChannelDevice,
"graphics" : virtinst.VirtualGraphics, "graphics" : virtinst.VirtualGraphics,
"video" : virtinst.VirtualVideoDevice, "video" : virtinst.VirtualVideoDevice,
"watchdog" : virtinst.VirtualWatchdog, "watchdog" : virtinst.VirtualWatchdog,
@ -653,11 +652,7 @@ class Guest(XMLBuilder):
devnode.virtinst_root_doc = self._xml_root_doc devnode.virtinst_root_doc = self._xml_root_doc
objclass = device_mappings.get(devnode.name) objclass = device_mappings.get(devnode.name)
if objclass == virtinst.VirtualCharDevice: dev = objclass(self.conn, parsexmlnode=devnode)
dev = objclass(self.conn, devnode.name,
parsexmlnode=devnode)
else:
dev = objclass(self.conn, parsexmlnode=devnode)
self._add_device(dev) self._add_device(dev)
self._xml_node.virtinst_root_doc = self._xml_root_doc self._xml_node.virtinst_root_doc = self._xml_root_doc
@ -681,9 +676,8 @@ class Guest(XMLBuilder):
return dev return dev
def _get_default_console_device(self): def _get_default_console_device(self):
dev = VirtualCharDevice.get_dev_instance(self.conn, dev = virtinst.VirtualConsoleDevice(self.conn)
VirtualCharDevice.DEV_CONSOLE, dev.type = dev.TYPE_PTY
VirtualCharDevice.CHAR_PTY)
return dev return dev
def _get_device_xml(self, devs, install=True): def _get_device_xml(self, devs, install=True):
@ -1383,16 +1377,15 @@ class Guest(XMLBuilder):
# Spice agent channel (only if we use spice) # Spice agent channel (only if we use spice)
def has_spice_agent(): def has_spice_agent():
for chn in devlist_func(channeltype): for chn in devlist_func(channeltype):
if chn.char_type == chn.CHAR_SPICEVMC: if chn.type == chn.TYPE_SPICEVMC:
return True return True
if (has_spice() and if (has_spice() and
not has_spice_agent() and not has_spice_agent() and
self.conn.check_conn_support( self.conn.check_conn_support(
self.conn.SUPPORT_CONN_HV_CHAR_SPICEVMC)): self.conn.SUPPORT_CONN_HV_CHAR_SPICEVMC)):
agentdev = VirtualCharDevice.get_dev_instance(self.conn, agentdev = virtinst.VirtualChannelDevice(self.conn)
VirtualCharDevice.DEV_CHANNEL, agentdev.type = agentdev.TYPE_SPICEVMC
VirtualCharDevice.CHAR_SPICEVMC)
self.add_device(agentdev) self.add_device(agentdev)
# Generate UUID # Generate UUID

View File

@ -22,7 +22,7 @@ from virtinst.xmlbuilder import XMLProperty
class VirtualAudio(VirtualDevice): class VirtualAudio(VirtualDevice):
_virtual_device_type = VirtualDevice.VIRTUAL_DEV_AUDIO virtual_device_type = VirtualDevice.VIRTUAL_DEV_AUDIO
MODEL_DEFAULT = "default" MODEL_DEFAULT = "default"
MODELS = ["es1370", "sb16", "pcspk", "ac97", "ich6", MODEL_DEFAULT] MODELS = ["es1370", "sb16", "pcspk", "ac97", "ich6", MODEL_DEFAULT]

View File

@ -18,617 +18,262 @@
# MA 02110-1301 USA. # MA 02110-1301 USA.
from virtinst.VirtualDevice import VirtualDevice from virtinst.VirtualDevice import VirtualDevice
from virtinst.util import xml_escape
from virtinst.xmlbuilder import XMLProperty from virtinst.xmlbuilder import XMLProperty
class VirtualCharDevice(VirtualDevice): class _VirtualCharDevice(VirtualDevice):
""" """
Base class for all character devices. Shouldn't be instantiated Base class for all character devices. Shouldn't be instantiated
directly. directly.
""" """
DEV_SERIAL = "serial" TYPE_PTY = "pty"
DEV_PARALLEL = "parallel" TYPE_DEV = "dev"
DEV_CONSOLE = "console" TYPE_STDIO = "stdio"
DEV_CHANNEL = "channel" TYPE_PIPE = "pipe"
dev_types = [DEV_SERIAL, DEV_PARALLEL, DEV_CONSOLE, DEV_CHANNEL] TYPE_FILE = "file"
TYPE_VC = "vc"
TYPE_NULL = "null"
TYPE_TCP = "tcp"
TYPE_UDP = "udp"
TYPE_UNIX = "unix"
TYPE_SPICEVMC = "spicevmc"
TYPES = [TYPE_PTY, TYPE_DEV, TYPE_STDIO, TYPE_FILE, TYPE_VC,
TYPE_PIPE, TYPE_NULL, TYPE_TCP, TYPE_UDP, TYPE_UNIX,
TYPE_SPICEVMC]
CHAR_PTY = "pty" MODE_CONNECT = "connect"
CHAR_DEV = "dev" MODE_BIND = "bind"
CHAR_STDIO = "stdio" MODES = [MODE_CONNECT, MODE_BIND]
CHAR_PIPE = "pipe"
CHAR_FILE = "file"
CHAR_VC = "vc"
CHAR_NULL = "null"
CHAR_TCP = "tcp"
CHAR_UDP = "udp"
CHAR_UNIX = "unix"
CHAR_SPICEVMC = "spicevmc"
char_types = [CHAR_PTY, CHAR_DEV, CHAR_STDIO, CHAR_FILE, CHAR_VC,
CHAR_PIPE, CHAR_NULL, CHAR_TCP, CHAR_UDP, CHAR_UNIX,
CHAR_SPICEVMC]
_non_channel_types = char_types[:] PROTOCOL_RAW = "raw"
_non_channel_types.remove(CHAR_SPICEVMC) PROTOCOL_TELNET = "telnet"
PROTOCOLS = [PROTOCOL_RAW, PROTOCOL_TELNET]
char_types_for_dev_type = { CHANNEL_TARGET_GUESTFWD = "guestfwd"
DEV_SERIAL: _non_channel_types, CHANNEL_TARGET_VIRTIO = "virtio"
DEV_PARALLEL: _non_channel_types, CHANNEL_TARGETS = [CHANNEL_TARGET_GUESTFWD,
DEV_CONSOLE: _non_channel_types, CHANNEL_TARGET_VIRTIO]
DEV_CHANNEL: [CHAR_SPICEVMC],
}
CHAR_MODE_CONNECT = "connect" CONSOLE_TARGET_SERIAL = "serial"
CHAR_MODE_BIND = "bind" CONSOLE_TARGET_UML = "uml"
char_modes = [CHAR_MODE_CONNECT, CHAR_MODE_BIND] CONSOLE_TARGET_XEN = "xen"
CONSOLE_TARGET_VIRTIO = "virtio"
CONSOLE_TARGETS = [CONSOLE_TARGET_SERIAL, CONSOLE_TARGET_UML,
CONSOLE_TARGET_XEN, CONSOLE_TARGET_VIRTIO]
CHAR_PROTOCOL_RAW = "raw" @staticmethod
CHAR_PROTOCOL_TELNET = "telnet" def pretty_type(ctype):
char_protocols = [CHAR_PROTOCOL_RAW, CHAR_PROTOCOL_TELNET]
CHAR_CHANNEL_TARGET_GUESTFWD = "guestfwd"
CHAR_CHANNEL_TARGET_VIRTIO = "virtio"
target_types = [CHAR_CHANNEL_TARGET_GUESTFWD,
CHAR_CHANNEL_TARGET_VIRTIO]
CHAR_CHANNEL_ADDRESS_VIRTIO_SERIAL = "virtio-serial"
address_types = [CHAR_CHANNEL_ADDRESS_VIRTIO_SERIAL]
CHAR_CONSOLE_TARGET_SERIAL = "serial"
CHAR_CONSOLE_TARGET_UML = "uml"
CHAR_CONSOLE_TARGET_XEN = "xen"
CHAR_CONSOLE_TARGET_VIRTIO = "virtio"
has_target = False
def get_char_type_desc(char_type):
""" """
Return a human readable description of the passed char type Return a human readable description of the passed char type
""" """
desc = "" desc = ""
if char_type == VirtualCharDevice.CHAR_PTY: if ctype == _VirtualCharDevice.TYPE_PTY:
desc = _("Pseudo TTY") desc = _("Pseudo TTY")
elif char_type == VirtualCharDevice.CHAR_DEV: elif ctype == _VirtualCharDevice.TYPE_DEV:
desc = _("Physical host character device") desc = _("Physical host character device")
elif char_type == VirtualCharDevice.CHAR_STDIO: elif ctype == _VirtualCharDevice.TYPE_STDIO:
desc = _("Standard input/output") desc = _("Standard input/output")
elif char_type == VirtualCharDevice.CHAR_PIPE: elif ctype == _VirtualCharDevice.TYPE_PIPE:
desc = _("Named pipe") desc = _("Named pipe")
elif char_type == VirtualCharDevice.CHAR_FILE: elif ctype == _VirtualCharDevice.TYPE_FILE:
desc = _("Output to a file") desc = _("Output to a file")
elif char_type == VirtualCharDevice.CHAR_VC: elif ctype == _VirtualCharDevice.TYPE_VC:
desc = _("Virtual console") desc = _("Virtual console")
elif char_type == VirtualCharDevice.CHAR_NULL: elif ctype == _VirtualCharDevice.TYPE_NULL:
desc = _("Null device") desc = _("Null device")
elif char_type == VirtualCharDevice.CHAR_TCP: elif ctype == _VirtualCharDevice.TYPE_TCP:
desc = _("TCP net console") desc = _("TCP net console")
elif char_type == VirtualCharDevice.CHAR_UDP: elif ctype == _VirtualCharDevice.TYPE_UDP:
desc = _("UDP net console") desc = _("UDP net console")
elif char_type == VirtualCharDevice.CHAR_UNIX: elif ctype == _VirtualCharDevice.TYPE_UNIX:
desc = _("Unix socket") desc = _("Unix socket")
elif char_type == VirtualCharDevice.CHAR_SPICEVMC: elif ctype == _VirtualCharDevice.TYPE_SPICEVMC:
desc = _("Spice agent") desc = _("Spice agent")
return desc return desc
get_char_type_desc = staticmethod(get_char_type_desc)
def get_char_mode_desc(char_mode): @staticmethod
def pretty_mode(char_mode):
""" """
Return a human readable description of the passed char type Return a human readable description of the passed char type
""" """
desc = "" desc = ""
if char_mode == VirtualCharDevice.CHAR_MODE_CONNECT: if char_mode == _VirtualCharDevice.MODE_CONNECT:
desc = _("Client mode") desc = _("Client mode")
elif char_mode == VirtualCharDevice.CHAR_MODE_BIND: elif char_mode == _VirtualCharDevice.MODE_BIND:
desc = _("Server mode") desc = _("Server mode")
return desc return desc
get_char_mode_desc = staticmethod(get_char_mode_desc)
# 'char_type' of class (must be properly set in subclass)
_char_type = None
def get_dev_instance(conn, dev_type, char_type):
"""
Set up the class attributes for the passed char_type
"""
# By default, all the possible parameters are enabled for the
# device class. We go through here and del() all the ones that
# don't apply. This is kind of whacky, but it's nice to to
# allow an API user to just use hasattr(obj, paramname) to see
# what parameters apply, instead of having to hardcode all that
# information.
if char_type == VirtualCharDevice.CHAR_PTY:
c = VirtualCharPtyDevice
elif char_type == VirtualCharDevice.CHAR_STDIO:
c = VirtualCharStdioDevice
elif char_type == VirtualCharDevice.CHAR_NULL:
c = VirtualCharNullDevice
elif char_type == VirtualCharDevice.CHAR_VC:
c = VirtualCharVcDevice
elif char_type == VirtualCharDevice.CHAR_DEV:
c = VirtualCharDevDevice
elif char_type == VirtualCharDevice.CHAR_FILE:
c = VirtualCharFileDevice
elif char_type == VirtualCharDevice.CHAR_PIPE:
c = VirtualCharPipeDevice
elif char_type == VirtualCharDevice.CHAR_TCP:
c = VirtualCharTcpDevice
elif char_type == VirtualCharDevice.CHAR_UNIX:
c = VirtualCharUnixDevice
elif char_type == VirtualCharDevice.CHAR_UDP:
c = VirtualCharUdpDevice
elif char_type == VirtualCharDevice.CHAR_SPICEVMC:
c = VirtualCharSpicevmcDevice
else:
raise ValueError(_("Unknown character device type '%s'.") %
char_type)
if dev_type == VirtualCharDevice.DEV_CONSOLE:
return VirtualConsoleDevice(conn)
return c(conn, dev_type)
get_dev_instance = staticmethod(get_dev_instance)
def __init__(self, conn, dev_type, parsexml=None, parsexmlnode=None):
if dev_type not in self.dev_types:
raise ValueError(_("Unknown character device type '%s'") % dev_type)
self._dev_type = dev_type
self._virtual_device_type = self._dev_type
VirtualDevice.__init__(self, conn, parsexml, parsexmlnode)
# Init
self._source_path = None
self._source_mode = self.CHAR_MODE_BIND
self._source_host = "127.0.0.1"
self._source_port = None
self._target_type = None
self._target_address = None
self._target_port = None
self._target_name = None
self._bind_host = None
self._bind_port = None
self._protocol = self.CHAR_PROTOCOL_RAW
self._address_type = None
if self.char_type == self.CHAR_UDP:
self._source_mode = self.CHAR_MODE_CONNECT
if self._is_parse():
return
if not self._char_type:
raise ValueError("Must be instantiated through a subclass.")
self.char_type = self._char_type
def supports_property(self, propname, ro=False): def supports_property(self, propname, ro=False):
""" """
Whether the character dev type supports the passed property name Whether the character dev type supports the passed property name
""" """
users = { users = {
"source_path" : [self.CHAR_FILE, self.CHAR_UNIX, "source_path" : [self.TYPE_FILE, self.TYPE_UNIX,
self.CHAR_DEV, self.CHAR_PIPE], self.TYPE_DEV, self.TYPE_PIPE],
"source_mode" : [self.CHAR_UNIX, self.CHAR_TCP], "source_mode" : [self.TYPE_UNIX, self.TYPE_TCP],
"source_host" : [self.CHAR_TCP, self.CHAR_UDP], "source_host" : [self.TYPE_TCP, self.TYPE_UDP],
"source_port" : [self.CHAR_TCP, self.CHAR_UDP], "source_port" : [self.TYPE_TCP, self.TYPE_UDP],
"protocol" : [self.CHAR_TCP], "protocol" : [self.TYPE_TCP],
"bind_host" : [self.CHAR_UDP], "bind_host" : [self.TYPE_UDP],
"bind_port" : [self.CHAR_UDP], "bind_port" : [self.TYPE_UDP],
} }
if ro: if ro:
users["source_path"] += [self.CHAR_PTY] users["source_path"] += [self.TYPE_PTY]
channel_users = { channel_users = {
"target_name" : [self.CHAR_CHANNEL_TARGET_VIRTIO], "target_name" : [self.CHANNEL_TARGET_VIRTIO],
} }
if users.get(propname): if users.get(propname):
return self.char_type in users[propname] return self.type in users[propname]
if channel_users.get(propname): if channel_users.get(propname):
return (self.dev_type == self.DEV_CHANNEL and return (self.virtual_device_type == "channel" and
self.target_type in channel_users[propname]) self.target_type in channel_users[propname])
return hasattr(self, propname) return hasattr(self, propname)
# Properties
def get_dev_type(self):
return self._dev_type
dev_type = property(get_dev_type)
def get_char_type(self): _XML_PROP_ORDER = ["type",
return self._char_type "bind_host", "bind_port",
def set_char_type(self, val): "source_mode", "source_path",
if val not in self.char_types: "source_host", "source_port",
raise ValueError(_("Unknown character device type '%s'") "target_type", "target_name"]
% val)
self._char_type = val type = XMLProperty(
char_type = XMLProperty(get_char_type, set_char_type,
doc=_("Method used to expose character device in the host."), doc=_("Method used to expose character device in the host."),
xpath="./@type") xpath="./@type")
# Properties functions used by the various subclasses
def get_source_path(self):
return self._source_path
def set_source_path(self, val):
self._source_path = val
def _sourcepath_get_xpath(self): def _sourcepath_get_xpath(self):
return "./source/@path | ./@tty" return "./source/@path | ./@tty"
source_path = XMLProperty(get_source_path, set_source_path, source_path = XMLProperty(xml_get_xpath=_sourcepath_get_xpath,
xml_get_xpath=_sourcepath_get_xpath, doc=_("Host input path to attach to the guest."),
xpath="./source/@path") xpath="./source/@path")
def get_source_mode(self): def _get_default_source_mode(self):
return self._source_mode if self.type == self.TYPE_UDP:
def set_source_mode(self, val): return self.MODE_CONNECT
if val not in self.char_modes: if not self.supports_property("source_mode"):
raise ValueError(_("Unknown character mode '%s'.") % val) return None
self._source_mode = val return self.MODE_BIND
def _sourcemode_xpath(self): def _sourcemode_xpath(self):
if self.char_type == self.CHAR_UDP: if self.type == self.TYPE_UDP:
return "./source[@mode='connect']/@mode" return "./source[@mode='connect']/@mode"
return "./source/@mode" return "./source/@mode"
source_mode = XMLProperty(get_source_mode, set_source_mode, source_mode = XMLProperty(name="char sourcemode",
name="char sourcemode", doc=_("Target connect/listen mode."),
xml_get_xpath=_sourcemode_xpath, xml_get_xpath=_sourcemode_xpath,
xml_set_xpath=_sourcemode_xpath) xml_set_xpath=_sourcemode_xpath,
default_cb=_get_default_source_mode)
def get_source_host(self): def _get_default_sourcehost(self):
return self._source_host if not self.supports_property("source_host"):
def set_source_host(self, val): return None
self._source_host = val return "127.0.0.1"
def _set_source_validate(self, val):
if val is None or self.type != self.TYPE_UDP:
return val
if not self._has_mode_connect:
self._has_mode_connect = self.MODE_CONNECT
return val
def _sourcehost_xpath(self): def _sourcehost_xpath(self):
return "./source[@mode='%s']/@host" % self.source_mode mode = self.source_mode
source_host = XMLProperty(get_source_host, set_source_host, if self.type == self.TYPE_UDP:
name="char sourcehost", mode = "connect"
xml_get_xpath=_sourcehost_xpath, return "./source[@mode='%s']/@host" % mode
xml_set_xpath=_sourcehost_xpath) source_host = XMLProperty(name="char sourcehost",
doc=_("Address to connect/listen to."),
xml_get_xpath=_sourcehost_xpath,
xml_set_xpath=_sourcehost_xpath,
default_cb=_get_default_sourcehost,
set_converter=_set_source_validate)
def get_source_port(self):
return self._source_port
def set_source_port(self, val):
self._source_port = int(val)
def _sourceport_xpath(self): def _sourceport_xpath(self):
return "./source[@mode='%s']/@service" % self.source_mode return "./source[@mode='%s']/@service" % self.source_mode
source_port = XMLProperty(get_source_port, set_source_port, def _get_sourceport_convert(self, val):
name="char sourceport", if val is None:
xml_get_xpath=_sourceport_xpath, return None
xml_set_xpath=_sourceport_xpath) return int(val)
def _set_sourceport_convert(self, val):
return self._get_sourceport_convert(self._set_source_validate(val))
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,
set_converter=_set_sourceport_convert,
get_converter=_get_sourceport_convert)
def get_bind_host(self): _has_mode_connect = XMLProperty(xpath="./source[@mode='connect']/@mode")
return self._bind_host _has_mode_bind = XMLProperty(xpath="./source[@mode='bind']/@mode")
def set_bind_host(self, val):
self._bind_host = val
bind_host = XMLProperty(get_bind_host, set_bind_host,
xpath="./source[@mode='bind']/@host")
def get_bind_port(self): def _set_bind_validate(self, val):
return self._bind_port if val is None:
def set_bind_port(self, val): return None
self._bind_port = int(val) if not self._has_mode_bind:
bind_port = XMLProperty(get_bind_port, set_bind_port, self._has_mode_bind = self.MODE_BIND
xpath="./source[@mode='bind']/@service") return val
bind_host = XMLProperty(xpath="./source[@mode='bind']/@host",
doc=_("Host addresss to bind to."),
set_converter=_set_bind_validate)
def _get_bindport_convert(self, val):
if val is None:
return None
return int(val)
def _set_bindport_convert(self, val):
return self._get_bindport_convert(self._set_bind_validate(val))
bind_port = XMLProperty(xpath="./source[@mode='bind']/@service",
doc=_("Host port to bind to."),
get_converter=_get_bindport_convert,
set_converter=_set_bindport_convert)
def get_protocol(self): def _get_default_protocol(self):
return self._protocol if not self.supports_property("protocol"):
def set_protocol(self, val): return None
if val not in self.char_protocols: return self.PROTOCOL_RAW
raise ValueError(_("Unknown protocol '%s'.") % val) protocol = XMLProperty(xpath="./protocol/@type",
self._protocol = val doc=_("Format used when sending data."),
protocol = XMLProperty(get_protocol, set_protocol, default_cb=_get_default_protocol)
xpath="./protocol/@type")
# GuestFWD target properties def _get_default_target_type(self):
def get_target_type(self): if self.type == self.TYPE_SPICEVMC:
return self._target_type return self.CHANNEL_TARGET_VIRTIO
def set_target_type(self, val): return None
if val not in self.target_types: target_type = XMLProperty(xpath="./target/@type",
raise ValueError(_("Unknown target type '%s'. Must be in: ") % val, doc=_("Channel type as exposed in the guest."),
self.target_types) default_cb=_get_default_target_type)
self._target_type = val
target_type = XMLProperty(get_target_type, set_target_type,
doc=_("Channel type as exposed in the guest."),
xpath="./target/@type")
def set_target_address(self, val): target_address = XMLProperty(xpath="./target/@address",
self._target_address = val doc=_("Guest forward channel address in the guest."))
def get_target_address(self):
return self._target_address
target_address = XMLProperty(get_target_address, set_target_address,
doc=_("Guest forward channel address in the guest."),
xpath="./target/@address")
def set_target_port(self, val): target_port = XMLProperty(xpath="./target/@port", is_int=True,
self._target_port = val doc=_("Guest forward channel port in the guest."))
def get_target_port(self):
return self._target_port
target_port = XMLProperty(get_target_port, set_target_port,
doc=_("Guest forward channel port in the guest."),
xpath="./target/@port")
def set_target_name(self, val): def _default_target_name(self):
self._target_name = val if self.type == self.TYPE_SPICEVMC:
def get_target_name(self): return "com.redhat.spice.0"
return self._target_name return None
target_name = XMLProperty(get_target_name, set_target_name, target_name = XMLProperty(xpath="./target/@name",
doc=_("Sysfs name of virtio port in the guest"), doc=_("Sysfs name of virtio port in the guest"),
xpath="./target/@name") default_cb=_default_target_name)
def get_address_type(self):
return self._address_type
def set_address_type(self, val):
if val not in self.address_types:
raise ValueError(_("Unknown address type '%s'. Must be in: ") % val,
self.address_types)
self._address_type = val
address_type = XMLProperty(get_address_type, set_address_type,
doc=_("Channel type as exposed in the guest."),
xpath="./address/@type")
# XML building helpers
def _char_empty_xml(self):
"""
Provide source xml for devices with no params (null, stdio, ...)
"""
return ""
def _char_file_xml(self):
"""
Provide source xml for devs that require only a path (dev, pipe)
"""
file_xml = ""
mode_xml = ""
if self.source_path:
file_xml = " path='%s'" % xml_escape(self.source_path)
else:
raise ValueError(_("A source path is required for character "
"device type '%s'" % self.char_type))
if self.supports_property("source_mode") and self.source_mode:
mode_xml = " mode='%s'" % xml_escape(self.source_mode)
xml = " <source%s%s/>\n" % (mode_xml, file_xml)
return xml
def _char_xml(self):
pass
def _get_target_xml(self):
xml = ""
if not self.target_type:
return xml
xml = " <target type='%s'" % self.target_type
if self._dev_type == self.DEV_CHANNEL:
if self.target_type == self.CHAR_CHANNEL_TARGET_GUESTFWD:
if not self.target_address and not self.target_port:
raise RuntimeError("A target address and port must be "
"specified for '%s'" % self.target_type)
xml += " address='%s'" % self.target_address
xml += " port='%s'" % self.target_port
elif self.target_type == self.CHAR_CHANNEL_TARGET_VIRTIO:
if self.target_name:
xml += " name='%s'" % self.target_name
xml += "/>\n" class VirtualConsoleDevice(_VirtualCharDevice):
return xml virtual_device_type = "console"
def _get_address_xml(self):
xml = ""
if not self.address_type:
return xml
xml = " <address type='%s'" % self.address_type
xml += "/>\n"
return xml
def _get_xml_config(self): class VirtualSerialDevice(_VirtualCharDevice):
xml = " <%s type='%s'" % (self._dev_type, self._char_type) virtual_device_type = "serial"
char_xml = self._char_xml()
target_xml = self._get_target_xml()
has_target = (self._dev_type == self.DEV_CHANNEL or
self._dev_type == self.DEV_CONSOLE or
self.has_target)
if target_xml and not has_target:
raise RuntimeError(
"Target parameters not used with '%s' devices, only '%s'" %
(self._dev_type, self.DEV_CHANNEL))
address_xml = self._get_address_xml()
has_address = self._target_type == self.CHAR_CHANNEL_TARGET_VIRTIO
if address_xml and not has_address:
raise RuntimeError(
"Address parameters not used with '%s' target, only '%s'" %
(self._target_type, self.CHAR_CHANNEL_TARGET_VIRTIO))
if char_xml or target_xml or address_xml:
xml += ">"
if char_xml:
xml += "\n%s" % char_xml
if target_xml:
xml += "\n%s" % target_xml
if address_xml:
xml += "\n%s" % target_xml
xml += " </%s>" % self._dev_type
else:
xml += "/>"
return xml
# Back compat class for building a simple PTY 'console' element
class VirtualConsoleDevice(VirtualCharDevice): class VirtualParallelDevice(_VirtualCharDevice):
_char_xml = VirtualCharDevice._char_empty_xml virtual_device_type = "parallel"
_char_type = VirtualCharDevice.CHAR_PTY
def __init__(self, conn, parsexml=None, parsexmlnode=None):
VirtualCharDevice.__init__(self, conn, VirtualCharDevice.DEV_CONSOLE,
parsexml, parsexmlnode)
self.target_types = [self.CHAR_CONSOLE_TARGET_SERIAL,
self.CHAR_CONSOLE_TARGET_VIRTIO,
self.CHAR_CONSOLE_TARGET_XEN,
self.CHAR_CONSOLE_TARGET_UML]
# Classes for each device 'type'
class VirtualCharPtyDevice(VirtualCharDevice): class VirtualChannelDevice(_VirtualCharDevice):
_char_type = VirtualCharDevice.CHAR_PTY virtual_device_type = "channel"
_char_xml = VirtualCharDevice._char_empty_xml TYPES = [_VirtualCharDevice.TYPE_SPICEVMC]
source_path = property(VirtualCharDevice.get_source_path,
VirtualCharDevice.set_source_path,
doc=_("PTY allocated to the guest."))
class VirtualCharStdioDevice(VirtualCharDevice):
_char_type = VirtualCharDevice.CHAR_STDIO
_char_xml = VirtualCharDevice._char_empty_xml
class VirtualCharNullDevice(VirtualCharDevice):
_char_type = VirtualCharDevice.CHAR_NULL
_char_xml = VirtualCharDevice._char_empty_xml
class VirtualCharVcDevice(VirtualCharDevice):
_char_type = VirtualCharDevice.CHAR_VC
_char_xml = VirtualCharDevice._char_empty_xml
class VirtualCharDevDevice(VirtualCharDevice):
_char_type = VirtualCharDevice.CHAR_DEV
_char_xml = VirtualCharDevice._char_file_xml
source_path = property(VirtualCharDevice.get_source_path,
VirtualCharDevice.set_source_path,
doc=_("Host character device to attach to guest."))
class VirtualCharPipeDevice(VirtualCharDevice):
_char_type = VirtualCharDevice.CHAR_PIPE
_char_xml = VirtualCharDevice._char_file_xml
source_path = property(VirtualCharDevice.get_source_path,
VirtualCharDevice.set_source_path,
doc=_("Named pipe to use for input and output."))
class VirtualCharFileDevice(VirtualCharDevice):
_char_type = VirtualCharDevice.CHAR_FILE
_char_xml = VirtualCharDevice._char_file_xml
source_path = property(VirtualCharDevice.get_source_path,
VirtualCharDevice.set_source_path,
doc=_("File path to record device output."))
class VirtualCharUnixDevice(VirtualCharDevice):
_char_type = VirtualCharDevice.CHAR_UNIX
_char_xml = VirtualCharDevice._char_file_xml
source_mode = property(VirtualCharDevice.get_source_mode,
VirtualCharDevice.set_source_mode,
doc=_("Target connect/listen mode."))
source_path = property(VirtualCharDevice.get_source_path,
VirtualCharDevice.set_source_path,
doc=_("Unix socket path."))
class VirtualCharTcpDevice(VirtualCharDevice):
_char_type = VirtualCharDevice.CHAR_TCP
source_mode = property(VirtualCharDevice.get_source_mode,
VirtualCharDevice.set_source_mode,
doc=_("Target connect/listen mode."))
source_host = property(VirtualCharDevice.get_source_host,
VirtualCharDevice.set_source_host,
doc=_("Address to connect/listen to."))
source_port = property(VirtualCharDevice.get_source_port,
VirtualCharDevice.set_source_port,
doc=_("Port on target host to connect/listen to."))
protocol = property(VirtualCharDevice.get_protocol,
VirtualCharDevice.set_protocol,
doc=_("Format used when sending data."))
def _char_xml(self):
if not self.source_host and not self.source_port:
raise ValueError(_("A host and port must be specified."))
xml = (" <source mode='%s' host='%s' service='%s'/>\n" %
(self.source_mode, self.source_host, self.source_port))
xml += " <protocol type='%s'/>\n" % self.protocol
return xml
class VirtualCharUdpDevice(VirtualCharDevice):
_char_type = VirtualCharDevice.CHAR_UDP
bind_host = property(VirtualCharDevice.get_bind_host,
VirtualCharDevice.set_bind_host,
doc=_("Host address to bind to."))
bind_port = property(VirtualCharDevice.get_bind_port,
VirtualCharDevice.set_bind_port,
doc=_("Host port to bind to."))
source_host = property(VirtualCharDevice.get_source_host,
VirtualCharDevice.set_source_host,
doc=_("Host address to send output to."))
source_port = property(VirtualCharDevice.get_source_port,
VirtualCharDevice.set_source_port,
doc=_("Host port to send output to."))
# XXX: UDP: Only source _connect_ port required?
def _char_xml(self):
if not self.source_port:
raise ValueError(_("A connection port must be specified."))
xml = ""
bind_xml = ""
bind_host_xml = ""
bind_port_xml = ""
source_host_xml = ""
if self.bind_port:
bind_port_xml = " service='%s'" % self.bind_port
if not self.bind_host:
self.bind_host = "127.0.0.1"
if self.bind_host:
bind_host_xml = " host='%s'" % self.bind_host
if self.source_host:
source_host_xml = " host='%s'" % self.source_host
if self.bind_host or self.bind_port:
bind_xml = (" <source mode='bind'%s%s/>\n" %
(bind_host_xml, bind_port_xml))
xml += bind_xml
xml += (" <source mode='connect'%s service='%s'/>\n" %
(source_host_xml, self.source_port))
return xml
class VirtualCharSpicevmcDevice(VirtualCharDevice):
_char_type = VirtualCharDevice.CHAR_SPICEVMC
_char_xml = VirtualCharDevice._char_empty_xml
target_types = [VirtualCharDevice.CHAR_CHANNEL_TARGET_VIRTIO]
has_target = True
def __init__(self, conn, dev_type=VirtualCharDevice.DEV_CHANNEL,
parsexml=None, parsexmlnode=None):
VirtualCharDevice.__init__(self, conn, dev_type,
parsexml, parsexmlnode)
self._target_type = VirtualCharDevice.CHAR_CHANNEL_TARGET_VIRTIO
self._target_name = "com.redhat.spice.0"

View File

@ -22,7 +22,7 @@ from virtinst.xmlbuilder import XMLProperty
class VirtualController(VirtualDevice): class VirtualController(VirtualDevice):
_virtual_device_type = VirtualDevice.VIRTUAL_DEV_CONTROLLER virtual_device_type = VirtualDevice.VIRTUAL_DEV_CONTROLLER
TYPE_IDE = "ide" TYPE_IDE = "ide"
TYPE_FDC = "fdc" TYPE_FDC = "fdc"

View File

@ -69,7 +69,7 @@ class VirtualDevice(XMLBuilder):
VIRTUAL_DEV_TPM] VIRTUAL_DEV_TPM]
# General device type (disk, interface, etc.) # General device type (disk, interface, etc.)
_virtual_device_type = None virtual_device_type = None
_XML_INDENT = 4 _XML_INDENT = 4
def __init__(self, conn, parsexml=None, parsexmlnode=None): def __init__(self, conn, parsexml=None, parsexmlnode=None):
@ -79,24 +79,20 @@ class VirtualDevice(XMLBuilder):
@param conn: libvirt connection to validate device against @param conn: libvirt connection to validate device against
""" """
XMLBuilder.__init__(self, conn, parsexml, parsexmlnode) XMLBuilder.__init__(self, conn, parsexml, parsexmlnode)
self._XML_ROOT_NAME = self._virtual_device_type self._XML_ROOT_NAME = self.virtual_device_type
self.alias = VirtualDeviceAlias(conn, parsexmlnode=parsexmlnode) self.alias = VirtualDeviceAlias(conn, parsexmlnode=parsexmlnode)
self.address = VirtualDeviceAddress(conn, parsexmlnode=parsexmlnode) self.address = VirtualDeviceAddress(conn, parsexmlnode=parsexmlnode)
self._XML_SUB_ELEMENTS = ["alias", "address"] self._XML_SUB_ELEMENTS = ["alias", "address"]
if not self._virtual_device_type: if not self.virtual_device_type:
raise ValueError(_("Virtual device type must be set in subclass.")) raise ValueError(_("Virtual device type must be set in subclass."))
if self._virtual_device_type not in self.virtual_device_types: if self.virtual_device_type not in self.virtual_device_types:
raise ValueError(_("Unknown virtual device type '%s'.") % raise ValueError(_("Unknown virtual device type '%s'.") %
self._virtual_device_type) self.virtual_device_type)
def get_virtual_device_type(self):
return self._virtual_device_type
virtual_device_type = property(get_virtual_device_type)
def setup(self, meter=None): def setup(self, meter=None):
""" """
Perform potentially hazardous device initialization, like Perform potentially hazardous device initialization, like

View File

@ -142,7 +142,7 @@ class VirtualDisk(VirtualDevice):
# pylint: disable=W0622 # pylint: disable=W0622
# Redefining built-in 'type', but it matches the XML so keep it # Redefining built-in 'type', but it matches the XML so keep it
_virtual_device_type = VirtualDevice.VIRTUAL_DEV_DISK virtual_device_type = VirtualDevice.VIRTUAL_DEV_DISK
DRIVER_FILE = "file" DRIVER_FILE = "file"
DRIVER_PHY = "phy" DRIVER_PHY = "phy"

View File

@ -24,7 +24,7 @@ from virtinst.xmlbuilder import XMLProperty
class VirtualFilesystem(VirtualDevice): class VirtualFilesystem(VirtualDevice):
_virtual_device_type = VirtualDevice.VIRTUAL_DEV_FILESYSTEM virtual_device_type = VirtualDevice.VIRTUAL_DEV_FILESYSTEM
_target_props = ["dir", "name", "file", "dev"] _target_props = ["dir", "name", "file", "dev"]

View File

@ -58,7 +58,7 @@ def _yes_bool(val):
class VirtualGraphics(VirtualDevice): class VirtualGraphics(VirtualDevice):
_virtual_device_type = VirtualDevice.VIRTUAL_DEV_GRAPHICS virtual_device_type = VirtualDevice.VIRTUAL_DEV_GRAPHICS
TYPE_SDL = "sdl" TYPE_SDL = "sdl"
TYPE_VNC = "vnc" TYPE_VNC = "vnc"

View File

@ -23,7 +23,7 @@ from virtinst import NodeDeviceParser
class VirtualHostDevice(VirtualDevice): class VirtualHostDevice(VirtualDevice):
_virtual_device_type = VirtualDevice.VIRTUAL_DEV_HOSTDEV virtual_device_type = VirtualDevice.VIRTUAL_DEV_HOSTDEV
@staticmethod @staticmethod
def device_from_node(conn, name=None, nodedev=None, is_dup=False, def device_from_node(conn, name=None, nodedev=None, is_dup=False,

View File

@ -22,7 +22,7 @@ from virtinst.xmlbuilder import XMLProperty
class VirtualInputDevice(VirtualDevice): class VirtualInputDevice(VirtualDevice):
_virtual_device_type = VirtualDevice.VIRTUAL_DEV_INPUT virtual_device_type = VirtualDevice.VIRTUAL_DEV_INPUT
TYPE_MOUSE = "mouse" TYPE_MOUSE = "mouse"
TYPE_TABLET = "tablet" TYPE_TABLET = "tablet"

View File

@ -22,7 +22,7 @@ from virtinst.xmlbuilder import XMLProperty
class VirtualMemballoon(VirtualDevice): class VirtualMemballoon(VirtualDevice):
_virtual_device_type = VirtualDevice.VIRTUAL_DEV_MEMBALLOON virtual_device_type = VirtualDevice.VIRTUAL_DEV_MEMBALLOON
MODEL_DEFAULT = "virtio" MODEL_DEFAULT = "virtio"
MODELS = ["xen", "none", MODEL_DEFAULT] MODELS = ["xen", "none", MODEL_DEFAULT]

View File

@ -66,7 +66,7 @@ class VirtualPort(XMLBuilder):
class VirtualNetworkInterface(VirtualDevice): class VirtualNetworkInterface(VirtualDevice):
_virtual_device_type = VirtualDevice.VIRTUAL_DEV_NET virtual_device_type = VirtualDevice.VIRTUAL_DEV_NET
TYPE_BRIDGE = "bridge" TYPE_BRIDGE = "bridge"
TYPE_VIRTUAL = "network" TYPE_VIRTUAL = "network"

View File

@ -26,7 +26,7 @@ from virtinst.xmlbuilder import XMLProperty
class VirtualRedirDevice(VirtualDevice): class VirtualRedirDevice(VirtualDevice):
_virtual_device_type = VirtualDevice.VIRTUAL_DEV_REDIRDEV virtual_device_type = VirtualDevice.VIRTUAL_DEV_REDIRDEV
BUS_DEFAULT = "default" BUS_DEFAULT = "default"
BUSES = ["usb"] BUSES = ["usb"]

View File

@ -25,7 +25,7 @@ from virtinst.xmlbuilder import XMLProperty
class VirtualSmartCardDevice(VirtualDevice): class VirtualSmartCardDevice(VirtualDevice):
_virtual_device_type = VirtualDevice.VIRTUAL_DEV_SMARTCARD virtual_device_type = VirtualDevice.VIRTUAL_DEV_SMARTCARD
# Default models list # Default models list
MODE_DEFAULT = "default" MODE_DEFAULT = "default"

View File

@ -28,7 +28,7 @@ from virtinst.xmlbuilder import XMLProperty
class VirtualTPMDevice(VirtualDevice): class VirtualTPMDevice(VirtualDevice):
_virtual_device_type = VirtualDevice.VIRTUAL_DEV_TPM virtual_device_type = VirtualDevice.VIRTUAL_DEV_TPM
TYPE_PASSTHROUGH = "passthrough" TYPE_PASSTHROUGH = "passthrough"
TYPE_DEFAULT = "default" TYPE_DEFAULT = "default"

View File

@ -23,7 +23,7 @@ from virtinst.xmlbuilder import XMLProperty
class VirtualVideoDevice(VirtualDevice): class VirtualVideoDevice(VirtualDevice):
_virtual_device_type = VirtualDevice.VIRTUAL_DEV_VIDEO virtual_device_type = VirtualDevice.VIRTUAL_DEV_VIDEO
# Default models list # Default models list
MODEL_DEFAULT = "default" MODEL_DEFAULT = "default"

View File

@ -23,7 +23,7 @@ from virtinst.xmlbuilder import XMLProperty
class VirtualWatchdog(VirtualDevice): class VirtualWatchdog(VirtualDevice):
_virtual_device_type = VirtualDevice.VIRTUAL_DEV_WATCHDOG virtual_device_type = VirtualDevice.VIRTUAL_DEV_WATCHDOG
MODEL_I6300 = "i6300esb" MODEL_I6300 = "i6300esb"
MODEL_IB700 = "ib700" MODEL_IB700 = "ib700"

View File

@ -28,7 +28,10 @@ from virtinst.VirtualAudio import VirtualAudio
from virtinst.VirtualInputDevice import VirtualInputDevice from virtinst.VirtualInputDevice import VirtualInputDevice
from virtinst.VirtualDisk import VirtualDisk from virtinst.VirtualDisk import VirtualDisk
from virtinst.VirtualHostDevice import VirtualHostDevice from virtinst.VirtualHostDevice import VirtualHostDevice
from virtinst.VirtualCharDevice import VirtualCharDevice from virtinst.VirtualCharDevice import (VirtualChannelDevice,
VirtualConsoleDevice,
VirtualParallelDevice,
VirtualSerialDevice)
from virtinst.VirtualVideoDevice import VirtualVideoDevice from virtinst.VirtualVideoDevice import VirtualVideoDevice
from virtinst.VirtualController import VirtualController from virtinst.VirtualController import VirtualController
from virtinst.VirtualWatchdog import VirtualWatchdog from virtinst.VirtualWatchdog import VirtualWatchdog

View File

@ -42,7 +42,6 @@ from virtinst import VirtualNetworkInterface
from virtinst import VirtualGraphics from virtinst import VirtualGraphics
from virtinst import VirtualAudio from virtinst import VirtualAudio
from virtinst import VirtualDisk from virtinst import VirtualDisk
from virtinst import VirtualCharDevice
DEFAULT_POOL_PATH = "/var/lib/libvirt/images" DEFAULT_POOL_PATH = "/var/lib/libvirt/images"
@ -1813,32 +1812,36 @@ def parse_memballoon(guest, optstring, dev=None):
###################################################### ######################################################
def parse_serial(guest, optstring, dev=None): def parse_serial(guest, optstring, dev=None):
return _parse_char(guest, optstring, "serial", dev) if not dev:
dev = virtinst.VirtualSerialDevice(guest.conn)
return _parse_char(optstring, "serial", dev)
def parse_parallel(guest, optstring, dev=None): def parse_parallel(guest, optstring, dev=None):
return _parse_char(guest, optstring, "parallel", dev) if not dev:
dev = virtinst.VirtualParallelDevice(guest.conn)
return _parse_char(optstring, "parallel", dev)
def parse_console(guest, optstring, dev=None): def parse_console(guest, optstring, dev=None):
return _parse_char(guest, optstring, "console", dev) if not dev:
dev = virtinst.VirtualConsoleDevice(guest.conn)
return _parse_char(optstring, "console", dev)
def parse_channel(guest, optstring, dev=None): def parse_channel(guest, optstring, dev=None):
return _parse_char(guest, optstring, "channel", dev) if not dev:
dev = virtinst.VirtualChannelDevice(guest.conn)
return _parse_char(optstring, "channel", dev)
def _parse_char(guest, optstring, dev_type, dev=None): def _parse_char(optstring, dev_type, dev=None):
""" """
Helper to parse --serial/--parallel options Helper to parse --serial/--parallel options
""" """
# Peel the char type off the front # Peel the char type off the front
opts = parse_optstr(optstring, remove_first="char_type") opts = parse_optstr(optstring, remove_first="char_type")
char_type = opts.get("char_type") ctype = opts.get("char_type")
if not dev:
dev = VirtualCharDevice.get_dev_instance(guest.conn,
dev_type, char_type)
def set_param(paramname, dictname, val=None): def set_param(paramname, dictname, val=None):
val = get_opt_param(opts, dictname, val) val = get_opt_param(opts, dictname, val)
@ -1848,7 +1851,7 @@ def _parse_char(guest, optstring, dev_type, dev=None):
if not dev.supports_property(paramname): if not dev.supports_property(paramname):
raise ValueError(_("%(devtype)s type '%(chartype)s' does not " raise ValueError(_("%(devtype)s type '%(chartype)s' does not "
"support '%(optname)s' option.") % "support '%(optname)s' option.") %
{"devtype" : dev_type, "chartype": char_type, {"devtype" : dev_type, "chartype": ctype,
"optname" : dictname}) "optname" : dictname})
setattr(dev, paramname, val) setattr(dev, paramname, val)
@ -1863,7 +1866,7 @@ def _parse_char(guest, optstring, dev_type, dev=None):
bind_host, bind_port = parse_host("bind_host") bind_host, bind_port = parse_host("bind_host")
target_addr, target_port = parse_host("target_address") target_addr, target_port = parse_host("target_address")
set_param("char_type", "char_type") set_param("type", "char_type")
set_param("source_path", "path") set_param("source_path", "path")
set_param("source_mode", "mode") set_param("source_mode", "mode")
set_param("protocol", "protocol") set_param("protocol", "protocol")

View File

@ -313,8 +313,8 @@ class XMLProperty(property):
raise RuntimeError("Can't set default_cb for old style XML " raise RuntimeError("Can't set default_cb for old style XML "
"prop.") "prop.")
property.__init__(self, fget=self.new_getter, fset=self.new_setter, property.__init__(self, fget=self.new_getter, fset=self.new_setter)
doc=doc) self.__doc__ = doc
################## ##################
@ -344,7 +344,7 @@ class XMLProperty(property):
Map the raw property() instance to the param name it's exposed Map the raw property() instance to the param name it's exposed
as in the XMLBuilder class. This is just for debug purposes. as in the XMLBuilder class. This is just for debug purposes.
""" """
for key, val in xmlbuilder._all_xml_props().items(): for key, val in xmlbuilder.all_xml_props().items():
if val is self: if val is self:
return key return key
raise RuntimeError("Didn't find expected property") raise RuntimeError("Didn't find expected property")
@ -703,7 +703,7 @@ class XMLBuilder(object):
Refresh the XML for the passed class propname. Used to adjust Refresh the XML for the passed class propname. Used to adjust
the XML when an interdependent property changes. the XML when an interdependent property changes.
""" """
self._all_xml_props()[propname].refresh_xml(self) self.all_xml_props()[propname].refresh_xml(self)
################### ###################
@ -772,7 +772,7 @@ class XMLBuilder(object):
self._set_xml_context() self._set_xml_context()
def _all_xml_props(self): def all_xml_props(self):
ret = {} ret = {}
for c in reversed(type.mro(self.__class__)[:-1]): for c in reversed(type.mro(self.__class__)[:-1]):
for key, val in c.__dict__.items(): for key, val in c.__dict__.items():
@ -782,7 +782,7 @@ class XMLBuilder(object):
def _do_add_parse_bits(self, xml): def _do_add_parse_bits(self, xml):
# Find all properties that have default callbacks # Find all properties that have default callbacks
xmlprops = self._all_xml_props() xmlprops = self.all_xml_props()
defaultprops = [v for v in xmlprops.values() if v.has_default_value()] defaultprops = [v for v in xmlprops.values() if v.has_default_value()]
for prop in defaultprops: for prop in defaultprops:
prop.set_default(self) prop.set_default(self)