Files
agc_2-X/bin/AST_update_AMI2.pl
T
mattf efc974d2c7 Added note about required version of Perl module Net Telnet 3.0.4. Must upgrade if using version older than April 21, 2013.
Disabled telnet logging in two of the new AMI2 scripts

git-svn-id: svn://192.168.202.10@2818 3d104415-ff17-0410-8863-d5cf3c621b8a
2017-09-21 22:36:21 +00:00

1653 lines
50 KiB
Perl

#!/usr/bin/perl
#
# AST_update_AMI2.pl version 2.14
#
# This script uses the Asterisk Manager interface to update the live_channels
# tables and verify the parked_channels table in the asterisk MySQL database
#
# Copyright (C) 2017 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
#
# CHANGES
# 170915-2110 - Initial version for Asterisk 13, based upon AST_update.pl
#
# constants
$DB=0; # Debug flag, set to 0 for no debug messages, lots of output
$DBX=0;
$run_check=1; # concurrency check
# loop time in seconds
$loop_time = 0.4;
# how often settings should be reloaded from the DB in seconds
$settings_reload_interval = 10;
# how often the server stats are updated
$server_stats_update_interval = 30;
# how often performance logging is triggered
$performance_logging_interval = 5;
### begin parsing run-time options ###
if (length($ARGV[0])>1)
{
$i=0;
while ($#ARGV >= $i)
{
$args = "$args $ARGV[$i]";
$i++;
}
if ($args =~ /--help/i)
{
print "allowed run time options:\n";
print " [--test] = test\n";
print " [--debug] = verbose debug messages\n";
print " [--debugX] = Extra-verbose debug messages\n";
print " [--help] = this screen\n";
print "\n";
exit;
}
else
{
if ($args =~ /--debug/i)
{
$DB=1; # Debug flag
print "\n----- DEBUGGING ENABLED -----\n\n";
}
if ($args =~ /--debugX/i)
{
$DBX=1;
print "\n----- SUPER-DUPER DEBUGGING -----\n\n";
}
if ($args =~ /--test/i)
{
$TEST=1;
$T=1;
}
}
}
### end parsing run-time options ###
# default path to astguiclient configuration file:
$PATHconf = '/etc/astguiclient.conf';
open(conf, "$PATHconf") || die "can't open $PATHconf: $!\n";
@conf = <conf>;
close(conf);
$i=0;
foreach(@conf)
{
$line = $conf[$i];
$line =~ s/ |>|\n|\r|\t|\#.*|;.*//gi;
if ($line =~ /^PATHhome/) {$PATHhome = $line; $PATHhome =~ s/.*=//gi;}
if ($line =~ /^PATHlogs/) {$PATHlogs = $line; $PATHlogs =~ s/.*=//gi;}
if ($line =~ /^PATHagi/) {$PATHagi = $line; $PATHagi =~ s/.*=//gi;}
if ($line =~ /^PATHweb/) {$PATHweb = $line; $PATHweb =~ s/.*=//gi;}
if ($line =~ /^PATHsounds/) {$PATHsounds = $line; $PATHsounds =~ s/.*=//gi;}
if ($line =~ /^PATHmonitor/) {$PATHmonitor = $line; $PATHmonitor =~ s/.*=//gi;}
if ($line =~ /^VARserver_ip/) {$VARserver_ip = $line; $VARserver_ip =~ s/.*=//gi;}
if ($line =~ /^VARDB_server/) {$VARDB_server = $line; $VARDB_server =~ s/.*=//gi;}
if ($line =~ /^VARDB_database/) {$VARDB_database = $line; $VARDB_database =~ s/.*=//gi;}
if ($line =~ /^VARDB_user/) {$VARDB_user = $line; $VARDB_user =~ s/.*=//gi;}
if ($line =~ /^VARDB_pass/) {$VARDB_pass = $line; $VARDB_pass =~ s/.*=//gi;}
if ($line =~ /^VARDB_port/) {$VARDB_port = $line; $VARDB_port =~ s/.*=//gi;}
$i++;
}
# Customized Variables
$server_ip = $VARserver_ip; # Asterisk server IP
### find df binary (partition usage)
$dfbin = '';
if ( -e ('/bin/df')) {$dfbin = '/bin/df';}
else
{
if ( -e ('/usr/bin/df')) {$dfbin = '/usr/bin/df';}
else
{
if ( -e ('/usr/local/bin/df')) {$dfbin = '/usr/local/bin/df';}
else
{
print "Can't find df binary! Exiting...\n";
exit;
}
}
}
if (!$VARDB_port) {$VARDB_port='3306';}
&get_time_now;
#use lib './lib', '../lib';
use Time::HiRes ('gettimeofday','usleep','sleep'); # necessary to have perl sleep command of less than one second
use DBI;
use Net::Telnet ();
use Switch;
use POSIX;
use Scalar::Util qw(looks_like_number);
use Term::ANSIColor qw(:constants);
$module = 'String::Escape qw( backslash unbackslash )';
$bs_loaded=0;
if (try_load($module))
{
$bs_loaded=1;
}
$dbhA = DBI->connect("DBI:mysql:$VARDB_database:$VARDB_server:$VARDB_port", "$VARDB_user", "$VARDB_pass")
or die "Couldn't connect to database: " . DBI->errstr;
### Grab Server values from the database
$stmtA = "SELECT telnet_host,telnet_port,ASTmgrUSERNAME,ASTmgrSECRET,ASTmgrUSERNAMEupdate,ASTmgrUSERNAMElisten,ASTmgrUSERNAMEsend,max_vicidial_trunks,answer_transfer_agent,local_gmt,ext_context,vd_server_logs,asterisk_version FROM servers where server_ip = '$server_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
if ($sthArows > 0)
{
@aryA = $sthA->fetchrow_array;
$DBtelnet_host = $aryA[0];
$DBtelnet_port = $aryA[1];
$DBASTmgrUSERNAME = $aryA[2];
$DBASTmgrSECRET = $aryA[3];
$DBASTmgrUSERNAMEupdate = $aryA[4];
$DBASTmgrUSERNAMElisten = $aryA[5];
$DBASTmgrUSERNAMEsend = $aryA[6];
$DBmax_vicidial_trunks = $aryA[7];
$DBanswer_transfer_agent= $aryA[8];
$DBSERVER_GMT = $aryA[9];
$DBext_context = $aryA[10];
$DBvd_server_logs = $aryA[11];
$asterisk_version = $aryA[12];
if ($DBtelnet_host) {$telnet_host = $DBtelnet_host;}
if ($DBtelnet_port) {$telnet_port = $DBtelnet_port;}
if ($DBASTmgrUSERNAME) {$ASTmgrUSERNAME = $DBASTmgrUSERNAME;}
if ($DBASTmgrSECRET) {$ASTmgrSECRET = $DBASTmgrSECRET;}
if ($DBASTmgrUSERNAMEupdate) {$ASTmgrUSERNAMEupdate = $DBASTmgrUSERNAMEupdate;}
if ($DBASTmgrUSERNAMEupdate) {$ASTmgrUSERNAMEupdate = $DBASTmgrUSERNAMEupdate;}
if ($DBASTmgrUSERNAMEsend) {$ASTmgrUSERNAMEsend = $DBASTmgrUSERNAMEsend;}
if ($DBmax_vicidial_trunks) {$max_vicidial_trunks = $DBmax_vicidial_trunks;}
if ($DBanswer_transfer_agent) {$answer_transfer_agent = $DBanswer_transfer_agent;}
if ($DBSERVER_GMT) {$SERVER_GMT = $DBSERVER_GMT;}
if ($DBext_context) {$ext_context = $DBext_context;}
if ($DBvd_server_logs =~ /Y/) {$SYSLOG = '1';}
else {$SYSLOG = '0';}
}
if (!$telnet_port) {$telnet_port = '5038';}
##### Check for a server_updater record, and if not present, insert one
$SUrec=0;
$stmtA = "SELECT count(*) FROM server_updater where server_ip='$server_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
@aryA = $sthA->fetchrow_array;
$SUrec = $aryA[0];
if($DB){print STDERR "\n|$SUrec|$stmtA|\n";}
if ($SUrec < 1)
{
&get_time_now;
$stmtU = "INSERT INTO server_updater set server_ip='$server_ip', last_update=NOW();";
if($DB){print STDERR "\n$stmtU\n";}
$affected_rows = $dbhA->do($stmtU);
}
$event_string='LOGGED INTO MYSQL SERVER ON 1 CONNECTION|';
event_logger($SYSLOG,$event_string);
### concurrency check (SCREEN uses script path, so check for more than 2 entries)
if ($run_check > 0)
{
my $grepout = `/bin/ps ax | grep $0 | grep -v grep | grep -v '/bin/sh'`;
my $grepnum=0;
$grepnum++ while ($grepout =~ m/\n/g);
if ($grepnum > 2)
{
if ($DB) {print "I am not alone! Another $0 is running! Exiting...\n";}
$event_string = "I am not alone! Another $0 is running! Exiting...";
&event_logger;
exit;
}
}
$event_string="STARTING NEW MANAGER TELNET CONNECTION||ATTEMPT|ONE DAY INTERVAL:$one_day_interval|";
event_logger($SYSLOG,$event_string);
$max_buffer = 4*1024*1024; # 4 meg buffer
### connect to asterisk manager through telnet
$tn = new Net::Telnet (
Port => $telnet_port,
Prompt => '/\r\n/',
Output_record_separator => "\n\n",
Max_buffer_length => $max_buffer,
Telnetmode => 0,
);
$UPtelnetlog = "$PATHlogs/update_telnet_log.txt"; # uncomment for telnet log
#$fh = $tn->dump_log("$UPtelnetlog"); # uncomment for telnet log
if (length($ASTmgrUSERNAMEupdate) > 3) {$telnet_login = $ASTmgrUSERNAMEupdate;}
else {$telnet_login = $ASTmgrUSERNAME;}
$tn->open("$telnet_host");
$tn->waitfor('/Asterisk Call Manager\//');
# get the AMI version number
$ami_version = $tn->getline(Errmode => Return, Timeout => 1,);
$ami_version =~ s/\n//gi;
print "----- AMI Version $ami_version -----\n";
# Login
$tn->print("Action: Login\nUsername: $telnet_login\nSecret: $ASTmgrSECRET");
$tn->waitfor('/Authentication accepted/'); # waitfor auth accepted
$tn->buffer_empty;
$event_string="STARTING NEW MANAGER TELNET CONNECTION|$telnet_login|CONFIRMED CONNECTION|AMI Version $ami_version|ONE DAY INTERVAL:$one_day_interval|";
event_logger($SYSLOG,$event_string);
%ast_ver_str = parse_asterisk_version($asterisk_version);
if (( $ast_ver_str{major} = 1 ) && ($ast_ver_str{minor} < 13))
{
print "Asterisk version too low for this script. Exiting.\n\n\n";
$event_string = "Asterisk version too low for this script. Exiting.";
&event_logger;
exit;
}
else
{
### BEGIN manager event handling for asterisk version >= 13
$endless_loop = 1;
# get the number of microseconds the loop is supposed to take
$loop_time_usec = $loop_time * 1000000;
$loop_time_usec = ceil($loop_time_usec); # take care of any floating point math
# total of the number of bad channel grabs from Asterisk
$total_bad_grabs = 0;
# the last time our settings were loaded from the DB
$last_config_reload = 0;
# the last time the server stats were updated
$last_stats_update = 0;
# the last time the performance data was logged
$last_perf_log = 0;
# the various channel counts from the last loop
$counts->{'psuedo'} = 0;
$counts->{'total'} = 0;
$counts->{'trunks'} = 0;
$counts->{'clients'} = 0;
$counts->{'sip'} = 0;
$counts->{'iax'} = 0;
$counts->{'dahdi'} = 0;
$counts->{'local'} = 0;
$counts->{'other'} = 0;
%parked_channels_hash = {};
$parked_channels = \%parked_channels_hash;
while($endless_loop)
{
# make a copy of our counts
%old_counts_hash = %{ $counts };
$old_counts = \%old_counts_hash;
# get the current time
( $now_sec, $now_micro_sec ) = gettimeofday();
# figure out how many micro seconds since epoch
$now_micro_epoch = $now_sec * 1000000;
$now_micro_epoch = $now_micro_epoch + $now_micro_sec;
$begin_micro_epoch = $now_micro_epoch;
# create a new action id
$action_id = "$now_sec.$now_micro_sec";
# ask the AMI for the channels
$action_string = "Action: CoreShowChannels\nActionID: $action_id";
$tn->print($action_string);
# wait till we get the response
$tn->waitfor('/Message: Channels will follow\n\n/');
# initialize the channal array
@chan_array = ();
# prepare to loop
$get_channels = 1;
# total number of channels pulled
$total_channels = 0;
# whether this channel pull was bad
$bad_grab = 0;
&get_time_now;
if ($DB) { print "\n\n$now_date\n|Channel List:\n"; }
# Loop to get all of the channels
$event_ref = {};
$match_string = '/Event: CoreShowChannelsComplete\nActionID: ' . $action_id . '\nEventList: Complete\nListItems: \d+/';
# get an entire record
( $read_input_buf, $match ) = $tn->waitfor(Errmode => Return, Timeout => 1, Match => "$match_string" );
chomp( $read_input_buf );
if (($DBX) && ($bs_loaded) && (length($read_input_buf) > 0)) { print "|read|" . backslash( $read_input_buf ) . "|\n"; }
if (($DBX) && ($bs_loaded) && (length($read_input_buf) > 0)) { print "|match|" . backslash( $match ) . "|\n"; }
( $junk, $list_items) = split( /ListItems: /, $match );
if ($DBX) { print "|total_channels|$list_items\n"; }
# check if there were any errors
$msg='';
$msg = $tn->errmsg;
if ( ( $msg ne '' ) && ( $msg !~ /read timed-out/i ) )
{
if ($msg =~ /filehandle isn\'t open/i)
{
# we have lost connection
$endless_loop=0;
$one_day_interval=0;
print "ERRMSG: |$msg|\n";
print "\nAsterisk server shutting down, PROCESS KILLED... EXITING\n\n";
$event_string="Asterisk server shutting down, PROCESS KILLED... EXITING|ONE DAY INTERVAL:$one_day_interval|$msg|";
event_logger($SYSLOG,$event_string);
}
else
{
# something happened
print "ERRMSG: |$msg|\n";
}
}
else
{
@records = split( /\n\n/, $read_input_buf );
foreach my $record ( @records )
{
# Loop to get all of the channels
$event_ref = {};
# break the record into lines
@lines = split( /\n/, $record );
foreach my $line ( @lines)
{
# add the line to the hash
($key,$value) = split( /: /, $line );
if ($key ne "")
{
$value =~ s/\n//gi; # remove new lines
$value =~ s/^ +//gi; # remove leading white space
$value =~ s/ +$//gi; # remove trailing white space
# change certain strings to conform with Asterisk 1.0 behavior
$value =~ s/Congestion\s+\(Empty\)/ SIP\/CONGEST/gi;
$value =~ s/\(Outgoing Line\)|\(None\)/SIP\/ring/gi;
$value =~ s/\(Empty\)/SIP\/internal/gi;
$event_ref->{"$key"} = $value;
}
}
$hash_size = keys(%$event_ref);
if ( ($DB) && ( $hash_size > 2 ) )
{
if ( $event_ref->{'Event'} eq "CoreShowChannel" )
{
if ( $total_channels == 0 )
{
print "|Channel|ChannelState|ChannelStateDesc|Exten|Priority|Context|CallerIDName|CallerIDNum|ConnectedLineName|ConnectedLineNum|Uniqueid|Linkedid|Application|ApplicationData|BridgeId|AccountCode|Language|Duration|\n";
}
print "|$event_ref->{'Channel'}";
print "|$event_ref->{'ChannelState'}";
print "|$event_ref->{'ChannelStateDesc'}";
print "|$event_ref->{'Exten'}";
print "|$event_ref->{'Priority'}";
print "|$event_ref->{'Context'}";
print "|$event_ref->{'CallerIDName'}";
print "|$event_ref->{'CallerIDNum'}";
print "|$event_ref->{'ConnectedLineName'}";
print "|$event_ref->{'ConnectedLineNum'}";
print "|$event_ref->{'Uniqueid'}";
print "|$event_ref->{'Linkedid'}";
print "|$event_ref->{'Application'}";
print "|$event_ref->{'ApplicationData'}";
print "|$event_ref->{'BridgeId'}";
print "|$event_ref->{'AccountCode'}";
print "|$event_ref->{'Language'}";
print "|$event_ref->{'Duration'}|";
print "\n";
}
}
$event_ref->{'AMIVersion'} = $ami_version;
$event_ref->{'ServerIP'} = $server_ip;
$retcode = 1;
# make sure this is an event not a response
if (exists($event_ref->{"Event"}))
{
if ( $event_ref->{"Event"} eq "CoreShowChannel" )
{
$total_channels++;
# We got a channel
if ( $event_ref->{"ActionID"} eq $action_id )
{
push( @chan_array, $event_ref );
}
else
{
if ($DB) { print STDERR "We got the wrong Action ID!!!!\n"; }
}
}
else
{
# We got something else???
}
}
elsif ( exists($event_ref->{"Response"}) )
{
# we got the response. Channels should follow.
}
}
}
if ( $total_channels != $list_items )
{
# something is wrong. we did not process the
# same number of channels as were reported.
$bad_grab = 1;
$total_bad_grabs++;
}
if ($DB) { print STDERR "$total_channels channels recieved out of $list_items reported.|$bad_grab|\n"; }
$chan_array_ref = \@chan_array;
# reload the settings from the DB at a fixed interval
$epoch = time();
if ( $epoch - $last_config_reload >= $settings_reload_interval )
{
# reload the server settings
$settings_ref = get_server_settings($dbhA,$server_ip);
%settings = %$settings_ref;
# reload the phone settings
$phones_ref = get_phones_settings($dbhA,$server_ip);
%phones = %$phones_ref;
$last_config_reload = time();
}
# update our time in the DB
$stmtA = "UPDATE server_updater set last_update=NOW() where server_ip='$server_ip'";
if($DB){print STDERR "\n$stmtA\n";}
$dbhA->do($stmtA);
# get the channels currently in the db
my ($db_trunks_ref, $db_clients_ref) = get_db_channels($dbhA,$server_ip);
# gather the various stats specific to the server stats
if ( $epoch - $last_stats_update >= $server_stats_update_interval )
{
$disk_usage = get_disk_space();
}
# gather the various stats specific to the performance log
if (( $settings_ref->{'sys_perf_log'} ) && ( $epoch - $last_perf_log >= $performance_logging_interval ))
{
( $mem_total, $mem_used, $mem_free ) = get_mem_usage();
$num_processes = get_num_processes();
( $reads, $writes ) = get_disk_rw();
}
# gather stats common to the performance log and server stats
if ( ( $epoch - $last_stats_update >= $server_stats_update_interval ) ||
(( $settings_ref->{'sys_perf_log'} ) && ( $epoch - $last_perf_log >= $performance_logging_interval )) )
{
$server_load = get_cpu_load();
(
$cpu_user_percent,
$cpu_idle_percent,
$cpu_sys_percent,
$cpu_vm_percent,
$user_diff,
$nice_diff,
$system_diff,
$idle_diff,
$iowait_diff,
$irq_diff,
$softirq_diff,
$steal_diff,
$guest_diff,
$guest_nice_diff
) = get_cpu_percent();
}
# check if there was something wrong with our channel grab
if ( $bad_grab )
{
if($DB){print STDERR "BAD GRAB!!!\n";}
# check if it is time to update the server stats
# if so use the old counts as the new ones are off
if ( $epoch - $last_stats_update >= $server_stats_update_interval )
{
server_stats_update( $dbhA, $server_ip, $old_counts, $server_load, $cpu_idle_percent, $disk_usage );
$last_stats_update = time();
}
# check if it is time to log the performance stats
# if so use the old counts as the new ones are off
if (( $settings_ref->{'sys_perf_log'} ) && ( $epoch - $last_perf_log >= $performance_logging_interval ))
{
server_perf_log( $dbhA, $server_ip, $old_counts, $server_load, $mem_free, $mem_used, $num_processes, $cpu_user_percent, $cpu_sys_percent, $cpu_idle_percent, $reads, $writes );
$last_perf_log = time();
}
usleep(10000); # sleep a hundreth of a second and try again
}
else
{
# Process the channel list
$counts = process_channels($dbhA,$chan_array_ref,$phones_ref,$db_trunks_ref,$db_clients_ref,$server_ip,$old_counts);
# make sure all the parked calls are valid
$parked_channels = validate_parked_channels( $dbhA, $parked_channels, $chan_array_ref, $server_ip );
# check if it is time to update the server stats
if ( $epoch - $last_stats_update >= $server_stats_update_interval )
{
server_stats_update( $dbhA, $server_ip, $counts, $server_load, $cpu_idle_percent, $disk_usage );
$last_stats_update = time();
}
# check if it is time to log the performance stats
if (( $settings_ref->{'sys_perf_log'} ) && ( $epoch - $last_perf_log >= $performance_logging_interval ))
{
server_perf_log( $dbhA, $server_ip, $counts, $server_load, $mem_free, $mem_used, $num_processes, $cpu_user_percent, $cpu_sys_percent, $cpu_idle_percent, $reads, $writes );
$last_perf_log = time();
}
# figure out how long that loop took.
# get the current time
( $now_sec, $now_micro_sec ) = gettimeofday();
# figure out how many micro seconds since epoch
$now_micro_epoch = $now_sec * 1000000;
$now_micro_epoch = $now_micro_epoch + $now_micro_sec;
$end_micro_epoch = $now_micro_epoch;
# subtract the current time in usec from time at the beginning of the loop
$loop_usec = $end_micro_epoch - $begin_micro_epoch;
# figure out how long to sleep
$sleep_usec = $loop_time_usec - $loop_usec;
# cannot sleep negative time
if ( $sleep_usec > 0 )
{
if ($DB) { print STDERR "loop took $loop_usec microseconds. sleeping for $sleep_usec microseconds to compensate\n"; }
# sleep it
usleep($sleep_usec);
}
}
}
}
if($DB){print "DONE... Exiting... Goodbye... See you later... Not really, initiating next loop...$one_day_interval left\n";}
$event_string='HANGING UP|';
event_logger($SYSLOG,$event_string);
@hangup = $tn->cmd(String => "Action: Logoff\n\n", Prompt => "/.*/", Errmode => Return, Timeout => 1);
$tn->buffer_empty;
$tn->waitfor(Match => '/Message:.*\n\n/', Timeout => 10);
$ok = $tn->close;
$event_string='CLOSING DB CONNECTION|';
event_logger($SYSLOG,$event_string);
$dbhA->disconnect();
if($DB){print "DONE... Exiting... Goodbye... See you later... Really I mean it this time\n";}
exit;
sub process_channels
{
my ($dbhA,$chan_array_ref,$phones_ref,$db_trunks_ref,$db_clients_ref,$server_ip,$old_counts) = @_;
$client_insert_sql = "";
$client_insert_count = 0;
$client_delete_sql = "";
$client_delete_count = 0;
$trunk_insert_sql = "";
$trunk_insert_count = 0;
$trunk_delete_sql = "";
$trunk_delete_count = 0;
$counts->{'psuedo'} = 0;
$counts->{'total'} = 0;
$counts->{'trunks'} = 0;
$counts->{'clients'} = 0;
$counts->{'sip'} = 0;
$counts->{'iax'} = 0;
$counts->{'dahdi'} = 0;
$counts->{'local'} = 0;
$counts->{'other'} = 0;
%cid_chan_hash = {};
foreach $channel_ref (@$chan_array_ref)
{
$call_id = get_valid_callid($channel_ref->{'CallerIDName'},$channel_ref->{'ConnectedLineName'});
# only need to match local channels to real channels on VDAD calls
if ( ( $call_id =~ /^V\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d$/ ) && ( $channel_ref->{'ConnectedLineName'} ne "<unknown>" ))
{
if ( $channel_ref->{'Channel'} =~ /^Local/ )
{
$cid_chan_hash{"$call_id"}->{'channel'} = $channel_ref->{'Channel'};
$cid_chan_hash{"$call_id"}->{'uniqueid'} = $channel_ref->{'Uniqueid'};
$cid_chan_hash{"$call_id"}->{'linkedid'} = $channel_ref->{'Linkedid'};
$cid_chan_hash{"$call_id"}->{'calleridname'} = $channel_ref->{'CallerIDName'};
$cid_chan_hash{"$call_id"}->{'connectedlinename'} = $channel_ref->{'ConnectedLineName'};
}
else
{
$cid_chan_hash{"$call_id"}->{'dest_channel'} = $channel_ref->{'Channel'};
$cid_chan_hash{"$call_id"}->{'dest_uniqueid'} = $channel_ref->{'Uniqueid'};
$cid_chan_hash{"$call_id"}->{'linkedid'} = $channel_ref->{'Linkedid'};
$cid_chan_hash{"$call_id"}->{'calleridname'} = $channel_ref->{'CallerIDName'};
$cid_chan_hash{"$call_id"}->{'connectedlinename'} = $channel_ref->{'ConnectedLineName'};
}
}
$extension = $channel_ref->{'ApplicationData'};
$extension =~ s/^SIP\///gi; # remove "SIP/" from the beginning
$extension =~ s/-\S+$//gi; # remove everything after a -
$extension =~ s/\|.*//gi; # remove everything after the |
$extension =~ s/,.*//gi; # remove everything after the ,
# make sure the channel is a channel type we care about
if ( $channel_ref->{'Channel'} =~ /^IAX2|^SIP|^Local|^DAHDI/)
{
# assume all channels are trunks then check if they are not
$line_type = 'TRUNK';
$channel_match = $channel_ref->{'Channel'};
# Local channels are not considered trunks
if ( $channel_match =~ /^Local/)
{
$line_type = 'CLIENT';
$counts->{'local'}++;
$counts->{'clients'}++;
}
elsif ( $channel_match =~ /^IAX2/)
{
# clean up the channel to get the extension
$channel_match =~ s/\/\d+$|-\d+$//gi;
$channel_match =~ s/^IAX2\///gi;
$channel_match =~ s/\*/\\\*/gi;
# if the channels extension is in phones
# and it is and IAX phone then it is a client
if ( ( exists ( $phones_ref->{ $channel_match } ) ) && ( $phones_ref->{ $channel_match }->{'protocol'} eq 'IAX2' ) )
{
$line_type = 'CLIENT';
$counts->{'iax'}++;
$counts->{'clients'}++;
}
}
elsif ($channel_ref->{'Channel'} =~ /^SIP/)
{
# clean up the channel to get the extension
$channel_match =~ s/-\S+$//gi;
$channel_match =~ s/^SIP\///gi;
$channel_match =~ s/\*/\\\*/gi;
# if the channels extension is in phones
# and it is and SIP phone then it is a client
if ( ( exists ( $phones_ref->{ $channel_match } ) ) && ( $phones_ref->{ $channel_match }->{'protocol'} eq 'SIP' ) )
{
$line_type = 'CLIENT';
$counts->{'sip'}++;
$counts->{'clients'}++;
}
}
# no point logging pseudo channels, just increment the psuedo count
elsif ( $channel_ref->{'Channel'} =~ /^DAHDI\/pseudo/ )
{
$line_type = 'PSEUDO';
$counts->{'psuedo'}++;
}
elsif ($channel_ref->{'Channel'} =~ /^DAHDI/)
{
# clean up the channel to get the extension
$channel_match =~ s/^DAHDI\///gi;
$channel_match =~ s/\*/\\\*/gi;
# if the channels extension is in phones
# and it is and DAHDI/ZAP phone then it is a client
if ( ( exists ( $phones_ref->{ $channel_match } ) ) && ( $phones_ref->{$channel_match}->{'protocol'} =~ /^ZAP|^DAHDI/) )
{
$line_type = 'CLIENT';
$counts->{'dahdi'}++;
$counts->{'clients'}++;
}
}
# count what is left of the trunks
if ( $line_type eq 'TRUNK' ) { $counts->{'trunks'}++; }
}
else
{
$counts->{'other'}++;
}
# count the total we have processed
$counts->{'total'}++;
# process the CLIENTs first
if ( $line_type eq 'CLIENT' )
{
# check if the channel is in the DB already
$in_db = 0;
foreach $db_client ( @$db_clients_ref )
{
if ( ( $db_client->{'channel'} eq $channel_ref->{'Channel'} ) && ( $db_client->{'extension'} eq $extension ) )
{
if ($DBX) { print STDERR "marking $db_client->{'channel'} active in db_clients\n"; }
$in_db = 1; # not that the channel is in the DB
$db_client->{'active'} = 1; # mark that this channel is still active
last; # break out of this foreach loop
}
}
if ( $in_db )
{
# channel already exists in the DB
}
else
{
# Add this channel to the client insert
if ( $client_insert_count > 0 ) { $client_insert_sql .= ", \n\t" }
$client_insert_sql .= "('$channel_ref->{'Channel'}','$server_ip','$extension','$channel_ref->{'ApplicationData'}')";
$client_insert_count++;
}
}
# if not a client it must be a TRUNK
elsif ( $line_type eq 'TRUNK' )
{
# check if the channel is in the DB already
$in_db = 0;
foreach $db_trunk ( @$db_trunks_ref )
{
if ( ( $db_trunk->{'channel'} eq $channel_ref->{'Channel'} ) && ( $db_trunk->{'extension'} eq $extension) )
{
if ($DBX) { print STDERR "marking $db_trunk->{'channel'} active in db_trunks\n"; }
$in_db = 1; # not that the channel is in the DB
$db_trunk->{'active'} = 1; # mark that this channel is still active
last; # break out of this foreach loop
}
}
if ( $in_db )
{
# channel already exists in the DB
}
else
{
# Add this channel to the trunk insert
if ( $trunk_insert_count > 0 ) { $trunk_insert_sql .= ", \n\t"; }
$trunk_insert_sql .= "('$channel_ref->{'Channel'}','$server_ip','$extension','$channel_ref->{'ApplicationData'}')";
$trunk_insert_count++;
}
}
}
if ( bad_grab_check( $counts, $old_counts ) )
{
if($DB){print STDERR "BAD GRAB!!!\n";}
usleep(10000); # sleep a hundreth of a second and try again
return $old_counts;
}
else
{
if ( $client_insert_count > 0 )
{
# insert all the new clients
my $stmtA = "INSERT INTO live_sip_channels (channel,server_ip,extension,channel_data) values \n\t" . $client_insert_sql;
if ($DB) { print STDERR "$stmtA\n"; }
$stmtA =~ s/\n|\t//gi;
$dbhA->do($stmtA);
}
elsif ($DB) { print STDERR "|no client channels to insert|\n"; }
if ( $trunk_insert_count > 0 )
{
# insert all the new trunks
my $stmtA = "INSERT INTO live_channels (channel,server_ip,extension,channel_data) values \n\t" . $trunk_insert_sql;
if ($DB) { print STDERR "$stmtA\n"; }
$stmtA =~ s/\n|\t//gi;
$dbhA->do($stmtA);
}
elsif ($DB) { print STDERR "|no trunk channels to insert|\n"; }
# find any clients that have hung up
foreach $db_client ( @$db_clients_ref )
{
# if DB client not in current channel list add it to the client delete
if ( ( !(exists( $db_client->{'active'} ) ) ) || ($db_client->{'active'} == 0 ) )
{
if ( $client_delete_count > 0 ) { $client_delete_sql .= " or \n\t"; }
$client_delete_sql .= "(server_ip='$server_ip' and channel='$db_client->{'channel'}' and extension='$db_client->{'extension'}')";
$client_delete_count++;
}
}
# find any trunks that have hung up
foreach $db_trunk ( @$db_trunks_ref )
{
# if DB trunk not in current channel list add it to the trunk delte
if ( ( !(exists( $db_trunk->{'active'} ) ) ) || ( $db_trunk->{'active'} == 0 ) )
{
if ( $trunk_delete_count > 0 ) { $trunk_delete_sql .= " or \n\t"; }
$trunk_delete_sql .= "(server_ip='$server_ip' and channel='$db_trunk->{'channel'}' and extension='$db_trunk->{'extension'}')";
$trunk_delete_count++;
}
}
# delete all the hung up clients
if ( $client_delete_count > 0 )
{
my $stmtA = "DELETE FROM live_sip_channels where \n\t(" . $client_delete_sql . " )";
if ($DB) { print STDERR "$stmtA\n"; }
$stmtA =~ s/\n|\t//gi;
$affected_rows = $dbhA->do($stmtA);
}
elsif ($DB) { print STDERR "|no client channels to delete|\n"; }
# delete all the hung up trunks
if ( $trunk_delete_count > 0 )
{
my $stmtA = "DELETE FROM live_channels where \n\t(" . $trunk_delete_sql . " )";
if ($DB) { print STDERR "$stmtA\n"; }
$stmtA =~ s/\n|\t//gi;
$affected_rows = $dbhA->do($stmtA);
}
elsif ($DB) { print STDERR "|no trunk channels to delete|\n"; }
# build the cid_channels_recent insert
$cid_chan_sql = '';
$cid_chan_count = 0;
foreach $call_id (keys %cid_chan_hash)
{
if ( ( $cid_chan_hash{"$call_id"}->{'channel'} ne "" ) && ( $cid_chan_hash{"$call_id"}->{'dest_channel'} ne "" ) )
{
if ( $cid_chan_count > 0 ) { $cid_chan_sql .= ",\n\t"; }
$cid_chan_sql .= "( ";
$cid_chan_sql .= "'" . $cid_chan_hash{"$call_id"}->{'calleridname'} . "', ";
$cid_chan_sql .= "'" . $cid_chan_hash{"$call_id"}->{'connectedlinename'} . "', ";
$cid_chan_sql .= "'$server_ip', ";
$cid_chan_sql .= "NOW(), ";
$cid_chan_sql .= "'" . $cid_chan_hash{"$call_id"}->{'channel'} . "', ";
$cid_chan_sql .= "'" . $cid_chan_hash{"$call_id"}->{'dest_channel'} . "', ";
$cid_chan_sql .= "'" . $cid_chan_hash{"$call_id"}->{'linkedid'} . "', ";
$cid_chan_sql .= "'" . $cid_chan_hash{"$call_id"}->{'uniqueid'} . "', ";
$cid_chan_sql .= "'" . $cid_chan_hash{"$call_id"}->{'dest_uniqueid'} . "'";
$cid_chan_sql .= " )";
$cid_chan_count++;
}
}
if ( $cid_chan_count > 0 )
{
$stmtA = "INSERT IGNORE INTO cid_channels_recent (caller_id_name, connected_line_name, server_ip, call_date, channel, dest_channel, linkedid, dest_uniqueid, uniqueid) values \n\t";
$stmtA .= $cid_chan_sql;
if ($DB) { print STDERR "$stmtA\n"; }
$stmtA =~ s/\n|\t//gi;
$dbhA->do($stmtA);
}
return $counts;
}
}
sub validate_parked_channels
{
( $dbhA, $parked_channels, $chan_array_ref, $server_ip ) = @_;
my $park_delete_sql = "";
my $park_delete_count = 0;
my $auto_delete_sql = "(";
# remove the duplicates caused by agents quickly parking, unparking, and parking again calls
$stmtA = "DELETE pc1 FROM parked_channels pc1, parked_channels pc2 WHERE pc1.parked_time < pc2.parked_time AND pc1.parked_time <> pc2.parked_time AND pc1.channel = pc2.channel AND pc1.server_ip='$server_ip' and pc2.server_ip='$server_ip'";
$deleted_rows = $dbhA->do($stmtA);
if ($DB) { print STDERR "Park Dup Del|$stmtA|$deleted_rows\n"; }
# get the channels currently parked
$stmtA = "SELECT channel,extension,parked_time,UNIX_TIMESTAMP(parked_time),channel_group FROM parked_channels where server_ip = '$server_ip' order by channel desc, parked_time desc;";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$ref = $sthA->fetchall_arrayref;
# loop through the parked channels
foreach my $row ( @{ $ref } )
{
$channel = $row->[0];
$extension = $row->[1];
$parked_time = $row->[2];
$unix_parked_time = $row->[3];
$channel_group = $row->[4];
# check if we already saw the parked channel before
if ( exists( $parked_channels->{"$channel"} ) )
{
# if we have look for it in the current active channels
$channel_found = 0;
foreach $channel_ref (@$chan_array_ref)
{
# if we found it note that it there
if ( $channel_ref->{'Channel'} eq $channel ) { $channel_found = 1; }
}
# if it was found set its count back to 0
if ($channel_found) { $parked_channels->{"$channel"} = 0; }
# otherwise increment its count
else { $parked_channels->{"$channel"}++; }
}
else
{
# if not add it to our list and set the count to 0
$parked_channels->{"$channel"} = 0;
}
# if a channel has been gone for more than 10 seconds (25 calls to this function)
if ( $parked_channels->{"$channel"} >= 25 )
{
# build the SQL for deleting stale values
if ( $park_delete_count > 0 )
{
$park_delete_sql .= " or ";
$auto_delete_sql .= ", ";
}
$park_delete_sql .= "(channel='$channel' and extension='$extension')";
$auto_delete_sql .= "'$channel_group'";
$park_delete_count++;
}
}
$auto_delete_sql .= " )";
# if we have records to delete
if ( $park_delete_count > 0 )
{
# delete the records from parked_channels
$stmtA = "DELETE FROM parked_channels WHERE (" . $park_delete_sql . ") and server_ip='$server_ip'";
$deleted_rows = $dbhA->do($stmtA);
if ($DB) { print STDERR "Park Del|$stmtA|$deleted_rows\n"; }
# delete the records from vicidial_auto_calls
$stmtA = "DELETE FROM vicidial_auto_calls WHERE callerid IN " . $auto_delete_sql;
$deleted_rows = $dbhA->do($stmtA);
if ($DB) { print STDERR "Auto Calls Del|$stmtA|$deleted_rows\n"; }
}
return $parked_channels;
}
sub bad_grab_check
{
my ($counts,$old_counts) = @_;
my $bad_grab = 0;
# calculate the percentage of the total number of channels that changed
if ( (!$old_counts->{'total'}) or ($counts->{'total'} < 2) )
{$percent_total_static = 0;}
else
{
$percent_total_static = ( ($counts->{'total'} / $old_counts->{'total'}) * 100);
$percent_total_static = sprintf("%6.2f", $percent_total_static);
}
# calculate the percentage of DAHDI client channels that changed including pseudo channels
$current_dahdi = $counts->{'dahdi'} + $counts->{'pseudo'};
$old_dahdi = $old_counts->{'dahdi'} + $_oldcounts->{'pseudo'};
if ( (!$current_dahdi) or ($old_dahdi < 2) )
{$percent_dahdi_client_static = 0;}
else
{
$percent_dahdi_client_static = ( ($current_dahdi / $old_dahdi) * 100);
$percent_dahdi_client_static = sprintf("%6.2f", $percent_dahdi_client_static);
}
# calculate the percentage of IAX client channels that changed
if ( (!$counts->{'iax'}) or ($old_counts->{'iax'} < 2) )
{$percent_iax_client_static = 0;}
else
{
$percent_iax_client_static = ( ($counts->{'iax'} / $old_counts->{'iax'}) * 100);
$percent_iax_client_static = sprintf("%6.2f", $percent_iax_client_static);
}
# calculate the percentage of Local client channels that changed
if ( (!$counts->{'local'}) or ($old_counts->{'local'} < 2) )
{$percent_local_client_static = 0;}
else
{
$percent_local_client_static = ( ($counts->{'local'} / $old_counts->{'local'}) * 100);
$percent_local_client_static = sprintf("%6.2f", $percent_local_client_static);
}
# calculate the percentage of SIP client channels that changed
if ( (!$counts->{'sip'}) or ($old_counts->{'sip'} < 2) )
{$percent_sip_client_static = 0;}
else
{
$percent_sip_client_static = ( ($counts->{'sip'} / $old_counts->{'sip'}) * 100);
$percent_sip_client_static = sprintf("%6.2f", $percent_sip_client_static);
}
if ($DB) { print "BG_check_stats [$percent_total_static|$counts->{'total'}:$old_counts->{'total'}\t$percent_dahdi_client_static|$counts->{'dahdi'}:$old_counts->{'dahdi'}\t$percent_iax_client_static|$counts->{'iax'}:$old_counts->{'iax'}\t$percent_local_client_static|$counts->{'local'}:$old_counts->{'local'}\t$percent_sip_client_static|$counts->{'sip'}:$old_counts->{'sip'}]\n"; }
# MASSIVE IF STATEMENT FOR CHECKING IF IT WAS A BAD GRAB
if (
# if we had > 3 trunks or > 4 clients and we now have less than 10% of those remaining
( ($percent_total_static < 10) && ( ($old_counts->{'trunk'} > 3) or ($old_counts->{'client'} > 4) ) ) or
# or if we had > 10 trunks or > 10 clients and we now have less than 20% of those remaining
( ($percent_total_static < 20) && ( ($old_counts->{'trunk'} > 10) or ($old_counts->{'client'} > 10) ) ) or
# or if we had > 20 trunks or > 20 clients and we now have less than 30% of those remaining
( ($percent_total_static < 30) && ( ($old_counts->{'trunk'} > 20) or ($old_counts->{'client'} > 20) ) ) or
# or if we had > 30 trunks or > 30 clients and we now have less than 40% of those remaining
( ($percent_total_static < 40) && ( ($old_counts->{'trunk'} > 30) or ($old_counts->{'client'} > 30) ) ) or
# or if we had > 40 trunks or > 40 clients and we now have less than 50% of those remaining
( ($percent_total_static < 50) && ( ($old_counts->{'trunk'} > 40) or ($old_counts->{'client'} > 40) ) ) or
# or if we had > 3 dahdi clients and we now have less than 20% of those remaining
( ($percent_dahdi_client_static < 20) && ( $old_counts->{'dahdi'} > 3 ) ) or
# or if we had > 9 dahdi clients and we now have less than 40% of those remaining
( ($percent_dahdi_client_static < 40) && ( $old_counts->{'dahdi'} > 9 ) ) or
# or if we had > 3 iax clients and we now have less than 20% of those remaining
( ($percent_iax_client_static < 20) && ( $old_counts->{'iax'} > 3 ) ) or
# or if we had > 9 iax clients and we now have less than 40% of those remaining
( ($percent_iax_client_static < 40) && ( $old_counts->{'iax'} > 9 ) ) or
# or if we had > 3 sip clients and we now have less than 20% of those remaining
( ($percent_sip_client_static < 20) && ( $old_counts->{'sip'} > 3 ) ) or
# or if we had > 9 sip clients and we now have less than 40% of those remaining
( ($percent_sip_client_static < 40) && ( $old_counts->{'sip'} > 9 ) )
)
{
$bad_grab = 1;
$event_string="------ UPDATER BAD GRAB!!!\n$percent_total_static|$counts->{'total'}:$old_counts->{'total'}\t$percent_dahdi_client_static|$counts->{'dahdi'}:$old_counts->{'dahdi'}\t$percent_iax_client_static|$counts->{'iax'}:$old_counts->{'iax'}\t$percent_local_client_static|$counts->{'local'}:$old_counts->{'local'}\t$percent_sip_client_static|$counts->{'sip'}:$old_counts->{'sip'}\n";
&event_logger;
}
return $bad_grab;
}
sub server_stats_update
{
( $dbhA, $server_ip, $channel_counts, $server_load, $cpu_idle_percent, $disk_usage ) = @_;
$stmt = "UPDATE servers SET sysload='$server_load', channels_total='$channel_counts->{'total'}', cpu_idle_percent='$cpu_idle_percent', disk_usage='$disk_usage' where server_ip='$server_ip';";
$rows = $dbhA->do($stmt);
if ($DB)
{
print STDERR BRIGHT_RED BOLD, "\nServer Stats Updated", RESET;
print STDERR "|$stmt|$rows\n";
}
}
sub server_perf_log
{
( $dbhA, $server_ip, $channel_counts, $server_load, $mem_free, $mem_used, $num_processes, $cpu_user_percent, $cpu_sys_percent, $cpu_idle_percent, $reads, $writes ) = @_;
$stmt = "INSERT INTO server_performance (start_time, server_ip, sysload, freeram, usedram, processes, channels_total, trunks_total, clients_total, clients_zap, clients_iax, clients_local, clients_sip, live_recordings, cpu_user_percent, cpu_system_percent, cpu_idle_percent, disk_reads, disk_writes) values( NOW(), '$server_ip', '$server_load', '$mem_free', '$mem_used', '$num_processes', '$channel_counts->{'total'}', '$channel_counts->{'trunks'}', '$channel_counts->{'clients'}', '$channel_counts->{'dahdi'}', '$channel_counts->{'iax'}', '$channel_counts->{'local'}', '$channel_counts->{'sip'}', '0', '$cpu_user_percent', '$cpu_sys_percent', '$cpu_idle_percent', '$reads', '$writes')";
$dbhA->do($stmt);
if ($DB)
{
print STDERR BRIGHT_BLUE BOLD, "\nPerformance Log Record Inserted", RESET;
print STDERR "|$stmt\n\n";
}
}
sub get_server_settings
{
my ($dbhA,$server_ip) = @_;
### Grab Server values from the database
$stmtA = "SELECT sys_perf_log,vd_server_logs FROM servers where server_ip='$server_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$sthArows=$sthA->rows;
$settings_ref = $sthA->fetchrow_hashref;
if ( $settings_ref->{'sys_perf_log'} eq 'Y' ) { $settings_ref->{'sys_perf_log'} = 1;}
else { $settings_ref->{'sys_perf_log'} = 0;}
if ( $settings_ref->{'vd_server_logs'} eq 'Y' ) { $settings_ref->{'vd_server_logs'} = 1;}
else { $settings_ref->{'vd_server_logs'} = 0;}
return $settings_ref;
}
sub get_phones_settings
{
my ($dbhA,$server_ip) = @_;
$stmtA = "SELECT extension, protocol FROM phones where server_ip='$server_ip' and phone_type NOT LIKE \"%trunk%\"";
if($DB){print STDERR "|$stmtA|\n";}
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
$phones_ref = $sthA->fetchall_hashref('extension');
$zap_phones = 0;
$sip_phones = 0;
$iax_phones = 0;
$zap_phone_list = "|";
$sip_phone_list = "|";
$iax_phone_list = "|";
foreach $key ( sort (keys %$phones_ref) )
{
if ($DB) { print STDERR "$key|$phones_ref->{$key}->{'protocol'}\n"; }
if ( $phones_ref->{$key}->{'protocol'} eq 'ZAP' )
{
$zap_phones++;
$zap_phone_list .= "$key|";
}
elsif ( $phones_ref->{$key}->{'protocol'} eq 'SIP' )
{
$sip_phones++;
$sip_phone_list .= "$key|";
}
elsif ( $phones_ref->{$key}->{'protocol'} eq 'IAX' )
{
$iax_phones++;
$iax_phone_list .= "$keys|";
}
}
$phones_ref->{'zap_phones'} = $zap_phones;
$phones_ref->{'sip_phones'} = $sip_phones;
$phones_ref->{'iax_phones'} = $iax_phones;
$phones_ref->{'zap_phone_list'} = $zap_phone_list;
$phones_ref->{'sip_phone_list'} = $sip_phone_list;
$phones_ref->{'iax_phone_list'} = $iax_phone_list;
return $phones_ref;
}
sub get_db_channels
{
my ($dbhA,$server_ip) = @_;
my @db_trunks;
my @db_clients;
my $stmtA = "SELECT channel,extension FROM live_channels where server_ip='$server_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
while ( $hash_ref = $sthA->fetchrow_hashref )
{
push( @db_trunks, $hash_ref );
}
my $stmtA = "SELECT channel,extension FROM live_sip_channels where server_ip='$server_ip';";
$sthA = $dbhA->prepare($stmtA) or die "preparing: ",$dbhA->errstr;
$sthA->execute or die "executing: $stmtA ", $dbhA->errstr;
while ( $hash_ref = $sthA->fetchrow_hashref )
{
push( @db_clients, $hash_ref );
}
return (\@db_trunks, \@db_clients);
}
# function to validate whether a CID Name is a Vicidial Call ID that we care about
sub validate_cid_name
{
my ($cid_name) = @_;
# check if it is a valid CID Name
if (
( $cid_name =~ /DC\d\d\d\d\d\dW\d\d\d\d\d\d\d\d\d\dW/ ) || # 3way transfers
( $cid_name =~ /M\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d/) || # Manual Dials
( $cid_name =~ /V\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d/) || # Auto Dials
( $cid_name =~ /Y\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d/) # Inbound Calls
)
{
return 1; # if so return 1 for true
}
else
{
return 0; # if not return 0 for false
}
}
# function to return the valid callid
sub get_valid_callid
{
my ( $CallerIDName, $ConnectedLineName ) = @_;
# remove everything after the space for Orex
if ( $CallerIDName =~ /\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S/) {$CallerIDName =~ s/ .*//gi;}
if ( $ConnectedLineName =~ /\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S/) {$ConnectedLineName =~ s/ .*//gi;}
# if the CallerIDName variable does not have a valid Vicidial Call ID
# but the ConnectedLineName does use the ConnectedLineName
if ( !(validate_cid_name($CallerIDName)) && (validate_cid_name($ConnectedLineName)) )
{
return $ConnectedLineName;
}
else
{
return $CallerIDName;
}
}
sub event_logger
{
my ($SYSLOG,$event_string) = @_;
if ($SYSLOG)
{
### open the log file for writing ###
open(Lout, ">>$PATHlogs/update.$action_log_date")
|| die "Can't open $PATHlogs/update.$action_log_date: $!\n";
print Lout "$now_date|$event_string|\n";
close(Lout);
}
$event_string='';
}
# subroutine to parse the asterisk version
# and return a hash with the various part
sub parse_asterisk_version
{
# grab the arguments
my $ast_ver_str = $_[0];
# get everything after the - and put it in $ast_ver_postfix
my @hyphen_parts = split( /-/ , $ast_ver_str );
my $ast_ver_postfix = $hyphen_parts[1];
# now split everything before the - up by the .
my @dot_parts = split( /\./ , $hyphen_parts[0] );
my %ast_ver_hash;
if ( $dot_parts[0] <= 1 )
{
%ast_ver_hash = (
"major" => $dot_parts[0],
"minor" => $dot_parts[1],
"build" => $dot_parts[2],
"revision" => $dot_parts[3],
"postfix" => $ast_ver_postfix
);
}
# digium dropped the 1 from asterisk 10 but we still need it
if ( $dot_parts[0] > 1 )
{
%ast_ver_hash = (
"major" => 1,
"minor" => $dot_parts[0],
"build" => $dot_parts[1],
"revision" => $dot_parts[2],
"postfix" => $ast_ver_postfix
);
}
return ( %ast_ver_hash );
}
sub get_time_now #get the current date and time and epoch for logging call lengths and datetimes
{
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = ($year + 1900);
$mon++;
if ($mon < 10) {$mon = "0$mon";}
if ($mday < 10) {$mday = "0$mday";}
if ($hour < 10) {$hour = "0$hour";}
if ($min < 10) {$min = "0$min";}
if ($sec < 10) {$sec = "0$sec";}
$now_date_epoch = time();
$now_date = "$year-$mon-$mday $hour:$min:$sec";
$action_log_date = "$year-$mon-$mday";
}
# try to load a module
sub try_load
{
my $mod = shift;
eval("use $mod");
if ($@)
{
#print "\$@ = $@\n";
return(0);
}
else
{
return(1);
}
}
sub print_now
{
my $string = shift;
# get the current time in microseconds
my ( $now_sec, $now_micro_sec ) = gettimeofday();
# figure out how many micro seconds since epoch
my $now_micro_epoch = $now_sec * 1000000;
$now_micro_epoch = $now_micro_epoch + $now_micro_sec;
print "\n$string|$now_micro_epoch\n\n";
}
sub get_cpu_percent
{
# stat file in proc
$stat = '/proc/stat';
# read it
open( FH , "<$stat" );
@lines = <FH>;
close( FH );
# get the various times spent doing stuff ( $cpu is useless )
($cpu, $user, $nice, $system, $idle, $iowait, $irq, $softirq, $steal, $guest, $guest_nice ) = split( ' ', $lines[0] );
# total the different catagories of time
$cpu_user = $user + $nice;
$cpu_idle = $idle + $iowait;
$cpu_sys = $system + $irq + $softirq;
$cpu_vm = $steal + $guest + $guest_nice;
# check if we have previous values
if ( defined ( $prev_user ) )
{
# get the differential from last time
$cpu_user_diff = $cpu_user - $prev_cpu_user;
$cpu_idle_diff = $cpu_idle - $prev_cpu_idle;
$cpu_sys_diff = $cpu_sys - $prev_cpu_sys;
$cpu_vm_diff = $cpu_vm - $prev_cpu_vm;
$user_diff = $user - $prev_user;
$nice_diff = $nice - $prev_nice;
$system_diff = $system - $prev_system;
$idle_diff = $idle - $prev_idle;
$iowait_diff = $iowait - $prev_iowait;
$irq_diff = $irq - $prev_irq;
$softirq_diff = $softirq - $prev_softirq;
$steal_diff = $steal - $prev_steal;
$guest_diff = $guest - $prev_guest;
$guest_nice_diff = $guest_nice - $prev_guest_nice;
# total the differentials
$cpu_total_diff = $cpu_user_diff + $cpu_idle_diff + $cpu_sys_diff + $cpu_vm_diff;
$cpu_user_percent = sprintf("%.0f", (( $cpu_user_diff / $cpu_total_diff ) * 100 ));
$cpu_idle_percent = sprintf("%.0f", (( $cpu_idle_diff / $cpu_total_diff ) * 100 ));
$cpu_sys_percent = sprintf("%.0f", (( $cpu_sys_diff / $cpu_total_diff ) * 100 ));
$cpu_vm_percent = sprintf("%.0f", (( $cpu_vm_diff / $cpu_total_diff ) * 100 ));
}
else
{
# first time runnings so there are no previous values.
# all we can do is base it off the system totals since boot.
$cpu_total = $cpu_user + $cpu_idle + $cpu_sys + $cpu_vm;
$cpu_user_percent = sprintf("%.0f", (( $cpu_user / $cpu_total ) * 100 ));
$cpu_idle_percent = sprintf("%.0f", (( $cpu_idle / $cpu_total ) * 100 ));
$cpu_sys_percent = sprintf("%.0f", (( $cpu_sys / $cpu_total ) * 100 ));
$cpu_vm_percent = sprintf("%.0f", (( $cpu_vm / $cpu_total ) * 100 ));
}
# store the values for the next call
$prev_user = $user;
$prev_nice = $nice;
$prev_system = $system;
$prev_idle = $idle;
$prev_iowait = $iowait;
$prev_irq = $irq;
$prev_softirq = $softirq;
$prev_steal = $steal;
$prev_guest = $guest;
$prev_guest_nice = $guest_nice;
$prev_cpu_user = $cpu_user;
$prev_cpu_idle = $cpu_idle;
$prev_cpu_sys = $cpu_sys;
$prev_cpu_vm = $cpu_vm;
return (
$cpu_user_percent,
$cpu_idle_percent,
$cpu_sys_percent,
$cpu_vm_percent,
$user_diff,
$nice_diff,
$system_diff,
$idle_diff,
$iowait_diff,
$irq_diff,
$softirq_diff,
$steal_diff,
$guest_diff,
$guest_nice_diff
);
}
sub get_cpu_load
{
$lavg = '/proc/loadavg';
open( FH , "<$lavg" );
@lines = <FH>;
close( FH );
$server_load = $lines[0];
$server_load =~ s/ .*//gi;
$server_load =~ s/\D//gi;
return $server_load;
}
sub get_mem_usage
{
$meminfo = '/proc/meminfo';
open( FH , "<$meminfo" );
@lines = <FH>;
close( FH );
$mem_total = $lines[0];
$mem_total =~ s/MemTotal: *//g;
$mem_free = $lines[1];
$mem_free =~ s/MemFree: *//g;
$mem_used = $mem_total - $mem_free;
$mem_used = floor( $mem_used / 1024 );
$mem_total = floor( $mem_total / 1024 );
$mem_free = floor( $mem_free / 1023 );
return ( $mem_total, $mem_used, $mem_free );
}
sub get_disk_space
{
@serverDISK = `$dfbin -B 1048576 -x nfs -x cifs -x sshfs -x ftpfs`;
$ct=0;
$ct_PCT=0;
$disk_usage = '';
foreach(@serverDISK)
{
if ($serverDISK[$ct] =~ /(\d+\%)/)
{
$ct_PCT++;
$usage = $1;
$usage =~ s/\%//gi;
$disk_usage .= "$ct_PCT $usage|";
}
$ct++;
}
return $disk_usage;
}
sub get_num_processes
{
$num_processes = 0;
opendir( DH, '/proc');
while ( readdir( DH ) )
{
if ( looks_like_number( $_ ) ) { $num_processes++; }
}
closedir( DH );
return ($num_processes);
}
sub get_disk_rw
{
$total_reads = 0;
$total_writes = 0;
$diskstats = "/proc/diskstats";
open( FH , "<$diskstats" );
@lines = <FH>;
close( FH );
foreach $line ( @lines )
{
# remove excess white space
$line =~ s/\h+/ /g;
$line =~ s/^\s+|\s+$//g;
# split the line
(
$major,
$minor,
$device,
$reads_completed,
$reads_merged,
$sectors_read,
$time_reading,
$writes_completed,
$writes_merged,
$sectors_written,
$time_writing,
$current_ios,
$ios_time,
$weighted_ios_time
) = split( ' ', $line );
# check if device is a drive or partition or raid
if ( $device !~ /\d/ )
{
$total_reads += $sectors_read;
$total_writes += $sectors_written;
}
}
# check if we previously got the total reads
if ( defined ( $prev_total_reads ) )
{
$reads = $total_reads - $prev_total_reads;
$writes = $total_writes - $prev_total_writes;
}
else
{
# cannot figure out the difference
# if we don't know what it was before
$reads = 0;
$writes = 0;
}
$prev_total_reads = $total_reads;
$prev_total_writes = $total_writes;
return ( $reads, $writes );
}