summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Breunig <christian@breunig.cc>2024-05-06 17:16:17 +0200
committerGitHub <noreply@github.com>2024-05-06 17:16:17 +0200
commit6a8b976d49842fb51b01e96b9b23f4431575b9fc (patch)
treef39933179d860be1c4ebe2f9736c782b62022ae7
parent2da9d989d17e90d12a6d22222270729531721a5e (diff)
parent255bf960995ec072ba7b72fe2d926cfd986adc2f (diff)
downloadvyos-build-6a8b976d49842fb51b01e96b9b23f4431575b9fc.tar.gz
vyos-build-6a8b976d49842fb51b01e96b9b23f4431575b9fc.zip
Merge pull request #593 from c-po/flavor-backport
build: backport of new flavor build system
-rw-r--r--Makefile15
l---------build-vyos-image2
-rw-r--r--data/build-flavors/dell-vep1400.toml116
-rw-r--r--data/build-flavors/dell-vep4600.toml267
-rw-r--r--docker/Dockerfile4
-rwxr-xr-xpackages/linux-kernel/build-linux-firmware.sh4
-rwxr-xr-xscripts/build-vyos-image526
-rwxr-xr-xscripts/check-build-env54
-rwxr-xr-xscripts/image-build/build-vyos-image644
-rw-r--r--scripts/image-build/defaults.py (renamed from scripts/vyos_build_defaults.py)12
-rw-r--r--scripts/image-build/raw_image.py211
-rw-r--r--scripts/image-build/utils.py (renamed from scripts/vyos_build_utils.py)11
-rwxr-xr-xscripts/import-local-packages13
-rwxr-xr-xscripts/list-package-arch7
-rwxr-xr-xscripts/list-required-firmware75
-rwxr-xr-xscripts/pbuilder-config54
-rwxr-xr-xscripts/pbuilder-setup52
-rwxr-xr-xscripts/pbuilder/hooks/C10shell6
-rwxr-xr-xtools/dell/90-vep.chroot16
-rwxr-xr-xtools/dell/vep-hook28
-rw-r--r--tools/dell/vep1400/10-eth0-000.link7
-rw-r--r--tools/dell/vep1400/10-eth1-000.link7
-rw-r--r--tools/dell/vep1400/10-eth2-000.link7
-rw-r--r--tools/dell/vep1400/10-eth3-000.link7
-rw-r--r--tools/dell/vep1400/10-eth4-000.link7
-rw-r--r--tools/dell/vep1400/10-eth5-000.link7
-rw-r--r--tools/dell/vep1400/10-eth6-000.link7
-rw-r--r--tools/dell/vep1400/10-eth7-000.link7
-rw-r--r--tools/dell/vep4600/10-eth0-000.link6
-rw-r--r--tools/dell/vep4600/10-eth0-001.link6
-rw-r--r--tools/dell/vep4600/10-eth1-000.link6
-rw-r--r--tools/dell/vep4600/10-eth1-001.link6
-rw-r--r--tools/dell/vep4600/10-eth10-000.link6
-rw-r--r--tools/dell/vep4600/10-eth11-000.link6
-rw-r--r--tools/dell/vep4600/10-eth12-000.link6
-rw-r--r--tools/dell/vep4600/10-eth13-000.link6
-rw-r--r--tools/dell/vep4600/10-eth14-000.link6
-rw-r--r--tools/dell/vep4600/10-eth2-000.link6
-rw-r--r--tools/dell/vep4600/10-eth2-001.link6
-rw-r--r--tools/dell/vep4600/10-eth3-000.link6
-rw-r--r--tools/dell/vep4600/10-eth4-000.link6
-rw-r--r--tools/dell/vep4600/10-eth5-000.link6
-rw-r--r--tools/dell/vep4600/10-eth6-000.link6
-rw-r--r--tools/dell/vep4600/10-eth7-000.link6
-rw-r--r--tools/dell/vep4600/10-eth8-000.link6
-rw-r--r--tools/dell/vep4600/10-eth9-000.link6
-rw-r--r--tools/dell/vep4600/10-unused0-000.link6
-rw-r--r--tools/dell/vep4600/10-unused0-001.link6
-rw-r--r--tools/dell/vep4600/10-unused1-000.link6
-rw-r--r--tools/dell/vep4600/10-unused1-001.link6
-rw-r--r--tools/dell/vep4600/99-default.link0
-rwxr-xr-xtools/get_latest_iso.py31
-rw-r--r--tools/gpl-header-template17
-rw-r--r--tools/submod-mk84
-rwxr-xr-xtools/switch-remote35
55 files changed, 1264 insertions, 1208 deletions
diff --git a/Makefile b/Makefile
index ebb37075..62587ced 100644
--- a/Makefile
+++ b/Makefile
@@ -7,19 +7,8 @@ all:
@echo "Make what specifically?"
@echo "The most common target is 'iso'"
-.PHONY: iso
-.ONESHELL:
-iso: clean
- set -o pipefail
- @./build-vyos-image iso
- exit 0
-
-.PHONY: prepare-package-env
-.ONESHELL:
-prepare-package-env:
- @set -e
- @scripts/pbuilder-config
- @scripts/pbuilder-setup
+%:
+ VYOS_TEMPLATE_DIR=`pwd`/packages/vyos-1x/data/templates/ ./build-vyos-image $*
.PHONY: checkiso
.ONESHELL:
diff --git a/build-vyos-image b/build-vyos-image
index 360be935..0c61a9d5 120000
--- a/build-vyos-image
+++ b/build-vyos-image
@@ -1 +1 @@
-scripts/build-vyos-image \ No newline at end of file
+scripts/image-build/build-vyos-image \ No newline at end of file
diff --git a/data/build-flavors/dell-vep1400.toml b/data/build-flavors/dell-vep1400.toml
new file mode 100644
index 00000000..8ce3d8b6
--- /dev/null
+++ b/data/build-flavors/dell-vep1400.toml
@@ -0,0 +1,116 @@
+# ISO image for Dell VEP4600 devices
+
+image_formats = "iso"
+
+# Replace built-in NIC naming rules with empty files
+# to prevent them from taking any effect
+
+[[includes_chroot]]
+ path = "lib/systemd/network/99-default.link"
+ data = ''
+
+[[includes_chroot]]
+ path = "lib/udev/rules.d/65-vyatta-net.rules"
+ data = ''
+
+[[includes_chroot]]
+ path = "lib/udev/rules.d/75-persistent-net-generator.rules"
+ data = ''
+
+# Install platform-specific link files
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-eth0-000.link"
+ data = '''
+[Match]
+Path=pci-0000:05:00.1
+Driver=ixgbe
+
+[Link]
+Name=eth0
+Alias=SFP+1
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-eth1-000.link"
+ data = '''
+[Match]
+Path=pci-0000:05:00.0
+Driver=ixgbe
+
+[Link]
+Name=eth1
+Alias=SFP+2
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-eth2-000.link"
+ data = '''
+[Match]
+Path=pci-0000:02:00.2
+Driver=igb
+
+[Link]
+Name=eth2
+Alias=GE1
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-eth3-000.link"
+ data = '''
+[Match]
+Path=pci-0000:02:00.3
+Driver=igb
+
+[Link]
+Name=eth3
+Alias=GE2
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-eth4-000.link"
+ data = '''
+[Match]
+Path=pci-0000:02:00.0
+Driver=igb
+
+[Link]
+Name=eth4
+Alias=GE3
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-eth5-000.link"
+ data = '''
+[Match]
+Path=pci-0000:02:00.1
+Driver=igb
+
+[Link]
+Name=eth5
+Alias=GE4
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-eth6-000.link"
+ data = '''
+[Match]
+Path=pci-0000:07:00.1
+Driver=ixgbe
+
+[Link]
+Name=eth6
+Alias=GE5
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-eth7-000.link"
+ data = '''
+[Match]
+Path=pci-0000:07:00.0
+Driver=ixgbe
+
+[Link]
+Name=eth7
+Alias=GE6
+'''
diff --git a/data/build-flavors/dell-vep4600.toml b/data/build-flavors/dell-vep4600.toml
new file mode 100644
index 00000000..97256b41
--- /dev/null
+++ b/data/build-flavors/dell-vep4600.toml
@@ -0,0 +1,267 @@
+# ISO image for Dell VEP4600 devices
+
+image_formats = "iso"
+
+# Replace built-in NIC naming rules with empty files
+# to prevent them from taking any effect
+
+[[includes_chroot]]
+ path = "lib/systemd/network/99-default.link"
+ data = ''
+
+[[includes_chroot]]
+ path = "lib/udev/rules.d/65-vyatta-net.rules"
+ data = ''
+
+[[includes_chroot]]
+ path = "lib/udev/rules.d/75-persistent-net-generator.rules"
+ data = ''
+
+# Install platform-specific link files
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-eth0-000.link"
+ data = '''
+[Match]
+Path=pci-0000:04:00.0
+Driver=igb
+
+[Link]
+Name=eth0
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-eth0-001.link"
+ data = '''
+[Match]
+Path=pci-0000:05:00.0
+Driver=igb
+
+[Link]
+Name=eth0
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-eth10-000.link"
+ data = '''
+[Match]
+Path=pci-0000:65:00.3
+Driver=i40e
+
+[Link]
+Name=eth10
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-eth1-000.link"
+ data = '''
+[Match]
+Path=pci-0000:b8:00.0
+Driver=i40e
+
+[Link]
+Name=eth1
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-eth1-001.link"
+ data = '''
+[Match]
+Path=pci-0000:b6:00.0
+Driver=i40e
+
+[Link]
+Name=eth1
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-eth11-000.link"
+ data = '''
+[Match]
+Path=pci-0000:17:00.0
+Driver=i40e
+
+[Link]
+Name=eth11
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-eth12-000.link"
+ data = '''
+[Match]
+Path=pci-0000:17:00.1
+Driver=i40e
+
+[Link]
+Name=eth12
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-eth13-000.link"
+ data = '''
+[Match]
+Path=pci-0000:17:00.2
+Driver=i40e
+
+[Link]
+Name=eth13
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-eth14-000.link"
+ data = '''
+[Match]
+Path=pci-0000:17:00.3
+Driver=i40e
+
+[Link]
+Name=eth14
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-eth2-000.link"
+ data = '''
+[Match]
+Path=pci-0000:b8:00.1
+Driver=i40e
+
+[Link]
+Name=eth2
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-eth2-001.link"
+ data = '''
+[Match]
+Path=pci-0000:b6:00.1
+Driver=i40e
+
+[Link]
+Name=eth2
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-eth3-000.link"
+ data = '''
+[Match]
+Path=pci-0000:02:00.1
+Driver=igb
+
+[Link]
+Name=eth3
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-eth4-000.link"
+ data = '''
+[Match]
+Path=pci-0000:02:00.0
+Driver=igb
+
+[Link]
+Name=eth4
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-eth5-000.link"
+ data = '''
+[Match]
+Path=pci-0000:02:00.3
+Driver=igb
+
+[Link]
+Name=eth5
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-eth6-000.link"
+ data = '''
+[Match]
+Path=pci-0000:02:00.2
+Driver=igb
+
+[Link]
+Name=eth6
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-eth7-000.link"
+ data = '''
+[Match]
+Path=pci-0000:65:00.0
+Driver=i40e
+
+[Link]
+Name=eth7
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-eth8-000.link"
+ data = '''
+[Match]
+Path=pci-0000:65:00.1
+Driver=i40e
+
+[Link]
+Name=eth8
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-eth9-000.link"
+ data = '''
+[Match]
+Path=pci-0000:65:00.2
+Driver=i40e
+
+[Link]
+Name=eth9
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-unused0-000.link"
+ data = '''
+[Match]
+Path=pci-0000:b8:00.2
+Driver=i40e
+
+[Link]
+Name=unused0
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-unused0-001.link"
+ data = '''
+[Match]
+Path=pci-0000:b6:00.2
+Driver=i40e
+
+[Link]
+Name=unused0
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-unused1-000.link"
+ data = '''
+[Match]
+Path=pci-0000:b8:00.3
+Driver=i40e
+
+[Link]
+Name=unused1
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/10-unused1-001.link"
+ data = '''
+[Match]
+Path=pci-0000:b6:00.3
+Driver=i40e
+
+[Link]
+Name=unused1
+'''
+
+[[includes_chroot]]
+ path = "etc/systemd/network/99-default.link"
+ data = '''
+'''
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 927c2fa9..9dad4693 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -104,7 +104,9 @@ RUN apt-get update && apt-get install -y \
python3-tomli \
yq \
debootstrap \
- live-build
+ live-build \
+ gdisk \
+ dosfstools
# Syslinux and Grub2 is only supported on x86 and x64 systems
RUN if dpkg-architecture -ii386 || dpkg-architecture -iamd64; then \
diff --git a/packages/linux-kernel/build-linux-firmware.sh b/packages/linux-kernel/build-linux-firmware.sh
index 39cb243b..2b1fa7b7 100755
--- a/packages/linux-kernel/build-linux-firmware.sh
+++ b/packages/linux-kernel/build-linux-firmware.sh
@@ -1,9 +1,5 @@
#!/bin/bash
-# This script will use "list-required-firmware" to scan the kernel source repository
-# in combination with its configuration file which drivers are compiled. Some of those
-# drivers require proprietary firmware.
-#
# All selected drivers are then precomfiled "make drivers/foo/bar.i" and we grep for
# the magic word "UNIQUE_ID_firmware" which identifies firmware files.
diff --git a/scripts/build-vyos-image b/scripts/build-vyos-image
deleted file mode 100755
index 141da5e2..00000000
--- a/scripts/build-vyos-image
+++ /dev/null
@@ -1,526 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2022-2024 VyOS maintainers and contributors
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 or later as
-# published by the Free Software Foundation.
-#
-# 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, see <http://www.gnu.org/licenses/>.
-#
-# File: build-vyos-image
-# Purpose: builds VyOS images using a fork of Debian's live-build tool
-
-import re
-import os
-import sys
-import uuid
-import glob
-import shutil
-import getpass
-import platform
-import argparse
-import datetime
-import functools
-import string
-
-import json
-
-try:
- import tomli
- import jinja2
- import git
-except ModuleNotFoundError as e:
- print(f"Cannot load a required library: {e}")
- print("Please make sure the following Python3 modules are installed: tomli jinja2 git")
-
-import vyos_build_utils as utils
-import vyos_build_defaults as defaults
-
-# argparse converts hyphens to underscores,
-# so for lookups in the original options hash we have to convert them back
-def field_to_option(s):
- return re.sub(r'_', '-', s)
-
-def get_default_build_by():
- return "{user}@{host}".format(user= getpass.getuser(), host=platform.node())
-
-def get_validator(optdict, name):
- try:
- return optdict[name][2]
- except KeyError:
- return None
-
-def merge_dicts(source, destination):
- """ Merge two dictionaries and return a new dict which has the merged key/value pairs.
- Merging logic is as follows:
- Sub-dicts are merged.
- List values are combined.
- Scalar values are set to those from the source dict.
- """
- from copy import deepcopy
- tmp = deepcopy(destination)
-
- for key, value in source.items():
- if key not in tmp:
- tmp[key] = value
- elif isinstance(source[key], dict):
- tmp[key] = merge_dicts(source[key], tmp[key])
- elif isinstance(source[key], list):
- tmp[key] = source[key] + tmp[key]
- else:
- tmp[key] = source[key]
-
- return tmp
-
-def has_nonempty_key(config, key):
- if key in config:
- if config[key]:
- return True
- return False
-
-def make_toml_path(dir, file_basename):
- return os.path.join(dir, file_basename + ".toml")
-
-
-if __name__ == "__main__":
- ## Check if the script is running wirh root permissions
- ## Since live-build requires privileged calls such as chroot(),
- ## there's no real way around it.
- if os.getuid() != 0:
- print("E: this script requires root privileges")
- sys.exit(1)
-
- ## Check if there are missing build dependencies
- deps = {
- 'packages': [
- 'sudo',
- 'make',
- 'live-build',
- 'pbuilder',
- 'devscripts',
- 'python3-pystache',
- 'python3-git',
- 'qemu-utils'
- ],
- 'binaries': []
- }
-
- print("I: Checking if packages required for VyOS image build are installed")
- try:
- checker = utils.check_system_dependencies(deps)
- except OSError as e:
- print(e)
- sys.exit(1)
-
- ## Load the file with default build configuration options
- try:
- with open(defaults.DEFAULTS_FILE, 'rb') as f:
- build_defaults = tomli.load(f)
- except Exception as e:
- print("Failed to open the defaults file {0}: {1}".format(defaults.DEFAULTS_FILE, e))
- sys.exit(1)
-
- ## Get a list of available build flavors
- build_flavors = list(map(lambda f: os.path.splitext(f)[0], os.listdir(defaults.BUILD_FLAVORS_DIR)))
-
- ## Set up the option parser
- ## XXX: It uses values from the default configuration file for its option defaults,
- ## which is why it's defined after loading the defaults.toml file data.
-
- # Options dict format:
- # '$option_name_without_leading_dashes': { ('$help_string', $default_value_generator_thunk, $value_checker_thunk) }
- options = {
- 'architecture': ('Image target architecture (amd64 or arm64)',
- lambda: build_defaults['architecture'], lambda x: x in ['amd64', 'arm64']),
- 'build-by': ('Builder identifier (e.g. jrandomhacker@example.net)', get_default_build_by, None),
- 'debian-mirror': ('Debian repository mirror', lambda: build_defaults['debian_mirror'], None),
- 'debian-security-mirror': ('Debian security updates mirror', lambda: build_defaults['debian_security_mirror'], None),
- 'pbuilder-debian-mirror': ('Debian repository mirror for pbuilder env bootstrap', lambda: build_defaults['debian_mirror'], None),
- 'vyos-mirror': ('VyOS package mirror', lambda: build_defaults["vyos_mirror"], None),
- 'build-type': ('Build type, release or development', lambda: 'development', lambda x: x in ['release', 'development']),
- 'version': ('Version number (release builds only)', None, None),
- 'build-comment': ('Optional build comment', lambda: '', None)
- }
-
- # Create the option parser
- parser = argparse.ArgumentParser()
- for k, v in options.items():
- help_string, default_value_thunk = v[0], v[1]
- if default_value_thunk is None:
- parser.add_argument('--' + k, type=str, help=help_string)
- else:
- parser.add_argument('--' + k, type=str, help=help_string, default=default_value_thunk())
-
- # The debug option is a bit special since it different type is different
- parser.add_argument('--debug', help='Enable debug output', action='store_true')
-
- parser.add_argument('--dry-run', help='Check build configuration and exit', action='store_true')
-
- # Custom APT entry and APT key options can be used multiple times
- parser.add_argument('--custom-apt-entry', help="Custom APT entry", action='append', default=[])
- parser.add_argument('--custom-apt-key', help="Custom APT key file", action='append', default=[])
- parser.add_argument('--custom-package', help="Custom package to install from repositories", action='append', default=[])
-
- # Build flavor is a positional argument
- parser.add_argument('build_flavor', help='Build flavor', nargs='?', action='store')
-
- args = vars(parser.parse_args())
-
- debug = args["debug"]
-
- # Validate options
- for k, v in args.items():
- key = field_to_option(k)
- func = get_validator(options, k)
- if func is not None:
- if not func(v):
- print("{v} is not a valid value for --{o} option".format(o=key, v=v))
- sys.exit(1)
-
- if not args["build_flavor"]:
- print("E: Build flavor is not specified!")
- print("E: For example, to build the generic ISO, run {} iso".format(sys.argv[0]))
- print("Available build flavors:\n")
- print("\n".join(build_flavors))
- sys.exit(1)
-
- # Some fixup for mirror settings.
- # The idea is: if --debian-mirror is specified but --pbuilder-debian-mirror is not,
- # use the --debian-mirror value for both lb and pbuilder bootstrap
- if (args['debian_mirror'] != build_defaults["debian_mirror"]) and \
- (args['pbuilder_debian_mirror'] == build_defaults["debian_mirror"]):
- args['pbuilder_debian_mirror'] = args['debian_mirror']
-
- # Version can only be set for release builds,
- # for dev builds it hardly makes any sense
- if args['build_type'] == 'development':
- if args['version'] is not None:
- print("Version can only be set for release builds")
- print("Use --build-type=release option if you want to set version number")
- sys.exit(1)
-
- # Validate characters in version name
- if 'version' in args and args['version'] != None:
- allowed = string.ascii_letters + string.digits + '.' + '-' + '+'
- if not set(args['version']) <= set(allowed):
- print(f'Version contained illegal character(s), allowed: {allowed}')
- sys.exit(1)
-
- ## Inject some useful hardcoded options
- args['build_dir'] = defaults.BUILD_DIR
- args['pbuilder_config'] = os.path.join(defaults.BUILD_DIR, defaults.PBUILDER_CONFIG)
-
- ## Combine the arguments with non-configurable defaults
- build_config = merge_dicts(args, build_defaults)
-
- ## Load the flavor file and mix-ins
- with open(make_toml_path(defaults.BUILD_TYPES_DIR, build_config["build_type"]), 'rb') as f:
- build_type_config = tomli.load(f)
- build_config = merge_dicts(build_type_config, build_config)
-
- with open(make_toml_path(defaults.BUILD_ARCHES_DIR, build_config["architecture"]), 'rb') as f:
- build_arch_config = tomli.load(f)
- build_config = merge_dicts(build_arch_config, build_config)
-
- with open(make_toml_path(defaults.BUILD_FLAVORS_DIR, build_config["build_flavor"]), 'rb') as f:
- flavor_config = tomli.load(f)
- build_config = merge_dicts(flavor_config, build_config)
-
- ## Rename and merge some fields for simplicity
- ## E.g. --custom-packages is for the user, but internally
- ## it's added to the same package list as everything else
- if has_nonempty_key(build_config, "custom_package"):
- build_config["packages"] += build_config["custom_package"]
- del build_config["custom_package"]
-
- ## Add architecture-dependent packages from the flavor
- if has_nonempty_key(build_config, "architectures"):
- arch = build_config["architecture"]
- if arch in build_config["architectures"]:
- build_config["packages"] += build_config["architectures"][arch]["packages"]
-
- ## Dump the complete config if the user enabled debug mode
- if debug:
- import json
- print("D: Effective build config:\n")
- print(json.dumps(build_config, indent=4))
-
- ## Clean up the old build config and set up a fresh copy
- lb_config_dir = os.path.join(defaults.BUILD_DIR, defaults.LB_CONFIG_DIR)
- print(lb_config_dir)
- shutil.rmtree(lb_config_dir, ignore_errors=True)
- shutil.copytree("data/live-build-config/", lb_config_dir)
- os.makedirs(lb_config_dir, exist_ok=True)
-
- ## Create the version file
-
- # Create a build timestamp
- now = datetime.datetime.today()
- build_timestamp = now.strftime("%Y%m%d%H%M")
-
- # FIXME: use aware rather than naive object
- build_date = now.strftime("%a %d %b %Y %H:%M UTC")
-
- # Assign a (hopefully) unique identifier to the build (UUID)
- build_uuid = str(uuid.uuid4())
-
- # Initialize Git object from our repository
- try:
- repo = git.Repo('.')
-
- # Retrieve the Git commit ID of the repository, 14 charaters will be sufficient
- build_git = repo.head.object.hexsha[:14]
- # If somone played around with the source tree and the build is "dirty", mark it
- if repo.is_dirty():
- build_git += "-dirty"
-
- # Retrieve git branch name or current tag
- # Building a tagged release might leave us checking out a git tag that is not the tip of a named branch (detached HEAD)
- # Check if the current HEAD is associated with a tag and use its name instead of an unavailable branch name.
- git_branch = next((tag.name for tag in repo.tags if tag.commit == repo.head.commit), None)
- if git_branch is None:
- git_branch = repo.active_branch.name
- except Exception as e:
- exit(f'Could not retrieve information from git: {e}')
- build_git = ""
- git_branch = ""
-
- # Create the build version string
- if build_config['build_type'] == 'development':
- try:
- if not git_branch:
- raise ValueError("git branch could not be determined")
-
- # Load the branch to version mapping file
- with open('data/versions') as f:
- version_mapping = json.load(f)
-
- branch_version = version_mapping[git_branch]
-
- version = "{0}-rolling-{1}".format(branch_version, build_timestamp)
- except Exception as e:
- print("Could not build a version string specific to git branch, falling back to default: {0}".format(str(e)))
- version = "999.{0}".format(build_timestamp)
- else:
- # Release build, use the version from ./configure arguments
- version = build_config['version']
-
- if build_config['build_type'] == 'development':
- lts_build = False
- else:
- lts_build = True
-
- version_data = {
- 'version': version,
- 'built_by': build_config['build_by'],
- 'built_on': build_date,
- 'build_uuid': build_uuid,
- 'build_git': build_git,
- 'build_branch': git_branch,
- 'release_train': build_config['release_train'],
- 'lts_build': lts_build,
- 'build_comment': build_config['build_comment'],
- 'bugtracker_url': build_config['bugtracker_url'],
- 'documentation_url': build_config['documentation_url'],
- 'project_news_url': build_config['project_news_url'],
- }
-
- # Multi line strings needs to be un-indented to not have leading
- # whitespaces in the resulting file
- os_release = f"""
-PRETTY_NAME="VyOS {version} ({build_config['release_train']})"
-NAME="VyOS"
-VERSION_ID="{version}"
-VERSION="{version} ({build_config['release_train']})"
-VERSION_CODENAME={build_defaults['debian_distribution']}
-ID=vyos
-BUILD_ID="{build_git}"
-HOME_URL="{build_defaults['website_url']}"
-SUPPORT_URL="{build_defaults['support_url']}"
-BUG_REPORT_URL="{build_defaults['bugtracker_url']}"
-DOCUMENTATION_URL="{build_config['documentation_url']}"
- """
-
- # Switch to the build directory, this is crucial for the live-build work
- # because the efective build config files etc. are there.
- #
- # All directory paths from this point must be relative to BUILD_DIR,
- # not to the vyos-build repository root.
- os.chdir(defaults.BUILD_DIR)
-
- chroot_includes_dir = defaults.CHROOT_INCLUDES_DIR
- vyos_data_dir = os.path.join(chroot_includes_dir, "usr/share/vyos")
- os.makedirs(vyos_data_dir, exist_ok=True)
- with open(os.path.join(vyos_data_dir, 'version.json'), 'w') as f:
- json.dump(version_data, f)
-
- # For backwards compatibility with 'add system image' script from older versions
- # we need a file in the old format so that script can find out the version of the image
- # for upgrade
- os.makedirs(os.path.join(chroot_includes_dir, 'opt/vyatta/etc/'), exist_ok=True)
- with open(os.path.join(chroot_includes_dir, 'opt/vyatta/etc/version'), 'w') as f:
- print("Version: {0}".format(version), file=f)
-
-
- # Define variables that influence to welcome message on boot
- os.makedirs(os.path.join(chroot_includes_dir, 'usr/lib/'), exist_ok=True)
- with open(os.path.join(chroot_includes_dir, 'usr/lib/os-release'), 'w') as f:
- print(os_release, file=f)
-
-
- ## Clean up earlier build state and artifacts
- print("I: Cleaning the build workspace")
- os.system("lb clean")
- #iter(lambda p: shutil.rmtree(p, ignore_errors=True),
- # ['config/binary', 'config/bootstrap', 'config/chroot', 'config/common', 'config/source'])
- artifacts = functools.reduce(
- lambda x, y: x + y,
- map(glob.glob, ['*.iso', '*.raw', '*.img', '*.xz', '*.ova', '*.ovf']))
- iter(os.remove, artifacts)
-
- ## Create live-build configuration files
-
- # Add the additional repositories to package lists
- print("I: Setting up additional APT entries")
- vyos_repo_entry = "deb {vyos_mirror} {vyos_branch} main\n".format(**build_config)
-
- apt_file = defaults.VYOS_REPO_FILE
-
- if debug:
- print(f"D: Adding these entries to {apt_file}:")
- print("\t", vyos_repo_entry)
-
- with open(apt_file, 'w') as f:
- f.write(vyos_repo_entry)
-
- # Add custom APT entries
- if build_config.get('additional_repositories', False):
- build_config['custom_apt_entry'] += build_config['additional_repositories']
-
- if build_config.get('custom_apt_entry', False):
- custom_apt_file = defaults.CUSTOM_REPO_FILE
- entries = "\n".join(build_config['custom_apt_entry'])
- if debug:
- print("D: Adding custom APT entries:")
- print(entries)
- with open(custom_apt_file, 'w') as f:
- f.write(entries)
- f.write("\n")
-
- # Add custom APT keys
- if has_nonempty_key(build_config, 'custom_apt_key'):
- key_dir = defaults.ARCHIVES_DIR
- for k in build_config['custom_apt_key']:
- dst_name = '{0}.key.chroot'.format(os.path.basename(k))
- shutil.copy(k, os.path.join(key_dir, dst_name))
-
- # Add custom packages
- if has_nonempty_key(build_config, 'packages'):
- package_list_file = defaults.PACKAGE_LIST_FILE
- packages = "\n".join(build_config['packages'])
- with open (package_list_file, 'w') as f:
- f.write(packages)
-
- ## Create includes
- if has_nonempty_key(build_config, "includes_chroot"):
- for i in build_config["includes_chroot"]:
- file_path = os.path.join(chroot_includes_dir, i["path"])
- os.makedirs(os.path.dirname(file_path), exist_ok=True)
- with open(file_path, 'w') as f:
- f.write(i["data"])
-
- ## Create the default config
- ## Technically it's just another includes.chroot entry,
- ## but it's special enough to warrant making it easier for flavor writers
- if has_nonempty_key(build_config, "default_config"):
- file_path = os.path.join(chroot_includes_dir, "opt/vyatta/etc/config.boot.default")
- os.makedirs(os.path.dirname(file_path), exist_ok=True)
- with open(file_path, 'w') as f:
- f.write(build_config["default_config"])
-
- ## Configure live-build
- lb_config_tmpl = jinja2.Template("""
- lb config noauto \
- --apt-indices false \
- --apt-options "--yes -oAPT::Get::allow-downgrades=true" \
- --apt-recommends false \
- --architecture {{architecture}} \
- --archive-areas {{debian_archive_areas}} \
- --backports true \
- --binary-image iso-hybrid \
- --bootappend-live "boot=live components hostname=vyos username=live nopersistence noautologin nonetworking union=overlay console=ttyS0,115200 console=tty0 net.ifnames=0 biosdevname=0" \
- --bootappend-live-failsafe "live components memtest noapic noapm nodma nomce nolapic nomodeset nosmp nosplash vga=normal console=ttyS0,115200 console=tty0 net.ifnames=0 biosdevname=0" \
- --bootloaders {{bootloaders}} \
- --checksums 'sha256 md5' \
- --chroot-squashfs-compression-type "{{squashfs_compression_type}}" \
- --debian-installer none \
- --debootstrap-options "--variant=minbase --exclude=isc-dhcp-client,isc-dhcp-common,ifupdown --include=apt-utils,ca-certificates,gnupg2" \
- --distribution {{debian_distribution}} \
- --firmware-binary false \
- --firmware-chroot false \
- --iso-application "VyOS" \
- --iso-publisher "{{build_by}}" \
- --iso-volume "VyOS" \
- --linux-flavours {{kernel_flavor}} \
- --linux-packages linux-image-{{kernel_version}} \
- --mirror-binary {{debian_mirror}} \
- --mirror-binary-security {{debian_security_mirror}} \
- --mirror-bootstrap {{debian_mirror}} \
- --mirror-chroot {{debian_mirror}} \
- --mirror-chroot-security {{debian_security_mirror}} \
- --security true \
- --updates true
- "${@}"
- """)
-
- lb_config_command = lb_config_tmpl.render(build_config)
-
- ## Pin release for VyOS packages
- apt_pin = f"""Package: *
-Pin: release n={build_config['release_train']}
-Pin-Priority: 600
-"""
-
- with open(defaults.VYOS_PIN_FILE, 'w') as f:
- f.write(apt_pin)
-
- print("I: Configuring live-build")
-
- if debug:
- print("D: live-build configuration command")
- print(lb_config_command)
-
- result = os.system(lb_config_command)
- if result > 0:
- print("E: live-build config failed")
- sys.exit(1)
-
- ## In dry-run mode, exit at this point
- if build_config["dry_run"]:
- print("I: dry-run, not starting image build")
- sys.exit(0)
-
- ## Add local packages
- local_packages = glob.glob('../packages/*.deb')
- if local_packages:
- for f in local_packages:
- shutil.copy(f, os.path.join(defaults.LOCAL_PACKAGES_PATH, os.path.basename(f)))
-
- ## Build the image
- print("I: Starting image build")
- if debug:
- print("D: It's not like I'm building this specially for you or anything!")
- res = os.system("lb build 2>&1")
- if res > 0:
- sys.exit(res)
-
- # Copy the image
- shutil.copy("live-image-{0}.hybrid.iso".format(build_config["architecture"]),
- "vyos-{0}-{1}.iso".format(version_data["version"], build_config["architecture"]))
diff --git a/scripts/check-build-env b/scripts/check-build-env
deleted file mode 100755
index 7377be64..00000000
--- a/scripts/check-build-env
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2015 VyOS maintainers and contributors
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 or later as
-# published by the Free Software Foundation.
-#
-# 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, see <http://www.gnu.org/licenses/>.
-#
-# File: check-build-env
-# Purpose:
-# Checks if packages required for package and ISO image build
-# are installed.
-
-
-import os
-import sys
-
-import util
-
-deps = {
- 'packages': [
- 'sudo',
- 'make',
- 'live-build',
- 'pbuilder',
- 'devscripts',
- 'python3-pystache',
- 'python3-git'
- ],
- 'binaries': []
-}
-
-print("Checking if packages required for VyOS image build are installed")
-
-checker = util.DependencyChecker(deps)
-
-missing = checker.get_missing_dependencies()
-if not missing:
- print("All dependencies are installed")
- sys.exit(0)
-else:
- checker.print_missing_deps()
- sys.exit(1)
-
-sys.exit(0)
-
diff --git a/scripts/image-build/build-vyos-image b/scripts/image-build/build-vyos-image
new file mode 100755
index 00000000..c2d39c82
--- /dev/null
+++ b/scripts/image-build/build-vyos-image
@@ -0,0 +1,644 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2022-2024 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# 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, see <http://www.gnu.org/licenses/>.
+#
+# File: build-vyos-image
+# Purpose: builds VyOS images using a fork of Debian's live-build tool
+
+# Import Python's standard library modules
+import re
+import os
+import sys
+import uuid
+import glob
+import json
+import shutil
+import getpass
+import platform
+import argparse
+import datetime
+import functools
+import string
+
+## Check if the script is running wirh root permissions
+## Since live-build requires privileged calls such as chroot(),
+## there's no real way around it.
+if os.getuid() != 0:
+ print("E: this script requires root privileges")
+ sys.exit(1)
+
+# Import third-party modules
+try:
+ import tomli
+ import jinja2
+ import git
+ import psutil
+except ModuleNotFoundError as e:
+ print(f"E: Cannot load required library {e}")
+ print("E: Please make sure the following Python3 modules are installed: tomli jinja2 git psutil")
+ sys.exit(1)
+
+# Import local defaults
+import defaults
+
+## Load the file with default build configuration options
+try:
+ with open(defaults.DEFAULTS_FILE, 'rb') as f:
+ build_defaults = tomli.load(f)
+except Exception as e:
+ print("E: Failed to open the defaults file {0}: {1}".format(defaults.DEFAULTS_FILE, e))
+ sys.exit(1)
+
+# Checkout vyos-1x under build directory
+try:
+ branch_name = build_defaults['vyos_branch']
+ url_vyos_1x = 'https://github.com/vyos/vyos-1x'
+ path_vyos_1x = os.path.join(defaults.BUILD_DIR, 'vyos-1x')
+ try:
+ repo_vyos_1x = git.Repo.clone_from(url_vyos_1x, path_vyos_1x, no_checkout=True)
+ except git.GitCommandError:
+ if os.path.exists(path_vyos_1x):
+ try:
+ repo_vyos_1x = git.Repo(path_vyos_1x)
+ except git.GitError:
+ print(f'E: Corrupted vyos-1x git repo: {path_vyos_1x}; remove')
+ sys.exit(1)
+ else:
+ raise
+ # alternatively, pass commit hash or tag as arg:
+ repo_vyos_1x.git.checkout(branch_name)
+except Exception as e:
+ print(f'E: Could not retrieve vyos-1x from branch {branch_name}: {repr(e)}')
+ sys.exit(1)
+
+# Add the vyos-1x directory to the Python path so that
+# we can import modules from it.
+VYOS1X_DIR = os.path.join(os.getcwd(), defaults.BUILD_DIR, 'vyos-1x/python')
+if not os.path.exists(VYOS1X_DIR):
+ print("E: vyos-1x subdirectory does not exist, did git checkout fail?")
+ sys.exit(1)
+else:
+ sys.path.append(VYOS1X_DIR)
+
+# Import local modules from scripts/image-build
+# They rely on modules from vyos-1x
+import utils
+import raw_image
+
+from utils import cmd
+
+## Check if there are missing build dependencies
+deps = {
+ 'packages': [
+ 'sudo',
+ 'make',
+ 'live-build',
+ 'pbuilder',
+ 'devscripts',
+ 'python3-pystache',
+ 'python3-git',
+ 'qemu-utils',
+ 'gdisk',
+ 'kpartx',
+ 'dosfstools'
+ ],
+ 'binaries': []
+}
+
+print("I: Checking if packages required for VyOS image build are installed")
+try:
+ utils.check_system_dependencies(deps)
+except OSError as e:
+ print(f"E: {e}")
+ sys.exit(1)
+
+# argparse converts hyphens to underscores,
+# so for lookups in the original options hash we have to convert them back
+def field_to_option(s):
+ return re.sub(r'_', '-', s)
+
+def get_default_build_by():
+ return "{user}@{host}".format(user= getpass.getuser(), host=platform.node())
+
+def get_validator(optdict, name):
+ try:
+ return optdict[name][2]
+ except KeyError:
+ return None
+
+def merge_dicts(source, destination, skip_none=False):
+ """ Merge two dictionaries and return a new dict which has the merged key/value pairs.
+ Merging logic is as follows:
+ Sub-dicts are merged.
+ List values are combined.
+ Scalar values are set to those from the source dict.
+ """
+ from copy import deepcopy
+ tmp = deepcopy(destination)
+
+ for key, value in source.items():
+ if key not in tmp:
+ tmp[key] = value
+ elif isinstance(source[key], dict):
+ tmp[key] = merge_dicts(source[key], tmp[key])
+ elif isinstance(source[key], list):
+ tmp[key] = source[key] + tmp[key]
+ elif not skip_none or source[key] is not None:
+ tmp[key] = source[key]
+
+ return tmp
+
+def has_nonempty_key(config, key):
+ if key in config:
+ if config[key]:
+ return True
+ return False
+
+def make_toml_path(dir, file_basename):
+ return os.path.join(dir, file_basename + ".toml")
+
+
+if __name__ == "__main__":
+ ## Get a list of available build flavors
+ flavor_dir_env = os.getenv("VYOS_BUILD_FLAVORS_DIR")
+ if flavor_dir_env:
+ flavor_dir = flavor_dir_env
+ else:
+ flavor_dir = defaults.BUILD_FLAVORS_DIR
+
+ print(f"I: using build flavors directory {flavor_dir}")
+ build_flavors = [f[0] for f in map(os.path.splitext, os.listdir(flavor_dir)) if (f[1] == ".toml")]
+
+ ## Set up the option parser
+ ## XXX: It uses values from the default configuration file for its option defaults,
+ ## which is why it's defined after loading the defaults.toml file data.
+
+ # Options dict format:
+ # '$option_name_without_leading_dashes': { ('$help_string', $default_value_generator_thunk, $value_checker_thunk) }
+ options = {
+ 'architecture': ('Image target architecture (amd64 or arm64)', None, lambda x: x in ['amd64', 'arm64', None]),
+ 'build-by': ('Builder identifier (e.g. jrandomhacker@example.net)', get_default_build_by, None),
+ 'debian-mirror': ('Debian repository mirror', None, None),
+ 'debian-security-mirror': ('Debian security updates mirror', None, None),
+ 'pbuilder-debian-mirror': ('Debian repository mirror for pbuilder env bootstrap', None, None),
+ 'vyos-mirror': ('VyOS package mirror', None, None),
+ 'build-type': ('Build type, release or development', None, lambda x: x in ['release', 'development']),
+ 'version': ('Version number (release builds only)', None, None),
+ 'build-comment': ('Optional build comment', lambda: '', None)
+ }
+
+ # Create the option parser
+ parser = argparse.ArgumentParser()
+ for k, v in options.items():
+ help_string, default_value_thunk = v[0], v[1]
+ if default_value_thunk is None:
+ parser.add_argument('--' + k, type=str, help=help_string)
+ else:
+ parser.add_argument('--' + k, type=str, help=help_string, default=default_value_thunk())
+
+ # Debug options
+ parser.add_argument('--debug', help='Enable debug output', action='store_true')
+ parser.add_argument('--dry-run', help='Check build configuration and exit', action='store_true')
+
+ # Custom APT entry and APT key options can be used multiple times
+ parser.add_argument('--custom-apt-entry', help="Custom APT entry", action='append', default=[])
+ parser.add_argument('--custom-apt-key', help="Custom APT key file", action='append', default=[])
+ parser.add_argument('--custom-package', help="Custom package to install from repositories", action='append', default=[])
+
+ # Options relevant for non-ISO format flavors
+ parser.add_argument('--reuse-iso', help='Use an existing ISO file to build additional image formats', type=str, action='store', default=None)
+ parser.add_argument('--disk-size', help='Disk size for non-ISO image formats', type=int, action='store', default=10)
+
+ # Build flavor is a positional argument
+ parser.add_argument('build_flavor', help='Build flavor', nargs='?', action='store')
+
+ args = vars(parser.parse_args())
+
+ debug = args["debug"]
+
+ # Validate options
+ for k, v in args.items():
+ key = field_to_option(k)
+ func = get_validator(options, k)
+ if func is not None:
+ if not func(v):
+ print("E: {v} is not a valid value for --{o} option".format(o=key, v=v))
+ sys.exit(1)
+
+ if not args["build_flavor"]:
+ print("E: Build flavor is not specified!")
+ print("E: For example, to build the generic ISO, run {} iso".format(sys.argv[0]))
+ print("Available build flavors:\n")
+ print("\n".join(build_flavors))
+ sys.exit(1)
+
+ ## Try to get correct architecture and build type from build flavor and CLI arguments
+ pre_build_config = merge_dicts({}, build_defaults)
+
+ flavor_config = {}
+ build_flavor = args["build_flavor"]
+ try:
+ toml_flavor_file = make_toml_path(flavor_dir, args["build_flavor"])
+ with open(toml_flavor_file, 'rb') as f:
+ flavor_config = tomli.load(f)
+ pre_build_config = merge_dicts(flavor_config, pre_build_config)
+ except FileNotFoundError:
+ print(f"E: Flavor '{build_flavor}' does not exist")
+ sys.exit(1)
+ except tomli.TOMLDecodeError as e:
+ print(f"E: Failed to parse TOML file for flavor '{build_flavor}': {e}")
+ sys.exit(1)
+
+ ## Combine configs args > flavor > defaults
+ pre_build_config = merge_dicts(args, pre_build_config, skip_none=True)
+
+ # Some fixup for mirror settings.
+ # The idea is: if --debian-mirror is specified but --pbuilder-debian-mirror is not,
+ # use the --debian-mirror value for both lb and pbuilder bootstrap
+ if pre_build_config['debian_mirror'] is None or pre_build_config['debian_security_mirror'] is None:
+ print("E: debian_mirror and debian_security_mirror cannot be empty")
+ sys.exit(1)
+
+ if pre_build_config['pbuilder_debian_mirror'] is None:
+ args['pbuilder_debian_mirror'] = pre_build_config['pbuilder_debian_mirror'] = pre_build_config['debian_mirror']
+
+ # Version can only be set for release builds,
+ # for dev builds it hardly makes any sense
+ if pre_build_config['build_type'] == 'development':
+ if args['version'] is not None:
+ print("E: Version can only be set for release builds")
+ print("Use --build-type=release option if you want to set version number")
+ sys.exit(1)
+
+ # Validate characters in version name
+ if 'version' in args and args['version'] != None:
+ allowed = string.ascii_letters + string.digits + '.' + '-' + '+'
+ if not set(args['version']) <= set(allowed):
+ print(f'Version contained illegal character(s), allowed: {allowed}')
+ sys.exit(1)
+
+ ## Inject some useful hardcoded options
+ args['build_dir'] = defaults.BUILD_DIR
+ args['pbuilder_config'] = os.path.join(defaults.BUILD_DIR, defaults.PBUILDER_CONFIG)
+
+ ## Combine the arguments with non-configurable defaults
+ build_config = merge_dicts({}, build_defaults)
+
+ ## Load correct mix-ins
+ with open(make_toml_path(defaults.BUILD_TYPES_DIR, pre_build_config["build_type"]), 'rb') as f:
+ build_type_config = tomli.load(f)
+ build_config = merge_dicts(build_type_config, build_config)
+
+ with open(make_toml_path(defaults.BUILD_ARCHES_DIR, pre_build_config["architecture"]), 'rb') as f:
+ build_arch_config = tomli.load(f)
+ build_config = merge_dicts(build_arch_config, build_config)
+
+ ## Override with flavor and then CLI arguments
+ build_config = merge_dicts(flavor_config, build_config)
+ build_config = merge_dicts(args, build_config, skip_none=True)
+
+ ## Rename and merge some fields for simplicity
+ ## E.g. --custom-packages is for the user, but internally
+ ## it's added to the same package list as everything else
+ if has_nonempty_key(build_config, "custom_package"):
+ build_config["packages"] += build_config["custom_package"]
+ del build_config["custom_package"]
+
+ ## Add architecture-dependent packages from the flavor
+ if has_nonempty_key(build_config, "architectures"):
+ arch = build_config["architecture"]
+ if arch in build_config["architectures"]:
+ if has_nonempty_key(build_config["architectures"], "packages"):
+ build_config["packages"] += build_config["architectures"][arch]["packages"]
+
+ ## Check if image format is specified,
+ ## else we have no idea what we are actually supposed to build.
+ if not has_nonempty_key(build_config, "image_format"):
+ print("E: image format is not specified in the build flavor file")
+ sys.exit(1)
+
+ ## Add default boot settings if needed
+ if "boot_settings" not in build_config:
+ build_config["boot_settings"] = defaults.boot_settings
+ else:
+ build_config["boot_settings"] = merge_dicts(defaults.boot_settings, build_config["boot_settings"])
+
+ ## Convert the image_format field to a single-item list if it's a scalar
+ ## (like `image_format = "iso"`)
+ if type(build_config["image_format"]) != list:
+ build_config["image_format"] = [ build_config["image_format"] ]
+
+ ## Dump the complete config if the user enabled debug mode
+ if debug:
+ import json
+ print("D: Effective build config:\n")
+ print(json.dumps(build_config, indent=4))
+
+ ## Clean up the old build config and set up a fresh copy
+ lb_config_dir = os.path.join(defaults.BUILD_DIR, defaults.LB_CONFIG_DIR)
+ shutil.rmtree(lb_config_dir, ignore_errors=True)
+ shutil.copytree("data/live-build-config/", lb_config_dir)
+ os.makedirs(lb_config_dir, exist_ok=True)
+
+ # Switch to the build directory, this is crucial for the live-build work
+ # because the efective build config files etc. are there.
+ #
+ # All directory paths from this point must be relative to BUILD_DIR,
+ # not to the vyos-build repository root.
+ os.chdir(defaults.BUILD_DIR)
+
+ iso_file = None
+
+ if build_config["reuse_iso"]:
+ iso_file = build_config["reuse_iso"]
+ else:
+ ## Create the version file
+
+ # Create a build timestamp
+ now = datetime.datetime.today()
+ build_timestamp = now.strftime("%Y%m%d%H%M")
+
+ # FIXME: use aware rather than naive object
+ build_date = now.strftime("%a %d %b %Y %H:%M UTC")
+
+ # Assign a (hopefully) unique identifier to the build (UUID)
+ build_uuid = str(uuid.uuid4())
+
+ # Initialize Git object from our repository
+ try:
+ repo = git.Repo('.', search_parent_directories=True)
+ # Retrieve the Git commit ID of the repository, 14 charaters will be sufficient
+ build_git = repo.head.object.hexsha[:14]
+ # If somone played around with the source tree and the build is "dirty", mark it
+ if repo.is_dirty():
+ build_git += "-dirty"
+
+ # Retrieve git branch name or current tag
+ # Building a tagged release might leave us checking out a git tag that is not the tip of a named branch (detached HEAD)
+ # Check if the current HEAD is associated with a tag and use its name instead of an unavailable branch name.
+ git_branch = next((tag.name for tag in repo.tags if tag.commit == repo.head.commit), None)
+ if git_branch is None:
+ git_branch = repo.active_branch.name
+ except Exception as e:
+ print(f'W: Could not retrieve information from git: {repr(e)}')
+ build_git = ""
+ git_branch = ""
+
+ # Create the build version string
+ if build_config['build_type'] == 'development':
+ try:
+ if not git_branch:
+ raise ValueError("git branch could not be determined")
+
+ # Load the branch to version mapping file
+ with open('../data/versions') as f:
+ version_mapping = json.load(f)
+
+ branch_version = version_mapping[git_branch]
+
+ version = "{0}-rolling-{1}".format(branch_version, build_timestamp)
+ except Exception as e:
+ print("W: Could not build a version string specific to git branch, falling back to default: {0}".format(str(e)))
+ version = "999.{0}".format(build_timestamp)
+ else:
+ # Release build, use the version from ./configure arguments
+ version = build_config['version']
+
+ if build_config['build_type'] == 'development':
+ lts_build = False
+ else:
+ lts_build = True
+
+ version_data = {
+ 'version': version,
+ 'built_by': build_config['build_by'],
+ 'built_on': build_date,
+ 'build_uuid': build_uuid,
+ 'build_git': build_git,
+ 'build_branch': git_branch,
+ 'release_train': build_config['release_train'],
+ 'lts_build': lts_build,
+ 'build_comment': build_config['build_comment'],
+ 'bugtracker_url': build_config['bugtracker_url'],
+ 'documentation_url': build_config['documentation_url'],
+ 'project_news_url': build_config['project_news_url'],
+ }
+
+ # Multi line strings needs to be un-indented to not have leading
+ # whitespaces in the resulting file
+ os_release = f"""
+ PRETTY_NAME="VyOS {version} ({build_config['release_train']})"
+ NAME="VyOS"
+ VERSION_ID="{version}"
+ VERSION="{version} ({build_config['release_train']})"
+ VERSION_CODENAME={build_defaults['debian_distribution']}
+ ID=vyos
+ BUILD_ID="{build_git}"
+ HOME_URL="{build_defaults['website_url']}"
+ SUPPORT_URL="{build_defaults['support_url']}"
+ BUG_REPORT_URL="{build_defaults['bugtracker_url']}"
+ DOCUMENTATION_URL="{build_config['documentation_url']}"
+ """
+
+ # Reminder: all paths relative to the build dir, not to the repository root
+ chroot_includes_dir = defaults.CHROOT_INCLUDES_DIR
+ binary_includes_dir = defaults.BINARY_INCLUDES_DIR
+ vyos_data_dir = os.path.join(chroot_includes_dir, "usr/share/vyos")
+ os.makedirs(vyos_data_dir, exist_ok=True)
+ with open(os.path.join(vyos_data_dir, 'version.json'), 'w') as f:
+ json.dump(version_data, f)
+ with open(os.path.join(binary_includes_dir, 'version.json'), 'w') as f:
+ json.dump(version_data, f)
+
+ # For backwards compatibility with 'add system image' script from older versions
+ # we need a file in the old format so that script can find out the version of the image
+ # for upgrade
+ os.makedirs(os.path.join(chroot_includes_dir, 'opt/vyatta/etc/'), exist_ok=True)
+ with open(os.path.join(chroot_includes_dir, 'opt/vyatta/etc/version'), 'w') as f:
+ print("Version: {0}".format(version), file=f)
+
+ # Define variables that influence to welcome message on boot
+ os.makedirs(os.path.join(chroot_includes_dir, 'usr/lib/'), exist_ok=True)
+ with open(os.path.join(chroot_includes_dir, 'usr/lib/os-release'), 'w') as f:
+ print(os_release, file=f)
+
+ ## Clean up earlier build state and artifacts
+ print("I: Cleaning the build workspace")
+ cmd("lb clean")
+ #iter(lambda p: shutil.rmtree(p, ignore_errors=True),
+ # ['config/binary', 'config/bootstrap', 'config/chroot', 'config/common', 'config/source'])
+ artifacts = functools.reduce(
+ lambda x, y: x + y,
+ map(glob.glob, ['*.iso', '*.raw', '*.img', '*.xz', '*.ova', '*.ovf']))
+ iter(os.remove, artifacts)
+
+ ## Create the target ISO file path
+ iso_file = "vyos-{0}-{1}.iso".format(version_data["version"], build_config["architecture"])
+
+ ## Create live-build configuration files
+
+ # Add the additional repositories to package lists
+ print("I: Setting up additional APT entries")
+ vyos_repo_entry = "deb {vyos_mirror} {vyos_branch} main\n".format(**build_config)
+
+ apt_file = defaults.VYOS_REPO_FILE
+
+ if debug:
+ print(f"D: Adding these entries to {apt_file}:")
+ print("\t", vyos_repo_entry)
+
+ with open(apt_file, 'w') as f:
+ f.write(vyos_repo_entry)
+
+ # Add custom APT entries
+ if build_config.get('additional_repositories', False):
+ build_config['custom_apt_entry'] += build_config['additional_repositories']
+
+ if build_config.get('custom_apt_entry', False):
+ custom_apt_file = defaults.CUSTOM_REPO_FILE
+ entries = "\n".join(build_config['custom_apt_entry'])
+ if debug:
+ print("D: Adding custom APT entries:")
+ print(entries)
+ with open(custom_apt_file, 'w') as f:
+ f.write(entries)
+ f.write("\n")
+
+ # Add custom APT keys
+ if has_nonempty_key(build_config, 'custom_apt_key'):
+ key_dir = defaults.ARCHIVES_DIR
+ for k in build_config['custom_apt_key']:
+ dst_name = '{0}.key.chroot'.format(os.path.basename(k))
+ shutil.copy(k, os.path.join(key_dir, dst_name))
+
+ # Add custom packages
+ if has_nonempty_key(build_config, 'packages'):
+ package_list_file = defaults.PACKAGE_LIST_FILE
+ packages = "\n".join(build_config['packages'])
+ with open (package_list_file, 'w') as f:
+ f.write(packages)
+
+ ## Create includes
+ if has_nonempty_key(build_config, "includes_chroot"):
+ for i in build_config["includes_chroot"]:
+ file_path = os.path.join(chroot_includes_dir, i["path"])
+ if debug:
+ print(f"D: Creating chroot include file: {file_path}")
+ os.makedirs(os.path.dirname(file_path), exist_ok=True)
+ with open(file_path, 'w') as f:
+ f.write(i["data"])
+
+ ## Create the default config
+ ## Technically it's just another includes.chroot entry,
+ ## but it's special enough to warrant making it easier for flavor writers
+ if has_nonempty_key(build_config, "default_config"):
+ file_path = os.path.join(chroot_includes_dir, "opt/vyatta/etc/config.boot.default")
+ os.makedirs(os.path.dirname(file_path), exist_ok=True)
+ with open(file_path, 'w') as f:
+ f.write(build_config["default_config"])
+
+ ## Configure live-build
+ lb_config_tmpl = jinja2.Template("""
+ lb config noauto \
+ --apt-indices false \
+ --apt-options "--yes -oAPT::Get::allow-downgrades=true" \
+ --apt-recommends false \
+ --architecture {{architecture}} \
+ --archive-areas {{debian_archive_areas}} \
+ --backports true \
+ --binary-image iso-hybrid \
+ --bootappend-live "boot=live components hostname=vyos username=live nopersistence noautologin nonetworking union=overlay console=ttyS0,115200 console=tty0 net.ifnames=0 biosdevname=0" \
+ --bootappend-live-failsafe "live components memtest noapic noapm nodma nomce nolapic nomodeset nosmp nosplash vga=normal console=ttyS0,115200 console=tty0 net.ifnames=0 biosdevname=0" \
+ --bootloaders {{bootloaders}} \
+ --checksums 'sha256 md5' \
+ --chroot-squashfs-compression-type "{{squashfs_compression_type}}" \
+ --debian-installer none \
+ --debootstrap-options "--variant=minbase --exclude=isc-dhcp-client,isc-dhcp-common,ifupdown --include=apt-utils,ca-certificates,gnupg2" \
+ --distribution {{debian_distribution}} \
+ --firmware-binary false \
+ --firmware-chroot false \
+ --iso-application "VyOS" \
+ --iso-publisher "{{build_by}}" \
+ --iso-volume "VyOS" \
+ --linux-flavours {{kernel_flavor}} \
+ --linux-packages linux-image-{{kernel_version}} \
+ --mirror-binary {{debian_mirror}} \
+ --mirror-binary-security {{debian_security_mirror}} \
+ --mirror-bootstrap {{debian_mirror}} \
+ --mirror-chroot {{debian_mirror}} \
+ --mirror-chroot-security {{debian_security_mirror}} \
+ --security true \
+ --updates true
+ "${@}"
+ """)
+
+ lb_config_command = lb_config_tmpl.render(build_config)
+
+ ## Pin release for VyOS packages
+ apt_pin = f"""Package: *
+ Pin: release n={build_config['release_train']}
+ Pin-Priority: 600
+ """
+
+ with open(defaults.VYOS_PIN_FILE, 'w') as f:
+ f.write(apt_pin)
+
+ print("I: Configuring live-build")
+
+ if debug:
+ print("D: live-build configuration command")
+ print(lb_config_command)
+
+ cmd(lb_config_command)
+
+ ## In dry-run mode, exit at this point
+ if build_config["dry_run"]:
+ print("I: dry-run, not starting image build")
+ sys.exit(0)
+
+ ## Add local packages
+ local_packages = glob.glob('../packages/*.deb')
+ if local_packages:
+ for f in local_packages:
+ shutil.copy(f, os.path.join(defaults.LOCAL_PACKAGES_PATH, os.path.basename(f)))
+
+ ## Build the image
+ print("I: Starting image build")
+ if debug:
+ print("D: It's not like I'm building this specially for you or anything!")
+ cmd("lb build 2>&1")
+
+ # Copy the image
+ shutil.copy("live-image-{0}.hybrid.iso".format(build_config["architecture"]), iso_file)
+
+ # Build additional flavors from the ISO,
+ # if the flavor calls for them
+ if build_config["image_format"] != ["iso"]:
+ raw_image = raw_image.create_raw_image(build_config, iso_file, "tmp/")
+
+ if has_nonempty_key(build_config, "post_build_hook"):
+ # Some flavors require special procedures that aren't covered by qemu-img
+ # (most notably, the VMware OVA that requires a custom tool to make and sign the image).
+ # For those cases, we support running a post-build hook on the raw image.
+ # The image_format field should be 'raw' if a post-build hook is used.
+ hook_path = build_config["post_build_hook"]
+ cmd(f"{hook_path} {raw_image}")
+ else:
+ # Most other formats, thankfully, can be produced with just `qemu-img convert`
+ other_formats = filter(lambda x: x not in ["iso", "raw"], build_config["image_format"])
+ for f in other_formats:
+ target = f"{os.path.splitext(raw_image)[0]}.{f}"
+ print(f"I: Building {f} file {target}")
+ cmd(f"qemu-img convert -f raw -O {f} {raw_image} {target}")
diff --git a/scripts/vyos_build_defaults.py b/scripts/image-build/defaults.py
index 975fcb71..9fd5eeed 100644
--- a/scripts/vyos_build_defaults.py
+++ b/scripts/image-build/defaults.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2018 VyOS maintainers and contributors
+# Copyright (C) 2024 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -18,6 +18,15 @@
import os
+# Default boot settings
+boot_settings: dict[str, str] = {
+ 'timeout': '5',
+ 'console_type': 'tty',
+ 'console_num': '0',
+ 'console_speed': '115200',
+ 'bootmode': 'normal'
+}
+
# Relative to the repository directory
BUILD_DIR = 'build'
@@ -37,6 +46,7 @@ PBUILDER_DIR = 'pbuilder'
LB_CONFIG_DIR = 'config'
CHROOT_INCLUDES_DIR = 'config/includes.chroot'
+BINARY_INCLUDES_DIR = 'config/includes.binary'
ARCHIVES_DIR = 'config/archives/'
VYOS_REPO_FILE = 'config/archives/vyos.list.chroot'
diff --git a/scripts/image-build/raw_image.py b/scripts/image-build/raw_image.py
new file mode 100644
index 00000000..ae061990
--- /dev/null
+++ b/scripts/image-build/raw_image.py
@@ -0,0 +1,211 @@
+# Copyright (C) 2024 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# 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, see <http://www.gnu.org/licenses/>.
+#
+# File: raw_image.py
+# Purpose: Helper functions for building raw images.
+
+import os
+import sys
+import shutil
+import traceback
+
+import vyos.utils.process
+
+SQUASHFS_FILE = 'live/filesystem.squashfs'
+VERSION_FILE = 'version.json'
+
+from utils import cmd
+
+def mkdir(path):
+ os.makedirs(path, exist_ok=True)
+
+
+class BuildContext:
+ def __init__(self, iso_path, work_dir, debug=False):
+ self.work_dir = work_dir
+ self.iso_path = iso_path
+ self.debug = debug
+ self.loop_device = None
+
+ def __enter__(self):
+ print(f"I: Setting up a raw image build directory in {self.work_dir}")
+
+ self.iso_dir = os.path.join(self.work_dir, "iso")
+ self.squash_dir = os.path.join(self.work_dir, "squash")
+ self.raw_dir = os.path.join(self.work_dir, "raw")
+ self.efi_dir = os.path.join(self.work_dir, "efi")
+
+ # Create mount point directories
+ mkdir(self.iso_dir)
+ mkdir(self.squash_dir)
+ mkdir(self.raw_dir)
+ mkdir(self.efi_dir)
+
+ # Mount the ISO image
+ cmd(f"""mount -t iso9660 -o ro,loop {self.iso_path} {self.iso_dir}""")
+
+ # Mount the SquashFS image
+ cmd(f"""mount -t squashfs -o ro,loop {self.iso_dir}/{SQUASHFS_FILE} {self.squash_dir}""")
+
+ return self
+
+ def __exit__(self, exc_type, exc_value, exc_tb):
+ print(f"I: Tearing down the raw image build environment in {self.work_dir}")
+ cmd(f"""umount {self.squash_dir}/dev/""")
+ cmd(f"""umount {self.squash_dir}/proc/""")
+ cmd(f"""umount {self.squash_dir}/sys/""")
+
+ cmd(f"umount {self.squash_dir}/boot/efi")
+ cmd(f"umount {self.squash_dir}/boot")
+
+ cmd(f"""umount {self.squash_dir}""")
+ cmd(f"""umount {self.iso_dir}""")
+ cmd(f"""umount {self.raw_dir}""")
+ cmd(f"""umount {self.efi_dir}""")
+
+ if self.loop_device:
+ cmd(f"""losetup -d {self.loop_device}""")
+
+def create_disk(path, size):
+ cmd(f"""qemu-img create -f raw "{path}" {size}G""")
+
+def read_version_data(iso_dir):
+ from json import load
+ with open(os.path.join(iso_dir, VERSION_FILE), 'r') as f:
+ data = load(f)
+ return data
+
+def setup_loop_device(con, raw_file):
+ from subprocess import Popen, PIPE, STDOUT
+ from re import match
+ command = f'losetup --show -f {raw_file}'
+ p = Popen(command, stderr=PIPE, stdout=PIPE, stdin=PIPE, shell=True)
+ (stdout, stderr) = p.communicate()
+
+ if p.returncode > 0:
+ raise OSError(f"Could not set up a loop device: {stderr.decode()}")
+
+ con.loop_device = stdout.decode().strip()
+ if con.debug:
+ print(f"I: Using loop device {con.loop_device}")
+
+def mount_image(con):
+ import vyos.system.disk
+
+ from subprocess import Popen, PIPE, STDOUT
+ from re import match
+
+ vyos.system.disk.filesystem_create(con.disk_details.partition['efi'], 'efi')
+ vyos.system.disk.filesystem_create(con.disk_details.partition['root'], 'ext4')
+
+ cmd(f"mount -t ext4 {con.disk_details.partition['root']} {con.raw_dir}")
+ cmd(f"mount -t vfat {con.disk_details.partition['efi']} {con.efi_dir}")
+
+def install_image(con, version):
+ from glob import glob
+
+ vyos_dir = os.path.join(con.raw_dir, f'boot/{version}/')
+ mkdir(vyos_dir)
+ mkdir(os.path.join(vyos_dir, 'work/work'))
+ mkdir(os.path.join(vyos_dir, 'rw'))
+
+ shutil.copy(f"{con.iso_dir}/{SQUASHFS_FILE}", f"{vyos_dir}/{version}.squashfs")
+
+ boot_files = glob(f'{con.squash_dir}/boot/*')
+ boot_files = [f for f in boot_files if os.path.isfile(f)]
+
+ for f in boot_files:
+ print(f"I: Copying file {f}")
+ shutil.copy(f, vyos_dir)
+
+ with open(f"{con.raw_dir}/persistence.conf", 'w') as f:
+ f.write("/ union\n")
+
+def setup_grub_configuration(build_config, root_dir) -> None:
+ """Install GRUB configurations
+
+ Args:
+ root_dir (str): a path to the root of target filesystem
+ """
+ from vyos.template import render
+ from vyos.system import grub
+
+ print('I: Installing GRUB configuration files')
+ grub_cfg_main = f'{root_dir}/{grub.GRUB_DIR_MAIN}/grub.cfg'
+ grub_cfg_vars = f'{root_dir}/{grub.CFG_VYOS_VARS}'
+ grub_cfg_modules = f'{root_dir}/{grub.CFG_VYOS_MODULES}'
+ grub_cfg_menu = f'{root_dir}/{grub.CFG_VYOS_MENU}'
+ grub_cfg_options = f'{root_dir}/{grub.CFG_VYOS_OPTIONS}'
+
+ # create new files
+ render(grub_cfg_main, grub.TMPL_GRUB_MAIN, {})
+ grub.common_write(root_dir)
+ grub.vars_write(grub_cfg_vars, build_config["boot_settings"])
+ grub.modules_write(grub_cfg_modules, [])
+ grub.write_cfg_ver(1, root_dir)
+ render(grub_cfg_menu, grub.TMPL_GRUB_MENU, {})
+ render(grub_cfg_options, grub.TMPL_GRUB_OPTS, {})
+
+def install_grub(con, version):
+ from re import match
+ from vyos.system import disk, grub
+
+ # Mount the required virtual filesystems
+ os.makedirs(f"{con.raw_dir}/boot/efi", exist_ok=True)
+ cmd(f"mount --bind /dev {con.squash_dir}/dev")
+ cmd(f"mount --bind /proc {con.squash_dir}/proc")
+ cmd(f"mount --bind /sys {con.squash_dir}/sys")
+
+ cmd(f"mount --bind {con.raw_dir}/boot {con.squash_dir}/boot")
+ cmd(f"mount --bind {con.efi_dir} {con.squash_dir}/boot/efi")
+
+ DIR_DST_ROOT = con.raw_dir
+
+ setup_grub_configuration(con.build_config, DIR_DST_ROOT)
+ # add information about version
+ grub.create_structure(DIR_DST_ROOT)
+ grub.version_add(version, DIR_DST_ROOT)
+ grub.set_default(version, DIR_DST_ROOT)
+ grub.set_console_type(con.build_config["boot_settings"]["console_type"], DIR_DST_ROOT)
+
+ print('I: Installing GRUB to the disk image')
+ grub.install(con.loop_device, f'/boot/', f'/boot/efi', chroot=con.squash_dir)
+
+ # sort inodes (to make GRUB read config files in alphabetical order)
+ grub.sort_inodes(f'{DIR_DST_ROOT}/{grub.GRUB_DIR_VYOS}')
+ grub.sort_inodes(f'{DIR_DST_ROOT}/{grub.GRUB_DIR_VYOS_VERS}')
+
+
+def create_raw_image(build_config, iso_file, work_dir):
+ from vyos.system.disk import parttable_create
+
+ if not os.path.exists(iso_file):
+ print(f"E: ISO file {iso_file} does not exist in the build directory")
+ sys.exit(1)
+
+ with BuildContext(iso_file, work_dir, debug=True) as con:
+ con.build_config = build_config
+ version_data = read_version_data(con.iso_dir)
+ version = version_data['version']
+ raw_file = f"vyos-{version}.raw"
+ print(f"I: Building raw file {raw_file}")
+ create_disk(raw_file, build_config["disk_size"])
+ setup_loop_device(con, raw_file)
+ disk_details = parttable_create(con.loop_device, (int(build_config["disk_size"]) - 1) * 1024 * 1024)
+ con.disk_details = disk_details
+ mount_image(con)
+ install_image(con, version)
+ install_grub(con, version)
+
+ return raw_file
diff --git a/scripts/vyos_build_utils.py b/scripts/image-build/utils.py
index ed358848..8c3ccbab 100644
--- a/scripts/vyos_build_utils.py
+++ b/scripts/image-build/utils.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2015 VyOS maintainers and contributors
+# Copyright (C) 2024 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -21,7 +21,9 @@ import sys
import os
from distutils.spawn import find_executable
-import vyos_build_defaults as defaults
+# Local modules
+import defaults
+import vyos
def check_build_config():
if not os.path.exists(defaults.BUILD_CONFIG):
@@ -75,3 +77,8 @@ def check_system_dependencies(deps):
raise OSError(checker.format_missing_dependencies())
else:
pass
+
+def cmd(command):
+ res = vyos.utils.process.call(command, shell=True)
+ if res > 0:
+ raise OSError(f"Command '{command}' failed")
diff --git a/scripts/import-local-packages b/scripts/import-local-packages
deleted file mode 100755
index 70b4c365..00000000
--- a/scripts/import-local-packages
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/sh
-
-LOCAL_PKG_DIR=build/config/packages.chroot
-
-mkdir -p $LOCAL_PKG_DIR
-
-FILES=packages/*.deb
-for f in $FILES
-do
- if [ -e "$f" ]; then
- cp $f $LOCAL_PKG_DIR
- fi
-done
diff --git a/scripts/list-package-arch b/scripts/list-package-arch
deleted file mode 100755
index c9a88654..00000000
--- a/scripts/list-package-arch
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/bash
-# Execute this script from the vyos-build top directory
-# Will generate a list of architectures in each repository
-for a in $(echo vyos-build; ./scripts/build-packages -l | egrep -e '^ \* ' | sed 's/^ \* //'); do
- n=$(curl https://raw.githubusercontent.com/vyos/${a}/sagitta/debian/control 2>/dev/null | grep "Architecture" | tr '\n' ',')
- printf "%-24s %s \n" "${a}" "${n}"
-done
diff --git a/scripts/list-required-firmware b/scripts/list-required-firmware
deleted file mode 100755
index 64280e03..00000000
--- a/scripts/list-required-firmware
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2020 VyOS maintainers and contributors
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 or later as
-# published by the Free Software Foundation.
-#
-# 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, see <http://www.gnu.org/licenses/>.
-#
-
-import re
-import os
-import sys
-import glob
-
-
-SRC_DIR = sys.argv[1]
-KERNEL_CONFIG = sys.argv[2]
-
-def load_config(path):
- with open(KERNEL_CONFIG, 'r') as f:
- config = f.read()
- targets = re.findall(r'(.*)=(?:y|m)', config)
- return targets
-
-def find_subdirs(config, path):
- try:
- with open(os.path.join(path, 'Makefile'), 'r') as f:
- makefile = f.read()
- except OSError:
- # No Makefile
- return []
-
- dir_stmts = re.findall(r'obj-\$\((.*)\)\s+\+=\s+(.*)(?:\n|$)', makefile)
- subdirs = []
- for ds in dir_stmts:
- print("Processing make targets from {0} ({1})".format(ds[1], ds[0]), file=sys.stderr)
- if ds[0] in config:
- dirname = os.path.dirname(ds[1])
- if dirname:
- subdirs.append(dirname)
- else:
- print("{0} is disabled in the config, ignoring {1}".format(ds[0], ds[1]), file=sys.stderr)
-
- return subdirs
-
-def find_firmware(file):
- with open(file, 'r') as f:
- source = f.read()
- fws = re.findall(r'MODULE_FIRMWARE\((.*)\)', source)
- return fws
-
-def walk_dir(config, path):
- subdirs = find_subdirs(config, path)
-
- print("Looking for C files in {0}".format(path), file=sys.stderr)
- c_files = glob.glob("{0}/*.c".format(path))
- for cf in c_files:
- fws = find_firmware(cf)
- if fws:
- print("Referenced firmware: {0}".format(fws))
-
- for d in subdirs:
- d = os.path.join(path, d)
- walk_dir(config, d)
-
-if __name__ == '__main__':
- config = load_config(KERNEL_CONFIG)
- walk_dir(config, SRC_DIR)
diff --git a/scripts/pbuilder-config b/scripts/pbuilder-config
deleted file mode 100755
index 06e14cbf..00000000
--- a/scripts/pbuilder-config
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2015 VyOS maintainers and contributors
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 or later as
-# published by the Free Software Foundation.
-#
-# 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, see <http://www.gnu.org/licenses/>.
-#
-# File: pbuilder-config
-# Purpose:
-# Generates a pbuilderrc file for use by package build scripts.
-
-
-import sys
-import os
-import json
-
-import pystache
-
-import defaults
-import util
-
-util.check_build_config()
-
-pbuilder_config_tmpl = """
-
-BASETGZ={{build_dir}}/base.tgz
-BUILDPLACE={{build_dir}}/pbuilder/
-MIRRORSITE={{pbuilder_debian_mirror}}
-BUILDRESULT={{build_dir}}/pbuilder/result/
-
-DISTRIBUTION={{distribution}}
-
-ARCHITECTURE={{architecture}}
-
-"""
-
-with open(defaults.BUILD_CONFIG, 'r') as f:
- build_config = json.load(f)
-
-pbuilder_config = pystache.render(pbuilder_config_tmpl, build_config)
-
-print("Configuring pbuilder")
-
-with open(defaults.PBUILDER_CONFIG, 'w+') as f:
- f.write(pbuilder_config)
diff --git a/scripts/pbuilder-setup b/scripts/pbuilder-setup
deleted file mode 100755
index a89348b8..00000000
--- a/scripts/pbuilder-setup
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2015 VyOS maintainers and contributors
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 or later as
-# published by the Free Software Foundation.
-#
-# 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, see <http://www.gnu.org/licenses/>.
-#
-# File: pbuilder-setup
-# Purpose:
-# Bootstraps a Debian environment for use by pbuilder.
-
-
-import sys
-import os
-import json
-import distutils.dir_util
-
-import pystache
-
-import defaults
-import util
-
-util.check_build_config()
-
-pbuilder_create_cmd_tmpl= """
- sudo pbuilder --create \
- --configfile {{pbuilder_config}}
-"""
-
-with open(defaults.BUILD_CONFIG, 'r') as f:
- build_config = json.load(f)
-
-pbuilder_create_command = pystache.render(pbuilder_create_cmd_tmpl, build_config)
-
-print("Creating a pbuilder environment")
-#os.chdir(defaults.BUILD_DIR)
-
-distutils.dir_util.mkpath(defaults.PBUILDER_DIR)
-
-result = os.system(pbuilder_create_command)
-if result > 0:
- print("pbuilder environment bootstrap failed")
- sys.exit(1)
diff --git a/scripts/pbuilder/hooks/C10shell b/scripts/pbuilder/hooks/C10shell
deleted file mode 100755
index f56f9f7f..00000000
--- a/scripts/pbuilder/hooks/C10shell
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-# invoke shell if build fails.
-
-apt-get install -y --force-yes vim nano less bash
-cd /tmp/buildd/*/debian/..
-/bin/bash < /dev/tty > /dev/tty 2> /dev/tty
diff --git a/tools/dell/90-vep.chroot b/tools/dell/90-vep.chroot
deleted file mode 100755
index a88a7de1..00000000
--- a/tools/dell/90-vep.chroot
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/sh
-echo I: Change the default serial baud rate.
-sed -i 's/9600/115200/g' /opt/vyatta/etc/config-migrate/migrate/system/3-to-4
-
-echo "ShowStatus=yes" >> /etc/systemd/system.conf
-
-echo I: Disable default link rule.
-rm /lib/systemd/network/99-default.link
-touch /lib/systemd/network/99-default.link
-rm /lib/udev/rules.d/65-vyatta-net.rules
-touch /lib/udev/rules.d/65-vyatta-net.rules
-rm /lib/udev/rules.d/75-persistent-net-generator.rules
-touch /lib/udev/rules.d/75-persistent-net-generator.rules
-
-echo I: Update initramfs.
-update-initramfs -u
diff --git a/tools/dell/vep-hook b/tools/dell/vep-hook
deleted file mode 100755
index 7dcaf034..00000000
--- a/tools/dell/vep-hook
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/sh -e
-
-PREREQS=""
-
-prereqs() { echo "$PREREQS"; }
-
-case "$1" in
- prereqs)
- prereqs
- exit 0
- ;;
-esac
-
-. /usr/share/initramfs-tools/hook-functions
-
-mkdir -p $DESTDIR/etc/systemd/network
-cp -p /etc/systemd/network/*.link $DESTDIR/etc/systemd/network/
-
-mkdir -p $DESTDIR/lib/udev/rules.d
-cp -p /lib/udev/rules.d/50-firmware.rules $DESTDIR/lib/udev/rules.d/
-cp -p /lib/udev/rules.d/50-udev-default.rules $DESTDIR/lib/udev/rules.d/
-cp -p /lib/udev/rules.d/55-dm.rules $DESTDIR/lib/udev/rules.d/
-cp -p /lib/udev/rules.d/60-cdrom_id.rules $DESTDIR/lib/udev/rules.d/
-cp -p /lib/udev/rules.d/60-persistent-storage-dm.rules $DESTDIR/lib/udev/rules.d/
-cp -p /lib/udev/rules.d/60-persistent-storage.rules $DESTDIR/lib/udev/rules.d/
-cp -p /lib/udev/rules.d/75-net-description.rules $DESTDIR/lib/udev/rules.d/
-cp -p /lib/udev/rules.d/80-drivers.rules $DESTDIR/lib/udev/rules.d/
-cp -p /lib/udev/rules.d/80-net-setup-link.rules $DESTDIR/lib/udev/rules.d/
diff --git a/tools/dell/vep1400/10-eth0-000.link b/tools/dell/vep1400/10-eth0-000.link
deleted file mode 100644
index db36f5ce..00000000
--- a/tools/dell/vep1400/10-eth0-000.link
+++ /dev/null
@@ -1,7 +0,0 @@
-[Match]
-Path=pci-0000:05:00.1
-Driver=ixgbe
-
-[Link]
-Name=eth0
-Alias=SFP+1
diff --git a/tools/dell/vep1400/10-eth1-000.link b/tools/dell/vep1400/10-eth1-000.link
deleted file mode 100644
index 7bf1a175..00000000
--- a/tools/dell/vep1400/10-eth1-000.link
+++ /dev/null
@@ -1,7 +0,0 @@
-[Match]
-Path=pci-0000:05:00.0
-Driver=ixgbe
-
-[Link]
-Name=eth1
-Alias=SFP+2
diff --git a/tools/dell/vep1400/10-eth2-000.link b/tools/dell/vep1400/10-eth2-000.link
deleted file mode 100644
index 81f3f5bc..00000000
--- a/tools/dell/vep1400/10-eth2-000.link
+++ /dev/null
@@ -1,7 +0,0 @@
-[Match]
-Path=pci-0000:02:00.2
-Driver=igb
-
-[Link]
-Name=eth2
-Alias=GE1
diff --git a/tools/dell/vep1400/10-eth3-000.link b/tools/dell/vep1400/10-eth3-000.link
deleted file mode 100644
index fe37dfac..00000000
--- a/tools/dell/vep1400/10-eth3-000.link
+++ /dev/null
@@ -1,7 +0,0 @@
-[Match]
-Path=pci-0000:02:00.3
-Driver=igb
-
-[Link]
-Name=eth3
-Alias=GE2
diff --git a/tools/dell/vep1400/10-eth4-000.link b/tools/dell/vep1400/10-eth4-000.link
deleted file mode 100644
index a76ecd24..00000000
--- a/tools/dell/vep1400/10-eth4-000.link
+++ /dev/null
@@ -1,7 +0,0 @@
-[Match]
-Path=pci-0000:02:00.0
-Driver=igb
-
-[Link]
-Name=eth4
-Alias=GE3
diff --git a/tools/dell/vep1400/10-eth5-000.link b/tools/dell/vep1400/10-eth5-000.link
deleted file mode 100644
index 0e848dde..00000000
--- a/tools/dell/vep1400/10-eth5-000.link
+++ /dev/null
@@ -1,7 +0,0 @@
-[Match]
-Path=pci-0000:02:00.1
-Driver=igb
-
-[Link]
-Name=eth5
-Alias=GE4
diff --git a/tools/dell/vep1400/10-eth6-000.link b/tools/dell/vep1400/10-eth6-000.link
deleted file mode 100644
index 10ad451d..00000000
--- a/tools/dell/vep1400/10-eth6-000.link
+++ /dev/null
@@ -1,7 +0,0 @@
-[Match]
-Path=pci-0000:07:00.1
-Driver=ixgbe
-
-[Link]
-Name=eth6
-Alias=GE5
diff --git a/tools/dell/vep1400/10-eth7-000.link b/tools/dell/vep1400/10-eth7-000.link
deleted file mode 100644
index 57b94502..00000000
--- a/tools/dell/vep1400/10-eth7-000.link
+++ /dev/null
@@ -1,7 +0,0 @@
-[Match]
-Path=pci-0000:07:00.0
-Driver=ixgbe
-
-[Link]
-Name=eth7
-Alias=GE6
diff --git a/tools/dell/vep4600/10-eth0-000.link b/tools/dell/vep4600/10-eth0-000.link
deleted file mode 100644
index 9b466fe8..00000000
--- a/tools/dell/vep4600/10-eth0-000.link
+++ /dev/null
@@ -1,6 +0,0 @@
-[Match]
-Path=pci-0000:04:00.0
-Driver=igb
-
-[Link]
-Name=eth0
diff --git a/tools/dell/vep4600/10-eth0-001.link b/tools/dell/vep4600/10-eth0-001.link
deleted file mode 100644
index c60acc3a..00000000
--- a/tools/dell/vep4600/10-eth0-001.link
+++ /dev/null
@@ -1,6 +0,0 @@
-[Match]
-Path=pci-0000:05:00.0
-Driver=igb
-
-[Link]
-Name=eth0
diff --git a/tools/dell/vep4600/10-eth1-000.link b/tools/dell/vep4600/10-eth1-000.link
deleted file mode 100644
index c49b7bda..00000000
--- a/tools/dell/vep4600/10-eth1-000.link
+++ /dev/null
@@ -1,6 +0,0 @@
-[Match]
-Path=pci-0000:b8:00.0
-Driver=i40e
-
-[Link]
-Name=eth1
diff --git a/tools/dell/vep4600/10-eth1-001.link b/tools/dell/vep4600/10-eth1-001.link
deleted file mode 100644
index c32e5e86..00000000
--- a/tools/dell/vep4600/10-eth1-001.link
+++ /dev/null
@@ -1,6 +0,0 @@
-[Match]
-Path=pci-0000:b6:00.0
-Driver=i40e
-
-[Link]
-Name=eth1
diff --git a/tools/dell/vep4600/10-eth10-000.link b/tools/dell/vep4600/10-eth10-000.link
deleted file mode 100644
index 414b2d30..00000000
--- a/tools/dell/vep4600/10-eth10-000.link
+++ /dev/null
@@ -1,6 +0,0 @@
-[Match]
-Path=pci-0000:65:00.3
-Driver=i40e
-
-[Link]
-Name=eth10
diff --git a/tools/dell/vep4600/10-eth11-000.link b/tools/dell/vep4600/10-eth11-000.link
deleted file mode 100644
index 0579dcff..00000000
--- a/tools/dell/vep4600/10-eth11-000.link
+++ /dev/null
@@ -1,6 +0,0 @@
-[Match]
-Path=pci-0000:17:00.0
-Driver=i40e
-
-[Link]
-Name=eth11
diff --git a/tools/dell/vep4600/10-eth12-000.link b/tools/dell/vep4600/10-eth12-000.link
deleted file mode 100644
index 9f9a3c0c..00000000
--- a/tools/dell/vep4600/10-eth12-000.link
+++ /dev/null
@@ -1,6 +0,0 @@
-[Match]
-Path=pci-0000:17:00.1
-Driver=i40e
-
-[Link]
-Name=eth12
diff --git a/tools/dell/vep4600/10-eth13-000.link b/tools/dell/vep4600/10-eth13-000.link
deleted file mode 100644
index 8b8c2254..00000000
--- a/tools/dell/vep4600/10-eth13-000.link
+++ /dev/null
@@ -1,6 +0,0 @@
-[Match]
-Path=pci-0000:17:00.2
-Driver=i40e
-
-[Link]
-Name=eth13
diff --git a/tools/dell/vep4600/10-eth14-000.link b/tools/dell/vep4600/10-eth14-000.link
deleted file mode 100644
index a746ada9..00000000
--- a/tools/dell/vep4600/10-eth14-000.link
+++ /dev/null
@@ -1,6 +0,0 @@
-[Match]
-Path=pci-0000:17:00.3
-Driver=i40e
-
-[Link]
-Name=eth14
diff --git a/tools/dell/vep4600/10-eth2-000.link b/tools/dell/vep4600/10-eth2-000.link
deleted file mode 100644
index 7c100cee..00000000
--- a/tools/dell/vep4600/10-eth2-000.link
+++ /dev/null
@@ -1,6 +0,0 @@
-[Match]
-Path=pci-0000:b8:00.1
-Driver=i40e
-
-[Link]
-Name=eth2
diff --git a/tools/dell/vep4600/10-eth2-001.link b/tools/dell/vep4600/10-eth2-001.link
deleted file mode 100644
index 4ff72387..00000000
--- a/tools/dell/vep4600/10-eth2-001.link
+++ /dev/null
@@ -1,6 +0,0 @@
-[Match]
-Path=pci-0000:b6:00.1
-Driver=i40e
-
-[Link]
-Name=eth2
diff --git a/tools/dell/vep4600/10-eth3-000.link b/tools/dell/vep4600/10-eth3-000.link
deleted file mode 100644
index 824670ec..00000000
--- a/tools/dell/vep4600/10-eth3-000.link
+++ /dev/null
@@ -1,6 +0,0 @@
-[Match]
-Path=pci-0000:02:00.1
-Driver=igb
-
-[Link]
-Name=eth3
diff --git a/tools/dell/vep4600/10-eth4-000.link b/tools/dell/vep4600/10-eth4-000.link
deleted file mode 100644
index ed3a80a2..00000000
--- a/tools/dell/vep4600/10-eth4-000.link
+++ /dev/null
@@ -1,6 +0,0 @@
-[Match]
-Path=pci-0000:02:00.0
-Driver=igb
-
-[Link]
-Name=eth4
diff --git a/tools/dell/vep4600/10-eth5-000.link b/tools/dell/vep4600/10-eth5-000.link
deleted file mode 100644
index 5d21982d..00000000
--- a/tools/dell/vep4600/10-eth5-000.link
+++ /dev/null
@@ -1,6 +0,0 @@
-[Match]
-Path=pci-0000:02:00.3
-Driver=igb
-
-[Link]
-Name=eth5
diff --git a/tools/dell/vep4600/10-eth6-000.link b/tools/dell/vep4600/10-eth6-000.link
deleted file mode 100644
index a00a0c43..00000000
--- a/tools/dell/vep4600/10-eth6-000.link
+++ /dev/null
@@ -1,6 +0,0 @@
-[Match]
-Path=pci-0000:02:00.2
-Driver=igb
-
-[Link]
-Name=eth6
diff --git a/tools/dell/vep4600/10-eth7-000.link b/tools/dell/vep4600/10-eth7-000.link
deleted file mode 100644
index 3db698ae..00000000
--- a/tools/dell/vep4600/10-eth7-000.link
+++ /dev/null
@@ -1,6 +0,0 @@
-[Match]
-Path=pci-0000:65:00.0
-Driver=i40e
-
-[Link]
-Name=eth7
diff --git a/tools/dell/vep4600/10-eth8-000.link b/tools/dell/vep4600/10-eth8-000.link
deleted file mode 100644
index 9858190a..00000000
--- a/tools/dell/vep4600/10-eth8-000.link
+++ /dev/null
@@ -1,6 +0,0 @@
-[Match]
-Path=pci-0000:65:00.1
-Driver=i40e
-
-[Link]
-Name=eth8
diff --git a/tools/dell/vep4600/10-eth9-000.link b/tools/dell/vep4600/10-eth9-000.link
deleted file mode 100644
index 62ba54f2..00000000
--- a/tools/dell/vep4600/10-eth9-000.link
+++ /dev/null
@@ -1,6 +0,0 @@
-[Match]
-Path=pci-0000:65:00.2
-Driver=i40e
-
-[Link]
-Name=eth9
diff --git a/tools/dell/vep4600/10-unused0-000.link b/tools/dell/vep4600/10-unused0-000.link
deleted file mode 100644
index 60acba9f..00000000
--- a/tools/dell/vep4600/10-unused0-000.link
+++ /dev/null
@@ -1,6 +0,0 @@
-[Match]
-Path=pci-0000:b8:00.2
-Driver=i40e
-
-[Link]
-Name=unused0
diff --git a/tools/dell/vep4600/10-unused0-001.link b/tools/dell/vep4600/10-unused0-001.link
deleted file mode 100644
index e9014fb0..00000000
--- a/tools/dell/vep4600/10-unused0-001.link
+++ /dev/null
@@ -1,6 +0,0 @@
-[Match]
-Path=pci-0000:b6:00.2
-Driver=i40e
-
-[Link]
-Name=unused0
diff --git a/tools/dell/vep4600/10-unused1-000.link b/tools/dell/vep4600/10-unused1-000.link
deleted file mode 100644
index 0860d005..00000000
--- a/tools/dell/vep4600/10-unused1-000.link
+++ /dev/null
@@ -1,6 +0,0 @@
-[Match]
-Path=pci-0000:b8:00.3
-Driver=i40e
-
-[Link]
-Name=unused1
diff --git a/tools/dell/vep4600/10-unused1-001.link b/tools/dell/vep4600/10-unused1-001.link
deleted file mode 100644
index de906fcf..00000000
--- a/tools/dell/vep4600/10-unused1-001.link
+++ /dev/null
@@ -1,6 +0,0 @@
-[Match]
-Path=pci-0000:b6:00.3
-Driver=i40e
-
-[Link]
-Name=unused1
diff --git a/tools/dell/vep4600/99-default.link b/tools/dell/vep4600/99-default.link
deleted file mode 100644
index e69de29b..00000000
--- a/tools/dell/vep4600/99-default.link
+++ /dev/null
diff --git a/tools/get_latest_iso.py b/tools/get_latest_iso.py
deleted file mode 100755
index f8228ff2..00000000
--- a/tools/get_latest_iso.py
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/usr/bin/env python3
-
-import os
-import sys
-from lxml import html
-from urllib.parse import unquote
-import requests
-
-BASE_URL = 'https://downloads.vyos.io/'
-PAGE_URL = BASE_URL+'?dir=rolling/sagitta/amd64'
-
-
-def download():
- page = requests.get(PAGE_URL)
- tree = html.fromstring(page.content)
- path = '//*[@id="directory-listing"]/li/a[1]/@href'
- isos = [x for x in tree.xpath(path) if os.path.splitext(x)[1] == '.iso']
- latest_iso_url = os.path.join(BASE_URL, isos[-1])
- filename = unquote(os.path.basename(latest_iso_url))
- print(filename)
- if os.path.exists(filename):
- print("{} already exists".format(filename))
- sys.exit(0)
- r = requests.get(latest_iso_url)
- with open(filename, 'wb') as fd:
- for chunk in r.iter_content(chunk_size=128):
- fd.write(chunk)
-
-
-if __name__ == '__main__':
- download()
diff --git a/tools/gpl-header-template b/tools/gpl-header-template
deleted file mode 100644
index 63be9d9a..00000000
--- a/tools/gpl-header-template
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright (C) 2016 VyOS maintainers and contributors
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 or later as
-# published by the Free Software Foundation.
-#
-# 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, see <http://www.gnu.org/licenses/>.
-#
-# File:
-# Purpose:
-
diff --git a/tools/submod-mk b/tools/submod-mk
deleted file mode 100644
index eb61da18..00000000
--- a/tools/submod-mk
+++ /dev/null
@@ -1,84 +0,0 @@
-#!/bin/bash
-#
-# **** License ****
-#
-# Copyright (C) 2013 Vyatta, Inc.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# 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, see <http://www.gnu.org/licenses/>.
-#
-# **** End License ****
-
-progname=${0##*/}
-shopt -s nullglob
-shopt -s extglob
-cd packages
-
-info=echo
-trace=
-noclean="-nc"
-build="debuild -i -b -uc -us"
-
-declare -a submodule
-declare -a debs
-for debian in !(installer|linux-kernel-di-i386-2.6)/debian ; do
- smod=${debian%/*}
- debs=( ${smod}_*.deb )
- if [ ${#debs[@]} -eq 0 ] ; then
- submodule+=( $smod )
- fi
-done
-
-while [ $# -gt 0 ] ; do
- case "$1" in
- -h | --help )
- cat <<-EOF
-Usage: $progname [Options] [ SUBMODULE... ]
-Options:
- -n | --do-nothing DonĀ“t actually remove or build anything,
- just show what would be done
- -q | --quiet Quiet, don't print progress info
- -c | --clean Clean build
- -b | --binary Skip source package build (default)
- -s | --source Build binary and source packages
- -S | --signed-source Build and sign packages
-
-If no SUBMODULE(s) given, build all checked-out submodules w/o debs.
-EOF
- exit 0;;
- -n | --do-nothing )
- trace=echo
- shift;;
- -q | --quiet )
- info='#'
- shift;;
- -c | --clean )
- noclean=
- shift;;
- -b | --binary )
- shift ;; # default
- -s | --source )
- build="git buildpackage -uc -us"
- shift;;
- -S | --signed-source )
- build="git buildpackage"
- shift;;
- * )
- submodule=( $@ )
- break;;
- esac
-done
-
-for (( i=0; i<${#submodule[@]}; i++)) ; do
- eval $info P: ${submodule[i]}
- ( cd ${submodule[i]} && eval $trace $build $noclean ) || exit $?
-done
diff --git a/tools/switch-remote b/tools/switch-remote
deleted file mode 100755
index 328b735c..00000000
--- a/tools/switch-remote
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/bin/sh
-
-HTTPS_BASE_URL="https://github.com/vyos"
-SSH_BASE_URL="git@github.com:vyos"
-
-REMOTE=`git config remote.origin.url`
-
-# extract vyatta-foo.git
-BASENAME=`echo $REMOTE | sed -re 's!.*/(.*)$!\1!'`
-echo "Changing remote for $BASENAME"
-
-# Print usage if no arguments given
-if [ -z "$1" ]; then
- echo "Switches remote URL to SSH or HTTPS"
- echo "Use \"$0 ssh\" to switch to SSH"
- echo "Use \"$0 https\" to switch to HTTPS"
-fi
-
-case $1 in
- ssh)
- echo "New remote: $SSH_BASE_URL/$BASENAME"
- git config remote.origin.url $SSH_BASE_URL/$BASENAME
- ;;
- https)
- echo "New remote: $HTTPS_BASE_URL/$BASENAME"
- git config remote.origin.url $HTTPS_BASE_URL/$BASENAME
- ;;
- *)
- echo "Wrong option, use \"ssh\" or \"https\""
- ;;
-esac
-
-
-
-