1
0
mirror of https://github.com/dkmstr/openuds.git synced 2025-10-07 15:33:51 +03:00

20 Commits
v3.0t ... v2.2

Author SHA1 Message Date
Adolfo Gómez García
1a18ff1d5e Changed "/multimedia" for "/video" 2020-06-17 10:16:48 +02:00
Adolfo Gómez García
56553a70a1 minor fixes for 2.2 version 2020-05-26 21:29:39 +02:00
Adolfo Gómez García
2c10e9445b fixed actor log level 2020-05-15 13:56:02 +02:00
Adolfo Gómez García
4ca387c370 Fixed log level for actor 2020-05-15 12:34:59 +02:00
Adolfo Gómez García
67eb4332b7 fixed logger.info issue 2020-05-13 13:47:12 +02:00
Adolfo Gómez García
a6077a61b4 fixed x2go app closing too early 2020-05-13 13:32:16 +02:00
Adolfo Gómez García
dc42433b86 fixed operations getidle for linux 2020-05-12 14:20:35 +02:00
Adolfo Gómez García
f67730cfad fixed Publication manager error on full persistent services 2020-04-20 10:18:45 +02:00
Adolfo Gómez García
8b8135ea98 Fixed xen SR error 2020-04-16 10:10:59 +02:00
Adolfo Gómez García
07c304cecb small fix on REST (visual) 2020-03-19 13:52:10 +01:00
Adolfo Gómez García
a3dd038e79 Testing clients 2020-03-04 15:24:17 +01:00
Adolfo Gómez García
f3522ae154 Updating udsclient 2020-03-04 15:17:43 +01:00
Adolfo Gómez García
67feb4aefa Fixed operations for getidle 2019-12-04 15:00:10 +01:00
Adolfo Gómez García
5953a67d3a Fixed support for deathkey on UDS 2019-10-14 09:21:27 +02:00
Adolfo Gómez García
c6f3c87b93 Fixed fastlinks for owner. Thanks to Daniel Torregosa for the fix :) 2019-09-11 11:10:01 +02:00
Adolfo Gómez García
eb270d883e Fixed OpenNebula "weird". We were defining "VmState" Module, and after that, redefining by importing common. Removed initial definition 2019-08-16 11:12:41 +02:00
Adolfo Gómez García
5ddd2519b0 fix for OpenNebula 2019-08-01 14:43:17 +02:00
Adolfo Gómez García
e5574fe2ba fix for newer opennebula settiong image to "non persistent" on publication clone 2019-07-25 11:47:46 +02:00
Adolfo Gómez García
4b9b386f14 fixed authorize of x2go for python2/3 compat 2019-07-10 11:30:04 +02:00
Adolfo Gómez García
8a61986dad fixed httpserver for python3 compat 2019-07-09 13:25:50 +02:00
36 changed files with 268 additions and 202 deletions

1
.gitignore vendored
View File

@@ -7,6 +7,7 @@
*_enterprise.*
.settings/
.ipynb_checkpoints
.mypy_cache
# Debian buildings
*.debhelper*

View File

@@ -2,8 +2,7 @@
# Resource object code
#
# Created: Mon Apr 27 22:05:02 2015
# by: The Resource Compiler for PyQt (Qt v4.8.6)
# Created by: The Resource Compiler for PyQt4 (Qt v4.8.7)
#
# WARNING! All changes made in this file will be lost!

View File

@@ -2,8 +2,7 @@
# Form implementation generated from reading ui file 'about-dialog.ui'
#
# Created: Mon Apr 27 22:05:02 2015
# by: PyQt4 UI code generator 4.11.2
# Created by: PyQt4 UI code generator 4.12.1
#
# WARNING! All changes made in this file will be lost!
@@ -34,8 +33,8 @@ class Ui_UDSAboutDialog(object):
UDSAboutDialog.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates))
UDSAboutDialog.setModal(True)
self.vboxlayout = QtGui.QVBoxLayout(UDSAboutDialog)
self.vboxlayout.setSpacing(9)
self.vboxlayout.setMargin(9)
self.vboxlayout.setSpacing(9)
self.vboxlayout.setObjectName(_fromUtf8("vboxlayout"))
self.LogoLabel = QtGui.QLabel(UDSAboutDialog)
self.LogoLabel.setObjectName(_fromUtf8("LogoLabel"))
@@ -55,8 +54,8 @@ class Ui_UDSAboutDialog(object):
self.aboutTab = QtGui.QWidget()
self.aboutTab.setObjectName(_fromUtf8("aboutTab"))
self.vboxlayout1 = QtGui.QVBoxLayout(self.aboutTab)
self.vboxlayout1.setSpacing(6)
self.vboxlayout1.setMargin(9)
self.vboxlayout1.setSpacing(6)
self.vboxlayout1.setObjectName(_fromUtf8("vboxlayout1"))
self.aboutBrowser = QtGui.QTextBrowser(self.aboutTab)
self.aboutBrowser.setOpenExternalLinks(True)
@@ -66,8 +65,8 @@ class Ui_UDSAboutDialog(object):
self.authorsTab = QtGui.QWidget()
self.authorsTab.setObjectName(_fromUtf8("authorsTab"))
self.vboxlayout2 = QtGui.QVBoxLayout(self.authorsTab)
self.vboxlayout2.setSpacing(6)
self.vboxlayout2.setMargin(9)
self.vboxlayout2.setSpacing(6)
self.vboxlayout2.setObjectName(_fromUtf8("vboxlayout2"))
self.authorsBrowser = QtGui.QTextBrowser(self.authorsTab)
self.authorsBrowser.setOpenExternalLinks(True)
@@ -77,8 +76,8 @@ class Ui_UDSAboutDialog(object):
self.licenseTab = QtGui.QWidget()
self.licenseTab.setObjectName(_fromUtf8("licenseTab"))
self.vboxlayout3 = QtGui.QVBoxLayout(self.licenseTab)
self.vboxlayout3.setSpacing(6)
self.vboxlayout3.setMargin(9)
self.vboxlayout3.setSpacing(6)
self.vboxlayout3.setObjectName(_fromUtf8("vboxlayout3"))
self.licenseBrowser = QtGui.QTextBrowser(self.licenseTab)
self.licenseBrowser.setObjectName(_fromUtf8("licenseBrowser"))
@@ -92,7 +91,7 @@ class Ui_UDSAboutDialog(object):
self.vboxlayout.addWidget(self.buttonBox)
self.retranslateUi(UDSAboutDialog)
self.tabWidget.setCurrentIndex(0)
self.tabWidget.setCurrentIndex(2)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("clicked(QAbstractButton*)")), UDSAboutDialog.closeDialog)
QtCore.QMetaObject.connectSlotsByName(UDSAboutDialog)
@@ -106,7 +105,7 @@ class Ui_UDSAboutDialog(object):
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'Verdana\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'Sans Serif\';\"><br /></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'Sans Serif\'; font-weight:600;\">(c) 2014, Virtual Cable S.L.U.</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'Sans Serif\'; font-weight:600;\">(c) 2012-2016, Virtual Cable S.L.U.</span></p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'Sans Serif\'; font-style:italic;\"><br /></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><a href=\"http://www.udsenterprise.com\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt; text-decoration: underline; color:#0000ff;\">http://www.udsenterprise.com</span></a></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><a href=\"http://www.openuds.org\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt; text-decoration: underline; color:#0000ff;\">http://www.openuds.org</span></a></p>\n"
@@ -122,7 +121,7 @@ class Ui_UDSAboutDialog(object):
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'Verdana\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">Copyright (c) 2014 Virtual Cable S.L.</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">Copyright (c) 2012-2016 Virtual Cable S.L.</span></p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"><br /></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">All rights reserved.</span></p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"><br /></p>\n"

View File

@@ -2,8 +2,7 @@
# Form implementation generated from reading ui file 'message-dialog.ui'
#
# Created: Mon Apr 27 22:05:02 2015
# by: PyQt4 UI code generator 4.11.2
# Created by: PyQt4 UI code generator 4.12.1
#
# WARNING! All changes made in this file will be lost!

View File

@@ -121,7 +121,7 @@
<x>20</x>
<y>20</y>
<width>361</width>
<height>131</height>
<height>166</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout">
@@ -205,7 +205,7 @@
<item row="3" column="1">
<widget class="QComboBox" name="logLevelComboBox">
<property name="currentIndex">
<number>1</number>
<number>3</number>
</property>
<property name="frame">
<bool>true</bool>
@@ -220,6 +220,11 @@
<string notr="true">INFO</string>
</property>
</item>
<item>
<property name="text">
<string>WARN</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">ERROR</string>

View File

@@ -2,8 +2,7 @@
# Form implementation generated from reading ui file 'setup-dialog.ui'
#
# Created: Mon Apr 27 22:05:03 2015
# by: PyQt4 UI code generator 4.11.2
# Created by: PyQt4 UI code generator 4.12.1
#
# WARNING! All changes made in this file will be lost!
@@ -63,7 +62,7 @@ class Ui_UdsActorSetupDialog(object):
self.cancelButton.setSizePolicy(sizePolicy)
self.cancelButton.setObjectName(_fromUtf8("cancelButton"))
self.layoutWidget = QtGui.QWidget(UdsActorSetupDialog)
self.layoutWidget.setGeometry(QtCore.QRect(20, 20, 361, 131))
self.layoutWidget.setGeometry(QtCore.QRect(20, 20, 361, 166))
self.layoutWidget.setObjectName(_fromUtf8("layoutWidget"))
self.formLayout = QtGui.QFormLayout(self.layoutWidget)
self.formLayout.setFieldGrowthPolicy(QtGui.QFormLayout.AllNonFixedFieldsGrow)
@@ -102,13 +101,14 @@ class Ui_UdsActorSetupDialog(object):
self.logLevelComboBox.addItem(_fromUtf8(""))
self.logLevelComboBox.setItemText(1, _fromUtf8("INFO"))
self.logLevelComboBox.addItem(_fromUtf8(""))
self.logLevelComboBox.setItemText(2, _fromUtf8("ERROR"))
self.logLevelComboBox.addItem(_fromUtf8(""))
self.logLevelComboBox.setItemText(3, _fromUtf8("FATAL"))
self.logLevelComboBox.setItemText(3, _fromUtf8("ERROR"))
self.logLevelComboBox.addItem(_fromUtf8(""))
self.logLevelComboBox.setItemText(4, _fromUtf8("FATAL"))
self.formLayout.setWidget(3, QtGui.QFormLayout.FieldRole, self.logLevelComboBox)
self.retranslateUi(UdsActorSetupDialog)
self.logLevelComboBox.setCurrentIndex(1)
self.logLevelComboBox.setCurrentIndex(3)
QtCore.QObject.connect(self.host, QtCore.SIGNAL(_fromUtf8("textChanged(QString)")), UdsActorSetupDialog.textChanged)
QtCore.QObject.connect(self.masterKey, QtCore.SIGNAL(_fromUtf8("textChanged(QString)")), UdsActorSetupDialog.textChanged)
QtCore.QObject.connect(self.cancelButton, QtCore.SIGNAL(_fromUtf8("pressed()")), UdsActorSetupDialog.cancelAndDiscard)
@@ -139,6 +139,7 @@ class Ui_UdsActorSetupDialog(object):
self.useSSl.setItemText(0, _translate("UdsActorSetupDialog", "Do not use SSL", None))
self.useSSl.setItemText(1, _translate("UdsActorSetupDialog", "Use SSL", None))
self.logLevelLabel.setText(_translate("UdsActorSetupDialog", "Log Level", None))
self.logLevelComboBox.setItemText(2, _translate("UdsActorSetupDialog", "WARN", None))
if __name__ == "__main__":

View File

@@ -116,8 +116,8 @@ class HTTPServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
try:
HTTPServerHandler.lock.acquire()
length = int(self.headers.getheader('content-length'))
content = self.rfile.read(length)
length = int(self.headers.get('content-length'))
content = self.rfile.read(length).decode('utf8')
logger.debug('length: {}, content >>{}<<'.format(length, content))
params = json.loads(content)
@@ -181,7 +181,7 @@ class HTTPServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
logger.error('HTTP ' + fmt % args)
def log_message(self, fmt, *args):
logger.info('HTTP ' + fmt % args)
logger.debug('HTTP ' + fmt % args)
class HTTPServerThread(threading.Thread):

View File

@@ -132,7 +132,7 @@ class ClientProcessor(threading.Thread):
if b == b'':
# Client disconnected
self.running = False
self.processRequest(REQ_LOGOUT, 'CLIENT_CONNECTION_LOST')
# self.processRequest(REQ_LOGOUT, 'CLIENT_CONNECTION_LOST')
break
buf = six.byte2int(b) # Empty buffer, this is set as non-blocking
if state is None:

View File

@@ -232,7 +232,7 @@ def getIdleDuration():
xss.XScreenSaverQueryInfo(display, xlib.XDefaultRootWindow(display), info)
# Centos seems to set state to 1?? (weird, but it's happening don't know why... will try this way)
if info.contents.state != 0 and 'centos' not in platform.linux_distribution()[0].lower().strip():
if info.contents.state == 1:
return 3600 * 100 * 1000 # If screen saver is active, return a high enough value
return info.contents.idle / 1000.0

View File

@@ -219,7 +219,7 @@ class UDSActorSvc(win32serviceutil.ServiceFramework, CommonService):
logger.info('PRECONNECT file not found & not executed')
except Exception as e:
# Ignore output of execution command
logger.error('Executing preconnect command give')
logger.error('Executing preconnect command give {}'.format(e))
return 'ok'

View File

@@ -215,8 +215,9 @@ def getIdleDuration():
return 0
# if lastInputInfo.dwTime > 1000000000: # Value toooo high, nonsense...
# return 0
millis = ctypes.windll.kernel32.GetTickCount() - lastInputInfo.dwTime # @UndefinedVariable
if millis < 0 or millis > 1000000000:
current = ctypes.c_uint(ctypes.windll.kernel32.GetTickCount())
millis = current.value - lastInputInfo.dwTime # @UndefinedVariable
if millis < 0:
return 0
return millis / 1000.0
except Exception as e:

View File

@@ -162,6 +162,7 @@ class UDSClient(QtGui.QMainWindow):
QtCore.QTimer.singleShot(1000, self.getVersion)
except Exception as e:
logger.exception('Version')
self.showError(e)
@@ -210,7 +211,7 @@ class UDSClient(QtGui.QMainWindow):
# if QtGui.QMessageBox.warning(None, 'ACCESS Warning', errorString, QtGui.QMessageBox.Yes | QtGui.QMessageBox.No) == QtGui.QMessageBox.No:
# raise Exception('Server not approved. Access denied.')
logger.debug('Script: {}'.format(script))
six.exec_(script, globals(), {'parent': self, 'sp': params})
except RetryException as e:
@@ -219,7 +220,7 @@ class UDSClient(QtGui.QMainWindow):
QtCore.QTimer.singleShot(10000, self.getTransportData)
except Exception as e:
#logger.exception('Got exception executing script:')
logger.exception('Got exception executing script:')
self.showError(e)
def endScript(self):

View File

@@ -46,7 +46,7 @@ logging.basicConfig(
filename=logFile,
filemode='a',
format='%(levelname)s %(asctime)s %(message)s',
level=logging.INFO
level=logging.DEBUG
)
logger = logging.getLogger('udsclient')

View File

@@ -81,14 +81,14 @@
<dependency>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-common</artifactId>
<version>0.9.14</version>
<version>1.0.0</version>
</dependency>
<!-- Guacamole JavaScript library -->
<dependency>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-common-js</artifactId>
<version>0.9.14</version>
<version>1.0.0</version>
<type>zip</type>
<scope>runtime</scope>
</dependency>

View File

@@ -263,7 +263,7 @@ GuacUI.Client = {
"min_zoom" : 1,
"max_zoom" : 3,
"connectionName" : "Guacamole",
"connectionName" : "UDS Remote Connection",
"attachedClient" : null,
/* Mouse emulation */
@@ -1433,7 +1433,11 @@ GuacUI.Client.attach = function(guac) {
* Route document-level keyboard events to the client.
*/
var sink = new Guacamole.InputSink();
document.body.appendChild(sink.getElement());
var keyboard = new Guacamole.Keyboard(document);
keyboard.listenTo(sink.getElement());
var show_keyboard_gesture_possible = true;
function __send_key(pressed, keysym) {

View File

@@ -78,7 +78,7 @@ class Dispatcher(View):
content_type = None
cls = None
while len(path) > 0:
while path:
# .json, .xml, ... will break path recursion
if path[0].find('.') != -1:
content_type = path[0].split('.')[1]
@@ -92,7 +92,7 @@ class Dispatcher(View):
break
full_path = '/'.join(full_path)
logger.debug("REST request: {} ({})".format(full_path, content_type))
logger.debug('REST request: %s (%s)', full_path, content_type)
# Here, service points to the path
cls = service['']

View File

@@ -92,6 +92,10 @@ class ServicesPools(ModelHandler):
custom_methods = [('setFallbackAccess', True), ('actionsList', True)]
def getItems(self, *args, **kwargs):
return super(ServicesPools, self).getItems(overview=kwargs.get('overview', True), prefetch=['service', 'service__provider', 'servicesPoolGroup', 'image', 'tags'])
# return super(ServicesPools, self).getItems(overview)
def item_as_dict(self, item):
summary = 'summarize' in self._params
# if item does not have an associated service, hide it (the case, for example, for a removed service)
@@ -162,106 +166,106 @@ class ServicesPools(ModelHandler):
g = self.addDefaultFields([], ['name', 'short_name', 'comments', 'tags'])
for f in [{
'name': 'service_id',
'values': [gui.choiceItem(-1, '')] + gui.sortedChoices([gui.choiceItem(v.uuid, v.provider.name + '\\' + v.name) for v in Service.objects.all()]),
'label': ugettext('Base service'),
'tooltip': ugettext('Service used as base of this service pool'),
'type': gui.InputField.CHOICE_TYPE,
'rdonly': True,
'order': 100, # Ensueres is At end
}, {
'name': 'osmanager_id',
'values': [gui.choiceItem(-1, '')] + gui.sortedChoices([gui.choiceItem(v.uuid, v.name) for v in OSManager.objects.all()]),
'label': ugettext('OS Manager'),
'tooltip': ugettext('OS Manager used as base of this service pool'),
'type': gui.InputField.CHOICE_TYPE,
'rdonly': True,
'order': 101,
}, {
'name': 'show_transports',
'value': True,
'label': ugettext('Show transports'),
'tooltip': ugettext('If active, alternative transports for user will be shown'),
'type': gui.InputField.CHECKBOX_TYPE,
'order': 110,
'tab': ugettext('Advanced'),
}, {
'name': 'allow_users_remove',
'value': False,
'label': ugettext('Allow removal by users'),
'tooltip': ugettext('If active, the user will be allowed to remove the service "manually". Be careful with this, because the user will have the "power" to delete it\'s own service'),
'type': gui.InputField.CHECKBOX_TYPE,
'order': 111,
'tab': ugettext('Advanced'),
}, {
'name': 'allow_users_reset',
'value': False,
'label': ugettext('Allow reset by users'),
'tooltip': ugettext('If active, the user will be allowed to reset the service'),
'type': gui.InputField.CHECKBOX_TYPE,
'order': 112,
'tab': ugettext('Advanced'),
}, {
'name': 'ignores_unused',
'value': False,
'label': ugettext('Ignores unused'),
'tooltip': ugettext('If the option is enabled, UDS will not attempt to detect and remove the user services assigned but not in use.'),
'type': gui.InputField.CHECKBOX_TYPE,
'order': 113,
'tab': ugettext('Advanced'),
}, {
'name': 'image_id',
'values': [gui.choiceImage(-1, '--------', DEFAULT_THUMB_BASE64)] + gui.sortedChoices([gui.choiceImage(v.uuid, v.name, v.thumb64) for v in Image.objects.all()]),
'label': ugettext('Associated Image'),
'tooltip': ugettext('Image assocciated with this service'),
'type': gui.InputField.IMAGECHOICE_TYPE,
'order': 120,
'tab': ugettext('Display'),
}, {
'name': 'servicesPoolGroup_id',
'values': [gui.choiceImage(-1, _('Default'), DEFAULT_THUMB_BASE64)] + gui.sortedChoices([gui.choiceImage(v.uuid, v.name, v.thumb64) for v in ServicesPoolGroup.objects.all()]),
'label': ugettext('Pool group'),
'tooltip': ugettext('Pool group for this pool (for pool classify on display)'),
'type': gui.InputField.IMAGECHOICE_TYPE,
'order': 121,
'tab': ugettext('Display'),
}, {
'name': 'initial_srvs',
'value': '0',
'minValue': '0',
'label': ugettext('Initial available services'),
'tooltip': ugettext('Services created initially for this service pool'),
'type': gui.InputField.NUMERIC_TYPE,
'order': 130,
'tab': ugettext('Availability'),
}, {
'name': 'cache_l1_srvs',
'value': '0',
'minValue': '0',
'label': ugettext('Services to keep in cache'),
'tooltip': ugettext('Services kept in cache for improved user service assignation'),
'type': gui.InputField.NUMERIC_TYPE,
'order': 131,
'tab': ugettext('Availability'),
}, {
'name': 'cache_l2_srvs',
'value': '0',
'minValue': '0',
'label': ugettext('Services to keep in L2 cache'),
'tooltip': ugettext('Services kept in cache of level2 for improved service generation'),
'type': gui.InputField.NUMERIC_TYPE,
'order': 132,
'tab': ugettext('Availability'),
}, {
'name': 'max_srvs',
'value': '0',
'minValue': '1',
'label': ugettext('Maximum number of services to provide'),
'tooltip': ugettext('Maximum number of service (assigned and L1 cache) that can be created for this service'),
'type': gui.InputField.NUMERIC_TYPE,
'order': 133,
'tab': ugettext('Availability'),
}]:
'name': 'service_id',
'values': [gui.choiceItem(-1, '')] + gui.sortedChoices([gui.choiceItem(v.uuid, v.provider.name + '\\' + v.name) for v in Service.objects.all()]),
'label': ugettext('Base service'),
'tooltip': ugettext('Service used as base of this service pool'),
'type': gui.InputField.CHOICE_TYPE,
'rdonly': True,
'order': 100, # Ensueres is At end
}, {
'name': 'osmanager_id',
'values': [gui.choiceItem(-1, '')] + gui.sortedChoices([gui.choiceItem(v.uuid, v.name) for v in OSManager.objects.all()]),
'label': ugettext('OS Manager'),
'tooltip': ugettext('OS Manager used as base of this service pool'),
'type': gui.InputField.CHOICE_TYPE,
'rdonly': True,
'order': 101,
}, {
'name': 'show_transports',
'value': True,
'label': ugettext('Show transports'),
'tooltip': ugettext('If active, alternative transports for user will be shown'),
'type': gui.InputField.CHECKBOX_TYPE,
'order': 110,
'tab': ugettext('Advanced'),
}, {
'name': 'allow_users_remove',
'value': False,
'label': ugettext('Allow removal by users'),
'tooltip': ugettext('If active, the user will be allowed to remove the service "manually". Be careful with this, because the user will have the "power" to delete it\'s own service'),
'type': gui.InputField.CHECKBOX_TYPE,
'order': 111,
'tab': ugettext('Advanced'),
}, {
'name': 'allow_users_reset',
'value': False,
'label': ugettext('Allow reset by users'),
'tooltip': ugettext('If active, the user will be allowed to reset the service'),
'type': gui.InputField.CHECKBOX_TYPE,
'order': 112,
'tab': ugettext('Advanced'),
}, {
'name': 'ignores_unused',
'value': False,
'label': ugettext('Ignores unused'),
'tooltip': ugettext('If the option is enabled, UDS will not attempt to detect and remove the user services assigned but not in use.'),
'type': gui.InputField.CHECKBOX_TYPE,
'order': 113,
'tab': ugettext('Advanced'),
}, {
'name': 'image_id',
'values': [gui.choiceImage(-1, '--------', DEFAULT_THUMB_BASE64)] + gui.sortedChoices([gui.choiceImage(v.uuid, v.name, v.thumb64) for v in Image.objects.all()]),
'label': ugettext('Associated Image'),
'tooltip': ugettext('Image assocciated with this service'),
'type': gui.InputField.IMAGECHOICE_TYPE,
'order': 120,
'tab': ugettext('Display'),
}, {
'name': 'servicesPoolGroup_id',
'values': [gui.choiceImage(-1, _('Default'), DEFAULT_THUMB_BASE64)] + gui.sortedChoices([gui.choiceImage(v.uuid, v.name, v.thumb64) for v in ServicesPoolGroup.objects.all()]),
'label': ugettext('Pool group'),
'tooltip': ugettext('Pool group for this pool (for pool classify on display)'),
'type': gui.InputField.IMAGECHOICE_TYPE,
'order': 121,
'tab': ugettext('Display'),
}, {
'name': 'initial_srvs',
'value': '0',
'minValue': '0',
'label': ugettext('Initial available services'),
'tooltip': ugettext('Services created initially for this service pool'),
'type': gui.InputField.NUMERIC_TYPE,
'order': 130,
'tab': ugettext('Availability'),
}, {
'name': 'cache_l1_srvs',
'value': '0',
'minValue': '0',
'label': ugettext('Services to keep in cache'),
'tooltip': ugettext('Services kept in cache for improved user service assignation'),
'type': gui.InputField.NUMERIC_TYPE,
'order': 131,
'tab': ugettext('Availability'),
}, {
'name': 'cache_l2_srvs',
'value': '0',
'minValue': '0',
'label': ugettext('Services to keep in L2 cache'),
'tooltip': ugettext('Services kept in cache of level2 for improved service generation'),
'type': gui.InputField.NUMERIC_TYPE,
'order': 132,
'tab': ugettext('Availability'),
}, {
'name': 'max_srvs',
'value': '0',
'minValue': '1',
'label': ugettext('Maximum number of services to provide'),
'tooltip': ugettext('Maximum number of service (assigned and L1 cache) that can be created for this service'),
'type': gui.InputField.NUMERIC_TYPE,
'order': 133,
'tab': ugettext('Availability'),
}]:
self.addField(g, f)
return g

View File

@@ -732,8 +732,28 @@ class ModelHandler(BaseModelHandler):
return method()
def getItems(self, overview=True, *args, **kwargs):
for item in self.model.objects.filter(*args, **kwargs):
def getItems(self, *args, **kwargs):
if 'overview' in kwargs:
overview = kwargs['overview']
del kwargs['overview']
else:
overview = False
if 'prefetch' in kwargs:
prefetch = kwargs['prefetch']
logger.debug('Prefetching %s', prefetch)
del kwargs['prefetch']
else:
prefetch = []
if 'query' in kwargs:
query = kwargs['query']
del kwargs['query']
else:
logger.debug('Args: %s, kwargs: %s', args, kwargs)
query = self.model.objects.filter(*args, **kwargs).prefetch_related(*prefetch)
for item in query:
try:
if permissions.checkPermissions(self._user, item, permissions.PERMISSION_READ) is False:
continue

View File

@@ -140,9 +140,9 @@ class PublicationFinishChecker(DelayedTask):
if doPublicationCleanup:
pc = PublicationOldMachinesCleaner(old.id)
pc.register(GlobalConfig.SESSION_EXPIRE_TIME.getInt(True) * 3600, 'pclean-' + str(old.id), True)
servicePoolPub.deployed_service.markOldUserServicesAsRemovables(servicePoolPub)
servicePoolPub.setState(State.USABLE)
servicePoolPub.deployed_service.markOldUserServicesAsRemovables(servicePoolPub)
elif State.isRemoving(prevState):
servicePoolPub.setState(State.REMOVED)
else: # State is canceling

View File

@@ -72,9 +72,9 @@ class StateUpdater(object):
def run(self, state):
executor = {
State.RUNNING: self.running,
State.ERROR: self.error,
State.FINISHED: self.finish
State.RUNNING: self.running,
State.ERROR: self.error,
State.FINISHED: self.finish
}.get(state, self.error)
logger.debug('Running updater with state {} and executor {}'.format(State.toString(state), executor))

View File

@@ -115,7 +115,8 @@ class CalendarAction(UUIDModel):
self.service_pool.save()
def save(self, *args, **kwargs):
self.next_execution = calendar.CalendarChecker(self.calendar).nextEvent(checkFrom=self.last_execution, startEvent=self.at_start, offset=self.offset)
lastExecution = self.last_execution or getSqlDatetime()
self.next_execution = calendar.CalendarChecker(self.calendar).nextEvent(checkFrom=lastExecution-self.offset, startEvent=self.at_start) + self.offset
return UUIDModel.save(self, *args, **kwargs)

View File

@@ -107,12 +107,15 @@ class WinDomainOsManager(WindowsOsManager):
_str = ''
try:
uri = "%s://%s:%d" % ('ldap', server[0], server[1])
uri = "%s://%s" % ('ldaps', server[0])
logger.debug('URI: {0}'.format(uri))
ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER) # Disable certificate check
l = ldap.initialize(uri=uri)
l.set_option(ldap.OPT_REFERRALS, 0)
# l.set_option(ldap.OPT_PROTOCOL_VERSION, 3)
# l.set_option(ldap.OPT_X_TLS,ldap.OPT_X_TLS_DEMAND)
# l.set_option( ldap.OPT_X_TLS_DEMAND, True )
l.network_timeout = l.timeout = 5
l.protocol_version = ldap.VERSION3

View File

@@ -150,6 +150,7 @@ class UsageByPool(StatsReport):
total = i.stamp - stamp
data.append({
'name': i.fld4,
'origin': i.fld2.split(':')[0], # Gets also origin
'date': datetime.datetime.fromtimestamp(stamp),
'time': total
})
@@ -186,9 +187,9 @@ class UsageByPoolCSV(UsageByPool):
reportData, poolName = self.getData()
writer.writerow([ugettext('Date'), ugettext('User'), ugettext('Seconds')])
writer.writerow([ugettext('Date'), ugettext('User'), ugettext('Seconds'), ugettext('Origin')])
for v in reportData:
writer.writerow([v['date'], v['name'], v['time']])
writer.writerow([v['date'], v['name'], v['time'], v['origin']])
return output.getvalue()

View File

@@ -49,12 +49,8 @@ logger = logging.getLogger(__name__)
module = sys.modules[__name__]
VmState = imp.new_module('VmState')
ImageState = imp.new_module('ImageState')
for i in enumerate(['INIT', 'PENDING', 'HOLD', 'ACTIVE', 'STOPPED', 'SUSPENDED', 'DONE', 'FAILED', 'POWEROFF', 'UNDEPLOYED']):
setattr(VmState, i[1], i[0])
for i in enumerate(['INIT', 'READY', 'USED', 'DISABLED', 'LOCKED', 'ERROR', 'CLONE', 'DELETE', 'USED_PERS', 'LOCKED_USED', 'LOCKED_USED_PERS']):
setattr(ImageState, i[1], i[0])

View File

@@ -101,12 +101,12 @@ def create(api, fromTemplateId, name, toDataStore):
# if api.imageInfo(imgId)[0]['IMAGE']['STATE'] != '1':
# raise Exception('The base machines images are not in READY state')
# Ensure base Image persistence is set to "False"
# api.makePersistentImage(imgId, False)
# Now clone the image
imgName = sanitizeName(name + ' DSK ' + six.text_type(counter))
newId = api.cloneImage(imgId, imgName, toDataStore) # api.call('image.clone', int(imgId), imgName, int(toDataStore))
# Ensure image is non persistent
api.makePersistentImage(newId, False)
# Now Store id/name
if fromId is True:
node.data = six.text_type(newId)
@@ -207,12 +207,15 @@ def checkPublished(api, templateId):
logger.debug('Found {} for checking'.format(imgId))
state = api.imageInfo(imgId)[0]['IMAGE']['STATE']
if state in ('0', '4'):
if state in ('0', '4', '6'):
return False
elif state != '1': # If error is not READY
raise Exception('Error publishing. Image is in an invalid state. (Check it and delete it if not needed anymore)')
# Ensure image is non persistent, do not ask first because this is a simple request and normally templates has only 1 image.
api.makePersistentImage(imgId, False)
except Exception:
logger.exception('Exception checking published')
raise
return True

View File

@@ -97,20 +97,20 @@ class LiveService(Service):
servicesTypeProvided = (serviceTypes.VDI,)
# Now the form part
region = gui.ChoiceField(label=_('Region'), order=1, tooltip=_('Service region'), required=True, rdonly=True)
project = gui.ChoiceField(label=_('Project'), order=2,
fills={
'callbackName' : 'osFillResources',
'function' : helpers.getResources,
'parameters' : ['ov', 'ev', 'project', 'region', 'legacy']
},
tooltip=_('Project for this service'), required=True, rdonly=True
)
#region = gui.ChoiceField(label=_('Region'), order=1, tooltip=_('Service region'), required=True, rdonly=True)
#project = gui.ChoiceField(label=_('Project'), order=2,
# fills={
# 'callbackName' : 'osFillResources',
# 'function' : helpers.getResources,
# 'parameters' : ['ov', 'ev', 'project', 'region', 'legacy']
# },
# tooltip=_('Project for this service'), required=True, rdonly=True
#)
availabilityZone = gui.ChoiceField(label=_('Availability Zones'), order=3,
fills={
'callbackName' : 'osFillVolumees',
'function' : helpers.getVolumes,
'parameters' : ['ov', 'ev', 'project', 'region', 'availabilityZone', 'legacy']
'parameters' : ['ov', 'ev', 'availabilityZone', 'legacy']
},
tooltip=_('Service availability zones'), required=True, rdonly=True
)
@@ -168,11 +168,17 @@ class LiveService(Service):
Loads required values inside
'''
api = self.parent().api()
regions = [gui.choiceItem(r['id'], r['id']) for r in api.listRegions()]
self.region.setValues(regions)
#regions = [gui.choiceItem(r['id'], r['id']) for r in api.listRegions()]
#self.region.setValues(regions)
tenants = [gui.choiceItem(t['id'], t['name']) for t in api.listProjects()]
self.project.setValues(tenants)
#tenants = [gui.choiceItem(t['id'], t['name']) for t in api.listProjects()]
#self.project.setValues(tenants)
self.availabilityZone.setValues([gui.choiceItem(z, z) for z in api.listAvailabilityZones()])
self.network.setValues([gui.choiceItem(z['id'], z['name']) for z in api.listNetworks()])
self.flavor.setValues([gui.choiceItem(z['id'], z['name']) for z in api.listFlavors()])
self.securityGroups.setValues([gui.choiceItem(z['id'], z['name']) for z in api.listSecurityGroups()])
# volumeTypes = [gui.choiceItem('-', _('None'))] + [gui.choiceItem(t['id'], t['name']) for t in api.listVolumeTypes()]
# So we can instantiate parent to get API
logger.debug(self.parent().serialize())
@@ -184,7 +190,7 @@ class LiveService(Service):
@property
def api(self):
if self._api is None:
self._api = self.parent().api(projectId=self.project.value, region=self.region.value)
self._api = self.parent().api()
return self._api

View File

@@ -109,8 +109,8 @@ class Provider(ServiceProvider):
timeout = gui.NumericField(length=3, label=_('Timeout'), defvalue='10', minValue=1, maxValue=128, order=99, tooltip=_('Timeout in seconds of connection to OpenStack'), required=True, tab=gui.ADVANCED_TAB)
# tenant = gui.TextField(length=64, label=_('Project'), order=6, tooltip=_('Project (tenant) for this provider'), required=True, defvalue='')
# region = gui.TextField(length=64, label=_('Region'), order=7, tooltip=_('Region for this provider'), required=True, defvalue='RegionOne')
tenant = gui.TextField(length=64, label=_('Project'), order=6, tooltip=_('Project (tenant) for this provider'), required=True, defvalue='')
region = gui.TextField(length=64, label=_('Region'), order=7, tooltip=_('Region for this provider'), required=True, defvalue='eu-de')
legacy = False
@@ -127,6 +127,8 @@ class Provider(ServiceProvider):
self.timeout.value = validators.validateTimeout(self.timeout.value, returnAsInteger=False)
def api(self, projectId=None, region=None):
projectId = projectId or self.tenant.value
region = region or self.region.value
return openStack.Client(self.endpoint.value, -1,
self.domain.value, self.username.value, self.password.value,
legacyVersion=False,

View File

@@ -30,7 +30,7 @@ def getResources(parameters):
provider = Provider(env)
provider.unserialize(parameters['ov'])
api = provider.api(parameters['project'], parameters['region'])
api = provider.api()
zones = [gui.choiceItem(z, z) for z in api.listAvailabilityZones()]
networks = [gui.choiceItem(z['id'], z['name']) for z in api.listNetworks()]
@@ -63,7 +63,7 @@ def getVolumes(parameters):
provider = Provider(env)
provider.unserialize(parameters['ov'])
api = provider.api(parameters['project'], parameters['region'])
api = provider.api()
volumes = [gui.choiceItem(v['id'], v['name']) for v in api.listVolumes() if v['name'] != '' and v['availability_zone'] == parameters['availabilityZone']]

View File

@@ -73,6 +73,7 @@ def getRecurringUrlJson(url, headers, key, params=None, errMsg=None, timeout=10)
counter += 1
logger.debug('Requesting url #{}: {} / {}'.format(counter, url, params))
r = requests.get(url, params=params, headers=headers, verify=VERIFY_SSL, timeout=timeout)
logger.debug('Response: %s', r.content)
ensureResponseIsValid(r, errMsg)
@@ -212,6 +213,8 @@ class Client(object):
if self._projectId is not None:
self._catalog = token['catalog']
# logger.debug(self._catalog)
def ensureAuthenticated(self):
if self._authenticated is False or self._projectId != self._authenticatedProjectId:
self.authPassword()
@@ -474,13 +477,20 @@ class Client(object):
@authProjectRequired
def deleteServer(self, serverId):
r = requests.post(self._getEndpointFor('compute') + '/servers/{server_id}/action'.format(server_id=serverId),
data='{"forceDelete": null}',
headers=self._requestHeaders(),
verify=VERIFY_SSL,
timeout=self._timeout)
r = requests.delete(
self._getEndpointFor('compute') + '/servers/{server_id}'.format(server_id=serverId),
headers=self._requestHeaders(),
verify=VERIFY_SSL,
timeout=self._timeout
)
ensureResponseIsValid(r, 'Cannot start server (probably server does not exists).')
# r = requests.post(self._getEndpointFor('compute') + '/servers/{server_id}/action'.format(server_id=serverId),
# data='{"forceDelete": null}',
# headers=self._requestHeaders(),
# verify=VERIFY_SSL,
# timeout=self._timeout)
ensureResponseIsValid(r, 'Cannot delete server (probably server does not exists).')
# This does not returns anything
@@ -570,7 +580,7 @@ class Client(object):
logger.exception('Authenticating')
raise Exception(_('Authentication error'))
except Exception: # Not json
# logger.exception('xx')
logger.exception('xx')
raise Exception('Invalid endpoint (maybe invalid version selected?)')
raise Exception(_('Openstack does not support identity API 3.2 or newer. This OpenStack server is not compatible with UDS.'))

View File

@@ -252,15 +252,13 @@ class XenServer(object):
if v not in allowed_ops:
valid = False
if not valid:
return
yield {
'id': srId,
'name': name_label,
'size': XenServer.toMb(self.SR.get_physical_size(srId)),
'used': XenServer.toMb(self.SR.get_physical_utilisation(srId))
}
if valid:
yield {
'id': srId,
'name': name_label,
'size': XenServer.toMb(self.SR.get_physical_size(srId)),
'used': XenServer.toMb(self.SR.get_physical_utilisation(srId))
}
def getSRInfo(self, srId):
return {

View File

@@ -226,7 +226,7 @@ gui.providers.link = (event) ->
onData: (data) ->
$.each data, (index, value) ->
value.owner = gui.fastLink(value.owner.replace /@/, '<span class="text-danger">@</span>', "#{value.owner_info.auth_id},u#{value.owner_info.user_id}", 'gui.providers.fastLink', 'goAuthLink')
value.owner = gui.fastLink(value.owner.replace(/@/, '<span class="text-danger">@</span>'), "#{value.owner_info.auth_id},u#{value.owner_info.user_id}", 'gui.providers.fastLink', 'goAuthLink')
value.pool = gui.fastLink(value.pool, value.pool_id, 'gui.providers.fastLink', 'goPoolLink')
buttons: [

View File

@@ -417,8 +417,7 @@ gui.servicesPools.link = (event) ->
value.in_use = gettext('Yes')
else
value.in_use = gettext('No')
value.owner = gui.fastLink(value.owner.replace /@/, '<span class="text-danger">@</span>', "#{value.owner_info.auth_id},u#{value.owner_info.user_id}", 'gui.servicesPools.fastLink', 'goAuthLink')
value.owner = gui.fastLink(value.owner.replace(/@/, '<span class="text-danger">@</span>'), "#{value.owner_info.auth_id},u#{value.owner_info.user_id}", 'gui.servicesPools.fastLink', 'goAuthLink')
return
onRefresh: () ->

View File

@@ -111,13 +111,11 @@ class RDPFile(object):
if self.alsa:
params.append('/sound:sys:alsa,format:1,quality:high')
params.append('/microphone:sys:alsa')
if self.multimedia:
params.append('/multimedia:sys:alsa')
else:
params.append('/sound')
params.append('/microphone')
if self.multimedia:
params.append('/multimedia')
if self.multimedia:
params.append('/video')
if self.redirectDrives != 'false':
params.append('/drive:media,/media')

View File

@@ -29,7 +29,7 @@ def updateAuthorizedKeys(user, pubKey):
sshFolder = '{}/.ssh'.format(home)
if not os.path.exists(sshFolder):
try:
os.makedirs(sshFolder, 0700)
os.makedirs(sshFolder, 0o700)
os.chown(sshFolder, uid, -1)
except OSError as e:
if e.errno != errno.EEXIST:
@@ -53,7 +53,7 @@ def updateAuthorizedKeys(user, pubKey):
# Ensure access is correct
os.chown(authorizedKeys, uid, -1)
os.chmod(authorizedKeys, 0600)
os.chmod(authorizedKeys, 0o600)
# Done

View File

@@ -191,12 +191,20 @@ def ticketAuth(request, ticketId):
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():
logger.debug("{} {}".format(v.uuid, v.name))
# for v in DeployedService.objects.all():
# logger.debug("{} {}".format(v.uuid, v.name))
# Check if servicePool is part of the ticket
if servicePool is not None:
# If service pool is in there, also is transport
# Deferred update transport
servicePoolDb = DeployedService.objects.get(uuid=servicePool)
for t in servicePoolDb.transports.order_by('priority'):
typeTrans = t.getType()
if t.validForIp(request.ip) and typeTrans.supportsOs(request.os['OS']) and t.validForOs(request.os['OS']):
transport = t.uuid
break
res = userServiceManager().getService(request.user, request.ip, 'F' + servicePool, transport, False)
_x, userService, _x, transport, _x = res

View File

@@ -191,10 +191,17 @@ def index(request):
else:
tbrt = ''
left = ''
# try:
# if svr.max_srvs > 0:
# left = ' (max {})'.format(svr.max_srvs - svr.assignedUserServices().filter(UserServiceManager.getStateFilter()).count())
# except Exception:
# logger.exception('Error')
services.append({
'id': 'F' + svr.uuid,
'name': svr.name,
'visual_name': svr.visual_name,
'name': svr.name + left,
'visual_name': svr.visual_name + left,
'description': svr.comments,
'group': group,
'transports': trans,