Script to connect to multiple network devices and run commands against it's running configuration

1.6k views Asked by At

I'm attempting to write a script that pulls ip addresses from a file, connect to a network device at that ip address, run a "show run" against the device, export that config to a temp file, then parse the file for certain commands.

I'm trying to write a function so that I can pass the device ip address to the function, run the function, and exit. Then it moves on to the next device.

from netmiko import ConnectHandler
import getpass
import os.path
from ciscoconfparse import CiscoConfParse
import numpy as np

####Ask for username...will be displayed when typed
uname=input("Enter your username :")

###Ask for password...will not be displayed when typed
p = getpass.getpass(prompt="Enter your password: ")

###Ask for path to device list
filepath=("D:\Scripts\IOSDevices.csv")
hosts = open(filepath).read().splitlines()
#print (hosts) #verify host file is actually reading correctly
hostname = np.array(hosts)
print (hostname) #verify hosts are present in the array 

def run_parseconfig():
    pass
    cf = open(".\tmp_file_conf.txt", "w+")
    #Connect to IOS devices
    device = ConnectHandler(device_type='cisco_ios', ip=hostname, username=uname, password=p)

    output = device.send_command("show run")
    device.disconnect()
    print (output)
    cf.write (output + "\n")
        
    parse = CiscoConfParse(".\tmp_file_conf.txt")
    cf.close()
    output = " "
    hostname_objs = parse.find_objects("^hostname")
    service_objs = parse.find_objects("^service")
    #f = open(hostname+"_config.txt", "a+")
    f = open("D:\Scripts\IOS-DEVICES.txt", "a+")
    f.write ("**** " + hostname + " ****" +"\n\n")
    
    for h_obj in hostname_objs:
        print (h_obj.text)
        f.write (h_obj.text +"\n")
        h_obj = " "
    for s_obj in service_objs:
        print (s_obj.text)
        f.write (s_obj.text +"\n")
        s_obj = " "
    f.write ("\n" + "**** End of " + hostname +"'s Commands" + "\n")
    f.write ("\n")
    f.close()
    parse = " "
    
#for hostname in hosts 
run_parseconfig()

Before I built the function, it would successfully run against the first device, then on the second, it would send the running config to a temp file but not parse it out. That's where the function came in.

2

There are 2 answers

0
Tes3awy On

You closed the cf file after parsing with CiscoConfParse and you kept resetting the variables to empty strings which is unecessary. Try to always use context managers instead of open() .close().

I did some modifications to your original code, and the code is commented:

from getpass import getpass
from typing import Dict, Any

from ciscoconfparse import CiscoConfParse
from netmiko import ConnectHandler

username = input("Please enter your username: ").strip()
password = getpass("Please enter your password: ")

# Define a device dictionary
device = {
    "device_type": "cisco_ios",
    "ip": "192.168.1.1",
    "username": username,
    "password": password,
    "fast_cli": False,
}

# Now run_parse_config takes one argument and it's the device dictionary
def run_parse_config(net_device: Dict[str, Any]):
    # Connect to the device
    with ConnectHandler(**device) as conn:
        # Get the running config
        run_cfg: str = conn.send_command(command_string="show running-config")

    # At this indentation level (4 spaces), you are automatically disconnected.
    # No need to call conn.disconnect()

    # Save the config to a tmp file
    # (I don't think this is necessary)
    # You can convert the run_cfg to a list and skip the tmp_file step

    # for a one liner solution, you can use the map() function:
    # run_cfg = list(map(str.strip, run_cfg.split("\n")))
    with open(file="tmp_file_conf.txt", mode="w+") as tmp_file:
        tmp_file.write(f"{run_cfg.strip()}\n")

    # Parse the running config with CiscoConfParse
    # If you converted the run_cfg to a list, pass it in the keyword arg config. 
    # Ex: `parsed_conf = CiscoConfParse(config=run_cfg)`
    parse = CiscoConfParse(config="tmp_file_conf.txt")

    # Find hostname and services objetcts
    hostname_objs = parse.find_objects("^hostname")
    service_objs = parse.find_objects("^service")

    # Append the filtered objects to a file
    with open(file="IOS-DEVICES.txt", mode="a+") as f:
        f.write(f"*** Start of {device['ip']}'s Commands ***\n\n")
        # write hostname object
        for obj in hostname_objs:
            print(obj.text)
            f.write(f"{obj.text}\n")
        # write services object
        for obj in service_objs:
            print(obj.text)
            f.write(f"{obj.text}\n")
        f.write(f"\n*** End of {device['ip']}'s Commands ***\n\n")


# Run the function
run_parse_config(net_device=device)
0
Thyrus On

I think this is simple way to do it.

This script will open file called 'devices'. (IP addresses writen in separate lines)

It will itearate over each IP address and connect to device with username and password given in RTR.

Note that you can make user_input= input("Enter your username")and pass that instead of passing it hardcoded. Same can be done with password.

Config is holding config file (commands) again writen in separate lines. output = net_connect.send_config_from_file(CONFIG) this will open file and send commands from file to device.

I hope this is helpful.

from netmiko import ConnectHandler
from getpass import getpass
from netmiko.ssh_exception import NetMikoTimeoutException
from netmiko.ssh_exception import NetMikoAuthenticationException
from paramiko.ssh_exception import SSHException

IP_LIST=open('devices')
CONFIG='config'
for IP in IP_LIST:
    RTR = {
        'ip':IP,
        'username': 'test',
        'password': 'test',
        'device_type': 'cisco_ios',
    }
    print ('\n #### Connecting to the Device ' + IP.strip() + ' ####\n')
    try:
        net_connect = ConnectHandler(**RTR)
    except NetMikoTimeoutException:
        print('Device not reachable')
        continue
    except NetMikoAuthenticationException:
        print ('Authentication Failure')
        continue
    except SSHException:
        print('Make sure SSH is enabled')
        continue
    output = net_connect.send_config_from_file(CONFIG)
    print(output)