I’ve been spending a lot of my time the last week on getting SnapVault with out FAS-filers to work. Out came a script, which does this for a given volume (and of course SnapVault Primary and Secondary).

The script expects, that SSH public key authentification has been set up.

  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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
#!/bin/bash

# Create a SnapVault relation between two volumes
# 1) create volume on target, if it doesn't exist
# 2) set snapshot reserve on target
# 3) start the snapvault relationship
# 4) create snapvault retention for this volume

KEY_FILE="/root/.ssh/netapp.dsa"
SSH_OPTS="/root/.ssh/netapp-ssh_config"

usage() {
	echo "Usage: fas-snapvault-start.sh <MODE> <VOLUME|HOSTNAME> <SV_SECONDARY> <SV_PRIMARY> <SV_RETENTION> [SV_SCHED_NAME] [SV_RATE_LIMIT]"
	echo ""
	if [ -n "$1" ] ; then
		echo "$1"
		echo ""
	fi
	echo "Required parameters:"
	echo ""
	echo "    - MODE:            Either host or volume (case sensitive)."
	echo ""
	echo "    - VOLUME:          Volume for which to configure SnapVault (if mode is set to volume)"
	echo "    - HOSTNAME:        Host for which to configure SnapVault (if mode is set to host)"
	echo "    - SV_SECONDARY:    SnapVault Secondary"
	echo "    - SV_PRIMARY:      SnapVault Primary"
	echo "    - SV_RETENTION:    How many SnapVault snapshots should be kept on the SV_SECONDARY"
	echo ""
	echo "Optional parameters:"
	echo ""
	echo "    - SV_SCHED_NAME:   Retention class for this schedule, defaults to 'daily'"
	echo "    - SV_RATE_LIMIT:   Limit the SnapVault transfer to xx kb, may help on busy systems."
        echo "                       Defaults to no limit at all, may cause harm to already busy FAS"
        echo "                       controllers."
	echo ""
	exit 1
}

ssh_fas() {
	# $@: commands for Data ONTAP
	COMMANDS="$@"

	/usr/bin/ssh -i $KEY_FILE -l root -F $SSH_OPTS $COMMANDS
}

snapvault_flexvol_size() {
	# $1: current size and unit
	# $2: retention period
	size=$1
	retention=$2
	UNIT_PARAM="$( echo "${#size} - 1" | bc )"
	UNIT="${size:$UNIT_PARAM:1}"

	case $UNIT in
		k) CONV="1024";;
		m) CONV="1024 * 1024";;
		g) CONV="1024 * 1024 * 1024";;
	esac

	SIZE="$( echo "scale=0; ${size/$UNIT/} * $CONV * $retention" | bc )"

	echo "${SIZE}k"
}

snapvault_setup() {

	if [ "$#" -lt 6 ] ; then
		break
	fi

	# $1: sv_secondary
	# $2: sv_primary
	# $3: sv_retention
	# $4: volume
	# $5: sv_sched_name
	# $6: sv_rate_limit

	sv_secondary=$1
	sv_primary=$2
	sv_retention=$3
	volume=$4
	sv_sched_name=$5
	sv_rate_limit=$6

	# Check if snapvault access is configured correctly
	sv_secondary_ip="$( ssh_fas $sv_secondary rdfile /etc/hosts | grep $sv_secondary-e0a | awk '{ print $1 }' )"
	sv_access="$( ssh_fas $sv_primary options snapvault.access | grep $sv_secondary_ip )"
	if [ -z "$sv_access" ] ; then
		echo "Please make sure, that SnapVault access is correctly"
		echo "configured on $sv_primary, so that $sv_secondary"
		echo "can access it using snapvault."
		echo
		echo "Hint: options snapvault.access should look like this:"
		echo "  options snapvault.access host=$sv_secondary_ip"
		echo
		exit 1
	fi

	# First, check if SnapVault is already configured!
	SV="$( ssh_fas $sv_primary snapvault status | grep -i "^$sv_primary:/vol/$volume/sv/" | awk '{ print $5 }' )"
	case $SV in
		Transferring|Idle)
			continue;;
	esac

	# Get vol size and snapreserve from sv_primary
	# and calculate the new size. Simply setting the volume to the original
       	# size isn't enough, as we need to keep the lun plus SV_RETENTION times
	# of snapshots ...
	VOLUME_SIZE="$( ssh_fas $sv_primary vol size $volume | awk '{ print $8 }' | sed "s,.,,"  )"
	VOLAUTO_SIZE="$( snapvault_flexvol_size $VOLUME_SIZE $sv_retention )"
	SNAP_RESERVE="$( ssh_fas $sv_primary snap reserve $volume | cut -d  -f7 | sed "s,%,," )"

	# Check if the is a qtree on sv_primary
	QTREE="$( ssh_fas $sv_primary qtree status | grep $volume | cut -d  -f2 | sed '/^$/d' )"

	if [ -z "$QTREE" ] ; then
		echo
		echo "SnapDrive only supports Qtree to Qtree relations!"
		echo "Please run the following commands to create a qtree and"
	        echo "move the lun to it:"
		echo
		echo "qtree create /vol/$volume/sv"
		for lun in $( ssh_fas $sv_primary lun show -l $volume | awk '{ print $1 }' | tr 'n' ' ' ); do
			lun_name="$( echo $lun | cut -d/ -f4 )"
			echo "lun move $lun /vol/$volume/sv/$lun_name"
		done
#	elif [ "$( ssh_fas $sv_secondary ping $sv_primary-igm1 )" != "$sv_primary-igm1 is alive" ] ; then
#		echo
#		echo "Please make sure the SV_SECONDARY $sv_secondary can reach"
#		echo "the SV_PRIMARY $sv_primary via igm1!"
#		echo
	else
		echo "SnapVault operations for FlexVol: $volume"
		echo "   - Creating FlexVol"
		# Assume to always use aggr1 on sv_secondary
		ssh_fas $sv_secondary vol create $volume -s none aggr1 $VOLUME_SIZE &>/dev/null

		echo "   - Disabling Unicode/atime/automatic snapshotting"
		ssh_fas $sv_secondary vol options $volume fractional_reserve 100
		ssh_fas $sv_secondary vol options $volume no_atime_update on
		ssh_fas $sv_secondary vol options $volume create_ucode off
		ssh_fas $sv_secondary vol options $volume nosnap on
		ssh_fas $sv_secondary vol options $volume convert_ucode off
		ssh_fas $sv_secondary snap reserve $volume $SNAP_RESERVE

		# Doesn't matter, as a snapvault update would resync source and destination
		#echo "   - Enabling Volume Autosizing (vol max: $VOLAUTO_SIZE)"
		#ssh_fas $sv_secondary vol autosize $volume -m $VOLAUTO_SIZE -i 1g
		#ssh_fas $sv_secondary vol autosize $volume on

		echo "   - Enabling Deduplication (mon-sun@15)"
		ssh_fas $sv_secondary sis on /vol/$volume &>/dev/null
		ssh_fas $sv_secondary sis config -s mon-sun@15 /vol/$volume

		# Now create the SnapVault relationship between sv_secondary and sv_primary
		[ -n $sv_rate_limit ] && sv_rate_limit="-k $sv_rate_limit"

		echo "   - Starting SnapVault relation between $sv_secondary and $sv_primary"
		COMMAND="$( ssh_fas $sv_secondary snapvault start $sv_rate_limit
			-S $sv_primary-igm1:/vol/$volume/sv/ /vol/$volume/sv )"

		if [ "$( echo $COMMAND | grep "Transfer aborted" )" != "" ] ; then
			echo
			echo "          FAILED"
			echo
			echo "Output from snapvault start was: $COMMAND"
		else
			echo "   - Creating retention class on $sv_primary"
			ssh_fas $sv_primary snapvault snap sched $volume $sv_sched_name $sv_retention@-

			echo "   - Creating retention class on $sv_secondary"
			ssh_fas $sv_secondary snapvault snap sched $volume $sv_sched_name $sv_retention@-

			echo
			echo "You can monitor the SnapVault initialization on the SnapVault Secondary ($sv_secondary)"
			echo "by using the following command:"
			echo
			echo "     'snapvault status /vol/$volume/sv'"
			echo
		fi
	fi
}

# Main script starts here.
#set -x
if [ "$#" -lt 5 ] ; then
	usage
fi

case $1 in
	host) MODE="host"; HOST=$2 ;;
	volume) MODE="volume"; VOLUME=$2 ;;
	*) usage "Invalid mode specified"
esac

SV_SECONDARY=$3
SV_PRIMARY=$4
SV_RETENTION=$5
SV_SCHED_NAME=${6:-daily}
SV_RATE_LIMIT=${7:-50000}

if [ "$MODE" == "host" ] ; then
	# Get the LUN list
	VOLUME_LIST="$( ssh_fas $SV_PRIMARY lun show -g $HOST | awk '{ print $1 }' | cut -d/ -f3 | grep -v windows | tr 'n' ' ' | sort -u )"

	for vol in $VOLUME_LIST; do
		# Check if snapreserve is enabled
		SNAP="$( ssh_fas $SV_PRIMARY snap reserve $vol | cut -d  -f7 | sed "s,%,," )"

		if [ $SNAP -ne "0" ] ; then
			snapvault_setup $SV_SECONDARY $SV_PRIMARY $SV_RETENTION $vol $SV_SCHED_NAME $SV_RATE_LIMIT
		else
			echo "No snap reserve configured for $vol"
		fi
	done
elif [ "$MODE" == "volume" ] ; then
	SNAP="$( ssh_fas $SV_PRIMARY snap reserve $VOLUME | cut -d  -f7 | sed "s,%,," )"

	if [ $SNAP -ne "0" ] ; then
		snapvault_setup $SV_SECONDARY $SV_PRIMARY $SV_RETENTION $VOLUME $SV_SCHED_NAME $SV_RATE_LIMIT
	else
		echo "No snap reserve configured for $vol"
	fi
fi
#set +x

The script expects that you set up SSH public key authentification, in order to access the primary and secondary SnapVault filer (in order to actually create the relationship between the two).

Additionaly the script expects the source to be a qtree. That is because in my tinkering, I’ve found Volume-based SnapVaults to be less reliable than Qtree-based SnapVaults (don’t ask me why though).