PageRenderTime 798ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/libexec.xendomains

#
Bash | 564 lines | 520 code | 44 blank | 0 comment | 0 complexity | 079680ce151f0b036716119ba87fafaa MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause, LGPL-2.0, GPL-2.0
  1. #!/bin/bash
  2. #
  3. # /etc/init.d/xendomains
  4. # Start / stop domains automatically when domain 0 boots / shuts down.
  5. #
  6. # chkconfig: 345 99 00
  7. # description: Start / stop Xen domains.
  8. #
  9. # This script offers fairly basic functionality. It should work on Redhat
  10. # but also on LSB-compliant SuSE releases and on Debian with the LSB package
  11. # installed. (LSB is the Linux Standard Base)
  12. #
  13. # Based on the example in the "Designing High Quality Integrated Linux
  14. # Applications HOWTO" by Avi Alkalay
  15. # <http://www.tldp.org/HOWTO/HighQuality-Apps-HOWTO/>
  16. #
  17. ### BEGIN INIT INFO
  18. # Provides: xendomains
  19. # Required-Start: $syslog $remote_fs xenstored xenconsoled
  20. # Should-Start: xend
  21. # Required-Stop: $syslog $remote_fs xenstored xenconsoled
  22. # Should-Stop: xend
  23. # Default-Start: 2 3 4 5
  24. # Default-Stop: 0 1 6
  25. # Short-Description: Start/stop secondary xen domains
  26. # Description: Start / stop domains automatically when domain 0
  27. # boots / shuts down.
  28. ### END INIT INFO
  29. CMD=xl
  30. $CMD list &> /dev/null
  31. if test $? -ne 0
  32. then
  33. CMD=xm
  34. fi
  35. $CMD list &> /dev/null
  36. if test $? -ne 0
  37. then
  38. exit 0;
  39. fi
  40. # Correct exit code would probably be 5, but it's enough
  41. # if xend complains if we're not running as privileged domain
  42. if ! [ -e /proc/xen/privcmd ]; then
  43. exit 0
  44. fi
  45. # See docs/misc/distro_mapping.txt
  46. if [ -d /var/lock/subsys ]; then
  47. LOCKFILE=/var/lock/subsys/xendomains
  48. else
  49. LOCKFILE=/var/lock/xendomains
  50. fi
  51. if [ -d /etc/sysconfig ]; then
  52. XENDOM_CONFIG=/etc/sysconfig/xendomains
  53. else
  54. XENDOM_CONFIG=/etc/default/xendomains
  55. fi
  56. test -r $XENDOM_CONFIG || { echo "$XENDOM_CONFIG not existing";
  57. if [ "$1" = "stop" ]; then exit 0;
  58. else exit 6; fi; }
  59. . $XENDOM_CONFIG
  60. # Use the SUSE rc_ init script functions;
  61. # emulate them on LSB, RH and other systems
  62. if test -e /etc/rc.status; then
  63. # SUSE rc script library
  64. . /etc/rc.status
  65. else
  66. _cmd=$1
  67. declare -a _SMSG
  68. if test "${_cmd}" = "status"; then
  69. _SMSG=(running dead dead unused unknown)
  70. _RC_UNUSED=3
  71. else
  72. _SMSG=(done failed failed missed failed skipped unused failed failed)
  73. _RC_UNUSED=6
  74. fi
  75. if test -e /lib/lsb/init-functions; then
  76. # LSB
  77. . /lib/lsb/init-functions
  78. if alias log_success_msg >/dev/null 2>/dev/null; then
  79. echo_rc()
  80. {
  81. echo " [${_SMSG[${_RC_RV}]}] "
  82. }
  83. else
  84. echo_rc()
  85. {
  86. if test ${_RC_RV} = 0; then
  87. log_success_msg " [${_SMSG[${_RC_RV}]}] "
  88. else
  89. log_failure_msg " [${_SMSG[${_RC_RV}]}] "
  90. fi
  91. }
  92. fi
  93. else
  94. # emulate it
  95. echo_rc()
  96. {
  97. echo " [${_SMSG[${_RC_RV}]}] "
  98. }
  99. fi
  100. rc_reset() { _RC_RV=0; }
  101. rc_failed()
  102. {
  103. if test -z "$1"; then
  104. _RC_RV=1;
  105. elif test "$1" != "0"; then
  106. _RC_RV=$1;
  107. fi
  108. return ${_RC_RV}
  109. }
  110. rc_check()
  111. {
  112. return rc_failed $?
  113. }
  114. rc_status()
  115. {
  116. rc_failed $?
  117. if test "$1" = "-r"; then _RC_RV=0; shift; fi
  118. if test "$1" = "-s"; then rc_failed 5; echo_rc; rc_failed 3; shift; fi
  119. if test "$1" = "-u"; then rc_failed ${_RC_UNUSED}; echo_rc; rc_failed 3; shift; fi
  120. if test "$1" = "-v"; then echo_rc; shift; fi
  121. if test "$1" = "-r"; then _RC_RV=0; shift; fi
  122. return ${_RC_RV}
  123. }
  124. rc_exit() { exit ${_RC_RV}; }
  125. rc_active()
  126. {
  127. if test -z "$RUNLEVEL"; then read RUNLEVEL REST < <(/sbin/runlevel); fi
  128. if test -e /etc/init.d/S[0-9][0-9]${1}; then return 0; fi
  129. return 1
  130. }
  131. fi
  132. if ! which usleep >&/dev/null
  133. then
  134. usleep()
  135. {
  136. if [ -n "$1" ]
  137. then
  138. sleep $(( $1 / 1000000 ))
  139. fi
  140. }
  141. fi
  142. # Reset status of this service
  143. rc_reset
  144. ##
  145. # Returns 0 (success) if the given parameter names a directory, and that
  146. # directory is not empty.
  147. #
  148. contains_something()
  149. {
  150. if [ -d "$1" ] && [ `/bin/ls $1 | wc -l` -gt 0 ]
  151. then
  152. return 0
  153. else
  154. return 1
  155. fi
  156. }
  157. # read name from xen config file
  158. rdname()
  159. {
  160. NM=$($CMD create --quiet --dryrun --defconfig "$1" |
  161. sed -n 's/^.*(name \(.*\))$/\1/p')
  162. }
  163. rdnames()
  164. {
  165. NAMES=
  166. if ! contains_something "$XENDOMAINS_AUTO"
  167. then
  168. return
  169. fi
  170. for dom in $XENDOMAINS_AUTO/*; do
  171. rdname $dom
  172. if test -z $NAMES; then
  173. NAMES=$NM;
  174. else
  175. NAMES="$NAMES|$NM"
  176. fi
  177. done
  178. }
  179. parseln()
  180. {
  181. if [[ "$1" =~ '(domain' ]]; then
  182. name=;id=
  183. else if [[ "$1" =~ '(name' ]]; then
  184. name=$(echo $1 | sed -e 's/^.*(name \(.*\))$/\1/')
  185. else if [[ "$1" =~ '(domid' ]]; then
  186. id=$(echo $1 | sed -e 's/^.*(domid \(.*\))$/\1/')
  187. fi; fi; fi
  188. [ -n "$name" -a -n "$id" ] && return 0 || return 1
  189. }
  190. is_running()
  191. {
  192. rdname $1
  193. RC=1
  194. name=;id=
  195. while read LN; do
  196. parseln "$LN" || continue
  197. if test $id = 0; then continue; fi
  198. case $name in
  199. ($NM)
  200. RC=0
  201. ;;
  202. esac
  203. done < <($CMD list -l | grep '(\(domain\|domid\|name\)')
  204. return $RC
  205. }
  206. start()
  207. {
  208. if [ -f $LOCKFILE ]; then
  209. echo -e "xendomains already running (lockfile exists)"
  210. return;
  211. fi
  212. saved_domains=" "
  213. if [ "$XENDOMAINS_RESTORE" = "true" ] &&
  214. contains_something "$XENDOMAINS_SAVE"
  215. then
  216. mkdir -p $(dirname "$LOCKFILE")
  217. touch $LOCKFILE
  218. echo -n "Restoring Xen domains:"
  219. saved_domains=`ls $XENDOMAINS_SAVE`
  220. for dom in $XENDOMAINS_SAVE/*; do
  221. if [ -f $dom ] ; then
  222. HEADER=`head -c 16 $dom | head -n 1 2> /dev/null`
  223. if [ $HEADER = "LinuxGuestRecord" ]; then
  224. echo -n " ${dom##*/}"
  225. XMR=`$CMD restore $dom 2>&1 1>/dev/null`
  226. #$CMD restore $dom
  227. if [ $? -ne 0 ]; then
  228. echo -e "\nAn error occurred while restoring domain ${dom##*/}:\n$XMR"
  229. rc_failed $?
  230. echo -e '!'
  231. else
  232. # mv $dom ${dom%/*}/.${dom##*/}
  233. rm $dom
  234. fi
  235. fi
  236. fi
  237. done
  238. echo -e
  239. fi
  240. if contains_something "$XENDOMAINS_AUTO"
  241. then
  242. touch $LOCKFILE
  243. echo -n "Starting auto Xen domains:"
  244. # We expect config scripts for auto starting domains to be in
  245. # XENDOMAINS_AUTO - they could just be symlinks to files elsewhere
  246. # Create all domains with config files in XENDOMAINS_AUTO.
  247. # TODO: We should record which domain name belongs
  248. # so we have the option to selectively shut down / migrate later
  249. # If a domain statefile from $XENDOMAINS_SAVE matches a domain name
  250. # in $XENDOMAINS_AUTO, do not try to start that domain; if it didn't
  251. # restore correctly it requires administrative attention.
  252. for dom in $XENDOMAINS_AUTO/*; do
  253. echo -n " ${dom##*/}"
  254. shortdom=$(echo $dom | sed -n 's/^.*\/\(.*\)$/\1/p')
  255. echo $saved_domains | grep -w $shortdom > /dev/null
  256. if [ $? -eq 0 ] || is_running $dom; then
  257. echo -n "(skip)"
  258. else
  259. XMC=`$CMD create --quiet --defconfig $dom`
  260. if [ $? -ne 0 ]; then
  261. echo -e "\nAn error occurred while creating domain ${dom##*/}: $XMC\n"
  262. rc_failed $?
  263. echo -e '!'
  264. else
  265. usleep $XENDOMAINS_CREATE_USLEEP
  266. fi
  267. fi
  268. done
  269. fi
  270. }
  271. all_zombies()
  272. {
  273. name=;id=
  274. while read LN; do
  275. parseln "$LN" || continue
  276. if test $id = 0; then continue; fi
  277. if test "$state" != "-b---d" -a "$state" != "-----d"; then
  278. return 1;
  279. fi
  280. done < <($CMD list -l | grep '(\(domain\|domid\|name\)')
  281. return 0
  282. }
  283. # Wait for max $XENDOMAINS_STOP_MAXWAIT for $CMD $1 to finish;
  284. # if it has not exited by that time kill it, so the init script will
  285. # succeed within a finite amount of time; if $2 is nonnull, it will
  286. # kill the command as well as soon as no domain (except for zombies)
  287. # are left (used for shutdown --all). Third parameter, if any, suppresses
  288. # output of dots per working state (formatting issues)
  289. watchdog_xencmd()
  290. {
  291. if test -z "$XENDOMAINS_STOP_MAXWAIT" -o "$XENDOMAINS_STOP_MAXWAIT" = "0"; then
  292. exit
  293. fi
  294. usleep 20000
  295. for no in `seq 0 $XENDOMAINS_STOP_MAXWAIT`; do
  296. # exit if $CMD save/migrate/shutdown is finished
  297. PSAX=`ps axlw | grep "$CMD $1" | grep -v grep`
  298. if test -z "$PSAX"; then exit; fi
  299. if ! test -n "$3"; then echo -n '.'; fi
  300. sleep 1
  301. # go to kill immediately if there's only zombies left
  302. if all_zombies && test -n "$2"; then break; fi
  303. done
  304. sleep 1
  305. read PSF PSUID PSPID PSPPID < <(echo "$PSAX")
  306. # kill $CMD $1
  307. kill $PSPID >/dev/null 2>&1
  308. echo -e .
  309. }
  310. stop()
  311. {
  312. exec 3>&2 2> /dev/null
  313. # Collect list of domains to shut down
  314. if test "$XENDOMAINS_AUTO_ONLY" = "true"; then
  315. rdnames
  316. fi
  317. echo -n "Shutting down Xen domains:"
  318. name=;id=
  319. while read LN; do
  320. parseln "$LN" || continue
  321. if test $id = 0; then continue; fi
  322. echo -n " $name"
  323. if test "$XENDOMAINS_AUTO_ONLY" = "true"; then
  324. eval "
  325. case \"\$name\" in
  326. ($NAMES)
  327. # nothing
  328. ;;
  329. (*)
  330. echo -e '(skip)'
  331. continue
  332. ;;
  333. esac
  334. "
  335. fi
  336. # XENDOMAINS_SYSRQ chould be something like just "s"
  337. # or "s e i u" or even "s e s i u o"
  338. # for the latter, you should set XENDOMAINS_USLEEP to 1200000 or so
  339. if test -n "$XENDOMAINS_SYSRQ"; then
  340. for sysrq in $XENDOMAINS_SYSRQ; do
  341. echo -n "(SR-$sysrq)"
  342. XMR=`$CMD sysrq $id $sysrq 2>&1 1>/dev/null`
  343. if test $? -ne 0; then
  344. echo -e "\nAn error occurred while doing sysrq on domain:\n$XMR\n"
  345. rc_failed $?
  346. echo -n '!'
  347. fi
  348. # usleep just ignores empty arg
  349. usleep $XENDOMAINS_USLEEP
  350. done
  351. fi
  352. if test "$state" = "-b---d" -o "$state" = "-----d"; then
  353. echo -n "(zomb)"
  354. continue
  355. fi
  356. if test -n "$XENDOMAINS_MIGRATE"; then
  357. echo -n "(migr)"
  358. watchdog_xencmd migrate &
  359. WDOG_PID=$!
  360. XMR=`$CMD migrate $id $XENDOMAINS_MIGRATE 2>&1 1>/dev/null`
  361. if test $? -ne 0; then
  362. echo -e "\nAn error occurred while migrating domain:\n$XMR\n"
  363. rc_failed $?
  364. echo -e '!'
  365. kill $WDOG_PID >/dev/null 2>&1
  366. else
  367. kill $WDOG_PID >/dev/null 2>&1
  368. echo -e .
  369. usleep 1000
  370. continue
  371. fi
  372. fi
  373. if test -n "$XENDOMAINS_SAVE"; then
  374. echo -n "(save)"
  375. watchdog_xencmd save &
  376. WDOG_PID=$!
  377. mkdir -p "$XENDOMAINS_SAVE"
  378. XMR=`$CMD save $id $XENDOMAINS_SAVE/$name 2>&1 1>/dev/null`
  379. if test $? -ne 0; then
  380. echo -e "\nAn error occurred while saving domain:\n$XMR\n"
  381. rc_failed $?
  382. echo -e '!'
  383. kill $WDOG_PID >/dev/null 2>&1
  384. else
  385. kill $WDOG_PID >/dev/null 2>&1
  386. echo -e .
  387. usleep 1000
  388. continue
  389. fi
  390. fi
  391. if test -n "$XENDOMAINS_SHUTDOWN"; then
  392. # XENDOMAINS_SHUTDOWN should be "--halt --wait"
  393. echo -n "(shut)"
  394. watchdog_xencmd shutdown &
  395. WDOG_PID=$!
  396. XMR=`$CMD shutdown $id $XENDOMAINS_SHUTDOWN 2>&1 1>/dev/null`
  397. if test $? -ne 0; then
  398. echo -e "\nAn error occurred while shutting down domain:\n$XMR\n"
  399. rc_failed $?
  400. echo -e '!'
  401. fi
  402. kill $WDOG_PID >/dev/null 2>&1
  403. fi
  404. done < <($CMD list -l | grep '(\(domain\|domid\|name\)')
  405. # NB. this shuts down ALL Xen domains (politely), not just the ones in
  406. # AUTODIR/*
  407. # This is because it's easier to do ;-) but arguably if this script is run
  408. # on system shutdown then it's also the right thing to do.
  409. if ! all_zombies && test -n "$XENDOMAINS_SHUTDOWN_ALL"; then
  410. # XENDOMAINS_SHUTDOWN_ALL should be "--all --halt --wait"
  411. echo -n " SHUTDOWN_ALL "
  412. watchdog_xencmd shutdown 1 false &
  413. WDOG_PID=$!
  414. XMR=`$CMD shutdown $XENDOMAINS_SHUTDOWN_ALL 2>&1 1>/dev/null`
  415. if test $? -ne 0; then
  416. echo -e "\nAn error occurred while shutting down all domains: $XMR\n"
  417. rc_failed $?
  418. echo -e '!'
  419. fi
  420. kill $WDOG_PID >/dev/null 2>&1
  421. fi
  422. # Unconditionally delete lock file
  423. rm -f $LOCKFILE
  424. exec 2>&3
  425. }
  426. check_domain_up()
  427. {
  428. name=;id=
  429. while read LN; do
  430. parseln "$LN" || continue
  431. if test $id = 0; then continue; fi
  432. case $name in
  433. ($1)
  434. return 0
  435. ;;
  436. esac
  437. done < <($CMD list -l | grep '(\(domain\|domid\|name\)')
  438. return 1
  439. }
  440. check_all_auto_domains_up()
  441. {
  442. if ! contains_something "$XENDOMAINS_AUTO"
  443. then
  444. return 0
  445. fi
  446. missing=
  447. for nm in $XENDOMAINS_AUTO/*; do
  448. rdname $nm
  449. found=0
  450. if check_domain_up "$NM"; then
  451. echo -n " $name"
  452. else
  453. missing="$missing $NM"
  454. fi
  455. done
  456. if test -n "$missing"; then
  457. echo -n " MISS AUTO:$missing"
  458. return 1
  459. fi
  460. return 0
  461. }
  462. check_all_saved_domains_up()
  463. {
  464. if ! contains_something "$XENDOMAINS_SAVE"
  465. then
  466. return 0
  467. fi
  468. missing=`/bin/ls $XENDOMAINS_SAVE`
  469. echo -n " MISS SAVED: " $missing
  470. return 1
  471. }
  472. # This does NOT necessarily restart all running domains: instead it
  473. # stops all running domains and then boots all the domains specified in
  474. # AUTODIR. If other domains have been started manually then they will
  475. # not get restarted.
  476. # Commented out to avoid confusion!
  477. restart()
  478. {
  479. stop
  480. start
  481. }
  482. reload()
  483. {
  484. restart
  485. }
  486. case "$1" in
  487. start)
  488. start
  489. rc_status
  490. if test -f $LOCKFILE; then rc_status -v; fi
  491. ;;
  492. stop)
  493. stop
  494. rc_status -v
  495. ;;
  496. restart)
  497. restart
  498. ;;
  499. reload)
  500. reload
  501. ;;
  502. status)
  503. echo -n "Checking for xendomains:"
  504. if test ! -f $LOCKFILE; then
  505. rc_failed 3
  506. else
  507. check_all_auto_domains_up
  508. rc_status
  509. check_all_saved_domains_up
  510. rc_status
  511. fi
  512. rc_status -v
  513. ;;
  514. *)
  515. echo "Usage: $0 {start|stop|restart|reload|status}"
  516. rc_failed 3
  517. rc_status -v
  518. ;;
  519. esac
  520. rc_exit