Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
#!/bin/bash # # /etc/init.d/virtdomains # Start / stop guests automatically when host boots / shuts down. # # chkconfig: 345 99 00 # description: Start / stop Xen/KVM guests. # # This script offers fairly basic functionality. It should work on Redhat # but also on LSB-compliant SuSE releases and on Debian with the LSB package # installed. (LSB is the Linux Standard Base) # # Based on the example in the "Designing High Quality Integrated Linux # Applications HOWTO" by Avi Alkalay # # # Revised by T.Nonogaki, Stray Penguin # # Rev.0.1.2 # ### BEGIN INIT INFO # Provides: virtdomains # Required-Start: $syslog $remote_fs libvirtd # Should-Start: # Required-Stop: $syslog $remote_fs libvirtd # Should-Stop: # Default-Start: 3 4 5 # Default-Stop: 0 1 2 6 # Default-Enabled: yes # Short-Description: Start/stop xen/KVM guests # Description: Start / stop guests automatically when host # boots / shuts down. ### END INIT INFO # Correct exit code would probably be 5, but it's enough # if xend complains if we're not running as privileged domain #if ! [ -e /proc/xen/privcmd ]; then # exit 0 #fi service libvirtd status > /dev/null || exit 0 LOCKFILE=/var/lock/subsys/virtdomains XENDOM_CONFIG=/etc/sysconfig/virtdomains test -r $XENDOM_CONFIG || { echo "$XENDOM_CONFIG not existing"; if [ "$1" = "stop" ]; then exit 0; else exit 6; fi; } . $XENDOM_CONFIG # Use the SUSE rc_ init script functions; # emulate them on LSB, RH and other systems if test -e /etc/rc.status; then # SUSE rc script library . /etc/rc.status else _cmd=$1 declare -a _SMSG if test "${_cmd}" = "status"; then _SMSG=(running dead dead unused unknown) _RC_UNUSED=3 else _SMSG=(done failed failed missed failed skipped unused failed failed) _RC_UNUSED=6 fi if test -e /etc/init.d/functions; then # REDHAT . /etc/init.d/functions echo_rc() { #echo -n " [${_SMSG[${_RC_RV}]}] " if test ${_RC_RV} = 0; then success " [${_SMSG[${_RC_RV}]}] " echo else failure " [${_SMSG[${_RC_RV}]}] " echo fi } elif test -e /lib/lsb/init-functions; then # LSB . /lib/lsb/init-functions if alias log_success_msg >/dev/null 2>/dev/null; then echo_rc() { echo " [${_SMSG[${_RC_RV}]}] " } else echo_rc() { if test ${_RC_RV} = 0; then log_success_msg " [${_SMSG[${_RC_RV}]}] " else log_failure_msg " [${_SMSG[${_RC_RV}]}] " fi } fi else # emulate it echo_rc() { echo " [${_SMSG[${_RC_RV}]}] " } fi rc_reset() { _RC_RV=0; } rc_failed() { if test -z "$1"; then _RC_RV=1; elif test "$1" != "0"; then _RC_RV=$1; fi return ${_RC_RV} } rc_check() { return rc_failed $? } rc_status() { rc_failed $? if test "$1" = "-r"; then _RC_RV=0; shift; fi if test "$1" = "-s"; then rc_failed 5; echo_rc; rc_failed 3; shift; fi if test "$1" = "-u"; then rc_failed ${_RC_UNUSED}; echo_rc; rc_failed 3; shift; fi if test "$1" = "-v"; then echo_rc; shift; fi if test "$1" = "-r"; then _RC_RV=0; shift; fi return ${_RC_RV} } rc_exit() { exit ${_RC_RV}; } rc_active() { if test -z "$RUNLEVEL"; then read RUNLEVEL REST < <(/sbin/runlevel); fi if test -e /etc/init.d/S[0-9][0-9]${1}; then return 0; fi return 1 } fi if ! which usleep &>/dev/null then usleep() { if [ -n "$1" ] then sleep $(( $1 / 1000000 )) fi } fi # Reset status of this service rc_reset ## # Returns 0 (success) if the given parameter name is a directory, and # that directory is not empty. contains_something() { if [ -d "$1" ] && [ `/bin/ls $1 | wc -l` -gt 0 ] then return 0 else return 1 fi } # Assume the first non empty, non comment line of the given file # reads a domain name. # Returns 0 (success) if a line is found, 1 if the given argument is # not a file, 2 if the file doesn't contain a valid line. get_dn_from_f() { local dn="" [ -f "$1" ] || return 1 dn=$(cat $1 | /bin/grep -Ev '^[[:space:]]*(#|$)' | /usr/bin/head -n 1) [ -z "$dn" ] && return 2 echo $dn return 0 } # Read a name from virsh output. rdname() { local nm nm=$(env LANG=C virsh dominfo ${1##*/} 2>/dev/null | /bin/awk '/^Name:[[:space:]]+/ { print $2; exit; }') echo $nm } # Generate a string suitable for "case" matching expression from the # content of the files under XENDOMAINS_AUTO directory. rdnames() { local dom fl dom nm NAMES= if ! contains_something "$XENDOMAINS_AUTO" then return fi for fl in $XENDOMAINS_AUTO/*; do dom=$(get_dn_from_f $fl) nm=$(rdname $dom) if test -z "$NAMES"; then NAMES=$nm; else NAMES="$NAMES|$nm" fi done } # Return 0 (true) if the given domain is up (includes running, paused, # dying or zombies as well). Return 1 (false) if and only if state is # "shut off". is_running() { local nm nm=$(rdname $1) RC=1 while read LN; do read id name state < <(echo "$LN") if [ "$id" = "Id" -o -z "${id##-*-}" ]; then continue; fi if [ "$id" = "0" -o "$state" = "shut off" ]; then continue; fi case $name in $nm) RC=0 break ;; esac done < <(env LANG=C virsh list --all 2>/dev/null) return $RC } # Starts or restores guest domains. start() { local RETVAL fl dom saved_domains autodoms nm if [ -f $LOCKFILE ]; then echo -n "virtdomains already running (lockfile exists)" rc_failed return; fi [ -d $(dirname "$LOCKFILE") ] || mkdir -p $(dirname "$LOCKFILE") if contains_something "$XENDOMAINS_AUTO" then # Start all domains with files in XENDOMAINS_AUTO. # We expect files for auto starting domains to be in XENDOMAINS_AUTO # - each file must contain a line that match the name of the domain. # You can manage the starting order through file names, since this # sorts the files before processing. # NOTE: This order is respected only when STARTing domains. # RESTORing doesn't take this into account for now. # # TODO: We should record which domain name belongs # so we have the option to selectively shut down / migrate later # If a domain statefile from $XENDOMAINS_SAVE matches a domain name # in $XENDOMAINS_AUTO, do not try to start that domain; if it didn't # restore correctly it requires administrative attention. saved_domains=" " if [ "$XENDOMAINS_RESTORE" = "true" ] && contains_something "$XENDOMAINS_SAVE"; then rdnames echo -n "Restoring guest domains: " saved_domains=`ls $XENDOMAINS_SAVE` for dom in $XENDOMAINS_SAVE/*; do case ${dom##*/} in $NAMES) # do nothing ;; *) continue ;; esac echo -n "${dom##*/} " virsh restore $dom &>/dev/null RETVAL=$? if [ $RETVAL -ne 0 ]; then rc_failed $RETVAL echo -n '!' else touch $LOCKFILE #mv $dom ${dom%/*}/.${dom##*/} #rm $dom fi echo -n ". " done HAVE_SAVE=1 fi [ $HAVE_SAVE -eq 1 ] && echo echo -n "Starting auto guest domains: " autodoms=($(ls -1 $XENDOMAINS_AUTO |sort)) for fl in ${autodoms[@]}; do nm=$(get_dn_from_f ${XENDOMAINS_AUTO}/$fl) if [ $? -ne 0 ]; then continue fi echo -n "$nm" echo $saved_domains | grep -qw $nm >/dev/null if [ $? -eq 0 ]; then echo -n "(skip)" elif is_running $nm; then echo -n "(skip)" else echo -n " " virsh start $nm &>/dev/null RETVAL=$? if [ $RETVAL -ne 0 ]; then rc_failed $RETVAL echo -n '!' else touch $LOCKFILE usleep $XENDOMAINS_CREATE_USLEEP fi HAVE_AUTO=1 fi echo -n ". " done [ $HAVE_AUTO -eq 1 ] || echo fi } # Return TRUE if it seems only zombie domains (not in shutdown process) # left, FALSE if no domains left or found any shutting-down healthily. # FIXME: Are these check conditions correct? all_zombies() { local all=0 local zomb=0 while read LN; do read id name state < <(echo "$LN") if [ "$id" = "Id" -o -z "${id##-*-}" ]; then continue; fi if [ "$id" = "0" -o "$state" = "shut off" ]; then continue; fi : $((all++)) case $state in dying) : $((zomb++)) ;; *) # do nothing ;; esac done < <(env LANG=C virsh list --all 2>/dev/null) [ $all -eq 0 ] && return 1 [ $all -eq $zomb ] && return 0 return 1 } # Call syntax: watchdog_vm $dom [force] # Wait for max $XENDOMAINS_STOP_MAXWAIT for a guest to shutdown; # if it has not exited by that time kill it, so the init script will # succeed within a finite amount of time; if force is added, # it will kill the guest immediately. watchdog_vm() { local dom PSAX opt local force=0 : ${XENDOMAINS_STOP_MAXWAIT:=0} dom=$1 if [ -n "$2" ]; then [ $2 = force ] && force=1 fi usleep 300000 for no in `seq 0 $XENDOMAINS_STOP_MAXWAIT`; do # go to kill immediately if force flag was set if [ $force -eq 1 ]; then break fi # exit if save/migrate/shutdown is finished if ! is_running $dom; then return; fi echo -n "."; sleep 1 done sleep 1 # If the domain still left - # give it another polite try is_running $dom || return 0 echo -n "(shut)." virsh shutdown $dom &>/dev/null # then forcibly destroy is_running $dom || return 0 echo -n "(destroy)." virsh destroy $dom &>/dev/null is_running $dom || return 0 # finally kill the qemu-kvm process PSAX=$(ps axlww | grep qemu-kvm | grep "-name $dom" | grep -v grep) read PSF PSUID PSPID PSPPID < <(echo "$PSAX") echo -n "(TERM)." kill $PSPID &>/dev/null PSAX=$(ps axlww | grep qemu-kvm | grep "-name $dom" | grep -v grep) test -z "$PSAX" && return 0 echo -n "(KILL)." kill -s KILL $PSPID &>/dev/null return 0 } stop() { local RETVAL id name state # Collect list of domains to shut down if test "$XENDOMAINS_AUTO_ONLY" = "true"; then rdnames fi echo -n "Shutting down guest domains: " if ! check_domains_left; then rm -f $LOCKFILE RETVAL=0 return 0 fi while read LN; do read id name state < <(echo "$LN") if [ "$id" = "Id" -o -z "${id##-*-}" ]; then continue; fi if [ "$id" = "0" -o -z "$id" ]; then continue; fi if [ "$state" != "running" ]; then continue; fi echo -n "$name" if test "$XENDOMAINS_AUTO_ONLY" = "true"; then case $name in $NAMES) # nothing ;; *) echo "(skip). " continue ;; esac fi if test "$state" = "dying"; then echo -n "(zomb). " continue fi if test -n "$XENDOMAINS_MIGRATE"; then echo -n "(migr)" virsh migrate $name $XENDOMAINS_MIGRATE &>/dev/null RETVAL=$? if [ $RETVAL -ne 0 ]; then rc_failed $RETVAL echo -n '!. ' else watchdog_vm $name echo -n ". " continue fi fi if test -n "$XENDOMAINS_SAVE"; then echo -n "(save)" mkdir -p "$XENDOMAINS_SAVE" virsh save $name ${XENDOMAINS_SAVE}/$name &>/dev/null RETVAL=$? if [ $RETVAL -ne 0 ]; then rc_failed $RETVAL echo -n '!. ' else watchdog_vm $name echo -n ". " continue fi fi if test -n "$XENDOMAINS_SHUTDOWN"; then # XENDOMAINS_SHUTDOWN should be "--halt --wait" echo -n "(shut)" virsh shutdown $name &>/dev/null RETVAL=$? if [ $RETVAL -ne 0 ]; then rc_failed $RETVAL echo -n '!' else watchdog_vm $name fi echo -n ". " fi done < <(env LANG=C virsh list --all 2>/dev/null) # NB. this stops ALL guest domains, not just the ones in AUTODIR/* # This is because it's easier to do ;-) but arguably if this script is run # on system shutdown then it's also the right thing to do. if test -n "$XENDOMAINS_SHUTDOWN_ALL"; then if ! all_zombies; then # XENDOMAINS_SHUTDOWN_ALL should be "--all --halt --wait" if ! check_domains_left; then rm -f $LOCKFILE return fi echo echo -n "SHUTDOWN_ALL " while read LN; do read id name state < <(echo "$LN") if [ "$id" = "Id" -o -z "${id##-*-}" ]; then continue; fi if [ "$id" = "0" -o -z "$id" ]; then continue; fi if [ "$state" = "shut off" ]; then continue; fi echo -n "$name" if [ "$state" = "running" ]; then echo -n "(shut)" virsh shutdown $name &>/dev/null RETVAL=$? if [ $RETVAL -ne 0 ]; then rc_failed $RETVAL echo -n '! ' else watchdog_vm $name echo -n ". " fi else watchdog_vm $name force echo -n ". " fi done < <(env LANG=C virsh list --all 2>/dev/null) fi fi # Unconditionally delete lock file rm -f $LOCKFILE } check_domain_up() { while read LN; do read id name state < <(echo "$LN") if [ "$id" = "Id" -o -z "${id##-*-}" ]; then continue; fi if [ "$id" = "0" -o -z "$id" ]; then continue; fi if [ "$state" != "running" ]; then continue; fi case $name in $1) return 0 ;; esac done < <(env LANG=C virsh list --all 2>/dev/null) return 1 } check_domains_left() { while read LN; do read id name state < <(echo "$LN") if [ "$id" = "Id" -o -z "${id##-*-}" ]; then continue; fi if [ "$id" = "0" -o -z "$id" ]; then continue; fi case $state in "shut off") continue;; *) return 0 ;; esac done < <(env LANG=C virsh list --all 2>/dev/null) return 1 } check_all_auto_domains_up() { local fl nm dom missing if ! contains_something "$XENDOMAINS_AUTO" then return 0 fi missing= for fl in $XENDOMAINS_AUTO/*; do dom=$(get_dn_from_f $fl) [ $? -ne 0 ] && continue nm=$(rdname $dom) if check_domain_up "$nm"; then echo -n " $nm" else missing="$missing $nm" fi done if test -n "$missing"; then echo -n " MISS AUTO:$missing" return 1 fi return 0 } check_all_saved_domains_up() { local missing if ! contains_something "$XENDOMAINS_SAVE" then return 0 fi missing=`/bin/ls $XENDOMAINS_SAVE` echo -n " MISS SAVED: " $missing return 1 } # This does NOT necessarily restart all running domains: instead it # stops all running domains and then boots all the domains specified in # AUTODIR. If other domains have been started manually then they will # not get restarted. # Commented out to avoid confusion! restart() { stop rc_status -v start rc_status } reload() { restart } HAVE_SAVE=0 HAVE_AUTO=0 case "$1" in start) start rc_status if test -f $LOCKFILE; then rc_status -v; fi ;; stop) stop rc_status -v ;; restart) restart ;; reload) reload ;; status) echo -n "Checking for virtdomains:" if test ! -f $LOCKFILE; then rc_failed 3 else check_all_auto_domains_up rc_status #check_all_saved_domains_up #rc_status fi rc_status -v ;; *) echo "Usage: $0 {start|stop|restart|reload|status}" rc_failed 3 rc_status -v ;; esac rc_exit