[PATCH 4/5] guestfs: add ARM64 support with cross-architecture image customization
Daniel Gomez <[email protected]>
| Newsgroups | dev.linux.lists.kdevops |
|---|---|
| Message-ID | <[email protected]> |
From: Daniel Gomez <[email protected]> Add ARM64 libguestfs support with architecture detection. Supports both same-architecture (full customization) and cross-architecture (firstboot-only) scenarios for flexible dev environments. * Add ARM64 configuration and target detection * Implement conditional virt-customize logic based on host/guest architecture * Same arch: Full kdevops user setup via --commands-from-file * Cross arch: Limited firstboot commands due to binary compatibility * Update libvirt templates and node generation for ARM64 Enables x86_64<->ARM64 development workflows while maintaining full functionality for native ARM64->ARM64 and x86_64->x86_64 scenarios. Generated-by: Claude AI Signed-off-by: Daniel Gomez <[email protected]> --- kconfigs/Kconfig.guestfs | 18 ++++++--- kconfigs/Kconfig.libvirt | 14 ++++++- kconfigs/arch/Kconfig | 3 ++ playbooks/roles/base_image/tasks/custom-image.yml | 44 +++++++++++++++++++++- playbooks/roles/gen_nodes/tasks/main.yml | 2 +- .../roles/gen_nodes/templates/guestfs_virt.j2.xml | 4 +- scripts/gen-nodes.Makefile | 4 ++ 7 files changed, 76 insertions(+), 13 deletions(-) diff --git a/kconfigs/Kconfig.guestfs b/kconfigs/Kconfig.guestfs index d1e922a6..52506a3b 100644 --- a/kconfigs/Kconfig.guestfs +++ b/kconfigs/Kconfig.guestfs @@ -30,9 +30,12 @@ config GUESTFS_CUSTOM_RAW_IMAGE_URL depends on GUESTFS_HAS_CUSTOM_RAW_IMAGE_URL string output yaml - default "https://cloud.debian.org/images/cloud/trixie/daily/latest/debian-13-generic-amd64-daily.raw" if GUESTFS_DEBIAN_TRIXIE_GENERIC_AMD64 - default "https://cloud.debian.org/images/cloud/trixie/daily/latest/debian-13-genericcloud-amd64-daily.raw" if GUESTFS_DEBIAN_TRIXIE_GENERIC_CLOUD_AMD64 - default "https://cloud.debian.org/images/cloud/trixie/daily/latest/debian-13-nocloud-amd64-daily.raw" if GUESTFS_DEBIAN_TRIXIE_NOCLOUD_AMD64 + default "https://cloud.debian.org/images/cloud/trixie/daily/latest/debian-13-generic-amd64-daily.raw" if GUESTFS_DEBIAN_TRIXIE_GENERIC_AMD64 && TARGET_ARCH_X86_64 + default "https://cloud.debian.org/images/cloud/trixie/daily/latest/debian-13-generic-arm64-daily.raw" if GUESTFS_DEBIAN_TRIXIE_GENERIC_AMD64 && TARGET_ARCH_ARM64 + default "https://cloud.debian.org/images/cloud/trixie/daily/latest/debian-13-genericcloud-amd64-daily.raw" if GUESTFS_DEBIAN_TRIXIE_GENERIC_CLOUD_AMD64 && TARGET_ARCH_X86_64 + default "https://cloud.debian.org/images/cloud/trixie/daily/latest/debian-13-genericcloud-arm64-daily.raw" if GUESTFS_DEBIAN_TRIXIE_GENERIC_CLOUD_AMD64 && TARGET_ARCH_ARM64 + default "https://cloud.debian.org/images/cloud/trixie/daily/latest/debian-13-nocloud-amd64-daily.raw" if GUESTFS_DEBIAN_TRIXIE_NOCLOUD_AMD64 && TARGET_ARCH_X86_64 + default "https://cloud.debian.org/images/cloud/trixie/daily/latest/debian-13-nocloud-arm64-daily.raw" if GUESTFS_DEBIAN_TRIXIE_NOCLOUD_AMD64 && TARGET_ARCH_ARM64 config GUESTFS_HAS_CUSTOM_RAW_IMAGE_SHA512SUMS bool @@ -177,9 +180,12 @@ config GUESTFS_DEBIAN_HOST_GUEST_MATCH config GUESTFS_DEBIAN_IMAGE_NAME string - default "debian-13-generic-amd64-daily" if GUESTFS_DEBIAN_TRIXIE_GENERIC_AMD64 - default "debian-13-genericcloud-amd64-daily" if GUESTFS_DEBIAN_TRIXIE_GENERIC_CLOUD_AMD64 - default "debian-13-nocloud-amd64-daily" if GUESTFS_DEBIAN_TRIXIE_NOCLOUD_AMD64 + default "debian-13-generic-amd64-daily" if GUESTFS_DEBIAN_TRIXIE_GENERIC_AMD64 && TARGET_ARCH_X86_64 + default "debian-13-generic-arm64-daily" if GUESTFS_DEBIAN_TRIXIE_GENERIC_AMD64 && TARGET_ARCH_ARM64 + default "debian-13-genericcloud-amd64-daily" if GUESTFS_DEBIAN_TRIXIE_GENERIC_CLOUD_AMD64 && TARGET_ARCH_X86_64 + default "debian-13-genericcloud-arm64-daily" if GUESTFS_DEBIAN_TRIXIE_GENERIC_CLOUD_AMD64 && TARGET_ARCH_ARM64 + default "debian-13-nocloud-amd64-daily" if GUESTFS_DEBIAN_TRIXIE_NOCLOUD_AMD64 && TARGET_ARCH_X86_64 + default "debian-13-nocloud-arm64-daily" if GUESTFS_DEBIAN_TRIXIE_NOCLOUD_AMD64 && TARGET_ARCH_ARM64 default "debian-12" if GUESTFS_DEBIAN_BUSTER config GUESTFS_DEBIAN_BOX_SHORT diff --git a/kconfigs/Kconfig.libvirt b/kconfigs/Kconfig.libvirt index 961276cc..25cb703f 100644 --- a/kconfigs/Kconfig.libvirt +++ b/kconfigs/Kconfig.libvirt @@ -287,8 +287,12 @@ endif # QEMU_BUILD config QEMU_BIN_PATH_LIBVIRT string "QEMU binary path to use" - default "/usr/local/bin/qemu-system-x86_64" if QEMU_USE_DEVELOPMENT_VERSION - default "/usr/bin/qemu-system-x86_64" if !QEMU_USE_DEVELOPMENT_VERSION + default "/usr/local/bin/qemu-system-x86_64" if QEMU_USE_DEVELOPMENT_VERSION && TARGET_ARCH_X86_64 + default "/usr/local/bin/qemu-system-aarch64" if QEMU_USE_DEVELOPMENT_VERSION && TARGET_ARCH_ARM64 + default "/usr/local/bin/qemu-system-ppc64le" if QEMU_USE_DEVELOPMENT_VERSION && TARGET_ARCH_PPC64LE + default "/usr/bin/qemu-system-x86_64" if !QEMU_USE_DEVELOPMENT_VERSION && TARGET_ARCH_X86_64 + default "/usr/bin/qemu-system-aarch64" if !QEMU_USE_DEVELOPMENT_VERSION && TARGET_ARCH_ARM64 + default "/usr/bin/qemu-system-ppc64le" if !QEMU_USE_DEVELOPMENT_VERSION && TARGET_ARCH_PPC64LE config QEMU_INSTALL_DIR_LIBVIRT string "Path to install QEMU" @@ -536,6 +540,12 @@ config LIBVIRT_MACHINE_TYPE_VIRT endchoice +config LIBVIRT_MACHINE_TYPE_STRING + string + output yaml + default "q35" if LIBVIRT_MACHINE_TYPE_Q35 + default "virt" if LIBVIRT_MACHINE_TYPE_VIRT + config LIBVIRT_HOST_PASSTHROUGH bool "Use CPU host-passthrough" default y diff --git a/kconfigs/arch/Kconfig b/kconfigs/arch/Kconfig index 4c0beaf7..cd049f7c 100644 --- a/kconfigs/arch/Kconfig +++ b/kconfigs/arch/Kconfig @@ -11,6 +11,7 @@ choice config TARGET_ARCH_X86_64 bool "x86_64" + output yaml help Enabling this will enable all features / workflows which depend on the x86_64 architecture. @@ -18,6 +19,7 @@ config TARGET_ARCH_X86_64 config TARGET_ARCH_ARM64 bool "arm64" select HAVE_ARCH_64K_PAGES + output yaml help Enabling this will enable all features / workflows which depend on the arm64 architecture. @@ -25,6 +27,7 @@ config TARGET_ARCH_ARM64 config TARGET_ARCH_PPC64LE bool "ppc64le" select HAVE_ARCH_64K_PAGES + output yaml help Enabling this will enable all features / workflows which depend on the ppc64le architecture. diff --git a/playbooks/roles/base_image/tasks/custom-image.yml b/playbooks/roles/base_image/tasks/custom-image.yml index 204e3099..bcf35933 100644 --- a/playbooks/roles/base_image/tasks/custom-image.yml +++ b/playbooks/roles/base_image/tasks/custom-image.yml @@ -172,7 +172,7 @@ when: - not sentinel_stat.stat.exists - - name: Customize the downloaded image with kdevops user and settings + - name: Customize the downloaded image with kdevops user and settings (same architecture) become: true become_method: ansible.builtin.sudo ansible.builtin.command: @@ -185,12 +185,33 @@ when: - libvirt_uri_system|bool - not sentinel_stat.stat.exists + - not (target_arch_arm64|default(false) and ansible_facts['architecture'] != 'aarch64') + - not (target_arch_x86_64|default(false) and ansible_facts['architecture'] == 'aarch64') + + - name: Customize the downloaded image with kdevops user and settings (cross-architecture using firstboot only) + become: true + become_method: ansible.builtin.sudo + ansible.builtin.command: + argv: + - "virt-customize" + - "-a" + - "{{ custom_image }}" + - "--firstboot-command" + - "systemctl stop ssh && systemctl start ssh" + - "--firstboot-command" + - "apt update && apt upgrade --yes || yum update -y || true" + when: + - libvirt_uri_system|bool + - not sentinel_stat.stat.exists + - >- + (target_arch_arm64|default(false) and ansible_facts['architecture'] != 'aarch64') or + (target_arch_x86_64|default(false) and ansible_facts['architecture'] == 'aarch64') vars: ansible_callback_diy_runner_on_ok_msg: | $ {{ ansible_callback_diy.result.output.cmd | join(' ') }} {{ ansible_callback_diy.result.output.stdout | default('') }} - - name: Customize the downloaded image with kdevops user and settings (non-root) + - name: Customize the downloaded image with kdevops user and settings (non-root, same architecture) ansible.builtin.command: argv: - "virt-customize" @@ -201,6 +222,25 @@ when: - not libvirt_uri_system|bool - not sentinel_stat.stat.exists + - not (target_arch_arm64|default(false) and ansible_facts['architecture'] != 'aarch64') + - not (target_arch_x86_64|default(false) and ansible_facts['architecture'] == 'aarch64') + + - name: Customize the downloaded image with kdevops user and settings (non-root, cross-architecture) + ansible.builtin.command: + argv: + - "virt-customize" + - "-a" + - "{{ custom_image }}" + - "--firstboot-command" + - "systemctl stop ssh && systemctl start ssh" + - "--firstboot-command" + - "apt update && apt upgrade --yes || yum update -y || true" + when: + - not libvirt_uri_system|bool + - not sentinel_stat.stat.exists + - >- + (target_arch_arm64|default(false) and ansible_facts['architecture'] != 'aarch64') or + (target_arch_x86_64|default(false) and ansible_facts['architecture'] == 'aarch64') vars: ansible_callback_diy_runner_on_ok_msg: | $ {{ ansible_callback_diy.result.output.cmd | join(' ') }} diff --git a/playbooks/roles/gen_nodes/tasks/main.yml b/playbooks/roles/gen_nodes/tasks/main.yml index 60e7f694..c3397a7d 100644 --- a/playbooks/roles/gen_nodes/tasks/main.yml +++ b/playbooks/roles/gen_nodes/tasks/main.yml @@ -993,7 +993,7 @@ hostname: "{{ item.name }}" guestidx: "{{ idx }}" ansible.builtin.template: - src: "guestfs_{{ libvirt_machine_type }}.j2.xml" + src: "guestfs_{{ libvirt_machine_type_string }}.j2.xml" dest: "{{ topdir_path }}/guestfs/{{ hostname }}/{{ hostname }}.xml" force: true mode: "0644" diff --git a/playbooks/roles/gen_nodes/templates/guestfs_virt.j2.xml b/playbooks/roles/gen_nodes/templates/guestfs_virt.j2.xml index 29818ea8..e57e6fc7 100644 --- a/playbooks/roles/gen_nodes/templates/guestfs_virt.j2.xml +++ b/playbooks/roles/gen_nodes/templates/guestfs_virt.j2.xml @@ -4,12 +4,12 @@ <currentMemory unit='MiB'>{{ libvirt_mem_mb }}</currentMemory> <vcpu placement='static'>{{ libvirt_vcpus_count }}</vcpu> <os firmware='efi'> - <type arch='aarch64' machine='virt-8.1'>hvm</type> + <type arch='aarch64' machine='virt'>hvm</type> <firmware> <feature enabled='no' name='enrolled-keys'/> <feature enabled='no' name='secure-boot'/> </firmware> - <loader readonly='yes' type='pflash' format='qcow2'>/usr/share/edk2/aarch64/QEMU_EFI-silent-pflash.qcow2</loader> + <loader readonly='yes' type='pflash'>/usr/share/AAVMF/AAVMF_CODE.fd</loader> <boot dev='hd'/> </os> <features> diff --git a/scripts/gen-nodes.Makefile b/scripts/gen-nodes.Makefile index 0be012d1..8ca11d60 100644 --- a/scripts/gen-nodes.Makefile +++ b/scripts/gen-nodes.Makefile @@ -13,6 +13,10 @@ ifeq (y,$(CONFIG_QEMU_BUILD)) GEN_NODES_EXTRA_ARGS += qemu_bin_path='$(subst ",,$(CONFIG_QEMU_INSTALL_DIR_LIBVIRT))/qemu-system-x86_64' endif + ifeq (y,$(CONFIG_TARGET_ARCH_ARM64)) + GEN_NODES_EXTRA_ARGS += qemu_bin_path='$(subst ",,$(CONFIG_QEMU_INSTALL_DIR_LIBVIRT))/qemu-system-aarch64' + endif + ifeq (y,$(CONFIG_TARGET_ARCH_PPC64LE)) GEN_NODES_EXTRA_ARGS += qemu_bin_path='$(subst ",,$(CONFIG_QEMU_INSTALL_DIR_LIBVIRT))/qemu-system-ppc64' endif -- 2.50.1