fix(backups): cover the case when service fails to stop

This commit is contained in:
Houkime 2024-08-09 13:39:53 +00:00 committed by Inex Code
parent 391e4802b2
commit 8ef63eb90e
3 changed files with 22 additions and 10 deletions

View file

@ -477,7 +477,8 @@ class StoppedService:
try: try:
self.service.stop() self.service.stop()
wait_until_true( wait_until_true(
lambda: self.service.get_status() == ServiceStatus.INACTIVE, lambda: self.service.get_status()
in [ServiceStatus.INACTIVE, ServiceStatus.FAILED],
timeout_sec=DEFAULT_START_STOP_TIMEOUT, timeout_sec=DEFAULT_START_STOP_TIMEOUT,
) )
except TimeoutError as error: except TimeoutError as error:

View file

@ -24,6 +24,7 @@ class DummyService(Service):
startstop_delay = 0.0 startstop_delay = 0.0
backuppable = True backuppable = True
movable = True movable = True
fail_to_stop = False
# if False, we try to actually move # if False, we try to actually move
simulate_moving = True simulate_moving = True
drive = "sda1" drive = "sda1"
@ -148,11 +149,20 @@ class DummyService(Service):
when moved""" when moved"""
cls.simulate_moving = enabled cls.simulate_moving = enabled
@classmethod
def simulate_fail_to_stop(cls, value: bool):
cls.fail_to_stop = value
@classmethod @classmethod
def stop(cls): def stop(cls):
# simulate a failing service unable to stop # simulate a failing service unable to stop
if not cls.get_status() == ServiceStatus.FAILED: if not cls.get_status() == ServiceStatus.FAILED:
cls.set_status(ServiceStatus.DEACTIVATING) cls.set_status(ServiceStatus.DEACTIVATING)
if cls.fail_to_stop:
cls.change_status_with_async_delay(
ServiceStatus.FAILED, cls.startstop_delay
)
else:
cls.change_status_with_async_delay( cls.change_status_with_async_delay(
ServiceStatus.INACTIVE, cls.startstop_delay ServiceStatus.INACTIVE, cls.startstop_delay
) )

View file

@ -483,20 +483,21 @@ def restore_strategy(request) -> RestoreStrategy:
return RestoreStrategy.INPLACE return RestoreStrategy.INPLACE
@pytest.fixture(params=["failed", "healthy"]) @pytest.fixture(params=["failed", "healthy", "fail_to_stop"])
def failed(request) -> bool: def failed(request) -> str:
if request.param == "failed": return request.param
return True
return False
def test_restore_snapshot_task( def test_restore_snapshot_task(
backups, dummy_service, restore_strategy, simulated_service_stopping_delay, failed backups, dummy_service, restore_strategy, simulated_service_stopping_delay, failed
): ):
dummy_service.set_delay(simulated_service_stopping_delay) dummy_service.set_delay(simulated_service_stopping_delay)
if failed: if failed == "failed":
dummy_service.set_status(ServiceStatus.FAILED) dummy_service.set_status(ServiceStatus.FAILED)
if failed == "fail_to_stop":
dummy_service.simulate_fail_to_stop(True)
Backups.back_up(dummy_service) Backups.back_up(dummy_service)
snaps = Backups.get_snapshots(dummy_service) snaps = Backups.get_snapshots(dummy_service)
assert len(snaps) == 1 assert len(snaps) == 1