#!/bin/bash
PSTORAGE_ISCSI_LIB=/usr/libexec/vstorage-iscsi/vstorage_functions
ROOT=""
IQN=""
LUN_SIZE=""
LUN_ID=""
CMD=""
ARGS="${@}"
TMP_DIRS=""
SCSI_SN=""
VOLUME_ATTR=""

function do_cleanup {
	[ -z "$TMP_DIRS" -o -z "$ISCSI_ROOT" ] && return
	for dir in $TMP_DIRS; do
		parent=`dirname ${dir}`
		[ "$parent" = "$ISCSI_ROOT/tmp" -a -d "${dir}" ] && rm -rf "${dir}"
	done
}

function print_usage {
        exec 1>&2
	if [ "x${CMD}" = "xlun-add" ] ; then
	echo "Add new LUN to iSCSI target."
	else
	echo "Delete existing LUN."
	fi
        echo "Usage:"
	echo -n " $CTL_TOOL ${CMD} -t,--target IQN -l,--lun ID "
	if [ "x${CMD}" = "xlun-add" ] ; then
		echo " -s,--size SIZE [--vstorage-attr ATTRS]"
	else
		echo ""
	fi
        echo "Options:"
	echo "  -t,--target IQN         target's IQN."
	if [ "x${CMD}" = "xlun-add" ]; then
	echo "  -l,--lun ID             ID for new LUN."
	echo "  -s,--size SIZE          size for new LUN. If no suffix is specified,"
	echo "                          the size is in sector units  (one  sector  is  512  bytes)."
	echo "                          One can specify optional K, M, or G suffix to set the size"
	echo "                          in kilo-, mega-, or gigabytes."
	echo "  -N,--serial SCSI_SN     SCSI serial number for new LUN (optional)."
	echo "  --vstorage-attr ATTRS   Set Vstorage attribues. The ATTRS are attributes delimited by"
	echo "                          comma (optional). Use command 'vstorage help set-attr' to get"
	echo "                          list of valid attributes."
	else
	echo "  -l,--lun ID             LUN's ID for delete."
	fi
        echo " "
        exit 1
}

function parse_args {
	if [ ${#} -eq 0 ]; then
		echo "Command not specified, expected lun-add or lun-del" 1>&2
		exit 1
	fi

	CMD="${1}"; shift
	if [ "$CMD" != "lun-add" -a "$CMD" != "lun-del" ] ; then
		echo "Unknown command '$CMD'" 1>&2
		exit 1
	fi

        while [ "${#}" -gt 0 ]; do
                case "${1}" in
			"-h"|"--help")
				print_usage
				;;
			"-r"|"--root")
				[ -z "${2}" ] && print_usage
				ROOT="${2}"
				shift
				shift
				;;
                        "-t"|"--target")
				[ -z "${2}" ] && print_usage
				IQN="${2}"
				shift
				shift
				;;
			"-l"|"--lun")
				[ -z "${2}" ] && print_usage
				LUN_ID="${2}"
				shift
				shift
				;;
			"-N"|"--serial")
				[ -z "${2}" ] && print_usage
				SCSI_SN="${2}"
				shift
				shift
				;;
			"-s"|"--size")
				[ "x$CMD" != "xlun-add" ] && print_usage
				[ -z "${2}" ] && print_usage
				LUN_SIZE="${2}"
				shift
				shift
				;;
			"--vstorage-attr")
				[ "x$CMD" != "xlun-add" ] && print_usage
				[ -z "${2}" ] && print_usage
				VOLUME_ATTR="${2}"
				shift
				shift
				;;
                        *)
                                echo "Unknown option '${1}'." 1>&2
                                print_usage
                                ;;
                esac
        done

	if [ -z "$IQN" ] ; then
		echo "Target (-t,--target) must be specified." 1>&2
		print_usage
	fi

	if [ -z "$LUN_ID" ] ; then
		echo "LUN id (-l,--lun) must be specified." 1>&2
		print_usage
	fi

	if [ "x$CMD" = "xlun-add" ]; then
		if [ -z "$LUN_SIZE" ] ; then
			echo "Lun size (-s,--size) must be specified." 1>&2
			print_usage
		fi
	fi
}

function delete_lun {
	local target="$1"
	local lun_id="$2"
	if [ ! -d "$ISCSI_ROOT/$target/lun${lun_id}" ] ; then
		echo "LUN $lun_id does not exist." 1>&2
		return 1
	fi

        tmp=`mktemp -d ${ISCSI_ROOT}/tmp/removed-lun.XXXXXXXX`
        if [ $? -ne 0 ] ; then
                echo "Can't create temporary directory." 1>&2
		return 2
        fi
        TMP_DIRS="${TMP_DIRS} ${tmp}"

	ctl_port=`pcs_iscsi_get_ctl_port $target`
	if [ -n "$ctl_port" ] ; then
		pcs_iscsi_down_lun $target $lun_id $ctl_port
		if [ $? -ne 0 ] ; then
			echo "Unable stop LUN $lun_id." 1>&2
			return 3
		fi
	fi

	mv "$ISCSI_ROOT/$IQN/lun$LUN_ID" "${tmp}/lun$LUN_ID"
	if [ $? -ne 0 ] ; then
		echo "Can't move $ISCSI_ROOT/$IQN/lun$LUN_ID to ${tmp}/lun$LUN_ID" 1>&2
		return 4
	fi

	pcs_iscsi_delete_snapshot_info "${tmp}/lun$LUN_ID"
	return 0
}

function make_lun {
	local target="$1"
	local id="$2"
	local size="$3"
	local uuid=""

	if [ -d "$ISCSI_ROOT/$target/lun$id" ] ; then
		echo "Lun with id '$id' already exist for target $target" 1>&2
			return 3
	fi
	
	tmp=`mktemp -d ${ISCSI_ROOT}/tmp/lun${id}.XXXXXXXX`
	if [ $? -ne 0 ] ; then
		echo "Can't create temporary directory"
		return 4
	fi

	TMP_DIRS="${TMP_DIRS} ${tmp}"
	if [ -n "$VOLUME_ATTR" ]; then
		attrs=$(echo $VOLUME_ATTR | tr "," "\n")
		for attr in $attrs
		do
			$VSTORAGE_BIN "set-attr" "${tmp}" $attr >/dev/null 2>&1
			if [ $? -ne 0 ]; then
				echo "Can't set attributes '$attr' for $tmp" 1>&2
				return 4
			fi
		done
	fi

	if [ -z "$SCSI_SN" ] ; then
		# make SCSI_SN for new LUN
		sn=`/usr/bin/uuidgen | cut -f1 -d '-'`
		SCSI_SN="PSTOR-$sn"
	fi

	echo "$SCSI_SN" | dd of="$tmp/serial_sn" conv=fsync >/dev/null 2>&1
	if [ $? -ne 0 ] ; then
		echo "Can't store SCSI serial in file $tmp/serial_sn" 1>&2
		return 4
	fi

	$PLOOP init -s $size -t none "${tmp}/ploop" >/dev/null 2>&1
	ret=$?
	if [ ${ret} -ne 0 ]; then
		echo "Unable create ploop image, exit code $ret"
		return 5
	fi

	mv ${tmp} "$ISCSI_ROOT/$target/lun${id}"
	if [ $? -ne 0 ] ; then
		echo "Can't move ${tmp} to $ISCSI_ROOT/$target/lun${id}"
		return 7
	fi

	return 0
}

function do_ctl {
	local iqn="$1"
	local cmd="$2"
	local lun_id="$3"
	local lun_size="$4"

	trap do_cleanup EXIT
	pcs_iscsi_check_target $iqn

	if [ "x$cmd" = "xlun-add" ]; then
		make_lun $iqn $lun_id $lun_size
		RET=$?
		[ $RET -ne 0 ] && exit $RET

		ctl_port=`pcs_iscsi_get_ctl_port $iqn`
		if [ -n "$ctl_port" ] ; then
			# add created lun to running target...
			pcs_iscsi_up_lun $IQN $ctl_port "lun${lun_id}"
			RET=$?
			[ $RET -ne 0 ] && exit 2
		fi
	else
		delete_lun $iqn $lun_id
		RET=$?
		[ $RET -ne 0 ] && exit 2
	fi

	exit $RET
}

if [ ! -x $PSTORAGE_ISCSI_LIB ] ; then
	echo "Unable find executable $PSTORAGE_ISCSI_LIB" 1>&2
	exit 1
fi

source $PSTORAGE_ISCSI_LIB
[ -f $ISCSI_ETC/config ] && source $ISCSI_ETC/config

parse_args $ARGS

ISCSI_ROOT=`pcs_iscsi_get_root "${ROOT}"`
pcs_iscsi_check_root
pcs_iscsi_lock_exec do_ctl "$IQN" "$CMD" "$LUN_ID" "$LUN_SIZE"
exit $?

