Add restore option to restic-batch

This commit is contained in:
Wojciech Kozlowski 2023-02-13 00:12:30 +01:00
parent c64427f4c8
commit 486a1e9809
8 changed files with 50 additions and 14 deletions

View File

@ -44,6 +44,10 @@ class Volume(abc.ABC):
def _backup_path(self): def _backup_path(self):
raise NotImplementedError raise NotImplementedError
@abc.abstractproperty
def _restore_path(self):
raise NotImplementedError
def backup(self): def backup(self):
print(f"Backing up {self._bucket_name}", flush=True) print(f"Backing up {self._bucket_name}", flush=True)
@ -68,9 +72,10 @@ class Volume(abc.ABC):
# -------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------
# Perform the backup. # Perform the backup.
# -------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------
subprocess.run(self._restic_cmd_base + ["backup", "."], cwd=self._backup_path, ps = subprocess.run(self._restic_cmd_base + ["backup", "."], cwd=self._backup_path,
env=self._environ, check=True, env=self._environ, check=True,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT) stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
print(ps.stdout.decode("ascii"), flush=True)
# -------------------------------------------------------------------------------------- # --------------------------------------------------------------------------------------
# Forget and prune old snapshots. # Forget and prune old snapshots.
@ -94,6 +99,19 @@ class Volume(abc.ABC):
print(err.stdout.decode("ascii"), flush=True) print(err.stdout.decode("ascii"), flush=True)
raise raise
def restore(self):
print(f"Restoring {self._bucket_name}", flush=True)
try:
subprocess.run(self._restic_cmd_base + ["restore", "latest", "--target", "."],
cwd=self._restore_path,
env=self._environ, check=True,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as err:
print(err.stdout.decode("ascii"), flush=True)
raise
class DirectoryVolume(Volume): class DirectoryVolume(Volume):
@ -105,6 +123,10 @@ class DirectoryVolume(Volume):
def _backup_path(self): def _backup_path(self):
return self.__directory return self.__directory
@property
def _restore_path(self):
return self.__directory
class DatasetMount: class DatasetMount:
@ -142,8 +164,9 @@ class DatasetVolume(Volume):
super().__init__(name, repo_config) super().__init__(name, repo_config)
self.__dataset = dataset self.__dataset = dataset
self.__snapshot = self.__get_last_daily_snapshot() self.__snapshot = self.__get_last_daily_snapshot()
self.__mountpoint = mountpoint
self.__backup_path = os.path.normpath( self.__backup_path = os.path.normpath(
os.path.join("/", "mnt", os.path.relpath(mountpoint, "/")) os.path.join("/", "mnt", os.path.relpath(self.__mountpoint, "/"))
) )
def __get_last_daily_snapshot(self): def __get_last_daily_snapshot(self):
@ -160,6 +183,10 @@ class DatasetVolume(Volume):
def _backup_path(self): def _backup_path(self):
return self.__backup_path return self.__backup_path
@property
def _restore_path(self):
return self.__mountpoint
def backup(self): def backup(self):
with DatasetMount(self.__snapshot, self._backup_path): with DatasetMount(self.__snapshot, self._backup_path):
super().backup() super().backup()

View File

@ -40,6 +40,10 @@
state: "directory" state: "directory"
mode: 0755 mode: 0755
- name: "install restic-batch dependencies"
ansible.builtin.apt:
name: "python3-yaml"
- name: "install the restic-batch script" - name: "install the restic-batch script"
ansible.builtin.copy: ansible.builtin.copy:
src: "./restic-batch" src: "./restic-batch"

View File

@ -1,7 +0,0 @@
---
argument_specs:
main:
options:
services_data_dataset:
type: "str"
required: true

View File

@ -0,0 +1,4 @@
---
services_backups_user_data_dataset: "{{ services_data_dataset }}/{{ services_service_user_name }}"
services_backups_user_data_directory: "\
{{ services_data_directory }}/{{ services_service_user_name }}"

View File

@ -1,2 +0,0 @@
---
services_backups_user_data_dataset: "{{ services_data_dataset }}/{{ services_service_user_name }}"

View File

@ -8,6 +8,12 @@ argument_specs:
services_service_name: services_service_name:
type: "str" type: "str"
required: true required: true
services_data_dataset:
type: "str"
required: false
services_data_directory:
type: "str"
required: false
services_backups_restic_services: services_backups_restic_services:
type: "dict" type: "dict"
elem: "dict" elem: "dict"

View File

@ -7,7 +7,7 @@
- name: "{{ services_service_name }} : tasks:vars" - name: "{{ services_service_name }} : tasks:vars"
ansible.builtin.import_role: ansible.builtin.import_role:
name: "services/backups/include" name: "services/backups/include"
vars_from: "main" vars_from: "datasets"
- name: "{{ services_service_name }} : create restic password file" - name: "{{ services_service_name }} : create restic password file"
ansible.builtin.template: ansible.builtin.template:

View File

@ -1,4 +1,8 @@
{% if services_data_dataset is defined %}
dataset: {{ services_backups_user_data_dataset }} dataset: {{ services_backups_user_data_dataset }}
{% else %}
directory: {{ services_backups_user_data_directory }}
{% endif %}
aws_bucket_keys_file: {{ services_backups_restic_services[services_service_name].aws_keys_file }} aws_bucket_keys_file: {{ services_backups_restic_services[services_service_name].aws_keys_file }}
aws_bucket_endpoint: {{ services_backups_restic_services[services_service_name].aws_bucket_endpoint }} aws_bucket_endpoint: {{ services_backups_restic_services[services_service_name].aws_bucket_endpoint }}
aws_bucket_prefix: {{ services_backups_restic_services[services_service_name].aws_bucket_prefix }} aws_bucket_prefix: {{ services_backups_restic_services[services_service_name].aws_bucket_prefix }}