mirror of
https://github.com/virt-manager/virt-manager.git
synced 2025-01-06 13:17:58 +03:00
cdbc3f56e6
Removing this was discussed here: https://www.redhat.com/archives/virt-tools-list/2019-June/msg00117.html This is the old default, where we would try to determine a static keymap value from host graphics config files, and set that in the XML. We haven't defaulted to this for a long time, setting a static keymap is suboptimal generally, and the file parsing code is not up to date for modern host config. So let's remove it The hostkeymap module is now unused, so remove it and all the custom testing for it. Signed-off-by: Cole Robinson <crobinso@redhat.com>
233 lines
7.4 KiB
Python
233 lines
7.4 KiB
Python
#
|
|
# Copyright 2006-2009, 2013 Red Hat, Inc.
|
|
#
|
|
# This work is licensed under the GNU GPLv2 or later.
|
|
# See the COPYING file in the top-level directory.
|
|
|
|
import os
|
|
|
|
from .device import Device
|
|
from ..logger import log
|
|
from ..xmlbuilder import XMLBuilder, XMLChildProperty, XMLProperty
|
|
|
|
|
|
def _get_mode_prop(channel_type):
|
|
xpath = "./channel[@name='%s']/@mode" % channel_type
|
|
return XMLProperty(xpath)
|
|
|
|
|
|
def _validate_port(name, val):
|
|
if val is None:
|
|
return val
|
|
val = int(val)
|
|
|
|
if val < 5900 and val != -1:
|
|
raise ValueError(_("%s must be above 5900, or "
|
|
"-1 for auto allocation") % name)
|
|
return val
|
|
|
|
|
|
class _GraphicsListen(XMLBuilder):
|
|
XML_NAME = "listen"
|
|
|
|
type = XMLProperty("./@type")
|
|
address = XMLProperty("./@address")
|
|
network = XMLProperty("./@network")
|
|
socket = XMLProperty("./@socket")
|
|
|
|
|
|
class DeviceGraphics(Device):
|
|
XML_NAME = "graphics"
|
|
|
|
TYPE_SDL = "sdl"
|
|
TYPE_VNC = "vnc"
|
|
TYPE_RDP = "rdp"
|
|
TYPE_SPICE = "spice"
|
|
|
|
CHANNEL_TYPE_MAIN = "main"
|
|
CHANNEL_TYPE_DISPLAY = "display"
|
|
CHANNEL_TYPE_INPUTS = "inputs"
|
|
CHANNEL_TYPE_CURSOR = "cursor"
|
|
CHANNEL_TYPE_PLAYBACK = "playback"
|
|
CHANNEL_TYPE_RECORD = "record"
|
|
|
|
_XML_PROP_ORDER = ["type", "gl", "_port", "_tlsPort", "autoport",
|
|
"keymap", "_listen",
|
|
"passwd", "display", "xauth"]
|
|
|
|
keymap = XMLProperty("./@keymap")
|
|
|
|
def _set_port(self, val):
|
|
val = _validate_port("Port", val)
|
|
self.autoport = self._get_default_autoport()
|
|
self._port = val
|
|
def _get_port(self):
|
|
return self._port
|
|
_port = XMLProperty("./@port", is_int=True)
|
|
port = property(_get_port, _set_port)
|
|
|
|
def _set_tlsport(self, val):
|
|
val = _validate_port("TLS Port", val)
|
|
self.autoport = self._get_default_autoport()
|
|
self._tlsPort = val
|
|
def _get_tlsport(self):
|
|
return self._tlsPort
|
|
_tlsPort = XMLProperty("./@tlsPort", is_int=True)
|
|
tlsPort = property(_get_tlsport, _set_tlsport)
|
|
|
|
autoport = XMLProperty("./@autoport", is_yesno=True)
|
|
|
|
channel_main_mode = _get_mode_prop(CHANNEL_TYPE_MAIN)
|
|
channel_display_mode = _get_mode_prop(CHANNEL_TYPE_DISPLAY)
|
|
channel_inputs_mode = _get_mode_prop(CHANNEL_TYPE_INPUTS)
|
|
channel_cursor_mode = _get_mode_prop(CHANNEL_TYPE_CURSOR)
|
|
channel_playback_mode = _get_mode_prop(CHANNEL_TYPE_PLAYBACK)
|
|
channel_record_mode = _get_mode_prop(CHANNEL_TYPE_RECORD)
|
|
|
|
xauth = XMLProperty("./@xauth")
|
|
display = XMLProperty("./@display")
|
|
|
|
|
|
def _set_listen(self, val):
|
|
if val == "none":
|
|
self._set_listen_none()
|
|
elif val == "socket":
|
|
self._remove_all_listens()
|
|
obj = self.listens.add_new()
|
|
obj.type = "socket"
|
|
else:
|
|
self._remove_all_listens()
|
|
self._listen = val
|
|
def _get_listen(self):
|
|
return self._listen
|
|
_listen = XMLProperty("./@listen")
|
|
listen = property(_get_listen, _set_listen)
|
|
|
|
type = XMLProperty("./@type")
|
|
passwd = XMLProperty("./@passwd")
|
|
passwdValidTo = XMLProperty("./@passwdValidTo")
|
|
socket = XMLProperty("./@socket")
|
|
connected = XMLProperty("./@connected")
|
|
defaultMode = XMLProperty("./@defaultMode")
|
|
|
|
listens = XMLChildProperty(_GraphicsListen)
|
|
def _remove_all_listens(self):
|
|
for listen in self.listens:
|
|
self.remove_child(listen)
|
|
|
|
def get_first_listen_type(self):
|
|
if len(self.listens) > 0:
|
|
return self.listens[0].type
|
|
return None
|
|
|
|
def _set_listen_none(self):
|
|
self._remove_all_listens()
|
|
self.listen = None
|
|
self.port = None
|
|
self.tlsPort = None
|
|
self.autoport = None
|
|
self.socket = None
|
|
|
|
if self.conn.support.conn_graphics_listen_none():
|
|
obj = self.listens.add_new()
|
|
obj.type = "none"
|
|
|
|
# Spice bits
|
|
image_compression = XMLProperty("./image/@compression")
|
|
streaming_mode = XMLProperty("./streaming/@mode")
|
|
clipboard_copypaste = XMLProperty("./clipboard/@copypaste", is_yesno=True)
|
|
mouse_mode = XMLProperty("./mouse/@mode")
|
|
filetransfer_enable = XMLProperty("./filetransfer/@enable", is_yesno=True)
|
|
gl = XMLProperty("./gl/@enable", is_yesno=True)
|
|
rendernode = XMLProperty("./gl/@rendernode")
|
|
zlib_compression = XMLProperty("./zlib/@compression")
|
|
|
|
|
|
##################
|
|
# Default config #
|
|
##################
|
|
|
|
def _spice_supported(self):
|
|
if not self.conn.is_qemu() and not self.conn.is_test():
|
|
return False
|
|
# Spice has issues on some host arches, like ppc, so whitelist it
|
|
if self.conn.caps.host.cpu.arch not in ["i686", "x86_64"]:
|
|
return False
|
|
return True
|
|
|
|
def _listen_need_port(self):
|
|
listen = self.get_first_listen_type()
|
|
return not listen or listen in ["address", "network"]
|
|
|
|
def _get_default_port(self):
|
|
if self.type in ["vnc", "spice"] and self._listen_need_port():
|
|
return -1
|
|
return None
|
|
|
|
def _get_default_tlsport(self):
|
|
if self.type == "spice" and self._listen_need_port():
|
|
return -1
|
|
return None
|
|
|
|
def _get_default_autoport(self):
|
|
# By default, don't do this for VNC to maintain back compat with
|
|
# old libvirt that didn't support 'autoport'
|
|
if self.type != "spice":
|
|
return None
|
|
if (self.port == -1 and self.tlsPort == -1):
|
|
return True
|
|
return None
|
|
|
|
def _default_type(self, guest):
|
|
gtype = guest.default_graphics_type
|
|
log.debug("Using default_graphics=%s", gtype)
|
|
if gtype == "spice" and not self._spice_supported():
|
|
log.debug("spice requested but HV doesn't support it. "
|
|
"Using vnc.")
|
|
gtype = "vnc"
|
|
return gtype
|
|
|
|
def _default_image_compression(self, _guest):
|
|
if self.type != "spice":
|
|
return None
|
|
if not self.conn.is_remote():
|
|
log.debug("Local connection, disabling spice image "
|
|
"compression.")
|
|
return "off"
|
|
return None
|
|
|
|
def _default_spice_gl(self, _guest):
|
|
if not self.conn.support.conn_spice_gl(): # pragma: no cover
|
|
raise ValueError(_("Host does not support spice GL"))
|
|
|
|
# If spice GL but rendernode wasn't specified, hardcode
|
|
# the first one
|
|
if not self.rendernode and self.conn.support.conn_spice_rendernode():
|
|
for nodedev in self.conn.fetch_all_nodedevs():
|
|
if not nodedev.is_drm_render():
|
|
continue
|
|
self.rendernode = nodedev.get_devnode().path
|
|
break
|
|
|
|
def set_defaults(self, guest):
|
|
if not self.type:
|
|
self.type = self._default_type(guest)
|
|
|
|
if self.type == "sdl":
|
|
if not self.xauth:
|
|
self.xauth = os.path.expanduser("~/.Xauthority")
|
|
if not self.display:
|
|
self.display = os.environ.get("DISPLAY")
|
|
|
|
if self.port is None:
|
|
self.port = self._get_default_port()
|
|
if self.tlsPort is None:
|
|
self.tlsPort = self._get_default_tlsport()
|
|
if self.autoport is None:
|
|
self.autoport = self._get_default_autoport()
|
|
|
|
if not self.image_compression:
|
|
self.image_compression = self._default_image_compression(guest)
|
|
if self.type == "spice" and self.gl:
|
|
self._default_spice_gl(guest)
|