functions (27990B)
1 # $Id$ --*- sh -*-- 2 3 # Copyright (C) 2003,2004,2005,2006 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de> 4 # 5 # This program is free software; you can redistribute it and/or modify 6 # it under the terms of the GNU General Public License as published by 7 # the Free Software Foundation; version 2 of the License. 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 _VS_LOGFILE= 19 _VS_ERRFILE= 20 21 _VS_NEWLINE=' 22 ' 23 declare -r _VS_NEWLINE=${_VS_NEWLINE:0-1} 24 25 function findObject 26 { 27 local _fo_mod=$1 28 local _fo_var=$2 29 local _fo_file= 30 local _fo_i=X 31 shift 2 32 33 for _fo_i; do 34 test -n "$_fo_i" || continue 35 test ! $_fo_mod "$_fo_i" || { _fo_file=$_fo_i; break; } 36 done 37 38 test -z "$_fo_i" -o -n "$_fo_file" || { 39 echo "Can not find file for '$_fo_var'; aborting" 40 exit 1 41 } >&2 42 43 eval "$_fo_var=\"$_fo_file\"" 44 } 45 46 function findFile 47 { 48 findObject -f "$@" 49 } 50 51 function findDir 52 { 53 findObject -d "$@" 54 } 55 56 function findAndCopy 57 { 58 local dst=$1 59 test ! -s "$dst" || return 0 60 61 local tmp 62 shift 63 findFile tmp "$@" 64 65 test -n "$tmp" -a -s "$tmp" || return 0 66 $_CP -af "$tmp" "$dst" 67 } 68 69 ## Usage: isRegularFile <filename> [<mod>] 70 function isRegularFile 71 { 72 test ${2:--f} "$1" || return 1 73 74 case $1 in 75 (*.rpmsave|*.rpmnew|*.rpmorig|*.cfsaved*|*.~*~|*~) return 1;; 76 esac 77 78 return 0 79 } 80 81 function getPhysicalDir 82 { 83 ( set -P && cd "$1" && pwd ) 84 } 85 86 ## Usage:: isDirectoryEmpty <dir> [<ignore-lost+found>] 87 function isDirectoryEmpty 88 { 89 ( 90 shopt -s dotglob || * 91 shopt -s nullglob || * 92 93 ignore_lostfound=1 94 test -n "$2" -a "$2" != 0 || ignore_lostfound= 95 96 for i in "$1"/*; do 97 case "$i" in 98 ($1/lost+found) 99 test "$ignore_lostfound" || exit 1 100 ;; 101 (*) echo "$i"; exit 1 102 esac 103 done 104 105 exit 0 106 ) 107 } 108 109 ## Usage: logging <message> 110 function logging 111 { 112 if test -n "$_VS_LOGFILE"; then 113 echo "$@" >>"$_VS_LOGFILE" 114 else 115 echo "$@" 116 fi 117 } 118 119 ## Usage: warning <message> 120 function warning 121 { 122 if test -n "$_VS_ERRFILE"; then 123 echo "$@" >>"$_VS_ERRFILE" 124 else 125 echo "$@" >&2 126 fi 127 } 128 129 ## Usage: panic <message> 130 function panic 131 { 132 if test -n "$_VS_ERRFILE"; then 133 echo "$@" >>"$_VS_ERRFILE" 134 else 135 echo "$@" >&2 136 fi 137 138 exit 1 139 } 140 141 ## Usage: execute <message> 142 function execute 143 { 144 test -z "${DEBUG_EXEC:-}" || echo "$@" 145 test "${DEBUG_EXEC:-}" = noexec || exec "$@" 146 exit 0 147 } 148 149 150 ## Usage: spawn <message> 151 function spawn 152 { 153 test -z "${DEBUG_EXEC:-}" || echo "$@" 154 test "${DEBUG_EXEC:-}" = noexec || "$@" 155 } 156 157 ## Usage: isNumber <arg> 158 function isNumber 159 { 160 local tmp 161 let tmp=$1+0 2>/dev/null || test -z "${1//0/}" -a -n "$1" || return 1 162 return 0 163 } 164 165 ## Usage: hasSubstring <haystack> <needle>+ 166 function hasSubstring 167 { 168 local pat=$1 169 local i 170 171 shift 172 173 for i; do 174 test x"${pat/*$i*/$i}" = x"$i" || continue 175 return 0 176 done 177 178 return 1 179 } 180 181 ## Usage: colorize <style> <command> 182 function colorize 183 { 184 local style=$1 185 shift 186 187 if ! $_TTY -s; then 188 "$@" 189 else 190 local cfile 191 findFile cfile "$__CONFDIR"/.defaults/styles/"$style" '' 192 if test -n "$cfile"; then 193 $_CAT "$cfile" 194 else 195 case "$style" in 196 (bold) echo -ne "\e[1m";; 197 (emph) echo -ne "\e[34m";; 198 (info) echo -ne "\e[0;34m";; 199 (warn*) echo -ne "\e[1;31m";; 200 (error) echo -ne "\e[1;33;41m";; 201 (*) ;; 202 esac 203 fi 204 205 ( "$@" ) 206 echo -ne "\e[m" 207 fi 208 } 209 210 function colpanic 211 { 212 if test -n "$_VS_ERRFILE"; then 213 echo "$@" >>"$_VS_ERRFILE" 214 else 215 colorize error echo -n "$@" >&2 216 fi 217 echo 218 219 exit 1 220 } 221 222 function colwarning 223 { 224 colorize warning warning "$@" 225 } 226 227 function colinfo 228 { 229 colorize info echo "$@" 230 } 231 232 233 ## Usage: xtermTitle <title> 234 function xtermTitle 235 { 236 $_TTY -s || return 0 237 echo -ne "\e]0;$@\007" 238 } 239 240 _VS_LOCKS='' 241 ## Usage: lock <lockfile> [<timeout>] 242 function lock 243 { 244 local tmp=$($_MKTEMP vserver-lock.XXXXXX) 245 $_RM -f $tmp 246 $_MKFIFO -m600 $tmp 247 248 $_LOCKFILE "$1" $tmp $2 & 249 $_GREP -q true $tmp 2>/dev/null || return 1 250 251 _VS_LOCKS="$! $_VS_LOCKS" 252 } 253 254 ## Usage: unlock [<num>] 255 function unlock 256 { 257 local num=$1 258 local i 259 260 set -- $_VS_LOCKS 261 while test "$#" -gt 0; do 262 kill -HUP "$1" >/dev/null || : 263 shift 264 test "$num" != 1 || break 265 test -z "$num" || let --num 266 done 267 _VS_LOCKS="$@" 268 } 269 270 function get_init_cwd 271 { 272 if test -n "$INIT_CWD"; then 273 echo "$INIT_CWD" 274 else 275 pwd 276 fi 277 } 278 function set_init_cwd 279 { 280 INIT_CWD="`pwd`" 281 export INIT_CWD 282 } 283 284 function _setVserverDir 285 { 286 local vserver="$1" 287 case "$vserver" in 288 ./*) VSERVER_DIR="`get_init_cwd`/$vserver";; 289 /*) VSERVER_DIR="$vserver" ;; 290 *) VSERVER_DIR="$__CONFDIR/$vserver" ;; 291 esac 292 } 293 294 function _setVserverName 295 { 296 VSERVER_NAME=$(basename "$VSERVER_DIR") 297 } 298 299 function _pkgMountBindDir() 300 { 301 test "$1" != "$2" || return 0 302 303 $_MOUNT -n --bind "$1" "$2" 304 } 305 306 function _pkgSetVarsBase 307 { 308 case "$vserver" in 309 ./*|/*) 310 if test -d "$vserver/vdir"; then 311 BASEDIR=$vserver 312 VDIR=$(getPhysicalDir "$vserver/vdir") 313 314 PKGDIR=$BASEDIR/apps/pkgmgmt 315 test -d "$PKGDIR" || { 316 echo "Can not find configuration-directory for package-managment tools" 317 exit 1 318 } >&2 319 findDir EXECDIR $PKGDIR/execdir / 320 else 321 VDIR=$(getPhysicalDir "$vserver") 322 PKGDIR= 323 fi 324 ;; 325 *) 326 BASEDIR=$__CONFDIR/$vserver 327 test -d "$BASEDIR" || { 328 echo "Can not find configuration-directory" 329 exit 1 330 } >&2 331 332 VDIR=$BASEDIR/vdir 333 test -d "$VDIR" || VDIR=$__DEFAULT_VSERVERDIR/$vserver 334 VDIR=$(getPhysicalDir "$VDIR") 335 336 PKGDIR=$BASEDIR/apps/pkgmgmt 337 test -d "$PKGDIR" || { 338 echo "Can not find configuration-directory for package-managment tools" 339 exit 1 340 } >&2 341 342 findDir EXECDIR $PKGDIR/execdir / 343 344 ;; 345 esac 346 347 if test -z "$WORKAROUND_106057"; then 348 _rpmdb_mntpoint=/dev 349 else 350 _rpmdb_mntpoint=/.rpmdb 351 fi 352 } 353 354 function _pkgSetVarsRPM 355 { 356 if test -n "$PKGDIR"; then 357 findDir RPMETCDIR $PKGDIR/rpmetc $PKGDIR/base/rpm/etc \ 358 $PKGDIR/base/etc/rpm /etc/rpm 359 findDir RPMSTATEDIR $PKGDIR/rpmstate $PKGDIR/base/rpm/state \ 360 $PKGDIR/base/var/lib/rpm 361 362 findDir RPMLIBDIR $PKGDIR/rpmlib / 363 364 else 365 findDir RPMETCDIR "$VDIR"/etc/rpm /etc/rpm 366 findDir RPMSTATEDIR "$VDIR"/var/lib/rpm 367 RPMLIBDIR=/ 368 fi 369 370 RPMSTATEDIR=$(getPhysicalDir "$RPMSTATEDIR") 371 RPMETCDIR=$(getPhysicalDir "$RPMETCDIR") 372 } 373 374 function _pkgSetVarsApt 375 { 376 if test -n "$PKGDIR"; then 377 findDir APTETCDIR $PKGDIR/aptetc $PKGDIR/base/apt/etc /etc/apt 378 findDir APTSTATEDIR $PKGDIR/aptstate $PKGDIR/base/apt/state 379 findDir APTCACHEDIR $PKGDIR/aptcache $PKGDIR/base/apt/cache 380 findDir APTARCHIVDIR $PKGDIR/aptarchives $PKGDIR/base/apt/archives /var/cache/apt/archives 381 else 382 findDir APTETCDIR "$VDIR"/etc/apt /etc/apt 383 findDir APTSTATEDIR "$VDIR"/var/state/apt 384 findDir APTCACHEDIR "$VDIR"/var/cache/apt 385 findDir APTARCHIVDIR "$VDIR"/var/cache/apt/archives /var/cache/apt/archives 386 fi 387 388 findFile APT_CONFIG "$APTETCDIR"/apt.conf "" 389 test -z "$APT_CONFIG" || export APT_CONFIG 390 } 391 392 function _pkgSetVarsYum 393 { 394 if test -n "$PKGDIR"; then 395 findDir YUMETCDIR $PKGDIR/yumetc $PKGDIR/base/yum/etc /etc 396 findDir YUMCACHEDIR $PKGDIR/yumcache $PKGDIR/base/yum/cache 397 else 398 findDir YUMETCDIR "$VDIR"/etc /etc 399 findDir YUMCACHEDIR "$VDIR"/var/cache/yum 400 fi 401 } 402 403 function _pkgSetVarsUrpmi 404 { 405 if test -n "$PKGDIR"; then 406 findDir URPMIETCDIR $PKGDIR/urpmietc $PKGDIR/base/etc/urpmi /etc/urpmi 407 findDir URPMISTATEDIR $PKGDIR/urpmistate $PKGDIR/base/var/lib/urpmi 408 else 409 findDir URPMIETCDIR "$VDIR"/etc/urpmi /etc/urpmi 410 findDir URPMISTATEDIR "$VDIR"/var/lib/urpmi /var/lib/urpmi 411 fi 412 } 413 414 415 function _pkgMountBase 416 { 417 : 418 } 419 420 function _pkgMountApt 421 { 422 : 423 } 424 425 function _pkgMountYum 426 { 427 : 428 } 429 430 function _pkgMountUrpmi 431 { 432 _pkgMountBindDir "$RPMSTATEDIR" "$URPMISTATEDIR/../../../.rpmdb" 433 } 434 435 function _pkgMountRPM 436 { 437 _pkgMountBindDir "$RPMETCDIR" /etc/rpm 438 test "$RPMLIBDIR" = "/" || _pkgMountBindDir "$RPMLIBDIR" /usr/lib/rpm 439 440 pushd "$VDIR" >/dev/null 441 442 $_SECURE_MOUNT --chroot -n --bind "$RPMSTATEDIR" "$_rpmdb_mntpoint" 443 test -z "$WORKAROUND_106057" || mount -n --bind "$RPMSTATEDIR" "$_rpmdb_mntpoint" 444 445 test -e "$VDIR"/proc/self/status || \ 446 $_SECURE_MOUNT --chroot -n -t proc none /proc 447 448 popd >/dev/null 449 } 450 451 function _pkgSetEnvBase 452 { 453 test "$EXECDIR" = "/" || { 454 PATH=$EXECDIR:$PATH 455 LD_LIBRARY_PATH=$EXECDIR${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} 456 } 457 458 export PATH LD_LIBRARY_PATH 459 } 460 461 function _pkgSetEnvApt 462 { 463 : 464 } 465 466 function _pkgSetEnvYum 467 { 468 : 469 } 470 471 function _pkgSetEnvUrpmi 472 { 473 : 474 } 475 476 function _pkgSetEnvRPM 477 { 478 CUR_VSERVER=$vserver 479 RPM_FAKE_NAMESPACE_MOUNTS=$_rpmdb_mntpoint 480 RPM_BINARY=$_VRPM_PRELOAD 481 482 export CUR_VSERVER RPM_FAKE_NAMESPACE_MOUNTS RPM_BINARY 483 } 484 485 function pkgInit 486 { 487 local i 488 local vserver=$1 489 shift 490 491 _pkgSetVarsBase 492 for i; do 493 case "$i" in 494 rpm) _pkgSetVarsRPM;; 495 apt) _pkgSetVarsApt;; 496 yum) _pkgSetVarsYum;; 497 urpmi) _pkgSetVarsUrpmi;; 498 *) echo "Unknown packaging flavor" >&2; exit 1;; 499 esac 500 done 501 502 _pkgMountBase 503 for i; do 504 case "$i" in 505 rpm) _pkgMountRPM;; 506 apt) _pkgMountApt;; 507 yum) _pkgMountYum;; 508 urpmi) _pkgMountUrpmi;; 509 esac 510 done 511 512 _pkgSetEnvBase 513 for i; do 514 case "$i" in 515 rpm) _pkgSetEnvRPM;; 516 apt) _pkgSetEnvApt;; 517 yum) _pkgSetEnvYum;; 518 urpmi) _pkgSetEnvUrpmi;; 519 esac 520 done 521 522 _PKG_FLAVORS="$@" 523 _PKG_VSERVER=$vserver 524 } 525 526 function isAvoidNamespace 527 { 528 local cfgdir 529 530 $_VSERVER_INFO - FEATURE namespace || return 0 531 cfgdir=$($_VSERVER_INFO "$1" CFGDIR) || return 0 532 test ! -e "$cfgdir"/namespace || return 1 533 test -e "$__CONFDIR"/.defaults/nonamespace -o \ 534 -e "$cfgdir"/nonamespace 535 } 536 537 function isNamespaceCleanup 538 { 539 local cfgdir 540 541 $_VSERVER_INFO - FEATURE namespace || return 1 542 cfgdir=$($_VSERVER_INFO "$1" CFGDIR) || return 1 543 isAvoidNamespace "$1" && return 1 544 test -e "$cfgdir"/namespace-cleanup && return 0 545 test -e "$cfgdir"/nonamespace-cleanup -o \ 546 -e "$__CONFDIR"/.defaults/nonamespace-cleanup && return 1 547 return 0 548 } 549 550 ## Usage: mountTriggerAutomount <cfgdir> 551 function mountTriggerAutomount 552 { 553 local cfgdir=$1 554 local vdir=$1/vdir 555 local f 556 local r=0 557 558 for f in fstab fstab.local fstab.remote; do 559 local fstab=$cfgdir/$f 560 test -e "$fstab" || continue 561 562 pushd "$vdir" >/dev/null 563 $_SECURE_MOUNT --trigger-automount -a --fstab "$fstab" || rc=1 564 popd >/dev/null 565 done 566 567 return $rc 568 } 569 570 ## Usage: getAllVservers <var> [<KIND>*] 571 function getAllVservers 572 { 573 local _ga_i 574 declare -a _ga_tmp=() 575 local _ga_IFS="$IFS" 576 IFS=, 577 local -a _ga_marks=( $3 ) 578 IFS="$_ga_IFS" 579 580 for _ga_i in $__CONFDIR/*; do 581 isRegularFile "$_ga_i" -d || continue 582 583 test ! -e "$_ga_i"/disabled || continue 584 test -d "$_ga_i"/vdir || continue 585 586 local _ga_doadd=1 587 local _ga_markfile=$_ga_i/apps/init/mark 588 589 case ${2:-ALL} in 590 (MARKED) test -s "$_ga_markfile" || _ga_doadd=;; 591 (UNMARKED) test ! -s "$_ga_markfile" || _ga_doadd=;; 592 (STOPPED) ! $_VSERVER "$_ga_i" running &>/dev/null || _ga_doadd=;; 593 (RUNNING) $_VSERVER "$_ga_i" running &>/dev/null || _ga_doadd=;; 594 (ALL) ;; 595 (MARK) local _ga_j 596 local _ga_mark 597 local _ga_f=false 598 local _ga_invert=false 599 for _ga_j in "${_ga_marks[@]}"; do 600 _ga_mark="$(echo "$_ga_j" | $_SED 's/^[!~]//')" 601 test "$_ga_j" = "$_ga_mark" || _ga_invert=true 602 test -s "$_ga_markfile" && $_GREP -qx "$_ga_mark" "$_ga_markfile" && \ 603 _ga_f=true || : 604 done 605 test $_ga_f = $_ga_invert && \ 606 _ga_doadd= 607 ;; 608 (*) panic $"Unknown vserver tagging '$2'";; 609 esac 610 611 test -z "$_ga_doadd" || _ga_tmp=( "${_ga_tmp[@]}" "${_ga_i##$__CONFDIR/}") 612 done 613 614 eval $1='( "${_ga_tmp[@]}" )' 615 } 616 617 declare -r VS_ALLVSERVERS_ARGS=all,marked,unmarked,stopped,running,mark: 618 ## Usage: getAllVserversByArg <var> <arg> 619 function getAllVserversByArg 620 { 621 local _gav_mark= 622 local _gav_v="$1" 623 local _gav_first=1 624 local _gav_res=() 625 shift 626 627 while test "$#" -ge 1; do 628 local _gav_extra= 629 local _gav_tmp=() 630 631 case "$1" in 632 (--all) _gav_mark=ALL;; 633 (--marked) _gav_mark=MARKED;; 634 (--unmarked) _gav_mark=UNMARKED;; 635 (--stopped) _gav_mark=STOPPED;; 636 (--running) _gav_mark=RUNNING;; 637 (--mark*) _gav_mark=MARK 638 _gav_extra=${_gav_i##*=} 639 test -n "$_gav_extra" -a "$_gav_extra" != "--mark" || \ 640 _gav_extra="$2" 641 shift 642 ;; 643 (--) break;; 644 (*) set -- "$_gav_v" "$@" 645 return 1;; 646 esac 647 648 getAllVservers _gav_tmp "$_gav_mark" $_gav_extra 649 if test -n "$_gav_first"; then 650 _gav_res=( "${_gav_tmp[@]}" ) 651 else 652 local _gav_i=0 653 local _gav_n="${#_gav_res[@]}" 654 while test $_gav_i -lt $_gav_n; do 655 local _gav_found=0 656 for _gav_j in "${_gav_tmp[@]}"; do 657 if test "$_gav_j" = "${_gav_res[$_gav_i]}"; then 658 _gav_found=1 659 break 660 fi 661 done 662 if test "$_gav_found" = 0; then 663 unset _gav_res[$_gav_i] 664 fi 665 let ++_gav_i 666 done 667 _gav_res=( "${_gav_res[@]}" ) 668 fi 669 shift 670 _gav_first= 671 done 672 eval $_gav_v='( "${_gav_res[@]}" )' 673 } 674 675 ## Usage: _getProcNumberCount <ctx> <var> 676 function _getProcNumberCount 677 { 678 local _gp_var=$2 679 local _gp_procnr_cnt=0 680 681 # Use /proc/virtual from kernel 2.6 when possible 682 if test -d "/proc/virtual"; then 683 set -- $($_GREP '^Tasks:' "/proc/virtual/$1/status" 2>/dev/null) 684 _gp_procnr_cnt=$2 685 else 686 _gp_procnr_cnt=$($_VPS ax | $_AWK '{print $2}' | $_GREP -x "$1" | $_WC -l ) 687 fi 688 689 let _gp_procnr_cnt=_gp_procnr_cnt+0 690 eval $_gp_var=\$_gp_procnr_cnt 691 } 692 693 ## Usage: getVserverCtx <vdir> <result-varname> [<procnumber-varname> [<do-cleanup>]] 694 ## Returns: 0 iff vserver is running 695 function getVserverStatus 696 { 697 test -r "$1"/run || return 1 698 699 local _gvs_ctx 700 read _gvs_ctx <"$1"/run 701 eval "$2"=\$_gvs_ctx 702 703 if test "$1" = "$($_VUNAME -g --xid "$_gvs_ctx" context)"; then 704 test -n "$3" || return 0 705 local _gvs_tmp 706 _getProcNumberCount "$_gvs_ctx" _gvs_tmp 707 eval "$3"=\$_gvs_tmp 708 else 709 test -n "$3" || return 1 710 eval "$3"=0 711 _gvs_tmp=0 712 fi 713 714 if test "$_gvs_tmp" = 0; then 715 local runfile=$($_READLINK "$1/run") 716 test -z "$4" || $_RM -f "$runfile" 717 return 1 718 fi 719 720 return 0 721 } 722 723 ## Usage: isCtxRunning <ctx> 724 function isCtxRunning 725 { 726 local _tmp 727 _getProcNumberCount "$1" _tmp 728 test $_tmp -gt 0 729 } 730 731 ## Usage: isVserverRunning <vdir> [<ctx-varname>] 732 function isVserverRunning 733 { 734 local _ivr_ctx _ivr_procnum 735 736 getVserverStatus "$1" _ivr_ctx _ivr_procnum 1 || return 1 737 test "$_ivr_procnum" != 0 || return 1 738 test -z "$2" || eval "$2"=\$_ivr_ctx 739 return 0 740 } 741 742 ## Called as 'getFileValue <varname> <filename>+' 743 function getFileValue 744 { 745 local _gfv_var=$1 746 local _gfv_file 747 shift 748 749 findFile _gfv_file "$@" '' 750 test -n "$_gfv_file" -a -r "$_gfv_file" || return 0 751 eval read "$_gfv_var" <"$_gfv_file" 752 } 753 754 ## Called as 'getFileArray <varname> <filename>+' 755 function getFileArray 756 { 757 local _gfa_var=$1 758 local _gfa_file 759 shift 760 761 findFile _gfa_file "$@" '' 762 test -n "$_gfa_file" -a -r "$_gfa_file" || return 0 763 local IFS=$_VS_NEWLINE 764 eval "$_gfa_var"='( $(< "$_gfa_file") )' 765 } 766 767 function checkComponents 768 { 769 local i 770 local msg=$1 771 local x_failed= 772 773 shift 774 775 for i; do 776 local failed= 777 case "$i" in 778 (core) test -x "$_CHBIND" || failed=1;; 779 (build) test -x "$_VSERVER_BUILD" || failed=1;; 780 (sysv) test -x "$__INITRDDIR/vserver" || failed=1;; 781 (devel) test -d "$__INCLUDEDIR/vserver.h" || failed=1;; 782 (*) echo "Unknown component '$i'" >&2 783 return false 784 ;; 785 esac 786 787 test -z "$failed" || { 788 echo "$msg: $i" 789 x_failed=1 790 } >&2 791 done 792 793 test -z "$x_failed" 794 } 795 796 ## Usage: isKernelAPI <ver> [<cmp-modifier>] 797 function isKernelAPI 798 { 799 local api 800 api=$($_VSERVER_INFO - APIVER) || api=0 801 test $[ $api ] -${2:-ge} $[ $1 ] 802 } 803 804 ## Usage: callInNamespace <vserver> <command> <args>* 805 function callInNamespace 806 { 807 local ctx= 808 809 isAvoidNamespace "$1" || \ 810 ctx=$( $_VSERVER_INFO "$1" CONTEXT f ) || ctx= 811 812 shift 813 if test -n "$ctx"; then 814 $_VSPACE "${OPTS_VSPACE[@]}" --mount --fs --enter "$ctx" -- "$@" 815 else 816 "$@" 817 fi 818 } 819 820 ## Usage: setDefaultTTY <vdir> [<fallback-tty>] 821 function setDefaultTTY 822 { 823 local cfgdir ttyname 824 825 cfgdir=$($_VSERVER_INFO "$1" APPDIR init) || cfgdir= 826 findObject -e ttyname \ 827 ${cfgdir:+"$cfgdir"/tty} \ 828 "$__CONFDIR/.defaults/apps/init/tty" \ 829 $2 /dev/null 830 831 if test -f "$ttyname"; then 832 exec </dev/null 833 else 834 exec <$ttyname 835 fi 836 exec >>$ttyname 2>&1 837 } 838 839 ## Usage: killContext <XID> [<SIG>] 840 function killContext 841 { 842 local sig=${2:-9} 843 844 #$_VKILL -s STOP --xid "$1" 1 &>/dev/null || : 845 $_VKILL -s "$sig" --xid "$1" 1 &>/dev/null || : 846 $_VKILL -s "$sig" --xid "$1" &>/dev/null || : 847 #$_VKILL -s "$sig" --xid "$1" 1 &>/dev/null || : 848 #$_VKILL -s CONT --xid "$1" 1 &>/dev/null || : 849 } 850 851 function useVlogin 852 { 853 test ! -e "$__CONFDIR/.defaults/apps/vlogin/disable" 854 } 855 856 ## Usage: pkgmgmt.guessStyle <vserver> <resultvar> 857 function pkgmgmt.guessStyle() 858 { 859 local _pgs_vdir 860 _pgs_vdir=$($_VSERVER_INFO "$1" VDIR) || { 861 echo $"Can not determine vserver-root" >&2 862 return 1 863 } 864 local _pgs_cfgdir=$($_VSERVER_INFO "$1" APPDIR pkgmgmt) || : 865 866 if test -n "$_pgs_cfgdir" -a -e "$_pgs_cfgdir"/style; then 867 read style <"$_pgs_cfgdir"/style 868 elif test -e "$_pgs_vdir"/etc/redhat-release -o -e "$_pgs_vdir"/etc/fedora-release; then 869 style=redhat 870 elif test -e "$_pgs_vdir"/etc/mandrake-release; then 871 style=mandrake 872 elif test -e "$_pgs_vdir"/etc/debian_version; then 873 style=debian 874 elif test -e "$_pgs_vdir"/etc/SuSE-release; then 875 style=suse 876 else 877 echo $"Can not determine packagemanagement style" >&2 878 return 1 879 fi 880 881 eval $2=\$style 882 return 0 883 } 884 885 ## Usage: pkgmgmt.isInternal <vserver> 886 ## returns true iff <vserver> is configured for internal packagemanagement 887 ## A typical application is 888 ## | is_external= 889 ## | pkgmgmt.isInternal "$vserver" || is_external=1 890 function pkgmgmt.isInternal 891 { 892 local cfgdir=$($_VSERVER_INFO "$1" APPDIR pkgmgmt) || : 893 894 test -z "$cfgdir" -o ! -d "$cfgdir" -o -e "$cfgdir"/internal 895 } 896 897 ## Usage: pkgmgmt.isAptAvailable <cfgdir> <vdir> [<is-internal>] 898 function pkgmgmt.isAptAvailable 899 { 900 local cfgdir="$1" 901 local vdir="$2" 902 local is_internal="$3" 903 904 local have_apt i 905 if test -n "$is_internal"; then 906 have_apt=1 907 test -d "$cfgdir"/base/apt -o -d "$cfgdir"/aptetc || have_apt= 908 else 909 have_apt= 910 for i in /bin /usr/bin /usr/local/bin; do 911 test ! -x "$vdir$i"/apt-get || { have_apt=1; break; } 912 done 913 fi 914 915 test -n "$have_apt" && return 0 || return 1 916 } 917 918 ## Usage: pkgmgmt.isYumAvailable <cfgdir> <vdir> [<is-internal>] 919 function pkgmgmt.isYumAvailable 920 { 921 local cfgdir="$1" 922 local vdir="$2" 923 local is_internal="$3" 924 925 local have_yum i 926 if test -n "$is_internal"; then 927 have_yum=1 928 test -d "$cfgdir"/base/yum -o -d "$cfgdir"/yumetc || have_yum= 929 else 930 have_yum= 931 for i in /bin /usr/bin /usr/local/bin; do 932 test ! -x "$vdir$i"/yum || { have_yum=1; break; } 933 done 934 fi 935 936 test -n "$have_yum" && return 0 || return 1 937 } 938 939 ## Usage: pkgmgmt.isUrpmiAvailable <cfgdir> <vdir> [<is-internal>] 940 function pkgmgmt.isUrpmiAvailable 941 { 942 local cfgdir="$1" 943 local vdir="$2" 944 local is_internal="$3" 945 946 local have_urpmi i 947 if test -n "$is_internal"; then 948 have_urpmi=1 949 test -d "$cfgdir"/base/var/lib/urpmi || have_urpmi= 950 else 951 have_urpmi= 952 for i in /bin /usr/bin /usr/local/bin; do 953 test ! -x "$vdir$i"/urpmi || { have_urpmi=1; break; } 954 done 955 fi 956 957 test -n "$have_urpmi" && return 0 || return 1 958 } 959 960 961 function vshelper.doSanityCheck 962 { 963 local vshelper this_xid i 964 declare -a warnings=() 965 local solution_disable= 966 local solution_sysctl= 967 968 vshelper.isEnabled && vshelper.isEnabled warning || return 0 969 970 this_xid=$($_VSERVER_INFO - XID) || 971 panic $"Failed to determine current context; aborting..." 972 973 ## Do nothing in other xid's; the helper will be executed in xid 0 only 974 test "$this_xid" = 0 || return 0 975 976 local proc_file=/proc/sys/kernel/vshelper 977 978 if ! test -r "$proc_file"; then 979 vshelper= 980 warnings=( "${warnings[@]}" 981 $"File '$proc_file' does not exist but is required for vshelper setup" ) 982 solution_disable=1 983 else 984 vshelper=$(cat "$proc_file") 985 986 $_CMP -s "$vshelper" "$_VSHELPER" || { 987 local readable="" 988 test -r "$vshelper" && readable=1 989 warnings=( "${warnings[@]}" 990 $"The configured vshelper '$vshelper' does not match the 'vshelper' 991 script of the util-vserver package.${readable:+ Maybe you have two versions installed?}" 992 ) 993 solution_disable=1 994 solution_sysctl=1 995 } 996 fi 997 998 test -d "$__VSHELPERSTATEDIR" || { 999 warnings=( "${warnings[@]}" 1000 $"\ 1001 The vshelper state-directory '$__VSHELPERSTATEDIR' does not exist; since 1002 it is created by 'make install', this indicates a serious problem with 1003 your util-vserver installation" ) 1004 solution_disable=1 1005 } 1006 1007 test "${#warnings[@]}" -eq 0 || { 1008 warning $"\ 1009 The following problem(s) were encountered while verifying vshelper 1010 functionality:" 1011 1012 for i in "${warnings[@]}"; do 1013 warning "* $i" 1014 done 1015 1016 warning $"\ 1017 1018 To fix this, you can:" 1019 1020 test -z "$solution_disable" || warning $"\ 1021 * disable vshelper entirely by executing 1022 | touch \"$__CONFDIR/.defaults/apps/vshelper/disabled\" 1023 * disable only this message by executing 1024 | touch \"$__CONFDIR/.defaults/apps/vshelper/warning-disabled\"" 1025 1026 test -x "$solution_sysctl" || warning $"\ 1027 * configure the util-vserver vshelper script, e.g. by adding 1028 | kernel.vshelper = $_VSHELPER 1029 to /etc/sysctl.conf and rebooting the machine, or by executing 1030 | echo \"$_VSHELPER\" >$proc_file" 1031 1032 warning "" 1033 1034 return 1 1035 } 1036 1037 return 0 1038 } 1039 1040 ## Usage: vshelper.isEnabled [<style>] [<vserver>] 1041 function vshelper.isEnabled 1042 { 1043 local f=${1:+$1-}disabled 1044 test ! -e "$__CONFDIR"/.defaults/apps/vshelper/"$f" || return 1 1045 $_VSERVER_INFO - FEATURE vshelper || return 1 1046 if test -n "$2"; then 1047 local appdir 1048 appdir=$($_VSERVER_INFO "$2" APPDIR vshelper) || return 0 1049 test -z "$2" -o ! -e "$appdir/$f" || return 1 1050 fi 1051 1052 return 0 1053 } 1054 1055 ## Usage: vshelper.isDebug [<vserver>] 1056 function vshelper.isDebug 1057 { 1058 test ! -e "$__CONFDIR"/.defaults/apps/vshelper/debug || return 0 1059 $_VSERVER_INFO - FEATURE vshelper || return 1 1060 if test -n "$1"; then 1061 local appdir 1062 appdir=$($_VSERVER_INFO "$1" APPDIR vshelper) || return 1 1063 test ! -e "$appdir/debug" || return 0 1064 fi 1065 1066 return 1 1067 } 1068 1069 function vshelper._getHandlerInternal 1070 { 1071 local _vghi_var=$1 1072 local _vghi_tmp 1073 shift 1074 shift ## HACK: see below the note about the 'set -u' mode 1075 1076 while test "$#" -ge 2; do 1077 local _vghi_mod=$1 1078 local _vghi_obj=$2 1079 shift 2 1080 1081 test "$_vghi_mod" "$_vghi_obj" || continue 1082 case "$_vghi_mod" in 1083 (-x) 1084 eval $_vghi_var=\$_vghi_obj 1085 ;; 1086 (-e) 1087 read _vghi_tmp <"$_vghi_obj" 1088 eval $_vghi_var=:\$_vghi_tmp 1089 ;; 1090 (*) panic $"Internal error, unexpected modifier '$_vghi_mod'" 1091 esac 1092 return 0 1093 done 1094 1095 return 1 1096 } 1097 1098 ## Usage: vshelper.getHandler <result-var> <vserver> <action> 1099 function vshelper.getHandler 1100 { 1101 local _vgh_appdir 1102 _vgh_appdir=$($_VSERVER_INFO "$2" APPDIR vshelper) || _vgh_appdir= 1103 1104 declare -a _vgh_search_list=( X ) 1105 ## HACK: when we are in 'set -u' mode, empty lists are causing errors 1106 1107 test -z "$_vgh_appdir" || _vgh_search_list=( "${_vgh_search_list[@]}" -x "$_vgh_appdir/$3" ) 1108 test -z "$_vgh_appdir" || _vgh_search_list=( "${_vgh_search_list[@]}" -e "$_vgh_appdir/action" ) 1109 _vgh_search_list=( "${_vgh_search_list[@]}" -x "$__CONFDIR"/.defaults/apps/vshelper/"$3" ) 1110 _vgh_search_list=( "${_vgh_search_list[@]}" -e "$__CONFDIR"/.defaults/apps/vshelper/action ) 1111 1112 ! vshelper._getHandlerInternal "$1" "${_vgh_search_list[@]}" || return 0 1113 eval $1=':restart' 1114 } 1115 1116 ## Usage: vshelper.init <vserver> [<method> <args>*] 1117 function vshelper.doInit 1118 { 1119 vshelper.isEnabled || return 0 1120 1121 local xid 1122 xid=$($_VSERVER_INFO "$1" CONTEXT false) && test -n "$xid" || { 1123 warning $"vshelper.init: can not determine xid of vserver '$vserver'; returned value was '$xid' 1124 1125 This usually means that you're using an init-less init-style, but the 1126 guest isn't configured to start any service. Try enabling a service, 1127 changing the init-style, or making the contexts persistent." 1128 return 1 1129 } 1130 1131 local f="$__VSHELPERSTATEDIR/$xid" 1132 1133 set -C 1134 $_RM -f "$f" 1135 echo "$1" >"$f" 1136 set +C 1137 1138 if test -n "$2"; then 1139 shift 1 1140 local i 1141 for i; do 1142 echo "$i" 1143 done 1144 else 1145 echo "default" 1146 fi >>"$f" 1147 1148 return 0 1149 } 1150 1151 ## Usage: vshelper.doDestroy <vserver> <xid> 1152 function vshelper.doDestroy 1153 { 1154 vshelper.isEnabled || return 0 1155 1156 $_RM -f "$__VSHELPERSTATEDIR/$2" 1157 } 1158 1159 ## Usage: vshelper.initSync <vserver> <pipe-varname> [<method>] 1160 function vshelper.initSync 1161 { 1162 local _vis_tmpdir 1163 _vis_tmpdir=$($_MKTEMPDIR vserver-stop.XXXXXX) || { 1164 warning $"Failed to generate temporary directory for vshelper sync" 1165 return 1 1166 } 1167 1168 local _vis_fifo="$_vis_tmpdir"/pipe 1169 $_MKFIFO -m700 "$_vis_fifo" 1170 vshelper.doInit "$1" "${3:-sync}" "$_vis_fifo" 1171 eval $2=\$_vis_fifo 1172 } 1173 1174 ## Usage: vshelper.getSyncTimeout <vserver> <varname> 1175 function vshelper.getSyncTimeout 1176 { 1177 local _vgst_appdir _vgst_file _vgst_tmp 1178 _vgst_appdir=$($_VSERVER_INFO "$1" APPDIR vshelper) || _vgst_appdir= 1179 1180 findFile _vgst_file ${_vgst_appdir:+"$_vgst_appdir"/sync-timeout} "$__CONFDIR"/.defaults/apps/vshelper/sync-timeout '' 1181 test -n "$_vgst_file" || return 1 1182 read _vgst_tmp <"$_vgst_file" 1183 eval $2=\$_vgst_tmp 1184 } 1185 1186 function vshelper.initStopSync 1187 { 1188 local _iss_sync_dir=$($_MKTEMPDIR vshelper-stop-sync.XXXXXX) || { 1189 warning $"Failed to generate directory for vshelper sync" 1190 exit 1 1191 } 1192 $_MKFIFO -m700 "$_iss_sync_dir/pipe" 1193 1194 eval "$1"=\$_iss_sync_dir 1195 VSHELPER_STOP_SYNC="$_iss_sync_dir/pipe" 1196 export VSHELPER_STOP_SYNC 1197 } 1198 1199 function vshelper.waitForStopSync 1200 { 1201 local sync_dir=$1 1202 cat "$sync_dir/pipe" &> /dev/null 1203 rm -fr "$sync_dir" 1204 } 1205 1206 function vshelper.doStopSync 1207 { 1208 test ! -p "$VSHELPER_STOP_SYNC" || echo stopped > "$VSHELPER_STOP_SYNC" 1209 } 1210 1211 function vshelper.isStopSync 1212 { 1213 test -p "$VSHELPER_STOP_SYNC" || return 1 1214 return 0 1215 } 1216 1217 function _rpmFake.getCapFlags 1218 { 1219 local ctx=$1 1220 1221 if test -n "$ctx" && ! $_VSERVER_INFO - FEATURE migrate; then 1222 set -- $($_CHCONTEXT_COMPAT --xid 1 \ 1223 $_SH -c "$_CAT /proc/[0-9]*/status | $_EGREP '^(CapBset|s_context|ctxflags)'" | \ 1224 $_GREP -B 1 -A 1 "^s_context: $ctx " | \ 1225 $_SED -e '1,3p;d' | $_AWK '{ print $2 }') 1226 else 1227 set -- 1228 fi 1229 1230 if test -n "$3"; then 1231 RPM_FAKE_CAP=$[ ~0x$1 ] 1232 RPM_FAKE_FLAGS=$3 1233 else 1234 RPM_FAKE_CAP=$[ ~0xd40c04ff ] 1235 RPM_FAKE_FLAGS=4 1236 fi 1237 } 1238 1239 function rpmFake.init 1240 { 1241 local vdir ctx 1242 1243 vdir=$($_VSERVER_INFO "$1" VDIR) || vdir="$1" 1244 ctx=$($_VSERVER_INFO "$1" CONTEXT) || ctx= 1245 1246 test -d "$vdir" || 1247 panic $"Can not find chroot environment at '$vdir' for '$1'" 1248 1249 _rpmFake.getCapFlags "$ctx" 1250 1251 RPM_FAKE_CHROOT=$vdir 1252 RPM_FAKE_CTX=$ctx 1253 } 1254 1255 function rpmFake.exec 1256 { 1257 export RPM_FAKE_CHROOT RPM_FAKE_CTX RPM_FAKE_CAP RPM_FAKE_FLAGS 1258 1259 LD_PRELOAD=$_RPM_FAKE_SO${LD_PRELOAD:+:$LD_PRELOAD} \ 1260 exec "$@" 1261 }