daemon-util.in 9.07 KB
Newer Older
1 2 3
#!/bin/bash
#

Michael Hanselmann's avatar
Michael Hanselmann committed
4
# Copyright (C) 2009, 2011, 2012 Google Inc.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.

set -e

23 24 25
@SHELL_ENV_INIT@

readonly defaults_file="$SYSCONFDIR/default/ganeti"
26

27 28 29 30
# This is a list of all daemons and the order in which they're started. The
# order is important as there are dependencies between them. On shutdown,
# they're stopped in reverse order.
DAEMONS=(
Petr Pudlak's avatar
Petr Pudlak committed
31
  ganeti-wconfd
32 33
  ganeti-noded
  ganeti-rapi
34
  ganeti-luxid
35 36
  )

37 38 39 40 41 42 43
# This is the list of daemons that are loaded on demand; they should only be
# stopped, not started.
ON_DEMAND_DAEMONS=(
  ganeti-metad
  ganeti-kvmd
  )

44 45 46 47 48
_confd_enabled() {
  [[ "@CUSTOM_ENABLE_CONFD@" == True ]]
}

if _confd_enabled; then
Iustin Pop's avatar
Iustin Pop committed
49 50 51
  DAEMONS+=( ganeti-confd )
fi

52 53 54 55 56 57 58 59
_mond_enabled() {
  [[ "@CUSTOM_ENABLE_MOND@" == True ]]
}

if _mond_enabled; then
  DAEMONS+=( ganeti-mond )
fi

60 61 62
# The full list of all daemons we know about
ALL_DAEMONS=( ${DAEMONS[@]} ${ON_DEMAND_DAEMONS[@]} )

63 64
NODED_ARGS=
CONFD_ARGS=
Petr Pudlak's avatar
Petr Pudlak committed
65
WCONFD_ARGS=
Thomas Thrainer's avatar
Thomas Thrainer committed
66
LUXID_ARGS=
67
RAPI_ARGS=
68
MOND_ARGS=
69 70 71 72 73 74

# Read defaults file if it exists
if [[ -s $defaults_file ]]; then
  . $defaults_file
fi

75 76 77 78 79 80
# Meant to facilitate use utilities in /etc/rc.d/init.d/functions in case
# start-stop-daemon is not available.
_ignore_error() {
  eval "$@" || :
}

81
_daemon_pidfile() {
82
  echo "$RUN_DIR/$1.pid"
83 84
}

85 86 87 88
_daemon_executable() {
  echo "@PREFIX@/sbin/$1"
}

89 90 91
_daemon_usergroup() {
  case "$1" in
    confd)
92
      echo "@GNTCONFDUSER@:@GNTCONFDGROUP@"
93
      ;;
Petr Pudlak's avatar
Petr Pudlak committed
94 95 96
    wconfd)
      echo "@GNTWCONFDUSER@:@GNTWCONFDGROUP@"
      ;;
Thomas Thrainer's avatar
Thomas Thrainer committed
97 98
    luxid)
      echo "@GNTLUXIDUSER@:@GNTLUXIDGROUP@"
99
      ;;
100 101 102 103
    rapi)
      echo "@GNTRAPIUSER@:@GNTRAPIGROUP@"
      ;;
    noded)
Michele Tartara's avatar
Michele Tartara committed
104
      echo "@GNTNODEDUSER@:@GNTNODEDGROUP@"
105
      ;;
106 107 108
    mond)
      echo "@GNTMONDUSER@:@GNTMONDGROUP@"
      ;;
109 110 111 112 113 114
    *)
      echo "root:@GNTDAEMONSGROUP@"
      ;;
  esac
}

115 116
# Checks whether the local machine is part of a cluster
check_config() {
117
  local server_pem=$DATA_DIR/server.pem
118 119 120 121 122 123 124 125 126 127 128 129
  local fname

  for fname in $server_pem; do
    if [[ ! -f $fname ]]; then
      echo "Missing configuration file $fname" >&2
      return 1
    fi
  done

  return 0
}

130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
# Checks the exit code of a daemon
check_exitcode() {
  if [[ "$#" -lt 1 ]]; then
    echo 'Missing exit code.' >&2
    return 1
  fi

  local rc="$1"; shift

  case "$rc" in
    0) ;;
    11)
      echo "not master"
    ;;
    *)
      echo "exit code $rc"
      return 1
    ;;
  esac

  return 0
}

153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
# Checks if we should use systemctl to start/stop daemons
use_systemctl() {
  # Is systemd running as PID 1?
  [ -d /run/systemd/system ] || return 1

  type -p systemctl >/dev/null || return 1

  # Does systemd know about Ganeti at all?
  loadstate="$(systemctl show -pLoadState ganeti.target)"
  if [ "$loadstate" = "LoadState=loaded" ]; then
    return 0
  fi

  return 1
}

169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
# Prints path to PID file for a daemon.
daemon_pidfile() {
  if [[ "$#" -lt 1 ]]; then
    echo 'Missing daemon name.' >&2
    return 1
  fi

  local name="$1"; shift

  _daemon_pidfile $name
}

# Prints path to daemon executable.
daemon_executable() {
  if [[ "$#" -lt 1 ]]; then
    echo 'Missing daemon name.' >&2
    return 1
  fi

  local name="$1"; shift

  _daemon_executable $name
}

193 194 195 196 197
# Prints a list of all daemons in the order in which they should be started
list_start_daemons() {
  local name

  for name in "${DAEMONS[@]}"; do
198
    echo "$name"
199 200 201 202 203
  done
}

# Prints a list of all daemons in the order in which they should be stopped
list_stop_daemons() {
204
  for name in "${ALL_DAEMONS[@]}"; do
205 206
    echo "$name"
  done | tac
207 208 209 210 211 212 213 214 215 216 217
}

# Checks whether a daemon name is known
is_daemon_name() {
  if [[ "$#" -lt 1 ]]; then
    echo 'Missing daemon name.' >&2
    return 1
  fi

  local name="$1"; shift

218
  for i in "${ALL_DAEMONS[@]}"; do
219 220 221 222 223 224 225 226 227
    if [[ "$i" == "$name" ]]; then
      return 0
    fi
  done

  echo "Unknown daemon name '$name'" >&2
  return 1
}

228 229 230 231
# Checks whether daemon is running
check() {
  if [[ "$#" -lt 1 ]]; then
    echo 'Missing daemon name.' >&2
232
    return 1
233 234 235
  fi

  local name="$1"; shift
236 237 238
  local pidfile=$(_daemon_pidfile $name)
  local daemonexec=$(_daemon_executable $name)

239 240 241 242 243 244 245 246
  if use_systemctl; then
    activestate="$(systemctl show -pActiveState "${name}.service")"
    if [ "$activestate" = "ActiveState=active" ]; then
      return 0
    else
      return 1
    fi
  elif type -p start-stop-daemon >/dev/null; then
247 248 249 250 251 252 253
    start-stop-daemon --stop --signal 0 --quiet \
      --pidfile $pidfile
  else
    _ignore_error status \
      -p $pidfile \
      $daemonexec
  fi
254 255 256 257 258 259
}

# Starts a daemon
start() {
  if [[ "$#" -lt 1 ]]; then
    echo 'Missing daemon name.' >&2
260
    return 1
261 262 263
  fi

  local name="$1"; shift
264 265 266
  # Convert daemon name to uppercase after removing "ganeti-" prefix
  local plain_name=${name#ganeti-}
  local ucname=$(tr a-z A-Z <<<$plain_name)
267 268 269
  local pidfile=$(_daemon_pidfile $name)
  local usergroup=$(_daemon_usergroup $plain_name)
  local daemonexec=$(_daemon_executable $name)
270

271
  if [[ "$name" == ganeti-confd ]] \
272
      && ! _confd_enabled; then
Iustin Pop's avatar
Iustin Pop committed
273 274 275 276
    echo 'ganeti-confd disabled at build time' >&2
    return 1
  fi

277 278 279 280 281
  if use_systemctl; then
    systemctl start "${name}.service"
    return $?
  fi

282
  # Read $<daemon>_ARGS and $EXTRA_<daemon>_ARGS
283
  eval local args="\"\$${ucname}_ARGS \$EXTRA_${ucname}_ARGS\""
284

285 286
  @PKGLIBDIR@/ensure-dirs

287 288 289 290 291 292 293 294 295 296 297 298 299 300
  if type -p start-stop-daemon >/dev/null; then
    start-stop-daemon --start --quiet --oknodo \
      --pidfile $pidfile \
      --startas $daemonexec \
      --chuid $usergroup \
      -- $args "$@"
  else
    # TODO: Find a way to start daemon with a group, until then the group must
    # be removed
    _ignore_error daemon \
      --pidfile $pidfile \
      --user ${usergroup%:*} \
      $daemonexec $args "$@"
  fi
301

302 303 304 305 306 307
}

# Stops a daemon
stop() {
  if [[ "$#" -lt 1 ]]; then
    echo 'Missing daemon name.' >&2
308
    return 1
309 310 311
  fi

  local name="$1"; shift
312
  local pidfile=$(_daemon_pidfile $name)
313

314 315 316
  if use_systemctl; then
    systemctl stop "${name}.service"
  elif type -p start-stop-daemon >/dev/null; then
317 318 319 320 321
    start-stop-daemon --stop --quiet --oknodo --retry 30 \
      --pidfile $pidfile
  else
    _ignore_error killproc -p $pidfile $name
  fi
322 323 324 325 326 327 328
}

# Starts a daemon if it's not yet running
check_and_start() {
  local name="$1"

  if ! check $name; then
329 330 331 332 333
    if use_systemctl; then
      echo "${name} supervised by systemd but not running, will not restart."
      return 1
    fi

334 335 336 337 338 339
    start $name
  fi
}

# Starts the master role
start_master() {
340 341 342 343 344 345 346
  if use_systemctl; then
    systemctl start ganeti-master.target
  else
    start ganeti-wconfd
    start ganeti-rapi
    start ganeti-luxid
  fi
347 348 349 350
}

# Stops the master role
stop_master() {
351 352 353 354 355 356 357
  if use_systemctl; then
    systemctl stop ganeti-master.target
  else
    stop ganeti-luxid
    stop ganeti-rapi
    stop ganeti-wconfd
  fi
358 359
}

360 361
# Start all daemons
start_all() {
362 363 364
  use_systemctl && systemctl start ganeti.target
  # Fall through so that we detect any errors.

365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
  for i in $(list_start_daemons); do
    local rc=0

    # Try to start daemon
    start $i || rc=$?

    if ! errmsg=$(check_exitcode $rc); then
      echo "$errmsg" >&2
      return 1
    fi
  done

  return 0
}

# Stop all daemons
stop_all() {
382 383 384 385 386 387 388
  if use_systemctl; then
    systemctl stop ganeti.target
  else
    for i in $(list_stop_daemons); do
      stop $i
    done
  fi
389 390
}

391 392 393 394 395 396 397 398 399 400 401 402 403
# SIGHUP a process to force re-opening its logfiles
rotate_logs() {
  if [[ "$#" -lt 1 ]]; then
    echo 'Missing daemon name.' >&2
    return 1
  fi

  local name="$1"; shift
  local pidfile=$(_daemon_pidfile $name)
  local daemonexec=$(_daemon_executable $name)

  if type -p start-stop-daemon >/dev/null; then
    start-stop-daemon --stop --signal HUP --quiet \
404
      --oknodo --pidfile $pidfile
405 406 407 408 409 410 411 412 413 414 415 416 417 418
  else
    _ignore_error killproc \
      -p $pidfile \
      $daemonexec -HUP
  fi
}

# SIGHUP all processes
rotate_all_logs() {
  for i in $(list_stop_daemons); do
    rotate_logs $i
  done
}

419 420 421 422 423
# Reloads the SSH keys
reload_ssh_keys() {
  @RPL_SSH_INITD_SCRIPT@ restart
}

424 425 426 427 428 429
# Read @SYSCONFDIR@/rc.d/init.d/functions if start-stop-daemon not available
if ! type -p start-stop-daemon >/dev/null && \
   [[ -f @SYSCONFDIR@/rc.d/init.d/functions ]]; then
  _ignore_error . @SYSCONFDIR@/rc.d/init.d/functions
fi

430 431 432 433 434 435 436
if [[ "$#" -lt 1 ]]; then
  echo "Usage: $0 <action>" >&2
  exit 1
fi

orig_action=$1; shift

437 438 439 440 441
if [[ "$orig_action" == *_* ]]; then
  echo "Command must not contain underscores" >&2
  exit 1
fi

442 443 444 445 446 447 448 449 450 451 452
# Replace all dashes (-) with underlines (_)
action=${orig_action//-/_}

# Is it a known function?
if ! declare -F "$action" >/dev/null 2>&1; then
  echo "Unknown command: $orig_action" >&2
  exit 1
fi

# Call handler function
$action "$@"