Whamcloud - gitweb
9c5bda2b8a76df1f4b08454c8caf51cdf0323eb9
[fs/lustre-release.git] / lustre / tests / sanity-sec.sh
1 #!/bin/bash
2 #
3 # Run select tests by setting ONLY, or as arguments to the script.
4 # Skip specific tests by setting EXCEPT.
5 #
6
7 set -e
8
9 ONLY=${ONLY:-"$*"}
10 # bug number for skipped test: 19430 19967 19967
11 ALWAYS_EXCEPT="                2     5     6    $SANITY_SEC_EXCEPT"
12 # UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
13
14 [ "$ALWAYS_EXCEPT$EXCEPT" ] && \
15         echo "Skipping tests: $ALWAYS_EXCEPT $EXCEPT"
16
17 SRCDIR=`dirname $0`
18 export PATH=$PWD/$SRCDIR:$SRCDIR:$PWD/$SRCDIR/../utils:$PATH:/sbin
19 export NAME=${NAME:-local}
20
21 LUSTRE=${LUSTRE:-$(dirname $0)/..}
22 . $LUSTRE/tests/test-framework.sh
23 init_test_env $@
24 . ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh}
25 init_logging
26
27 RUNAS_CMD=${RUNAS_CMD:-runas}
28
29 WTL=${WTL:-"$LUSTRE/tests/write_time_limit"}
30
31 CONFDIR=/etc/lustre
32 PERM_CONF=$CONFDIR/perm.conf
33 FAIL_ON_ERROR=false
34
35 HOSTNAME_CHECKSUM=$(hostname | sum | awk '{ print $1 }')
36 SUBNET_CHECKSUM=$(expr $HOSTNAME_CHECKSUM % 250 + 1)
37 NODEMAP_COUNT=16
38 NODEMAP_RANGE_COUNT=3
39 NODEMAP_IPADDR_LIST="1 10 64 128 200 250"
40 NODEMAP_MAX_ID=128
41
42 require_dsh_mds || exit 0
43 require_dsh_ost || exit 0
44
45 clients=${CLIENTS//,/ }
46 num_clients=$(get_node_count ${clients})
47 clients_arr=($clients)
48
49 ID0=${ID0:-500}
50 ID1=${ID1:-501}
51 USER0=$(grep :$ID0:$ID0: /etc/passwd | cut -d: -f1)
52 USER1=$(grep :$ID1:$ID1: /etc/passwd | cut -d: -f1)
53
54 [ -z "$USER0" ] &&
55         skip "need to add user0 ($ID0:$ID0) to /etc/passwd" && exit 0
56
57 [ -z "$USER1" ] &&
58         skip "need to add user1 ($ID1:$ID1) to /etc/passwd" && exit 0
59
60 IDBASE=${IDBASE:-60000}
61
62 # changes to mappings must be reflected in test 23
63 FOPS_IDMAPS=(
64         [0]="$((IDBASE+3)):$((IDBASE+0)) $((IDBASE+4)):$((IDBASE+2))"
65         [1]="$((IDBASE+5)):$((IDBASE+1)) $((IDBASE+6)):$((IDBASE+2))"
66         )
67
68 check_and_setup_lustre
69
70 sec_cleanup() {
71         if [ "$I_MOUNTED" = "yes" ]; then
72                 cleanupall -f || error "sec_cleanup"
73         fi
74 }
75
76 DIR=${DIR:-$MOUNT}
77 [ -z "`echo $DIR | grep $MOUNT`" ] && \
78         error "$DIR not in $MOUNT" && sec_cleanup && exit 1
79
80 [ `echo $MOUNT | wc -w` -gt 1 ] && \
81         echo "NAME=$MOUNT mounted more than once" && sec_cleanup && exit 0
82
83 [ $MDSCOUNT -gt 1 ] && \
84         echo "skip multi-MDS test" && sec_cleanup && exit 0
85
86 # for GSS_SUP
87 GSS_REF=$(lsmod | grep ^ptlrpc_gss | awk '{print $3}')
88 if [ ! -z "$GSS_REF" -a "$GSS_REF" != "0" ]; then
89         GSS_SUP=1
90         echo "with GSS support"
91 else
92         GSS_SUP=0
93         echo "without GSS support"
94 fi
95
96 MDT=$(do_facet $SINGLEMDS lctl get_param -N "mdt.\*MDT0000" |
97         cut -d. -f2 || true)
98 [ -z "$MDT" ] && error "fail to get MDT device" && exit 1
99 do_facet $SINGLEMDS "mkdir -p $CONFDIR"
100 IDENTITY_FLUSH=mdt.$MDT.identity_flush
101 IDENTITY_UPCALL=mdt.$MDT.identity_upcall
102 MDSCAPA=mdt.$MDT.capa
103 CAPA_TIMEOUT=mdt.$MDT.capa_timeout
104 MDSSECLEVEL=mdt.$MDT.sec_level
105
106 # for CLIENT_TYPE
107 if [ -z "$(lctl get_param -n llite.*.client_type | grep remote 2>/dev/null)" ]
108 then
109         CLIENT_TYPE="local"
110         echo "local client"
111 else
112         CLIENT_TYPE="remote"
113         echo "remote client"
114 fi
115
116 SAVE_PWD=$PWD
117
118 build_test_filter
119
120 sec_login() {
121         local user=$1
122         local group=$2
123
124         if ! $RUNAS_CMD -u $user krb5_login.sh; then
125                 error "$user login kerberos failed."
126                 exit 1
127         fi
128
129         if ! $RUNAS_CMD -u $user -g $group ls $DIR > /dev/null 2>&1; then
130                 $RUNAS_CMD -u $user lfs flushctx -k
131                 $RUNAS_CMD -u $user krb5_login.sh
132                 if ! $RUNAS_CMD -u$user -g$group ls $DIR > /dev/null 2>&1; then
133                         error "init $user $group failed."
134                         exit 2
135                 fi
136         fi
137 }
138
139 declare -a identity_old
140
141 sec_setup() {
142         for num in `seq $MDSCOUNT`; do
143                 switch_identity $num true || identity_old[$num]=$?
144         done
145
146         if ! $RUNAS_CMD -u $ID0 ls $DIR > /dev/null 2>&1; then
147                 sec_login $USER0 $USER0
148         fi
149
150         if ! $RUNAS_CMD -u $ID1 ls $DIR > /dev/null 2>&1; then
151                 sec_login $USER1 $USER1
152         fi
153 }
154 sec_setup
155
156 # run as different user
157 test_0() {
158         umask 0022
159
160         chmod 0755 $DIR || error "chmod (1)"
161         rm -rf $DIR/$tdir || error "rm (1)"
162         mkdir -p $DIR/$tdir || error "mkdir (1)"
163
164         if [ "$CLIENT_TYPE" = "remote" ]; then
165                 do_facet $SINGLEMDS "echo '* 0 normtown' > $PERM_CONF"
166                 do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
167                 chown $USER0 $DIR/$tdir && error "chown (1)"
168                 do_facet $SINGLEMDS "echo '* 0 rmtown' > $PERM_CONF"
169                 do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
170         else
171                 chown $USER0 $DIR/$tdir || error "chown (2)"
172         fi
173
174         $RUNAS_CMD -u $ID0 ls $DIR || error "ls (1)"
175         rm -f $DIR/f0 || error "rm (2)"
176         $RUNAS_CMD -u $ID0 touch $DIR/f0 && error "touch (1)"
177         $RUNAS_CMD -u $ID0 touch $DIR/$tdir/f1 || error "touch (2)"
178         $RUNAS_CMD -u $ID1 touch $DIR/$tdir/f2 && error "touch (3)"
179         touch $DIR/$tdir/f3 || error "touch (4)"
180         chown root $DIR/$tdir || error "chown (3)"
181         chgrp $USER0 $DIR/$tdir || error "chgrp (1)"
182         chmod 0775 $DIR/$tdir || error "chmod (2)"
183         $RUNAS_CMD -u $ID0 touch $DIR/$tdir/f4 || error "touch (5)"
184         $RUNAS_CMD -u $ID1 touch $DIR/$tdir/f5 && error "touch (6)"
185         touch $DIR/$tdir/f6 || error "touch (7)"
186         rm -rf $DIR/$tdir || error "rm (3)"
187
188         if [ "$CLIENT_TYPE" = "remote" ]; then
189                 do_facet $SINGLEMDS "rm -f $PERM_CONF"
190                 do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
191         fi
192 }
193 run_test 0 "uid permission ============================="
194
195 # setuid/gid
196 test_1() {
197         [ $GSS_SUP = 0 ] && skip "without GSS support." && return
198
199         if [ "$CLIENT_TYPE" = "remote" ]; then
200                 do_facet $SINGLEMDS "echo '* 0 rmtown' > $PERM_CONF"
201                 do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
202         fi
203
204         rm -rf $DIR/$tdir
205         mkdir -p $DIR/$tdir
206
207         chown $USER0 $DIR/$tdir || error "chown (1)"
208         $RUNAS_CMD -u $ID1 -v $ID0 touch $DIR/$tdir/f0 && error "touch (2)"
209         echo "enable uid $ID1 setuid"
210         do_facet $SINGLEMDS "echo '* $ID1 setuid' >> $PERM_CONF"
211         do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
212         $RUNAS_CMD -u $ID1 -v $ID0 touch $DIR/$tdir/f1 || error "touch (3)"
213
214         chown root $DIR/$tdir || error "chown (4)"
215         chgrp $USER0 $DIR/$tdir || error "chgrp (5)"
216         chmod 0770 $DIR/$tdir || error "chmod (6)"
217         $RUNAS_CMD -u $ID1 -g $ID1 touch $DIR/$tdir/f2 && error "touch (7)"
218         $RUNAS_CMD -u$ID1 -g$ID1 -j$ID0 touch $DIR/$tdir/f3 && error "touch (8)"
219         echo "enable uid $ID1 setuid,setgid"
220         do_facet $SINGLEMDS "echo '* $ID1 setuid,setgid' > $PERM_CONF"
221         do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
222         $RUNAS_CMD -u $ID1 -g $ID1 -j $ID0 touch $DIR/$tdir/f4 ||
223                 error "touch (9)"
224         $RUNAS_CMD -u $ID1 -v $ID0 -g $ID1 -j $ID0 touch $DIR/$tdir/f5 ||
225                 error "touch (10)"
226
227         rm -rf $DIR/$tdir
228
229         do_facet $SINGLEMDS "rm -f $PERM_CONF"
230         do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
231 }
232 run_test 1 "setuid/gid ============================="
233
234 run_rmtacl_subtest() {
235     $SAVE_PWD/rmtacl/run $SAVE_PWD/rmtacl/$1.test
236     return $?
237 }
238
239 # remote_acl
240 # for remote client only
241 test_2 () {
242         [ "$CLIENT_TYPE" = "local" ] && \
243                 skip "remote_acl for remote client only" && return
244         [ -z "$(lctl get_param -n mdc.*-mdc-*.connect_flags | grep ^acl)" ] && \
245                 skip "must have acl enabled" && return
246         [ -z "$(which setfacl 2>/dev/null)" ] && \
247                 skip "could not find setfacl" && return
248         [ "$UID" != 0 ] && skip "must run as root" && return
249
250         do_facet $SINGLEMDS "echo '* 0 rmtacl,rmtown' > $PERM_CONF"
251         do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
252
253         sec_login root root
254         sec_login bin bin
255         sec_login daemon daemon
256         sec_login games users
257
258         SAVE_UMASK=`umask`
259         umask 0022
260         cd $DIR
261
262         echo "performing cp ..."
263         run_rmtacl_subtest cp || error "cp"
264         echo "performing getfacl-noacl..."
265         run_rmtacl_subtest getfacl-noacl || error "getfacl-noacl"
266         echo "performing misc..."
267         run_rmtacl_subtest misc || error "misc"
268         echo "performing permissions..."
269         run_rmtacl_subtest permissions || error "permissions"
270         echo "performing setfacl..."
271         run_rmtacl_subtest setfacl || error "setfacl"
272
273         # inheritance test got from HP
274         echo "performing inheritance..."
275         cp $SAVE_PWD/rmtacl/make-tree .
276         chmod +x make-tree
277         run_rmtacl_subtest inheritance || error "inheritance"
278         rm -f make-tree
279
280         cd $SAVE_PWD
281         umask $SAVE_UMASK
282
283         do_facet $SINGLEMDS "rm -f $PERM_CONF"
284         do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
285 }
286 run_test 2 "rmtacl ============================="
287
288 # rootsquash
289 # root_squash will be redesigned in Lustre 1.7
290 test_3() {
291         skip "root_squash will be redesigned in Lustre 1.7" && return
292 }
293 run_test 3 "rootsquash ============================="
294
295 # bug 3285 - supplementary group should always succeed.
296 # NB: the supplementary groups are set for local client only,
297 # as for remote client, the groups of the specified uid on MDT
298 # will be obtained by upcall /sbin/l_getidentity and used.
299 test_4() {
300         if [ "$CLIENT_TYPE" = "remote" ]; then
301                 do_facet $SINGLEMDS "echo '* 0 rmtown' > $PERM_CONF"
302                 do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
303         fi
304
305         rm -rf $DIR/$tdir
306         mkdir -p $DIR/$tdir
307         chmod 0771 $DIR/$tdir
308         chgrp $ID0 $DIR/$tdir
309         $RUNAS_CMD -u $ID0 ls $DIR/$tdir || error "setgroups (1)"
310         if [ "$CLIENT_TYPE" = "local" ]; then
311                 do_facet $SINGLEMDS "echo '* $ID1 setgrp' > $PERM_CONF"
312                 do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
313                 $RUNAS_CMD -u $ID1 -G1,2,$ID0 ls $DIR/$tdir ||
314                         error "setgroups (2)"
315         fi
316         $RUNAS_CMD -u $ID1 -G1,2 ls $DIR/$tdir && error "setgroups (3)"
317         rm -rf $DIR/$tdir
318
319         do_facet $SINGLEMDS "rm -f $PERM_CONF"
320         do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
321 }
322 run_test 4 "set supplementary group ==============="
323
324 mds_capability_timeout() {
325         [ $# -lt 1 ] && echo "Miss mds capability timeout value" && return 1
326
327         echo "Set mds capability timeout as $1 seconds"
328         do_facet $SINGLEMDS "lctl set_param -n $CAPA_TIMEOUT=$1"
329         return 0
330 }
331
332 mds_sec_level_switch() {
333         [ $# -lt 1 ] && echo "Miss mds sec level switch value" && return 1
334
335         case $1 in
336                 0) echo "Disable capa for all clients";;
337                 1) echo "Enable capa for remote client";;
338                 3) echo "Enable capa for all clients";;
339                 *) echo "Invalid mds sec level switch value" && return 2;;
340         esac
341
342         do_facet $SINGLEMDS "lctl set_param -n $MDSSECLEVEL=$1"
343         return 0
344 }
345
346 oss_sec_level_switch() {
347         [ $# -lt 1 ] && echo "Miss oss sec level switch value" && return 1
348
349         case $1 in
350                 0) echo "Disable capa for all clients";;
351                 1) echo "Enable capa for remote client";;
352                 3) echo "Enable capa for all clients";;
353                 *) echo "Invalid oss sec level switch value" && return 2;;
354         esac
355
356         for i in `seq $OSTCOUNT`; do
357                 local j=`expr $i - 1`
358                 local OST="`do_facet ost$i "lctl get_param -N obdfilter.\*OST\*$j/stats 2>/dev/null | cut -d"." -f2" || true`"
359                 [ -z "$OST" ] && return 3
360                 do_facet ost$i "lctl set_param -n obdfilter.$OST.sec_level=$1"
361         done
362         return 0
363 }
364
365 mds_capability_switch() {
366         [ $# -lt 1 ] && echo "Miss mds capability switch value" && return 1
367
368         case $1 in
369                 0) echo "Turn off mds capability";;
370                 3) echo "Turn on mds capability";;
371                 *) echo "Invalid mds capability switch value" && return 2;;
372         esac
373
374         do_facet $SINGLEMDS "lctl set_param -n $MDSCAPA=$1"
375         return 0
376 }
377
378 oss_capability_switch() {
379         [ $# -lt 1 ] && echo "Miss oss capability switch value" && return 1
380
381         case $1 in
382                 0) echo "Turn off oss capability";;
383                 1) echo "Turn on oss capability";;
384                 *) echo "Invalid oss capability switch value" && return 2;;
385         esac
386
387         for i in `seq $OSTCOUNT`; do
388                 local j=`expr $i - 1`
389                 local OST="`do_facet ost$i "lctl get_param -N obdfilter.\*OST\*$j/stats 2>/dev/null | cut -d"." -f2" || true`"
390                 [ -z "$OST" ] && return 3
391                 do_facet ost$i "lctl set_param -n obdfilter.$OST.capa=$1"
392         done
393         return 0
394 }
395
396 turn_mds_capa_on() {
397         mds_capability_switch 3 || return 1
398         mds_sec_level_switch 3  || return 2
399         return 0
400 }
401
402 turn_oss_capa_on() {
403         oss_capability_switch 1 || return 1
404         oss_sec_level_switch 3  || return 2
405         return 0
406 }
407
408 turn_capability_on() {
409         local capa_timeout=${1:-"1800"}
410
411         # To turn on fid capability for the system,
412         # there is a requirement that fid capability
413         # is turned on on all MDS/OSS servers before
414         # client mount.
415
416         turn_mds_capa_on || return 1
417         turn_oss_capa_on || return 2
418         mds_capability_timeout $capa_timeout || return 3
419         remount_client $MOUNT || return 4
420         return 0
421 }
422
423 turn_mds_capa_off() {
424         mds_sec_level_switch 0  || return 1
425         mds_capability_switch 0 || return 2
426         return 0
427 }
428
429 turn_oss_capa_off() {
430         oss_sec_level_switch 0  || return 1
431         oss_capability_switch 0 || return 2
432         return 0
433 }
434
435 turn_capability_off() {
436         # to turn off fid capability, you can just do
437         # it in a live system. But, please turn off
438         # capability of all OSS servers before MDS servers.
439
440         turn_oss_capa_off || return 1
441         turn_mds_capa_off || return 2
442         return 0
443 }
444
445 # We demonstrate that access to the objects in the filesystem are not
446 # accessible without supplying secrets from the MDS by disabling a
447 # proc variable on the mds so that it does not supply secrets. We then
448 # try and access objects which result in failure.
449 test_5() {
450         local file=$DIR/f5
451
452         [ $GSS_SUP = 0 ] && skip "without GSS support." && return
453         if ! remote_mds; then
454                 skip "client should be separated from server."
455                 return
456         fi
457
458         rm -f $file
459
460         turn_capability_off
461         if [ $? != 0 ]; then
462                 error "turn_capability_off"
463                 return 1
464         fi
465
466         turn_oss_capa_on
467         if [ $? != 0 ]; then
468                 error "turn_oss_capa_on"
469                 return 2
470         fi
471
472         if [ "$CLIENT_TYPE" = "remote" ]; then
473                 remount_client $MOUNT && return 3
474                 turn_oss_capa_off
475                 return 0
476         else
477                 remount_client $MOUNT || return 4
478         fi
479
480         # proc variable disabled -- access to the objects in the filesystem
481         # is not allowed
482         echo "Should get Write error here : (proc variable are disabled "\
483              "-- access to the objects in the filesystem is denied."
484         $WTL $file 30
485         if [ $? == 0 ]; then
486                 error "Write worked well even though secrets not supplied."
487                 return 5
488         fi
489
490         turn_capability_on
491         if [ $? != 0 ]; then
492                 error "turn_capability_on"
493                 return 6
494         fi
495
496         sleep 5
497
498         # proc variable enabled, secrets supplied -- write should work now
499         echo "Should not fail here : (proc variable enabled, secrets supplied "\
500              "-- write should work now)."
501         $WTL $file 30
502         if [ $? != 0 ]; then
503                 error "Write failed even though secrets supplied."
504                 return 7
505         fi
506
507         turn_capability_off
508         if [ $? != 0 ]; then
509                 error "turn_capability_off"
510                 return 8
511         fi
512         rm -f $file
513 }
514 run_test 5 "capa secrets ========================="
515
516 # Expiry: A test program is performing I/O on a file. It has credential
517 # with an expiry half a minute later. While the program is running the
518 # credentials expire and no automatic extensions or renewals are
519 # enabled. The program will demonstrate an I/O failure.
520 test_6() {
521         local file=$DIR/f6
522
523         [ $GSS_SUP = 0 ] && skip "without GSS support." && return
524         if ! remote_mds; then
525                 skip "client should be separated from server."
526                 return
527         fi
528
529         turn_capability_off
530         if [ $? != 0 ]; then
531                 error "turn_capability_off"
532                 return 1
533         fi
534
535         rm -f $file
536
537         turn_capability_on 30
538         if [ $? != 0 ]; then
539                 error "turn_capability_on 30"
540                 return 2
541         fi
542
543         # Token expiry
544         $WTL $file 60
545         if [ $? != 0 ]; then
546                 error "$WTL $file 60"
547                 return 3
548         fi
549
550         # Reset MDS capability timeout
551         mds_capability_timeout 30
552         if [ $? != 0 ]; then
553                 error "mds_capability_timeout 30"
554                 return 4
555         fi
556
557         $WTL $file 60 &
558         local PID=$!
559         sleep 5
560
561         # To disable automatic renew, only need turn capa off on MDS.
562         turn_mds_capa_off
563         if [ $? != 0 ]; then
564                 error "turn_mds_capa_off"
565                 return 5
566         fi
567
568         echo "We expect I/O failure."
569         wait $PID
570         if [ $? == 0 ]; then
571                 echo "no I/O failure got."
572                 return 6
573         fi
574
575         turn_capability_off
576         if [ $? != 0 ]; then
577                 error "turn_capability_off"
578                 return 7
579         fi
580         rm -f $file
581 }
582 run_test 6 "capa expiry ========================="
583
584 create_nodemaps() {
585         local i
586         local out
587         local rc
588
589         squash_id default 99 0
590         squash_id default 99 1
591         for (( i = 0; i < NODEMAP_COUNT; i++ )); do
592                 if ! do_facet mgs $LCTL nodemap_add                     \
593                         ${HOSTNAME_CHECKSUM}_${i}; then
594                         return 1
595                 fi
596                 out=$(do_facet mgs $LCTL get_param                      \
597                         nodemap.${HOSTNAME_CHECKSUM}_${i}.id)
598                 ## This needs to return zero if the following statement is 1
599                 rc=$(echo $out | grep -c ${HOSTNAME_CHECKSUM}_${i})
600                 [[ $rc == 0 ]] && return 1
601         done
602         return 0
603 }
604
605 delete_nodemaps() {
606         local i
607         local out
608         local rc
609
610         for ((i = 0; i < NODEMAP_COUNT; i++)); do
611                 if ! do_facet mgs $LCTL nodemap_del                     \
612                         ${HOSTNAME_CHECKSUM}_${i}; then
613                         error "nodemap_del ${HOSTNAME_CHECKSUM}_${i}    \
614                                 failed with $rc"
615                         return 3
616                 fi
617                 out=$(do_facet mgs $LCTL get_param                      \
618                         nodemap.${HOSTNAME_CHECKSUM}_${i}.id)
619                 rc=$(echo $out | grep -c ${HOSTNAME_CHECKSUM}_${i})
620                 [[ $rc != 0 ]] && return 1
621         done
622         return 0
623 }
624
625 add_range() {
626         local j
627         local cmd="$LCTL nodemap_add_range"
628         local range
629         local rc=0
630
631         for ((j = 0; j < NODEMAP_RANGE_COUNT; j++)); do
632                 range="$SUBNET_CHECKSUM.${2}.${j}.[1-253]@tcp"
633                 if ! do_facet mgs $cmd --name $1        \
634                         --range $range; then
635                         rc=$(($rc + 1))
636                 fi
637         done
638         return $rc
639 }
640
641 delete_range() {
642         local j
643         local cmd="$LCTL nodemap_del_range"
644         local range
645         local rc=0
646
647         for ((j = 0; j < NODEMAP_RANGE_COUNT; j++)); do
648                 range="$SUBNET_CHECKSUM.${2}.${j}.[1-253]@tcp"
649                 if ! do_facet mgs $cmd --name $1        \
650                         --range $range; then
651                         rc=$(($rc + 1))
652                 fi
653         done
654
655         return $rc
656 }
657
658 add_idmaps() {
659         local i
660         local j
661         local client_id
662         local fs_id
663         local cmd="$LCTL nodemap_add_idmap"
664         local rc=0
665
666         for ((i = 0; i < NODEMAP_COUNT; i++)); do
667                 for ((j = 500; j < NODEMAP_MAX_ID; j++)); do
668                         client_id=$j
669                         fs_id=$(($j + 1))
670                         if ! do_facet mgs $cmd                          \
671                         --name ${HOSTNAME_CHECKSUM}_${i}                \
672                         --idtype uid --idmap $client_id:$fs_id; then
673                                 rc=$(($rc + 1))
674                         fi
675                         if ! do_facet mgs $cmd                          \
676                         --name ${HOSTNAME_CHECKSUM}_${i}                \
677                         --idtype gid --idmap $client_id:$fs_id; then
678                                 rc=$(($rc + 1))
679                         fi
680                 done
681         done
682
683         return $rc
684 }
685
686 delete_idmaps() {
687         local i
688         local j
689         local client_id
690         local fs_id
691         local cmd="$LCTL nodemap_del_idmap"
692         local rc=0
693
694         for ((i = 0; i < NODEMAP_COUNT; i++)); do
695                 for ((j = 500; j < NODEMAP_MAX_ID; j++)); do
696                         client_id=$j
697                         fs_id=$(($j + 1))
698                         if ! do_facet mgs $cmd                          \
699                         --name ${HOSTNAME_CHECKSUM}_${i}                \
700                         --idtype uid --idmap $client_id:$fs_id; then
701                                 rc=$(($rc + 1))
702                         fi
703                         if ! do_facet mgs $cmd                          \
704                         --name ${HOSTNAME_CHECKSUM}_${i}                \
705                         --idtype gid --idmap $client_id:$fs_id; then
706                                 rc=$(($rc + 1))
707                         fi
708                 done
709         done
710
711         return $rc
712 }
713
714 modify_flags() {
715         local i
716         local proc
717         local option
718         local cmd="$LCTL nodemap_modify"
719         local rc=0
720
721         proc[0]="admin_nodemap"
722         proc[1]="trusted_nodemap"
723         option[0]="admin"
724         option[1]="trusted"
725
726         for ((idx = 0; idx < 2; idx++)); do
727                 if ! do_facet mgs $cmd --name $1        \
728                         --property ${option[$idx]}      \
729                         --value 1; then
730                         rc=$((rc + 1))
731                 fi
732
733                 if ! do_facet mgs $cmd --name $1        \
734                         --property ${option[$idx]}      \
735                         --value 0; then
736                         rc=$((rc + 1))
737                 fi
738         done
739
740         return $rc
741 }
742
743 squash_id() {
744         local cmd
745
746         cmd[0]="$LCTL nodemap_modify --property squash_uid"
747         cmd[1]="$LCTL nodemap_modify --property squash_gid"
748
749         if ! do_facet mgs ${cmd[$3]} --name $1 --value $2; then
750                 return 1
751         fi
752 }
753
754 # ensure that the squash defaults are the expected defaults
755 squash_id default 99 0
756 squash_id default 99 1
757
758 test_nid() {
759         local cmd
760
761         cmd="$LCTL nodemap_test_nid"
762
763         nid=$(do_facet mgs $cmd $1)
764
765         if [ $nid == $2 ]; then
766                 return 0
767         fi
768
769         return 1
770 }
771
772 test_idmap() {
773         local i
774         local j
775         local fs_id
776         local cmd="$LCTL nodemap_test_id"
777         local rc=0
778
779         ## nodemap deactivated
780         if ! do_facet mgs lctl nodemap_activate 0; then
781                 return 1
782         fi
783         for ((id = 500; id < NODEMAP_MAX_ID; id++)); do
784                 for ((j = 0; j < NODEMAP_RANGE_COUNT; j++)); do
785                         nid="$SUBNET_CHECKSUM.0.${j}.100@tcp"
786                         fs_id=$(do_facet mgs $cmd --nid $nid    \
787                                 --idtype uid --id $id)
788                         if [ $fs_id != $id ]; then
789                                 echo "expected $id, got $fs_id"
790                                 rc=$((rc + 1))
791                         fi
792                 done
793         done
794
795         ## nodemap activated
796         if ! do_facet mgs lctl nodemap_activate 1; then
797                 return 2
798         fi
799
800         for ((id = 500; id < NODEMAP_MAX_ID; id++)); do
801                 for ((j = 0; j < NODEMAP_RANGE_COUNT; j++)); do
802                         nid="$SUBNET_CHECKSUM.0.${j}.100@tcp"
803                         fs_id=$(do_facet mgs $cmd --nid $nid    \
804                                 --idtype uid --id $id)
805                         expected_id=$((id + 1))
806                         if [ $fs_id != $expected_id ]; then
807                                 echo "expected $expected_id, got $fs_id"
808                                 rc=$((rc + 1))
809                         fi
810                 done
811         done
812
813         ## trust client ids
814         for ((i = 0; i < NODEMAP_COUNT; i++)); do
815                 if ! do_facet mgs $LCTL nodemap_modify                  \
816                                 --name ${HOSTNAME_CHECKSUM}_${i}        \
817                                 --property trusted --value 1; then
818                         error "nodemap_modify ${HOSTNAME_CHECKSUM}_${i} "
819                                 "failed with $rc"
820                         return 3
821                 fi
822         done
823
824         for ((id = 500; id < NODEMAP_MAX_ID; id++)); do
825                 for ((j = 0; j < NODEMAP_RANGE_COUNT; j++)); do
826                         nid="$SUBNET_CHECKSUM.0.${j}.100@tcp"
827                         fs_id=$(do_facet mgs $cmd --nid $nid    \
828                                 --idtype uid --id $id)
829                         if [ $fs_id != $id ]; then
830                                 echo "expected $id, got $fs_id"
831                                 rc=$((rc + 1))
832                         fi
833                 done
834         done
835
836         ## ensure allow_root_access is enabled
837         for ((i = 0; i < NODEMAP_COUNT; i++)); do
838                 if ! do_facet mgs $LCTL nodemap_modify          \
839                         --name ${HOSTNAME_CHECKSUM}_${i}        \
840                         --property admin --value 1; then
841                         error "nodemap_modify ${HOSTNAME_CHECKSUM}_${i} "
842                                 "failed with $rc"
843                         return 3
844                 fi
845         done
846
847         ## check that root allowed
848         for ((j = 0; j < NODEMAP_RANGE_COUNT; j++)); do
849                 nid="$SUBNET_CHECKSUM.0.${j}.100@tcp"
850                 fs_id=$(do_facet mgs $cmd --nid $nid --idtype uid --id 0)
851                 if [ $fs_id != 0 ]; then
852                         echo "root allowed expected 0, got $fs_id"
853                         rc=$((rc + 1))
854                 fi
855         done
856
857         ## ensure allow_root_access is disabled
858         for ((i = 0; i < NODEMAP_COUNT; i++)); do
859                 if ! do_facet mgs $LCTL nodemap_modify          \
860                                 --name ${HOSTNAME_CHECKSUM}_${i}        \
861                                 --property admin --value 0; then
862                         error "nodemap_modify ${HOSTNAME_CHECKSUM}_${i} "
863                                 "failed with $rc"
864                         return 3
865                 fi
866         done
867
868         ## check that root is mapped to 99
869         for ((j = 0; j < NODEMAP_RANGE_COUNT; j++)); do
870                 nid="$SUBNET_CHECKSUM.0.${j}.100@tcp"
871                 fs_id=$(do_facet mgs $cmd --nid $nid --idtype uid --id 0)
872                 if [ $fs_id != 99 ]; then
873                         error "root squash expected 99, got $fs_id"
874                         rc=$((rc + 1))
875                 fi
876         done
877
878         ## reset client trust to 0
879         for ((i = 0; i < NODEMAP_COUNT; i++)); do
880                 if ! do_facet mgs $LCTL nodemap_modify          \
881                         --name ${HOSTNAME_CHECKSUM}_${i}        \
882                         --property trusted --value 0; then
883                         error "nodemap_modify ${HOSTNAME_CHECKSUM}_${i} "
884                                 "failed with $rc"
885                         return 3
886                 fi
887         done
888
889         return $rc
890 }
891
892 test_7() {
893         local rc
894
895         remote_mgs_nodsh && skip "remote MGS with nodsh" && return
896         [ $(lustre_version_code $SINGLEMGS) -lt $(version_code 2.5.53) ] &&
897                 skip "No nodemap on $(get_lustre_version) MGS, need 2.5.53+" &&
898                 return
899
900         create_nodemaps
901         rc=$?
902         [[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 1
903
904         delete_nodemaps
905         rc=$?
906         [[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 2
907
908         return 0
909 }
910 run_test 7 "nodemap create and delete"
911
912 test_8() {
913         local rc
914
915         remote_mgs_nodsh && skip "remote MGS with nodsh" && return
916         [ $(lustre_version_code $SINGLEMGS) -lt $(version_code 2.5.53) ] &&
917                 skip "No nodemap on $(get_lustre_version) MGS, need 2.5.53+" &&
918                 return
919
920         # Set up nodemaps
921
922         create_nodemaps
923         rc=$?
924         [[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 1
925
926         # Try duplicates
927
928         create_nodemaps
929         rc=$?
930         [[ $rc == 0 ]] && error "duplicate nodemap_add allowed with $rc" &&
931         return 2
932
933         # Clean up
934         delete_nodemaps
935         rc=$?
936         [[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 3
937
938         return 0
939 }
940 run_test 8 "nodemap reject duplicates"
941
942 test_9() {
943         local i
944         local rc
945
946         remote_mgs_nodsh && skip "remote MGS with nodsh" && return
947         [ $(lustre_version_code $SINGLEMGS) -lt $(version_code 2.5.53) ] &&
948                 skip "No nodemap on $(get_lustre_version) MGS, need 2.5.53+" &&
949                 return
950
951         rc=0
952         create_nodemaps
953         rc=$?
954         [[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 1
955
956         rc=0
957         for ((i = 0; i < NODEMAP_COUNT; i++)); do
958                 if ! add_range ${HOSTNAME_CHECKSUM}_${i} $i; then
959                         rc=$((rc + 1))
960                 fi
961         done
962         [[ $rc != 0 ]] && error "nodemap_add_range failed with $rc" && return 2
963
964         rc=0
965         for ((i = 0; i < NODEMAP_COUNT; i++)); do
966                 if ! delete_range ${HOSTNAME_CHECKSUM}_${i} $i; then
967                         rc=$((rc + 1))
968                 fi
969         done
970         [[ $rc != 0 ]] && error "nodemap_del_range failed with $rc" && return 4
971
972         rc=0
973         delete_nodemaps
974         rc=$?
975         [[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 4
976
977         return 0
978 }
979 run_test 9 "nodemap range add"
980
981 test_10() {
982         local rc
983
984         remote_mgs_nodsh && skip "remote MGS with nodsh" && return
985         [ $(lustre_version_code $SINGLEMGS) -lt $(version_code 2.5.53) ] &&
986                 skip "No nodemap on $(get_lustre_version) MGS, need 2.5.53+" &&
987                 return
988
989         rc=0
990         create_nodemaps
991         rc=$?
992         [[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 1
993
994         rc=0
995         for ((i = 0; i < NODEMAP_COUNT; i++)); do
996                 if ! add_range ${HOSTNAME_CHECKSUM}_${i} $i; then
997                         rc=$((rc + 1))
998                 fi
999         done
1000         [[ $rc != 0 ]] && error "nodemap_add_range failed with $rc" && return 2
1001
1002         rc=0
1003         for ((i = 0; i < NODEMAP_COUNT; i++)); do
1004                 if ! add_range ${HOSTNAME_CHECKSUM}_${i} $i; then
1005                         rc=$((rc + 1))
1006                 fi
1007         done
1008         [[ $rc == 0 ]] && error "nodemap_add_range duplicate add with $rc" &&
1009                 return 2
1010
1011
1012         rc=0
1013         for ((i = 0; i < NODEMAP_COUNT; i++)); do
1014                 if ! delete_range ${HOSTNAME_CHECKSUM}_${i} $i; then
1015                         rc=$((rc + 1))
1016                 fi
1017         done
1018         [[ $rc != 0 ]] && error "nodemap_del_range failed with $rc" && return 4
1019
1020         delete_nodemaps
1021         rc=$?
1022         [[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 5
1023
1024         return 0
1025 }
1026 run_test 10 "nodemap reject duplicate ranges"
1027
1028 test_11() {
1029         local rc
1030
1031         remote_mgs_nodsh && skip "remote MGS with nodsh" && return
1032         [ $(lustre_version_code $SINGLEMGS) -lt $(version_code 2.5.53) ] &&
1033                 skip "No nodemap on $(get_lustre_version) MGS, need 2.5.53+" &&
1034                 return
1035
1036         rc=0
1037         create_nodemaps
1038         rc=$?
1039         [[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 1
1040
1041         rc=0
1042         for ((i = 0; i < NODEMAP_COUNT; i++)); do
1043                 if ! modify_flags ${HOSTNAME_CHECKSUM}_${i}; then
1044                         rc=$((rc + 1))
1045                 fi
1046         done
1047         [[ $rc != 0 ]] && error "nodemap_modify with $rc" && return 2
1048
1049         rc=0
1050         delete_nodemaps
1051         rc=$?
1052         [[ $rc != 0 ]] && error "nodemap_del failed with $rc" && return 3
1053
1054         return 0
1055 }
1056 run_test 11 "nodemap modify"
1057
1058 test_12() {
1059         local rc
1060
1061         remote_mgs_nodsh && skip "remote MGS with nodsh" && return
1062         [ $(lustre_version_code $SINGLEMGS) -lt $(version_code 2.5.53) ] &&
1063                 skip "No nodemap on $(get_lustre_version) MGS, need 2.5.53+" &&
1064                 return
1065
1066         rc=0
1067         create_nodemaps
1068         rc=$?
1069         [[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 1
1070
1071         rc=0
1072         for ((i = 0; i < NODEMAP_COUNT; i++)); do
1073                 if ! squash_id ${HOSTNAME_CHECKSUM}_${i} 88 0; then
1074                         rc=$((rc + 1))
1075                 fi
1076         done
1077         [[ $rc != 0 ]] && error "nodemap squash_uid with $rc" && return 2
1078
1079         rc=0
1080         for ((i = 0; i < NODEMAP_COUNT; i++)); do
1081                 if ! squash_id ${HOSTNAME_CHECKSUM}_${i} 88 1; then
1082                         rc=$((rc + 1))
1083                 fi
1084         done
1085         [[ $rc != 0 ]] && error "nodemap squash_gid with $rc" && return 3
1086
1087         rc=0
1088         delete_nodemaps
1089         rc=$?
1090         [[ $rc != 0 ]] && error "nodemap_del failed with $rc" && return 4
1091
1092         return 0
1093 }
1094 run_test 12 "nodemap set squash ids"
1095
1096 test_13() {
1097         local rc
1098
1099         remote_mgs_nodsh && skip "remote MGS with nodsh" && return
1100         [ $(lustre_version_code $SINGLEMGS) -lt $(version_code 2.5.53) ] &&
1101                 skip "No nodemap on $(get_lustre_version) MGS, need 2.5.53+" &&
1102                 return
1103
1104         rc=0
1105         create_nodemaps
1106         rc=$?
1107         [[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 1
1108
1109         rc=0
1110         for ((i = 0; i < NODEMAP_COUNT; i++)); do
1111                 if ! add_range ${HOSTNAME_CHECKSUM}_${i} $i; then
1112                         rc=$((rc + 1))
1113                 fi
1114         done
1115         [[ $rc != 0 ]] && error "nodemap_add_range failed with $rc" && return 2
1116
1117         rc=0
1118         for ((i = 0; i < NODEMAP_COUNT; i++)); do
1119                 for ((j = 0; j < NODEMAP_RANGE_COUNT; j++)); do
1120                         for k in $NODEMAP_IPADDR_LIST; do
1121                                 if ! test_nid $SUBNET_CHECKSUM.$i.$j.$k \
1122                                        ${HOSTNAME_CHECKSUM}_${i}; then
1123                                         rc=$((rc + 1))
1124                                 fi
1125                         done
1126                 done
1127         done
1128         [[ $rc != 0 ]] && error "nodemap_test_nid failed with $rc" && return 3
1129
1130         rc=0
1131         delete_nodemaps
1132         rc=$?
1133         [[ $rc != 0 ]] && error "nodemap_del failed with $rc" && return 4
1134
1135         return 0
1136 }
1137 run_test 13 "test nids"
1138
1139 test_14() {
1140         local rc
1141
1142         remote_mgs_nodsh && skip "remote MGS with nodsh" && return
1143         [ $(lustre_version_code $SINGLEMGS) -lt $(version_code 2.5.53) ] &&
1144                 skip "No nodemap on $(get_lustre_version) MGS, need 2.5.53+" &&
1145                 return
1146
1147         rc=0
1148         create_nodemaps
1149         rc=$?
1150         [[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 1
1151
1152         rc=0
1153         for ((i = 0; i < NODEMAP_COUNT; i++)); do
1154                 for ((j = 0; j < NODEMAP_RANGE_COUNT; j++)); do
1155                         for k in $NODEMAP_IPADDR_LIST; do
1156                                 if ! test_nid $SUBNET_CHECKSUM.$i.$j.$k \
1157                                         default; then
1158                                         rc=$((rc + 1))
1159                                 fi
1160                         done
1161                 done
1162         done
1163         [[ $rc != 0 ]] && error "nodemap_test_nid failed with $rc" && return 3
1164
1165         rc=0
1166         delete_nodemaps
1167         rc=$?
1168         [[ $rc != 0 ]] && error "nodemap_del failed with $rc" && return 4
1169
1170         return 0
1171 }
1172 run_test 14 "test default nodemap nid lookup"
1173
1174 test_15() {
1175         local rc
1176
1177         remote_mgs_nodsh && skip "remote MGS with nodsh" && return
1178         [ $(lustre_version_code $SINGLEMGS) -lt $(version_code 2.5.53) ] &&
1179                 skip "No nodemap on $(get_lustre_version) MGS, need 2.5.53+" &&
1180                 return
1181
1182         rc=0
1183         create_nodemaps
1184         rc=$?
1185         [[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 1
1186
1187         rc=0
1188         for ((i = 0; i < NODEMAP_COUNT; i++)); do
1189                 if ! add_range ${HOSTNAME_CHECKSUM}_${i} $i; then
1190                         rc=$((rc + 1))
1191                 fi
1192         done
1193         [[ $rc != 0 ]] && error "nodemap_add_range failed with $rc" && return 2
1194
1195         rc=0
1196         add_idmaps
1197         rc=$?
1198         [[ $rc != 0 ]] && error "nodemap_add_idmap failed with $rc" && return 3
1199
1200         rc=0
1201         test_idmap
1202         rc=$?
1203         [[ $rc != 0 ]] && error "nodemap_test_id failed with $rc" && return 4
1204
1205         rc=0
1206         delete_idmaps
1207         rc=$?
1208         [[ $rc != 0 ]] && error "nodemap_del_idmap failed with $rc" && return 5
1209
1210         rc=0
1211         delete_nodemaps
1212         rc=$?
1213         [[ $rc != 0 ]] && error "nodemap_delete failed with $rc" && return 6
1214
1215         return 0
1216 }
1217 run_test 15 "test id mapping"
1218
1219 create_fops_nodemaps() {
1220         local i=0
1221         local client
1222         for client in $clients; do
1223                 local client_ip=$(host_nids_address $client $NETTYPE)
1224                 local client_nid=$(h2$NETTYPE $client_ip)
1225                 do_facet mgs $LCTL nodemap_add c${i} || return 1
1226                 do_facet mgs $LCTL nodemap_add_range    \
1227                         --name c${i} --range $client_nid || return 1
1228                 do_facet ost0 $LCTL set_param nodemap.add_nodemap=c${i} ||
1229                         return 1
1230                 do_facet ost0 "$LCTL set_param nodemap.add_nodemap_range='c$i \
1231                         $client_nid'" || return 1
1232                 for map in ${FOPS_IDMAPS[i]}; do
1233                         do_facet mgs $LCTL nodemap_add_idmap --name c${i} \
1234                                 --idtype uid --idmap ${map} || return 1
1235                         do_facet ost0 "$LCTL set_param \
1236                                 nodemap.add_nodemap_idmap='c$i uid ${map}'" ||
1237                                 return 1
1238                         do_facet mgs $LCTL nodemap_add_idmap --name c${i} \
1239                                 --idtype gid --idmap ${map} || return 1
1240                         do_facet ost0 "$LCTL set_param \
1241                                 nodemap.add_nodemap_idmap='c$i gid ${map}'" ||
1242                                 return 1
1243                 done
1244                 out1=$(do_facet mgs $LCTL get_param nodemap.c${i}.idmap)
1245                 out2=$(do_facet ost0 $LCTL get_param nodemap.c${i}.idmap)
1246                 [ "$out1" != "$out2" ] && error "mgs and oss maps mismatch"
1247                 i=$((i + 1))
1248         done
1249         return 0
1250 }
1251
1252 delete_fops_nodemaps() {
1253         local i=0
1254         local client
1255         for client in $clients; do
1256                 do_facet mgs $LCTL nodemap_del c${i} || return 1
1257                 do_facet ost0 $LCTL set_param nodemap.remove_nodemap=c${i} ||
1258                         return 1
1259                 i=$((i + 1))
1260         done
1261         return 0
1262 }
1263
1264 # acl test directory needs to be initialized on a privileged client
1265 fops_test_setup() {
1266         local admin=$(do_facet mgs $LCTL get_param -n nodemap.c0.admin_nodemap)
1267         local trust=$(do_facet mgs $LCTL get_param -n \
1268                 nodemap.c0.trusted_nodemap)
1269
1270         do_facet mgs $LCTL nodemap_modify --name c0 --property admin --value 1
1271         do_facet mgs $LCTL nodemap_modify --name c0 --property trusted --value 1
1272         do_facet ost0 $LCTL set_param nodemap.c0.admin_nodemap=1
1273         do_facet ost0 $LCTL set_param nodemap.c0.trusted_nodemap=1
1274
1275         do_node ${clients_arr[0]} rm -rf $DIR/$tdir
1276         do_node ${clients_arr[0]} mkdir -p $DIR/$tdir
1277         do_node ${clients_arr[0]} chown $user $DIR/$tdir
1278
1279         do_facet mgs $LCTL nodemap_modify --name c0 \
1280                 --property admin --value $admin
1281         do_facet mgs $LCTL nodemap_modify --name c0 \
1282                 --property trusted --value $trust
1283         do_facet ost0 $LCTL set_param nodemap.c0.admin_nodemap=$admin
1284         do_facet ost0 $LCTL set_param nodemap.c0.trusted_nodemap=$trust
1285
1286         # flush MDT locks to make sure they are reacquired before test
1287         do_node ${clients_arr[0]} lctl set_param \
1288                 ldlm.namespaces.$FSNAME-MDT*.lru_size=clear
1289 }
1290
1291 do_create_delete() {
1292         local run_u=$1
1293         local key=$2
1294         local testfile=$DIR/$tdir/$tfile
1295         local rc=0
1296         local c=0 d=0
1297         local qused_new
1298         if $run_u touch $testfile >& /dev/null; then
1299                 c=1
1300                 $run_u rm $testfile && d=1
1301         fi >& /dev/null
1302
1303         local res="$c $d"
1304         local expected=$(get_cr_del_expected $key)
1305         [ "$res" != "$expected" ] && error "test $key expected " \
1306                 "$expected, got $res" && rc=$(($rc+1))
1307         return $rc
1308 }
1309
1310 nodemap_check_quota() {
1311         local run_u="$1"
1312         $run_u lfs quota -q $DIR | awk '{ print $2; exit; }'
1313 }
1314
1315 do_fops_quota_test() {
1316         local run_u=$1
1317         # define fuzz as 2x ost block size in K
1318         local quota_fuzz=$(($(lctl get_param -n \
1319                 osc.$FSNAME-OST0000-*.blocksize | head -1) / 512))
1320         local qused_orig=$(nodemap_check_quota "$run_u")
1321         local qused_low=$((qused_orig - quota_fuzz))
1322         local qused_high=$((qused_orig + quota_fuzz))
1323         local testfile=$DIR/$tdir/$tfile
1324         chmod 777 $DIR/$tdir
1325         $run_u dd if=/dev/zero of=$testfile bs=1M count=1 >& /dev/null
1326         sync; sync_all_data || true
1327
1328         local qused_new=$(nodemap_check_quota "$run_u")
1329         [ $((qused_low + 1024)) -le $((qused_new)) \
1330                 -a $((qused_high + 1024)) -ge $((qused_new)) ] ||
1331                 error "$qused_new != $qused_orig + 1M after write"
1332         $run_u rm $testfile && d=1
1333         $NODEMAP_TEST_QUOTA && wait_delete_completed_mds
1334
1335         qused_new=$(nodemap_check_quota "$run_u")
1336         [ $((qused_low)) -le $((qused_new)) \
1337                 -a $((qused_high)) -ge $((qused_new)) ] ||
1338                 error "quota not reclaimed, expect $qused_orig got $qused_new"
1339 }
1340
1341 get_fops_mapped_user() {
1342         local cli_user=$1
1343
1344         for ((i=0; i < ${#FOPS_IDMAPS[@]}; i++)); do
1345                 for map in ${FOPS_IDMAPS[i]}; do
1346                         if [ $(cut -d: -f1 <<< "$map") == $cli_user ]; then
1347                                 cut -d: -f2 <<< "$map"
1348                                 return
1349                         fi
1350                 done
1351         done
1352         echo -1
1353 }
1354
1355 get_cr_del_expected() {
1356         local -a key
1357         IFS=":" read -a key <<< "$1"
1358         local mapmode="${key[0]}"
1359         local mds_user="${key[1]}"
1360         local cluster="${key[2]}"
1361         local cli_user="${key[3]}"
1362         local mode="0${key[4]}"
1363         local SUCCESS="1 1"
1364         local FAILURE="0 0"
1365         local noadmin=0
1366         local mapped=0
1367         local other=0
1368
1369         [[ $mapmode == *mapped* ]] && mapped=1
1370         # only c1 is mapped in these test cases
1371         [[ $mapmode == mapped_trusted* ]] && [ "$cluster" == "c0" ] && mapped=0
1372         [[ $mapmode == *noadmin* ]] && noadmin=1
1373
1374         # o+wx works as long as the user isn't mapped
1375         if [ $((mode & 3)) -eq 3 ]; then
1376                 other=1
1377         fi
1378
1379         # if client user is root, check if root is squashed
1380         if [ "$cli_user" == "0" ]; then
1381                 # squash root succeed, if other bit is on
1382                 case $noadmin in
1383                         0) echo $SUCCESS;;
1384                         1) [ "$other" == "1" ] && echo $SUCCESS
1385                            [ "$other" == "0" ] && echo $FAILURE;;
1386                 esac
1387                 return
1388         fi
1389         if [ "$mapped" == "0" ]; then
1390                 [ "$other" == "1" ] && echo $SUCCESS
1391                 [ "$other" == "0" ] && echo $FAILURE
1392                 return
1393         fi
1394
1395         # if mapped user is mds user, check for u+wx
1396         mapped_user=$(get_fops_mapped_user $cli_user)
1397         [ "$mapped_user" == "-1" ] &&
1398                 error "unable to find mapping for client user $cli_user"
1399
1400         if [ "$mapped_user" == "$mds_user" -a  \
1401                         $(((mode & 0300) == 0300)) -eq 1 ]; then
1402                 echo $SUCCESS
1403                 return
1404         fi
1405         if [ "$mapped_user" != "$mds_user" -a "$other" == "1" ]; then
1406                 echo $SUCCESS
1407                 return
1408         fi
1409         echo $FAILURE
1410 }
1411
1412 test_fops() {
1413         local mapmode="$1"
1414         local single_client="$2"
1415         local client_user_list=([0]="0 $((IDBASE+3)) $((IDBASE+4))"
1416                                 [1]="0 $((IDBASE+5)) $((IDBASE+6))")
1417         local mds_i
1418         local rc=0
1419         local perm_bit_list="0 3 $((0300)) $((0303))"
1420         [ "$SLOW" == "yes" ] && perm_bit_list=$(seq 0 511)
1421
1422         # step through mds users. -1 means root
1423         for mds_i in -1 0 1 2; do
1424                 local user=$((mds_i + IDBASE))
1425                 local client
1426                 local x
1427
1428                 [ "$mds_i" == "-1" ] && user=0
1429
1430                 echo mkdir -p $DIR/$tdir
1431                 fops_test_setup
1432                 local cli_i=0
1433                 for client in $clients; do
1434                         local u
1435                         local admin=$(do_facet mgs $LCTL get_param -n \
1436                                 nodemap.c$cli_i.admin_nodemap)
1437                         for u in ${client_user_list[$cli_i]}; do
1438                                 local run_u="do_node $client \
1439                                              $RUNAS_CMD -u$u -g$u -G$u"
1440                                 for perm_bits in $perm_bit_list; do
1441                                         local mode=$(printf %03o $perm_bits)
1442                                         do_facet mgs $LCTL nodemap_modify \
1443                                                 --name c$cli_i \
1444                                                 --property admin \
1445                                                 --value 1
1446                                         do_node $client chmod $mode $DIR/$tdir
1447                                         do_facet mgs $LCTL nodemap_modify \
1448                                                 --name c$cli_i \
1449                                                 --property admin \
1450                                                 --value $admin
1451
1452                                         local key
1453                                         key="$mapmode:$user:c$cli_i:$u:$mode"
1454                                         do_create_delete "$run_u" "$key"
1455                                 done
1456
1457                                 # check quota
1458                                 do_fops_quota_test "$run_u"
1459                         done
1460
1461                         cli_i=$((cli_i + 1))
1462                         [ "$single_client" == "1" ] && break
1463                 done
1464                 rm -rf $DIR/$tdir
1465         done
1466         return $rc
1467 }
1468
1469 nodemap_test_setup() {
1470         local rc
1471         local active_nodemap=$1
1472
1473         do_facet mgs $LCTL set_param $IDENTITY_UPCALL=NONE
1474
1475         remote_mgs_nodsh && skip "remote MGS with nodsh" && return
1476         [ $(lustre_version_code $SINGLEMGS) -lt $(version_code 2.6.90) ] &&
1477                 skip "Skip test on $(get_lustre_version) MGS, need 2.6.90+" &&
1478                 return
1479
1480         rc=0
1481         create_fops_nodemaps
1482         rc=$?
1483         [[ $rc != 0 ]] && error "adding fops nodemaps failed $rc"
1484
1485         if [ "$active_nodemap" == "0" ]; then
1486                 do_facet mgs $LCTL set_param nodemap.active=0
1487                 do_facet ost0 $LCTL set_param nodemap.active=0
1488                 return
1489         fi
1490
1491         do_facet mgs $LCTL nodemap_activate 1
1492         do_facet ost0 $LCTL set_param nodemap.active=1
1493         do_facet mgs $LCTL nodemap_modify --name default \
1494                 --property admin --value 1
1495         do_facet mgs $LCTL nodemap_modify --name default \
1496                 --property trusted --value 1
1497         do_facet ost0 $LCTL set_param nodemap.default.admin_nodemap=1
1498         do_facet ost0 $LCTL set_param nodemap.default.trusted_nodemap=1
1499 }
1500
1501 nodemap_test_cleanup() {
1502         delete_fops_nodemaps
1503         rc=$?
1504         [[ $rc != 0 ]] && error "removing fops nodemaps failed $rc"
1505
1506         return 0
1507 }
1508
1509 nodemap_clients_admin_trusted() {
1510         local admin=$1
1511         local tr=$2
1512         local i=0
1513         for client in $clients; do
1514                 do_facet mgs $LCTL nodemap_modify --name c0 \
1515                         --property admin --value $admin
1516                 do_facet ost0 $LCTL set_param nodemap.c${i}.admin_nodemap=$admin
1517                 do_facet mgs $LCTL nodemap_modify --name c0 \
1518                         --property trusted --value $tr
1519                 do_facet ost0 $LCTL set_param nodemap.c${i}.trusted_nodemap=$tr
1520                 i=$((i + 1))
1521         done
1522 }
1523
1524 test_16() {
1525         nodemap_test_setup 0
1526
1527         test_fops all_off
1528         nodemap_test_cleanup
1529 }
1530 run_test 16 "test nodemap all_off fileops"
1531
1532 test_17() {
1533         nodemap_test_setup
1534
1535         nodemap_clients_admin_trusted 0 1
1536         test_fops trusted_noadmin 1
1537         nodemap_test_cleanup
1538 }
1539 run_test 17 "test nodemap trusted_noadmin fileops"
1540
1541 test_18() {
1542         nodemap_test_setup
1543         nodemap_clients_admin_trusted 0 0
1544         test_fops mapped_noadmin 1
1545         nodemap_test_cleanup
1546 }
1547 run_test 18 "test nodemap mapped_noadmin fileops"
1548
1549 test_19() {
1550         nodemap_test_setup
1551         nodemap_clients_admin_trusted 1 1
1552         test_fops trusted_admin 1
1553         nodemap_test_cleanup
1554 }
1555 run_test 19 "test nodemap trusted_admin fileops"
1556
1557 test_20() {
1558         nodemap_test_setup
1559         nodemap_clients_admin_trusted 1 0
1560         test_fops mapped_admin 1
1561         nodemap_test_cleanup
1562 }
1563 run_test 20 "test nodemap mapped_admin fileops"
1564
1565 test_21() {
1566         nodemap_test_setup
1567         local x=1
1568         local i=0
1569         for client in $clients; do
1570                 do_facet mgs $LCTL nodemap_modify --name c${i} \
1571                         --property admin --value 0
1572                 do_facet mgs $LCTL nodemap_modify --name c${i} \
1573                         --property trusted --value $x
1574                 do_facet ost0 $LCTL set_param nodemap.c${i}.admin_nodemap=0
1575                 do_facet ost0 $LCTL set_param nodemap.c${i}.trusted_nodemap=$x
1576                 x=0
1577                 i=$((i + 1))
1578         done
1579         test_fops mapped_trusted_noadmin
1580         nodemap_test_cleanup
1581 }
1582 run_test 21 "test nodemap mapped_trusted_noadmin fileops"
1583
1584 test_22() {
1585         nodemap_test_setup
1586         local x=1
1587         local i=0
1588         for client in $clients; do
1589                 do_facet mgs $LCTL nodemap_modify --name c${i} \
1590                         --property admin --value 1
1591                 do_facet mgs $LCTL nodemap_modify --name c${i} \
1592                         --property trusted --value $x
1593                 do_facet ost0 $LCTL set_param nodemap.c${i}.admin_nodemap=1
1594                 do_facet ost0 $LCTL set_param nodemap.c${i}.trusted_nodemap=$x
1595                 x=0
1596                 i=$((i + 1))
1597         done
1598         test_fops mapped_trusted_admin
1599         nodemap_test_cleanup
1600 }
1601 run_test 22 "test nodemap mapped_trusted_admin fileops"
1602
1603 # acl test directory needs to be initialized on a privileged client
1604 nodemap_acl_test_setup() {
1605         local admin=$(do_facet mgs $LCTL get_param -n nodemap.c0.admin_nodemap)
1606         local trust=$(do_facet mgs $LCTL get_param -n \
1607                 nodemap.c0.trusted_nodemap)
1608
1609         do_facet mgs $LCTL nodemap_modify --name c0 --property admin --value 1
1610         do_facet mgs $LCTL nodemap_modify --name c0 --property trusted --value 1
1611         do_facet ost0 $LCTL set_param nodemap.c0.admin_nodemap=1
1612         do_facet ost0 $LCTL set_param nodemap.c0.trusted_nodemap=1
1613
1614         do_node ${clients_arr[0]} rm -rf $DIR/$tdir
1615         do_node ${clients_arr[0]} mkdir -p $DIR/$tdir
1616         do_node ${clients_arr[0]} chmod a+rwx $DIR/$tdir
1617
1618         do_facet mgs $LCTL nodemap_modify --name c0 \
1619                 --property admin --value $admin
1620         do_facet mgs $LCTL nodemap_modify --name c0 \
1621                 --property trusted --value $trust
1622         do_facet ost0 $LCTL set_param nodemap.c0.admin_nodemap=$admin
1623         do_facet ost0 $LCTL set_param nodemap.c0.trusted_nodemap=$trust
1624
1625 }
1626
1627 # returns 0 if the number of ACLs does not change on the second (mapped) client
1628 # after being set on the first client
1629 nodemap_acl_test() {
1630         local user="$1"
1631         local set_client="$2"
1632         local get_client="$3"
1633         local check_setfacl="$4"
1634         local setfacl_error=0
1635         local testfile=$DIR/$tdir/$tfile
1636         local RUNAS_USER="$RUNAS_CMD -u $user"
1637         local acl_count=0
1638         local acl_count_post=0
1639
1640         nodemap_acl_test_setup
1641         sleep 5
1642
1643         do_node $set_client $RUNAS_USER touch $testfile
1644
1645         # ACL masks aren't filtered by nodemap code, so we ignore them
1646         acl_count=$(do_node $get_client getfacl $testfile | grep -v mask |
1647                 wc -l)
1648         do_node $set_client $RUNAS_USER setfacl -m $user:rwx $testfile ||
1649                 setfacl_error=1
1650
1651         # if check setfacl is set to 1, then it's supposed to error
1652         if [ "$check_setfacl" == "1" ]; then
1653                 [ "$setfacl_error" != "1" ] && return 1
1654                 return 0
1655         fi
1656         [ "$setfacl_error" == "1" ] && echo "WARNING: unable to setfacl"
1657
1658         acl_count_post=$(do_node $get_client getfacl $testfile | grep -v mask |
1659                 wc -l)
1660         [ $acl_count -eq $acl_count_post ] && return 0
1661         return 1
1662 }
1663
1664 test_23() {
1665         nodemap_test_setup
1666
1667         # 1 trusted cluster, 1 mapped cluster
1668         local unmapped_fs=$((IDBASE+0))
1669         local unmapped_c1=$((IDBASE+5))
1670         local mapped_fs=$((IDBASE+2))
1671         local mapped_c0=$((IDBASE+4))
1672         local mapped_c1=$((IDBASE+6))
1673
1674         do_facet mgs $LCTL nodemap_modify --name c0 --property admin --value 1
1675         do_facet mgs $LCTL nodemap_modify --name c0 --property trusted --value 1
1676         do_facet ost0 $LCTL set_param nodemap.c0.admin_nodemap=1
1677         do_facet ost0 $LCTL set_param nodemap.c0.trusted_nodemap=1
1678
1679         do_facet mgs $LCTL nodemap_modify --name c1 --property admin --value 0
1680         do_facet mgs $LCTL nodemap_modify --name c1 --property trusted --value 0
1681         do_facet ost0 $LCTL set_param nodemap.c1.admin_nodemap=0
1682         do_facet ost0 $LCTL set_param nodemap.c1.trusted_nodemap=0
1683
1684         # setfacl on trusted cluster to unmapped user, verify it's not seen
1685         nodemap_acl_test $unmapped_fs ${clients_arr[0]} ${clients_arr[1]} ||
1686                 error "acl count (1)"
1687
1688         # setfacl on trusted cluster to mapped user, verify it's seen
1689         nodemap_acl_test $mapped_fs ${clients_arr[0]} ${clients_arr[1]} &&
1690                 error "acl count (2)"
1691
1692         # setfacl on mapped cluster to mapped user, verify it's seen
1693         nodemap_acl_test $mapped_c1 ${clients_arr[1]} ${clients_arr[0]} &&
1694                 error "acl count (3)"
1695
1696         # setfacl on mapped cluster to unmapped user, verify error
1697         nodemap_acl_test $unmapped_fs ${clients_arr[1]} ${clients_arr[0]} 1 ||
1698                 error "acl count (4)"
1699
1700         # 2 mapped clusters
1701         do_facet mgs $LCTL nodemap_modify --name c0 --property admin --value 0
1702         do_facet mgs $LCTL nodemap_modify --name c0 --property trusted --value 0
1703         do_facet ost0 $LCTL set_param nodemap.c0.admin_nodemap=0
1704         do_facet ost0 $LCTL set_param nodemap.c0.trusted_nodemap=0
1705
1706         # setfacl to mapped user on c1, also mapped to c0, verify it's seen
1707         nodemap_acl_test $mapped_c1 ${clients_arr[1]} ${clients_arr[0]} &&
1708                 error "acl count (5)"
1709
1710         # setfacl to mapped user on c1, not mapped to c0, verify not seen
1711         nodemap_acl_test $unmapped_c1 ${clients_arr[1]} ${clients_arr[0]} ||
1712                 error "acl count (6)"
1713
1714         nodemap_test_cleanup
1715 }
1716 run_test 23 "test mapped ACLs"
1717
1718 log "cleanup: ======================================================"
1719
1720 sec_unsetup() {
1721         ## nodemap deactivated
1722         do_facet mgs lctl nodemap_activate 0
1723
1724         for num in $(seq $MDSCOUNT); do
1725                 if [ "${identity_old[$num]}" = 1 ]; then
1726                         switch_identity $num false || identity_old[$num]=$?
1727                 fi
1728         done
1729
1730         $RUNAS_CMD -u $ID0 ls $DIR
1731         $RUNAS_CMD -u $ID1 ls $DIR
1732 }
1733 sec_unsetup
1734
1735 sec_cleanup
1736
1737 complete $SECONDS
1738 exit_status