summaryrefslogtreecommitdiff
path: root/scripts/build-packages
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/build-packages')
-rwxr-xr-xscripts/build-packages332
1 files changed, 332 insertions, 0 deletions
diff --git a/scripts/build-packages b/scripts/build-packages
new file mode 100755
index 00000000..e800b80a
--- /dev/null
+++ b/scripts/build-packages
@@ -0,0 +1,332 @@
+#!/usr/bin/env python3
+
+import os
+import subprocess
+import sys
+import shutil
+import argparse
+import logging
+
+current_working_directory = os.getcwd()
+repo_root = subprocess.check_output('git rev-parse --show-toplevel', shell=True, universal_newlines=True).rstrip('\n')
+repo_sha = subprocess.check_output('git rev-parse --short=12 HEAD', shell=True, universal_newlines=True).rstrip('\n')
+
+def add_package(name, url=None, commit='HEAD', branch='current', tag=None, custombuild_cmd=None):
+ """
+ Build up source package with URL and build commands executed during the later
+ called build_package step.
+
+ If no additional information is passed we will use the latest commit from current
+ branch
+
+ If no URL is passed we assume it's a regular VyOS package from the VyOS Github
+ namespace at https://github.com/vyos
+ """
+
+ if not url:
+ url = 'https://github.com/vyos/' + name + '.git'
+
+ package = {
+ 'name': name,
+ 'url': url,
+ 'commit': commit,
+ 'tag': tag,
+ 'branch': branch,
+ 'path': repo_root + '/packages/' + name,
+ 'custombuild_cmd': custombuild_cmd
+ }
+
+ return package
+
+
+
+def call(bashCommand, log, **kwargs):
+ """
+ Run command with arguments. Wait for command to complete.
+
+ Send output to logging module passed as 'log'.
+ """
+
+ from subprocess import Popen, PIPE, STDOUT, check_output, CalledProcessError
+ from tempfile import TemporaryFile
+ from time import sleep
+
+ log.debug("Executing '{}'".format(bashCommand))
+
+ # code borrowsed from:
+ # https://stackoverflow.com/questions/38374063/python-can-we-use-tempfile-with-subprocess-to-get-non-buffering-live-output-in-p
+ # the temp file will be automatically cleaned up
+ output = TemporaryFile()
+ error = TemporaryFile()
+
+ kwargs['stdout'] = output
+ kwargs['stderr'] = error
+ kwargs['shell'] = True
+ kwargs['universal_newlines'] = True
+
+ sub = Popen(bashCommand, **kwargs)
+ while sub.poll() is None:
+ where = output.tell()
+ lines = output.readline()
+ if not lines:
+ sleep(0.3)
+ output.seek(where)
+ else:
+ log.debug(lines.decode().rstrip('\n'))
+
+ where = error.tell()
+ lines = error.readline()
+ if not lines:
+ sleep(0.3)
+ error.seek(where)
+ else:
+ log.info(lines.decode().rstrip('\n'))
+
+ error.close()
+ output.close()
+ return sub.returncode
+
+def clone_package(pkg, log):
+ """
+ Clone Git repository from URL embedded in pkg to local disk
+
+ First cleanup any possible leftovers from previous builds
+ """
+
+ if args.clean:
+ # delete repository from disk
+ if os.path.isdir(pkg['path']):
+ log.debug("Cleaning '{}'".format(pkg['path']))
+ shutil.rmtree(pkg['path'])
+ else:
+ if os.path.isdir(pkg['path']):
+ # Change current directory into Git repo for this package
+ os.chdir(pkg['path'])
+
+ bashCommand = 'git clean -d -x --force && git reset --hard ' + pkg['commit']
+ return call(bashCommand, log)
+
+ # resolve given tag to commit id to use shallow clone
+ bashCommand = 'git clone ' + pkg['url']
+ if pkg['tag']:
+ bashCommand += ' --branch ' + pkg['tag']
+ elif pkg['branch']:
+ bashCommand += ' --depth 1 --branch ' + pkg['branch']
+
+ bashCommand += ' ' + pkg['path']
+ return call(bashCommand, log)
+
+
+def build_package(pkg, log=None):
+ """
+ Generate Debian package from passed 'pkg'
+ """
+
+ # Change current directory into Git repo for this package
+ os.chdir(pkg['path'])
+
+ # Overwrite custom build command if required, e.g. libyang
+ bashCommand = ''
+ if pkg['custombuild_cmd']:
+ bashCommand = pkg['custombuild_cmd']
+ else:
+ # Build package
+ bashCommand = 'dpkg-buildpackage -uc -us -tc -b'
+ if args.parallel:
+ bashCommand += ' -j' + str(os.cpu_count())
+
+ return call(bashCommand, log)
+
+# a List of all Vyatta/VyOS based packages
+vyos_packages = ['vyatta-bash',
+ 'vyatta-cfg',
+ 'vyatta-op',
+ 'vyatta-cfg-system',
+ 'vyatta-cfg-firewall',
+ 'vyatta-op-firewall',
+ 'vyatta-cfg-vpn',
+ 'vyatta-op-vpn',
+ 'vyatta-cfg-qos',
+ 'vyatta-op-qos',
+ 'vyatta-cfg-op-pppoe',
+ 'vyatta-openvpn',
+ 'vyatta-conntrack',
+ 'vyatta-conntrack-sync',
+ 'vyatta-nat',
+ 'vyatta-config-mgmt',
+ 'vyatta-config-migrate',
+ 'vyatta-zone',
+ 'vyatta-cluster',
+ 'vyatta-eventwatch',
+ 'vyatta-webproxy',
+ 'vyatta-cfg-quagga',
+ 'vyatta-op-quagga',
+ 'vyatta-op-dhcp-server',
+ 'vyatta-wireless',
+ 'vyatta-wirelessmodem',
+ 'vyatta-wanloadbalance',
+ 'vyatta-netflow',
+ 'vyatta-lldp',
+ 'vyatta-ipv6-rtradv',
+ 'vyatta-ravpn',
+ 'vyos-nhrp',
+ 'vyos-world',
+ 'vyos-1x',
+ 'vyatta-iproute',
+ 'vyatta-quagga',
+ 'vyos-strongswan',
+ 'vyos-vmwaretools-scripts',
+ 'vyos-netplug',
+ 'vyos-xe-guest-utilities',
+ 'vyatta-biosdevname',
+ 'vyos-opennhrp',
+ 'vyos-salt-minion',
+ 'xl2tpd',
+ 'mdns-repeater',
+ 'udp-broadcast-relay',
+ 'pmacct',
+ 'ddclient',
+ 'igmpproxy',
+ 'eventwatchd',
+ 'conntrack-tools']
+
+# Special packages mean packages which are located no in the VyOS namespace
+# or require fancy build instructions
+pkg_special = []
+
+# libvyosconfig/ipaddrcheck uses a different default branch
+libvyosconfig_build_cmd = "eval $(opam env --root=/opt/opam --set-root) && " \
+ "dpkg-buildpackage -b -us -uc -tc"
+pkg_special.append( add_package('libvyosconfig', branch='master', custombuild_cmd=libvyosconfig_build_cmd))
+pkg_special.append( add_package('ipaddrcheck', branch='master'))
+
+# Packages where we directly build the upstream source
+pkg_special.append( add_package('hvinfo', url='https://github.com/dmbaturin/hvinfo.git', branch='master') )
+pkg_special.append( add_package('lldpd', url='https://github.com/vincentbernat/lldpd.git', branch='master', tag='1.0.3') )
+
+#
+# FreeRangeRouting (FRR) packages
+#
+pkg_special.append( add_package('rtrlib', url='https://github.com/rtrlib/rtrlib.git', branch='master', tag='v0.6.3') )
+
+frr_build_cmd = './tools/tarsource.sh -V && dpkg-buildpackage -us -uc -Ppkg.frr.rtrlib -d'
+pkg_special.append( add_package('frr', url='https://github.com/FRRouting/frr.git', branch='master', tag='frr-7.0', custombuild_cmd=frr_build_cmd) )
+#libyang_build_cmd = 'mkdir build && cd build && cmake .. && make build-deb && mv debs/* ' + repo_root + '/packages'
+#pkg_special.append( add_package('libyang', url='https://github.com/opensourcerouting/libyang.git', commit='179da47', branch='master', custombuild_cmd=libyang_build_cmd) )
+
+
+#
+# Linux (VyOS) Kernel
+#
+kernel_build_cmd = "export VERSION=$(grep '^VERSION' Makefile | grep -Eo '[0-9]{1,4}') && " \
+ "export PATCHLEVEL=$(grep '^PATCHLEVEL' Makefile | grep -Eo '[0-9]{1,4}') && " \
+ "export SUBLEVEL=$(grep '^SUBLEVEL' Makefile | grep -Eo '[0-9]{1,4}') && " \
+ "echo ${VERSION}.${PATCHLEVEL}.${SUBLEVEL}-amd64-vyos > " + repo_root + "/data/kernel_version && " \
+ "make x86_64_vyos_defconfig && " \
+ "LOCALVERSION='' make-kpkg --rootcmd fakeroot --initrd --append_to_version -amd64-vyos " \
+ " --revision=${VERSION}.${PATCHLEVEL}.${SUBLEVEL}-0 kernel_headers kernel_image -j" + str(os.cpu_count())
+pkg_special.append( add_package('vyos-kernel', branch='linux-vyos-4.19.y', custombuild_cmd=kernel_build_cmd) )
+
+
+
+#
+# WireGuard Kernel Module
+#
+wireguard_build_cmd = "echo 'src/wireguard.ko /lib/modules/'$(cat " + repo_root + "/data/kernel_version) > debian/wireguard-modules.install && " \
+ "KERNELDIR=" + repo_root + "/packages/vyos-kernel dpkg-buildpackage -b -us -uc -tc -j" + str(os.cpu_count())
+pkg_special.append( add_package('vyos-wireguard', custombuild_cmd=wireguard_build_cmd) )
+
+
+
+#
+# Accell-PPP Package and Kernel Module
+#
+accel_ppp_build_cmd = "echo 'lib/modules/'$(cat " + repo_root + "/data/kernel_version)'/extra/*.ko' > debian/vyos-accel-ppp-ipoe-kmod.install && " \
+ "sed -i 's#[0-9].[0-9][0-9].[0-9]*-amd64-vyos#'$(cat " + repo_root + "/data/kernel_version)'#g' debian/rules && " \
+ "KERNELDIR=" + repo_root + "/packages/vyos-kernel dpkg-buildpackage -b -us -uc -tc -j" + str(os.cpu_count())
+pkg_special.append( add_package('vyos-accel-ppp', custombuild_cmd=accel_ppp_build_cmd) )
+
+
+# A list of all packages we will build in the end
+pkg_build = []
+
+
+
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser()
+ parser.add_argument('-v', '--verbose', action='count', default=0, help='Increase logging verbosity for each occurance')
+ parser.add_argument('-c', '--clean', action='store_true', help='Re-clone required Git repositories')
+ parser.add_argument('-l', '--list-packages', action='store_true', help='List all packages to build')
+ parser.add_argument('-b', '--build', nargs='+', help='Whitespace separated list of packages to build')
+ parser.add_argument('-f', '--fetch', action='store_true', help='Fetch sources only, no build')
+ parser.add_argument('-p', '--parallel', action='store_true', help='Build on all CPUs')
+
+
+ args = parser.parse_args()
+
+ levels = [ logging.INFO, logging.WARNING, logging.DEBUG ]
+ level = levels[min(len(levels)-1,args.verbose)] # capped to number of levels
+ logging.basicConfig(level=level, format="%(asctime)s %(name)s %(message)s")
+
+ print("Using vyos-build repository ('{}') commit '{}'\n".format(repo_root, repo_sha))
+
+ if args.list_packages:
+ print("Individual packages available for build:")
+ for pkg in vyos_packages:
+ print(' * ' + pkg)
+ for pkg in pkg_special:
+ print(' * ' + pkg['name'])
+
+ sys.exit(0)
+
+ #
+ # Only add selective packages to the build list
+ #
+ if args.build:
+ # NOTE: remove double added packages from list
+ for target in args.build:
+ if target in vyos_packages:
+ pkg_build.append(add_package( target ))
+ continue
+
+ found = False
+ for pkg in pkg_special:
+ if target == pkg['name']:
+ found = True
+ # package already formed
+ pkg_build.append( pkg )
+ break
+
+ if not found:
+ print("Invalid choice '" + target + "', for -b/--build use --list-packages for complete list!")
+ sys.exit(1)
+
+ else:
+ # Add all VyOS packages to the package list
+ for pkg in vyos_packages:
+ pkg_build.append(add_package( pkg ))
+
+ # We also wan't to build all of our special packages
+ for pkg in pkg_special:
+ pkg_build.append( pkg )
+
+ # Build all VyOS packages (packages found on https://github.com/vyos
+ # and referenced in vyos_packages)
+ for pkg in pkg_build:
+ # Create a logging instance per package
+ log = logging.getLogger(pkg['name'])
+
+ ret = clone_package(pkg, log)
+ if ret:
+ log.error("ERROR cloning source")
+ sys.exit(1)
+ else:
+ # only build packages if fetch flag is not set
+ if not args.fetch:
+ ret = build_package(pkg, log)
+ if ret:
+ log.error("ERROR building source")
+ sys.exit(1)
+
+ sys.exit(0)