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