1
0
mirror of https://github.com/dkmstr/openuds.git synced 2024-12-22 13:34:04 +03:00

chore: Update UDS admin runtime, polyfills, and main scripts. Updated minor cache definitions

This commit is contained in:
Adolfo Gómez García 2024-05-03 03:34:56 +02:00
parent 6adcc3e1f4
commit 04f144cd2d
No known key found for this signature in database
GPG Key ID: DD1ABF20724CDA23
9 changed files with 70 additions and 35 deletions

View File

@ -34,11 +34,13 @@ import typing
# Default timeouts, in seconds
DEFAULT_CACHE_TIMEOUT: typing.Final[int] = 60 * 3 # 3 minutes
LONG_CACHE_TIMEOUT: typing.Final[int] = DEFAULT_CACHE_TIMEOUT * 20 # 1 hour
EXTREME_CACHE_TIMEOUT: typing.Final[int] = LONG_CACHE_TIMEOUT * 24 # 1 day
SHORT_CACHE_TIMEOUT: typing.Final[int] = DEFAULT_CACHE_TIMEOUT // 3 # 1 minute
SHORTEST_CACHE_TIMEOUT: typing.Final[int] = 3 # 3 seconds
BASE_CACHE_TIMEOUT: typing.Final[int] = 3 # 3 seconds
DEFAULT_CACHE_TIMEOUT: typing.Final[int] = BASE_CACHE_TIMEOUT * 60 # 3 minutes
LONG_CACHE_TIMEOUT: typing.Final[int] = BASE_CACHE_TIMEOUT * 60 * 60 # 1 hour
EXTREME_CACHE_TIMEOUT: typing.Final[int] = BASE_CACHE_TIMEOUT * 60 * 60 * 24 # 1 day
SHORT_CACHE_TIMEOUT: typing.Final[int] = BASE_CACHE_TIMEOUT * 20 # 1 minute
SHORTEST_CACHE_TIMEOUT: typing.Final[int] = BASE_CACHE_TIMEOUT # 6 seconds
# Used to mark a cache as not found
# use "cache.get(..., default=CACHE_NOT_FOUND)" to check if a cache is non existing instead of real None value

View File

@ -102,7 +102,9 @@ class DynamicPublication(services.Publication, autoserializable.AutoSerializable
retries = data.get('retries', 0) + 1
data['retries'] = retries
if retries > self.max_retries: # Use self to access class variables, so we can override them on subclasses
if (
retries > self.max_retries
): # Use self to access class variables, so we can override them on subclasses
return self._error(f'Max retries reached')
return None
@ -190,7 +192,6 @@ class DynamicPublication(services.Publication, autoserializable.AutoSerializable
self._queue.insert(0, Operation.RETRY)
return types.states.TaskState.FINISHED
def service(self) -> 'DynamicService':
return typing.cast('DynamicService', super().service())

View File

@ -186,16 +186,6 @@ class DynamicService(services.Service, abc.ABC): # pylint: disable=too-many-pub
# Default is to stop "hard"
return self.stop(caller_instance, vmid)
def suspend(
self, caller_instance: 'DynamicUserService | DynamicPublication', vmid: str
) -> None:
"""
Suspends the machine
Defaults to shutdown_machine.
Can be overriden if the service supports suspending.
"""
return self.shutdown(caller_instance, vmid)
@abc.abstractmethod
def delete(
self, caller_instance: 'DynamicUserService | DynamicPublication', vmid: str

View File

@ -132,6 +132,17 @@ class DynamicUserService(services.UserService, autoserializable.AutoSerializable
types.services.Operation.FINISH,
]
_move_to_l1_queue: typing.ClassVar[list[types.services.Operation]] = [
types.services.Operation.START,
types.services.Operation.FINISH,
]
_move_to_l2_queue: typing.ClassVar[list[types.services.Operation]] = [
types.services.Operation.SUSPEND,
types.services.Operation.SUSPEND_COMPLETED,
types.services.Operation.FINISH,
]
@typing.final
def _reset_checks_counter(self) -> None:
with self.storage.as_dict() as data:
@ -227,7 +238,11 @@ class DynamicUserService(services.UserService, autoserializable.AutoSerializable
self.do_log(types.log.LogLevel.ERROR, f'Error removing machine: {e}')
else:
logger.debug('Keep on error is enabled, not removing machine')
self._set_queue([types.services.Operation.FINISH] if self.keep_state_sets_error else [types.services.Operation.ERROR])
self._set_queue(
[types.services.Operation.FINISH]
if self.keep_state_sets_error
else [types.services.Operation.ERROR]
)
return types.states.TaskState.FINISHED
self._set_queue([types.services.Operation.ERROR])
@ -280,7 +295,6 @@ class DynamicUserService(services.UserService, autoserializable.AutoSerializable
self._queue.insert(0, types.services.Operation.RETRY)
return types.states.TaskState.FINISHED
# Utility overrides for type checking...
# Probably, overriden again on child classes
def service(self) -> 'service.DynamicService':
@ -343,6 +357,14 @@ class DynamicUserService(services.UserService, autoserializable.AutoSerializable
self._set_queue(self._create_queue_l2_cache.copy())
return self._execute_queue()
@typing.final
def move_to_cache(self, level: types.services.CacheLevel) -> types.states.TaskState:
if level == types.services.CacheLevel.L1:
self._set_queue(self._move_to_l1_queue.copy())
else:
self._set_queue(self._move_to_l2_queue.copy())
return self._execute_queue()
@typing.final
def process_ready_from_os_manager(self, data: typing.Any) -> types.states.TaskState:
# Eat the WAIT operation if it is in the queue
@ -364,14 +386,26 @@ class DynamicUserService(services.UserService, autoserializable.AutoSerializable
self.cache.put('ready', '1', consts.cache.SHORT_CACHE_TIMEOUT // 2) # short cache timeout
self._set_queue([types.services.Operation.FINISH])
else:
self._set_queue([types.services.Operation.START, types.services.Operation.START_COMPLETED, types.services.Operation.FINISH])
self._set_queue(
[
types.services.Operation.START,
types.services.Operation.START_COMPLETED,
types.services.Operation.FINISH,
]
)
except Exception as e:
return self._error(f'Error on setReady: {e}')
return self._execute_queue()
def reset(self) -> types.states.TaskState:
if self._vmid != '':
self._set_queue([types.services.Operation.RESET, types.services.Operation.RESET_COMPLETED, types.services.Operation.FINISH])
self._set_queue(
[
types.services.Operation.RESET,
types.services.Operation.RESET_COMPLETED,
types.services.Operation.FINISH,
]
)
return types.states.TaskState.FINISHED
@ -586,7 +620,7 @@ class DynamicUserService(services.UserService, autoserializable.AutoSerializable
This does nothing, as it's a NOP operation
"""
pass
def op_destroy_validator(self) -> None:
"""
This method is called to check if the userservice has an vmid to stop destroying it if needed
@ -745,7 +779,7 @@ class DynamicUserService(services.UserService, autoserializable.AutoSerializable
This method is called to check if the service is doing nothing
"""
return types.states.TaskState.FINISHED
@typing.final
def op_retry_checker(self) -> types.states.TaskState:
# If max retrieas has beeen reached, error should already have been set
@ -813,7 +847,9 @@ _EXECUTORS: typing.Final[
# Same af before, but for check methods
_CHECKERS: typing.Final[
collections.abc.Mapping[types.services.Operation, collections.abc.Callable[[DynamicUserService], types.states.TaskState]]
collections.abc.Mapping[
types.services.Operation, collections.abc.Callable[[DynamicUserService], types.states.TaskState]
]
] = {
types.services.Operation.INITIALIZE: DynamicUserService.op_initialize_checker,
types.services.Operation.CREATE: DynamicUserService.op_create_checker,

File diff suppressed because one or more lines are too long

View File

@ -102,6 +102,6 @@
</svg>
</div>
</uds-root>
<script src="/uds/res/admin/runtime.js?stamp=1714412827" type="module"></script><script src="/uds/res/admin/polyfills.js?stamp=1714412827" type="module"></script><script src="/uds/res/admin/main.js?stamp=1714412827" type="module"></script></body>
<script src="/uds/res/admin/runtime.js?stamp=1714699983" type="module"></script><script src="/uds/res/admin/polyfills.js?stamp=1714699983" type="module"></script><script src="/uds/res/admin/main.js?stamp=1714699983" type="module"></script></body>
</html>

View File

@ -76,7 +76,7 @@ class TestProxmovLinkedService(UDSTestCase):
with fixtures.patch_provider_api() as _api:
service = fixtures.create_linked_service()
storage = utils.find_attr_in_list(fixtures.STORAGES_INFO, 'id', service.datastore.value)
storage = utils.search_item_by_attr(fixtures.STORAGES_INFO, 'id', service.datastore.value)
# Ensure available is greater that configured on service
old_available = storage.available # For future tests to restore it
try:

View File

@ -60,7 +60,7 @@ class TestOVirtLinkedService(UDSTransactionTestCase):
for _ in limited_iterator(lambda: state == types.states.TaskState.RUNNING, limit=128):
state = userservice.check_state()
# Ensure machine status is always DOWN, so the test does not end
utils.find_attr_in_list(fixtures.VMS_INFO, 'id', userservice._vmid).status = ov_types.VMStatus.DOWN
utils.search_item_by_attr(fixtures.VMS_INFO, 'id', userservice._vmid).status = ov_types.VMStatus.DOWN
self.assertEqual(state, types.states.TaskState.ERROR)
self.assertGreater(
@ -88,7 +88,7 @@ class TestOVirtLinkedService(UDSTransactionTestCase):
# this user service expects the machine to be started at some point, so after a few iterations, we set it to started
# note that the user service has a counter for max "recheck" without any success, and if reached, it will fail
if counter == 12:
vm = utils.find_attr_in_list(fixtures.VMS_INFO, 'id', userservice._vmid)
vm = utils.search_item_by_attr(fixtures.VMS_INFO, 'id', userservice._vmid)
vm.status = ov_types.VMStatus.UP
state = userservice.check_state()
@ -130,11 +130,11 @@ class TestOVirtLinkedService(UDSTransactionTestCase):
# this user service expects the machine to be started at some point, so after a few iterations, we set it to started
# note that the user service has a counter for max "recheck" without any success, and if reached, it will fail
if counter == 12:
vm = utils.find_attr_in_list(fixtures.VMS_INFO, 'id', userservice._vmid)
vm = utils.search_item_by_attr(fixtures.VMS_INFO, 'id', userservice._vmid)
vm.status = ov_types.VMStatus.UP
# Again, machine will be suspended for L2, so we set it to suspended after a few iterations more
if counter == 24:
vm = utils.find_attr_in_list(fixtures.VMS_INFO, 'id', userservice._vmid)
vm = utils.search_item_by_attr(fixtures.VMS_INFO, 'id', userservice._vmid)
vm.status = ov_types.VMStatus.SUSPENDED
state = userservice.check_state()
@ -180,7 +180,7 @@ class TestOVirtLinkedService(UDSTransactionTestCase):
# this user service expects the machine to be started at some point, so after a few iterations, we set it to started
# note that the user service has a counter for max "recheck" without any success, and if reached, it will fail
if counter == 12:
vm = utils.find_attr_in_list(fixtures.VMS_INFO, 'id', userservice._vmid)
vm = utils.search_item_by_attr(fixtures.VMS_INFO, 'id', userservice._vmid)
vm.status = ov_types.VMStatus.UP
state = userservice.check_state()
@ -221,7 +221,7 @@ class TestOVirtLinkedService(UDSTransactionTestCase):
# skip create and use next in queue
userservice._queue.pop(0) # Remove create
# And ensure vm is up
utils.find_attr_in_list(fixtures.VMS_INFO, 'id', userservice._vmid).status = (
utils.search_item_by_attr(fixtures.VMS_INFO, 'id', userservice._vmid).status = (
ov_types.VMStatus.UP
)
@ -244,7 +244,7 @@ class TestOVirtLinkedService(UDSTransactionTestCase):
state = userservice.check_state()
# Ensure that, after a few iterations, the machine is removed (state is UNKNOWN)
# if counter == 5:
# utils.find_attr_in_list(fixtures.VMS_INFO, 'id', userservice._vmid).status = ov_types.VMStatus.UNKNOWN
# utils.search_item_by_attr(fixtures.VMS_INFO, 'id', userservice._vmid).status = ov_types.VMStatus.UNKNOWN
self.assertEqual(
state, types.states.TaskState.FINISHED, f'Graceful: {graceful}, Counter: {counter}'

View File

@ -163,7 +163,7 @@ class MustBeOfType:
def __repr__(self) -> str:
return self.__str__()
def find_attr_in_list(lst: list[T], attribute: str, value: typing.Any) -> T:
def search_item_by_attr(lst: list[T], attribute: str, value: typing.Any) -> T:
"""
Returns an item from a list of items
"""
@ -172,6 +172,12 @@ def find_attr_in_list(lst: list[T], attribute: str, value: typing.Any) -> T:
return item
raise ValueError(f'Item with id {value} not found in list')
def filter_list_by_attr(lst: list[T], attribute: str, value: typing.Any) -> list[T]:
"""
Returns a list of items from a list of items
"""
return [item for item in lst if getattr(item, attribute) == value]
def check_userinterface_values(obj: ui.UserInterface, values: ui.gui.ValuesDictType) -> None:
"""
Checks that a user interface object has the values specified