]>
Commit | Line | Data |
---|---|---|
88d20d00 TP |
1 | #!/bin/sh |
2 | # Copyright (C) 2000-2009, Parallels, Inc. All rights reserved. | |
3 | # | |
4 | # This program is free software; you can redistribute it and/or modify | |
5 | # it under the terms of the GNU General Public License as published by | |
6 | # the Free Software Foundation; either version 2 of the License, or | |
7 | # (at your option) any later version. | |
8 | # | |
9 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. | |
13 | # | |
14 | # You should have received a copy of the GNU General Public License | |
15 | # along with this program; if not, write to the Free Software | |
16 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
17 | # | |
18 | # | |
19 | # OpenVZ startup script, used for redhat and debian related distributions. | |
20 | ||
21 | ### | |
22 | # chkconfig: 2345 96 88 | |
23 | # description: OpenVZ startup script. | |
24 | ### | |
25 | ||
26 | ### BEGIN INIT INFO | |
27 | # Provides: vz | |
28 | # Required-start: $network $remote_fs $syslog | |
29 | # Required-stop: $network $remote_fs $syslog | |
30 | # Should-Start: sshd vzeventd | |
31 | # Should-Stop: sshd vzeventd | |
32 | # Default-Start: 2 3 4 5 | |
33 | # Default-Stop: 0 1 6 | |
34 | # Short-Description: OpenVZ startup script | |
35 | # Description: OpenVZ startup script. | |
36 | ### END INIT INFO | |
37 | ||
38 | ||
39 | # This line is needed to cheat /etc/init.d/rc who expects action word | |
40 | ||
41 | . /etc/rc.d/init.d/functions | |
1062ae9c | 42 | . @SCRIPTDIR@/initd-functions |
88d20d00 TP |
43 | |
44 | VZQUOTA=@SBINDIR@/vzquota | |
45 | CONFIG_DIR=@PKGCONFDIR@/conf | |
46 | LOCKFILE=/var/lock/subsys/vz_lock | |
47 | SUBSYS_VZ=/var/lock/subsys/vz | |
48 | VESTAT=/proc/vz/vestat | |
49 | VZDEV=venet0 | |
50 | PRELOAD_MODULES= | |
51 | MODULES= | |
52 | MODULES_OTHER= | |
53 | NET_MODULES= | |
54 | IPT_MODULES= | |
55 | ||
56 | if [ "${MODULES_DISABLED}" != "yes" ]; then | |
57 | PRELOAD_MODULES="af_packet" | |
58 | MODULES="vzmon vzdquota vzdev" | |
59 | CPT_MODULES="vzcpt vzrst" | |
60 | MODULES_OTHER="vzcompat ${CPT_MODULES}" | |
61 | VNET_MODULES="vznetdev vznet" | |
62 | VETH_MODULES="vzethdev" | |
63 | NET_MODULES="${VNET_MODULES} ${VETH_MODULES}" | |
64 | if [ "${VZWDOG}" = "yes" ]; then | |
65 | MODULES="${MODULES} vzwdog" | |
66 | fi | |
67 | IPT_MODULES="ip_tables ${IPTABLES} xt_tcpudp" | |
68 | if [ "${IPV6}" = "yes" ]; then | |
69 | IPT_MODULES="${IPT_MODULES} ${IP6TABLES}" | |
70 | fi | |
71 | VZFS_MODULES="simfs" | |
72 | fi | |
73 | ||
74 | ||
75 | VEINFO="" | |
76 | RETVAL=0 | |
77 | # Number of the containers to stop in parallel. | |
78 | # In case of empty value the number of CTs is calculated as 'num_cpu * 4' | |
79 | PARALLEL= | |
80 | cd / | |
81 | ||
82 | check_kernel() | |
83 | { | |
84 | if ! test -d /proc/vz ; then | |
85 | fail | |
86 | print_warning "Running kernel is not OpenVZ kernel." | |
87 | exit 1 | |
88 | fi | |
89 | } | |
90 | ||
91 | get_kernel_version() | |
92 | { | |
93 | [ ! -z "$KERNEL_MAJOR" ] && return | |
94 | ||
95 | local ver=$(uname -r) | |
96 | local kernel=$(echo $ver | sed s/[-+].*//) | |
97 | KERNEL_MAJOR=$(echo $kernel | awk -F . '{print $1}') | |
98 | KERNEL_MINOR=$(echo $kernel | awk -F . '{print $2}') | |
99 | KERNEL_PATCHLEVEL=$(echo $kernel | awk -F . '{print $3}') | |
100 | } | |
101 | ||
102 | check_kernel_config() | |
103 | { | |
104 | test -r /proc/config.gz || return 0 | |
105 | ||
106 | local conf opt err=0 | |
107 | local opt_must="SIM_FS VE VE_CALLS VZ_GENCALLS" | |
108 | get_kernel_version | |
109 | # For kernels >= 2.6.9 VZ_DEV must be set. | |
110 | test "${KERNEL_MINOR}" -ge 6 && | |
111 | test "${KERNEL_PATCHLEVEL}" -gt 9 && | |
112 | opt_must="${opt_must} VZ_DEV" | |
113 | # local opt_rec="SCHED_VCPU FAIRSCHED VZ_QUOTA VZ_QUOTA_UGID VE_NETDEV VE_ETHDEV | |
114 | # VE_IPTABLES VZ_CHECKPOINT VZ_WDOG" | |
115 | ||
116 | conf="`zcat /proc/config.gz 2>/dev/null | grep -E -v '^#|^$'`" | |
117 | ||
118 | for opt in $opt_must; do | |
119 | if ! echo "$conf" 2>/dev/null | grep -q "$opt="; then | |
120 | show "ERROR: Missing kernel config option: CONFIG_$opt" | |
121 | err=1 | |
122 | fi | |
123 | done | |
124 | if [ $err != 0 ]; then | |
125 | fail | |
126 | print_warning "Please recompile your kernel." | |
127 | exit 1 | |
128 | fi | |
129 | } | |
130 | ||
131 | get_parallel() | |
132 | { | |
133 | [ -n "${PARALLEL}" ] && return | |
134 | PARALLEL=`awk ' | |
135 | BEGIN { num=0; } | |
136 | $1 == "processor" { num++; } | |
137 | END { print num * 4; }' /proc/cpuinfo` | |
138 | } | |
139 | ||
140 | get_veinfo() | |
141 | { | |
142 | if [ -f /proc/vz/veinfo ]; then | |
143 | VEINFO=/proc/vz/veinfo | |
144 | elif [ -f /proc/veinfo ]; then | |
145 | VEINFO=/proc/veinfo | |
146 | elif [ ! -f $VESTAT ]; then | |
147 | return 1 | |
148 | fi | |
149 | return 0 | |
150 | } | |
151 | ||
152 | is_running() | |
153 | { | |
154 | get_veinfo || return 1 | |
155 | [ -f $SUBSYS_VZ ] || return 1 | |
156 | } | |
157 | ||
158 | status() | |
159 | { | |
160 | check_kernel | |
161 | ||
162 | if is_running; then | |
163 | nls "OpenVZ is running..." | |
164 | return 0 | |
165 | else | |
166 | nls "OpenVZ is stopped." | |
167 | return 3 | |
168 | fi | |
169 | } | |
170 | ||
171 | start_net() | |
172 | { | |
173 | local mod | |
174 | ||
175 | # load all kernel modules needed for containers networking | |
176 | for mod in ${NET_MODULES}; do | |
177 | modprobe ${mod} 2>/dev/null | |
178 | done | |
179 | ||
180 | if ip addr list | grep -q "venet0:.*UP" 2>/dev/null; then | |
181 | return 0 | |
182 | fi | |
183 | ||
184 | get_veinfo | |
185 | if [ -z "$VEINFO" ]; then | |
186 | return 0 | |
187 | fi | |
188 | show "Bringing up interface $VZDEV" | |
189 | busy | |
190 | ok | |
191 | ip link set $VZDEV up | |
192 | ||
193 | ip addr add 0.0.0.0/0 dev $VZDEV | |
194 | if [ "${IPV6}" = "yes" ]; then | |
195 | ip -6 addr add fe80::1/128 dev $VZDEV | |
196 | fi | |
197 | sysctl -q -w net.ipv4.conf.$VZDEV.send_redirects=0 | |
198 | if [ "$(sysctl -n -e net.ipv4.ip_forward)" != "1" ]; then | |
199 | print_warning "Warning ! IP forwarding is not enabled !" | |
200 | fi | |
201 | } | |
202 | ||
203 | stop_net() | |
204 | { | |
205 | local mod | |
206 | ||
207 | if ip addr list | grep -q "venet0:.*UP" 2>/dev/null; then | |
208 | show "Bringing down interface $VZDEV" | |
209 | ip link set $VZDEV down | |
210 | print_result | |
211 | fi | |
212 | for mod in ${NET_MODULES}; do | |
213 | /sbin/modprobe -r ${mod} > /dev/null 2>&1 | |
214 | done | |
215 | } | |
216 | ||
217 | setup_ve0() | |
218 | { | |
219 | if test -z "${VE0CPUUNITS}"; then | |
220 | echo "Warning: VE0CPUUNITS is not set in ${VZCONF}; using value of 1000" | |
221 | VE0CPUUNITS=1000 | |
222 | fi | |
223 | msg=`${VZCTL} set 0 --cpuunits ${VE0CPUUNITS} 2>&1` | |
224 | if [ $? -ne 0 ]; then | |
225 | fail | |
226 | print_warning "vzctl set 0 --cpuunits ${VE0CPUUNITS} failed: $msg" | |
227 | fi | |
228 | ||
229 | if ! test -f "${CONFIG_DIR}/0.conf"; then | |
230 | return | |
231 | fi | |
232 | if ! grep -q '^ONBOOT=yes\|^ONBOOT=\"yes\"' ${CONFIG_DIR}/0.conf; | |
233 | then | |
234 | return | |
235 | fi | |
236 | show "Configure node UB resources: " | |
237 | msg=`$VZCTL set 0 --reset_ub 2>&1` | |
238 | print_result "$msg" | |
239 | } | |
240 | ||
241 | start_ves() | |
242 | { | |
243 | local veid | |
244 | local velist | |
245 | local msg | |
246 | local need_restart | |
247 | ||
248 | need_restart="" | |
249 | velist=$(vzlist -aH -octid,onboot -s-bootorder | | |
250 | awk '$2 == "yes" {print $1}') | |
251 | sysctl -q -w net.ipv4.route.src_check=0 | |
252 | for veid in $velist; do | |
253 | [ "${veid}" = "0" ] && continue | |
254 | show "Starting CT ${veid}" | |
255 | if [ "x${VZFASTBOOT}" = "xyes" -a "x${DISK_QUOTA}" = "xyes" ]; | |
256 | then | |
257 | $VZQUOTA stat ${veid} >/dev/null 2>&1 | |
258 | if [ $? -eq 6 ]; then | |
259 | if $VZQUOTA show ${veid} 2>&1 | grep "vzquota : (warning) Quota is running" >/dev/null 2>&1; then | |
260 | $VZQUOTA on ${veid} --nocheck >/dev/null 2>&1 | |
261 | need_restart="${need_restart} ${veid}" | |
262 | fi | |
263 | fi | |
264 | fi | |
265 | msg=`$VZCTL start ${veid} 2>&1` | |
266 | print_result "$msg" | |
267 | done | |
268 | for veid in ${need_restart}; do | |
269 | msg_stopping "CT ${veid}: " | |
270 | busy | |
271 | ok | |
272 | $VZCTL stop ${veid} 2>&1 >/dev/null 2>&1 | |
273 | print_result | |
274 | msg_starting "CT ${veid}: " | |
275 | busy | |
276 | ok | |
277 | msg=`$VZCTL start ${veid} 2>&1` | |
278 | print_result | |
279 | done | |
280 | } | |
281 | ||
282 | stop_ves() | |
283 | { | |
284 | local veid | |
285 | local velist | |
286 | local msg | |
287 | local m | |
288 | local mounts | |
289 | local fail | |
290 | local iter | |
291 | local quota | |
292 | local pids | |
293 | ||
294 | if get_veinfo; then | |
295 | get_parallel | |
296 | for i in 0 1 2; do | |
297 | iter=0; | |
298 | pids= | |
299 | velist=`awk '$1 != "VEID" && $1 != "Version:" {print $1}' ${VESTAT}` | |
300 | for veid in $velist; do | |
301 | msg_stopping "CT $veid" | |
302 | busy | |
303 | echo | |
304 | # Set fairsched parameters to maximum so | |
305 | # CT will stop fast | |
306 | $VZCTL set $veid --cpuunits 2000 --cpulimit 0 >/dev/null 2>&1 | |
307 | $VZCTL --skiplock stop $veid >/dev/null 2>&1 & | |
308 | pids="$pids $!" | |
309 | iter=$(($iter+1)) | |
310 | if [ ${iter} -gt ${PARALLEL} ]; then | |
311 | for pid in ${pids}; do | |
312 | wait ${pid} | |
313 | done | |
314 | pids= | |
315 | iter=0 | |
316 | fi | |
317 | done | |
318 | for pid in $pids; do | |
319 | wait $pid | |
320 | done | |
321 | done | |
322 | fi | |
323 | iter=0 | |
324 | fail=1 | |
325 | while test $iter -lt 5 -a $fail -ne 0; do | |
326 | fail=0 | |
327 | mounts=`awk '{if ($3=="simfs") print $2}' /proc/mounts` | |
328 | for m in $mounts; do | |
329 | show "Unmounting CT area " | |
330 | echo -n $m | |
331 | msg=`umount $m 2>&1` | |
332 | if [ $? -eq 0 ]; then | |
333 | ok | |
334 | else | |
335 | fail | |
336 | print_warning "$msg" | |
337 | fail=$((fail+1)) | |
338 | fuser -k -m ${m} > /dev/null 2>&1 | |
339 | fi | |
340 | done | |
341 | iter=$(($iter+1)) | |
342 | done | |
343 | # turn quota off | |
344 | quota=`awk -F: '/^[0-9]+:/{print $1}' /proc/vz/vzquota 2>/dev/null` | |
345 | for m in ${quota}; do | |
346 | show "Turn quota off for CT " | |
347 | echo -n $m | |
348 | msg=`vzquota off ${m} 2>&1` | |
349 | print_result "$msg" | |
350 | done | |
351 | } | |
352 | ||
353 | lockfile() | |
354 | { | |
355 | local TEMPFILE="${1}.$$" | |
356 | local LOCKFILE="${1}" | |
357 | ||
358 | trap -- "rm -f ${LOCKFILE} ${TEMPFILE}" EXIT | |
359 | ||
360 | echo $$ > ${TEMPFILE} 2> /dev/null || { | |
361 | echo "Can't write to ${TEMPFILE}" | |
362 | } | |
363 | ln ${TEMPFILE} ${LOCKFILE} >/dev/null 2>&1 && { | |
364 | rm -f ${TEMPFILE}; | |
365 | return 0; | |
366 | } | |
367 | kill -0 `cat $LOCKFILE` >/dev/null 2>&1 && { | |
368 | return 1; | |
369 | } | |
370 | ln ${TEMPFILE} ${LOCKFILE} >/dev/null 2>&1 && { | |
371 | rm -f ${TEMPFILE}; | |
372 | return 0; | |
373 | } | |
374 | rm -f ${LOCKFILE} | |
375 | echo $$ > ${LOCKFILE} | |
376 | return 0 | |
377 | } | |
378 | ||
379 | start() | |
380 | { | |
381 | local veid | |
382 | local velist | |
383 | local msg | |
384 | local mod | |
385 | ||
386 | check_kernel | |
387 | check_kernel_config | |
388 | ||
389 | if ! lockfile $LOCKFILE; then | |
390 | show "OpenVZ is locked" | |
391 | fail | |
392 | return 1 | |
393 | fi | |
394 | if [ -f ${SUBSYS_VZ} ]; then | |
395 | nls "OpenVZ already running" | |
396 | return 1 | |
397 | fi | |
398 | msg_starting "OpenVZ" | |
399 | if [ "$?" = "0" ]; then | |
400 | ok | |
401 | else | |
402 | fail | |
403 | fi | |
404 | load_modules "${IPT_MODULES}" | |
405 | for mod in $PRELOAD_MODULES; do | |
406 | /sbin/modprobe -r $mod >/dev/null 2>&1 | |
407 | /sbin/modprobe $mod >/dev/null 2>&1 | |
408 | done | |
409 | for mod in $MODULES; do | |
410 | /sbin/modprobe $mod >/dev/null 2>&1 | |
411 | RETVAL=$? | |
412 | if [ $RETVAL -ne 0 ]; then | |
413 | fail | |
414 | print_warning "failed to load module ${mod}" | |
415 | return $RETVAL | |
416 | fi | |
417 | done | |
418 | load_modules "${MODULES_OTHER} ${VZFS_MODULES}" | |
419 | show "loading OpenVZ modules" | |
420 | ok | |
421 | ||
422 | if [ ! -e /dev/vzctl ]; then | |
423 | # On most modern distros udev will create a device for you, | |
424 | # while on the old distros /dev/vzctl comes with vzctl rpm. | |
425 | # So the below mknod call is probably not needed at all. | |
426 | /bin/mknod -m 600 /dev/vzctl c 126 0 > /dev/null 2>&1 | |
427 | RETVAL=$? | |
428 | if [ $RETVAL -ne 0 ]; then | |
429 | fail | |
430 | print_warning "creating /dev/vzctl" | |
431 | return $RETVAL | |
432 | fi | |
433 | fi | |
434 | ||
435 | start_net | |
436 | setup_ve0 | |
437 | start_ves | |
438 | ||
439 | rm -f $LOCKFILE | |
440 | touch $SUBSYS_VZ | |
441 | } | |
442 | ||
443 | stop() | |
444 | { | |
445 | local mod | |
446 | ||
447 | # Avoid stop action inside a CT, check we are in CT0 | |
448 | if ! egrep -q '^[[:space:]]*0:[[:space:]]' \ | |
449 | /proc/user_beancounters; then | |
450 | print_failure "Looks like we are inside a container!" | |
451 | RETVAL=1 | |
452 | return 1 | |
453 | fi | |
454 | ||
455 | if ! lockfile $LOCKFILE; then | |
456 | show "OpenVZ is locked" | |
457 | fail | |
458 | RETVAL=1 | |
459 | return 1 | |
460 | fi | |
461 | ||
462 | stop_ves | |
463 | stop_net | |
464 | msg_stopping "OpenVZ" | |
465 | for mod in ${MODULES_OTHER} ${MODULES} ${PRELOAD_MODULES} ${IPT_MODULES} ${VZFS_MODULES}; do | |
466 | /sbin/modprobe -r ${mod} > /dev/null 2>&1 | |
467 | done | |
468 | rm -f $LOCKFILE | |
469 | rm -f $SUBSYS_VZ | |
470 | print_result | |
471 | } | |
472 | ||
473 | load_modules() | |
474 | { | |
475 | local modules=$1 | |
476 | local mod | |
477 | ||
478 | for mod in ${modules}; do | |
479 | if /sbin/lsmod | grep -qw ${mod}; then | |
480 | continue | |
481 | fi | |
482 | /sbin/modprobe ${mod} >/dev/null 2>&1 | |
483 | done | |
484 | } | |
485 | ||
486 | # See how we were called. | |
487 | case "$1" in | |
488 | start) | |
489 | start | |
490 | ;; | |
491 | stop) | |
492 | stop | |
493 | ;; | |
494 | restart|force-reload) | |
495 | stop | |
496 | start | |
497 | ;; | |
498 | status) | |
499 | status | |
500 | RETVAL=$? | |
501 | ;; | |
502 | *) | |
503 | echo "Usage: $0 {start|stop|status|restart|force-reload}" | |
504 | exit 1 | |
505 | esac | |
506 | ||
507 | exit $RETVAL |