aboutsummaryrefslogtreecommitdiff
path: root/zfs-squash-datasets.sh
blob: 3623edfce224f966e7e37b8dce2ce9672df6541f (plain)
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/usr/local/bin/bash

# DO NOT USE THIS SCRIPT
# It is in a state of hot garbage and will probably be deleted soon


print_help_and_exit() {
    echo "Please run this program with a source and a target dataset name as arguments"
    echo "e.g. $0 zpool/dataset1 zpool/dataset2"
    exit
}

SIMULATION=0

args=$(getopt n $*)
test $? == 0 || print_help_and_exit

set -- $args

while :; do
    sleep 1
    echo $1
    case "$1" in
        --) shift; break ;;
        -n) SIMULATION=1 ; shift ;;
    esac
done

DATASET_ROOT=$1
DATASET_TARGET=$2

if ! zfs get mountpoint $DATASET_TARGET >/dev/null; then
    echo "Dataset $DATASET_TARGET does not exist and will be created."
    echo "You have 10 seconds to abort this with CTRL-C"
    sleep 10
    if ! $SIMULATION; then
        zfs create $DATASET_TARGET
    fi
fi

if zfs get -H -t filesystem -o name,value -r snapdir zeus/data/projects | grep -v visible >/dev/null; then
    echo Please make all snapdirs visible:
    zfs get -H -t filesystem -o name,value -r snapdir zeus/data/projects
    exit 2
fi


MOUNTPOINT_TARGET=$(zfs get -o value -H mountpoint $DATASET_TARGET)
test ${SIMULATION:0} = 1 && test $MOUNTPOINT_TARGET == "" && MOUNTPOINT_TARGET="datapool/simulation"

test -d "$MOUNTPOINT_TARGET" || print_help_and_exit

# make sure, that ctrl-c also works in the inner loops
trap exit INT

# recursively contains all snapshot names (the part after the @) from root on, sorted and only once
SNAPSHOTS=$(zfs list -H  -oname -tsnap -r $DATASET_ROOT | cut -d@ -f2 | sort -u)
DATASETS=$(zfs list -H -oname -t filesystem -r $DATASET_ROOT)

test "${SIMULATION:-0}" = 1 && echo "SIMULATION MODE"

$DATASETS


echo "We are going to flatten the hierachy of this dataset:"
printf "\t%s\n" $DATASETS
echo -e "into the dataset with the name:"
echo -e "\t$DATASET_TARGET"
echo -e "mounted under:"
echo -e "\t$MOUNTPOINT_TARGET"
echo -e "with the following snapshots:"
printf "\t%s\n" $SNAPSHOTS
echo ""
echo "You have 10 seconds to abort this with CTRL-C"
sleep 10

set -- $SNAPSHOTS
SNAPSHOTS_TOTAL=$#
SNAPSHOT_CURRENT=0

set -- $DATASETS
shift
SUBDATASETS=$@

for SNAPSHOT in $SNAPSHOTS; do
    echo ""
    echo ""
    SNAPSHOT_CURRENT=$((SNAPSHOT_CURRENT + 1))
    echo "[$SNAPSHOT_CURRENT/$SNAPSHOTS_TOTAL] Next snapshot is: $SNAPSHOT"

    for DATASET in $SUBDATASETS; do

        DATASET_RELATIVE=${DATASET##$DATASET_ROOT}

        MOUNTPOINT=$(zfs get -H -o value mountpoint $DATASET)
        echo "RELATIVE=$DATASET_RELATIVE"

        if [[ $MOUNTPOINT == "legacy" ]]; then
            MOUNTPOINT=$(findmnt -n -o target $DATASET)
            if test -d $MOUNTPOINT; then
                >&2 echo "Dataset has a legacy mountpoint, but was not found in the fstab: $DATASET"
                continue
            fi
        fi

        if [[ $MOUNTPOINT == "-" ]]; then
            >&2 echo "Dataset does not have a mount point or is a vdev: $DATASET"
            continue
        fi

        SNAPDIR=$MOUNTPOINT/.zfs/snapshot/$SNAPSHOT
        if test -d $SNAPDIR; then

            TARGET_DIR="${MOUNTPOINT_TARGET}${DATASET_RELATIVE}"

            echo -e \\trsync --info=stats3 --delete -a "$SNAPDIR/" "$TARGET_DIR/"
            if test "${SIMULATION:-0}" = 0; then

                mkdir -p "$TARGET_DIR"

                if ! rsync --info=stats3 --delete -a "$SNAPDIR/" "$TARGET_DIR/" ; then
                    >&2 echo "rsync could not entirely copy from $SNAPDIR to $DATASET_TARGET"
                fi
            fi
        else
            echo -e "\tSKIP: Snapshot $SNAPSHOT does not exist for dataset $DATASET"
        fi
    done

    NEW_SNAPSHOT="$DATASET_TARGET@$SNAPSHOT"
    echo ""
    echo -e "\t> Concluding snapshot: ${NEW_SNAPSHOT} <"
    echo ""

    if test "${SIMULATION:-0}" = 0; then
        zfs snap $NEW_SNAPSHOT
    fi
done

..