Whamcloud - gitweb
4676026148d3a3c1dc4187adf32c0e25ef3c036e
[fs/lustre-release.git] / contrib / scripts / pacemaker / healthLNET
1 #!/bin/sh
2 #
3 #
4 #       LNet OCF RA
5 #
6
7
8 # License:      GNU General Public License (GPL)v2
9 # Description:  Manages ZFS and Lustre on a shared storage
10 # Written by:   Gabriele Paciucci
11 # Release Date: 01 November 2016
12 # Release Version: 0.99.4
13
14 # Copyright (c) 2009 Andrew Beekhof
15 # Copyright (c) 2016, Intel Corporation
16
17
18 #
19 # This program is free software; you can redistribute it and/or modify
20 # it under the terms of version 2 of the GNU General Public License as
21 # published by the Free Software Foundation.
22 #
23 # This program is distributed in the hope that it would be useful, but
24 # WITHOUT ANY WARRANTY; without even the implied warranty of
25 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
26 #
27 # Further, this software is distributed without any warranty that it is
28 # free of the rightful claim of any third person regarding infringement
29 # or the like.  Any license provided herein, whether implied or
30 # otherwise, applies only to this software file.  Patent licenses, if
31 # any, provided herein do not apply to combinations of this program with
32 # other software, or any other product whatsoever.
33 #
34 # You should have received a copy of the GNU General Public License
35 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
36 #
37
38 #######################################################################
39 # Initialization:
40
41 : ${OCF_FUNCTIONS=${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs}
42 . ${OCF_FUNCTIONS}
43 : ${__OCF_ACTION=$1}
44
45 #######################################################################
46
47 meta_data() {
48         cat <<END
49 <?xml version="1.0"?>
50 <!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
51 <resource-agent name="healthLNET">
52 <version>0.99.4</version>
53
54 <longdesc lang="en">
55 Every time the monitor action is run, this resource agent records (in the CIB)
56 the current number of lctl ping nodes the host can connect to.
57 </longdesc>
58 <shortdesc lang="en">LNet connectivity</shortdesc>
59
60 <parameters>
61
62 <parameter name="pidfile" unique="0">
63 <longdesc lang="en">PID file</longdesc>
64 <shortdesc lang="en">PID file</shortdesc>
65 <content type="string" default="$HA_VARRUN/ping-${OCF_RESOURCE_INSTANCE}" />
66 </parameter>
67
68 <parameter name="dampen" unique="0">
69 <longdesc lang="en">
70 The time to wait (dampening) further changes occur
71 </longdesc>
72 <shortdesc lang="en">Dampening interval</shortdesc>
73 <content type="integer" default="5s"/>
74 </parameter>
75
76 <parameter name="name" unique="0">
77 <longdesc lang="en">
78 The name of the attributes to set.  This is the name to be used in the constraints.
79 </longdesc>
80 <shortdesc lang="en">Attribute name</shortdesc>
81 <content type="string" default="pingd"/>
82 </parameter>
83
84 <parameter name="multiplier" unique="0">
85 <longdesc lang="en">
86 The number by which to multiply the number of connected ping nodes by
87 </longdesc>
88 <shortdesc lang="en">Value multiplier</shortdesc>
89 <content type="integer" default=""/>
90 </parameter>
91
92 <parameter name="host_list" unique="0" required="1">
93 <longdesc lang="en">
94 The list of ping nodes to count.
95 </longdesc>
96 <shortdesc lang="en">Host list</shortdesc>
97 <content type="string" default=""/>
98 </parameter>
99
100 <parameter name="attempts" unique="0">
101 <longdesc lang="en">
102 Number of ping attempts, per host, before declaring it dead
103 </longdesc>
104 <shortdesc lang="en">no. of ping attempts</shortdesc>
105 <content type="integer" default="2"/>
106 </parameter>
107
108 <parameter name="timeout" unique="0">
109 <longdesc lang="en">
110 How long, in seconds, to wait before declaring a ping lost
111 </longdesc>
112 <shortdesc lang="en">ping timeout in seconds</shortdesc>
113 <content type="integer" default="2"/>
114 </parameter>
115
116 <parameter name="lctl" unique="0">
117 <longdesc lang="en">
118 Option to enable lctl ping. The default is true
119 </longdesc>
120 <shortdesc lang="en">Extra Options</shortdesc>
121 <content type="string" default="true"/>
122 </parameter>
123
124 <parameter name="device" unique="0">
125 <longdesc lang="en">
126 Device used for the LNET network. We assume the same device accross the cluster
127 </longdesc>
128 <shortdesc lang="en">LNET device</shortdesc>
129 <content type="string" default=""/>
130 </parameter>
131
132
133 <parameter name="options" unique="0">
134 <longdesc lang="en">
135 A catch all for any other options that need to be passed to ping.
136 </longdesc>
137 <shortdesc lang="en">Extra Options</shortdesc>
138 <content type="string" default=""/>
139 </parameter>
140
141 <parameter name="failure_score" unique="0">
142 <longdesc lang="en">
143 Resource is failed if the score is less than failure_score.
144 Default never fails.
145 </longdesc>
146 <shortdesc lang="en">failure_score</shortdesc>
147 <content type="integer" default=""/>
148 </parameter>
149
150 <parameter name="debug" unique="0">
151 <longdesc lang="en">
152 Enables to use default attrd_updater verbose logging on every call.
153 </longdesc>
154 <shortdesc lang="en">Verbose logging</shortdesc>
155 <content type="string" default="false"/>
156 </parameter>
157
158 </parameters>
159
160 <actions>
161 <action name="start"   timeout="300s" />
162 <action name="stop"    timeout="300s" />
163 <action name="reload"  timeout="300s" />
164 <action name="monitor" depth="0"  timeout="300s" interval="20s"/>
165 <action name="meta-data"  timeout="5" />
166 <action name="validate-all"  timeout="30" />
167 </actions>
168 </resource-agent>
169 END
170 }
171
172 #######################################################################
173
174 ping_conditional_log() {
175         level=$1; shift
176         if [ ${OCF_RESKEY_debug} = "true" ]; then
177                 ocf_log $level "$*"
178         fi
179 }
180
181 ping_usage() {
182         cat <<END
183         usage: $0 {start|stop|monitor|migrate_to|migrate_from|validate-all|meta-data}
184
185         Expects to have a fully populated OCF RA-compliant environment set.
186 END
187 }
188
189 ping_start() {
190     ping_monitor
191     if [ $? =  $OCF_SUCCESS ]; then
192         return $OCF_SUCCESS
193     fi
194     touch ${OCF_RESKEY_pidfile}
195     ping_update
196 }
197
198 ping_stop() {
199
200         rm -f ${OCF_RESKEY_pidfile}
201         attrd_updater -D -n $OCF_RESKEY_name -d $OCF_RESKEY_dampen $attrd_options
202         return $OCF_SUCCESS
203 }
204
205 ping_monitor() {
206     if [ -f ${OCF_RESKEY_pidfile} ]; then
207         ping_update
208         if [ $? -eq 0 ]; then
209             return $OCF_SUCCESS
210         fi
211         return $OCF_ERR_GENERIC
212     fi
213     return $OCF_NOT_RUNNING
214 }
215
216 ping_validate() {
217         # Is the state directory writable?
218         state_dir=`dirname "$OCF_RESKEY_pidfile"`
219         touch "$state_dir/$$"
220         if [ $? != 0 ]; then
221                 ocf_log err "Invalid location for 'state': $state_dir is not writable"
222                 return $OCF_ERR_ARGS
223         fi
224         rm "$state_dir/$$"
225
226 # Pidfile better be an absolute path
227     case $OCF_RESKEY_pidfile in
228         /*) ;;
229         *) ocf_log warn "You should use an absolute path for pidfile not: $OCF_RESKEY_pidfile" ;;
230     esac
231
232 # Check the host list
233         if [ "x" = "x$OCF_RESKEY_host_list" ]; then
234                 ocf_log err "Empty host_list.  Please specify some nodes to ping"
235                 exit $OCF_ERR_CONFIGURED
236         fi
237
238         check_binary ping
239
240         return $OCF_SUCCESS
241 }
242
243 lctl_check() {
244         active=0
245         for host in $OCF_RESKEY_host_list; do
246             lctl_exe="lctl ping"
247
248             lctl_out=`$lctl_exe $host $OCF_RESKEY_timeout 2>&1`; rc=$?
249             # debug
250             # ocf_log info "$lctl_exe $host $OCF_RESKEY_timeout"
251
252             case $rc in
253                 0) active=`expr $active + 1`;;
254                 1) ping_conditional_log warn "$host is inactive: $lctl_out";;
255                 *) ocf_log err "Unexpected result for '$lctl_exe $host $OCF_RESKEY_timeout' $rc: $p_out";;
256         esac
257         done
258         return $active
259
260
261 }
262
263
264
265 ping_check() {
266         active=0
267         for host in $OCF_RESKEY_host_list; do
268                 p_exe=ping
269
270                 case `uname` in
271                     Linux) p_args="-n -q -W $OCF_RESKEY_timeout -c $OCF_RESKEY_attempts";;
272                     Darwin) p_args="-n -q -t $OCF_RESKEY_timeout -c $OCF_RESKEY_attempts -o";;
273                     *) ocf_log err "Unknown host type: `uname`"; exit $OCF_ERR_INSTALLED;;
274                 esac
275
276                 case $host in
277                     *:*) p_exe=ping6
278                 esac
279
280                 p_out=`$p_exe $p_args $OCF_RESKEY_options $host 2>&1`; rc=$?
281
282                 case $rc in
283                     0) active=`expr $active + 1`;;
284                     1) ping_conditional_log warn "$host is inactive: $p_out";;
285                     *) ocf_log err "Unexpected result for '$p_exe $p_args $OCF_RESKEY_options $host' $rc: $p_out";;
286                 esac
287         done
288         return $active
289 }
290
291 ping_update() {
292         # first I'm testing if I have the physical link up.
293         # If not I give up without any additional tests.
294         # but first we need to find which is the device we are using on the localhost.
295
296         CARRIER=/sys/class/net/$OCF_RESKEY_device/carrier
297         OPERSTATE=/sys/class/net/$OCF_RESKEY_device/operstate
298
299         CAR_STAT=$(cat $CARRIER)
300         OPER_STAT=$(cat $OPERSTATE)
301
302         # debug
303         # ocf_log info "$CAR_STAT - $OPER_STAT"
304
305
306         if [ "$CAR_STAT" == "1" ] && [ "$OPER_STAT" == "up" ]; then
307                 if [ ${OCF_RESKEY_lctl} = "true" ]; then
308                         lctl_check
309                         active=$?
310                 else
311                         ping_check
312                         active=$?
313                 fi
314         else
315                 active=0
316         fi
317
318         # debug
319         # ocf_log info "$active"
320
321         score=`expr $active \* $OCF_RESKEY_multiplier`
322         attrd_updater -n $OCF_RESKEY_name -v $score -d $OCF_RESKEY_dampen $attrd_options
323         rc=$?
324         case $rc in
325                 0) ping_conditional_log debug "Updated $OCF_RESKEY_name = $score" ;;
326                 *) ocf_log warn "Could not update $OCF_RESKEY_name = $score: rc=$rc";;
327         esac
328         if [ $rc -ne 0 ]; then
329             return $rc
330         fi
331         if [ $score -eq 0 ]; then
332                  ocf_log err "LNet connection failed please check"
333         fi
334         if [ -n "$OCF_RESKEY_failure_score" -a "$score" -lt "$OCF_RESKEY_failure_score" ]; then
335             ocf_log warn "$OCF_RESKEY_name is less than failure_score($OCF_RESKEY_failure_score)"
336             return 1
337         fi
338         return 0
339 }
340
341 : ${OCF_RESKEY_name:="pingd"}
342 : ${OCF_RESKEY_dampen:="5s"}
343 : ${OCF_RESKEY_attempts:="3"}
344 : ${OCF_RESKEY_multiplier:="1"}
345 : ${OCF_RESKEY_debug:="false"}
346 : ${OCF_RESKEY_lctl:="true"}
347 #: ${OCF_RESKEY_device:="eth1"}
348 : ${OCF_RESKEY_failure_score:="0"}
349
350 : ${OCF_RESKEY_CRM_meta_timeout:="20000"}
351 : ${OCF_RESKEY_CRM_meta_globally_unique:="true"}
352
353 integer=`echo ${OCF_RESKEY_timeout} | egrep -o '[0-9]*'`
354 case ${OCF_RESKEY_timeout} in
355     *[0-9]ms|*[0-9]msec) OCF_RESKEY_timeout=`expr $integer / 1000`;;
356     *[0-9]m|*[0-9]min) OCF_RESKEY_timeout=`expr $integer \* 60`;;
357     *[0-9]h|*[0-9]hr)  OCF_RESKEY_timeout=`expr $integer \* 60 \* 60`;;
358     *) OCF_RESKEY_timeout=$integer;;
359 esac
360
361 if [ -z ${OCF_RESKEY_timeout} ]; then
362         if [ x"$OCF_RESKEY_host_list" != x ]; then
363                 host_count=`echo $OCF_RESKEY_host_list | awk '{print NF}'`
364                 OCF_RESKEY_timeout=`expr $OCF_RESKEY_CRM_meta_timeout / $host_count / $OCF_RESKEY_attempts`
365                 OCF_RESKEY_timeout=`expr $OCF_RESKEY_timeout / 1100` # Convert to seconds and finish 10% early
366         else
367                 OCF_RESKEY_timeout=5
368         fi
369 fi
370
371 if [ ${OCF_RESKEY_timeout} -lt 1 ]; then
372         OCF_RESKEY_timeout=5
373         elif [ ${OCF_RESKEY_timeout} -gt 1000 ]; then
374                 # ping actually complains if this value is too high, 5 minutes is plenty
375                 OCF_RESKEY_timeout=300
376 fi
377
378 if [ ${OCF_RESKEY_CRM_meta_globally_unique} = "false" ]; then
379         : ${OCF_RESKEY_pidfile:="$HA_VARRUN/ping-${OCF_RESKEY_name}"}
380 else
381         : ${OCF_RESKEY_pidfile:="$HA_VARRUN/ping-${OCF_RESOURCE_INSTANCE}"}
382 fi
383
384 attrd_options='-q'
385 if ocf_is_true ${OCF_RESKEY_debug} ; then
386         attrd_options=''
387 fi
388
389 # Check the debug option
390 case "${OCF_RESKEY_debug}" in
391         true|True|TRUE|1)    OCF_RESKEY_debug=true;;
392         false|False|FALSE|0) OCF_RESKEY_debug=false;;
393         *)
394         ocf_log warn "Value for 'debug' is incorrect. Please specify 'true' or 'false' not: ${OCF_RESKEY_debug}"
395         OCF_RESKEY_debug=false
396         ;;
397 esac
398
399 case $__OCF_ACTION in
400 meta-data)      meta_data
401                 exit $OCF_SUCCESS
402                 ;;
403 start)          ping_start;;
404 stop)           ping_stop;;
405 monitor)        ping_monitor;;
406 reload)         ping_start;;
407 validate-all)   ping_validate;;
408 usage|help)     ping_usage
409                 exit $OCF_SUCCESS
410                 ;;
411 *)              ping_usage
412                 exit $OCF_ERR_UNIMPLEMENTED
413                 ;;
414 esac