After figuring out the SnapVault stuff, I needed to implement a whole bunch of SnapMirror relations. As I am lazy (as in click-lazy), I ended up writing a somewhat short Bash script, that’ll either establish a bunch of SnapMirror relations (for a single host) or just for a single volume.

The script expects, that SSH public key authentification has been set up, and that the source for the SnapMirror exists and is online/not-restricted.

  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
#!/bin/bash -f

# Create a SnapMirror relation between two volumes
# 1) create volume on target, if it doesn't exist
# 2) set snapshot reserve on target
# 3) start the snapmirror relationship

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

usage() {
	echo "Usage: fas-snapmirror-start.sh <MODE> <VOLUME|HOSTNAME> <SM_PRIMARY> <SM_SECONDARY> [SM_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 SnapMirror (if mode is set to volume)"
	echo "    - HOSTNAME:        Host for which to configure SnapMirror (if mode is set to host)"
	echo "    - SM_SECONDARY:    Hostname of the SnapMirror Secondary"
	echo "    - SM_PRIMARY:      Hostname of the SnapMirror Primary"
	echo ""
	echo "Optional parameters:"
	echo ""
	echo "    - SM_RATE_LIMIT:   Limit the SnapMirror 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
}

snapmirror_setup() {
	if [ "$#" -lt 4 ] ; then
		break
	fi

	# $1: sm_secondary
	# $2: sm_primary
	# $4: volume
	# $6: sm_rate_limit

	sm_secondary=$1
	sm_primary=$2
	volume=$3
	sm_rate_limit=$4

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

	# Get FlexVol size from SM_PRIMARY (SnapMirror destination has the same
	# size as the SnapMirror source)
	VOL_SIZE="$( ssh_fas $sm_primary vol size $volume | awk '{ print $8 }' | sed "s,.,,"  )"

	# Check if the is a qtree on SM_PRIMARY
	QTREE="$( ssh_fas $sm_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 create a qtree (qtree create /vol/${volume}/sv"
		echo
		exit 1
	fi

	# Assume to always use aggr1 on SM_SECONDARY
	echo "SnapMirror operations for FlexVol: $volume"
	echo "   - Creating FlexVol"
	ssh_fas $sm_secondary vol create $volume -s none aggr1 $VOL_SIZE &>/dev/null

	echo "   - Disabling Unicode/atime/automatic snapshotting"
	ssh_fas $sm_secondary vol options $volume fractional_reserve 100
	ssh_fas $sm_secondary vol options $volume no_atime_update on
	ssh_fas $sm_secondary vol options $volume create_ucode off
	ssh_fas $sm_secondary vol options $volume nosnap on
	ssh_fas $sm_secondary vol options $volume convert_ucode off
	ssh_fas $sm_secondary vol autosize $volume off &>/dev/null
	ssh_fas $sm_secondary snap reserve $volume $SNAP_RESERVE &>/dev/null

	echo "   - Restricting volume on $sm_secondary"
	ssh_fas $sm_secondary vol restrict $volume &>/dev/null

	# Now create the SnapMirror relationship between SM_SECONDARY and SM_PRIMARY
	if [ -n $sm_rate_limit ] ; then
		smi_rate_limit="-k $sm_rate_limit"
		smc_rate_limit="kbs=$sm_rate_limit"
	else
		smc_rate_limit="-"
	fi

	echo "   - Starting SnapMirror relation between $sm_secondary and $sm_primary"
	ssh_fas $sm_secondary snapmirror initialize $smi_rate_limit
		-S $sm_primary-e0a:$volume $sm_secondary:$volume &>/dev/null

	echo "   - Updating snapmirror.conf on $sm_secondary"
	smc_opts="$sm_primary-e0a:$volume $sm_secondary:$volume $smc_rate_limit * 0-23/1 * *"
	ssh_fas $sm_secondary wrfile -a /etc/snapmirror.conf $smc_opts

	echo
	echo "You can monitor the SnapMirror initialization on the SnapMirror Secondary ($sm_secondary)"
	echo "by using the following command:"
	echo
	echo "     'snapmirror status $volume'"
	echo
}

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

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

SM_PRIMARY=$3
SM_SECONDARY=$4
SM_RATE_LIMIT=${5:-10000}

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

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

		if [ $SNAP -ne "0" ] ; then
			snapmirror_setup $SM_SECONDARY $SM_PRIMARY $vol $SM_RATE_LIMIT
		else
			echo "No snap reserve configured for $vol"
		fi
	done
elif [ "$MODE" == "volume" ] ; then
	SNAP="$( ssh_fas $SM_PRIMARY snap reserve $VOLUME | cut -d  -f7 | sed "s,%,," )"

	if [ $SNAP -ne "0" ] ; then
		snapmirror_setup $SM_SECONDARY $SM_PRIMARY $VOLUME $SM_RATE_LIMIT
	else
		echo "No snap reserve configured for $vol"
	fi
fi

#set -x