Skip to content

Commit 641bbad

Browse files
committed
feat: add arm64 support for iPXE and image
Signed-off-by: synthe102 <leonard@suslian.engineer>
1 parent a058212 commit 641bbad

File tree

10 files changed

+85
-24
lines changed

10 files changed

+85
-24
lines changed

.github/workflows/ironic-image-build-pr.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,16 @@ on:
66

77
jobs:
88
build:
9-
runs-on: ubuntu-latest
9+
runs-on: ${{ matrix.platform == 'linux/amd64' && 'ubuntu-latest' || matrix.platform == 'linux/arm64' && 'ubuntu-24.04-arm'}}
1010
strategy:
1111
fail-fast: false
1212
matrix:
1313
centos_version:
1414
- stream9
1515
- stream10
16+
platform:
17+
- linux/amd64
18+
- linux/arm64
1619

1720
steps:
1821
- name: Checkout repository
@@ -34,6 +37,7 @@ jobs:
3437
file: ./Dockerfile
3538
push: false
3639
tags: ironic:${{ matrix.centos_version }}
40+
platforms: ${{ matrix.platform }}
3741
build-args: |
3842
BASE_IMAGE=${{ steps.base-image.outputs.base_image }}
3943
cache-from: type=gha,scope=${{ matrix.centos_version }}

Dockerfile

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,16 @@ ARG BASE_IMAGE=quay.io/centos/centos:stream9
77
FROM $BASE_IMAGE AS ironic-builder
88

99
ARG IPXE_COMMIT_HASH=e965f179e1654103eca33feed7a9cc4c51d91be6
10-
11-
RUN --mount=type=cache,target=/var/cache/dnf \
12-
echo "install_weak_deps=False" >> /etc/dnf/dnf.conf && \
13-
echo "tsflags=nodocs" >> /etc/dnf/dnf.conf && \
14-
echo "keepcache=1" >> /etc/dnf/dnf.conf && \
15-
dnf install -y gcc git make xz-devel
10+
ARG TARGETARCH
1611

1712
WORKDIR /tmp
1813

19-
RUN git clone https://github.com/ipxe/ipxe.git && \
20-
cd ipxe && \
21-
git reset --hard $IPXE_COMMIT_HASH && \
22-
cd src && \
23-
ARCH=$(uname -m | sed 's/aarch/arm/') && \
24-
# NOTE(elfosardo): warning should not be treated as errors by default
25-
NO_WERROR=1 make bin/undionly.kpxe "bin-$ARCH-efi/snponly.efi"
14+
COPY prepare-ipxe.sh /bin/
15+
RUN --mount=type=cache,target=/var/cache/dnf,sharing=locked \
16+
prepare-ipxe.sh
17+
18+
COPY build-ipxe.sh /bin/
19+
RUN build-ipxe.sh
2620

2721
COPY prepare-efi.sh /bin/
2822
RUN prepare-efi.sh centos
@@ -39,7 +33,10 @@ LABEL org.opencontainers.image.title="Metal3 Ironic Container"
3933
LABEL org.opencontainers.image.url="https://github.com/metal3-io/ironic-image"
4034
LABEL org.opencontainers.image.vendor="Metal3-io"
4135

36+
ARG TARGETARCH
37+
4238
ARG PKGS_LIST=main-packages-list.txt
39+
ARG ARCH_PKGS_LIST=main-packages-list-${TARGETARCH}.txt
4340
ARG EXTRA_PKGS_LIST
4441
ARG PATCH_LIST
4542

@@ -49,7 +46,7 @@ ARG IRONIC_SOURCE=7fe20fe31f0e184c68b7029e04acdb5d286fc4b2 # master
4946
ARG SUSHY_SOURCE
5047

5148
COPY sources /sources/
52-
COPY ${UPPER_CONSTRAINTS_FILE} ironic-packages-list ${PKGS_LIST} \
49+
COPY ${UPPER_CONSTRAINTS_FILE} ironic-packages-list ${PKGS_LIST} ${ARCH_PKGS_LIST} \
5350
${EXTRA_PKGS_LIST:-$PKGS_LIST} ${PATCH_LIST:-$PKGS_LIST} \
5451
/tmp/
5552
COPY ironic-config/inspector.ipxe.j2 ironic-config/httpd-ironic-api.conf.j2 \
@@ -58,12 +55,12 @@ COPY ironic-config/inspector.ipxe.j2 ironic-config/httpd-ironic-api.conf.j2 \
5855
COPY prepare-image.sh patch-image.sh configure-nonroot.sh /bin/
5956
COPY scripts/ /bin/
6057

61-
RUN --mount=type=cache,target=/var/cache/dnf \
58+
RUN --mount=type=cache,target=/var/cache/dnf,sharing=locked \
6259
prepare-image.sh && \
6360
rm -f /bin/prepare-image.sh
6461

6562
# IRONIC #
66-
COPY --from=ironic-builder /tmp/ipxe/src/bin/undionly.kpxe /tmp/ipxe/src/bin-x86_64-efi/snponly.efi /tftpboot/
63+
COPY --from=ironic-builder /tmp/ipxe/out/ /tftpboot/
6764
COPY --from=ironic-builder /tmp/uefi_esp*.img /templates/
6865

6966
COPY ironic-config/ironic.conf.j2 /etc/ironic/

build-ipxe.sh

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/usr/bin/bash
2+
3+
set -euxo pipefail
4+
5+
git clone https://github.com/ipxe/ipxe.git
6+
cd ipxe
7+
mkdir out
8+
git reset --hard "$IPXE_COMMIT_HASH"
9+
cd src
10+
11+
# Build iPXE binaries based on architecture
12+
if [[ "$TARGETARCH" == "amd64" ]]; then
13+
NO_WERROR=1 make bin/undionly.kpxe bin-x86_64-efi/snponly.efi
14+
NO_WERROR=1 make CROSS=aarch64-linux-gnu- bin-arm64-efi/snponly.efi
15+
elif [[ "$TARGETARCH" == "arm64" ]]; then
16+
NO_WERROR=1 make bin-arm64-efi/snponly.efi
17+
NO_WERROR=1 make CROSS=x86_64-linux-gnu- bin/undionly.kpxe bin-x86_64-efi/snponly.efi
18+
else
19+
echo "ERROR: Unsupported build architecture: $TARGETARCH"
20+
exit 1
21+
fi
22+
23+
cp bin/undionly.kpxe ../out/
24+
cp bin-x86_64-efi/snponly.efi ../out/snponly-x86_64.efi
25+
cp bin-arm64-efi/snponly.efi ../out/snponly-arm64.efi

ironic-config/dnsmasq.conf.j2

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,13 @@ dhcp-option=option:router,{{ env["GATEWAY_IP"] }}
3737
# Note: Need to test EFI booting
3838
dhcp-match=set:efi,option:client-arch,7
3939
dhcp-match=set:efi,option:client-arch,9
40-
dhcp-match=set:efi,option:client-arch,11
4140
# Client is (i)PXE booting on EFI machine
42-
dhcp-boot=tag:efi,/snponly.efi,{{ env.IRONIC_IP }}
41+
dhcp-boot=tag:efi,/snponly-x86_64.efi,{{ env.IRONIC_IP }}
42+
# Client is (i)PXE booting on arm64 EFI machine
43+
dhcp-match=set:efi-arm64,option:client-arch,11
44+
dhcp-boot=tag:efi-arm64,/snponly-arm64.efi,{{ env.IRONIC_IP }}
4345
# Client is running (i)PXE on BIOS machine
44-
dhcp-boot=tag:!efi,/undionly.kpxe,{{ env.IRONIC_IP }}
46+
dhcp-boot=tag:!efi,tag:!efi-arm64,/undionly.kpxe,{{ env.IRONIC_IP }}
4547
{%- if env.IPXE_TLS_SETUP != "true" %}
4648
dhcp-boot=tag:ipxe,http://{{ env.IRONIC_URL_HOST }}:{{ env.HTTP_PORT }}/boot.ipxe
4749
{% endif %}
@@ -55,7 +57,12 @@ ra-param={{ env.PROVISIONING_INTERFACE }},0,0
5557
dhcp-vendorclass=set:pxe6,enterprise:343,PXEClient
5658
dhcp-userclass=set:ipxe6,iPXE
5759
# Client is (i)PXE booting on EFI machine
58-
dhcp-option=tag:pxe6,option6:bootfile-url,tftp://{{ env.IRONIC_URL_HOST }}/snponly.efi
60+
dhcp-match=set:amd64,option:client-arch,7
61+
dhcp-match=set:amd64,option:client-arch,9
62+
dhcp-option=tag:pxe6,tag:amd64,option6:bootfile-url,tftp://{{ env.IRONIC_URL_HOST }}/snponly-x86_64.efi
63+
# Client is (i)PXE booting on arm64 EFI machine
64+
dhcp-match=set:arm64,option:client-arch,11
65+
dhcp-option=tag:pxe6,tag:arm64,option6:bootfile-url,tftp://{{ env.IRONIC_URL_HOST }}/snponly-arm64.efi
5966
# Client is running (i)PXE on BIOS machine
6067
dhcp-option=tag:!pxe6,option6:bootfile-url,tftp://{{ env.IRONIC_URL_HOST }}/undionly.kpxe
6168
{%- if env.IPXE_TLS_SETUP != "true" %}

main-packages-list-amd64.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
syslinux-nonlinux

main-packages-list-arm64.txt

Whitespace-only changes.

main-packages-list.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,5 @@ mod_ssl
99
procps
1010
qemu-img
1111
sqlite
12-
syslinux-nonlinux
1312
util-linux
1413
xorriso

prepare-image.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ getent passwd ironic > /dev/null || useradd -r -g ironic -u "${IRONIC_UID}" -s /
6262
dnf remove -y "${BUILD_DEPS[@]}"
6363

6464
xargs -rtd'\n' dnf install -y < /tmp/"${PKGS_LIST}"
65+
if [[ -s "/tmp/${ARCH_PKGS_LIST}" ]]; then
66+
xargs -rtd'\n' dnf install -y < /tmp/"${ARCH_PKGS_LIST}"
67+
fi
6568

6669
if [[ -n "${EXTRA_PKGS_LIST:-}" ]]; then
6770
if [[ -s "/tmp/${EXTRA_PKGS_LIST}" ]]; then

prepare-ipxe.sh

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/usr/bin/bash
2+
3+
set -euxo pipefail
4+
5+
echo "install_weak_deps=False" >> /etc/dnf/dnf.conf && \
6+
echo "tsflags=nodocs" >> /etc/dnf/dnf.conf && \
7+
echo "keepcache=1" >> /etc/dnf/dnf.conf && \
8+
dnf install -y epel-release && \
9+
dnf config-manager --set-disabled epel && \
10+
dnf install -y git make xz-devel
11+
12+
# Install appropriate gcc binaries based on build architecture
13+
if [[ "$TARGETARCH" == "amd64" ]]; then
14+
# On x86_64, we need native gcc for x86 builds and cross-compiler for arm64
15+
dnf install -y gcc && \
16+
dnf install --enablerepo=epel -y gcc-aarch64-linux-gnu gcc-c++-aarch64-linux-gnu
17+
elif [[ "$TARGETARCH" == "arm64" ]]; then
18+
# On arm64, we need native gcc for arm64 builds and cross-compiler for x86_64
19+
dnf install -y gcc && \
20+
dnf install --enablerepo=epel -y gcc-x86_64-linux-gnu gcc-c++-x86_64-linux-gnu
21+
else
22+
echo "ERROR: Unsupported build architecture: $TARGETARCH"
23+
exit 1
24+
fi

scripts/rundnsmasq

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@ mkdir -p /shared/tftpboot
2424
# Copy files to shared mount
2525
if [[ -r "${IPXE_CUSTOM_FIRMWARE_DIR}" ]]; then
2626
cp "${IPXE_CUSTOM_FIRMWARE_DIR}/undionly.kpxe" \
27-
"${IPXE_CUSTOM_FIRMWARE_DIR}/snponly.efi" \
27+
"${IPXE_CUSTOM_FIRMWARE_DIR}/snponly-x86_64.efi" \
28+
"${IPXE_CUSTOM_FIRMWARE_DIR}/snponly-arm64.efi" \
2829
"/shared/tftpboot"
2930
else
30-
cp /tftpboot/undionly.kpxe /tftpboot/snponly.efi /shared/tftpboot
31+
cp /tftpboot/undionly.kpxe /tftpboot/snponly-x86_64.efi /tftpboot/snponly-arm64.efi /shared/tftpboot
3132
fi
3233

3334
# Template and write dnsmasq.conf

0 commit comments

Comments
 (0)