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