1# 2# Copyright 2009, 2013 Red Hat, Inc. 3# 4# This work is licensed under the GNU GPLv2 or later. 5# See the COPYING file in the top-level directory. 6 7from .device import Device, DeviceSeclabel 8from ..xmlbuilder import XMLBuilder, XMLChildProperty, XMLProperty 9from .. import xmlutil 10 11 12def _set_host_helper(obj, hostparam, portparam, val): 13 def parse_host(val): 14 host, ignore, port = (val or "").partition(":") 15 return host or None, port or None 16 17 host, port = parse_host(val) 18 if port and not host: 19 host = "127.0.0.1" 20 xmlutil.set_prop_path(obj, hostparam, host) 21 if port: 22 xmlutil.set_prop_path(obj, portparam, port) 23 24 25class CharSource(XMLBuilder): 26 XML_NAME = "source" 27 _XML_PROP_ORDER = ["bind_host", "bind_service", 28 "mode", "connect_host", "connect_service", 29 "path", "channel"] 30 31 def set_friendly_connect(self, val): 32 _set_host_helper(self, "connect_host", "connect_service", val) 33 def set_friendly_bind(self, val): 34 _set_host_helper(self, "bind_host", "bind_service", val) 35 def set_friendly_host(self, val): 36 _set_host_helper(self, "host", "service", val) 37 38 seclabels = XMLChildProperty(DeviceSeclabel) 39 40 host = XMLProperty("./@host") 41 service = XMLProperty("./@service", is_int=True) 42 path = XMLProperty("./@path") 43 channel = XMLProperty("./@channel") 44 master = XMLProperty("./@master") 45 slave = XMLProperty("./@slave") 46 mode = XMLProperty("./@mode") 47 48 # It's weird to track these properties here, since the XML is set on 49 # the parent, but this is how libvirt does it internally, which means 50 # everything that shares a charsource has these values too. 51 protocol = XMLProperty("./../protocol/@type") 52 log_file = XMLProperty("./../log/@file") 53 log_append = XMLProperty("./../log/@append", is_onoff=True) 54 55 56 # Convenience source helpers for setting connect/bind host and service 57 connect_host = XMLProperty("./../source[@mode='connect']/@host") 58 connect_service = XMLProperty( 59 "./../source[@mode='connect']/@service", is_int=True) 60 bind_host = XMLProperty("./../source[@mode='bind']/@host") 61 bind_service = XMLProperty("./../source[@mode='bind']/@service", is_int=True) 62 63 64class _DeviceChar(Device): 65 """ 66 Base class for all character devices. Shouldn't be instantiated 67 directly. 68 """ 69 70 TYPE_PTY = "pty" 71 TYPE_DEV = "dev" 72 TYPE_STDIO = "stdio" 73 TYPE_PIPE = "pipe" 74 TYPE_FILE = "file" 75 TYPE_VC = "vc" 76 TYPE_NULL = "null" 77 TYPE_TCP = "tcp" 78 TYPE_UDP = "udp" 79 TYPE_UNIX = "unix" 80 TYPE_SPICEVMC = "spicevmc" 81 TYPE_SPICEPORT = "spiceport" 82 TYPE_NMDM = "nmdm" 83 84 CHANNEL_NAME_SPICE = "com.redhat.spice.0" 85 CHANNEL_NAME_QEMUGA = "org.qemu.guest_agent.0" 86 CHANNEL_NAME_LIBGUESTFS = "org.libguestfs.channel.0" 87 CHANNEL_NAME_SPICE_WEBDAV = "org.spice-space.webdav.0" 88 CHANNEL_NAMES = [CHANNEL_NAME_SPICE, 89 CHANNEL_NAME_QEMUGA, 90 CHANNEL_NAME_LIBGUESTFS, 91 CHANNEL_NAME_SPICE_WEBDAV] 92 93 def set_friendly_target(self, val): 94 _set_host_helper(self, "target_address", "target_port", val) 95 96 _XML_PROP_ORDER = ["type", "source", 97 "target_type", "target_name", "target_state"] 98 99 type = XMLProperty("./@type") 100 source = XMLChildProperty(CharSource, is_single=True) 101 102 target_address = XMLProperty("./target/@address") 103 target_port = XMLProperty("./target/@port", is_int=True) 104 target_type = XMLProperty("./target/@type") 105 target_name = XMLProperty("./target/@name") 106 target_state = XMLProperty("./target/@state") 107 target_model_name = XMLProperty("./target/model/@name") 108 109 110 ################## 111 # Default config # 112 ################## 113 114 def set_defaults(self, _guest): 115 if (not self.source.mode and 116 self.type in [self.TYPE_UNIX, self.TYPE_TCP]): 117 self.source.mode = "bind" 118 if not self.target_type and self.DEVICE_TYPE == "channel": 119 self.target_type = "virtio" 120 if not self.target_name and self.type == self.TYPE_SPICEVMC: 121 self.target_name = self.CHANNEL_NAME_SPICE 122 123 124 125class DeviceConsole(_DeviceChar): 126 @staticmethod 127 def get_console_duplicate(guest, serial): 128 """ 129 Determine if the passed serial device has a duplicate 130 <console> device in the passed Guest 131 """ 132 if serial.DEVICE_TYPE != "serial": 133 return 134 135 consoles = guest.devices.console 136 if not consoles: 137 return # pragma: no cover 138 139 console = consoles[0] 140 if (console.type == serial.type and 141 (console.target_type is None or console.target_type == "serial")): 142 return console 143 144 XML_NAME = "console" 145 146 147class DeviceSerial(_DeviceChar): 148 XML_NAME = "serial" 149 150 151class DeviceParallel(_DeviceChar): 152 XML_NAME = "parallel" 153 154 155class DeviceChannel(_DeviceChar): 156 XML_NAME = "channel" 157