mirror of
https://github.com/dkmstr/openuds.git
synced 2025-11-17 08:24:12 +03:00
Compare commits
22 Commits
dev/andres
...
v4.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1780d85bc1 | ||
|
|
2c31b7da36 | ||
|
|
bc950acf1d | ||
|
|
d511451997 | ||
|
|
1096edf79f | ||
|
|
bd7ab4f22e | ||
|
|
7df6babad0 | ||
|
|
335c1a8c05 | ||
|
|
b07a062ad6 | ||
|
|
a099e37c16 | ||
|
|
88b3dc8d0c | ||
|
|
8fed907c73 | ||
|
|
bb2a097d86 | ||
|
|
3398762cb4 | ||
|
|
b85beacc22 | ||
|
|
2a3ed794c4 | ||
|
|
5057131b47 | ||
|
|
48c3c07f0f | ||
|
|
49d9bbb6f7 | ||
|
|
48cc171ba4 | ||
|
|
551740fccc | ||
|
|
398ec1aac0 |
@@ -153,7 +153,7 @@ class TunnelRegister(ServerRegisterBase):
|
||||
name = 'register'
|
||||
|
||||
# Just a compatibility method for old tunnel servers
|
||||
def post(self) -> collections.abc.MutableMapping[str, typing.Any]:
|
||||
def post(self) -> dict[str, typing.Any]:
|
||||
self._params['type'] = types.servers.ServerType.TUNNEL
|
||||
self._params['os'] = self._params.get(
|
||||
'os', types.os.KnownOS.LINUX.os_name()
|
||||
|
||||
@@ -46,7 +46,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class BaseThread(threading.Thread, abc.ABC):
|
||||
|
||||
|
||||
@abc.abstractmethod
|
||||
def request_stop(self) -> None:
|
||||
raise NotImplementedError
|
||||
@@ -108,7 +108,9 @@ class TaskManager(metaclass=singleton.Singleton):
|
||||
def add_other_tasks(self) -> None:
|
||||
logger.info("Registering other tasks")
|
||||
|
||||
from uds.core.messaging.processor import MessageProcessorThread # pylint: disable=import-outside-toplevel
|
||||
from uds.core.messaging.processor import (
|
||||
MessageProcessorThread,
|
||||
) # pylint: disable=import-outside-toplevel
|
||||
|
||||
thread = MessageProcessorThread()
|
||||
thread.start()
|
||||
@@ -126,11 +128,14 @@ class TaskManager(metaclass=singleton.Singleton):
|
||||
self.register_scheduled_tasks()
|
||||
|
||||
n_schedulers: int = GlobalConfig.SCHEDULER_THREADS.as_int()
|
||||
n_delayed_tasks: int = GlobalConfig.DELAYED_TASKS_THREADS.as_int()
|
||||
if n_schedulers < 1:
|
||||
n_schedulers = 1 # At least one scheduler
|
||||
|
||||
logger.info(
|
||||
'Starting %s schedulers and %s task executors', n_schedulers, n_delayed_tasks
|
||||
)
|
||||
n_delayed_tasks: int = GlobalConfig.DELAYED_TASKS_THREADS.as_int()
|
||||
if n_delayed_tasks < 1:
|
||||
n_delayed_tasks = 1 # At least one delayed task
|
||||
|
||||
logger.info('Starting %s schedulers and %s task executors', n_schedulers, n_delayed_tasks)
|
||||
|
||||
signal.signal(signal.SIGTERM, TaskManager.sig_term)
|
||||
signal.signal(signal.SIGINT, TaskManager.sig_term)
|
||||
|
||||
@@ -144,7 +144,7 @@ class StorageInfo:
|
||||
type=StorageType.from_str(storage.type.value),
|
||||
available=storage.available,
|
||||
used=storage.used,
|
||||
status=StorageStatus.from_str(storage.status.value),
|
||||
status=StorageStatus.from_str(storage.status.value if storage.status else 'unknown'),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -201,12 +201,12 @@ class OpenNebulaLiveDeployment(services.UserService, autoserializable.AutoSerial
|
||||
Operation.FINISH,
|
||||
]
|
||||
|
||||
def _check_machine_state(self, state: on.types.VmState) -> types.states.TaskState:
|
||||
def _check_machine_state(self, check_state: on.types.VmState) -> types.states.TaskState:
|
||||
logger.debug(
|
||||
'Checking that state of machine %s (%s) is %s',
|
||||
self._vmid,
|
||||
self._name,
|
||||
state,
|
||||
check_state,
|
||||
)
|
||||
state = self.service().get_machine_state(self._vmid)
|
||||
|
||||
@@ -219,12 +219,8 @@ class OpenNebulaLiveDeployment(services.UserService, autoserializable.AutoSerial
|
||||
|
||||
ret = types.states.TaskState.RUNNING
|
||||
|
||||
if isinstance(state, (list, tuple)):
|
||||
if state in state:
|
||||
ret = types.states.TaskState.FINISHED
|
||||
else:
|
||||
if state == state:
|
||||
ret = types.states.TaskState.FINISHED
|
||||
if state == check_state:
|
||||
ret = types.states.TaskState.FINISHED
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
@@ -5,17 +5,30 @@ import os.path
|
||||
import shutil
|
||||
import os
|
||||
|
||||
# Asegura que subprocess, shutil, os, os.path y typing estén en el scope global para clientes antiguos (3.6)
|
||||
globals()['subprocess'] = subprocess
|
||||
globals()['shutil'] = shutil
|
||||
globals()['os'] = os
|
||||
globals()['os.path'] = os.path
|
||||
globals()['typing'] = typing
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# On older client versions, need importing globally to allow inner functions to work
|
||||
import subprocess # type: ignore
|
||||
try:
|
||||
from uds.log import logger # For UDS Clients 3.6
|
||||
except ImportError:
|
||||
logger = logging.getLogger(__name__) # For UDS Clients 4.0
|
||||
|
||||
# También asegura logger en globales
|
||||
globals()['logger'] = logger
|
||||
|
||||
# Avoid type checking annoing errors
|
||||
try:
|
||||
from uds import tools # type: ignore
|
||||
except ImportError:
|
||||
tools: typing.Any = None
|
||||
raise
|
||||
|
||||
# Asegura tools en globales
|
||||
globals()['tools'] = tools
|
||||
|
||||
if 'sp' not in globals():
|
||||
# Inject local passed sp into globals for inner functions if not already there
|
||||
@@ -64,6 +77,13 @@ def exec_thincast(thincast: str) -> None:
|
||||
params = [os.path.expandvars(i) for i in [thincast] + sp['as_new_xfreerdp_params'] + [f'/v:{sp["address"]}']] # type: ignore
|
||||
_exec_client_with_params(thincast, params)
|
||||
|
||||
# Añade las funciones al scope global para clientes antiguos (3.6)
|
||||
globals()['_prepare_rdp_file'] = _prepare_rdp_file
|
||||
globals()['_exec_client_with_params'] = _exec_client_with_params
|
||||
globals()['exec_udsrdp'] = exec_udsrdp
|
||||
globals()['exec_new_xfreerdp'] = exec_new_xfreerdp
|
||||
globals()['exec_thincast'] = exec_thincast
|
||||
|
||||
# Typical Thincast Routes on Linux
|
||||
thincast_list = [
|
||||
'/usr/bin/thincast-remote-desktop-client',
|
||||
@@ -106,7 +126,7 @@ if not executable:
|
||||
'''
|
||||
)
|
||||
else:
|
||||
logging.debug(f'RDP client found: {executable} of kind {kind}')
|
||||
logger.debug(f'RDP client found: {executable} of kind {kind}')
|
||||
|
||||
# Execute the client found
|
||||
if kind == 'thincast':
|
||||
|
||||
@@ -1 +1 @@
|
||||
Y7IpJNU/ne7JUqmOqNPu5gPlCWRDjK6nYKK69K6yxjEu7PT6g1ZkGlrNS2QeQY9bvOuxTlWF8nF+inbQTUQOte6rIX8kSZUJFcOKbxxcWDJiJvPArE5iKCJPpPPHFFH97MVVDYuYT4C5XvR7bDQNVlmxB6oUGvO/71mC4D3gxau1FA24fISRio3aCUVWFjEBlt55PyVhg9qn4r+jBP4bwBVW1NmmjONsIrf6+pvI3gIspYIwzBg9Nflv67aKY7tLdylkcQ7lHx2pY20onaDuT+WGRlQdqc4K0kAzZyTO9FEe/SGe0Nsi0BPMBK1LjFtNJ0KQABLWoTZWSXgloY/2JQvoOC1Z57K4g9R8Nq2BDNpCWADz2nP713zt30dK4Emg6Uh3lkew4zF98atY9Mb5bdNmzQp3dCv9xGAGPm66eIqQUEKDt7zone6j6r81c8jPbl7m/9f/iul8d3a4bPEv5DMHTL23YdFSc6AHDp32ngaB4qLxgtDCvQhnkrayqiYHOlYnS1A/TBS7c2K/Od0nZvuxZKUuDiC7RlSxEAo/EdmWSbeA01cYeh7v0lkdkQaOMGI45DPjLaCwuhgb85cbHcFEDo1CpZSYhyhqApx15/0Jt/CIuFM3FG0cf4B6/6T7Ll7IqGCeTl6nuF2N3ux1ND7UAMBpqjWAlg9/Y7T+aq4=
|
||||
QvtwKeb/U+eyrCDzuaYDwqzgP0zSbKOo49gNPDs4h9w12D6NJsn4F8fsyaUQ7H8PQaIID+lThQGPGTKKYN0wNrhFHYx+PchgeyWOJkfvjlPDxu4JKkwmdlkvHAkfHjW7rJbzh90UkhJmRev3fX7mMAqNBUSbXEcL0/mB31iELzhMYY+RHrMrMpcIO86R0XAxNcaEnJhSW4gQuXonhRf6vrRfWbexqce9+XtftqxbOINlSgRFaFWdZu0Mtdm2kQ2FWq9XGxebha2+5PC1PRBhoxCRip2fEcTn9PzEy8gOjhm9masK8UJ/isVcfiM/ISJPbyDz3jSPV9Z+xtYkcrVQKV+GwvPuj3GCdMInxzAkUEPPNVTnqupHKfXXjAhi+sYZHO+TC0F79FiydxZmxMrJjcZbt+e1rCSDSzKdXn/WTHAuwTtwUj8cbrkrEwHrZWtQzgSGHSK/PlunZD7ASYg6QP7Dq8HRaYT1RmRmjH0tVzs/7y/HYMwdg0MI17zJcEyG7Q67PPa/RcUeSZ4eOMetnTnwPv29u9KpuAZm2P8mn+y4dMaRTC2uAARIHg77khWbVElhoO8JpVb31yHeLENvBmRxZv3Gli404cmzrH66N38xWHadZXYP6fiErptLGPdsL0sGKZRHbAZUjqppx5qwHmHWaNuBY2XOfIrlFvOr5UQ=
|
||||
@@ -1,11 +1,21 @@
|
||||
import typing
|
||||
import shutil
|
||||
import os
|
||||
import logging
|
||||
import subprocess
|
||||
import os.path
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
# Asegura que subprocess y shutil estén en el scope global para clientes antiguos (3.6)
|
||||
globals()['subprocess'] = subprocess
|
||||
globals()['shutil'] = shutil
|
||||
globals()['os'] = os
|
||||
globals()['os.path'] = os.path
|
||||
globals()['typing'] = typing
|
||||
|
||||
try:
|
||||
from uds.log import logger # For UDS Clients 3.6
|
||||
except ImportError:
|
||||
import logger
|
||||
logger = logger.getLogger(__name__) # For UDS Clients 4.0
|
||||
|
||||
# On older client versions, need importing globally to allow inner functions to work
|
||||
import subprocess # type: ignore
|
||||
@@ -55,7 +65,7 @@ def _exec_client_with_params(executable: str, params: typing.List[str], unlink_f
|
||||
tools.addFileToUnlink(unlink_file)
|
||||
|
||||
def exec_udsrdp(udsrdp: str, port: int) -> None:
|
||||
logging.debug('UDSRDP client will use command line parameters')
|
||||
logger.debug('UDSRDP client will use command line parameters')
|
||||
params: typing.List[str] = [os.path.expandvars(i) for i in [app] + sp['as_new_xfreerdp_params'] + [f'/v:127.0.0.1:{port}']] # type: ignore
|
||||
_exec_client_with_params(udsrdp, params)
|
||||
|
||||
@@ -66,7 +76,7 @@ def exec_new_xfreerdp(xfreerdp: str, port: int) -> None:
|
||||
params = [xfreerdp, dest_filename, f'/p:{sp.get("password", "")}'] # type: ignore
|
||||
_exec_client_with_params(xfreerdp, params, unlink_file=dest_filename)
|
||||
else:
|
||||
logging.debug('XFREERDP client will use command line parameters')
|
||||
logger.debug('XFREERDP client will use command line parameters (xfreerdp)')
|
||||
params: typing.List[str] = [os.path.expandvars(i) for i in [app] + sp['as_new_xfreerdp_params'] + [f'/v:127.0.0.1:{port}']] # type: ignore
|
||||
_exec_client_with_params(xfreerdp, params)
|
||||
|
||||
@@ -77,7 +87,7 @@ def exec_thincast(thincast: str, port: int) -> None:
|
||||
params = [thincast, dest_filename, f'/p:{sp.get("password", "")}'] # type: ignore
|
||||
_exec_client_with_params(thincast, params, unlink_file=dest_filename)
|
||||
else:
|
||||
logging.debug('Thincast client will use command line parameters')
|
||||
logger.debug('Thincast client will use command line parameters (xfreerdp)')
|
||||
params: typing.List[str] = [os.path.expandvars(i) for i in [app] + sp['as_new_xfreerdp_params'] + [f'/v:127.0.0.1:{port}']] # type: ignore
|
||||
_exec_client_with_params(thincast, params)
|
||||
|
||||
@@ -108,8 +118,7 @@ if fs.check() is False:
|
||||
|
||||
# If thincast exists, use it. If not, continue with UDSRDP/XFREERDP as before
|
||||
if thincast_executable:
|
||||
logging.debug('Thincast client found, using it')
|
||||
#logging.debug(f'RDP file params: {sp.get("as_file", "")}')
|
||||
logger.debug('Thincast client found, using it')
|
||||
fnc, app = exec_thincast, thincast_executable
|
||||
else:
|
||||
xfreerdp: typing.Optional[str] = tools.findApp('xfreerdp3') or tools.findApp('xfreerdp') or tools.findApp('xfreerdp2')
|
||||
@@ -130,5 +139,16 @@ else:
|
||||
'''
|
||||
)
|
||||
|
||||
# Asegura que app y fnc sean globales para clientes antiguos (3.6)
|
||||
globals()['app'] = app
|
||||
globals()['fnc'] = fnc
|
||||
|
||||
# Añade las funciones al scope global para clientes antiguos (3.6)
|
||||
globals()['_prepare_rdp_file'] = _prepare_rdp_file
|
||||
globals()['_exec_client_with_params'] = _exec_client_with_params
|
||||
globals()['exec_udsrdp'] = exec_udsrdp
|
||||
globals()['exec_new_xfreerdp'] = exec_new_xfreerdp
|
||||
globals()['exec_thincast'] = exec_thincast
|
||||
|
||||
if fnc is not None and app is not None:
|
||||
fnc(app, fs.server_address[1])
|
||||
|
||||
@@ -1 +1 @@
|
||||
n3a+b8OD5i8IAbP/fK2c72A1UzRScr7kH2BeY4zSaVJoJf+Xn4+F6Osm0emtS+1muStwHvIE9Hqnxdg8lbYHIrjRAGvFazs5xcExIvYU1rVA/gmBjaViqUl6SQc+3zWa7xXwOVrwQdoXF9WGYOAH8DAPT/aiKgeaCoKlCFNyrxlMImxWPlWRvCKrZQlWxvB6rKFC0apO+xxi4FU3xXIomWBufnLuDppYL+xwVzMj4YNWec3rdV6RT8cpBQzfkNec7rgHBOB+Py2BnY54TtMqlECpXZlEYy4NVORI0rwZ+aK8dvpGvRS4nWQnq3edRkWTzDZAo+Kkp17/fmCTEGucQ/TC4Y2qBoB35kxQmv1aWhWWyJ/BdpHI6lNJR884lK/yup3I+vQbf7ZJzu6wT98YHk0x+rsPt97FPxJsVdsxWG4IcaVgheuIjlYPNShMDoy/slOyEz/k0j7jWAhRu0WWMHjI/ozighX+jHmNeIG9EPim0sKZ/04okSXxhwwC1UzwcevUdrI2eUyaUEbq9Ua3SMCuQNmDVKFlJJ6PUucbWvgKsdsSMbW1L4syA41yTPk9dcYHlu32k8oaZ1o3QIDw7Do48pygwnWSJM9XlynFcRcYmOikRIrINJlJmKH6oY+ez9nva7cAV6rFel+jk7bgSZUrKMfdsnsLh1PSabnLJ/s=
|
||||
PwNGSn1G1RSI6m56VoamK3c3DASZhca6H9ejQ8gzX3Izny7c/JjKAd6vU9/BL7vyM9a/46UaOPDH+R9kD7j6rbtvwo/32ULDqGU9Dt+9taRyzediIdfwg/XkI5A2H7pxamXiFWAwLW24FFSBEa5/DBPSSjBwFaEeJbGm6IqSuDfJQdR4C/6uy0wbwakMUhMsY6ZcUYB7QOKa4sKF6jQorjZ+RUHkkPiEtTCZvjP56c743B0nZ5qqBlA6sOV4vUPDntG8RSwdo6ds73foz8+Q/13qlTCh5IA7E+S2HoxRuF3nPDUL6ML1wHfWLlUnAQjrmYtD59YDh1PCBVuqasHZ6Qe4ShXepSwIzJUp4bmd3gQh6U7FMfbv0T9e9gx7WYQ1LUNJtpLXM0c84cLGAO0a6sPBJZ6S6R5Pxc9OCRxwykkBIm9FEjE8+8bcDyRGiTRtw/t7HUHP4gUM06sp/wnx63COKGzk9GBb+vMcx9VHH5sAZKs3Ghs8DB/7z4C8iIsIqBxVesWYAJQlngIXwxTAw9llrFnSTDPEmB9e2HgsWejezE35s1bICF5r0L9LxxCcqna+YkGFrgAjo9to9BW3WjRMmcRqvEQmucwCEcqaVJXBw2ffvGZEozrJ6HSOCpKKd4Hz2SxWS8MaQQHYMlysPo4I6pyPXGPHT4SCGL+XoNg=
|
||||
@@ -51,4 +51,4 @@ if executable is None:
|
||||
|
||||
subprocess.Popen([executable, filename]) # nosec
|
||||
|
||||
# tools.addFileToUnlink(filename)
|
||||
tools.addFileToUnlink(filename)
|
||||
|
||||
@@ -1 +1 @@
|
||||
R3sdB3d7hhz6VEoAGNzdX0vIKgss4Xe1aEU62cTQKIA7Inw2zHkaBK0wRVxZqMYH5Of/iiyMiG+NlKFAWutSrOOthoyVT83RNtDpR4F+vDTZMpW2qopiiK6XbxX5PuJq/E3UWNsnElZasAIpJk9rKqlNEJ+tkycWyDkIYIHxE6M2yrqH+dWx/V3AaDMURtnzuZStzpxPMuEzezNdCI9Kbs1fCwSz18SRSkAtNINiMJbgBV573wwKEUUgKLzRHn1ijRk65OHRVLFDlRgXz/ArN0/nkW/FkQ9pYJW5MosD4TJfptO8QZ104jYPM960maMxObLWa4LZyzEVNZ2uIE9xIWHh9SCZ3zv37DfSU6hM9n4gOKlIVGIO5hrctjZLzAwRcgsBFcXLXxtlrHQERjh7Zgr5mevjXz0yO+76pUbdgEWVwlT8G5SG4yq7083drwfNgMv5uht8GyRqes+FD952ECjv+hVeoLRItg+mxaUnILHHJOyw8A47Ex0PikHzpbT/SxzQA+CkxEMRPSD6GDPBYiKBAYm+b0Yazo5Yzo85S2GRubPaEVp6UQ6AVgWEtsfhx5yeU+tJx6AD1+MYEpB04Re6XjMeSV5zdDsHkS/HQ7kafbxS0RxU78e0LEltbW06zGNGvk/cZlIr1SE93Ztvyi1R4wZNdDRaM6vLKOD3RGo=
|
||||
b0NrFPNRgkQmGycaL/gUhFKShW34N3Yto33JyDT9ructKOTEzT8qCEnvp5ypb0vwZQBhCfya0ExGDO77DdRPb2QAvtQylPxaX+D7FdLAKZO8WOw+clCJGJHFlpiAi7a1lY0ve6dfJotu47vNppmOy5RGO1Iz9FMQuOpq0xNXcrGz9I5zez47Se0FkhU1XlYgrrI8uexQqc8faz+nw6fJE4ADnfqo+b6mJmRIm7gbE9VyMZz6NR65zqtcyOWgmRrDOO3w6dirEYOIES2GFfZXOl4L+5bIDTVbtrYGoTtPIgmom8fjFfOP2qWAhjQ7jsjDqC0pPshOlNqB4FyORoAEzQ10yt53bPJHaOe/9uzW75THNGCj8AVntzbLGDghdJG49Yv9gAxJPFpdkGhtesy92Q0pryDjtTtLBtTyWvj9iCpUremYp71tROFHdEY40ypG7YDmDHNdkK6vz99MsFwHpcjs9XnHAJlaJHy96FdI6dHBC4ePlaJSVABOb9SS74WyYVB/VOF6bZ55mbvD7XpzzsG7fk/JV6If047tULGnCdWJCvOZ05rI0H1nUJAwgg42VmOKxNKJnBKdP0hVPuvRg2L2pNDioocXxnXvYfUWBr6bq/6Vkv/qrkkkWy+XMhTSGD9nwskhpFdOMNfjeelr50bSGcl2QGzEO2SnKzrfdTo=
|
||||
@@ -11,12 +11,14 @@ from uds import tools # type: ignore
|
||||
|
||||
# Lets find remote viewer
|
||||
# There is a bug that when installed, the remote viewer (at least 64 bits version) does not store correctly its path, so lets find it "a las bravas"
|
||||
extraPaths = ()
|
||||
executable = None
|
||||
|
||||
for env in ('PROGRAMFILES', 'PROGRAMW6432'):
|
||||
if env in os.environ:
|
||||
extraPaths += tuple(p + '\\bin' for p in glob.glob(os.environ[env] + '\\VirtViewer*')) # type: ignore
|
||||
|
||||
executable = tools.findApp('remote-viewer.exe', extraPaths)
|
||||
for base_folder in glob.glob(os.environ[env] + '\\VirtViewer*'):
|
||||
executable = tools.findApp('remote-viewer.exe', os.path.join(base_folder, 'bin'))
|
||||
if executable is not None:
|
||||
break
|
||||
|
||||
if executable is None:
|
||||
raise Exception(
|
||||
|
||||
@@ -1 +1 @@
|
||||
KztBdwmg7Pz6I0Qu0MIGN8M/TC5ggVSjeqpWNK5fmi63zIRv1J2Mpv/v+BbFms/T6veQqJDQ7IngTavo3GMcJZxbLyGyTu192Hzj29nmxTWMTyhuUWEP2ye+0ctVRqz3L6qiJuaQ0b6lQwWTdXq858XvtB04+BVaEgpWXkKHRwdl1P1ra++pEOm4bFBblArpQxLwBoOMyljNJRC9SP7/zvYnXc2cbi/VJXowy9Mk4jUckKyIyCurUblNU54CVgQE7YULx7YHy7LPTxZ8Ul9VujEJsMkGKKpanmZwM8LirJQTqFBLUxvmLWMcQXGoKHMIiX8aBWpUYD9MB+Xf1XmPOXaC12XVMKckCUtoSisp9C4/Hk34P5Z/uXA5QGvNbnUozjgJnYcJXBPE9xyVV91t02YefANBe2C20cxeJfMi8ya36grA6rr0XAz11pHarji9IfHxNx6CGtsGNuA6zQC3Sj0VBgwV5i0ZUBFnNU16masMHm2i9t4AZCos81HuD/K2qNawFDOVGNvSrFtDqO5XdKoQd79jwKc/9EH1d59tQk23QNEcZFN1k4izdQ1JiA0EJBS7MdQJfqJ1/JdxFY+HMPWCfw7CmD0E9kTCL+iY6+iqEP6Mxi66ZWxVuKkur9vB+yzkzpocq3f8t0Eq06Y6rQM5j/sH6WxA9nAnUA1oG3g=
|
||||
cH1rujpb4TXrilcSsjLckNv8xDUILhuLl4Ree3LpGOYY9fmDnIYU3xX9TzJAGhIfBonUuwdG1/m/y89SgyfFihQp7YN2DIyIp0Rm9nzMo12u6efNPO4Ae8X9UweNedKie9E9giMEPTMRSglhkSyMbV9pRRh5gPu49+jNRRMbs7Yhsx9MVaJnfSXrCVMx13aZTr0tCEkvZqcex6DYd0TwVcWN5fZgB7haCUQ//FCFXIVxwj72EBtwcIqDeDi97JOLXmLQ3sQo6zNeB0KutQGagNhvYsfCdkUQZPJDK+UrvXBg1q7IjCFC5CuilFzxcDcetmzAWxG1kKotkFfOPhRYYyUvWdrRvVKbRFrfDeFhWOfWzqhQokvRBes52s4YoQygnAsnamkYr9r27SHDLKyz/6i2eI7LiTdCG3P/LaPZI9alxkgjTKfqXqyaEed+5tWNXrniffZH4liIK+YtGVI5DpdsXbxOiQF8TeJOTyG4kLPjstS1dvc7OeP59BwCohGBR1Ebcmj4cjh/H112zzfMs1C9UuN8Jg3E+BeSTGsqObMti51Z+/FL6UA4OYx0WitXigxBeRtYxC9PlmXXpt4V/Wv3j4/fnDK94q6VUtnMq/PL0kMt6XiIjE5vTjm1LhHNiC2xMABFSZ2tBE9up3uFFJ8z6mNTGlJEpfrUHSAGcFY=
|
||||
@@ -12,12 +12,13 @@ from uds.tunnel import forward # type: ignore
|
||||
|
||||
# Lets find remote viewer
|
||||
# There is a bug that when installed, the remote viewer (at least 64 bits version) does not store correctly its path, so lets find it "a las bravas"
|
||||
extraPaths = ()
|
||||
executable = None
|
||||
for env in ('PROGRAMFILES', 'PROGRAMW6432'):
|
||||
if env in os.environ:
|
||||
extraPaths += tuple(p + '\\bin' for p in glob.glob(os.environ[env] + '\\VirtViewer*')) # type: ignore
|
||||
|
||||
executable = tools.findApp('remote-viewer.exe', extraPaths)
|
||||
for base_folder in glob.glob(os.environ[env] + '\\VirtViewer*'):
|
||||
executable = tools.findApp('remote-viewer.exe', os.path.join(base_folder, 'bin'))
|
||||
if executable is not None:
|
||||
break
|
||||
|
||||
if executable is None:
|
||||
raise Exception(
|
||||
@@ -38,9 +39,7 @@ if sp['ticket']: # type: ignore
|
||||
|
||||
# Check that tunnel works..
|
||||
if fs.check() is False:
|
||||
raise Exception(
|
||||
'<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>'
|
||||
)
|
||||
raise Exception('<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>')
|
||||
|
||||
fss = None
|
||||
if sp['ticket_secure']: # type: ignore
|
||||
|
||||
@@ -1 +1 @@
|
||||
nhj3N8ZUuQwdkFb68fTd57q0xEOtZHYiaHgW0xBOE9JKI7AhjUDDSt2Zvvr1QzTX2HzNSLNiQZ0wAPhAd1ol46xAcIL9GVEmJSlSb6BXBfO21YEstVwxM3BbAZlAQOK7e9NtxzeM8O+GcgvxFrLkLxrgnKw1odH8RDQiS8B/Ed1BCoWAS+pNbbHOwMOoL7o8rIPwSho2FBP+ulRb9RiIVfZSyKttJ+ryC+QSCOIPSdW38uk2tKD0cKhDao/kpigwHOPRmWc2jHULXHgOdUzX759Brg7aMX+saFYbd7bq6YvDIJ5V7jCucqnOyMfuXuFuu7sgRvNJibqoNpYPS+WAYM11nv5GXBd4t9+miVKKsh/llhYvKhY0wvUG7REIUYdojXR1yy1JENo+BS7SvI8wQZCKx1//TVNxMTQ3zYu6XzK5HZD+lAUDnnTmgIxWTLjwSDG8nf95i+D0sofVYZCHPYlZh8bkbxNBmk0LHNfT6C3cyFZJSTrYMS1m2O3Siq0bNI9vvNWG0Vvr2dxINReWrI2mvTrVXfN9j6CFAZHI5QY+iypTAXMLp/exR1+iN0K8QXVdNC16xKTDQLAOukK1+IbCNK2T+GZQHtOlPi34mLa5DUOScmpjlcdt/4szRFjGaWdQclj2+gtfXcN4DiqbwhFGw739ayY/CCJB7KfPnak=
|
||||
WfChDg7NFGG1NjcvcVNA3I0TAiDG6IeRojb51w4K4iMYSUm540o2jHW2FpYD+tmcMQCmf788kw+2R5GHXMA37gXo1qHB1QlkXM0aCTJLp6UyZ8i8CcLsyWHrkjp2NzI24XQLNSYHAJn2zTfhCMd5Zyqw3gZmMTQKmkX+f+t2Oi0FGHwVhCp6ZVCRKLWKEFcc6b/uYFJ6IP9WaSXLg3ftOLw/e+GDzdYsrf9m2ytCBlXtm9XrtyhEszpIs+bseIUTbhKw2FDr2UoORezQPFN8pLZE/WoQ+A87tgfRaf0foc/LOm/Yo5Xkh5p7Q33eYY6jsGWiFWgYugQ3PzLHrK8agpZTYmHJymVUHItvZxGR2w1npIxAyzv6FM7aLhOSi+0nXLotCY01nRzBxCs46kmSapjKi2XpaRVskiM1dPdYJ8TUCKb9c2Gb7MUxVrXnWOgDBZZx5yQJaEKz5JXYlHwHb74xDleqwl93Vbv4KdKvYd/sBwK0uqdpojCzIIvNuwfpBqXrFWORGUnkrnIK0cCw2tA+oqBjMyFlIS6NhLLYfdqvsVPMV8CP3hRlmIX42EVi/f7XLHZQuOJcEhZuLg8RqwrSPX7b4sC/KLjOmXdMsUulwOFyVk39x5Ze6mNjDqxO7RNA4hZ3+6TlZnCbo5keZIEretOk+JwkWCZEbLFz5+I=
|
||||
@@ -31,6 +31,7 @@ Author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
import datetime
|
||||
import logging
|
||||
import typing
|
||||
|
||||
from django.db.models import Count
|
||||
|
||||
@@ -41,7 +42,7 @@ from uds.core.util.model import sql_now
|
||||
from uds.core.util import config
|
||||
|
||||
# from uds.core.util.config import GlobalConfig
|
||||
|
||||
MAX_BATCH_SIZE: typing.Final[int] = 32768
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -52,6 +53,7 @@ class LogMaintenance(Job):
|
||||
friendly_name = 'Log maintenance'
|
||||
|
||||
def run(self) -> None:
|
||||
logger.debug('Starting Log maintenance')
|
||||
# Select all disctinct owner_id and owner_type and count of each
|
||||
# For each one, check if it has more than max_elements, and if so, delete the oldest ones
|
||||
for owner_id, owner_type, count in (
|
||||
@@ -68,19 +70,30 @@ class LogMaintenance(Job):
|
||||
continue
|
||||
|
||||
max_elements = owner_type.get_max_elements()
|
||||
# Ensures that last hour logs are not deleted
|
||||
removing_before = sql_now() - datetime.timedelta(seconds=3600)
|
||||
|
||||
if 0 < max_elements < count: # Negative max elements means "unlimited"
|
||||
# We will delete the oldest ones
|
||||
for record in models.Log.objects.filter(
|
||||
owner_id=owner_id,
|
||||
owner_type=owner_type,
|
||||
created__lt=removing_before,
|
||||
).order_by('created', 'id')[: count - max_elements + 1]:
|
||||
record.delete()
|
||||
logger.debug(
|
||||
'Log maintenance: Owner %s of type %s has %d logs, max is %d, cleaning up',
|
||||
owner_id,
|
||||
owner_type.name,
|
||||
count,
|
||||
max_elements,
|
||||
)
|
||||
ids_to_delete = list(
|
||||
models.Log.objects.filter(
|
||||
owner_id=owner_id,
|
||||
owner_type=owner_type,
|
||||
)
|
||||
.order_by('created', 'id')
|
||||
.values_list('id', flat=True)[max_elements : max_elements + MAX_BATCH_SIZE]
|
||||
)
|
||||
|
||||
if ids_to_delete:
|
||||
models.Log.objects.filter(id__in=ids_to_delete).delete()
|
||||
|
||||
# Also, delete all logs older than config.GlobalConfig.STATS_DURATION.as_int()*2 days
|
||||
# This is to ensure we do not have "orphan" logs too old
|
||||
models.Log.objects.filter(
|
||||
created__lt=sql_now() - datetime.timedelta(days=config.GlobalConfig.STATS_DURATION.as_int() * 2)
|
||||
).delete()
|
||||
logger.debug('Log maintenance done')
|
||||
|
||||
@@ -288,3 +288,4 @@ class ServiceCacheUpdater(Job):
|
||||
self.reduce_l2_cache(servicepool_stat)
|
||||
elif servicepool_stat.is_l2_cache_growth_required(): # We need more L2 items
|
||||
self.grow_l2_cache(servicepool_stat)
|
||||
logger.debug('Cache checking done')
|
||||
@@ -42,7 +42,10 @@ class SystemInformation(Job):
|
||||
friendly_name = 'System Information update'
|
||||
|
||||
def run(self) -> None:
|
||||
logger.debug('System information started')
|
||||
try:
|
||||
cluster.store_cluster_info()
|
||||
except Exception as e:
|
||||
logger.error('Error storing cluster hostname: %s', e)
|
||||
|
||||
logger.debug('System information done')
|
||||
|
||||
@@ -258,8 +258,8 @@ class ServerManagerManagedServersTest(UDSTestCase):
|
||||
uuid, counter = assignation
|
||||
# uuid shuld be one on registered servers
|
||||
self.assertTrue(uuid in self.all_uuids)
|
||||
# And only one assignment, so counter is 1
|
||||
self.assertTrue(counter, 1)
|
||||
# And only assignements so counter is assignations + 1
|
||||
self.assertTrue(counter, assignations + 1)
|
||||
# Server locked should be None
|
||||
self.assertIsNotNone(models.Server.objects.get(uuid=uuid).locked_until)
|
||||
|
||||
|
||||
@@ -202,7 +202,6 @@ class TestXenClient(UDSTransactionTestCase):
|
||||
'start_delay': 0,
|
||||
'shutdown_delay': 0,
|
||||
'order': 0,
|
||||
'ha_restart_priority': '',
|
||||
'ha_always_run': False,
|
||||
'ha_restart_priority': '',
|
||||
'recommendations': '',
|
||||
|
||||
@@ -34,22 +34,29 @@ import functools
|
||||
import dataclasses
|
||||
from unittest import mock
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class AutoSpecMethodInfo:
|
||||
name: str|typing.Callable[..., typing.Any]
|
||||
name: str | typing.Callable[..., typing.Any]
|
||||
returns: typing.Any = None # Can be a callable or a value
|
||||
partial_args: typing.Tuple[typing.Any, ...] = ()
|
||||
partial_kwargs: dict[str, typing.Any] = dataclasses.field(default_factory=dict[str, typing.Any])
|
||||
|
||||
|
||||
def autospec(cls: type, metods_info: collections.abc.Iterable[AutoSpecMethodInfo], **kwargs: typing.Any) -> mock.Mock:
|
||||
needs_self: bool = False # If the method needs self as first argument (for side_effect callables)
|
||||
|
||||
|
||||
def autospec(
|
||||
cls: type,
|
||||
metods_info: collections.abc.Iterable[AutoSpecMethodInfo],
|
||||
test_data: dict[str, typing.Any]|None = None,
|
||||
**kwargs: typing.Any
|
||||
) -> mock.Mock:
|
||||
"""
|
||||
This is a helper function that will create a mock object with the same methods as the class passed as parameter.
|
||||
This is useful for testing purposes, where you want to mock a class and still have the same methods available.
|
||||
|
||||
|
||||
Take some care when using decorators and methods instead of string for its name. Ensure decorator do not hide the original method.
|
||||
(using functools.wraps or similar will do the trick, but take care of it)
|
||||
|
||||
|
||||
The returned value is in fact a mock object, but with the same methods as the class passed as parameter.
|
||||
"""
|
||||
obj = mock.create_autospec(cls, **kwargs)
|
||||
@@ -58,9 +65,27 @@ def autospec(cls: type, metods_info: collections.abc.Iterable[AutoSpecMethodInfo
|
||||
name = method_info.name if isinstance(method_info.name, str) else method_info.name.__name__
|
||||
mck = getattr(obj, name)
|
||||
if callable(method_info.returns):
|
||||
mck.side_effect = functools.partial(method_info.returns, *method_info.partial_args, **method_info.partial_kwargs)
|
||||
#mck.side_effect = method_info.returns
|
||||
if method_info.needs_self:
|
||||
def side_effect_with_self(*args: typing.Any, **kwargs: typing.Any) -> typing.Any:
|
||||
return method_info.returns(obj, *args, **kwargs)
|
||||
mck.side_effect = side_effect_with_self
|
||||
else:
|
||||
mck.side_effect = functools.partial(
|
||||
method_info.returns, *method_info.partial_args, **method_info.partial_kwargs
|
||||
)
|
||||
# mck.side_effect = method_info.returns
|
||||
else:
|
||||
mck.return_value = method_info.returns
|
||||
|
||||
return obj
|
||||
|
||||
obj._test_data = dict() if test_data is None else test_data
|
||||
|
||||
def get_test_data(attr: str) -> typing.Any:
|
||||
return obj._test_data.get(attr)
|
||||
|
||||
def set_test_data(attr: str, data: typing.Any) -> None:
|
||||
obj._test_data[attr] = data
|
||||
|
||||
obj.get_test_data = get_test_data
|
||||
obj.set_test_data = set_test_data
|
||||
|
||||
return obj
|
||||
|
||||
Reference in New Issue
Block a user