public inbox for isar-users@googlegroups.com
 help / color / mirror / Atom feed
From: Anton Mikanovich <amikan@ilbers.de>
To: Kasturi shekar <kasturi.shekar@siemens.com>, isar-users@googlegroups.com
Subject: Re: [PATCH v2 3/4] installer: add installer flow module and entrypoint
Date: Thu, 4 Jun 2026 15:56:51 +0300	[thread overview]
Message-ID: <8b658081-ce7b-4ffc-b108-1691f5a8ceaf@ilbers.de> (raw)
In-Reply-To: <20260514091951.1572682-4-kasturi.shekar@siemens.com>

Hello Kasturi,

14.05.2026 12:19, 'Kasturi shekar' via isar-users wrote:
> From: Kasturi Shekar <kasturi.shekar@siemens.com>
>
> high-level orchestration and keep deploy-image-wic.sh as a thin launcher.
>
> This keeps the externally used script name stable while making the flow easier
> to review and maintain by separating:
>   - backend APIs
>   - UI frontend
>   - mode/orchestration flow
>
> Signed-off-by: Kasturi Shekar <kasturi.shekar@siemens.com>
> ---
>   .../files/usr/bin/deploy-image-wic.sh         | 475 +++++++-----------
>   1 file changed, 192 insertions(+), 283 deletions(-)
>   mode change 100755 => 100644 meta-isar/recipes-installer/deploy-image/files/usr/bin/deploy-image-wic.sh
>
> diff --git a/meta-isar/recipes-installer/deploy-image/files/usr/bin/deploy-image-wic.sh b/meta-isar/recipes-installer/deploy-image/files/usr/bin/deploy-image-wic.sh
> old mode 100755
> new mode 100644
> index 9a4102b2..a692b679
> --- a/meta-isar/recipes-installer/deploy-image/files/usr/bin/deploy-image-wic.sh
> +++ b/meta-isar/recipes-installer/deploy-image/files/usr/bin/deploy-image-wic.sh
> @@ -1,6 +1,6 @@
>   #!/usr/bin/env bash
>   # This software is a part of Isar.
> -# Copyright (C) Siemens AG, 2024
> +# Copyright (C) Siemens AG, 2026
>   #
>   # SPDX-License-Identifier: MIT
>   
> @@ -9,293 +9,202 @@ installdata=${INSTALL_DATA:-/install}
>   SCRIPT_DIR=$( dirname -- "$( readlink -f -- "$0"; )"; )
>   
>   . "${SCRIPT_DIR}/../lib/deploy-image-wic/handle-config.sh"
> +. "${SCRIPT_DIR}/sys_api.sh"
> +. "${SCRIPT_DIR}/installer_ui.sh"
>   
> -if [ "$installer_unattended" = true ] && [ "$installer_unattended_abort_enable" = true ]; then
> -    abort_file=/run/attended_mode_trigger
> -    for ((i=$installer_unattended_abort_timeout; i>0; i--)); do
> -        echo -ne "\rUnattended installation will start in $i seconds. Press any key to switch to attended mode..."
> +#--------------------------------------------------------------------------
> +# This module contains high-level installer flow logic
> +# while keeping low-level backend APIs in sys_api.sh
> +# and user-facing dialogs in installer_ui.sh.
> +#--------------------------------------------------------------------------
>   
> -        # Switch to attended mode if the abort file exists or any key pressed during countdown
> -        # Create abort file to notify all other console instances to abort
> -        if [ -f "$abort_file" ] || read -n 1 -t 1; then
> -            installer_unattended=false
> -            touch "$abort_file"
> -            break
> -        fi
> -    done
> -fi
> -
> -if ! $installer_unattended; then
> -    installer_image_uri=$(find "$installdata" -type f -iname "*.wic*" -a -not -iname "*.wic.bmap" -exec basename {} \;)
> -    if [ -z "$installer_image_uri" ] || [ ! -f "$installdata/$installer_image_uri" ]; then
> -        pushd "$installdata"
> -        for f in $(find . -type f ! -iname "*.wic.bmap"); do
> -            array+=("$f" "$f")
> -        done
> -        popd
> -        if [ ${#array[@]} -gt 0 ]; then
> -            if ! installer_image_uri=$(dialog --no-tags \
> -                              --menu "Select image to be installed" 10 60 3 \
> -                              "${array[@]}" --output-fd 1); then
> -                exit 0
> -            fi
> -        fi
> -    fi
> -
> -    if [ ! -f "$installdata/$installer_image_uri" ]; then
> -        dialog --msgbox "Could not find an image to install. Installation aborted." 6 60
> -        exit 1
> -    fi
> -
> -    # inspired by poky/meta/recipes-core/initrdscripts/files/install-efi.sh
> -    target_device_list=""
> -    current_root_dev_type=$(findmnt / -o fstype -n)
> -    exclude_list=()
> -
> -    if [ "$current_root_dev_type" = "nfs" ]; then
> -        current_root_dev="nfs"
> -        exclude_list+=("nfs")
> -    else
> -    # For normal or immutable systems, get the backing device of '/'
> -        root_source=$(findmnt / -o source -n)
> -        root_source_resolved=$(readlink -f "$root_source" 2>/dev/null || echo "$root_source")
> -        current_root_dev=${root_source_resolved#/dev/}
> -
> -        # Always exclude the exact device mounted as /
> -        exclude_list+=("$current_root_dev")
> -
> -        if [[ "$current_root_dev" =~ ^(mmcblk|nvme) ]]; then
> -            base_no_part="${current_root_dev%p[0-9]*}"
> -        else
> -            base_no_part="${current_root_dev%%[0-9]*}"
> -        fi
> -        if [ -n "$base_no_part" ]; then
> -            exclude_list+=("$base_no_part")
> -        fi
> -
> -        # If root is coming through a dm-* device (e.g., dm-verity),
> -        # the actual physical devices appear under /sys/block/<dm>/slaves/.
> -        # We must exclude those slaves as well, otherwise the installer
> -        # might show the live USB stick as a valid target.
> -        if [ -d "/sys/block/$current_root_dev/slaves" ]; then
> -            for slave in /sys/block/"$current_root_dev"/slaves/*; do
> -                [ -e "$slave" ] || continue
> -                slave_dev=$(basename "$slave")
> -                exclude_list+=("$slave_dev")
> -                slave_base=${slave_dev%%[0-9]*}
> -                [ -n "$slave_base" ] && exclude_list+=("$slave_base")
> -            done
> -        fi
> -    fi
> -
> -    echo "Searching for target device..."
> -
> -    devices=$(find /sys/block/ -type b,c,f,l -not -iname "mmcblk*" -printf "%f\n") || true
> -    mmc_devices=$(find /sys/block/ -type b,c,f,l -iname "mmcblk[0-9]" -printf "%f\n") || true
> -    devices="$devices $mmc_devices"
> -
> -    for device in $devices; do
> -        is_raid_member=0
> -
> -        if [ -d "/sys/block/$device/holders" ] && [ ! -d "/sys/block/$device/md" ]; then
> -            for holder_path in /sys/block/$device/holders/*; do
> -                holder_name=$(basename "$holder_path")
> -                case "$holder_name" in
> -                    md[0-9]*)
> -                        is_raid_member=1
> -                        break
> -                        ;;
> -                esac
> -            done
> -        fi
> -
> -        if [ "$is_raid_member" -eq 1 ]; then
> -            continue # Skip RAID member disks
> -        fi
> -
> -        if [[ "$device" == md* ]]; then
> -            if [ -f "/sys/block/$device/md/array_state" ]; then
> -                state=$(cat /sys/block/$device/md/array_state)
> -                if [ "$state" != "active" ] && [ "$state" != "clean" ]; then
> -                    continue
> -                fi
> -            else
> -                continue
> -            fi
> -        fi
> -
> -        case $device in
> -            dm-*)
> -                # skip device-mapper device
> -                ;;
> -            loop*)
> -                # skip loop device
> -                ;;
> -            mtd*)
> -                ;;
> -            sr*)
> -                # skip CDROM device
> -                ;;
> -            ram*)
> -                # skip ram device
> -                ;;
> -            zram*)
> -                # skip zram device
> -                ;;
> -            *)
> -                #skip any excluded devices (root and its slaves)
> -                skip_device=0
> -                for ex in "${exclude_list[@]}"; do
> -                    if [[ "$device" == "$ex"* ]]; then
> -                        skip_device=1
> -                        break
> -                    fi
> -                done
> -
> -                if [ "$skip_device" -eq 0 ]; then
> -                    target_device_list="$target_device_list $device"
> -                fi
> -                ;;
> -        esac
> -    done
> -
> -    if [ -z "${target_device_list}" ]; then
> -        dialog --msgbox "You need another device (besides the live device /dev/${current_root_dev}) to install the image. Installation aborted." 7 60
> -        exit 1
> -    fi
> -
> -    if [ "$(echo "$target_device_list" | wc -w)" -gt 1 ]; then
> -        array=()
> -        for target in $(echo "$target_device_list" | xargs -n1 | sort); do
> -            target_size=$(lsblk --nodeps --noheadings -o SIZE /dev/"$target" | tr -d " ")
> -            if cmp /dev/zero /dev/"$target" -n 1M; then
> -                state="empty"
> -            else
> -                state="contains data"
> -            fi
> -            array+=("/dev/$target" "/dev/$target ($target_size, $state)")
> -        done
> -        if ! installer_target_dev=$(dialog --no-tags \
> -                             --menu "Select device to install image to" 10 60 3 \
> -                             "${array[@]}" --output-fd 1); then
> -            exit 0
> -        fi
> -    else
> -        installer_target_dev="/dev/$(echo "$target_device_list" | tr -d " ")"
> -    fi
> -    TARGET_DEVICE_SIZE=$(lsblk --nodeps --noheadings -o SIZE "$installer_target_dev" | tr -d " ")
> -    if ! dialog --yes-label Ok --no-label Cancel \
> -                --yesno "Start installing\n'$installer_image_uri'\nto $installer_target_dev (capacity: $TARGET_DEVICE_SIZE)" 7 60; then
> -        exit 0
> -    fi
> -
> -    # set absolute paths to be compatible with unattended mode
> -    installer_image_uri="$installdata/$installer_image_uri"
> -fi
> -
> -if ! cmp /dev/zero "$installer_target_dev" -n 1M; then
> -    if ! $installer_unattended; then
> -        if ! dialog --defaultno \
> -                    --yesno "WARNING: Target device is not empty! Continue anyway?" 5 60; then
> -            exit 0
> -        fi
> -    else
> -        if [ "$installer_target_overwrite" != "OVERWRITE" ]; then
> -            echo "Target device is not empty! -> Abort"
> -            echo "If you want to override existing data set \"installer.target.overwrite=OVERWRITE\" on your kernel cmdline or edit your \"auto.install\" file accordingly."
> -
> -            exit 1
> -        fi
> -    fi
> -fi
> -
> -bmap_options=""
> -
> -# bmap file is expected to be next to the installer image
> -DISK_BMAP="${installer_image_uri%.wic*}.wic.bmap"
> -
> -if [ ! -f "$DISK_BMAP" ]; then
> -    bmap_options="--nobmap"
> -fi
> -
> -if ! $installer_unattended; then
> -    clear
> -fi
> -
> -# Function to compare version numbers
> -version_ge() {
> -    if [ "$(printf '%s\n' "$1"X "$2" | sort -V | head -n 1)" != "$1"X ]; then
> -        return 0
> -    else
> -        return 1
> -    fi
> +#--------------------------------------------------------------------------
> +# flow_run_attended
> +#
> +# Handles all attended-mode interactions and assigns:
> +#   installer_image_uri
> +#   installer_target_dev
> +#
> +# Returns:
> +#   0 on success
> +#   1 on hard error
> +#   2 on user cancel
> +#--------------------------------------------------------------------------
> +flow_run_attended() {
> +	local default_image
> +	local selected_image
> +	local selected_target
> +	local target_device_size
> +
> +	default_image=$(sys_first_default_image_name "$installdata")
> +	if [ -n "$default_image" ] && [ -f "$installdata/$default_image" ]; then
> +		installer_image_uri="$default_image"
> +	fi
> +
> +	if [ -z "$installer_image_uri" ] || [ ! -f "$installdata/$installer_image_uri" ]; then
This check is never hit because installer_image_uri is always set after 
calling
sys_first_default_image_name.
It results in skipping image selection dialog and always installing the 
first
one.
> +		selected_image=$(ui_select_image_menu "$installdata")
> +		case $? in
> +			0)
> +				installer_image_uri="$selected_image"
> +				;;
> +			1)
> +				ui_show_error "Could not find an image to install. Installation aborted."
> +				return 1
> +				;;
> +			2)
> +				return 2
> +				;;
> +			*)
> +				return 1
> +				;;
> +		esac
> +	fi
> +
> +	if [ ! -f "$installdata/$installer_image_uri" ]; then
> +		ui_show_error "Could not find an image to install. Installation aborted."
> +		return 1
> +	fi
> +
> +	echo "Searching for target device..."
> +	sys_discover_target_devices
> +	if [ "${#SYS_TARGET_DEVICES[@]}" -eq 0 ]; then
> +		ui_show_error "You need another device (besides the live device /dev/${SYS_CURRENT_ROOT_DEV}) to install the image. Installation aborted."
> +		return 1
> +	fi
> +
> +	if [ "${#SYS_TARGET_DEVICES[@]}" -gt 1 ]; then
> +		selected_target=$(ui_select_target_device_menu "${SYS_TARGET_DEVICES[@]}")
> +		case $? in
> +			0)
> +				installer_target_dev="$selected_target"
> +				;;
> +			1)
> +				ui_show_error "No installable target devices available. Installation aborted."
> +				return 1
> +				;;
> +			2)
> +				return 2
> +				;;
> +			*)
> +				return 1
> +				;;
> +		esac
> +	else
> +		installer_target_dev="${SYS_TARGET_DEVICES[0]}"
> +	fi
> +
> +	target_device_size=$(sys_device_size "$installer_target_dev")
> +	if ! ui_confirm_install "$installer_image_uri" "$installer_target_dev" "$target_device_size"; then
> +		return 2
> +	fi
> +
> +	installer_image_uri="$installdata/$installer_image_uri"
> +	return 0
>   }
>   
> -lockfile="/run/installer.lock"
> -progress_pipe="/run/installer.fifo"
> -
> -exec 9>"$lockfile"
> -if flock -n 9; then
> -    # Get bmap-tools version
> -    bmap_version=$(bmaptool --version | awk '{ print $NF }')
> -
> -    if version_ge "$bmap_version" "3.6"; then
> -        if ! mkfifo "$progress_pipe"; then
> -            echo "Error: Failed to create named pipe $progress_pipe"
> -            exit 1
> -        fi
> -
> -        # Add psplash pipe to bmap_options
> -        bmap_options="$bmap_options --psplash-pipe=$progress_pipe"
> -        quiet_flag="-q"
> -
> -        # Initialize the dialog gauge and update it dynamically
> -        (
> -            while true; do
> -                if read -r line < "$progress_pipe"; then
> -                    percentage=$(echo "$line" | awk '{ print $2 }')
> -                    echo "$percentage"
> -                fi
> -            done
> -        ) | dialog --gauge "Flashing image, please wait..." 10 70 0 &
> -
> -        gauge_pid=$!
> -    fi
> -
> -    if ! bmaptool $quiet_flag copy $bmap_options "$installer_image_uri" "$installer_target_dev"; then
> -        kill "$gauge_pid"
> -        exit 1
> -    fi
> -
> -    # Attempt to terminate the gauge process if still running.
> -    # Errors are ignored since the process may already have exited.
> -    kill "$gauge_pid" 2>/dev/null
> -else
> -    echo "Installation already running in another console."
> +#--------------------------------------------------------------------------
> +# flow_validate_target_overwrite_policy
> +#
> +# Enforces overwrite policy for non-empty targets in both attended and
> +# unattended modes.
> +#
> +# Returns:
> +#   0 when policy permits installation
> +#   1 when policy rejects installation
> +#   2 when user cancels in attended mode
> +#--------------------------------------------------------------------------
> +flow_validate_target_overwrite_policy() {
> +	if sys_device_is_empty "$installer_target_dev"; then
> +		return 0
> +	fi
> +
> +	if ! $installer_unattended; then
> +		if ! ui_confirm_overwrite; then
> +			return 2
> +		fi
> +	else
> +		if [ "$installer_target_overwrite" != "OVERWRITE" ]; then
> +			echo "Target device is not empty! -> Abort"
> +			echo "If you want to override existing data set \"installer.target.overwrite=OVERWRITE\" on your kernel cmdline or edit your \"auto.install\" file accordingly."
> +			return 1
> +		fi
> +	fi
> +
> +	return 0
> +}
>   
> -    # Wait for running console to create the progress pipe
> -    sleep 5
> +#--------------------------------------------------------------------------
> +# flow_maybe_switch_to_attended
> +#
> +# If unattended abort-by-key is enabled, this function offers a timeout
> +# window to switch to attended mode.
> +#--------------------------------------------------------------------------
> +flow_maybe_switch_to_attended() {
> +	local abort_file
> +
> +	if [ "$installer_unattended" = true ] && [ "$installer_unattended_abort_enable" = true ]; then
> +		abort_file=/run/attended_mode_trigger
> +		if ui_countdown_allow_attended_switch "$installer_unattended_abort_timeout" "$abort_file"; then
> +			installer_unattended=false
> +		fi
> +	fi
> +}
>   
> -    # Check if progress pipe exists and has content
> -    if [ -e "$progress_pipe" ]; then
> -        echo "Installation progress..."
> -        tail -f "$progress_pipe" | while read line; do
> -            printf "\r%s%%" "$line"
> -        done
> -    else
> -        # Periodically check if bmaptool is still running every 5 seconds
> -        echo "Waiting for installation to finish..."
> -        while pgrep -x "bmaptool" > /dev/null; do
> -            sleep 5
> -        done
> -    fi
> -fi
> +#--------------------------------------------------------------------------
> +# flow_run
> +#
> +# Main installer flow combining attended/unattended execution paths.
> +#--------------------------------------------------------------------------
> +flow_run() {
> +	flow_maybe_switch_to_attended
> +
> +	if ! $installer_unattended; then
> +		flow_run_attended
> +		case $? in
> +			0)
> +				;;
> +			2)
> +				return 0
> +				;;
> +			*)
> +				return 1
> +				;;
> +		esac
> +	fi
> +
> +	flow_validate_target_overwrite_policy
> +	case $? in
> +		0)
> +			;;
> +		2)
> +			return 0
> +			;;
> +		*)
> +			return 1
> +			;;
> +	esac
> +
> +	if ! $installer_unattended; then
> +		clear
> +	fi
> +
> +	if ! sys_install_image_with_lock "$installer_image_uri" "$installer_target_dev"; then
> +		if ! $installer_unattended; then
> +			ui_show_error "Installation failed."
> +		fi
> +		return 1
> +	fi
> +
> +	if ! $installer_unattended; then
> +		ui_show_info "Installation was successful. System will be rebooted. Please remove the USB stick."
> +	else
> +		echo "Installation was successful."
> +	fi
> +
> +	return 0
> +}
>   
> -if ! $installer_unattended; then
> -    dialog --title "Reboot" \
> -           --msgbox "Installation was successful. System will be rebooted. Please remove the USB stick." 6 60
> -else
> -    echo "Installation was successful."
> -fi
> +# Entrypoint: run the installer flow and propagate status.
> +flow_run
> +exit $?
>   
> -exit 0

-- 
You received this message because you are subscribed to the Google Groups "isar-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to isar-users+unsubscribe@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/isar-users/8b658081-ce7b-4ffc-b108-1691f5a8ceaf%40ilbers.de.

  reply	other threads:[~2026-06-04 12:57 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-27  6:39 [PATCH 0/4] installer: separate installer into backend, UI, and flow modules 'Kasturi shekar' via isar-users
2026-04-27  6:39 ` [PATCH 1/4] installer: extract backend helpers to sys_api.sh 'Kasturi shekar' via isar-users
2026-04-27  6:39 ` [PATCH 2/4] installer: extract attended UI to installer_ui.sh 'Kasturi shekar' via isar-users
2026-04-27  6:39 ` [PATCH 3/4] installer: add installer flow module and entrypoint 'Kasturi shekar' via isar-users
2026-05-14  9:19   ` [PATCH v2 0/4] installer: separate installer into backend, UI, and flow modules 'Kasturi shekar' via isar-users
2026-05-14  9:19     ` [PATCH v2 1/4] installer: extract backend helpers to sys_api.sh 'Kasturi shekar' via isar-users
2026-05-14  9:19     ` [PATCH v2 2/4] installer: extract attended UI to installer_ui.sh 'Kasturi shekar' via isar-users
2026-05-14  9:19     ` [PATCH v2 3/4] installer: add installer flow module and entrypoint 'Kasturi shekar' via isar-users
2026-06-04 12:56       ` Anton Mikanovich [this message]
2026-06-08  5:17         ` [PATCH v3 0/4] installer: separate installer into backend, UI, and flow modules 'Kasturi shekar' via isar-users
2026-06-08  5:17           ` [PATCH v3 1/4] installer: extract backend helpers to sys_api.sh 'Kasturi shekar' via isar-users
2026-06-08  5:17           ` [PATCH v3 2/4] installer: extract attended UI to installer_ui.sh 'Kasturi shekar' via isar-users
2026-06-08  5:17           ` [PATCH v3 3/4] installer: add installer flow module and entrypoint 'Kasturi shekar' via isar-users
2026-06-08  5:17           ` [PATCH v3 4/4] installer: install seprated installer modules in recipe 'Kasturi shekar' via isar-users
2026-06-12 10:50           ` [PATCH v3 0/4] installer: separate installer into backend, UI, and flow modules Anton Mikanovich
2026-05-14  9:19     ` [PATCH v2 4/4] installer: install seprated installer modules in recipe 'Kasturi shekar' via isar-users
2026-04-27  6:39 ` [PATCH " 'Kasturi shekar' via isar-users
2026-05-14  6:20   ` Anton Mikanovich

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=8b658081-ce7b-4ffc-b108-1691f5a8ceaf@ilbers.de \
    --to=amikan@ilbers.de \
    --cc=isar-users@googlegroups.com \
    --cc=kasturi.shekar@siemens.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox