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