summaryrefslogtreecommitdiff
path: root/scripts/image-build
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/image-build')
-rwxr-xr-xscripts/image-build/build-vyos-image32
-rw-r--r--scripts/image-build/raw_image.py93
2 files changed, 93 insertions, 32 deletions
diff --git a/scripts/image-build/build-vyos-image b/scripts/image-build/build-vyos-image
index d969c157..3275c5de 100755
--- a/scripts/image-build/build-vyos-image
+++ b/scripts/image-build/build-vyos-image
@@ -367,6 +367,11 @@ if __name__ == "__main__":
shutil.copytree("data/live-build-config/", lb_config_dir)
os.makedirs(lb_config_dir, exist_ok=True)
+ ## Secure Boot - Copy public Keys to image
+ sb_certs = 'data/certificates'
+ if os.path.isdir(sb_certs):
+ shutil.copytree(sb_certs, f'{lb_config_dir}/includes.chroot/var/lib/shim-signed/mok')
+
# Switch to the build directory, this is crucial for the live-build work
# because the efective build config files etc. are there.
#
@@ -611,33 +616,34 @@ DOCUMENTATION_URL="{build_config['documentation_url']}"
## Configure live-build
lb_config_tmpl = jinja2.Template("""
lb config noauto \
+ --no-color \
--apt-indices false \
- --apt-options "--yes -oAPT::Get::allow-downgrades=true" \
+ --apt-options "--yes" \
--apt-recommends false \
- --architecture {{architecture}} \
- --archive-areas {{debian_archive_areas}} \
+ --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' \
+ --bootloaders "{{bootloaders}}" \
+ --checksums "sha256" \
--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,linux-kbuild-6.1" \
- --distribution {{debian_distribution}} \
+ --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}} \
+ --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 \
--utc-time true
diff --git a/scripts/image-build/raw_image.py b/scripts/image-build/raw_image.py
index d850eead..a88ed020 100644
--- a/scripts/image-build/raw_image.py
+++ b/scripts/image-build/raw_image.py
@@ -63,22 +63,38 @@ class BuildContext:
return self
- def __exit__(self, exc_type, exc_value, exc_tb):
+ def __exit__(self, exc_type, exc_value, traceback):
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}""")
+ for mount in [
+ f"{self.squash_dir}/dev/",
+ f"{self.squash_dir}/proc/",
+ f"{self.squash_dir}/sys/",
+ f"{self.squash_dir}/boot/efi",
+ f"{self.squash_dir}/boot",
+ f"{self.squash_dir}",
+ f"{self.iso_dir}",
+ f"{self.raw_dir}",
+ f"{self.efi_dir}"
+ ]:
+ if os.path.ismount(mount):
+ try:
+ cmd(f"umount {mount}")
+ except Exception as e:
+ print(f"W: Failed to umount {mount}: {e}")
+
+ # Remove kpartx mappings
if self.loop_device:
- cmd(f"""losetup -d {self.loop_device}""")
+ mapper_base = os.path.basename(self.loop_device)
+ try:
+ cmd(f"kpartx -d {self.loop_device}")
+ except Exception as e:
+ print(f"W: Failed to remove kpartx mappings for {mapper_base}: {e}")
+
+ try:
+ cmd(f"losetup -d {self.loop_device}")
+ except Exception as e:
+ print(f"W: Failed to detach loop device {self.loop_device}: {e}")
def create_disk(path, size):
cmd(f"""qemu-img create -f raw "{path}" {size}G""")
@@ -106,14 +122,23 @@ def setup_loop_device(con, raw_file):
def mount_image(con):
import vyos.system.disk
- from subprocess import Popen, PIPE, STDOUT
- from re import match
+ try:
+ root = con.disk_details.partition['root']
+ efi = con.disk_details.partition['efi']
+ except (AttributeError, KeyError):
+ raise RuntimeError("E: No valid root or EFI partition found in disk details")
+
+ vyos.system.disk.filesystem_create(efi, 'efi')
+ vyos.system.disk.filesystem_create(root, 'ext4')
- vyos.system.disk.filesystem_create(con.disk_details.partition['efi'], 'efi')
- vyos.system.disk.filesystem_create(con.disk_details.partition['root'], 'ext4')
+ print(f"I: Mounting root: {root} to {con.raw_dir}")
+ cmd(f"mount -t ext4 {root} {con.raw_dir}")
+ cmd(f"mount -t vfat {efi} {con.efi_dir}")
- 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}")
+ if not os.path.ismount(con.efi_dir):
+ cmd(f"mount -t vfat {con.disk_details.partition['efi']} {con.efi_dir}")
+ else:
+ print(f"I: {con.disk_details.partition['efi']} already mounted on {con.efi_dir}")
def install_image(con, version):
from glob import glob
@@ -205,6 +230,36 @@ def create_raw_image(build_config, iso_file, work_dir):
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)
+
+ # Map partitions using kpartx
+ print("I: Mapping partitions using kpartx...")
+ cmd(f"kpartx -av {con.loop_device}")
+ cmd("udevadm settle")
+
+
+ # Detect mapped partitions
+ from glob import glob
+ import time
+
+ mapper_base = os.path.basename(con.loop_device).replace("/dev/", "")
+ mapped_parts = sorted(glob(f"/dev/mapper/{mapper_base}p*"))
+
+ if not mapped_parts:
+ raise RuntimeError(f"E: No partitions were found in /dev/mapper for {mapper_base}")
+
+ print(f"I: Found mapped partitions: {mapped_parts}")
+
+ if len(mapped_parts) == 2:
+ # Assume [0] = EFI, [1] = root
+ disk_details.partition['efi'] = mapped_parts[0]
+ disk_details.partition['root'] = mapped_parts[1]
+ elif len(mapped_parts) >= 3:
+ # Common layout: [1] = EFI, [2] = root (skip 0 if it's BIOS boot)
+ disk_details.partition['efi'] = mapped_parts[1]
+ disk_details.partition['root'] = mapped_parts[2]
+ else:
+ raise RuntimeError(f"E: Unexpected partition layout: {mapped_parts}")
+
con.disk_details = disk_details
mount_image(con)
install_image(con, version)