Issue with AlmaLinux 9 Kickstart Script Failing After Clearing Partition Table

I’m encountering an issue with my Kickstart script when installing AlmaLinux 9 on a disk that previously had an OS installed. After clearing the partition table with dd, the installation fails with the error: Failed to save storage configuration.

Here are the details:

  • Failure Scenario: After clearing the partition table, the Kickstart installation fails with Failed to save storage configuration due to Requested disk sda doesn't have a usable disklabel for partitioning.
  • Successful Scenario: Rebooting the system and running the Kickstart script again succeeds. The script works properly on empty disks and in AlmaLinux 8.

I would expect that after clearing the partition table, using the command clearpart --initlabel --drives=$sysdisk --disklabel=gpt would create a GPT label on the specified disk.

#version=RHEL9
#Clear disk 
%pre  --interpreter=/bin/bash
#!/bin/sh
exec < /dev/tty6 > /dev/tty6 2> /dev/tty6
chvt 6

timeout=30
vggroup='almalinux'

# Function to prompt for input with default values
prompt_input() {
    local prompt_message="$1"
    local default_value="$2"
    local user_input
    read -t $timeout -p "$prompt_message (default: $default_value): " user_input
    echo "${user_input:-$default_value}"
}

# Function to validate IP address
validate_ip() {
    local ip="$1"
    if [[ "$ip" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
        return 0
    else
        return 1
    fi
}

# Function to validate netmask
validate_netmask() {
    local netmask="$1"
    if [[ "$netmask" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
        return 0
    else
        return 1
    fi
}

# Function to validate DNS servers
validate_dns() {
    local dns="$1"
    IFS=',' read -r -a dns_array <<< "$dns"
    for dns_server in "${dns_array[@]}"; do
        if ! validate_ip "$dns_server"; then
            return 1
        fi
    done
    return 0
}


sysdisk=""
disk_list=`lsblk -do name,tran,size | grep -v 'usb\|NAME\|loop\|sr0\|ram'`
default_disk=$(echo "$disk_list" | head -n 1 | awk '{print $1}')

echo "Available disks: "
echo "$disk_list" 

while [ -z "$sysdisk" ]; do
    echo
    selected_disk=$(prompt_input "Please enter the disk to install the OS" "$default_disk")
    echo
    if test -e "/dev/$selected_disk"; then
        # Valid disk selected
        sysdisk=$selected_disk
        echo "Setting disk to $sysdisk."        
    else
        # Invalid disk or does not exist
        echo "Disk does not exist or invalid selection."
        echo
        echo "Available disks: "
        echo "$disk_list" 
    fi
done

if vgs | grep -q vghost; then
    echo 
    printf 'y\n' | vgremove "$vggroup" 
fi

echo
default_clear="all"

while [ "$clear_input" != "exit" ]; do
    selected_disk=$(prompt_input "Please enter the disk to clear" "$default_clear")
    echo
    if [ -z "$clear_input" ] || [ "$clear_input" == "all" ]; then
        # No input within timeout, use default
        echo "Clearing all disks."
        while read clear_disk; do
            echo "Clearing $clear_disk"
            if test -e "/dev/$clear_disk"; then 
                dd if=/dev/zero of=/dev/$clear_disk bs=4096 count=4096
                dd if=/dev/zero of=/dev/$clear_disk bs=512 count=4096 seek=$(expr `blockdev --getsz /dev/$sysdisk` - 4096)
            fi
        done< <(echo "$disk_list" | awk '{print $1}' | grep -v -e '^$') 
        clear_input="exit"
    elif test -e "/dev/$clear_input"; then
        # Valid disk selected
        clear_disk="$clear_input"
        echo "Disk to clear $clear_disk."
        dd if=/dev/zero of=/dev/$clear_disk bs=4096 count=4096
        dd if=/dev/zero of=/dev/$clear_disk bs=512 count=4096 seek=$(expr `blockdev --getsz /dev/$sysdisk` - 4096)               
    else
        # Invalid disk or does not exist
        echo "Disk does not exist or invalid selection."
        echo
        echo "Available disks: "
        echo "$disk_list"         
    fi
done

echo
swapdisk=""

while [ -z "$swapsize" ]; do
    read -t $timeout -p "Enter the swap diskspace size (default: 7629 bytes (<64GB RAM), 15258 bytes (>=64GB RAM)): " swap_input
    echo
    if [ -z "$swapsize" ]; then
        # No input within timeout, use default
        TOTAL_MEM=$(free --mega | grep Mem | awk '{print $2}')
        if [ $TOTAL_MEM -ge 65536 ]; then
            swapsize=15258
        else
            swapsize=7629
        fi
        echo "Setting swap to default value: $swapsize."
    elif [ -n "$swap_input" ] && [ "$swap_input" -eq "$swap_input" ] 2>/dev/null; then
        # Valid disk selected
        if [ $swap_input -lt 7629 ]; then
            echo "Invalid swap size. Swap should be greater than 7629."
        else            
            swapsize=$swap_input
            echo "Setting swap size to $swapsize."        
        fi
    else
        echo "Invalid swap size. Swap should be greater than 7629."
    fi
done

echo "clearpart --initlabel --drives=$sysdisk --disklabel=gpt" > /tmp/part-include

# Disk partitioning information
if [ -d /sys/firmware/efi ]; then
    echo "part /boot/efi --fstype='efi' --ondisk=$sysdisk --size=600 --fsoptions='umask=0077,shortname=winnt' --label=boot_efi" >> /tmp/part-include
else
    echo "part biosboot --fstype='biosboot' --ondisk=$sysdisk --size=1" >> /tmp/part-include
fi
echo "part /boot --fstype='xfs' --ondisk=$sysdisk --size=1024 --label=boot" >> /tmp/part-include
echo "part pv.1847 --fstype='lvmpv' --ondisk=$sysdisk --grow" >> /tmp/part-include
echo "volgroup almalinux --pesize=4096 pv.1847" >> /tmp/part-include
echo "logvol /var/log --fstype='xfs' --size=9536 --label='logs' --name=logs --vgname=almalinux" >> /tmp/part-include
echo "logvol /var --fstype='xfs' --size=19536 --label='var' --name=var --vgname=almalinux" >> /tmp/part-include
echo "logvol swap --fstype='swap' --size=$swapsize --name=swap --vgname=almalinux" >> /tmp/part-include
echo "logvol / --fstype='xfs' --grow --percent=100  --label='root' --name=root --vgname=almalinux" >> /tmp/part-include

# Default values
default_nm_method='dhcp'
default_ip_address='172.16.16.1'
default_netmask='255.255.255.0'
default_gateway='172.16.16.254'
default_dns_server='172.16.150.1,172.16.150.2,8.8.8.8'

echo 
echo "Setting up network"
# Network configuration:
while true; do
    nm_method=$(prompt_input "Please the IPv4 method: static or dhcp" "$default_nm_method")
    echo
    if [ -z "$nm_method" ]; then
        # No input within timeout, use default
        nm_method="$default_nm_method"
        echo "Setting the IP method to $nm_method."
        break
    elif [ "$nm_method" == "dhcp" ] || [ "$nm_method" == "static" ]; then
        break
    else
        echo "IPv4 method is bot valid. Options are: static or dhcp."
    fi
done

# Main loop
while [ "$nm_method" != "dhcp" ]; do
    # Prompt user for input
    ip_address=$(prompt_input "Enter IP address" "$default_ip_address")
    echo    
    netmask=$(prompt_input "Enter net mask" "$default_netmask")
    echo    
    gateway=$(prompt_input "Enter gateway" "$default_gateway")
    echo    
    dns_servers=$(prompt_input "Enter DNS servers (comma delimited)" "$default_dns_server")
    echo    

    # Validate inputs
    if ! validate_ip "$ip_address"; then
        echo "Invalid IP address format. Please try again."
        continue
    fi

    if ! validate_netmask "$netmask"; then
        echo "Invalid net mask format. Please try again."
        continue
    fi

    if ! validate_ip "$gateway"; then
        echo "Invalid gateway format. Please try again."
        continue
    fi

    if ! validate_dns "$dns_servers"; then
        echo "Invalid DNS servers format. Please try again."
        continue
    fi

    # Display the collected information
    echo "Configuration:"
    echo "IP Address: $ip_address"
    echo "Net Mask: $netmask"
    echo "Gateway: $gateway"
    echo "DNS Servers: $dns_servers"

    # Exit the loop if everything is correct
    echo "Configuration is correct. Exiting."
    break
done

if [ "$nm_method" == "static" ]; then
    echo "network --bootproto=static --ip=$ip_address --netmask=$netmask --gateway=$gateway --nameserver=$dns_servers --ipv6=auto --activate" >> /tmp/network-include
else 
    echo "network  --bootproto=dhcp --ipv6=auto --activate" >> /tmp/network-include
fi
echo "network  --hostname=localhost.localdomain" >> /tmp/network-include

chvt 1
exec < /dev/tty1 > /dev/tty1 2> /dev/tty1
%end

%include /tmp/part-include
%include /tmp/network-include

I ran into this problem, and found that you have to add the kickstart command “zerombr” to the kickstart before the “clearpart” statement. It took a couple of days pouring through the various Fedora and EL message boards and documentation before I saw reference to this problem. I also use a %pre script to set up multiple partitions and set up networking with hostname resolution and static IP4 addressing. you can contact me offline if you would like to see the scripts. They are on this message board as part of an answer to another Kickstart problem.