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:
parent
8f98314c97
commit
9320eb3adf
@ -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,
|
||||
}
|
@ -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
|
@ -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
|
@ -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__)
|
||||
|
@ -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:
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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__)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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')
|
||||
|
||||
|
@ -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')
|
||||
|
Loading…
Reference in New Issue
Block a user