Add the git review file
[zfs-ubuntu/.git] / snap.sh
1 #!/bin/bash
2
3 exec >> /var/log/snap.log 2>&1
4
5 # This script makes the following assumptions/requirements:
6 #  * this script only handles one zfs filesystem, a wrapper should be created
7 #    to handle more
8 #  * this script handles all snapshots that are named in this format:
9 #    YYYY-MM-DD.hh.mm
10 #  * It ignores other snapshots that don't follow this naming convention
11
12 # This converts the YYYY-MM-DD.hh.mm format to an integer.
13 datetime_to_minutes() {
14   perl -n -e '/(\d+)-(\d+)-(\d+)\.(\d+)\.(\d+)/; print $1 * 527040 + $2 * 44640 + $3 * 1440 + $4 * 60 + $5,"\n"'
15 }
16
17 datetime_to_minutes2() {
18   perl -n -e '/(\d+)-(\d+)-(\d+)\.(\d+)\.(\d+)/; $monthadj=int(($2-1)/3)-1; $minadj=int($5/15); $houradj=int($4/3); print $1 * 1048576 + ( $2 + $monthadj ) * 65536 + $3 * 2048 + ( $4 + $houradj ) * 64 + $5 + $minadj,"\n"'
19 }
20
21 # filesystem: This is the zfs filesystem to snapshot
22 # mountpoint: This is the mountpoint of the zfs filesystem to snapshot
23 # numsnapshots: This number is the number of equally spaced snapshots that should exist over any given period in the past
24 # maxagedays: This is the maximum number of days to keep any snapshot around for (0=infinite) (default=0).
25 filesystem=$1
26 mountpoint=$2
27 numsnapshots=${3-12}
28 maxagedays=${4-0}
29 lockdir="/tmp/${filesystem}.lock"
30 pool=`echo "$filesystem" | awk -F '/' '{ print $1 }'`
31
32 if [ -z "$filesystem" ] || [ -z "$mountpoint" ] || [ -z "$numsnapshots" ] || [ -z "$maxagedays" ]; then
33    echo "-E- Usage: $0 <filesystem> <mountpoint> <numsnapshots> <maxagedays>"
34    exit 1
35 fi
36
37 if [ ! -d "$mountpoint" ]; then
38    echo "-E- Unable to find the mountpoint: $mountpoint"
39    exit 1
40 fi
41
42 snapshotdir="${mountpoint}/.zfs/snapshot"
43 if [ ! -d "$snapshotdir" ]; then
44    echo "-E- Unable to find the snapshotdir: $snapshotdir"
45    exit 1
46 fi
47
48 # Check to see if this zfs filesystem has a scrub being performed on it now.
49 # If it does, we cannot perform any snapshot create or destroy operations.
50 zpool status $pool | grep scrub: | grep "in progress" > /dev/null 2>&1
51 if [ $? == 0 ]; then
52    echo "-W- The zfs pool '$pool' is currently being scrubbed. Skipping all snapshot operations."
53    exit 0
54 fi
55
56 # Get the various components of the date
57 datetime=${ZFSDATETIME:-$(date +%Y-%m-%d.%H.%M)}
58
59 # Create the snapshot for this minute
60 echo "-I- Creating ${filesystem}@${datetime}"
61 zfs snapshot "${filesystem}@${datetime}"
62
63 minutes=$(echo $datetime | datetime_to_minutes)
64
65 lockdir="/tmp/zfs-admin-lock"
66 if ! mkdir "$lockdir" >/dev/null 2>&1; then
67   exit 0
68 fi
69 cleanup() { rm -rf "$lockdir"; }
70 trap cleanup EXIT
71
72 # Trim them down
73 snapshots=$(ls -d ${snapshotdir}/????-??-??.??.?? 2>/dev/null)
74 for snapshot in $snapshots; do
75   snapminutes=$(echo "$snapshot" | sed 's,.*/,,' | datetime_to_minutes)
76   snapminutes2=$(echo "$snapshot" | sed 's,.*/,,' | datetime_to_minutes2)
77   age=$((minutes - snapminutes))
78   window=1
79   while true; do
80     if [ $age -lt $((window * numsnapshots)) ]; then
81       case $((snapminutes2 % window)) in
82         0) ;;
83         *)
84           snapname=$(echo "$snapshot" |
85                        sed 's,/\(.*\)/.zfs/snapshot/\(.*\),\1@\2,')
86           echo "-I- Destroying $snapname"
87           zfs destroy "$snapname"
88         ;;
89       esac
90       break
91     fi
92     window=$((window*2))
93   done
94   if [ $maxagedays -gt 0 ] && [ $age -gt $((maxagedays * 24 * 60)) ]; then
95     snapname=$(echo "$snapshot" |
96                      sed 's,/\(.*\)/.zfs/snapshot/\(.*\),\1@\2,')
97     echo "-I- Destroying old $snapname"
98     zfs destroy "$snapname"
99   fi
100 done