/[fai]/trunk/bin/install_packages
ViewVC logotype

Contents of /trunk/bin/install_packages

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4073 - (show annotations) (download)
Mon Oct 9 23:30:52 2006 UTC (6 years, 8 months ago) by lange
File size: 13596 byte(s)
add missing package list to yum and rpm calls
1 #!/usr/bin/perl
2
3 # $Id$
4 #*********************************************************************
5 #
6 # install_packages -- read package config and install packages via apt-get
7 #
8 # This script is part of FAI (Fully Automatic Installation)
9 # (c) 2000-2006, Thomas Lange, lange@informatik.uni-koeln.de
10 #
11 #*********************************************************************
12 # This program is free software; you can redistribute it and/or modify
13 # it under the terms of the GNU General Public License as published by
14 # the Free Software Foundation; either version 2 of the License, or
15 # (at your option) any later version.
16 #
17 # This program is distributed in the hope that it will be useful, but
18 # WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 # General Public License for more details.
21 #
22 # You should have received a copy of the GNU General Public License
23 # along with this program; see the file COPYING. If not, write to the
24 # Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 # MA 02111-1307, USA.
26 #*********************************************************************
27
28 my $version = "Version 3.4.1, 10-oct-2006";
29 $0=~ s#.+/##; # remove path from program name
30
31 # import variables: $verbose, $MAXPACKAGES, $classes, $FAI, $FAI_ROOT
32
33 use strict;
34 use Getopt::Std;
35 use AptPkg::Config '$_config';
36 use AptPkg::System '$_system';
37 use AptPkg::Cache;
38
39 # global variables
40 our ($opt_d,$opt_l,$opt_L,$opt_v,$opt_h,$opt_t,$opt_m,$opt_p);
41 my $listonly; # flag, that indicates that only a list of packages will be printed
42 our @commands;
43 our %command;
44 our $atype; # type of action (for apt-get, aptitude,..) that will be performed
45 my $test;
46 my $verbose;
47 my $FAI_ROOT;
48 my @classes;
49 my $classpath;
50 my $rootcmd;
51 my @preloadlist;
52 my @preloadrmlist;
53 my %list;
54 my %classisdef;
55 my $maxpl; # maximum length of package list
56 my $cache; # instance of AptPkg::Cache
57 my @unknown; # unknown packages
58 my @known; # list of all known packages
59 my $downloaddir="/var/cache/apt/archives/partial/"; # where to download packages that gets only unpacked
60
61 # PRELOAD feature from Thomas Gebhardt <gebhardt@hrz.uni-marburg.de>
62
63 $| = 1;
64 # order of commands to execute
65
66 my $aptopt='-y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold"';
67
68 @commands = qw/y2i y2r yast rpmr urpmi urpme yumgroup yumi yumr hold taskrm taskinst clean aptitude aptitude-r install unpack remove dselect-upgrade/;
69 %command = (
70 install => "apt-get $aptopt --fix-missing install",
71 ninstall => "apt-get $aptopt --fix-missing -s install",
72 remove => "apt-get $aptopt --purge remove",
73 "dselect-upgrade" => "apt-get $aptopt dselect-upgrade",
74 "taskinst" => "tasksel -n install",
75 "taskrm" => "tasksel -n remove",
76 "hold" => "dpkg --set-selections",
77 "clean" => "apt-get clean",
78 "aptitude" => "aptitude -R $aptopt install",
79 "aptitude-r" => "aptitude -r $aptopt install",
80 "unpack" => "cd $downloaddir; aptitude download",
81 "unpack-internal" => "dpkg --unpack --recursive $downloaddir; rm $downloaddir/*.deb",
82 "pending" => "dpkg --configure --pending",
83 "dpkgc" => "dpkg -C",
84 urpmi => "urpmi --auto --foce --allow-force --keep",
85 urpme => "urpme --auto --foce --allow-force --keep",
86 yumi => "yum -y install",
87 yumr => "yum -y remove",
88 yumgroup => "yum -y groupinstall",
89 y2i => "y2pmsh isc",
90 y2r => "y2pmsh remove",
91 yast => "yast -i",
92 rpmr => "rpm -e",
93 );
94
95 $test = 0;
96 getopts('dthvlLm:p:');
97
98 $listonly = $opt_l || $opt_L;
99 $opt_h && usage();
100 $opt_t and $test = 1;
101 $verbose=$ENV{verbose} || $opt_v;
102 $opt_d && setdownloadonly();
103 $maxpl=$ENV{MAXPACKAGES} || $opt_m ;
104 $maxpl && $verbose && warn "Maxmimum number of packages installed at a time set to $maxpl\n";
105 $maxpl or $maxpl = 99 ; # set default value
106
107 my $qopt="-qq" unless $verbose;
108 my $devnull=">/dev/null" unless $verbose;
109
110 $FAI_ROOT = $ENV{FAI_ROOT};
111 $classpath = $opt_p || "$ENV{FAI}/package_config";
112 $rootcmd = ($FAI_ROOT eq "/" ) ? '' : "chroot $FAI_ROOT";
113 @classes = grep { !/^#|^\s*$/ } split(/[\s\n]+/,$ENV{classes});
114 foreach (@classes) { $classisdef{$_}=1;}
115
116 $_config->init; # initialize AptPkg
117 $_config->set("Dir",$FAI_ROOT); # simulate "chroot"
118 $_config->{quiet}=2; # don't show cache initialization messages
119 $_system = $_config->system;
120 $cache = new AptPkg::Cache;
121
122 # read all package config files
123 foreach (@classes) {
124 my $filename = "$classpath/$_";
125 &readconfig($filename) if -f $filename;
126 }
127
128 # get files which must exist before installing packages
129 foreach my $entry (@preloadlist,@preloadrmlist) {
130 my ($url, $directory) = @$entry;
131 if ($url =~ m!^file:/(.+)!) {
132 my $file = $1;
133 execute("cp $FAI_ROOT/$file $FAI_ROOT/$directory") unless $listonly;
134 } else {
135 execute("wget -nv -P$FAI_ROOT/$directory $url") unless $listonly;
136 }
137 }
138
139 # call apt-get or tasksel for each type of command whith the list of packages
140 foreach $atype (@commands) {
141
142 if ($atype eq "clean") {
143 execute("$rootcmd $command{clean}") unless $listonly;
144 next;
145 }
146
147 # skip if empty list
148 next unless defined $list{$atype};
149
150 if ($atype eq "dselect-upgrade") {
151 dselectupgrade($atype);
152 next;
153 }
154
155 my $packlist = join(' ',@{$list{$atype}});
156
157 if ($atype =~ /rpm|yum|y2/) {
158 $command{clean} = "true"; # do not cal apt-get lcean for rpm and yum packages
159 execute("$rootcmd $command{$atype} $packlist") if $packlist;
160 next;
161 }
162
163 if ($atype eq "hold") {
164 my $hold = join " hold\n", @{$list{hold}};
165 $hold .= " hold\n";
166 execute("echo \"$hold\" | $rootcmd $command{hold}");
167 next;
168 }
169
170 if ($atype eq "install" || $atype eq "aptitude" || $atype eq "unpack" || $opt_l || $opt_L) {
171
172 mkpackagelist(@{$list{$atype}}); # create lists of known and unknown packages
173 if ($opt_l) {
174 # only print the package list
175 print join ' ',@known,"\n";
176 exit 0;
177 }
178 if ($opt_L) {
179 # only print the package list
180 execute("$rootcmd $command{ninstall} @known | egrep ^Inst");
181 exit 0;
182 }
183 # pass only maxpl packages to apt-get
184 while (@known) {
185 my $shortlist = join(' ', splice @known,0,$maxpl);
186 # print "SL $shortlist\n";
187 execute("$rootcmd $command{$atype} $shortlist") if $shortlist;
188 execute("$rootcmd $command{'clean'}"); # XXX do not execute always
189 execute("$rootcmd $command{'unpack-internal'}") if ($atype eq "unpack"); # unpack and rm deb files
190 }
191 next;
192 }
193
194 if ($atype eq "taskinst" || $atype eq "taskrm") {
195 foreach my $tsk (@{$list{$atype}}) {
196 execute("$rootcmd $command{$atype} $tsk");
197 }
198 next;
199 }
200
201 # other types
202 execute("$rootcmd $command{$atype} $packlist") if $packlist;
203 }
204
205 # remove preloaded files
206 foreach my $entry (@preloadrmlist) {
207 my ($url, $directory) = @$entry;
208 $url =~ m#/([^/]+$)#;
209 my $file = "$directory/$1";
210 print "rm $file\n" if $verbose;
211 unlink $file || warn "Can't remove $file\n";
212 }
213
214
215 # in case of unconfigured packages because of apt errors
216 # retry configuration
217 execute("$rootcmd $command{pending}");
218 # check if all went right
219 execute("$rootcmd $command{dpkgc}");
220 # clean apt cache
221 execute("$rootcmd $command{clean}");
222 # - - - - - - - - - - - - - - - - - - - - - - - - - - -
223 sub readconfig {
224
225 my $filename = shift;
226 my ($package,$type,$cllist,@oclasses,$doit);
227
228 open (FILE,"$filename") || warn "ERROR $0: Can't read config file: $filename\n";
229 warn "$0: read config file $filename\n" if $verbose;
230
231 while (<FILE>) {
232 next if /^#/; # skip comments
233 s/#.*$//; # delete comments
234 next if /^\s*$/; # skip empty lines
235 chomp;
236 /^PRELOAD\s+(\S+)\s+(\S+)/ and push(@preloadlist, [$1,$2]),next;
237 /^PRELOADRM\s+(\S+)\s+(\S+)/ and push(@preloadrmlist, [$1,$2]),next;
238
239 if (/^PACKAGES\s+(\S+)\s*/) {
240 ($type,$cllist) = ($1,$');
241 warn "WARNING: Unknow action $type after PACKAGES\n." unless defined $command{$type};
242 # by default no classes are listed after this command so doit
243 $doit = 1;
244 if ($cllist) {
245 # no classes specified after PACKAGES command
246 # so add all packages listed
247 # use packages on for a list of classes
248 $doit = 0; # assume no class is defined
249 @oclasses = split(/\s+/,$cllist);
250 # if a listed class is defined, add the packaes, otherwise skip these packages
251 foreach (@oclasses) { exists $classisdef{$_} and $doit = 1;}
252 }
253 next;
254 }
255
256 # warning if uppercase letters are found (package are always lowercase)
257 warn "WARNING: Uppercase character found in package name in line $_\n" if $_ =~ /[A-Z]/;
258 warn "ERROR: PACKAGES .. line missing in $filename\n",next unless $type;
259 push @{$list{$type}}, split if $doit;
260 }
261 }
262 # - - - - - - - - - - - - - - - - - - - - - - - - - - -
263 sub execute {
264
265 # execute a command or only print it
266 my @cmds = @_;
267
268 # TODO: split cmds into array except when a pipe is found
269
270 my $command = join (' ',@cmds);
271 my $error;
272
273 $test and $verbose = 1;
274 $verbose and warn "$0: executing $command\n";
275 $test and return;
276
277 # @cmds should me more efficient
278 $error = system @cmds;
279 warn "ERROR: $error $?\n" if $error;
280 }
281 # - - - - - - - - - - - - - - - - - - - - - - - - - - -
282 sub dselectupgrade {
283
284 my $type = shift;
285 my ($package,$action,$list);
286 my $tempfile = "$FAI_ROOT/tmp/dpkg-selections.tmp"; # TODO: use better uniq filename
287 while (@{$list{$type}}) {
288 $package = shift @{$list{$type}};
289 $action = shift @{$list{$type}};
290 $list .= "$package $action\n";
291 }
292
293 open TMP,"> $tempfile" || die " Can't write to $tempfile";
294 print TMP $list;
295 close TMP;
296
297 execute("$rootcmd dpkg --set-selections < $tempfile");
298 execute("$rootcmd $command{$type}");
299 unlink $tempfile;
300 }
301 # - - - - - - - - - - - - - - - - - - - - - - - - - - -
302 sub installable {
303 # ckeck, wether package can be installed.
304 # return false for packages which only exist in
305 # dpkg status files
306
307 my $package = shift;
308 # print "Checking wether $package is installable...\n";
309
310 # version list of package
311 my $vlist = $cache->{$package}{VersionList};
312
313 # for each version
314 foreach my $version (@$vlist) {
315 # list of package files
316 my $flist = $version->{FileList};
317 foreach my $fitem (@$flist) {
318 # if the file is a package index (not a dpkg status file)
319 # the package is installable
320 return 1 if ($fitem->{File}{IndexType} eq "Debian Package Index");
321 }
322 }
323
324 # no package index file found for the current package
325 return 0;
326 }
327 # - - - - - - - - - - - - - - - - - - - - - - - - - - -
328 sub mkpackagelist {
329
330 my @complete = @_; # copy original list
331 my @orig = ();
332 @unknown = @known = ();
333 my %complete = ();
334
335 # create two list of packages
336 # @unknown contains the unknown packages
337 # @known contains the known packages
338
339 # ignore packages ending with - when using -d
340 @complete = grep {!/-$/} @complete if $opt_d;
341
342 foreach (reverse @complete) {
343 my $pack = $_;
344 if ( /^(.+)[_=+-]$/ and $1 and $cache->exists($1)) {
345 $pack = $1;
346 }
347 if (! defined ($complete{$pack})) {
348 $complete{$pack} = 1;
349 unshift @orig, $_;
350 }
351 }
352
353 # currently we disable the complete checking of package names if aptitude
354 # is used. This is because we can't check task names, which are supported by aptitude
355 if ($atype eq "aptitude") {
356 @known=@orig;
357 return;
358 }
359
360 foreach my $pack (@orig) {
361
362 # if ($atype eq "aptitude" && $pack =~ /^~/) {
363 # # add to known if is it an aptitude search pattern
364 # push @known, $pack;
365 # next;
366 # }
367 # TODO: aptitude also can install tasks. How do we check them? Currently they will push to @unknown
368
369 if ($cache->exists($pack)) { # simple package name
370 # check for packages with no installation candidates
371 # explicitely don't check if the name is provided by some other package:
372 # apt-get install <virtual> fails with newer apt
373
374 if (installable($pack)) {
375 push @known, $pack;
376 } else {
377 push @unknown, $pack;
378 }
379
380 }
381
382 # simulate APTs and aptitudes understanding of "special" package names
383 # suffixed by -, +
384 elsif ( $pack =~ /^(.+)[_=+-]$/ and $cache->exists($1)) {
385
386 if (defined ($cache->{$1}{VersionList})) {
387 push @known, $pack;
388 } else {
389 push @unknown, $pack;
390 }
391
392 } else {
393 push @unknown, $pack;
394 }
395 }
396 warn "WARNING: These unknown packages are removed from the installation list: " . join(' ',sort @unknown) . "\n" if @unknown;
397 }
398 # - - - - - - - - - - - - - - - - - - - - - - - - - - -
399 sub usage {
400
401 print << "EOF";
402 install_packages $version
403
404 Please read the manual pages install_packages(8).
405 EOF
406 exit 0;
407 }
408 # - - - - - - - - - - - - - - - - - - - - - - - - - - -
409 sub setdownloadonly {
410
411 # Definitions for install_packages(8) for download only mode
412 # Used by fai-mirror(1)
413
414 # we are using a variable from %ENV
415 # for debugging remove >/dev/null and -q
416
417 undef @commands;
418 undef %command;
419
420 $maxpl=9999;
421 @commands = qw/taskinst aptitude aptitude-r install unpack/;
422 %command = (
423 install => "apt-get $qopt -d $ENV{aptoptions} -y --fix-missing install",
424 "taskinst" => "aptitude -d $ENV{aptoptions} -y install $devnull",
425 "aptitude" => "aptitude -R -d $ENV{aptoptions} -y install $devnull",
426 "aptitude-r" => "aptitude -r -d $ENV{aptoptions} -y install $devnull",
427 "unpack" => "cd $downloaddir; aptitude download",
428 "clean" => 'true',
429 "pending" => 'true',
430 "dpkgc" => 'true',
431 );
432
433 }
434 # - - - - - - - - - - - - - - - - - - - - - - - - - - -

Properties

Name Value
svn:eol-style native
svn:executable *
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.5