Files
eidf-infra-backup/lxc-backup.sh
T
2026-01-12 15:28:42 +00:00

107 lines
2.5 KiB
Bash
Executable File

#!/usr/bin/env bash
main() {
while getopts ":l:d:t:c:h" opt; do
case "${opt}" in
l)
unset VM_FILTER
IFS="," read -r -a VM_FILTER <<< "$OPTARG"
;;
d)
local backup_location="${OPTARG}"
backup_location="${backup_location%/}"
;;
t)
declare -g TARGET="$OPTARG"
;;
c)
declare -g run_cleanup=y
declare -g files_to_keep="${OPTARG}"
;;
h)
usage
;;
*)
usage
;;
esac
done
backup_location=${backup_location:-$PWD}
if [[ "${#VM_FILTER[*]}" -gt 0 ]]; then
backup_vms "$backup_location" "${VM_FILTER[@]}"
else
backup_vms "$backup_location"
fi
}
lxc() {
local lxc_cmd="${TARGET:-lxc}"
command "$lxc_cmd" "$@"
}
list_vms() {
lxc list -c n -f csv
}
usage() {
cat <<EOF
Usage: ${0##*/} [-l vm[,vm...]] [-d backup_dir] [-t lxc|incus] [-c <keep n backups>] [-h]
Options:
-l Comma-separated list of VMs to back up
-d Directory where backups will be stored (default: current directory)
-t Manager type: lxc or incus (default: lxc)
-c Cleanup old backups keeping a set number (default: 2)
-h Show this message
EOF
exit 1
}
backup_vms() {
local backup_location="$1"; shift
local vms=("$@")
# when no argument use list of all VMs
if ((${#vms[@]} == 0)); then
mapfile -t vms < <(list_vms)
fi
for vm in "${vms[@]}"; do
[[ -n $vm ]] || continue
start_backup "$vm" "$backup_location"
done
}
start_backup() {
local vm=$1
local backup_base="$2"
local destination="${backup_base}/${vm}"
local backup_name="${vm}_$(date +"%Y-%m-%d_%H-%M-%S").tar"
[[ -d "$backup_base" ]] || { echo "${backup_base} is not a directory"; exit 1; }
[[ -d "$destination" ]] || mkdir "$destination"
[[ -f "${destination}/${backup_name}" ]] && { echo "Backup already exists"; return 2; }
lxc export "$vm" --instance-only --compression none "${destination}/${backup_name}" || { echo "Error exporting $vm"; return 1; }
[[ -n "$run_cleanup" ]] && prune_backups "$destination"
}
prune_backups() {
local backup_directory="$1"
mapfile -t backup_files < <(find "$backup_directory" -maxdepth 1 -name "*.tar" -printf '%T@ %p\n' | sort -n | head -n "-${files_to_keep}" | cut -d' ' -f2-)
if [[ ${#backup_files[@]} -gt 0 ]]; then
echo "Removing ${#qcow2_files[@]} old backup files for $vm (keeping last $total_files_to_keep files)"
printf '%s\0' "${backup_files[@]}" | xargs -0 rm -fv
else
echo "No old backups to remove for $vm"
fi
}
main "$@"