pkgmgmt (13247B)
1 #!/bin/bash 2 # $Id$ 3 4 # Copyright (C) 2004,2005 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de> 5 # 6 # This program is free software; you can redistribute it and/or modify 7 # it under the terms of the GNU General Public License as published by 8 # the Free Software Foundation; version 2 of the License. 9 # 10 # This program is distributed in the hope that it will be useful, 11 # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 # GNU General Public License for more details. 14 # 15 # You should have received a copy of the GNU General Public License 16 # along with this program; if not, write to the Free Software 17 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 19 : ${UTIL_VSERVER_VARS:=/usr/lib/util-vserver/util-vserver-vars} 20 test -e "$UTIL_VSERVER_VARS" || { 21 echo $"Can not find util-vserver installation (the file '$UTIL_VSERVER_VARS' would be expected); aborting..." >&2 22 exit 1 23 } 24 . "$UTIL_VSERVER_VARS" 25 . "$_LIB_FUNCTIONS" 26 . "$_LIB_VSERVER_BUILD_FUNCTIONS" 27 . "$_LIB_VSERVER_BUILD_FUNCTIONS_PKGMGMT" 28 . "$_LIB_VSERVER_FUNCTIONS" 29 30 function showHelp() 31 { 32 echo \ 33 $"Usage: $0 --externalize|--internalize [-y] [--] <vserver-name> 34 35 Report bugs to <$PACKAGE_BUGREPORT>." 36 exit 0 37 } 38 39 function showVersion() 40 { 41 echo $"\ 42 vpkg $PACKAGE_VERSION -- shows information about packages in vservers 43 This program is part of $PACKAGE_STRING 44 45 Copyright (C) 2004,2005 Enrico Scholz 46 This program is free software; you may redistribute it under the terms of 47 the GNU General Public License. This program has absolutely no warranty." 48 exit 0 49 } 50 51 function init() 52 { 53 if test -z "$WORKAROUND_106057"; then 54 rpmdb_mntpoint=/dev 55 else 56 rpmdb_mntpoint=/.rpmdb 57 fi 58 } 59 60 function _createDirs() 61 { 62 for i; do 63 test -n "$i" || continue 64 mkdir -p -m755 "$i" 65 done 66 } 67 68 function _copySecure() 69 { 70 local chroot=$1 71 local srcdir=$2 72 local dstdir=$3 73 74 75 ( cd "$srcdir" && tar chf - '.' ) | \ 76 ( cd "$chroot" && $_EXEC_CD "$dstdir" $_TAR xf - ) 77 } 78 79 function _copySecureRev() 80 { 81 local chroot=$1 82 local srcdir=$2 83 local dstdir=$3 84 85 ( cd "$chroot" && $_EXEC_CD "$srcdir" $_TAR cf - '.' ) | \ 86 ( cd "$dstdir" && tar xf - ) 87 } 88 89 ## Usage: _substFile <filename> <sed-expression> 90 function _substFile() 91 { 92 local file=$1 93 local expr=$2 94 95 $_CHROOT_SH testfile "$file" || return 0 96 97 local tmp=$($_MKTEMP pkgmgmt_subst.XXXXXX) 98 trap "$_RM -f $tmp" EXIT 99 100 $_CHROOT_SH cat "$file" | \ 101 $_SED -e "$expr" >$tmp 102 103 $_CHROOT_SH cat "$file" | $_CMP -s $tmp - || \ 104 $_CHROOT_SH truncate "$file" <$tmp 105 106 $_RM -f $tmp 107 } 108 109 function _hashAuto() 110 { 111 local file=$1 112 local hash=$2 113 114 $_CHROOT_SH testfile "$file" || return 0 115 116 local tmp=$($_MKTEMP apt.conf.XXXXXX) 117 trap "$_RM -f $tmp" EXIT 118 119 $_CHROOT_SH cat "$file" | \ 120 $_SED -e "s|^\([^$hash].*@autogenerated@\)|$hash$hash\1|" >$tmp 121 122 $_CHROOT_SH cat "$file" | $_CMP -s $tmp - || \ 123 $_CHROOT_SH truncate "$file" <$tmp 124 125 $_RM -f $tmp 126 } 127 128 function _unhashAuto() 129 { 130 test -e "$1" || return 0 131 132 local hash=$2 133 local tmp=$($_MKTEMP apt.conf.XXXXXX) 134 trap "$_RM -f $tmp" EXIT 135 136 $_SED -e "s|^$hash$hash\(.*@autogenerated@\)|\1|" "$1" >$tmp 137 $_CMP -s "$tmp" "$1" || \ 138 $_CAT "$tmp" >"$1" 139 140 $_RM -f $tmp 141 } 142 143 function _mountFilesystemsInternal() 144 { 145 local fstab="$1" 146 test -e "$fstab" || return 0 147 shift 148 149 pushd "$vdir" >/dev/null 150 "$@" $_SECURE_MOUNT -n -a --chroot --fstab "$fstab" 151 popd >/dev/null 152 } 153 154 function _mountFilesystems() 155 { 156 local cfgdir 157 cfgdir=$($_VSERVER_INFO "$1" CFGDIR) || { 158 echo "Can not determine configuration directory for '$1'; ..." >&2 159 return 1 160 } 161 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1" 162 163 _mountFilesystemsInternal "$cfgdir"/fstab || return 1 164 _mountFilesystemsInternal "$cfgdir"/fstab.local || return 1 165 _mountFilesystemsInternal "$cfgdir"/fstab.remote "${CHBIND_CMD[@]}" || return 1 166 } 167 168 function _umountFilesystems() 169 { 170 local cfgdir 171 cfgdir=$($_VSERVER_INFO "$1" CFGDIR) || { 172 echo "Can not determine configuration directory for '$1'; ..." >&2 173 return 1 174 } 175 local vdir=$cfgdir/vdir 176 local is_ok=1 177 test -n "$_HAVE_CHBIND_OPTIONS" || _generateChbindOptions "$1" 178 179 pushd "$vdir/" >/dev/null || return 1 180 _umountVserverInternal "$cfgdir"/fstab.remote "${CHBIND_CMD[@]}" || is_ok= 181 _umountVserverInternal "$cfgdir"/fstab.local || is_ok= 182 _umountVserverInternal "$cfgdir"/fstab || is_ok= 183 popd >/dev/null || return 1 184 185 test -n "$is_ok" 186 } 187 188 # Usage: verifyInternalPackages <vserver> <style> 189 function verifyInternalPackages() 190 { 191 local pkgs res=0 192 local ERR="\ 193 The following errors occured while trying to internalize the 194 packagemanagement: 195 " 196 197 case $2 in 198 (RH) pkgs=$(vrpm "$1" -- -q --qf '---%{NAME}---\n' rpm apt yum urpmi "${YUM_RELEASEPKGS[@]}") 199 hasSubstring "$pkgs" ---rpm--- || { 200 warning "$ERR 201 * The vserver does not seem to have the 'rpm' package which is required 202 for internal package management. It is suggested to install it before 203 continuing." 204 res=1 205 ERR= 206 } 207 208 hasSubstring "$pkgs" ---apt--- ---yum--- ---urpmi--- || { 209 warning "$ERR 210 * The vserver does not seem to have a depsolver like 'apt' or 'yum' 211 installed. It is suggested to install such a program before setting 212 up internal package management." 213 res=1 214 ERR= 215 } 216 217 test -n "$have_apt" || test -n "$have_urpmi" || 218 test -z "$have_yum" || \ 219 hasSubstring "$pkgs" "${YUM_RELEASEPKGS[@]}" || { 220 warning "$ERR 221 * yum requires a special package which describes the version of the 222 distribution. Such a package could not be found within the vserver 223 so please install it before continuing. Usually, this package is 224 named 'redhat-release' of 'fedora-release'." 225 res=1 226 ERR= 227 } 228 ;; 229 esac 230 231 return $res 232 } 233 234 function processVserver_RH() 235 { 236 local vserver=$1 237 local is_internalize=$2 238 local have_apt 239 local have_yum 240 local have_urpmi 241 local cfgdir 242 local i 243 244 cfgdir=$($_VSERVER_INFO "$vserver" APPDIR pkgmgmt) || \ 245 cfgdir=$($_VSERVER_INFO "$vserver" APPDIR)/pkgmgmt 246 247 ## Figure out the environment.... 248 have_apt=1 249 have_yum=1 250 have_urpmi=1 251 pkgmgmt.isAptAvailable "$cfgdir" "$vdir" "$is_internalize" || have_apt= 252 pkgmgmt.isYumAvailable "$cfgdir" "$vdir" "$is_internalize" || have_yum= 253 pkgmgmt.isUrpmiAvailable "$cfgdir" "$vdir" "$is_internalize" || have_urpmi= 254 255 local APTETCDIR= 256 local APTSTATEDIR= 257 local APTCACHEDIR= 258 local APTARCHIVDIR= 259 local RPMETCDIR= 260 local RPMSTATEDIR= 261 262 ## Create directories and assign variables where configuration 263 ## can/will be found on the host 264 if test -n "$is_internalize"; then 265 verifyInternalPackages "$vserver" RH || test -n "$IS_FORCE" || 266 panic " 267 Can not continue; use '--force' to override this check" 268 269 pushd "$vdir" >/dev/null 270 271 test ! -L var/lib/rpm || { 272 $_EXEC_CD /var/lib $_RM rpm && 273 $_EXEC_CD /var/lib $_MKDIR -m755 rpm && 274 $_EXEC_CD /var/lib $_CHOWN rpm:rpm rpm || 275 : 276 } </dev/null 2>/dev/null 277 278 for i in var/cache/apt/{,archives/{,partial},genpkglist,gensrclist} \ 279 var/state/{,apt/{,lists/{,partial}}} \ 280 etc/apt etc/rpm; do 281 test -d "$i" || 282 $_EXEC_CD /$(dirname "$i") $_MKDIR -m755 $(basename "$i") || : 283 done #2>/dev/null 284 285 popd >/dev/null 286 287 if test -n "$have_apt"; then 288 findDir APTETCDIR "$cfgdir"/aptetc "$cfgdir"/base/apt/etc /etc/apt / 289 elif test -n "$have_urpmi"; then 290 findDir URPMISTATEDIR "$cfgdir"/base/var/lib/urpmi 291 findDir URPMIETCDIR "$cfgdir"/base/etc/urpmi 292 fi 293 294 findDir RPMETCDIR "$cfgdir"/rpmetc "$cfgdir"/base/rpm/etc \ 295 "$cfgdir"/base/etc/rpm /etc/rpm / 296 findDir RPMSTATEDIR "$cfgdir"/rpmstate "$cfgdir"/base/rpm/state \ 297 "$cfgdir"/base/var/lib/rpm 298 else 299 mkdir -m755 -p "$cfgdir" 300 local need_base= 301 302 if test -n "$have_apt"; then 303 findDir APTETCDIR "$cfgdir"/aptetc "$cfgdir"/base/apt/etc / 304 findDir APTSTATEDIR "$cfgdir"/aptstate "$cfgdir"/base/apt/state / 305 findDir APTCACHEDIR "$cfgdir"/aptcache "$cfgdir"/base/apt/cache / 306 findDir APTARCHIVDIR "$cfgdir"/aptarchives "$cfgdir"/base/apt/archives / 307 308 test "$APTETCDIR" != / || APTETCDIR=$cfgdir/base/apt/etc 309 test "$APTSTATEDIR" != / || APTSTATEDIR=$cfgdir/base/apt/state 310 test "$APTCACHEDIR" != / || APTCACHEDIR=$cfgdir/base/apt/cache 311 test "$APTARCHIVDIR" != / || APTARCHIVDIR=$cfgdir/base/apt/archive 312 313 test -d "$cfgdir"/aptetc -a -d "$cfgdir"/aptstate -a \ 314 -d "$cfgdir"/aptcache -a -d "$cfgdir"/aptarchives || need_base=1 315 fi 316 317 findDir RPMETCDIR "$cfgdir"/rpmetc "$cfgdir"/base/rpm/etc / 318 findDir RPMSTATEDIR "$cfgdir"/rpmstate "$cfgdir"/base/rpm/state / 319 320 test "$RPMETCDIR" != / || RPMETCDIR=$cfgdir/base/rpm/etc 321 test "$RPMSTATEDIR" != / || RPMSTATEDIR=$cfgdir/base/rpm/state 322 323 test -d "$cfgdir"/rpmetc -a -d "$cfgdir"/rpmstate || need_base=1 324 test ! -e "$cfgdir"/base || need_base= 325 326 test -z "$need_base" || ln -s "$PKGCFGDIR" "$cfgdir"/base 327 328 mkdir -m755 -p "$PKGCFGDIR" 329 _createDirs "$APTETCDIR" "$APTSTATEDIR" "$APTCACHEDIR" "$APTARCHIVDIR" \ 330 "$RPMETCDIR" "$RPMSTATEDIR" 331 fi 332 333 ## Copy the files... 334 if test -n "$is_internalize"; then 335 if test -n "$have_apt"; then 336 _copySecure "$vdir" "$APTETCDIR" /etc/apt 337 pushd "$vdir" >/dev/null 338 _hashAuto /etc/apt/apt.conf '/' 339 popd >/dev/null 340 elif test -n "$have_urpmi"; then 341 _copySecure "$vdir" "$URPMISTATEDIR" /var/lib/urpmi 342 _copySecure "$vdir" "$URPMIETCDIR" /etc/urpmi 343 fi 344 345 _copySecure "$vdir" "$RPMETCDIR" /etc/rpm 346 _copySecure "$vdir" "$RPMSTATEDIR" /var/lib/rpm 347 348 pushd "$vdir" >/dev/null 349 ## remove %_dbpath settings 350 _substFile /etc/rpm/macros '/^%_dbpath[ \t].*/D' 351 popd >/dev/null 352 else 353 if test -n "$have_apt"; then 354 _copySecureRev "$vdir" /etc/apt "$APTETCDIR" 355 _unhashAuto "$APTETCDIR"/apt.conf '/' 356 fi 357 358 _copySecureRev "$vdir" /etc/rpm "$RPMETCDIR" 359 _copySecureRev "$vdir" /var/lib/rpm "$RPMSTATEDIR" 360 361 echo -e "%_dbpath\t\t$rpmdb_mntpoint" >>$RPMETCDIR/macros 362 fi 363 364 ## Cleanups... 365 if test -n "$is_internalize"; then 366 : 367 else 368 tmpdir=$($_MKTEMPDIR -p /var/tmp pkgmgmt.XXXXXX) 369 trap "$_RM -rf $tmpdir" EXIT 370 pushd "$vdir" >/dev/null 371 $_EXEC_CD /var/lib $_MV rpm $tmpdir/ 372 $_EXEC_CD /var/lib $_LN_S "$rpmdb_mntpoint" rpm 373 $_RM -rf $tmpdir 374 fi 375 376 ## Finish it... 377 if test -n "$is_internalize"; then 378 $_TOUCH "$cfgdir"/internal 379 else 380 $_RM -f "$cfgdir"/internal 381 fi 382 } 383 384 function processVserver_Debian() 385 { 386 local vserver=$1 387 local is_internalize=$2 388 389 if test -n "$is_internalize"; then 390 echo $"Debian vservers should be internalized everytime; do not know how to handle '$vserver'" >&2 391 else 392 echo $"External packagemanagement is not supported for Debian vserver" >&2 393 fi 394 395 return 1 396 } 397 398 function processVserver() 399 { 400 local vserver=$1 401 local is_external= 402 local skip=1 403 local vdir 404 405 ! $_VSERVER_INFO -q "$vserver" RUNNING || { 406 echo $"Can not operate on running vservers; please stop '$vserver' and retry again..." 407 return 1 408 } >&2 409 410 vdir=$($_VSERVER_INFO "$vserver" VDIR) && test -d "$vdir" || { 411 echo $"Vserver '$vserver' does not seem to exist; skipping it..." 412 return 1 413 } >&2 414 415 _setVserverDir "$vserver" 416 _setVserverName 417 _setVserverDirName 418 pkgmgmt.initVariables 419 420 pkgmgmt.isInternal "$vserver" || is_external=1 421 422 case "$is_external"X"$IS_INTERNALIZE"X"$IS_EXTERNALIZE" in 423 (*X1X1) echo $"Can not externalize and internalize at the same time";; 424 (*XX) echo $"No operation specified; try '--help' for more information";; 425 (1XX1) echo $"Vserver '$vserver' has already external packagemanagment; skipping it...";; 426 (X1X) echo $"Vserver '$vserver' has already internal packagemanagment; skipping it...";; 427 (*) skip= 428 esac >&2 429 430 test -z "$skip" || return 1 431 432 local style 433 _mountFilesystems "$vserver" || return 1 434 pkgmgmt.guessStyle "$vserver" style || return 1 435 436 case "$style" in 437 (redhat|mandrake) processVserver_RH "$vserver" "$IS_INTERNALIZE";; 438 (debian) processVserver_Debian "$vserver" "$IS_INTERNALIZE";; 439 (*) 440 echo $"Vserver style '$style' is not supported for packagemanagment" >&2 441 return 1 442 esac 443 444 _umountFilesystems "$vserver" || return 1 445 } 446 447 tmp=$(getopt -o y --long debug,externalize,internalize,help,version,force -n "$0" -- "$@") || exit 1 448 eval set -- "$tmp" 449 450 IS_EXTERNALIZE= 451 IS_INTERNALIZE= 452 IS_YES= 453 IS_FORCE= 454 455 while true; do 456 case "$1" in 457 (--help) showHelp $0;; 458 (--version) showVersion;; 459 (--debug) set -x;; 460 (--externalize) IS_EXTERNALIZE=1;; 461 (--internalize) IS_INTERNALIZE=1;; 462 (--force) IS_FORCE=1;; 463 (-y) IS_YES=1;; 464 (--) shift; break;; 465 (*) echo $"vserver: internal error; arg=='$1'" >&2; exit 1;; 466 esac 467 shift 468 done 469 470 test -n "$1" || { 471 echo $"No vserver specified; try '--help' for more information" 472 exit 1 473 } >&2 474 475 476 set -e 477 init 478 479 ok=1 480 passed= 481 for i; do 482 processVserver "$i" && passed=1 || ok= 483 done 484 485 test -z "$ok" || exit 0 486 test -z "$passed" || exit 1 487 exit 2