[Fai-commit] r5246 - in people/faiguy/bugfixes: . 514160
meissner-guest at alioth.debian.org
meissner-guest at alioth.debian.org
Wed Feb 4 19:57:35 UTC 2009
Author: meissner-guest
Date: 2009-02-04 19:57:35 +0000 (Wed, 04 Feb 2009)
New Revision: 5246
Added:
people/faiguy/bugfixes/514160/
people/faiguy/bugfixes/514160/install_packages
Log:
* added basic zypper support to install_packages
Copied: people/faiguy/bugfixes/514160/install_packages (from rev 5245, trunk/bin/install_packages)
===================================================================
--- people/faiguy/bugfixes/514160/install_packages (rev 0)
+++ people/faiguy/bugfixes/514160/install_packages 2009-02-04 19:57:35 UTC (rev 5246)
@@ -0,0 +1,516 @@
+#!/usr/bin/perl
+
+# $Id$
+#*********************************************************************
+#
+# install_packages -- read package config and install packages via apt-get
+#
+# This script is part of FAI (Fully Automatic Installation)
+# (c) 2000-2008, Thomas Lange, lange at informatik.uni-koeln.de
+# (c) 2003-2004, Henning Glawe, glaweh at physik.fu-berlin.de
+# (c) 2004 , Jonas Hoffmann, jhoffman at physik.fu-berlin.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.
+#*********************************************************************
+
+my $version = "Version 4.1.6, 27-oct-2008";
+$0=~ s#.+/##; # remove path from program name
+
+# import variables: $verbose, $MAXPACKAGES, $classes, $FAI, $FAI_ROOT
+
+use strict;
+use Getopt::Std;
+
+# global variables
+our ($opt_d,$opt_l,$opt_L,$opt_v,$opt_h,$opt_H,$opt_m,$opt_n,$opt_N,$opt_p);
+my $listonly; # flag, that indicates that only a list of packages will be printed
+our @commands;
+our %command;
+our $atype; # type of action (for apt-get, aptitude,..) that will be performed
+my $dryrun=0;
+my $verbose;
+my $FAI_ROOT;
+my @classes;
+my $classpath;
+my $rootcmd;
+my @preloadlist;
+my @preloadrmlist;
+my $_config;
+my $_system;
+my $hasdebian=0; # some Debian related commands/types are used in package_config
+my %list; # hash of arrays, key=type (yumi,aptitude,..), list of packages
+my %types; # hash containing the types found in all loaded package_config files
+my %classisdef;
+my $maxpl; # maximum length of package list
+my $cache; # instance of AptPkg::Cache
+my @unknown; # unknown packages
+my @known; # list of all known packages
+my $execerrors; # counts execution errors
+my $downloaddir="/var/cache/apt/archives/partial/"; # where to download packages that gets only unpacked
+
+# PRELOAD feature from Thomas Gebhardt <gebhardt at hrz.uni-marburg.de>
+
+$| = 1;
+# order of commands to execute
+
+my $aptopt='-y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold"';
+ at commands = qw/y2i y2r yast rpmr urpmi urpme yumgroup yumi yumr smarti smartr hold taskrm taskinst clean-internal aptitude aptitude-r install unpack remove dselect-upgrade zyppin/;
+%command = (
+ "install" => "apt-get $aptopt --fix-missing install",
+ "inst-internal" => "apt-get $aptopt --fix-missing -s install",
+ "remove" => "apt-get $aptopt --purge remove",
+ "dselect-upgrade" => "apt-get $aptopt dselect-upgrade",
+ "taskinst" => "tasksel install",
+ "taskrm" => "tasksel remove",
+ "hold" => "dpkg --set-selections",
+ "clean-internal" => "apt-get clean",
+ "aptitude" => "aptitude -R $aptopt install",
+ "aptitude-r" => "aptitude -r $aptopt install",
+ "unpack" => "cd $downloaddir; aptitude download",
+ "unpack-internal" => "dpkg --unpack --recursive $downloaddir; rm $downloaddir/*.deb",
+ "pending-internal" => "dpkg --configure --pending",
+ "dpkgc-internal" => "dpkg -C",
+ "urpmi" => "urpmi --auto --foce --allow-force --keep",
+ "urpme" => "urpme --auto --foce --allow-force --keep",
+ "yumi" => "yum -y install",
+ "yumr" => "yum -y remove",
+ "yumgroup" => "yum -y groupinstall",
+ "y2i" => "y2pmsh isc",
+ "y2r" => "y2pmsh remove",
+ "yast" => "yast -i",
+ "rpmr" => "rpm -e",
+ smarti => "smart install -y",
+ smartr => "smart remove -y",
+ "smartc-internal" => "smart clean",
+ "zyppin" => "zypper -n in --force-resolution",
+);
+
+getopts('dhHvlLm:p:nN');
+
+my $use_aptpkg=0;
+$opt_N || check_aptpkg(); # do not use AptPkg when -N is given
+
+$listonly = $opt_l || $opt_L;
+$opt_h && usage();
+$opt_H && showcommands();
+$dryrun=1 if $opt_n;
+$verbose=$ENV{verbose} || $opt_v;
+$opt_d && setdownloadonly();
+$maxpl=$ENV{MAXPACKAGES} || $opt_m ;
+$maxpl && $verbose && warn "Maxmimum number of packages installed at a time set to $maxpl\n";
+$maxpl or $maxpl = 99 ; # set default value
+
+my $qopt="-qq" unless $verbose;
+my $devnull=">/dev/null" unless $verbose;
+
+$FAI_ROOT = $ENV{FAI_ROOT};
+$classpath = $opt_p || "$ENV{FAI}/package_config";
+$rootcmd = ($FAI_ROOT eq "/" ) ? '' : "chroot $FAI_ROOT";
+ at classes = grep { !/^#|^\s*$/ } split(/[\s\n]+/,$ENV{classes});
+foreach (@classes) { $classisdef{$_}=1;}
+
+# do not use AptPkg if target is not a Debian system
+if ($use_aptpkg) {
+ $_config->init; # initialize AptPkg
+ $_config->set("Dir",$FAI_ROOT); # simulate "chroot"
+ $_config->{quiet}=2; # don't show cache initialization messages
+ $_system = $_config->system;
+ $cache = new AptPkg::Cache;
+}
+
+warn "$0: reading config files from directory $classpath\n";
+# read all package config files
+foreach (@classes) {
+ &readconfig($classpath,$_) if -f "$classpath/$_";
+}
+
+# check if any Debian related commands/types are used in package_config
+my @debiantypes= qw/taskinst aptitude aptitude-r install remove dselect-upgrade smarti/;
+foreach my $dt (@debiantypes) {
+ $types{$dt} and $hasdebian=1;
+ if ($types{$dt} eq 'smarti') {
+ $command{'clean-internal'} = $command{'smartc-internal'};
+ $command{'pending-internal'} = "true";
+ $command{'dpkgc-internal'} = "true";
+ }
+}
+
+# get files which must exist before installing packages
+foreach my $entry (@preloadlist, at preloadrmlist) {
+ my ($url, $directory) = @$entry;
+ if ($url =~ m!^file:/(.+)!) {
+ my $file = $1;
+ execute("cp $FAI_ROOT/$file $FAI_ROOT/$directory") unless $listonly;
+ } else {
+ execute("wget -nv -P$FAI_ROOT/$directory $url") unless $listonly;
+ }
+}
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# begin of the big foreach loop
+# - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# call apt-get or tasksel for each type of command whith the list of packages
+foreach $atype (@commands) {
+
+ if ($atype eq "clean-internal" && $hasdebian) {
+ execute("$rootcmd $command{'clean-internal'}") unless $listonly;
+ next;
+ }
+
+ # skip if empty list
+ next unless defined $list{$atype};
+
+ if ($atype eq "dselect-upgrade") {
+ dselectupgrade($atype);
+ next;
+ }
+
+ my $packlist = join(' ',@{$list{$atype}});
+
+ if ($atype eq "hold") {
+ my $hold = join " hold\n", @{$list{hold}}, " hold\n";
+ execute("echo \"$hold\" | $rootcmd $command{hold}");
+ next;
+ }
+
+ if ($atype eq "install" || $atype eq "smarti" || $atype eq "aptitude" || $atype eq "unpack" || $opt_l || $opt_L) {
+
+ mkpackagelist(@{$list{$atype}}); # create lists of known and unknown packages
+ if ($opt_l) {
+ # only print the package list
+ print join ' ', at known,"\n";
+ exit 0;
+ }
+ if ($opt_L) {
+ # only print the package list
+ execute("$rootcmd $command{'inst-internal'} @known | egrep ^Inst");
+ exit 0;
+ }
+ # pass only maxpl packages to apt-get
+ while (@known) {
+ my $shortlist = join(' ', splice @known,0,$maxpl);
+ # print "SL $shortlist\n";
+ execute("$rootcmd $command{$atype} $shortlist") if $shortlist;
+ execute("$rootcmd $command{'clean-internal'}") if $hasdebian;
+ execute("$rootcmd $command{'unpack-internal'}") if ($atype eq "unpack"); # unpack and rm deb files
+ }
+ next;
+ }
+
+ if ($atype eq "taskinst" || $atype eq "taskrm") {
+ foreach my $tsk (@{$list{$atype}}) {
+ execute("$rootcmd $command{$atype} $tsk");
+ }
+ next;
+ }
+
+ # other types
+ execute("$rootcmd $command{$atype} $packlist") if $packlist;
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# end of the big foreach loop
+# - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+# remove preloaded files
+foreach my $entry (@preloadrmlist) {
+ my ($url, $directory) = @$entry;
+ $url =~ m#/([^/]+$)#;
+ my $file = "$directory/$1";
+ print "rm $file\n" if $verbose;
+ unlink $file || warn "Can't remove $file\n";
+}
+
+if ($hasdebian) {
+ # in case of unconfigured packages because of apt errors
+ # retry configuration
+ execute("$rootcmd $command{'pending-internal'}");
+ # check if all went right
+ execute("$rootcmd $command{'dpkgc-internal'}");
+ # clean apt cache
+ execute("$rootcmd $command{'clean-internal'}");
+}
+
+if ($execerrors) {
+ warn "$execerrors errors during executing of commands\n";
+ exit 3;
+}
+
+exit 0; # end of program
+# - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub readconfig {
+
+ my ($path,$file) = @_;
+ my ($package,$type,$cllist, at oclasses,$doit);
+
+ open (FILE,"$path/$file") || warn "ERROR $0: Can't read config file: $path/$file\n";
+ warn "$0: read config file $file\n" if $verbose;
+
+ while (<FILE>) {
+ next if /^#/; # skip comments
+ s/#.*$//; # delete comments
+ next if /^\s*$/; # skip empty lines
+ chomp;
+ /^PRELOAD\s+(\S+)\s+(\S+)/ and push(@preloadlist, [$1,$2]),next;
+ /^PRELOADRM\s+(\S+)\s+(\S+)/ and push(@preloadrmlist, [$1,$2]),next;
+
+ if (/^PACKAGES\s+(\S+)\s*/) {
+ ($type,$cllist) = ($1,$');
+ warn "WARNING: Unknow action $type after PACKAGES\n." unless defined $command{$type};
+ # by default no classes are listed after this command so doit
+ $doit = 1;
+ if ($cllist) {
+ # no classes specified after PACKAGES command
+ # so add all packages listed
+ # use packages on for a list of classes
+ $doit = 0; # assume no class is defined
+ @oclasses = split(/\s+/,$cllist);
+ # if a listed class is defined, add the packaes, otherwise skip these packages
+ foreach (@oclasses) { exists $classisdef{$_} and $doit = 1;}
+ }
+ next;
+ }
+
+ # warning if uppercase letters are found (package are always lowercase)
+ warn "WARNING: Uppercase character found in package name in line $_\n" if $_ =~ /[A-Z]/;
+ warn "ERROR: PACKAGES .. line missing in $file\n",next unless $type;
+ push @{$list{$type}}, split if $doit;
+ $types{$type}=1 if $doit; # remember which types are used in package_config
+ }
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub execute {
+
+ # execute a command or only print it
+ my @cmds = @_;
+
+ # TODO: split cmds into array except when a pipe is found
+
+ my $command = join (' ', at cmds);
+ my $error;
+
+ $dryrun and $verbose = 1;
+ $verbose and warn "$0: executing $command\n";
+ $dryrun and return;
+
+ # @cmds should me more efficient
+ $error = system @cmds;
+ warn "ERROR: $error $?\n" if $error;
+ my $rc = $?>>8;
+ warn "ERROR: $cmds[0] return code $rc\n" if $rc;
+ $execerrors++ if $rc;
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub dselectupgrade {
+
+ my $type = shift;
+ my ($package,$action,$list);
+ my $tempfile = "$FAI_ROOT/tmp/dpkg-selections.tmp"; # TODO: use better uniq filename
+ while (@{$list{$type}}) {
+ $package = shift @{$list{$type}};
+ $action = shift @{$list{$type}};
+ $list .= "$package $action\n";
+ }
+
+ open TMP,"> $tempfile" || die " Can't write to $tempfile";
+ print TMP $list;
+ close TMP;
+
+ execute("$rootcmd dpkg --set-selections < $tempfile");
+ execute("$rootcmd $command{$type}");
+ unlink $tempfile;
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub installable {
+
+ # ckeck, wether package can be installed.
+ # return false for packages which only exist in
+ # dpkg status files
+
+ my $package = shift;
+ # print "Checking wether $package is installable...\n";
+
+ # version list of package
+ my $vlist = $cache->{$package}{VersionList};
+
+ # for each version
+ foreach my $version (@$vlist) {
+ # list of package files
+ my $flist = $version->{FileList};
+ foreach my $fitem (@$flist) {
+ # if the file is a package index (not a dpkg status file)
+ # the package is installable
+ return 1 if ($fitem->{File}{IndexType} eq "Debian Package Index");
+ }
+ }
+
+ # no package index file found for the current package
+ return 0;
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub mkpackagelist {
+
+ my @complete = @_; # copy original list
+ my @orig = ();
+ @unknown = @known = ();
+ my %complete = ();
+
+ # create two list of packages
+ # @unknown contains the unknown packages
+ # @known contains the known packages
+
+ # nothing to do, when no Debian types/commands are used at all
+ unless ($hasdebian) {
+ @known = @complete;
+ return;
+ }
+
+ # no package name checking when using smart
+ if ($atype eq "smarti" || $atype eq "smartr") {
+ @known=@complete;
+ return;
+ }
+
+ # ignore packages ending with - when using -d
+ @complete = grep {!/-$/} @complete if $opt_d;
+
+ foreach (reverse @complete) {
+ my $pack = $_;
+ if ( /^(.+)[_=+-]$/ and $1 and $cache->exists($1)) {
+ $pack = $1;
+ }
+ if (! defined ($complete{$pack})) {
+ $complete{$pack} = 1;
+ unshift @orig, $_;
+ }
+ }
+
+ # currently we disable the complete checking of package names if aptitude
+ # is used. This is because we can't check task names, which are supported by aptitude
+ if ($atype eq "aptitude") {
+ @known=@orig;
+ return;
+ }
+
+ foreach my $pack (@orig) {
+
+# if ($atype eq "aptitude" && $pack =~ /^~/) {
+# # add to known if is it an aptitude search pattern
+# push @known, $pack;
+# next;
+# }
+# TODO: aptitude also can install tasks. How do we check them? Currently they will push to @unknown
+
+ if ($cache->exists($pack)) { # simple package name
+ # check for packages with no installation candidates
+ # explicitely don't check if the name is provided by some other package:
+ # apt-get install <virtual> fails with newer apt
+
+ if (installable($pack)) {
+ push @known, $pack;
+ } else {
+ push @unknown, $pack;
+ }
+
+ }
+
+ # simulate APTs and aptitudes understanding of "special" package names
+ # suffixed by -, +
+ elsif ( $pack =~ /^(.+)[_=+-]$/ and $cache->exists($1)) {
+
+ if (defined ($cache->{$1}{VersionList})) {
+ push @known, $pack;
+ } else {
+ push @unknown, $pack;
+ }
+
+ } else {
+ push @unknown, $pack;
+ }
+ }
+ warn "WARNING: These unknown packages are removed from the installation list: " . join(' ',sort @unknown) . "\n" if @unknown;
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub usage {
+
+ print << "EOF";
+install_packages $version
+
+ Please read the manual pages install_packages(8).
+EOF
+ exit 0;
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub setdownloadonly {
+
+# Definitions for install_packages(8) for download only mode
+# Used by fai-mirror(1)
+
+# we are using a variable from %ENV
+# for debugging remove >/dev/null and -q
+
+undef @commands;
+undef %command;
+
+$maxpl=9999;
+ at commands = qw/taskinst aptitude aptitude-r install unpack/;
+%command = (
+ "install" => "apt-get $qopt -d $ENV{aptoptions} -y --fix-missing install",
+ "taskinst" => "aptitude -d $ENV{aptoptions} -y install $devnull",
+ "aptitude" => "aptitude -R -d $ENV{aptoptions} -y install $devnull",
+ "aptitude-r" => "aptitude -r -d $ENV{aptoptions} -y install $devnull",
+ "unpack" => "cd $downloaddir; aptitude download",
+ "clean-internal" => 'true',
+ "pending-internal" => 'true',
+ "dpkgc-internal" => 'true',
+);
+
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub check_aptpkg {
+
+ # check if the Perl module is available
+ if (eval "require AptPkg::Config") {
+ $use_aptpkg=1;
+ eval "require AptPkg::System";
+ eval "require AptPkg::Cache";
+
+ $_config = $AptPkg::Config::_config;
+ $_system = $AptPkg::System::_system;
+ eval 'import AptPkg::Config $_config';
+ eval 'import AptPkg::System $_system';
+ eval 'import AptPkg::Cache';
+ }
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub showcommands {
+
+ # show all available commands
+ print "List of known commands for package_config files\n";
+ print "Short list:\n";
+ foreach (sort keys %command) {
+ next if /-internal/; # skip internal commands
+ print "$_\n";
+ }
+
+ print "\nLong list:\n";
+ foreach (sort keys %command) {
+ next if /-internal/; # skip internal commands
+ printf "%15s $command{$_}\n",$_;
+ }
+ exit 0;
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - -
Property changes on: people/faiguy/bugfixes/514160/install_packages
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:keywords
+ Author Date Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ native
More information about the Fai-commit
mailing list