Automating Cisco switch deployment with Perl over Serial

Camels and serial ports

I was recently given the task to write up some scripts to automate the deployment of Cisco switches via a serial port (or whatever else you’d like to call it – console port, rs232 etc.). While at first glance, the process seemed pretty straightforward, I soon ran into a couple of issues – I couldn’t find any quick and dirty way to do this. Following a couple hours of digging, I found just the right solution.

My first choice was Device::SerialPort, which offers pretty much everything under the sun for those of you who would like to be serial port overlords. Unfortunately it was just a bit too heavy for my needs. What I was looking for was more Net::Telnet(::Cisco) like, where I could just send data back and forth, retrieve output and move on. Yes, I know, Device::SerialPort has lookfor(), however, the work required/involved still seems to be a bit too much.

Next contender was Net::Appliance::Session – it supports Telnet, SSH and Serial, however, it is also dependent on cu, which is basically a terminal utility for connecting to other devices via Ethernet, serial or whatever else. While I do not mind my script being dependent on another binary, to my dismay, the Serial transport did not work at all in this module, failing to ‘connect’ to the serial port. Although Net::Appliance::Session did not fit my bill, it does have a large list of different OS syntaxes it supports, besides the default IOS – there’s also CatOS, FWSM, Pix OS, Junos and more. So, my search continued for serial port bliss.

After digging through some old forum posts, I found just the right module for the task – Device::Modem, written by Cosimo Streppone. Although the module centers around communicating with a modem, it is equally effective in dealing with Cisco, or whatever other devices via serial. Skipping over most of the functionality (sorry), the useful bits for me were: $obj->atsend() and $obj->answer(). With these two functions alone, I was able to get the project rolling in no time. While it is no Net::Telnet::Cisco and you’ll have to perform your own output parsing, it is still nevertheless, effective, quick and simple.

Here’s a quick example I hacked up:

#!/usr/bin/perl
#
# Note: we're making the assumption here that the switch has been reset and has default settings, hence no auth.
# Thankfully, it'd be still pretty easy to add some checks for prompts.

use strict;
use warnings;

use Device::Modem;

my $serial_port = '/dev/ttyS1';

my $serial = new Device::Modem( port => "$serial_port" );

if(!($serial->connect( baudrate => 9600 ))) {

    print("Could not connect to serial port '$serial_port'\n");

}

# Do a quick check, whether we're up
$serial->atsend("\r\r");
$serial->atsend("show ver | inc IOS\r");
my $output = $serial->answer;

if(!($output)) { die("Not able to receive anything from the device connected on '$serial_port'!\n"); }

# Or if you want to check for prompts, just loop through @s_out and look for /^username:\s+/.

my @s_out = split(/\n/, $output);

my $found = 0;
my $version;

for(@s_out) {

    next if($_ =~ /inc IOS/);

    if($_ =~ /IOS/) {

        $found = 1;
        $version = $_;
        $version =~ /.+Version\s+(.+),\s+RELEASE.+/g;
        my $r_version = $1;
        print("Detected IOS Version: $r_version\n");
        last;

    } else {

        next;
    }
}

if(!($found)) {
    die("Could not find IOS version...\n");
}

Share

2 Comments

  1. Arun

    Hi, How do I telnet to a router and connect to the serial line of each device console from there ? Any examples, please. Any help is appreciated.

    Thanks
    Arun

Leave a Reply

Your email address will not be published. Required fields are marked *

197 views2 comments