Skip to content

Commit

Permalink
Add progress bar for Secure Copy (#1828)
Browse files Browse the repository at this point in the history
  • Loading branch information
ktbyers committed Jul 5, 2020
1 parent 0aa1126 commit e765138
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 5 deletions.
2 changes: 1 addition & 1 deletion EXAMPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ A set of common Netmiko use cases.
- [Standard logging](#standard-logging)

#### Secure Copy
- [Secure Copy](#secure-copy)
- [Secure Copy](#secure-copy-1)

#### Auto Detection of Device Type
- [Auto detection using SSH](#auto-detection-using-ssh)
Expand Down
3 changes: 2 additions & 1 deletion netmiko/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
)
from netmiko.ssh_autodetect import SSHDetect
from netmiko.base_connection import BaseConnection
from netmiko.scp_functions import file_transfer
from netmiko.scp_functions import file_transfer, progress_bar

# Alternate naming
Netmiko = ConnectHandler
Expand All @@ -40,6 +40,7 @@
"BaseConnection",
"Netmiko",
"file_transfer",
"progress_bar",
)

# Cisco cntl-shift-six sequence
Expand Down
11 changes: 11 additions & 0 deletions netmiko/cisco/cisco_ios.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,24 @@ def __init__(
direction="put",
source_config=None,
socket_timeout=10.0,
progress=None,
progress4=None,
):

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.")

if progress is not None or progress4 is not None:
raise NotImplementedError(
"Progress bar is not supported on inline transfers."
)
else:
self.progress = progress
self.progress4 = progress4

self.ssh_ctl_chan = ssh_conn
if source_file:
self.source_file = source_file
Expand Down
4 changes: 4 additions & 0 deletions netmiko/cisco/cisco_nxos_ssh.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ def __init__(
file_system="bootflash:",
direction="put",
socket_timeout=10.0,
progress=None,
progress4=None,
):
self.ssh_ctl_chan = ssh_conn
self.source_file = source_file
Expand All @@ -60,6 +62,8 @@ def __init__(
raise ValueError("Invalid direction specified")

self.socket_timeout = socket_timeout
self.progress = progress
self.progress4 = progress4

def check_file_exists(self, remote_cmd=""):
"""Check if the dest_file already exists on the file system (return boolean)."""
Expand Down
27 changes: 27 additions & 0 deletions netmiko/scp_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,29 @@
from netmiko import FileTransfer, InLineTransfer


def progress_bar(filename, size, sent, peername=None):
max_width = 50
filename = filename.decode()
clear_screen = chr(27) + "[2J"
terminating_char = "|"

# Percentage done
percent_complete = sent / size
percent_str = f"{percent_complete*100:.2f}%"
hash_count = int(percent_complete * max_width)
progress = hash_count * ">"

if peername is None:
header_msg = f"Transferring file: {filename}\n"
else:
header_msg = f"Transferring file to {peername}: {filename}\n"

msg = f"{progress:<50}{terminating_char:1} ({percent_str})"
print(clear_screen)
print(header_msg)
print(msg)


def verifyspace_and_transferfile(scp_transfer):
"""Verify space and transfer file."""
if not scp_transfer.verify_space_available():
Expand All @@ -27,6 +50,8 @@ def file_transfer(
inline_transfer=False,
overwrite_file=False,
socket_timeout=10.0,
progress=None,
progress4=None,
verify_file=None,
):
"""Use Secure Copy or Inline (IOS-only) to transfer files to/from network devices.
Expand Down Expand Up @@ -72,6 +97,8 @@ def file_transfer(
"dest_file": dest_file,
"direction": direction,
"socket_timeout": socket_timeout,
"progress": progress,
"progress4": progress4,
}
if file_system is not None:
scp_args["file_system"] = file_system
Expand Down
20 changes: 17 additions & 3 deletions netmiko/scp_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ class SCPConn(object):
Must close the SCP connection to get the file to write to the remote filesystem
"""

def __init__(self, ssh_conn, socket_timeout=10.0):
def __init__(self, ssh_conn, socket_timeout=10.0, progress=None, progress4=None):
self.ssh_ctl_chan = ssh_conn
self.socket_timeout = socket_timeout
self.progress = progress
self.progress4 = progress4
self.establish_scp_conn()

def establish_scp_conn(self):
Expand All @@ -33,7 +35,10 @@ def establish_scp_conn(self):
self.scp_conn = self.ssh_ctl_chan._build_ssh_client()
self.scp_conn.connect(**ssh_connect_params)
self.scp_client = scp.SCPClient(
self.scp_conn.get_transport(), socket_timeout=self.socket_timeout
self.scp_conn.get_transport(),
socket_timeout=self.socket_timeout,
progress=self.progress,
progress4=self.progress4,
)

def scp_transfer_file(self, source_file, dest_file):
Expand Down Expand Up @@ -64,13 +69,17 @@ def __init__(
file_system=None,
direction="put",
socket_timeout=10.0,
progress=None,
progress4=None,
hash_supported=True,
):
self.ssh_ctl_chan = ssh_conn
self.source_file = source_file
self.dest_file = dest_file
self.direction = direction
self.socket_timeout = socket_timeout
self.progress = progress
self.progress4 = progress4

auto_flag = (
"cisco_ios" in ssh_conn.device_type
Expand Down Expand Up @@ -107,7 +116,12 @@ def __exit__(self, exc_type, exc_value, traceback):

def establish_scp_conn(self):
"""Establish SCP connection."""
self.scp_conn = SCPConn(self.ssh_ctl_chan, socket_timeout=self.socket_timeout)
self.scp_conn = SCPConn(
self.ssh_ctl_chan,
socket_timeout=self.socket_timeout,
progress=self.progress,
progress4=self.progress4,
)

def close_scp_chan(self):
"""Close the SCP connection to the remote network device."""
Expand Down

0 comments on commit e765138

Please sign in to comment.