Merge branch 'devel-2.5'
[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 defaults_file=@SYSCONFDIR@/default/ganeti
24
25 # This is a list of all daemons and the order in which they're started. The
26 # order is important as there are dependencies between them. On shutdown,
27 # they're stopped in reverse order.
28 DAEMONS=(
29   ganeti-noded
30   ganeti-masterd
31   ganeti-rapi
32   )
33
34 if [[ "@CUSTOM_ENABLE_CONFD@" == True ]]; then
35   DAEMONS+=( ganeti-confd )
36 fi
37
38 NODED_ARGS=
39 MASTERD_ARGS=
40 CONFD_ARGS=
41 RAPI_ARGS=
42
43 # Read defaults file if it exists
44 if [[ -s $defaults_file ]]; then
45   . $defaults_file
46 fi
47
48 _daemon_pidfile() {
49   echo "@LOCALSTATEDIR@/run/ganeti/$1.pid"
50 }
51
52 _daemon_executable() {
53   echo "@PREFIX@/sbin/$1"
54 }
55
56 _daemon_usergroup() {
57   case "$1" in
58     masterd)
59       echo "@GNTMASTERUSER@:@GNTMASTERDGROUP@"
60       ;;
61     confd)
62       echo "@GNTCONFDUSER@:@GNTCONFDGROUP@"
63       ;;
64     rapi)
65       echo "@GNTRAPIUSER@:@GNTRAPIGROUP@"
66       ;;
67     noded)
68       echo "@GNTNODEDUSER@:@GNTDAEMONSGROUP@"
69       ;;
70     *)
71       echo "root:@GNTDAEMONSGROUP@"
72       ;;
73   esac
74 }
75
76 # Checks whether the local machine is part of a cluster
77 check_config() {
78   local server_pem=@LOCALSTATEDIR@/lib/ganeti/server.pem
79   local fname
80
81   for fname in $server_pem; do
82     if [[ ! -f $fname ]]; then
83       echo "Missing configuration file $fname" >&2
84       return 1
85     fi
86   done
87
88   return 0
89 }
90
91 # Checks the exit code of a daemon
92 check_exitcode() {
93   if [[ "$#" -lt 1 ]]; then
94     echo 'Missing exit code.' >&2
95     return 1
96   fi
97
98   local rc="$1"; shift
99
100   case "$rc" in
101     0) ;;
102     11)
103       echo "not master"
104     ;;
105     *)
106       echo "exit code $rc"
107       return 1
108     ;;
109   esac
110
111   return 0
112 }
113
114 # Prints path to PID file for a daemon.
115 daemon_pidfile() {
116   if [[ "$#" -lt 1 ]]; then
117     echo 'Missing daemon name.' >&2
118     return 1
119   fi
120
121   local name="$1"; shift
122
123   _daemon_pidfile $name
124 }
125
126 # Prints path to daemon executable.
127 daemon_executable() {
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_executable $name
136 }
137
138 # Prints a list of all daemons in the order in which they should be started
139 list_start_daemons() {
140   local name
141
142   for name in "${DAEMONS[@]}"; do
143     echo "$name"
144   done
145 }
146
147 # Prints a list of all daemons in the order in which they should be stopped
148 list_stop_daemons() {
149   list_start_daemons | tac
150 }
151
152 # Checks whether a daemon name is known
153 is_daemon_name() {
154   if [[ "$#" -lt 1 ]]; then
155     echo 'Missing daemon name.' >&2
156     return 1
157   fi
158
159   local name="$1"; shift
160
161   for i in "${DAEMONS[@]}"; do
162     if [[ "$i" == "$name" ]]; then
163       return 0
164     fi
165   done
166
167   echo "Unknown daemon name '$name'" >&2
168   return 1
169 }
170
171 # Checks whether daemon is running
172 check() {
173   if [[ "$#" -lt 1 ]]; then
174     echo 'Missing daemon name.' >&2
175     return 1
176   fi
177
178   local name="$1"; shift
179
180   start-stop-daemon --stop --signal 0 --quiet \
181     --pidfile $(_daemon_pidfile $name)
182 }
183
184 # Starts a daemon
185 start() {
186   if [[ "$#" -lt 1 ]]; then
187     echo 'Missing daemon name.' >&2
188     return 1
189   fi
190
191   local name="$1"; shift
192
193   if [[ "$name" == ganeti-confd &&
194         "@CUSTOM_ENABLE_CONFD@" == False ]]; then
195     echo 'ganeti-confd disabled at build time' >&2
196     return 1
197   fi
198
199   # Convert daemon name to uppercase after removing "ganeti-" prefix
200   local plain_name=${name#ganeti-}
201   local ucname=$(tr a-z A-Z <<<$plain_name)
202
203   # Read $<daemon>_ARGS and $EXTRA_<daemon>_ARGS
204   eval local args="\"\$${ucname}_ARGS \$EXTRA_${ucname}_ARGS\""
205
206   @PKGLIBDIR@/ensure-dirs
207
208   start-stop-daemon --start --quiet --oknodo \
209     --pidfile $(_daemon_pidfile $name) \
210     --startas $(_daemon_executable $name) \
211     --chuid $(_daemon_usergroup $plain_name) \
212     -- $args "$@"
213 }
214
215 # Stops a daemon
216 stop() {
217   if [[ "$#" -lt 1 ]]; then
218     echo 'Missing daemon name.' >&2
219     return 1
220   fi
221
222   local name="$1"; shift
223
224   start-stop-daemon --stop --quiet --oknodo --retry 30 \
225     --pidfile $(_daemon_pidfile $name)
226 }
227
228 # Starts a daemon if it's not yet running
229 check_and_start() {
230   local name="$1"
231
232   if ! check $name; then
233     start $name
234   fi
235 }
236
237 # Starts the master role
238 start_master() {
239   start ganeti-masterd
240   start ganeti-rapi
241 }
242
243 # Stops the master role
244 stop_master() {
245   stop ganeti-rapi
246   stop ganeti-masterd
247 }
248
249 # Start all daemons
250 start_all() {
251   for i in $(list_start_daemons); do
252     local rc=0
253
254     # Try to start daemon
255     start $i || rc=$?
256
257     if ! errmsg=$(check_exitcode $rc); then
258       echo "$errmsg" >&2
259       return 1
260     fi
261   done
262
263   return 0
264 }
265
266 # Stop all daemons
267 stop_all() {
268   for i in $(list_stop_daemons); do
269     stop $i
270   done
271 }
272
273 # Reloads the SSH keys
274 reload_ssh_keys() {
275   @RPL_SSH_INITD_SCRIPT@ restart
276 }
277
278 if [[ "$#" -lt 1 ]]; then
279   echo "Usage: $0 <action>" >&2
280   exit 1
281 fi
282
283 orig_action=$1; shift
284
285 if [[ "$orig_action" == *_* ]]; then
286   echo "Command must not contain underscores" >&2
287   exit 1
288 fi
289
290 # Replace all dashes (-) with underlines (_)
291 action=${orig_action//-/_}
292
293 # Is it a known function?
294 if ! declare -F "$action" >/dev/null 2>&1; then
295   echo "Unknown command: $orig_action" >&2
296   exit 1
297 fi
298
299 # Call handler function
300 $action "$@"