#!/usr/bin/python import contextlib import glob import os import shutil import subprocess import sys import tempfile import tempita # Mapping of expected packages to there full name... PKG_MP = { 'boto': 'python-boto', 'tempita': 'python-tempita', 'prettytable': 'python-prettytable', 'oauth': 'python-oauth', 'configobj': 'python-configobj', 'yaml': 'PyYAML', 'argparse': 'python-argparse' } @contextlib.contextmanager def tmpdir(): t = tempfile.mkdtemp() try: yield t finally: shutil.rmtree(t) def join(*paths): p = os.path.join(*paths) return os.path.abspath(p) def tiny_p(cmd): # Darn python 2.6 doesn't have check_output (argggg) info("Running %s" % (cmd)) sp = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=None) (out, err) = sp.communicate() if sp.returncode not in [0]: raise RuntimeError("Failed running %s [rc=%s] (%s, %s)" % (cmd, sp.returncode, out, err)) return (out, err) def info(msg): print("INFO: %s" % (msg)) def warn(msg): print("WARNING: %s" % (msg)) def generate_spec_contents(tmpl_fn, revno, version): # Tmpl params subs = {} subs['version'] = version subs['revno'] = revno subs['release'] = revno subs['archive_name'] = '%{name}-%{version}-' + subs['revno'] + '.tar.gz' subs['bd_requires'] = ['python-devel', 'python-setuptools'] requires = [] cmd = [sys.executable, join(os.pardir, 'tools', 'read-dependencies')] (stdout, _stderr) = tiny_p(cmd) pkgs = stdout.splitlines() # Map to known packages for e in pkgs: e = e.lower().strip() tgt_pkg = None for n in PKG_MP.keys(): if e.find(n) != -1: tgt_pkg = PKG_MP.get(n) if not tgt_pkg: raise RuntimeError(("Do not know how to translate %s to " " a known package") % (e)) else: requires.append(tgt_pkg) base_name = 'cloud-init-%s-%s' % (version, subs['revno']) subs['requires'] = requires (stdout, _stderr) = tiny_p([sys.executable, join(os.getcwd(), 'rpm-changelog')]) subs['changelog'] = stdout.strip() # See: http://www.zarb.org/~jasonc/macros.php # Pickup any special files docs = [ 'TODO', 'LICENSE', 'ChangeLog', 'Requires', '%{_defaultdocdir}/cloud-init/*', ] subs['docs'] = docs configs = [ 'cloud/cloud.cfg', 'cloud/cloud.cfg.d/*.cfg', 'cloud/cloud.cfg.d/README', 'cloud/templates/*', ] subs['configs'] = configs other_files = [ '%{_bindir}/*', '/usr/lib/cloud-init/*', ] subs['files'] = other_files with open(tmpl_fn, 'r') as fh: tmpl = tempita.Template(fh.read()) contents = tmpl.substitute(**subs) return (base_name, '%s.tar.gz' % (base_name), contents) def archive_code(): (stdout, _stderr) = tiny_p([sys.executable, join(os.getcwd(), 'tar-me')]) lines = stdout.splitlines() revno = lines[0] version = lines[1] bname = lines[2] arc_fn = lines[3] return (revno, version, arc_fn) def main(): # Clean out the root dir and make sure the dirs we want are in place root_dir = os.path.expanduser("~/rpmbuild") info("Cleaning %s" % (root_dir)) if os.path.isdir(root_dir): shutil.rmtree(root_dir) arc_dir = os.path.join(root_dir, 'SOURCES') for d in [root_dir, arc_dir]: os.makedirs(d) # Archive the code (revno, version, archive_fn) = archive_code() real_archive_fn = os.path.join(arc_dir, os.path.basename(archive_fn)) shutil.move(archive_fn, real_archive_fn) info("Archived code to %s" % (real_archive_fn)) # Form the spec file to be used tmpl_fn = os.path.join(os.getcwd(), 'brpm.tmpl') info("Generated spec file from template %s" % (tmpl_fn)) (base_name, arc_name, contents) = generate_spec_contents(tmpl_fn, revno, version) spec_fn = os.path.join(root_dir, 'cloud-init.spec') with open(spec_fn, 'w') as fh: fh.write(contents) info("Wrote spec file to %s" % (spec_fn)) # Now build it! cmd = ['rpmbuild', '-ba', spec_fn] info("Running rpmbuild %s" % (cmd)) tiny_p(cmd) info("Rpmbuild completed!") # Copy the items built to our local dir globs = [] globs.extend(glob.glob("%s/*.rpm" % (os.path.join(root_dir, 'RPMS', 'noarch')))) globs.extend(glob.glob("%s/*.rpm" % (os.path.join(root_dir, 'RPMS')))) globs.extend(glob.glob("%s/*.rpm" % (os.path.join(root_dir, 'SRPMS')))) for fn in globs: n = os.path.basename(fn) tgt_fn = os.path.join(os.getcwd(), n) shutil.move(fn, tgt_fn) info("Copied %s to %s" % (n, tgt_fn)) return 0 if __name__ == '__main__': sys.exit(main())