#!/bin/sh # Copyright (C) 2000-2009, Parallels, Inc. All rights reserved. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # OpenVZ startup script, used for redhat and debian related distributions. ### # chkconfig: 2345 96 88 # description: OpenVZ startup script. ### ### BEGIN INIT INFO # Provides: vz # Required-start: $network $remote_fs $syslog # Required-stop: $network $remote_fs $syslog # Should-Start: sshd vzeventd # Should-Stop: sshd vzeventd # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: OpenVZ startup script # Description: OpenVZ startup script. ### END INIT INFO # This line is needed to cheat /etc/init.d/rc who expects action word . /etc/rc.d/init.d/functions . @SCRIPTDIR@/initd-functions VZQUOTA=@SBINDIR@/vzquota CONFIG_DIR=@PKGCONFDIR@/conf LOCKFILE=/var/lock/subsys/vz_lock SUBSYS_VZ=/var/lock/subsys/vz VESTAT=/proc/vz/vestat VZDEV=venet0 PRELOAD_MODULES= MODULES= MODULES_OTHER= NET_MODULES= IPT_MODULES= if [ "${MODULES_DISABLED}" != "yes" ]; then PRELOAD_MODULES="af_packet" MODULES="vzmon vzdquota vzdev" CPT_MODULES="vzcpt vzrst" MODULES_OTHER="vzcompat ${CPT_MODULES}" VNET_MODULES="vznetdev vznet" VETH_MODULES="vzethdev" NET_MODULES="${VNET_MODULES} ${VETH_MODULES}" if [ "${VZWDOG}" = "yes" ]; then MODULES="${MODULES} vzwdog" fi IPT_MODULES="ip_tables ${IPTABLES} xt_tcpudp" if [ "${IPV6}" = "yes" ]; then IPT_MODULES="${IPT_MODULES} ${IP6TABLES}" fi VZFS_MODULES="simfs" fi VEINFO="" RETVAL=0 # Number of the containers to stop in parallel. # In case of empty value the number of CTs is calculated as 'num_cpu * 4' PARALLEL= cd / check_kernel() { if ! test -d /proc/vz ; then fail print_warning "Running kernel is not OpenVZ kernel." exit 1 fi } get_kernel_version() { [ ! -z "$KERNEL_MAJOR" ] && return local ver=$(uname -r) local kernel=$(echo $ver | sed s/[-+].*//) KERNEL_MAJOR=$(echo $kernel | awk -F . '{print $1}') KERNEL_MINOR=$(echo $kernel | awk -F . '{print $2}') KERNEL_PATCHLEVEL=$(echo $kernel | awk -F . '{print $3}') } check_kernel_config() { test -r /proc/config.gz || return 0 local conf opt err=0 local opt_must="SIM_FS VE VE_CALLS VZ_GENCALLS" get_kernel_version # For kernels >= 2.6.9 VZ_DEV must be set. test "${KERNEL_MINOR}" -ge 6 && test "${KERNEL_PATCHLEVEL}" -gt 9 && opt_must="${opt_must} VZ_DEV" # local opt_rec="SCHED_VCPU FAIRSCHED VZ_QUOTA VZ_QUOTA_UGID VE_NETDEV VE_ETHDEV # VE_IPTABLES VZ_CHECKPOINT VZ_WDOG" conf="`zcat /proc/config.gz 2>/dev/null | grep -E -v '^#|^$'`" for opt in $opt_must; do if ! echo "$conf" 2>/dev/null | grep -q "$opt="; then show "ERROR: Missing kernel config option: CONFIG_$opt" err=1 fi done if [ $err != 0 ]; then fail print_warning "Please recompile your kernel." exit 1 fi } get_parallel() { [ -n "${PARALLEL}" ] && return PARALLEL=`awk ' BEGIN { num=0; } $1 == "processor" { num++; } END { print num * 4; }' /proc/cpuinfo` } get_veinfo() { if [ -f /proc/vz/veinfo ]; then VEINFO=/proc/vz/veinfo elif [ -f /proc/veinfo ]; then VEINFO=/proc/veinfo elif [ ! -f $VESTAT ]; then return 1 fi return 0 } is_running() { get_veinfo || return 1 [ -f $SUBSYS_VZ ] || return 1 } status() { check_kernel if is_running; then nls "OpenVZ is running..." return 0 else nls "OpenVZ is stopped." return 3 fi } start_net() { local mod # load all kernel modules needed for containers networking for mod in ${NET_MODULES}; do modprobe ${mod} 2>/dev/null done if ip addr list | grep -q "venet0:.*UP" 2>/dev/null; then return 0 fi get_veinfo if [ -z "$VEINFO" ]; then return 0 fi show "Bringing up interface $VZDEV" busy ok ip link set $VZDEV up ip addr add 0.0.0.0/0 dev $VZDEV if [ "${IPV6}" = "yes" ]; then ip -6 addr add fe80::1/128 dev $VZDEV fi sysctl -q -w net.ipv4.conf.$VZDEV.send_redirects=0 if [ "$(sysctl -n -e net.ipv4.ip_forward)" != "1" ]; then print_warning "Warning ! IP forwarding is not enabled !" fi } stop_net() { local mod if ip addr list | grep -q "venet0:.*UP" 2>/dev/null; then show "Bringing down interface $VZDEV" ip link set $VZDEV down print_result fi for mod in ${NET_MODULES}; do /sbin/modprobe -r ${mod} > /dev/null 2>&1 done } setup_ve0() { if test -z "${VE0CPUUNITS}"; then echo "Warning: VE0CPUUNITS is not set in ${VZCONF}; using value of 1000" VE0CPUUNITS=1000 fi msg=`${VZCTL} set 0 --cpuunits ${VE0CPUUNITS} 2>&1` if [ $? -ne 0 ]; then fail print_warning "vzctl set 0 --cpuunits ${VE0CPUUNITS} failed: $msg" fi if ! test -f "${CONFIG_DIR}/0.conf"; then return fi if ! grep -q '^ONBOOT=yes\|^ONBOOT=\"yes\"' ${CONFIG_DIR}/0.conf; then return fi show "Configure node UB resources: " msg=`$VZCTL set 0 --reset_ub 2>&1` print_result "$msg" } start_ves() { local veid local velist local msg local need_restart need_restart="" velist=$(vzlist -aH -octid,onboot -s-bootorder | awk '$2 == "yes" {print $1}') sysctl -q -w net.ipv4.route.src_check=0 for veid in $velist; do [ "${veid}" = "0" ] && continue show "Starting CT ${veid}" if [ "x${VZFASTBOOT}" = "xyes" -a "x${DISK_QUOTA}" = "xyes" ]; then $VZQUOTA stat ${veid} >/dev/null 2>&1 if [ $? -eq 6 ]; then if $VZQUOTA show ${veid} 2>&1 | grep "vzquota : (warning) Quota is running" >/dev/null 2>&1; then $VZQUOTA on ${veid} --nocheck >/dev/null 2>&1 need_restart="${need_restart} ${veid}" fi fi fi msg=`$VZCTL start ${veid} 2>&1` print_result "$msg" done for veid in ${need_restart}; do msg_stopping "CT ${veid}: " busy ok $VZCTL stop ${veid} 2>&1 >/dev/null 2>&1 print_result msg_starting "CT ${veid}: " busy ok msg=`$VZCTL start ${veid} 2>&1` print_result done } stop_ves() { local veid local velist local msg local m local mounts local fail local iter local quota local pids if get_veinfo; then get_parallel for i in 0 1 2; do iter=0; pids= velist=`awk '$1 != "VEID" && $1 != "Version:" {print $1}' ${VESTAT}` for veid in $velist; do msg_stopping "CT $veid" busy echo # Set fairsched parameters to maximum so # CT will stop fast $VZCTL set $veid --cpuunits 2000 --cpulimit 0 >/dev/null 2>&1 $VZCTL --skiplock stop $veid >/dev/null 2>&1 & pids="$pids $!" iter=$(($iter+1)) if [ ${iter} -gt ${PARALLEL} ]; then for pid in ${pids}; do wait ${pid} done pids= iter=0 fi done for pid in $pids; do wait $pid done done fi iter=0 fail=1 while test $iter -lt 5 -a $fail -ne 0; do fail=0 mounts=`awk '{if ($3=="simfs") print $2}' /proc/mounts` for m in $mounts; do show "Unmounting CT area " echo -n $m msg=`umount $m 2>&1` if [ $? -eq 0 ]; then ok else fail print_warning "$msg" fail=$((fail+1)) fuser -k -m ${m} > /dev/null 2>&1 fi done iter=$(($iter+1)) done # turn quota off quota=`awk -F: '/^[0-9]+:/{print $1}' /proc/vz/vzquota 2>/dev/null` for m in ${quota}; do show "Turn quota off for CT " echo -n $m msg=`vzquota off ${m} 2>&1` print_result "$msg" done } lockfile() { local TEMPFILE="${1}.$$" local LOCKFILE="${1}" trap -- "rm -f ${LOCKFILE} ${TEMPFILE}" EXIT echo $$ > ${TEMPFILE} 2> /dev/null || { echo "Can't write to ${TEMPFILE}" } ln ${TEMPFILE} ${LOCKFILE} >/dev/null 2>&1 && { rm -f ${TEMPFILE}; return 0; } kill -0 `cat $LOCKFILE` >/dev/null 2>&1 && { return 1; } ln ${TEMPFILE} ${LOCKFILE} >/dev/null 2>&1 && { rm -f ${TEMPFILE}; return 0; } rm -f ${LOCKFILE} echo $$ > ${LOCKFILE} return 0 } start() { local veid local velist local msg local mod check_kernel check_kernel_config if ! lockfile $LOCKFILE; then show "OpenVZ is locked" fail return 1 fi if [ -f ${SUBSYS_VZ} ]; then nls "OpenVZ already running" return 1 fi msg_starting "OpenVZ" if [ "$?" = "0" ]; then ok else fail fi load_modules "${IPT_MODULES}" for mod in $PRELOAD_MODULES; do /sbin/modprobe -r $mod >/dev/null 2>&1 /sbin/modprobe $mod >/dev/null 2>&1 done for mod in $MODULES; do /sbin/modprobe $mod >/dev/null 2>&1 RETVAL=$? if [ $RETVAL -ne 0 ]; then fail print_warning "failed to load module ${mod}" return $RETVAL fi done load_modules "${MODULES_OTHER} ${VZFS_MODULES}" show "loading OpenVZ modules" ok if [ ! -e /dev/vzctl ]; then # On most modern distros udev will create a device for you, # while on the old distros /dev/vzctl comes with vzctl rpm. # So the below mknod call is probably not needed at all. /bin/mknod -m 600 /dev/vzctl c 126 0 > /dev/null 2>&1 RETVAL=$? if [ $RETVAL -ne 0 ]; then fail print_warning "creating /dev/vzctl" return $RETVAL fi fi start_net setup_ve0 start_ves rm -f $LOCKFILE touch $SUBSYS_VZ } stop() { local mod # Avoid stop action inside a CT, check we are in CT0 if ! egrep -q '^[[:space:]]*0:[[:space:]]' \ /proc/user_beancounters; then print_failure "Looks like we are inside a container!" RETVAL=1 return 1 fi if ! lockfile $LOCKFILE; then show "OpenVZ is locked" fail RETVAL=1 return 1 fi stop_ves stop_net msg_stopping "OpenVZ" for mod in ${MODULES_OTHER} ${MODULES} ${PRELOAD_MODULES} ${IPT_MODULES} ${VZFS_MODULES}; do /sbin/modprobe -r ${mod} > /dev/null 2>&1 done rm -f $LOCKFILE rm -f $SUBSYS_VZ print_result } load_modules() { local modules=$1 local mod for mod in ${modules}; do if /sbin/lsmod | grep -qw ${mod}; then continue fi /sbin/modprobe ${mod} >/dev/null 2>&1 done } # See how we were called. case "$1" in start) start ;; stop) stop ;; restart|force-reload) stop start ;; status) status RETVAL=$? ;; *) echo "Usage: $0 {start|stop|status|restart|force-reload}" exit 1 esac exit $RETVAL