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

Some renaming for better significance

This commit is contained in:
Adolfo Gómez García 2024-03-23 23:12:00 +01:00
parent 8f98314c97
commit 9320eb3adf
No known key found for this signature in database
GPG Key ID: DD1ABF20724CDA23
20 changed files with 151 additions and 167 deletions

View File

@ -10,6 +10,7 @@ Author: Adolfo Gómez, dkmaster at dkmon dot com
import abc
import collections.abc
import functools
import logging
import time
import typing
@ -20,11 +21,23 @@ from uds.core.types.services import Operation
from uds.core.util import autoserializable
if typing.TYPE_CHECKING:
from .dynamic_service import DynamicService
from .service import DynamicService
logger = logging.getLogger(__name__)
# Decorator that tests that _vmid is not empty
# Used by some default methods that require a vmid to work
def must_have_vmid(fnc: typing.Callable[[typing.Any], None]) -> typing.Callable[['DynamicPublication'], None]:
@functools.wraps(fnc)
def wrapper(self: 'DynamicPublication') -> None:
if self._vmid == '':
raise Exception(f'No machine id on {self._name} for {fnc}')
return fnc(self)
return wrapper
class DynamicPublication(services.Publication, autoserializable.AutoSerializable, abc.ABC):
# Very simmilar to DynamicUserService, but with some differences
suggested_delay = 20 # For publications, we can check every 20 seconds
@ -102,12 +115,6 @@ class DynamicPublication(services.Publication, autoserializable.AutoSerializable
"""
return True
def publish(self) -> types.states.TaskState:
""" """
self._queue = self._publish_queue.copy()
self._debug('publish')
return self._execute_queue()
def _execute_queue(self) -> types.states.TaskState:
self._debug('execute_queue')
op = self._current_op()
@ -135,6 +142,14 @@ class DynamicPublication(services.Publication, autoserializable.AutoSerializable
logger.exception('Unexpected FixedUserService exception: %s', e)
return self._error(str(e))
@typing.final
def publish(self) -> types.states.TaskState:
""" """
self._queue = self._publish_queue.copy()
self._debug('publish')
return self._execute_queue()
@typing.final
def check_state(self) -> types.states.TaskState:
"""
Check what operation is going on, and acts acordly to it
@ -246,6 +261,7 @@ class DynamicPublication(services.Publication, autoserializable.AutoSerializable
"""
pass
@must_have_vmid
def op_start(self) -> None:
"""
This method is called when the service is started
@ -258,6 +274,7 @@ class DynamicPublication(services.Publication, autoserializable.AutoSerializable
"""
pass
@must_have_vmid
def op_stop(self) -> None:
"""
This method is called for stopping the service
@ -270,6 +287,7 @@ class DynamicPublication(services.Publication, autoserializable.AutoSerializable
"""
pass
@must_have_vmid
def op_shutdown(self) -> None:
"""
This method is called for shutdown the service
@ -282,31 +300,6 @@ class DynamicPublication(services.Publication, autoserializable.AutoSerializable
"""
pass
def op_suspend(self) -> None:
"""
This method is called for suspend the service
"""
# Note that by default suspend is "shutdown" and not "stop" because we
self.service().suspend_machine(self, self._vmid)
def op_suspend_completed(self) -> None:
"""
This method is called when the service suspension is completed
"""
pass
def op_reset(self) -> None:
"""
This method is called when the service is reset
"""
pass
def op_reset_completed(self) -> None:
"""
This method is called when the service reset is completed
"""
self.service().reset_machine(self, self._vmid)
def op_remove(self) -> None:
"""
This method is called when the service is removed
@ -320,14 +313,6 @@ class DynamicPublication(services.Publication, autoserializable.AutoSerializable
"""
pass
def op_wait(self) -> None:
"""
This method is called when the service is waiting
Basically, will stop the execution of the queue until something external changes it (i.e. poping from the queue)
Executor does nothing
"""
pass
def op_nop(self) -> None:
"""
This method is called when the service is doing nothing
@ -397,24 +382,6 @@ class DynamicPublication(services.Publication, autoserializable.AutoSerializable
"""
return types.states.TaskState.FINISHED
def op_suspend_checker(self) -> types.states.TaskState:
"""
This method is called to check if the service is suspended
"""
return types.states.TaskState.FINISHED
def op_suspend_completed_checker(self) -> types.states.TaskState:
"""
This method is called to check if the service suspension is completed
"""
return types.states.TaskState.FINISHED
def op_reset_checker(self) -> types.states.TaskState:
"""
This method is called to check if the service is reset
"""
return types.states.TaskState.FINISHED
def op_remove_checker(self) -> types.states.TaskState:
"""
This method is called to check if the service is removed
@ -427,12 +394,6 @@ class DynamicPublication(services.Publication, autoserializable.AutoSerializable
"""
return types.states.TaskState.FINISHED
def op_wait_checker(self) -> types.states.TaskState:
"""
Wait will remain in the same state until something external changes it (i.e. poping from the queue)
"""
return types.states.TaskState.RUNNING
def op_nop_checker(self) -> types.states.TaskState:
"""
This method is called to check if the service is doing nothing
@ -446,6 +407,14 @@ class DynamicPublication(services.Publication, autoserializable.AutoSerializable
return types.states.TaskState.FINISHED
# ERROR, FINISH and UNKNOWN are not here, as they are final states not needing to be checked
# We use same operation type for Publication and UserService. We add "unsupported" to
# cover not defined operations (will raise an exception)
def op_unsupported(self) -> None:
raise Exception('Operation not defined')
def op_unsupported_checker(self) -> types.states.TaskState:
raise Exception('Operation not defined')
@staticmethod
def _op2str(op: Operation) -> str:
@ -480,11 +449,11 @@ _EXECUTORS: typing.Final[
Operation.STOP_COMPLETED: DynamicPublication.op_stop_completed,
Operation.SHUTDOWN: DynamicPublication.op_shutdown,
Operation.SHUTDOWN_COMPLETED: DynamicPublication.op_shutdown_completed,
Operation.SUSPEND: DynamicPublication.op_suspend,
Operation.SUSPEND_COMPLETED: DynamicPublication.op_suspend_completed,
Operation.SUSPEND: DynamicPublication.op_unsupported,
Operation.SUSPEND_COMPLETED: DynamicPublication.op_unsupported,
Operation.REMOVE: DynamicPublication.op_remove,
Operation.REMOVE_COMPLETED: DynamicPublication.op_remove_completed,
Operation.WAIT: DynamicPublication.op_wait,
Operation.WAIT: DynamicPublication.op_unsupported,
Operation.NOP: DynamicPublication.op_nop,
}
@ -501,10 +470,10 @@ _CHECKERS: typing.Final[
Operation.STOP_COMPLETED: DynamicPublication.op_stop_completed_checker,
Operation.SHUTDOWN: DynamicPublication.op_shutdown_checker,
Operation.SHUTDOWN_COMPLETED: DynamicPublication.op_shutdown_completed_checker,
Operation.SUSPEND: DynamicPublication.op_suspend_checker,
Operation.SUSPEND_COMPLETED: DynamicPublication.op_suspend_completed_checker,
Operation.SUSPEND: DynamicPublication.op_unsupported_checker,
Operation.SUSPEND_COMPLETED: DynamicPublication.op_unsupported_checker,
Operation.REMOVE: DynamicPublication.op_remove_checker,
Operation.REMOVE_COMPLETED: DynamicPublication.op_remove_completed_checker,
Operation.WAIT: DynamicPublication.op_wait_checker,
Operation.WAIT: DynamicPublication.op_unsupported_checker,
Operation.NOP: DynamicPublication.op_nop_checker,
}

View File

@ -39,8 +39,8 @@ from uds.core.util import fields, validators
# Not imported at runtime, just for type checking
if typing.TYPE_CHECKING:
from .dynamic_userservice import DynamicUserService
from .dynamic_publication import DynamicPublication
from .userservice import DynamicUserService
from .publication import DynamicPublication
logger = logging.getLogger(__name__)
@ -149,7 +149,7 @@ class DynamicService(services.Service, abc.ABC): # pylint: disable=too-many-pub
@abc.abstractmethod
def start_machine(
self, caller_instance: 'DynamicUserService | DynamicPublication', machine_id: str
) -> typing.Any:
) -> None:
"""
Starts the machine
Can return a task, or None if no task is returned
@ -157,7 +157,7 @@ class DynamicService(services.Service, abc.ABC): # pylint: disable=too-many-pub
...
@abc.abstractmethod
def stop_machine(self, caller_instance: 'DynamicUserService | DynamicPublication', machine_id: str) -> typing.Any:
def stop_machine(self, caller_instance: 'DynamicUserService | DynamicPublication', machine_id: str) -> None:
"""
Stops the machine
Can return a task, or None if no task is returned
@ -166,7 +166,7 @@ class DynamicService(services.Service, abc.ABC): # pylint: disable=too-many-pub
def shutdown_machine(
self, caller_instance: 'DynamicUserService | DynamicPublication', machine_id: str
) -> typing.Any:
) -> None:
"""
Shutdowns the machine
Defaults to stop_machine
@ -176,7 +176,7 @@ class DynamicService(services.Service, abc.ABC): # pylint: disable=too-many-pub
def reset_machine(
self, caller_instance: 'DynamicUserService | DynamicPublication', machine_id: str
) -> typing.Any:
) -> None:
"""
Resets the machine
Can return a task, or None if no task is returned
@ -186,7 +186,7 @@ class DynamicService(services.Service, abc.ABC): # pylint: disable=too-many-pub
def suspend_machine(
self, caller_instance: 'DynamicUserService | DynamicPublication', machine_id: str
) -> typing.Any:
) -> None:
"""
Suspends the machine
Defaults to shutdown_machine.
@ -197,7 +197,7 @@ class DynamicService(services.Service, abc.ABC): # pylint: disable=too-many-pub
@abc.abstractmethod
def remove_machine(
self, caller_instance: 'DynamicUserService | DynamicPublication', machine_id: str
) -> typing.Any:
) -> None:
"""
Removes the machine, or queues it for removal, or whatever :)
"""
@ -207,7 +207,17 @@ class DynamicService(services.Service, abc.ABC): # pylint: disable=too-many-pub
if self.has_field('maintain_on_error'): # If has been defined on own class...
return self.maintain_on_error.value
return False
def can_clean_errored_userservices(self) -> bool:
"""
Returns if this service can clean errored services. This is used to check if a service can be cleaned
from the stuck cleaner job, for example. By default, this method returns True.
"""
if self.has_field('maintain_on_error'):
return not self.maintain_on_error.value
return True
def try_graceful_shutdown(self) -> bool:
if self.has_field('try_soft_shutdown'):
return self.try_soft_shutdown.value

View File

@ -44,7 +44,7 @@ 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
from . import dynamic_service
from . import service
logger = logging.getLogger(__name__)
@ -52,7 +52,6 @@ logger = logging.getLogger(__name__)
# Decorator that tests that _vmid is not empty
# Used by some default methods that require a vmid to work
def must_have_vmid(fnc: typing.Callable[[typing.Any], None]) -> typing.Callable[['DynamicUserService'], None]:
@functools.wraps(fnc)
def wrapper(self: 'DynamicUserService') -> None:
if self._vmid == '':
@ -71,8 +70,8 @@ class DynamicUserService(services.UserService, autoserializable.AutoSerializable
suggested_delay = 8
# Some customization fields
# If ip can be manually overriden
can_set_ip: typing.ClassVar[bool] = False
# If ip can be manually overriden, normally True... (set by actor, for example)
can_set_ip: typing.ClassVar[bool] = True
# How many times we will check for a state before giving up
max_state_checks: typing.ClassVar[int] = 20
# If keep_state_sets_error is true, and an error occurs, the machine is set to FINISHED instead of ERROR
@ -223,8 +222,8 @@ class DynamicUserService(services.UserService, autoserializable.AutoSerializable
# Utility overrides for type checking...
# Probably, overriden again on child classes
def service(self) -> 'dynamic_service.DynamicService':
return typing.cast('dynamic_service.DynamicService', super().service())
def service(self) -> 'service.DynamicService':
return typing.cast('service.DynamicService', super().service())
@typing.final
def get_name(self) -> str:
@ -253,14 +252,14 @@ class DynamicUserService(services.UserService, autoserializable.AutoSerializable
@typing.final
def get_ip(self) -> str:
# Provide self to the service, so it can some of our methods to generate the unique id
try:
if self._vmid:
return self.service().get_machine_ip(self, self._vmid)
except Exception:
logger.warning('Error obtaining IP for %s: %s', self.__class__.__name__, self._vmid, exc_info=True)
pass
return ''
if self._ip == '':
try:
if self._vmid:
# Provide self to the service, so it can use some of our methods for whaterever it needs
self._ip = self.service().get_machine_ip(self, self._vmid)
except Exception:
logger.warning('Error obtaining IP for %s: %s', self.__class__.__name__, self._vmid, exc_info=True)
return self._ip
@typing.final
def deploy_for_user(self, user: 'models.User') -> types.states.TaskState:
@ -337,6 +336,7 @@ class DynamicUserService(services.UserService, autoserializable.AutoSerializable
logger.exception('Unexpected FixedUserService exception: %s', e)
return self._error(e)
@typing.final
def check_state(self) -> types.states.TaskState:
"""
Check what operation is going on, and acts acordly to it

View File

@ -41,7 +41,7 @@ from uds.core.ui import gui
# Not imported at runtime, just for type checking
if typing.TYPE_CHECKING:
from uds import models
from .fixed_userservice import FixedUserService
from .userservice import FixedUserService
logger = logging.getLogger(__name__)

View File

@ -42,7 +42,7 @@ from uds.core.util import log, autoserializable
# Not imported at runtime, just for type checking
if typing.TYPE_CHECKING:
from uds import models
from . import fixed_service
from . import service
logger = logging.getLogger(__name__)
@ -136,8 +136,8 @@ class FixedUserService(services.UserService, autoserializable.AutoSerializable,
# Utility overrides for type checking...
# Probably, overriden again on child classes
def service(self) -> 'fixed_service.FixedService':
return typing.cast('fixed_service.FixedService', super().service())
def service(self) -> 'service.FixedService':
return typing.cast('service.FixedService', super().service())
@typing.final
def get_name(self) -> str:

View File

@ -34,7 +34,7 @@ import logging
import typing
from uds.core import types
from uds.core.services.generics.fixed_machine.fixed_userservice import FixedUserService, Operation
from uds.core.services.generics.fixed.userservice import FixedUserService, Operation
from uds.core.util import autoserializable
from .openstack import types as openstack_types

View File

@ -35,8 +35,8 @@ import typing
from django.utils.translation import gettext_noop as _
from uds.core import services, types
from uds.core.services.generics.fixed_machine.fixed_service import FixedService
from uds.core.services.generics.fixed_machine.fixed_userservice import FixedUserService
from uds.core.services.generics.fixed.service import FixedService
from uds.core.services.generics.fixed.userservice import FixedUserService
from uds.core.ui import gui
from uds.core.util import log

View File

@ -34,7 +34,7 @@ import logging
import typing
from uds.core import types
from uds.core.services.generics.fixed_machine.fixed_userservice import FixedUserService, Operation
from uds.core.services.generics.fixed.userservice import FixedUserService, Operation
from uds.core.util import autoserializable
from . import client

View File

@ -36,7 +36,7 @@ import logging
import typing
from uds.core import types, consts
from uds.core.services.generics.dynamic_machine.dynamic_userservice import DynamicUserService, Operation
from uds.core.services.generics.dynamic.userservice import DynamicUserService, Operation
from uds.core.managers.userservice import UserServiceManager
from uds.core.util import autoserializable

View File

@ -35,7 +35,7 @@ import typing
from django.utils.translation import gettext as _
from uds.core import types
from uds.core.services.generics.dynamic_machine.dynamic_publication import DynamicPublication
from uds.core.services.generics.dynamic.publication import DynamicPublication
from uds.core.util import autoserializable
# Not imported at runtime, just for type checking

View File

@ -35,8 +35,8 @@ import typing
from django.utils.translation import gettext_noop as _
from uds.core import services, types
from uds.core.services.generics.fixed_machine.fixed_service import FixedService
from uds.core.services.generics.fixed_machine.fixed_userservice import FixedUserService
from uds.core.services.generics.fixed.service import FixedService
from uds.core.services.generics.fixed.userservice import FixedUserService
from uds.core.ui import gui
from uds.core.util import log

View File

@ -34,9 +34,9 @@ import typing
from django.utils.translation import gettext_noop as _
from uds.core import types
from uds.core.services.generics.dynamic_machine.dynamic_publication import DynamicPublication
from uds.core.services.generics.dynamic_machine.dynamic_service import DynamicService
from uds.core.services.generics.dynamic_machine.dynamic_userservice import DynamicUserService
from uds.core.services.generics.dynamic.publication import DynamicPublication
from uds.core.services.generics.dynamic.service import DynamicService
from uds.core.services.generics.dynamic.userservice import DynamicUserService
from uds.core.ui import gui
from uds.core.util import validators, log, fields
@ -48,9 +48,9 @@ from .publication import ProxmoxPublication
if typing.TYPE_CHECKING:
from . import client
from .provider import ProxmoxProvider
from uds.core.services.generics.dynamic_machine.dynamic_publication import DynamicPublication
from uds.core.services.generics.dynamic_machine.dynamic_service import DynamicService
from uds.core.services.generics.dynamic_machine.dynamic_userservice import DynamicUserService
from uds.core.services.generics.dynamic.publication import DynamicPublication
from uds.core.services.generics.dynamic.service import DynamicService
from uds.core.services.generics.dynamic.userservice import DynamicUserService
logger = logging.getLogger(__name__)

View File

@ -34,7 +34,7 @@ import logging
import typing
from uds.core import types
from uds.core.services.generics.fixed_machine.fixed_userservice import FixedUserService, Operation
from uds.core.services.generics.fixed.userservice import FixedUserService, Operation
from uds.core.util import log, autoserializable
from . import xen_client

View File

@ -35,8 +35,8 @@ import collections.abc
from django.utils.translation import gettext_noop as _
from uds.core import consts, services, types
from uds.core.services.generics.fixed_machine.fixed_service import FixedService
from uds.core.services.generics.fixed_machine.fixed_userservice import FixedUserService
from uds.core.services.generics.fixed.service import FixedService
from uds.core.services.generics.fixed.userservice import FixedUserService
from uds.core.ui import gui
from uds.core.util import log
from uds.core.util.decorators import cached

View File

@ -36,9 +36,9 @@ from unittest import mock
from uds import models
from uds.core import services, types
from uds.core.services.generics.fixed_machine import (
fixed_service,
fixed_userservice,
from uds.core.services.generics.fixed import (
service,
userservice,
)
from uds.core.ui.user_interface import gui
@ -47,7 +47,7 @@ from ....utils.test import UDSTestCase
@dataclasses.dataclass
class FixedServiceIterationInfo:
queue: list[fixed_userservice.Operation]
queue: list[userservice.Operation]
service_calls: list[mock._Call] = dataclasses.field(default_factory=list)
user_service_calls: list[mock._Call] = dataclasses.field(default_factory=list)
state: str = types.states.TaskState.RUNNING
@ -60,11 +60,11 @@ EXPECTED_DEPLOY_ITERATIONS_INFO: typing.Final[list[FixedServiceIterationInfo]] =
# Initial state for queue
FixedServiceIterationInfo(
queue=[
fixed_userservice.Operation.CREATE,
fixed_userservice.Operation.SNAPSHOT_CREATE,
fixed_userservice.Operation.PROCESS_TOKEN,
fixed_userservice.Operation.START,
fixed_userservice.Operation.FINISH,
userservice.Operation.CREATE,
userservice.Operation.SNAPSHOT_CREATE,
userservice.Operation.PROCESS_TOKEN,
userservice.Operation.START,
userservice.Operation.FINISH,
],
service_calls=[
mock.call.get_and_assign_machine(),
@ -76,12 +76,12 @@ EXPECTED_DEPLOY_ITERATIONS_INFO: typing.Final[list[FixedServiceIterationInfo]] =
# (this is what our testing example does, but maybe it's not the best approach for all services)
FixedServiceIterationInfo(
queue=[
fixed_userservice.Operation.NOP,
fixed_userservice.Operation.STOP,
fixed_userservice.Operation.SNAPSHOT_CREATE,
fixed_userservice.Operation.PROCESS_TOKEN,
fixed_userservice.Operation.START,
fixed_userservice.Operation.FINISH,
userservice.Operation.NOP,
userservice.Operation.STOP,
userservice.Operation.SNAPSHOT_CREATE,
userservice.Operation.PROCESS_TOKEN,
userservice.Operation.START,
userservice.Operation.FINISH,
],
service_calls=[
mock.call.process_snapshot(False, mock.ANY),
@ -89,21 +89,21 @@ EXPECTED_DEPLOY_ITERATIONS_INFO: typing.Final[list[FixedServiceIterationInfo]] =
),
FixedServiceIterationInfo(
queue=[
fixed_userservice.Operation.STOP,
fixed_userservice.Operation.SNAPSHOT_CREATE,
fixed_userservice.Operation.PROCESS_TOKEN,
fixed_userservice.Operation.START,
fixed_userservice.Operation.FINISH,
userservice.Operation.STOP,
userservice.Operation.SNAPSHOT_CREATE,
userservice.Operation.PROCESS_TOKEN,
userservice.Operation.START,
userservice.Operation.FINISH,
],
user_service_calls=[mock.call._stop_machine()],
),
# The current operation is snapshot, so check previous operation (Finished) and then process snapshot
FixedServiceIterationInfo(
queue=[
fixed_userservice.Operation.SNAPSHOT_CREATE,
fixed_userservice.Operation.PROCESS_TOKEN,
fixed_userservice.Operation.START,
fixed_userservice.Operation.FINISH,
userservice.Operation.SNAPSHOT_CREATE,
userservice.Operation.PROCESS_TOKEN,
userservice.Operation.START,
userservice.Operation.FINISH,
],
service_calls=[
mock.call.process_snapshot(False, mock.ANY),
@ -112,16 +112,16 @@ EXPECTED_DEPLOY_ITERATIONS_INFO: typing.Final[list[FixedServiceIterationInfo]] =
),
FixedServiceIterationInfo(
queue=[
fixed_userservice.Operation.PROCESS_TOKEN,
fixed_userservice.Operation.START,
fixed_userservice.Operation.FINISH,
userservice.Operation.PROCESS_TOKEN,
userservice.Operation.START,
userservice.Operation.FINISH,
],
user_service_calls=[mock.call.db_obj()],
),
FixedServiceIterationInfo(
queue=[
fixed_userservice.Operation.START,
fixed_userservice.Operation.FINISH,
userservice.Operation.START,
userservice.Operation.FINISH,
],
user_service_calls=[mock.call._start_machine()],
),
@ -129,7 +129,7 @@ EXPECTED_DEPLOY_ITERATIONS_INFO: typing.Final[list[FixedServiceIterationInfo]] =
# (or if queue is empty, but that's not the case here)
FixedServiceIterationInfo(
queue=[
fixed_userservice.Operation.FINISH,
userservice.Operation.FINISH,
],
user_service_calls=[mock.call._start_checker()],
state=types.states.TaskState.FINISHED,
@ -139,22 +139,22 @@ EXPECTED_DEPLOY_ITERATIONS_INFO: typing.Final[list[FixedServiceIterationInfo]] =
EXPECTED_REMOVAL_ITERATIONS_INFO: typing.Final[list[FixedServiceIterationInfo]] = [
FixedServiceIterationInfo(
queue=[
fixed_userservice.Operation.REMOVE,
fixed_userservice.Operation.SNAPSHOT_RECOVER,
fixed_userservice.Operation.FINISH,
userservice.Operation.REMOVE,
userservice.Operation.SNAPSHOT_RECOVER,
userservice.Operation.FINISH,
],
service_calls=[mock.call.remove_and_free_machine('assigned')],
),
FixedServiceIterationInfo(
queue=[
fixed_userservice.Operation.SNAPSHOT_RECOVER,
fixed_userservice.Operation.FINISH,
userservice.Operation.SNAPSHOT_RECOVER,
userservice.Operation.FINISH,
],
service_calls=[mock.call.process_snapshot(True, mock.ANY)],
),
FixedServiceIterationInfo(
queue=[
fixed_userservice.Operation.FINISH,
userservice.Operation.FINISH,
],
state=types.states.TaskState.FINISHED,
),
@ -222,11 +222,11 @@ class FixedServiceTest(UDSTestCase):
service.mock.reset_mock()
userservice.mock.reset_mock()
def test_fixed_service_deploy(self) -> None:
def test_service_deploy(self) -> None:
_prov, service, userservice = self.create_elements()
self.check_iterations(service, userservice, EXPECTED_DEPLOY_ITERATIONS_INFO, removal=False)
def test_fixed_service_deploy_no_machine(self) -> None:
def test_service_deploy_no_machine(self) -> None:
_prov, service, userservice = self.create_elements()
service.available_machines_number = 2
self.deploy_service(service, userservice) # Should be deployed without issues
@ -234,7 +234,7 @@ class FixedServiceTest(UDSTestCase):
# And now, should fail to deploy again
self.assertRaises(Exception, self.deploy_service, service, userservice)
def test_fixed_service_removal(self) -> None:
def test_service_removal(self) -> None:
_prov, service, userservice = self.create_elements()
# Ensure fully deployed state for userservice
@ -244,7 +244,7 @@ class FixedServiceTest(UDSTestCase):
self.check_iterations(service, userservice, EXPECTED_REMOVAL_ITERATIONS_INFO, removal=True)
class FixedTestingUserService(fixed_userservice.FixedUserService):
class FixedTestingUserService(userservice.FixedUserService):
mock: 'mock.Mock' = mock.MagicMock()
def start_machine(self) -> None:
@ -266,14 +266,14 @@ class FixedTestingUserService(fixed_userservice.FixedUserService):
return None
class FixedTestingService(fixed_service.FixedService):
class FixedTestingService(service.FixedService):
type_name = 'Fixed Service'
type_type = 'FixedService'
type_description = 'Fixed Service description'
token = fixed_service.FixedService.token
snapshot_type = fixed_service.FixedService.snapshot_type
machines = fixed_service.FixedService.machines
token = service.FixedService.token
snapshot_type = service.FixedService.snapshot_type
machines = service.FixedService.machines
user_service_type = FixedTestingUserService
first_process_called = False
@ -281,15 +281,15 @@ class FixedTestingService(fixed_service.FixedService):
mock: 'mock.Mock' = mock.MagicMock()
def process_snapshot(self, remove: bool, userservice_instance: fixed_userservice.FixedUserService) -> None:
def process_snapshot(self, remove: bool, userservice_instance: userservice.FixedUserService) -> None:
self.mock.process_snapshot(remove, userservice_instance)
if not remove and not self.first_process_called:
# We want to call start, then snapshot, again
# As we have snapshot on top of queue, we need to insert NOP -> STOP
# This way, NOP will be consumed right now, then start will be called and then
# this will be called again
userservice_instance._push_front_op(fixed_userservice.Operation.STOP)
userservice_instance._push_front_op(fixed_userservice.Operation.NOP)
userservice_instance._push_front_op(userservice.Operation.STOP)
userservice_instance._push_front_op(userservice.Operation.NOP)
self.first_process_called = True
def get_machine_name(self, vmid: str) -> str:

View File

@ -34,7 +34,6 @@
# We use commit/rollback
from ...utils.test import UDSTransactionTestCase
from uds.core.util.cache import Cache
from uds.core.util.decorators import cached
import time
# Some random chars, that include unicode non-ascci chars

View File

@ -42,7 +42,7 @@ from ...utils.generators import limited_iterator
# We use transactions on some related methods (storage access, etc...)
class TestProxmovLinkedService(UDSTransactionTestCase):
class TestProxmoxFixedUserService(UDSTransactionTestCase):
def setUp(self) -> None:
fixtures.set_all_vm_state('stopped')

View File

@ -43,7 +43,7 @@ from ...utils.generators import limited_iterator
# We use transactions on some related methods (storage access, etc...)
class TestProxmovLinkedService(UDSTransactionTestCase):
class TestProxmovLinkedUserService(UDSTransactionTestCase):
def setUp(self) -> None:
fixtures.set_all_vm_state('stopped')
@ -237,14 +237,14 @@ class TestProxmovLinkedService(UDSTransactionTestCase):
self.assertEqual(state, types.states.TaskState.RUNNING)
# Ensure DESTROY_VALIDATOR is in the queue
self.assertIn(types.services.Operation.DESTROY_VALIDATOR, userservice._queue)
for _ in limited_iterator(lambda: state == types.states.TaskState.RUNNING, limit=128):
state = userservice.check_state()
# Now, should be finished without any problem, no call to api should have been done
self.assertEqual(state, types.states.TaskState.FINISHED)
self.assertEqual(len(api.mock_calls), 0)
# Now again, but process check_queue a couple of times before cancel
# we we have an _vmid
state = userservice.deploy_for_user(models.User())
@ -282,3 +282,9 @@ class TestProxmovLinkedService(UDSTransactionTestCase):
api.shutdown_machine.assert_called()
else:
api.stop_machine.assert_called()
def test_userservice_basics(self) -> None:
with fixtures.patch_provider_api() as _api:
userservice = fixtures.create_userservice_linked()
userservice.set_ip('1.2.3.4')
self.assertEqual(userservice.get_ip(), '1.2.3.4')