2023-02-03 17:04:35 +00:00
""" Class representing Bitwarden service """
2024-07-26 19:59:44 +00:00
2023-02-03 17:04:35 +00:00
import base64
2023-07-10 17:03:10 +00:00
import subprocess
2023-04-14 11:20:03 +00:00
from typing import List
2023-07-10 17:03:10 +00:00
from os import path
# from enum import Enum
2023-02-03 17:04:35 +00:00
2024-03-13 12:50:41 +00:00
from selfprivacy_api . jobs import Job
from selfprivacy_api . services . service import Service , ServiceStatus
2023-02-03 17:04:35 +00:00
from selfprivacy_api . utils . block_devices import BlockDevice
from selfprivacy_api . services . test_service . icon import BITWARDEN_ICON
2023-07-10 17:03:10 +00:00
DEFAULT_DELAY = 0
2023-02-03 17:04:35 +00:00
class DummyService ( Service ) :
""" A test service """
2023-07-10 17:03:10 +00:00
folders : List [ str ] = [ ]
2023-10-06 10:45:46 +00:00
startstop_delay = 0.0
2023-07-19 15:09:49 +00:00
backuppable = True
2023-10-06 13:17:48 +00:00
movable = True
2024-08-09 13:39:53 +00:00
fail_to_stop = False
2023-10-11 17:19:45 +00:00
# if False, we try to actually move
simulate_moving = True
drive = " sda1 "
2023-07-10 17:03:10 +00:00
2023-04-14 12:29:23 +00:00
def __init_subclass__ ( cls , folders : List [ str ] ) :
cls . folders = folders
2023-02-03 17:04:35 +00:00
2023-07-10 17:03:10 +00:00
def __init__ ( self ) :
super ( ) . __init__ ( )
2023-09-29 12:52:13 +00:00
with open ( self . status_file ( ) , " w " ) as file :
2023-07-10 17:03:10 +00:00
file . write ( ServiceStatus . ACTIVE . value )
2023-02-03 17:04:35 +00:00
@staticmethod
def get_id ( ) - > str :
""" Return service id. """
return " testservice "
@staticmethod
def get_display_name ( ) - > str :
""" Return service display name. """
return " Test Service "
@staticmethod
def get_description ( ) - > str :
""" Return service description. """
return " A small service used for test purposes. Does nothing. "
@staticmethod
def get_svg_icon ( ) - > str :
""" Read SVG icon from file and return it as base64 encoded string. """
# return ""
return base64 . b64encode ( BITWARDEN_ICON . encode ( " utf-8 " ) ) . decode ( " utf-8 " )
2023-10-06 13:17:48 +00:00
@classmethod
def is_movable ( cls ) - > bool :
return cls . movable
2023-02-03 17:04:35 +00:00
@staticmethod
def is_required ( ) - > bool :
return False
2023-06-29 11:27:08 +00:00
@staticmethod
def get_backup_description ( ) - > str :
return " How did we get here? "
2023-07-10 17:03:10 +00:00
@classmethod
def status_file ( cls ) - > str :
dir = cls . folders [ 0 ]
2023-07-12 16:00:36 +00:00
# we do not REALLY want to store our state in our declared folders
return path . join ( dir , " .. " , " service_status " )
2023-02-03 17:04:35 +00:00
2023-07-10 17:03:10 +00:00
@classmethod
def set_status ( cls , status : ServiceStatus ) :
with open ( cls . status_file ( ) , " w " ) as file :
2024-03-13 12:50:41 +00:00
file . write ( status . value )
2023-02-03 17:04:35 +00:00
2023-07-10 17:03:10 +00:00
@classmethod
def get_status ( cls ) - > ServiceStatus :
2024-06-05 11:36:47 +00:00
filepath = cls . status_file ( )
if filepath in [ None , " " ] :
raise ValueError ( f " We do not have a path for our test dummy status file! " )
if not path . exists ( filepath ) :
raise FileNotFoundError ( filepath )
2023-07-10 17:03:10 +00:00
with open ( cls . status_file ( ) , " r " ) as file :
status_string = file . read ( ) . strip ( )
2024-06-05 11:36:47 +00:00
if status_string in [ None , " " ] :
raise NotImplementedError (
f " It appears our test service no longer has any status in the statusfile. Filename = { cls . status_file } , status string inside is ' { status_string } ' (quoted) "
)
2023-07-10 17:03:10 +00:00
return ServiceStatus [ status_string ]
2023-02-03 17:04:35 +00:00
2023-07-10 17:03:10 +00:00
@classmethod
def change_status_with_async_delay (
cls , new_status : ServiceStatus , delay_sec : float
) :
""" simulating a delay on systemd side """
2024-06-05 11:36:47 +00:00
if not isinstance ( new_status , ServiceStatus ) :
raise ValueError (
f " received an invalid new status for test service. new status: { str ( new_status ) } "
)
2024-03-13 12:50:41 +00:00
if delay_sec == 0 :
cls . set_status ( new_status )
return
2023-07-10 17:03:10 +00:00
2024-03-13 12:50:41 +00:00
status_file = cls . status_file ( )
2023-07-10 17:03:10 +00:00
command = [
" bash " ,
" -c " ,
f " sleep { delay_sec } && echo { new_status . value } > { status_file } " ,
]
2024-03-13 12:50:41 +00:00
subprocess . Popen ( command )
2023-02-03 17:04:35 +00:00
2023-07-19 15:09:49 +00:00
@classmethod
def set_backuppable ( cls , new_value : bool ) - > None :
""" For tests: because can_be_backed_up is static,
we can only set it up dynamically for tests via a classmethod """
cls . backuppable = new_value
2023-10-06 13:17:48 +00:00
@classmethod
def set_movable ( cls , new_value : bool ) - > None :
""" For tests: because is_movale is static,
we can only set it up dynamically for tests via a classmethod """
cls . movable = new_value
2023-07-19 15:09:49 +00:00
@classmethod
def can_be_backed_up ( cls ) - > bool :
""" `True` if the service can be backed up. """
return cls . backuppable
2023-07-10 17:03:10 +00:00
@classmethod
2023-10-06 10:45:46 +00:00
def set_delay ( cls , new_delay_sec : float ) - > None :
cls . startstop_delay = new_delay_sec
2023-07-12 12:27:55 +00:00
2023-10-11 17:19:45 +00:00
@classmethod
def set_drive ( cls , new_drive : str ) - > None :
cls . drive = new_drive
@classmethod
def set_simulated_moves ( cls , enabled : bool ) - > None :
""" If True, this service will not actually call moving code
when moved """
cls . simulate_moving = enabled
2024-08-09 13:39:53 +00:00
@classmethod
def simulate_fail_to_stop ( cls , value : bool ) :
cls . fail_to_stop = value
2023-07-12 12:27:55 +00:00
@classmethod
def stop ( cls ) :
2023-08-23 13:39:12 +00:00
# simulate a failing service unable to stop
if not cls . get_status ( ) == ServiceStatus . FAILED :
cls . set_status ( ServiceStatus . DEACTIVATING )
2024-08-09 13:39:53 +00:00
if cls . fail_to_stop :
cls . change_status_with_async_delay (
ServiceStatus . FAILED , cls . startstop_delay
)
else :
cls . change_status_with_async_delay (
ServiceStatus . INACTIVE , cls . startstop_delay
)
2023-07-10 17:03:10 +00:00
@classmethod
2023-07-12 12:27:55 +00:00
def start ( cls ) :
2023-07-10 17:03:10 +00:00
cls . set_status ( ServiceStatus . ACTIVATING )
2023-07-12 12:27:55 +00:00
cls . change_status_with_async_delay ( ServiceStatus . ACTIVE , cls . startstop_delay )
2023-07-10 17:03:10 +00:00
@classmethod
2023-07-12 12:27:55 +00:00
def restart ( cls ) :
2023-07-10 17:03:10 +00:00
cls . set_status ( ServiceStatus . RELOADING ) # is a correct one?
2023-07-12 12:27:55 +00:00
cls . change_status_with_async_delay ( ServiceStatus . ACTIVE , cls . startstop_delay )
2023-07-10 17:03:10 +00:00
2024-07-26 15:33:04 +00:00
@classmethod
def get_configuration ( cls ) :
2023-02-03 17:04:35 +00:00
return { }
2024-07-26 15:33:04 +00:00
@classmethod
def set_configuration ( cls , config_items ) :
2023-02-03 17:04:35 +00:00
return super ( ) . set_configuration ( config_items )
@staticmethod
def get_logs ( ) :
return " "
@staticmethod
def get_storage_usage ( ) - > int :
storage_usage = 0
return storage_usage
2023-10-11 17:19:45 +00:00
@classmethod
def get_drive ( cls ) - > str :
return cls . drive
2023-04-14 10:32:14 +00:00
@classmethod
2023-04-14 11:20:03 +00:00
def get_folders ( cls ) - > List [ str ] :
2023-04-14 12:29:23 +00:00
return cls . folders
2023-02-03 17:04:35 +00:00
2024-02-18 23:58:00 +00:00
def do_move_to_volume ( self , volume : BlockDevice , job : Job ) - > Job :
2023-10-11 17:19:45 +00:00
if self . simulate_moving is False :
2024-02-18 23:58:00 +00:00
return super ( DummyService , self ) . do_move_to_volume ( volume , job )
2023-10-11 17:19:45 +00:00
else :
2024-02-18 23:58:00 +00:00
self . set_drive ( volume . name )
return job