POSIX shell doesn't allow 'local' outside functions. Fixed for busybox/ash compatibility. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
236 lines
5.5 KiB
Bash
236 lines
5.5 KiB
Bash
#!/bin/sh
|
|
# SecuBox Backup Manager RPCD Handler
|
|
|
|
. /usr/share/libubox/jshn.sh
|
|
|
|
BACKUP_CMD="/usr/sbin/secubox-backup"
|
|
|
|
case "$1" in
|
|
list)
|
|
cat <<-EOF
|
|
{
|
|
"status": {},
|
|
"list": { "type": "string" },
|
|
"container_list": {},
|
|
"create": { "type": "string" },
|
|
"restore": { "file": "string", "dry_run": "boolean" },
|
|
"cleanup": {},
|
|
"container_backup": { "name": "string" },
|
|
"container_restore": { "name": "string", "file": "string" }
|
|
}
|
|
EOF
|
|
;;
|
|
|
|
call)
|
|
case "$2" in
|
|
status)
|
|
json_init
|
|
|
|
# Get storage info
|
|
storage=$($BACKUP_CMD status 2>/dev/null | grep "Storage Path" | cut -d: -f2 | tr -d ' ')
|
|
used=$($BACKUP_CMD status 2>/dev/null | grep "Storage Used" | cut -d: -f2 | tr -d ' ')
|
|
|
|
json_add_string "storage_path" "${storage:-/srv/backups}"
|
|
json_add_string "storage_used" "${used:-0}"
|
|
|
|
# Last backup times
|
|
json_add_object "last_backup"
|
|
for type in config containers services; do
|
|
latest=$(ls -t "${storage:-/srv/backups}/$type/"*.tar* 2>/dev/null | head -1)
|
|
if [ -n "$latest" ]; then
|
|
bdate=$(stat -c %Y "$latest" 2>/dev/null)
|
|
json_add_int "$type" "${bdate:-0}"
|
|
else
|
|
json_add_int "$type" 0
|
|
fi
|
|
done
|
|
json_close_object
|
|
|
|
# Container count
|
|
containers=$(ls -d /srv/lxc/*/ 2>/dev/null | wc -l)
|
|
json_add_int "container_count" "$containers"
|
|
|
|
json_dump
|
|
;;
|
|
|
|
list)
|
|
json_load "$3"
|
|
json_get_var type type
|
|
type="${type:-all}"
|
|
|
|
storage=$(uci -q get backup.main.storage_path)
|
|
storage="${storage:-/srv/backups}"
|
|
|
|
json_init
|
|
json_add_array "backups"
|
|
|
|
# List config backups
|
|
if [ "$type" = "all" ] || [ "$type" = "config" ]; then
|
|
ls "$storage/config/"*.tar* 2>/dev/null | while read f; do
|
|
[ -f "$f" ] || continue
|
|
json_add_object ""
|
|
json_add_string "file" "$(basename "$f")"
|
|
json_add_string "type" "config"
|
|
json_add_string "size" "$(du -h "$f" 2>/dev/null | cut -f1)"
|
|
json_add_int "timestamp" "$(stat -c %Y "$f" 2>/dev/null)"
|
|
json_close_object
|
|
done
|
|
fi
|
|
|
|
# List container backups
|
|
if [ "$type" = "all" ] || [ "$type" = "containers" ]; then
|
|
ls "$storage/containers/"*.tar* 2>/dev/null | while read f; do
|
|
[ -f "$f" ] || continue
|
|
json_add_object ""
|
|
json_add_string "file" "$(basename "$f")"
|
|
json_add_string "type" "container"
|
|
json_add_string "size" "$(du -h "$f" 2>/dev/null | cut -f1)"
|
|
json_add_int "timestamp" "$(stat -c %Y "$f" 2>/dev/null)"
|
|
json_close_object
|
|
done
|
|
fi
|
|
|
|
# List service backups
|
|
if [ "$type" = "all" ] || [ "$type" = "services" ]; then
|
|
ls "$storage/services/"*.tar* 2>/dev/null | while read f; do
|
|
[ -f "$f" ] || continue
|
|
json_add_object ""
|
|
json_add_string "file" "$(basename "$f")"
|
|
json_add_string "type" "service"
|
|
json_add_string "size" "$(du -h "$f" 2>/dev/null | cut -f1)"
|
|
json_add_int "timestamp" "$(stat -c %Y "$f" 2>/dev/null)"
|
|
json_close_object
|
|
done
|
|
fi
|
|
|
|
json_close_array
|
|
json_dump
|
|
;;
|
|
|
|
container_list)
|
|
json_init
|
|
json_add_array "containers"
|
|
|
|
for dir in /srv/lxc/*/; do
|
|
[ -d "$dir" ] || continue
|
|
name=$(basename "$dir")
|
|
[ -f "$dir/config" ] || continue
|
|
|
|
state="stopped"
|
|
lxc-info -n "$name" 2>/dev/null | grep -q "RUNNING" && state="running"
|
|
size=$(du -sh "$dir" 2>/dev/null | awk '{print $1}')
|
|
|
|
# Count backups for this container
|
|
storage=$(uci -q get backup.main.storage_path)
|
|
storage="${storage:-/srv/backups}"
|
|
backup_count=$(ls -1 "$storage/containers/${name}-"*.tar* 2>/dev/null | wc -l)
|
|
|
|
json_add_object ""
|
|
json_add_string "name" "$name"
|
|
json_add_string "state" "$state"
|
|
json_add_string "size" "$size"
|
|
json_add_int "backups" "$backup_count"
|
|
json_close_object
|
|
done
|
|
|
|
json_close_array
|
|
json_dump
|
|
;;
|
|
|
|
create)
|
|
json_load "$3"
|
|
json_get_var type type
|
|
type="${type:-full}"
|
|
|
|
result=$($BACKUP_CMD create --$type 2>&1)
|
|
rc=$?
|
|
|
|
json_init
|
|
json_add_int "code" "$rc"
|
|
json_add_string "output" "$result"
|
|
json_dump
|
|
;;
|
|
|
|
restore)
|
|
json_load "$3"
|
|
json_get_var file file
|
|
json_get_var dry_run dry_run
|
|
|
|
[ -z "$file" ] && {
|
|
json_init
|
|
json_add_int "code" 1
|
|
json_add_string "error" "No file specified"
|
|
json_dump
|
|
exit 0
|
|
}
|
|
|
|
opts=""
|
|
[ "$dry_run" = "1" ] || [ "$dry_run" = "true" ] && opts="--dry-run"
|
|
|
|
result=$($BACKUP_CMD restore "$file" $opts 2>&1)
|
|
rc=$?
|
|
|
|
json_init
|
|
json_add_int "code" "$rc"
|
|
json_add_string "output" "$result"
|
|
json_dump
|
|
;;
|
|
|
|
cleanup)
|
|
result=$($BACKUP_CMD cleanup 2>&1)
|
|
rc=$?
|
|
|
|
json_init
|
|
json_add_int "code" "$rc"
|
|
json_add_string "output" "$result"
|
|
json_dump
|
|
;;
|
|
|
|
container_backup)
|
|
json_load "$3"
|
|
json_get_var name name
|
|
|
|
[ -z "$name" ] && {
|
|
json_init
|
|
json_add_int "code" 1
|
|
json_add_string "error" "No container name specified"
|
|
json_dump
|
|
exit 0
|
|
}
|
|
|
|
result=$($BACKUP_CMD container backup "$name" 2>&1)
|
|
rc=$?
|
|
|
|
json_init
|
|
json_add_int "code" "$rc"
|
|
json_add_string "output" "$result"
|
|
json_dump
|
|
;;
|
|
|
|
container_restore)
|
|
json_load "$3"
|
|
json_get_var name name
|
|
json_get_var file file
|
|
|
|
[ -z "$name" ] || [ -z "$file" ] && {
|
|
json_init
|
|
json_add_int "code" 1
|
|
json_add_string "error" "Container name and backup file required"
|
|
json_dump
|
|
exit 0
|
|
}
|
|
|
|
result=$($BACKUP_CMD container restore "$name" "$file" 2>&1)
|
|
rc=$?
|
|
|
|
json_init
|
|
json_add_int "code" "$rc"
|
|
json_add_string "output" "$result"
|
|
json_dump
|
|
;;
|
|
esac
|
|
;;
|
|
esac
|
|
|
|
exit 0
|