Skip to content

Commit 48fb5a3

Browse files
Merge pull request #167 from pkalever/interactive-mode
daemonized-mode: add interactive shell support
2 parents e09fa8c + 534c475 commit 48fb5a3

File tree

3 files changed

+111
-25
lines changed

3 files changed

+111
-25
lines changed

scripts/targetcli

Lines changed: 79 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class TargetCLI(ConfigShell):
6464
'max_backup_files': '10',
6565
'auto_add_default_portal': True,
6666
'auto_use_daemon': False,
67+
'daemon_use_batch_mode': False,
6768
}
6869

6970
def usage():
@@ -121,7 +122,7 @@ def completer(text, state):
121122
except IndexError:
122123
return None
123124

124-
def call_daemon(shell, req):
125+
def call_daemon(shell, req, interactive):
125126
try:
126127
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
127128
except socket.error as err:
@@ -139,9 +140,23 @@ def call_daemon(shell, req):
139140
"then run '#targetcli --disable-daemon'", 'red'))
140141
sys.exit(1)
141142

143+
# Two cases where we want to get pwd:
144+
# 1. Before starting shell in interactive mode, needed for setting terminal
145+
# 2. And only in Interactive mode, having command 'cd'
146+
get_pwd = False
147+
if interactive:
148+
if not req:
149+
req = "pwd"
150+
get_pwd = True
151+
elif "cd " in req:
152+
req += "%pwd"
153+
get_pwd = True
154+
else:
155+
req = "cd /%" + req # Non-interactive modes always consider start at '/'
156+
142157
try:
143158
# send request
144-
sock.sendall(req)
159+
sock.sendall(req.encode())
145160
except socket.error as err:
146161
shell.con.display(shell.con.render_text(err, 'red'))
147162
sys.exit(1)
@@ -152,17 +167,31 @@ def call_daemon(shell, req):
152167
amount_received = 0
153168

154169
# get the actual data in chunks
170+
output = ""
171+
path = ""
155172
while amount_received < amount_expected:
156173
data = sock.recv(1024)
157174
data = data.decode()
158175
amount_received += len(data)
159-
print(data, end ="")
176+
output += data
177+
178+
if get_pwd:
179+
output_split = output.splitlines()
180+
lines = len(output_split)
181+
for i in range(0, lines):
182+
if i == lines-1:
183+
path = str(output_split[i])
184+
else:
185+
print(str(output_split[i]), end ="\n")
186+
else:
187+
print(output, end ="")
160188

161189
sock.send(b'-END@OF@DATA-')
162190
sock.close()
163-
sys.exit(0)
164191

165-
def get_arguments(shell):
192+
return path
193+
194+
def switch_to_daemon(shell, interactive):
166195
readline.set_completer(completer)
167196
readline.set_completer_delims('')
168197

@@ -173,27 +202,50 @@ def get_arguments(shell):
173202

174203
if len(sys.argv) > 1:
175204
command = " ".join(sys.argv[1:])
205+
call_daemon(shell, command, False)
206+
sys.exit(0)
207+
208+
if interactive:
209+
shell.con.display("targetcli shell version %s\n"
210+
"Entering targetcli interactive mode for daemonized approach.\n"
211+
"Type 'exit' to quit.\n"
212+
% targetcli_version)
176213
else:
177-
inputs = []
178214
shell.con.display("targetcli shell version %s\n"
179-
"Entering targetcli batch mode for daemonized approach.\n"
180-
"Enter multiple commands separated by newline and "
181-
"type 'exit' to run them all in one go.\n"
182-
% targetcli_version)
183-
while True:
184-
shell.con.raw_write("/> ")
185-
command = six.moves.input()
186-
if command.lower() == "exit":
187-
break
215+
"Entering targetcli batch mode for daemonized approach.\n"
216+
"Enter multiple commands separated by newline and "
217+
"type 'exit' to run them all in one go.\n"
218+
% targetcli_version)
219+
220+
prompt_path = "/"
221+
if interactive:
222+
prompt_path = call_daemon(shell, None, interactive) # get the initial path
223+
224+
inputs = []
225+
real_exit=False
226+
while True:
227+
command = six.moves.input("%s> " %prompt_path)
228+
if command.lower() == "exit":
229+
real_exit=True
230+
elif not command:
231+
continue
232+
if not interactive:
188233
inputs.append(command)
189-
command = '%'.join(inputs) # delimit multiple commands with '%'
190-
191-
if not command:
192-
sys.exit(1)
193-
194-
usage_version(command);
234+
if real_exit:
235+
command = '%'.join(inputs) # delimit multiple commands with '%'
236+
call_daemon(shell, command, interactive)
237+
break
238+
else:
239+
if real_exit:
240+
break
241+
path = call_daemon(shell, command, interactive)
242+
if path:
243+
if path[0] == "/":
244+
prompt_path = path
245+
else:
246+
print(path) # Error No Path ...
195247

196-
return command
248+
sys.exit(0)
197249

198250
def main():
199251
'''
@@ -225,8 +277,12 @@ def main():
225277
if sys.argv[1] in ("disable-daemon", "--disable-daemon"):
226278
disable_daemon=True
227279

280+
interactive_mode = True
281+
if shell.prefs['daemon_use_batch_mode']:
282+
interactive_mode = False
283+
228284
if use_daemon and not disable_daemon:
229-
call_daemon(shell, get_arguments(shell).encode())
285+
switch_to_daemon(shell, interactive_mode)
230286
# does not return
231287

232288
try:

targetcli/ui_node.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ def __init__(self, name, parent=None, shell=None):
5252
self.define_config_group_param(
5353
'global', 'auto_use_daemon', 'bool',
5454
'If true, commands will be sent to targetclid.')
55+
self.define_config_group_param(
56+
'global', 'daemon_use_batch_mode', 'bool',
57+
'If true, use batch mode for daemonized approach.')
5558

5659
def assert_root(self):
5760
'''

targetclid.8

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,38 @@ $ targetcli set global auto_use_daemon=true
3030
.br
3131
$ targetcli ls
3232
.TP
33-
You can use batch mode for sending multiple commands in one go,
33+
You can use interactive mode,
3434
.br
3535
$ targetcli <hit-enter>
3636
.br
37-
targetcli shell version 2.1.50
37+
targetcli shell version 2.1.51
38+
.br
39+
Entering targetcli interactive mode for daemonized approach.
40+
.br
41+
Type 'exit' to quit.
42+
.br
43+
/> pwd
44+
.br
45+
/
46+
.br
47+
/> cd /iscsi
48+
.br
49+
/> pwd
50+
.br
51+
/iscsi
52+
.br
53+
/> exit
54+
.br
55+
.TP
56+
You can also use batch mode for sending multiple commands in one go,
57+
.br
58+
$ targetcli set global daemon_use_batch_mode=true
59+
.br
60+
Parameter daemon_use_batch_mode is now 'true'.
61+
.br
62+
$ targetcli <hit-enter>
63+
.br
64+
targetcli shell version 2.1.51
3865
.br
3966
Entering targetcli batch mode for daemonized approach.
4067
.br

0 commit comments

Comments
 (0)