Tizen 2.1 base
[external/device-mapper.git] / test / test-utils.sh
1 # Copyright (C) 2008 Red Hat, Inc. All rights reserved.
2 #
3 # This copyrighted material is made available to anyone wishing to use,
4 # modify, copy, or redistribute it subject to the terms and conditions
5 # of the GNU General Public License v.2.
6 #
7 # You should have received a copy of the GNU General Public License
8 # along with this program; if not, write to the Free Software Foundation,
9 # Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
10
11 aux() {
12         # use just "$@" for verbose operation
13         "$@" > /dev/null 2> /dev/null
14         #"$@"
15 }
16
17 STACKTRACE() {
18         trap - ERR;
19         i=0;
20
21         while FUNC=${FUNCNAME[$i]}; test "$FUNC" != "main"; do 
22                 echo "$i ${FUNC}() called from ${BASH_SOURCE[$i]}:${BASH_LINENO[$i]}"
23                 i=$(($i + 1));
24         done
25
26         # Get backtraces from coredumps
27         if which gdb >& /dev/null; then
28                 echo bt full > gdb_commands.txt
29                 echo l >> gdb_commands.txt
30                 echo quit >> gdb_commands.txt
31                 for core in `ls core* 2>/dev/null`; do
32                         bin=$(gdb -batch -c $core 2>&1 | grep "generated by" | \
33                                 sed -e "s,.*generated by \`\([^ ']*\).*,\1,")
34                         gdb -batch -c $core -x gdb_commands.txt `which $bin`
35                 done
36         fi
37
38         test -f debug.log && {
39                 sed -e "s,^,## DEBUG: ,;s,$top_srcdir/\?,," < debug.log
40         }
41 }
42
43 init_udev_transaction() {
44         if test "$DM_UDEV_SYNCHRONISATION" = 1; then
45                 COOKIE=$(dmsetup udevcreatecookie)
46                 # Cookie is not generated if udev is not running!
47                 if test -n "$COOKIE"; then
48                         export DM_UDEV_COOKIE=$COOKIE
49                 fi
50         fi
51 }
52
53 finish_udev_transaction() {
54         if test "$DM_UDEV_SYNCHRONISATION" = 1 -a -n "$DM_UDEV_COOKIE"; then
55                 dmsetup udevreleasecookie
56                 unset DM_UDEV_COOKIE
57         fi
58 }
59
60 prepare_clvmd() {
61         if test -z "$LVM_TEST_LOCKING" || test "$LVM_TEST_LOCKING" -ne 3 ; then
62                 return 0 # not needed
63         fi
64
65         if pgrep clvmd ; then
66                 echo "Cannot use fake cluster locking with real clvmd ($(pgrep clvmd)) running."
67                 exit 200
68         fi
69
70         # skip if we don't have our own clvmd...
71         (which clvmd | grep $abs_builddir) || exit 200
72
73         # skip if we singlenode is not compiled in
74         (clvmd --help 2>&1 | grep "Available cluster managers" | grep singlenode) || exit 200
75
76         trap_teardown
77
78         clvmd -Isinglenode -d 1 &
79         LOCAL_CLVMD="$!"
80
81         # check that it is really running now
82         sleep .1
83         ps $LOCAL_CLVMD || exit 200
84 }
85
86 prepare_dmeventd() {
87         if pgrep dmeventd ; then
88                 echo "Cannot test dmeventd with real dmeventd ($(pgrep dmeventd)) running."
89                 exit 200
90         fi
91
92         # skip if we don't have our own dmeventd...
93         (which dmeventd | grep $abs_builddir) || exit 200
94
95         trap_teardown
96
97         dmeventd -f &
98         LOCAL_DMEVENTD="$!"
99 }
100
101 prepare_testroot() {
102         OLDPWD="`pwd`"
103         PREFIX="LVMTEST$$"
104
105         trap_teardown
106         TESTDIR=$($abs_srcdir/mkdtemp ${LVM_TEST_DIR-$(pwd)} $PREFIX.XXXXXXXXXX) \
107                 || { echo "failed to create temporary directory in ${LVM_TEST_DIR-$(pwd)}"; exit 1; }
108
109         export LVM_SYSTEM_DIR=$TESTDIR/etc
110         export DM_DEV_DIR=$TESTDIR/dev
111         mkdir $LVM_SYSTEM_DIR $DM_DEV_DIR $DM_DEV_DIR/mapper $TESTDIR/lib
112
113         cd $TESTDIR
114
115         for i in `find $abs_top_builddir/daemons/dmeventd/plugins/ -name \*.so`; do
116                 echo Setting up symlink from $i to $TESTDIR/lib
117                 ln -s $i $TESTDIR/lib
118         done
119 }
120
121 teardown_devs() {
122         test -n "$PREFIX" && {
123                 rm -rf $TESTDIR/dev/$PREFIX*
124
125                 init_udev_transaction
126                 while dmsetup table | grep -q ^$PREFIX; do
127                         for s in `dmsetup info -c -o name --noheading | grep ^$PREFIX`; do
128                                 umount -fl $DM_DEV_DIR/mapper/$s || true
129                                 dmsetup remove $s >& /dev/null || true
130                         done
131                 done
132                 finish_udev_transaction
133
134         }
135
136         # NOTE: SCSI_DEBUG_DEV test must come before the LOOP test because
137         # prepare_scsi_debug_dev() also sets LOOP to short-circuit prepare_loop()
138         if [ -n "$SCSI_DEBUG_DEV" ] ; then
139                 modprobe -r scsi_debug
140         else
141                 test -n "$LOOP" && losetup -d $LOOP
142                 test -n "$LOOPFILE" && rm -f $LOOPFILE
143         fi
144         unset devs # devs is set in prepare_devs()
145         unset LOOP
146 }
147
148 teardown() {
149         echo $LOOP
150         echo $PREFIX
151
152         test -n "$LOCAL_CLVMD" && {
153                 kill "$LOCAL_CLVMD"
154                 sleep .1
155                 kill -9 "$LOCAL_CLVMD" || true
156         }
157
158         test -n "$LOCAL_DMEVENTD" && kill -9 "$LOCAL_DMEVENTD"
159
160         teardown_devs
161
162         test -n "$TESTDIR" && {
163                 cd $OLDPWD
164                 rm -rf $TESTDIR || echo BLA
165         }
166 }
167
168 trap_teardown() {
169         trap 'set +vx; STACKTRACE; set -vx' ERR
170         trap 'aux teardown' EXIT # don't forget to clean up
171 }
172
173 make_ioerror() {
174         echo 0 10000000 error | dmsetup create ioerror
175         ln -s $DM_DEV_DIR/mapper/ioerror $DM_DEV_DIR/ioerror
176 }
177
178 prepare_loop() {
179         size=$1
180         test -n "$size" || size=32
181
182         # skip if prepare_scsi_debug_dev() was used
183         if [ -n "$SCSI_DEBUG_DEV" -a -n "$LOOP" ]; then
184                 return 0
185         fi
186
187         test -z "$LOOP"
188         test -n "$DM_DEV_DIR"
189
190         trap_teardown
191
192         for i in 0 1 2 3 4 5 6 7; do
193                 test -e $DM_DEV_DIR/loop$i || mknod $DM_DEV_DIR/loop$i b 7 $i
194         done
195
196         LOOPFILE="$PWD/test.img"
197         dd if=/dev/zero of="$LOOPFILE" bs=$((1024*1024)) count=0 seek=$(($size-1))
198         if LOOP=`losetup -s -f "$LOOPFILE" 2>/dev/null`; then
199                 return 0
200         elif LOOP=`losetup -f` && losetup $LOOP "$LOOPFILE"; then
201                 # no -s support
202                 return 0
203         else
204                 # no -f support 
205                 # Iterate through $DM_DEV_DIR/loop{,/}{0,1,2,3,4,5,6,7}
206                 for slash in '' /; do
207                         for i in 0 1 2 3 4 5 6 7; do
208                                 local dev=$DM_DEV_DIR/loop$slash$i
209                                 ! losetup $dev >/dev/null 2>&1 || continue
210                                 # got a free
211                                 losetup "$dev" "$LOOPFILE"
212                                 LOOP=$dev
213                                 break
214                         done
215                         if [ -n "$LOOP" ]; then 
216                                 break
217                         fi
218                 done
219                 test -n "$LOOP" # confirm or fail
220                 return 0
221         fi
222         exit 1 # should not happen
223 }
224
225 # A drop-in replacement for prepare_loop() that uses scsi_debug to create
226 # a ramdisk-based SCSI device upon which all LVM devices will be created
227 # - scripts must take care not to use a DEV_SIZE that will enduce OOM-killer
228 prepare_scsi_debug_dev()
229 {
230     local DEV_SIZE="$1"
231     shift
232     local SCSI_DEBUG_PARAMS="$@"
233
234     test -n "$SCSI_DEBUG_DEV" && return 0
235     test -z "$LOOP"
236     test -n "$DM_DEV_DIR"
237
238     trap_teardown
239
240     # Skip test if awk isn't available (required for get_sd_devs_)
241     which awk || exit 200
242
243     # Skip test if scsi_debug module is unavailable or is already in use
244     modprobe --dry-run scsi_debug || exit 200
245     lsmod | grep -q scsi_debug && exit 200
246
247     # Create the scsi_debug device and determine the new scsi device's name
248     # NOTE: it will _never_ make sense to pass num_tgts param;
249     # last param wins.. so num_tgts=1 is imposed
250     modprobe scsi_debug dev_size_mb=$DEV_SIZE $SCSI_DEBUG_PARAMS num_tgts=1 || exit 200
251     sleep 2 # allow for async Linux SCSI device registration
252
253     local DEBUG_DEV=/dev/$(grep -H scsi_debug /sys/block/*/device/model | cut -f4 -d /)
254     [ -b $DEBUG_DEV ] || exit 1 # should not happen
255
256     # Create symlink to scsi_debug device in $DM_DEV_DIR
257     SCSI_DEBUG_DEV=$DM_DEV_DIR/$(basename $DEBUG_DEV)
258     # Setting $LOOP provides means for prepare_devs() override
259     LOOP=$SCSI_DEBUG_DEV
260     ln -snf $DEBUG_DEV $SCSI_DEBUG_DEV
261     return 0
262 }
263
264 cleanup_scsi_debug_dev()
265 {
266     aux teardown_devs
267     unset SCSI_DEBUG_DEV
268     unset LOOP
269 }
270
271 prepare_devs() {
272         local n="$1"
273         test -z "$n" && n=3
274         local devsize="$2"
275         test -z "$devsize" && devsize=34
276         local pvname="$3"
277         test -z "$pvname" && pvname="pv"
278
279         prepare_loop $(($n*$devsize))
280
281         if ! loopsz=`blockdev --getsz $LOOP 2>/dev/null`; then
282                 loopsz=`blockdev --getsize $LOOP 2>/dev/null`
283         fi
284
285         local size=$(($loopsz/$n))
286
287         init_udev_transaction
288         for i in `seq 1 $n`; do
289                 local name="${PREFIX}$pvname$i"
290                 local dev="$DM_DEV_DIR/mapper/$name"
291                 eval "dev$i=$dev"
292                 devs="$devs $dev"
293                 echo 0 $size linear $LOOP $((($i-1)*$size)) > $name.table
294                 dmsetup create $name $name.table
295         done
296         finish_udev_transaction
297
298         for i in `seq 1 $n`; do
299                 local name="${PREFIX}$pvname$i"
300                 dmsetup info -c $name
301         done
302         for i in `seq 1 $n`; do
303                 local name="${PREFIX}$pvname$i"
304                 dmsetup table $name
305         done
306 }
307
308 disable_dev() {
309
310         init_udev_transaction
311         for dev in "$@"; do
312         # first we make the device inaccessible
313                 echo 0 10000000 error | dmsetup load $dev
314                 dmsetup resume $dev
315         # now let's try to get rid of it if it's unused
316         #dmsetup remove $dev
317         done
318         finish_udev_transaction
319
320 }
321
322 enable_dev() {
323
324         init_udev_transaction
325         for dev in "$@"; do
326                 local name=`echo "$dev" | sed -e 's,.*/,,'`
327                 dmsetup create $name $name.table || dmsetup load $name $name.table
328                 dmsetup resume $dev
329         done
330         finish_udev_transaction
331 }
332
333 backup_dev() {
334         for dev in "$@"; do
335                 dd if=$dev of=$dev.backup bs=1024
336         done
337 }
338
339 restore_dev() {
340         for dev in "$@"; do
341                 test -e $dev.backup || {
342                         echo "Internal error: $dev not backed up, can't restore!"
343                         exit 1
344                 }
345                 dd of=$dev if=$dev.backup bs=1024
346         done
347 }
348
349 prepare_pvs() {
350         prepare_devs "$@"
351         pvcreate -ff $devs
352 }
353
354 prepare_vg() {
355         vgremove -ff $vg || true
356         teardown_devs
357
358         prepare_pvs "$@"
359         vgcreate -c n $vg $devs
360         pvs -v
361 }
362
363 prepare_lvmconf() {
364         local filter="$1"
365         test -z "$filter" && \
366                 filter='[ "a/dev\/mirror/", "a/dev\/mapper\/.*pv[0-9_]*$/", "r/.*/" ]'
367         locktype=
368         if test -z "$LVM_TEST_CONFIG_SNAPSHOT_AUTOEXTEND"; then
369                 LVM_TEST_CONFIG_SNAPSHOT_AUTOEXTEND="
370     snapshot_autoextend_percent = 50
371     snapshot_autoextend_threshold = 50"
372         fi
373         if test -n "$LVM_TEST_LOCKING"; then locktype="locking_type = $LVM_TEST_LOCKING"; fi
374         cat > $TESTDIR/etc/lvm.conf.new <<-EOF
375   $LVM_TEST_CONFIG
376   devices {
377     dir = "$DM_DEV_DIR"
378     scan = "$DM_DEV_DIR"
379     filter = $filter
380     cache_dir = "$TESTDIR/etc"
381     sysfs_scan = 0
382     default_data_alignment = 1
383     $LVM_TEST_CONFIG_DEVICES
384   }
385   log {
386     syslog = 0
387     indent = 1
388     level = 9
389     file = "$TESTDIR/debug.log"
390     overwrite = 1
391     activation = 1
392   }
393   backup {
394     backup = 0
395     archive = 0
396   }
397   global {
398     abort_on_internal_errors = 1
399     library_dir = "$TESTDIR/lib"
400     locking_dir = "$TESTDIR/var/lock/lvm"
401     $locktype
402     si_unit_consistency = 1
403     fallback_to_local_locking = 0
404   }
405   activation {
406     udev_sync = 1
407     udev_rules = 1
408     polling_interval = 0
409     $LVM_TEST_CONFIG_SNAPSHOT_AUTOEXTEND
410   }
411 EOF
412         # FIXME remove this workaround after mmap & truncating file problems solved
413         mv -f $TESTDIR/etc/lvm.conf.new $TESTDIR/etc/lvm.conf
414         cat $TESTDIR/etc/lvm.conf
415 }
416
417 prepare() {
418         ulimit -c unlimited
419         # FIXME any way to set this just for our children?
420         # echo 1 > /proc/sys/kernel/core_uses_pid
421         prepare_testroot
422         prepare_lvmconf
423         prepare_clvmd
424
425         # set up some default names
426         vg=${PREFIX}vg
427         vg1=${PREFIX}vg1
428         vg2=${PREFIX}vg2
429         lv=LV
430         lv1=LV1
431         lv2=LV2
432         lv3=LV3
433         lv4=LV4
434 }
435
436 apitest() {
437         t=$1
438         shift
439         test -x $abs_top_builddir/test/api/$t.t || exit 200
440         $abs_top_builddir/test/api/$t.t "$@"
441 }
442
443 api() {
444         test -x $abs_top_builddir/test/api/wrapper || exit 200
445         $abs_top_builddir/test/api/wrapper "$@"
446 }
447
448 LANG=C
449 LC_ALL=C
450 TZ=UTC
451 unset CDPATH
452
453 . ./init.sh || { echo >&2 you must run make first; exit 1; }
454 . ./lvm-utils.sh
455
456 set -vexE -o pipefail
457 aux prepare