From a135b25e80e8093cb35aa03507f22568803444b9 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Sep 29 2020 06:55:58 +0000 Subject: import targetcli-2.1.51-2.el7 --- diff --git a/.gitignore b/.gitignore index ba01e7f..4f66cec 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/targetcli-fb-2.1.fb49.tar.gz +SOURCES/targetcli-fb-2.1.51.tar.gz diff --git a/.targetcli.metadata b/.targetcli.metadata index 52a4911..2a071a5 100644 --- a/.targetcli.metadata +++ b/.targetcli.metadata @@ -1 +1 @@ -f55bb874f9644991a042ee83f25c14d44a86d2db SOURCES/targetcli-fb-2.1.fb49.tar.gz +3e6f8caa6fc7a2591a97fd8b5c37554c71c1dd52 SOURCES/targetcli-fb-2.1.51.tar.gz diff --git a/SOURCES/0001-setup.py-add-the-socket-and-service-files-to-the-dat.patch b/SOURCES/0001-setup.py-add-the-socket-and-service-files-to-the-dat.patch new file mode 100644 index 0000000..1c784e1 --- /dev/null +++ b/SOURCES/0001-setup.py-add-the-socket-and-service-files-to-the-dat.patch @@ -0,0 +1,26 @@ +From 9c4be0387f7ae49a85db2ab3e31eb9d7834dded1 Mon Sep 17 00:00:00 2001 +From: Maurizio Lombardi +Date: Thu, 21 Nov 2019 09:58:55 +0100 +Subject: [PATCH] setup.py: add the socket and service files to the data_files + section + +Signed-off-by: Maurizio Lombardi +--- + setup.py | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/setup.py b/setup.py +index 8dff55e..4518165 100755 +--- a/setup.py ++++ b/setup.py +@@ -34,6 +34,7 @@ setup( + 'scripts/targetcli', + 'daemon/targetclid' + ], ++ data_files = [('/usr/lib/systemd/system', ['systemd/targetclid.socket', 'systemd/targetclid.service'])], + classifiers = [ + "Programming Language :: Python", + "Programming Language :: Python :: 3", +-- +2.21.0 + diff --git a/SOURCES/0002-Use-StringIO-as-a-buffer-instead-of-a-file.patch b/SOURCES/0002-Use-StringIO-as-a-buffer-instead-of-a-file.patch new file mode 100644 index 0000000..220bed8 --- /dev/null +++ b/SOURCES/0002-Use-StringIO-as-a-buffer-instead-of-a-file.patch @@ -0,0 +1,55 @@ +From 3db75315b7e436e57943efb132f7b331a7a7744c Mon Sep 17 00:00:00 2001 +From: Matt Coleman +Date: Thu, 7 Nov 2019 18:21:32 -0500 +Subject: [PATCH] Use StringIO as a buffer instead of a file + +--- + daemon/targetclid | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/daemon/targetclid b/daemon/targetclid +index fb472dc..dfc22ce 100755 +--- a/daemon/targetclid ++++ b/daemon/targetclid +@@ -32,6 +32,7 @@ import struct + import fcntl + import signal + import errno ++import io + + + err = sys.stderr +@@ -153,7 +154,7 @@ class TargetCLI: + connection.close() + still_listen = False + else: +- self.con._stdout = self.con._stderr = f = open("/tmp/data.txt", "w") ++ self.con._stdout = self.con._stderr = f = io.StringIO() + try: + # extract multiple commands delimited with '%' + list_data = data.decode().split('%') +@@ -165,14 +166,14 @@ class TargetCLI: + # Restore + self.con._stdout = self.con_stdout_ + self.con._stderr = self.con_stderr_ +- f.close() + +- with open('/tmp/data.txt', 'r') as f: +- output = f.read() +- var = struct.pack('i', len(output)) +- connection.sendall(var) # length of string +- if len(output): +- connection.sendall(output.encode()) # actual string ++ output = f.getvalue() ++ var = struct.pack('i', len(output)) ++ connection.sendall(var) # length of string ++ if len(output): ++ connection.sendall(output.encode()) # actual string ++ ++ f.close() + + + def usage(): +-- +2.21.0 + diff --git a/SOURCES/0003-Fix-targetclid-daemon-infinite-stuck.patch b/SOURCES/0003-Fix-targetclid-daemon-infinite-stuck.patch new file mode 100644 index 0000000..49c5113 --- /dev/null +++ b/SOURCES/0003-Fix-targetclid-daemon-infinite-stuck.patch @@ -0,0 +1,29 @@ +From 5349bc9d1105c71158fce8dfd6a4733eb90dbb1a Mon Sep 17 00:00:00 2001 +From: Prasanna Kumar Kalever +Date: Mon, 30 Mar 2020 19:36:26 +0530 +Subject: [PATCH] Fix targetclid daemon infinite stuck + +We need to open a byte IO stream because we are actually dealing with +binary data in memory. + +Signed-off-by: Prasanna Kumar Kalever +--- + daemon/targetclid | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/daemon/targetclid b/daemon/targetclid +index dfc22ce..d4c6562 100755 +--- a/daemon/targetclid ++++ b/daemon/targetclid +@@ -154,7 +154,7 @@ class TargetCLI: + connection.close() + still_listen = False + else: +- self.con._stdout = self.con._stderr = f = io.StringIO() ++ self.con._stdout = self.con._stderr = f = io.BytesIO() + try: + # extract multiple commands delimited with '%' + list_data = data.decode().split('%') +-- +2.21.0 + diff --git a/SOURCES/0004-targetclid.sock-change-SocketMode-to-0600.patch b/SOURCES/0004-targetclid.sock-change-SocketMode-to-0600.patch new file mode 100644 index 0000000..86c6be0 --- /dev/null +++ b/SOURCES/0004-targetclid.sock-change-SocketMode-to-0600.patch @@ -0,0 +1,33 @@ +From 6e4f39357a90a914d11bac21cc2d2b52c07c213d Mon Sep 17 00:00:00 2001 +From: Prasanna Kumar Kalever +Date: Thu, 26 Mar 2020 17:18:47 +0530 +Subject: [PATCH] targetclid.sock: change SocketMode to 0600 + +SocketMode= +If listening on a file system socket or FIFO, this option specifies the +file system access mode used when creating the file node. Takes an +access mode in octal notation. Defaults to 0666. + +Thanks Alex Murray[@alexmurray], for reporting. + +Fixes: #162 +Signed-off-by: Prasanna Kumar Kalever +--- + systemd/targetclid.socket | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/systemd/targetclid.socket b/systemd/targetclid.socket +index 4730fce..ba29ebb 100644 +--- a/systemd/targetclid.socket ++++ b/systemd/targetclid.socket +@@ -4,6 +4,7 @@ Documentation=man:targetclid(8) + + [Socket] + ListenStream=/var/run/targetclid.sock ++SocketMode=0600 + + [Install] + WantedBy=sockets.target +-- +2.21.0 + diff --git a/SOURCES/0005-Fix-StringIO-BytesIO-stuck-issue.patch b/SOURCES/0005-Fix-StringIO-BytesIO-stuck-issue.patch new file mode 100644 index 0000000..3c752af --- /dev/null +++ b/SOURCES/0005-Fix-StringIO-BytesIO-stuck-issue.patch @@ -0,0 +1,113 @@ +From 0157f74a31adc1bd999ea5e5bc3a9c34af90b98c Mon Sep 17 00:00:00 2001 +From: Prasanna Kumar Kalever +Date: Thu, 2 Apr 2020 16:03:57 +0530 +Subject: [PATCH] Fix StringIO/BytesIO stuck issue + +We all know the way python3 handles strings is a bit different. + +$ python2 +Python 2.7.16 (default, Apr 30 2019, 15:54:43) +[GCC 9.0.1 20190312 (Red Hat 9.0.1-0.10)] on linux2 +Type "help", "copyright", "credits" or "license" for more information. +>>> import io +>>> s=io.BytesIO() +>>> s.write('hello') +5L +>>> s.getvalue() +'hello' +>>> s=io.StringIO() +>>> s.write('hello') +Traceback (most recent call last): + File "", line 1, in +TypeError: unicode argument expected, got 'str' +>>> s.write(u'hello') +5L +>>> s.getvalue() +u'hello' +>>> + +$ python3 +Python 3.6.8 (default, Dec 5 2019, 15:45:45) +[GCC 8.3.1 20191121 (Red Hat 8.3.1-5)] on linux +Type "help", "copyright", "credits" or "license" for more information. +>>> import io +>>> s=io.BytesIO() +>>> s.write('hello') +Traceback (most recent call last): + File "", line 1, in +TypeError: a bytes-like object is required, not 'str' +>>> s.write(b'hello') +5 +>>> s.getvalue() +b'hello' +>>> s=io.StringIO() +>>> s.write('hello') +5 +>>> s.getvalue() +'hello' +>>> + +The way Python2 and Python3 handles String and Bytes IO is different. +* In Python2 BytesIO() accepts text format syntax, and StringIO() expects unicodes +* While in Python3 StringIO() accepts text format syntax, and BytesIO() expects bytes like objects + +I think the compatibility of using both the IO streams with python2 and python3 is compromised. + +Hence this patch, uses BytesIO() and StringIO() based on python version. + +Signed-off-by: Prasanna Kumar Kalever +--- + daemon/targetclid | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/daemon/targetclid b/daemon/targetclid +index d4c6562..5df6ca2 100755 +--- a/daemon/targetclid ++++ b/daemon/targetclid +@@ -32,9 +32,13 @@ import struct + import fcntl + import signal + import errno +-import io + + ++if sys.version_info < (3, 0): ++ from io import BytesIO as StringIO ++else: ++ from io import StringIO ++ + err = sys.stderr + + class TargetCLI: +@@ -154,24 +158,23 @@ class TargetCLI: + connection.close() + still_listen = False + else: +- self.con._stdout = self.con._stderr = f = io.BytesIO() ++ self.con._stdout = self.con._stderr = f = StringIO() + try: + # extract multiple commands delimited with '%' + list_data = data.decode().split('%') + for cmd in list_data: + self.shell.run_cmdline(cmd) + except Exception as e: +- print(str(e), file=f) # push error to stream ++ print(str(e).encode(), file=f) # push error to stream + + # Restore + self.con._stdout = self.con_stdout_ + self.con._stderr = self.con_stderr_ +- +- output = f.getvalue() ++ output = f.getvalue().encode() + var = struct.pack('i', len(output)) + connection.sendall(var) # length of string + if len(output): +- connection.sendall(output.encode()) # actual string ++ connection.sendall(output) # actual string + + f.close() + +-- +2.21.0 + diff --git a/SOURCES/0006-Use-temp-file-objects-for-temporary-storage-area.patch b/SOURCES/0006-Use-temp-file-objects-for-temporary-storage-area.patch new file mode 100644 index 0000000..ed82c5b --- /dev/null +++ b/SOURCES/0006-Use-temp-file-objects-for-temporary-storage-area.patch @@ -0,0 +1,112 @@ +From 4f6611ed208b6029b4523ca7760a802e82b6a199 Mon Sep 17 00:00:00 2001 +From: Prasanna Kumar Kalever +Date: Fri, 3 Apr 2020 20:06:48 +0530 +Subject: [PATCH] Use temp file objects for temporary storage area + +happen to see yet another issue after we switch to stringIO/bytesIO: + +$ targetcli ls +'unicode' does not have the buffer interface + +After which I felt like dealing with StringIO/BytesIO is like a +wild goose chase and we are after all attempting to deal with python +incompatible apis. + +Technically speaking, the rtslib and configshell libraries are expecting a +string IO stream, but then for python2 with ByteIO() we are passing a +bytestream, and stringIO() is behaving a bit different in python2 than +expected as explained in my previous patch. + +Lets simply switch to temporary file in the most secure manner possible, +opening files in string mode will assure the compatibility across the platforms. + +At the end we wish to have a consistent behaviour across all python versions. + +Signed-off-by: Prasanna Kumar Kalever +--- + daemon/targetclid | 26 +++++++++++++------------- + scripts/targetcli | 3 ++- + 2 files changed, 15 insertions(+), 14 deletions(-) + +diff --git a/daemon/targetclid b/daemon/targetclid +index 5df6ca2..329cede 100755 +--- a/daemon/targetclid ++++ b/daemon/targetclid +@@ -26,19 +26,16 @@ from configshell_fb import ConfigShell + from os import getuid, getenv, unlink + from threading import Thread + ++import os + import sys + import socket + import struct + import fcntl + import signal + import errno ++import tempfile + + +-if sys.version_info < (3, 0): +- from io import BytesIO as StringIO +-else: +- from io import StringIO +- + err = sys.stderr + + class TargetCLI: +@@ -158,26 +155,29 @@ class TargetCLI: + connection.close() + still_listen = False + else: +- self.con._stdout = self.con._stderr = f = StringIO() ++ self.con._stdout = self.con._stderr = f = tempfile.NamedTemporaryFile(mode='w', delete=False) + try: + # extract multiple commands delimited with '%' + list_data = data.decode().split('%') + for cmd in list_data: + self.shell.run_cmdline(cmd) + except Exception as e: +- print(str(e).encode(), file=f) # push error to stream ++ print(str(e), file=f) # push error to stream + + # Restore + self.con._stdout = self.con_stdout_ + self.con._stderr = self.con_stderr_ +- output = f.getvalue().encode() +- var = struct.pack('i', len(output)) +- connection.sendall(var) # length of string +- if len(output): +- connection.sendall(output) # actual string +- + f.close() + ++ with open(f.name, 'r') as f: ++ output = f.read() ++ var = struct.pack('i', len(output)) ++ connection.sendall(var) # length of string ++ if len(output): ++ connection.sendall(output.encode()) # actual string ++ ++ os.unlink(f.name) ++ + + def usage(): + print("Usage: %s [--version|--help]" % sys.argv[0], file=err) +diff --git a/scripts/targetcli b/scripts/targetcli +index 04e5aba..f11ece4 100755 +--- a/scripts/targetcli ++++ b/scripts/targetcli +@@ -154,8 +154,9 @@ def call_daemon(shell, req): + # get the actual data in chunks + while amount_received < amount_expected: + data = sock.recv(1024) ++ data = data.decode() + amount_received += len(data) +- print(data.decode(), end ="") ++ print(data, end ="") + + sock.send(b'-END@OF@DATA-') + sock.close() +-- +2.21.0 + diff --git a/SOURCES/0007-daemonized-mode-add-interactive-shell-support.patch b/SOURCES/0007-daemonized-mode-add-interactive-shell-support.patch new file mode 100644 index 0000000..bab0c85 --- /dev/null +++ b/SOURCES/0007-daemonized-mode-add-interactive-shell-support.patch @@ -0,0 +1,202 @@ +From 15abdd481c5babd4128f3f0a9f0ac2f983bf1c89 Mon Sep 17 00:00:00 2001 +From: Prasanna Kumar Kalever +Date: Fri, 3 Apr 2020 13:01:06 +0530 +Subject: [PATCH 1/3] daemonized-mode: add interactive shell support + +set interactive mode as default to make it appear similar to cli approach, + +$ targetcli +targetcli shell version 2.1.51 +Entering targetcli interactive mode for daemonized approach. +Type 'exit' to quit. + +/> pwd +/ +/> cd /iscsi +/> pwd +/iscsi +/> exit + +Here we introduce a new global option daemon_use_batch_mode for switching between +batch and interactive modes. + +$ targetcli set global daemon_use_batch_mode=true +Parameter daemon_use_batch_mode is now 'true'. + +$ targetcli +targetcli shell version 2.1.51 +Entering targetcli batch mode for daemonized approach. +Enter multiple commands separated by newline and type 'exit' to run them +all in one go. + +/> pwd +/> cd /iscsi +/> pwd +/ +/iscsi + +Fixes: #160 +Signed-off-by: Prasanna Kumar Kalever +--- + scripts/targetcli | 57 ++++++++++++++++++++++++++++---------------- + targetcli/ui_node.py | 3 +++ + targetclid.8 | 31 ++++++++++++++++++++++-- + 3 files changed, 69 insertions(+), 22 deletions(-) + +diff --git a/scripts/targetcli b/scripts/targetcli +index f11ece4..3496126 100755 +--- a/scripts/targetcli ++++ b/scripts/targetcli +@@ -64,6 +64,7 @@ class TargetCLI(ConfigShell): + 'max_backup_files': '10', + 'auto_add_default_portal': True, + 'auto_use_daemon': False, ++ 'daemon_use_batch_mode': False, + } + + def usage(): +@@ -160,9 +161,8 @@ def call_daemon(shell, req): + + sock.send(b'-END@OF@DATA-') + sock.close() +- sys.exit(0) + +-def get_arguments(shell): ++def switch_to_daemon(shell, interactive): + readline.set_completer(completer) + readline.set_completer_delims('') + +@@ -173,27 +173,40 @@ def get_arguments(shell): + + if len(sys.argv) > 1: + command = " ".join(sys.argv[1:]) ++ call_daemon(shell, command.encode()) ++ sys.exit(0) ++ ++ if interactive: ++ shell.con.display("targetcli shell version %s\n" ++ "Entering targetcli interactive mode for daemonized approach.\n" ++ "Type 'exit' to quit.\n" ++ % targetcli_version) + else: +- inputs = [] + shell.con.display("targetcli shell version %s\n" +- "Entering targetcli batch mode for daemonized approach.\n" +- "Enter multiple commands separated by newline and " +- "type 'exit' to run them all in one go.\n" +- % targetcli_version) +- while True: +- shell.con.raw_write("/> ") +- command = six.moves.input() +- if command.lower() == "exit": +- break ++ "Entering targetcli batch mode for daemonized approach.\n" ++ "Enter multiple commands separated by newline and " ++ "type 'exit' to run them all in one go.\n" ++ % targetcli_version) ++ ++ inputs = [] ++ real_exit=False ++ while True: ++ shell.con.raw_write("/> ") ++ command = six.moves.input() ++ if command.lower() == "exit": ++ real_exit=True ++ if not interactive: + inputs.append(command) +- command = '%'.join(inputs) # delimit multiple commands with '%' +- +- if not command: +- sys.exit(1) +- +- usage_version(command); ++ if real_exit: ++ command = '%'.join(inputs) # delimit multiple commands with '%' ++ call_daemon(shell, command.encode()) ++ break ++ else: ++ if real_exit: ++ break ++ call_daemon(shell, command.encode()) + +- return command ++ sys.exit(0) + + def main(): + ''' +@@ -225,8 +238,12 @@ def main(): + if sys.argv[1] in ("disable-daemon", "--disable-daemon"): + disable_daemon=True + ++ interactive_mode = True ++ if shell.prefs['daemon_use_batch_mode']: ++ interactive_mode = False ++ + if use_daemon and not disable_daemon: +- call_daemon(shell, get_arguments(shell).encode()) ++ switch_to_daemon(shell, interactive_mode) + # does not return + + try: +diff --git a/targetcli/ui_node.py b/targetcli/ui_node.py +index 58a70c6..0485950 100644 +--- a/targetcli/ui_node.py ++++ b/targetcli/ui_node.py +@@ -52,6 +52,9 @@ class UINode(ConfigNode): + self.define_config_group_param( + 'global', 'auto_use_daemon', 'bool', + 'If true, commands will be sent to targetclid.') ++ self.define_config_group_param( ++ 'global', 'daemon_use_batch_mode', 'bool', ++ 'If true, use batch mode for daemonized approach.') + + def assert_root(self): + ''' +diff --git a/targetclid.8 b/targetclid.8 +index a783091..5760168 100644 +--- a/targetclid.8 ++++ b/targetclid.8 +@@ -30,11 +30,38 @@ $ targetcli set global auto_use_daemon=true + .br + $ targetcli ls + .TP +-You can use batch mode for sending multiple commands in one go, ++You can use interactive mode, + .br + $ targetcli + .br +-targetcli shell version 2.1.50 ++targetcli shell version 2.1.51 ++.br ++Entering targetcli interactive mode for daemonized approach. ++.br ++Type 'exit' to quit. ++.br ++/> pwd ++.br ++/ ++.br ++/> cd /iscsi ++.br ++/> pwd ++.br ++/iscsi ++.br ++/> exit ++.br ++.TP ++You can also use batch mode for sending multiple commands in one go, ++.br ++$ targetcli set global daemon_use_batch_mode=true ++.br ++Parameter daemon_use_batch_mode is now 'true'. ++.br ++$ targetcli ++.br ++targetcli shell version 2.1.51 + .br + Entering targetcli batch mode for daemonized approach. + .br +-- +2.21.0 + diff --git a/SOURCES/0008-daemonized-mode-fix-issues-noticed-with-curser-posit.patch b/SOURCES/0008-daemonized-mode-fix-issues-noticed-with-curser-posit.patch new file mode 100644 index 0000000..a5e035c --- /dev/null +++ b/SOURCES/0008-daemonized-mode-fix-issues-noticed-with-curser-posit.patch @@ -0,0 +1,35 @@ +From 3cfd45bb22cdcb1512228c3f8101a1e3f74af3ee Mon Sep 17 00:00:00 2001 +From: Prasanna Kumar Kalever +Date: Mon, 6 Apr 2020 16:05:56 +0530 +Subject: [PATCH 2/3] daemonized-mode: fix issues noticed with curser position + +* get/set x and y postions of the curser dynamically +* skip accepting command if no command is provided + eg: just hit enter with no command + +Signed-off-by: Prasanna Kumar Kalever +--- + scripts/targetcli | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/scripts/targetcli b/scripts/targetcli +index 3496126..97f41eb 100755 +--- a/scripts/targetcli ++++ b/scripts/targetcli +@@ -192,9 +192,13 @@ def switch_to_daemon(shell, interactive): + real_exit=False + while True: + shell.con.raw_write("/> ") ++ pos = shell.con.get_cursor_xy() ++ shell.con.set_cursor_xy(pos[0], pos[1]) + command = six.moves.input() + if command.lower() == "exit": + real_exit=True ++ elif not command: ++ continue + if not interactive: + inputs.append(command) + if real_exit: +-- +2.21.0 + diff --git a/SOURCES/0009-daemon-interactive-show-path-on-prompt.patch b/SOURCES/0009-daemon-interactive-show-path-on-prompt.patch new file mode 100644 index 0000000..3db9b39 --- /dev/null +++ b/SOURCES/0009-daemon-interactive-show-path-on-prompt.patch @@ -0,0 +1,140 @@ +From 853bbc4f85427206bb27e5d63727d8b9fbe10972 Mon Sep 17 00:00:00 2001 +From: Prasanna Kumar Kalever +Date: Mon, 6 Apr 2020 19:33:20 +0530 +Subject: [PATCH 3/3] daemon-interactive: show path on prompt + +$ targetcli +targetcli shell version 2.1.51 +Entering targetcli interactive mode for daemonized approach. +Type 'exit' to quit. + +/> pwd +/ +/> cd /iscsi +/iscsi> ls +o- iscsi .......................................... [Targets: 0] +/iscsi> exit + +Signed-off-by: Prasanna Kumar Kalever +--- + scripts/targetcli | 52 ++++++++++++++++++++++++++++++++++++++++------- + 1 file changed, 45 insertions(+), 7 deletions(-) + +diff --git a/scripts/targetcli b/scripts/targetcli +index 97f41eb..e1ec178 100755 +--- a/scripts/targetcli ++++ b/scripts/targetcli +@@ -122,7 +122,7 @@ def completer(text, state): + except IndexError: + return None + +-def call_daemon(shell, req): ++def call_daemon(shell, req, interactive): + try: + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + except socket.error as err: +@@ -140,9 +140,23 @@ def call_daemon(shell, req): + "then run '#targetcli --disable-daemon'", 'red')) + sys.exit(1) + ++ # Two cases where we want to get pwd: ++ # 1. Before starting shell in interactive mode, needed for setting terminal ++ # 2. And only in Interactive mode, having command 'cd' ++ get_pwd = False ++ if interactive: ++ if not req: ++ req = "pwd" ++ get_pwd = True ++ elif "cd " in req: ++ req += "%pwd" ++ get_pwd = True ++ else: ++ req = "cd /%" + req # Non-interactive modes always consider start at '/' ++ + try: + # send request +- sock.sendall(req) ++ sock.sendall(req.encode()) + except socket.error as err: + shell.con.display(shell.con.render_text(err, 'red')) + sys.exit(1) +@@ -153,15 +167,30 @@ def call_daemon(shell, req): + amount_received = 0 + + # get the actual data in chunks ++ output = "" ++ path = "" + while amount_received < amount_expected: + data = sock.recv(1024) + data = data.decode() + amount_received += len(data) +- print(data, end ="") ++ output += data ++ ++ if get_pwd: ++ output_split = output.splitlines() ++ lines = len(output_split) ++ for i in range(0, lines): ++ if i == lines-1: ++ path = str(output_split[i]) ++ else: ++ print(str(output_split[i]), end ="\n") ++ else: ++ print(output, end ="") + + sock.send(b'-END@OF@DATA-') + sock.close() + ++ return path ++ + def switch_to_daemon(shell, interactive): + readline.set_completer(completer) + readline.set_completer_delims('') +@@ -173,7 +202,7 @@ def switch_to_daemon(shell, interactive): + + if len(sys.argv) > 1: + command = " ".join(sys.argv[1:]) +- call_daemon(shell, command.encode()) ++ call_daemon(shell, command, False) + sys.exit(0) + + if interactive: +@@ -188,10 +217,14 @@ def switch_to_daemon(shell, interactive): + "type 'exit' to run them all in one go.\n" + % targetcli_version) + ++ prompt_path = "/" ++ if interactive: ++ prompt_path = call_daemon(shell, None, interactive) # get the initial path ++ + inputs = [] + real_exit=False + while True: +- shell.con.raw_write("/> ") ++ shell.con.raw_write("%s> " %prompt_path) + pos = shell.con.get_cursor_xy() + shell.con.set_cursor_xy(pos[0], pos[1]) + command = six.moves.input() +@@ -203,12 +236,17 @@ def switch_to_daemon(shell, interactive): + inputs.append(command) + if real_exit: + command = '%'.join(inputs) # delimit multiple commands with '%' +- call_daemon(shell, command.encode()) ++ call_daemon(shell, command, interactive) + break + else: + if real_exit: + break +- call_daemon(shell, command.encode()) ++ path = call_daemon(shell, command, interactive) ++ if path: ++ if path[0] == "/": ++ prompt_path = path ++ else: ++ print(path) # Error No Path ... + + sys.exit(0) + +-- +2.21.0 + diff --git a/SPECS/targetcli.spec b/SPECS/targetcli.spec index 932dcb2..24f179f 100644 --- a/SPECS/targetcli.spec +++ b/SPECS/targetcli.spec @@ -4,10 +4,19 @@ Name: targetcli License: ASL 2.0 Group: System Environment/Libraries Summary: An administration shell for storage targets -Version: 2.1.fb49 -Release: 1%{?dist} -URL: https://fedorahosted.org/targetcli-fb/ -Source: https://fedorahosted.org/released/targetcli-fb/%{oname}-%{version}.tar.gz +Version: 2.1.51 +Release: 2%{?dist} +URL: https://github.com/open-iscsi/%{oname} +Source: %{url}/archive/v%{version}/%{oname}-%{version}.tar.gz +Patch0: 0001-setup.py-add-the-socket-and-service-files-to-the-dat.patch +Patch1: 0002-Use-StringIO-as-a-buffer-instead-of-a-file.patch +Patch2: 0003-Fix-targetclid-daemon-infinite-stuck.patch +Patch3: 0004-targetclid.sock-change-SocketMode-to-0600.patch +Patch4: 0005-Fix-StringIO-BytesIO-stuck-issue.patch +Patch5: 0006-Use-temp-file-objects-for-temporary-storage-area.patch +Patch6: 0007-daemonized-mode-add-interactive-shell-support.patch +Patch7: 0008-daemonized-mode-fix-issues-noticed-with-curser-posit.patch +Patch8: 0009-daemon-interactive-show-path-on-prompt.patch BuildArch: noarch BuildRequires: python-devel python-setuptools Requires: python-rtslib >= 2.1.fb41, python-configshell, python-ethtool @@ -21,26 +30,56 @@ users will also need to install and use fcoe-utils. %prep %setup -q -n %{oname}-%{version} +%patch0 -p1 +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 %build %{__python} setup.py build gzip --stdout targetcli.8 > targetcli.8.gz +gzip --stdout targetclid.8 > targetclid.8.gz %install %{__python} setup.py install --skip-build --root %{buildroot} mkdir -p %{buildroot}%{_sysconfdir}/target/backup +mkdir -p %{buildroot}%{_sysconfdir}/target/pr mkdir -p %{buildroot}%{_mandir}/man8/ install -m 644 targetcli.8.gz %{buildroot}%{_mandir}/man8/ +install -m 644 targetclid.8.gz %{buildroot}%{_mandir}/man8/ %files %{python_sitelib}/* %{_bindir}/targetcli +%{_bindir}/targetclid %dir %{_sysconfdir}/target %dir %{_sysconfdir}/target/backup +%dir %{_sysconfdir}/target/pr %doc COPYING README.md %{_mandir}/man8/targetcli.8.gz +%{_mandir}/man8/targetclid.8.gz +%{_usr}/lib/systemd/system/targetclid.service +%{_usr}/lib/systemd/system/targetclid.socket + %changelog +* Mon Apr 06 2020 Maurizio Lombardi - 2.1.51-2 +- Add the interactive daemon console. + +* Fri Apr 03 2020 Maurizio Lombardi - 2.1.fb51-1 +- Update to a new upstream version + +* Wed Mar 25 2020 Maurizio Lombardi - 2.1.fb49-3 +- Respin a new release of targetcli. + +* Mon Sep 09 2019 Maurizio Lombardi - 2.1.fb49-2 +- Get a lock to avoid the issues with concurrent backstore creation + * Tue Jan 29 2019 Maurizio Lombardi - 2.1.fb49-1 - Rebase to latest upstream version