PM port/modem testing (fwd)(LONG)

Port Master users list (pm@carver.pinc.com)
Fri, 6 Sep 96 15:36:23 PDT

Forwarded message:
> From: ned@olympus.net (Ned Schumann)
>
> Is anyone using expect and perl to dial up modems and verify
> that they connect to/roll over to an appropriate port on the PM?
>
> How about statistical analysis of Radius data to identify problem
> ports/modems?
>
> Ned
>

Sure, I do it every night from a Linux box. Here's the code to check
the modems using perl, expect, and cu

It runs from cron like this::
0 3 * * * cd /usr/local/modemlog;./checkmodems;./stats.pl -h <modemlog >modem.html

The checkmodems script:
-----------------cut-------------------------

#!/usr/local/bin/expect
#
# Copyright 1995, Bare Metal Designs.
# Written by Tom Brown, tbrown@baremetal.com, December 1995
#
# PLEASE, LET'S HAVE the COURTESY of NOT having everyone POLLING the
# same providers! I expect some of them to be sufficiently annoyed
# with me as it is!
#
# This program is published under the Gnu Public License...
#
#############################################################
#
# print the number and the response (NO DIALTONE, BUSY, CARRIER, VOICE, NO ANS..
#
# The program runs under Linux, using the Expect language.
# It uses cu to talk to open the serial port and then deals with the
# modem itself. Any references to Minicom are out of date... (another
# case of survival of the fittest. Minicom is a nice program, but this
# wasn't the place for it.
#

proc result {message} {
send_user $message
system logger -plocal7.notice -tdialer $message
}

proc dial {name number} {
send_user "Dialing $name ($number)...\n"
# try to flush buffer
expect "*" { send_user "flushed <$expect_out(buffer)>\n" }
sleep .2
set timeout 1
send "\r"
sleep 2
send "at+fclass=0\r"
sleep 1
expect "OK" {send_user "got OK\n"} \
timeout {result "at&f... command did not get an OK\n"};
set timeout .1
expect "OK" {send_user "got another OK?\n"}
expect "OK" {send_user "got another OK?\n"}
expect "OK" {send_user "got another OK?\n"}
sleep 1
set timeout 75
send "ATDT9,$number\r"
expect "BUSY" {result "$name CALLED $number: BUSY\n"} \
"NO DIAL" {result "$name CALLED $number: NO DIALTONE\n"} \
"NO CARRIER" {result "$name CALLED $number: NO CARRIER\n"} \
"NO DIALTONE" {result "$name CALLED $number: NO DIALTONE\n"} \
-re "CONNECT (\[0-9]*)" {
send_user "got $expect_out(0,string), looking for ogin:\n"
set timeout 9
expect "ogin:" { result "$name CALLED $number: LOGIN$expect_out(1,string)\n"} \
timeout { result "$name CALLED $number: CONNECT\n"}
sleep 1
send "+++"
set timeout 3
expect "OK" {send_user "got modem's attention\n" } \
timeout {send_user "Timeout: missed OK on +++\n"}
# we either slept 3 or got the OK sleep 1
send "ath\r"
expect "OK" {send_user "modem OKd hangup command\n" } \
timeout {send_user "Timeout: missed OK on ath\n"}
} \
"VOICE" {result "$name CALLED $number: VOICE\n"} \
"OK" {result "$name CALLED $number: drat, got OK\n"} \
timeout {result "$name CALLED $number: timed out"}

}

###############################################################
log_user 0
spawn cu -l cua0 -s 38400
sleep 2
# give minicom time to startup
set timeout 15
expect "Connected" {send_user "cu started correctly\n"} \
timeout send_user "cu didn't run correctly? \n"

dial "Pinc79" "744-3851"
dial "Pinc78" "744-3047"
dial "Pinc77" "744-3178"
dial "Pinc76" "744-1492"
dial "Pinc75" "744-5917"
dial "Pinc74" "744-3056"
dial "Pinc73" "744-1498"
dial "Pinc72" "744-1634"
dial "Pinc72" "744-1068"
dial "Pinc70" "744-5920"
dial "Pinc69" "744-5075"
dial "Pinc68" "744-1965"
dial "Pinc67" "744-3815"
dial "Pinc66" "744-5918"
dial "Pinc65" "744-5687"
dial "Pinc64" "744-2136"
dial "Pinc63" "744-1583"
dial "Pinc62" "744-1894"
dial "Pinc61" "744-5981"
dial "Pinc60" "744-5867"
dial "Pinc59" "744-3148"
dial "Pinc58" "744-3158"
dial "Pinc57" "744-2892"
dial "Pinc56" "744-2619"
dial "Pinc55" "744-5608"
dial "Pinc54" "744-3273"
dial "Pinc53" "744-2687"
dial "Pinc52" "744-3506"
dial "Pinc51" "744-1786"
dial "Pinc50" "744-3137"
dial "Pinc49" "744-3754"
dial "Pinc48" "744-3752"
dial "Pinc47" "744-3491"
dial "Pinc46" "744-3468"
dial "Pinc45" "744-3462"
dial "Pinc44" "744-3431"
dial "Pinc43" "744-3430"
dial "Pinc42" "744-3421"
dial "Pinc41" "744-3415"
dial "Pinc40" "744-3413"

send_user "Shutting down\n"
set timeout 1
send "atL0M0\r"
expect "OK" {send_user "modem OKd volume OFF command\n" } \
timeout {send_user "Timeout: missed OK on volume off command\n"}

#exit this is ^Ax - minicoms exit sequence
sleep 1
set timeout 10
send "~.\n"
expect "Disconnected" {send_user "cu ended correctly\n"} \
timeout send_user "cu didn't end correctly? \n"
close
wait

--------------------cut-----------------

And a nice little program to put the resulting log into an HTML page:
stats.pl

--------------------cut-----------------

#!/usr/bin/perl
#
# Basic Perl script to process the dialing statistics log file.
# Copyright 1995/1996 BareMetal Designs - Tom Brown.
# Released under the GNU Public License...
#
# 2nd generation report generator... accepts LOGIN, other, BUSY
# parameters

#$debug=1;
$= = 999;

require "getopts.pl";
&Getopts('tch'); # -h flag means produce HTML output
# -c means include CONNECTS as good calls
# -t means include "timed out" as lost calls

# -c means include CONNECTS as good calls

while ( $line = <> ) {
chop( $line );
##Mar 1 02:00:33 fax dialer: Line79 CALLED 9,744-3851: LOGIN

$line =~ tr/ / /s; # squeeze!

## the above line shrinks the double space to single space

($mon, $day, $time, $host, $daemon, $provider, $called, $number,
$stat) = split(/ /,$line, 9);
# ($number) = ($number =~ /..(........)/);
chop($number);
$number = ":" . $number;

$providers{$provider} = $provider . $number; # need an array with ALL providers

if ( $stat =~ /LOGIN/ ) {
$login{$provider} += 1;
$last{$provider} = $stat;
$lastgood{$provider}= join(' ',$mon,$day);
} elsif ( $stat eq "BUSY" ) {
$last{$provider} = $last{$provider} . " " . $stat;
$lastgood{$provider}= join(' ',$mon,$day);
$busy{$provider} += 1;
} elsif ( $stat eq "CONNECT" ) {
$lastbad{$provider} = join(' ',$mon,$day);
$miss{$provider} = $stat;
$connect{$provider} += 1;
} elsif( $stat eq "NO CARRIER") {
$lastbad{$provider} = join(' ',$mon,$day);
$miss{$provider} = $stat;
$ugly{$provider} += 1;
} elsif( $stat eq "NO DIALTONE") {
$lastbad{$provider} = join(' ',$mon,$day);
$miss{$provider} = $stat;
$ugly{$provider} += 1;
}
# elseif ( $opt_d ) {
else {
# print "Throwing out response $stat, for provider $provider\n";
}

}

if ($opt_h) {
open (HTML, ">&STDOUT") || die("couldn't get HTML copy of stdout");
select (HTML) || die("couldn't select HTML");
$= = 999;

format HTML_TOP =
<TABLE border>
<TR><TH>Phone line</TH><TH>%Good</TH><TH>Last Connect</TH><TH>Date</TH><TH>Last Miss</TH><TH>Date</TH></TR>
.

format HTML =
<TR><TD>@<<<<<<<<<<<<<<<< </TD><TD> @###.## </TD><TD> @>>>>>>>>>>>>>> </TD><TD> @>>>>>>>>>>>>>>>> </TD><TD> @>>>>>>>>>>>>>>> </TD><TD> @>>>>>>>>>>>>>>>> </TD></TR>
$phoneno, $pgood, $last{$prvdr}, $lastgood{$prvdr},$miss{$prvdr},$lastbad{$prvdr}
.
}
else {
format STDOUT_TOP =
Provider %Good Last Connect Last Good Last Miss Last Bad
----------------- ----- ------------ ------------- --------- --------------
.

format STDOUT =
@<<<<<<<<<<<<<<<< @###.# @>>>>>>>>>>>> @>>>>>>>>>>>>> @>>>>>>>>>>>>> @>>>>>>>>>>>>>>>
$phoneno, $pgood, $last{$prvdr},$lastgood{$prvdr},$miss{$prvdr},$lastbad{$prvdr}
.
}

foreach $prvdr (sort(keys(%providers))) {
# printf "%15s busy = %3d, called %3d times, percent busy = %4.1f\n",$prvdr,
# $busy{$prvdr},
# $connect{$prvdr}+$busy{$prvdr},
# 100*$busy{$prvdr}/($connect{$prvdr}+$busy{$prvdr});

$total = $busy{$prvdr}+ $login{$prvdr}+ $connect{$prvdr}+ $ugly{$prvdr};

if ($total) {
if ($opt_c) { # include "CONNECT as a good call"
$pgood = 100 * ($login{$prvdr}+$connect{$prvdr}) / $total;
} else {
$pgood = 100 * $login{$prvdr} / $total;
}
$phoneno = $providers{$prvdr};
write
}
}

if ($opt_h) { # for HTML we have to end the table...
print "\n</TABLE>\n";
}

################### END MAIN ROUTINE ##################

--------------------cut-----------------