diff options
| -rwxr-xr-x | zfs-squash-datasets.sh | 115 |
1 files changed, 93 insertions, 22 deletions
diff --git a/zfs-squash-datasets.sh b/zfs-squash-datasets.sh index d668c80..3623edf 100755 --- a/zfs-squash-datasets.sh +++ b/zfs-squash-datasets.sh | |||
| @@ -1,42 +1,99 @@ | |||
| 1 | #!/usr/local/bin/bash | 1 | #!/usr/local/bin/bash |
| 2 | DATASET_ROOT=$1 | ||
| 3 | DATASET_TARGET=$2 | ||
| 4 | 2 | ||
| 5 | MOUNTPOINT_TARGET=$(zfs get -o value -H mountpoint $DATASET_TARGET) | 3 | # DO NOT USE THIS SCRIPT |
| 4 | # It is in a state of hot garbage and will probably be deleted soon | ||
| 6 | 5 | ||
| 7 | if ! test -d "$MOUNTPOINT_TARGET"; then | 6 | |
| 7 | print_help_and_exit() { | ||
| 8 | echo "Please run this program with a source and a target dataset name as arguments" | 8 | echo "Please run this program with a source and a target dataset name as arguments" |
| 9 | echo "e.g. $0 zpool/dataset1 zpool/dataset2" | 9 | echo "e.g. $0 zpool/dataset1 zpool/dataset2" |
| 10 | exit | 10 | exit |
| 11 | } | ||
| 12 | |||
| 13 | SIMULATION=0 | ||
| 14 | |||
| 15 | args=$(getopt n $*) | ||
| 16 | test $? == 0 || print_help_and_exit | ||
| 17 | |||
| 18 | set -- $args | ||
| 19 | |||
| 20 | while :; do | ||
| 21 | sleep 1 | ||
| 22 | echo $1 | ||
| 23 | case "$1" in | ||
| 24 | --) shift; break ;; | ||
| 25 | -n) SIMULATION=1 ; shift ;; | ||
| 26 | esac | ||
| 27 | done | ||
| 28 | |||
| 29 | DATASET_ROOT=$1 | ||
| 30 | DATASET_TARGET=$2 | ||
| 31 | |||
| 32 | if ! zfs get mountpoint $DATASET_TARGET >/dev/null; then | ||
| 33 | echo "Dataset $DATASET_TARGET does not exist and will be created." | ||
| 34 | echo "You have 10 seconds to abort this with CTRL-C" | ||
| 35 | sleep 10 | ||
| 36 | if ! $SIMULATION; then | ||
| 37 | zfs create $DATASET_TARGET | ||
| 38 | fi | ||
| 11 | fi | 39 | fi |
| 12 | 40 | ||
| 41 | if zfs get -H -t filesystem -o name,value -r snapdir zeus/data/projects | grep -v visible >/dev/null; then | ||
| 42 | echo Please make all snapdirs visible: | ||
| 43 | zfs get -H -t filesystem -o name,value -r snapdir zeus/data/projects | ||
| 44 | exit 2 | ||
| 45 | fi | ||
| 46 | |||
| 47 | |||
| 48 | MOUNTPOINT_TARGET=$(zfs get -o value -H mountpoint $DATASET_TARGET) | ||
| 49 | test ${SIMULATION:0} = 1 && test $MOUNTPOINT_TARGET == "" && MOUNTPOINT_TARGET="datapool/simulation" | ||
| 50 | |||
| 51 | test -d "$MOUNTPOINT_TARGET" || print_help_and_exit | ||
| 52 | |||
| 13 | # make sure, that ctrl-c also works in the inner loops | 53 | # make sure, that ctrl-c also works in the inner loops |
| 14 | trap exit INT | 54 | trap exit INT |
| 15 | 55 | ||
| 16 | # recursively contains all snapshot names (the part after the @) from root on, sorted and only once | 56 | # recursively contains all snapshot names (the part after the @) from root on, sorted and only once |
| 17 | SNAPSHOTS=$(zfs list -H -oname -tsnap -r $DATASET_ROOT| cut -d@ -f2 | sort | uniq) | 57 | SNAPSHOTS=$(zfs list -H -oname -tsnap -r $DATASET_ROOT | cut -d@ -f2 | sort -u) |
| 18 | DATASETS=$(zfs list -H -oname -t filesystem -r $DATASET_ROOT) | 58 | DATASETS=$(zfs list -H -oname -t filesystem -r $DATASET_ROOT) |
| 19 | 59 | ||
| 60 | test "${SIMULATION:-0}" = 1 && echo "SIMULATION MODE" | ||
| 61 | |||
| 62 | $DATASETS | ||
| 63 | |||
| 64 | |||
| 20 | echo "We are going to flatten the hierachy of this dataset:" | 65 | echo "We are going to flatten the hierachy of this dataset:" |
| 21 | printf " %s\n" $DATASETS | 66 | printf "\t%s\n" $DATASETS |
| 22 | echo "into the dataset with the name:" | 67 | echo -e "into the dataset with the name:" |
| 23 | echo " $DATASET_TARGET" | 68 | echo -e "\t$DATASET_TARGET" |
| 24 | echo "mounted under:" | 69 | echo -e "mounted under:" |
| 25 | echo " $MOUNTPOINT_TARGET" | 70 | echo -e "\t$MOUNTPOINT_TARGET" |
| 71 | echo -e "with the following snapshots:" | ||
| 72 | printf "\t%s\n" $SNAPSHOTS | ||
| 26 | echo "" | 73 | echo "" |
| 27 | echo "You have 10 seconds to abort this with CTRL-C" | 74 | echo "You have 10 seconds to abort this with CTRL-C" |
| 28 | sleep 10 | 75 | sleep 10 |
| 29 | 76 | ||
| 77 | set -- $SNAPSHOTS | ||
| 78 | SNAPSHOTS_TOTAL=$# | ||
| 79 | SNAPSHOT_CURRENT=0 | ||
| 80 | |||
| 81 | set -- $DATASETS | ||
| 82 | shift | ||
| 83 | SUBDATASETS=$@ | ||
| 84 | |||
| 30 | for SNAPSHOT in $SNAPSHOTS; do | 85 | for SNAPSHOT in $SNAPSHOTS; do |
| 31 | echo "" | 86 | echo "" |
| 32 | echo "" | 87 | echo "" |
| 33 | echo "===========================" | 88 | SNAPSHOT_CURRENT=$((SNAPSHOT_CURRENT + 1)) |
| 34 | echo "Next snapshot is: $SNAPSHOT" | 89 | echo "[$SNAPSHOT_CURRENT/$SNAPSHOTS_TOTAL] Next snapshot is: $SNAPSHOT" |
| 35 | echo "===========================" | 90 | |
| 91 | for DATASET in $SUBDATASETS; do | ||
| 36 | 92 | ||
| 37 | for DATASET in $DATASETS; do | 93 | DATASET_RELATIVE=${DATASET##$DATASET_ROOT} |
| 38 | 94 | ||
| 39 | MOUNTPOINT=$(zfs get -H -o value mountpoint $DATASET) | 95 | MOUNTPOINT=$(zfs get -H -o value mountpoint $DATASET) |
| 96 | echo "RELATIVE=$DATASET_RELATIVE" | ||
| 40 | 97 | ||
| 41 | if [[ $MOUNTPOINT == "legacy" ]]; then | 98 | if [[ $MOUNTPOINT == "legacy" ]]; then |
| 42 | MOUNTPOINT=$(findmnt -n -o target $DATASET) | 99 | MOUNTPOINT=$(findmnt -n -o target $DATASET) |
| @@ -51,18 +108,32 @@ for SNAPSHOT in $SNAPSHOTS; do | |||
| 51 | continue | 108 | continue |
| 52 | fi | 109 | fi |
| 53 | 110 | ||
| 54 | SNAPDIR=$(realpath $MOUNTPOINT/.zfs/snapshot/$SNAPSHOT) | 111 | SNAPDIR=$MOUNTPOINT/.zfs/snapshot/$SNAPSHOT |
| 55 | if test -d $SNAPDIR; then | 112 | if test -d $SNAPDIR; then |
| 56 | TARGET_DIR="$(realpath $MOUNTPOINT_TARGET)$(realpath $MOUNTPOINT)" | 113 | |
| 57 | mkdir -p "$TARGET_DIR" | 114 | TARGET_DIR="${MOUNTPOINT_TARGET}${DATASET_RELATIVE}" |
| 58 | echo rsync --info=stats3 -a "$SNAPDIR/" "$TARGET_DIR/" | 115 | |
| 59 | if ! rsync --info=stats3 -a "$SNAPDIR/" "$TARGET_DIR/" ; then | 116 | echo -e \\trsync --info=stats3 --delete -a "$SNAPDIR/" "$TARGET_DIR/" |
| 60 | >&2 echo "rsync could not entirely copy from $SNAPDIR to $DATASET_TARGET" | 117 | if test "${SIMULATION:-0}" = 0; then |
| 118 | |||
| 119 | mkdir -p "$TARGET_DIR" | ||
| 120 | |||
| 121 | if ! rsync --info=stats3 --delete -a "$SNAPDIR/" "$TARGET_DIR/" ; then | ||
| 122 | >&2 echo "rsync could not entirely copy from $SNAPDIR to $DATASET_TARGET" | ||
| 123 | fi | ||
| 61 | fi | 124 | fi |
| 125 | else | ||
| 126 | echo -e "\tSKIP: Snapshot $SNAPSHOT does not exist for dataset $DATASET" | ||
| 62 | fi | 127 | fi |
| 63 | done | 128 | done |
| 129 | |||
| 64 | NEW_SNAPSHOT="$DATASET_TARGET@$SNAPSHOT" | 130 | NEW_SNAPSHOT="$DATASET_TARGET@$SNAPSHOT" |
| 65 | echo "Files copied, creating snapshot: $NEW_SNAPSHOT" | 131 | echo "" |
| 66 | zfs snap $NEW_SNAPSHOT | 132 | echo -e "\t> Concluding snapshot: ${NEW_SNAPSHOT} <" |
| 133 | echo "" | ||
| 134 | |||
| 135 | if test "${SIMULATION:-0}" = 0; then | ||
| 136 | zfs snap $NEW_SNAPSHOT | ||
| 137 | fi | ||
| 67 | done | 138 | done |
| 68 | 139 | ||
