#! /bin/bash # $Id$ #********************************************************************* # # fai-mirror -- create and manage a partitial mirror for FAI # # This script is part of FAI (Fully Automatic Installation) # (c) 2004-2005, Thomas Lange, lange@informatik.uni-koeln.de # #********************************************************************* # 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; see the file COPYING. If not, write to the # Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, # MA 02111-1307, USA. #********************************************************************* version="Version 1.4.2, 23-nov-2005" # variables: NFSROOT, FAI_CONFIGDIR # NFSROOT_PACKAGES, packages from make-fai-nfsroot.conf debdist=sarge set -a . /etc/fai/fai.conf . /etc/fai/make-fai-nfsroot.conf FAI_ROOT=/ # do not execute in chroot set +a trap "umount_dirs" EXIT ERR # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - usage() { echo "fai-mirror -- create and manage a partitial mirror for FAI." echo "$version" echo "Please the the manual page fai-mirror(1)." exit } # - - - - - - - - - - - - - - - - - - - - - - - - - - die() { local e=$1 # first parameter is the exit code shift echo "$@" # print error message exit $e } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - excludeclass() { # removes/excludes all classes in $* from $classes local insert eclasses newclass c e eclasses="$*" eclasses=${eclasses//,/ } for c in $classes; do insert=1 for e in $eclasses; do [ $c = $e ] && insert=0 done [ $insert = 1 ] && newclass="$newclass $c" done classes="$newclass" } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - get_addpackages() { # add packages (mostly kernels) which are defined in the variable $addpackages # TODO: maybe better to create a tmp file with all these package # names, then to call install_packages for the tmp file local f p pkg pkglist for f in $(echo $FAI_CONFIGDIR/class/*.var); do pkg=$(egrep ^addpackages= $f | sed 's/addpackages=//'|sed 's/"//g'| perl -pe 's/\$[\w_-]+//g') [ -n "$pkg" ] && pkglist="$pkglist $pkg" done [ -z "$pkglist" ] && return 0 echo -n "Adding packages from variable \$addpackages:" # loop over the list, because maybe some packages doesn't exist in the # partitial mirror, but only in the local repository. These can't be # downloaded via the normal method for p in $pkglist; do echo -n " $p" # test if .deb file is available if [ ! -f $FAI_CONFIG/files/packages/${p}_*.deb ]; then apt-get $qflag -d $aptoptions -y --force-yes --fix-missing install $p fi done echo "" } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - umount_dirs() { [ "$FAI_DEBMIRROR" ] && umount $FAI_ROOT/$MNTPOINT 2>/dev/null 1>&2 || true } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - cleandirs() { return # currently nothing to do # rm $statefile # rm -rf $mirrordir/.apt-move $statefile # [ $debug -eq 1 ] || rm -rf $aptcache $archivedir # rm -rf $aptcache $archivedir } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - initialize() { # TODO: root is only needed when FAI_DEBMIRROR is defined. Then we # must mount a directory # store all packages temporary in the mirror partition so we need only a move, # not a copy later during apt-move aptcache=$mirrordir/aptcache # holds the package cache data archivedir=$aptcache/var/cache/apt/archives aptmovefile=$aptcache/etc/apt-move.conf # stores apt-move.conf statefile=$aptcache/statefile # also used in install_pacakges.conf export aptoptions=" \ -o Aptitude::Log=/dev/null \ -o DPkg::force-conflicts::=yes \ -o Dir::State::status=$statefile \ -o Dir::Cache=$aptcache/var/cache/apt \ -o Dir::State=$aptcache/var/cache/apt \ -o Dir::Cache::Archives=$archivedir \ -o Dir::Etc::sourcelist=$aptcache/etc/apt/sources.list \ -o Dir::State::Lists=$aptcache/var/lib/apt/lists/" # not needed # -o APT::Get::ReInstall # ."-o APT::Get::Download-Only=true -o Aptitude::Cmd-Line::Download-Only=true " # we only need some empty dirs mkdir -p $archivedir/partial $aptcache/etc/apt mkdir -p $aptcache/var/lib/apt/lists/partial > $statefile } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - delete_base_packages() { # now delete all packages that are already included in base.tgz local p if [ ! -f $NFSROOT/var/tmp/base-pkgs.lis ]; then echo "$NFSROOT/var/tmp/base-pkgs.lis not available." echo "Can't remove wasteful packages that are already in base.tgz." return fi echo "Removing packages that are already included in base.tgz" for p in $(cat $NFSROOT/var/tmp/base-pkgs.lis); do if [ -f $archivedir/${p}_*.deb ]; then [ $verbose -eq 1 ] && echo "deleting package $p" rm $archivedir/${p}_*.deb # else commands only for debugging # else # echo "package $p not found" # ls $archivedir/${p}_*.deb fi done } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - add_base_packages() { local plist # add packages from base.tgz and additional packages in nfsroot echo "Adding packages from base.tgz and packages defined in make-fai-nfsroot.conf." if [ -f $NFSROOT/var/tmp/base-pkgs.lis ]; then plist=$(< $NFSROOT/var/tmp/base-pkgs.lis) apt-get $qflag -d $aptoptions -y --force-yes --fix-missing install $plist fi # arch dependent packages defined in make-fai-nfsroot if [ -f $NFSROOT/var/tmp/packages.arch ]; then plist=$(< $NFSROOT/var/tmp/packages.arch) apt-get $qflag -d $aptoptions -y --force-yes --fix-missing install $plist fi # also add packages defined in make-fai-nfsroot.conf apt-get $qflag -d $aptoptions -y --force-yes --fix-missing install $packages $NFSROOT_PACKAGES } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - set-classes() { # if -c is given, ignore -x if [ -n "$cclasses" ]; then export classes=${cclasses//,/ } return fi set +e # all available file names are classes classes=$(cd $FAI_CONFIGDIR/package_config; ls -1 | egrep -i "^[A-Z0-9_-]+$") addclasses=$(grep -h PACKAGES $FAI_CONFIGDIR/package_config/* | awk '{printf $3"\n"$4"\n"$5"\n"$6"\n"}') export classes=$(echo -e "$classes\n$addclasses\n" | sort | uniq) [ -n "$exclasses" ] && excludeclass $exclasses set -e } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [ -x "$(which apt-move)" ] || die 5 "apt-move not found. Please install package." preserve=0 verbose=0 add=0 qflag=-qq while getopts "avhx:pc:" opt ; do case "$opt" in a) add=1 ;; h) usage ;; x) exclasses="$OPTARG";; c) cclasses="$OPTARG";; p) preserve=1;; v) verbose=1; vflag=-v; qflag='';; ?) die 1 "Unknown option";; esac done shift $(($OPTIND - 1)) [ -n "$exclasses" -a -n "$cclasses" ] && die 3 "Options -x and -c not allowed at the same time." debug=0 [ $debug -eq 0 ] && quiet=-q mirrordir=$1 if [ -z "$mirrordir" ]; then die 2 "Please give the absolute path to the mirror." fi { echo $mirrordir | egrep -q '^/'; } || die 4 "Mirrordir must start with a slash /." if [ -d $mirrordir/pool -o -d $mirrordir/dists ]; then die 3 "Please first remove $mirrordir/pool and $mirrordir/dists" fi initialize # if we are using nfs mounts for Debian mirror, this may fail here, since inside a chroot environment different dir are used # if sources.list includes file AND FAI_DEBMIRROR is defined we have to mount # otherwise mounting is not needed. call task_mirror if [ "$FAI_DEBMIRROR" ]; then mount -r $FAI_DEBMIRROR $FAI_ROOT/$MNTPOINT || exit 9 fi # TODO: use -p to preserve sources.list perl -p -e 's/file:/copy:/' /etc/fai/sources.list > $aptcache/etc/apt/sources.list echo "Getting package information" apt-get $quiet $aptoptions update >/dev/null set-classes echo "Downloading packages for classes:" $classes FAI=$FAI_CONFIGDIR install_packages -d $vflag [ $add -eq 1 ] && add_base_packages get_addpackages umount_dirs trap "" EXIT ERR [ $add -eq 0 ] && delete_base_packages # create mirror directory structure echo "Calling apt-move" cat > $aptmovefile <