diff --git a/hack/update-template-amazonlinux.sh b/hack/update-template-amazonlinux.sh new file mode 100755 index 00000000000..6f91ca1a21b --- /dev/null +++ b/hack/update-template-amazonlinux.sh @@ -0,0 +1,190 @@ +#!/usr/bin/env bash + +# SPDX-FileCopyrightText: Copyright The Lima Authors +# SPDX-License-Identifier: Apache-2.0 + +set -eu -o pipefail + +# Functions in this script assume error handling with 'set -e'. +# To ensure 'set -e' works correctly: +# - Use 'set +e' before assignments and '$(set -e; )' to capture output without exiting on errors. +# - Avoid calling functions directly in conditions to prevent disabling 'set -e'. +# - Use 'shopt -s inherit_errexit' (Bash 4.4+) to avoid repeated 'set -e' in all '$(...)'. +shopt -s inherit_errexit || error_exit "inherit_errexit not supported. Please use bash 4.4 or later." + +function amazonlinux_print_help() { + cat <... + +Description: + This script updates the Amazon Linux 2023 image location in the specified templates. + Image location format: + https://cdn.amazonlinux.com/al2023/os-images/// + + Latest version information is fetched from: + https://cdn.amazonlinux.com/al2023/os-images/latest/ + +Examples: + Update the Amazon Linux 2023 image location in templates/**.yaml: + $ $(basename "${BASH_SOURCE[0]}") templates/**.yaml + +Flags: + -h, --help Print this help message +HELP +} + +function amazonlinux_cache_key_for_image_kernel() { + local location=$1 + case "${location}" in + https://cdn.amazonlinux.com/al2023/os-images/*) ;; + *) return 1 ;; + esac + # Cache key based on architecture and variant derived from location + # We use a simple heuristic: file path components. + # The URL structure is .../os-images///... + # We want a key that represents "amazonlinux:al2023:" + local folder + if [[ ${location} == *"/kvm-arm64/"* ]]; then + folder="kvm-arm64" + elif [[ ${location} == *"/kvm/"* ]]; then + folder="kvm" + else + return 1 + fi + echo "amazonlinux:al2023:${folder}" +} + +function amazonlinux_image_entry_for_image_kernel() { + local location=$1 + case "${location}" in + https://cdn.amazonlinux.com/al2023/os-images/*) ;; + *) return 1 ;; + esac + + local latest_url + # Get the redirect URL to find the latest version + latest_url=$(curl -Ls -o /dev/null -w '%{url_effective}' https://cdn.amazonlinux.com/al2023/os-images/latest/) + local version + version=$(basename "${latest_url}") + + local arch folder + if [[ ${location} == *"x86_64"* ]]; then + # shellcheck disable=SC2034 + arch="x86_64" + folder="kvm" + elif [[ ${location} == *"arm64"* ]] || [[ ${location} == *"aarch64"* ]]; then + # shellcheck disable=SC2034 + arch="aarch64" + folder="kvm-arm64" + else + error_exit "Unknown arch for amazonlinux location: ${location}" + fi + + local base_url="https://cdn.amazonlinux.com/al2023/os-images/${version}/${folder}" + local checksums + checksums=$(download_to_cache "${base_url}/SHA256SUMS") + + local filename digest line + # Find the qcow2 file in SHA256SUMS + line=$(grep "\.qcow2$" "${checksums}" | head -n 1) + [[ -n ${line} ]] || error_exit "No qcow2 image found in ${base_url}/SHA256SUMS" + + # shellcheck disable=SC2034 + digest=$(echo "${line}" | awk '{print "sha256:"$1}') + filename=$(echo "${line}" | awk '{print $2}') + + # shellcheck disable=SC2034 + local location="${base_url}/${filename}" + + json_vars location arch digest +} + +# check if the script is executed or sourced +# shellcheck disable=SC1091 +if [[ ${BASH_SOURCE[0]} == "${0}" ]]; then + scriptdir=$(dirname "${BASH_SOURCE[0]}") + # shellcheck source=./cache-common-inc.sh + . "${scriptdir}/cache-common-inc.sh" + + # shellcheck source=/dev/null # avoid shellcheck hangs on source looping + . "${scriptdir}/update-template.sh" +else + # this script is sourced + if [[ -v SUPPORTED_DISTRIBUTIONS ]]; then + SUPPORTED_DISTRIBUTIONS+=("amazonlinux") + else + declare -a SUPPORTED_DISTRIBUTIONS=("amazonlinux") + fi + return 0 +fi + +declare -a templates=() +while [[ $# -gt 0 ]]; do + case "$1" in + -h | --help) + amazonlinux_print_help + exit 0 + ;; + -d | --debug) set -x ;; + *.yaml) templates+=("$1") ;; + *) + error_exit "Unknown argument: $1" + ;; + esac + shift +done + +if [[ ${#templates[@]} -eq 0 ]]; then + amazonlinux_print_help + exit 0 +fi + +declare -A image_entry_cache=() + +for template in "${templates[@]}"; do + echo "Processing ${template}" + # 1. extract location by parsing template + yq_filter=" + .images[] | [.location, .kernel.location, .kernel.cmdline] | @tsv + " + parsed=$(yq eval "${yq_filter}" "${template}") + + # 2. get the image location + arr=() + while IFS= read -r line; do arr+=("${line}"); done <<<"${parsed}" + locations=("${arr[@]}") + for ((index = 0; index < ${#locations[@]}; index++)); do + [[ ${locations[index]} != "null" ]] || continue + set -e + IFS=$'\t' read -r location _kernel_location _kernel_cmdline <<<"${locations[index]}" + set +e # Disable 'set -e' to avoid exiting on error for the next assignment. + cache_key=$( + set -e # Enable 'set -e' for the next command. + amazonlinux_cache_key_for_image_kernel "${location}" + ) # Check exit status separately to prevent disabling 'set -e' by using the function call in the condition. + # shellcheck disable=2181 + [[ $? -eq 0 ]] || continue + image_entry=$( + set -e # Enable 'set -e' for the next command. + if [[ -v image_entry_cache[${cache_key}] ]]; then + echo "${image_entry_cache[${cache_key}]}" + else + amazonlinux_image_entry_for_image_kernel "${location}" + fi + ) # Check exit status separately to prevent disabling 'set -e' by using the function call in the condition. + # shellcheck disable=2181 + [[ $? -eq 0 ]] || continue + set -e + image_entry_cache[${cache_key}]="${image_entry}" + if [[ -n ${image_entry} ]]; then + echo "${image_entry}" | jq + limactl edit --log-level error --set " + .images[${index}] = ${image_entry}| + (.images[${index}] | ..) style = \"double\" + " "${template}" + fi + done +done diff --git a/hack/update-template.sh b/hack/update-template.sh index df38ee92300..106b61bfad6 100755 --- a/hack/update-template.sh +++ b/hack/update-template.sh @@ -174,6 +174,8 @@ if [[ ${BASH_SOURCE[0]} == "${0}" ]]; then . "${scriptdir}/update-template-freebsd.sh" # shellcheck source=./update-template-macos.sh . "${scriptdir}/update-template-macos.sh" + # shellcheck source=./update-template-amazonlinux.sh + . "${scriptdir}/update-template-amazonlinux.sh" else # this script is sourced return 0 diff --git a/pkg/cidata/cidata.TEMPLATE.d/boot.Linux/04-amazonlinux-virtiofs.sh b/pkg/cidata/cidata.TEMPLATE.d/boot.Linux/04-amazonlinux-virtiofs.sh new file mode 100644 index 00000000000..f4900d73999 --- /dev/null +++ b/pkg/cidata/cidata.TEMPLATE.d/boot.Linux/04-amazonlinux-virtiofs.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +# SPDX-FileCopyrightText: Copyright The Lima Authors +# SPDX-License-Identifier: Apache-2.0 + +set -eux -o pipefail + +# Workaround for Amazon Linux 2023 +if [ -f /etc/os-release ] && grep -q "Amazon Linux" /etc/os-release; then + # 1. Create missing mount.virtiofs helper + if [ ! -e /sbin/mount.virtiofs ]; then + cat >/sbin/mount.virtiofs <<'EOF' +#!/bin/sh +exec mount -i -t virtiofs "$@" +EOF + chmod +x /sbin/mount.virtiofs + fi + + # Amazon Linux 2023 requires a workaround for virtiofs mounts. + # The mount.virtiofs helper script is missing, and cloud-init + # may fail to mount the filesystems. This creates the helper + # and manually mounts them. + USER_DATA="/var/lib/cloud/instance/user-data.txt" + if [ -f "${USER_DATA}" ]; then + # Parse all mount entries from user-data (mount0, mount1, ...) + MOUNT_ENTRIES=$(grep -E '^\s*-\s+\[mount[0-9]+,' "${USER_DATA}" || true) + if [ -n "${MOUNT_ENTRIES}" ]; then + echo "${MOUNT_ENTRIES}" | while IFS= read -r entry; do + MOUNT_TAG=$(echo "${entry}" | grep -oP 'mount\K[0-9]+') + MOUNT_POINT=$(echo "${entry}" | awk -F, '{print $2}' | tr -d '[:space:]') + if [ -n "${MOUNT_TAG}" ] && [ -n "${MOUNT_POINT}" ] && ! mountpoint -q "${MOUNT_POINT}"; then + mkdir -p "${MOUNT_POINT}" + mount -t virtiofs "mount${MOUNT_TAG}" "${MOUNT_POINT}" || true + fi + done + fi + fi +fi diff --git a/templates/README.md b/templates/README.md index 8d198b898e1..aaa2ddc4e5c 100644 --- a/templates/README.md +++ b/templates/README.md @@ -40,6 +40,7 @@ lima - [`almalinux-kitten-10`](./almalinux-kitten-10.yaml), `almalinux-kitten`: AlmaLinux Kitten 10 - [`alpine`](./alpine.yaml): ☆Alpine Linux - [`alpine-iso`](./alpine-iso.yaml): ☆Alpine Linux (ISO9660 image). Compatible with the `alpine` template used in Lima prior to v1.0. +- [`amazonlinux-2023`](./amazonlinux-2023.yaml): Amazon Linux 2023 - [`archlinux`](./archlinux.yaml): ☆Arch Linux - [`centos-stream-9`](./centos-stream-9.yaml), `centos-stream`: CentOS Stream 9 - [`centos-stream-10`](./centos-stream-10.yaml): CentOS Stream 10 diff --git a/templates/_images/amazonlinux-2023.yaml b/templates/_images/amazonlinux-2023.yaml new file mode 100644 index 00000000000..cf51b5061f0 --- /dev/null +++ b/templates/_images/amazonlinux-2023.yaml @@ -0,0 +1,9 @@ +# More information: https://docs.aws.amazon.com/linux/al2023/ug/outside-ec2-download.html + +images: +- location: "https://cdn.amazonlinux.com/al2023/os-images/2023.11.20260406.2/kvm/al2023-kvm-2023.11.20260406.2-kernel-6.1-x86_64.xfs.gpt.qcow2" + arch: "x86_64" + digest: "sha256:72e10d974e832d9b56b84e71fe6f2e22589c9c539cc38e6d00cd84177839e2e8" +- location: "https://cdn.amazonlinux.com/al2023/os-images/2023.11.20260406.2/kvm-arm64/al2023-kvm-2023.11.20260406.2-kernel-6.1-arm64.xfs.gpt.qcow2" + arch: "aarch64" + digest: "sha256:c012f9ecb88f377c49e4338c2c6f5702ca885a37e96118119ce67266d0a7524d" diff --git a/templates/amazonlinux-2023.yaml b/templates/amazonlinux-2023.yaml new file mode 100644 index 00000000000..f93d6f91b2f --- /dev/null +++ b/templates/amazonlinux-2023.yaml @@ -0,0 +1,5 @@ +minimumLimaVersion: 2.1.2 + +base: +- template:_images/amazonlinux-2023 +- template:_default/mounts diff --git a/templates/amazonlinux.yaml b/templates/amazonlinux.yaml new file mode 120000 index 00000000000..bfa2d7b735d --- /dev/null +++ b/templates/amazonlinux.yaml @@ -0,0 +1 @@ +amazonlinux-2023.yaml \ No newline at end of file