#!/bin/bash

set -e

# Kernel networking params to persist
PERSIST_KERNEL_NET_PARAMS=("ipv6.disable" "net.ifnames" "net.naming-scheme")

# Dracut networking params to persist
# Everything other than rd.neednet.
# List from https://www.mankier.com/7/dracut.cmdline#Description-Network
PERSIST_DRACUT_NET_PARAMS=("ip" "ifname" "rd.route" "bootdev" "BOOTIF" "rd.bootif" "nameserver" "rd.peerdns" "biosdevname" "vlan" "bond" "team" "bridge" "rd.net.timeout.carrier" "coreos.no_persist_ip" "coreos.force_persist_ip")

# IBM S390X params to persist
PERSIST_S390X_PARAMS=("rd.dasd" "rd.zfcp" "rd.znet" "zfcp.allow_lun_scan" "cio_ignore")

# Installer config directory
INSTALLER_CONFIG_DIR=/etc/coreos/installer.d

args=("install")

IFS=" " read -r -a cmdline <<< "$(</proc/cmdline)"
karg() {
    local name="$1" value="$2"
    for arg in "${cmdline[@]}"; do
        if [[ "${arg%%=*}" == "${name}" ]]; then
            value="${arg#*=}"
        fi
    done
    echo "${value}"
}

karg_bool() {
    local value
    value=$(karg "$@")
    case "$value" in
        ""|0|no|off) return 1;;
        *) return 0;;
    esac
}

copy_arg() {
    local arg="$1"; shift
    local opt="$1"; shift

    local value
    value="$(karg "${arg}")"
    if [ -n "${value}" ]; then
        args+=("${opt}" "${value}")
    fi
}

# Warn on deprecated kargs
if [ "$(karg coreos.inst)" = yes ]; then
    echo '"coreos.inst=yes" is deprecated and no longer has any effect.'
fi

# Config files
have_config_file=
for file in "${INSTALLER_CONFIG_DIR}/"*; do
    if [ -f "${file}" ]; then
        args+=("--config-file" "${file}")
        have_config_file=1
    fi
done

# Get install device
device="$(karg coreos.inst.install_dev)"
if [ -n "${device}" ]; then
    if [ "${device##*/}" = "${device}" ]; then
        # karg contains no slashes.  Prepend "/dev/" for compatibility.
        echo "The \"coreos.inst.install_dev=$device\" syntax is deprecated."
        echo "Use \"coreos.inst.install_dev=/dev/$device\" instead."
        device="/dev/${device}"
    fi
    args+=("${device}")
elif [ -z "${have_config_file}" ]; then
    # If there's a config file, it may not specify the install device, but
    # we assume it does.
    echo "No install device specified."
    exit 1
fi

# Ignition URL
ignition_url="$(karg coreos.inst.ignition_url)"
# Ignore "skip" for compatibility
if [ -n "${ignition_url}" ] && [ "${ignition_url}" != "skip" ]; then
    # Allow HTTP URLs for compatibility
    args+=("--ignition-url" "${ignition_url}" "--insecure-ignition")
fi

# Forward whitelisted kernel arguments to the installed system. We have
# separate sets of whitelists for first-boot kargs and persistent kargs.
# If additional networking options have been specified, add `rd.neednet=1`
# to activate nm-initrd-generator on first boot.
firstboot_args=""
for item in "${cmdline[@]}"; do
    for param in "${PERSIST_KERNEL_NET_PARAMS[@]}" "${PERSIST_DRACUT_NET_PARAMS[@]}"; do
        if [[ $item =~ ^$param(=.*)?$ ]]; then
            firstboot_args+="${item} "
        fi
    done
    for param in "${PERSIST_S390X_PARAMS[@]}"; do
        if [[ $item =~ ^$param(=.*)?$ ]]; then
            args+=("--append-karg" "${item}")
        fi
    done
done
if [ -n "${firstboot_args}" ]; then
    args+=("--firstboot-args" "rd.neednet=1 ${firstboot_args}")
fi

# Other args that should just be copied over
copy_arg coreos.inst.image_url       --image-url
copy_arg coreos.inst.platform_id     --platform
copy_arg coreos.inst.stream          --stream
copy_arg coreos.inst.save_partlabel  --save-partlabel
copy_arg coreos.inst.save_partindex  --save-partindex

# Insecure boolean
if karg_bool coreos.inst.insecure; then
    args+=("--insecure")
fi

# Always retry HTTP requests; we've got nothing to lose since we fail anyway.
args+=("--fetch-retries" "infinite")

# Ensure device nodes have been created
udevadm settle

# Install
echo "coreos-installer ${args[*]}"
coreos-installer "${args[@]}"

# Delete config files to avoid boot loops outside of a live system
rm -rf "${INSTALLER_CONFIG_DIR}"
