summaryrefslogtreecommitdiffstats
path: root/heartbeat/pound
blob: 48aa2218399abfcd3582b7c63c0c55ecfb10638a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
#!/bin/sh
#
#
# Pound
#
# Description:  Manage pound instances as a HA resource
#
# Author:       Taro Matsuzawa <btm@tech.email.ne.jp>
#
# License:      GNU General Public License (GPL)
#
# See usage() for more details
#
# OCF instance parameters:
#   OCF_RESKEY_pid
#   OCF_RESKEY_binary
#   OCF_RESKEY_ctl_binary
#   OCF_RESKEY_socket_path
#   OCF_RESKEY_config
#   OCF_RESKEY_name
#   OCF_RESKEY_maxfiles
#
#######################################################################
# Initialization:
: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs

#######################################################################
# Set default paramenter values

# Set these two first, as other defaults depend on it
OCF_RESKEY_name_default=${OCF_RESOURCE_INSTANCE}
: ${OCF_RESKEY_name=${OCF_RESKEY_name_default}}

OCF_RESKEY_config_default=""
OCF_RESKEY_binary_default=pound
OCF_RESKEY_ctl_binary_default=poundctl
OCF_RESKEY_pid_default=/var/run/pound_${OCF_RESKEY_name}.pid
OCF_RESKEY_socket_path_default=/var/lib/pound/pound.cfg
OCF_RESKEY_maxfiles_default=""

: ${OCF_RESKEY_config=${OCF_RESKEY_config_default}}
: ${OCF_RESKEY_binary=${OCF_RESKEY_binary_default}}
: ${OCF_RESKEY_ctl_binary=${OCF_RESKEY_ctl_binary_default}}
: ${OCF_RESKEY_pid=${OCF_RESKEY_pid_default}}
: ${OCF_RESKEY_socket_path=${OCF_RESKEY_socket_path_default}}
: ${OCF_RESKEY_maxfiles=${OCF_RESKEY_maxfiles_default}}

meta_data() {
	cat <<END
<?xml version="1.0"?>
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
<resource-agent name="pound" version="1.0">
<version>1.0</version>

<longdesc lang="en">
The Pound Resource Agent can manage Pound instances.
</longdesc>
<shortdesc lang="en">Manage a Pound instance</shortdesc>

<parameters>

<parameter name="config" unique="1" required="1">
<longdesc lang="en">
The Pound configuration file that Pound should manage, for example
"/etc/pound.cfg".
</longdesc>
<shortdesc lang="en">Pound configuration file</shortdesc>
<content type="string" default="${OCF_RESKEY_config_default}" />
</parameter>

<parameter name="name" unique="1">
<longdesc lang="en">
Override the name of the instance that should be given to Pound
(defaults to the resource identifier).
</longdesc>
<shortdesc lang="en">Instance name</shortdesc>
<content type="string" default="${OCF_RESKEY_name_default}" />
</parameter>

<parameter name="pid" unique="1">
<longdesc lang="en">
Write the process's PID to the specified file.
The default will include the specified name, i.e.:
"/var/run/pound_production.pid". Unlike what this help message shows,
it is most likely not necessary to change this parameter.
</longdesc>
<shortdesc lang="en">Pidfile</shortdesc>
<content type="string" default="${OCF_RESKEY_pid_default}" />
</parameter>

<parameter name="binary">
<longdesc lang="en">
This is used to start Pound server.
Normally use pound.
</longdesc>
<shortdesc lang="en"></shortdesc>
<content type="string" default="${OCF_RESKEY_binary_default}" />
</parameter>

<parameter name="ctl_binary">
<longdesc lang="en">
This is used to watch Pound status via Unix socket.
Normally use poundctl.
</longdesc>
<shortdesc lang="en"></shortdesc>
<content type="string" default="${OCF_RESKEY_ctl_binary_default}" />
</parameter>

<parameter name="socket_path">
<longdesc lang="en">
Write the process's Unix socket.
This parameter is same 'Control' parameter in configuration file, i.e.:
Control "/var/lib/pound/pound.cfg".
</longdesc>
<shortdesc lang="en"></shortdesc>
<content type="string" default="${OCF_RESKEY_socket_path_default}" />
</parameter>

<parameter name="maxfiles">
<longdesc lang="en">
Determines how many files pound is allowed to open at
a time. Helps to fix the 'Too many open files' error message.
</longdesc>
<shortdesc lang="en">Allowed number of open files.</shortdesc>
<content type="integer" default="${OCF_RESKEY_maxfiles_default}" />
</parameter>

</parameters>

<actions>
<action name="start"        timeout="20s" />
<action name="stop"         timeout="20s" />
<action name="monitor"      timeout="20s" interval="10s" depth="0" />
<action name="status"       timeout="20s" />
<action name="meta-data"    timeout="5s" />
<action name="validate-all"   timeout="20s" />
</actions>
</resource-agent>
END
}

#######################################################################


pound_usage() {
	cat <<END
usage: $0 {start|stop|monitor|validate-all|meta-data}

Expects to have a fully populated OCF RA-compliant environment set.
END
}

pound_status() {
    local pid
    local rc

    # FAILED = pidfile exist, but no running proc (or mismatch pid)
    # SUCCES = contents of pidfile == running process id
    # NOTRUN = no pidfile, no running process

    # check if pidfile exists and larger than 0 bytes
    if [ -s $OCF_RESKEY_pid ]; then
        # it does, now check if the pid exists
        pid=$(cat $OCF_RESKEY_pid)
        ocf_run kill -s 0 $pid
        rc=$?
        if [ $rc -eq 0 ]; then
            ocf_log info "Pound is running"
            # check if the poundctl
            ocf_run $OCF_RESKEY_ctl_binary -c $OCF_RESKEY_socket_path
            p_rc=$?
            if [ "$p_rc" -eq 0 ]; then
                ocf_log info "poundctl reports success"
                return $OCF_SUCCESS
            else
                ocf_log err "poundctl reports error"
                return $OCF_ERR_GENERIC
            fi
        else
            ocf_log err "Pound PID file exists, but pound is not running"
            return $OCF_ERR_GENERIC
        fi
    fi
    
    return $OCF_NOT_RUNNING
}

pound_start() {
    local rc
    local backend_options

    pound_status
    rc=$?
    if [ $rc -eq $OCF_SUCCESS ]; then
        ocf_log info "Pound already running"
        return $OCF_SUCCESS
    fi

    # check configuration before start
    ocf_run $OCF_RESKEY_binary \
        -c -f $OCF_RESKEY_config
    c_rc=$?
    if [ "$c_rc" -ne 0 ]; then
        ocf_log err "Pound configuration file is not valid"
        return $OCF_ERR_CONFIGURED
    fi 

    if [ -n "$OCF_RESKEY_maxfiles" ]; then
        ulimit -n $OCF_RESKEY_maxfiles
        u_rc=$?
        if [ "$u_rc" -ne 0 ]; then
           ocf_log warn "Could not set ulimit for open files for Pound to '$OCF_RESKEY_maxfiles'"
        fi
    fi

    ocf_run $OCF_RESKEY_binary \
        -f $OCF_RESKEY_config \
        -p $OCF_RESKEY_pid
    rc=$?
    if [ $rc -ne 0 ]; then
        ocf_log err "Pound failed to start"
        return $OCF_ERR_GENERIC
    fi

    # Spin waiting for pound to come up.
    # Let the CRM/LRM time us out if required
    while true; do
        pound_status
        rc=$?
        [ $rc -eq $OCF_SUCCESS ] && break
        if [ $rc -ne $OCF_NOT_RUNNING ]; then
            ocf_log err "Pound start failed"
            exit $OCF_ERR_GENERIC
        fi
        sleep 2
    done

    ocf_log info "Pound started succesfully"
    return $OCF_SUCCESS
}

pound_stop() {
    local rc
    local pid

    pound_status
    rc=$?
    if [ $rc -eq $OCF_NOT_RUNNING ]; then
        ocf_log info "Pound already stopped"
        return $OCF_SUCCESS
    fi

    # kill the pound process
    pid=$(cat $OCF_RESKEY_pid)
    ocf_run kill -s 0 $pid
    rc=$?

    if [ $rc -ne 0 ]; then
        ocf_log warn "Pound pid is not a valid process. Assume it is already stopped"
        rm -f $OCF_RESKEY_pid
        return $OCF_SUCCESS
    fi

    ocf_run kill -s TERM $pid
    rc=$?

    if [ $rc -ne 0 ]; then
        ocf_log err "Pound failed to stop"
        return $OCF_ERR_GENERIC
    fi

    # stop waiting
    shutdown_timeout=$((($OCF_RESKEY_CRM_meta_timeout/1000)-5))
    count=0
    while [ $count -lt $shutdown_timeout ]; do
        # check if process still exists
        ocf_run kill -s 0 $pid
        rc=$?
        if [ $rc -ne 0 ]; then
            # Pound stopped succesfully, so let's delete the pidfile
            rm -f $OCF_RESKEY_pid
            break
        fi
        count=$(expr $count + 1)
        sleep 1
        ocf_log info "Pound still hasn't stopped yet. Waiting..."
    done 

    pound_status
    rc=$?
    if [ $rc -ne $OCF_NOT_RUNNING ]; then
        # Poound didn't quit on a SIGTERM, try SIGKILL
        ocf_log warn "Pound failed to stop after ${shutdown_timeout}s using SIGTERM. Trying SIGKILL..."
        ocf_run kill -s KILL $pid
        # delete the pidfile
        rm -f $OCF_RESKEY_pid
    fi

    ocf_log info "Pound stopped"
    return $OCF_SUCCESS
}


pound_validate() {
    if [ -f $OCF_RESKEY_config ]; then
        return $OCF_SUCCESS
    else
        return $OCF_ERR_INSTALLED
    fi
}


case $__OCF_ACTION in
    meta-data)
        meta_data
        exit $OCF_SUCCESS
        ;;
    start)
        pound_start
        ;;
    stop)
        pound_stop
        ;;
    monitor|status)
        pound_status
        ;;
    validate-all)
        pound_validate
        ;;
    usage|help)
        pound_usage
        exit $OCF_SUCCESS
        ;;
    *)
        pound_usage
        exit $OCF_ERR_UNIMPLEMENTED
        ;;
esac
rc=$?
ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc"
exit $rc