de31e1c19dd75ece6849b249c397f87e730f5a7c
[openafs.git] / src / packaging / RedHat / mockbuild.pl
1 #!/usr/bin/perl
2 # mockbuild - mass RPM build driver for use with mock and many kernel-devel
3 #             RPMs
4 # from Simon Wilkinson for OpenAFS
5 # for "modern" yum, use "showdupesfromrepos=1" in all cfg files in /etc/mock
6
7 use strict;
8 use warnings;
9
10 use Getopt::Long;
11 use File::Path;
12 use IO::Dir;
13
14 my $suser="nsu";
15 my $rootbase="/var/lib/mock/";
16 my $resultbase="/tmp/result/";
17 my $stashbase="/disk/scratch/repository/";
18 my $mockcommand = "/usr/bin/mock";
19 my $buildall = 0;
20 my $ignorerelease = 1;
21 my @newrpms;
22
23 # Words cannot describe how gross this is. Yum no longer provides usable
24 # output, so we need to call the python interface. At some point this
25 # probably means this script should be entirely rewritten in python,
26 # but this is not that point.
27
28 sub findKernelModules {
29   my ($root, $uname, @modules) = @_;
30
31   my $modlist = join(",",map { "'".$_."'" } @modules);
32   my $python = <<EOS;
33 import yum;
34 import sys;
35 base = yum.YumBase();
36 base.doConfigSetup('$root/etc/yum.conf', '$root');
37 base.doRepoSetup();
38 base.doSackSetup();
39 EOS
40
41   if ($uname) {
42     $python.= <<EOS;
43
44 for pkg, values in base.searchPackageProvides(['kernel-devel-uname-r']).items():
45   if values[0].find('kernel-devel-uname-r = ') != -1:
46     print '%s.%s %s' % (pkg.name, pkg.arch, values[0].replace('kernel-devel-uname-r = ',''));
47
48 EOS
49   } else {
50     $python.= <<EOS;
51
52 print '\\n'.join(['%s.%s %s' % (x.name, x.arch, x.printVer()) for x in base.searchPackageProvides([$modlist]).keys()]);
53
54 EOS
55   }
56
57 #  my $output = `$suser -c "python -c \\\"$python\\\"" `;
58   my $output = `python -c "$python"`;
59
60   die "Python script to figure out available kernels failed : $output" 
61     if $?;
62
63   return $output;
64 }
65
66
67 my %platconf = ( "fedora-5-i386" => { osver => "fc5",
68                                       kmod => '1',
69                                       basearch => 'i386',
70                                       updaterepo => 'updates-released',
71                                       results => 'fedora-5/i386' },
72                  "fedora-5-x86_64" => { osver => "fc5",
73                                        kmod => '1',
74                                        basearch => 'x86_64',
75                                        updaterepo => 'updates-released',
76                                        results => 'fedora-5/x86_64' },
77                  "fedora-6-i386" => { osver => "fc6", 
78                                       kmod => '1', 
79                                       basearch => 'i386',
80                                       updaterepo => 'updates-released',
81                                       results => "fedora-6/i386" },
82                  "fedora-6-x86_64" => { osver => "fc6",
83                                         kmod => '1',
84                                         basearch => 'x86_64',
85                                         updaterepo => 'updates-released',
86                                         results => "fedora-6/x86_64" },
87                  "fedora-7-i386" => { osver => "fc7", 
88                                       kmod => '1', 
89                                       basearch => 'i386',
90                                       updaterepo => 'updates-released',
91                                       results => "fedora-7/i386" },
92                  "fedora-7-x86_64" => { osver => "fc7",
93                                         kmod => '1',
94                                         basearch => 'x86_64',
95                                         updaterepo => 'updates-released',
96                                         results => "fedora-7/x86_64" },
97                  "fedora-8-i386" => { osver => "fc8", 
98                                       kmod => '1', 
99                                       basearch => 'i386',
100                                       updaterepo => 'updates-released',
101                                       results => "fedora-8/i386" },
102                  "fedora-8-x86_64" => { osver => "fc8",
103                                         kmod => '1',
104                                         basearch => 'x86_64',
105                                         updaterepo => 'updates-released',
106                                         results => "fedora-8/x86_64" },
107                  "centos-4-i386" => { osver => "el4",
108                                      kmod => '1',
109                                      basearch => 'i386',
110                                      updaterepo => 'update',
111                                      results => 'rhel4/i386' },
112                  "centos-4-x86_64" => { osver => "el4",
113                                        kmod => '1',
114                                        basearch => 'x86_64',
115                                        updaterepo => 'update',
116                                        results => "rhel4/x86_64" },
117                  "centos-5-i386" => { osver => "el5", 
118                                       kmod => '1', 
119                                       basearch => 'i386',
120                                       updaterepo => 'update',
121                                       results => "rhel5/i386" },
122                  "centos-5-x86_64" => { osver => "el5",
123                                         kmod => '1',
124                                         basearch => 'x86_64',
125                                         updaterepo => 'update',
126                                         results => "rhel5/x86_64" },
127                  "fedora-9-i386" => { osver => "fc9",
128                                       kmod => '1',
129                                       basearch => 'i386',
130                                       updaterepo => "updates-released",
131                                       results => 'fedora-9/i386' },
132                  "fedora-9-x86_64" => { osver => "fc9",
133                                         kmod => "1",
134                                         basearch => "x86_64",
135                                         updaterepo => "updates-released",
136                                         results => "fedora-9/x86_64" },
137                  "fedora-development-i386" => { osver => "fcd",
138                                           kmod => '1',
139                                           basearch => 'i386',
140                                           results => 'fedora-devel/i386'},
141                  "fedora-development-x86_64" => { osver => "fcd",
142                                             kmod => '1',
143                                             basearch => 'x86_64',
144                                             results => 'fedora-devel/x86_64'} 
145 );
146
147 # The following are kernels that we can't successfully build modules against
148 # due to issues in the packaged kernel-devel RPM.
149
150 my %badkernels = (
151         "2.6.21-2950.fc8" => { "xen" => 1}, # Missing build ID
152 );
153
154 my $help;
155 my $ok = GetOptions("resultdir=s" => \$resultbase,
156                     "help" => \$help);
157
158 my @platforms = @ARGV;
159 my $srpm = pop @platforms;
160
161 if (!$ok || $help || !$srpm || $#platforms==-1) {
162   print "Usage: $0 [options] <platform> [<platform> [...]]  <srpm>\n";
163   print "    Options are : \n";
164   print "         --resultdir <dir>    Location to place output RPMS\n";
165   print "\n";
166   print "    Platform may be:\n";
167   foreach ("all", sort(keys(%platconf))) { print "        ".$_."\n"; };
168   exit(1);
169 }
170
171 my $oafsversion = `rpm -q --queryformat=%{VERSION} -p $srpm` or die $!;
172 chomp $oafsversion;
173 my $oafsrelease = `rpm -q --queryformat=%{RELEASE} -p $srpm` or die $!;
174 chomp $oafsrelease;
175 $oafsrelease=~s/^[^\.]*\.(.*)$/$1/;
176
177 print "Release is $oafsrelease\n";
178
179 if ($platforms[0] eq "all" and $#platforms == 0) {
180   @platforms = keys(%platconf);
181 }
182
183 foreach my $platform (@platforms) {
184   print "*******************************************************************\n";
185   print "Building for $platform\n";
186   die "Unknown platform $platform" if !$platconf{$platform};
187   my $osver = $platconf{$platform}{'osver'};
188   my $root = $rootbase.$platform."/root";
189   my $mockresults = $rootbase.$platform."/result";
190   my $resultdir = $resultbase."/".$platconf{$platform}{'results'};
191   my $basearch = $platconf{$platform}{'basearch'};
192   my $rpmstashdir = $stashbase.$platconf{$platform}{'results'}."/";
193
194   my $yumcachedir;
195   if (exists($platconf{$platform}{'updaterepo'})) {
196     $yumcachedir = $rootbase."cache/".$platform."/yum_cache/".
197                    $platconf{$platform}{'updaterepo'}."/packages/";
198   }
199
200   File::Path::mkpath($resultdir, 0, 0755);
201
202   if (system($mockcommand, "-r", $platform, "init") != 0) {
203     die "Initialising the root failed: $?\n";
204   }
205
206   my %modulelist;
207
208   print "-------------------------------------------------------------------\n";
209   print "Finding available kernel modules\n";
210
211   my $arbitraryversion = "";
212
213   my $modules;
214   if ($platform=~/fedora-development/) {
215     $modules = findKernelModules($root, 0, "kernel-devel");
216   } elsif ($platform=~/centos-4/) {
217     $modules = findKernelModules($root, 0, "kernel-devel", "kernel-smp-devel", 
218                                  "kernel-hugemem-devel", "kernel-xenU-devel");
219   } else {
220     $modules = findKernelModules($root, 0, 'kernel-devel');
221   }
222
223   foreach my $module (split(/\n/, $modules)) {
224       chomp $module;
225       my ($package, $version, $repo)=split(/\s+/, $module);
226       my ($arch) = ($package=~/\.(.*)$/);
227       my ($variant) = ($package=~/kernel-(.*)-devel/);
228       $variant = "" if !defined($variant);
229       next if ($package !~ /^kernel/);
230       next if ($arch eq "noarch");
231       next 
232           if (exists($badkernels{$version}) && ($badkernels{$version}{$variant}));
233       if ($platform=~/fedora-5/) {
234           next if ($variant eq "xen0"); # Fedora 5 has some bad xen0 kernel-devels
235           next if ($variant eq "smp");
236       }
237       if ($platform=~/fedora-8/ || $platform=~/fedora-9/ || $platform=~/fedora-development/) {
238           next if ($variant =~/debug$/); # Fedora 8 debug kernels are bad
239       }
240       print "$arch : $variant : $version\n";
241       $modulelist{$arch} ={} if !$modulelist{$arch};
242       $modulelist{$arch}{$version} = {} if !$modulelist{$arch}{$version};
243       $modulelist{$arch}{$version}{$variant} = 1;
244       $arbitraryversion = $version;
245   }
246
247   if (!$arbitraryversion) {
248     die "Unable to find a valid kernel-devel package for $platform\n";
249   }
250
251   print "-------------------------------------------------------------------\n";
252   print "Building the userland RPMs\n";
253   my @rpms = ('openafs', 'openafs-authlibs', 'openafs-authlibs-devel', 
254               'openafs-client', 'openafs-compat', 'openafs-debuginfo', 
255               'openafs-devel', 'openafs-docs', 'openafs-kernel-source', 
256               'openafs-kpasswd', 'openafs-krb5', 'openafs-server',
257               'dkms-openafs');
258   my @missingrpms=();
259
260   my $missing = 0;
261   foreach my $rpm (@rpms) {
262     if (! -f $resultdir."/".$rpm."-".$oafsversion."-".$osver.".".
263              $oafsrelease.".".$basearch.".rpm") {
264       $missing++;
265       print $resultdir."/".$rpm."-".$oafsversion."-".$osver.".".
266             $oafsrelease.".".$basearch.".rpm is missing!\n";
267       push @missingrpms, $rpm;
268     }
269   }
270   if ($missing) {
271     system($mockcommand." -r ".$platform." rebuild ".
272                         ' --define "fedorakmod 1" '.
273                         ' --define "kernvers '.$arbitraryversion.'" '.
274                         ' --define "osvers '.$osver.'" '.
275                         ' --define "build_modules 0" '.
276                         ' --define "build_userspace 1" '.
277                         ' --define "build_authlibs 1" '.
278                         $srpm) == 0
279       or die "build failed with : $!\n";
280     foreach my $rpm (@missingrpms) {
281       system("cp ".$mockresults."/".$rpm."-".$oafsversion."-".
282                    $osver.".".$oafsrelease.".".$basearch.".rpm ".
283                    $resultdir) == 0
284           or die "Copy failed with : $!\n";
285       push @newrpms, $mockresults."/".$rpm."-".$oafsversion."-".
286                      $osver.".".$oafsrelease.".".$basearch.".rpm";
287     }
288   } else {
289     print "All userland RPMs present for $platform. Skipping build\n";
290   }
291
292    print "-------------------------------------------------------------------\n";
293   print "Building kernel modules\n";
294
295  foreach my $arch (keys(%modulelist)) {
296     foreach my $version (keys(%{$modulelist{$arch}})) {
297       my $kversion = $version;
298       $kversion=~s/-/_/g;
299       my @tobuild;
300
301       if ($buildall) {
302         @tobuild = keys(%{$modulelist{$arch}{$version}});
303       } else {
304         foreach my $variant (keys(%{$modulelist{$arch}{$version}})) {
305           my $dvariant=$variant;
306           $dvariant.="-" if ($dvariant);
307           if (!-f $resultdir."/kmod-openafs-".$dvariant.
308                   $oafsversion."-".$oafsrelease.".".$kversion.".".
309                   $arch.".rpm") {
310             my @done = glob ($resultdir."/kmod-openafs-".$dvariant.
311                              $oafsversion."-*.".$kversion.".".$arch.".rpm");
312
313             if ($ignorerelease && $#done>=0) {
314               print "Kernel module for $kversion already exists for an".
315                     "older release. Skipping building it this time.\n";
316             } else {
317               push @tobuild, $variant;
318               print $resultdir."/kmod-openafs-".$dvariant.
319                     $oafsversion."-".$oafsrelease.".".$kversion.".".
320                     $arch.".rpm is missing\n";
321             }
322           }
323         }
324       }
325
326       if ($#tobuild>=0) {
327         my $variants = join(" ", map {$_ or '\\\\\"\\\\\"'} @tobuild);
328         print "Building $arch module for kernel $version with variants $variants\n";
329         system ("setarch $arch $mockcommand -r $platform rebuild ".
330                              " --arch ".$arch.
331                              ' --define "fedorakmod 1" '.
332                              ' --define "osvers '.$osver.'" '.
333                              ' --define "kernvers '.$version.'" '.
334                              ' --define "kvariants '.$variants.'" '.
335                              ' --define "build_modules 1" '.
336                              ' --define "build_userspace 0" '.
337                              $srpm) == 0
338           or die "Build failed with : $!\n";
339         foreach my $variant (@tobuild) {
340           if ($variant) {
341             $variant.="-";
342           }
343           system("cp ".$mockresults."/kmod-openafs-".$variant.$oafsversion."-".$oafsrelease.".".$kversion.".".$arch.".rpm $resultdir") == 0
344             or die "Copy failed with : $!\n";
345           push @newrpms, $mockresults."/kmod-openafs-".$variant.$oafsversion."-".$oafsrelease.".".$kversion.".".$arch.".rpm";
346         }
347       } else {
348          print "All kernel modules already built for $version on $arch\n";
349       }
350     }
351   }
352   print "-------------------------------------------------------------------\n";
353   print "Creating repository data\n";
354   system ("cd $resultdir; createrepo .") == 0
355     or die "Unable to build repository data\n";
356
357   if ($yumcachedir) {
358     print "-------------------------------------------------------------------\n";
359     print "Stashing kernel-devel RPMs\n";
360   
361     my $changed;
362     my $dirh = IO::Dir->new($yumcachedir);
363     if (defined($dirh)) {
364       my $file;
365       while (defined($file = $dirh->read)) {
366         if ( $file=~/^kernel.*devel/ &&
367               -f $yumcachedir.$file && ! -f $rpmstashdir.$file) {
368           print "Stashing $file for later use\n";
369           system("cp ".$yumcachedir.$file." ".$rpmstashdir.$file) == 0
370             or die "Copy failed with : $!\n";
371           $changed++;
372         }
373       }
374     }
375  
376     if ($changed) {
377       print "Updating stash repodata\n";
378       system ("cd $rpmstashdir; createrepo .") == 0
379         or die "Unable to update RPM stash repository data\n";
380     }
381   }
382 }
383
384 print "=====================================================================\n";
385 print "All builds complete\nBuilt:\n";
386 print join("\n",@newrpms);
387