Statistics
| Branch: | Tag: | Revision:

root / daemons / daemon-util.in @ c6bca2d1

History | View | Annotate | Download (7.1 kB)

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