|
|
@ -10,23 +10,45 @@ PROG=/usr/sbin/tgtd |
|
|
|
USE_PROCD=1 |
|
|
|
|
|
|
|
tgtadm="/usr/sbin/tgtadm --lld iscsi" |
|
|
|
logger="logger -p daemon.err -s -t $NAME" |
|
|
|
|
|
|
|
validate_lun_section() { |
|
|
|
uci_validate_section tgt lun $1 \ |
|
|
|
'device:file' \ |
|
|
|
'type:or("disk", "cd", "pt"):disk' \ |
|
|
|
'bstype:or("rdwr", "aio", "sg"):rdwr' \ |
|
|
|
'sync:bool:0' \ |
|
|
|
'direct:bool:0' \ |
|
|
|
'blocksize:uinteger' \ |
|
|
|
'mode_page:string' \ |
|
|
|
'product_id:string' \ |
|
|
|
'product_rev:string' \ |
|
|
|
'readonly:bool:0' \ |
|
|
|
'removable:bool' \ |
|
|
|
'scsi_id:string' \ |
|
|
|
'scsi_sn:string' \ |
|
|
|
'sense_format:range(0, 1)' \ |
|
|
|
'vendor_id:string' |
|
|
|
} |
|
|
|
|
|
|
|
handle_lun() { |
|
|
|
local tgt_lun=$1 |
|
|
|
local tgtid=$2 |
|
|
|
local ro device type bstype sync direct |
|
|
|
local readonly device type bstype sync direct |
|
|
|
local my_tgtid=${tgt_lun%_*} |
|
|
|
local lun=${tgt_lun#*_} |
|
|
|
|
|
|
|
[ $my_tgtid -eq $tgtid ] || return 0 |
|
|
|
|
|
|
|
config_get device $1 device "" |
|
|
|
[ "$device" ] || return 1 |
|
|
|
validate_lun_section $tgt_lun || { |
|
|
|
$logger "Validation failed for LUN $tgt_lun" |
|
|
|
return 1 |
|
|
|
} |
|
|
|
[ "$device" ] || { |
|
|
|
$logger "Device is required for target $tgt_lun" |
|
|
|
return 1 |
|
|
|
} |
|
|
|
|
|
|
|
config_get type $1 type disk |
|
|
|
config_get bstype $1 bstype rdwr |
|
|
|
config_get_bool readonly $1 readonly 0 |
|
|
|
config_get_bool sync $1 sync 0 |
|
|
|
config_get_bool direct $1 direct 0 |
|
|
|
if [ $sync -ne 0 -o $direct -ne 0 ]; then |
|
|
|
local bsoflags |
|
|
|
[ $sync -ne 0 ] && bsoflags="sync" |
|
|
@ -35,70 +57,173 @@ handle_lun() { |
|
|
|
bsoflags="--bsoflags $bsoflags" |
|
|
|
fi |
|
|
|
|
|
|
|
blocksize=${blocksize+--blocksize=$blocksize} |
|
|
|
local params='' i |
|
|
|
for i in mode_page product_id product_rev readonly removable scsi_id scsi_sn sense_format vendor_id; do |
|
|
|
eval params=\${$i+$i=\$$i,}\$params |
|
|
|
done |
|
|
|
|
|
|
|
local _tgtadm="$tgtadm --mode logicalunit --tid $tgtid --lun $lun" |
|
|
|
$_tgtadm --op new --backing-store $device --device-type $type --bstype $bstype --bstype $bstype $bsoflags || return 1 |
|
|
|
$_tgtadm --op update --param readonly=$readonly || return 1 |
|
|
|
$_tgtadm --op new --backing-store $device --device-type $type --bstype $bstype --bstype $bstype $bsoflags $blocksize || { |
|
|
|
$logger "Failed to create lun $tgt_lun" |
|
|
|
return 1 |
|
|
|
} |
|
|
|
$_tgtadm --op update --param $params || { |
|
|
|
$logger "Failed to update lun $tgt_lun" |
|
|
|
return 1 |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
validate_account_section () { |
|
|
|
uci_validate_section tgt account $1 \ |
|
|
|
'target:list(uinteger)' \ |
|
|
|
'user:string' \ |
|
|
|
'password:string' \ |
|
|
|
'outgoing:bool:0' |
|
|
|
} |
|
|
|
|
|
|
|
handle_account() { |
|
|
|
local tgtid=$2 |
|
|
|
local _tgtadm="$tgtadm --mode account" |
|
|
|
local target user password outgoing |
|
|
|
local user password target outgoing |
|
|
|
|
|
|
|
validate_account_section $1 || { |
|
|
|
$logger "Validation failed for account ${user:-$1}" |
|
|
|
return 1 |
|
|
|
} |
|
|
|
[ "$user" ] || { |
|
|
|
$logger "User is required for account $1. Run 'uci show tgt.$1' and check options" |
|
|
|
return 1 |
|
|
|
} |
|
|
|
[ "$target" ] || { |
|
|
|
$logger "Target is required for account $user" |
|
|
|
return 1 |
|
|
|
} |
|
|
|
[ "$password" ] || { |
|
|
|
$logger "Password is required for account $user" |
|
|
|
return 1 |
|
|
|
} |
|
|
|
$_tgtadm --op new --user "$user" --password "$password" || { |
|
|
|
$logger "Failed to create user $username" |
|
|
|
return 1 |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
config_get target $1 target "" |
|
|
|
[ "$target" ] || return 1 |
|
|
|
[ $target -eq $tgtid ] || return 0 |
|
|
|
bind_account_to_target() { |
|
|
|
local _tgtadm="$tgtadm --mode account" |
|
|
|
local tgtid=$2 user password outgoing |
|
|
|
|
|
|
|
config_get user $1 user "" |
|
|
|
[ "$user" ] || return 1 |
|
|
|
validate_account_section $1 || { |
|
|
|
$logger "Validation failed for account ${user:-$1}" |
|
|
|
return 1 |
|
|
|
} |
|
|
|
|
|
|
|
config_get password $1 password "" |
|
|
|
config_get_bool outgoing $1 outgoing 0 |
|
|
|
[ "$outgoing" -ne 0 ] && outgoing=--outgoing || outgoing="" |
|
|
|
local t |
|
|
|
for t in $target; do |
|
|
|
[ "$t" -eq "$tgtid" ] && { |
|
|
|
$_tgtadm --op bind --tid $tgtid --user "$user" $outgoing || { |
|
|
|
$logger "Failed to bind user $username to target $tgtid" |
|
|
|
return 1 |
|
|
|
} |
|
|
|
} |
|
|
|
done |
|
|
|
return 0 |
|
|
|
} |
|
|
|
|
|
|
|
$_tgtadm --op new --user "$user" --password "$password" || return 1 |
|
|
|
$_tgtadm --op bind --tid $tgtid --user "$user" $outgoing || return 1 |
|
|
|
validate_target_section() { |
|
|
|
uci_validate_section tgt target $1 \ |
|
|
|
'name:string:iqn.2012-06.org.openwrt' \ |
|
|
|
'allow_address:list(string):ALL' \ |
|
|
|
'allow_name:list(string)' |
|
|
|
} |
|
|
|
|
|
|
|
handle_target() { |
|
|
|
local tgtid=$1 |
|
|
|
local tgtname allow |
|
|
|
local _tgtadm="$tgtadm --mode target" |
|
|
|
local name allow |
|
|
|
|
|
|
|
[ $tgtid -ge 0 ] || return 1 |
|
|
|
|
|
|
|
config_get tgtname $1 name iqn.2012-06.org.openwrt |
|
|
|
config_get allow $1 allow ALL |
|
|
|
|
|
|
|
$_tgtadm --op new --tid $tgtid --targetname $tgtname || return 1 |
|
|
|
$_tgtadm --op bind --tid $tgtid -I $allow || return 1 |
|
|
|
|
|
|
|
validate_target_section $tgtid || { |
|
|
|
$logger "Validation failed for target $tgtid" |
|
|
|
return 1 |
|
|
|
} |
|
|
|
$_tgtadm --op new --tid $tgtid --targetname $name || { |
|
|
|
$logger "Failed to create target $tgtid" |
|
|
|
return 1 |
|
|
|
} |
|
|
|
local i |
|
|
|
for i in $allow_address; do |
|
|
|
$_tgtadm --op bind --tid $tgtid --initiator-address $i || { |
|
|
|
$logger "Failed to set allow $i to connect to target $tgtid" |
|
|
|
return 1 |
|
|
|
} |
|
|
|
done |
|
|
|
for i in $allow_name; do |
|
|
|
$_tgtadm --op bind --tid $tgtid --initiator-name $i || { |
|
|
|
$logger "Failed to set allow $i to connect to target $tgtid" |
|
|
|
return 1 |
|
|
|
} |
|
|
|
done |
|
|
|
config_foreach handle_lun lun $tgtid || return 1 |
|
|
|
config_foreach handle_account account $tgtid || return 1 |
|
|
|
config_foreach bind_account_to_target account $tgtid || return 1 |
|
|
|
} |
|
|
|
|
|
|
|
configure() { |
|
|
|
config_load $NAME |
|
|
|
$tgtadm --mode sys --op update --name State -v offline || return 1 |
|
|
|
$tgtadm --mode sys --op update --name State -v offline || { |
|
|
|
$logger "Failed to set system state to Offline" |
|
|
|
return 1 |
|
|
|
} |
|
|
|
config_foreach handle_account account || return 1 |
|
|
|
config_foreach handle_target target || return 1 |
|
|
|
$tgtadm --mode sys --op update --name State -v ready || return 1 |
|
|
|
$tgtadm --mode sys --op update --name State -v ready || { |
|
|
|
$logger "Failed to set system state to Ready" |
|
|
|
return 1 |
|
|
|
} |
|
|
|
return 0 |
|
|
|
} |
|
|
|
|
|
|
|
validate_tgt_section() { |
|
|
|
uci_validate_section tgt options $1 \ |
|
|
|
'iothreads:uinteger' \ |
|
|
|
'portal:list(string)' \ |
|
|
|
'nop_interval:uinteger' \ |
|
|
|
'nop_count:uinteger' |
|
|
|
} |
|
|
|
|
|
|
|
start_service() { |
|
|
|
local iothreads portal nop_interval nop_count |
|
|
|
validate_tgt_section tgt || { |
|
|
|
$logger "Validation failed for tgt options" |
|
|
|
return 1 |
|
|
|
} |
|
|
|
procd_open_instance |
|
|
|
procd_set_param command $PROG -f |
|
|
|
[ "$iothreads" ] && procd_append_param command -t $iothreads |
|
|
|
[ "${portal}${nop_interval}${nop_count}" ] && { |
|
|
|
local iscsi="" i |
|
|
|
for i in nop_interval nop_count; do |
|
|
|
eval iscsi=\${$i+$i=\$$i,}\$iscsi |
|
|
|
done |
|
|
|
for i in $portal; do |
|
|
|
iscsi="portal=$i,$iscsi" |
|
|
|
done |
|
|
|
procd_append_param command --iscsi $iscsi |
|
|
|
} |
|
|
|
procd_set_param respawn |
|
|
|
procd_close_instance |
|
|
|
logger -t $NAME -s "Configuration will be loaded in seconds" |
|
|
|
logger -p daemon.info -t $NAME -s "Configuration will be loaded in seconds" |
|
|
|
( sleep 5; configure || { stop_service; exit 1; } ) & |
|
|
|
} |
|
|
|
|
|
|
|
stop_service() { |
|
|
|
$tgtadm --mode sys --op update --name State -v offline |
|
|
|
$tgtadm --mode target --op show \ |
|
|
|
| awk '$1 == "Target" {sub(/:/,"",$2); print $2}' \ |
|
|
|
| xargs -n1 $tgtadm --mode target --op delete --force --tid |
|
|
|
$tgtadm --mode sys --op update --name State -v offline || { |
|
|
|
$logger "Failed to set system state to Offline" |
|
|
|
return 1 |
|
|
|
} |
|
|
|
$tgtadm --mode target --op show \ |
|
|
|
| awk '$1 == "Target" {sub(/:/,"",$2); print $2}' \ |
|
|
|
| xargs -r -n1 $tgtadm --mode target --op delete --force --tid |
|
|
|
$tgtadm --mode sys --op delete |
|
|
|
} |
|
|
|
|
|
|
|