mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2024-11-26 06:31:04 +01:00
Optimized auto backup
This commit is contained in:
parent
6b8e03a0ab
commit
bbb19b7452
@ -4,22 +4,18 @@ This Ansible role automates the process of performing backups to a swappable USB
|
|||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Automatically starts the backup process when a specific USB device is plugged in.
|
- Automatically starts the backup process when mounted to a specific destination.
|
||||||
- Provides a systemd service to run the backup script at boot if the USB device is already connected.
|
- Supports customization of the backup source path and destination.
|
||||||
- Supports customization of the backup source path and mount point.
|
- Provides a systemd service to run the backup script.
|
||||||
|
|
||||||
## Configuration
|
## Author
|
||||||
|
|
||||||
The following variables can be customized in the `vars/main.yml` file:
|
This role was created and is maintained by Kevin Veen-Birkenbach.
|
||||||
|
|
||||||
- `mount_point`: The mount point where the USB device will be mounted.
|
## License
|
||||||
- `backup_to_usb_script_path`: The path to the backup script that will be executed when the USB device is connected.
|
|
||||||
|
This code is released under the AGPL v3 license. Please refer to the [LICENSE](LICENSE) file for more details.
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
This role was created and maintained by Kevin Veen-Birkenbach.
|
This software was created with the assistance of [OpenAI ChatGPT](https://chat.openai.com/share/a75ca771-d8a4-4b75-9912-c515ba371ae4).
|
||||||
Contact: kevin@veen.world
|
|
||||||
|
|
||||||
## More Information
|
|
||||||
|
|
||||||
For more details on how the `independent_backup-to-usb` role works, please refer to the Ansible documentation and the role's source code.
|
|
60
roles/independent_backup-to-usb/files/backup-to-usb.python
Normal file
60
roles/independent_backup-to-usb/files/backup-to-usb.python
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import subprocess
|
||||||
|
import shutil
|
||||||
|
import os
|
||||||
|
import glob
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
def main():
|
||||||
|
source_path = sys.argv[1]
|
||||||
|
print(f"source path: {source_path}")
|
||||||
|
|
||||||
|
backup_to_usb_destination_path = sys.argv[2]
|
||||||
|
print(f"backup to usb destination path: {backup_to_usb_destination_path}")
|
||||||
|
|
||||||
|
if not os.path.isdir(backup_to_usb_destination_path):
|
||||||
|
print(f"Directory {backup_to_usb_destination_path} does not exist")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
machine_id = subprocess.run(["sha256sum", "/etc/machine-id"], capture_output=True, text=True).stdout.strip()[:64]
|
||||||
|
print(f"machine id: {machine_id}")
|
||||||
|
|
||||||
|
versions_path = os.path.join(backup_to_usb_destination_path, f"{machine_id}/backup-to-usb/")
|
||||||
|
print(f"versions path: {versions_path}")
|
||||||
|
|
||||||
|
if not os.path.isdir(versions_path):
|
||||||
|
print(f"Creating {versions_path}...")
|
||||||
|
os.makedirs(versions_path, exist_ok=True)
|
||||||
|
|
||||||
|
previous_version_path = max(glob.glob(f"{versions_path}*"), key=os.path.getmtime, default=None)
|
||||||
|
print(f"previous versions path: {previous_version_path}")
|
||||||
|
|
||||||
|
current_version_path = os.path.join(versions_path, datetime.datetime.now().strftime("%Y%m%d%H%M%S"))
|
||||||
|
print(f"current versions path: {current_version_path}")
|
||||||
|
|
||||||
|
print("Creating backup destination folder...")
|
||||||
|
os.makedirs(current_version_path, exist_ok=True)
|
||||||
|
|
||||||
|
print("Starting synchronization...")
|
||||||
|
try:
|
||||||
|
rsync_command = [
|
||||||
|
"rsync", "-abP", "--delete", "--delete-excluded",
|
||||||
|
"--link-dest=" + previous_version_path,
|
||||||
|
source_path, current_version_path
|
||||||
|
]
|
||||||
|
rsync_output = subprocess.check_output(rsync_command, stderr=subprocess.STDOUT, text=True)
|
||||||
|
|
||||||
|
if "rsync warning: some files vanished before they could be transferred" in rsync_output:
|
||||||
|
print("Synchronization finished with rsync warning")
|
||||||
|
sys.exit(0)
|
||||||
|
else:
|
||||||
|
print("Synchronization finished")
|
||||||
|
sys.exit(0)
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print("Synchronization failed:", e.output)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
@ -1,3 +1,6 @@
|
|||||||
---
|
- name: "reload backup-to-usb.service"
|
||||||
- name: Reload udev rules
|
systemd:
|
||||||
command: udevadm control --reload-rules && udevadm trigger
|
name: backup-to-usb.service
|
||||||
|
state: reloaded
|
||||||
|
enabled: yes
|
||||||
|
daemon_reload: yes
|
||||||
|
@ -1,13 +1,6 @@
|
|||||||
---
|
|
||||||
- name: Copy udev rule to the rules directory
|
|
||||||
template:
|
|
||||||
src: 99-usbstick.rules.j2
|
|
||||||
dest: /etc/udev/rules.d/
|
|
||||||
notify: Reload udev rules
|
|
||||||
|
|
||||||
- name: Copy backup script to the scripts directory
|
- name: Copy backup script to the scripts directory
|
||||||
template:
|
copy:
|
||||||
src: backup-to-usb.sh.j2
|
src: backup-to-usb.python
|
||||||
dest: "{{ backup_to_usb_script_path }}"
|
dest: "{{ backup_to_usb_script_path }}"
|
||||||
owner: root
|
owner: root
|
||||||
group: root
|
group: root
|
||||||
@ -20,9 +13,4 @@
|
|||||||
owner: root
|
owner: root
|
||||||
group: root
|
group: root
|
||||||
mode: '0644'
|
mode: '0644'
|
||||||
|
notify: reload backup-to-usb.service
|
||||||
- name: Enable and start service
|
|
||||||
systemd:
|
|
||||||
name: backup-to-usb
|
|
||||||
enabled: yes
|
|
||||||
state: started
|
|
@ -1 +0,0 @@
|
|||||||
ACTION=="add", SUBSYSTEM=="block", ENV{ID_SERIAL_SHORT}=="{{ backup_to_usb_serial_short }}", RUN+="/usr/bin/systemd-mount --no-block $devnode {{ mount_point }}", SYMLINK+="backup_usb"
|
|
@ -1,10 +1,13 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=Backup to USB when it's plugged in
|
Description=Backup to USB when mounted to {{ backup_to_usb_mount }}
|
||||||
After=local-fs.target
|
Wants={{systemctl_mount_service_name}}
|
||||||
|
After={{systemctl_mount_service_name}}
|
||||||
OnFailure=systemd-email@%n.service
|
OnFailure=systemd-email@%n.service
|
||||||
|
Requires=backups-cleanup.service
|
||||||
|
After=backups-cleanup.service
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
ExecStart={{ backup_to_usb_script_path }} {{ mount_point }}/{{ backup_to_usb_subdirectory }} {{ backup_to_usb_source_path }}
|
ExecStart=/bin/python {{ backup_to_usb_script_path }} {{backup_to_usb_source}} {{backup_to_usb_destination}}
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
@ -1,35 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
backup_to_usb_destination_path="{{ mount_point }}" &&
|
|
||||||
echo "backup to usb destination path: $backup_to_usb_destination_path" &&
|
|
||||||
|
|
||||||
source_path="{{ backup_to_usb_source_path }}" &&
|
|
||||||
echo "source path: $source_path" || exit 1
|
|
||||||
|
|
||||||
if [ ! -d "$backup_to_usb_destination_path" ]; then
|
|
||||||
echo "Directory $backup_to_usb_destination_path does not exist" &&
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
machine_id="$(sha256sum /etc/machine-id | head -c 64 )" &&
|
|
||||||
echo "machine id: $machine_id" &&
|
|
||||||
|
|
||||||
versions_path="$backup_to_usb_destination_path$machine_id/backup-to-usb/" &&
|
|
||||||
echo "versions path: $versions_path" || exit 1
|
|
||||||
|
|
||||||
if [ ! -d "$versions_path" ]; then
|
|
||||||
echo "Creating $versions_path..." &&
|
|
||||||
mkdir -vp $versions_path || exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
previous_version_path="$(ls -d $versions_path* | tail -1)" &&
|
|
||||||
echo "previous versions path: $previous_version_path" &&
|
|
||||||
|
|
||||||
current_version_path="$versions_path$(date '+%Y%m%d%H%M%S')" &&
|
|
||||||
echo "current versions path: $current_version_path" &&
|
|
||||||
|
|
||||||
echo "creating backup destination folder..." &&
|
|
||||||
mkdir -vp "$current_version_path" &&
|
|
||||||
|
|
||||||
echo "Starting synchronization..."
|
|
||||||
rsync -abP --delete --delete-excluded --link-dest="$previous_version_path" "$source_path" "$current_version_path" &&
|
|
||||||
echo "Synchronization finished." || exit 1
|
|
@ -1,4 +1,4 @@
|
|||||||
---
|
backup_to_usb_script_path: "/usr/local/sbin/backup-to-usb.python"
|
||||||
mount_point: "/mnt/usbstick_{{ backup_to_usb_serial_short }}"
|
backup_to_usb_destination: "{{backup_to_usb_mount}}{{backup_to_usb_destination_subdirectory}}"
|
||||||
backup_to_usb_script_path: "/usr/local/sbin/backup-to-usb.sh"
|
backups_folder_path: "{{backup_to_usb_destination}}"
|
||||||
backups_folder_path: "{{mount_point}}{{backup_to_usb_subdirectory}}"
|
systemctl_mount_service_name: "{{ backup_to_usb_mount | trim('/') | replace('/', '-') }}.mount"
|
Loading…
Reference in New Issue
Block a user