2021-11-11 18:31:28 +00:00
|
|
|
#!/usr/bin/env python3
|
2021-11-16 16:14:01 +00:00
|
|
|
"""Backups management module"""
|
2021-12-01 14:51:38 +00:00
|
|
|
from flask_restful import Resource, reqparse
|
2021-11-11 18:31:28 +00:00
|
|
|
|
|
|
|
from selfprivacy_api.resources.services import api
|
2021-12-01 14:51:38 +00:00
|
|
|
from selfprivacy_api.utils import WriteUserData
|
2021-12-06 06:48:29 +00:00
|
|
|
from selfprivacy_api.restic_controller import tasks as restic_tasks
|
|
|
|
from selfprivacy_api.restic_controller import ResticController, ResticStates
|
2021-11-11 18:31:28 +00:00
|
|
|
|
2021-11-16 16:14:01 +00:00
|
|
|
|
2021-11-11 18:31:28 +00:00
|
|
|
class ListAllBackups(Resource):
|
2021-11-16 16:14:01 +00:00
|
|
|
"""List all restic backups"""
|
|
|
|
|
2021-11-11 18:31:28 +00:00
|
|
|
def get(self):
|
2021-11-16 16:14:01 +00: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 06:48:29 +00:00
|
|
|
restic = ResticController()
|
|
|
|
return restic.snapshot_list
|
2021-11-11 18:31:28 +00:00
|
|
|
|
|
|
|
|
2021-11-16 10:02:36 +00:00
|
|
|
class AsyncCreateBackup(Resource):
|
2021-11-16 16:14:01 +00:00
|
|
|
"""Create a new restic backup"""
|
|
|
|
|
2021-11-11 18:31:28 +00:00
|
|
|
def put(self):
|
2021-11-16 16:14:01 +00: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 06:48:29 +00:00
|
|
|
409:
|
|
|
|
description: Backup already in progress
|
2021-11-16 16:14:01 +00:00
|
|
|
"""
|
2021-12-06 06:48:29 +00: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 18:31:28 +00:00
|
|
|
return {
|
|
|
|
"status": 0,
|
|
|
|
"message": "Backup creation has started",
|
|
|
|
}
|
|
|
|
|
2021-11-16 16:14:01 +00:00
|
|
|
|
2021-11-16 10:02:36 +00:00
|
|
|
class CheckBackupStatus(Resource):
|
2021-11-16 16:14:01 +00:00
|
|
|
"""Check current backup status"""
|
|
|
|
|
2021-11-16 10:02:36 +00:00
|
|
|
def get(self):
|
|
|
|
"""
|
2021-11-16 16:14:01 +00:00
|
|
|
Get backup status
|
|
|
|
---
|
|
|
|
tags:
|
|
|
|
- Backups
|
|
|
|
security:
|
|
|
|
- bearerAuth: []
|
|
|
|
responses:
|
|
|
|
200:
|
|
|
|
description: Backup status
|
|
|
|
400:
|
|
|
|
description: Bad request
|
|
|
|
401:
|
|
|
|
description: Unauthorized
|
|
|
|
"""
|
2021-12-06 06:48:29 +00:00
|
|
|
restic = ResticController()
|
|
|
|
|
|
|
|
return {
|
|
|
|
"status": restic.state.name,
|
|
|
|
"progress": restic.progress,
|
|
|
|
"error_message": restic.error_message,
|
|
|
|
}
|
2021-11-16 10:02:36 +00:00
|
|
|
|
2021-12-02 15:06:23 +00:00
|
|
|
|
2021-12-06 06:48:29 +00:00
|
|
|
class ForceReloadSnapshots(Resource):
|
|
|
|
"""Force reload snapshots"""
|
2021-11-16 10:02:36 +00:00
|
|
|
|
2021-12-06 06:48:29 +00: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-16 10:02:36 +00:00
|
|
|
|
2021-11-11 18:31:28 +00:00
|
|
|
|
2021-11-25 10:31:18 +00:00
|
|
|
class AsyncRestoreBackup(Resource):
|
|
|
|
"""Trigger backup restoration process"""
|
|
|
|
|
|
|
|
def put(self):
|
|
|
|
"""
|
|
|
|
Start backup restoration
|
|
|
|
---
|
|
|
|
tags:
|
|
|
|
- Backups
|
|
|
|
security:
|
|
|
|
- bearerAuth: []
|
2021-12-02 15:06:23 +00:00
|
|
|
parameters:
|
|
|
|
- in: body
|
|
|
|
required: true
|
|
|
|
name: backup
|
|
|
|
description: Backup to restore
|
|
|
|
schema:
|
|
|
|
type: object
|
|
|
|
required:
|
|
|
|
- backupId
|
|
|
|
properties:
|
|
|
|
backupId:
|
|
|
|
type: string
|
2021-11-25 10:31:18 +00:00
|
|
|
responses:
|
|
|
|
200:
|
|
|
|
description: Backup restoration process started
|
|
|
|
400:
|
|
|
|
description: Bad request
|
|
|
|
401:
|
|
|
|
description: Unauthorized
|
|
|
|
"""
|
2021-12-02 15:06:23 +00:00
|
|
|
parser = reqparse.RequestParser()
|
|
|
|
parser.add_argument("backupId", type=str, required=True)
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
2021-12-06 06:48:29 +00: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 10:31:18 +00:00
|
|
|
|
|
|
|
|
2021-12-01 14:51:38 +00: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:
|
|
|
|
data["backblaze"]["accountId"] = args["accountId"]
|
|
|
|
data["backblaze"]["accountKey"] = args["accountKey"]
|
|
|
|
data["backblaze"]["bucket"] = args["bucket"]
|
|
|
|
|
2021-12-06 06:48:29 +00:00
|
|
|
restic_tasks.update_keys_from_userdata()
|
|
|
|
|
2021-12-01 14:51:38 +00:00
|
|
|
return "New Backblaze settings saved"
|
|
|
|
|
|
|
|
|
2021-11-11 18:31:28 +00:00
|
|
|
api.add_resource(ListAllBackups, "/restic/backup/list")
|
2021-11-16 08:25:44 +00:00
|
|
|
api.add_resource(AsyncCreateBackup, "/restic/backup/create")
|
2021-11-16 10:02:36 +00:00
|
|
|
api.add_resource(CheckBackupStatus, "/restic/backup/status")
|
2021-11-25 10:31:18 +00:00
|
|
|
api.add_resource(AsyncRestoreBackup, "/restic/backup/restore")
|
2021-12-01 14:51:38 +00:00
|
|
|
api.add_resource(BackblazeConfig, "/restic/backblaze/config")
|
2021-12-06 06:48:29 +00:00
|
|
|
api.add_resource(ForceReloadSnapshots, "/restic/backup/reload")
|