#!/usr/bin/python # # buildpkg.py -- Builds RPMS in chroots # Copyright (C) 2004 NC State University # Written by Jack Neely # Jeremy Katz # # SDG # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # import os,sys,shutil import rpm import pwd, grp sys.path.append('/usr/share/rkmaint') from buildmisc import * buildUser="prospector" buildGroup="prospector" buildDir="/dist/build" distroots="/distroots" outDir="/dist/pkgs" logDir="/dist/logs" buildUid = pwd.getpwnam(buildUser)[2] buildGid = grp.getgrnam(buildGroup)[2] ts = rpm.TransactionSet() def usage(): print "Usage: %s [architectures to build]" % (sys.argv[0]) # make sure that things look sane def sanityCheckArgs(srpm, chrootDir): if not os.path.exists(srpm): usage() print "No such source RPM: %s" %(srpm) sys.exit(2) if not os.path.isdir(chrootDir): usage() print "No such directory: %s" %(chrootDir) sys.exit(3) # read the rpm header from file and return the header def getRpmHeader(file): fd = os.open(file, os.O_RDONLY) hdr = ts.hdrFromFdno(fd) os.close(fd) return hdr def getBaseRpmArgs(buildTopDir): args = ['--define', '_topdir %s' % buildTopDir, '--define', '_srcrpmdir %s/SRPMS' % buildTopDir, '--define', '_tmppath %s/tmp' % buildTopDir ] return args def getBuildRpmArgs(buildTopDir, arch): args = ['--define', '_buildroot=%s/buildroot' % buildTopDir, '--define', 'packager NCSU Realm Linux ', '--define', 'distribution NCSU Realm Linux', '--define', 'vendor (none)', '--target=%s' % arch] return args def installSrpm(file, chrootDir, buildTopDir): shutil.copy(file, "%s/%s/src.rpm" % (chrootDir, buildTopDir)) childpid = os.fork() if (not childpid): os.chroot(chrootDir) os.setgid(buildGid) os.setuid(buildUid) installArgs = (["/bin/rpm"] + getBaseRpmArgs(buildTopDir) + ["-i", "%s/src.rpm" % (buildTopDir)]) # print installArgs os.execv(installArgs[0], installArgs) sys.exit(0) pid, status = os.waitpid(childpid,0) if not os.WIFEXITED(status) or os.WEXITSTATUS(status) != 0: raise RuntimeError, "SRPM install failed" def buildPackage(specfile, chrootDir, buildTopDir, logfile, arch): childpid = os.fork() if (not childpid): os.chroot(chrootDir) os.setgid(buildGid) os.setuid(buildUid) installArgs = ["/usr/bin/rpmbuild"] + \ getBaseRpmArgs(buildTopDir) + \ getBuildRpmArgs(buildTopDir, arch) + \ ["-ba", "%s/SPECS/%s" % (buildTopDir, specfile)] execWithRedirect(installArgs[0], installArgs, stdout = logfile, stderr = logfile) sys.exit(0) pid, status = os.waitpid(childpid,0) if not os.WIFEXITED(status) or os.WEXITSTATUS(status) != 0: raise RuntimeError, "Package build failed" def main(): if len(sys.argv) < 3: usage() sys.exit(1) srpm=sys.argv[1] buildVersion=sys.argv[2] chrootDir = "%s/%s" % (distroots, buildVersion) if len(sys.argv) > 3: arches = sys.argv[3:] else: # XXX different default? arches = ["i386"] sanityCheckArgs(srpm, chrootDir) # make sure correct logDir exists and has the right perms if not os.access("%s/%s" % (logDir, buildVersion), os.W_OK): os.makedirs("%s/%s" % (logDir, buildVersion), 0755) # now the logDir needs to be writable by anyone os.chmod("%s/%s" % (logDir, buildVersion), 01777) # create the top dir for the build buildTopDir = "%s/%s/%s" % (buildDir, buildVersion, getRandomString()) if os.access(buildTopDir, os.X_OK): raise RuntimeError, "(random) buildTopDir %s already exists -- aborting" % (buildTopDir) os.makedirs(buildTopDir, 0755) # create needed subdirs for i in ("BUILD", "SPECS", "SRPMS", "RPMS", "SOURCES", "buildroot", "tmp"): os.makedirs("%s/%s" % (buildTopDir, i), 0755) # now it all needs to be owned by our build user os.system("chown -R %s:%s %s" % (buildUser, buildGroup, buildTopDir)) hdr = getRpmHeader(srpm) specidx = hdr[rpm.RPMTAG_FILEFLAGS].index(32) # XXX 32 == RPMFILE_SPECFILE specfile = hdr[rpm.RPMTAG_FILENAMES][specidx] installSrpm(srpm, chrootDir, buildTopDir) for arch in arches: logfile = "%s/%s/%s-%s-%s.%s.log" % (logDir, buildVersion, hdr[rpm.RPMTAG_NAME], hdr[rpm.RPMTAG_VERSION], hdr[rpm.RPMTAG_RELEASE], arch) buildPackage(specfile, chrootDir, buildTopDir, logfile, arch) dirs = os.listdir("%s/RPMS/" % (buildTopDir)) pkgOutDir = "%s/%s/%s/%s-%s" % (outDir, buildVersion, hdr[rpm.RPMTAG_NAME], hdr[rpm.RPMTAG_VERSION], hdr[rpm.RPMTAG_RELEASE]) if os.access(pkgOutDir, os.X_OK): rmrf(pkgOutDir) os.makedirs(pkgOutDir, 0755) for i in dirs: os.rename("%s/RPMS/%s/" % (buildTopDir, i), "%s/%s" % (pkgOutDir, i)) os.rename("%s/SRPMS" % (buildTopDir), "%s/SRPMS" % (pkgOutDir)) # remove the temporary directory rmrf(buildTopDir) if __name__ == "__main__": main()