From c4cce386319448f9bc572e4e689113f079f2b2c7 Mon Sep 17 00:00:00 2001 From: Aastha Rawat Date: Thu, 6 Nov 2025 15:04:12 +0000 Subject: [PATCH] scripts: aarch64: replace guestmount for image modification Replace the use of `guestmount and `guestunmount` with standard tools (losetup, mount) to modify cloud disk image. This eliminates dependency on guestmount which requires /dev/kvm and is not available in MSHV root partition. Signed-off-by: Aastha Rawat --- scripts/run_integration_tests_aarch64.sh | 9 +- scripts/run_metrics.sh | 14 +++- scripts/test-util.sh | 100 +++++++++++++++++++++++ 3 files changed, 115 insertions(+), 8 deletions(-) diff --git a/scripts/run_integration_tests_aarch64.sh b/scripts/run_integration_tests_aarch64.sh index 6262eb885..483c9e8d3 100755 --- a/scripts/run_integration_tests_aarch64.sh +++ b/scripts/run_integration_tests_aarch64.sh @@ -134,11 +134,12 @@ update_workloads() { FOCAL_OS_RAW_IMAGE_UPDATE_KERNEL_NAME="focal-server-cloudimg-arm64-custom-20210929-0-update-kernel.raw" cp "$WORKLOADS_DIR/$FOCAL_OS_RAW_IMAGE_NAME" "$WORKLOADS_DIR/$FOCAL_OS_RAW_IMAGE_UPDATE_KERNEL_NAME" FOCAL_OS_RAW_IMAGE_UPDATE_KERNEL_ROOT_DIR="$WORKLOADS_DIR/focal-server-cloudimg-root" + NEW_KERNEL="$WORKLOADS_DIR/Image-arm64.gz" + DST_KERNEL_PATH="boot/vmlinuz" mkdir -p "$FOCAL_OS_RAW_IMAGE_UPDATE_KERNEL_ROOT_DIR" - # Mount the 'raw' image, replace the compressed kernel file and umount the working folder - guestmount -a "$WORKLOADS_DIR/$FOCAL_OS_RAW_IMAGE_UPDATE_KERNEL_NAME" -m /dev/sda1 "$FOCAL_OS_RAW_IMAGE_UPDATE_KERNEL_ROOT_DIR" || exit 1 - cp "$WORKLOADS_DIR"/Image-arm64.gz "$FOCAL_OS_RAW_IMAGE_UPDATE_KERNEL_ROOT_DIR"/boot/vmlinuz - guestunmount "$FOCAL_OS_RAW_IMAGE_UPDATE_KERNEL_ROOT_DIR" + IMG="$WORKLOADS_DIR/$FOCAL_OS_RAW_IMAGE_UPDATE_KERNEL_NAME" + # Mount image partition, copy kernel, and unmount + copy_to_image "$IMG" "$FOCAL_OS_RAW_IMAGE_UPDATE_KERNEL_ROOT_DIR" "$NEW_KERNEL" "$DST_KERNEL_PATH" || exit 1 # Build virtiofsd build_virtiofsd diff --git a/scripts/run_metrics.sh b/scripts/run_metrics.sh index 3f82abda3..988d90aaf 100755 --- a/scripts/run_metrics.sh +++ b/scripts/run_metrics.sh @@ -74,10 +74,16 @@ if [ "${TEST_ARCH}" == "aarch64" ]; then if [ ! -d "$FOCAL_OS_RAW_IMAGE_UPDATE_TOOL_ROOT_DIR" ]; then mkdir -p "$FOCAL_OS_RAW_IMAGE_UPDATE_TOOL_ROOT_DIR" fi - # Mount the 'raw' image, replace the fio and umount the working folder - guestmount -a "$WORKLOADS_DIR/$FOCAL_OS_RAW_IMAGE_UPDATE_TOOL_NAME" -m /dev/sda1 "$FOCAL_OS_RAW_IMAGE_UPDATE_TOOL_ROOT_DIR" || exit 1 - cp "$WORKLOADS_DIR"/fio "$FOCAL_OS_RAW_IMAGE_UPDATE_TOOL_ROOT_DIR"/usr/bin/fio - guestunmount "$FOCAL_OS_RAW_IMAGE_UPDATE_TOOL_ROOT_DIR" + # Mount image partition + IMG="$WORKLOADS_DIR/$FOCAL_OS_RAW_IMAGE_UPDATE_TOOL_NAME" + + # Update fio binary in the image + SRC_FIO_PATH="$WORKLOADS_DIR/fio" + DST_FIO_PATH="usr/bin/fio" + + # Mount image partition, copy fio, and unmount + chmod +x "$SRC_FIO_PATH" + copy_to_image "$IMG" "$FOCAL_OS_RAW_IMAGE_UPDATE_TOOL_ROOT_DIR" "$SRC_FIO_PATH" "$DST_FIO_PATH" || exit fi # Prepare linux image (build from source or download pre-built) diff --git a/scripts/test-util.sh b/scripts/test-util.sh index 78f738655..f0cf93608 100644 --- a/scripts/test-util.sh +++ b/scripts/test-util.sh @@ -179,3 +179,103 @@ download_ovmf() { time wget --quiet $OVMF_FW_URL || exit 1 popd || exit } + +# Function to mount image partition, execute commands, and cleanup. +# Arguments: $1: Image file path, $2: Mount directory, $3+: Commands to execute. +mount_and_exec() { + local IMG="$1" + local MOUNT_DIR="$2" + local LOOP_DEV="" + local PARTITION_DEV="" + local COMMAND_STATUS=0 + + # Cleanup function to unmount and detach loop device + # shellcheck disable=SC2317 + cleanup() { + if [ -n "$MOUNT_DIR" ]; then + echo "Cleanup: Unmounting $MOUNT_DIR..." >&2 + sudo umount -l "$MOUNT_DIR" 2>/dev/null || true + fi + if [ -n "$LOOP_DEV" ]; then + echo "Cleanup: Detaching loop device $LOOP_DEV..." >&2 + sudo losetup -d "$LOOP_DEV" 2>/dev/null || true + fi + } + + if [ ! -f "$IMG" ] || [ -z "$MOUNT_DIR" ]; then + echo "ERROR: Image path ($IMG) or mount directory ($MOUNT_DIR) is invalid." >&2 + return 1 + fi + mkdir -p "$MOUNT_DIR" + + # Create loop device for the entire disk image + LOOP_DEV=$(sudo losetup -f --show "$IMG") + if [ -z "$LOOP_DEV" ]; then + echo "ERROR: Failed to create loop device for $IMG." >&2 + return 1 + fi + + # Set the trap now that LOOP_DEV is active. + trap cleanup EXIT INT TERM + + # Scan for partitions and define partition device node (p1) + sudo partprobe "$LOOP_DEV" 2>/dev/null + PARTITION_DEV="${LOOP_DEV}p1" + + local MAX_RETRIES=5 + local RETRY_DELAY=1 + + # Wait for partition node with retries + for i in $(seq 1 "$MAX_RETRIES"); do + if sudo test -b "$PARTITION_DEV"; then + break + fi + if [ "$i" -eq "$MAX_RETRIES" ]; then + echo "ERROR: Partition device node $PARTITION_DEV not found after $MAX_RETRIES attempts." >&2 + return 1 + fi + echo "Partition node $PARTITION_DEV not found, waiting $RETRY_DELAY second(s)... (Attempt $i/$MAX_RETRIES)" >&2 + sleep "$RETRY_DELAY" + done + + # Mount the partition + if ! sudo mount "$PARTITION_DEV" "$MOUNT_DIR"; then + echo "ERROR: Failed to mount $PARTITION_DEV." >&2 + return 1 + fi + + # Execute the commands + shift 2 + "$@" + COMMAND_STATUS=$? + + trap - EXIT INT TERM + return $COMMAND_STATUS +} + +# Function to copy a file from the host into the mounted disk image. +# Arguments: +# $1: Image file path +# $2: Mount directory +# $3: Source file path +# $4: Destination file path +copy_to_image() { + local IMG="$1" + local MOUNT_DIR="$2" + local SRC_FILE="$3" + local DST_PATH="$4" + + if [ ! -f "$SRC_FILE" ]; then + echo "ERROR: Source file not found at $SRC_FILE." >&2 + return 1 + elif [ -z "$DST_PATH" ]; then + echo "ERROR: Destination path cannot be empty." >&2 + return 1 + fi + + # Define the command to copy the file + local COPY_COMMAND="sudo cp \"$SRC_FILE\" \"$MOUNT_DIR/$DST_PATH\"" + + mount_and_exec "$IMG" "$MOUNT_DIR" /bin/bash -c "$COPY_COMMAND" + return $? +}