From 9cbe70f8f4ab4c1bc9cea886c61a02c36959a748 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Tue, 17 Jan 2017 12:00:20 -0800 Subject: [PATCH 1/4] Minor fix to TCL transfer exit --- netmiko/scp_handler.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/netmiko/scp_handler.py b/netmiko/scp_handler.py index d4e1865e0..47dd66bd6 100644 --- a/netmiko/scp_handler.py +++ b/netmiko/scp_handler.py @@ -305,7 +305,9 @@ def _exit_tcl_mode(self): time.sleep(1) output = self.ssh_ctl_chan.read_channel() if '(tcl)' in output: - output += self.ssh_ctl_chan.write_channel(TCL_EXIT + "\r") + self.ssh_ctl_chan.write_channel(TCL_EXIT + "\r") + time.sleep(1) + output += self.ssh_ctl_chan.read_channel() return output def establish_scp_conn(self): From 19dfe4f1138c8be0e2ba82268f0e837f616cefc2 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Tue, 17 Jan 2017 18:53:48 -0800 Subject: [PATCH 2/4] Fixing Netmiko TCL transfer timing issues --- netmiko/scp_handler.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/netmiko/scp_handler.py b/netmiko/scp_handler.py index 47dd66bd6..4cd4b7442 100644 --- a/netmiko/scp_handler.py +++ b/netmiko/scp_handler.py @@ -339,8 +339,13 @@ def put_file(self): self.ssh_ctl_chan.write_channel(file_contents) self.ssh_ctl_chan.write_channel(TCL_FILECMD_EXIT + "\r") - time.sleep(1) - output = self.ssh_ctl_chan.read_channel() + output = '' + while True: + time.sleep(1.5) + new_output = self.ssh_ctl_chan.read_channel() + if not new_output: + break + output += new_output # The file doesn't write until tclquit TCL_EXIT = 'tclquit' From 3bdc960fa01c6600378a529e2f3357091633fe24 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Tue, 17 Jan 2017 20:21:44 -0800 Subject: [PATCH 3/4] Adding support for config in InLineTransfer --- netmiko/scp_handler.py | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/netmiko/scp_handler.py b/netmiko/scp_handler.py index 4cd4b7442..5799957bf 100644 --- a/netmiko/scp_handler.py +++ b/netmiko/scp_handler.py @@ -259,6 +259,31 @@ def disable_scp(self, cmd=None): class InLineTransfer(FileTransfer): """Use TCL on Cisco IOS to directly transfer file.""" + def __init__(self, ssh_conn, source_file, dest_file, file_system=None, direction='put', + source_config=''): + if source_file and source_config: + msg = "Invalid call to InLineTransfer both source_file and source_config specified." + raise ValueError(msg) + if direction != 'put': + raise ValueError("Only put operation supported by InLineTransfer.") + + self.ssh_ctl_chan = ssh_conn + if source_file: + self.source_file = source_file + self.source_md5 = self.file_md5(source_file) + self.file_size = os.stat(source_file).st_size + elif source_config: + self.source_config = source_config + self.source_md5 = self.config_md5(source_config) + self.file_size = len(source_config.encode('UTF-8')) + self.dest_file = dest_file + self.direction = direction + + if not file_system: + self.file_system = self.ssh_ctl_chan._autodetect_fs() + else: + self.file_system = file_system + @staticmethod def _read_file(file_name): with open(file_name, "rt") as f: @@ -326,13 +351,22 @@ def file_md5(self, file_name): file_contents = file_contents.encode('UTF-8') return hashlib.md5(file_contents).hexdigest() + def config_md5(self, source_config): + """Compute MD5 hash of file.""" + file_contents = source_config + '\n' # Cisco IOS automatically adds this + file_contents = file_contents.encode('UTF-8') + return hashlib.md5(file_contents).hexdigest() + def put_file(self): curlybrace = r'{' TCL_FILECMD_ENTER = 'puts [open "{}{}" w+] {}'.format(self.file_system, self.dest_file, curlybrace) TCL_FILECMD_EXIT = '}' - file_contents = self._read_file(self.source_file) + if self.source_file: + file_contents = self._read_file(self.source_file) + elif self.source_config: + file_contents = self.source_config file_contents = self._tcl_newline_rationalize(file_contents) self.ssh_ctl_chan.write_channel(TCL_FILECMD_ENTER) From 1b5b0aeaca67d159a04a90dd2d0da41e957f6e0e Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Wed, 18 Jan 2017 15:25:03 -0800 Subject: [PATCH 4/4] Adding default arguments to InLineTransfer --- netmiko/__init__.py | 2 +- netmiko/scp_handler.py | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/netmiko/__init__.py b/netmiko/__init__.py index 2e34a5b85..93de175dd 100644 --- a/netmiko/__init__.py +++ b/netmiko/__init__.py @@ -17,7 +17,7 @@ NetmikoTimeoutError = NetMikoTimeoutException NetmikoAuthError = NetMikoAuthenticationException -__version__ = '1.2.4' +__version__ = '1.2.7' __all__ = ('ConnectHandler', 'ssh_dispatcher', 'platforms', 'SCPConn', 'FileTransfer', 'NetMikoTimeoutException', 'NetMikoAuthenticationException', diff --git a/netmiko/scp_handler.py b/netmiko/scp_handler.py index 5799957bf..bf3a88d81 100644 --- a/netmiko/scp_handler.py +++ b/netmiko/scp_handler.py @@ -259,8 +259,8 @@ def disable_scp(self, cmd=None): class InLineTransfer(FileTransfer): """Use TCL on Cisco IOS to directly transfer file.""" - def __init__(self, ssh_conn, source_file, dest_file, file_system=None, direction='put', - source_config=''): + def __init__(self, ssh_conn, source_file=None, dest_file=None, file_system=None, direction='put', + source_config=None): if source_file and source_config: msg = "Invalid call to InLineTransfer both source_file and source_config specified." raise ValueError(msg) @@ -270,9 +270,11 @@ def __init__(self, ssh_conn, source_file, dest_file, file_system=None, direction self.ssh_ctl_chan = ssh_conn if source_file: self.source_file = source_file + self.source_config = None self.source_md5 = self.file_md5(source_file) self.file_size = os.stat(source_file).st_size elif source_config: + self.source_file = None self.source_config = source_config self.source_md5 = self.config_md5(source_config) self.file_size = len(source_config.encode('UTF-8'))