#!/bin/sh
#
# This implementation is incomplete: Discovery mode is not implemented and
# the argument handling doesn't follow currently agreed formats. This is mainly
# because rfc4173 does not say anything about iscsi_initiator but open-iscsi's
# iscsistart needs this.
#

. /lib/dracut-lib.sh

PATH=$PATH:/sbin:/usr/sbin

# Huh? Empty $1?
[ -z "$1" ] && exit 1

# Huh? Empty $2?
[ -z "$2" ] && exit 1

# Huh? Empty $3? This isn't really necessary, since NEWROOT isn't
# used here. But let's be consistent
[ -z "$3" ] && exit 1

# root is in the form root=iscsi:[<servername>]:[<protocol>]:[<port>]:[<LUN>]:<targetname>
netif="$1"
iroot="$2"

source_all /etc/conf.d

# If it's not iscsi we don't continue
[ "${iroot%%:*}" = "iscsi" ] || exit 1

iroot=${iroot#iscsi:}

[ -e /tmp/root.info ] && . /tmp/root.info

[ -e /sys/module/bnx2i ] && iscsiuio

if getarg iscsi_firmware && ! [ -f /tmp/iscsistarted-firmware-ok ]; then
    for p in $(getargs iscsi_param); do
        iscsi_param="$iscsi_param --param $p"
    done

    if [ -n "${root%%block:*}" ]; then
        # if root is not specified try to mount the whole iSCSI LUN
        printf 'ENV{DEVTYPE}!="partition", SYMLINK=="disk/by-path/*-iscsi-*-*", SYMLINK+="root"\n' > /etc/udev/rules.d/99-iscsi-root.rules
    fi

    # start it in the background and wait for it in initqueue-finished
    (
        echo "[ -f \"/tmp/iscsistarted-iscsi-$$\" ]" > /initqueue-finished/iscsistarted-iscsi-$$.sh
        # serialize iscsistart -b jobs
        while [ -f /tmp/iscsistart-inprogress ]; do
                sleep 0.2
        done
        echo "starting $$" > "/tmp/iscsistart-inprogress"

        iscsistart -N
        if iscsistart -b $iscsi_param </dev/null >>/tmp/iscsiroot.out 2>&1; then
            echo 'started' > "/tmp/iscsistarted-firmware-ok"
        fi
        echo 'started' > "/tmp/iscsistarted-firmware"
        echo 'started' > "/tmp/iscsistarted-iscsi-$$"
        echo 'started' > "/tmp/iscsistarted-iscsi"
        rm -f /tmp/iscsistart-inprogress
    ) &

    exit 0
fi

handle_netroot()
{
    local iscsi_initiator iscsi_target_name iscsi_target_ip iscsi_target_port
    local iscsi_target_group iscsi_protocol iscsirw iscsi_lun
    local iscsi_username iscsi_password
    local iscsi_in_username iscsi_in_password
    local iscsi_iface_name iscsi_netdev_name
    local iscsi_param
    local p
# override conf settings by command line options
    arg=$(getarg iscsi_initiator)
    [ -n "$arg" ] && iscsi_initiator=$arg
    arg=$(getarg iscsi_target_name)
    [ -n "$arg" ] && iscsi_target_name=$arg
    arg=$(getarg iscsi_target_ip)
    [ -n "$arg" ] && iscsi_target_ip=$arg
    arg=$(getarg iscsi_target_port)
    [ -n "$arg" ] && iscsi_target_port=$arg
    arg=$(getarg iscsi_target_group)
    [ -n "$arg" ] && iscsi_target_group=$arg
    arg=$(getarg iscsi_username)
    [ -n "$arg" ] && iscsi_username=$arg
    arg=$(getarg iscsi_password)
    [ -n "$arg" ] && iscsi_password=$arg
    arg=$(getarg iscsi_in_username)
    [ -n "$arg" ] && iscsi_in_username=$arg
    arg=$(getarg iscsi_in_password)
    [ -n "$arg" ] && iscsi_in_password=$arg

    for p in $(getargs iscsi_param); do
	iscsi_param="$iscsi_param --param $p"
    done

    parse_iscsi_root "$1" || return 1

# XXX is this needed?
    getarg ro && iscsirw=ro
    getarg rw && iscsirw=rw
    fsopts=${fsopts+$fsopts,}${iscsirw}
    if [ -z $iscsi_initiator ]; then
    # XXX Where are these from?
	[ -f /etc/initiatorname.iscsi ] && . /etc/initiatorname.iscsi
	[ -f /etc/iscsi/initiatorname.iscsi ] && . /etc/iscsi/initiatorname.iscsi
	iscsi_initiator=$InitiatorName

    # XXX rfc3720 says 'SCSI Initiator Name: The iSCSI Initiator Name specifies
    # the worldwide unique name of the initiator.' Could we use hostname/ip
    # if missing?
    fi

    if [ -z $iscsi_initiator ]; then
	if [ -f /sys/firmware/ibft/initiator/initiator-name ]; then
	    iscsi_initiator=$(while read line; do echo $line;done < /sys/firmware/ibft/initiator-name)
	fi
    fi

    if [ -z $iscsi_target_port ]; then
	iscsi_target_port=3260
    fi

    if [ -z $iscsi_target_group ]; then
	iscsi_target_group=1
    fi

    if [ -z $iscsi_initiator ]; then
    # XXX is this correct?
	iscsi_initiator=$(iscsi-iname)
    fi

    if [ -z $iscsi_lun ]; then
	iscsi_lun=0
    fi

    echo "InitiatorName='$iscsi_initiator'" > /dev/.initiatorname.iscsi

# FIXME $iscsi_protocol??

    if [ -n "${root%%block:*}" ]; then
    # if root is not specified try to mount the whole iSCSI LUN
	printf 'SYMLINK=="disk/by-path/*-iscsi-*-%s", SYMLINK+="root"\n' $iscsi_lun >> /etc/udev/rules.d/99-iscsi-root-lun.rules
    fi

    # inject new exit_if_exists
    echo 'settle_exit_if_exists="--exit-if-exists=/dev/root"; rm "$job"' > /initqueue/iscsi-settle.sh

    # force udevsettle to break
    > /initqueue/work

    iscsistart -i $iscsi_initiator -t $iscsi_target_name	\
	       -g $iscsi_target_group -a $iscsi_target_ip	\
	       -p $iscsi_target_port \
	       ${iscsi_username+-u $iscsi_username} \
	       ${iscsi_password+-w $iscsi_password} \
	       ${iscsi_in_username+-U $iscsi_in_username} \
	       ${iscsi_in_password+-W $iscsi_in_password} \
	       ${iscsi_iface_name+--param iface.iscsi_ifacename=$iscsi_iface_name} \
	       ${iscsi_netdev_name+--param iface.net_ifacename=$iscsi_netdev_name} \
	       ${iscsi_param} \
    &

    # give 10 seconds to connect to the iscsi target
    _cnt=0
    while [ $_cnt -lt 100 ]; do
        pidof iscsistart || break
        sleep 0.1
        _cnt=$(($_cnt+1))
    done
    [ $_cnt -lt 100 ] || killproc iscsistart

    netroot_enc=$(str_replace "$1" '/' '\2f')
    echo 'started' > "/tmp/iscsistarted-iscsi:${netroot_enc}"


# install mount script
    if [ -n "${root%%block:*}" ]; then
    # if root is not specified try to mount the whole iSCSI LUN
	echo "iscsi_lun=$iscsi_lun . /bin/mount-lun.sh " > /mount/01-$$-iscsi.sh
    fi
}

# loop over all netroot parameter
if getarg netroot; then
    for nroot in $(getargs netroot); do
        [ "${nroot%%:*}" = "iscsi" ] || continue
	handle_netroot ${nroot##iscsi:}
    done
else
    [ -n "${iroot##iscsi}" ] && handle_netroot $iroot
fi

# now we have a root filesystem somewhere in /dev/sda*
# let the normal block handler handle root=
exit 0
