#!/usr/bin/env python """Build OpenDaylight's .debs using YAML build configs and Jinja2 templates.""" import argparse import os import shutil from string import Template import subprocess import sys import cache.cache as cache import templates.build_debianfiles as build_debfiles try: import yaml except ImportError: sys.stderr.write("We recommend using our included Vagrant env.\n") sys.stderr.write("Else, install the Python libs it installs.\n") raise # Common paths used in this script # This file is assumed to be in the root of the .deb build logic's dir # structure project_root = os.path.dirname(os.path.abspath(__file__)) # Cache directory for OpenDaylight's release tarball cache_dir = os.path.join(project_root, "cache") # Debian templates directory templates_dir = os.path.join(project_root, "templates") # Specialized opendaylight directory for each build odl_dir_template = Template("opendaylight/opendaylight-$version_major.$version_minor." "$version_patch-$pkg_version/") odl_deb_template = Template("opendaylight/opendaylight_$version_major.$version_minor." "$version_patch-${pkg_version}_all.deb") def build_deb(build): """Build the .deb described by the given build description. :param build: Description of a debian build, typically from build_vars.yaml :type build: dict """ # Specialize a series of name templates for the given build odl_dir_name = odl_dir_template.substitute(build) odl_dir_path = os.path.join(templates_dir, os.pardir, odl_dir_name) odl_deb = odl_deb_template.substitute(build) # Call helper script to build the required debian files build_debfiles.build_debfiles(build) # Call a helper function to cache the artifacts required for each build odl_tarball_path = cache.cache_build(build) # Move ODL's tarball to the specialized OpenDaylight directory shutil.copy(odl_tarball_path, odl_dir_path) # Build debian package os.chdir(odl_dir_path) subprocess.call(["dpkg-buildpackage", "-us -uc -b", odl_dir_path], shell=True) # Install opendaylight's dependencies control_file_path = os.path.join(odl_dir_path, "debian/control") subprocess.call(["sudo mk-build-deps -i " + control_file_path], shell=True) os.chdir(project_root) # Copy the .debs from their output dir to the cache dir shutil.copy(odl_deb, cache_dir) # When run as a script, accept a set of builds and execute them if __name__ == "__main__": # Load .deb build variables from a YAML config file build_vars_path = os.path.join(project_root, "build_vars.yaml") with open(build_vars_path) as deb_var_file: build_vars = yaml.load(deb_var_file) # Accept the version(s) of the build(s) to perform as args parser = argparse.ArgumentParser() existing_build_group = parser.add_argument_group("Existing build") existing_build_group.add_argument( "-v", "--version", action="append", metavar="major minor patch deb", nargs="*", help="Deb version(s) to build" ) new_build_group = parser.add_argument_group("New build") new_build_group.add_argument( "--major", help="Major (element) version to build") new_build_group.add_argument("--minor", help="Minor (SR) version to build") new_build_group.add_argument("--patch", help="Patch version to build") new_build_group.add_argument("--deb", help="Deb version to build") new_build_group.add_argument( "--sysd_commit", help="Version of ODL unitfile to package") new_build_group.add_argument("--codename", help="Codename for ODL version") new_build_group.add_argument( "--download_url", help="Tarball to repackage into .deb") new_build_group.add_argument( "--java_version", help="Java dependency for the ODL release") new_build_group.add_argument( "--changelog_date", help="Date this .deb was defined") new_build_group.add_argument( "--changelog_time", help="Time this .deb was defined") new_build_group.add_argument( "--changelog_name", help="Name of person who defined .deb") new_build_group.add_argument( "--changelog_email", help="Email of person who defined .deb") # Print help if no arguments are given if len(sys.argv) == 1: parser.print_help() sys.exit(1) # Parse the given args args = parser.parse_args() # Build list of .deb builds to perform builds = [] if args.version: # Build a list of requested versions as dicts of version components versions = [] version_keys = ["version_major", "version_minor", "version_patch", "pkg_version"] # For each version arg, match all version components to build_vars name for version in args.version: versions.append(dict(zip(version_keys, version))) # Find every .deb build that matches any version argument # A passed version "matches" a build when the provided version # components are a subset of the version components of a build. Any # version components that aren't passed are simply not checked, so # they can't fail the match, effectively wild-carding them. for build in build_vars["builds"]: for version in versions: # Converts both dicts' key:value pairs to lists of tuples and # checks that each tuple in the version list is present in the # build list. if all(item in build.items() for item in version.items()): builds.append(build) else: builds.append({"version_major": args.major, "version_minor": args.minor, "version_patch": args.patch, "pkg_version": args.deb, "sysd_commit": args.sysd_commit, "codename": args.codename, "download_url": args.download_url, "java_version": args.java_version, "changelog_date": args.changelog_date, "changelog_time": args.changelog_time, "changelog_name": args.changelog_name, "changelog_email": args.changelog_email}) for build in builds: build_deb(build)