From 5fb38d3e5f201934d64bae186c5300e7de7af3d4 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Fri, 16 Apr 2021 14:33:34 +0300 Subject: [PATCH] chore: refactor Dockerfile for cross-compilation This has two big visible changes: * `installer` image now contains assets for both `amd64` and `arm64`, so it can be used to generate any Talos image (including RPi on amd64 host) * Talos is using cross-compilation instead of emulation to build non-native architectures: on amd64, Go amd64 compiler produces binaries for both arm64 and amd64 (before this change: Go arm64 compiler via QEMU produces arm64 binaries on amd64) CI implications: we no longer require arm64 nodes. Changes walkthrough: * `installer` container now keeps assets under `/usr/install/` * Dockerfile build starts forcing toolchain/base image to use the build host native architecture, not target architecture * lots of duplication for amd64/arm64 as we want to combine assets for both arches in a single image (e.g. we have multi-arch amd64/arm64 installer image, each arch has native installer binary, but both arches contain full set of amd64/arm64 assets) * fixed a small bug preventing arm64 on amd64 talosctl cluster create Signed-off-by: Andrey Smirnov --- .drone.jsonnet | 24 +- Dockerfile | 271 +++++++++++++----- Makefile | 12 +- cmd/installer/cmd/image.go | 21 +- cmd/installer/cmd/iso.go | 7 +- cmd/installer/cmd/root.go | 2 + cmd/installer/pkg/install/install.go | 2 + cmd/installer/pkg/install/manifest.go | 4 +- cmd/installer/pkg/ova/ova.go | 5 +- .../board/bananapi_m64/bananapi_m64.go | 4 +- .../libretech_all_h3_cc_h5.go | 4 +- .../runtime/v1alpha1/board/rock64/rock64.go | 4 +- .../runtime/v1alpha1/board/rockpi4/rockpi4.go | 4 +- .../pkg/runtime/v1alpha1/board/rpi_4/rpi_4.go | 4 +- .../runtime/v1alpha1/bootloader/grub/grub.go | 20 +- pkg/machinery/constants/constants.go | 4 +- pkg/provision/providers/qemu/preflight.go | 4 + 17 files changed, 272 insertions(+), 124 deletions(-) diff --git a/.drone.jsonnet b/.drone.jsonnet index 04f9a9dca2..486bd83ddc 100644 --- a/.drone.jsonnet +++ b/.drone.jsonnet @@ -103,7 +103,7 @@ local volumes = { // This provides the docker service. local docker = { name: 'docker', - image: 'docker:19.03-dind', + image: 'docker:20.10-dind', entrypoint: ['dockerd'], privileged: true, command: [ @@ -194,15 +194,13 @@ local check_dirty = Step("check-dirty", depends_on=[generate]); local build = Step("build", target="talosctl-linux talosctl-darwin kernel initramfs installer talos", depends_on=[check_dirty], environment={"IMAGE_REGISTRY": local_registry, "PUSH": true}); local lint = Step("lint", depends_on=[build]); local talosctl_cni_bundle = Step('talosctl-cni-bundle', depends_on=[build, lint]); -local iso_amd64 = Step("iso-amd64", target="iso", depends_on=[build], environment={"IMAGE_REGISTRY": local_registry}); -local iso_arm64 = Step("iso-arm64", target="iso", depends_on=[build], environment={"IMAGE_REGISTRY": local_registry, "DOCKER_HOST": "tcp://docker-arm64.ci.svc:2376"}); -local images_amd64 = Step("images-amd64", target="images", depends_on=[iso_amd64], environment={"IMAGE_REGISTRY": local_registry}); -local images_arm64 = Step("images-arm64", target="images", depends_on=[iso_arm64], environment={"IMAGE_REGISTRY": local_registry, "DOCKER_HOST": "tcp://docker-arm64.ci.svc:2376"}); -local sbcs_arm64 = Step("sbcs-arm64", target="sbcs", depends_on=[images_amd64, images_arm64], environment={"IMAGE_REGISTRY": local_registry, "DOCKER_HOST": "tcp://docker-arm64.ci.svc:2376"}); +local iso = Step("iso", target="iso", depends_on=[build], environment={"IMAGE_REGISTRY": local_registry}); +local images = Step("images", target="images", depends_on=[iso], environment={"IMAGE_REGISTRY": local_registry}); +local sbcs = Step("sbcs", target="sbcs", depends_on=[images], environment={"IMAGE_REGISTRY": local_registry}); local unit_tests = Step("unit-tests", target="unit-tests unit-tests-race", depends_on=[build, lint]); local e2e_docker = Step("e2e-docker-short", depends_on=[build, unit_tests], target="e2e-docker", environment={"SHORT_INTEGRATION_TEST": "yes", "IMAGE_REGISTRY": local_registry}); local e2e_qemu = Step("e2e-qemu-short", privileged=true, target="e2e-qemu", depends_on=[build, unit_tests, talosctl_cni_bundle], environment={"IMAGE_REGISTRY": local_registry, "SHORT_INTEGRATION_TEST": "yes"}, when={event: ['pull_request']}); -local e2e_iso = Step("e2e-iso", privileged=true, target="e2e-iso", depends_on=[build, unit_tests, iso_amd64, talosctl_cni_bundle], when={event: ['pull_request']}, environment={"IMAGE_REGISTRY": local_registry}); +local e2e_iso = Step("e2e-iso", privileged=true, target="e2e-iso", depends_on=[build, unit_tests, iso, talosctl_cni_bundle], when={event: ['pull_request']}, environment={"IMAGE_REGISTRY": local_registry}); local coverage = { name: 'coverage', @@ -279,7 +277,7 @@ local save_artifacts = { 's3cmd --host=rook-ceph-rgw-ci-store.rook-ceph.svc --host-bucket=rook-ceph-rgw-ci-store.rook-ceph.svc --no-ssl --stats sync _out s3://${CI_COMMIT_SHA}${DRONE_TAG//./-}', ], volumes: volumes.ForStep(), - depends_on: [build.name, images_amd64.name, images_arm64.name, iso_amd64.name, iso_arm64.name, sbcs_arm64.name, talosctl_cni_bundle.name], + depends_on: [build.name, images.name, iso.name, sbcs.name, talosctl_cni_bundle.name], }; local load_artifacts = { @@ -304,11 +302,9 @@ local default_steps = [ build, lint, talosctl_cni_bundle, - iso_amd64, - iso_arm64, - images_amd64, - images_arm64, - sbcs_arm64, + iso, + images, + sbcs, unit_tests, save_artifacts, coverage, @@ -565,7 +561,7 @@ local release = { when: { event: ['tag'], }, - depends_on: [build.name, boot.name, talosctl_cni_bundle.name, images_amd64.name, images_arm64.name, sbcs_arm64.name, iso_amd64.name, iso_arm64.name, push.name, release_notes.name] + depends_on: [build.name, boot.name, talosctl_cni_bundle.name, images.name, sbcs.name, iso.name, push.name, release_notes.name] }; local release_steps = default_steps + [ diff --git a/Dockerfile b/Dockerfile index bb10fa6cb7..0f1321963a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,29 +11,74 @@ ARG EXTRAS FROM ghcr.io/talos-systems/fhs:${PKGS} AS pkg-fhs FROM ghcr.io/talos-systems/ca-certificates:${PKGS} AS pkg-ca-certificates -FROM ghcr.io/talos-systems/cryptsetup:${PKGS} AS pkg-cryptsetup -FROM ghcr.io/talos-systems/containerd:${PKGS} AS pkg-containerd -FROM ghcr.io/talos-systems/dosfstools:${PKGS} AS pkg-dosfstools -FROM ghcr.io/talos-systems/eudev:${PKGS} AS pkg-eudev + +FROM --platform=amd64 ghcr.io/talos-systems/cryptsetup:${PKGS} AS pkg-cryptsetup-amd64 +FROM --platform=arm64 ghcr.io/talos-systems/cryptsetup:${PKGS} AS pkg-cryptsetup-arm64 + +FROM --platform=amd64 ghcr.io/talos-systems/containerd:${PKGS} AS pkg-containerd-amd64 +FROM --platform=arm64 ghcr.io/talos-systems/containerd:${PKGS} AS pkg-containerd-arm64 + +FROM --platform=amd64 ghcr.io/talos-systems/dosfstools:${PKGS} AS pkg-dosfstools-amd64 +FROM --platform=arm64 ghcr.io/talos-systems/dosfstools:${PKGS} AS pkg-dosfstools-arm64 + +FROM --platform=amd64 ghcr.io/talos-systems/eudev:${PKGS} AS pkg-eudev-amd64 +FROM --platform=arm64 ghcr.io/talos-systems/eudev:${PKGS} AS pkg-eudev-arm64 + FROM ghcr.io/talos-systems/grub:${PKGS} AS pkg-grub -FROM ghcr.io/talos-systems/iptables:${PKGS} AS pkg-iptables -FROM ghcr.io/talos-systems/libjson-c:${PKGS} AS pkg-libjson-c -FROM ghcr.io/talos-systems/libpopt:${PKGS} AS pkg-libpopt -FROM ghcr.io/talos-systems/libressl:${PKGS} AS pkg-libressl -FROM ghcr.io/talos-systems/libseccomp:${PKGS} AS pkg-libseccomp -FROM ghcr.io/talos-systems/linux-firmware:${PKGS} AS pkg-linux-firmware -FROM ghcr.io/talos-systems/lvm2:${PKGS} AS pkg-lvm2 -FROM ghcr.io/talos-systems/libaio:${PKGS} AS pkg-libaio -FROM ghcr.io/talos-systems/musl:${PKGS} AS pkg-musl -FROM ghcr.io/talos-systems/open-iscsi:${PKGS} AS pkg-open-iscsi -FROM ghcr.io/talos-systems/open-isns:${PKGS} AS pkg-open-isns -FROM ghcr.io/talos-systems/runc:${PKGS} AS pkg-runc -FROM ghcr.io/talos-systems/xfsprogs:${PKGS} AS pkg-xfsprogs -FROM ghcr.io/talos-systems/util-linux:${PKGS} AS pkg-util-linux -FROM ghcr.io/talos-systems/kmod:${PKGS} AS pkg-kmod +FROM --platform=amd64 ghcr.io/talos-systems/grub:${PKGS} AS pkg-grub-amd64 +FROM --platform=arm64 ghcr.io/talos-systems/grub:${PKGS} AS pkg-grub-arm64 + +FROM --platform=amd64 ghcr.io/talos-systems/iptables:${PKGS} AS pkg-iptables-amd64 +FROM --platform=arm64 ghcr.io/talos-systems/iptables:${PKGS} AS pkg-iptables-arm64 + +FROM --platform=amd64 ghcr.io/talos-systems/libjson-c:${PKGS} AS pkg-libjson-c-amd64 +FROM --platform=arm64 ghcr.io/talos-systems/libjson-c:${PKGS} AS pkg-libjson-c-arm64 + +FROM --platform=amd64 ghcr.io/talos-systems/libpopt:${PKGS} AS pkg-libpopt-amd64 +FROM --platform=arm64 ghcr.io/talos-systems/libpopt:${PKGS} AS pkg-libpopt-arm64 + +FROM --platform=amd64 ghcr.io/talos-systems/libressl:${PKGS} AS pkg-libressl-amd64 +FROM --platform=arm64 ghcr.io/talos-systems/libressl:${PKGS} AS pkg-libressl-arm64 + +FROM --platform=amd64 ghcr.io/talos-systems/libseccomp:${PKGS} AS pkg-libseccomp-amd64 +FROM --platform=arm64 ghcr.io/talos-systems/libseccomp:${PKGS} AS pkg-libseccomp-arm64 + +FROM --platform=amd64 ghcr.io/talos-systems/linux-firmware:${PKGS} AS pkg-linux-firmware-amd64 +FROM --platform=arm64 ghcr.io/talos-systems/linux-firmware:${PKGS} AS pkg-linux-firmware-arm64 + +FROM --platform=amd64 ghcr.io/talos-systems/lvm2:${PKGS} AS pkg-lvm2-amd64 +FROM --platform=arm64 ghcr.io/talos-systems/lvm2:${PKGS} AS pkg-lvm2-arm64 + +FROM --platform=amd64 ghcr.io/talos-systems/libaio:${PKGS} AS pkg-libaio-amd64 +FROM --platform=arm64 ghcr.io/talos-systems/libaio:${PKGS} AS pkg-libaio-arm64 + +FROM --platform=amd64 ghcr.io/talos-systems/musl:${PKGS} AS pkg-musl-amd64 +FROM --platform=arm64 ghcr.io/talos-systems/musl:${PKGS} AS pkg-musl-arm64 + +FROM --platform=amd64 ghcr.io/talos-systems/open-iscsi:${PKGS} AS pkg-open-iscsi-amd64 +FROM --platform=arm64 ghcr.io/talos-systems/open-iscsi:${PKGS} AS pkg-open-iscsi-arm64 + +FROM --platform=amd64 ghcr.io/talos-systems/open-isns:${PKGS} AS pkg-open-isns-amd64 +FROM --platform=arm64 ghcr.io/talos-systems/open-isns:${PKGS} AS pkg-open-isns-arm64 + +FROM --platform=amd64 ghcr.io/talos-systems/runc:${PKGS} AS pkg-runc-amd64 +FROM --platform=arm64 ghcr.io/talos-systems/runc:${PKGS} AS pkg-runc-arm64 + +FROM --platform=amd64 ghcr.io/talos-systems/xfsprogs:${PKGS} AS pkg-xfsprogs-amd64 +FROM --platform=arm64 ghcr.io/talos-systems/xfsprogs:${PKGS} AS pkg-xfsprogs-arm64 + +FROM --platform=amd64 ghcr.io/talos-systems/util-linux:${PKGS} AS pkg-util-linux-amd64 +FROM --platform=arm64 ghcr.io/talos-systems/util-linux:${PKGS} AS pkg-util-linux-arm64 + +FROM --platform=amd64 ghcr.io/talos-systems/kmod:${PKGS} AS pkg-kmod-amd64 +FROM --platform=arm64 ghcr.io/talos-systems/kmod:${PKGS} AS pkg-kmod-arm64 + FROM ghcr.io/talos-systems/kernel:${PKGS} AS pkg-kernel -FROM ghcr.io/talos-systems/u-boot:${PKGS} AS pkg-u-boot -FROM ghcr.io/talos-systems/raspberrypi-firmware:${PKGS} AS pkg-raspberrypi-firmware +FROM --platform=amd64 ghcr.io/talos-systems/kernel:${PKGS} AS pkg-kernel-amd64 +FROM --platform=arm64 ghcr.io/talos-systems/kernel:${PKGS} AS pkg-kernel-arm64 + +FROM --platform=arm64 ghcr.io/talos-systems/u-boot:${PKGS} AS pkg-u-boot-arm64 +FROM --platform=arm64 ghcr.io/talos-systems/raspberrypi-firmware:${PKGS} AS pkg-raspberrypi-firmware-arm64 # Resolve package images using ${EXTRAS} to be used later in COPY --from=. @@ -43,7 +88,7 @@ FROM ghcr.io/talos-systems/talosctl-cni-bundle-install:${EXTRAS} AS extras-talos FROM $IMPORTVET as importvet -FROM $TOOLS AS tools +FROM --platform=${BUILDPLATFORM} $TOOLS AS tools ENV PATH /toolchain/bin:/toolchain/go/bin RUN ["/toolchain/bin/mkdir", "/bin", "/tmp"] RUN ["/toolchain/bin/ln", "-svf", "/toolchain/bin/bash", "/bin/sh"] @@ -65,8 +110,7 @@ COPY --from=importvet /importvet /toolchain/go/bin/importvet # The build target creates a container that will be used to build Talos source # code. -FROM scratch AS build -COPY --from=tools / / +FROM --platform=${BUILDPLATFORM} tools AS build SHELL ["/toolchain/bin/bash", "-c"] ENV PATH /toolchain/bin:/toolchain/go/bin ENV GO111MODULE on @@ -123,7 +167,7 @@ WORKDIR /pkg/machinery RUN --mount=type=cache,target=/.cache go generate /pkg/machinery/config/types/v1alpha1/... WORKDIR / -FROM scratch AS generate +FROM --platform=${BUILDPLATFORM} scratch AS generate COPY --from=generate-build /api/common/*.pb.go /pkg/machinery/api/common/ COPY --from=generate-build /api/health/*.pb.go /pkg/machinery/api/health/ COPY --from=generate-build /api/security/*.pb.go /pkg/machinery/api/security/ @@ -155,25 +199,43 @@ WORKDIR /src # The init target builds the init binary. -FROM base AS init-build +FROM base AS init-build-amd64 +WORKDIR /src/internal/app/init +ARG GO_BUILDFLAGS +ARG GO_LDFLAGS +RUN --mount=type=cache,target=/.cache GOOS=linux GOARCH=amd64 go build ${GO_BUILDFLAGS} -ldflags "${GO_LDFLAGS}" -o /init +RUN chmod +x /init + +FROM base AS init-build-arm64 WORKDIR /src/internal/app/init ARG GO_BUILDFLAGS ARG GO_LDFLAGS -RUN --mount=type=cache,target=/.cache go build ${GO_BUILDFLAGS} -ldflags "${GO_LDFLAGS}" -o /init +RUN --mount=type=cache,target=/.cache GOOS=linux GOARCH=arm64 go build ${GO_BUILDFLAGS} -ldflags "${GO_LDFLAGS}" -o /init RUN chmod +x /init +FROM init-build-${TARGETARCH} AS init-build + FROM scratch AS init COPY --from=init-build /init /init # The machined target builds the machined binary. -FROM base AS machined-build +FROM base AS machined-build-amd64 +WORKDIR /src/internal/app/machined +ARG GO_BUILDFLAGS +ARG GO_LDFLAGS +RUN --mount=type=cache,target=/.cache GOOS=linux GOARCH=amd64 go build ${GO_BUILDFLAGS} -ldflags "${GO_LDFLAGS}" -o /machined +RUN chmod +x /machined + +FROM base AS machined-build-arm64 WORKDIR /src/internal/app/machined ARG GO_BUILDFLAGS ARG GO_LDFLAGS -RUN --mount=type=cache,target=/.cache go build ${GO_BUILDFLAGS} -ldflags "${GO_LDFLAGS}" -o /machined +RUN --mount=type=cache,target=/.cache GOOS=linux GOARCH=arm64 go build ${GO_BUILDFLAGS} -ldflags "${GO_LDFLAGS}" -o /machined RUN chmod +x /machined +FROM machined-build-${TARGETARCH} AS machined-build + FROM scratch AS machined COPY --from=machined-build /machined /machined @@ -240,33 +302,75 @@ COPY --from=pkg-kernel /boot/vmlinuz /vmlinuz-${TARGETARCH} # The rootfs target provides the Talos rootfs. -FROM build AS rootfs-base +FROM build AS rootfs-base-amd64 +COPY --from=pkg-fhs / /rootfs +COPY --from=pkg-ca-certificates / /rootfs +COPY --from=pkg-cryptsetup-amd64 / /rootfs +COPY --from=pkg-containerd-amd64 / /rootfs +COPY --from=pkg-dosfstools-amd64 / /rootfs +COPY --from=pkg-eudev-amd64 / /rootfs +COPY --from=pkg-iptables-amd64 / /rootfs +COPY --from=pkg-libjson-c-amd64 / /rootfs +COPY --from=pkg-libpopt-amd64 / /rootfs +COPY --from=pkg-libressl-amd64 / /rootfs +COPY --from=pkg-libseccomp-amd64 / /rootfs +COPY --from=pkg-linux-firmware-amd64 /lib/firmware/bnx2 /rootfs/lib/firmware/bnx2 +COPY --from=pkg-linux-firmware-amd64 /lib/firmware/bnx2x /rootfs/lib/firmware/bnx2x +COPY --from=pkg-lvm2-amd64 / /rootfs +COPY --from=pkg-libaio-amd64 / /rootfs +COPY --from=pkg-musl-amd64 / /rootfs +COPY --from=pkg-open-iscsi-amd64 / /rootfs +COPY --from=pkg-open-isns-amd64 / /rootfs +COPY --from=pkg-runc-amd64 / /rootfs +COPY --from=pkg-xfsprogs-amd64 / /rootfs +COPY --from=pkg-util-linux-amd64 /lib/libblkid.* /rootfs/lib/ +COPY --from=pkg-util-linux-amd64 /lib/libuuid.* /rootfs/lib/ +COPY --from=pkg-util-linux-amd64 /lib/libmount.* /rootfs/lib/ +COPY --from=pkg-kmod-amd64 /usr/lib/libkmod.* /rootfs/lib/ +COPY --from=pkg-kernel-amd64 /lib/modules /rootfs/lib/modules +COPY --from=machined-build-amd64 /machined /rootfs/sbin/init +# NB: We run the cleanup step before creating extra directories, files, and +# symlinks to avoid accidentally cleaning them up. +COPY ./hack/cleanup.sh /toolchain/bin/cleanup.sh +RUN cleanup.sh /rootfs +COPY hack/containerd.toml /rootfs/etc/cri/containerd.toml +RUN touch /rootfs/etc/resolv.conf +RUN touch /rootfs/etc/hosts +RUN touch /rootfs/etc/os-release +RUN mkdir -pv /rootfs/{boot,usr/local/share,mnt,system} +RUN mkdir -pv /rootfs/{etc/kubernetes/manifests,etc/cni,usr/libexec/kubernetes} +RUN ln -s /etc/ssl /rootfs/etc/pki +RUN ln -s /etc/ssl /rootfs/usr/share/ca-certificates +RUN ln -s /etc/ssl /rootfs/usr/local/share/ca-certificates +RUN ln -s /etc/ssl /rootfs/etc/ca-certificates + +FROM build AS rootfs-base-arm64 COPY --from=pkg-fhs / /rootfs COPY --from=pkg-ca-certificates / /rootfs -COPY --from=pkg-cryptsetup / /rootfs -COPY --from=pkg-containerd / /rootfs -COPY --from=pkg-dosfstools / /rootfs -COPY --from=pkg-eudev / /rootfs -COPY --from=pkg-iptables / /rootfs -COPY --from=pkg-libjson-c / /rootfs -COPY --from=pkg-libpopt / /rootfs -COPY --from=pkg-libressl / /rootfs -COPY --from=pkg-libseccomp / /rootfs -COPY --from=pkg-linux-firmware /lib/firmware/bnx2 /rootfs/lib/firmware/bnx2 -COPY --from=pkg-linux-firmware /lib/firmware/bnx2x /rootfs/lib/firmware/bnx2x -COPY --from=pkg-lvm2 / /rootfs -COPY --from=pkg-libaio / /rootfs -COPY --from=pkg-musl / /rootfs -COPY --from=pkg-open-iscsi / /rootfs -COPY --from=pkg-open-isns / /rootfs -COPY --from=pkg-runc / /rootfs -COPY --from=pkg-xfsprogs / /rootfs -COPY --from=pkg-util-linux /lib/libblkid.* /rootfs/lib/ -COPY --from=pkg-util-linux /lib/libuuid.* /rootfs/lib/ -COPY --from=pkg-util-linux /lib/libmount.* /rootfs/lib/ -COPY --from=pkg-kmod /usr/lib/libkmod.* /rootfs/lib/ -COPY --from=pkg-kernel /lib/modules /rootfs/lib/modules -COPY --from=machined /machined /rootfs/sbin/init +COPY --from=pkg-cryptsetup-arm64 / /rootfs +COPY --from=pkg-containerd-arm64 / /rootfs +COPY --from=pkg-dosfstools-arm64 / /rootfs +COPY --from=pkg-eudev-arm64 / /rootfs +COPY --from=pkg-iptables-arm64 / /rootfs +COPY --from=pkg-libjson-c-arm64 / /rootfs +COPY --from=pkg-libpopt-arm64 / /rootfs +COPY --from=pkg-libressl-arm64 / /rootfs +COPY --from=pkg-libseccomp-arm64 / /rootfs +COPY --from=pkg-linux-firmware-arm64 /lib/firmware/bnx2 /rootfs/lib/firmware/bnx2 +COPY --from=pkg-linux-firmware-arm64 /lib/firmware/bnx2x /rootfs/lib/firmware/bnx2x +COPY --from=pkg-lvm2-arm64 / /rootfs +COPY --from=pkg-libaio-arm64 / /rootfs +COPY --from=pkg-musl-arm64 / /rootfs +COPY --from=pkg-open-iscsi-arm64 / /rootfs +COPY --from=pkg-open-isns-arm64 / /rootfs +COPY --from=pkg-runc-arm64 / /rootfs +COPY --from=pkg-xfsprogs-arm64 / /rootfs +COPY --from=pkg-util-linux-arm64 /lib/libblkid.* /rootfs/lib/ +COPY --from=pkg-util-linux-arm64 /lib/libuuid.* /rootfs/lib/ +COPY --from=pkg-util-linux-arm64 /lib/libmount.* /rootfs/lib/ +COPY --from=pkg-kmod-arm64 /usr/lib/libkmod.* /rootfs/lib/ +COPY --from=pkg-kernel-arm64 /lib/modules /rootfs/lib/modules +COPY --from=machined-build-arm64 /machined /rootfs/sbin/init # NB: We run the cleanup step before creating extra directories, files, and # symlinks to avoid accidentally cleaning them up. COPY ./hack/cleanup.sh /toolchain/bin/cleanup.sh @@ -282,23 +386,39 @@ RUN ln -s /etc/ssl /rootfs/usr/share/ca-certificates RUN ln -s /etc/ssl /rootfs/usr/local/share/ca-certificates RUN ln -s /etc/ssl /rootfs/etc/ca-certificates -FROM rootfs-base AS rootfs-squashfs +FROM rootfs-base-${TARGETARCH} AS rootfs-base + +FROM rootfs-base-arm64 AS rootfs-squashfs-arm64 +RUN mksquashfs /rootfs /rootfs.sqsh -all-root -noappend -comp xz -Xdict-size 100% -no-progress + +FROM rootfs-base-amd64 AS rootfs-squashfs-amd64 RUN mksquashfs /rootfs /rootfs.sqsh -all-root -noappend -comp xz -Xdict-size 100% -no-progress -FROM scratch AS squashfs -COPY --from=rootfs-squashfs /rootfs.sqsh / +FROM scratch AS squashfs-arm64 +COPY --from=rootfs-squashfs-arm64 /rootfs.sqsh / + +FROM scratch AS squashfs-amd64 +COPY --from=rootfs-squashfs-amd64 /rootfs.sqsh / FROM scratch AS rootfs COPY --from=rootfs-base /rootfs / # The initramfs target provides the Talos initramfs image. -FROM build AS initramfs-archive +FROM build AS initramfs-archive-arm64 +WORKDIR /initramfs +COPY --from=squashfs-arm64 /rootfs.sqsh . +COPY --from=init-build-arm64 /init . +RUN set -o pipefail && find . 2>/dev/null | cpio -H newc -o | xz -v -C crc32 -0 -e -T 0 -z >/initramfs.xz + +FROM build AS initramfs-archive-amd64 WORKDIR /initramfs -COPY --from=squashfs /rootfs.sqsh . -COPY --from=init /init . +COPY --from=squashfs-amd64 /rootfs.sqsh . +COPY --from=init-build-amd64 /init . RUN set -o pipefail && find . 2>/dev/null | cpio -H newc -o | xz -v -C crc32 -0 -e -T 0 -z >/initramfs.xz +FROM initramfs-archive-${TARGETARCH} AS initramfs-archive + FROM scratch AS initramfs ARG TARGETARCH COPY --from=initramfs-archive /initramfs.xz /initramfs-${TARGETARCH}.xz @@ -318,12 +438,27 @@ FROM base AS installer-build ARG GO_BUILDFLAGS ARG GO_LDFLAGS WORKDIR /src/cmd/installer -RUN --mount=type=cache,target=/.cache go build ${GO_BUILDFLAGS} -ldflags "${GO_LDFLAGS}" -o /installer +ARG TARGETARCH +RUN --mount=type=cache,target=/.cache GOOS=linux GOARCH=${TARGETARCH} go build ${GO_BUILDFLAGS} -ldflags "${GO_LDFLAGS}" -o /installer RUN chmod +x /installer FROM alpine:3.13.5 AS unicode-pf2 RUN apk add --no-cache --update grub +FROM scratch AS install-artifacts +COPY --from=pkg-grub-amd64 /usr/lib/grub /usr/lib/grub +COPY --from=pkg-grub-arm64 /usr/lib/grub /usr/lib/grub +COPY --from=pkg-grub / / +COPY --from=unicode-pf2 /usr/share/grub/unicode.pf2 /usr/share/grub/unicode.pf2 +COPY --from=pkg-kernel-amd64 /boot/vmlinuz /usr/install/amd64/vmlinuz +COPY --from=pkg-kernel-arm64 /boot/vmlinuz /usr/install/arm64/vmlinuz +COPY --from=pkg-kernel-amd64 /dtb /usr/install/amd64/dtb +COPY --from=pkg-kernel-arm64 /dtb /usr/install/arm64/dtb +COPY --from=initramfs-archive-amd64 /initramfs.xz /usr/install/amd64/initramfs.xz +COPY --from=initramfs-archive-arm64 /initramfs.xz /usr/install/arm64/initramfs.xz +COPY --from=pkg-u-boot-arm64 / /usr/install/arm64/u-boot +COPY --from=pkg-raspberrypi-firmware-arm64 / /usr/install/arm64/raspberrypi-firmware + FROM alpine:3.13.5 AS installer RUN apk add --no-cache --update \ bash \ @@ -335,14 +470,8 @@ RUN apk add --no-cache --update \ xfsprogs \ xorriso \ xz -COPY --from=pkg-grub / / -COPY --from=unicode-pf2 /usr/share/grub/unicode.pf2 /usr/share/grub/unicode.pf2 ARG TARGETARCH -COPY --from=kernel /vmlinuz-${TARGETARCH} /usr/install/vmlinuz -COPY --from=pkg-kernel /dtb /usr/install/dtb -COPY --from=initramfs /initramfs-${TARGETARCH}.xz /usr/install/initramfs.xz -COPY --from=pkg-u-boot / /usr/install/u-boot -COPY --from=pkg-raspberrypi-firmware / /usr/install/raspberrypi-firmware +COPY --from=install-artifacts / / COPY --from=installer-build /installer /bin/installer RUN ln -s /bin/installer /bin/talosctl ARG TAG @@ -356,7 +485,7 @@ ONBUILD RUN apk add --no-cache --update \ xz ONBUILD WORKDIR /initramfs ONBUILD ARG RM -ONBUILD RUN xz -d /usr/install/initramfs.xz \ +ONBUILD RUN xz -d /usr/install/${TARGETARCH}/initramfs.xz \ && cpio -idvm < /usr/install/initramfs \ && unsquashfs -f -d /rootfs rootfs.sqsh \ && for f in ${RM}; do rm -rfv /rootfs$f; done \ @@ -365,7 +494,7 @@ ONBUILD RUN xz -d /usr/install/initramfs.xz \ ONBUILD COPY --from=customization / /rootfs ONBUILD RUN find /rootfs \ && mksquashfs /rootfs rootfs.sqsh -all-root -noappend -comp xz -Xdict-size 100% -no-progress \ - && set -o pipefail && find . 2>/dev/null | cpio -H newc -o | xz -v -C crc32 -0 -e -T 0 -z >/usr/install/initramfs.xz \ + && set -o pipefail && find . 2>/dev/null | cpio -H newc -o | xz -v -C crc32 -0 -e -T 0 -z >/usr/install/${TARGETARCH}/initramfs.xz \ && rm -rf /rootfs \ && rm -rf /initramfs ONBUILD WORKDIR / @@ -440,7 +569,7 @@ RUN --mount=type=cache,target=/.cache golangci-lint run --config ../../.golangci WORKDIR /src RUN --mount=type=cache,target=/.cache importvet github.com/talos-systems/talos/... RUN find . -name '*.pb.go' | xargs rm -RUN FILES="$(gofumports -l -local github.com/talos-systems/talos .)" && test -z "${FILES}" || (echo -e "Source code is not formatted with 'gofumports -w -local github.com/talos-systems/talos .':\n${FILES}"; exit 1) +RUN --mount=type=cache,target=/.cache FILES="$(gofumports -l -local github.com/talos-systems/talos .)" && test -z "${FILES}" || (echo -e "Source code is not formatted with 'gofumports -w -local github.com/talos-systems/talos .':\n${FILES}"; exit 1) # The protolint target performs linting on protobuf files. diff --git a/Makefile b/Makefile index 960729e178..0657edd6c7 100644 --- a/Makefile +++ b/Makefile @@ -198,20 +198,26 @@ talosctl: $(TALOSCTL_DEFAULT_TARGET) ## Builds the talosctl binary for the local image-%: ## Builds the specified image. Valid options are aws, azure, digital-ocean, gcp, and vmware (e.g. image-aws) @docker pull $(REGISTRY_AND_USERNAME)/installer:$(TAG) - @docker run --rm -v /dev:/dev --privileged $(REGISTRY_AND_USERNAME)/installer:$(TAG) image --platform $* --tar-to-stdout | tar xz -C $(ARTIFACTS) + @for platform in $(subst $(,),$(space),$(PLATFORM)); do \ + arch=`basename "$${platform}"` ; \ + docker run --rm -v /dev:/dev --privileged $(REGISTRY_AND_USERNAME)/installer:$(TAG) image --platform $* --arch $$arch --tar-to-stdout | tar xz -C $(ARTIFACTS) ; \ + done images: image-aws image-azure image-digital-ocean image-gcp image-metal image-openstack image-vmware ## Builds all known images (AWS, Azure, DigitalOcean, GCP, Metal, Openstack, and VMware). sbc-%: ## Builds the specified SBC image. Valid options are rpi_4, rock64, bananapi_m64, libretech_all_h3_cc_h5, and rockpi_4 (e.g. sbc-rpi_4) @docker pull $(REGISTRY_AND_USERNAME)/installer:$(TAG) - @docker run --rm -v /dev:/dev --privileged $(REGISTRY_AND_USERNAME)/installer:$(TAG) image --platform metal --board $* --tar-to-stdout | tar xz -C $(ARTIFACTS) + @docker run --rm -v /dev:/dev --privileged $(REGISTRY_AND_USERNAME)/installer:$(TAG) image --platform metal --arch arm64 --board $* --tar-to-stdout | tar xz -C $(ARTIFACTS) sbcs: sbc-rpi_4 sbc-rock64 sbc-bananapi_m64 sbc-libretech_all_h3_cc_h5 sbc-rockpi_4 ## Builds all known SBC images (Raspberry Pi 4 Model B, Rock64, Banana Pi M64, Radxa ROCK Pi 4, and Libre Computer Board ALL-H3-CC). .PHONY: iso iso: ## Builds the ISO and outputs it to the artifact directory. @docker pull $(REGISTRY_AND_USERNAME)/installer:$(TAG) - @docker run --rm -i $(REGISTRY_AND_USERNAME)/installer:$(TAG) iso --tar-to-stdout | tar xz -C $(ARTIFACTS) + @for platform in $(subst $(,),$(space),$(PLATFORM)); do \ + arch=`basename "$${platform}"` ; \ + docker run --rm -i $(REGISTRY_AND_USERNAME)/installer:$(TAG) iso --arch $$arch --tar-to-stdout | tar xz -C $(ARTIFACTS) ; \ + done .PHONY: boot boot: ## Creates a compressed tarball that includes vmlinuz-{amd64,arm64} and initramfs-{amd64,arm64}.xz. Note that these files must already be present in the artifacts directory. diff --git a/cmd/installer/cmd/image.go b/cmd/installer/cmd/image.go index 18585209e3..3baecb506a 100644 --- a/cmd/installer/cmd/image.go +++ b/cmd/installer/cmd/image.go @@ -10,7 +10,6 @@ import ( "log" "os" "path/filepath" - stdruntime "runtime" "strings" "github.com/spf13/cobra" @@ -97,7 +96,7 @@ func runImageCmd() (err error) { return err } - if err := finalize(p, img); err != nil { + if err := finalize(p, img, options.Arch); err != nil { return err } @@ -111,7 +110,7 @@ func runImageCmd() (err error) { } //nolint:gocyclo -func finalize(platform runtime.Platform, img string) (err error) { +func finalize(platform runtime.Platform, img, arch string) (err error) { dir := filepath.Dir(img) file := filepath.Base(img) @@ -119,7 +118,7 @@ func finalize(platform runtime.Platform, img string) (err error) { switch platform.Name() { case "aws": - if err = tar(fmt.Sprintf("aws-%s.tar.gz", stdruntime.GOARCH), file, dir); err != nil { + if err = tar(fmt.Sprintf("aws-%s.tar.gz", arch), file, dir); err != nil { return err } case "azure": @@ -129,28 +128,28 @@ func finalize(platform runtime.Platform, img string) (err error) { return err } - if err = tar(fmt.Sprintf("azure-%s.tar.gz", stdruntime.GOARCH), file, dir); err != nil { + if err = tar(fmt.Sprintf("azure-%s.tar.gz", arch), file, dir); err != nil { return err } case "digital-ocean": - if err = tar(fmt.Sprintf("digital-ocean-%s.tar.gz", stdruntime.GOARCH), file, dir); err != nil { + if err = tar(fmt.Sprintf("digital-ocean-%s.tar.gz", arch), file, dir); err != nil { return err } case "gcp": - if err = tar(fmt.Sprintf("gcp-%s.tar.gz", stdruntime.GOARCH), file, dir); err != nil { + if err = tar(fmt.Sprintf("gcp-%s.tar.gz", arch), file, dir); err != nil { return err } case "openstack": - if err = tar(fmt.Sprintf("openstack-%s.tar.gz", stdruntime.GOARCH), file, dir); err != nil { + if err = tar(fmt.Sprintf("openstack-%s.tar.gz", arch), file, dir); err != nil { return err } case "vmware": - if err = ova.CreateOVAFromRAW(name, img, outputArg); err != nil { + if err = ova.CreateOVAFromRAW(name, img, outputArg, arch); err != nil { return err } case "metal": if options.Board != constants.BoardNone { - name := fmt.Sprintf("metal-%s-%s.img", options.Board, stdruntime.GOARCH) + name := fmt.Sprintf("metal-%s-%s.img", options.Board, arch) file = filepath.Join(outputArg, name) @@ -168,7 +167,7 @@ func finalize(platform runtime.Platform, img string) (err error) { break } - name := fmt.Sprintf("metal-%s.tar.gz", stdruntime.GOARCH) + name := fmt.Sprintf("metal-%s.tar.gz", arch) if err = tar(name, file, dir); err != nil { return err diff --git a/cmd/installer/cmd/iso.go b/cmd/installer/cmd/iso.go index ddfcf776ff..0597bdbfaa 100644 --- a/cmd/installer/cmd/iso.go +++ b/cmd/installer/cmd/iso.go @@ -11,7 +11,6 @@ import ( "log" "os" "path/filepath" - "runtime" "github.com/spf13/cobra" @@ -58,8 +57,8 @@ func runISOCmd() error { } files := map[string]string{ - "/usr/install/vmlinuz": "/mnt/boot/vmlinuz", - "/usr/install/initramfs.xz": "/mnt/boot/initramfs.xz", + fmt.Sprintf("/usr/install/%s/vmlinuz", options.Arch): "/mnt/boot/vmlinuz", + fmt.Sprintf("/usr/install/%s/initramfs.xz", options.Arch): "/mnt/boot/initramfs.xz", } for src, dest := range files { @@ -103,7 +102,7 @@ func runISOCmd() error { log.Println("creating ISO") - out := fmt.Sprintf("/tmp/talos-%s.iso", runtime.GOARCH) + out := fmt.Sprintf("/tmp/talos-%s.iso", options.Arch) if err := pkg.CreateISO(out, "/mnt"); err != nil { return err diff --git a/cmd/installer/cmd/root.go b/cmd/installer/cmd/root.go index 900733ab3f..4cd636a027 100644 --- a/cmd/installer/cmd/root.go +++ b/cmd/installer/cmd/root.go @@ -7,6 +7,7 @@ package cmd import ( "fmt" "os" + "runtime" "github.com/spf13/cobra" @@ -36,6 +37,7 @@ func init() { rootCmd.PersistentFlags().StringVar(&options.ConfigSource, "config", "", "The value of "+constants.KernelParamConfig) rootCmd.PersistentFlags().StringVar(&options.Disk, "disk", "", "The path to the disk to install to") rootCmd.PersistentFlags().StringVar(&options.Platform, "platform", "", "The value of "+constants.KernelParamPlatform) + rootCmd.PersistentFlags().StringVar(&options.Arch, "arch", runtime.GOARCH, "The target architecture") rootCmd.PersistentFlags().StringVar(&options.Board, "board", constants.BoardNone, "The value of "+constants.KernelParamBoard) rootCmd.PersistentFlags().StringArrayVar(&options.ExtraKernelArgs, "extra-kernel-arg", []string{}, "Extra argument to pass to the kernel") rootCmd.PersistentFlags().BoolVar(&options.Bootloader, "bootloader", true, "Install a booloader to the specified disk") diff --git a/cmd/installer/pkg/install/install.go b/cmd/installer/pkg/install/install.go index 6e5f0e5ea6..1a3feaf81f 100644 --- a/cmd/installer/pkg/install/install.go +++ b/cmd/installer/pkg/install/install.go @@ -29,6 +29,7 @@ type Options struct { ConfigSource string Disk string Platform string + Arch string Board string ExtraKernelArgs []string Bootloader bool @@ -92,6 +93,7 @@ func NewInstaller(cmdline *procfs.Cmdline, seq runtime.Sequence, opts *Options) options: opts, bootloader: &grub.Grub{ BootDisk: opts.Disk, + Arch: opts.Arch, }, } diff --git a/cmd/installer/pkg/install/manifest.go b/cmd/installer/pkg/install/manifest.go index 945f9b0dfe..da0b371cba 100644 --- a/cmd/installer/pkg/install/manifest.go +++ b/cmd/installer/pkg/install/manifest.go @@ -118,11 +118,11 @@ func NewManifest(label string, sequence runtime.Sequence, bootPartitionFound boo PreserveContents: bootPartitionFound, Assets: []*Asset{ { - Source: constants.KernelAssetPath, + Source: fmt.Sprintf(constants.KernelAssetPath, opts.Arch), Destination: filepath.Join(constants.BootMountPoint, label, constants.KernelAsset), }, { - Source: constants.InitramfsAssetPath, + Source: fmt.Sprintf(constants.InitramfsAssetPath, opts.Arch), Destination: filepath.Join(constants.BootMountPoint, label, constants.InitramfsAsset), }, }, diff --git a/cmd/installer/pkg/ova/ova.go b/cmd/installer/pkg/ova/ova.go index 79c59084c1..5ed78f4657 100644 --- a/cmd/installer/pkg/ova/ova.go +++ b/cmd/installer/pkg/ova/ova.go @@ -12,7 +12,6 @@ import ( "io/ioutil" "os" "path/filepath" - "runtime" "strings" "text/template" @@ -132,7 +131,7 @@ const ovfTpl = ` // CreateOVAFromRAW creates an OVA from a RAW disk. //nolint:gocyclo -func CreateOVAFromRAW(name, src, out string) (err error) { +func CreateOVAFromRAW(name, src, out, arch string) (err error) { dir, err := ioutil.TempDir("/tmp", "talos") if err != nil { return err @@ -187,7 +186,7 @@ func CreateOVAFromRAW(name, src, out string) (err error) { return err } - if _, err = cmd.Run("tar", "-cvf", filepath.Join(out, fmt.Sprintf("vmware-%s.ova", runtime.GOARCH)), "-C", dir, name+".ovf", name+".mf", name+".vmdk"); err != nil { + if _, err = cmd.Run("tar", "-cvf", filepath.Join(out, fmt.Sprintf("vmware-%s.ova", arch)), "-C", dir, name+".ovf", name+".mf", name+".vmdk"); err != nil { return err } diff --git a/internal/app/machined/pkg/runtime/v1alpha1/board/bananapi_m64/bananapi_m64.go b/internal/app/machined/pkg/runtime/v1alpha1/board/bananapi_m64/bananapi_m64.go index be8c148ce7..3edb3d5825 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/board/bananapi_m64/bananapi_m64.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/board/bananapi_m64/bananapi_m64.go @@ -20,7 +20,7 @@ import ( ) var ( - bin = fmt.Sprintf("/usr/install/u-boot/%s/u-boot-sunxi-with-spl.bin", constants.BoardBananaPiM64) + bin = fmt.Sprintf("/usr/install/arm64/u-boot/%s/u-boot-sunxi-with-spl.bin", constants.BoardBananaPiM64) off int64 = 1024 * 8 dtb = "/dtb/allwinner/sun50i-a64-bananapi-m64.dtb" ) @@ -74,7 +74,7 @@ func (b *BananaPiM64) Install(disk string) (err error) { return err } - src := "/usr/install" + dtb + src := "/usr/install/arm64" + dtb dst := "/boot/EFI" + dtb err = os.MkdirAll(filepath.Dir(dst), 0o600) diff --git a/internal/app/machined/pkg/runtime/v1alpha1/board/libretech_all_h3_cc_h5/libretech_all_h3_cc_h5.go b/internal/app/machined/pkg/runtime/v1alpha1/board/libretech_all_h3_cc_h5/libretech_all_h3_cc_h5.go index 72e263d376..7c6df20194 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/board/libretech_all_h3_cc_h5/libretech_all_h3_cc_h5.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/board/libretech_all_h3_cc_h5/libretech_all_h3_cc_h5.go @@ -20,7 +20,7 @@ import ( ) var ( - bin = fmt.Sprintf("/usr/install/u-boot/%s/u-boot-sunxi-with-spl.bin", constants.BoardLibretechAllH3CCH5) + bin = fmt.Sprintf("/usr/install/arm64/u-boot/%s/u-boot-sunxi-with-spl.bin", constants.BoardLibretechAllH3CCH5) off int64 = 1024 * 8 dtb = "/dtb/allwinner/sun50i-h5-libretech-all-h3-cc.dtb" ) @@ -71,7 +71,7 @@ func (l *LibretechAllH3CCH5) Install(disk string) (err error) { return err } - src := "/usr/install" + dtb + src := "/usr/install/arm64" + dtb dst := "/boot/EFI" + dtb err = os.MkdirAll(filepath.Dir(dst), 0o600) diff --git a/internal/app/machined/pkg/runtime/v1alpha1/board/rock64/rock64.go b/internal/app/machined/pkg/runtime/v1alpha1/board/rock64/rock64.go index b4a0a2047a..0634a2b8fd 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/board/rock64/rock64.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/board/rock64/rock64.go @@ -20,7 +20,7 @@ import ( ) var ( - bin = fmt.Sprintf("/usr/install/u-boot/%s/u-boot-rockchip.bin", constants.BoardRock64) + bin = fmt.Sprintf("/usr/install/arm64/u-boot/%s/u-boot-rockchip.bin", constants.BoardRock64) off int64 = 512 * 64 dtb = "/dtb/rockchip/rk3328-rock64.dtb" ) @@ -71,7 +71,7 @@ func (r *Rock64) Install(disk string) (err error) { return err } - src := "/usr/install" + dtb + src := "/usr/install/arm64" + dtb dst := "/boot/EFI" + dtb err = os.MkdirAll(filepath.Dir(dst), 0o600) diff --git a/internal/app/machined/pkg/runtime/v1alpha1/board/rockpi4/rockpi4.go b/internal/app/machined/pkg/runtime/v1alpha1/board/rockpi4/rockpi4.go index 3ebb1d93fe..1bc0e21785 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/board/rockpi4/rockpi4.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/board/rockpi4/rockpi4.go @@ -20,7 +20,7 @@ import ( ) var ( - bin = fmt.Sprintf("/usr/install/u-boot/%s/u-boot-rockchip.bin", constants.BoardRockpi4) + bin = fmt.Sprintf("/usr/install/arm64/u-boot/%s/u-boot-rockchip.bin", constants.BoardRockpi4) off int64 = 512 * 64 dtb = "/dtb/rockchip/rk3399-rock-pi-4c.dtb" ) @@ -69,7 +69,7 @@ func (r *Rockpi4) Install(disk string) (err error) { return err } - src := "/usr/install" + dtb + src := "/usr/install/arm64" + dtb dst := "/boot/EFI" + dtb err = os.MkdirAll(filepath.Dir(dst), 0o600) diff --git a/internal/app/machined/pkg/runtime/v1alpha1/board/rpi_4/rpi_4.go b/internal/app/machined/pkg/runtime/v1alpha1/board/rpi_4/rpi_4.go index 9953bb47a4..5215f83dc2 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/board/rpi_4/rpi_4.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/board/rpi_4/rpi_4.go @@ -30,12 +30,12 @@ func (r *RPi4) Name() string { // Install implements the runtime.Board. func (r *RPi4) Install(disk string) (err error) { - err = copy.Dir("/usr/install/raspberrypi-firmware/boot", "/boot/EFI") + err = copy.Dir("/usr/install/arm64/raspberrypi-firmware/boot", "/boot/EFI") if err != nil { return err } - err = copy.File("/usr/install/u-boot/rpi_4/u-boot.bin", "/boot/EFI/u-boot.bin") + err = copy.File("/usr/install/arm64/u-boot/rpi_4/u-boot.bin", "/boot/EFI/u-boot.bin") if err != nil { return err } diff --git a/internal/app/machined/pkg/runtime/v1alpha1/bootloader/grub/grub.go b/internal/app/machined/pkg/runtime/v1alpha1/bootloader/grub/grub.go index 85d8800fe9..45cefdb752 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/bootloader/grub/grub.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/bootloader/grub/grub.go @@ -60,9 +60,15 @@ menuentry "{{ $label.Root }}" { {{ end }} ` +const ( + amd64 = "amd64" + arm64 = "arm64" +) + // Grub represents the grub bootloader. type Grub struct { BootDisk string + Arch string } // Labels implements the Bootloader interface. @@ -135,12 +141,18 @@ func (g *Grub) Install(fallback string, config interface{}, sequence runtime.Seq loopDevice := strings.HasPrefix(blk, "/dev/loop") - // default: run for GRUB default platform - platforms := []string{""} + var platforms []string - if goruntime.GOARCH == "amd64" && loopDevice { - // building cloud image for amd64, install both BIOS & UEFI GRUB + switch g.Arch { + case amd64: platforms = []string{"x86_64-efi", "i386-pc"} + case arm64: + platforms = []string{"arm64-efi"} + } + + if goruntime.GOARCH == amd64 && g.Arch == amd64 && !loopDevice { + // let grub choose the platform automatically if not building an image + platforms = []string{""} } for _, platform := range platforms { diff --git a/pkg/machinery/constants/constants.go b/pkg/machinery/constants/constants.go index bc4b979cca..77896f61e9 100644 --- a/pkg/machinery/constants/constants.go +++ b/pkg/machinery/constants/constants.go @@ -325,7 +325,7 @@ const ( KernelAssetWithArch = "vmlinuz-" + ArchVariable // KernelAssetPath is the path to the kernel on disk. - KernelAssetPath = "/usr/install/" + KernelAsset + KernelAssetPath = "/usr/install/%s/" + KernelAsset // InitramfsAsset defines a well known name for our initramfs filename. InitramfsAsset = "initramfs.xz" @@ -334,7 +334,7 @@ const ( InitramfsAssetWithArch = "initramfs-" + ArchVariable + ".xz" // InitramfsAssetPath is the path to the initramfs on disk. - InitramfsAssetPath = "/usr/install/" + InitramfsAsset + InitramfsAssetPath = "/usr/install/%s/" + InitramfsAsset // RootfsAsset defines a well known name for our rootfs filename. RootfsAsset = "rootfs.sqsh" diff --git a/pkg/provision/providers/qemu/preflight.go b/pkg/provision/providers/qemu/preflight.go index fbe03bd1b4..25543c5934 100644 --- a/pkg/provision/providers/qemu/preflight.go +++ b/pkg/provision/providers/qemu/preflight.go @@ -76,6 +76,10 @@ func (check *preflightCheckContext) qemuExecutable(ctx context.Context) error { func (check *preflightCheckContext) checkFlashImages(ctx context.Context) error { for _, flashImage := range check.arch.PFlash(check.options.UEFIEnabled) { + if len(flashImage.SourcePaths) == 0 { + continue + } + found := false for _, path := range flashImage.SourcePaths {