1#
2# CDDL HEADER START
3#
4# The contents of this file are subject to the terms of the
5# Common Development and Distribution License (the "License").
6# You may not use this file except in compliance with the License.
7#
8# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9# or http://www.opensolaris.org/os/licensing.
10# See the License for the specific language governing permissions
11# and limitations under the License.
12#
13# When distributing Covered Code, include this CDDL HEADER in each
14# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15# If applicable, add the following below this CDDL HEADER, with the
16# fields enclosed by brackets "[]" replaced with your own identifying
17# information: Portions Copyright [yyyy] [name of copyright owner]
18#
19# CDDL HEADER END
20#
21
22#
23# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24# Use is subject to license terms.
25#
26
27#
28# Copyright (c) 2013 by Delphix. All rights reserved.
29#
30
31. $STF_SUITE/include/libtest.shlib
32. $STF_SUITE/tests/functional/rsend/rsend.cfg
33
34#
35# Set up test model which includes various datasets
36#
37#               @final
38#               @snapB
39#               @init
40#               |
41#   ______ pclone
42#  |      /
43#  |@psnap
44#  ||                         @final
45#  ||@final       @final      @snapC
46#  ||@snapC       @snapC      @snapB
47#  ||@snapA       @snapB      @snapA
48#  ||@init        @init       @init
49#  |||            |           |
50# $pool -------- $FS ------- fs1 ------- fs2
51#    \             \\_____     \          |
52#     vol           vol   \____ \         @fsnap
53#      |              |        \ \              \
54#      @init          @vsnap   |  ------------ fclone
55#      @snapA         @init \  |                    |
56#      @final         @snapB \ |                    @init
57#                     @snapC  vclone                @snapA
58#                     @final       |                @final
59#                                 @init
60#                                 @snapC
61#                                 @final
62#
63# $1 pool name
64#
65function setup_test_model
66{
67	typeset pool=$1
68
69	log_must $ZFS create -p $pool/$FS/fs1/fs2
70
71	log_must $ZFS snapshot $pool@psnap
72	log_must $ZFS clone $pool@psnap $pool/pclone
73
74	if is_global_zone ; then
75		log_must $ZFS create -V 16M $pool/vol
76		log_must $ZFS create -V 16M $pool/$FS/vol
77
78		log_must $ZFS snapshot $pool/$FS/vol@vsnap
79		log_must $ZFS clone $pool/$FS/vol@vsnap $pool/$FS/vclone
80	fi
81
82	log_must snapshot_tree $pool/$FS/fs1/fs2@fsnap
83	log_must $ZFS clone $pool/$FS/fs1/fs2@fsnap $pool/$FS/fs1/fclone
84	log_must $ZFS snapshot -r $pool@init
85
86	log_must snapshot_tree $pool@snapA
87	log_must snapshot_tree $pool@snapC
88	log_must snapshot_tree $pool/pclone@snapB
89	log_must snapshot_tree $pool/$FS@snapB
90	log_must snapshot_tree $pool/$FS@snapC
91	log_must snapshot_tree $pool/$FS/fs1@snapA
92	log_must snapshot_tree $pool/$FS/fs1@snapB
93	log_must snapshot_tree $pool/$FS/fs1@snapC
94	log_must snapshot_tree $pool/$FS/fs1/fclone@snapA
95
96	if is_global_zone ; then
97		log_must $ZFS snapshot $pool/vol@snapA
98		log_must $ZFS snapshot $pool/$FS/vol@snapB
99		log_must $ZFS snapshot $pool/$FS/vol@snapC
100		log_must $ZFS snapshot $pool/$FS/vclone@snapC
101	fi
102
103	log_must $ZFS snapshot -r $pool@final
104
105	return 0
106}
107
108#
109# Cleanup the BACKDIR and given pool content and all the sub datasets
110#
111# $1 pool name
112#
113function cleanup_pool
114{
115	typeset pool=$1
116	log_must $RM -rf $BACKDIR/*
117
118	if is_global_zone ; then
119		log_must $ZFS destroy -Rf $pool
120	else
121		typeset list=$($ZFS list -H -r -t filesystem,snapshot,volume -o name $pool)
122		for ds in $list ; do
123			if [[ $ds != $pool ]] ; then
124				if datasetexists $ds ; then
125					log_must $ZFS destroy -Rf $ds
126				fi
127			fi
128		done
129	fi
130
131	typeset mntpnt=$(get_prop mountpoint $pool)
132	if ! ismounted $pool ; then
133		# Make sure mountpoint directory is empty
134		if [[ -d $mntpnt ]]; then
135			log_must $RM -rf $mntpnt/*
136		fi
137
138		log_must $ZFS mount $pool
139	fi
140	if [[ -d $mntpnt ]]; then
141		log_must $RM -rf $mntpnt/*
142	fi
143
144	return 0
145}
146
147#
148# Detect if the given two filesystems have same sub-datasets
149#
150# $1 source filesystem
151# $2 destination filesystem
152#
153function cmp_ds_subs
154{
155	typeset src_fs=$1
156	typeset dst_fs=$2
157
158	$ZFS list -r -H -t filesystem,snapshot,volume -o name $src_fs > $BACKDIR/src1
159	$ZFS list -r -H -t filesystem,snapshot,volume -o name $dst_fs > $BACKDIR/dst1
160
161	eval $SED -e 's:^$src_fs:PREFIX:g' < $BACKDIR/src1 > $BACKDIR/src
162	eval $SED -e 's:^$dst_fs:PREFIX:g' < $BACKDIR/dst1 > $BACKDIR/dst
163
164	$DIFF $BACKDIR/src $BACKDIR/dst
165	typeset -i ret=$?
166
167	$RM -f $BACKDIR/src $BACKDIR/dst $BACKDIR/src1 $BACKDIR/dst1
168
169	return $ret
170}
171
172#
173# Compare all the directores and files in two filesystems
174#
175# $1 source filesystem
176# $2 destination filesystem
177#
178function cmp_ds_cont
179{
180	typeset src_fs=$1
181	typeset dst_fs=$2
182
183	typeset srcdir dstdir
184	srcdir=$(get_prop mountpoint $src_fs)
185	dstdir=$(get_prop mountpoint $dst_fs)
186
187	$DIFF -r $srcdir $dstdir > /dev/null 2>&1
188	echo $?
189}
190
191#
192# Compare the given two dataset properties
193#
194# $1 dataset 1
195# $2 dataset 2
196#
197function cmp_ds_prop
198{
199	typeset dtst1=$1
200	typeset dtst2=$2
201
202	for item in "type" "origin" "volblocksize" "aclinherit" "aclmode" \
203		"atime" "canmount" "checksum" "compression" "copies" "devices" \
204		"exec" "quota" "readonly" "recordsize" "reservation" "setuid" \
205		"sharenfs" "snapdir" "version" "volsize" "xattr" "zoned" \
206		"mountpoint";
207	do
208		$ZFS get -H -o property,value,source $item $dtst1 >> \
209			$BACKDIR/dtst1
210		$ZFS get -H -o property,value,source $item $dtst2 >> \
211			$BACKDIR/dtst2
212	done
213
214	eval $SED -e 's:$dtst1:PREFIX:g' < $BACKDIR/dtst1 > $BACKDIR/dtst1
215	eval $SED -e 's:$dtst2:PREFIX:g' < $BACKDIR/dtst2 > $BACKDIR/dtst2
216
217	$DIFF $BACKDIR/dtst1 $BACKDIR/dtst2
218	typeset -i ret=$?
219
220	$RM -f $BACKDIR/dtst1 $BACKDIR/dtst2
221
222	return $ret
223
224}
225
226#
227# Random create directories and files
228#
229# $1 directory
230#
231function random_tree
232{
233	typeset dir=$1
234
235	if [[ -d $dir ]]; then
236		$RM -rf $dir
237	fi
238	$MKDIR -p $dir
239	typeset -i ret=$?
240
241	typeset -i nl nd nf
242	((nl = RANDOM % 6 + 1))
243	((nd = RANDOM % 3 ))
244	((nf = RANDOM % 5 ))
245	$MKTREE -b $dir -l $nl -d $nd -f $nf
246	((ret |= $?))
247
248	return $ret
249}
250
251#
252# Put data in filesystem and take snapshot
253#
254# $1 snapshot name
255#
256function snapshot_tree
257{
258	typeset snap=$1
259	typeset ds=${snap%%@*}
260	typeset type=$(get_prop "type" $ds)
261
262	typeset -i ret=0
263	if [[ $type == "filesystem" ]]; then
264		typeset mntpnt=$(get_prop mountpoint $ds)
265		((ret |= $?))
266
267		if ((ret == 0)) ; then
268			eval random_tree $mntpnt/${snap##$ds}
269			((ret |= $?))
270		fi
271	fi
272
273	if ((ret == 0)) ; then
274		$ZFS snapshot $snap
275		((ret |= $?))
276	fi
277
278	return $ret
279}
280
281#
282# Destroy the given snapshot and stuff
283#
284# $1 snapshot
285#
286function destroy_tree
287{
288	typeset -i ret=0
289	typeset snap
290	for snap in "$@" ; do
291		$ZFS destroy $snap
292		ret=$?
293
294		typeset ds=${snap%%@*}
295		typeset type=$(get_prop "type" $ds)
296		if [[ $type == "filesystem" ]]; then
297			typeset mntpnt=$(get_prop mountpoint $ds)
298			((ret |= $?))
299
300			if ((ret != 0)); then
301				$RM -r $mntpnt/$snap
302				((ret |= $?))
303			fi
304		fi
305
306		if ((ret != 0)); then
307			return $ret
308		fi
309	done
310
311	return 0
312}
313
314#
315# Get all the sub-datasets of give dataset with specific suffix
316#
317# $1 Given dataset
318# $2 Suffix
319#
320function getds_with_suffix
321{
322	typeset ds=$1
323	typeset suffix=$2
324
325	typeset list=$($ZFS list -r -H -t filesystem,snapshot,volume -o name $ds \
326		| $GREP "$suffix$")
327
328	$ECHO $list
329}
330
331#
332# Output inherited properties whitch is edited for file system
333#
334function fs_inherit_prop
335{
336	typeset fs_prop
337	if is_global_zone ; then
338		fs_prop=$($ZFS inherit 2>&1 | \
339			$AWK '$2=="YES" && $3=="YES" {print $1}')
340		if ! is_te_enabled ; then
341		        fs_prop=$(echo $fs_prop | $GREP -v "mlslabel")
342		fi
343	else
344		fs_prop=$($ZFS inherit 2>&1 | \
345			$AWK '$2=="YES" && $3=="YES" {print $1}'|
346			$EGREP -v "devices|mlslabel|sharenfs|sharesmb|zoned")
347	fi
348
349	$ECHO $fs_prop
350}
351
352#
353# Output inherited properties for volume
354#
355function vol_inherit_prop
356{
357	$ECHO "checksum readonly"
358}
359
360#
361# Get the destination dataset to compare
362#
363function get_dst_ds
364{
365	typeset srcfs=$1
366	typeset dstfs=$2
367
368	#
369	# If the srcfs is not pool
370	#
371	if ! $ZPOOL list $srcfs > /dev/null 2>&1 ; then
372		eval dstfs="$dstfs/${srcfs#*/}"
373	fi
374
375	$ECHO $dstfs
376}
377