2013-03-18 01:06:52 +04:00
#
2013-10-28 00:59:46 +04:00
# Copyright 2006-2009, 2013 Red Hat, Inc.
2013-03-18 01:06:52 +04:00
# Jeremy Katz <katzj@redhat.com>
#
2018-04-04 16:35:41 +03:00
# This work is licensed under the GNU GPLv2 or later.
2018-03-20 22:00:02 +03:00
# See the COPYING file in the top-level directory.
2013-03-18 01:06:52 +04:00
import os
2018-03-20 19:18:35 +03:00
from . device import Device
2018-03-20 19:27:37 +03:00
from . . xmlbuilder import XMLBuilder , XMLChildProperty , XMLProperty
2013-03-18 01:06:52 +04:00
2013-04-13 22:34:52 +04:00
2013-03-18 01:06:52 +04:00
def _get_mode_prop ( channel_type ) :
xpath = " ./channel[@name= ' %s ' ]/@mode " % channel_type
2013-09-19 21:27:30 +04:00
return XMLProperty ( xpath )
2013-03-18 01:06:52 +04:00
2013-04-13 22:34:52 +04:00
2013-07-16 02:53:53 +04:00
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
2014-01-29 17:18:01 +04:00
class _GraphicsListen ( XMLBuilder ) :
2018-03-21 17:53:34 +03:00
XML_NAME = " listen "
2014-01-29 17:18:01 +04:00
type = XMLProperty ( " ./@type " )
address = XMLProperty ( " ./@address " )
network = XMLProperty ( " ./@network " )
2017-09-06 11:26:33 +03:00
socket = XMLProperty ( " ./@socket " )
2014-01-29 17:18:01 +04:00
2018-03-20 19:18:35 +03:00
class DeviceGraphics ( Device ) :
2018-03-21 17:53:34 +03:00
XML_NAME = " graphics "
2013-03-18 01:06:52 +04:00
TYPE_SDL = " sdl "
TYPE_VNC = " vnc "
TYPE_RDP = " rdp "
TYPE_SPICE = " spice "
2013-07-16 02:53:53 +04:00
TYPES = [ TYPE_VNC , TYPE_SDL , TYPE_RDP , TYPE_SPICE ]
2013-03-18 01:06:52 +04:00
CHANNEL_TYPE_MAIN = " main "
CHANNEL_TYPE_DISPLAY = " display "
CHANNEL_TYPE_INPUTS = " inputs "
CHANNEL_TYPE_CURSOR = " cursor "
CHANNEL_TYPE_PLAYBACK = " playback "
CHANNEL_TYPE_RECORD = " record "
2013-07-16 02:53:53 +04:00
CHANNEL_TYPES = [ CHANNEL_TYPE_MAIN , CHANNEL_TYPE_DISPLAY ,
2013-03-18 01:06:52 +04:00
CHANNEL_TYPE_INPUTS , CHANNEL_TYPE_CURSOR ,
CHANNEL_TYPE_PLAYBACK , CHANNEL_TYPE_RECORD ]
CHANNEL_MODE_SECURE = " secure "
CHANNEL_MODE_INSECURE = " insecure "
CHANNEL_MODE_ANY = " any "
2013-07-16 02:53:53 +04:00
CHANNEL_MODES = [ CHANNEL_MODE_SECURE , CHANNEL_MODE_INSECURE ,
2013-03-18 01:06:52 +04:00
CHANNEL_MODE_ANY ]
KEYMAP_LOCAL = " local "
KEYMAP_DEFAULT = " default "
_special_keymaps = [ KEYMAP_LOCAL , KEYMAP_DEFAULT ]
@staticmethod
def valid_keymaps ( ) :
"""
Return a list of valid keymap values .
"""
2018-03-20 19:27:37 +03:00
from . . import hostkeymap
2013-03-18 01:06:52 +04:00
2017-10-11 14:35:46 +03:00
orig_list = list ( hostkeymap . keytable . values ( ) )
2013-03-18 01:06:52 +04:00
sort_list = [ ]
orig_list . sort ( )
for k in orig_list :
if k not in sort_list :
sort_list . append ( k )
return sort_list
@staticmethod
def pretty_type_simple ( gtype ) :
2018-03-20 19:18:35 +03:00
if ( gtype in [ DeviceGraphics . TYPE_VNC ,
DeviceGraphics . TYPE_SDL ,
DeviceGraphics . TYPE_RDP ] ) :
2013-03-18 01:06:52 +04:00
return str ( gtype ) . upper ( )
return str ( gtype ) . capitalize ( )
2013-09-11 19:47:09 +04:00
def __init__ ( self , * args , * * kwargs ) :
2018-03-20 19:18:35 +03:00
Device . __init__ ( self , * args , * * kwargs )
2013-03-18 01:06:52 +04:00
2013-04-14 00:14:14 +04:00
self . _local_keymap = - 1
2013-03-18 01:06:52 +04:00
2013-07-16 02:53:53 +04:00
2016-03-04 14:31:51 +03:00
_XML_PROP_ORDER = [ " type " , " gl " , " port " , " tlsPort " , " autoport " ,
2013-07-16 02:53:53 +04:00
" keymap " , " listen " ,
" passwd " , " display " , " xauth " ]
2013-04-14 00:14:14 +04:00
def _default_keymap ( self , force_local = False ) :
2013-07-16 02:53:53 +04:00
if self . type != " vnc " and self . type != " spice " :
return None
2013-07-06 04:14:57 +04:00
if ( not force_local and
2013-10-06 18:08:04 +04:00
self . conn . check_support (
2013-07-06 19:20:28 +04:00
self . conn . SUPPORT_CONN_KEYMAP_AUTODETECT ) ) :
2013-03-18 01:06:52 +04:00
return None
2013-04-14 00:14:14 +04:00
if self . _local_keymap == - 1 :
2018-03-20 19:27:37 +03:00
from . . import hostkeymap
2013-04-14 00:31:13 +04:00
self . _local_keymap = hostkeymap . default_keymap ( )
2013-04-14 00:14:14 +04:00
return self . _local_keymap
2013-03-18 01:06:52 +04:00
2013-07-16 02:53:53 +04:00
def _set_keymap_converter ( self , val ) :
if val == self . KEYMAP_DEFAULT :
2013-03-18 01:06:52 +04:00
return self . _default_keymap ( )
2013-07-16 02:53:53 +04:00
if val == self . KEYMAP_LOCAL :
2013-04-14 00:14:14 +04:00
return self . _default_keymap ( force_local = True )
2013-07-16 02:53:53 +04:00
return val
2013-09-19 21:27:30 +04:00
keymap = XMLProperty ( " ./@keymap " ,
2013-07-16 02:53:53 +04:00
default_cb = _default_keymap ,
set_converter = _set_keymap_converter )
2014-03-23 02:25:53 +04:00
def _set_port_converter ( self , val ) :
val = _validate_port ( " Port " , val )
self . autoport = self . _get_default_autoport ( )
return val
def _set_tlsport_converter ( self , val ) :
val = _validate_port ( " TLS Port " , val )
self . autoport = self . _get_default_autoport ( )
return val
2017-09-06 11:14:35 +03:00
def _listen_need_port ( self ) :
listen = self . get_first_listen_type ( )
return not listen or listen in [ " address " , " network " ]
2013-07-16 02:53:53 +04:00
def _get_default_port ( self ) :
2017-09-06 11:14:35 +03:00
if ( self . type == " vnc " or self . type == " spice " ) and self . _listen_need_port ( ) :
2013-07-16 02:53:53 +04:00
return - 1
return None
def _get_default_tlsport ( self ) :
2017-09-06 11:14:35 +03:00
if self . type == " spice " and self . _listen_need_port ( ) :
2013-07-16 02:53:53 +04:00
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'
2013-09-02 19:54:02 +04:00
if self . type != " spice " :
return None
2014-01-29 03:44:40 +04:00
if ( self . port == - 1 and self . tlsPort == - 1 ) :
2013-09-02 19:54:02 +04:00
return True
2013-07-16 02:53:53 +04:00
return None
2013-09-19 21:27:30 +04:00
port = XMLProperty ( " ./@port " , is_int = True ,
2014-03-23 02:25:53 +04:00
set_converter = _set_port_converter ,
2013-07-16 02:53:53 +04:00
default_cb = _get_default_port )
2013-09-19 21:27:30 +04:00
tlsPort = XMLProperty ( " ./@tlsPort " , is_int = True ,
2014-03-23 02:25:53 +04:00
set_converter = _set_tlsport_converter ,
2013-07-16 02:53:53 +04:00
default_cb = _get_default_tlsport )
2013-09-19 21:27:30 +04:00
autoport = XMLProperty ( " ./@autoport " , is_yesno = True ,
2013-07-16 21:04:24 +04:00
default_cb = _get_default_autoport )
2013-03-18 01:06:52 +04:00
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 )
2013-07-16 02:53:53 +04:00
def _get_default_display ( self ) :
if self . type != " sdl " :
return None
if " DISPLAY " not in os . environ :
raise RuntimeError ( " No DISPLAY environment variable set. " )
return os . environ [ " DISPLAY " ]
def _get_default_xauth ( self ) :
if self . type != " sdl " :
return None
return os . path . expanduser ( " ~/.Xauthority " )
2013-09-19 21:27:30 +04:00
xauth = XMLProperty ( " ./@xauth " ,
2013-07-16 02:53:53 +04:00
default_cb = _get_default_xauth )
2013-09-19 21:27:30 +04:00
display = XMLProperty ( " ./@display " ,
2013-07-16 02:53:53 +04:00
default_cb = _get_default_display )
2014-01-29 17:18:01 +04:00
def _set_listen ( self , val ) :
# Update the corresponding <listen> block
find_listen = [ l for l in self . listens if
( l . type == " address " and l . address == self . listen ) ]
if find_listen :
if val is None :
2016-06-11 23:44:54 +03:00
self . remove_child ( find_listen [ 0 ] )
2014-01-29 17:18:01 +04:00
else :
find_listen [ 0 ] . address = val
return val
listen = XMLProperty ( " ./@listen " , set_converter = _set_listen )
2013-10-03 02:06:52 +04:00
type = XMLProperty ( " ./@type " ,
default_cb = lambda s : " vnc " ,
default_name = " default " )
2013-09-19 21:27:30 +04:00
passwd = XMLProperty ( " ./@passwd " )
passwdValidTo = XMLProperty ( " ./@passwdValidTo " )
socket = XMLProperty ( " ./@socket " )
2014-01-29 18:52:49 +04:00
connected = XMLProperty ( " ./@connected " )
2014-02-28 02:43:59 +04:00
defaultMode = XMLProperty ( " ./@defaultMode " )
2013-07-24 16:46:55 +04:00
2014-01-29 17:18:01 +04:00
listens = XMLChildProperty ( _GraphicsListen )
2016-06-11 23:44:54 +03:00
def remove_all_listens ( self ) :
for listen in self . listens :
self . remove_child ( listen )
2017-02-21 16:00:59 +03:00
def get_first_listen_type ( self ) :
if len ( self . listens ) > 0 :
return self . listens [ 0 ] . type
return None
2016-06-11 23:44:54 +03:00
def set_listen_none ( self ) :
self . remove_all_listens ( )
2017-02-21 16:00:58 +03:00
self . listen = None
2016-06-11 23:44:54 +03:00
self . port = None
self . tlsPort = None
2017-02-21 16:00:57 +03:00
self . autoport = None
2016-06-11 23:44:54 +03:00
self . socket = None
if self . conn . check_support (
2017-09-20 10:36:27 +03:00
self . conn . SUPPORT_CONN_GRAPHICS_LISTEN_NONE ) :
2018-02-08 01:27:56 +03:00
obj = self . listens . add_new ( )
2016-06-11 23:44:54 +03:00
obj . type = " none "
2014-01-29 17:18:01 +04:00
2015-04-11 23:56:27 +03:00
# 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 )
2016-03-04 14:31:51 +03:00
gl = XMLProperty ( " ./gl/@enable " , is_yesno = True )
2017-02-21 16:01:00 +03:00
rendernode = XMLProperty ( " ./gl/@rendernode " )