Scripts
From NMSWiki
Contents |
[edit]
Assorted NMS Scripts
[edit]
Perl Scripts
Asynchronous SNMP poller (Perl)
Execute commands on a router/switch using Telnet (Perl)
[edit]
Data Extraction Engine - DEE
[edit]
Get XML data from DEE
Use the following script to pull the XML data out of CiscoWorks RME. This script was written by Jobe Bittman.
#!/usr/bin/perl
use LWP::UserAgent;
# XML POST DATA
my $device = $ARGV[0] or "172.17.253.4";
my $rmeserver = "127.0.0.1";
my $login = "admin";
my $password = "foobar";
my $xml ="<payload>
<inputinfo>
<username>$login</username>
<password>$password</password>
<command>inventory</command>
<device>$device</device>
<email></email>
<log></log>
<debug></debug>
<view></view>
<continue></continue>
</inputinfo>
</payload>";
# HTTP request starts here.
my $ua = LWP::UserAgent->new;
my $request = HTTP::Request->new(POST => "http://$rmeserver:1741/CSCOnm/servlet/com.cisco.nm.dee.servlet.CwExportServlet");
$request->content_type('text/html');
$request->content($xml);
my $result = $ua->request($request);
my $rcontent = $result->content;
# Strip out embedded newlines and returns if line doesn't end in tag.
$rcontent =~ s/\r//g;
$rcontent =~ s/([^>])\n/$1/g;
# Take out leading and trailing spaces
$rcontent =~ s/\>\ /\>/g;
$rcontent =~ s/\ \</\</g;
# Excommunicate funky unicode Serial numbers from some 3662's.
$rcontent =~ s/\377 /0/g;
# I've never seen it, but Mike Freeman claims ConfigReg sometimes is missing a leading quote. Just in case, I test for a missing quote after name.
$rcontent =~ s/name=([^\"])/name=\"$1/g;
print $rcontent;
[edit]
Parse DEE output
This is a simple script to parse the XML output derived from DEE/RME
#!/usr/bin/perl
# Michael J. Freeman (mfreeman@multimax.com)
# Copyright 2003 (c) WAM!Net Government Services
# Copyright 2005 (c) Netco Government Services
# Copyright 2006 (c) MULTIMAX
# Released under the GPL v2
# $Id: $
# DEE Tool XML parser
###############################################
# To understand this, read the XML::Simple #
# Manpage and the XML file you are processing #
###############################################
# foreach my $line ( @{ $_->{explanation}} ) {
use strict;
use XML::Simple qw(:strict);
use Data::Dumper;
my $xmlfile = shift @ARGV;
my $ref = XMLin("$xmlfile", ForceArray => [ "Device" ], KeyAttr => [ ]);
my $foo = $ref->{Device};
my $DEBUG = 0;
foreach (@$foo) {
# Print the name/IP
print "$_->{name},";
if ((ref $_->{system}{command}) eq "ARRAY") {
my $cmdarray3 = $_->{system}{command};
foreach my $cmd (@$cmdarray3) {
print "$1," if $cmd =~ /set\ssystem\sname\s (.*)/;
}
} elsif ((ref $_->{Global}{command}) eq "ARRAY") {
my $cmdarray = $_->{Global}{command};
foreach my $cmd (@$cmdarray) {
print "$1," if $cmd =~ /hostname\s(.*?)$/;
}
} elsif ((ref $_->{Supervisor}{system}{command}) eq "ARRAY") {
my $cmdarray = $_->{Supervisor}{system}{command};
foreach my $cmd (@$cmdarray) {
print "$1," if $cmd =~ /set\ssystem\sname\s (.*?)$/;
}
} else { print "," }
# Is this a catalyst?
if ($_->{Supervisor}) {
print "$_->{Supervisor}{version}{command},";
print "$1"
if $_->{Supervisor}{'module_1_-_2-port_1000BaseX_Supervisor'}{command}[0]
=~ /set module name\s \d \s (.*)/;
} elsif ($_->{version}{command}) {
# Is this a catalyst trying to trick us?
print "$_->{version}{command},";
print "$1"
if $_->{'module_1_-_2-port_1000BaseX_Supervisor'}{command}[0]
=~ /set module name\s \d \s (.*)/;
} else {
# Print the IOS version
my $cmdarray = $_->{Global}{command};
if ((ref $_->{Global}{command}) eq "ARRAY") {
foreach my $cmd (@$cmdarray) {
print "$1," if $cmd =~ /version\s(.*?)$/;
}
} else { print "\nGlobal: NOT AN ARRAY\n" if ($DEBUG); }
# Print description from int Vlan1
my $intarray = $_->{Interface}{Interface_Vlan1}{command};
if ((ref $intarray) eq "ARRAY") {
foreach my $int (@$intarray) {
print "$1" if $int =~ /description\s(.*?)$/;
}
} else { print "\nInterface Vlan1: NOT AN ARRAY\n" if ($DEBUG); }
# Print description from int VLAN1
my $intarray = $_->{Interface}{Interface_VLAN1}{command};
if ((ref $intarray) eq "ARRAY") {
foreach my $int (@$intarray) {
print "$1" if $int =~ /description\s(.*?)$/;
}
} else { print "\nInterface VLAN1: NOT AN ARRAY\n" if ($DEBUG); }
}
print "\n";
}
[edit]
LMS to MySQL
I wrote the following Perl script to import devices into a Common Management Database using a dumpfile from LMS
Here's the logic of this script:
- Parse an export file from LMS, read each line and get ip address, hostname, etc. (all LMS fields).
- Ping the device - if it has an IP address (some devices do not have one) and it is pingable, continue. If not, log error and goto next device.
- If ICMP passes, test for UDP port 161 response, if it fails, log error and move to the next device.
- For each SNMP OID defined, get the variables (OIDS defined: Sysname, IOS Rev, Flash, Chassistype). If unable to read OID, log error and goto next device.
- Upon successful poll, query DB for existing record (using hostname). If record exists, run UPDATE on table, if not, run INSERT.
- Send report.csv output (error log) to email recipient(s).
- Profit!
Here's the DB table structure:
DROP TABLE IF EXISTS ciscoworks; CREATE TABLE ciscoworks ( id int(11) NOT NULL auto_increment, mip varchar(15) default NULL, hostname varchar(75) NOT NULL default '', domainname varchar(75) NOT NULL default '', devid varchar(75) default NULL, displayname varchar(75) default NULL, sysobjid varchar(75) default NULL, dcrdevtype varchar(75) default NULL, mdftype varchar(75) default NULL, v2ro varchar(75) default NULL, v2rw varchar(75) default NULL, v3uid varchar(75) default NULL, v3pass varchar(75) default NULL, v3engid varchar(75) default NULL, v3authalg varchar(75) default NULL, username varchar(75) default NULL, password varchar(75) default NULL, enable varchar(75) default NULL, softrev varchar(75) default NULL, flashfn varchar(75) default NULL, chassistype varchar(75) default NULL, sysname varchar(75) default NULL, cwservername varchar(75) default NULL, EntryDate datetime NOT NULL default '2006-06-19 01:37:00', PRIMARY KEY (id), UNIQUE KEY (hostname) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Here's a copy of the script:
#!/usr/bin/perl
########################################################################
# DCR Import
# Clayton Dukes (cdukes@cisco.com)
# Changelog:
# 9/18/06 - Added Support for emailing report results
########################################################################
# Set up includes
use BER; # Gentoo: emerge "dev-perl/SNMP_Session -pv"
use SNMP_util;
use SNMP_Session;
use Net::Ping;
use Data::Dumper;
use DBI;
use POSIX qw(strftime);
# http://www.annocpan.org/~TSCANLAN/NetworkInfo-Discovery-0.12/lib/NetworkInfo/Discovery.pm
use NetworkInfo::Discovery;
use NetworkInfo::Discovery::Register;
use NetworkInfo::Discovery::Scan;
# Let's be nice...
use strict;
# Added mail sending stuff to send reports # emerge: dev-perl/Mail-Sendmail (http://alma.ch/perl/Mail-Sendmail-FAQ.html)
use MIME::QuotedPrint;
use MIME::Base64;
use Mail::Sendmail 0.75; # doesn't work with v. 0.74!
our %mail = (
from => 'dbse-import@servername',
to => 'cdukes@cisco.com',
Smtp => 'smtp.server.tld:25',
subject => 'Report Output for DBSE Import', );
# Set VARS
my $datetime = strftime "%Y-%m-%d %H:%M:%S", gmtime; my $config = "config.ini";
# Open config file for reading DB variables open( CONFIG, $config ) or die "Can't open $config : $!"; my @config = <CONFIG>; close( CONFIG );
# Set DB vars
my($dbtable,$dbuser,$dbpass,$dbname,$dbhost,$dbport,$DEBUG);
foreach my $var (@config) {
next unless $var =~ /^define/; # read only def's
$dbtable = $1 if ($var =~ /'DBTABLE', '(\w )'/);
$dbuser = $1 if ($var =~ /'DBADMIN', '(\w )'/);
$dbpass = $1 if ($var =~ /'DBADMINPW', '(\w )'/);
$dbname = $1 if ($var =~ /'DBNAME', '(\w )'/);
$dbhost = $1 if ($var =~ /'DBHOST', '(\w )'/);
$dbport = $1 if ($var =~ /'DBPORT', '(\w )'/);
$DEBUG = $1 if ($var =~ /'DEBUG', '(\w )'/); } # Error out if no vars are read from file if ( ! $dbtable ) {
print "Error: Unable to read config variables from $config\n";
exit;
}
# Dump if debug is on
if ($DEBUG > 0) {
print "Table: $dbtable\n";
print "Adminuser: $dbuser\n";
print "PW: $dbpass\n";
print "DB: $dbname\n";
print "DB Host: $dbhost\n";
print "DB Port: $dbport\n";
#exit;
}
# Die if input file (LMS export) is not specified if (@ARGV < 1){
usage();
}
sub usage {
print "This file will test devices dumped from LMS\n";
print "Prior to importing them into the DBSE\n";
print "NOTE: Devices that fail testing WILL NOT get inserted into the database...\n";
print "However, it will be logged to result.csv\n";
print "Usage: dcrImport.pl <Ciscoworks Dumpfile>\n";
print "Example:\n";
print "perl dcrImport.pl ALL.csv\n";
exit(-1);
}
# Set OIDs to collect information on
my $Sysname = ".1.3.6.1.2.1.1.5.0";
my $Rev = ".1.3.6.1.2.1.1.1.0";
my $Flash = ".1.3.6.1.2.1.16.19.6.0";
my $chassisType = ".1.3.6.1.4.1.9.3.6.1.0";
# Store the OIDs in an array for later use
my @mibs = ($Sysname,$Rev,$Flash,$chassisType);
my $ctypes =("ChassisTypes");
my $reportlog = "report.csv";
my $cwservername = "cw-lms";
# Set up DB connections for later use
# Connect to DB
my $dbh = DBI->connect('dbi:mysql:'.$dbname,$dbuser,$dbpass)
or die("Couldn't connect to mySQL ", $dbname ," : $DBI::errstr");
# Count # of rows for query -- used to check if record already exists
my $query = "SELECT count(*) FROM $dbtable WHERE hostname=?";
my $sth_query = $dbh->prepare($query);
# Prepare update statement
my $update = "UPDATE $dbtable SET mip=?, domainname=?, devid=?, displayname=?, sysobjid=?,
dcrdevtype=?, mdftype=?, v2ro=?, v2rw=?, v3uid=?, v3pass=?, v3engid=?, v3authalg=?,
username=?, password=?, enable=?, softrev=?, flashfn=?, chassistype=?, sysname=?,
cwservername=?, EntryDate=? WHERE hostname=?";
my $sth_update= $dbh->prepare($update);
# Prepare insert statement
my $insert = "INSERT INTO $dbtable (id, mip, hostname, domainname, devid, displayname, sysobjid,
dcrdevtype, mdftype, v2ro, v2rw, v3uid, v3pass, v3engid, v3authalg, username, password, enable,
softrev, flashfn, chassistype, sysname, cwservername, EntryDate) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
my $sth = $dbh->prepare($insert);
# Open error output log
open CSV, ">$reportlog";
print CSV "IP Address,DNS_Hostname,Error\n"; close CSV; print "\n\n\t\tFailed device information will be logged to $reportlog\n\n\n";
# Open LMS export file for reading
open (FILE, $ARGV[0]);
my $total = `wc -l < $ARGV[0]`;
die "wc failed: $?" if $?;
chomp($total);
$total = ($total - 2);
my $count = 1;
while (<FILE>) {
s/;.*//; # Skip commented lines
next if /^(\s)*$/; # Skip empty lines
next if /^Cisco/; # Skip lines that begin with "Cisco"
next if /^#/; # Skip commented lines
chomp;
# read csv values into variables
my($management_ip_address,$hostname,$domain_name,$device_identity,$display_name,$sysObjectID,
$dcr_device_type,$mdf_type,$snmp_v2_ro_comm_string,$snmp_v2_rw_comm_string,$snmp_v3_user_id,
$snmp_v3_password,$snmp_v3_engine_id,$snmp_v3_auth_algorithm,$primary_username,$primary_password,
$primary_enable_password,$http_username,$http_password,$http_mode,$http_port,$https_port,$cert_common_name)= split/,/;
my($softrev,$flashfn,$chassistype,$sysname);
# Debug info
print "Device $count of $total\n" if ($DEBUG);
if ($count > 0) { # use for quick debugging of large imports.
print "\t\t################################################\n" if ($DEBUG);
print "\t\t# IP: $management_ip_address\n\t\t# Hostname: $hostname\n\t\t# Domain: $domain_name\n" if ($DEBUG);
# Test for ICMP before doing anything, skip device if it fails and log to error log
my $p = Net::Ping->new();
if (($management_ip_address =~ "[0-9]*\.[0-9]*\.[0-9]*\.[0-9]" )
# END

