Whamcloud - gitweb
LU-6142 tests: Fix style issues for mkdirmany.c
[fs/lustre-release.git] / lustre / tests / setup_kerberos.sh
1 #!/bin/bash
2 # -*- mode: Bash; tab-width: 4; indent-tabs-mode: t; -*-
3 # vim:shiftwidth=4:softtabstop=4:tabstop=4:
4
5 #
6 # setup_kerberos.sh - setup the Kerberos environment on Lustre cluster
7 #
8 # Notes:
9 #  * Only one KDC involved, no slave KDC.
10 #  * Only one Kerberos realm involved, no multiple Kerberos realms.
11 #
12 ###############################################################################
13
14 # usage
15 my_usage() {
16     cat <<EOF
17 Usage: $(basename $0) <KDC_distro> <KDC_node> <MGS_node> <MDS_node>[:MDS_node:...]
18                       <OSS_node>[:OSS_node:...] <CLIENT_node>[:CLIENT_node:...]
19
20     This script is used to setup the Kerberos environment on Lustre cluster.
21
22     KDC_distro      distribution on the KDC node (rhel5 or sles10)
23     KDC_node        KDC node name
24     MGS_node        Lustre MGS node name
25     MDS_node        Lustre MDS node name
26     OSS_node        Lustre OSS node name
27     CLIENT_node     Lustre client node name
28
29     e.g.: $(basename $0) rhel5 scsi2 scsi2 sata2 sata3 client5
30     e.g.: $(basename $0) sles10 scsi2 scsi2 scsi2 sata3:sata5 client2:client3
31     e.g.: $(basename $0) rhel5 scsi2 scsi2 scsi2 scsi2 scsi2
32
33     Notes:
34     1) The script will destroy all the old Kerberos settings by default. If you
35     want to reserve the original krb5.conf and KDC configuration, please set
36     "RESET_KDC=false".
37
38     2) The script will create principals for some runas users and add them into
39     the Kerberos database by default. The UIDs of the runas users specified in
40     "LOCAL_UIDS" variable need exist on KDC, MDS and Client nodes. If you do not
41     need runas users, please set "CFG_RUNAS=false".
42
43 EOF
44 }
45
46 # ************************ Parameters and Variables ************************ #
47 MY_KDC_DISTRO=$1
48 MY_KDCNODE=$2
49 MY_MGSNODE=$3
50 MY_MDSNODES=$4
51 MY_OSSNODES=$5
52 MY_CLIENTNODES=$6
53
54 # translate to lower case letters
55 MY_KDC_DISTRO=$(echo $MY_KDC_DISTRO | tr '[A-Z]' '[a-z]')
56
57 if [ -z "$MY_KDC_DISTRO" -o -z "$MY_KDCNODE" -o -z "$MY_MDSNODES" -o \
58     -z "$MY_OSSNODES" -o -z "$MY_CLIENTNODES" -o -z "$MY_MGSNODE" ]; then
59     my_usage
60     exit 1
61 fi
62
63 LUSTRE=${LUSTRE:-$(cd $(dirname $0)/..; echo $PWD)}
64 . $LUSTRE/tests/test-framework.sh
65 init_test_env
66 . ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh}
67
68 SCP=${SCP:-"scp -q"}
69 ACCEPTOR_PORT=${ACCEPTOR_PORT:-988}
70
71 # check and configure runas users
72 CFG_RUNAS=${CFG_RUNAS:-true}
73 # uids for local users
74 LOCAL_UIDS=${LOCAL_UIDS:-"500 501"}
75
76 # remove the original Kerberos and KDC settings
77 RESET_KDC=${RESET_KDC:-true}
78
79 # generate unique keytab for each client node
80 SPLIT_KEYTAB=${SPLIT_KEYTAB:-true}
81
82 # encryption types for generating keytab
83 MDS_ENCTYPE=${MDS_ENCTYPE:-"aes128-cts"}
84 MGS_ENCTYPE=${MGS_ENCTYPE:-"$MDS_ENCTYPE"}
85 OSS_ENCTYPE=${OSS_ENCTYPE:-"aes128-cts"}
86 CLIENT_ENCTYPE=${CLIENT_ENCTYPE:-"aes128-cts"}
87
88 # configuration file for Kerberos
89 KRB5_CONF=${KRB5_CONF:-"/etc/krb5.conf"}
90 KRB5_KEYTAB=${KRB5_KEYTAB:-"/etc/krb5.keytab"}
91 KRB5_TICKET_LIFETIME=${KRB5_TICKET_LIFETIME:-"24h"}
92
93 # configuration files for libgssapi and keyutils
94 GSSAPI_MECH_CONF=${GSSAPI_MECH_CONF:-"/etc/gssapi_mech.conf"}
95 REQUEST_KEY_CONF=${REQUEST_KEY_CONF:-"/etc/request-key.conf"}
96
97 # krb5 realm & domain
98 KRB5_REALM=${KRB5_REALM:-"CO.CFS"}
99 KRB5_DOMAIN=$(echo $KRB5_REALM | tr '[A-Z]' '[a-z]')
100
101 MY_MDSNODES=${MY_MDSNODES//:/ }
102 MY_OSSNODES=${MY_OSSNODES//:/ }
103 MY_CLIENTNODES=${MY_CLIENTNODES//:/ }
104
105 # set vars according to the KDC distribution
106 KRB5PKG_SVR="krb5-server"
107 KRB5PKG_DEV="krb5-devel"
108 case $MY_KDC_DISTRO in
109     rhel5)
110         KRB5PKG_CLI="krb5-workstation"
111         KRB5PKG_LIB="krb5-libs"
112         KDC_CONF_DIR="/var/kerberos/krb5kdc"
113         ;;
114     sles10)
115         KRB5PKG_CLI="krb5-client"
116         KRB5PKG_LIB="krb5"
117         KDC_CONF_DIR="/var/lib/kerberos/krb5kdc"
118         ;;
119     *)
120         echo "Unsupported KDC distro: $MY_KDC_DISTRO!"
121         exit 1
122 esac
123 KDC_CONF="$KDC_CONF_DIR/kdc.conf"
124 KDC_ACL="$KDC_CONF_DIR/kadm5.acl"
125
126 # ******************************** Functions ******************************** #
127 is_part_of() {
128     local name="$1"
129     shift
130     local list="$@"
131
132     if [ -z "$name" -o -z "$list" ]; then
133         false
134         return
135     fi
136
137     if [[ " $list " == *\ $name\ * ]]; then
138         true
139     else
140         false
141     fi
142
143     return
144 }
145
146 my_do_node() {
147     local node=$1
148     shift
149     local nodename=${node%.$KRB5_DOMAIN}
150     do_node $node "PATH=\$PATH:/usr/kerberos/sbin:/usr/kerberos/bin:\
151 /usr/lib/mit/sbin:/usr/lib/mit/bin $@" | sed "s/^${nodename}: //"
152     return ${PIPESTATUS[0]}
153 }
154
155 do_node_mute() {
156     local output
157     output=$(my_do_node "$@" 2>&1)
158     return ${PIPESTATUS[0]}
159 }
160
161 do_kdc() {
162     my_do_node $MY_KDCNODE "$@"
163     return ${PIPESTATUS[0]}
164 }
165
166 do_kdc_mute() {
167     do_node_mute $MY_KDCNODE "$@"
168     return ${PIPESTATUS[0]}
169 }
170
171 #
172 # convert a space-delimited node name list to a canonical name list
173 #
174 get_fqdn() {
175     local nodename_list="$@"
176     local fqdn_list=""
177     local name
178     local fqdn
179     local rc
180
181     for name in $nodename_list; do
182         fqdn=$(do_kdc "gethostip -n $name 2>&1")
183         rc=${PIPESTATUS[0]}
184         if [ $rc -ne 0 ]; then
185             echo "Can not get the FQDN of node $name: $fqdn"
186             return $rc
187         fi
188         [ -z "$fqdn_list" ] && fqdn_list="$fqdn" \
189         || fqdn_list="$fqdn_list $fqdn"
190
191     done
192
193     echo "$fqdn_list"
194     return 0
195 }
196
197 #
198 # convert MDS/OSS nodes to their canonical name, it required by
199 # kerberos. we also convert kdc and client too in order to make
200 # node name comparison easier
201 #
202 normalize_names() {
203     local rc
204
205     # KDC
206     MY_KDCNODE=$(get_fqdn $MY_KDCNODE)
207     rc=${PIPESTATUS[0]}
208     if [ $rc -ne 0 ]; then
209         echo $MY_KDCNODE
210         return $rc
211     fi
212
213     # MGS node
214     MY_MGSNODE=$(get_fqdn $MY_MGSNODE)
215     rc=${PIPESTATUS[0]}
216     if [ $rc -ne 0 ]; then
217         echo $MY_MGSNODE
218         return $rc
219     fi
220
221     # MDS nodes
222     MY_MDSNODES=$(get_fqdn $MY_MDSNODES)
223     rc=${PIPESTATUS[0]}
224     if [ $rc -ne 0 ]; then
225         echo $MY_MDSNODES
226         return $rc
227     fi
228
229     # OSS nodes
230     MY_OSSNODES=$(get_fqdn $MY_OSSNODES)
231     rc=${PIPESTATUS[0]}
232     if [ $rc -ne 0 ]; then
233         echo $MY_OSSNODES
234         return $rc
235     fi
236
237     # client nodes
238     MY_CLIENTNODES=$(get_fqdn $MY_CLIENTNODES)
239     rc=${PIPESTATUS[0]}
240     if [ $rc -ne 0 ]; then
241         echo $MY_CLIENTNODES
242         return $rc
243     fi
244
245     return 0
246 }
247
248 #
249 # verify remote shell works on all nodes
250 #
251 check_rsh() {
252     local checked=""
253     local node
254
255     echo "+++ Checking remote shell"
256
257     for node in $MY_KDCNODE $MY_MGSNODE $MY_OSSNODES $MY_MDSNODES $MY_CLIENTNODES
258     do
259         is_part_of $node $checked && continue
260
261         echo -n "Checking remote shell on $node..."
262         do_node_mute $node true || return ${PIPESTATUS[0]}
263         echo "OK!"
264
265         checked="$checked $node"
266     done
267 }
268
269 #
270 # verify the entropy (random numbers) on the KDC node, which is
271 # used by kdb5_util to create Kerberos database
272 #
273 check_entropy() {
274     local limit=170
275     local avail
276
277     echo "+++ Checking the entropy on the KDC"
278
279     echo -n "Checking $MY_KDCNODE..."
280     avail=$(do_kdc "sysctl -n kernel.random.entropy_avail")
281     local rc=${PIPESTATUS[0]}
282     if [ $rc -eq 0 ]; then
283         if [ $avail -lt $limit ]; then
284             echo -e "\nWarning: The entropy on the KDC node is only $avail, \
285 which is not enough for kdb5_util to create Kerberos database! \
286 Let's use /dev/urandom!"
287             do_kdc "rm -f /dev/random.bak && mv /dev/random{,.bak} && \
288 mknod /dev/random c 1 9"
289             return ${PIPESTATUS[0]}
290         fi
291     else
292         echo "Can not get the entropy on the KDC node!"
293         return $rc
294     fi
295     echo "OK!"
296 }
297
298 #
299 # verify runas users and groups
300 #
301 check_users() {
302     local checked=""
303     local node
304     local id
305     local user
306
307     echo "+++ Checking users and groups"
308
309     for node in $MY_KDCNODE $MY_MGSNODE $MY_MDSNODES $MY_CLIENTNODES; do
310         is_part_of $node $checked && continue
311
312         for id in $LOCAL_UIDS; do
313             echo -n "Checking uid/gid $id/$id on $node..."
314             user=$(my_do_node $node getent passwd | grep :$id:$id: | cut -d: -f1)
315             if [ -z "$user" ]; then
316                                 echo -e "\nPlease set LOCAL_UIDS to some users \
317 which exist on KDC, MDS and client or add user/group $id/$id on these nodes."
318                 return 1
319             fi
320             echo "OK!"
321         done
322         checked="$checked $node"
323     done
324 }
325
326 cfg_mount() {
327     local node=$1
328     local dev=$2
329     local dir=$3
330
331     echo -n "Checking $dev mount on $node..."
332     if do_node_mute $node "grep -q $dir' ' /proc/mounts"; then
333         echo "OK!"
334         return 0
335     fi
336
337     if ! do_node_mute $node "grep -q ^$dev /etc/fstab"; then
338         my_do_node $node "echo '$dev $dir $dev defaults 0 0' >> /etc/fstab" || \
339             return ${PIPESTATUS[0]}
340     fi
341     my_do_node $node "mkdir -p $dir && mount $dir" || true
342
343     if ! do_node_mute $node "grep -q $dir' ' /proc/mounts"; then
344         echo "Failed to mount fs $dev at $dir!"
345         return 1
346     fi
347     echo "OK!"
348 }
349
350 #
351 # configure nfsd mount on MDS and OSS nodes
352 #
353 cfg_nfs_mount() {
354     local checked=""
355     local node
356
357     echo "+++ Configuring nfsd mount"
358
359     for node in $MY_MGSNODE $MY_OSSNODES $MY_MDSNODES; do
360         is_part_of $node $checked && continue
361         cfg_mount $node nfsd /proc/fs/nfsd || return ${PIPESTATUS[0]}
362         checked="$checked $node"
363     done
364 }
365
366 get_pkgname() {
367     local node=$1
368     local pkg=$2
369
370     my_do_node $node "rpm -q $pkg 2>&1" | tail -n1
371     return ${PIPESTATUS[0]}
372 }
373
374 get_krb5pkgname() {
375     local node=$1
376     local flavor=$2
377
378     my_do_node $node cat /etc/SuSE-release 2>/dev/null | \
379     grep -q 'Enterprise Server 10'
380     if [ ${PIPESTATUS[1]} -eq 0 ]; then
381         case $flavor in
382             cli) echo "krb5-client";;
383             lib) echo "krb5";;
384         esac
385     else
386         case $flavor in
387             cli) echo "krb5-workstation";;
388             lib) echo "krb5-libs";;
389         esac
390     fi
391 }
392
393 check_kdc() {
394     local pkg
395     local rc
396
397     echo "+++ Checking KDC installation"
398
399     echo -n "Checking $MY_KDCNODE..."
400     pkg=$(get_pkgname $MY_KDCNODE $KRB5PKG_SVR)
401     rc=${PIPESTATUS[0]}
402     if [ $rc -ne 0 ]; then
403         echo -e "\nCan not find $KRB5PKG_SVR package on $MY_KDCNODE: $pkg"
404         return $rc
405     fi
406     echo "OK!"
407 }
408
409 check_krb5() {
410     local checked=""
411     local pkg
412     local rc
413     local krb5pkg_cli
414
415     echo "+++ Checking Kerberos 5 installation"
416     for node in $MY_MGSNODE $MY_OSSNODES $MY_MDSNODES $MY_CLIENTNODES; do
417         is_part_of $node $checked && continue
418
419         echo -n "Checking $node..."
420         krb5pkg_cli=$(get_krb5pkgname $node cli)
421
422         pkg=$(get_pkgname $node $krb5pkg_cli)
423         rc=${PIPESTATUS[0]}
424         if [ $rc -ne 0 ]; then
425             echo -e "\nCan not find $krb5pkg_cli package on $node: $pkg"
426             return $rc
427         fi
428         echo "OK!"
429         checked="$checked $node"
430     done
431 }
432
433 check_libgssapi() {
434     local checked=""
435     local node
436     local pkg
437     local rc
438
439     echo "+++ Checking libgssapi installation"
440
441     LIBGSSAPI=$(get_pkgname $MY_KDCNODE libgssapi)
442     rc=${PIPESTATUS[0]}
443     if [ $rc -ne 0 ]; then
444         echo "Can not find libgssapi package on $MY_KDCNODE: $LIBGSSAPI"
445         return $rc
446     fi
447
448     for node in $MY_MGSNODE $MY_OSSNODES $MY_MDSNODES $MY_CLIENTNODES; do
449         is_part_of $node $checked && continue
450
451         echo -n "Checking $node..."
452         pkg=$(get_pkgname $node libgssapi)
453         rc=${PIPESTATUS[0]}
454         if [ $rc -ne 0 ]; then
455             echo -e "\nCan not find libgssapi package on $node: $pkg"
456             return $rc
457         fi
458         echo "OK!"
459         checked="$checked $node"
460     done
461 }
462
463 #
464 # check and update the /etc/gssapi_mech.conf file on each node
465 # We only support MIT Kerberos 5 GSS-API mechanism.
466 #
467 cfg_libgssapi() {
468     local checked=""
469     local node
470     local pkg
471     local rc
472     local krb5pkg_lib
473     local krb5_lib 
474
475     echo "+++ Updating $GSSAPI_MECH_CONF"
476
477     for node in $MY_KDCNODE $MY_MGSNODE $MY_OSSNODES $MY_MDSNODES $MY_CLIENTNODES
478     do
479         is_part_of $node $checked && continue
480
481         krb5pkg_lib=$(get_krb5pkgname $node lib)
482         pkg=$(get_pkgname $node $krb5pkg_lib)
483         rc=${PIPESTATUS[0]}
484         if [ $rc -ne 0 ]; then
485             echo -e "\nCan not find $krb5pkg_lib package on $node: $pkg"
486             return $rc
487         fi
488
489         krb5_lib=$(my_do_node $node "rpm -ql $pkg" | \
490                     grep libgssapi_krb5.so | head -n1)
491
492         if ! do_node_mute $node \
493 "egrep -q \\\"^$krb5_lib|^$(basename $krb5_lib)\\\" $GSSAPI_MECH_CONF"; then
494             do_node_mute $node \
495 "echo '$krb5_lib mechglue_internal_krb5_init' >> $GSSAPI_MECH_CONF"
496         fi
497         checked="$checked $node"
498     done
499     echo "OK!"
500 }
501
502 #
503 # check and update the /etc/request-key.conf file on each MDS and client node
504 #
505 cfg_keyutils() {
506     local checked=""
507     local node
508     local lgss_keyring
509
510     echo "+++ Updating $REQUEST_KEY_CONF"
511
512     for node in $MY_OSSNODES $MY_MDSNODES $MY_CLIENTNODES; do
513         is_part_of $node $checked && continue
514         lgss_keyring=$(my_do_node $node "which lgss_keyring") || \
515             return ${PIPESTATUS[0]}
516
517         if ! do_node_mute $node \
518 "grep -q \\\"^create.*$lgss_keyring\\\" $REQUEST_KEY_CONF"; then
519             do_node_mute $node \
520 "echo 'create lgssc * * $lgss_keyring %o %k %t %d %c %u %g %T %P %S' \
521 >> $REQUEST_KEY_CONF"
522         fi
523         checked="$checked $node"
524     done
525     echo "OK!"
526 }
527
528 add_svc_princ() {
529     local fqdn=$1
530     local type=$2
531
532     echo -n "Creating service principal lustre_$type/$fqdn@$KRB5_REALM..."
533     do_kdc_mute "kadmin.local -r $KRB5_REALM <<EOF
534 addprinc -randkey lustre_$type/$fqdn@$KRB5_REALM
535 EOF"
536     local rc=${PIPESTATUS[0]}
537     [ $rc -ne 0 ] && echo "Failed!" || echo "OK!"
538
539     return $rc
540 }
541
542 add_svc_princ_root() {
543     echo -n "Creating service principal lustre_root@$KRB5_REALM..."
544     do_kdc_mute "kadmin.local -r $KRB5_REALM <<EOF
545 addprinc -randkey lustre_root@$KRB5_REALM
546 EOF"
547     local rc=${PIPESTATUS[0]}
548     [ $rc -ne 0 ] && echo "Failed!" || echo "OK!"
549
550     return $rc
551 }
552
553 add_user_princ() {
554     local user=$1
555
556     echo -n "Creating user principal $user@$KRB5_REALM..."
557     do_kdc_mute "kadmin.local -r $KRB5_REALM <<EOF
558 addprinc -pw $user $user@$KRB5_REALM
559 EOF"
560     local rc=${PIPESTATUS[0]}
561     [ $rc -ne 0 ] && echo "Failed!" || echo "OK!"
562
563     return $rc
564 }
565
566 add_test_princ_id() {
567     local id=$1
568     local user
569
570     user=$(do_kdc getent passwd $id | cut -d: -f1)
571     if [ -z "$user" ]; then
572         echo "Can not find the user with uid $id on the KDC!"
573         return 1
574     fi
575
576     add_user_princ $user || return ${PIPESTATUS[0]}
577 }
578
579 #
580 # create principals for the client, MDS, OSS, runas users and add them to 
581 # the Kerberos database
582 #
583 cfg_kdc_princs() {
584     local node
585
586     add_svc_princ $MY_MGSNODE mgs || return ${PIPESTATUS[0]}
587
588     for node in $MY_MDSNODES; do
589         add_svc_princ $node mds || return ${PIPESTATUS[0]}
590     done
591
592     for node in $MY_OSSNODES; do
593         add_svc_princ $node oss || return ${PIPESTATUS[0]}
594     done
595
596     for node in $MY_CLIENTNODES; do
597         if $SPLIT_KEYTAB; then
598             add_svc_princ $node root || return ${PIPESTATUS[0]}
599         else
600             add_svc_princ_root || return ${PIPESTATUS[0]}
601         fi
602     done
603
604     if ! $SPLIT_KEYTAB; then 
605         add_user_princ lustre_root || return ${PIPESTATUS[0]}
606     fi
607     add_user_princ bin || return ${PIPESTATUS[0]}
608     add_user_princ daemon || return ${PIPESTATUS[0]}
609     add_user_princ games || return ${PIPESTATUS[0]}
610
611     if $CFG_RUNAS; then
612         for uid in $LOCAL_UIDS; do
613             add_test_princ_id $uid || return ${PIPESTATUS[0]}
614         done
615     fi
616 }
617
618 #
619 # create and install the KDC configuration file kdc.conf on the KDC, which 
620 # will destroy the old KDC setting
621 #
622 cfg_kdc() {
623     local tmpdir="$TMP/krb5_cfg_tmp_$UID"
624     local tmpcfg=$tmpdir/kdc.conf
625     local tmpacl=$tmpdir/kadm5.acl
626
627     echo "+++ Configuring KDC on $MY_KDCNODE"
628     echo "Warning: old KDC setting on $MY_KDCNODE will be destroied!!!"
629
630     echo -n "Checking the existence of KDC config dir..."
631     do_kdc_mute "[ -d $KDC_CONF_DIR ]"
632     if [ ${PIPESTATUS[0]} -ne 0 ]; then
633         echo -e "\nUnrecognized krb5 distribution!"
634         return 1
635     else
636         echo "OK!"
637     fi
638
639     # stop KDC daemon
640     do_kdc_mute "/etc/init.d/krb5kdc stop < /dev/null" || true
641
642     echo -n "Removing old KDC configurations..."
643     do_kdc_mute "rm -f $KDC_CONF_DIR/*"
644     echo "OK!"
645
646     # create kdc.conf locally
647     rm -rf $tmpdir
648     mkdir -p $tmpdir || return ${PIPESTATUS[0]}
649     cat <<EOF > $tmpcfg
650 [kdcdefaults]
651  acl_file = $KDC_ACL
652
653 [realms]
654  $KRB5_REALM = {
655   master_key_type = aes128-cts
656   supported_enctypes = des3-hmac-sha1:normal aes128-cts:normal aes256-cts:normal des-cbc-md5:normal
657  }
658 EOF
659
660     # install kdc.conf remotely
661     echo -n "Installing kdc.conf on $MY_KDCNODE..."
662     $SCP $tmpcfg root@$MY_KDCNODE:$KDC_CONF || return ${PIPESTATUS[0]}
663     echo "OK!"
664
665     # initialize KDC database
666     echo -n "Creating Kerberos database on $MY_KDCNODE..."
667     do_kdc_mute "kdb5_util create -r $KRB5_REALM -s -P 111111"
668     local rc=${PIPESTATUS[0]}
669     if [ $rc -ne 0 ]; then
670         echo "Failed!"
671         return $rc
672     else
673         echo "OK!"
674     fi
675
676     # create ACL file locally & install remotely
677     cat <<EOF > $tmpacl
678 */admin@$KRB5_REALM   *
679 root@$KRB5_REALM      *
680 EOF
681     echo -n "Installing kadm5.acl on $MY_KDCNODE..."
682     $SCP $tmpacl root@$MY_KDCNODE:$KDC_ACL || return ${PIPESTATUS[0]}
683     echo "OK!"
684     rm -rf $tmpdir || true
685
686     # start KDC daemon
687     do_kdc "/etc/init.d/krb5kdc restart < /dev/null" || return ${PIPESTATUS[0]}
688 }
689
690 #
691 # create and install the Kerberos configuration file krb5.conf on the KDC, 
692 # client, MDS and OSS
693 #
694 cfg_krb5_conf() {
695     local tmpdir="$TMP/krb5_cfg_tmp_$UID"
696     local tmpcfg="$tmpdir/krb5.conf"
697     local checked=""
698
699     echo "+++ Installing krb5.conf on all nodes"
700
701     # create krb5.conf locally
702     rm -rf $tmpdir
703     mkdir -p $tmpdir || return ${PIPESTATUS[0]}
704     cat <<EOF > $tmpcfg
705 [libdefaults]
706  default_realm = $KRB5_REALM
707  dns_lookup_realm = false
708  dns_lookup_kdc = false
709  ticket_lifetime = $KRB5_TICKET_LIFETIME
710  forwardable = yes
711
712 [realms]
713  $KRB5_REALM = {
714   kdc = $MY_KDCNODE:88
715   admin_server = $MY_KDCNODE:749
716   default_domain = $KRB5_DOMAIN
717  }
718
719 [domain_realm]
720  .$KRB5_DOMAIN = $KRB5_REALM
721  $KRB5_DOMAIN = $KRB5_REALM
722
723 [kdc]
724  profile = $KDC_CONF
725
726 [appdefaults]
727  pam = {
728   debug = false
729   forwardable = true
730   krb4_convert = false
731  }
732 EOF
733
734     # install krb5.conf remotely
735     for node in $MY_KDCNODE $MY_MGSNODE $MY_OSSNODES $MY_MDSNODES $MY_CLIENTNODES
736     do
737         is_part_of $node $checked && continue
738
739         echo -n "Installing krb5.conf on $node..."
740         $SCP $tmpcfg root@$node:$KRB5_CONF || return ${PIPESTATUS[0]}
741         echo "OK!"
742
743         checked="$checked $node"
744     done
745     rm -rf $tmpdir || true
746 }
747
748 add_keytab() {
749     local tab=$1
750     local princ=$2
751     local enctype=$3
752
753     do_kdc_mute "kadmin.local -r $KRB5_REALM <<EOF
754 ktadd -k $tab -e $enctype:normal $princ@$KRB5_REALM
755 EOF"
756 }
757
758 add_keytab_svc() {
759     local tab=$1
760     local fqdn=$2
761     local type=$3
762     local enctype=$4
763
764     add_keytab $tab lustre_$type/$fqdn $enctype
765 }
766
767 add_keytab_root() {
768     local tab=$1
769     local enctype=$2
770
771     add_keytab $tab lustre_root $enctype
772 }
773
774 merge_keytab() {
775     local tab=$1
776     local node=$2
777
778     $SCP $tab root@$node:$tab || return ${PIPESTATUS[0]}
779     do_node_mute $node "ktutil <<EOF
780 rkt $tab
781 wkt $KRB5_KEYTAB
782 EOF" || return ${PIPESTATUS[0]}
783 }
784
785 #
786 # create and install the keytab file krb5.keytab on the client, MDS and OSS
787 #
788 cfg_keytab() {
789     local tmptab="$TMP/keytab.tmp"
790     local node
791
792     echo "+++ Generating keytabs"
793
794     # remove old keytabs
795     echo -n "Deleting old keytabs on all nodes..."
796     for node in $MY_MGSNODE $MY_OSSNODES $MY_MDSNODES $MY_CLIENTNODES; do
797         do_node_mute $node "rm -f $KRB5_KEYTAB $TMP/krb5cc*"
798     done
799     echo "OK!"
800
801     # install for MDS nodes
802     for node in $MY_MDSNODES; do
803         echo -n "Preparing for MDS $node..."
804         do_kdc_mute "rm -f $tmptab"
805         add_keytab_svc $tmptab $node mds $MDS_ENCTYPE || return ${PIPESTATUS[0]}
806
807         if is_part_of $node $MY_MGSNODE; then
808             echo -n "also be an MGS..."
809             add_keytab_svc $tmptab $node mgs $MGS_ENCTYPE || \
810                 return ${PIPESTATUS[0]}
811         fi
812
813         if is_part_of $node $MY_OSSNODES; then
814             echo -n "also be an OSS..."
815             add_keytab_svc $tmptab $node oss $OSS_ENCTYPE || \
816                 return ${PIPESTATUS[0]}
817         fi
818         echo "OK!"
819
820         echo -n "Installing krb5.keytab on $node..."
821         $SCP root@$MY_KDCNODE:$tmptab $tmptab || return ${PIPESTATUS[0]}
822         $SCP $tmptab root@$node:$KRB5_KEYTAB || return ${PIPESTATUS[0]}
823         echo "OK!"
824         rm -f $tmptab
825     done
826
827     # install for MGS node
828     echo -n "Preparing for MGS $MY_MGSNODE..."
829     if ! is_part_of $MY_MGSNODE $MY_MDSNODES; then
830         do_kdc_mute "rm -f $tmptab"
831         add_keytab_svc $tmptab $MY_MGSNODE mgs $MGS_ENCTYPE || \
832             return ${PIPESTATUS[0]}
833
834         if is_part_of $MY_MGSNODE $MY_OSSNODES; then
835             echo -n "also be an OSS..."
836             add_keytab_svc $tmptab $MY_MGSNODE oss $OSS_ENCTYPE || \
837                 return ${PIPESTATUS[0]}
838         fi
839         echo "OK!"
840
841         echo -n "Installing krb5.keytab on $MY_MGSNODE..."
842         $SCP root@$MY_KDCNODE:$tmptab $tmptab || return ${PIPESTATUS[0]}
843         $SCP $tmptab root@$MY_MGSNODE:$KRB5_KEYTAB || return ${PIPESTATUS[0]}
844         echo "OK!"
845         rm -f $tmptab
846     else
847         echo "also be an MDS, already done, skip"
848     fi
849
850     # install for OSS nodes
851     for node in $MY_OSSNODES; do
852         echo -n "Preparing for OSS $node..."
853         if is_part_of $node $MY_MDSNODES; then
854             echo "also be an MDS, already done, skip"
855         elif is_part_of $node $MY_MGSNODE; then
856             echo "also be an MGS, already done, skip"
857         else
858             do_kdc_mute "rm -f $tmptab"
859             add_keytab_svc $tmptab $node oss $OSS_ENCTYPE || \
860                 return ${PIPESTATUS[0]}
861             echo "OK!"
862
863             echo -n "Installing krb5.keytab on $node..."
864             $SCP root@$MY_KDCNODE:$tmptab $tmptab || return ${PIPESTATUS[0]}
865             $SCP $tmptab root@$node:$KRB5_KEYTAB || return ${PIPESTATUS[0]}
866             echo "OK!"
867             rm -f $tmptab
868         fi
869     done
870
871     # install for client nodes
872     do_kdc_mute "rm -f $tmptab"
873     if ! $SPLIT_KEYTAB; then
874         echo -n "Preparing for client..."
875         add_keytab_root $tmptab $CLIENT_ENCTYPE || return ${PIPESTATUS[0]}
876         $SCP root@$MY_KDCNODE:$tmptab $tmptab || return ${PIPESTATUS[0]}
877         echo "OK!"
878     else
879         for node in $MY_CLIENTNODES; do
880             echo -n "Preparing for client $node..."
881             # don't generate keytabs if it's also an MDS
882             if is_part_of $node $MY_MDSNODES; then
883                 echo "also be an MDS, already done, skip"
884                 continue
885             fi
886
887             add_keytab_svc $tmptab $node root $CLIENT_ENCTYPE || \
888                 return ${PIPESTATUS[0]}
889             $SCP root@$MY_KDCNODE:$tmptab $tmptab || return ${PIPESTATUS[0]}
890             echo "OK!"
891         done
892     fi
893     for node in $MY_CLIENTNODES; do
894         echo -n "Installing krb5.keytab on client $node..."
895
896         # don't install if it's also an MDS
897         if is_part_of $node $MY_MDSNODES; then
898             echo "also be an MDS, already done, skip"
899             continue
900         fi
901
902         # merge keytab if it's also an MGS
903         if is_part_of $node $MY_MGSNODE; then
904             echo -n "also be an MGS, merging keytab..."
905             merge_keytab $tmptab $node || return ${PIPESTATUS[0]}
906             echo "OK!"
907             continue 
908         fi
909
910         # merge keytab if it's also an OSS
911         if is_part_of $node $MY_OSSNODES; then
912             echo -n "also be an OSS, merging keytab..."
913             merge_keytab $tmptab $node || return ${PIPESTATUS[0]}
914             echo "OK!"
915             continue 
916         fi
917
918         # simply install otherwise
919         $SCP $tmptab root@$node:$KRB5_KEYTAB || return ${PIPESTATUS[0]}
920         echo "OK!"
921     done
922     rm -f $tmptab || true
923 }
924
925 check_acceptor_port() {
926     local node=$1
927     local port=$2
928
929     if [ -z "$port" ]; then
930         echo "Missing acceptor port!"
931         return 1
932     fi
933
934     local WAIT=0
935     local MAX_WAIT=300
936     while [ $WAIT -lt $MAX_WAIT ]; do
937         sleep 5
938         my_do_node $node "netstat -tpan" | grep -q ":$port .*TIME_WAIT"
939         if [ ${PIPESTATUS[1]} -ne 0 ]; then
940             return 0
941         fi
942         WAIT=$((WAIT + 5))
943     done
944
945     echo "LNET acceptor port $port is in use on node $node!"
946     return 2
947 }
948
949 get_client_nids() {
950     local client_nids=""
951     local node
952     local nid
953     local local_fqdn
954     local rc
955
956     # get the fqdn of the local host
957     local_fqdn=$(get_fqdn $HOSTNAME)
958     rc=${PIPESTATUS[0]}
959     if [ $rc -ne 0 ]; then
960         echo $local_fqdn
961         return $rc
962     fi
963
964     for node in $MY_CLIENTNODES; do
965         my_do_node $node lsmod | grep -q lnet || \
966         my_do_node $node "modprobe lnet" || {
967             if [ "$node" = "$local_fqdn" ]; then
968                 lsmod | grep -q lnet || load_modules
969             else
970                 echo "Failed to load lnet module on node $node!"
971                 return 1
972             fi
973         }
974
975         check_acceptor_port $node $ACCEPTOR_PORT || return ${PIPESTATUS[0]}
976
977         nid=$(set +x; my_do_node $node \
978 "$LCTL net up 1>/dev/null && $LCTL list_nids" 2>&1 | head -n1
979 exit ${PIPESTATUS[0]})
980         rc=${PIPESTATUS[0]}
981         if [ $rc -ne 0 ]; then
982             echo "Failed to get the nid for node $node: $nid"
983             return $rc
984         fi
985         [ -z "$client_nids" ] && client_nids="$nid" \
986         || client_nids="$client_nids $nid"
987
988         my_do_node $node "$LCTL net down 1>/dev/null" || true
989     done
990
991     echo "$client_nids"
992     return 0
993 }
994
995 # ******************************** Main Flow ******************************** #
996 normalize_names || exit ${PIPESTATUS[0]}
997 check_rsh || exit ${PIPESTATUS[0]}
998 check_entropy || exit ${PIPESTATUS[0]}
999
1000 if $CFG_RUNAS; then
1001     check_users || exit ${PIPESTATUS[0]}
1002 fi
1003
1004 check_kdc || exit ${PIPESTATUS[0]}
1005 check_krb5 || exit ${PIPESTATUS[0]}
1006 check_libgssapi || exit ${PIPESTATUS[0]}
1007
1008 echo "===================================================================="
1009 echo " Configure Kerberos testing environment for Lustre"
1010 echo " KDC: $MY_KDCNODE"
1011 echo " realm: $KRB5_REALM, domain: $KRB5_DOMAIN"
1012 echo " Using gssapi package: $LIBGSSAPI"
1013 echo " MGS node:"
1014 echo "     $MY_MGSNODE"
1015 echo " OSS nodes:"
1016 for i in $MY_OSSNODES; do echo "     $i"; done
1017 echo " MDS nodes:"
1018 for i in $MY_MDSNODES; do echo "     $i"; done
1019 echo " CLIENT nodes:"
1020 for i in $MY_CLIENTNODES; do echo "     $i"; done
1021 echo "===================================================================="
1022
1023 cfg_nfs_mount || exit ${PIPESTATUS[0]}
1024 cfg_libgssapi || exit ${PIPESTATUS[0]}
1025 cfg_keyutils || exit ${PIPESTATUS[0]}
1026
1027 if $RESET_KDC; then
1028     cfg_krb5_conf || exit ${PIPESTATUS[0]}
1029     cfg_kdc || exit ${PIPESTATUS[0]}
1030 fi
1031
1032 cfg_kdc_princs || exit ${PIPESTATUS[0]}
1033 cfg_keytab || exit ${PIPESTATUS[0]}
1034
1035 echo "Complete successfully!"