mirror of
https://github.com/virt-manager/virt-manager.git
synced 2024-12-23 17:34:21 +03:00
44033b43bb
This is a quirk of libvirt that the first <device> is usually a logical duplicate of the first <serial> device. Adjust virt-xml to understand this quirk and remove both devices at the same time, like we already do in virt-manager https://bugzilla.redhat.com/show_bug.cgi?id=1685541 Signed-off-by: Cole Robinson <crobinso@redhat.com>
157 lines
4.9 KiB
Python
157 lines
4.9 KiB
Python
#
|
|
# Copyright 2009, 2013 Red Hat, Inc.
|
|
#
|
|
# This work is licensed under the GNU GPLv2 or later.
|
|
# See the COPYING file in the top-level directory.
|
|
|
|
from .device import Device, DeviceSeclabel
|
|
from ..xmlbuilder import XMLBuilder, XMLChildProperty, XMLProperty
|
|
from .. import xmlutil
|
|
|
|
|
|
def _set_host_helper(obj, hostparam, portparam, val):
|
|
def parse_host(val):
|
|
host, ignore, port = (val or "").partition(":")
|
|
return host or None, port or None
|
|
|
|
host, port = parse_host(val)
|
|
if port and not host:
|
|
host = "127.0.0.1"
|
|
xmlutil.set_prop_path(obj, hostparam, host)
|
|
if port:
|
|
xmlutil.set_prop_path(obj, portparam, port)
|
|
|
|
|
|
class CharSource(XMLBuilder):
|
|
XML_NAME = "source"
|
|
_XML_PROP_ORDER = ["bind_host", "bind_service",
|
|
"mode", "connect_host", "connect_service",
|
|
"path", "channel"]
|
|
|
|
def set_friendly_connect(self, val):
|
|
_set_host_helper(self, "connect_host", "connect_service", val)
|
|
def set_friendly_bind(self, val):
|
|
_set_host_helper(self, "bind_host", "bind_service", val)
|
|
def set_friendly_host(self, val):
|
|
_set_host_helper(self, "host", "service", val)
|
|
|
|
seclabels = XMLChildProperty(DeviceSeclabel)
|
|
|
|
host = XMLProperty("./@host")
|
|
service = XMLProperty("./@service", is_int=True)
|
|
path = XMLProperty("./@path")
|
|
channel = XMLProperty("./@channel")
|
|
master = XMLProperty("./@master")
|
|
slave = XMLProperty("./@slave")
|
|
mode = XMLProperty("./@mode")
|
|
|
|
# It's weird to track these properties here, since the XML is set on
|
|
# the parent, but this is how libvirt does it internally, which means
|
|
# everything that shares a charsource has these values too.
|
|
protocol = XMLProperty("./../protocol/@type")
|
|
log_file = XMLProperty("./../log/@file")
|
|
log_append = XMLProperty("./../log/@append", is_onoff=True)
|
|
|
|
|
|
# Convenience source helpers for setting connect/bind host and service
|
|
connect_host = XMLProperty("./../source[@mode='connect']/@host")
|
|
connect_service = XMLProperty(
|
|
"./../source[@mode='connect']/@service", is_int=True)
|
|
bind_host = XMLProperty("./../source[@mode='bind']/@host")
|
|
bind_service = XMLProperty("./../source[@mode='bind']/@service", is_int=True)
|
|
|
|
|
|
class _DeviceChar(Device):
|
|
"""
|
|
Base class for all character devices. Shouldn't be instantiated
|
|
directly.
|
|
"""
|
|
|
|
TYPE_PTY = "pty"
|
|
TYPE_DEV = "dev"
|
|
TYPE_STDIO = "stdio"
|
|
TYPE_PIPE = "pipe"
|
|
TYPE_FILE = "file"
|
|
TYPE_VC = "vc"
|
|
TYPE_NULL = "null"
|
|
TYPE_TCP = "tcp"
|
|
TYPE_UDP = "udp"
|
|
TYPE_UNIX = "unix"
|
|
TYPE_SPICEVMC = "spicevmc"
|
|
TYPE_SPICEPORT = "spiceport"
|
|
TYPE_NMDM = "nmdm"
|
|
|
|
CHANNEL_NAME_SPICE = "com.redhat.spice.0"
|
|
CHANNEL_NAME_QEMUGA = "org.qemu.guest_agent.0"
|
|
CHANNEL_NAME_LIBGUESTFS = "org.libguestfs.channel.0"
|
|
CHANNEL_NAME_SPICE_WEBDAV = "org.spice-space.webdav.0"
|
|
CHANNEL_NAMES = [CHANNEL_NAME_SPICE,
|
|
CHANNEL_NAME_QEMUGA,
|
|
CHANNEL_NAME_LIBGUESTFS,
|
|
CHANNEL_NAME_SPICE_WEBDAV]
|
|
|
|
def set_friendly_target(self, val):
|
|
_set_host_helper(self, "target_address", "target_port", val)
|
|
|
|
_XML_PROP_ORDER = ["type", "source",
|
|
"target_type", "target_name", "target_state"]
|
|
|
|
type = XMLProperty("./@type")
|
|
source = XMLChildProperty(CharSource, is_single=True)
|
|
|
|
target_address = XMLProperty("./target/@address")
|
|
target_port = XMLProperty("./target/@port", is_int=True)
|
|
target_type = XMLProperty("./target/@type")
|
|
target_name = XMLProperty("./target/@name")
|
|
target_state = XMLProperty("./target/@state")
|
|
target_model_name = XMLProperty("./target/model/@name")
|
|
|
|
|
|
##################
|
|
# Default config #
|
|
##################
|
|
|
|
def set_defaults(self, _guest):
|
|
if (not self.source.mode and
|
|
self.type in [self.TYPE_UNIX, self.TYPE_TCP]):
|
|
self.source.mode = "bind"
|
|
if not self.target_type and self.DEVICE_TYPE == "channel":
|
|
self.target_type = "virtio"
|
|
if not self.target_name and self.type == self.TYPE_SPICEVMC:
|
|
self.target_name = self.CHANNEL_NAME_SPICE
|
|
|
|
|
|
|
|
class DeviceConsole(_DeviceChar):
|
|
@staticmethod
|
|
def get_console_duplicate(guest, serial):
|
|
"""
|
|
Determine if the passed serial device has a duplicate
|
|
<console> device in the passed Guest
|
|
"""
|
|
if serial.DEVICE_TYPE != "serial":
|
|
return
|
|
|
|
consoles = guest.devices.console
|
|
if not consoles:
|
|
return # pragma: no cover
|
|
|
|
console = consoles[0]
|
|
if (console.type == serial.type and
|
|
(console.target_type is None or console.target_type == "serial")):
|
|
return console
|
|
|
|
XML_NAME = "console"
|
|
|
|
|
|
class DeviceSerial(_DeviceChar):
|
|
XML_NAME = "serial"
|
|
|
|
|
|
class DeviceParallel(_DeviceChar):
|
|
XML_NAME = "parallel"
|
|
|
|
|
|
class DeviceChannel(_DeviceChar):
|
|
XML_NAME = "channel"
|