]> git.ipfire.org Git - thirdparty/dracut.git/commitdiff
iscsi: integrate with systemd and improve robustness
authorHarald Hoyer <harald@redhat.com>
Wed, 12 Aug 2015 12:33:49 +0000 (14:33 +0200)
committerHarald Hoyer <harald@redhat.com>
Wed, 12 Aug 2015 12:33:49 +0000 (14:33 +0200)
parse-cmdline sets up an initial initiator-name to let iscsid start.

iscsid is started before doing any iscsistart business.

iscsistart is done with systemd-run asynchrone to do things in
paralllel. Also restarted for every new interface which shows up.

If rd.iscsi.waitnet (default) is set, iscsistart is done only
after all interfaces are up.

If not all interfaces are up and rd.iscsi.testroute (default) is set,
the route to a iscsi target IP is checked and skipped, if there is none.

If all things fail, we issue a "dummy" interface iscsiroot to retry
everything in the initqueue/timeout.

modules.d/95iscsi/cleanup-iscsi.sh
modules.d/95iscsi/iscsiroot.sh
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 460e4386decd1be5461d34ad6dce5b0db285e77b..fc624259d7e6806bfeb7ad9e53ccd41f7b3ee861 100755 (executable)
@@ -36,7 +36,7 @@ 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
@@ -105,28 +105,47 @@ handle_netroot()
 
     parse_iscsi_root "$1" || return 1
 
+    # Bail out early, if there is no route to the destination
+    if is_ip "$iscsi_target_ip" && [ "$netif" != "dummy" ] && ! all_ifaces_up && getargbool 1 rd.iscsi.testroute; then
+        ip route get "$iscsi_target_ip" >/dev/null 2>&1 || return 0
+    fi
+
 # XXX is this needed?
     getarg ro && iscsirw=ro
     getarg rw && iscsirw=rw
     fsopts=${fsopts:+$fsopts,}${iscsirw}
 
+    if [ -z $iscsi_initiator ] && [ -f /sys/firmware/ibft/initiator/initiator-name ] && ! [ -f /tmp/iscsi_set_initiator ]; then
+           iscsi_initiator=$(while read line || [ -n "$line" ]; do echo $line;done < /sys/firmware/ibft/initiator/initiator-name)
+           echo "InitiatorName=$iscsi_initiator" > /run/initiatorname.iscsi
+           rm -f /etc/iscsi/initiatorname.iscsi
+           mkdir -p /etc/iscsi
+           ln -fs /run/initiatorname.iscsi /etc/iscsi/initiatorname.iscsi
+           systemctl restart iscsid
+           sleep 1
+           > /tmp/iscsi_set_initiator
+    fi
+
     if [ -z $iscsi_initiator ]; then
-    # XXX Where are these from?
+        [ -f /run/initiatorname.iscsi ] && . /run/initiatorname.iscsi
         [ -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 || [ -n "$line" ]; do echo $line;done < /sys/firmware/ibft/initiator/initiator-name)
-       fi
+        iscsi_initiator=$(iscsi-iname)
+        echo "InitiatorName=$iscsi_initiator" > /run/initiatorname.iscsi
+        rm -f /etc/iscsi/initiatorname.iscsi
+        mkdir -p /etc/iscsi
+        ln -fs /run/initiatorname.iscsi /etc/iscsi/initiatorname.iscsi
+        systemctl restart iscsid
+        > /tmp/iscsi_set_initiator
+        # FIXME: iscsid is not yet ready, when the service is :-/
+        sleep 1
     fi
 
+
     if [ -z $iscsi_target_port ]; then
         iscsi_target_port=3260
     fi
@@ -135,23 +154,21 @@ handle_netroot()
         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'" > /run/initiatorname.iscsi
+    echo "InitiatorName=$iscsi_initiator" > /run/initiatorname.iscsi
     ln -fs /run/initiatorname.iscsi /dev/.initiatorname.iscsi
-
+    if ! [ -e /etc/iscsi/initiatorname.iscsi ]; then
+        mkdir -p /etc/iscsi
+        ln -fs /run/initiatorname.iscsi /etc/iscsi/initiatorname.iscsi
+    fi
 # FIXME $iscsi_protocol??
 
-    if [ "$root" = "dhcp" ]; then
+    if [ "$root" = "dhcp" ] || [ "$netroot" = "dhcp" ]; 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.rules
+        printf 'SYMLINK=="disk/by-path/*-iscsi-*-%s", SYMLINK+="root"\n' "$iscsi_lun" >> /etc/udev/rules.d/99-iscsi-root.rules
         udevadm control --reload
         write_fs_tab /dev/root
         wait_for_dev -n /dev/root
@@ -161,29 +178,58 @@ handle_netroot()
             echo "iscsi_lun=$iscsi_lun . /bin/mount-lun.sh " > $hookdir/mount/01-$$-iscsi.sh
     fi
 
-    # 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 [ -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" \
+                            --unit="$netroot_enc" -- \
+                            $(command -v 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} >/dev/null 2>&1
+            else
+                systemctl --no-block restart "$netroot_enc" >/dev/null 2>&1
+            fi
+        fi
+    else
+        > $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} \
+           || :
+    fi
     netroot_enc=$(str_replace "$1" '/' '\2f')
     echo 'started' > "/tmp/iscsistarted-iscsi:${netroot_enc}"
+    return 0
 }
 
 ret=0
 
+if [ "$netif" != "dummy" ] && getargbool 1 rd.iscsi.waitnet; then
+    all_ifaces_up || exit 0
+fi
+
 # loop over all netroot parameter
-if getarg netroot; then
+netroot=$(getarg netroot)
+if [ $? -eq 0 ] && [ "$netroot" != "dhcp" ]; then
     for nroot in $(getargs netroot); do
         [ "${nroot%%:*}" = "iscsi" ] || continue
         nroot="${nroot##iscsi:}"
@@ -210,6 +256,6 @@ fi
 
 need_shutdown
 
-# now we have a root filesystem somewhere in /dev/sda*
+# now we have a root filesystem somewhere in /dev/sd*
 # let the normal block handler handle root=
 exit $ret
index 406a9da054035d893d1270c814c833f02510062a..3002591582f22e2eaa3be3234e62068a48893b5a 100755 (executable)
@@ -226,6 +226,37 @@ install() {
     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 \
+            ; 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
+
     dracut_need_initqueue
 }
index 52f7a97d7fa958e3e69aeb4579b42a9f7b16f5b1..2532adac351a5f2ba17727d98e130c62fb648cb8 100755 (executable)
@@ -62,9 +62,10 @@ if [ -n "$iscsi_firmware" ] ; then
     [ -z "$netroot" ] && netroot=iscsi:
     modprobe -b -q iscsi_boot_sysfs 2>/dev/null
     modprobe -b -q iscsi_ibft
-    initqueue --onetime --timeout /sbin/iscsiroot dummy "$netroot" "$NEWROOT"
 fi
 
+initqueue --onetime --timeout /sbin/iscsiroot dummy "$netroot" "$NEWROOT"
+
 # If it's not iscsi we don't continue
 [ "${netroot%%:*}" = "iscsi" ] || return
 
@@ -86,6 +87,16 @@ if [ -n "$netroot" ] && [ "$root" != "/dev/root" ] && [ "$root" != "dhcp" ]; the
     fi
 fi
 
+if arg=$(getarg rd.iscsi.initiator -d iscsi_initiator=) && [ -n "$arg" ]; then
+    iscsi_initiator=$arg
+    echo "InitiatorName=$iscsi_initiator" > /run/initiatorname.iscsi
+    ln -fs /run/initiatorname.iscsi /dev/.initiatorname.iscsi
+    if ! [ -e /etc/iscsi/initiatorname.iscsi ]; then
+        mkdir -p /etc/iscsi
+        ln -fs /run/initiatorname.iscsi /etc/iscsi/initiatorname.iscsi
+    fi
+fi
+
 if [ -n "$iscsi_firmware" ] ; then
     echo "[ -f '/tmp/iscsistarted-firmware' ]" > $hookdir/initqueue/finished/iscsi_started.sh
 else