-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathincus-backup-zfs
executable file
·84 lines (75 loc) · 2.68 KB
/
incus-backup-zfs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#!/bin/bash
set -eu
function is_available {
command -v $1 >/dev/null 2>&1 || { echo "Required binary '$1' not available." >&2; exit 1; }
}
is_available yq
is_available jq
is_available numfmt
is_available incus
is_available zfs
is_available pv
is_available grep
is_available awk
ARGNUM=3
if [ $# -lt $(($ARGNUM)) ] || [ $# -gt $ARGNUM ]; then
COMMAND='help'
else
COMMAND=${1:-help}
CONTAINER=$2
TARGET=$3
if [ $CONTAINER == '-a' ]; then
if [ ! -d ${TARGET} ]; then
echo "Error: directory '${TARGET}' does not exist."
exit 1
fi
container_list="$(incus list -c ns | awk '!/NAME/{ if ( $4 == "RUNNING" ) print $2}')"
for container in $container_list; do
$0 $COMMAND $container $TARGET/$container.zfs
done
exit 0
fi
if [[ ! "$CONTAINER" =~ ^[a-zA-Z0-9] ]]; then
echo "Error: container name needs to start with alphanumeric character."
exit 1
fi
HASH=$(echo $CONTAINER | shasum | cut -b 1-30)
SNAPSHOT_INCUS="$HASH"
SNAPSHOT_ZFS="snapshot-$SNAPSHOT_INCUS"
fi
STORAGENAME=$(incus profile device get default root pool)
POOLNAME=$(incus storage show $STORAGENAME | grep zfs.pool_name: | awk '{print $2}')
POOLDRIVER=$(incus storage show $STORAGENAME | grep driver: | awk '{print $2}')
[ "$POOLDRIVER" != 'zfs' ] && echo "Error: default storage pool is of type '$POOLDRIVER', only ZFS is supported." && exit 1
case "$COMMAND" in
"export")
if [ -d ${TARGET} ]; then
echo "Error: file '${TARGET}' is a directory."
exit 1
fi
incus info $CONTAINER >/dev/null
CONTAINER_STATE=$(incus query /1.0/instances/$CONTAINER | jq .status)
incus snapshot delete $CONTAINER $SNAPSHOT_INCUS 2>/dev/null || true
[ $CONTAINER_STATE == '"Running"' ] && incus stop $CONTAINER 2>/dev/null || true
incus snapshot create --no-expiry $CONTAINER $SNAPSHOT_INCUS
[ $CONTAINER_STATE == '"Running"' ] && incus start $CONTAINER 2>/dev/null || true
SIZE=$(zfs send -Pnc $POOLNAME/containers/$CONTAINER@$SNAPSHOT_ZFS | grep size | awk '{print $2}')
zfs send -c $POOLNAME/containers/$CONTAINER@$SNAPSHOT_ZFS | pv -s $SIZE > ${TARGET}
incus snapshot delete $CONTAINER $SNAPSHOT_INCUS
;;
"import")
if [ ! -f ${TARGET} ]; then
echo "Error: file '${TARGET}' does not exist."
exit 1
fi
incus create $CONTAINER --empty >/dev/null
pv < ${TARGET} | zfs receive -F $POOLNAME/containers/$CONTAINER
zfs destroy $POOLNAME/containers/$CONTAINER@%
;;
*)
echo
echo "Wrong parameters! Usage: incus-backup-zfs [ export | import ] [ CONTAINER | -a ] FILENAME"
echo " (-a parameter exports all running containers)"
echo "This script only works for containers on ZFS storage pools and exports to a native ZFS data file."
;;
esac