Applied. Cheers,
Dejan On Mon, Jul 06, 2009 at 07:58:39AM +0200, Florian Haas wrote: > # HG changeset patch > # User Florian Haas <florian.h...@linbit.com> > # 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.<reversed domain name>[: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: Linux-HA-Dev@lists.linux-ha.org > http://lists.linux-ha.org/mailman/listinfo/linux-ha-dev > Home Page: http://linux-ha.org/ _______________________________________________________ Linux-HA-Dev: Linux-HA-Dev@lists.linux-ha.org http://lists.linux-ha.org/mailman/listinfo/linux-ha-dev Home Page: http://linux-ha.org/