# HG changeset patch
# User Florian Haas <[email protected]>
# Date 1246859908 -7200
# Node ID 8132bf3e995fe0cc6f5124985d864f82a1d88ee0
# Parent  ed09fd5d12fb494f94026bf01a5e3f16cbde5470
RA: iSCSITarget, iSCSILogicalUnit: identify targets by IQN

While implementing LIO functionality for these RAs, I noticed a design
flaw in the existing RAs: They identify a target by a numeric "target
ID", which is actually IET/stgt specific and not supported in LIO (and
presumably, other target implementations). So, I've rewritten these
agents to identify and reference targets by iSCSI Qualified Name
(IQN).

As a consequence:

- the iSCSITarget parameter previously named "name" (which was stupid
  and ambigious, anyway) is now named "iqn";

- the iSCSITarget parameter "tid" has gone away. Instead, where the
  implementation requires it, a "target ID" is discerned on the fly;

- the iSCSILogicalUnit resource parameter "tid" has also gone away;

- iSCSILogicalUnit now has a required parameter "target_iqn", which is
  to hold the target IQN and is, of course, used to assign the LU to
  an existing target.

Sorry for not realizing this design flaw sooner; this makes the patch
much more disruptive than the incremental patches I usually try to
submit. On the plus side, at least this hasn't yet been rolled into an
official release, so shouldn't be affecting any production systems.

Cheers,
Florian

diff -r ed09fd5d12fb -r 8132bf3e995f resources/OCF/iSCSILogicalUnit
--- a/resources/OCF/iSCSILogicalUnit    Thu Jul 02 16:48:03 2009 +0200
+++ b/resources/OCF/iSCSILogicalUnit    Mon Jul 06 07:58:28 2009 +0200
@@ -67,12 +67,12 @@
 <content type="string" default="${OCF_RESKEY_implementation_default}"/>
 </parameter>
 
-<parameter name="tid" required="1" unique="0">
+<parameter name="target_iqn" required="1" unique="0">
 <longdesc lang="en">
-The numeric target ID. Must not be zero.
+The iSCSI Qualified Name (IQN) that this Logical Unit belongs to.
 </longdesc>
-<shortdesc lang="en">iSCSI target ID</shortdesc>
-<content type="integer" />
+<shortdesc lang="en">iSCSI target IQN</shortdesc>
+<content type="string" />
 </parameter>
 
 <parameter name="lun" required="1" unique="0">
@@ -193,8 +193,15 @@
 
     case $OCF_RESKEY_implementation in
        iet)
+           params="Path=${OCF_RESKEY_path}"
+           # use blockio if path points to a block device, fileio
+           # otherwise.
+           if [ -b "${OCF_RESKEY_path}" ]; then
+               params="${params} Type=blockio"
+           else
+               params="${params} Type=fileio"
+           fi
            # in IET, we have to set LU parameters on creation
-           params="Path=${OCF_RESKEY_path}"
            if [ -n "${OCF_RESKEY_scsi_id}" ]; then
                params="${params} ScsiId=${OCF_RESKEY_scsi_id}"
            fi
@@ -203,7 +210,7 @@
            fi
            params="${params} ${OCF_RESKEY_additional_parameters}"
            do_cmd ietadm --op new \
-               --tid=${OCF_RESKEY_tid} \
+               --tid=${TID} \
                --lun=${OCF_RESKEY_lun} \
                --params ${params// /,} && return $OCF_SUCCESS
            ;;
@@ -221,14 +228,14 @@
            done
            params="${params} ${OCF_RESKEY_additional_parameters}"
            do_cmd tgtadm --lld iscsi --op new --mode logicalunit \
-               --tid=${OCF_RESKEY_tid} \
+               --tid=${TID} \
                --lun=${OCF_RESKEY_lun} \
                --backing-store ${OCF_RESKEY_path} || return $OCF_ERR_GENERIC
            if [ -z "$params" ]; then
                return $OCF_SUCCESS
            else
                do_cmd tgtadm --lld iscsi --op update --mode logicalunit \
-                   --tid=${OCF_RESKEY_tid} \
+                   --tid=${TID} \
                    --lun=${OCF_RESKEY_lun} \
                    --params ${params// /,} && return $OCF_SUCCESS
            fi
@@ -244,7 +251,7 @@
            iet)
                # IET allows us to remove LUs while they are in use
                do_cmd ietadm --op delete \
-                   --tid=${OCF_RESKEY_tid} \
+                   --tid=${TID} \
                    --lun=${OCF_RESKEY_lun} && return $OCF_SUCCESS
                ;;
            tgt)
@@ -255,7 +262,7 @@
                # decides that the LU is no longer in use, or we get
                # timed out by the LRM.
                while ! do_cmd tgtadm --lld iscsi --op delete --mode 
logicalunit \
-                   --tid ${OCF_RESKEY_tid} \
+                   --tid ${TID} \
                    --lun=${OCF_RESKEY_lun}; do
                    sleep 1
                done
@@ -271,11 +278,26 @@
 iSCSILogicalUnit_monitor() {
     case $OCF_RESKEY_implementation in
        iet)
+           # Figure out and set the target ID
+           TID=`sed -ne "s/tid:\([[:digit:]]\+\) 
name:${OCF_RESKEY_target_iqn}/\1/p" < /proc/net/iet/volume`
+           if [ -z "${TID}" ]; then
+               # Our target is not configured, thus we're not
+               # running.
+               return $OCF_NOT_RUNNING
+           fi
            # FIXME: this looks for a matching LUN and path, but does
            # not actually test for the correct target ID.
            grep -E -q 
"[[:space:]]+lun:${OCF_RESKEY_lun}.*path:${OCF_RESKEY_path}" 
/proc/net/iet/volume && return $OCF_SUCCESS
            ;;
        tgt)
+           # Figure out and set the target ID
+           TID=`tgtadm --lld iscsi --op show --mode target \
+               | sed -ne "s/^Target \([[:digit:]]\+\): 
${OCF_RESKEY_target_iqn}/\1/p"`
+           if [ -z "$TID" ]; then
+               # Our target is not configured, thus we're not
+               # running.
+               return $OCF_NOT_RUNNING
+           fi
            # This only looks for the backing store, but does not test
            # for the correct target ID and LUN.
            tgtadm --lld iscsi --op show --mode target \
@@ -288,7 +310,7 @@
 
 iSCSILogicalUnit_validate() {
     # Do we have all required variables?
-    for var in implementation tid lun path; do
+    for var in implementation target_iqn lun path; do
        param="OCF_RESKEY_${var}"
        if [ -z "${!param}" ]; then
            ocf_log error "Missing resource parameter \"$var\"!"
@@ -310,21 +332,6 @@
            return $OCF_ERR_CONFIGURED
     esac
 
-    # Do we have a valid target ID?
-    [ $OCF_RESKEY_tid -ge 1 ]
-    case $? in
-       0)
-           # OK
-           ;;
-       1)
-           ocf_log err "Invalid target ID $OCF_RESKEY_tid (must be greater 
than 0)."
-           return $OCF_ERR_CONFIGURED
-           ;;
-       *)
-           ocf_log err "Invalid target ID $OCF_RESKEY_tid (must be an 
integer)."
-           return $OCF_ERR_CONFIGURED
-    esac
-
     # Do we have a valid LUN?
     case $OCF_RESKEY_implementation in
        iet)
diff -r ed09fd5d12fb -r 8132bf3e995f resources/OCF/iSCSITarget
--- a/resources/OCF/iSCSITarget Thu Jul 02 16:48:03 2009 +0200
+++ b/resources/OCF/iSCSITarget Mon Jul 06 07:58:28 2009 +0200
@@ -67,20 +67,12 @@
 <content type="string" default="${OCF_RESKEY_implementation_default}"/>
 </parameter>
 
-<parameter name="tid" required="1" unique="0">
+<parameter name="iqn" required="1" unique="1">
 <longdesc lang="en">
-The numeric target ID. Must not be zero.
-</longdesc>
-<shortdesc lang="en">iSCSI target ID</shortdesc>
-<content type="integer" />
-</parameter>
-
-<parameter name="name" required="1" unique="1">
-<longdesc lang="en">
-The logical target name. Should follow the conventional
+The target iSCSI Qualified Name (IQN). Should follow the conventional
 "iqn.yyyy-mm.&lt;reversed domain name&gt;[:identifier]" syntax.
 </longdesc>
-<shortdesc lang="en">iSCSI target name</shortdesc>
+<shortdesc lang="en">iSCSI target IQN</shortdesc>
 <content type="string" />
 </parameter>
 
@@ -185,43 +177,62 @@
 
     case $OCF_RESKEY_implementation in
        iet)
+           local lasttid
+           local tid
+           # Figure out the last used target ID, add 1 to get the new
+           # target ID.
+           lasttid=`sed -ne "s/tid:\([[:digit:]]\+\) name:.*/\1/p" < 
/proc/net/iet/volume | sort -n | tail -n1`
+           [ -z "${lasttid}" ] && lasttid=0
+           tid=$((++lasttid))
+           # Create the target.
            do_cmd ietadm --op new \
-               --tid=${OCF_RESKEY_tid} \
-               --params Name=${OCF_RESKEY_name} || return $OCF_ERR_GENERIC
+               --tid=${tid} \
+               --params Name=${OCF_RESKEY_iqn} || return $OCF_ERR_GENERIC
+           # Set additional parameters.
            for param in ${OCF_RESKEY_additional_parameters}; do
                name=${param%=*}
                value=${param#*=}
                do_cmd ietadm --op update \
-                   --tid=${OCF_RESKEY_tid} \
+                   --tid=${tid} \
                    --params ${name}=${value} || return $OCF_ERR_GENERIC
            done
            # For iet, access to new targets is allowed by default. To
            # specifically enable access based on initiator address,
            # we must first deny access to the target globally, then
            # re-enable by specific initiator.
-           if [ -n ${OCF_RESKEY_allowed_initiators} ]; then
-               echo "${OCF_RESKEY_name} ALL" >> /etc/initiators.deny
-               echo "${OCF_RESKEY_name} ${OCF_RESKEY_initiators// /,}" >> 
/etc/initiators.allow
+           if [ -n "${OCF_RESKEY_allowed_initiators}" ]; then
+               echo "${OCF_RESKEY_iqn} ALL" >> /etc/initiators.deny
+               echo "${OCF_RESKEY_iqn} ${OCF_RESKEY_allowed_initiators// /,}" 
>> /etc/initiators.allow
            fi
            # In iet, adding a new user and assigning it to a target
            # is one operation.
            if [ -n "${OCF_RESKEY_username}" ]; then
                do_cmd ietadm --op new --user \
-                   --tid=${OCF_RESKEY_tid} \
+                   --tid=${tid} \
                    
--params=IncomingUser=${OCF_RESKEY_username},Password=${OCF_RESKEY_password} \
                    || return $OCF_ERR_GENERIC
            fi
            return $OCF_SUCCESS
            ;;
        tgt)
+           local lasttid
+           local tid
+           # Figure out the last used target ID, add 1 to get the new
+           # target ID.
+           lasttid=`tgtadm --lld iscsi --op show --mode target \
+                | sed -ne "s/^Target \([[:digit:]]\+\): .*/\1/p" | sort -n | 
tail -n1`
+           [ -z "${lasttid}" ] && lasttid=0
+           tid=$((++lasttid))
+           # Create the target.
            do_cmd tgtadm --lld iscsi --op new --mode target \
-               --tid=${OCF_RESKEY_tid} \
-               --targetname ${OCF_RESKEY_name} || return $OCF_ERR_GENERIC
+               --tid=${tid} \
+               --targetname ${OCF_RESKEY_iqn} || return $OCF_ERR_GENERIC
+           # Set parameters.
            for param in ${OCF_RESKEY_additional_parameters}; do
                name=${param%=*}
                value=${param#*=}
                do_cmd tgtadm --lld iscsi --op update --mode target \
-                   --tid=${OCF_RESKEY_tid} \
+                   --tid=${tid} \
                    --name=${name} --value=${value} || return $OCF_ERR_GENERIC
            done
            # For tgt, we always have to add access per initiator;
@@ -230,7 +241,7 @@
            # keyword ALL.
            for initiator in ${OCF_RESKEY_allowed_initiators=ALL}; do
                do_cmd tgtadm --lld iscsi --op bind --mode target \
-                   --tid=${OCF_RESKEY_tid} \
+                   --tid=${tid} \
                    --initiator-address=${initiator} || return $OCF_ERR_GENERIC
            done
            # In tgt, we must first create a user account, then assign
@@ -240,7 +251,7 @@
                    --user=${OCF_RESKEY_username} \
                    --password=${OCF_RESKEY_password} || return $OCF_ERR_GENERIC
                do_cmd tgtadm --lld iscsi --mode account --op bind \
-                   --tid=${OCF_RESKEY_tid} \
+                   --tid=${tid} \
                    --user=${OCF_RESKEY_username} || return $OCF_ERR_GENERIC
            fi
            return $OCF_SUCCESS
@@ -252,12 +263,19 @@
 iSCSITarget_stop() {
     iSCSITarget_monitor
     if [ $? =  $OCF_SUCCESS ]; then
+       local tid
        case $OCF_RESKEY_implementation in
            iet)
+               # Figure out the target ID
+               tid=`sed -ne "s/tid:\([[:digit:]]\+\) 
name:${OCF_RESKEY_iqn}/\1/p" < /proc/net/iet/volume`
+               if [ -z "${tid}" ]; then
+                   ocf_log err "Failed to retrieve target ID for IQN 
${OCF_RESKEY_iqn}"
+                   return $OCF_ERR_GENERIC
+               fi
                # Close existing connections. There is no other way to
                # do this in IET than to parse the contents of
                # /proc/net/iet/session.
-               set -- $(sed -ne '/^tid:'${OCF_RESKEY_tid}' /,/^tid/ {
+               set -- $(sed -ne '/^tid:'${tid}' /,/^tid/ {
                           /^[[:space:]]*sid:\([0-9]\+\)/ {
                              s/^[[:space:]]*sid:\([0-9]*\).*/--sid=\1/; h;
                           };
@@ -268,35 +286,40 @@
                while [[ -n $2 ]]; do
                     # $2 $1 looks like "--sid=X --cid=Y"
                    do_cmd ietadm --op delete \
-                            --tid=${OCF_RESKEY_tid} $2 $1
+                            --tid=${tid} $2 $1
                    shift 2
                done
                # In iet, unassigning a user from a target and
                # deleting the user account is one operation.
                if [ -n "${OCF_RESKEY_username}" ]; then
                    do_cmd ietadm --op delete --user \
-                       --tid=${OCF_RESKEY_tid} \
+                       --tid=${tid} \
                        --params=IncomingUser=${OCF_RESKEY_username} \
                        || return $OCF_ERR_GENERIC
                fi
                do_cmd ietadm --op delete \
-                   --tid=${OCF_RESKEY_tid} || return $OCF_ERR_GENERIC
-               if [ -n ${OCF_RESKEY_allowed_initiators} ]; then
-                   # Avoid stale /etc/initiators.{allow,deny} entries
-                   # for this target
-                   do_cmd sed -e "/^${OCF_RESKEY_name}[[:space:]]/d" \
-                       -i /etc/initiators.deny
-                   do_cmd sed -e "/^${OCF_RESKEY_name}[[:space:]]/d" \
-                       -i /etc/initiators.allow
-               fi
+                   --tid=${tid} || return $OCF_ERR_GENERIC
+               # Avoid stale /etc/initiators.{allow,deny} entries
+               # for this target
+               do_cmd sed -e "/^${OCF_RESKEY_iqn}[[:space:]]/d" \
+                   -i /etc/initiators.deny
+               do_cmd sed -e "/^${OCF_RESKEY_iqn}[[:space:]]/d" \
+                   -i /etc/initiators.allow
                return $OCF_SUCCESS
                ;;
            tgt)
+               # Figure out the target ID
+               tid=`tgtadm --lld iscsi --op show --mode target \
+                   | sed -ne "s/^Target \([[:digit:]]\+\): 
${OCF_RESKEY_iqn}/\1/p"`
+               if [ -z "$tid" ]; then
+                   ocf_log err "Failed to retrieve target ID for IQN 
${OCF_RESKEY_iqn}"
+                   return $OCF_ERR_GENERIC
+               fi
                # Close existing connections. There is no other way to
                # do this in tgt than to parse the output of "tgtadm --op
                # show".
                set -- $(tgtadm --lld iscsi --op show --mode target \
-                   | sed -ne '/^Target '${OCF_RESKEY_tid}':/,/^Target/ {
+                   | sed -ne '/^Target '${tid}':/,/^Target/ {
                           /^[[:space:]]*I_T nexus: \([0-9]\+\)/ {
                              s/^.*: \([0-9]*\).*/--sid=\1/; h;
                           };
@@ -308,20 +331,20 @@
                while [[ -n $2 ]]; do
                     # $2 $1 looks like "--sid=X --cid=Y"
                    do_cmd tgtadm --lld iscsi --op delete --mode connection \
-                       --tid=${OCF_RESKEY_tid} $2 $1
+                       --tid=${tid} $2 $1
                    shift 2
                done
                # In tgt, we must first unbind the user account from
                # the target, then remove the account itself.
                if [ -n "${OCF_RESKEY_username}" ]; then
                    do_cmd tgtadm --lld iscsi --mode account --op unbind \
-                       --tid=${OCF_RESKEY_tid} \
+                       --tid=${tid} \
                        --user=${OCF_RESKEY_username} || return $OCF_ERR_GENERIC
                    do_cmd tgtadm --lld iscsi --mode account --op delete \
                        --user=${OCF_RESKEY_username} || return $OCF_ERR_GENERIC
                fi
                do_cmd tgtadm --lld iscsi --op delete --mode target \
-                   --tid=${OCF_RESKEY_tid} && return $OCF_SUCCESS
+                   --tid=${tid} && return $OCF_SUCCESS
                # In tgt, we don't have to worry about our ACL
                # entries. They are automatically removed upon target
                # deletion.
@@ -336,11 +359,11 @@
 iSCSITarget_monitor() {
     case $OCF_RESKEY_implementation in
        iet)
-           grep -q "tid:${OCF_RESKEY_tid} name:${OCF_RESKEY_name}" 
/proc/net/iet/volume && return $OCF_SUCCESS
+           grep -Eq "tid:[0-9]+ name:${OCF_RESKEY_iqn}" /proc/net/iet/volume 
&& return $OCF_SUCCESS
            ;;
        tgt)
-           do_cmd tgtadm --lld iscsi --op show --mode target \
-               | grep -q "Target ${OCF_RESKEY_tid}: ${OCF_RESKEY_name}" && 
return $OCF_SUCCESS
+           tgtadm --lld iscsi --op show --mode target \
+               | grep -Eq "Target [0-9]+: ${OCF_RESKEY_iqn}" && return 
$OCF_SUCCESS
            ;;
     esac
     
@@ -349,7 +372,7 @@
 
 iSCSITarget_validate() {
     # Do we have all required variables?
-    for var in implementation tid name; do
+    for var in implementation iqn; do
        param="OCF_RESKEY_${var}"
        if [ -z "${!param}" ]; then
            ocf_log error "Missing resource parameter \"$var\"!"
@@ -371,21 +394,6 @@
            return $OCF_ERR_CONFIGURED
     esac
 
-    # Do we have a valid target ID?
-    [ $OCF_RESKEY_tid -ge 1 ]
-    case $? in
-       0)
-           # OK
-           ;;
-       1)
-           ocf_log err "Invalid target ID $OCF_RESKEY_tid (must be greater 
than 0)."
-           return $OCF_ERR_CONFIGURED
-           ;;
-       *)
-           ocf_log err "Invalid target ID $OCF_RESKEY_tid (must be an 
integer)."
-           return $OCF_ERR_CONFIGURED
-    esac
-
     # Is the required kernel functionality available?
     case $OCF_RESKEY_implementation in
        iet)
_______________________________________________________
Linux-HA-Dev: [email protected]
http://lists.linux-ha.org/mailman/listinfo/linux-ha-dev
Home Page: http://linux-ha.org/

Reply via email to