Print this page
7290 ZFS test suite needs to control what utilities it can run
Reviewed by: Dan Kimmel <dan.kimmel@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/test/zfs-tests/tests/functional/inheritance/inherit_001_pos.ksh
+++ new/usr/src/test/zfs-tests/tests/functional/inheritance/inherit_001_pos.ksh
1 1 #! /bin/ksh -p
2 2 #
3 3 # CDDL HEADER START
4 4 #
5 5 # The contents of this file are subject to the terms of the
6 6 # Common Development and Distribution License (the "License").
7 7 # You may not use this file except in compliance with the License.
8 8 #
9 9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 # or http://www.opensolaris.org/os/licensing.
11 11 # See the License for the specific language governing permissions
12 12 # and limitations under the License.
13 13 #
14 14 # When distributing Covered Code, include this CDDL HEADER in each
15 15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 # If applicable, add the following below this CDDL HEADER, with the
17 17 # fields enclosed by brackets "[]" replaced with your own identifying
|
↓ open down ↓ |
17 lines elided |
↑ open up ↑ |
18 18 # information: Portions Copyright [yyyy] [name of copyright owner]
19 19 #
20 20 # CDDL HEADER END
21 21 #
22 22
23 23 #
24 24 # Copyright 2009 Sun Microsystems, Inc. All rights reserved.
25 25 # Use is subject to license terms.
26 26
27 27 #
28 -# Copyright (c) 2013 by Delphix. All rights reserved.
28 +# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
29 29 #
30 30
31 31 . $STF_SUITE/include/libtest.shlib
32 32 . $STF_SUITE/tests/functional/inheritance/inherit.kshlib
33 33
34 34 #
35 35 # DESCRIPTION:
36 36 # Test that properties are correctly inherited using 'zfs set',
37 37 # 'zfs inherit' and 'zfs inherit -r'.
38 38 #
39 39 # STRATEGY:
40 40 # 1) Read a configX.cfg file and create the specified datasets
41 41 # 2) Read a stateX.cfg file and execute the commands within it
42 42 # and verify that the properties have the correct values
43 43 # 3) Repeat steps 1-2 for each configX and stateX files found.
44 44 #
45 45
46 46 verify_runnable "global"
47 47
48 48 log_assert "Test properties are inherited correctly"
49 49
50 50 #
|
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
51 51 # Simple function to create specified datasets.
52 52 #
53 53 function create_dataset { #name type disks
54 54 typeset dataset=$1
55 55 typeset type=$2
56 56 typeset disks=$3
57 57
58 58 if [[ $type == "POOL" ]]; then
59 59 create_pool "$dataset" "$disks"
60 60 elif [[ $type == "CTR" ]]; then
61 - log_must $ZFS create $dataset
62 - log_must $ZFS set canmount=off $dataset
61 + log_must zfs create $dataset
62 + log_must zfs set canmount=off $dataset
63 63 elif [[ $type == "FS" ]]; then
64 - log_must $ZFS create $dataset
64 + log_must zfs create $dataset
65 65 else
66 66 log_fail "Unrecognised type $type"
67 67 fi
68 68
69 69 list="$list $dataset"
70 70 }
71 71
72 72 #
73 73 # Function to walk through all the properties in a
74 74 # dataset, setting them to a 'local' value if required.
75 75 #
76 76 function init_props { #dataset init_code
77 77 typeset dataset=$1
78 78 typeset init_code=$2
79 79 typeset dir=$3
80 80
81 81 typeset -i i=0
82 82
83 83 #
84 84 # Though the effect of '-' and 'default' is the same we
85 85 # call them out via a log_note to aid in debugging the
86 86 # config files
87 87 #
88 88 if [[ $init_code == "-" ]]; then
89 89 log_note "Leaving properties for $dataset unchanged."
90 90 [[ $def_recordsize == 0 ]] && \
91 91 update_recordsize $dataset $init_code
92 92 return;
93 93 elif [[ $init_code == "default" ]]; then
94 94 log_note "Leaving properties for $dataset at default values."
95 95 [[ $def_recordsize == 0 ]] && \
96 96 update_recordsize $dataset $init_code
97 97 return;
98 98 elif [[ $init_code == "local" ]]; then
99 99 log_note "Setting properties for $dataset to local values."
100 100 while (( i < ${#prop[*]} )); do
101 101 if [[ ${prop[i]} == "recordsize" ]]; then
102 102 update_recordsize $dataset $init_code
103 103 else
104 104 if [[ ${prop[i]} == "mountpoint" ]]; then
105 105 set_n_verify_prop ${prop[i]} \
106 106 ${local_val[((i/2))]}.$dir $dataset
107 107 else
108 108 set_n_verify_prop ${prop[i]} \
109 109 ${local_val[((i/2))]} $dataset
110 110 fi
111 111 fi
112 112
113 113 ((i = i + 2))
114 114 done
115 115 else
116 116 log_fail "Unrecognised init code $init_code"
117 117 fi
118 118 }
119 119
120 120 #
121 121 # We enter this function either to update the recordsize value
122 122 # in the default array, or to update the local value array.
123 123 #
124 124 function update_recordsize { #dataset init_code
125 125 typeset dataset=$1
126 126 typeset init_code=$2
127 127 typeset idx=0
128 128 typeset record_val
129 129
130 130 #
131 131 # First need to find where the recordsize property is
132 132 # located in the arrays
133 133 #
134 134 while (( idx < ${#prop[*]} )); do
135 135 [[ ${prop[idx]} == "recordsize" ]] && break
|
↓ open down ↓ |
61 lines elided |
↑ open up ↑ |
136 136
137 137 ((idx = idx + 2))
138 138 done
139 139
140 140 ((idx = idx / 2))
141 141 record_val=`get_prop recordsize $dataset`
142 142 if [[ $init_code == "-" || $init_code == "default" ]]; then
143 143 def_val[idx]=$record_val
144 144 def_recordsize=1
145 145 elif [[ $init_code == "local" ]]; then
146 - log_must $ZFS set recordsize=$record_val $dataset
146 + log_must zfs set recordsize=$record_val $dataset
147 147 local_val[idx]=$record_val
148 148 fi
149 149 }
150 150
151 151 #
152 152 # The mountpoint property is slightly different from other properties and
153 153 # so is handled here. For all other properties if they are set to a specific
154 154 # value at a higher level in the data hierarchy (i.e. checksum=on) then that
155 155 # value propogates down the hierarchy unchanged, with the source field being
156 156 # set to 'inherited from <higher dataset>'.
157 157 #
158 158 # The mountpoint property is different in that while the value propogates
159 159 # down the hierarchy, the value at each level is determined by a combination
160 160 # of the top-level value and the current level in the hierarchy.
161 161 #
162 162 # For example consider the case where we have a pool (called pool1), containing
163 163 # a dataset (ctr) which in turn contains a filesystem (fs). If we set the
164 164 # mountpoint of the pool to '/mnt2' then the mountpoints for the dataset and
165 165 # filesystem are '/mnt2/ctr' and /mnt2/ctr/fs' respectively, with the 'source'
166 166 # field being set to 'inherited from pool1'.
167 167 #
168 168 # So at the filesystem level to calculate what our mountpoint property should
169 169 # be set to we walk back up the hierarchy sampling the mountpoint property at
170 170 # each level and forming up the expected mountpoint value piece by piece until
171 171 # we reach the level specified in the 'source' field, which in this example is
172 172 # the top-level pool.
173 173 #
174 174 function get_mntpt_val #dataset src index
175 175 {
176 176 typeset dataset=$1
177 177 typeset src=$2
178 178 typeset idx=$3
179 179 typeset new_path=""
180 180 typeset dset
181 181 typeset mntpt=""
182 182
183 183 if [[ $src == "local" ]]; then
184 184 # Extract mount points specific to datasets
185 185 if [[ $dataset == "TESTPOOL" ]]; then
186 186 mntpt=${local_val[idx]}.1
187 187 elif [[ $dataset == "TESTPOOL/TESTCTR" ]]; then
188 188 mntpt=${local_val[idx]}.2
189 189 else
190 190 mntpt=${local_val[idx]}.3
191 191 fi
192 192 elif [[ $src == "default" ]]; then
193 193 mntpt="/$dataset"
194 194 else
195 195 # Walk back up the hierarchy building up the
196 196 # expected mountpoint property value.
197 197 obj_name=${dataset##*/}
198 198
199 199 while [[ $src != $dataset ]]; do
200 200 dset=${dataset%/*}
201 201
202 202 mnt_val=`get_prop mountpoint $dset`
203 203
204 204 mod_prop_val=${mnt_val##*/}
205 205 new_path="/"$mod_prop_val$new_path
206 206 dataset=$dset
207 207 done
208 208
209 209 mntpt=$new_path"/"$obj_name
210 210 fi
211 211 echo $mntpt
212 212 }
213 213
214 214 #
215 215 # Simple function to verify that a property has the
216 216 # expected value.
217 217 #
218 218 function verify_prop_val #property dataset src index
219 219 {
220 220 typeset prop=$1
221 221 typeset dataset=$2
222 222 typeset src=$3
223 223 typeset idx=$4
224 224 typeset new_path=""
225 225 typeset dset
226 226 typeset exp_val
227 227 typeset prop_val
228 228
229 229 prop_val=`get_prop $prop $dataset`
230 230
231 231 # mountpoint property is handled as a special case
232 232 if [[ $prop == "mountpoint" ]]; then
233 233 exp_val=`get_mntpt_val $dataset $src $idx`
234 234 else
235 235 if [[ $src == "local" ]]; then
236 236 exp_val=${local_val[idx]}
237 237 elif [[ $src == "default" ]]; then
238 238 exp_val=${def_val[idx]}
239 239 else
240 240 #
241 241 # We are inheriting the value from somewhere
242 242 # up the hierarchy.
243 243 #
244 244 exp_val=`get_prop $prop $src`
245 245 fi
246 246 fi
247 247
248 248 if [[ $prop_val != $exp_val ]]; then
249 249 # After putback PSARC/2008/231 Apr,09,2008,
250 250 # the default value of aclinherit has changed to be
251 251 # 'restricted' instead of 'secure',
252 252 # but the old interface of 'secure' still exist
253 253
254 254 if [[ $prop != "aclinherit" || \
255 255 $exp_val != "secure" || \
256 256 $prop_val != "restricted" ]]; then
257 257
258 258 log_fail "$prop of $dataset is [$prop_val] rather "\
259 259 "than [$exp_val]"
260 260 fi
261 261 fi
262 262 }
263 263
264 264 #
265 265 # Function to read the configX.cfg files and create the specified
266 266 # dataset hierarchy
267 267 #
268 268 function scan_config { #config-file
269 269 typeset config_file=$1
270 270
271 271 DISK=${DISKS%% *}
272 272
273 273 list=""
274 274 typeset -i mount_dir=1
275 275
276 276 grep "^[^#]" $config_file | {
277 277 while read name type init ; do
278 278 create_dataset $name $type $DISK
279 279 init_props $name $init $mount_dir
280 280 ((mount_dir = mount_dir + 1))
281 281 done
282 282 }
283 283 }
284 284
285 285 #
286 286 # Function to check an exit flag, calling log_fail if that exit flag
287 287 # is non-zero. Can be used from code that runs in a tight loop, which
288 288 # would otherwise result in a lot of journal output.
289 289 #
290 290 function check_failure { # int status, error message to use
291 291
292 292 typeset -i exit_flag=$1
293 293 error_message=$2
294 294
295 295 if [[ $exit_flag -ne 0 ]]; then
296 296 log_fail "$error_message"
297 297 fi
298 298 }
299 299
300 300
301 301 #
302 302 # Main function. Executes the commands specified in the stateX.cfg
303 303 # files and then verifies that all the properties have the correct
304 304 # values and 'source' fields.
305 305 #
306 306 function scan_state { #state-file
307 307 typeset state_file=$1
308 308 typeset -i i=0
309 309 typeset -i j=0
310 310
311 311 log_note "Reading state from $state_file"
312 312
313 313 while ((i < ${#prop[*]})); do
314 314 grep "^[^#]" $state_file | {
315 315 while IFS=: read target op; do
316 316 #
317 317 # The user can if they wish specify that no
318 318 # operation be performed (by specifying '-'
319 319 # rather than a command). This is not as
320 320 # useless as it sounds as it allows us to
321 321 # verify that the dataset hierarchy has been
322 322 # set up correctly as specified in the
323 323 # configX.cfg file (which includes 'set'ting
324 324 # properties at a higher level and checking
|
↓ open down ↓ |
168 lines elided |
↑ open up ↑ |
325 325 # that they propogate down to the lower levels.
326 326 #
327 327 # Note in a few places here, we use
328 328 # check_failure, rather than log_must - this
329 329 # substantially reduces journal output.
330 330 #
331 331 if [[ $op == "-" ]]; then
332 332 log_note "No operation specified"
333 333 else
334 334 export __ZFS_POOL_RESTRICT="$TESTPOOL"
335 - log_must $ZFS unmount -a
335 + log_must zfs unmount -a
336 336 unset __ZFS_POOL_RESTRICT
337 337
338 338 for p in ${prop[i]} ${prop[((i+1))]}; do
339 - $ZFS $op $p $target
339 + zfs $op $p $target
340 340 ret=$?
341 - check_failure $ret "$ZFS $op $p \
341 + check_failure $ret "zfs $op $p \
342 342 $target"
343 343 done
344 344 fi
345 345 for check_obj in $list; do
346 346 read init_src final_src
347 347
348 348 for p in ${prop[i]} ${prop[((i+1))]}; do
349 349 # check_failure to keep journal small
350 350 verify_prop_src $check_obj $p \
351 351 $final_src
352 352 ret=$?
353 353 check_failure $ret "verify" \
354 354 "_prop_src $check_obj $p" \
355 355 "$final_src"
356 356
357 357 # Again, to keep journal size down.
358 358 verify_prop_val $p $check_obj \
359 359 $final_src $j
360 360 ret=$?
361 361 check_failure $ret "verify" \
362 362 "_prop_val $check_obj $p" \
363 363 "$final_src"
364 364 done
365 365 done
366 366 done
367 367 }
368 368 ((i = i + 2))
369 369 ((j = j + 1))
370 370 done
371 371 }
372 372
373 373
374 374 set -A prop "checksum" "" \
375 375 "compression" "compress" \
376 376 "atime" "" \
377 377 "devices" "" \
378 378 "exec" "" \
379 379 "setuid" "" \
380 380 "sharenfs" "" \
381 381 "recordsize" "recsize" \
382 382 "mountpoint" "" \
383 383 "snapdir" "" \
384 384 "aclmode" "" \
385 385 "aclinherit" "" \
386 386 "readonly" "rdonly"
387 387
388 388 #
389 389 # Note except for the mountpoint default value (which is handled in
390 390 # the routine itself), each property specified in the 'prop' array
391 391 # above must have a corresponding entry in the two arrays below.
392 392 #
393 393
394 394 set -A def_val "on" "off" "on" "on" "on" \
395 395 "on" "off" "" \
396 396 "" "hidden" "discard" "secure" \
397 397 "off"
398 398
399 399 set -A local_val "off" "on" "off" "off" "off" \
400 400 "off" "on" "" \
401 401 "$TESTDIR" "visible" "groupmask" "discard" \
402 402 "off"
403 403
404 404 #
405 405 # Global flag indicating whether the default record size had been
406 406 # read.
407 407 #
408 408 typeset def_recordsize=0
409 409
410 410 set -A config_files $(ls $STF_SUITE/tests/functional/inheritance/config*[1-9]*.cfg)
411 411 set -A state_files $(ls $STF_SUITE/tests/functional/inheritance/state*.cfg)
412 412
413 413 #
414 414 # Global list of datasets created.
415 415 #
416 416 list=""
417 417
418 418 typeset -i k=0
419 419
420 420 if [[ ${#config_files[*]} != ${#state_files[*]} ]]; then
421 421 log_fail "Must have the same number of config files " \
422 422 " (${#config_files[*]}) and state files ${#state_files[*]}"
423 423 fi
424 424
425 425 while ((k < ${#config_files[*]})); do
426 426 default_cleanup_noexit
427 427 def_recordsize=0
428 428
429 429 log_note "Testing configuration ${config_files[k]}"
430 430
431 431 scan_config ${config_files[k]}
432 432 scan_state ${state_files[k]}
433 433
434 434 ((k = k + 1))
435 435 done
436 436
437 437 log_pass "Properties correctly inherited as expected"
|
↓ open down ↓ |
86 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX