# 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.<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: [email protected]
http://lists.linux-ha.org/mailman/listinfo/linux-ha-dev
Home Page: http://linux-ha.org/