diff --git a/install.sh b/install.sh index e316e55b94..ceb1cf4817 100755 --- a/install.sh +++ b/install.sh @@ -183,7 +183,8 @@ else CHOWN_DIRS="$ROOT" fi -SHARE_DIRS="$SHARE_LOCATION/examples" +SHARE_DIRS="$SHARE_LOCATION/examples \ + $SHARE_LOCATION/tgt" ETC_DIRS="$ETC_LOCATION/im_ec2 \ $ETC_LOCATION/vmm_ec2 \ @@ -451,6 +452,7 @@ INSTALL_FILES=( NETWORK_OVSWITCH_FILES:$VAR_LOCATION/remotes/vnm/ovswitch NETWORK_VMWARE_FILES:$VAR_LOCATION/remotes/vnm/vmware EXAMPLE_SHARE_FILES:$SHARE_LOCATION/examples + TGT_SHARE_FILES:$SHARE_LOCATION/tgt INSTALL_NOVNC_SHARE_FILE:$SHARE_LOCATION INSTALL_GEMS_SHARE_FILE:$SHARE_LOCATION HOOK_FT_FILES:$VAR_LOCATION/remotes/hooks/ft @@ -1065,6 +1067,12 @@ EXAMPLE_SHARE_FILES="share/examples/vm.template \ share/examples/private.net \ share/examples/public.net" +#------------------------------------------------------------------------------- +# File required to interact with a tgtd server +#------------------------------------------------------------------------------- + +TGT_SHARE_FILES="share/scripts/tgt/tgt-setup-lun-one" + #------------------------------------------------------------------------------- # HOOK scripts, to be installed under $VAR_LOCATION/remotes/hooks #------------------------------------------------------------------------------- diff --git a/share/scripts/tgt/tgt-setup-lun-one b/share/scripts/tgt/tgt-setup-lun-one new file mode 100755 index 0000000000..faf08949b5 --- /dev/null +++ b/share/scripts/tgt/tgt-setup-lun-one @@ -0,0 +1,279 @@ +#!/bin/bash + +# LUN assignment script +# +# Copyright (C) 2007 Erez Zilber +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation, version 2 of the +# License. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA + +usage() +{ + name=$(basename $0); + echo "usage:"; + echo -e "\t$name -n tgt_name -d dev -b bs_name -t transport [initiator_IP1 initiator_IP2 ...]"; + echo "defaults:"; + echo -e "\tbacking store: rdwr"; + echo -e "\ttransport: iscsi"; + echo -e "\tinitiator: ALL"; + echo "examples:"; + echo -e "\t$name -n tgt-1 -d /dev/sdb1 192.168.1.2"; + echo -e "\t$name -n tgt-2 -d /tmp/null -b null -t iser"; + echo -e "\t$name -n tgt-3 -d ~/disk3.bin -b rdwr 192.168.1.2 192.168.1.3"; +} + +verify_params() +{ + if ! [ "$dev" -o "$bs_type" == "null" ]; then + echo "Error: a device is mandatory"; + exit 1; + else + return; + fi + + # Make sure that the device exists + if ! [ -b $dev -o -f $dev -o -c $dev ]; then + echo "Error: $dev is not a device"; + exit 1; + fi + + if ! [ "$tgt_name" ]; then + echo "Error: target name is mandatory"; + exit 1; + fi + + if ! [ "$lld_name" ]; then + echo "Error: lld name empty"; + exit 1; + fi +} + +find_vacant_tgt_id() +{ + tmp_file=`mktemp` + tgtadm --lld $lld_name --op show --mode target | strings > $tmp_file + id_list=$(cat $tmp_file | grep Target | cut -d" " -f2 | sed s/://) + next_vacant_id=1 + for id in $id_list; do + if (($id > $next_vacant_id)); then + break; + else + next_vacant_id=$((next_vacant_id+1)) + fi + done + rm -f $tmp_file + echo $next_vacant_id +} + +find_vacant_lun() +{ + tid=$1 + tgt_found=0 + next_vacant_lun=0 + tmp_file=`mktemp` + + tgtadm --lld $lld_name --op show --mode target | strings | tgt-admin -s | grep 'LUN\|Target' > $tmp_file + retcode=$? + while read line; do + # Check if we finished going over this target + if ((tgt_found == 1 && $(echo $line | grep -c "^Target") == 1)); then + break + fi + + # Check if we found the requested target + if (($(echo $line | grep -c "Target $tid:") == 1)); then + tgt_found=1 + continue + fi + + if ((tgt_found == 1 && $(echo $line | grep -c "LUN:") == 1)); then + curr_lun=$(echo $line | cut -d" " -f2) + if (($curr_lun > $next_vacant_lun)); then + break + else + next_vacant_lun=$((next_vacant_lun+1)) + fi + fi + done < $tmp_file + + rm -f $tmp_file + + if ((tgt_found == 0)); then + echo "Error: could not find a LUN for target $tid, guessing 1 as next vacant LUN" + return 1 + fi + if ((next_vacant_lun == 0)); then + echo "Error: could not find a LUN for target $tid, guessing 1 as next vacant LUN" + return 1 + fi + + return $next_vacant_lun +} + +err_exit() +{ + if ((new_tgt == 0)); then + exit 1 + fi + + echo "Deleting new target, tid=$tid" + tgtadm --lld $lld_name --op delete --mode target --tid $tid + res=$? + + if [ $res -ne 0 ]; then + echo "Error: failed to delete target, tid=$tid" + fi + + exit 1 +} + +check_if_tgt_exists() +{ + tgt_list=$(tgtadm --lld $lld_name --op show --mode target | strings | grep Target | cut -d" " -f3) + + for curr_tgt in $tgt_list; do + if [ $tgt_name = $curr_tgt ]; then + return 1 + fi + done + + return 0 +} + +if [ $# -eq 0 ]; then + usage + exit 1 +fi + +lld_name="iscsi" + +while getopts "d:n:b:t:h:" opt +do + case ${opt} in + d) + dev=$OPTARG;; + n) + tgt_name=$OPTARG;; + b) + bs_type=$OPTARG;; + t) + lld_name=$OPTARG;; + h*) + usage + exit 1 + esac +done + +shift $(($OPTIND - 1)) + +initiators=$* + +verify_params + +# Check if tgtd is running (we should have 2 daemons) +tgtd_count=`pidof tgtd | wc -w` +if [ $tgtd_count -lt 1 ]; then + echo "tgtd is not running" + echo "Exiting..." + exit 1 +fi + +echo "Using transport: $lld_name" + +if ! [[ $tgt_name =~ ^iqn ]]; then + tgt_name="iqn.2001-04.com.$(hostname -s)-$tgt_name" +fi + +# Make sure that a target with the same name doesn't exist +check_if_tgt_exists +if [ $? -eq 1 ]; then + echo "Error: target named $tgt_name already exists" + read -p "Add a new lun to the existing target? (yes/NO): " add_lun + if [ $add_lun != "yes" ]; then + exit 1 + fi + tid=$(tgtadm --lld $lld_name --op show --mode target | strings | grep $tgt_name | cut -d" " -f2) + tid=${tid%:} + new_tgt=0 +else + + i=0 + while [ true ] + do + let i=i+1 + tid=`find_vacant_tgt_id` + #tid=$? + # Create the new target + echo -n "Creating new target (name=$tgt_name, tid=$tid)..." + tgtoutput=`tgtadm --lld $lld_name --op new --mode target --tid $tid -T $tgt_name 2>&1` + res=$? + if [ "$tgtoutput" == "tgtadm: this target already exists" ]; then + echo "Target already exists (this should not happen)... Attempt $i" + elif [ $res -eq 0 ]; then # output is not about duplication and return value is zero, this is the normal condition + break + fi + if [ $i -eq 100 ]; then + echo "Too many attempts, giving up" + break + fi + done + if [ $res -ne 0 ]; then + echo "Error: failed to create target (name=$tgt_name, tid=$tid)" + exit 1 + fi + new_tgt=1 +fi +echo "OK" +find_vacant_lun $tid +lun=$? +echo "LUN ok, $lun" + +# Add a logical unit to the target +echo "Adding a logical unit ($dev) to target, tid=$tid" +if [ $bs_type ]; then + echo "Setting backing store type: $bs_type" + bs_opt="-E $bs_type" +fi +tgtadm --lld $lld_name --op new --mode logicalunit --tid $tid --lun $lun -b $dev $bs_opt +res=$? + +if [ $res -ne 0 ]; then + echo "Error: failed to add a logical unit ($dev) to target, tid=$tid" + err_exit +fi + +# Define which initiators can use this target +if test "$initiators" ; then + # Allow access only for specific initiators + echo "Accepting connections only from $initiators" + for initiator in $initiators; do + tgtadm --lld $lld_name --op bind --mode target --tid $tid -I $initiator + res=$? + + if [ $res -ne 0 ]; then + echo "Error: could not assign initiator $initiator to the target" + fi + done +else + # Allow access for everyone + echo "Accepting connections from all initiators" + tgtadm --lld $lld_name --op bind --mode target --tid $tid -I ALL + res=$? + + if [ $res -ne 0 ]; then + echo "Error: failed to set access for all initiators" + err_exit + fi +fi diff --git a/src/datastore_mad/remotes/iscsi/clone b/src/datastore_mad/remotes/iscsi/clone index f60dd02fa8..e0055a085b 100755 --- a/src/datastore_mad/remotes/iscsi/clone +++ b/src/datastore_mad/remotes/iscsi/clone @@ -64,6 +64,9 @@ BASE_IQN="${XPATH_ELEMENTS[6]:-$BASE_IQN}" SRC="${XPATH_ELEMENTS[7]}" SIZE="${XPATH_ELEMENTS[8]}" +# Check if 'TGTSETUPLUN' is installed +tgt_setup_lun_install "$DST_HOST" "$BASE_PATH" + set_up_datastore "$BASE_PATH" "$RESTRICTED_DIRS" "$SAFE_DIRS" "$UMASK" LV_NAME="lv-one-${ID}" @@ -76,13 +79,9 @@ DEV_SRC="/dev/$VG_NAME/$LV_SRC" CLONE_CMD=$(cat <&1 | \ + $GREP -q "command not found" + if [ "$?" = "0" ]; then + error_message "$TGTSETUPLUN is not installed in $DST_HOST." + exit 127 + else + touch "$CHECK_FILE" + fi + fi +} + +function tgt_setup_lun { + IQN="$1" + DEV="$2" + echo "$TGTSETUPLUN -d $DEV -n $IQN 1>&2" +} + function iqn_get_host { IQN="$1" TARGET=`echo "$IQN"|$CUT -d: -f2` @@ -426,10 +451,10 @@ function vmfs_set_up { if [ "$USE_SSH" != "yes" ]; then USERNAME=`echo $(cat $VMWARERC |grep ":username:"|cut -d":" -f 3|tr -d '"')` PASSWORD=`echo $(cat $VMWARERC |grep ":password:"|cut -d":" -f 3|tr -d '"')` - if [ -z $PASSWORD ]; then - VI_PARAMS="--server $DST_HOST --username $USERNAME --password \"\"" - else - VI_PARAMS="--server $DST_HOST --username $USERNAME --password $PASSWORD" + if [ -z $PASSWORD ]; then + VI_PARAMS="--server $DST_HOST --username $USERNAME --password \"\"" + else + VI_PARAMS="--server $DST_HOST --username $USERNAME --password $PASSWORD" fi fi } diff --git a/src/tm_mad/iscsi/clone b/src/tm_mad/iscsi/clone index ccce7f0df8..89feebfc55 100755 --- a/src/tm_mad/iscsi/clone +++ b/src/tm_mad/iscsi/clone @@ -81,14 +81,10 @@ CLONE_CMD=$(cat <