Transferring Files with Netmiko SCP (file_transfer) Function

When it comes to copying files to and from network devices, the Netmiko SCP file_transfer function offers a straightforward and reliable solution. In this blog post, we will take a close look at how to use the Netmiko SCP function to transfer files easily and securely, providing you with a clear understanding of this useful tool.

Overview

Secure Copy Protocol (SCP) is a file transfer protocol that enables secure and efficient copying of files over a network. It is based on the Secure Shell (SSH) protocol, which ensures the protection of data during transmission by encrypting the files.

This Netmiko function is really helpful when you need to copy the same file, like an IOS image, to many devices. Instead of copying files one by one, which takes a lot of time and can lead to mistakes, you can use a script that will do the work for you, making it easier and quicker to get the files where they need to go.

Netmiko supports the following platforms for Secure Copy

  • arista_eos
  • ciena_saos
  • cisco_asa
  • cisco_ios
  • cisco_nxos
  • cisco_xe
  • cisco_xr
  • dell_os10
  • juniper_junos
  • linux
  • nokia_sros

Copy Files to Cisco IOS-XE Device

In this section, we will walk you through an example of how to copy a test file over to a Cisco network device using the Netmiko file_transfer function.

from netmiko import ConnectHandler, file_transfer
import getpass

passwd = getpass.getpass('Enter your password: ')

test_switch = {
    "device_type": "cisco_ios",
    "host": "10.1.10.10",
    "username": "admin",
    "password": passwd
}

source_file = "test_file.txt"
destination_file = "test_file.txt"
direction = "put"
file_system = 'flash:'

connection = ConnectHandler(**test_switch) # unpacking the dictionary
transfer_dict = file_transfer(
        connection,
        source_file=source_file,
        dest_file=destination_file,
        file_system=file_system,
        direction=direction,
        overwrite_file=True,
    )

connection.disconnect()
print(transfer_dict)

Here is a line-by-line explanation of the code

  1. from netmiko import ConnectHandler, file_transfer - This line imports the necessary functions from the Netmiko library, namely ConnectHandler for establishing a connection to the network device and file_transfer for transferring the file.
  2. import getpass - This line imports the getpass module, which allows secure input of the password without displaying it on the screen.
  3. passwd = getpass.getpass('Enter your password: ') - This line prompts the user to enter their password securely, storing it in the variable passwd.
  4. test_switch dictionary - This block of code defines a dictionary containing the necessary information for connecting to the Cisco device, such as device type, host IP address, username, and password.
  5. source_file = "test_file.txt" - This line defines the source file name to be copied to the Cisco device.
  6. destination_file = "test_file.txt" - This line defines the destination file name on the Cisco device.
  7. direction = "put" - This line sets the direction of the transfer as 'put', which means the file will be copied to the Cisco device.
  8. file_system = 'flash:' - This line specifies the file system on the Cisco device where the file will be stored.
  9. connection = ConnectHandler(**test_switch) - This line creates a connection to the Cisco device using the ConnectHandler class and the information provided in the test_switch dictionary.
  10. transfer_dict = file_transfer(...) - This block of code calls the file_transfer function with the required arguments, such as the established connection, source and destination file names, file system, direction, and an option to overwrite the file if it already exists on the device. The function returns a dictionary containing information about the transfer, which is stored in the variable transfer_dict.
  11. connection.disconnect() - This line closes the connection to the Cisco device.
  12. print(transfer_dict): -This line prints the information about the transfer, such as success status, file size, and transfer time, to the console.

Idempotency

An important feature of the Netmiko SCP function is its idempotent behaviour. This means that if the file already exists on the Cisco device and has a matching MD5 checksum, the function will not copy the file again. This helps to save time and network resources by avoiding unnecessary file transfers.

Let's consider a scenario where the test file does not initially exist on the Cisco device. When you run the script for the first time, it will copy the test file over to the Cisco device. The output will be as follows. This output indicates that the file was successfully transferred and verified.

{'file_exists': True, 'file_transferred': True, 'file_verified': True}

If you run the script again, the output will be slightly different. This output shows that the file already exists on the Cisco device, and the MD5 checksums match. As a result, the file transfer was not executed again, demonstrating the idempotent behaviour.

{'file_exists': True, 'file_transferred': False, 'file_verified': True}

Of course, if I make a slight change to the file and try again, the MD5 checksum will not match and the amended file will be copied over as shown below.

{'file_exists': True, 'file_transferred': True, 'file_verified': True}

Copy Files from Cisco IOS-XE Device

In this example, we will demonstrate how to copy files from a Cisco device to your local machine using the Netmiko file_transfer function. To achieve this, you need to make two changes to the previous script.

  1. Change the direction variable value to "get", indicating that you want to retrieve a file from the Cisco device.
  2. Change the file_system variable value to "system:", as this is where the running-config file is stored on the Cisco device.

Here is the modified script for copying the running-config file from the Cisco device to your local machine.

from netmiko import ConnectHandler, file_transfer
import getpass

passwd = getpass.getpass('Enter your password: ')

test_switch = {
    "device_type": "cisco_ios",
    "host": "10.1.10.10",
    "username": "admin",
    "password": passwd
}

source_file = "running-config"
destination_file = "running-config"
direction = "get"
file_system = 'system:'

connection = ConnectHandler(**test_switch) # unpacking the dictionary
transfer_dict = file_transfer(
        connection,
        source_file=source_file,
        dest_file=destination_file,
        file_system=file_system,
        direction=direction,
        overwrite_file=True,
    )

connection.disconnect()
print(transfer_dict)
#output
{'file_exists': True, 'file_transferred': True, 'file_verified': True}

Closing Up

In summary, the Netmiko file_transfer function provides a simple, secure, and efficient method for transferring files to and from network devices, eliminating the need for FTP or TFTP servers.

As always, I value your feedback and comments, so please feel free to share your thoughts and experiences.

References

https://pynet.twb-tech.com/blog/expanding-netmiko-secure-copy-support.html