Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories

How do I dynamically wait for router prompt while using paramiko module in python?

NeilNeil bangalorePosts: 1

Hi,

I am writing a program to collect show command output from Cisco routers. I am using paramiko module with python. When the command output is small there is no problem. When output is large I see that recv() is getting incomplete data. Please see code below.

Initially my understanding was that I can send a command to router and can immediately start reading from the socket. I do not have to wait for the command to complete to start reading from the socket. However, looks like this may no be correct. In get_command_output(), I am waiting for 3 sec after sending "show ip route vrf all" to the router. I always get incomplete output when configuration is large. However, if I wait for 30 sec instead of 3 sec then I get the complete output.

I don't want to blindly wait for 30 sec for every show command. Is there way to do this dynamically? Is there a way where I can execute the command and start reading the socket and let command to generate output in the background and when there is no more data in socket buffer I know that command is complete? Or should I wait for the router prompt to come back to understand that the command is complete(can this be done in python? because this is something which can be done in expect)? Could someone please help?

Thank you.

#!/usr/bin/env python

import paramiko
import time
import os


def get_command_output(cmd, remote_conn, inFile, vsh, vsh_lc):
    '''Execute command & captures output in inFile'''

    remote_conn.send(cmd)

    # Wait for the command to start generating output
    time.sleep(3)

    not_done = True
    MAX_RETRY = 5

    while (not_done or MAX_RETRY > 0):
        if remote_conn.recv_ready():
            output = remote_conn.recv(65535)
            inFile.write(output)
            output = 0
            if MAX_RETRY < 5:
                print ("RESET RETRY")
                MAX_RETRY = 5
        else:
            not_done = False
            MAX_RETRY = MAX_RETRY - 1


if __name__ == '__main__':


    # VARIABLES THAT NEED CHANGED
    ip = '172.68.100'
    username = 'admin'
    password = 'pass'

    # Create instance of SSHClient object
    remote_conn_pre = paramiko.SSHClient()

    # Automatically add untrusted hosts (make sure okay for security policy in your environment)
    remote_conn_pre.set_missing_host_key_policy(
         paramiko.AutoAddPolicy())

    # initiate SSH connection
    remote_conn_pre.connect(ip, username=username, password=password, 
                            look_for_keys=False, allow_agent=False)
    print "SSH connection established to %s" % ip

    # Use invoke_shell to establish an 'interactive session'
    remote_conn = remote_conn_pre.invoke_shell()
    print "Interactive SSH session established"

    disable_paging(remote_conn)

    # Login to IFC, get show switch o/p
    remote_conn.send("\n")
    remote_conn.send("show switch > show_switch_op\n")
    time.sleep(2)
    os.system("sshpass -p 'pass' scp -o StrictHostKeyChecking=no 
               admin@172.68.1.100:/home/admin/show_switch_op ./")
    os.system("cat show_switch_op | tr -s ' ' > show_switch_op.tmp")

    # File manipulation to get addresses
    ingredients = file("show_switch_op.tmp", 'r')
    cols, indexToName =  getColumns(ingredients)
    ingredients.close()
    num_of_nodes = len(cols[3])
    for switch_cnt in range(2, num_of_nodes-1):
        inband_addr = cols[3][switch_cnt]
        print (inband_addr)

        cmd1 = "sshpass -p 'pass' ssh " + str(inband_addr)
        #print (cmd1)
        remote_conn.send(cmd1 + "\n")
        time.sleep(10)

        switch_name = str(cols[11][switch_cnt])
        filename = "tech_support_" + str(cols[11][switch_cnt])
        filepath = "/var/log/"
        file = filepath + filename
        print (file)
        f = open(str(filename), 'a+')

        # Clear the buffer
        output = remote_conn.recv(1000)
        output = 0

        remote_conn.send("\n")
        print ("DEBUG LOG END READ WRITE START " + switch_name + " 
               !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
        get_command_output("show ip route vrf all\n", remote_conn, f, 
                           False, False)
        f.close()
        print ("DEBUG LOG END READ WRITE COMPLETE " + switch_name + " 
                !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")

        remote_conn.send("\n")
        time.sleep(1)

        # Exit from switch & back to IFC
        remote_conn.send("exit\n")
        time.sleep(1)

        # Close the connection and open a new one
        # XXX If same ssh connection is used for multiple send/rcv then it 
        # crashes.
        # Hence opening new connection for every switch.
        remote_conn.close();

        # Create instance of SSHClient object
        remote_conn_pre = paramiko.SSHClient()

        # Automatically add untrusted hosts (make sure okay for security policy 
        #   in your environment)
        remote_conn_pre.set_missing_host_key_policy(paramiko.AutoAddPolicy())

        # initiate SSH connection
        remote_conn_pre.connect(ip, username=username, password=password,    
                                 look_for_keys=False, allow_agent=False)
        print "SSH connection established to %s" % ip

        # Use invoke_shell to establish an 'interactive session'
        remote_conn = remote_conn_pre.invoke_shell()
        print "Interactive SSH session established"

        disable_paging(remote_conn)

    remote_conn.close()
Tagged:
Sign In or Register to comment.