]>
Commit | Line | Data |
---|---|---|
ea04106b AX |
1 | #!/bin/bash |
2 | # | |
3 | # Verify that an assortment of known good reference pools can be imported | |
4 | # using different versions of the ZoL code. | |
5 | # | |
6 | # By default references pools for the major ZFS implementation will be | |
7 | # checked against the most recent ZoL tags and the master development branch. | |
8 | # Alternate tags or branches may be verified with the '-s <src-tag> option. | |
9 | # Passing the keyword "installed" will instruct the script to test whatever | |
10 | # version is installed. | |
11 | # | |
12 | # Preferentially a reference pool is used for all tests. However, if one | |
13 | # does not exist and the pool-tag matches one of the src-tags then a new | |
14 | # reference pool will be created using binaries from that source build. | |
15 | # This is particularly useful when you need to test your changes before | |
16 | # opening a pull request. The keyword 'all' can be used as short hand | |
17 | # refer to all available reference pools. | |
18 | # | |
19 | # New reference pools may be added by placing a bzip2 compressed tarball | |
20 | # of the pool in the scripts/zfs-images directory and then passing | |
21 | # the -p <pool-tag> option. To increase the test coverage reference pools | |
22 | # should be collected for all the major ZFS implementations. Having these | |
23 | # pools easily available is also helpful to the developers. | |
24 | # | |
25 | # Care should be taken to run these tests with a kernel supported by all | |
26 | # the listed tags. Otherwise build failure will cause false positives. | |
27 | # | |
28 | # | |
29 | # EXAMPLES: | |
30 | # | |
31 | # The following example will verify the zfs-0.6.2 tag, the master branch, | |
32 | # and the installed zfs version can correctly import the listed pools. | |
33 | # Note there is no reference pool available for master and installed but | |
34 | # because binaries are available one is automatically constructed. The | |
35 | # working directory is also preserved between runs (-k) preventing the | |
36 | # need to rebuild from source for multiple runs. | |
37 | # | |
38 | # zimport.sh -k -f /var/tmp/zimport \ | |
39 | # -s "zfs-0.6.2 master installed" \ | |
40 | # -p "zevo-1.1.1 zol-0.6.2 zol-0.6.2-173 master installed" | |
41 | # | |
42 | # --------------------- ZFS on Linux Source Versions -------------- | |
43 | # zfs-0.6.2 master 0.6.2-175_g36eb554 | |
44 | # ----------------------------------------------------------------- | |
45 | # Clone SPL Local Local Skip | |
46 | # Clone ZFS Local Local Skip | |
47 | # Build SPL Pass Pass Skip | |
48 | # Build ZFS Pass Pass Skip | |
49 | # ----------------------------------------------------------------- | |
50 | # zevo-1.1.1 Pass Pass Pass | |
51 | # zol-0.6.2 Pass Pass Pass | |
52 | # zol-0.6.2-173 Fail Pass Pass | |
53 | # master Pass Pass Pass | |
54 | # installed Pass Pass Pass | |
55 | # | |
56 | basedir="$(dirname $0)" | |
57 | ||
58 | SCRIPT_COMMON=common.sh | |
59 | if [ -f "${basedir}/${SCRIPT_COMMON}" ]; then | |
60 | . "${basedir}/${SCRIPT_COMMON}" | |
61 | else | |
62 | echo "Missing helper script ${SCRIPT_COMMON}" && exit 1 | |
63 | fi | |
64 | ||
65 | PROG=zimport.sh | |
66 | ||
67 | SRC_TAGS="zfs-0.6.1 zfs-0.6.2 master" | |
68 | POOL_TAGS="all master" | |
69 | TEST_DIR=`mktemp -u -d -p /var/tmp zimport.XXXXXXXX` | |
70 | KEEP=0 | |
71 | VERBOSE=0 | |
72 | COLOR=1 | |
73 | REPO="https://github.com/zfsonlinux" | |
74 | IMAGES_DIR="$SCRIPTDIR/zfs-images/" | |
75 | IMAGES_TAR="https://github.com/zfsonlinux/zfs-images/tarball/master" | |
ea04106b AX |
76 | ERROR=0 |
77 | ||
cae5b340 AX |
78 | CONFIG_LOG="configure.log" |
79 | CONFIG_OPTIONS=${CONFIG_OPTIONS:-""} | |
80 | MAKE_LOG="make.log" | |
81 | MAKE_OPTIONS=${MAKE_OPTIONS:-"-s -j$(nproc)"} | |
82 | ||
ea04106b AX |
83 | usage() { |
84 | cat << EOF | |
85 | USAGE: | |
86 | zimport.sh [hvl] [-r repo] [-s src-tag] [-i pool-dir] [-p pool-tag] [-f path] | |
87 | ||
88 | DESCRIPTION: | |
89 | ZPOOL import verification tests | |
90 | ||
91 | OPTIONS: | |
92 | -h Show this message | |
93 | -v Verbose | |
94 | -c No color | |
95 | -k Keep temporary directory | |
96 | -r <repo> Source repository ($REPO) | |
97 | -s <src-tag>... Verify ZoL versions with the listed tags | |
98 | -i <pool-dir> Pool image directory | |
99 | -p <pool-tag>... Verify pools created with the listed tags | |
100 | -f <path> Temporary directory to use | |
101 | ||
102 | EOF | |
103 | } | |
104 | ||
105 | while getopts 'hvckr:s:i:p:f:?' OPTION; do | |
106 | case $OPTION in | |
107 | h) | |
108 | usage | |
109 | exit 1 | |
110 | ;; | |
111 | v) | |
112 | VERBOSE=1 | |
113 | ;; | |
114 | c) | |
115 | COLOR=0 | |
116 | ;; | |
117 | k) | |
118 | KEEP=1 | |
119 | ;; | |
120 | r) | |
121 | REPO="$OPTARG" | |
122 | ;; | |
123 | s) | |
124 | SRC_TAGS="$OPTARG" | |
125 | ;; | |
126 | i) | |
127 | IMAGES_DIR="$OPTARG" | |
128 | ;; | |
129 | p) | |
130 | POOL_TAGS="$OPTARG" | |
131 | ;; | |
132 | f) | |
133 | TEST_DIR="$OPTARG" | |
134 | ;; | |
135 | ?) | |
136 | usage | |
137 | exit | |
138 | ;; | |
139 | esac | |
140 | done | |
141 | ||
142 | # Initialize the test suite | |
143 | init | |
144 | check_modules || die "ZFS modules must be unloaded" | |
145 | ||
146 | SRC_DIR="$TEST_DIR/src" | |
147 | SRC_DIR_SPL="$SRC_DIR/spl" | |
148 | SRC_DIR_ZFS="$SRC_DIR/zfs" | |
149 | ||
150 | if [ $COLOR -eq 0 ]; then | |
151 | COLOR_GREEN="" | |
152 | COLOR_BROWN="" | |
153 | COLOR_RED="" | |
154 | COLOR_RESET="" | |
155 | fi | |
156 | ||
157 | pass_nonewline() { | |
158 | echo -n -e "${COLOR_GREEN}Pass${COLOR_RESET}\t\t" | |
159 | } | |
160 | ||
161 | skip_nonewline() { | |
162 | echo -n -e "${COLOR_BROWN}Skip${COLOR_RESET}\t\t" | |
163 | } | |
164 | ||
165 | fail_nonewline() { | |
166 | echo -n -e "${COLOR_RED}Fail${COLOR_RESET}\t\t" | |
167 | } | |
168 | ||
169 | # | |
170 | # Set several helper variables which are derived from a source tag. | |
171 | # | |
172 | # SPL_TAG - The tag zfs-x.y.z is translated to spl-x.y.z. | |
173 | # SPL_DIR - The spl directory name. | |
174 | # SPL_URL - The spl github URL to fetch the tarball. | |
175 | # ZFS_TAG - The passed zfs-x.y.z tag | |
176 | # ZFS_DIR - The zfs directory name | |
177 | # ZFS_URL - The zfs github URL to fetch the tarball | |
178 | # | |
179 | src_set_vars() { | |
180 | local TAG=$1 | |
181 | ||
182 | SPL_TAG=`echo $TAG | sed -e 's/zfs/spl/'` | |
183 | SPL_DIR=$SRC_DIR_SPL/$SPL_TAG | |
184 | SPL_URL=$REPO/spl/tarball/$SPL_TAG | |
185 | ||
186 | ZFS_TAG=$TAG | |
187 | ZFS_DIR=$SRC_DIR_ZFS/$ZFS_TAG | |
188 | ZFS_URL=$REPO/zfs/tarball/$ZFS_TAG | |
189 | ||
190 | if [ "$TAG" = "installed" ]; then | |
191 | ZPOOL_CMD=`which zpool` | |
192 | ZFS_CMD=`which zfs` | |
193 | ZFS_SH="/usr/share/zfs/zfs.sh" | |
194 | ZPOOL_CREATE="/usr/share/zfs/zpool-create.sh" | |
195 | else | |
196 | ZPOOL_CMD="./cmd/zpool/zpool" | |
197 | ZFS_CMD="./cmd/zfs/zfs" | |
198 | ZFS_SH="./scripts/zfs.sh" | |
199 | ZPOOL_CREATE="./scripts/zpool-create.sh" | |
200 | fi | |
201 | } | |
202 | ||
203 | # | |
204 | # Set several helper variables which are derived from a pool name such | |
205 | # as zol-0.6.x, zevo-1.1.1, etc. These refer to example pools from various | |
206 | # ZFS implementations which are used to verify compatibility. | |
207 | # | |
208 | # POOL_TAG - The example pools name in scripts/zfs-images/. | |
209 | # POOL_BZIP - The full path to the example bzip2 compressed pool. | |
210 | # POOL_DIR - The top level test path for this pool. | |
211 | # POOL_DIR_PRISTINE - The directory containing a pristine version of the pool. | |
212 | # POOL_DIR_COPY - The directory containing a working copy of the pool. | |
213 | # POOL_DIR_SRC - Location of a source build if it exists for this pool. | |
214 | # | |
215 | pool_set_vars() { | |
216 | local TAG=$1 | |
217 | ||
218 | POOL_TAG=$TAG | |
219 | POOL_BZIP=$IMAGES_DIR/$POOL_TAG.tar.bz2 | |
220 | POOL_DIR=$TEST_DIR/pools/$POOL_TAG | |
221 | POOL_DIR_PRISTINE=$POOL_DIR/pristine | |
222 | POOL_DIR_COPY=$POOL_DIR/copy | |
223 | POOL_DIR_SRC=`echo -n "$SRC_DIR_ZFS/"; \ | |
224 | echo "$POOL_TAG" | sed -e 's/zol/zfs/'` | |
225 | } | |
226 | ||
227 | # | |
228 | # Construct a non-trivial pool given a specific version of the source. More | |
229 | # interesting pools provide better test coverage so this function should | |
230 | # extended as needed to create more realistic pools. | |
231 | # | |
232 | pool_create() { | |
233 | pool_set_vars $1 | |
234 | src_set_vars $1 | |
235 | ||
236 | if [ "$POOL_TAG" != "installed" ]; then | |
237 | cd $POOL_DIR_SRC | |
238 | fi | |
239 | ||
240 | $ZFS_SH zfs="spa_config_path=$POOL_DIR_PRISTINE" || fail 1 | |
241 | ||
242 | # Create a file vdev RAIDZ pool. | |
243 | FILEDIR="$POOL_DIR_PRISTINE" $ZPOOL_CREATE \ | |
244 | -c file-raidz -p $POOL_TAG -v -x >/dev/null || fail 2 | |
245 | ||
246 | # Create a pool/fs filesystem with some random contents. | |
247 | $ZFS_CMD create $POOL_TAG/fs || fail 3 | |
248 | populate /$POOL_TAG/fs/ 10 100 | |
249 | ||
250 | # Snapshot that filesystem, clone it, remove the files/dirs, | |
251 | # replace them with new files/dirs. | |
252 | $ZFS_CMD snap $POOL_TAG/fs@snap || fail 4 | |
253 | $ZFS_CMD clone $POOL_TAG/fs@snap $POOL_TAG/clone || fail 5 | |
254 | rm -Rf /$POOL_TAG/clone/* || fail 6 | |
255 | populate /$POOL_TAG/clone/ 10 100 | |
256 | ||
257 | # Scrub the pool, delay slightly, then export it. It is now | |
258 | # somewhat interesting for testing purposes. | |
259 | $ZPOOL_CMD scrub $POOL_TAG || fail 7 | |
260 | sleep 10 | |
261 | $ZPOOL_CMD export $POOL_TAG || fail 8 | |
262 | ||
263 | $ZFS_SH -u || fail 9 | |
264 | } | |
265 | ||
266 | # If the zfs-images directory doesn't exist fetch a copy from Github then | |
267 | # cache it in the $TEST_DIR and update $IMAGES_DIR. | |
268 | if [ ! -d $IMAGES_DIR ]; then | |
269 | IMAGES_DIR="$TEST_DIR/zfs-images" | |
270 | mkdir -p $IMAGES_DIR | |
271 | curl -sL $IMAGES_TAR | \ | |
272 | tar -xz -C $IMAGES_DIR --strip-components=1 || fail 10 | |
273 | fi | |
274 | ||
275 | # Given the available images in the zfs-images directory substitute the | |
cae5b340 | 276 | # list of available images for the reserved keyword 'all'. |
ea04106b AX |
277 | for TAG in $POOL_TAGS; do |
278 | ||
279 | if [ "$TAG" = "all" ]; then | |
280 | ALL_TAGS=`ls $IMAGES_DIR | grep "tar.bz2" | \ | |
281 | sed 's/.tar.bz2//' | tr '\n' ' '` | |
282 | NEW_TAGS="$NEW_TAGS $ALL_TAGS" | |
283 | else | |
284 | NEW_TAGS="$NEW_TAGS $TAG" | |
285 | fi | |
286 | done | |
287 | POOL_TAGS="$NEW_TAGS" | |
288 | ||
289 | if [ $VERBOSE -ne 0 ]; then | |
290 | echo "---------------------------- Options ----------------------------" | |
291 | echo "VERBOSE=$VERBOSE" | |
292 | echo "KEEP=$KEEP" | |
293 | echo "REPO=$REPO" | |
294 | echo "SRC_TAGS="$SRC_TAGS"" | |
295 | echo "POOL_TAGS="$POOL_TAGS"" | |
296 | echo "PATH=$TEST_DIR" | |
297 | echo | |
298 | fi | |
299 | ||
300 | if [ ! -d $TEST_DIR ]; then | |
301 | mkdir -p $TEST_DIR | |
302 | fi | |
303 | ||
304 | if [ ! -d $SRC_DIR ]; then | |
305 | mkdir -p $SRC_DIR | |
306 | fi | |
307 | ||
308 | # Print a header for all tags which are being tested. | |
309 | echo "--------------------- ZFS on Linux Source Versions --------------" | |
310 | printf "%-16s" " " | |
311 | for TAG in $SRC_TAGS; do | |
312 | src_set_vars $TAG | |
313 | ||
314 | if [ "$TAG" = "installed" ]; then | |
315 | ZFS_VERSION=`modinfo zfs | awk '/version:/ { print $2; exit }'` | |
316 | if [ -n "$ZFS_VERSION" ]; then | |
317 | printf "%-16s" $ZFS_VERSION | |
318 | else | |
319 | echo "ZFS is not installed\n" | |
320 | fail | |
321 | fi | |
322 | else | |
323 | printf "%-16s" $TAG | |
324 | fi | |
325 | done | |
326 | echo -e "\n-----------------------------------------------------------------" | |
327 | ||
328 | # | |
329 | # Attempt to generate the tarball from your local git repository, if that | |
330 | # fails then attempt to download the tarball from Github. | |
331 | # | |
332 | printf "%-16s" "Clone SPL" | |
333 | for TAG in $SRC_TAGS; do | |
334 | src_set_vars $TAG | |
335 | ||
336 | if [ -d $SPL_DIR ]; then | |
337 | skip_nonewline | |
338 | elif [ "$SPL_TAG" = "installed" ]; then | |
339 | skip_nonewline | |
340 | else | |
341 | cd $SRC_DIR | |
342 | ||
343 | if [ ! -d $SRC_DIR_SPL ]; then | |
344 | mkdir -p $SRC_DIR_SPL | |
345 | fi | |
346 | ||
347 | git archive --format=tar --prefix=$SPL_TAG/ $SPL_TAG \ | |
348 | -o $SRC_DIR_SPL/$SPL_TAG.tar &>/dev/nul || \ | |
349 | rm $SRC_DIR_SPL/$SPL_TAG.tar | |
350 | if [ -s $SRC_DIR_SPL/$SPL_TAG.tar ]; then | |
351 | tar -xf $SRC_DIR_SPL/$SPL_TAG.tar -C $SRC_DIR_SPL | |
352 | rm $SRC_DIR_SPL/$SPL_TAG.tar | |
353 | echo -n -e "${COLOR_GREEN}Local${COLOR_RESET}\t\t" | |
354 | else | |
355 | mkdir -p $SPL_DIR || fail 1 | |
356 | curl -sL $SPL_URL | tar -xz -C $SPL_DIR \ | |
357 | --strip-components=1 || fail 2 | |
358 | echo -n -e "${COLOR_GREEN}Remote${COLOR_RESET}\t\t" | |
359 | fi | |
360 | fi | |
361 | done | |
362 | printf "\n" | |
363 | ||
364 | # | |
365 | # Attempt to generate the tarball from your local git repository, if that | |
366 | # fails then attempt to download the tarball from Github. | |
367 | # | |
368 | printf "%-16s" "Clone ZFS" | |
369 | for TAG in $SRC_TAGS; do | |
370 | src_set_vars $TAG | |
371 | ||
372 | if [ -d $ZFS_DIR ]; then | |
373 | skip_nonewline | |
374 | elif [ "$ZFS_TAG" = "installed" ]; then | |
375 | skip_nonewline | |
376 | else | |
377 | cd $SRC_DIR | |
378 | ||
379 | if [ ! -d $SRC_DIR_ZFS ]; then | |
380 | mkdir -p $SRC_DIR_ZFS | |
381 | fi | |
382 | ||
383 | git archive --format=tar --prefix=$ZFS_TAG/ $ZFS_TAG \ | |
384 | -o $SRC_DIR_ZFS/$ZFS_TAG.tar &>/dev/nul || \ | |
385 | rm $SRC_DIR_ZFS/$ZFS_TAG.tar | |
386 | if [ -s $SRC_DIR_ZFS/$ZFS_TAG.tar ]; then | |
387 | tar -xf $SRC_DIR_ZFS/$ZFS_TAG.tar -C $SRC_DIR_ZFS | |
388 | rm $SRC_DIR_ZFS/$ZFS_TAG.tar | |
389 | echo -n -e "${COLOR_GREEN}Local${COLOR_RESET}\t\t" | |
390 | else | |
391 | mkdir -p $ZFS_DIR || fail 1 | |
392 | curl -sL $ZFS_URL | tar -xz -C $ZFS_DIR \ | |
393 | --strip-components=1 || fail 2 | |
394 | echo -n -e "${COLOR_GREEN}Remote${COLOR_RESET}\t\t" | |
395 | fi | |
396 | fi | |
397 | done | |
398 | printf "\n" | |
399 | ||
400 | # Build the listed tags | |
401 | printf "%-16s" "Build SPL" | |
402 | for TAG in $SRC_TAGS; do | |
403 | src_set_vars $TAG | |
404 | ||
405 | if [ -f $SPL_DIR/module/spl/spl.ko ]; then | |
406 | skip_nonewline | |
407 | elif [ "$SPL_TAG" = "installed" ]; then | |
408 | skip_nonewline | |
409 | else | |
410 | cd $SPL_DIR | |
411 | make distclean &>/dev/null | |
cae5b340 AX |
412 | ./autogen.sh >>$CONFIG_LOG 2>&1 || fail 1 |
413 | ./configure $CONFIG_OPTIONS >>$CONFIG_LOG 2>&1 || fail 2 | |
414 | make ${MAKE_OPTIONS} >>$MAKE_LOG 2>&1 || fail 3 | |
ea04106b AX |
415 | pass_nonewline |
416 | fi | |
417 | done | |
418 | printf "\n" | |
419 | ||
420 | # Build the listed tags | |
421 | printf "%-16s" "Build ZFS" | |
422 | for TAG in $SRC_TAGS; do | |
423 | src_set_vars $TAG | |
424 | ||
425 | if [ -f $ZFS_DIR/module/zfs/zfs.ko ]; then | |
426 | skip_nonewline | |
427 | elif [ "$ZFS_TAG" = "installed" ]; then | |
428 | skip_nonewline | |
429 | else | |
430 | cd $ZFS_DIR | |
431 | make distclean &>/dev/null | |
cae5b340 AX |
432 | ./autogen.sh >>$CONFIG_LOG 2>&1 || fail 1 |
433 | ./configure --with-spl=$SPL_DIR $CONFIG_OPTIONS \ | |
434 | >>$CONFIG_LOG 2>&1 || fail 2 | |
435 | make ${MAKE_OPTIONS} >>$MAKE_LOG 2>&1 || fail 3 | |
ea04106b AX |
436 | pass_nonewline |
437 | fi | |
438 | done | |
439 | printf "\n" | |
440 | echo "-----------------------------------------------------------------" | |
441 | ||
442 | # Either create a new pool using 'zpool create', or alternately restore an | |
443 | # existing pool from another ZFS implementation for compatibility testing. | |
444 | for TAG in $POOL_TAGS; do | |
445 | pool_set_vars $TAG | |
446 | SKIP=0 | |
447 | ||
448 | printf "%-16s" $POOL_TAG | |
449 | rm -Rf $POOL_DIR | |
450 | mkdir -p $POOL_DIR_PRISTINE | |
451 | ||
452 | # Use the existing compressed image if available. | |
453 | if [ -f $POOL_BZIP ]; then | |
454 | tar -xjf $POOL_BZIP -C $POOL_DIR_PRISTINE \ | |
455 | --strip-components=1 || fail 1 | |
456 | # Use the installed version to create the pool. | |
457 | elif [ "$TAG" = "installed" ]; then | |
458 | pool_create $TAG | |
459 | # A source build is available to create the pool. | |
460 | elif [ -d $POOL_DIR_SRC ]; then | |
461 | pool_create $TAG | |
462 | else | |
463 | SKIP=1 | |
464 | fi | |
465 | ||
466 | # Verify 'zpool import' works for all listed source versions. | |
467 | for TAG in $SRC_TAGS; do | |
468 | ||
469 | if [ $SKIP -eq 1 ]; then | |
470 | skip_nonewline | |
471 | continue | |
472 | fi | |
473 | ||
474 | src_set_vars $TAG | |
475 | if [ "$TAG" != "installed" ]; then | |
476 | cd $ZFS_DIR | |
477 | fi | |
478 | $ZFS_SH zfs="spa_config_path=$POOL_DIR_COPY" | |
479 | ||
480 | cp -a --sparse=always $POOL_DIR_PRISTINE \ | |
481 | $POOL_DIR_COPY || fail 2 | |
482 | POOL_NAME=`$ZPOOL_CMD import -d $POOL_DIR_COPY | \ | |
483 | awk '/pool:/ { print $2; exit 0 }'` | |
484 | ||
485 | $ZPOOL_CMD import -N -d $POOL_DIR_COPY $POOL_NAME &>/dev/null | |
486 | if [ $? -ne 0 ]; then | |
487 | fail_nonewline | |
488 | ERROR=1 | |
489 | else | |
490 | $ZPOOL_CMD export $POOL_NAME || fail 3 | |
491 | pass_nonewline | |
492 | fi | |
493 | ||
494 | rm -Rf $POOL_DIR_COPY | |
495 | ||
496 | $ZFS_SH -u || fail 4 | |
497 | done | |
498 | printf "\n" | |
499 | done | |
500 | ||
501 | if [ ! $KEEP ]; then | |
502 | rm -Rf $TEST_DIR | |
503 | fi | |
504 | ||
505 | exit $ERROR |