1
0
mirror of https://github.com/dkmstr/openuds.git synced 2025-03-20 06:50:23 +03:00

Advancing on x2go implementation

This commit is contained in:
Adolfo Gómez García 2016-10-24 16:59:29 +02:00
parent 26c0532fd5
commit a07f1d5b24
6 changed files with 203 additions and 19 deletions

View File

@ -38,6 +38,7 @@ from uds.core.ui.UserInterface import gui
from uds.core.transports.BaseTransport import Transport
from uds.core.transports import protocols
from uds.core.util import OsDetector
from uds.core.util import connection
# This transport is specific for oVirt, so we need to point to it
@ -46,7 +47,7 @@ import six
import os
import logging
__updated__ = '2016-10-23'
__updated__ = '2016-10-24'
logger = logging.getLogger(__name__)
@ -89,10 +90,58 @@ class BaseX2GOTransport(Transport):
{'id': 'gnome-session-cinnamon2d', 'text': 'Cinnamon 2.2 (see docs)'},
], tab=gui.PARAMETERS_TAB)
keyboardLayout = gui.TextField(label=_('Keyboard'), order=12, tooltip=_('Keyboard layout (es, us, fr, ...). Empty value means autodetect.'),
default='',
sound = gui.CheckBoxField(
order=12,
label=_('Enable sound'),
tooltip=_('If checked, sound will be available'),
defvalue=gui.TRUE,
tab=gui.PARAMETERS_TAB
)
exports = gui.CheckBoxField(
order=13,
label=_('Redirect root folder'),
tooltip=_('If checked, user home folder will be redirected'),
defvalue=gui.FALSE,
tab=gui.PARAMETERS_TAB
)
soundType = gui.ChoiceField(label=_('Desktop'), order=30, tooltip=_('Desktop session'),
defvalue='pulse',
values=[
{'id': 'pulse', 'text': 'Pulse'},
{'id': 'esd', 'text': 'ESD'},
], tab=gui.ADVANCED_TAB
)
keyboardLayout = gui.TextField(label=_('Keyboard'), order=31, tooltip=_('Keyboard layout (es, us, fr, ...). Empty value means autodetect.'),
defvalue='',
tab=gui.ADVANCED_TAB
)
# 'nopack', '8', '64', '256', '512', '4k', '32k', '64k', '256k', '2m', '16m'
# '256-rdp', '256-rdp-compressed', '32k-rdp', '32k-rdp-compressed', '64k-rdp'
# '64k-rdp-compressed', '16m-rdp', '16m-rdp-compressed'
# 'rfb-hextile', 'rfb-tight', 'rfb-tight-compressed'
# '8-tight', '64-tight', '256-tight', '512-tight', '4k-tight', '32k-tight'
# '64k-tight', '256k-tight', '2m-tight', '16m-tight'
# '8-jpeg-%', '64-jpeg', '256-jpeg', '512-jpeg', '4k-jpeg', '32k-jpeg'
# '64k-jpeg', '256k-jpeg', '2m-jpeg', '16m-jpeg-%'
# '8-png-jpeg-%', '64-png-jpeg', '256-png-jpeg', '512-png-jpeg', '4k-png-jpeg'
# '32k-png-jpeg', '64k-png-jpeg', '256k-png-jpeg', '2m-png-jpeg', '16m-png-jpeg-%'
# '8-png-%', '64-png', '256-png', '512-png', '4k-png'
# '32k-png', '64k-png', '256k-png', '2m-png', '16m-png-%'
# '16m-rgb-%', '16m-rle-%'
pack = gui.TextField(label=_('Pack'), order=32, tooltip=_('Pack format. Change with care!'),
defvalue='4k-jpeg',
tab=gui.ADVANCED_TAB
)
quality = gui.NumericField(label=_('Quality'), order=33, tooltip=_('Quality value used on some pack formats.'),
length=1, defvalue='8', minValue=1, maxValue=9, required=True,
tab=gui.ADVANCED_TAB)
def isAvailableFor(self, userService, ip):
'''
@ -100,7 +149,15 @@ class BaseX2GOTransport(Transport):
Override this in yours transports
'''
logger.debug('Checking availability for {0}'.format(ip))
return True # Spice is available, no matter what IP machine has (even if it does not have one)
ready = self.cache.get(ip)
if ready is None:
# Check again for ready
if connection.testServer(ip, '22') is True:
self.cache.put(ip, 'Y', READY_CACHE_TIMEOUT)
return True
else:
self.cache.put(ip, 'N', READY_CACHE_TIMEOUT)
return ready == 'Y'
def processedUser(self, userService, userName):
v = self.processUserPassword(userService, userName, '')
@ -117,7 +174,7 @@ class BaseX2GOTransport(Transport):
return {'protocol': self.protocol, 'username': username, 'password': ''}
def getConnectionInfo(self, service, user, password):
def getConnectionInfo(self, service, user, password): # Password is ignored in this transport, auth is done using SSH
return self.processUserPassword(service, user, password)
def genKeyPairForSsh(self):

View File

@ -32,13 +32,15 @@
'''
from django.utils.translation import ugettext_noop as _
from uds.core.managers.UserPrefsManager import CommonPrefs
from uds.core.util import OsDetector
from uds.core.util import tools
from .BaseX2GOTransport import BaseX2GOTransport
from . import x2gofile
import logging
__updated__ = '2016-10-23'
__updated__ = '2016-10-24'
logger = logging.getLogger(__name__)
@ -53,9 +55,60 @@ class X2GOTransport(BaseX2GOTransport):
typeDescription = _('X2Go Transport for direct connection (EXPERIMENTAL)')
fixedName = BaseX2GOTransport.fixedName
fullScreen = BaseX2GOTransport.fullScreen
# fullScreen = BaseX2GOTransport.fullScreen
desktopType = BaseX2GOTransport.desktopType
sound = BaseX2GOTransport.sound
exports = BaseX2GOTransport.exports
soundType = BaseX2GOTransport.soundType
keyboardLayout = BaseX2GOTransport.keyboardLayout
pack = BaseX2GOTransport.pack
quality = BaseX2GOTransport.quality
def getUDSTransportScript(self, userService, transport, ip, os, user, password, request):
self.getAndPushKey('user', userService)
return ''
prefs = user.prefs('nx')
priv, pub = self.getAndPushKey('user', userService)
prefs = user.prefs('rdp')
ci = self.getConnectionInfo(userService, user, password)
username = ci['username']
width, height = CommonPrefs.getWidthHeight(prefs)
xf = x2gofile.getTemplate(
pack=self.pack.value,
quality=self.quality.value,
sound=self.sound.isTrue(),
soundSystem=self.sound.value,
windowManager=self.desktopType.value,
exports=self.exports.isTrue())
# data
data = {
'os': os['OS'],
'ip': ip,
'port': 22,
'username': username,
'key': priv,
'width': width,
'height': height,
'printers': True,
'drives': self.exports.isTrue(),
'fullScreen': width == -1 or height == -1,
'this_server': request.build_absolute_uri('/'),
'xf': xf
}
m = tools.DictAsObj(data)
os = {
OsDetector.Windows: 'windows',
OsDetector.Linux: 'linux',
# OsDetector.Macintosh: 'macosx'
}.get(m.os)
if os is None:
return super(X2GOTransport, self).getUDSTransportScript(self, userService, transport, ip, os, user, password, request)
return self.getScript('scripts/{}/direct.py'.format(os)).format(m=m)

View File

@ -35,3 +35,7 @@ from django.utils.translation import ugettext_noop as _
from uds.core.managers.UserPrefsManager import UserPrefsManager, CommonPrefs
from .X2GOTransport import X2GOTransport
from .TX2GOTransport import TX2GOTransport
# We will use same prefs as for NX, X2GO is based on it
UserPrefsManager.manager().registerPrefs('nx', _('NX Protocol'), [CommonPrefs.screenSizePref])

View File

@ -0,0 +1,27 @@
# This is a template
# Saved as .py for easier editing
from __future__ import unicode_literals
# pylint: disable=import-error, no-name-in-module
from PyQt4 import QtCore, QtGui
import win32crypt # @UnresolvedImport
import os
import subprocess
from uds import tools # @UnresolvedImport
import six
# The password must be encoded, to be included in a .rdp file, as 'UTF-16LE' before protecting (CtrpyProtectData) it in order to work with mstsc
keyFile = tools.saveTempFile('''{m.key}''')
theFile = '''{m.xf}'''.format(exports='c:\\', keyFile=keyFile.replace('\\', '/'), ip='{m.ip}')
filename = tools.saveTempFile(theFile)
x2goPath = os.environ['PROGRAMFILES(X86)'] + '\\x2goclient'
executable = tools.findApp('x2goclient.exe', [x2goPath])
# executable = tools.findApp('mstsc.exe')
# subprocess.Popen([executable, filename])
# tools.addFileToUnlink(filename)
QtGui.QMessageBox.critical(parent, 'Notice', executable + ' -- ' + keyFile + ', ' + filename, QtGui.QMessageBox.Ok) # @UndefinedVariable

View File

@ -0,0 +1,38 @@
# This is a template
# Saved as .py for easier editing
from __future__ import unicode_literals
# pylint: disable=import-error, no-name-in-module, too-many-format-args, undefined-variable
from PyQt4 import QtCore, QtGui
import win32crypt # @UnresolvedImport
import os
import subprocess
from uds.forward import forward # @UnresolvedImport
from uds import tools # @UnresolvedImport
import six
forwardThread, port = forward('{m.tunHost}', '{m.tunPort}', '{m.tunUser}', '{m.tunPass}', '{m.ip}', 3389)
if forwardThread.status == 2:
raise Exception('Unable to open tunnel')
tools.addTaskToWait(forwardThread)
# The password must be encoded, to be included in a .rdp file, as 'UTF-16LE' before protecting (CtrpyProtectData) it in order to work with mstsc
theFile = '''{m.r.as_file}'''.format(
password=win32crypt.CryptProtectData(six.binary_type('{m.password}'.encode('UTF-16LE')), None, None, None, None, 0x01).encode('hex'),
address='127.0.0.1:{{}}'.format(port)
)
filename = tools.saveTempFile(theFile)
executable = tools.findApp('mstsc.exe')
if executable is None:
raise Exception('Unable to find mstsc.exe')
subprocess.Popen([executable, filename])
tools.addFileToUnlink(filename)
# QtGui.QMessageBox.critical(parent, 'Notice', filename + ", " + executable, QtGui.QMessageBox.Ok)

View File

@ -34,12 +34,12 @@
template = '''[General]
UDS=@ByteArray()
[20161019100758147]
[20160101100758147]
speed=4
pack=16m-jpeg
quality=8
pack={pack}
quality={quality}
fstunnel=true
export="/home/user:1;"
{export}
iconvto=UTF-8
iconvfrom=ISO8859-1
useiconv=false
@ -57,18 +57,18 @@ xinerama=false
clipboard=both
usekbd=true
type=auto
sound=true
soundsystem=pulse
sound={sound}
soundsystem={soundSystem}
startsoundsystem=true
soundtunnel=true
defsndport=true
sndport=4713
print=true
name=UDS/uds-test
name=UDS/connect
icon=:/img/icons/128x128/x2gosession.png
host=172.27.0.208
host={{ip}}
user=user
key=/home/user/remotekey.txt
key={{keyFile}}
rdpport=3389
sshport=22
autologin=false
@ -78,7 +78,7 @@ directrdp=false
rootless=false
published=false
applications=WWWBROWSER, MAILCLIENT, OFFICE, TERMINAL
command=XFCE
command={windowManager}
rdpoptions=
rdpserver=
xdmcpserver=localhost
@ -93,3 +93,8 @@ sshproxysameuser=false
sshproxyautologin=false
sshproxykrblogin=false
'''
def getTemplate(pack, quality, sound, soundSystem, windowManager, exports):
trueFalse = lambda(x): 'true' if x else 'false'
export = 'export="{{export}}"' if exports else ''
return template.format(pack=pack, quality=quality, sound=trueFalse(sound), soundSystem=soundSystem, windowManager=windowManager, export=export)