Skip to content

Commit 0e37efd

Browse files
author
Jérome Tissières
committed
Added multi-vendor support
1 parent c48231b commit 0e37efd

File tree

3 files changed

+63
-39
lines changed

3 files changed

+63
-39
lines changed

README.md

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
# NX-OS-SCP-Bulk-Transfer
22

3-
A Simple Python script to upload and verify (checksum) files to multiple Cisco NX-OS devices in parallel, with the support of Netmiko.
3+
A Simple Python script to upload and verify (checksum) files to multiple network devices in parallel, supported by Netmiko
44

55

66
## Use Case Description
77

88
If you have a large number of NX-OS devices and need to upload a file, for example a new version of NX-OS, to all these devices without the help of an external tool like Cisco DCNM or similar, it can be very time-consuming. This script takes care of everything.
99

10+
This script uses the strength and functionality of Netmiko to copy, in parallel, a single file to multiple network devices.
11+
12+
Supported devices are:
13+
14+
Cisco Cisco IOS/IOS-XE/IOS-XR/NX-OS, Arista EOS, Juniper JunOS
15+
16+
1017
## Installation
1118

1219
Requirements: All you need is Python and pip.
@@ -19,12 +26,21 @@ Installation:
1926

2027
## Configuration
2128

22-
Update the file hosts.txt with the list of your NX-OS hosts, one host per line.
29+
Update the file hosts.csv with the list of your network hosts, one host per line, including the vendor type..
30+
31+
Vendor types are:
32+
33+
cisco_ios
34+
arista_eos
35+
juniper_junos
36+
cisco_nxos
2337

2438
Example:
2539

26-
host01.example.com
27-
host02.example.com
40+
host01.example.com,cisco_ios
41+
host02.example.com,cisco_nxos
42+
43+
The file system is the default defined into Netmiko. Please refer to the Netmiko documentation here[https://pynet.twb-tech.com/blog/automation/netmiko-scp.html]
2844

2945
## Usage
3046

hosts.txt

Lines changed: 0 additions & 7 deletions
This file was deleted.

nxos-scp-upload.py

Lines changed: 43 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
#!/usr/bin/python
22
from getpass import getpass
33
from argparse import ArgumentParser
4+
import csv
45
import os.path
6+
import sys
57
from time import time
68
from concurrent.futures import ProcessPoolExecutor, wait
79
from netmiko import ConnectHandler, file_transfer
810
from netmiko.ssh_exception import NetMikoAuthenticationException, NetMikoTimeoutException
911
from paramiko.ssh_exception import AuthenticationException
1012

11-
# --- Define the variables
12-
SW_LIST = []
13+
# --- Define the threads
1314
MAX_THREADS = 4
14-
future_list = []
15-
1615

1716
# --- Check file exists function
1817
def is_valid_file(parser, arg):
@@ -55,21 +54,21 @@ def upload_nemiko(net_device):
5554
transfer_dict = file_transfer(ssh_conn,
5655
source_file=SOURCE_FILE,
5756
dest_file=SOURCE_FILE,
58-
file_system='bootflash:',
59-
direction='put',
60-
overwrite_file=True)
61-
print('Results for:', HOST)
57+
)
58+
print(80*"=")
59+
print('Results for', HOST+':')
6260
print('File exists already: ',transfer_dict['file_exists'])
6361
print('File transferred: ',transfer_dict['file_transferred'])
6462
print('MD5 verified :',transfer_dict['file_verified'])
65-
print(80*"=")
6663
except NetMikoTimeoutException:
67-
print('Skipped: SSH Timed out')
6864
print(80*"=")
65+
print('Results for', HOST+':')
66+
print('Skipped: SSH Timed out')
6967
#continue
7068
except (AuthenticationException, NetMikoAuthenticationException):
71-
print('Skipped: Authentication failed')
7269
print(80*"=")
70+
print('Results for', HOST+':')
71+
print('Skipped: Authentication failed')
7372
#continue
7473

7574
# --- Init argparse
@@ -80,20 +79,29 @@ def upload_nemiko(net_device):
8079
# --- Define the OS file to upload
8180
SOURCE_FILE = (args.filename)
8281

83-
# --- Define the switch list
84-
with open("./hosts.txt", 'r') as FILE:
85-
SW_LIST = [line.rstrip() for line in FILE]
82+
# --- Check the hosts.csv file and get the list of hosts
83+
VENDORS_TYPES = ["cisco_ios", "arista_eos", "juniper_junos", "cisco_nxos"]
84+
VENDOR_TYPE = ''
85+
HOSTS_LIST = []
86+
87+
with open("./hosts.csv", 'r') as csvfile:
88+
csv_reader = csv.reader(csvfile, delimiter=',')
89+
for row in csv_reader:
90+
if VENDOR_TYPE in VENDORS_TYPES not in str(row[1]):
91+
print('Invalid CSV, please check the vendor types. Must be: cisco_ios, arista_eos, juniper_junos or cisco_nxos')
92+
sys.exit()
93+
HOSTS_LIST.append(row[0])
8694

8795
# --- Ask confirmation
8896
print(80*"=")
89-
print('Please, confirm the upload of:',SOURCE_FILE+' on: ')
90-
print(*SW_LIST, sep ='\n')
97+
print('Please, confirm the upload of',SOURCE_FILE+' on: ')
98+
print(*HOSTS_LIST, sep ='\n')
9199
prompt = str("Proceed?")
92100

93101
if confirm(prompt=prompt, resp=False) == True:
94102
# --- Get credentials
95103
print(80*"-")
96-
USERNAME = input('Please insert your NX-OS username: ')
104+
USERNAME = input('Please insert your username: ')
97105
print("And your password")
98106
PASSWORD = getpass()
99107
print(80*"-")
@@ -105,19 +113,26 @@ def upload_nemiko(net_device):
105113
pool = ProcessPoolExecutor(MAX_THREADS)
106114

107115
# --- SCP itself, in multi-threads
108-
for HOST in SW_LIST:
109-
net_device = {
110-
'device_type': 'cisco_nxos',
111-
'host': HOST,
112-
'username': USERNAME,
113-
'password': PASSWORD,
114-
}
115-
future = pool.submit(upload_nemiko, net_device)
116-
future_list.append(future)
117-
118-
wait(future_list)
116+
SW_LIST = []
117+
FUTURE_LIST = []
118+
with open("./hosts.csv", 'r') as csvfile:
119+
SW_LIST = csv.reader(csvfile, delimiter=',')
120+
for CSV_ROW in SW_LIST:
121+
HOST = CSV_ROW[0]
122+
DEVICE_TYPE = CSV_ROW[1]
123+
net_device = {
124+
'device_type': DEVICE_TYPE,
125+
'host': HOST,
126+
'username': USERNAME,
127+
'password': PASSWORD,
128+
}
129+
FUTURE = pool.submit(upload_nemiko, net_device)
130+
FUTURE_LIST.append(FUTURE)
131+
132+
wait(FUTURE_LIST)
119133

120134
# --- All done confirmation
135+
print(80*"=")
121136
print("Uploads completed in {} seconds.".format(time() - start_time))
122137
print(80*"=")
123138
else:

0 commit comments

Comments
 (0)