forked from shaba/openuds
Merged with 2.1
This commit is contained in:
commit
506364d578
@ -34,7 +34,7 @@ from __future__ import unicode_literals
|
||||
# On centos, old six release does not includes byte2int, nor six.PY2
|
||||
import six
|
||||
|
||||
VERSION = '2.0.0'
|
||||
VERSION = '2.1.0'
|
||||
|
||||
__title__ = 'udsactor'
|
||||
__version__ = VERSION
|
||||
|
@ -196,13 +196,22 @@ class HTTPServerThread(threading.Thread):
|
||||
|
||||
self.initiateServer(address)
|
||||
|
||||
def getPort(self):
|
||||
return self.address[1]
|
||||
|
||||
def getIp(self):
|
||||
return self.address[0]
|
||||
|
||||
def initiateServer(self, address):
|
||||
self.server = socketserver.TCPServer(address, HTTPServerHandler)
|
||||
self.address = (address[0], address[1]) # Copy address & keep it for future reference...
|
||||
|
||||
addr = ('0.0.0.0', address[1]) # Adapt to listen on 0.0.0.0
|
||||
|
||||
self.server = socketserver.TCPServer(addr, HTTPServerHandler)
|
||||
self.server.socket = ssl.wrap_socket(self.server.socket, certfile=self.certFile, server_side=True)
|
||||
|
||||
def getServerUrl(self):
|
||||
return 'https://{}:{}/{}'.format(self.server.server_address[0], self.server.server_address[1], HTTPServerHandler.uuid)
|
||||
return 'https://{}:{}/{}'.format(self.getIp(), self.getPort(), HTTPServerHandler.uuid)
|
||||
|
||||
def stop(self):
|
||||
logger.debug('Stopping REST Service')
|
||||
@ -211,11 +220,14 @@ class HTTPServerThread(threading.Thread):
|
||||
def restart(self, address=None):
|
||||
|
||||
if address is None:
|
||||
address = self.server.server_address
|
||||
# address = self.server.server_address
|
||||
address = self.address
|
||||
|
||||
self.stop()
|
||||
self.address = (address[0], self.address[1]) # Copy address & keep it for future reference, port is never changed once assigned on init
|
||||
|
||||
self.initiateServer(address)
|
||||
# Listening on 0.0.0.0, does not need to restart listener..
|
||||
# self.stop()
|
||||
# self.initiateServer(address)
|
||||
|
||||
def run(self):
|
||||
self.server.serve_forever()
|
||||
|
@ -211,7 +211,7 @@ class CommonService(object):
|
||||
self.knownIps = dict(((v.mac, v.ip) for v in netInfo))
|
||||
|
||||
# And notify new listening address to broker
|
||||
address = (self.knownIps[self.api.mac], random.randrange(43900, 44000))
|
||||
address = (self.knownIps[self.api.mac], self.httpServer.getPort())
|
||||
# And new listening address
|
||||
self.httpServer.restart(address)
|
||||
# sends notification
|
||||
|
@ -1,3 +1,9 @@
|
||||
udsclient (2.1.0) stable; urgency=medium
|
||||
|
||||
* Updated release
|
||||
|
||||
-- Adolfo Gómez García <agomez@virtualcable.es> Sun, 23 Oct 2016 21:12:23 +0200
|
||||
|
||||
udsclient (2.0.0) stable; urgency=medium
|
||||
|
||||
* Release upgrade
|
||||
|
@ -1 +1 @@
|
||||
udsclient_2.0.0_all.deb admin optional
|
||||
udsclient_2.1.0_all.deb admin optional
|
||||
|
@ -34,7 +34,7 @@ from __future__ import unicode_literals
|
||||
# On centos, old six release does not includes byte2int, nor six.PY2
|
||||
import six
|
||||
|
||||
VERSION = '2.0.0'
|
||||
VERSION = '2.1.0'
|
||||
|
||||
__title__ = 'udclient'
|
||||
__version__ = VERSION
|
||||
|
@ -13,6 +13,7 @@ python-ldap
|
||||
MySQL-python
|
||||
reportlab
|
||||
bitarray
|
||||
paramiko
|
||||
python-dateutil
|
||||
defusedxml
|
||||
requests
|
||||
|
@ -22,7 +22,7 @@ DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
|
||||
'OPTIONS': {
|
||||
'init_command': 'SET storage_engine=INNODB; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;',
|
||||
'init_command': 'SET default_storage_engine=INNODB; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;',
|
||||
# 'init_command': 'SET storage_engine=INNODB, SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED',
|
||||
# 'init_command': 'SET storage_engine=MYISAM, SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED',
|
||||
},
|
||||
|
@ -109,6 +109,10 @@ class CalendarRules(DetailHandler): # pylint: disable=too-many-public-methods
|
||||
# We need this fields for all
|
||||
logger.debug('Saving rule {0} / {1}'.format(parent, item))
|
||||
fields = self.readFieldsFromParams(['name', 'comments', 'frequency', 'start', 'end', 'interval', 'duration', 'duration_unit'])
|
||||
|
||||
if int(fields['interval']) < 1:
|
||||
self.invalidItemException('Repeat must be greater than zero')
|
||||
|
||||
# Convert timestamps to datetimes
|
||||
fields['start'] = datetime.datetime.fromtimestamp(fields['start'])
|
||||
if fields['end'] != None:
|
||||
|
@ -46,6 +46,7 @@ from uds.core.ui.UserInterface import gui
|
||||
from .user_services import AssignedService, CachedService, Groups, Transports, Publications, Changelog
|
||||
from .services_pool_calendars import AccessCalendars, ActionsCalendars
|
||||
from .services import Services
|
||||
from uds.core.managers import userServiceManager
|
||||
|
||||
import logging
|
||||
|
||||
@ -74,10 +75,12 @@ class ServicesPools(ModelHandler):
|
||||
table_title = _('Service Pools')
|
||||
table_fields = [
|
||||
{'name': {'title': _('Name')}},
|
||||
{'parent': {'title': _('Parent Service')}},
|
||||
{'state': {'title': _('status'), 'type': 'dict', 'dict': State.dictionary()}},
|
||||
{'user_services_count': {'title': _('User services'), 'type': 'number'}},
|
||||
{'user_services_in_preparation': {'title': _('In Preparation')}},
|
||||
{'show_transports': {'title': _('Shows transports'), 'type': 'callback'}},
|
||||
{'pool_group_name': {'title': _('Pool Group')}},
|
||||
{'parent': {'title': _('Parent Service')}},
|
||||
{'tags': {'title': _('tags'), 'visible': False}},
|
||||
]
|
||||
# Field from where to get "class" and prefix for that class, so this will generate "row-state-A, row-state-X, ....
|
||||
@ -97,6 +100,13 @@ class ServicesPools(ModelHandler):
|
||||
poolGroupName = item.servicesPoolGroup.name
|
||||
if item.servicesPoolGroup.image is not None:
|
||||
poolGroupThumb = item.servicesPoolGroup.image.thumb64
|
||||
|
||||
state = item.state
|
||||
if item.isInMaintenance():
|
||||
state = State.MAINTENANCE
|
||||
elif userServiceManager().canInitiateServiceFromDeployedService(item) is False:
|
||||
state = State.SLOWED_DOWN
|
||||
|
||||
val = {
|
||||
'id': item.uuid,
|
||||
'name': item.name,
|
||||
@ -104,7 +114,7 @@ class ServicesPools(ModelHandler):
|
||||
'parent': item.service.name,
|
||||
'parent_type': item.service.data_type,
|
||||
'comments': item.comments,
|
||||
'state': item.state if item.isInMaintenance() is False else State.MAINTENANCE,
|
||||
'state': state,
|
||||
'thumb': item.image.thumb64 if item.image is not None else DEFAULT_THUMB_BASE64,
|
||||
'service_id': item.service.uuid,
|
||||
'provider_id': item.service.provider.uuid,
|
||||
@ -117,6 +127,7 @@ class ServicesPools(ModelHandler):
|
||||
'cache_l2_srvs': item.cache_l2_srvs,
|
||||
'max_srvs': item.max_srvs,
|
||||
'user_services_count': item.userServices.count(),
|
||||
'user_services_in_preparation': item.userServices.filter(state=State.PREPARING).count(),
|
||||
'restrained': item.isRestrained(),
|
||||
'show_transports': item.show_transports,
|
||||
'fallbackAccess': item.fallbackAccess,
|
||||
|
@ -38,6 +38,7 @@ from __future__ import unicode_literals
|
||||
from uds.core.Environment import Environmentable
|
||||
from uds.core.Serializable import Serializable
|
||||
from uds.core.BaseModule import Module
|
||||
import time
|
||||
|
||||
VERSION = '2.x.x-DEVEL'
|
||||
VERSION_STAMP = '{}-DEVEL'.format(time.strftime("%Y%m%d"))
|
||||
|
@ -51,7 +51,7 @@ import requests
|
||||
import json
|
||||
import logging
|
||||
|
||||
__updated__ = '2016-10-14'
|
||||
__updated__ = '2016-11-04'
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -411,6 +411,7 @@ class UserServiceManager(object):
|
||||
'''
|
||||
If allowed, send script to user service
|
||||
'''
|
||||
# logger.debug('Senging script: {}'.format(script))
|
||||
url = uService.getCommsUrl()
|
||||
if url is None:
|
||||
logger.error('Can\'t connect with actor (no actor or legacy actor)')
|
||||
|
@ -48,6 +48,7 @@ class State(object):
|
||||
FINISHED = 'F'
|
||||
BALANCING = 'H'
|
||||
INACTIVE = 'I'
|
||||
SLOWED_DOWN = 'J' # Only used on admin dashboard, not internal real state
|
||||
CANCELING = 'K'
|
||||
LAUNCHING = 'L'
|
||||
REMOVING = 'M'
|
||||
@ -78,7 +79,8 @@ class State(object):
|
||||
FOR_EXECUTE: _('Waiting execution'),
|
||||
BALANCING: _('Balancing'),
|
||||
MAINTENANCE: _('In maintenance'),
|
||||
WAITING_OS: _('Waiting OS')
|
||||
WAITING_OS: _('Waiting OS'),
|
||||
SLOWED_DOWN: _('Too many preparing services'),
|
||||
}
|
||||
|
||||
# States that are merely for "information" to the user. They don't contain any usable instance
|
||||
|
@ -46,7 +46,7 @@ import six
|
||||
import bitarray
|
||||
import logging
|
||||
|
||||
__updated__ = '2016-04-26'
|
||||
__updated__ = '2016-10-31'
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -85,7 +85,11 @@ class CalendarChecker(object):
|
||||
ruleDurationMinutes = rule.duration_as_minutes
|
||||
ruleFrequencyMinutes = rule.frequency_as_minutes
|
||||
|
||||
ruleDurationMinutes = ruleDurationMinutes
|
||||
# Skip "bogus" definitions
|
||||
if ruleDurationMinutes == 0 or ruleFrequencyMinutes == 0:
|
||||
continue
|
||||
|
||||
# ruleDurationMinutes = ruleDurationMinutes
|
||||
# Relative start, rrule can "spawn" the days, so we get the start at least the ruleDurationMinutes of rule to see if it "matches"
|
||||
# This means, we need the previous matching day to be "executed" so we can get the "actives" correctly
|
||||
diff = ruleFrequencyMinutes if ruleFrequencyMinutes > ruleDurationMinutes else ruleDurationMinutes
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
__updated__ = '2016-04-05'
|
||||
__updated__ = '2016-10-31'
|
||||
|
||||
from django.db import models
|
||||
from django.utils.encoding import python_2_unicode_compatible
|
||||
@ -113,6 +113,9 @@ class CalendarRule(UUIDModel):
|
||||
app_label = 'uds'
|
||||
|
||||
def as_rrule(self):
|
||||
if self.interval == 0: # Fix 0 intervals
|
||||
self.interval = 1
|
||||
|
||||
if self.frequency == WEEKDAYS:
|
||||
dw = []
|
||||
l = self.interval
|
||||
|
@ -43,7 +43,7 @@ import six
|
||||
import xmlrpclib
|
||||
from uds.core.util import xml2dict
|
||||
|
||||
__updated__ = '2016-07-26'
|
||||
__updated__ = '2016-11-10'
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -132,7 +132,7 @@ class OpenNebulaClient(object):
|
||||
3.- When the next parameter is >= -1 this is the Range start ID. Can be -1. For smaller values this is the offset used for pagination.
|
||||
4.- For values >= -1 this is the Range end ID. Can be -1 to get until the last ID. For values < -1 this is the page size used for pagination.
|
||||
'''
|
||||
result = self.connection.one.templatepool.info(self.sessionString, -3, -1, -1)
|
||||
result = self.connection.one.templatepool.info(self.sessionString, -1, -1, -1)
|
||||
result = checkResult(result)
|
||||
for ds in asList(result['VMTEMPLATE_POOL']['VMTEMPLATE']):
|
||||
try:
|
||||
@ -149,7 +149,7 @@ class OpenNebulaClient(object):
|
||||
3.- When the next parameter is >= -1 this is the Range start ID. Can be -1. For smaller values this is the offset used for pagination.
|
||||
4.- For values >= -1 this is the Range end ID. Can be -1 to get until the last ID. For values < -1 this is the page size used for pagination.
|
||||
'''
|
||||
result = self.connection.one.imagepool.info(self.sessionString, -3, -1, -1)
|
||||
result = self.connection.one.imagepool.info(self.sessionString, -1, -1, -1)
|
||||
result = checkResult(result)
|
||||
for ds in asList(result['IMAGE_POOL']['IMAGE']):
|
||||
yield(ds['ID'], ds['NAME'])
|
||||
@ -260,7 +260,7 @@ class OpenNebulaClient(object):
|
||||
4.- For values >= -1 this is the Range end ID. Can be -1 to get until the last ID. For values < -1 this is the page size used for pagination.
|
||||
5.- VM state to filter by. (-2 = any state including DONE, -1 = any state EXCEPT DONE)
|
||||
'''
|
||||
result = self.connection.one.vmpool.info(self.sessionString, -3, -1, -1, -1)
|
||||
result = self.connection.one.vmpool.info(self.sessionString, -1, -1, -1, -1)
|
||||
result = checkResult(result)
|
||||
for ds in asList(result['VM_POOL']['VM']):
|
||||
yield(ds['ID'], ds['NAME'])
|
||||
|
@ -209,6 +209,8 @@
|
||||
column.render = renderTextTransform(opts.dict) if opts.dict?
|
||||
when "callback"
|
||||
column.render = renderCallBack(v)
|
||||
when "number"
|
||||
column.render = $.fn.dataTable.render.number(get_format("THOUSAND_SEPARATOR"), get_format("DECIMAL_SEPARATOR"))
|
||||
else
|
||||
column.type = opts.type
|
||||
columns.push column
|
||||
|
@ -30,7 +30,10 @@ else:
|
||||
port = -1
|
||||
|
||||
if {m.secure_port} != -1: # @UndefinedVariable
|
||||
forwardThread2, secure_port = forwardThread1.clone('{m.ip}', {m.secure_port}) # @UndefinedVariable
|
||||
if port != -1:
|
||||
forwardThread2, secure_port = forwardThread1.clone('{m.ip}', {m.secure_port}) # @UndefinedVariable
|
||||
else:
|
||||
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')
|
||||
|
@ -35,7 +35,10 @@ else:
|
||||
port = -1
|
||||
|
||||
if {m.secure_port} != -1: # @UndefinedVariable
|
||||
forwardThread2, secure_port = forwardThread1.clone('{m.ip}', {m.secure_port}) # @UndefinedVariable
|
||||
if port != -1:
|
||||
forwardThread2, secure_port = forwardThread1.clone('{m.ip}', {m.secure_port}) # @UndefinedVariable
|
||||
else:
|
||||
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')
|
||||
|
@ -38,7 +38,11 @@ else:
|
||||
port = -1
|
||||
|
||||
if {m.secure_port} != -1: # @UndefinedVariable
|
||||
forwardThread2, secure_port = forwardThread1.clone('{m.ip}', {m.secure_port}) # @UndefinedVariable
|
||||
if port != -1:
|
||||
forwardThread2, secure_port = forwardThread1.clone('{m.ip}', {m.secure_port}) # @UndefinedVariable
|
||||
else:
|
||||
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')
|
||||
|
@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2012 Virtual Cable S.L.
|
||||
# Copyright (c) 2016 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -33,23 +33,27 @@
|
||||
|
||||
from django.utils.translation import ugettext_noop as _
|
||||
from uds.core.managers.UserPrefsManager import CommonPrefs
|
||||
from uds.core.managers import userServiceManager
|
||||
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
|
||||
|
||||
import logging
|
||||
import paramiko
|
||||
import six
|
||||
import os
|
||||
import logging
|
||||
|
||||
__updated__ = '2016-09-07'
|
||||
__updated__ = '2016-11-07'
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
READY_CACHE_TIMEOUT = 30
|
||||
|
||||
SSH_KEY_LENGTH = 1024
|
||||
|
||||
class BaseX2GOTransport(Transport):
|
||||
'''
|
||||
@ -58,32 +62,98 @@ class BaseX2GOTransport(Transport):
|
||||
'''
|
||||
iconFile = 'x2go.png'
|
||||
protocol = protocols.X2GO
|
||||
supportedOss = OsDetector.Linux
|
||||
supportedOss = (OsDetector.Linux, OsDetector.Windows)
|
||||
|
||||
useEmptyCreds = gui.CheckBoxField(
|
||||
order=1,
|
||||
label=_('Empty credentials'),
|
||||
tooltip=_('If checked, the credentials used to connect will be emtpy'),
|
||||
tab=gui.CREDENTIALS_TAB
|
||||
)
|
||||
fixedName = gui.TextField(
|
||||
order=2,
|
||||
label=_('Username'),
|
||||
tooltip=_('If not empty, this username will be always used as credential'),
|
||||
tab=gui.CREDENTIALS_TAB
|
||||
)
|
||||
fixedPassword = gui.PasswordField(
|
||||
order=3,
|
||||
label=_('Password'),
|
||||
tooltip=_('If not empty, this password will be always used as credential'),
|
||||
tab=gui.CREDENTIALS_TAB
|
||||
)
|
||||
|
||||
fullScreen = gui.CheckBoxField(
|
||||
order=5,
|
||||
order=10,
|
||||
label=_('Show fullscreen'),
|
||||
tooltip=_('If checked, viewer will be shown on fullscreen mode-'),
|
||||
tab=gui.PARAMETERS_TAB
|
||||
)
|
||||
|
||||
desktopType = gui.ChoiceField(label=_('Desktop'), order=11, tooltip=_('Desktop session'),
|
||||
values=[
|
||||
{'id': 'XFCE', 'text': 'Xfce'},
|
||||
{'id': 'MATE', 'text': 'Mate'},
|
||||
{'id': 'LXDE', 'text': 'Lxde'},
|
||||
{'id': 'GNOME', 'text': 'Gnome (see docs)'},
|
||||
{'id': 'KDE', 'text': 'Kde (see docs)'},
|
||||
# {'id': 'UNITY', 'text': 'Unity (see docs)'},
|
||||
{'id': 'gnome-session-cinnamon', 'text': 'Cinnamon 1.4 (see docs)'},
|
||||
{'id': 'gnome-session-cinnamon2d', 'text': 'Cinnamon 2.2 (see docs)'},
|
||||
], tab=gui.PARAMETERS_TAB)
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
speed = gui.ChoiceField(
|
||||
label=_('Speed'),
|
||||
order=14,
|
||||
tooltip=_('Connection speed'),
|
||||
defvalue='3',
|
||||
values=[
|
||||
{'id': '0', 'text': 'MODEM'},
|
||||
{'id': '1', 'text': 'ISDN'},
|
||||
{'id': '2', 'text': 'ADSL'},
|
||||
{'id': '3', 'text': 'WAN'},
|
||||
{'id': '4', 'text': 'LAN'},
|
||||
], 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='16m-jpeg',
|
||||
tab=gui.ADVANCED_TAB
|
||||
)
|
||||
|
||||
quality = gui.NumericField(label=_('Quality'), order=33, tooltip=_('Quality value used on some pack formats.'),
|
||||
length=1, defvalue='6', minValue=1, maxValue=9, required=True,
|
||||
tab=gui.ADVANCED_TAB)
|
||||
|
||||
|
||||
|
||||
def isAvailableFor(self, userService, ip):
|
||||
'''
|
||||
@ -91,7 +161,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, '')
|
||||
@ -103,19 +181,45 @@ class BaseX2GOTransport(Transport):
|
||||
if self.fixedName.value != '':
|
||||
username = self.fixedName.value
|
||||
|
||||
if self.fixedPassword.value != '':
|
||||
password = self.fixedPassword.value
|
||||
if self.useEmptyCreds.isTrue():
|
||||
username, password = '', '', ''
|
||||
|
||||
# Fix username/password acording to os manager
|
||||
username, password = service.processUserPassword(username, password)
|
||||
|
||||
return {'protocol': self.protocol, 'username': username, 'password': password}
|
||||
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):
|
||||
'''
|
||||
Generates a key pair for use with x2go
|
||||
The private part is used by client
|
||||
the public part must be "appended" to authorized_keys if it is not already added.
|
||||
If .ssh folder does not exists, it must be created
|
||||
if authorized_keys does not exists, it must be created
|
||||
On key adition, we can look for every key that has a "UDS@X2GOCLIENT" as comment, so we can remove them before adding new ones
|
||||
|
||||
Windows (tested):
|
||||
C:\Program Files (x86)\\x2goclient>x2goclient.exe --session-conf=c:/temp/sessions --session=UDS/test-session --close-disconnect --hide --no-menu
|
||||
Linux (tested):
|
||||
HOME=[temporal folder, where we create a .x2goclient folder and a sessions inside] pyhoca-cli -P UDS/test-session
|
||||
'''
|
||||
key = paramiko.RSAKey.generate(SSH_KEY_LENGTH)
|
||||
privFile = six.StringIO()
|
||||
key.write_private_key(privFile)
|
||||
priv = privFile.getvalue()
|
||||
|
||||
pub = key.get_base64() # 'ssh-rsa {} UDS@X2GOCLIENT'.format(key.get_base64())
|
||||
return (priv, pub)
|
||||
|
||||
def getAuthorizeScript(self, user, pubKey):
|
||||
return self.getScript('scripts/authorize.py').replace('__USER__', user).replace('__KEY__', pubKey)
|
||||
|
||||
def getAndPushKey(self, user, userService):
|
||||
priv, pub = self.genKeyPairForSsh()
|
||||
authScript = self.getAuthorizeScript(user, pub)
|
||||
userServiceManager().sendScript(userService, authScript)
|
||||
return priv, pub
|
||||
|
||||
def getScript(self, script):
|
||||
with open(os.path.join(os.path.dirname(__file__), script)) as f:
|
||||
data = f.read()
|
||||
|
@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2012 Virtual Cable S.L.
|
||||
# Copyright (c) 2016 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -33,20 +33,20 @@
|
||||
|
||||
from django.utils.translation import ugettext_noop as _
|
||||
from uds.core.ui.UserInterface import gui
|
||||
from uds.core.transports.BaseTransport import Transport
|
||||
from uds.core.transports.BaseTransport import TUNNELED_GROUP
|
||||
from uds.core.transports import protocols
|
||||
from uds.core.managers.UserPrefsManager import CommonPrefs
|
||||
from uds.core.util import OsDetector
|
||||
from uds.core.util import tools
|
||||
from uds.core.transports.BaseTransport import TUNNELED_GROUP
|
||||
from uds.models import TicketStore
|
||||
|
||||
from .BaseX2GOTransport import BaseX2GOTransport
|
||||
from . import x2gofile
|
||||
|
||||
|
||||
import logging
|
||||
import random
|
||||
import string
|
||||
|
||||
__updated__ = '2016-10-14'
|
||||
__updated__ = '2016-11-07'
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -56,19 +56,89 @@ class TX2GOTransport(BaseX2GOTransport):
|
||||
Provides access via SPICE to service.
|
||||
This transport can use an domain. If username processed by authenticator contains '@', it will split it and left-@-part will be username, and right password
|
||||
'''
|
||||
typeName = _('X2Go Transport (tunneled)')
|
||||
typeName = _('X2Go Transport Experimental (tunneled)')
|
||||
typeType = 'TX2GOTransport'
|
||||
typeDescription = _('X2Go Transport for tunneled connection (EXPERIMENTAL)')
|
||||
protocol = protocols.SPICE
|
||||
typeDescription = _('X2Go Transport for tunneled connection (EXPERIMENTAL)')
|
||||
group = TUNNELED_GROUP
|
||||
|
||||
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)'), tab=gui.TUNNEL_TAB)
|
||||
|
||||
fixedName = BaseX2GOTransport.fixedName
|
||||
# fullScreen = BaseX2GOTransport.fullScreen
|
||||
desktopType = BaseX2GOTransport.desktopType
|
||||
sound = BaseX2GOTransport.sound
|
||||
exports = BaseX2GOTransport.exports
|
||||
speed = BaseX2GOTransport.speed
|
||||
|
||||
soundType = BaseX2GOTransport.soundType
|
||||
keyboardLayout = BaseX2GOTransport.keyboardLayout
|
||||
pack = BaseX2GOTransport.pack
|
||||
quality = BaseX2GOTransport.quality
|
||||
|
||||
|
||||
def initialize(self, values):
|
||||
if values is not None:
|
||||
if values['tunnelServer'].count(':') != 1:
|
||||
raise Transport.ValidationException(_('Must use HOST:PORT in Tunnel Server Field'))
|
||||
raise BaseX2GOTransport.ValidationException(_('Must use HOST:PORT in Tunnel Server Field'))
|
||||
|
||||
def getUDSTransportScript(self, userService, transport, ip, os, user, password, request):
|
||||
pass
|
||||
priv, pub = self.getAndPushKey('user', userService)
|
||||
|
||||
prefs = user.prefs('nx')
|
||||
|
||||
ci = self.getConnectionInfo(userService, user, password)
|
||||
username = ci['username']
|
||||
|
||||
width, height = CommonPrefs.getWidthHeight(prefs)
|
||||
|
||||
logger.debug('')
|
||||
|
||||
xf = x2gofile.getTemplate(
|
||||
speed=self.speed.value,
|
||||
pack=self.pack.value,
|
||||
quality=self.quality.value,
|
||||
sound=self.sound.isTrue(),
|
||||
soundSystem=self.sound.value,
|
||||
windowManager=self.desktopType.value,
|
||||
exports=self.exports.isTrue(),
|
||||
width=width,
|
||||
height=height
|
||||
)
|
||||
|
||||
tunpass = ''.join(random.choice(string.letters + string.digits) for _i in range(12))
|
||||
tunuser = TicketStore.create(tunpass)
|
||||
|
||||
sshHost, sshPort = self.tunnelServer.value.split(':')
|
||||
|
||||
# data
|
||||
data = {
|
||||
'os': os['OS'],
|
||||
'ip': ip,
|
||||
'port': 22,
|
||||
'tunUser': tunuser,
|
||||
'tunPass': tunpass,
|
||||
'tunHost': sshHost,
|
||||
'tunPort': sshPort,
|
||||
'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(BaseX2GOTransport, self).getUDSTransportScript(self, userService, transport, ip, os, user, password, request)
|
||||
|
||||
return self.getScript('scripts/{}/tunnel.py'.format(os)).format(m=m)
|
||||
|
@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2012 Virtual Cable S.L.
|
||||
# Copyright (c) 2016 Virtual Cable S.L.
|
||||
# All rights reservem.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -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-09-07'
|
||||
__updated__ = '2016-11-07'
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -48,13 +50,69 @@ class X2GOTransport(BaseX2GOTransport):
|
||||
Provides access via SPICE to service.
|
||||
This transport can use an domain. If username processed by authenticator contains '@', it will split it and left-@-part will be username, and right password
|
||||
'''
|
||||
typeName = _('X2Go Transport (direct)')
|
||||
typeName = _('X2Go Transport Experimental (direct)')
|
||||
typeType = 'X2GOTransport'
|
||||
typeDescription = _('X2Go Transport for direct connection (EXPERIMENTAL)')
|
||||
|
||||
# useEmptyCreds = BaseSpiceTransport.useEmptyCreds
|
||||
# fixedName = BaseSpiceTransport.fixedName
|
||||
# fixedPassword = BaseSpiceTransport.fixedPassword
|
||||
fixedName = BaseX2GOTransport.fixedName
|
||||
# fullScreen = BaseX2GOTransport.fullScreen
|
||||
desktopType = BaseX2GOTransport.desktopType
|
||||
sound = BaseX2GOTransport.sound
|
||||
exports = BaseX2GOTransport.exports
|
||||
speed = BaseX2GOTransport.speed
|
||||
|
||||
soundType = BaseX2GOTransport.soundType
|
||||
keyboardLayout = BaseX2GOTransport.keyboardLayout
|
||||
pack = BaseX2GOTransport.pack
|
||||
quality = BaseX2GOTransport.quality
|
||||
|
||||
def getUDSTransportScript(self, userService, transport, ip, os, user, password, request):
|
||||
pass
|
||||
priv, pub = self.getAndPushKey('user', userService)
|
||||
|
||||
prefs = user.prefs('nx')
|
||||
|
||||
ci = self.getConnectionInfo(userService, user, password)
|
||||
username = ci['username']
|
||||
|
||||
width, height = CommonPrefs.getWidthHeight(prefs)
|
||||
|
||||
xf = x2gofile.getTemplate(
|
||||
speed=self.speed.value,
|
||||
pack=self.pack.value,
|
||||
quality=self.quality.value,
|
||||
sound=self.sound.isTrue(),
|
||||
soundSystem=self.sound.value,
|
||||
windowManager=self.desktopType.value,
|
||||
exports=self.exports.isTrue(),
|
||||
width=width,
|
||||
height=height
|
||||
)
|
||||
|
||||
# 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)
|
||||
|
@ -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])
|
||||
|
60
server/src/uds/transports/X2GO/scripts/authorize.py
Normal file
60
server/src/uds/transports/X2GO/scripts/authorize.py
Normal file
@ -0,0 +1,60 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import sys
|
||||
import os
|
||||
import errno
|
||||
import pwd
|
||||
|
||||
USER = '__USER__'
|
||||
KEY = '__KEY__'
|
||||
|
||||
def logError(err):
|
||||
print(err)
|
||||
|
||||
def updateAuthorizedKeys(user, pubKey):
|
||||
# No X2Go server on windows
|
||||
if 'win' in sys.platform:
|
||||
logError('Not a linux platform')
|
||||
return
|
||||
|
||||
# Create .ssh on user home
|
||||
home = os.path.expanduser('~{}'.format(user))
|
||||
uid = pwd.getpwnam(user)
|
||||
if not os.path.exists(home): # User not found, nothing done
|
||||
logError('Home folder for user {} not found'.format(user))
|
||||
return
|
||||
|
||||
uid = pwd.getpwnam(user).pw_uid
|
||||
|
||||
sshFolder = '{}/.ssh'.format(home)
|
||||
if not os.path.exists(sshFolder):
|
||||
try:
|
||||
os.makedirs(sshFolder, 0700)
|
||||
os.chown(sshFolder, uid, -1)
|
||||
except OSError as e:
|
||||
if e.errno != errno.EEXIST:
|
||||
logError('Error creating .ssh folder for user {}: {}'.format(user, e))
|
||||
return
|
||||
# Folder has been created in between test & creation, thats ok
|
||||
|
||||
authorizedKeys = '{}/authorized_keys'.format(sshFolder)
|
||||
try:
|
||||
with open(authorizedKeys, 'r') as f:
|
||||
lines = f.readlines()
|
||||
except Exception:
|
||||
lines = []
|
||||
|
||||
with open(authorizedKeys, 'w') as f:
|
||||
for line in lines:
|
||||
if 'UDS@X2GOCLIENT' not in line and len(line.strip()) > 0:
|
||||
f.write(line)
|
||||
# Append pubkey
|
||||
f.write('ssh-rsa {} UDS@X2GOCLIENT\n'.format(pubKey))
|
||||
|
||||
# Ensure access is correct
|
||||
os.chown(authorizedKeys, uid, -1)
|
||||
os.chmod(authorizedKeys, 0600)
|
||||
|
||||
# Done
|
||||
|
||||
updateAuthorizedKeys(USER, KEY)
|
@ -3,23 +3,27 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
# pylint: disable=import-error, no-name-in-module
|
||||
from PyQt4 import QtCore, QtGui # @UnresolvedImport
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
from uds import tools # @UnresolvedImport
|
||||
|
||||
executable = tools.findApp('remote-viewer')
|
||||
|
||||
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>
|
||||
''')
|
||||
|
||||
theFile = '''{m.r.as_file}'''
|
||||
import six
|
||||
|
||||
keyFile = tools.saveTempFile('''{m.key}''')
|
||||
theFile = '''{m.xf}'''.format(export='/:1;', keyFile=keyFile.replace('\\', '/'), ip='{m.ip}', port='22')
|
||||
filename = tools.saveTempFile(theFile)
|
||||
|
||||
subprocess.Popen([executable, filename])
|
||||
# HOME=[temporal folder, where we create a .x2goclient folder and a sessions inside] pyhoca-cli -P UDS/test-session
|
||||
|
||||
# QtGui.QMessageBox.critical(parent, 'Notice', filename + ", " + executable, QtGui.QMessageBox.Ok)
|
||||
executable = tools.findApp('x2goclient')
|
||||
if executable is None:
|
||||
raise Exception('''<p>You must have installed latest X2GO Client in order to connect to this UDS service.</p>
|
||||
<p>Please, install the required packages for your platform</p>''')
|
||||
|
||||
subprocess.Popen([executable, '--session-conf={{}}'.format(filename), '--session=UDS/connect', '--close-disconnect', '--hide', '--no-menu', '--add-to-known-hosts'])
|
||||
# tools.addFileToUnlink(filename)
|
||||
# tools.addFileToUnlink(keyFile)
|
||||
|
||||
# QtGui.QMessageBox.critical(parent, 'Notice', executable + ' -- ' + keyFile + ', ' + filename, QtGui.QMessageBox.Ok) # @UndefinedVariable
|
||||
|
@ -2,47 +2,35 @@
|
||||
# Saved as .py for easier editing
|
||||
from __future__ import unicode_literals
|
||||
|
||||
# pylint: disable=import-error, no-name-in-module, undefined-variable
|
||||
import subprocess
|
||||
# pylint: disable=import-error, no-name-in-module, too-many-format-args, undefined-variable
|
||||
|
||||
from uds import tools # @UnresolvedImport
|
||||
from PyQt4 import QtCore, QtGui # @UnresolvedImport
|
||||
import os
|
||||
import subprocess
|
||||
from uds.forward import forward # @UnresolvedImport
|
||||
|
||||
executable = tools.findApp('remote-viewer')
|
||||
from uds import tools # @UnresolvedImport
|
||||
|
||||
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>
|
||||
''')
|
||||
import six
|
||||
|
||||
forwardThread, port = forward('{m.tunHost}', '{m.tunPort}', '{m.tunUser}', '{m.tunPass}', '{m.ip}', 22)
|
||||
|
||||
if {m.port} != -1: # @UndefinedVariable
|
||||
forwardThread1, port = forward('{m.tunHost}', '{m.tunPort}', '{m.tunUser}', '{m.tunPass}', '{m.ip}', {m.port}) # @UndefinedVariable
|
||||
if forwardThread.status == 2:
|
||||
raise Exception('Unable to open tunnel')
|
||||
|
||||
if forwardThread1.status == 2:
|
||||
raise Exception('Unable to open tunnel')
|
||||
else:
|
||||
port = -1
|
||||
|
||||
if {m.secure_port} != -1: # @UndefinedVariable
|
||||
forwardThread2, secure_port = forwardThread1.clone('{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
|
||||
)
|
||||
tools.addTaskToWait(forwardThread)
|
||||
|
||||
keyFile = tools.saveTempFile('''{m.key}''')
|
||||
theFile = '''{m.xf}'''.format(export='/:1;', keyFile=keyFile.replace('\\', '/'), ip='127.0.0.1', port=port)
|
||||
filename = tools.saveTempFile(theFile)
|
||||
|
||||
# HOME=[temporal folder, where we create a .x2goclient folder and a sessions inside] pyhoca-cli -P UDS/test-session
|
||||
|
||||
subprocess.Popen([executable, filename])
|
||||
executable = tools.findApp('x2goclient')
|
||||
if executable is None:
|
||||
raise Exception('''<p>You must have installed latest X2GO Client in order to connect to this UDS service.</p>
|
||||
<p>Please, install the required packages for your platform</p>''')
|
||||
|
||||
subprocess.Popen([executable, '--session-conf={{}}'.format(filename), '--session=UDS/connect', '--close-disconnect', '--hide', '--no-menu', '--add-to-known-hosts'])
|
||||
|
||||
# QtGui.QMessageBox.critical(parent, 'Notice', filename + ", " + executable, QtGui.QMessageBox.Ok)
|
||||
|
30
server/src/uds/transports/X2GO/scripts/windows/direct.py
Normal file
30
server/src/uds/transports/X2GO/scripts/windows/direct.py
Normal file
@ -0,0 +1,30 @@
|
||||
# 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 # @UnresolvedImport
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
from uds import tools # @UnresolvedImport
|
||||
|
||||
import six
|
||||
|
||||
keyFile = tools.saveTempFile('''{m.key}''')
|
||||
theFile = '''{m.xf}'''.format(export='c:\\:1;', keyFile=keyFile.replace('\\', '/'), ip='{m.ip}', port='22')
|
||||
filename = tools.saveTempFile(theFile)
|
||||
|
||||
x2goPath = os.environ['PROGRAMFILES(X86)'] + '\\x2goclient'
|
||||
executable = tools.findApp('x2goclient.exe', [x2goPath])
|
||||
if executable is None:
|
||||
raise Exception('''<p>You must have installed latest X2GO Client in order to connect to this UDS service.</p>
|
||||
<p>You can download it for windows from <a href="http://wiki.x2go.org/doku.php">X2Go Site</a>.</p>''')
|
||||
|
||||
# C:\Program Files (x86)\\x2goclient>x2goclient.exe --session-conf=c:/temp/sessions --session=UDS/test-session --close-disconnect --hide --no-menu
|
||||
|
||||
subprocess.Popen([executable, '--session-conf={{}}'.format(filename), '--session=UDS/connect', '--close-disconnect', '--hide', '--no-menu', '--add-to-known-hosts'])
|
||||
# tools.addFileToUnlink(filename)
|
||||
# tools.addFileToUnlink(keyFile)
|
||||
|
||||
# QtGui.QMessageBox.critical(parent, 'Notice', executable + ' -- ' + keyFile + ', ' + filename, QtGui.QMessageBox.Ok) # @UndefinedVariable
|
35
server/src/uds/transports/X2GO/scripts/windows/tunnel.py
Normal file
35
server/src/uds/transports/X2GO/scripts/windows/tunnel.py
Normal file
@ -0,0 +1,35 @@
|
||||
# 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 # @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}', 22)
|
||||
|
||||
if forwardThread.status == 2:
|
||||
raise Exception('Unable to open tunnel')
|
||||
|
||||
tools.addTaskToWait(forwardThread)
|
||||
|
||||
keyFile = tools.saveTempFile('''{m.key}''')
|
||||
theFile = '''{m.xf}'''.format(export='c:\\:1;', keyFile=keyFile.replace('\\', '/'), ip='127.0.0.1', port=port)
|
||||
filename = tools.saveTempFile(theFile)
|
||||
|
||||
x2goPath = os.environ['PROGRAMFILES(X86)'] + '\\x2goclient'
|
||||
executable = tools.findApp('x2goclient.exe', [x2goPath])
|
||||
if executable is None:
|
||||
raise Exception('''<p>You must have installed latest X2GO Client in default program file folder in order to connect to this UDS service.</p>
|
||||
<p>You can download it for windows from <a href="http://wiki.x2go.org/doku.php">X2Go Site</a>.</p>''')
|
||||
|
||||
subprocess.Popen([executable, '--session-conf={{}}'.format(filename), '--session=UDS/connect', '--close-disconnect', '--hide', '--no-menu', '--add-to-known-hosts'])
|
||||
|
||||
# QtGui.QMessageBox.critical(parent, 'Notice', filename + ", " + executable, QtGui.QMessageBox.Ok)
|
117
server/src/uds/transports/X2GO/x2gofile.py
Normal file
117
server/src/uds/transports/X2GO/x2gofile.py
Normal file
@ -0,0 +1,117 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2016 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
|
||||
template = '''[General]
|
||||
UDS=@ByteArray()
|
||||
|
||||
[20160101100758147]
|
||||
speed={speed}
|
||||
pack={pack}
|
||||
quality={quality}
|
||||
fstunnel=true
|
||||
{export}
|
||||
iconvto=UTF-8
|
||||
iconvfrom=ISO8859-1
|
||||
useiconv=false
|
||||
fullscreen={fullscreen}
|
||||
multidisp=false
|
||||
display=1
|
||||
maxdim=false
|
||||
rdpclient=rdesktop
|
||||
directrdpsettings=
|
||||
width={width}
|
||||
height={height}
|
||||
dpi=96
|
||||
setdpi=true
|
||||
xinerama=false
|
||||
clipboard=both
|
||||
usekbd=true
|
||||
type=auto
|
||||
sound={sound}
|
||||
soundsystem={soundSystem}
|
||||
startsoundsystem=true
|
||||
soundtunnel=true
|
||||
defsndport=true
|
||||
sndport=4713
|
||||
print=true
|
||||
name=UDS/connect
|
||||
icon=:/img/icons/128x128/x2gosession.png
|
||||
host={{ip}}
|
||||
user=user
|
||||
key={{keyFile}}
|
||||
rdpport=3389
|
||||
sshport={{port}}
|
||||
autologin=false
|
||||
krblogin=false
|
||||
krbdelegation=false
|
||||
directrdp=false
|
||||
rootless=false
|
||||
published=false
|
||||
applications=WWWBROWSER, MAILCLIENT, OFFICE, TERMINAL
|
||||
command={windowManager}
|
||||
rdpoptions=
|
||||
rdpserver=
|
||||
xdmcpserver=localhost
|
||||
usesshproxy=false
|
||||
sshproxytype=SSH
|
||||
sshproxyuser=
|
||||
sshproxykeyfile=
|
||||
sshproxyhost=
|
||||
sshproxyport=22
|
||||
sshproxysamepass=false
|
||||
sshproxysameuser=false
|
||||
sshproxyautologin=false
|
||||
sshproxykrblogin=false
|
||||
'''
|
||||
|
||||
def getTemplate(speed, pack, quality, sound, soundSystem, windowManager, exports, width, height):
|
||||
trueFalse = lambda(x): 'true' if x else 'false'
|
||||
export = 'export="{export}"' if exports else ''
|
||||
if width == -1 or height == -1:
|
||||
width = 800
|
||||
height = 600
|
||||
fullscreen = 'true'
|
||||
else:
|
||||
fullscreen = 'false'
|
||||
return template.format(
|
||||
speed=speed,
|
||||
pack=pack,
|
||||
quality=quality,
|
||||
sound=trueFalse(sound),
|
||||
soundSystem=soundSystem,
|
||||
windowManager=windowManager,
|
||||
export=export,
|
||||
width=width,
|
||||
height=height,
|
||||
fullscreen=fullscreen
|
||||
)
|
@ -58,7 +58,7 @@ import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
__updated__ = '2016-08-26'
|
||||
__updated__ = '2016-11-22'
|
||||
|
||||
|
||||
@csrf_exempt
|
||||
@ -186,6 +186,7 @@ def ticketAuth(request, ticketId):
|
||||
webLogin(request, None, usr, password)
|
||||
|
||||
request.user = usr # Temporarily store this user as "authenticated" user, next requests will be done using session
|
||||
request.session['ticket'] = '1' # Store that user access is done using ticket
|
||||
|
||||
logger.debug("Service & transport: {}, {}".format(servicePool, transport))
|
||||
for v in DeployedService.objects.all():
|
||||
|
@ -37,7 +37,7 @@ from django.utils import formats
|
||||
|
||||
from django.template import RequestContext
|
||||
|
||||
from uds.core.auths.auth import webLoginRequired
|
||||
from uds.core.auths.auth import webLoginRequired, webLogout
|
||||
|
||||
from uds.models import DeployedService, Transport, UserService, Network, ServicesPoolGroup
|
||||
from uds.core.util.Config import GlobalConfig
|
||||
@ -51,7 +51,7 @@ import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
__updated__ = '2016-08-26'
|
||||
__updated__ = '2016-11-22'
|
||||
|
||||
|
||||
def about(request):
|
||||
@ -74,6 +74,9 @@ def index(request):
|
||||
Renders the main page.
|
||||
:param request: http request
|
||||
'''
|
||||
if request.session.get('ticket') == '1':
|
||||
return webLogout()
|
||||
|
||||
# Session data
|
||||
os = request.os
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user