1
0
mirror of https://github.com/dkmstr/openuds.git synced 2025-03-11 00:58:39 +03:00

Fixed user service manager to treat correctly "reset" an instance

This commit is contained in:
Adolfo Gómez García 2024-10-30 19:56:51 +01:00
parent 5ac2e2a73d
commit 3fbdea1e23
No known key found for this signature in database
GPG Key ID: DD1ABF20724CDA23
7 changed files with 48 additions and 53 deletions

View File

@ -594,6 +594,8 @@ class Ready(BaseReadyChange):
result = super().action()
# Set as "inUse" to false because a ready can only ocurr if an user is not logged in
# Note that an assigned dynamic user service that gets "restarted", will be marked as not in use
# until it's logged ing again. So, id the system has
userservice = self.get_userservice()
userservice.set_in_use(False)

View File

@ -764,17 +764,25 @@ class UserServiceManager(metaclass=singleton.Singleton):
return False
def reset(self, user_service: UserService) -> None:
user_service.refresh_from_db()
def reset(self, userservice: UserService) -> None:
userservice.refresh_from_db()
if not user_service.deployed_service.service.get_type().can_reset:
if not userservice.deployed_service.service.get_type().can_reset:
return
operations_logger.info('Reseting %s', user_service)
operations_logger.info('Reseting %s', userservice)
userservice_instance = user_service.get_instance()
userservice_instance = userservice.get_instance()
try:
state = userservice_instance.reset()
userservice.update_state_date()
log.log(
userservice,
types.log.LogLevel.INFO,
'Service reset by user',
types.log.LogSource.WEB,
)
except Exception:
logger.exception('Reseting service')
return
@ -782,10 +790,10 @@ class UserServiceManager(metaclass=singleton.Singleton):
logger.debug('State: %s', state)
if state == types.states.TaskState.FINISHED:
user_service.update_data(userservice_instance)
userservice.update_data(userservice_instance)
return
UserServiceOpChecker.make_unique(user_service, state)
UserServiceOpChecker.make_unique(userservice, state)
def notify_preconnect(self, user_service: UserService, info: types.connections.ConnectionData) -> None:
try:

View File

@ -65,8 +65,11 @@ class StateUpdater(abc.ABC):
def save(self, new_state: typing.Optional[str] = None) -> None:
if new_state:
self.userservice.set_state(new_state)
instance = self.userservice.get_instance()
# logger.debug('Instance: _queue: %s', getattr(instance, '_queue', '????'))
self.userservice.update_data(self.userservice.get_instance())
self.userservice.update_data(instance)
def log_ip(self) -> None:
ip = self.userservice.get_instance().get_ip()
@ -186,6 +189,13 @@ class UpdateFromCanceling(StateUpdater):
self.save(types.states.State.CANCELED)
class UpdateFromValid(StateUpdater):
# Some operations, like "reset", are done on "valid" states
# Simply, do nothing on finish except saving the state
def state_finish(self) -> None:
logger.debug('Finishing %s', self.userservice.friendly_name)
# All done
self.save()
class UpdateFromOther(StateUpdater):
def state_finish(self) -> None:
@ -245,6 +255,7 @@ class UserServiceOpChecker(DelayedTask):
types.states.State.PREPARING: UpdateFromPreparing,
types.states.State.REMOVING: UpdateFromRemoving,
types.states.State.CANCELING: UpdateFromCanceling,
types.states.State.USABLE: UpdateFromValid,
}.get(types.states.State.from_str(userservice.state), UpdateFromOther),
)

View File

@ -41,7 +41,6 @@ from uds.core.util import autoserializable, log
from uds.core.util.model import sql_stamp_seconds
# Not imported at runtime, just for type checking
if typing.TYPE_CHECKING:
from uds import models
@ -425,8 +424,7 @@ class DynamicUserService(services.UserService, autoserializable.AutoSerializable
types.services.Operation.FINISH,
]
)
return types.states.TaskState.FINISHED
return self._execute_queue()
@typing.final
def check_state(self) -> types.states.TaskState:
@ -646,7 +644,7 @@ class DynamicUserService(services.UserService, autoserializable.AutoSerializable
def op_delete(self) -> None:
"""
This method is called when the service is removed
Note:
If you override this method, probably you will need to override "op_delete_completed" too
Because the op_delete_completed method uses the information generated by service().delete

View File

@ -45,20 +45,6 @@ from uds.models.config import Config as DBConfig
logger = logging.getLogger(__name__)
# Pair of section/value removed from current UDS version
# Note: As of version 4.0, all previous REMOVED values has been moved to migration script 0043
REMOVED_CONFIG_ELEMENTS = {
'RGS': (
'downloadUrl',
'tunnelOpenedTime',
),
'SAML': (
'Organization Name',
'Org. Display Name',
'Organization URL',
),
}
class Config:
# Global configuration values
@ -307,13 +293,6 @@ class Config:
# Skip removed configuration values, even if they are in database
logger.debug('Key: %s, val: %s', cfg.section, cfg.key)
if cfg.key in REMOVED_CONFIG_ELEMENTS.get(cfg.section, ()):
# Try to remove it, a left-behind value
try:
DBConfig.objects.filter(section=cfg.section, key=cfg.key).delete()
except Exception:
pass
continue
# Hidden field, not to be edited by admin interface
if cfg.field_type == Config.FieldType.HIDDEN:
@ -500,12 +479,7 @@ class GlobalConfig:
type=Config.FieldType.NUMERIC,
help=_('How long should the user service be unused before os manager considers it for removal'),
) # Defaults to 10 minutes
CHECK_UNUSED_DELAY: Config.Value = Config.section(Config.SectionType.GLOBAL).value(
'checkUnusedDelay',
'300',
type=Config.FieldType.NUMERIC,
help=_('Time betwen checks of unused user services by os managers'),
) # Defaults to 10 minutes
# Default CSS Used: REMOVED! (keep the for for naw, for reference, but will be cleaned on future...)
# CSS: Config.Value = Config.section(Config.SectionType.GLOBAL).value('css', settings.STATIC_URL + 'css/uds.css', type=Config.FieldType.TEXT_FIELD)
# Max logins before blocking an account
@ -537,13 +511,6 @@ class GlobalConfig:
type=Config.FieldType.BOOLEAN,
help=_('Do autorun of service if just one service'),
)
# Redirect HTTP to HTTPS
REDIRECT_TO_HTTPS: Config.Value = Config.section(Config.SectionType.GLOBAL).value(
'redirectToHttps',
'1',
type=Config.FieldType.BOOLEAN,
help=_('Redirect HTTP to HTTPS on connection to UDS'),
)
REDIRECT_TO_TAG_ON_LOGOUT: Config.Value = Config.section(Config.SectionType.GLOBAL).value(
'Redirect to tag on logout',
'0',
@ -866,3 +833,8 @@ signals.post_migrate.connect(_post_migrate)
# Will be here for at least one major version, so we can remove them from database for sure
Config.removed(Config.SectionType.CUSTOM, 'Logout URL') # Removed on 4.0
Config.removed(Config.SectionType.SECURITY, 'Max Audit Logs duration') # Removed on 4.0
Config.removed(Config.SectionType.GLOBAL, 'checkUnusedDelay') # Removed on 4.0
Config.removed(Config.SectionType.GLOBAL, 'redirectToHttps') # Removed on 4.0
# Old saml related data
Config.removed(Config.SectionType.OTHER, 'Global logout on exit') # Removed on 4.0

View File

@ -110,7 +110,7 @@ class UserService(UUIDModel, properties.PropertiesMixin):
# objects: 'models.manager.Manager["UserService"]'
sessions: 'models.manager.RelatedManager[UserServiceSession]'
accounting: 'AccountUsage'
_cached_instance: typing.Optional['services.UserService'] = None
class Meta(UUIDModel.Meta): # pylint: disable=too-few-public-methods
@ -200,7 +200,7 @@ class UserService(UUIDModel, properties.PropertiesMixin):
"""
if self._cached_instance:
return self._cached_instance
# We get the service instance, publication instance and osmanager instance
servicepool = self.deployed_service
if not servicepool.service:
@ -372,7 +372,7 @@ class UserService(UUIDModel, properties.PropertiesMixin):
Returns True if this User Service needs an os manager (i.e. parent services pools is marked to use an os manager)
"""
return bool(self.get_osmanager())
def allow_putting_back_to_cache(self) -> bool:
return self.deployed_service.service.get_instance().allow_putting_back_to_cache()
@ -426,6 +426,10 @@ class UserService(UUIDModel, properties.PropertiesMixin):
self.state = state
self.save(update_fields=['state', 'state_date'])
def update_state_date(self) -> None:
self.state_date = sql_now()
self.save(update_fields=['state_date'])
def set_os_state(self, state: str) -> None:
"""
Updates the os state (state of the os) of this object and, optionally, saves it
@ -552,7 +556,7 @@ class UserService(UUIDModel, properties.PropertiesMixin):
# import traceback
# logger.info('Removing user service %s', self)
# logger.info('\n* '.join(traceback.format_stack()))
if immediate:
self.set_state(State.REMOVED)
else:
@ -606,7 +610,7 @@ class UserService(UUIDModel, properties.PropertiesMixin):
def notify_preconnect(self) -> None:
"""
Notifies preconnect to userservice.
Notifies preconnect to userservice.
TODO: Currently not used
"""
pass

View File

@ -46,8 +46,8 @@ logger = logging.getLogger(__name__)
class AssignedAndUnused(Job):
frecuency = 300 # Once every 5 minute, but look for GlobalConfig.CHECK_UNUSED_TIME
frecuency_cfg = GlobalConfig.CHECK_UNUSED_DELAY
frecuency = 60
# frecuency_cfg = GlobalConfig.CHECK_UNUSED_DELAY
friendly_name = 'Unused services checker'
def run(self) -> None: