From c426dc773fe654aed309375e20e398e9299ca34e Mon Sep 17 00:00:00 2001
From: Thomas Blume <Thomas.Blume@suse.com>
Date: Mon, 19 Oct 2015 09:14:53 +0200
Subject: Replace iscsistart with iscsiadm
References: FATE#319024

iscsistart allows for a single connection only, and offers no means
or terminating or re-establishing another one.
So replace iscsistart with iscsiadm to allow several connection for
multipath booting and also to ease maintenance in case of error.

Signed-off-by: Thomas Blume <thomas.blume@suse.com>
---
 modules.d/95iscsi/iscsiroot.sh       | 48 ++++++++++++++++++++++++------------
 modules.d/95iscsi/module-setup.sh    | 19 ++++++++++++--
 modules.d/95iscsi/parse-iscsiroot.sh |  2 +-
 3 files changed, 50 insertions(+), 19 deletions(-)

diff --git a/modules.d/95iscsi/iscsiroot.sh b/modules.d/95iscsi/iscsiroot.sh
index 1c4be4e..bc9b0e1 100755
--- a/modules.d/95iscsi/iscsiroot.sh
+++ b/modules.d/95iscsi/iscsiroot.sh
@@ -46,8 +46,8 @@ fi
 handle_firmware()
 {
     if ! [ -e /tmp/iscsistarted-firmware ]; then
-        if ! iscsistart -f; then
-            warn "iscistart: Could not get list of targets from firmware."
+        if ! iscsiadm -m fw; then
+            warn "iscsiadm: Could not get list of targets from firmware."
             return 1
         fi
 
@@ -55,8 +55,8 @@ handle_firmware()
 	    iscsi_param="$iscsi_param --param $p"
         done
 
-        if ! iscsistart -b $iscsi_param; then
-            warn "'iscsistart -b $iscsi_param' failed"
+        if ! iscsiadm -m fw -l; then
+            warn "iscsiadm: Log-in to iscsi target failed"
         fi
 
         if [ -d /sys/class/iscsi_session ]; then
@@ -85,7 +85,7 @@ handle_netroot()
     # override conf settings by command line options
     arg=$(getarg rd.iscsi.initiator -d iscsi_initiator=)
     [ -n "$arg" ] && iscsi_initiator=$arg
-    arg=$(getarg rd.iscsi.target.name -d iscsi_target_name=)
+    arg=$(getargs rd.iscsi.target.name -d iscsi_target_name=)
     [ -n "$arg" ] && iscsi_target_name=$arg
     arg=$(getarg rd.iscsi.target.ip -d iscsi_target_ip)
     [ -n "$arg" ] && iscsi_target_ip=$arg
@@ -166,17 +166,33 @@ handle_netroot()
     # force udevsettle to break
     > $hookdir/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} \
-	|| :
+    if iscsiadm -m node; then
+        targets=$(iscsiadm -m node | sed 's/^.*iqn/iqn/')
+    else
+        targets=$(iscsiadm -m discovery -t st -p $iscsi_target_ip:${iscsi_target_port:+$iscsi_target_port} | sed 's/^.*iqn/iqn/')
+        [ -z "$targets" ] && echo "Target discovery to $iscsi_target_ip:${iscsi_target_port:+$iscsi_target_port} failed with status $?" && exit 1
+    fi
+
+    for target in $iscsi_target_name; do
+        if [[ "$targets" =~ "$target" ]]; then
+            if [ -n "$iscsi_iface_name" ]; then
+                $(iscsiadm -m iface -I $iscsi_iface_name --op=new)
+                [ -n "$iscsi_initiator" ] && $(iscsiadm -m iface -I $iscsi_iface_name --op=update --name=iface.initiatorname --value=$iscsi_initiator)
+                [ -n "$iscsi_netdev_name" ] && $(iscsiadm -m iface -I $iscsi_iface_name --op=update --name=iface.net_ifacename --value=$iscsi_netdev_name)
+                COMMAND="iscsiadm -m node -T $target -p $iscsi_target_ip${iscsi_target_port:+:$iscsi_target_port} -I $iscsi_iface_name --op=update"
+            else
+                COMMAND="iscsiadm -m node -T $target -p $iscsi_target_ip${iscsi_target_port:+:$iscsi_target_port} --op=update"
+            fi
+            $($COMMAND --name=node.startup --value=onboot)
+            [ -n "$iscsi_username" ] && $($COMMAND --name=node.session.auth.username --value=$iscsi_username)
+            [ -n "$iscsi_password" ] && $($COMMAND --name=node.session.auth.password --value=$iscsi_password)
+            [ -n "$iscsi_in_username" ] && $($COMMAND --name=node.session.auth.username_in --value=$iscsi_in_username)
+            [ -n "$iscsi_in_password" ] && $($COMMAND --name=node.session.auth.password_in --value=$iscsi_in_password)
+            [ -n "$iscsi_param" ] && $($COMMAND --name=${iscsi_param%=*} --value=${iscsi_param#*=})
+        fi
+    done
+
+    iscsiadm -m node -L onboot || :
 
     netroot_enc=$(str_replace "$1" '/' '\2f')
     echo 'started' > "/tmp/iscsistarted-iscsi:${netroot_enc}"
diff --git a/modules.d/95iscsi/module-setup.sh b/modules.d/95iscsi/module-setup.sh
index 4784ea3..74444c0 100755
--- a/modules.d/95iscsi/module-setup.sh
+++ b/modules.d/95iscsi/module-setup.sh
@@ -128,7 +128,7 @@ install_softiscsi() {
 check() {
     local _rootdev
     # If our prerequisites are not met, fail anyways.
-    require_binaries iscsistart hostname iscsi-iname || return 1
+    require_binaries hostname iscsi-iname iscsiadm iscsid || return 1
 
     # If hostonly was requested, fail the check if we are not actually
     # booting from root.
@@ -214,9 +214,22 @@ cmdline() {
 
 # called by dracut
 install() {
-    inst_multiple umount iscsistart hostname iscsi-iname
     inst_multiple -o iscsiuio
     inst_libdir_file 'libgcc_s.so*'
+    inst_multiple umount hostname iscsi-iname iscsiadm iscsid
+
+    ln -sf $systemdsystemunitdir/iscsid.socket $systemdsystemunitdir/sockets.target.wants/iscsid.socket
+    ln -sf $systemdsystemunitdir/iscsiuio.socket $systemdsystemunitdir/sockets.target.wants/iscsiuio.socket
+
+    inst_multiple -o \
+        $systemdsystemunitdir/iscsid.socket \
+        $systemdsystemunitdir/iscsid.service \
+        $systemdsystemunitdir/iscsiuio.service \
+        $systemdsystemunitdir/iscsiuio.socket \
+        $systemdsystemunitdir/sockets.target.wants/iscsid.socket \
+        $systemdsystemunitdir/sockets.target.wants/iscsiuio.socket
+
+    [[ -d /etc/iscsi ]] && inst_dir $(/usr/bin/find /etc/iscsi)
 
     # Detect iBFT and perform mandatory steps
     if [[ $hostonly_cmdline == "yes" ]] ; then
@@ -224,6 +237,8 @@ install() {
         [[ $_iscsiconf ]] && printf "%s\n" "$_iscsiconf" >> "${initdir}/etc/cmdline.d/95iscsi.conf"
     fi
 
+    echo 'rd.neednet=1' >> "${initdir}/etc/cmdline.d/95iscsi.conf"
+
     inst_hook cmdline 90 "$moddir/parse-iscsiroot.sh"
     inst_hook cleanup 90 "$moddir/cleanup-iscsi.sh"
     inst "$moddir/iscsiroot.sh" "/sbin/iscsiroot"
diff --git a/modules.d/95iscsi/parse-iscsiroot.sh b/modules.d/95iscsi/parse-iscsiroot.sh
index 3a572f7..ff36472 100755
--- a/modules.d/95iscsi/parse-iscsiroot.sh
+++ b/modules.d/95iscsi/parse-iscsiroot.sh
@@ -92,7 +92,7 @@ if [ -n "$netroot" ] && [ "$root" != "/dev/root" ] && [ "$root" != "dhcp" ]; the
     fi
 fi
 
-if [ -n "$iscsi_firmware" ] ; then
+if [ -n "$iscsi_firmware" ] && iscsiadm -m fw; then
     echo "[ -f '/tmp/iscsistarted-firmware' ]" > $hookdir/initqueue/finished/iscsi_started.sh
 else
     netroot_enc=$(str_replace "$netroot" '/' '\2f')
-- 
1.8.4.5

