#!/usr/bin/perl -w # This program is used to monitor and manage Layer4 connections # # Written by Candela Technologies Inc. use strict; use warnings; use Carp; # Un-buffer output $| = 1; use lib '/home/lanforge/scripts'; use LANforge::Endpoint; use LANforge::Port; use LANforge::Utils; use Net::Telnet (); use Getopt::Long; use constant NA => "NA"; use constant NL => "\n"; our $shelf_num = 1; our $utils; # Default values for ye ole cmd-line args. our $resource = 1; our $quiet = "yes"; our $cx_name = ""; our $do_cmd = NA; our $action = "show_port"; our $lfmgr_host = "localhost"; our $lfmgr_port = 4001; our $cx_vals = undef; our $stop_at = ""; our $fail_msg = ""; our $interval = 10; our $reqs_sufx = qq; our $bytes_sufx = qq; our $secs_sufx = qq; our $known_suffixes = qq<$reqs_sufx|$bytes_sufx|$secs_sufx>; our $rx_bytes = 0; our $url_count = 0; our $runtime = 0; our $is_running = 0; ######################################################################## # Nothing to configure below here, most likely. ######################################################################## # nice but not requested # show_endp output can be narrowed with key-value arguments #[--cx_vals {key,key,key,key}] # Examples: # --action show_cx --cx_vals MinTxRate,DestMAC,Avg-Jitter my $usage = "$0 --action { show_cx | watch_cx | list_cx } ] [--mgr {host-name | IP}] [--mgr_port {ip port}] [--cx_name {name}] [--resource {number}] [--interval {number of seconds}] [--stop_at {[seconds]sec | [requests]req | [transferred]bytes} req can also be: requests reqs url urls [--quiet { yes | no }] Example: $0 --mgr jedtest --action watch_cx --cx_name gl4g00 --interval 2 --stop_at 3urls "; my $i = 0; GetOptions ( 'action|a=s' => \$action, 'cx_name|e=s' => \$cx_name, 'cx_vals|o=s' => \$cx_vals, 'mgr|m=s' => \$lfmgr_host, 'mgr_port|p=i' => \$lfmgr_port, 'resource|r=i' => \$resource, 'quiet|q=s' => \$quiet, 'stop_at|s=s' => \$stop_at, 'interval|i=i' => \$interval, ) || do_err_exit("$usage"); if ($do_cmd ne "NA") { $action = "do_cmd"; } if (!(($action eq "show_cx") || ($action eq "watch_cx") || ($action eq "list_cx") || ($action eq "list_ports"))) { do_err_exit("Invalid action: $action\n$usage\n"); } do_err_exit("mgr should not be empty; $usage") if ("$lfmgr_host" eq "" ); do_err_exit("mgr_port should not be empty; $usage") if ("$lfmgr_port" eq "" ); do_err_exit("resource should not be empty; $usage") if ("$resource" eq "" ); if ($action eq "show_cx") { do_err_exit("cx_name should not be empty; $usage") if ("$cx_name" eq "" ); } elsif( $action eq "watch_cx") { do_err_exit("stop_at should be greater than zero; $usage") if ("$stop_at" eq ""); do_err_exit("interval should be greater than zero; $usage") if ($interval < 1 ); do_err_exit("cx_name should not be empty; $usage") if ("$cx_name" eq "" ); if ($stop_at !~ /^\d+($known_suffixes)$/) { do_err_exit("stop_at should not have spaces and should end with $known_suffixes; $usage"); } } ## ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- sub do_err_exit { my $errmsg = shift; print $errmsg.NL; exit(1); } ## ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- # Open connection to the LANforge server. # Wait up to 20 seconds when requesting info from LANforge. sub init { my $t = new Net::Telnet(Prompt => '/default\@btbits\>\>/', Timeout => 20); $t->open(Host => $lfmgr_host, Port => $lfmgr_port, Timeout => 10); $t->waitfor("/btbits\>\>/"); $::utils = new LANforge::Utils(); $::utils->connect($lfmgr_host, $lfmgr_port); } ## ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ## ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- sub stop_cx { my $_name = $::cx_name; $_name = "CX_".$::cx_name if ( $::cx_name !~ /^CX_/); my $result = $utils->doAsyncCmd("set_cx_state default_tm $_name STOPPED"); print $result.NL; } ## ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ## ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- sub summarize_cx { my $name = $::cx_name; do_err_exit("please call summarize_cx() with endpoint name") if (!defined $name || "$name" eq ""); $name = "CX_".$::cx_name if ( $::cx_name !~ /^CX_/); my @lines = split(NL, $::utils->doAsyncCmd("show_cxe default_tm $name")); for my $line (@lines) { chomp $line; if ( $line =~ /^L4Endp /) { ($line =~ /^L4Endp .*? \((\w+)\)/); $::is_running = ("$1" eq "RUNNING") ? 1 : 0; } if ( $line =~ / RunningFor: /) { ($::runtime) = ($line =~ / RunningFor: (\d+s) /); } if ( $line =~ / URLs Processed: / ) { ($::url_count) = ($line =~ / Total: (\d+) /); } if ( $line =~ / Bytes Read: / ) { ($::rx_bytes) = ($line =~ / Total: (\d+) /); } } } ## ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ## ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ## ## M A I N ## ## ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- # begin our connection. init(); ## ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- if( $action eq "list_cx") { my @lines = split(NL, $utils->doAsyncCmd("show_endpoints")); my $msg = ""; my $l4_flag = 0; my $print_flag = 0; for my $line (@lines) { chomp $line; $l4_flag = 1 if ( $line =~ /^L4Endp /); next if (! $l4_flag); if ( $line =~ /^L4Endp /) { ($msg) = ($line =~ /^L4Endp (.*)$/); } if ( $line =~ /^\s+URL: /) { (my $u) = ($line =~ /^\s+URL: \S+ (\S+) /); $msg .= " $u"; $print_flag = 1; } if ( $print_flag ) { print $msg . NL; $l4_flag = 0; $print_flag = 0; $msg = ''; } } exit 0; } ## ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- if ($action eq "show_cx") { my $_name = $::cx_name; $_name = "CX_".$::cx_name if ( $::cx_name !~ /^CX_/); print $utils->doAsyncCmd("show_cxe default_tm $_name") . NL; exit 0; } if( $action eq "watch_cx") { my $thresh; ($thresh) = ( $stop_at =~ /^(\d+)\w+$/); do_err_exit("stop_at should be greater than zero; $usage") if ("$stop_at" eq ""); do_err_exit("stop_at should be greater than zero; $usage") if ($thresh < 1); do_err_exit("interval should be greater than zero; $usage") if ($interval < 1 ); do_err_exit("cx_name should not be empty; $usage") if ("$cx_name" eq "" ); summarize_cx( $cx_name ); my $continue = 1; while ($continue) { sleep $interval; summarize_cx( $cx_name ); print "$cx_name: " .($is_running ? "active":"inactive"); print " $::runtime, $::url_count urls, $::rx_bytes bytes\n"; # now check for bailout #print "Thresh $thresh | $stop_at | runtime $::runtime urls $::url_count rx $::rx_bytes\n"; if ( $stop_at =~ /^\d+$secs_sufx$/ ) { my ($rtime) = ($::runtime =~ /^(\d+)s/); if ($rtime >= $thresh) { $continue = 0; } } elsif ( $stop_at =~ /^\d+($reqs_sufx)$/) { if ($::url_count >= $thresh) { $continue = 0; } } elsif ( $stop_at =~ /^\d+$bytes_sufx*$/ ) { if ($::rx_bytes >= $thresh) { $continue = 0; } } } stop_cx(); print "connection $cx_name stopped.\n"; } #eof