9481dc0438d3507760bb5f36846923f02e83777b
[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 NODED_ARGS=
45 MASTERD_ARGS=
46 CONFD_ARGS=
47 RAPI_ARGS=
48
49 # Read defaults file if it exists
50 if [[ -s $defaults_file ]]; then
51   . $defaults_file
52 fi
53
54 # Meant to facilitate use utilities in /etc/rc.d/init.d/functions in case
55 # start-stop-daemon is not available.
56 _ignore_error() {
57   eval "$@" || :
58 }
59
60 _daemon_pidfile() {
61   echo "$RUN_DIR/$1.pid"
62 }
63
64 _daemon_executable() {
65   echo "@PREFIX@/sbin/$1"
66 }
67
68 _daemon_usergroup() {
69   case "$1" in
70     masterd)
71       echo "@GNTMASTERUSER@:@GNTMASTERDGROUP@"
72       ;;
73     confd)
74       echo "@GNTCONFDUSER@:@GNTCONFDGROUP@"
75       ;;
76     rapi)
77       echo "@GNTRAPIUSER@:@GNTRAPIGROUP@"
78       ;;
79     noded)
80       echo "@GNTNODEDUSER@:@GNTDAEMONSGROUP@"
81       ;;
82     *)
83       echo "root:@GNTDAEMONSGROUP@"
84       ;;
85   esac
86 }
87
88 # Checks whether the local machine is part of a cluster
89 check_config() {
90   local server_pem=$DATA_DIR/server.pem
91   local fname
92
93   for fname in $server_pem; do
94     if [[ ! -f $fname ]]; then
95       echo "Missing configuration file $fname" >&2
96       return 1
97     fi
98   done
99
100   return 0
101 }
102
103 # Checks the exit code of a daemon
104 check_exitcode() {
105   if [[ "$#" -lt 1 ]]; then
106     echo 'Missing exit code.' >&2
107     return 1
108   fi
109
110   local rc="$1"; shift
111
112   case "$rc" in
113     0) ;;
114     11)
115       echo "not master"
116     ;;
117     *)
118       echo "exit code $rc"
119       return 1
120     ;;
121   esac
122
123   return 0
124 }
125
126 # Prints path to PID file for a daemon.
127 daemon_pidfile() {
128   if [[ "$#" -lt 1 ]]; then
129     echo 'Missing daemon name.' >&2
130     return 1
131   fi
132
133   local name="$1"; shift
134
135   _daemon_pidfile $name
136 }
137
138 # Prints path to daemon executable.
139 daemon_executable() {
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_executable $name
148 }
149
150 # Prints a list of all daemons in the order in which they should be started
151 list_start_daemons() {
152   local name
153
154   for name in "${DAEMONS[@]}"; do
155     echo "$name"
156   done
157 }
158
159 # Prints a list of all daemons in the order in which they should be stopped
160 list_stop_daemons() {
161   list_start_daemons | tac
162 }
163
164 # Checks whether a daemon name is known
165 is_daemon_name() {
166   if [[ "$#" -lt 1 ]]; then
167     echo 'Missing daemon name.' >&2
168     return 1
169   fi
170
171   local name="$1"; shift
172
173   for i in "${DAEMONS[@]}"; do
174     if [[ "$i" == "$name" ]]; then
175       return 0
176     fi
177   done
178
179   echo "Unknown daemon name '$name'" >&2
180   return 1
181 }
182
183 # Checks whether daemon is running
184 check() {
185   if [[ "$#" -lt 1 ]]; then
186     echo 'Missing daemon name.' >&2
187     return 1
188   fi
189
190   local name="$1"; shift
191   local pidfile=$(_daemon_pidfile $name)
192   local daemonexec=$(_daemon_executable $name)
193
194   if type -p start-stop-daemon >/dev/null; then
195     start-stop-daemon --stop --signal 0 --quiet \
196       --pidfile $pidfile
197   else
198     _ignore_error status \
199       -p $pidfile \
200       $daemonexec
201   fi
202 }
203
204 # Starts a daemon
205 start() {
206   if [[ "$#" -lt 1 ]]; then
207     echo 'Missing daemon name.' >&2
208     return 1
209   fi
210
211   local name="$1"; shift
212   # Convert daemon name to uppercase after removing "ganeti-" prefix
213   local plain_name=${name#ganeti-}
214   local ucname=$(tr a-z A-Z <<<$plain_name)
215   local pidfile=$(_daemon_pidfile $name)
216   local usergroup=$(_daemon_usergroup $plain_name)
217   local daemonexec=$(_daemon_executable $name)
218
219   if [[ "$name" == ganeti-confd ]] && ! _confd_enabled; then
220     echo 'ganeti-confd disabled at build time' >&2
221     return 1
222   fi
223
224   # Read $<daemon>_ARGS and $EXTRA_<daemon>_ARGS
225   eval local args="\"\$${ucname}_ARGS \$EXTRA_${ucname}_ARGS\""
226
227   @PKGLIBDIR@/ensure-dirs
228
229   if type -p start-stop-daemon >/dev/null; then
230     start-stop-daemon --start --quiet --oknodo \
231       --pidfile $pidfile \
232       --startas $daemonexec \
233       --chuid $usergroup \
234       -- $args "$@"
235   else
236     # TODO: Find a way to start daemon with a group, until then the group must
237     # be removed
238     _ignore_error daemon \
239       --pidfile $pidfile \
240       --user ${usergroup%:*} \
241       $daemonexec $args "$@"
242   fi
243
244   # FIXME: This is a workaround for issue 477. Remove this once confd does not
245   # mess up the permissions anymore.
246   if [[ "$name" == ganeti-confd ]]; then
247     @PKGLIBDIR@/ensure-dirs;
248   fi
249 }
250
251 # Stops a daemon
252 stop() {
253   if [[ "$#" -lt 1 ]]; then
254     echo 'Missing daemon name.' >&2
255     return 1
256   fi
257
258   local name="$1"; shift
259   local pidfile=$(_daemon_pidfile $name)
260
261   if type -p start-stop-daemon >/dev/null; then
262     start-stop-daemon --stop --quiet --oknodo --retry 30 \
263       --pidfile $pidfile
264   else
265     _ignore_error killproc -p $pidfile $name
266   fi
267 }
268
269 # Starts a daemon if it's not yet running
270 check_and_start() {
271   local name="$1"
272
273   if ! check $name; then
274     start $name
275   fi
276 }
277
278 # Starts the master role
279 start_master() {
280   start ganeti-masterd
281   start ganeti-rapi
282 }
283
284 # Stops the master role
285 stop_master() {
286   stop ganeti-rapi
287   stop ganeti-masterd
288 }
289
290 # Start all daemons
291 start_all() {
292   for i in $(list_start_daemons); do
293     local rc=0
294
295     # Try to start daemon
296     start $i || rc=$?
297
298     if ! errmsg=$(check_exitcode $rc); then
299       echo "$errmsg" >&2
300       return 1
301     fi
302   done
303
304   return 0
305 }
306
307 # Stop all daemons
308 stop_all() {
309   for i in $(list_stop_daemons); do
310     stop $i
311   done
312 }
313
314 # Reloads the SSH keys
315 reload_ssh_keys() {
316   @RPL_SSH_INITD_SCRIPT@ restart
317 }
318
319 # Read @SYSCONFDIR@/rc.d/init.d/functions if start-stop-daemon not available
320 if ! type -p start-stop-daemon >/dev/null && \
321    [[ -f @SYSCONFDIR@/rc.d/init.d/functions ]]; then
322   _ignore_error . @SYSCONFDIR@/rc.d/init.d/functions
323 fi
324
325 if [[ "$#" -lt 1 ]]; then
326   echo "Usage: $0 <action>" >&2
327   exit 1
328 fi
329
330 orig_action=$1; shift
331
332 if [[ "$orig_action" == *_* ]]; then
333   echo "Command must not contain underscores" >&2
334   exit 1
335 fi
336
337 # Replace all dashes (-) with underlines (_)
338 action=${orig_action//-/_}
339
340 # Is it a known function?
341 if ! declare -F "$action" >/dev/null 2>&1; then
342   echo "Unknown command: $orig_action" >&2
343   exit 1
344 fi
345
346 # Call handler function
347 $action "$@"