selfprivacy-rest-api/selfprivacy_api/resources/services/restic.py

242 lines
6.9 KiB
Python
Raw Normal View History

2021-11-11 20:31:28 +02:00
#!/usr/bin/env python3
2021-11-16 18:14:01 +02:00
"""Backups management module"""
2021-12-01 16:51:38 +02:00
from flask_restful import Resource, reqparse
2021-11-11 20:31:28 +02:00
from selfprivacy_api.resources.services import api
2021-12-01 16:51:38 +02:00
from selfprivacy_api.utils import WriteUserData
2021-12-06 08:48:29 +02:00
from selfprivacy_api.restic_controller import tasks as restic_tasks
from selfprivacy_api.restic_controller import ResticController, ResticStates
2021-11-11 20:31:28 +02:00
2021-11-16 18:14:01 +02:00
2021-11-11 20:31:28 +02:00
class ListAllBackups(Resource):
2021-11-16 18:14:01 +02:00
"""List all restic backups"""
2021-11-11 20:31:28 +02:00
def get(self):
2021-11-16 18:14:01 +02:00
"""
Get all restic backups
---
tags:
- Backups
security:
- bearerAuth: []
responses:
200:
description: A list of snapshots
400:
description: Bad request
401:
description: Unauthorized
"""
2021-12-06 08:48:29 +02:00
restic = ResticController()
return restic.snapshot_list
2021-11-11 20:31:28 +02:00
class AsyncCreateBackup(Resource):
2021-11-16 18:14:01 +02:00
"""Create a new restic backup"""
2021-11-11 20:31:28 +02:00
def put(self):
2021-11-16 18:14:01 +02:00
"""
Initiate a new restic backup
---
tags:
- Backups
security:
- bearerAuth: []
responses:
200:
description: Backup creation has started
400:
description: Bad request
401:
description: Unauthorized
2021-12-06 08:48:29 +02:00
409:
description: Backup already in progress
2021-11-16 18:14:01 +02:00
"""
2021-12-06 08:48:29 +02:00
restic = ResticController()
if restic.state is ResticStates.NO_KEY:
return {"error": "No key provided"}, 400
if restic.state is ResticStates.INITIALIZING:
return {"error": "Backup is initializing"}, 400
if restic.state is ResticStates.BACKING_UP:
return {"error": "Backup is already running"}, 409
restic_tasks.start_backup()
2021-11-11 20:31:28 +02:00
return {
"status": 0,
"message": "Backup creation has started",
}
2021-11-16 18:14:01 +02:00
class CheckBackupStatus(Resource):
2021-11-16 18:14:01 +02:00
"""Check current backup status"""
def get(self):
"""
2021-11-16 18:14:01 +02:00
Get backup status
---
tags:
- Backups
security:
- bearerAuth: []
responses:
200:
description: Backup status
400:
description: Bad request
401:
description: Unauthorized
"""
2021-12-06 08:48:29 +02:00
restic = ResticController()
return {
"status": restic.state.name,
"progress": restic.progress,
"error_message": restic.error_message,
}
2021-12-02 17:06:23 +02:00
2021-12-06 08:48:29 +02:00
class ForceReloadSnapshots(Resource):
"""Force reload snapshots"""
2021-12-06 08:48:29 +02:00
def get(self):
"""
Force reload snapshots
---
tags:
- Backups
security:
- bearerAuth: []
responses:
200:
description: Snapshots reloaded
400:
description: Bad request
401:
description: Unauthorized
"""
restic_tasks.load_snapshots()
return {
"status": 0,
"message": "Snapshots reload started",
}
2021-11-11 20:31:28 +02:00
2021-11-25 12:31:18 +02:00
class AsyncRestoreBackup(Resource):
"""Trigger backup restoration process"""
def put(self):
"""
Start backup restoration
---
tags:
- Backups
security:
- bearerAuth: []
2021-12-02 17:06:23 +02:00
parameters:
- in: body
required: true
name: backup
description: Backup to restore
schema:
type: object
required:
- backupId
properties:
backupId:
type: string
2021-11-25 12:31:18 +02:00
responses:
200:
description: Backup restoration process started
400:
description: Bad request
401:
description: Unauthorized
"""
2021-12-02 17:06:23 +02:00
parser = reqparse.RequestParser()
parser.add_argument("backupId", type=str, required=True)
args = parser.parse_args()
2021-12-06 08:48:29 +02:00
restic = ResticController()
if restic.state is ResticStates.NO_KEY:
return {"error": "No key provided"}, 400
if restic.state is ResticStates.NOT_INITIALIZED:
return {"error": "Repository is not initialized"}, 400
if restic.state is ResticStates.BACKING_UP:
return {"error": "Backup is already running"}, 409
if restic.state is ResticStates.INITIALIZING:
return {"error": "Repository is initializing"}, 400
if restic.state is ResticStates.RESTORING:
return {"error": "Restore is already running"}, 409
for backup in restic.snapshot_list:
if backup["short_id"] == args["backupId"]:
restic_tasks.restore_from_backup(args["backupId"])
return {
"status": 0,
"message": "Backup restoration procedure started",
}
return {"error": "Backup not found"}, 404
2021-11-25 12:31:18 +02:00
2021-12-01 16:51:38 +02:00
class BackblazeConfig(Resource):
"""Backblaze config"""
def put(self):
"""
Set the new key for backblaze
---
tags:
- Backups
security:
- bearerAuth: []
parameters:
- in: body
required: true
name: backblazeSettings
description: New Backblaze settings
schema:
type: object
required:
- accountId
- accountKey
- bucket
properties:
accountId:
type: string
accountKey:
type: string
bucket:
type: string
responses:
200:
description: New Backblaze settings
400:
description: Bad request
401:
description: Unauthorized
"""
parser = reqparse.RequestParser()
parser.add_argument("accountId", type=str, required=True)
parser.add_argument("accountKey", type=str, required=True)
parser.add_argument("bucket", type=str, required=True)
args = parser.parse_args()
with WriteUserData() as data:
2021-12-14 11:51:49 +02:00
if "backblaze" not in data:
data["backblaze"] = {}
2021-12-01 16:51:38 +02:00
data["backblaze"]["accountId"] = args["accountId"]
data["backblaze"]["accountKey"] = args["accountKey"]
data["backblaze"]["bucket"] = args["bucket"]
2021-12-06 08:48:29 +02:00
restic_tasks.update_keys_from_userdata()
2021-12-01 16:51:38 +02:00
return "New Backblaze settings saved"
2021-11-11 20:31:28 +02:00
api.add_resource(ListAllBackups, "/restic/backup/list")
2021-11-16 10:25:44 +02:00
api.add_resource(AsyncCreateBackup, "/restic/backup/create")
api.add_resource(CheckBackupStatus, "/restic/backup/status")
2021-11-25 12:31:18 +02:00
api.add_resource(AsyncRestoreBackup, "/restic/backup/restore")
2021-12-01 16:51:38 +02:00
api.add_resource(BackblazeConfig, "/restic/backblaze/config")
2021-12-06 08:48:29 +02:00
api.add_resource(ForceReloadSnapshots, "/restic/backup/reload")