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:
parent
e69914a9a5
commit
04ec90ad61
@ -51,6 +51,8 @@ import requests
|
||||
import json
|
||||
import logging
|
||||
|
||||
__updated__ = '2015-05-06'
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
USERSERVICE_TAG = 'cm-'
|
||||
|
@ -40,6 +40,8 @@ from uds.core.transports import protocols
|
||||
|
||||
import logging
|
||||
|
||||
__updated__ = '2015-05-06'
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
@ -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))
|
||||
|
@ -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)
|
||||
|
@ -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):
|
||||
'''
|
||||
|
@ -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
|
||||
|
@ -46,7 +46,6 @@ from .RDPFile import RDPFile
|
||||
import logging
|
||||
import random
|
||||
import string
|
||||
import time
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -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
|
||||
)
|
||||
|
||||
|
@ -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
|
||||
)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
]
|
||||
)
|
||||
|
@ -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)
|
||||
|
@ -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])
|
||||
|
@ -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])
|
||||
|
@ -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])
|
||||
|
@ -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])
|
||||
|
@ -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])
|
||||
|
Loading…
Reference in New Issue
Block a user