1
0
mirror of https://github.com/dkmstr/openuds.git synced 2024-12-22 13:34:04 +03:00

* Transports associadted to Providers working correctly

* Spice transport added (EXPERIMENTAL version)
This commit is contained in:
Adolfo Gómez García 2015-05-10 07:19:57 +02:00
parent e69914a9a5
commit 04ec90ad61
18 changed files with 410 additions and 534 deletions

View File

@ -51,6 +51,8 @@ import requests
import json
import logging
__updated__ = '2015-05-06'
logger = logging.getLogger(__name__)
USERSERVICE_TAG = 'cm-'

View File

@ -40,6 +40,8 @@ from uds.core.transports import protocols
import logging
__updated__ = '2015-05-06'
logger = logging.getLogger(__name__)

View File

@ -30,7 +30,6 @@
'''
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
'''
from uds.core.services import UserDeployment
from uds.core.util.State import State
from uds.core.util import log
@ -38,6 +37,9 @@ from uds.core.util import log
import cPickle
import logging
__updated__ = '2015-05-09'
logger = logging.getLogger(__name__)
opCreate, opStart, opStop, opSuspend, opRemove, opWait, opError, opFinish, opRetry, opChangeMac = range(10)
@ -181,6 +183,12 @@ class OVirtLinkedDeployment(UserDeployment):
self.cache().put('ready', '1')
return State.FINISHED
def getConsoleConnection(self):
return self.service().getConsoleConnection(self._vmid)
def desktopLogin(self, username, password, domain=''):
return self.service().desktopLogin(self._vmId, username, password, domain)
def notifyReadyFromOsManager(self, data):
# Here we will check for suspending the VM (when full ready)
logger.debug('Checking if cache 2 for {0}'.format(self._name))

View File

@ -30,7 +30,6 @@
'''
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
'''
from django.utils.translation import ugettext_noop as _, ugettext
from uds.core.services import Service
from .OVirtPublication import OVirtPublication
@ -41,6 +40,8 @@ from uds.core.ui import gui
import logging
__updated__ = '2015-05-09'
logger = logging.getLogger(__name__)
@ -104,29 +105,71 @@ class OVirtLinkedService(Service):
tooltip=_("Cluster to contain services"), required=True
)
datastore = gui.ChoiceField(label=_("Datastore Domain"), rdonly=False, order=3,
tooltip=_('Datastore domain where to publish and put incrementals'), required=True)
datastore = gui.ChoiceField(
label=_("Datastore Domain"),
rdonly=False,
order=3,
tooltip=_('Datastore domain where to publish and put incrementals'),
required=True
)
minSpaceGB = gui.NumericField(length=3, label=_('Reserved Space'), defvalue='32', order=4, tooltip=_('Minimal free space in GB'), required=True)
minSpaceGB = gui.NumericField(
length=3,
label=_('Reserved Space'),
defvalue='32',
order=4,
tooltip=_('Minimal free space in GB'),
required=True
)
memory = gui.NumericField(label=_("Memory (Mb)"), length=4, defvalue=512, rdonly=False, order=5,
tooltip=_('Memory assigned to machines'), required=True)
memory = gui.NumericField(
label=_("Memory (Mb)"),
length=4,
defvalue=512,
rdonly=False,
order=5,
tooltip=_('Memory assigned to machines'),
required=True
)
memoryGuaranteed = gui.NumericField(label=_("Memory Guaranteed (Mb)"), length=4, defvalue=256, rdonly=False, order=6,
tooltip=_('Physical memory guaranteed to machines'), required=True)
memoryGuaranteed = gui.NumericField(
label=_("Memory Guaranteed (Mb)"),
length=4,
defvalue=256,
rdonly=False,
order=6,
tooltip=_('Physical memory guaranteed to machines'),
required=True
)
baseName = gui.TextField(label=_('Machine Names'), rdonly=False, order=6, tooltip=('Base name for clones from this machine'), required=True)
baseName = gui.TextField(
label=_('Machine Names'),
rdonly=False,
order=6,
tooltip=('Base name for clones from this machine'),
required=True
)
lenName = gui.NumericField(length=1, label=_('Name Length'), defvalue=5, order=7,
tooltip=_('Size of numeric part for the names of these machines (between 3 and 6)'), required=True)
lenName = gui.NumericField(
length=1,
label=_('Name Length'),
defvalue=5,
order=7,
tooltip=_('Size of numeric part for the names of these machines (between 3 and 6)'),
required=True
)
display = gui.ChoiceField(label=_('Display'), rdonly=False, order=8,
tooltip=_('Display type (only for administration purposes)'),
values=[gui.choiceItem('spice', 'Spice'),
gui.choiceItem('vnc', 'Vnc')
],
defvalue='1' # Default value is the ID of the choicefield
)
display = gui.ChoiceField(
label=_('Display'),
rdonly=False,
order=8,
tooltip=_('Display type (only for administration purposes)'),
values=[
gui.choiceItem('spice', 'Spice'),
gui.choiceItem('vnc', 'Vnc')
],
defvalue='1' # Default value is the ID of the choicefield
)
ov = gui.HiddenField()
ev = gui.HiddenField() # We need to keep the env so we can instantiate the Provider
@ -347,3 +390,8 @@ class OVirtLinkedService(Service):
'''
return self.display.value
def getConsoleConnection(self, machineId):
return self.parent().getConsoleConnection(machineId)
def desktopLogin(self, machineId, username, password, domain):
return self.parent().desktopLogin(machineId, username, password, domain)

View File

@ -45,6 +45,8 @@ from client import oVirtClient
import logging
__updated__ = '2015-05-09'
logger = logging.getLogger(__name__)
CACHE_TIME_FOR_SERVER = 1800
@ -370,6 +372,14 @@ class Provider(ServiceProvider):
def getMacRange(self):
return self.macsRange.value
def getConsoleConnection(self, machineId):
return self.__getApi().getConsoleConnection(machineId)
def desktopLogin(self, machineId, username, password, domain):
'''
'''
return self.__getApi().desktopLogin(machineId, username, password, domain)
@staticmethod
def test(env, data):
'''

View File

@ -10,6 +10,8 @@ from ovirtsdk.api import API
import threading
import logging
__updated__ = '2015-05-09'
logger = logging.getLogger(__name__)
lock = threading.Lock()
@ -360,20 +362,30 @@ class Client(object):
if vm.get_status().get_state() != 'down':
raise Exception('Machine must be in down state to publish it')
print vm.disks.list()
# Create disks description to be created in specified storage domain, one for each disk
sd = params.StorageDomains(storage_domain=[params.StorageDomain(id=storageId)])
dsks = []
for dsk in vm.disks.list():
dsks.append(params.Disk(id=dsk.get_id(), storage_domains=sd))
dsks.append(params.Disk(id=dsk.get_id(), storage_domains=sd, name='test', alias='test'))
# dsks.append(dsk)
disks = params.Disks(disk=dsks)
# Create display description
display = params.Display(type_=displayType)
# display = params.Display(type_=displayType)
# TODO: Restore proper template creation mechanism
template = params.Template(
name=name,
# vm=params.VM(id=vm.get_id(), disks=disks),
vm=params.VM(id=vm.get_id()),
cluster=params.Cluster(id=cluster.get_id()),
description=comments
)
template = params.Template(name=name, vm=params.VM(id=vm.get_id(), disks=disks),
cluster=params.Cluster(id=cluster.get_id()), description=comments)
# display=display)
return api.templates.add(template).get_id()
@ -622,7 +634,7 @@ class Client(object):
finally:
lock.release()
def getConnetcionInfo(self, machineId):
def getConsoleConnection(self, machineId):
'''
Gets the connetion info for the specified machine
'''
@ -652,3 +664,6 @@ class Client(object):
finally:
lock.release()
def desktopLogin(self, machineId, username, password, domain):
pass

View File

@ -46,7 +46,6 @@ from .RDPFile import RDPFile
import logging
import random
import string
import time
logger = logging.getLogger(__name__)

View File

@ -44,6 +44,9 @@ from uds.services.OVirt.OVirtProvider import Provider as oVirtProvider
import logging
import os
__updated__ = '2015-05-10'
logger = logging.getLogger(__name__)
READY_CACHE_TIMEOUT = 30
@ -59,26 +62,26 @@ class BaseSpiceTransport(Transport):
allowedProviders = oVirtProvider.offers
useEmptyCreds = gui.CheckBoxField(
label=_('Empty creds'),
order=1,
label=_('Empty creds'),
tooltip=_('If checked, the credentials used to connect will be emtpy')
)
fixedName = gui.TextField(
label=_('Username'),
order=2,
label=_('Username'),
tooltip=_('If not empty, this username will be always used as credential')
)
fixedPassword = gui.PasswordField(
label=_('Password'),
order=3,
label=_('Password'),
tooltip=_('If not empty, this password will be always used as credential')
)
serverCertificate = gui.TextField(
order=2,
order=4,
length=4096,
multiline=4,
label=_('Certificate'),
tooltip=_('Server certificate (public), can be found on your ovirt engine, probably at /etc/pki/ovirt-engine/certs/ca.der'),
tooltip=_('Server certificate (public), can be found on your ovirt engine, probably at /etc/pki/ovirt-engine/certs/ca.der (Use the contents of this file).'),
required=True
)

View File

@ -3,25 +3,29 @@ Created on May 6, 2015
@author: dkmaster
'''
from __future__ import unicode_literals
import six
import os
__updated__ = '2015-05-10'
'''
[virt-viewer]
type=spice
host=ovirtnode1.dkmon.com
port=5900
password=S9MATvnrQNGr
tls-port=5901
fullscreen=0
title=ovirt00004:%d - Press SHIFT+F12 to Release Cursor
enable-smartcard=0
enable-usb-autoshare=1
delete-this-file=1
TEMPLATE = '''[virt-viewer]
type={type}
host={host}
port={port}
password={password}
tls-port={tls_port}
fullscreen={fullscreen}
title={title}:%d - Press SHIFT+F12 to Release Cursor
enable-smartcard={smartcard}
enable-usb-autoshare={usb_auto_share}
delete-this-file={delete_file}
usb-filter=-1,-1,-1,-1,0
tls-ciphers=DEFAULT
host-subject=O=dkmon.com,CN=ovirtnode1.dkmon.com
ca=-----BEGIN CERTIFICATE-----\nMIIDsjCCApqgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwQTELMAkGA1UEBhMCVVMxEjAQBgNVBAoT\nCWRrbW9uLmNvbTEeMBwGA1UEAxMVb3ZpcnQuZGttb24uY29tLjk5MTAxMCIXETEzMTIxMTE5MDA0\nNCswMDAwFw0yMzEyMTAxOTAwNDRaMEExCzAJBgNVBAYTAlVTMRIwEAYDVQQKEwlka21vbi5jb20x\nHjAcBgNVBAMTFW92aXJ0LmRrbW9uLmNvbS45OTEwMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\nAQoCggEBAMeMD3njBOLjuS5XQY0kUu3+dT5S0HUhk2RyPv0Bf59Zun215jLX7qJLrDWCxq8xcdB0\n79Krn2wm+QpPBArSJGVZNXkwQSqnmQK7PGuC119wfOx/bQbgHGJuL6XzuRnLn1xMmcp9N33Q+Cic\nkV5B8bVF+bV5FUWzDbSQKsWJUMFwUXd7px9mZJWBCkY4cOoXdhdu5EMGWcEm2e4RkE+Fb611RAU2\nPL1iJwEu1qtG/OYvWh8DsO9OfFP4dZuJhy2oXmKudHgalNCm8hWYa498c1DA/uXZCGLjoN5en9yy\nXU2wkTDJGA0M95mkGlwoIaNXJMM4i4Q5lmzkU6xntp3/zNkCAwEAAaOBrzCBrDAdBgNVHQ4EFgQU\nOQAXE0qEasnOi3qEFFtMg19GqqYwagYDVR0jBGMwYYAUOQAXE0qEasnOi3qEFFtMg19GqqahRaRD\nMEExCzAJBgNVBAYTAlVTMRIwEAYDVQQKEwlka21vbi5jb20xHjAcBgNVBAMTFW92aXJ0LmRrbW9u\nLmNvbS45OTEwMYICEAAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcN\nAQEFBQADggEBABDS5koE1TcBf8hvRP86AEu07KfWby/BvWXMcGuWRgPnkjrLS0mYshXx2Y40Pblm\nYm/DHXtefrDHJ203T/zkuCLtMSI28peeyX5HS32lGhVAMaylKrQ4mRTBQ+TM2hVLyBv7o16FUcei\nBuGNsm6F8b1RtrGTvSlkNxDUU3haDDH6gRMmMjgYrFqVMrozlPgPyHlFc4A1Q9rM/WIXtRioFgAz\ntCL1n5PK61ZIjk6j6a/upj6jYDfq1G0hpR9XOV8CD1bY3ZaCaMwOaILf1yIzQFqNDmx0p5e949at\nZIflG2pSv/5NA7PoRPF2tHf/PfrNmkA81R03dRXps1UAGg5ds3c=\n-----END CERTIFICATE-----\n
host-subject={host_subject}
ca={ca}
toggle-fullscreen=shift+f11
release-cursor=shift+f12
secure-attention=ctrl+alt+end
@ -30,4 +34,53 @@ secure-channels=main;inputs;cursor;playback;record;display;usbredir;smartcard
class RemoteViewerFile(object):
pass
type = 'spice'
host = None
port = None
tls_port = None
password = None
fullscreen = False
title = 'UDS Enterprise'
host_subject = ''
ca = ''
smartcard = False
usb_auto_share = True
delete_file = True
def __init__(self, host, port, tls_port, password, ca, host_subject, fullscreen=False):
self.host = host
self.port = port
self.tls_port = tls_port
self.password = password
self.ca = ca
self.host_subject = host_subject
self.fullscreen = False
@property
def as_file(self):
return self.get()
def get(self):
fullscreen = '01'[self.fullscreen]
smartcard = '01'[self.smartcard]
delete_file = '01'[self.delete_file]
usb_auto_share = '01'[self.usb_auto_share]
ca = self.ca.strip().replace('\n', '\\\\n') # So we get '\\n' and script works fine after replacement
return TEMPLATE.format(
type=self.type,
host=self.host,
port=self.port,
tls_port=self.tls_port,
password=self.password,
fullscreen=fullscreen,
title=self.title,
smartcard=smartcard,
usb_auto_share=usb_auto_share,
delete_file=delete_file,
host_subject=self.host_subject,
ca=ca
)

View File

@ -32,16 +32,16 @@
'''
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 .BaseSPICETransport import BaseSpiceTransport
from .RemoteViewerFile import RemoteViewerFile
import logging
logger = logging.getLogger(__name__)
__updated__ = '2015-05-10'
READY_CACHE_TIMEOUT = 30
logger = logging.getLogger(__name__)
class SPICETransport(BaseSpiceTransport):
@ -51,7 +51,7 @@ class SPICETransport(BaseSpiceTransport):
'''
typeName = _('SPICE Transport (direct)')
typeType = 'SPICETransport'
typeDescription = _('SPICE Transport for direct connection')
typeDescription = _('SPICE Transport for direct connection (EXPERIMENTAL)')
useEmptyCreds = BaseSpiceTransport.useEmptyCreds
fixedName = BaseSpiceTransport.fixedName
@ -59,69 +59,29 @@ class SPICETransport(BaseSpiceTransport):
serverCertificate = BaseSpiceTransport.serverCertificate
def getUDSTransportScript(self, userService, transport, ip, os, user, password, request):
# We use helper to keep this clean
prefs = user.prefs('rdp')
userServiceInstance = userService.getInstance()
ci = self.getConnectionInfo(userService, user, password)
username, password, domain = ci['username'], ci['password'], ci['domain']
con = userServiceInstance.getConsoleConnection()
width, height = CommonPrefs.getWidthHeight(prefs)
depth = CommonPrefs.getDepth(prefs)
logger.debug('Connection data: {}'.format(con))
# r = SPICEFile(width == -1 or height == -1, width, height, depth, target=os['OS'])
# r.address = '{}:{}'.format(ip, 3389)
# r.username = username
# r.password = password
# r.domain = domain
# r.redirectPrinters = self.allowPrinters.isTrue()
# r.redirectSmartcards = self.allowSmartcards.isTrue()
# r.redirectDrives = self.allowDrives.isTrue()
# r.redirectSerials = self.allowSerials.isTrue()
# r.showWallpaper = self.wallpaper.isTrue()
# r.multimon = self.multimon.isTrue()
#
# # data
# data = {
# 'os': os['OS'],
# 'ip': ip,
# 'port': 3389,
# 'username': username,
# 'password': password,
# 'hasCredentials': username != '' and password != '',
# 'domain': domain,
# 'width': width,
# 'height': height,
# 'depth': depth,
# 'printers': self.allowPrinters.isTrue(),
# 'smartcards': self.allowSmartcards.isTrue(),
# 'drives': self.allowDrives.isTrue(),
# 'serials': self.allowSerials.isTrue(),
# 'compression': True,
# 'wallpaper': self.wallpaper.isTrue(),
# 'multimon': self.multimon.isTrue(),
# 'fullScreen': width == -1 or height == -1,
# 'this_server': request.build_absolute_uri('/'),
# 'r': r,
# }
#
# m = tools.DictAsObj(data)
#
# if m.domain != '':
# m.usernameWithDomain = '{}\\\\{}'.format(m.domain, m.username)
# else:
# m.usernameWithDomain = m.username
#
# if m.os == OsDetector.Windows:
# m.r.password = '{password}'
#
# os = {
# OsDetector.Windows: 'windows',
# OsDetector.Linux: 'linux',
# OsDetector.Macintosh: 'macosx'
#
# }.get(m.os)
#
# if os is None:
# return super(SPICETransport, self).getUDSTransportScript(self, userService, transport, ip, os, user, password, request)
#
# return self.getScript('scripts/{}/direct.py'.format(os)).format(m=m)
port, secure_port = con['port'], con['secure_port']
port = -1 if port is None else port
secure_port = -1 if secure_port is None else secure_port
r = RemoteViewerFile(con['address'], port, secure_port, con['ticket']['value'], self.serverCertificate.value, con['cert_subject'], fullscreen=False)
m = tools.DictAsObj({
'r': r
})
os = {
OsDetector.Windows: 'windows',
OsDetector.Linux: 'linux',
OsDetector.Macintosh: 'macosx'
}.get(os.OS)
if os is None:
return super(SPICETransport, self).getUDSTransportScript(self, userService, transport, ip, os, user, password, request)
return self.getScript('scripts/{}/direct.py'.format(os)).format(m=m)

View File

@ -32,25 +32,24 @@
'''
from django.utils.translation import ugettext_noop as _
from uds.core.managers.UserPrefsManager import CommonPrefs
from uds.core.ui.UserInterface import gui
from uds.core.transports.BaseTransport import Transport
from uds.core.transports import protocols
from uds.models import TicketStore
from uds.core.util import OsDetector
from uds.core.util import tools
from uds.models import TicketStore
from .BaseSPICETransport import BaseSpiceTransport
from .RemoteViewerFile import RemoteViewerFile
import logging
import random
import string
import time
__updated__ = '2015-05-10'
logger = logging.getLogger(__name__)
READY_CACHE_TIMEOUT = 30
class TSPICETransport(BaseSpiceTransport):
'''
@ -59,17 +58,13 @@ class TSPICETransport(BaseSpiceTransport):
'''
typeName = _('SPICE Transport (tunneled)')
typeType = 'TSSPICETransport'
typeDescription = _('SPICE Transport for tunneled connection')
typeDescription = _('SPICE Transport for tunneled connection (EXPERIMENTAL)')
iconFile = 'rdp.png'
needsJava = True # If this transport needs java for rendering
protocol = protocols.SPICE
tunnelServer = gui.TextField(label=_('Tunnel server'), order=1, tooltip=_('IP or Hostname of tunnel server sent to client device ("public" ip) and port. (use HOST:PORT format)'))
tunnelCheckServer = gui.TextField(label=_('Tunnel host check'), order=2, tooltip=_('If not empty, this server will be used to check if service is running before assigning it to user. (use HOST:PORT format)'))
useEmptyCreds = BaseSpiceTransport.useEmptyCreds
fixedName = BaseSpiceTransport.fixedName
fixedPassword = BaseSpiceTransport.fixedPassword
serverCertificate = BaseSpiceTransport.serverCertificate
def initialize(self, values):
@ -78,80 +73,40 @@ class TSPICETransport(BaseSpiceTransport):
raise Transport.ValidationException(_('Must use HOST:PORT in Tunnel Server Field'))
def getUDSTransportScript(self, userService, transport, ip, os, user, password, request):
# We use helper to keep this clean
prefs = user.prefs('rdp')
userServiceInstance = userService.getInstance()
ci = self.getConnectionInfo(userService, user, password)
username, password, domain = ci['username'], ci['password'], ci['domain']
width, height = CommonPrefs.getWidthHeight(prefs)
depth = CommonPrefs.getDepth(prefs)
# Spice connection
con = userServiceInstance.getConsoleConnection()
port, secure_port = con['port'], con['secure_port']
port = -1 if port is None else port
secure_port = -1 if secure_port is None else secure_port
# Ticket
tunpass = ''.join(random.choice(string.letters + string.digits) for _i in range(12))
tunuser = TicketStore.create(tunpass)
sshHost, sshPort = self.tunnelServer.value.split(':')
logger.debug('Username generated: {0}, password: {1}'.format(tunuser, tunpass))
r = RemoteViewerFile('127.0.0.1', '{port}', '{secure_port}', con['ticket']['value'], self.serverCertificate.value, con['cert_subject'], fullscreen=False)
# r = SPICEFile(width == -1 or height == -1, width, height, depth, target=os['OS'])
# r.address = '{address}'
# r.username = username
# r.password = password
# r.domain = domain
# r.redirectPrinters = self.allowPrinters.isTrue()
# r.redirectSmartcards = self.allowSmartcards.isTrue()
# r.redirectDrives = self.allowDrives.isTrue()
# r.redirectSerials = self.allowSerials.isTrue()
# r.showWallpaper = self.wallpaper.isTrue()
# r.multimon = self.multimon.isTrue()
#
#
# # data
# data = {
# 'os': os['OS'],
# 'ip': ip,
# 'tunUser': tunuser,
# 'tunPass': tunpass,
# 'tunHost': sshHost,
# 'tunPort': sshPort,
# 'username': username,
# 'password': password,
# 'hasCredentials': username != '' and password != '',
# 'domain': domain,
# 'width': width,
# 'height': height,
# 'depth': depth,
# 'printers': self.allowPrinters.isTrue(),
# 'smartcards': self.allowSmartcards.isTrue(),
# 'drives': self.allowDrives.isTrue(),
# 'serials': self.allowSerials.isTrue(),
# 'compression': True,
# 'wallpaper': self.wallpaper.isTrue(),
# 'multimon': self.multimon.isTrue(),
# 'fullScreen': width == -1 or height == -1,
# 'this_server': request.build_absolute_uri('/'),
# 'r': r,
# }
#
# m = tools.DictAsObj(data)
#
# if m.domain != '':
# m.usernameWithDomain = '{}\\\\{}'.format(m.domain, m.username)
# else:
# m.usernameWithDomain = m.username
#
# if m.os == OsDetector.Windows:
# r.password = '{password}'
#
# os = {
# OsDetector.Windows: 'windows',
# OsDetector.Linux: 'linux',
# OsDetector.Macintosh: 'macosx'
#
# }.get(m.os)
#
# if os is None:
# return super(TSPICETransport, self).getUDSTransportScript(self, userService, transport, ip, os, user, password, request)
#
# return self.getScript('scripts/{}/tunnel.py'.format(os)).format(m=m)
m = tools.DictAsObj({
'r': r,
'tunUser': tunuser,
'tunPass': tunpass,
'tunHost': sshHost,
'tunPort': sshPort,
'ip': con['address'],
'port': port,
'secure_port': secure_port
})
os = {
OsDetector.Windows: 'windows',
OsDetector.Linux: 'linux',
OsDetector.Macintosh: 'macosx'
}.get(os.OS)
if os is None:
return super(TSPICETransport, self).getUDSTransportScript(self, userService, transport, ip, os, user, password, request)
return self.getScript('scripts/{}/tunnel.py'.format(os)).format(m=m)

View File

@ -35,11 +35,3 @@ from django.utils.translation import ugettext_noop as _
from uds.core.managers.UserPrefsManager import UserPrefsManager, CommonPrefs
from .SPICETransport import SPICETransport
from .TSPICETransport import TSPICETransport
UserPrefsManager.manager().registerPrefs('rdp',
_('Remote Desktop Protocol'),
[
CommonPrefs.screenSizePref,
CommonPrefs.depthPref
]
)

View File

@ -2,61 +2,24 @@
# 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, invalid-sequence-index
from PyQt4 import QtCore, QtGui
# pylint: disable=import-error, no-name-in-module
import subprocess
import re
from uds import tools # @UnresolvedImport
import six
executable = tools.findApp('remote-viewer')
def execNewXFreeRdp(parent, xfreerdp):
import subprocess # @Reimport
params = [xfreerdp] + {m.r.as_new_xfreerdp_params} + ['/v:{m.r.address}'] # @UndefinedVariable
tools.addTaskToWait(subprocess.Popen(params))
def execRdesktop(parent, rdesktop):
import subprocess # @Reimport
params = [rdesktop] + {m.r.as_rdesktop_params} + ['{m.r.address}'] # @UndefinedVariable
p = subprocess.Popen(params, stdin=subprocess.PIPE)
if '{m.password}' != '':
p.stdin.write('{m.password}')
p.stdin.close()
tools.addTaskToWait(p)
# Try to locate a "valid" version of xfreerdp as first option (<1.1 does not allows drive redirections, so it will not be used if found)
xfreerdp = tools.findApp('xfreerdp')
rdesktop = tools.findApp('rdesktop')
fnc, app = None, None
if rdesktop is not None:
fnc, app = execRdesktop, rdesktop
if xfreerdp is not None:
# Check for nice version
try:
try:
version = subprocess.check_output([xfreerdp, '--version'])
except subprocess.CalledProcessError as e:
version = e.output
version = float(re.search(r'version ([0-9]*\.[0-9]*)', version).groups()[0])
if version < 1.1:
raise Exception()
else:
fnc, app = execNewXFreeRdp, xfreerdp
except Exception as e: # Valid version not found, pass to check rdesktop
# QtGui.QMessageBox.critical(parent, 'Notice', six.text_type(e), QtGui.QMessageBox.Ok) # @UndefinedVariable
pass
if app is None or fnc is None:
raise Exception('''<p>You need to have installed xfreerdp (>= 1.1) or rdesktop, and have them in your PATH in order to connect to this UDS service.</p>
<p>Please, install apropiate package for your system.</p>
<p>Also note that xfreerdp prior to version 1.1 will not be taken into consideration.</p>
if executable is None:
raise Exception('''<p>You need to have installed virt-viewer to connect to this UDS service.</p>
<p>
Please, install appropriate package for your Linux system. (probably named something like <b>remote-viewer</b>)
</p>
''')
else:
fnc(parent, app) # @UndefinedVariable
theFile = '''{m.r.as_file}'''
filename = tools.saveTempFile(theFile)
subprocess.Popen([executable, filename])
# QtGui.QMessageBox.critical(parent, 'Notice', filename + ", " + executable, QtGui.QMessageBox.Ok)

View File

@ -2,68 +2,47 @@
# 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, invalid-sequence-index
from PyQt4 import QtCore, QtGui
# pylint: disable=import-error, no-name-in-module, undefined-variable
import subprocess
import re
from uds.forward import forward # @UnresolvedImport
from uds import tools # @UnresolvedImport
from uds.forward import forward # @UnresolvedImport
import six
executable = tools.findApp('remote-viewer')
def execNewXFreeRdp(parent, xfreerdp, port):
import subprocess # @Reimport
params = [xfreerdp] + {m.r.as_new_xfreerdp_params} + ['/v:127.0.0.1:{{}}'.format(port)] # @UndefinedVariable
tools.addTaskToWait(subprocess.Popen(params))
def execRdesktop(parent, rdesktop, port):
import subprocess # @Reimport
params = [rdesktop] + {m.r.as_rdesktop_params} + ['127.0.0.1:{{}}'.format(port)] # @UndefinedVariable
p = subprocess.Popen(params, stdin=subprocess.PIPE)
if {m.hasCredentials}: # @UndefinedVariable
p.stdin.write('{m.password}')
p.stdin.close()
tools.addTaskToWait(p)
# Try to locate a "valid" version of xfreerdp as first option (<1.1 does not allows drive redirections, so it will not be used if found)
xfreerdp = tools.findApp('xfreerdp')
rdesktop = tools.findApp('rdesktop')
fnc, app = None, None
if rdesktop is not None:
fnc, app = execRdesktop, rdesktop
if xfreerdp is not None:
# Check for nice version
try:
try:
version = subprocess.check_output([xfreerdp, '--version'])
except subprocess.CalledProcessError as e:
version = e.output
version = float(re.search(r'version ([0-9]*\.[0-9]*)', version).groups()[0])
if version < 1.1:
raise Exception()
else:
fnc, app = execNewXFreeRdp, xfreerdp
except Exception as e: # Valid version not found, pass to check rdesktop
# QtGui.QMessageBox.critical(parent, 'Notice', six.text_type(e), QtGui.QMessageBox.Ok) # @UndefinedVariable
pass
if app is None or fnc is None:
raise Exception('''<p>You need to have installed xfreerdp (>= 1.1) or rdesktop, and have them in your PATH in order to connect to this UDS service.</p>
<p>Please, install apropiate package for your system.</p>
<p>Also note that xfreerdp prior to version 1.1 will not be taken into consideration.</p>
if executable is None:
raise Exception('''<p>You need to have installed virt-viewer to connect to this UDS service.</p>
<p>
Please, install appropriate package for your system.
</p>
<p>
Please, install appropriate package for your Linux system. (probably named something like <b>virt-viewer</b>)
</p>
''')
else:
# Open tunnel
forwardThread, port = forward('{m.tunHost}', '{m.tunPort}', '{m.tunUser}', '{m.tunPass}', '{m.ip}', 3389)
if forwardThread.status == 2:
if {m.port} != -1: # @UndefinedVariable
forwardThread1, port = forward('{m.tunHost}', '{m.tunPort}', '{m.tunUser}', '{m.tunPass}', '{m.ip}', {m.port}) # @UndefinedVariable
if forwardThread1.status == 2:
raise Exception('Unable to open tunnel')
else:
port = -1
fnc(parent, app, port) # @UndefinedVariable
if {m.secure_port} != -1: # @UndefinedVariable
forwardThread2, secure_port = forward('{m.tunHost}', '{m.tunPort}', '{m.tunUser}', '{m.tunPass}', '{m.ip}', {m.secure_port}) # @UndefinedVariable
if forwardThread2.status == 2:
raise Exception('Unable to open tunnel')
else:
secure_port = -1
theFile = '''{m.r.as_file}'''.format(
secure_port=secure_port,
port=port
)
filename = tools.saveTempFile(theFile)
subprocess.Popen([executable, filename])

View File

@ -2,110 +2,34 @@
# 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, invalid-sequence-index
from PyQt4 import QtCore, QtGui
import subprocess
# pylint: disable=import-error, no-name-in-module
import os
import urllib
import subprocess
from uds import tools # @UnresolvedImport
import six
remoteViewer = '/Applications/RemoteViewer.app/Contents/MacOS/RemoteViewer'
if not os.path.isfile(remoteViewer):
raise Exception('''<p>You need to have installed virt-viewer to connect to this UDS service.</p>
<p>
Please, install appropriate package for your system.
</p>
<p>
<a href="http://www.spice-space.org/page/OSX_Client">Open download page</a>
</p>
<p>
Please, note that in order to UDS Connector to work correctly, you must copy the Remote Viewer app to your Applications Folder.<br/>
Also remember, that in order to allow this app to run on your system, you must open it one time once it is copied to your App folder
</p>
''')
theFile = '''{m.r.as_file}'''
# First, try to locate Remote Desktop Connection (version 2, from Microsoft website, not the app store one)
filename = tools.saveTempFile(theFile)
filename = tools.saveTempFile(theFile)
msrdc = '/Applications/Remote Desktop Connection.app/Contents/MacOS/Remote Desktop Connection'
cord = "/Applications/CoRD.app/Contents/MacOS/CoRD"
if os.path.isfile(msrdc):
executable = msrdc
elif os.path.isfile(cord):
executable = cord
else:
executable = None
def onExit():
import subprocess # @Reimport
subprocess.call(
[
'security',
'delete-generic-password',
'-a', '{m.usernameWithDomain}',
'-s', 'Remote Desktop Connection 2 Password for {m.ip}',
]
)
if executable is None:
QtGui.QMessageBox.critical(parent, 'Notice', # @UndefinedVariable
'''<p><b>Microsoft Remote Desktop Connection not found</b></p>
<p>In order to connect to UDS RDP Sessions, you need to have at least one of the following:<p>
<ul>
<li>
<p><b>Microsoft Remote Desktop Connection version 2.</b> (Recommended)</p>
<p>You can get it from <a href="http://www.microsoft.com/es-es/download/details.aspx?id=18140">this link</a></p>
<p>Remember that you need to use the One from the Microsoft site (the link provided), not the one from the AppStore</p>
</li>
<li>
<p><b>CoRD</b> (A bit unstable from 10.7 onwards)</p>
<p>You can get it from <a href="{m.this_server}static/other/CoRD.pkg">this link</a></p>
</li>
</ul>
<p>If both apps are installed, Remote Desktop Connection will be used as first option</p>
''', QtGui.QMessageBox.Ok)
elif executable == msrdc:
try:
if {m.hasCredentials}: # @UndefinedVariable
subprocess.call(
[
'security',
'add-generic-password',
'-w', '{m.password}',
'-U',
'-a', '{m.usernameWithDomain}',
'-s', 'Remote Desktop Connection 2 Password for {m.ip}',
'-T', '/Applications/Remote Desktop Connection.app',
]
)
tools.addExecBeforeExit(onExit)
# Call and wait for exit
tools.addTaskToWait(subprocess.Popen([executable, filename]))
tools.addFileToUnlink(filename)
except Exception as e:
QtGui.QMessageBox.critical(parent, 'Notice', six.text_type(e), QtGui.QMessageBox.Ok) # @UndefinedVariable
else: # CoRD
url = 'rdp://'
username, domain = '{m.username}', '{m.domain}'
if username != '':
url += username
if '{m.password}' != '':
url += ':' + urllib.quote('{m.password}')
url += '@'
url += '{m.ip}/'
if domain != '':
url += domain
url += '?screenDepth={m.r.bpp}'
if {m.r.fullScreen}: # @UndefinedVariable
url += '&fullscreen=true'
else:
url += 'screenWidth={m.r.width}&screenHeight={m.r.height}'
url += '&forwardAudio=' + '01'[{m.r.redirectAudio}] # @UndefinedVariable
if {m.r.redirectDrives}: # @UndefinedVariable
url += '&forwardDisks=true'
if {m.r.redirectPrinters}: # @UndefinedVariable
url += '&forwardPrinters=true'
tools.addTaskToWait(subprocess.Popen(['open', url]))
subprocess.Popen([remoteViewer, filename])

View File

@ -2,119 +2,51 @@
# 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, invalid-sequence-index
from PyQt4 import QtCore, QtGui
import subprocess
# pylint: disable=import-error, no-name-in-module, undefined-variable
import os
import urllib
from uds.forward import forward # @UnresolvedImport
import subprocess
from uds import tools # @UnresolvedImport
from uds.forward import forward # @UnresolvedImport
import six
remoteViewer = '/Applications/RemoteViewer.app/Contents/MacOS/RemoteViewer'
# First, try to locate Remote Desktop Connection (version 2, from Microsoft website, not the app store one)
msrdc = '/Applications/Remote Desktop Connection.app/Contents/MacOS/Remote Desktop Connection'
cord = "/Applications/CoRD.app/Contents/MacOS/CoRD"
if not os.path.isfile(remoteViewer):
raise Exception('''<p>You need to have installed virt-viewer to connect to this UDS service.</p>
<p>
Please, install appropriate package for your system.
</p>
<p>
<a href="http://virt-manager.org/download/">Open download page</a>
</p>
<p>
Please, note that in order to UDS Connector to work correctly, you must copy the Remote Viewer app to your Applications Folder.<br/>
Also remember, that in order to allow this app to run on your system, you must open it one time once it is copied to your App folder
</p>
''')
if os.path.isfile(msrdc):
executable = msrdc
elif os.path.isfile(cord):
executable = cord
if {m.port} != -1: # @UndefinedVariable
forwardThread1, port = forward('{m.tunHost}', '{m.tunPort}', '{m.tunUser}', '{m.tunPass}', '{m.ip}', {m.port}) # @UndefinedVariable
if forwardThread1.status == 2:
raise Exception('Unable to open tunnel')
else:
executable = None
port = -1
if {m.secure_port} != -1: # @UndefinedVariable
forwardThread2, secure_port = forward('{m.tunHost}', '{m.tunPort}', '{m.tunUser}', '{m.tunPass}', '{m.ip}', {m.secure_port}) # @UndefinedVariable
def onExit():
import subprocess # @Reimport
subprocess.call(
[
'security',
'delete-generic-password',
'-a', '{m.username}',
'-s', 'Remote Desktop Connection 2 Password for 127.0.0.1',
]
)
if executable is None:
QtGui.QMessageBox.critical(parent, 'Notice', # @UndefinedVariable
'''<p><b>Microsoft Remote Desktop Connection not found</b></p>
<p>In order to connect to UDS RDP Sessions, you need to have at least one of the following:<p>
<ul>
<li>
<p><b>Microsoft Remote Desktop Connection version 2.</b> (Recommended)</p>
<p>You can get it from <a href="http://www.microsoft.com/es-es/download/details.aspx?id=18140">this link</a></p>
<p>Remember that you need to use the One from the Microsoft site (the link provided), not the one from the AppStore</p>
</li>
<li>
<p><b>CoRD</b> (A bit unstable from 10.7 onwards)</p>
<p>You can get it from <a href="{m.this_server}static/other/CoRD.pkg">this link</a></p>
</li>
</ul>
<p>If both apps are installed, Remote Desktop Connection will be used as first option</p>
''', QtGui.QMessageBox.Ok)
forwardThread, port = forward('{m.tunHost}', '{m.tunPort}', '{m.tunUser}', '{m.tunPass}', '{m.ip}', 3389)
if forwardThread.status == 2:
raise Exception('Unable to open tunnel')
if forwardThread2.status == 2:
raise Exception('Unable to open tunnel')
else:
theFile = '''{m.r.as_file}'''.format(
address='127.0.0.1:{{}}'.format(port)
)
filename = tools.saveTempFile(theFile)
tools.addFileToUnlink(filename)
secure_port = -1
if executable == msrdc:
try:
if {m.hasCredentials}: # @UndefinedVariable
subprocess.call(
[
'security',
'add-generic-password',
'-w', '{m.password}',
'-U',
'-a', '{m.username}',
'-s', 'Remote Desktop Connection 2 Password for 127.0.0.1'.format(port),
'-T', '/Applications/Remote Desktop Connection.app',
]
)
tools.addExecBeforeExit(onExit)
# Call but do not wait for exit
tools.addTaskToWait(subprocess.Popen([executable, filename]))
theFile = '''{m.r.as_file}'''.format(
secure_port=secure_port,
port=port
)
tools.addFileToUnlink(filename)
except Exception as e:
QtGui.QMessageBox.critical(parent, 'Notice', six.text_type(e), QtGui.QMessageBox.Ok) # @UndefinedVariable
else: # CoRD
url = 'rdp://'
username, domain = '{m.username}', '{m.domain}'
filename = tools.saveTempFile(theFile)
if username != '':
url += username
if '{m.password}' != '':
url += ':' + urllib.quote('{m.password}')
url += '@'
url += '127.0.0.1:3389/'
if domain != '':
url += domain
url += '?screenDepth={m.r.bpp}'
if {m.r.fullScreen}: # @UndefinedVariable
url += '&fullscreen=true'
else:
url += 'screenWidth={m.r.width}&screenHeight={m.r.height}'
url += '&forwardAudio=' + '01'[{m.r.redirectAudio}] # @UndefinedVariable
if {m.r.redirectDrives}: # @UndefinedVariable
url += '&forwardDisks=true'
if {m.r.redirectPrinters}: # @UndefinedVariable
url += '&forwardPrinters=true'
tools.addTaskToWait(subprocess.Popen(['open', url]))
subprocess.Popen([remoteViewer, filename])

View File

@ -3,21 +3,33 @@
from __future__ import unicode_literals
# pylint: disable=import-error, no-name-in-module
from PyQt4 import QtCore, QtGui
import win32crypt # @UnresolvedImport
import os
import glob
import subprocess
from uds import tools # @UnresolvedImport
import six
# Lets find remote viewer
# There is a bug that when installed, the remote viewer (at least 64 bits version) does not store correctly its path, so lets find it "a las bravas"
extraPaths = ()
for env in ('PROGRAMFILES', 'PROGRAMW6432'):
if env in os.environ:
extraPaths += tuple(p + '\\bin' for p in glob.glob(os.environ[env] + '\\VirtViewer*'))
# 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'))
executable = tools.findApp('remote-viewer.exe', extraPaths)
if executable is None:
raise Exception('''<p>You need to have installed virt-viewer to connect to this UDS service.</p>
<p>
Please, install appropriate package for your system.
</p>
<p>
<a href="http://virt-manager.org/download/">Open download page</a>
</p>
''')
theFile = '''{m.r.as_file}'''
filename = tools.saveTempFile(theFile)
executable = tools.findApp('mstsc.exe')
subprocess.call([executable, filename])
tools.addFileToUnlink(filename)
# QtGui.QMessageBox.critical(parent, 'Notice', filename + ", " + executable, QtGui.QMessageBox.Ok)
subprocess.Popen([executable, filename])

View File

@ -2,35 +2,54 @@
# 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
# pylint: disable=import-error, no-name-in-module, undefined-variable
import os
import glob
import subprocess
from uds.forward import forward # @UnresolvedImport
from uds import tools # @UnresolvedImport
from uds.forward import forward # @UnresolvedImport
import six
# Lets find remote viewer
# There is a bug that when installed, the remote viewer (at least 64 bits version) does not store correctly its path, so lets find it "a las bravas"
extraPaths = ()
for env in ('PROGRAMFILES', 'PROGRAMW6432'):
if env in os.environ:
extraPaths += tuple(p + '\\bin' for p in glob.glob(os.environ[env] + '\\VirtViewer*'))
forwardThread, port = forward('{m.tunHost}', '{m.tunPort}', '{m.tunUser}', '{m.tunPass}', '{m.ip}', 3389)
executable = tools.findApp('remote-viewer.exe', extraPaths)
if forwardThread.status == 2:
raise Exception('Unable to open tunnel')
if executable is None:
raise Exception('''<p>You need to have installed virt-viewer to connect to this UDS service.</p>
<p>
Please, install appropriate package for your system.
</p>
<p>
<a href="http://virt-manager.org/download/">Open download page</a>
</p>
''')
if {m.port} != -1: # @UndefinedVariable
forwardThread1, port = forward('{m.tunHost}', '{m.tunPort}', '{m.tunUser}', '{m.tunPass}', '{m.ip}', {m.port}) # @UndefinedVariable
if forwardThread1.status == 2:
raise Exception('Unable to open tunnel')
else:
port = -1
if {m.secure_port} != -1: # @UndefinedVariable
forwardThread2, secure_port = forward('{m.tunHost}', '{m.tunPort}', '{m.tunUser}', '{m.tunPass}', '{m.ip}', {m.secure_port}) # @UndefinedVariable
if forwardThread2.status == 2:
raise Exception('Unable to open tunnel')
else:
secure_port = -1
# 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)
secure_port=secure_port,
port=port
)
filename = tools.saveTempFile(theFile)
executable = tools.findApp('mstsc.exe')
if executable is None:
raise Exception('Unable to find mstsc.exe')
subprocess.call([executable, filename])
tools.addFileToUnlink(filename)
# QtGui.QMessageBox.critical(parent, 'Notice', filename + ", " + executable, QtGui.QMessageBox.Ok)
subprocess.Popen([executable, filename])