[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