--- resource-agents-orig/heartbeat/iSCSITarget	2012-05-25 09:23:59.000000000 -0700
+++ resource-agents/heartbeat/iSCSITarget	2012-07-03 00:21:59.062013980 -0700
@@ -115,12 +115,13 @@
 <content type="string" default=""/>
 </parameter>
 
-<parameter name="incoming_username" required="0" unique="1">
+<parameter name="incoming_username" required="0" unique="0">
 <longdesc lang="en">
 A username used for incoming initiator authentication. If unspecified,
 allowed initiators will be able to log in without authentication.
-This is a unique parameter, as it not allowed to re-use a single
+For IET and TGT this is a unique parameter, as it not allowed to re-use a single
 username across multiple target instances.
+For LIO you may reuse the username.
 </longdesc>
 <shortdesc lang="en">Incoming account username</shortdesc>
 <content type="string"/>
@@ -134,6 +135,55 @@
 <content type="string"/>
 </parameter>
 
+<parameter name="mutualchap_username" required="0" unique="0">
+<longdesc lang="en">
+A username used for incoming Mutual CHAP initiator authentication. If unspecified,
+allowed initiators will be able to log in without Mutual CHAP authentication.
+</longdesc>
+<shortdesc lang="en">Mutual CHAP username</shortdesc>
+<content type="string"/>
+</parameter>
+
+<parameter name="mutualchap_password" required="0" unique="0">
+<longdesc lang="en">
+A password used for Mutual CHAP initiator authentication.
+</longdesc>
+<shortdesc lang="en">Mutual CHAP password</shortdesc>
+<content type="string"/>
+</parameter>
+
+<parameter name="lun" required="0" unique="0">
+<longdesc lang="en">
+The Mapped Logical Unit number (LUN) for Target.
+</longdesc>
+<shortdesc lang="en">Target LUN</shortdesc>
+<content type="integer" />
+</parameter>
+
+<parameter name="tpgt" required="0" unique="0">
+<longdesc lang="en">
+The Target Portal Group Tag
+</longdesc>
+<shortdesc lang="en">Target Portal Group Tag</shortdesc>
+<content type="integer" />
+</parameter>
+
+<parameter name="hba_name" required="0" unique="0">
+<longdesc lang="en">
+The HBA Name used by iSCSILogicalUnit
+</longdesc>
+<shortdesc lang="en">hba_name</shortdesc>
+<content type="string" />
+</parameter>
+
+<parameter name="storage_object_name" required="0" unique="0">
+<longdesc lang="en">
+The storage object name used by iSCSILogicalUnit's OCF_RESOURCE_INSTANCE
+</longdesc>
+<shortdesc lang="en">Storage Object Name</shortdesc>
+<content type="string" />
+</parameter>
+
 <parameter name="additional_parameters" required="0" unique="0">
 <longdesc lang="en">
 Additional target parameters. A space-separated list of "name=value"
@@ -262,51 +312,75 @@
 	    fi
 	    ;;
 	lio)
-	    # lio distinguishes between targets and target portal
-	    # groups (TPGs). We will always create one TPG, with the
-	    # number 1. In lio, creating a network portal
-	    # automatically creates the corresponding target if it
-	    # doesn't already exist.
+	    # Add TPG - before Add LUN
+	    ocf_run lio_node --addtpg=${OCF_RESKEY_iqn} ${OCF_RESKEY_tpgt}
+	    #  Add LUN to HBA
+	    ocf_run lio_node --addlun=${OCF_RESKEY_iqn} ${OCF_RESKEY_tpgt} ${OCF_RESKEY_lun} \
+		${OCF_RESKEY_lun} ${OCF_RESKEY_hba_name}/${OCF_RESKEY_storage_object_name} || exit $OCF_ERR_GENERIC
+	    # Add Network Portal
 	    for portal in ${OCF_RESKEY_portals}; do
-		ocf_run lio_node --addnp ${OCF_RESKEY_iqn} 1 \
+		ocf_run lio_node --addnp ${OCF_RESKEY_iqn} ${OCF_RESKEY_tpgt} \
 		    ${portal} || exit $OCF_ERR_GENERIC
 	    done
-	    # in lio, we can set target parameters by manipulating
-	    # the appropriate configfs entries
-	    for param in ${OCF_RESKEY_additional_parameters}; do
-		name=${param%=*}
-		value=${param#*=}
-		configfs_path="/sys/kernel/config/target/iscsi/${OCF_RESKEY_iqn}/tpgt_1/param/${name}"
-		if [ -e ${configfs_path} ]; then
-		    echo ${value} > ${configfs_path} || exit $OCF_ERR_GENERIC
-		else
-		    ocf_log warn "Unsupported iSCSI target parameter ${name}: will be ignored."
-		fi
-	    done
-	    # lio does per-initiator filtering by default. To disable
-	    # this, we need to switch the target to "permissive mode".
+	    # ACL Mode
+	    if [ -n "${OCF_RESKEY_incoming_username}" ] || [ -n "${OCF_RESKEY_mutualchap_username}" ]; then
+		# enableaclmode is required in case disableaclmode was ever used
+		ocf_run lio_node --enableaclmode ${OCF_RESKEY_iqn} ${OCF_RESKEY_tpgt} || exit $OCF_ERR_GENERIC
+	    else
+		ocf_run lio_node --disableauth ${OCF_RESKEY_iqn} ${OCF_RESKEY_tpgt} || exit $OCF_ERR_GENERIC
+	    fi
+	    # Node ACL
 	    if [ -n "${OCF_RESKEY_allowed_initiators}" ]; then
 		for initiator in ${OCF_RESKEY_allowed_initiators}; do
-		    ocf_run lio_node --addnodeacl ${OCF_RESKEY_iqn} 1 \
+		    ocf_run lio_node --addnodeacl ${OCF_RESKEY_iqn} ${OCF_RESKEY_tpgt} \
 			${initiator} || exit $OCF_ERR_GENERIC
 		done
 	    else
-		ocf_run lio_node --permissive ${OCF_RESKEY_iqn} 1 || exit $OCF_ERR_GENERIC
+		ocf_run lio_node --permissive ${OCF_RESKEY_iqn} ${OCF_RESKEY_tpgt} || exit $OCF_ERR_GENERIC
 		# permissive mode enables read-only access by default,
 		# so we need to change that to RW to be in line with
 		# the other implementations.
-		echo 0 > "/sys/kernel/config/target/iscsi/${OCF_RESKEY_iqn}/tpgt_1/attrib/demo_mode_write_protect"
-		if [ `cat /sys/kernel/config/target/iscsi/${OCF_RESKEY_iqn}/tpgt_1/attrib/demo_mode_write_protect` -ne 0 ]; then
+		echo 0 > "/sys/kernel/config/target/iscsi/${OCF_RESKEY_iqn}/tpgt_${OCF_RESKEY_tpgt}/attrib/demo_mode_write_protect"
+		if [ `cat /sys/kernel/config/target/iscsi/${OCF_RESKEY_iqn}/tpgt_${OCF_RESKEY_tpgt}/attrib/demo_mode_write_protect` -ne 0 ]; then
 		    ocf_log err "Failed to disable write protection for target ${OCF_RESKEY_iqn}."
 		    exit $OCF_ERR_GENERIC
 		fi
 	    fi
-	    # TODO: add CHAP authentication support when it gets added
-	    # back into LIO
-	    ocf_run lio_node --disableauth ${OCF_RESKEY_iqn} 1 || exit $OCF_ERR_GENERIC
-	    # Finally, we need to enable the target to allow
-	    # initiators to connect
-	    ocf_run lio_node --enabletpg=${OCF_RESKEY_iqn} 1 || exit $OCF_ERR_GENERIC
+	    # LUN ACL
+	    if [ -n "${OCF_RESKEY_allowed_initiators}" ]; then
+		for initiator in ${OCF_RESKEY_allowed_initiators}; do
+		    ocf_run lio_node --addlunacl=${OCF_RESKEY_iqn} ${OCF_RESKEY_tpgt} \
+			${initiator} ${OCF_RESKEY_lun} ${OCF_RESKEY_lun} || exit $OCF_ERR_GENERIC
+		done
+	    fi
+	    # CHAP Authentication
+	    if [ -n "${OCF_RESKEY_incoming_username}" ]; then
+		for initiator in ${OCF_RESKEY_allowed_initiators}; do
+		    ocf_run lio_node --setchapauth ${OCF_RESKEY_iqn} ${OCF_RESKEY_tpgt} \
+			${initiator} ${OCF_RESKEY_incoming_username} ${OCF_RESKEY_incoming_password} || exit $OCF_ERR_GENERIC
+	    	done
+	    fi
+	    # Mutual CHAP Authentication
+	    if [ -n "${OCF_RESKEY_mutualchap_username}" ]; then
+		for initiator in ${OCF_RESKEY_allowed_initiators}; do
+		    ocf_run lio_node --setchapmutualauth ${OCF_RESKEY_iqn} ${OCF_RESKEY_tpgt} \
+			${initiator} ${OCF_RESKEY_mutualchap_username} ${OCF_RESKEY_mutualchap_password} || exit $OCF_ERR_GENERIC
+	    	done
+	    fi
+	    # in lio, we can set target parameters by manipulating
+	    # the appropriate configfs entries
+	    for param in ${OCF_RESKEY_additional_parameters}; do
+		name=${param%=*}
+		value=${param#*=}
+		configfs_path="/sys/kernel/config/target/iscsi/${OCF_RESKEY_iqn}/tpgt_${OCF_RESKEY_tpgt}/param/${name}"
+		if [ -e ${configfs_path} ]; then
+		    echo ${value} > ${configfs_path} || exit $OCF_ERR_GENERIC
+		else
+		    ocf_log warn "Unsupported iSCSI target parameter ${name}: will be ignored."
+		fi
+	    done
+	    # Finally, we need to enable the target to allow initiators to connect
+	    ocf_run lio_node --enabletpg=${OCF_RESKEY_iqn} ${OCF_RESKEY_tpgt} || exit $OCF_ERR_GENERIC
 	    ;;
     esac
 
@@ -418,6 +492,8 @@
 		# deletion.
 		;;
 	    lio)
+		# Disable TPG first due to known bug - http://permalink.gmane.org/gmane.linux.scsi.target.devel/1705
+		ocf_run lio_node --disabletpg=${OCF_RESKEY_iqn} ${OCF_RESKEY_tpgt} || exit $OCF_ERR_GENERIC
 		# In lio, removing a target automatically removes all
 		# associated TPGs, network portals, and LUNs.
 		ocf_run lio_node --deliqn ${OCF_RESKEY_iqn} || exit $OCF_ERR_GENERIC
@@ -443,7 +519,7 @@
 	    [ -d /sys/kernel/config/target/iscsi/${OCF_RESKEY_iqn} ] || return $OCF_NOT_RUNNING
 	    # if the target is there, but its TPG is not enabled, then
 	    # we also consider it stopped
-	    [ `cat /sys/kernel/config/target/iscsi/${OCF_RESKEY_iqn}/tpgt_1/enable` -eq 1 ] || return $OCF_NOT_RUNNING
+	    [ `cat /sys/kernel/config/target/iscsi/${OCF_RESKEY_iqn}/tpgt_${OCF_RESKEY_tpgt}/enable` -eq ${OCF_RESKEY_tpgt} ] || return $OCF_NOT_RUNNING
 	    return $OCF_SUCCESS
 	    ;;
     esac
@@ -452,6 +528,24 @@
 }
 
 iSCSITarget_validate() {
+    # Is the configured implementation supported?
+    case "$OCF_RESKEY_implementation" in
+	"iet"|"tgt"|"lio")
+	    ;;
+	"")
+	    # The user didn't specify an implementation, and we were
+	    # unable to determine one from installed binaries (in
+	    # other words: no binaries for any supported
+	    # implementation could be found)
+	    ocf_log error "Undefined iSCSI target implementation"
+	    exit $OCF_ERR_INSTALLED
+	    ;;
+	*)
+	    ocf_log error "Unsupported iSCSI target implementation \"$OCF_RESKEY_implementation\"!"
+	    exit $OCF_ERR_CONFIGURED
+	    ;;
+    esac
+
     # Do we have all required variables?
     local required_vars
     case $OCF_RESKEY_implementation in
@@ -461,6 +555,9 @@
 	tgt)
 	    required_vars="iqn tid"
 	    ;;
+	lio)
+	    required_vars="iqn tpgt lun hba_name storage_object_name"
+	    ;;
     esac
     for var in ${required_vars}; do
 	param="OCF_RESKEY_${var}"
@@ -470,21 +567,45 @@
 	fi
     done
 
-    # Is the configured implementation supported?
-    case "$OCF_RESKEY_implementation" in
-	"iet"|"tgt"|"lio")
-	    ;;
-	"")
-	    # The user didn't specify an implementation, and we were
-	    # unable to determine one from installed binaries (in
-	    # other words: no binaries for any supported
-	    # implementation could be found)
-	    ocf_log error "Undefined iSCSI target implementation"
-	    exit $OCF_ERR_INSTALLED
+    # Do we have a valid LUN?
+    case $OCF_RESKEY_implementation in
+	lio)
+	    # lio allows LUN 0 and up
+	    [ $OCF_RESKEY_lun -ge 0 ]
+	    case $? in
+		0)
+		    # OK
+		    ;;
+		1)
+		    ocf_log err "Invalid LUN $OCF_RESKEY_lun (must be a non-negative integer)."
+		    exit $OCF_ERR_CONFIGURED
+		    ;;
+		*)
+		    ocf_log err "Invalid LUN $OCF_RESKEY_lun (must be an integer)."
+		    exit $OCF_ERR_CONFIGURED
+		    ;;
+	    esac
 	    ;;
-	*)
-	    ocf_log error "Unsupported iSCSI target implementation \"$OCF_RESKEY_implementation\"!"
-	    exit $OCF_ERR_CONFIGURED
+    esac
+
+    # Do we have a valid TPGT?
+    case $OCF_RESKEY_implementation in
+	lio)
+	    # lio allows TPGT 1 and up
+	    [ $OCF_RESKEY_tpgt -ge 1 ]
+	    case $? in
+		0)
+		    # OK
+		    ;;
+		1)
+		    ocf_log err "Invalid TPGT $OCF_RESKEY_tpgt (must be a non-negative integer)."
+		    exit $OCF_ERR_CONFIGURED
+		    ;;
+		*)
+		    ocf_log err "Invalid TGPT $OCF_RESKEY_tgpt (must be an integer)."
+		    exit $OCF_ERR_CONFIGURED
+		    ;;
+	    esac
 	    ;;
     esac
 
@@ -495,14 +616,17 @@
     local envar
     case $OCF_RESKEY_implementation in
 	iet|tgt)
-	    # IET and tgt do not support binding a target portal to a
-	    # specific IP address.
-	    unsupported_params="portals"
+	    # IET and tgt do not support:
+	    #  - binding a target portal to a specific IP address.
+	    #  - mutual chap
+	    #  - lun
+	    #  - tpgt
+	    #  - hba_name
+	    #  - storage_object_name
+	    unsupported_params="portals mutualchap_username mutualchap_password lun tpgt hba_name storage_object_name"
 	    ;;
 	lio)
-	    # TODO: Remove incoming_username and incoming_password
-	    # from this check when LIO 3.0 gets CHAP authentication
-	    unsupported_params="tid incoming_username incoming_password"
+	    unsupported_params="tid"
 	    ;;
     esac
     for var in ${unsupported_params}; do
@@ -524,7 +648,6 @@
 		check_binary tgtadm
 		;;
 	    lio)
-		check_binary tcm_node
 		check_binary lio_node
 		;;
 	esac
@@ -548,8 +671,8 @@
 		    exit $OCF_ERR_INSTALLED
 		fi
 	        # check for configfs entries created by target_core_mod
-		if [ ! -d /sys/kernel/config/target ]; then
-		    ocf_log err "/sys/kernel/config/target does not exist or is not a directory -- check if required modules are loaded."
+		if [ ! -d /sys/kernel/config/target/iscsi ]; then
+		    ocf_log err "/sys/kernel/config/target/iscsi does not exist or is not a directory -- check if required modules are loaded."
 		    exit $OCF_ERR_INSTALLED
 		fi
 		;;
