Merge branch 'stable-2.7' into stable-2.8
[ganeti-local] / daemons / daemon-util.in
1 #!/bin/bash
2 #
3
4 # Copyright (C) 2009, 2011, 2012 Google Inc.
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 # General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 # 02110-1301, USA.
20
21 set -e
22
23 @SHELL_ENV_INIT@
24
25 readonly defaults_file="$SYSCONFDIR/default/ganeti"
26
27 # This is a list of all daemons and the order in which they're started. The
28 # order is important as there are dependencies between them. On shutdown,
29 # they're stopped in reverse order.
30 DAEMONS=(
31   ganeti-noded
32   ganeti-masterd
33   ganeti-rapi
34   )
35
36 _confd_enabled() {
37   [[ "@CUSTOM_ENABLE_CONFD@" == True ]]
38 }
39
40 if _confd_enabled; then
41   DAEMONS+=( ganeti-confd )
42 fi
43
44 _mond_enabled() {
45   [[ "@CUSTOM_ENABLE_MOND@" == True ]]
46 }
47
48 if _mond_enabled; then
49   DAEMONS+=( ganeti-mond )
50 fi
51
52 NODED_ARGS=
53 MASTERD_ARGS=
54 CONFD_ARGS=
55 RAPI_ARGS=
56 MOND_ARGS=
57
58 # Read defaults file if it exists
59 if [[ -s $defaults_file ]]; then
60   . $defaults_file
61 fi
62
63 # Meant to facilitate use utilities in /etc/rc.d/init.d/functions in case
64 # start-stop-daemon is not available.
65 _ignore_error() {
66   eval "$@" || :
67 }
68
69 _daemon_pidfile() {
70   echo "$RUN_DIR/$1.pid"
71 }
72
73 _daemon_executable() {
74   echo "@PREFIX@/sbin/$1"
75 }
76
77 _daemon_usergroup() {
78   case "$1" in
79     masterd)
80       echo "@GNTMASTERUSER@:@GNTMASTERDGROUP@"
81       ;;
82     confd)
83       echo "@GNTCONFDUSER@:@GNTCONFDGROUP@"
84       ;;
85     rapi)
86       echo "@GNTRAPIUSER@:@GNTRAPIGROUP@"
87       ;;
88     noded)
89       echo "@GNTNODEDUSER@:@GNTDAEMONSGROUP@"
90       ;;
91     mond)
92       echo "@GNTMONDUSER@:@GNTMONDGROUP@"
93       ;;
94     *)
95       echo "root:@GNTDAEMONSGROUP@"
96       ;;
97   esac
98 }
99
100 # Checks whether the local machine is part of a cluster
101 check_config() {
102   local server_pem=$DATA_DIR/server.pem
103   local fname
104
105   for fname in $server_pem; do
106     if [[ ! -f $fname ]]; then
107       echo "Missing configuration file $fname" >&2
108       return 1
109     fi
110   done
111
112   return 0
113 }
114
115 # Checks the exit code of a daemon
116 check_exitcode() {
117   if [[ "$#" -lt 1 ]]; then
118     echo 'Missing exit code.' >&2
119     return 1
120   fi
121
122   local rc="$1"; shift
123
124   case "$rc" in
125     0) ;;
126     11)
127       echo "not master"
128     ;;
129     *)
130       echo "exit code $rc"
131       return 1
132     ;;
133   esac
134
135   return 0
136 }
137
138 # Prints path to PID file for a daemon.
139 daemon_pidfile() {
140   if [[ "$#" -lt 1 ]]; then
141     echo 'Missing daemon name.' >&2
142     return 1
143   fi
144
145   local name="$1"; shift
146
147   _daemon_pidfile $name
148 }
149
150 # Prints path to daemon executable.
151 daemon_executable() {
152   if [[ "$#" -lt 1 ]]; then
153     echo 'Missing daemon name.' >&2
154     return 1
155   fi
156
157   local name="$1"; shift
158
159   _daemon_executable $name
160 }
161
162 # Prints a list of all daemons in the order in which they should be started
163 list_start_daemons() {
164   local name
165
166   for name in "${DAEMONS[@]}"; do
167     echo "$name"
168   done
169 }
170
171 # Prints a list of all daemons in the order in which they should be stopped
172 list_stop_daemons() {
173   list_start_daemons | tac
174 }
175
176 # Checks whether a daemon name is known
177 is_daemon_name() {
178   if [[ "$#" -lt 1 ]]; then
179     echo 'Missing daemon name.' >&2
180     return 1
181   fi
182
183   local name="$1"; shift
184
185   for i in "${DAEMONS[@]}"; do
186     if [[ "$i" == "$name" ]]; then
187       return 0
188     fi
189   done
190
191   echo "Unknown daemon name '$name'" >&2
192   return 1
193 }
194
195 # Checks whether daemon is running
196 check() {
197   if [[ "$#" -lt 1 ]]; then
198     echo 'Missing daemon name.' >&2
199     return 1
200   fi
201
202   local name="$1"; shift
203   local pidfile=$(_daemon_pidfile $name)
204   local daemonexec=$(_daemon_executable $name)
205
206   if type -p start-stop-daemon >/dev/null; then
207     start-stop-daemon --stop --signal 0 --quiet \
208       --pidfile $pidfile
209   else
210     _ignore_error status \
211       -p $pidfile \
212       $daemonexec
213   fi
214 }
215
216 # Starts a daemon
217 start() {
218   if [[ "$#" -lt 1 ]]; then
219     echo 'Missing daemon name.' >&2
220     return 1
221   fi
222
223   local name="$1"; shift
224   # Convert daemon name to uppercase after removing "ganeti-" prefix
225   local plain_name=${name#ganeti-}
226   local ucname=$(tr a-z A-Z <<<$plain_name)
227   local pidfile=$(_daemon_pidfile $name)
228   local usergroup=$(_daemon_usergroup $plain_name)
229   local daemonexec=$(_daemon_executable $name)
230
231   if [[ "$name" == ganeti-confd ]] && ! _confd_enabled; then
232     echo 'ganeti-confd disabled at build time' >&2
233     return 1
234   fi
235
236   # Read $<daemon>_ARGS and $EXTRA_<daemon>_ARGS
237   eval local args="\"\$${ucname}_ARGS \$EXTRA_${ucname}_ARGS\""
238
239   @PKGLIBDIR@/ensure-dirs
240
241   if type -p start-stop-daemon >/dev/null; then
242     start-stop-daemon --start --quiet --oknodo \
243       --pidfile $pidfile \
244       --startas $daemonexec \
245       --chuid $usergroup \
246       -- $args "$@"
247   else
248     # TODO: Find a way to start daemon with a group, until then the group must
249     # be removed
250     _ignore_error daemon \
251       --pidfile $pidfile \
252       --user ${usergroup%:*} \
253       $daemonexec $args "$@"
254   fi
255 }
256
257 # Stops a daemon
258 stop() {
259   if [[ "$#" -lt 1 ]]; then
260     echo 'Missing daemon name.' >&2
261     return 1
262   fi
263
264   local name="$1"; shift
265   local pidfile=$(_daemon_pidfile $name)
266
267   if type -p start-stop-daemon >/dev/null; then
268     start-stop-daemon --stop --quiet --oknodo --retry 30 \
269       --pidfile $pidfile
270   else
271     _ignore_error killproc -p $pidfile $name
272   fi
273 }
274
275 # Starts a daemon if it's not yet running
276 check_and_start() {
277   local name="$1"
278
279   if ! check $name; then
280     start $name
281   fi
282 }
283
284 # Starts the master role
285 start_master() {
286   start ganeti-masterd
287   start ganeti-rapi
288 }
289
290 # Stops the master role
291 stop_master() {
292   stop ganeti-rapi
293   stop ganeti-masterd
294 }
295
296 # Start all daemons
297 start_all() {
298   for i in $(list_start_daemons); do
299     local rc=0
300
301     # Try to start daemon
302     start $i || rc=$?
303
304     if ! errmsg=$(check_exitcode $rc); then
305       echo "$errmsg" >&2
306       return 1
307     fi
308   done
309
310   return 0
311 }
312
313 # Stop all daemons
314 stop_all() {
315   for i in $(list_stop_daemons); do
316     stop $i
317   done
318 }
319
320 # Reloads the SSH keys
321 reload_ssh_keys() {
322   @RPL_SSH_INITD_SCRIPT@ restart
323 }
324
325 # Read @SYSCONFDIR@/rc.d/init.d/functions if start-stop-daemon not available
326 if ! type -p start-stop-daemon >/dev/null && \
327    [[ -f @SYSCONFDIR@/rc.d/init.d/functions ]]; then
328   _ignore_error . @SYSCONFDIR@/rc.d/init.d/functions
329 fi
330
331 if [[ "$#" -lt 1 ]]; then
332   echo "Usage: $0 <action>" >&2
333   exit 1
334 fi
335
336 orig_action=$1; shift
337
338 if [[ "$orig_action" == *_* ]]; then
339   echo "Command must not contain underscores" >&2
340   exit 1
341 fi
342
343 # Replace all dashes (-) with underlines (_)
344 action=${orig_action//-/_}
345
346 # Is it a known function?
347 if ! declare -F "$action" >/dev/null 2>&1; then
348   echo "Unknown command: $orig_action" >&2
349   exit 1
350 fi
351
352 # Call handler function
353 $action "$@"