Whamcloud - gitweb
LU-1193 tests: test script fixes for incompatibility
[fs/lustre-release.git] / lustre / tests / recovery-double-scale.sh
1 #!/bin/bash
2 # vim:expandtab:shiftwidth=4:softtabstop=4:tabstop=4:
3
4 # All pairwise combinations of node failures.
5 # Was cmd3-17
6 #
7 # Author: Chris Cooper <ccooper@clusterfs.com>
8 #
9 # Script fails pair of nodes:
10 # --  in parallel by default
11 # --  in series if SERIAL is set
12 set -e
13
14 ONLY=${ONLY:-"$*"}
15
16 # bug number for skipped test:
17 ALWAYS_EXCEPT="$RECOVERY_DOUBLE_SCALE_EXCEPT"
18 # UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
19
20 LUSTRE=${LUSTRE:-$(cd $(dirname $0)/..; echo $PWD)}
21 . $LUSTRE/tests/test-framework.sh
22 init_test_env $@
23 . ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh}
24 init_logging
25
26 remote_mds_nodsh && skip_env "remote MDS with nodsh" && exit 0
27 remote_ost_nodsh && skip_env "remote OST with nodsh" && exit 0
28
29 [ -z "$CLIENTS" -o $CLIENTCOUNT -lt 3 ] &&
30     skip_env "need three or more clients" && exit 0
31
32 if [ -z "$SHARED_DIRECTORY" ] || ! check_shared_dir $SHARED_DIRECTORY; then
33     skip_env "SHARED_DIRECTORY should be specified with a shared directory \
34 which is accessable on all of the nodes"
35     exit 0
36 fi
37
38 [[ $FAILURE_MODE = SOFT ]] && \
39     log "WARNING: $0 is not functional with FAILURE_MODE = SOFT, bz22797"
40
41 # Set SERIAL to serialize the failure through a recovery of the first failure.
42 SERIAL=${SERIAL:-""}
43 ERRORS_OK="yes"
44
45 [ "$SERIAL" ] && ERRORS_OK=""
46
47 FAILOVER_PERIOD=${FAILOVER_PERIOD:-$((60 * 5))} # 5 minutes
48
49 END_RUN_FILE=${END_RUN_FILE:-$SHARED_DIRECTORY/end_run_file}
50 LOAD_PID_FILE=${LOAD_PID_FILE:-$TMP/client-load.pid}
51
52 reboot_recover_node () {
53     # item var contains a pair of clients if nodetype=clients
54     # I would prefer to have a list here
55     local item=$1
56     local nodetype=$2
57     local c
58
59     # MDS, OST item contains the facet
60     case $nodetype in
61         MDS|OST )   facet_failover $item
62                     [ "$SERIAL" ] && wait_recovery_complete $item || true
63                     ;;
64         clients)    for c in ${item//,/ }; do
65                         # make sure the client loads die
66                         stop_process $c $LOAD_PID_FILE
67                         shutdown_client $c
68                         boot_node $c
69                         echo "Reintegrating $c"
70                         zconf_mount $c $MOUNT ||
71                             error "mount $MOUNT on $c failed"
72                         client_up $c || error "start client on $c failed"
73                     done
74                     start_client_loads $item
75                     ;;
76         * )         echo "ERROR: invalid nodetype=$nodetype." \
77                          "Must be one of 'MDS', 'OST', or 'clients'."
78                     exit 1;;
79     esac
80 }
81
82 get_item_type () {
83     local type=$1
84     local excluded=${2:-""}
85
86     local list
87     case $type in
88        MDS )    list=$MDTS;;
89        OST )    list=$OSTS;;
90        clients) list=$NODES_TO_USE;;
91        * )      echo "ERROR: invalid type=$type." \
92                      "Must be one of 'MDS', 'OST', or 'clients'."
93                 exit 1;;
94     esac
95
96     [ "$excluded" ] && list=$(exclude_items_from_list $list $excluded)
97     # empty list
98     if [ ! "$(echo $list)" ]; then
99         echo
100         return
101     fi
102
103     local item=$(get_random_entry $list)
104     if [ "$type" = "clients" ]; then
105         item="$item $(get_random_entry $(exclude_items_from_list $list $item))"
106         item=$(comma_list $item)
107     fi
108     echo $item
109 }
110
111 # failover_pair
112 #
113 # for the two nodetypes specified, chooses a random node(s) from each
114 # class, reboots the nodes sequentially, and then restarts lustre on
115 # the nodes.
116 failover_pair() {
117     local type1=$1
118     local type2=$2
119     local title=$3
120
121     local client_nodes=""
122     local item1=
123     local item2=
124     local client1=
125     local client2=
126
127     log "
128 ==== START === $title"
129
130     item1=$(get_item_type $type1)
131     [ "$item1" ] || \
132         { echo "type1=$type1 item1 is empty" && return 0; }
133     item2=$(get_item_type $type2 $item1)
134     [ "$item2" ] || \
135         { echo "type1=$type1 item1=$item1 type2=$type2 item2=$item2 is empty" \
136           && return 0; }
137
138     # Check that our client loads are still running. If any have died,
139     # that means they have died outside of recovery, which is unacceptable.
140     log "==== Checking the clients loads BEFORE failover -- failure NOT OK"
141     # FIXME. need print summary on exit
142     check_client_loads $NODES_TO_USE || exit $?
143
144     log "Done checking client loads. Failing type1=$type1 item1=$item1 ... "
145     reboot_recover_node $item1 $type1 || exit $?
146
147     # Hendrix test17 description:
148     # Introduce a failure, wait at
149     # least 5 minutes (for recovery),
150     # introduce a 2nd
151     # failure, and wait another 5
152     # minutes
153
154     # reboot_recover_node waits recovery in according to
155     # SERIAL value.
156     # We have a "double failures" if SERIAL is not set,
157     # do not need a sleep between failures for "double failures"
158
159     log "                            Failing type2=$type2 item2=$item2 ... "
160     reboot_recover_node $item2 $type2 || exit $?
161
162     # Client loads are allowed to die while in recovery, so we just
163     # restart them.
164     log "==== Checking the clients loads AFTER failovers -- ERRORS_OK=$ERRORS_OK"
165     restart_client_loads $NODES_TO_USE $ERRORS_OK || exit $?
166     log "Done checking / re-starting client loads. PASS"
167     return 0
168 }
169
170 summary_and_cleanup () {
171     local rc=$?
172     trap 0
173
174     CURRENT_TS=$(date +%s)
175     ELAPSED=$((CURRENT_TS - START_TS))
176
177     # Having not empty END_RUN_FILE means the failed loads only
178     if [ -s $END_RUN_FILE ]; then
179         print_end_run_file $END_RUN_FILE
180         rc=1
181     fi
182
183     echo $(date +'%F %H:%M:%S') Terminating clients loads ...
184     echo "$0" >> $END_RUN_FILE
185     local result=PASS
186     [ $rc -eq 0 ] || result=FAIL
187
188     log "
189 Server failover period: $FAILOVER_PERIOD seconds
190 Exited after:           $ELAPSED seconds
191 Status: $result: rc=$rc"
192
193     # stop the client loads
194     stop_client_loads $NODES_TO_USE $LOAD_PID_FILE
195
196     if [ $rc -ne 0 ]; then
197         # we are interested in only on failed clients and servers
198         local failedclients=$(cat $END_RUN_FILE | grep -v $0)
199         # FIXME: need ostfailover-s nodes also for FLAVOR=OST
200         gather_logs $(comma_list $(osts_nodes) $(mdts_nodes) \
201                       $mdsfailover_HOST $failedclients)
202     fi
203
204     exit $rc
205 }
206
207 ################################## Main Flow ###################################
208 build_test_filter
209
210 check_and_setup_lustre
211 rm -rf $DIR/[Rdfs][0-9]*
212
213 check_timeout || exit 1
214
215 # The test node needs to be insulated from a lustre failure as much as possible,
216 # so not even loading the lustre modules is ideal.
217 # -- umount lustre
218 # -- remove hostname from clients list
219 zconf_umount $HOSTNAME $MOUNT
220 NODES_TO_USE=${NODES_TO_USE:-$CLIENTS}
221 NODES_TO_USE=$(exclude_items_from_list $NODES_TO_USE $HOSTNAME)
222
223 check_progs_installed $NODES_TO_USE ${CLIENT_LOADS[@]}
224
225 MDTS=$(get_facets MDS)
226 OSTS=$(get_facets OST)
227
228 ELAPSED=0
229 START_TS=$(date +%s)
230 CURRENT_TS=$START_TS
231
232 # Every pairwise combination of client failures (2 clients),
233 # MDS failure, and OST failure will be tested.
234 test_pairwise_fail() {
235     trap summary_and_cleanup EXIT TERM INT
236
237     # Start client loads.
238     rm -f $END_RUN_FILE
239     start_client_loads $NODES_TO_USE
240
241     echo clients load pids:
242     do_nodesv $NODES_TO_USE "cat $LOAD_PID_FILE" || exit 3
243
244     # FIXME: Do we want to have an initial sleep period where the clients
245     # just run before introducing a failure?
246     sleep $FAILOVER_PERIOD
247
248     # CMD_TEST_NUM=17.1
249     failover_pair MDS OST "test 1: failover MDS, then OST =========="
250     sleep $FAILOVER_PERIOD
251
252     # CMD_TEST_NUM=17.2
253     failover_pair MDS clients "test 2: failover MDS, then 2 clients ===="
254     sleep $FAILOVER_PERIOD
255
256     # CMD_TEST_NUM=17.3
257     if [ $MDSCOUNT -gt 1 ]; then
258         failover_pair MDS MDS "test 3: failover MDS, then another MDS =="
259         sleep $FAILOVER_PERIOD
260     else
261         skip_env "has less than 2 MDTs, test 3 skipped"
262     fi
263
264     # CMD_TEST_NUM=17.4
265     if [ $OSTCOUNT -gt 1 ]; then
266         failover_pair OST OST "test 4: failover OST, then another OST =="
267         sleep $FAILOVER_PERIOD
268     else
269         skip_env "has less than 2 OSTs, test 4 skipped"
270     fi
271
272     # CMD_TEST_NUM=17.5
273     failover_pair OST clients "test 5: failover OST, then 2 clients ===="
274     sleep $FAILOVER_PERIOD
275
276     # CMD_TEST_NUM=17.6
277     failover_pair OST MDS "test 6: failover OST, then MDS =========="
278     sleep $FAILOVER_PERIOD
279
280     # CMD_TEST_NUM=17.7
281     failover_pair clients MDS "test 7: failover 2 clients, then MDS ===="
282     sleep $FAILOVER_PERIOD
283
284     # CMD_TEST_NUM=17.8
285     failover_pair clients OST "test 8: failover 2 clients, then OST ===="
286     sleep $FAILOVER_PERIOD
287
288     # CMD_TEST_NUM=17.9
289     if [ $CLIENTCOUNT -gt 4 ]; then
290         failover_pair clients clients \
291             "test 9: failover 2 clients, then 2 different clients =="
292         sleep $FAILOVER_PERIOD
293     else
294         skip_env "has less than 5 Clients, test 9 skipped"
295     fi
296
297     log "==== Checking the clients loads AFTER all failovers -- failure NOT OK"
298     if ! check_client_loads $NODES_TO_USE; then
299         log "Client load failed after failover. Exiting..."
300         exit 5
301     fi
302
303     exit 0
304 }
305 run_test pairwise_fail "pairwise combination of clients, MDS, and OST failures"
306
307 zconf_mount $HOSTNAME $MOUNT || error "mount $MOUNT on $HOSTNAME failed"
308 client_up || error "start client on $HOSTNAME failed"
309
310 complete $(basename $0) $SECONDS
311 check_and_cleanup_lustre
312 exit_status