|
@@ -10,23 +10,45 @@ PROG=/usr/sbin/tgtd
|
10
|
10
|
USE_PROCD=1
|
11
|
11
|
|
12
|
12
|
tgtadm="/usr/sbin/tgtadm --lld iscsi"
|
|
13
|
+logger="logger -p daemon.err -s -t $NAME"
|
|
14
|
+
|
|
15
|
+validate_lun_section() {
|
|
16
|
+ uci_validate_section tgt lun $1 \
|
|
17
|
+ 'device:file' \
|
|
18
|
+ 'type:or("disk", "cd", "pt"):disk' \
|
|
19
|
+ 'bstype:or("rdwr", "aio", "sg"):rdwr' \
|
|
20
|
+ 'sync:bool:0' \
|
|
21
|
+ 'direct:bool:0' \
|
|
22
|
+ 'blocksize:uinteger' \
|
|
23
|
+ 'mode_page:string' \
|
|
24
|
+ 'product_id:string' \
|
|
25
|
+ 'product_rev:string' \
|
|
26
|
+ 'readonly:bool:0' \
|
|
27
|
+ 'removable:bool' \
|
|
28
|
+ 'scsi_id:string' \
|
|
29
|
+ 'scsi_sn:string' \
|
|
30
|
+ 'sense_format:range(0, 1)' \
|
|
31
|
+ 'vendor_id:string'
|
|
32
|
+}
|
13
|
33
|
|
14
|
34
|
handle_lun() {
|
15
|
35
|
local tgt_lun=$1
|
16
|
36
|
local tgtid=$2
|
17
|
|
- local ro device type bstype sync direct
|
|
37
|
+ local readonly device type bstype sync direct
|
18
|
38
|
local my_tgtid=${tgt_lun%_*}
|
19
|
39
|
local lun=${tgt_lun#*_}
|
|
40
|
+
|
20
|
41
|
[ $my_tgtid -eq $tgtid ] || return 0
|
21
|
42
|
|
22
|
|
- config_get device $1 device ""
|
23
|
|
- [ "$device" ] || return 1
|
|
43
|
+ validate_lun_section $tgt_lun || {
|
|
44
|
+ $logger "Validation failed for LUN $tgt_lun"
|
|
45
|
+ return 1
|
|
46
|
+ }
|
|
47
|
+ [ "$device" ] || {
|
|
48
|
+ $logger "Device is required for target $tgt_lun"
|
|
49
|
+ return 1
|
|
50
|
+ }
|
24
|
51
|
|
25
|
|
- config_get type $1 type disk
|
26
|
|
- config_get bstype $1 bstype rdwr
|
27
|
|
- config_get_bool readonly $1 readonly 0
|
28
|
|
- config_get_bool sync $1 sync 0
|
29
|
|
- config_get_bool direct $1 direct 0
|
30
|
52
|
if [ $sync -ne 0 -o $direct -ne 0 ]; then
|
31
|
53
|
local bsoflags
|
32
|
54
|
[ $sync -ne 0 ] && bsoflags="sync"
|
|
@@ -35,70 +57,173 @@ handle_lun() {
|
35
|
57
|
bsoflags="--bsoflags $bsoflags"
|
36
|
58
|
fi
|
37
|
59
|
|
|
60
|
+ blocksize=${blocksize+--blocksize=$blocksize}
|
|
61
|
+ local params='' i
|
|
62
|
+ for i in mode_page product_id product_rev readonly removable scsi_id scsi_sn sense_format vendor_id; do
|
|
63
|
+ eval params=\${$i+$i=\$$i,}\$params
|
|
64
|
+ done
|
|
65
|
+
|
38
|
66
|
local _tgtadm="$tgtadm --mode logicalunit --tid $tgtid --lun $lun"
|
39
|
|
- $_tgtadm --op new --backing-store $device --device-type $type --bstype $bstype --bstype $bstype $bsoflags || return 1
|
40
|
|
- $_tgtadm --op update --param readonly=$readonly || return 1
|
|
67
|
+ $_tgtadm --op new --backing-store $device --device-type $type --bstype $bstype --bstype $bstype $bsoflags $blocksize || {
|
|
68
|
+ $logger "Failed to create lun $tgt_lun"
|
|
69
|
+ return 1
|
|
70
|
+ }
|
|
71
|
+ $_tgtadm --op update --param $params || {
|
|
72
|
+ $logger "Failed to update lun $tgt_lun"
|
|
73
|
+ return 1
|
|
74
|
+ }
|
|
75
|
+}
|
|
76
|
+
|
|
77
|
+validate_account_section () {
|
|
78
|
+ uci_validate_section tgt account $1 \
|
|
79
|
+ 'target:list(uinteger)' \
|
|
80
|
+ 'user:string' \
|
|
81
|
+ 'password:string' \
|
|
82
|
+ 'outgoing:bool:0'
|
41
|
83
|
}
|
42
|
84
|
|
43
|
85
|
handle_account() {
|
44
|
|
- local tgtid=$2
|
45
|
86
|
local _tgtadm="$tgtadm --mode account"
|
46
|
|
- local target user password outgoing
|
|
87
|
+ local user password target outgoing
|
|
88
|
+
|
|
89
|
+ validate_account_section $1 || {
|
|
90
|
+ $logger "Validation failed for account ${user:-$1}"
|
|
91
|
+ return 1
|
|
92
|
+ }
|
|
93
|
+ [ "$user" ] || {
|
|
94
|
+ $logger "User is required for account $1. Run 'uci show tgt.$1' and check options"
|
|
95
|
+ return 1
|
|
96
|
+ }
|
|
97
|
+ [ "$target" ] || {
|
|
98
|
+ $logger "Target is required for account $user"
|
|
99
|
+ return 1
|
|
100
|
+ }
|
|
101
|
+ [ "$password" ] || {
|
|
102
|
+ $logger "Password is required for account $user"
|
|
103
|
+ return 1
|
|
104
|
+ }
|
|
105
|
+ $_tgtadm --op new --user "$user" --password "$password" || {
|
|
106
|
+ $logger "Failed to create user $username"
|
|
107
|
+ return 1
|
|
108
|
+ }
|
|
109
|
+}
|
47
|
110
|
|
48
|
|
- config_get target $1 target ""
|
49
|
|
- [ "$target" ] || return 1
|
50
|
|
- [ $target -eq $tgtid ] || return 0
|
|
111
|
+bind_account_to_target() {
|
|
112
|
+ local _tgtadm="$tgtadm --mode account"
|
|
113
|
+ local tgtid=$2 user password outgoing
|
51
|
114
|
|
52
|
|
- config_get user $1 user ""
|
53
|
|
- [ "$user" ] || return 1
|
|
115
|
+ validate_account_section $1 || {
|
|
116
|
+ $logger "Validation failed for account ${user:-$1}"
|
|
117
|
+ return 1
|
|
118
|
+ }
|
54
|
119
|
|
55
|
|
- config_get password $1 password ""
|
56
|
|
- config_get_bool outgoing $1 outgoing 0
|
57
|
120
|
[ "$outgoing" -ne 0 ] && outgoing=--outgoing || outgoing=""
|
|
121
|
+ local t
|
|
122
|
+ for t in $target; do
|
|
123
|
+ [ "$t" -eq "$tgtid" ] && {
|
|
124
|
+ $_tgtadm --op bind --tid $tgtid --user "$user" $outgoing || {
|
|
125
|
+ $logger "Failed to bind user $username to target $tgtid"
|
|
126
|
+ return 1
|
|
127
|
+ }
|
|
128
|
+ }
|
|
129
|
+ done
|
|
130
|
+ return 0
|
|
131
|
+}
|
58
|
132
|
|
59
|
|
- $_tgtadm --op new --user "$user" --password "$password" || return 1
|
60
|
|
- $_tgtadm --op bind --tid $tgtid --user "$user" $outgoing || return 1
|
|
133
|
+validate_target_section() {
|
|
134
|
+ uci_validate_section tgt target $1 \
|
|
135
|
+ 'name:string:iqn.2012-06.org.openwrt' \
|
|
136
|
+ 'allow_address:list(string):ALL' \
|
|
137
|
+ 'allow_name:list(string)'
|
61
|
138
|
}
|
62
|
139
|
|
63
|
140
|
handle_target() {
|
64
|
141
|
local tgtid=$1
|
65
|
|
- local tgtname allow
|
66
|
142
|
local _tgtadm="$tgtadm --mode target"
|
|
143
|
+ local name allow
|
67
|
144
|
|
68
|
145
|
[ $tgtid -ge 0 ] || return 1
|
69
|
|
-
|
70
|
|
- config_get tgtname $1 name iqn.2012-06.org.openwrt
|
71
|
|
- config_get allow $1 allow ALL
|
72
|
|
-
|
73
|
|
- $_tgtadm --op new --tid $tgtid --targetname $tgtname || return 1
|
74
|
|
- $_tgtadm --op bind --tid $tgtid -I $allow || return 1
|
75
|
|
-
|
|
146
|
+ validate_target_section $tgtid || {
|
|
147
|
+ $logger "Validation failed for target $tgtid"
|
|
148
|
+ return 1
|
|
149
|
+ }
|
|
150
|
+ $_tgtadm --op new --tid $tgtid --targetname $name || {
|
|
151
|
+ $logger "Failed to create target $tgtid"
|
|
152
|
+ return 1
|
|
153
|
+ }
|
|
154
|
+ local i
|
|
155
|
+ for i in $allow_address; do
|
|
156
|
+ $_tgtadm --op bind --tid $tgtid --initiator-address $i || {
|
|
157
|
+ $logger "Failed to set allow $i to connect to target $tgtid"
|
|
158
|
+ return 1
|
|
159
|
+ }
|
|
160
|
+ done
|
|
161
|
+ for i in $allow_name; do
|
|
162
|
+ $_tgtadm --op bind --tid $tgtid --initiator-name $i || {
|
|
163
|
+ $logger "Failed to set allow $i to connect to target $tgtid"
|
|
164
|
+ return 1
|
|
165
|
+ }
|
|
166
|
+ done
|
76
|
167
|
config_foreach handle_lun lun $tgtid || return 1
|
77
|
|
- config_foreach handle_account account $tgtid || return 1
|
|
168
|
+ config_foreach bind_account_to_target account $tgtid || return 1
|
78
|
169
|
}
|
79
|
170
|
|
80
|
171
|
configure() {
|
81
|
172
|
config_load $NAME
|
82
|
|
- $tgtadm --mode sys --op update --name State -v offline || return 1
|
|
173
|
+ $tgtadm --mode sys --op update --name State -v offline || {
|
|
174
|
+ $logger "Failed to set system state to Offline"
|
|
175
|
+ return 1
|
|
176
|
+ }
|
|
177
|
+ config_foreach handle_account account || return 1
|
83
|
178
|
config_foreach handle_target target || return 1
|
84
|
|
- $tgtadm --mode sys --op update --name State -v ready || return 1
|
|
179
|
+ $tgtadm --mode sys --op update --name State -v ready || {
|
|
180
|
+ $logger "Failed to set system state to Ready"
|
|
181
|
+ return 1
|
|
182
|
+ }
|
85
|
183
|
return 0
|
86
|
184
|
}
|
87
|
185
|
|
|
186
|
+validate_tgt_section() {
|
|
187
|
+ uci_validate_section tgt options $1 \
|
|
188
|
+ 'iothreads:uinteger' \
|
|
189
|
+ 'portal:list(string)' \
|
|
190
|
+ 'nop_interval:uinteger' \
|
|
191
|
+ 'nop_count:uinteger'
|
|
192
|
+}
|
|
193
|
+
|
88
|
194
|
start_service() {
|
|
195
|
+ local iothreads portal nop_interval nop_count
|
|
196
|
+ validate_tgt_section tgt || {
|
|
197
|
+ $logger "Validation failed for tgt options"
|
|
198
|
+ return 1
|
|
199
|
+ }
|
89
|
200
|
procd_open_instance
|
90
|
201
|
procd_set_param command $PROG -f
|
|
202
|
+ [ "$iothreads" ] && procd_append_param command -t $iothreads
|
|
203
|
+ [ "${portal}${nop_interval}${nop_count}" ] && {
|
|
204
|
+ local iscsi="" i
|
|
205
|
+ for i in nop_interval nop_count; do
|
|
206
|
+ eval iscsi=\${$i+$i=\$$i,}\$iscsi
|
|
207
|
+ done
|
|
208
|
+ for i in $portal; do
|
|
209
|
+ iscsi="portal=$i,$iscsi"
|
|
210
|
+ done
|
|
211
|
+ procd_append_param command --iscsi $iscsi
|
|
212
|
+ }
|
91
|
213
|
procd_set_param respawn
|
92
|
214
|
procd_close_instance
|
93
|
|
- logger -t $NAME -s "Configuration will be loaded in seconds"
|
|
215
|
+ logger -p daemon.info -t $NAME -s "Configuration will be loaded in seconds"
|
94
|
216
|
( sleep 5; configure || { stop_service; exit 1; } ) &
|
95
|
217
|
}
|
96
|
218
|
|
97
|
219
|
stop_service() {
|
98
|
|
- $tgtadm --mode sys --op update --name State -v offline
|
99
|
|
- $tgtadm --mode target --op show \
|
100
|
|
- | awk '$1 == "Target" {sub(/:/,"",$2); print $2}' \
|
101
|
|
- | xargs -n1 $tgtadm --mode target --op delete --force --tid
|
|
220
|
+ $tgtadm --mode sys --op update --name State -v offline || {
|
|
221
|
+ $logger "Failed to set system state to Offline"
|
|
222
|
+ return 1
|
|
223
|
+ }
|
|
224
|
+ $tgtadm --mode target --op show \
|
|
225
|
+ | awk '$1 == "Target" {sub(/:/,"",$2); print $2}' \
|
|
226
|
+ | xargs -r -n1 $tgtadm --mode target --op delete --force --tid
|
102
|
227
|
$tgtadm --mode sys --op delete
|
103
|
228
|
}
|
104
|
229
|
|