summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/PULL_REQUEST_TEMPLATE.md4
-rw-r--r--.github/workflows/pr-conflicts.yml4
-rw-r--r--.gitmodules3
-rw-r--r--Makefile8
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--data/defaults.toml2
-rwxr-xr-xdata/live-build-config/hooks/live/18-enable-disable_services.chroot3
-rw-r--r--data/live-build-config/includes.binary/isolinux/splash.pngbin40176 -> 39611 bytes
-rw-r--r--data/live-build-config/includes.chroot/opt/vyatta/etc/config.boot.default10
-rw-r--r--data/live-build-config/includes.chroot/usr/share/vyos/keys/vyos-rolling-release.minisign.pub4
-rw-r--r--docker/Dockerfile10
-rw-r--r--packages/dropbear/Jenkinsfile4
-rwxr-xr-xpackages/dropbear/build.sh4
-rw-r--r--packages/hsflowd/Jenkinsfile2
-rw-r--r--packages/linux-kernel/Jenkinsfile2
-rw-r--r--packages/linux-kernel/patches/kernel/0002-inotify-support-for-stackable-filesystems.patch6
m---------packages/vyos-1x0
-rwxr-xr-xscripts/build-vyos-image535
-rwxr-xr-xscripts/check-pr-title-and-commit-messages.py54
-rwxr-xr-xscripts/check-qemu-install8
-rwxr-xr-xscripts/image-build/build-vyos-image620
-rw-r--r--scripts/image-build/defaults.py (renamed from scripts/vyos_build_defaults.py)11
-rw-r--r--scripts/image-build/raw_image.py211
-rw-r--r--scripts/image-build/utils.py (renamed from scripts/vyos_build_utils.py)15
-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
-rw-r--r--vars/buildPackage.groovy7
60 files changed, 1343 insertions, 801 deletions
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 87eee2e7..03aca946 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -18,8 +18,8 @@ the box, please use [x]
- [ ] Other (please describe):
## Related Task(s)
-<!-- All submitted PRs must be linked to a Task on Phabricator. -->
-* https://vyos.dev/Txxxx
+<!-- optional: Link to related other tasks on Phabricator. -->
+<!-- * https://vyos.dev/Txxxx -->
## Component(s) name
<!-- A rather incomplete list of components: ethernet, wireguard, bgp, mpls, ldp, l2tp, dhcp ... -->
diff --git a/.github/workflows/pr-conflicts.yml b/.github/workflows/pr-conflicts.yml
index 96040cd6..2fd0bb42 100644
--- a/.github/workflows/pr-conflicts.yml
+++ b/.github/workflows/pr-conflicts.yml
@@ -6,10 +6,10 @@ on:
jobs:
Conflict_Check:
name: 'Check PR status: conflicts and resolution'
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-latest
steps:
- name: check if PRs are dirty
- uses: eps1lon/actions-label-merge-conflict@releases/2.x
+ uses: eps1lon/actions-label-merge-conflict@v3
with:
dirtyLabel: "state: conflict"
removeOnDirtyLabel: "state: conflict resolved"
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 00000000..7d26010c
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "packages/vyos-1x"]
+ path = packages/vyos-1x
+ url = https://github.com/vyos/vyos-1x
diff --git a/Makefile b/Makefile
index 18fd3939..67c2cdc4 100644
--- a/Makefile
+++ b/Makefile
@@ -7,12 +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
+%:
+ 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/data/defaults.toml b/data/defaults.toml
index 9a655c4f..c4d5c32c 100644
--- a/data/defaults.toml
+++ b/data/defaults.toml
@@ -14,7 +14,7 @@ vyos_mirror = "https://rolling-packages.vyos.net/current"
vyos_branch = "current"
release_train = "current"
-kernel_version = "6.6.22"
+kernel_version = "6.6.29"
bootloaders = "syslinux,grub-efi"
squashfs_compression_type = "xz -Xbcj x86 -b 256k -always-use-fragments -no-recovery"
diff --git a/data/live-build-config/hooks/live/18-enable-disable_services.chroot b/data/live-build-config/hooks/live/18-enable-disable_services.chroot
index 08404a62..4680c869 100755
--- a/data/live-build-config/hooks/live/18-enable-disable_services.chroot
+++ b/data/live-build-config/hooks/live/18-enable-disable_services.chroot
@@ -21,7 +21,6 @@ systemctl disable conntrackd.service
systemctl disable 'udp-broadcast-relay@*.service'
systemctl disable pdns-recursor.service
systemctl disable tftpd-hpa.service
-systemctl disable logd.service
systemctl disable frr.service
systemctl disable salt-minion.service
systemctl disable certbot.service
@@ -29,7 +28,6 @@ systemctl disable certbot.timer
systemctl disable nginx.service
systemctl disable wpa_supplicant.service
systemctl disable squid.service
-systemctl disable heartbeat.service
systemctl disable apt-daily.service
systemctl disable apt-daily.timer
systemctl disable apt-daily-upgrade.timer
@@ -70,7 +68,6 @@ systemctl disable podman-auto-update.timer
systemctl disable podman-restart.service
systemctl disable vyos-wan-load-balance.service
systemctl disable nvmf-autoconnect.service
-systemctl disable vpp.service
systemctl disable dpkg-db-backup.timer
systemctl disable dpkg-db-backup.service
systemctl disable zabbix-agent2.service
diff --git a/data/live-build-config/includes.binary/isolinux/splash.png b/data/live-build-config/includes.binary/isolinux/splash.png
index 932ca36e..4137d52b 100644
--- a/data/live-build-config/includes.binary/isolinux/splash.png
+++ b/data/live-build-config/includes.binary/isolinux/splash.png
Binary files differ
diff --git a/data/live-build-config/includes.chroot/opt/vyatta/etc/config.boot.default b/data/live-build-config/includes.chroot/opt/vyatta/etc/config.boot.default
index 7123ef54..c3ff6c79 100644
--- a/data/live-build-config/includes.chroot/opt/vyatta/etc/config.boot.default
+++ b/data/live-build-config/includes.chroot/opt/vyatta/etc/config.boot.default
@@ -19,6 +19,16 @@ system {
}
}
ntp {
+ allow-client {
+ address 127.0.0.0/8
+ address 169.254.0.0/16
+ address 10.0.0.0/8
+ address 172.16.0.0/12
+ address 192.168.0.0/16
+ address ::1/128
+ address fe80::/10
+ address fc00::/7
+ }
server "time1.vyos.net"
server "time2.vyos.net"
server "time3.vyos.net"
diff --git a/data/live-build-config/includes.chroot/usr/share/vyos/keys/vyos-rolling-release.minisign.pub b/data/live-build-config/includes.chroot/usr/share/vyos/keys/vyos-rolling-release.minisign.pub
index 29a30825..320b41c4 100644
--- a/data/live-build-config/includes.chroot/usr/share/vyos/keys/vyos-rolling-release.minisign.pub
+++ b/data/live-build-config/includes.chroot/usr/share/vyos/keys/vyos-rolling-release.minisign.pub
@@ -1,2 +1,2 @@
-untrusted comment: minisign public key 21AF69D8B86794DC
-RWTclGe42GmvIX/xnNiXdigNll7NSfpYGl1rj+sEERcLgoEsse5EwAgA
+untrusted comment: minisign public key D3643767F448688
+RWSIhkR/dkM2DSaBRniv/bbbAf8hmDqdbOEmgXkf1RxRoxzodgKcDyGq
diff --git a/docker/Dockerfile b/docker/Dockerfile
index d3fe875f..de6b147f 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
# Packages for TPM test
RUN apt-get update && apt-get install -y swtpm
@@ -151,7 +153,7 @@ RUN eval $(opam env --root=/opt/opam --set-root) && opam install -y \
# Build VyConf which is required to build libvyosconfig
RUN eval $(opam env --root=/opt/opam --set-root) && \
- opam pin add vyos1x-config https://github.com/vyos/vyos1x-config.git#406158f8 -y
+ opam pin add vyos1x-config https://github.com/vyos/vyos1x-config.git#f8d6abdf -y
# Packages needed for libvyosconfig
RUN apt-get update && apt-get install -y \
@@ -162,7 +164,7 @@ RUN apt-get update && apt-get install -y \
# Build libvyosconfig
RUN eval $(opam env --root=/opt/opam --set-root) && \
git clone https://github.com/vyos/libvyosconfig.git /tmp/libvyosconfig && \
- cd /tmp/libvyosconfig && git checkout 63175de4 && \
+ cd /tmp/libvyosconfig && git checkout c6141d97 && \
dpkg-buildpackage -uc -us -tc -b && \
dpkg -i /tmp/libvyosconfig0_*_$(dpkg-architecture -qDEB_HOST_ARCH).deb
@@ -244,7 +246,6 @@ RUN pip install --break-system-packages \
python3 \
python3-setuptools \
python3-inotify \
- python3-sphinx \
python3-xmltodict \
python3-lxml \
python3-nose \
@@ -255,6 +256,7 @@ RUN pip install --break-system-packages \
python3-stdeb \
python3-all \
python3-coverage \
+ pylint \
quilt \
whois
diff --git a/packages/dropbear/Jenkinsfile b/packages/dropbear/Jenkinsfile
index a15793d1..539d7578 100644
--- a/packages/dropbear/Jenkinsfile
+++ b/packages/dropbear/Jenkinsfile
@@ -1,4 +1,4 @@
-// Copyright (C) 2022-2023 VyOS maintainers and contributors
+// Copyright (C) 2022-2024 VyOS maintainers and contributors
//
// This program is free software; you can redistribute it and/or modify
// in order to easy exprort images built to "external" world
@@ -21,7 +21,7 @@
def pkgList = [
['name': 'dropbear',
- 'scmCommit': 'debian/2022.83-1',
+ 'scmCommit': 'debian/2022.83-1+deb12u1',
'scmUrl': 'https://salsa.debian.org/debian/dropbear.git',
'buildCmd': 'sudo mk-build-deps --install --tool "apt-get --yes --no-install-recommends"; cd ..; ./build.sh'],
]
diff --git a/packages/dropbear/build.sh b/packages/dropbear/build.sh
index 0934f4f7..9376fa7a 100755
--- a/packages/dropbear/build.sh
+++ b/packages/dropbear/build.sh
@@ -19,5 +19,9 @@ if [ -d $PATCH_DIR ]; then
fi
cd ${SRC}
+
+echo "I: Installing build dependencies"
+sudo apt-get install -y libpam0g-dev
+
echo "I: Build Debian Package"
dpkg-buildpackage -uc -us -tc -b
diff --git a/packages/hsflowd/Jenkinsfile b/packages/hsflowd/Jenkinsfile
index a0e4ecd9..bb9dd68d 100644
--- a/packages/hsflowd/Jenkinsfile
+++ b/packages/hsflowd/Jenkinsfile
@@ -23,7 +23,7 @@
// and not via a DEB package
def pkgList = [
['name': 'host-sflow',
- 'scmCommit': 'v2.0.52-1',
+ 'scmCommit': 'v2.0.55-1',
'scmUrl': 'https://github.com/sflow/host-sflow.git',
'buildCmd': 'cd ..; ./build.sh'],
]
diff --git a/packages/linux-kernel/Jenkinsfile b/packages/linux-kernel/Jenkinsfile
index a4c9f274..9d88663a 100644
--- a/packages/linux-kernel/Jenkinsfile
+++ b/packages/linux-kernel/Jenkinsfile
@@ -49,7 +49,7 @@ def pkgList = [
'buildCmd': 'cd ..; ./build-linux-firmware.sh'],
// Accel-PPP
- ['name': 'accel-ppp', 'scmCommit': '19c36e593d9b',
+ ['name': 'accel-ppp', 'scmCommit': '1.13.0',
'scmUrl': 'https://github.com/accel-ppp/accel-ppp.git',
'buildCmd': 'cd ..; pwd; ls -al; ./build-accel-ppp.sh'],
diff --git a/packages/linux-kernel/patches/kernel/0002-inotify-support-for-stackable-filesystems.patch b/packages/linux-kernel/patches/kernel/0002-inotify-support-for-stackable-filesystems.patch
index 31544af4..b19a8d25 100644
--- a/packages/linux-kernel/patches/kernel/0002-inotify-support-for-stackable-filesystems.patch
+++ b/packages/linux-kernel/patches/kernel/0002-inotify-support-for-stackable-filesystems.patch
@@ -190,7 +190,7 @@ index 1c4bfdab008d..cf567cc33679 100644
struct inotify_inode_mark *i_mark)
{
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
-index 3fa2416264a4..38930c1e70d8 100644
+index 2c056d737c27..2cb1f0024e70 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -15,6 +15,7 @@
@@ -201,7 +201,7 @@ index 3fa2416264a4..38930c1e70d8 100644
#include <linux/file.h>
#include <linux/fs_context.h>
#include <linux/fs_parser.h>
-@@ -1525,6 +1526,18 @@ static void ovl_inode_init_once(void *foo)
+@@ -1528,6 +1529,18 @@ static void ovl_inode_init_once(void *foo)
inode_init_once(&oi->vfs_inode);
}
@@ -220,7 +220,7 @@ index 3fa2416264a4..38930c1e70d8 100644
static int __init ovl_init(void)
{
int err;
-@@ -1540,18 +1553,24 @@ static int __init ovl_init(void)
+@@ -1543,18 +1556,24 @@ static int __init ovl_init(void)
err = ovl_aio_request_cache_init();
if (!err) {
err = register_filesystem(&ovl_fs_type);
diff --git a/packages/vyos-1x b/packages/vyos-1x
new file mode 160000
+Subproject b5d3d36d1f70e53ef6a8a6634ab863d94d791bf
diff --git a/scripts/build-vyos-image b/scripts/build-vyos-image
deleted file mode 100755
index fb7eb540..00000000
--- a/scripts/build-vyos-image
+++ /dev/null
@@ -1,535 +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 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, 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__":
- ## 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)', 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())
-
- # 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)
-
- ## Try to get correct architecture and build type from build flavor and CLI arguments
- pre_build_config = merge_dicts({}, build_defaults)
-
- flavor_config = {}
- with open(make_toml_path(defaults.BUILD_FLAVORS_DIR, args["build_flavor"]), 'rb') as f:
- flavor_config = tomli.load(f)
- pre_build_config = merge_dicts(flavor_config, pre_build_config)
-
- ## 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("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("Version can only be set for release builds")
- print("Use --build-type=release option if you want to set version number")
- 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"]:
- 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
- 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")
- 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"])
- 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)
-
- 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-pr-title-and-commit-messages.py b/scripts/check-pr-title-and-commit-messages.py
new file mode 100755
index 00000000..f7376e98
--- /dev/null
+++ b/scripts/check-pr-title-and-commit-messages.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env python3
+
+import re
+import sys
+import time
+
+import requests
+
+# Use the same regex for PR title and commit messages for now
+title_regex = r'^(([a-zA-Z\-_.]+:\s)?)T\d+:\s+[^\s]+.*'
+commit_regex = title_regex
+
+
+def check_pr_title(title):
+ if not re.match(title_regex, title):
+ print(f"PR title '{title}' does not match the required format!")
+ print("Valid title example: T99999: make IPsec secure")
+ sys.exit(1)
+
+
+def check_commit_message(title):
+ if not re.match(commit_regex, title):
+ print(f"Commit title '{title}' does not match the required format!")
+ print("Valid title example: T99999: make IPsec secure")
+ sys.exit(1)
+
+
+if __name__ == '__main__':
+ if len(sys.argv) < 2:
+ print("Please specify pull request URL!")
+ sys.exit(1)
+
+ # There seems to be a race condition that causes this scripts to receive
+ # an incomplete PR object that is missing certain fields,
+ # which causes temporary CI failures that require re-running the script
+ #
+ # It's probably better to add a small delay to prevent that
+ time.sleep(5)
+
+ # Get the pull request object
+ pr = requests.get(sys.argv[1]).json()
+ if "title" not in pr:
+ print("The PR object does not have a title field!")
+ print("Did not receive a valid pull request object, please check the URL!")
+ sys.exit(1)
+
+ check_pr_title(pr["title"])
+
+ # Get the list of commits
+ commits = requests.get(pr["commits_url"]).json()
+ for c in commits:
+ # Retrieve every individual commit and check its title
+ co = requests.get(c["url"]).json()
+ check_commit_message(co["commit"]["message"])
diff --git a/scripts/check-qemu-install b/scripts/check-qemu-install
index 41c566e6..b8f3806b 100755
--- a/scripts/check-qemu-install
+++ b/scripts/check-qemu-install
@@ -336,7 +336,9 @@ try:
c.expect('\nWhat would you like to name this image?.*')
c.sendline('')
c.expect(f'\nPlease enter a password for the "{default_user}" user.*')
- c.sendline('')
+ c.sendline('vyos')
+ c.expect(f'\nPlease confirm password for the "{default_user}" user.*')
+ c.sendline('vyos')
c.expect('\nWhat console should be used by default?.*')
c.sendline('S')
@@ -347,6 +349,8 @@ try:
c.sendline('y')
c.expect('\nInstallation will delete all data on both drives. Continue?.*')
c.sendline('y')
+ c.expect('\nWhich file would you like as boot config?.*')
+ c.sendline('')
else:
c.expect('\nWhich one should be used for installation?.*')
c.sendline('')
@@ -354,6 +358,8 @@ try:
c.sendline('y')
c.expect('\nWould you like to use all the free space on the drive?.*')
c.sendline('y')
+ c.expect('\nWhich file would you like as boot config?.*')
+ c.sendline('')
log.info('system installed, shutting down')
diff --git a/scripts/image-build/build-vyos-image b/scripts/image-build/build-vyos-image
new file mode 100755
index 00000000..c6e76208
--- /dev/null
+++ b/scripts/image-build/build-vyos-image
@@ -0,0 +1,620 @@
+#!/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
+
+# 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")
+
+# Initialize Git object from our repository
+try:
+ repo = git.Repo('.', search_parent_directories=True)
+ repo.git.submodule('update', '--init')
+
+ # 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 = ""
+
+# Add the vyos-1x submodule directory to the Python path
+# so that we can import modules from it.
+VYOS1X_DIR = os.path.join(os.getcwd(), 'packages/vyos-1x/python')
+if not os.path.exists(VYOS1X_DIR):
+ print("E: packages/vyos-1x subdirectory does not exist, did git submodules fail to initialize?")
+else:
+ sys.path.append(VYOS1X_DIR)
+
+# Import local modules from scripts/image-build
+# They rely on modules from vyos-1x
+import utils
+import defaults
+import raw_image
+
+from utils import cmd
+
+# 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__":
+ ## 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',
+ 'gdisk',
+ 'kpartx',
+ 'dosfstools'
+ ],
+ '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(f"E: {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("E: Failed to open the defaults file {0}: {1}".format(defaults.DEFAULTS_FILE, e))
+ sys.exit(1)
+
+ ## 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())
+
+ # 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 1e153f4b..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'
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..7002b281 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
@@ -19,9 +19,11 @@
import sys
import os
-from distutils.spawn import find_executable
+import shutil
-import vyos_build_defaults as defaults
+# Local modules
+import defaults
+import vyos
def check_build_config():
if not os.path.exists(defaults.BUILD_CONFIG):
@@ -51,7 +53,7 @@ class DependencyChecker(object):
def _get_missing_binaries(self, binaries):
missing_binaries = []
for b in binaries:
- if not find_executable(b):
+ if not shutil.which(b):
missing_binaries.append(b)
return missing_binaries
@@ -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/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/vars/buildPackage.groovy b/vars/buildPackage.groovy
index 9e1ba1db..531e51d9 100644
--- a/vars/buildPackage.groovy
+++ b/vars/buildPackage.groovy
@@ -194,6 +194,13 @@ def call(description=null, pkgList=null, buildCmd=null, buildArm=false, changesP
sh(script: "ssh ${SSH_OPTS} ${SSH_REMOTE} -t \"uncron-add 'reprepro -v -b ${VYOS_REPO_PATH} removesrc ${RELEASE} ${PACKAGE}'\"")
}
}
+ files = findFiles(glob: '**/*-build-deps_*.deb')
+ if (files) {
+ echo "Remove Debian build dependency files from the workspace..."
+ files.each { FILE ->
+ sh(script: "rm -f ${FILE}")
+ }
+ }
files = findFiles(glob: '**/*.deb')
if (files) {