]> git.ipfire.org Git - thirdparty/dracut.git/commitdiff
95iscsi: Replace iscsistart with iscsid
authorDaniel Molkentin <dmolkentin@suse.com>
Thu, 26 Apr 2018 13:03:29 +0000 (15:03 +0200)
committerHarald Hoyer <harald@redhat.com>
Wed, 4 Jul 2018 11:05:56 +0000 (13:05 +0200)
This allows to setup multiple paths to targets, which is
required for iscsi multipath.

modules.d/95iscsi/cleanup-iscsi.sh
modules.d/95iscsi/iscsiroot.sh
modules.d/95iscsi/iscsistart-flocked.sh [deleted file]
modules.d/95iscsi/module-setup.sh
modules.d/95iscsi/parse-iscsiroot.sh

index e97d65ac48738f2b85dd8370a3e15c453303a7ea..bfc8aefc588ff37b1b216cb961f58897394d275e 100755 (executable)
@@ -1,4 +1,4 @@
 #!/bin/sh
 
-[ -e /sys/module/bnx2i ] && killproc iscsiuio
+[ -z "${DRACUT_SYSTEMD}" ] && [ -e /sys/module/bnx2i ] && killproc iscsiuio
 
index f7c99a603b1aa04ca3ece44a2d8e8e3d9d38f82e..3a2463f547d93218c6544d0f116cf8945a26c4d4 100755 (executable)
@@ -36,31 +36,52 @@ iroot=${iroot#:}
 # figured out a way how to check whether this is built-in or not
 modprobe crc32c 2>/dev/null
 
-if [ -e /sys/module/bnx2i ] && ! [ -e /tmp/iscsiuio-started ]; then
+if [ -z "${DRACUT_SYSTEMD}" ] && [ -e /sys/module/bnx2i ] && ! [ -e /tmp/iscsiuio-started ]; then
         iscsiuio
         > /tmp/iscsiuio-started
 fi
 
+#set value for initial login retry
+set_login_retries() {
+    local default retries
+    default=2
+    retries=$(getarg rd.iscsilogin.retries)
+    return ${retries:-$default}
+}
+
 handle_firmware()
 {
-    if ! iscsistart-flocked -f; then
-        warn "iscistart: Could not get list of targets from firmware. Skipping."
-        echo 'skipped' > "/tmp/iscsistarted-firmware"
-        return 0
-    fi
-
-    for p in $(getargs rd.iscsi.param -d iscsi_param); do
-       iscsi_param="$iscsi_param --param $p"
-    done
+    local ifaces retry
+
+    # Depending on the 'ql4xdisablesysfsboot' qla4xxx
+    # will be autostarting sessions without presenting
+    # them via the firmware interface.
+    # In these cases 'iscsiadm -m fw' will fail, but
+    # the iSCSI sessions will still be present.
+    if ! iscsiadm -m fw; then
+        warn "iscsiadm: Could not get list of targets from firmware."
+    else
+        ifaces=( $(echo /sys/firmware/ibft/ethernet*) )
+        retry=$(cat /tmp/session-retry)
+
+        if [ $retry -lt ${#ifaces[*]} ]; then
+            let retry++
+            echo $retry > /tmp/session-retry
+            return 1
+        else
+            rm /tmp/session-retry
+        fi
 
-    if ! iscsistart-flocked -b $iscsi_param; then
-        warn "'iscsistart -b $iscsi_param' failed with return code $?"
+        if ! iscsiadm -m fw -l; then
+            warn "iscsiadm: Log-in to iscsi target failed"
+        else
+            need_shutdown
+        fi
     fi
-
+    [ -d /sys/class/iscsi_session ] || return 1
     echo 'started' > "/tmp/iscsistarted-iscsi:"
     echo 'started' > "/tmp/iscsistarted-firmware"
 
-    need_shutdown
     return 0
 }
 
@@ -72,13 +93,13 @@ handle_netroot()
     local iscsi_username iscsi_password
     local iscsi_in_username iscsi_in_password
     local iscsi_iface_name iscsi_netdev_name
-    local iscsi_param
+    local iscsi_param param
     local p
 
     # 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
@@ -95,7 +116,7 @@ handle_netroot()
     arg=$(getarg rd.iscsi.in.password -d iscsi_in_password=)
     [ -n "$arg" ] && iscsi_in_password=$arg
     for p in $(getargs rd.iscsi.param -d iscsi_param); do
-       iscsi_param="$iscsi_param --param $p"
+       iscsi_param="$iscsi_param $p"
     done
 
     parse_iscsi_root "$1" || return 1
@@ -105,6 +126,15 @@ handle_netroot()
         ip route get "$iscsi_target_ip" >/dev/null 2>&1 || return 0
     fi
 
+    #limit iscsistart login retries
+    if [[ ! "$iscsi_param" =~ "node.session.initial_login_retry_max" ]]; then
+        set_login_retries
+        retries=$?
+        if [ $retries -gt 0 ]; then
+            iscsi_param="${iscsi_param% } node.session.initial_login_retry_max=$retries"
+        fi
+    fi
+
 # XXX is this needed?
     getarg ro && iscsirw=ro
     getarg rw && iscsirw=rw
@@ -117,6 +147,11 @@ handle_netroot()
            mkdir -p /etc/iscsi
            ln -fs /run/initiatorname.iscsi /etc/iscsi/initiatorname.iscsi
            > /tmp/iscsi_set_initiator
+           if [ -n "$DRACUT_SYSTEMD" ]; then
+               systemctl try-restart iscsid
+               # FIXME: iscsid is not yet ready, when the service is :-/
+               sleep 1
+           fi
     fi
 
     if [ -z "$iscsi_initiator" ]; then
@@ -133,6 +168,11 @@ handle_netroot()
         mkdir -p /etc/iscsi
         ln -fs /run/initiatorname.iscsi /etc/iscsi/initiatorname.iscsi
         > /tmp/iscsi_set_initiator
+        if [ -n "$DRACUT_SYSTEMD" ]; then
+            systemctl try-restart iscsid
+            # FIXME: iscsid is not yet ready, when the service is :-/
+            sleep 1
+        fi
     fi
 
 
@@ -153,6 +193,11 @@ handle_netroot()
     if ! [ -e /etc/iscsi/initiatorname.iscsi ]; then
         mkdir -p /etc/iscsi
         ln -fs /run/initiatorname.iscsi /etc/iscsi/initiatorname.iscsi
+        if [ -n "$DRACUT_SYSTEMD" ]; then
+            systemctl try-restart iscsid
+            # FIXME: iscsid is not yet ready, when the service is :-/
+            sleep 1
+        fi
     fi
 # FIXME $iscsi_protocol??
 
@@ -168,46 +213,37 @@ handle_netroot()
             echo "iscsi_lun=$iscsi_lun . /bin/mount-lun.sh " > $hookdir/mount/01-$$-iscsi.sh
     fi
 
-    if [ -n "$DRACUT_SYSTEMD" ] && command -v systemd-run >/dev/null 2>&1; then
-        netroot_enc=$(systemd-escape "iscsistart_${1}")
-        status=$(systemctl is-active "$netroot_enc" 2>/dev/null)
-        is_active=$?
-        if [ $is_active -ne 0 ]; then
-            if [ "$status" != "activating" ] && ! systemctl is-failed "$netroot_enc" >/dev/null 2>&1; then
-                systemd-run --no-block --service-type=oneshot --remain-after-exit --quiet \
-                            --description="Login iSCSI Target $iscsi_target_name" \
-                            -p 'DefaultDependencies=no' \
-                            --unit="$netroot_enc" -- \
-                            $(command -v iscsistart-flocked) \
-                            -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} >/dev/null 2>&1 \
-                   && { > $hookdir/initqueue/work ; }
+    ### ToDo: Upstream calls systemd-run - Shall we, do we have to port this?
+
+    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
-                systemctl --no-block restart "$netroot_enc" >/dev/null 2>&1 \
-                   && { > $hookdir/initqueue/work ; }
+                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" ] && for param in $iscsi_param; do $($COMMAND --name=${param%=*} --value=${param#*=}); done
         fi
-    else
-        iscsistart-flocked -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} \
-           && { > $hookdir/initqueue/work ; }
-    fi
+    done
+
+    iscsiadm -m node -L onboot || :
+    > $hookdir/initqueue/work
+
     netroot_enc=$(str_replace "$1" '/' '\2f')
     echo 'started' > "/tmp/iscsistarted-iscsi:${netroot_enc}"
     return 0
@@ -215,12 +251,21 @@ handle_netroot()
 
 ret=0
 
-if [ "$netif" != "timeout" ] && getargbool 1 rd.iscsi.waitnet; then
+if [ "$netif" != "timeout" ] && getargbool 0 rd.iscsi.waitnet; then
     all_ifaces_setup || exit 0
 fi
 
+if [ "$netif" = "timeout" ] && all_ifaces_setup; then
+    # s.th. went wrong and the timeout script hits
+    # restart
+    systemctl restart iscsid
+    # damn iscsid is not ready after unit says it's ready
+    sleep 2
+fi
+
 if getargbool 0 rd.iscsi.firmware -d -y iscsi_firmware ; then
-    if [ "$netif" = "timeout" ] || [ "$netif" = "online" ]; then
+    if [ "$netif" = "timeout" ] || [ "$netif" = "online" ] || [ "$netif" = "dummy" ]; then
+        [ -f /tmp/session-retry ] || echo 1 > /tmp/session-retry
         handle_firmware
         ret=$?
     fi
diff --git a/modules.d/95iscsi/iscsistart-flocked.sh b/modules.d/95iscsi/iscsistart-flocked.sh
deleted file mode 100755 (executable)
index 6366335..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-{
-    flock -e 9
-    iscsistart "$@"
-} 9>/tmp/.iscsi_lock
index 5c47750a5f0581d9ec0ebb21fa0614c39f9a0bc3..d8405fcec3e8788652200311a9dd00ce5d0bebcc 100755 (executable)
@@ -4,7 +4,7 @@
 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.
@@ -61,7 +61,7 @@ install_ibft() {
         fi
         if [ -d ${d}/initiator ] ; then
             if [ ${d##*/} = "ibft" ] && [ "$ibft_mod" != "bnx2i" ] ; then
-                echo -n "ip=ibft "
+                echo -n "rd.iscsi.ibft=1 "
             fi
             echo -n "rd.iscsi.firmware=1"
         fi
@@ -70,7 +70,7 @@ install_ibft() {
 
 install_iscsiroot() {
     local devpath=$1
-    local scsi_path iscsi_lun session c d conn
+    local scsi_path iscsi_lun session c d conn host flash
     local iscsi_session iscsi_address iscsi_port iscsi_targetname iscsi_tpgt
 
     scsi_path=${devpath%%/block*}
@@ -81,6 +81,19 @@ install_iscsiroot() {
     [ "$session" = "$devpath" ] && return 1
     iscsi_session=${session##*/}
     [ "$iscsi_session" = "$session" ] && return 1
+    host=${session%%/session*}
+    [ "$host" = "$session" ] && return 1
+    iscsi_host=${host##*/}
+
+    for flash in ${host}/flashnode_sess-* ; do
+        is_boot=$(cat $flash/is_boot_target)
+        if [ $is_boot -eq 1 ] ; then
+            # qla4xxx flashnode session; skip iBFT discovery
+            iscsi_initiator=$(cat /sys/class/iscsi_host/${iscsi_host}/initiatorname)
+            echo "rd.iscsi.initiator=${iscsi_initiator}"
+            return;
+        fi
+    done
 
     for d in ${session}/* ; do
         case $d in
@@ -104,7 +117,14 @@ install_iscsiroot() {
     [ -z "$iscsi_address" ] && return
     local_address=$(ip -o route get to $iscsi_address | sed -n 's/.*src \([0-9a-f.:]*\).*/\1/p')
     ifname=$(ip -o route get to $iscsi_address | sed -n 's/.*dev \([^ ]*\).*/\1/p')
-    printf 'ip=%s:static ' ${ifname}
+
+    #follow ifcfg settings for boot protocol
+    bootproto=$(sed -n "/BOOTPROTO/s/BOOTPROTO='\([[:alpha:]]*6\?\)4\?'/\1/p" /etc/sysconfig/network/ifcfg-$ifname)
+    if [ $bootproto ]; then
+        printf 'ip=%s:%s ' ${ifname} ${bootproto}
+    else
+        printf 'ip=%s:static ' ${ifname}
+    fi
 
     if [ -e /sys/class/net/$ifname/address ] ; then
         ifmac=$(cat /sys/class/net/$ifname/address)
@@ -128,6 +148,7 @@ install_iscsiroot() {
         # can sort out rd.iscsi.initiator= duplicates
         echo "rd.iscsi.initiator=${iscsi_initiator}"
         echo "netroot=iscsi:${iscsi_address}::${iscsi_port}:${iscsi_lun}:${iscsi_targetname}"
+        echo "rd.neednet=1"
     fi
     return 0
 }
@@ -159,15 +180,14 @@ installkernel() {
     local _arch=$(uname -m)
     local _funcs='iscsi_register_transport'
 
-    instmods bnx2i qla4xxx cxgb3i cxgb4i be2iscsi
+    instmods bnx2i qla4xxx cxgb3i cxgb4i be2iscsi qedi
     hostonly="" instmods iscsi_tcp iscsi_ibft crc32c iscsi_boot_sysfs
 
     if [ "$_arch" = "s390" -o "$_arch" = "s390x" ]; then
         _s390drivers="=drivers/s390/scsi"
     fi
 
-    dracut_instmods -o -s "$_funcs" "=drivers/scsi" ${_s390drivers:+"$_s390drivers"}
-
+    dracut_instmods -o -s ${_funcs} =drivers/scsi ${_s390drivers:+"$_s390drivers"}
 }
 
 # called by dracut
@@ -184,9 +204,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
@@ -194,12 +227,42 @@ install() {
         [[ $_iscsiconf ]] && printf "%s\n" "$_iscsiconf" >> "${initdir}/etc/cmdline.d/95iscsi.conf"
     fi
 
-    inst "$moddir/iscsistart-flocked.sh" "/bin/iscsistart-flocked"
     inst_hook cmdline 90 "$moddir/parse-iscsiroot.sh"
     inst_hook cleanup 90 "$moddir/cleanup-iscsi.sh"
     inst "$moddir/iscsiroot.sh" "/sbin/iscsiroot"
     if ! dracut_module_included "systemd"; then
         inst "$moddir/mount-lun.sh" "/bin/mount-lun.sh"
+    else
+        inst_multiple -o \
+                      $systemdsystemunitdir/iscsi.service \
+                      $systemdsystemunitdir/iscsid.service \
+                      $systemdsystemunitdir/iscsid.socket \
+                      $systemdsystemunitdir/iscsiuio.service \
+                      $systemdsystemunitdir/iscsiuio.socket \
+                      iscsiadm iscsid
+
+        mkdir -p "${initdir}/$systemdsystemunitdir/sockets.target.wants"
+        for i in \
+                iscsiuio.socket \
+            ; do
+            ln_r "$systemdsystemunitdir/${i}" "$systemdsystemunitdir/sockets.target.wants/${i}"
+        done
+
+        mkdir -p "${initdir}/$systemdsystemunitdir/basic.target.wants"
+        for i in \
+                iscsid.service \
+                iscsiuio.service \
+            ; do
+            ln_r "$systemdsystemunitdir/${i}" "$systemdsystemunitdir/basic.target.wants/${i}"
+        done
+
+        # Make sure iscsid is started after dracut-cmdline and ready for the initqueue
+        mkdir -p "${initdir}/$systemdsystemunitdir/iscsid.service.d"
+        (
+            echo "[Unit]"
+            echo "After=dracut-cmdline.service"
+            echo "Before=dracut-initqueue.service"
+        ) > "${initdir}/$systemdsystemunitdir/iscsid.service.d/dracut.conf"
     fi
     inst_dir /var/lib/iscsi
     dracut_need_initqueue
index c8c66ccf4e4a9f51dd6539fed1bc81083a772ffb..f884e6847295f2d9768951ca09a2b1d24d716a5d 100755 (executable)
@@ -96,7 +96,7 @@ fi
 
 initqueue --unique --onetime --timeout /sbin/iscsiroot timeout "$netroot" "$NEWROOT"
 
-initqueue --onetime modprobe --all -b -q qla4xxx cxgb3i cxgb4i bnx2i be2iscsi
+initqueue --onetime modprobe --all -b -q qla4xxx cxgb3i cxgb4i bnx2i be2iscsi qedi
 
 # ISCSI actually supported?
 if ! [ -e /sys/module/iscsi_tcp ]; then
@@ -116,6 +116,11 @@ if arg=$(getarg rd.iscsi.initiator -d iscsi_initiator=) && [ -n "$arg" ] && ! [
     if ! [ -e /etc/iscsi/initiatorname.iscsi ]; then
         mkdir -p /etc/iscsi
         ln -fs /run/initiatorname.iscsi /etc/iscsi/initiatorname.iscsi
+        if [ -n "$DRACUT_SYSTEMD" ]; then
+            systemctl try-restart iscsid
+            # FIXME: iscsid is not yet ready, when the service is :-/
+            sleep 1
+        fi
     fi
 fi
 
@@ -128,6 +133,11 @@ if [ -z $iscsi_initiator ] && [ -f /sys/firmware/ibft/initiator/initiator-name ]
         mkdir -p /etc/iscsi
         ln -fs /run/initiatorname.iscsi /etc/iscsi/initiatorname.iscsi
         > /tmp/iscsi_set_initiator
+        if [ -n "$DRACUT_SYSTEMD" ]; then
+            systemctl try-restart iscsid
+            # FIXME: iscsid is not yet ready, when the service is :-/
+            sleep 1
+        fi
     fi
 fi