mirror of
https://github.com/dkmstr/openuds.git
synced 2024-12-22 13:34:04 +03:00
* Added support for "reset" services that support it.
Right now, we will test on enterprise this feature.
This commit is contained in:
parent
ee72b65534
commit
92de41d410
@ -62,6 +62,7 @@ class Services(DetailHandler): # pylint: disable=too-many-public-methods
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def serviceInfo(item):
|
def serviceInfo(item):
|
||||||
info = item.getType()
|
info = item.getType()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'icon': info.icon().replace('\n', ''),
|
'icon': info.icon().replace('\n', ''),
|
||||||
'needs_publication': info.publicationType is not None,
|
'needs_publication': info.publicationType is not None,
|
||||||
@ -74,6 +75,7 @@ class Services(DetailHandler): # pylint: disable=too-many-public-methods
|
|||||||
'allowedProtocols': info.allowedProtocols,
|
'allowedProtocols': info.allowedProtocols,
|
||||||
'servicesTypeProvided': info.servicesTypeProvided,
|
'servicesTypeProvided': info.servicesTypeProvided,
|
||||||
'must_assign_manually': info.mustAssignManually,
|
'must_assign_manually': info.mustAssignManually,
|
||||||
|
'can_reset': info.canReset,
|
||||||
}
|
}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -72,7 +72,8 @@ class ServicesPools(ModelHandler):
|
|||||||
save_fields = ['name', 'short_name', 'comments', 'tags', 'service_id',
|
save_fields = ['name', 'short_name', 'comments', 'tags', 'service_id',
|
||||||
'osmanager_id', 'image_id', 'servicesPoolGroup_id', 'initial_srvs',
|
'osmanager_id', 'image_id', 'servicesPoolGroup_id', 'initial_srvs',
|
||||||
'cache_l1_srvs', 'cache_l2_srvs', 'max_srvs', 'show_transports',
|
'cache_l1_srvs', 'cache_l2_srvs', 'max_srvs', 'show_transports',
|
||||||
'allow_users_remove', 'ignores_unused']
|
'allow_users_remove', 'allow_users_reset', 'ignores_unused']
|
||||||
|
|
||||||
remove_fields = ['osmanager_id', 'service_id']
|
remove_fields = ['osmanager_id', 'service_id']
|
||||||
|
|
||||||
table_title = _('Service Pools')
|
table_title = _('Service Pools')
|
||||||
@ -134,6 +135,7 @@ class ServicesPools(ModelHandler):
|
|||||||
'restrained': item.isRestrained(),
|
'restrained': item.isRestrained(),
|
||||||
'show_transports': item.show_transports,
|
'show_transports': item.show_transports,
|
||||||
'allow_users_remove': item.allow_users_remove,
|
'allow_users_remove': item.allow_users_remove,
|
||||||
|
'allow_users_reset': item.allow_users_reset,
|
||||||
'ignores_unused': item.ignores_unused,
|
'ignores_unused': item.ignores_unused,
|
||||||
'fallbackAccess': item.fallbackAccess,
|
'fallbackAccess': item.fallbackAccess,
|
||||||
'permission': permissions.getEffectivePermission(self._user, item),
|
'permission': permissions.getEffectivePermission(self._user, item),
|
||||||
@ -186,13 +188,21 @@ class ServicesPools(ModelHandler):
|
|||||||
'type': gui.InputField.CHECKBOX_TYPE,
|
'type': gui.InputField.CHECKBOX_TYPE,
|
||||||
'order': 111,
|
'order': 111,
|
||||||
'tab': ugettext('Advanced'),
|
'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',
|
'name': 'ignores_unused',
|
||||||
'value': False,
|
'value': False,
|
||||||
'label': ugettext('Ignores unused'),
|
'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.'),
|
'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,
|
'type': gui.InputField.CHECKBOX_TYPE,
|
||||||
'order': 112,
|
'order': 113,
|
||||||
'tab': ugettext('Advanced'),
|
'tab': ugettext('Advanced'),
|
||||||
}, {
|
}, {
|
||||||
'name': 'image_id',
|
'name': 'image_id',
|
||||||
|
@ -51,7 +51,7 @@ import requests
|
|||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
__updated__ = '2018-03-02'
|
__updated__ = '2018-03-14'
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
traceLogger = logging.getLogger('traceLog')
|
traceLogger = logging.getLogger('traceLog')
|
||||||
@ -360,6 +360,20 @@ class UserServiceManager(object):
|
|||||||
UserServiceOpChecker.makeUnique(uService, ui, state)
|
UserServiceOpChecker.makeUnique(uService, ui, state)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def reset(self, uService):
|
||||||
|
UserService.objects.update()
|
||||||
|
uService = UserService.objects.get(id=uService.id)
|
||||||
|
if uService.deployed_service.service.getType().canReset is False:
|
||||||
|
return
|
||||||
|
|
||||||
|
logger.debug('Reseting'.format(uService))
|
||||||
|
|
||||||
|
ui = uService.getInstance()
|
||||||
|
try:
|
||||||
|
ui.reset()
|
||||||
|
except Exception:
|
||||||
|
logger.exception('Reseting service')
|
||||||
|
|
||||||
def notifyPreconnect(self, uService, userName, protocol):
|
def notifyPreconnect(self, uService, userName, protocol):
|
||||||
url = uService.getCommsUrl()
|
url = uService.getCommsUrl()
|
||||||
if url is None:
|
if url is None:
|
||||||
|
@ -36,7 +36,7 @@ from uds.core import Environmentable
|
|||||||
from uds.core import Serializable
|
from uds.core import Serializable
|
||||||
from uds.core.util.State import State
|
from uds.core.util.State import State
|
||||||
|
|
||||||
__updated__ = '2017-09-29'
|
__updated__ = '2018-03-14'
|
||||||
|
|
||||||
|
|
||||||
class UserDeployment(Environmentable, Serializable):
|
class UserDeployment(Environmentable, Serializable):
|
||||||
@ -574,6 +574,13 @@ class UserDeployment(Environmentable, Serializable):
|
|||||||
'''
|
'''
|
||||||
raise Exception('cancel method for class {0} not provided!'.format(self.__class__.__name__))
|
raise Exception('cancel method for class {0} not provided!'.format(self.__class__.__name__))
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
'''
|
||||||
|
This method is invoked for "reset" an user service
|
||||||
|
This method is not intended to be a task right now, it's more like the
|
||||||
|
'''
|
||||||
|
raise Exception('reset method for class {0} not provided!'.format(self.__class__.__name__))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
'''
|
'''
|
||||||
Mainly used for debugging purposses
|
Mainly used for debugging purposses
|
||||||
|
@ -37,7 +37,7 @@ from uds.core import Module
|
|||||||
from uds.core.transports import protocols
|
from uds.core.transports import protocols
|
||||||
from . import types
|
from . import types
|
||||||
|
|
||||||
__updated__ = '2016-03-09'
|
__updated__ = '2018-03-14'
|
||||||
|
|
||||||
|
|
||||||
class Service(Module):
|
class Service(Module):
|
||||||
@ -167,14 +167,14 @@ class Service(Module):
|
|||||||
# : Default behavior is False (and most common), but some services may need to respawn a new "copy" on every launch
|
# : Default behavior is False (and most common), but some services may need to respawn a new "copy" on every launch
|
||||||
spawnsNew = False
|
spawnsNew = False
|
||||||
|
|
||||||
|
# : If the service allows "reset", here we will announce it
|
||||||
|
# : Defaults to False
|
||||||
|
canReset = False
|
||||||
|
|
||||||
# : 'kind' of services that this service provides:
|
# : 'kind' of services that this service provides:
|
||||||
# : For example, VDI, VAPP, ...
|
# : For example, VDI, VAPP, ...
|
||||||
servicesTypeProvided = types.ALL
|
servicesTypeProvided = types.ALL
|
||||||
|
|
||||||
# : If the service can provide any other option on release appart of "delete" & "keep assigned"
|
|
||||||
# : Defaults to None (no any other options are provided)
|
|
||||||
actionsOnRelease = None
|
|
||||||
|
|
||||||
def __init__(self, environment, parent, values=None):
|
def __init__(self, environment, parent, values=None):
|
||||||
'''
|
'''
|
||||||
Do not forget to invoke this in your derived class using "super(self.__class__, self).__init__(environment, parent, values)".
|
Do not forget to invoke this in your derived class using "super(self.__class__, self).__init__(environment, parent, values)".
|
||||||
|
@ -39,7 +39,7 @@ import logging
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
__updated__ = '2016-04-25'
|
__updated__ = '2018-03-14'
|
||||||
|
|
||||||
|
|
||||||
class ServiceProvider(Module):
|
class ServiceProvider(Module):
|
||||||
@ -120,7 +120,6 @@ class ServiceProvider(Module):
|
|||||||
# : Note: this variable can be either a fixed value (integer, string) or a Gui text field (with a .value)
|
# : Note: this variable can be either a fixed value (integer, string) or a Gui text field (with a .value)
|
||||||
ignoreLimits = None
|
ignoreLimits = None
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def getServicesTypes(cls):
|
def getServicesTypes(cls):
|
||||||
'''
|
'''
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.9.9 on 2018-03-14 06:06
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('uds', '0026_auto_20180302_0525'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='deployedservice',
|
||||||
|
name='allow_users_reset',
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
]
|
@ -62,7 +62,7 @@ import logging
|
|||||||
import pickle
|
import pickle
|
||||||
import six
|
import six
|
||||||
|
|
||||||
__updated__ = '2017-11-29'
|
__updated__ = '2018-03-14'
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -83,8 +83,12 @@ class DeployedService(UUIDModel, TaggingMixin):
|
|||||||
state = models.CharField(max_length=1, default=states.servicePool.ACTIVE, db_index=True)
|
state = models.CharField(max_length=1, default=states.servicePool.ACTIVE, db_index=True)
|
||||||
state_date = models.DateTimeField(default=NEVER)
|
state_date = models.DateTimeField(default=NEVER)
|
||||||
show_transports = models.BooleanField(default=True)
|
show_transports = models.BooleanField(default=True)
|
||||||
|
|
||||||
allow_users_remove = models.BooleanField(default=False)
|
allow_users_remove = models.BooleanField(default=False)
|
||||||
|
allow_users_reset = models.BooleanField(default=False)
|
||||||
|
|
||||||
ignores_unused = models.BooleanField(default=False)
|
ignores_unused = models.BooleanField(default=False)
|
||||||
|
|
||||||
image = models.ForeignKey(Image, null=True, blank=True, related_name='deployedServices', on_delete=models.SET_NULL)
|
image = models.ForeignKey(Image, null=True, blank=True, related_name='deployedServices', on_delete=models.SET_NULL)
|
||||||
|
|
||||||
servicesPoolGroup = models.ForeignKey(ServicesPoolGroup, null=True, blank=True, related_name='servicesPools', on_delete=models.SET_NULL)
|
servicesPoolGroup = models.ForeignKey(ServicesPoolGroup, null=True, blank=True, related_name='servicesPools', on_delete=models.SET_NULL)
|
||||||
|
@ -72,6 +72,7 @@ gui.servicesPools.link = (event) ->
|
|||||||
serviceChangedFnc = (formId) ->
|
serviceChangedFnc = (formId) ->
|
||||||
$fld = $(formId + " [name=\"service_id\"]")
|
$fld = $(formId + " [name=\"service_id\"]")
|
||||||
$osmFld = $(formId + " [name=\"osmanager_id\"]")
|
$osmFld = $(formId + " [name=\"osmanager_id\"]")
|
||||||
|
$canResetFld = $(formId + " [name=\"allow_users_reset\"]")
|
||||||
selectors = []
|
selectors = []
|
||||||
$.each [
|
$.each [
|
||||||
"initial_srvs"
|
"initial_srvs"
|
||||||
@ -89,6 +90,13 @@ gui.servicesPools.link = (event) ->
|
|||||||
unless $fld.val() is -1
|
unless $fld.val() is -1
|
||||||
api.providers.service $fld.val(), (data) ->
|
api.providers.service $fld.val(), (data) ->
|
||||||
gui.doLog "Onchange", data
|
gui.doLog "Onchange", data
|
||||||
|
if $canResetFld.bootstrapSwitch("readonly") == data.info.can_reset
|
||||||
|
gui.doLog('reset doent not match field')
|
||||||
|
$canResetFld.bootstrapSwitch "toggleReadonly", true
|
||||||
|
if data.info.can_reset is false
|
||||||
|
gui.doLog($canResetFld.bootstrapSwitch("readonly"), data.info.can_reset)
|
||||||
|
|
||||||
|
|
||||||
if data.info.needs_manager is false
|
if data.info.needs_manager is false
|
||||||
$osmFld.prop "disabled", "disabled"
|
$osmFld.prop "disabled", "disabled"
|
||||||
else
|
else
|
||||||
|
@ -50,6 +50,9 @@
|
|||||||
{% if ser.allow_users_remove %}
|
{% if ser.allow_users_remove %}
|
||||||
<span data-href="{% url 'Releaser' idService=ser.id %}" class="release fa fa-trash"> </span>
|
<span data-href="{% url 'Releaser' idService=ser.id %}" class="release fa fa-trash"> </span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if ser.allow_users_reset %}
|
||||||
|
<span data-href="{% url 'Reseter' idService=ser.id %}" class="reseter fa fa-refresh"> </span>
|
||||||
|
{% endif %}
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
@ -284,6 +287,10 @@
|
|||||||
span.gear > span.release {
|
span.gear > span.release {
|
||||||
cursor: cell;
|
cursor: cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
span.gear > span.reseter {
|
||||||
|
cursor: cell;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
@ -377,6 +384,26 @@
|
|||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('div.service:not(.maintenance, .notaccesible) > span.gear > span.release').on("click", function (event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
if ( confirm("{%trans 'Are you sure that you want to release this service. Its current content will be lost!' %}") ) {
|
||||||
|
window.location.href = $(this).attr('data-href');
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$('div.service:not(.maintenance, .notaccesible) > span.gear > span.reseter').on("click", function (event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
if ( confirm("{%trans 'Are you sure that you want to reset this service. USE WITH CAUTION!' %}") ) {
|
||||||
|
window.location.href = $(this).attr('data-href');
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
$(".maintenance").click( function(event) {
|
$(".maintenance").click( function(event) {
|
||||||
$('#maintenance-dialog').modal({
|
$('#maintenance-dialog').modal({
|
||||||
keyboard: false
|
keyboard: false
|
||||||
|
@ -69,8 +69,9 @@ urlpatterns = patterns(
|
|||||||
# Client access enabler
|
# Client access enabler
|
||||||
url(r'^enable/(?P<idService>.+)/(?P<idTransport>.+)$', 'web.views.clientEnabler', name='ClientAccessEnabler'),
|
url(r'^enable/(?P<idService>.+)/(?P<idTransport>.+)$', 'web.views.clientEnabler', name='ClientAccessEnabler'),
|
||||||
|
|
||||||
# Releaser
|
# Releaser & reset
|
||||||
url(r'^release/(?P<idService>.+)$', 'web.views.release', name='Releaser'),
|
url(r'^release/(?P<idService>.+)$', 'web.views.release', name='Releaser'),
|
||||||
|
url(r'^reset/(?P<idService>.+)$', 'web.views.reset', name='Reseter'),
|
||||||
|
|
||||||
# Custom authentication callback
|
# Custom authentication callback
|
||||||
(r'^auth/(?P<authName>.+)', 'web.views.authCallback'),
|
(r'^auth/(?P<authName>.+)', 'web.views.authCallback'),
|
||||||
|
@ -35,7 +35,7 @@ import logging
|
|||||||
from .login import login, logout, customAuth
|
from .login import login, logout, customAuth
|
||||||
from .index import index, about
|
from .index import index, about
|
||||||
from .prefs import prefs
|
from .prefs import prefs
|
||||||
from .service import transportOwnLink, transportIcon, clientEnabler, serviceImage, release
|
from .service import transportOwnLink, transportIcon, clientEnabler, serviceImage, release, reset
|
||||||
from .auth import authCallback, authInfo, ticketAuth
|
from .auth import authCallback, authInfo, ticketAuth
|
||||||
from .download import download
|
from .download import download
|
||||||
from .client_download import client_downloads, plugin_detection
|
from .client_download import client_downloads, plugin_detection
|
||||||
@ -44,6 +44,6 @@ from ..errors import error
|
|||||||
from .images import image
|
from .images import image
|
||||||
from .file_storage import file_storage
|
from .file_storage import file_storage
|
||||||
|
|
||||||
__updated__ = '2017-10-26'
|
__updated__ = '2018-03-14'
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -52,7 +52,7 @@ import logging
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
__updated__ = '2017-11-10'
|
__updated__ = '2018-03-14'
|
||||||
|
|
||||||
|
|
||||||
def about(request):
|
def about(request):
|
||||||
@ -141,6 +141,7 @@ def index(request):
|
|||||||
'imageId': imageId,
|
'imageId': imageId,
|
||||||
'show_transports': servicePool.show_transports,
|
'show_transports': servicePool.show_transports,
|
||||||
'allow_users_remove': servicePool.allow_users_remove,
|
'allow_users_remove': servicePool.allow_users_remove,
|
||||||
|
'allow_users_reset': servicePool.allow_users_reset,
|
||||||
'maintenance': servicePool.isInMaintenance(),
|
'maintenance': servicePool.isInMaintenance(),
|
||||||
'not_accesible': not servicePool.isAccessAllowed(),
|
'not_accesible': not servicePool.isAccessAllowed(),
|
||||||
'in_use': svr.in_use,
|
'in_use': svr.in_use,
|
||||||
@ -200,6 +201,7 @@ def index(request):
|
|||||||
'imageId': imageId,
|
'imageId': imageId,
|
||||||
'show_transports': svr.show_transports,
|
'show_transports': svr.show_transports,
|
||||||
'allow_users_remove': svr.allow_users_remove,
|
'allow_users_remove': svr.allow_users_remove,
|
||||||
|
'allow_users_reset': svr.allow_users_reset,
|
||||||
'maintenance': svr.isInMaintenance(),
|
'maintenance': svr.isInMaintenance(),
|
||||||
'not_accesible': not svr.isAccessAllowed(),
|
'not_accesible': not svr.isAccessAllowed(),
|
||||||
'in_use': in_use,
|
'in_use': in_use,
|
||||||
|
@ -56,7 +56,7 @@ import logging
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
__updated__ = '2017-11-16'
|
__updated__ = '2018-03-14'
|
||||||
|
|
||||||
|
|
||||||
@webLoginRequired(admin=False)
|
@webLoginRequired(admin=False)
|
||||||
@ -159,7 +159,7 @@ def clientEnabler(request, idService, idTransport):
|
|||||||
def release(request, idService):
|
def release(request, idService):
|
||||||
logger.debug('ID Service: {}'.format(idService))
|
logger.debug('ID Service: {}'.format(idService))
|
||||||
userService = userServiceManager().locateUserService(request.user, idService, create=False)
|
userService = userServiceManager().locateUserService(request.user, idService, create=False)
|
||||||
logger.debug('UserSrvice: >{}<'.format(userService))
|
logger.debug('UserService: >{}<'.format(userService))
|
||||||
if userService is not None and userService.deployed_service.allow_users_remove:
|
if userService is not None and userService.deployed_service.allow_users_remove:
|
||||||
log.doLog(
|
log.doLog(
|
||||||
userService.deployed_service,
|
userService.deployed_service,
|
||||||
@ -172,3 +172,23 @@ def release(request, idService):
|
|||||||
|
|
||||||
return HttpResponseRedirect(reverse('Index'))
|
return HttpResponseRedirect(reverse('Index'))
|
||||||
|
|
||||||
|
|
||||||
|
@webLoginRequired(admin=False)
|
||||||
|
@never_cache
|
||||||
|
def reset(request, idService):
|
||||||
|
logger.debug('ID Service: {}'.format(idService))
|
||||||
|
userService = userServiceManager().locateUserService(request.user, idService, create=False)
|
||||||
|
logger.debug('UserService: >{}<'.format(userService))
|
||||||
|
if (userService is not None and userService.deployed_service.allow_users_reset
|
||||||
|
and userService.deployed_service.service.getType().canReset):
|
||||||
|
log.doLog(
|
||||||
|
userService.deployed_service,
|
||||||
|
log.INFO,
|
||||||
|
"Reseting User Service {} as requested by {} from {}".format(userService.friendly_name, request.user.pretty_name, request.ip),
|
||||||
|
log.WEB
|
||||||
|
)
|
||||||
|
# userServiceManager().requestLogoff(userService)
|
||||||
|
userServiceManager().reset(userService)
|
||||||
|
|
||||||
|
return HttpResponseRedirect(reverse('Index'))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user