1

I have written a small code in python to automate the configuration tasks on multiple Cisco routers using telnet library. In the first iteration everything works fine, the problem is I am getting timed out in the second iteration on the function read_all(). If I remove the time-out parameter from the telnetlib.Telnet() function, I am stuck forever in the same iteration.

from telnet import telnet

import xlrd

class handler:
 excel_sheet=None
 ipv4_devices=None
 ipv6_devices=None
 config=None
 telnet=None

def __init__(self):
 self.excel_sheet = xlrd.open_workbook("ipv4_devices.xlsx")
 self.config=open("config.txt","r")
 output_init = open("output.txt","w+")
 output_init.write("")
 output_init.close()  

def execute(self):
 row = None
 column = None
 self.ipv4_devices = self.excel_sheet.sheet_by_index(0)
 for row in range(self.ipv4_devices.nrows-1):
  self.telnet = telnet(self.ipv4_devices.cell_value(row+1,0),self.ipv4_devices.cell_value(row+1,1), self.ipv4_devices.cell_value(row+1,2), self.ipv4_devices.cell_value(row+1,3), self.config)
 self.telnet.do_telnet()
 self.telnet=None
self.config.close()

Above is my Handler.py file, which in turn calls my telnet.py file containing the actual telnet code.

import sys
import telnetlib

class telnet:
 ipv4_address=None
 port=0
 username=None 
 passphrase=None
 config=None

 def __init__(self, ipv4_address=None, port=23, username=None, passphrase=None, config=None):
  if (ipv4_address is not None) and (username is not None) and (passphrase is not None) and (config is not None) : 
   self.ipv4_address = ipv4_address
   self.port = port
   self.username = username
   self.passphrase = passphrase
   self.config = config
  else:
   exit()  

 def do_telnet(self):
  output = open("output.txt","a")
  remote= telnetlib.Telnet(self.ipv4_address,int(self.port))
  remote.read_until("Username: ")
  remote.write(self.username.encode('ascii')+"\n")
  remote.read_until("Password: ")
  remote.write(self.passphrase.encode('ascii')+"\n")
  remote.write(self.config.read().encode('ascii')+"\n")
  output.write(remote.read_all()+"\n"+"  -------  "+"\n")
  remote.close()
  output.close()

Below is the error I get, when I am timed out

Traceback (most recent call last):
  File "Automate.py", line 5, in <module>
    automate_it.execute()
  File "/home/abdultayyeb/Desktop/Automation/handler.py", line 30, in execute
    self.telnet.do_telnet()
  File "/home/abdultayyeb/Desktop/Automation/telnet.py", line 31, in do_telnet
    output.write(remote.read_all()+"\n"+"  -------  "+"\n")
  File "/usr/lib/python2.7/telnetlib.py", line 385, in read_all
    self.fill_rawq()
  File "/usr/lib/python2.7/telnetlib.py", line 576, in fill_rawq
    buf = self.sock.recv(50)
  socket.timeout: timed out
James Z
  • 12,209
  • 10
  • 24
  • 44
Abdul Tayyeb
  • 157
  • 1
  • 2
  • 13
  • As documented [read_all](https://docs.python.org/3.1/library/telnetlib.html#telnetlib.Telnet.read_all) will *"Read all data until EOF as bytes; __block until connection closed__."*. In other words: it will not read everything which the server just has send but wait for more data until the connection gets explicitly closed by the server - which isn't usually the case if you just login to somewhere via telnet and which does not seem to happen here either. So if you expect a specific output you should wait for exactly for this with `read_until`. – Steffen Ullrich Jan 13 '19 at 07:51
  • If that's the case, then why it is not getting blocked in the first iteration? Why it is getting blocked in the second iteration, for the second Cisco router? – Abdul Tayyeb Jan 13 '19 at 08:22
  • Maybe because of different behaviors of the routers, i.e. one router is closing the connection and the other not. I have no idea how these routers are supposed to behave. You might try to connect by hand with telnet and check yourself if the router closes the connection after sending the data or not. – Steffen Ullrich Jan 13 '19 at 11:09

1 Answers1

0

I suggest re-writing this to use netmiko as it will handle the idiosyncrasies of dealing with Cisco IOS.

The key is to specify your device type as cisco_ios_telnet.

This will have the added benefit of not needing to re-write your code when you convert your systems to SSH. You would simply change the device type from cisco_ios_telnet to cisco_ios

https://pynet.twb-tech.com/blog/automation/netmiko.html

Greg Mueller
  • 506
  • 3
  • 7