2023-05-12 11:07:55 +00:00
|
|
|
from typing import Optional, List
|
2023-04-21 11:59:15 +00:00
|
|
|
|
2023-06-07 15:05:58 +00:00
|
|
|
from selfprivacy_api.models.backup.snapshot import Snapshot
|
2023-04-21 11:59:15 +00:00
|
|
|
from selfprivacy_api.jobs import Jobs, Job, JobStatus
|
|
|
|
from selfprivacy_api.services.service import Service
|
2024-07-24 15:15:31 +00:00
|
|
|
from selfprivacy_api.services import ServiceManager
|
2023-04-21 11:59:15 +00:00
|
|
|
|
|
|
|
|
2023-05-12 11:07:55 +00:00
|
|
|
def job_type_prefix(service: Service) -> str:
|
|
|
|
return f"services.{service.get_id()}"
|
|
|
|
|
|
|
|
|
|
|
|
def backup_job_type(service: Service) -> str:
|
|
|
|
return f"{job_type_prefix(service)}.backup"
|
|
|
|
|
|
|
|
|
2024-02-23 18:16:25 +00:00
|
|
|
def autobackup_job_type() -> str:
|
2024-03-01 13:59:43 +00:00
|
|
|
return "backups.autobackup"
|
2024-02-23 18:16:25 +00:00
|
|
|
|
|
|
|
|
2023-06-07 14:11:22 +00:00
|
|
|
def restore_job_type(service: Service) -> str:
|
|
|
|
return f"{job_type_prefix(service)}.restore"
|
|
|
|
|
|
|
|
|
2023-05-12 11:07:55 +00:00
|
|
|
def get_jobs_by_service(service: Service) -> List[Job]:
|
|
|
|
result = []
|
|
|
|
for job in Jobs.get_jobs():
|
|
|
|
if job.type_id.startswith(job_type_prefix(service)) and job.status in [
|
|
|
|
JobStatus.CREATED,
|
|
|
|
JobStatus.RUNNING,
|
|
|
|
]:
|
|
|
|
result.append(job)
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
2023-07-07 12:49:52 +00:00
|
|
|
def is_something_running_for(service: Service) -> bool:
|
|
|
|
running_jobs = [
|
|
|
|
job for job in get_jobs_by_service(service) if job.status == JobStatus.RUNNING
|
|
|
|
]
|
|
|
|
return len(running_jobs) != 0
|
2023-04-21 11:59:15 +00:00
|
|
|
|
|
|
|
|
2024-02-23 18:16:25 +00:00
|
|
|
def add_autobackup_job(services: List[Service]) -> Job:
|
|
|
|
service_names = [s.get_display_name() for s in services]
|
|
|
|
pretty_service_list: str = ", ".join(service_names)
|
|
|
|
job = Jobs.add(
|
|
|
|
type_id=autobackup_job_type(),
|
2024-03-01 13:59:43 +00:00
|
|
|
name="Automatic backup",
|
2024-03-03 21:45:45 +00:00
|
|
|
description=f"Scheduled backup for services: {pretty_service_list}",
|
2024-02-23 18:16:25 +00:00
|
|
|
)
|
|
|
|
return job
|
|
|
|
|
|
|
|
|
2023-04-21 11:59:15 +00:00
|
|
|
def add_backup_job(service: Service) -> Job:
|
2023-07-07 12:49:52 +00:00
|
|
|
if is_something_running_for(service):
|
2023-05-12 11:07:55 +00:00
|
|
|
message = (
|
2023-07-07 12:49:52 +00:00
|
|
|
f"Cannot start a backup of {service.get_id()}, another operation is running: "
|
2023-05-12 11:07:55 +00:00
|
|
|
+ get_jobs_by_service(service)[0].type_id
|
|
|
|
)
|
|
|
|
raise ValueError(message)
|
2023-04-21 11:59:15 +00:00
|
|
|
display_name = service.get_display_name()
|
|
|
|
job = Jobs.add(
|
|
|
|
type_id=backup_job_type(service),
|
|
|
|
name=f"Backup {display_name}",
|
|
|
|
description=f"Backing up {display_name}",
|
|
|
|
)
|
|
|
|
return job
|
|
|
|
|
|
|
|
|
2024-07-24 15:15:31 +00:00
|
|
|
def complain_about_service_operation_running(service: Service) -> str:
|
2024-09-11 10:02:10 +00:00
|
|
|
message = f"Cannot start a restore of {service.get_id()}, another operation is running: {get_jobs_by_service(service)[0].type_id}"
|
2024-07-24 15:15:31 +00:00
|
|
|
raise ValueError(message)
|
|
|
|
|
|
|
|
|
|
|
|
def add_total_restore_job() -> Job:
|
2024-09-06 11:40:16 +00:00
|
|
|
for service in ServiceManager.get_enabled_services():
|
|
|
|
ensure_nothing_runs_for(service)
|
2024-07-24 15:15:31 +00:00
|
|
|
|
|
|
|
job = Jobs.add(
|
|
|
|
type_id="backups.total_restore",
|
2024-09-06 11:40:16 +00:00
|
|
|
name=f"Total restore",
|
2024-09-11 10:02:10 +00:00
|
|
|
description="Restoring all enabled services",
|
2024-09-06 11:40:16 +00:00
|
|
|
)
|
|
|
|
return job
|
|
|
|
|
|
|
|
|
|
|
|
def ensure_nothing_runs_for(service: Service):
|
|
|
|
if (
|
|
|
|
# TODO: try removing the exception. Why would we have it?
|
|
|
|
not isinstance(service, ServiceManager)
|
|
|
|
and is_something_running_for(service) is True
|
|
|
|
):
|
|
|
|
complain_about_service_operation_running(service)
|
|
|
|
|
|
|
|
|
|
|
|
def add_total_backup_job() -> Job:
|
|
|
|
for service in ServiceManager.get_enabled_services():
|
|
|
|
ensure_nothing_runs_for(service)
|
|
|
|
|
|
|
|
job = Jobs.add(
|
|
|
|
type_id="backups.total_backup",
|
|
|
|
name=f"Total backup",
|
|
|
|
description="Backing up all the enabled services",
|
2024-07-24 15:15:31 +00:00
|
|
|
)
|
|
|
|
return job
|
|
|
|
|
|
|
|
|
2023-06-07 15:05:58 +00:00
|
|
|
def add_restore_job(snapshot: Snapshot) -> Job:
|
2024-07-24 15:15:31 +00:00
|
|
|
service = ServiceManager.get_service_by_id(snapshot.service_name)
|
2023-06-23 09:40:10 +00:00
|
|
|
if service is None:
|
|
|
|
raise ValueError(f"no such service: {snapshot.service_name}")
|
2023-07-07 12:49:52 +00:00
|
|
|
if is_something_running_for(service):
|
2024-07-24 15:15:31 +00:00
|
|
|
complain_about_service_operation_running(service)
|
2023-06-07 15:05:58 +00:00
|
|
|
display_name = service.get_display_name()
|
|
|
|
job = Jobs.add(
|
|
|
|
type_id=restore_job_type(service),
|
|
|
|
name=f"Restore {display_name}",
|
2024-09-11 10:02:10 +00:00
|
|
|
description=f"Restoring {display_name} from {snapshot.id}",
|
2023-06-07 15:05:58 +00:00
|
|
|
)
|
|
|
|
return job
|
|
|
|
|
|
|
|
|
2023-04-21 11:59:15 +00:00
|
|
|
def get_job_by_type(type_id: str) -> Optional[Job]:
|
|
|
|
for job in Jobs.get_jobs():
|
|
|
|
if job.type_id == type_id and job.status in [
|
|
|
|
JobStatus.CREATED,
|
|
|
|
JobStatus.RUNNING,
|
|
|
|
]:
|
|
|
|
return job
|
2024-03-01 12:43:07 +00:00
|
|
|
return None
|
2023-04-21 11:59:15 +00:00
|
|
|
|
|
|
|
|
2023-11-07 01:00:38 +00:00
|
|
|
def get_failed_job_by_type(type_id: str) -> Optional[Job]:
|
|
|
|
for job in Jobs.get_jobs():
|
|
|
|
if job.type_id == type_id and job.status == JobStatus.ERROR:
|
|
|
|
return job
|
2024-03-01 12:43:07 +00:00
|
|
|
return None
|
2023-11-07 01:00:38 +00:00
|
|
|
|
|
|
|
|
2023-04-21 11:59:15 +00:00
|
|
|
def get_backup_job(service: Service) -> Optional[Job]:
|
|
|
|
return get_job_by_type(backup_job_type(service))
|
2023-06-07 14:11:22 +00:00
|
|
|
|
|
|
|
|
2023-11-07 01:00:38 +00:00
|
|
|
def get_backup_fail(service: Service) -> Optional[Job]:
|
|
|
|
return get_failed_job_by_type(backup_job_type(service))
|
|
|
|
|
|
|
|
|
2023-06-07 14:11:22 +00:00
|
|
|
def get_restore_job(service: Service) -> Optional[Job]:
|
|
|
|
return get_job_by_type(restore_job_type(service))
|