2012-05-16 16:26:19 +00:00
< ? php
2014-12-15 11:10:26 +00:00
/* Copyright ( C ) 2014 Daniel Preussker < f0o @ devilcode . org >
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
2015-07-13 20:10:26 +02:00
*
2014-12-15 11:10:26 +00:00
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
2015-07-13 20:10:26 +02:00
*
2014-12-15 11:10:26 +00:00
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http :// www . gnu . org / licenses />. */
2012-05-16 16:26:19 +00:00
2015-07-13 20:10:26 +02:00
/*
2014-12-15 11:10:26 +00:00
* Alerts Tracking
* @ author Daniel Preussker < f0o @ devilcode . org >
* @ copyright 2014 f0o , LibreNMS
* @ license GPL
* @ package LibreNMS
* @ subpackage Alerts
2012-05-16 16:26:19 +00:00
*/
2018-11-19 15:58:59 +00:00
use App\Models\DevicePerf ;
2018-07-14 22:15:43 +01:00
use LibreNMS\Alert\Template ;
2018-07-21 13:34:59 -06:00
use LibreNMS\Alert\AlertData ;
2018-03-14 20:25:19 +00:00
use LibreNMS\Alerting\QueryBuilderParser ;
2018-09-11 07:51:35 -05:00
use LibreNMS\Authentication\LegacyAuth ;
2018-07-21 13:34:59 -06:00
use LibreNMS\Alert\AlertUtil ;
2019-02-15 13:58:59 +00:00
use LibreNMS\Config ;
2019-02-15 07:53:41 +01:00
use PHPMailer\PHPMailer\PHPMailer ;
2019-03-18 03:09:58 +01:00
use LibreNMS\Util\Time ;
2015-04-03 18:22:29 +00:00
2018-03-14 20:25:19 +00:00
/**
* @ param $rule
* @ param $query_builder
* @ return bool | string
*/
function GenSQL ( $rule , $query_builder = false )
{
if ( $query_builder ) {
2018-03-20 07:49:57 -05:00
return QueryBuilderParser :: fromJson ( $query_builder ) -> toSql ();
2018-03-14 20:25:19 +00:00
} else {
return GenSQLOld ( $rule );
}
}
2012-05-16 16:26:19 +00:00
/**
2014-12-15 11:10:26 +00:00
* Generate SQL from Rule
* @ param string $rule Rule to generate SQL for
2015-04-25 11:10:37 +00:00
* @ return string | boolean
2014-12-15 11:10:26 +00:00
*/
2018-03-14 20:25:19 +00:00
function GenSQLOld ( $rule )
2016-08-28 12:32:58 -05:00
{
2015-07-13 20:10:26 +02:00
$rule = RunMacros ( $rule );
2016-08-28 12:32:58 -05:00
if ( empty ( $rule )) {
2015-07-13 20:10:26 +02:00
//Cannot resolve Macros due to recursion. Rule is invalid.
return false ;
}
//Pretty-print rule to dissect easier
2017-05-13 23:32:41 +02:00
$pretty = array ( '&&' => ' && ' , '||' => ' || ' );
2016-08-28 12:32:58 -05:00
$rule = str_replace ( array_keys ( $pretty ), $pretty , $rule );
$tmp = explode ( " " , $rule );
2015-07-13 20:10:26 +02:00
$tables = array ();
2016-08-28 12:32:58 -05:00
foreach ( $tmp as $opt ) {
if ( strstr ( $opt , '%' ) && strstr ( $opt , '.' )) {
$tmpp = explode ( " . " , $opt , 2 );
$tmpp [ 0 ] = str_replace ( " % " , " " , $tmpp [ 0 ]);
$tables [] = mres ( str_replace ( " ( " , " " , $tmpp [ 0 ]));
$rule = str_replace ( $opt , $tmpp [ 0 ] . '.' . $tmpp [ 1 ], $rule );
2015-07-13 20:10:26 +02:00
}
}
$tables = array_keys ( array_flip ( $tables ));
2016-08-28 12:32:58 -05:00
if ( dbFetchCell ( 'SELECT 1 FROM information_schema.COLUMNS WHERE TABLE_NAME = ? && COLUMN_NAME = ?' , array ( $tables [ 0 ], 'device_id' )) != 1 ) {
2015-07-13 20:10:26 +02:00
//Our first table has no valid glue, append the 'devices' table to it!
array_unshift ( $tables , 'devices' );
}
$x = sizeof ( $tables ) - 1 ;
$i = 0 ;
$join = " " ;
2016-08-28 12:32:58 -05:00
while ( $i < $x ) {
if ( isset ( $tables [ $i + 1 ])) {
$gtmp = ResolveGlues ( array ( $tables [ $i + 1 ]), 'device_id' );
if ( $gtmp === false ) {
2015-11-30 19:13:32 +00:00
//Cannot resolve glue-chain. Rule is invalid.
return false ;
2015-07-13 20:10:26 +02:00
}
2015-11-30 19:13:32 +00:00
$last = " " ;
$qry = " " ;
2016-08-28 12:32:58 -05:00
foreach ( $gtmp as $glue ) {
if ( empty ( $last )) {
list ( $tmp , $last ) = explode ( '.' , $glue );
2015-11-30 19:13:32 +00:00
$qry .= $glue . ' = ' ;
2016-08-28 12:32:58 -05:00
} else {
list ( $tmp , $new ) = explode ( '.' , $glue );
2015-11-30 19:13:32 +00:00
$qry .= $tmp . '.' . $last . ' && ' . $tmp . '.' . $new . ' = ' ;
$last = $new ;
}
2016-08-28 12:32:58 -05:00
if ( ! in_array ( $tmp , $tables )) {
2015-11-30 19:13:32 +00:00
$tables [] = $tmp ;
2015-07-13 20:10:26 +02:00
}
}
2015-11-30 19:13:32 +00:00
$join .= " ( " . $qry . $tables [ 0 ] . " .device_id ) && " ;
2015-07-13 20:10:26 +02:00
}
$i ++ ;
}
2016-08-28 12:32:58 -05:00
$sql = " SELECT * FROM " . implode ( " , " , $tables ) . " WHERE ( " . $join . " " . str_replace ( " ( " , " " , $tables [ 0 ]) . " .device_id = ?) && ( " . str_replace ( array ( " % " , " @ " , " !~ " , " ~ " ), array ( " " , " .* " , " NOT REGEXP " , " REGEXP " ), $rule ) . " ) " ;
2015-07-13 20:10:26 +02:00
return $sql ;
2012-05-16 16:26:19 +00:00
}
2015-04-24 19:05:55 +00:00
/**
* Process Macros
* @ param string $rule Rule to process
2015-05-07 14:09:41 +00:00
* @ param int $x Recursion - Anchor
2015-04-25 11:10:37 +00:00
* @ return string | boolean
2015-04-24 19:05:55 +00:00
*/
2016-08-28 12:32:58 -05:00
function RunMacros ( $rule , $x = 1 )
{
2015-07-13 20:10:26 +02:00
global $config ;
krsort ( $config [ 'alert' ][ 'macros' ][ 'rule' ]);
2016-08-28 12:32:58 -05:00
foreach ( $config [ 'alert' ][ 'macros' ][ 'rule' ] as $macro => $value ) {
if ( ! strstr ( $macro , " " )) {
2018-03-23 09:39:50 -05:00
$rule = str_replace ( '%macros.' . $macro , '(' . $value . ')' , $rule );
2015-07-13 20:10:26 +02:00
}
}
2018-03-23 09:39:50 -05:00
if ( strstr ( $rule , " %macros. " )) {
2016-08-28 12:32:58 -05:00
if ( ++ $x < 30 ) {
$rule = RunMacros ( $rule , $x );
} else {
2015-07-13 20:10:26 +02:00
return false ;
}
}
return $rule ;
2015-04-24 19:05:55 +00:00
}
2015-04-03 18:22:29 +00:00
/**
* Get Alert - Rules for Devices
2018-03-15 11:03:45 -05:00
* @ param int $device_id Device - ID
2015-04-03 18:22:29 +00:00
* @ return array
*/
2018-03-15 11:03:45 -05:00
function GetRules ( $device_id )
2016-08-28 12:32:58 -05:00
{
2018-03-15 11:03:45 -05:00
$query = " SELECT DISTINCT a.* FROM alert_rules a
LEFT JOIN alert_device_map d ON a . id = d . rule_id
LEFT JOIN alert_group_map g ON a . id = g . rule_id
LEFT JOIN device_group_device dg ON g . group_id = dg . device_group_id
WHERE a . disabled = 0 AND (( d . device_id IS NULL AND g . group_id IS NULL ) OR d . device_id = ? OR dg . device_id = ? ) " ;
2018-03-14 20:25:19 +00:00
2018-03-15 11:03:45 -05:00
$params = [ $device_id , $device_id ];
2018-03-14 20:25:19 +00:00
return dbFetchRows ( $query , $params );
2015-04-03 18:22:29 +00:00
}
2012-05-16 16:26:19 +00:00
2015-04-20 16:39:55 +00:00
/**
* Check if device is under maintenance
2019-01-03 16:42:12 -06:00
* @ param int $device_id Device - ID
* @ return bool
2015-04-20 16:39:55 +00:00
*/
2019-01-03 16:42:12 -06:00
function IsMaintenance ( $device_id )
2016-08-28 12:32:58 -05:00
{
2019-01-03 16:42:12 -06:00
return \App\Models\Device :: find ( $device_id ) -> isUnderMaintenance ();
2015-04-20 16:39:55 +00:00
}
2012-05-16 16:26:19 +00:00
/**
2014-12-15 11:10:26 +00:00
* Run all rules for a device
2018-03-15 11:03:45 -05:00
* @ param int $device_id Device - ID
2014-12-15 11:10:26 +00:00
* @ return void
*/
2018-03-15 11:03:45 -05:00
function RunRules ( $device_id )
2016-08-28 12:32:58 -05:00
{
2018-03-15 11:03:45 -05:00
if ( IsMaintenance ( $device_id ) > 0 ) {
2015-07-13 20:10:26 +02:00
echo " Under Maintenance, Skipping alerts. \r \n " ;
return false ;
}
2018-03-15 11:03:45 -05:00
foreach ( GetRules ( $device_id ) as $rule ) {
2016-09-25 16:01:58 +01:00
c_echo ( 'Rule %p#' . $rule [ 'id' ] . ' (' . $rule [ 'name' ] . '):%n ' );
2017-03-23 08:23:01 +00:00
$extra = json_decode ( $rule [ 'extra' ], true );
if ( isset ( $extra [ 'invert' ])) {
$inv = ( bool ) $extra [ 'invert' ];
2016-08-28 12:32:58 -05:00
} else {
2015-07-13 20:10:26 +02:00
$inv = false ;
}
2016-09-25 16:01:58 +01:00
d_echo ( PHP_EOL );
2016-10-15 00:29:55 +01:00
if ( empty ( $rule [ 'query' ])) {
2018-03-14 20:25:19 +00:00
$rule [ 'query' ] = GenSQL ( $rule [ 'rule' ], $rule [ 'builder' ]);
2016-10-15 00:29:55 +01:00
}
$sql = $rule [ 'query' ];
2018-03-15 11:03:45 -05:00
$qry = dbFetchRows ( $sql , array ( $device_id ));
2016-12-30 00:50:22 +01:00
$cnt = count ( $qry );
for ( $i = 0 ; $i < $cnt ; $i ++ ) {
if ( isset ( $qry [ $i ][ 'ip' ])) {
$qry [ $i ][ 'ip' ] = inet6_ntop ( $qry [ $i ][ 'ip' ]);
}
2016-02-27 11:51:31 +00:00
}
2015-07-13 20:10:26 +02:00
$s = sizeof ( $qry );
2016-08-28 12:32:58 -05:00
if ( $s == 0 && $inv === false ) {
2015-07-13 20:10:26 +02:00
$doalert = false ;
2016-08-28 12:32:58 -05:00
} elseif ( $s > 0 && $inv === false ) {
2015-07-13 20:10:26 +02:00
$doalert = true ;
2016-08-28 12:32:58 -05:00
} elseif ( $s == 0 && $inv === true ) {
2015-07-13 20:10:26 +02:00
$doalert = true ;
2016-08-28 12:32:58 -05:00
} else { //( $s > 0 && $inv == false ) {
2015-07-13 20:10:26 +02:00
$doalert = false ;
}
2018-08-07 01:49:49 -05:00
$current_state = dbFetchCell ( " SELECT state FROM alerts WHERE rule_id = ? AND device_id = ? ORDER BY id DESC LIMIT 1 " , [ $rule [ 'id' ], $device_id ]);
2016-08-28 12:32:58 -05:00
if ( $doalert ) {
2018-08-07 01:49:49 -05:00
if ( $current_state == 2 ) {
2016-09-25 16:01:58 +01:00
c_echo ( 'Status: %ySKIP' );
2018-08-07 01:49:49 -05:00
} elseif ( $current_state >= 1 ) {
2017-04-18 02:08:52 +01:00
c_echo ( 'Status: %bNOCHG' );
2017-03-22 09:02:47 +00:00
// NOCHG here doesn't mean no change full stop. It means no change to the alert state
// So we update the details column with any fresh changes to the alert output we might have.
2018-03-15 11:03:45 -05:00
$alert_log = dbFetchRow ( 'SELECT alert_log.id, alert_log.details FROM alert_log,alert_rules WHERE alert_log.rule_id = alert_rules.id && alert_log.device_id = ? && alert_log.rule_id = ? && alert_rules.disabled = 0 ORDER BY alert_log.id DESC LIMIT 1' , array ( $device_id , $rule [ 'id' ]));
2018-08-29 15:34:23 +01:00
$details = [];
if ( ! empty ( $alert_log [ 'details' ])) {
$details = json_decode ( gzuncompress ( $alert_log [ 'details' ]), true );
}
2017-04-18 02:08:52 +01:00
$details [ 'contacts' ] = GetContacts ( $qry );
$details [ 'rule' ] = $qry ;
$details = gzcompress ( json_encode ( $details ), 9 );
dbUpdate ( array ( 'details' => $details ), 'alert_log' , 'id = ?' , array ( $alert_log [ 'id' ]));
2016-08-28 12:32:58 -05:00
} else {
2017-04-18 02:08:52 +01:00
$extra = gzcompress ( json_encode ( array ( 'contacts' => GetContacts ( $qry ), 'rule' => $qry )), 9 );
2018-08-07 01:49:49 -05:00
if ( dbInsert ([ 'state' => 1 , 'device_id' => $device_id , 'rule_id' => $rule [ 'id' ], 'details' => $extra ], 'alert_log' )) {
if ( is_null ( $current_state )) {
2018-03-15 11:03:45 -05:00
dbInsert ( array ( 'state' => 1 , 'device_id' => $device_id , 'rule_id' => $rule [ 'id' ], 'open' => 1 , 'alerted' => 0 ), 'alerts' );
2018-08-07 01:49:49 -05:00
} else {
dbUpdate ([ 'state' => 1 , 'open' => 1 ], 'alerts' , 'device_id = ? && rule_id = ?' , [ $device_id , $rule [ 'id' ]]);
2015-07-13 20:10:26 +02:00
}
2016-09-25 16:01:58 +01:00
c_echo ( PHP_EOL . 'Status: %rALERT' );
2015-07-13 20:10:26 +02:00
}
}
2016-08-28 12:32:58 -05:00
} else {
2018-08-07 01:49:49 -05:00
if ( ! is_null ( $current_state ) && $current_state == 0 ) {
2016-09-25 16:01:58 +01:00
c_echo ( 'Status: %bNOCHG' );
2016-08-28 12:32:58 -05:00
} else {
2018-08-07 01:49:49 -05:00
if ( dbInsert ([ 'state' => 0 , 'device_id' => $device_id , 'rule_id' => $rule [ 'id' ]], 'alert_log' )) {
if ( is_null ( $current_state )) {
dbInsert ([ 'state' => 0 , 'device_id' => $device_id , 'rule_id' => $rule [ 'id' ], 'open' => 1 , 'alerted' => 0 ], 'alerts' );
} else {
dbUpdate ([ 'state' => 0 , 'open' => 1 , 'note' => '' ], 'alerts' , 'device_id = ? && rule_id = ?' , [ $device_id , $rule [ 'id' ]]);
2015-07-13 20:10:26 +02:00
}
2018-08-07 01:49:49 -05:00
2016-09-25 16:01:58 +01:00
c_echo ( PHP_EOL . 'Status: %gOK' );
2015-07-13 20:10:26 +02:00
}
}
}
2016-09-25 16:01:58 +01:00
c_echo ( '%n' . PHP_EOL );
2015-07-13 20:10:26 +02:00
}
2012-05-16 16:26:19 +00:00
}
/**
2014-12-15 11:10:26 +00:00
* Find contacts for alert
* @ param array $results Rule - Result
* @ return array
*/
2016-08-28 12:32:58 -05:00
function GetContacts ( $results )
{
2019-02-15 13:58:59 +00:00
global $config ;
2017-12-01 05:27:04 +00:00
2019-02-15 13:58:59 +00:00
if ( empty ( $results )) {
return [];
2015-07-13 20:10:26 +02:00
}
2019-02-15 13:58:59 +00:00
if ( Config :: get ( 'alert.default_only' ) === true || Config :: get ( 'alerts.email.default_only' ) === true ) {
$email = Config :: get ( 'alert.default_mail' , Config :: get ( 'alerts.email.default' ));
return $email ? [ $email => '' ] : [];
2015-07-13 20:10:26 +02:00
}
2018-09-11 07:51:35 -05:00
$users = LegacyAuth :: get () -> getUserlist ();
2015-07-13 20:10:26 +02:00
$contacts = array ();
$uids = array ();
2016-08-28 12:32:58 -05:00
foreach ( $results as $result ) {
$tmp = null ;
if ( is_numeric ( $result [ " bill_id " ])) {
$tmpa = dbFetchRows ( " SELECT user_id FROM bill_perms WHERE bill_id = ? " , array ( $result [ " bill_id " ]));
foreach ( $tmpa as $tmp ) {
2015-07-13 20:10:26 +02:00
$uids [ $tmp [ 'user_id' ]] = $tmp [ 'user_id' ];
}
}
2016-08-28 12:32:58 -05:00
if ( is_numeric ( $result [ " port_id " ])) {
2018-09-05 07:34:50 -05:00
$tmpa = dbFetchRows ( " SELECT user_id FROM ports_perms WHERE port_id = ? " , array ( $result [ " port_id " ]));
2016-08-28 12:32:58 -05:00
foreach ( $tmpa as $tmp ) {
2015-07-13 20:10:26 +02:00
$uids [ $tmp [ 'user_id' ]] = $tmp [ 'user_id' ];
}
}
2016-08-28 12:32:58 -05:00
if ( is_numeric ( $result [ " device_id " ])) {
if ( $config [ 'alert' ][ 'syscontact' ] == true ) {
2018-08-07 01:49:49 -05:00
if ( dbFetchCell ( " SELECT attrib_value FROM devices_attribs WHERE attrib_type = 'override_sysContact_bool' AND device_id = ? " , [ $result [ " device_id " ]])) {
2016-08-28 12:32:58 -05:00
$tmpa = dbFetchCell ( " SELECT attrib_value FROM devices_attribs WHERE attrib_type = 'override_sysContact_string' AND device_id = ? " , array ( $result [ " device_id " ]));
} else {
$tmpa = dbFetchCell ( " SELECT sysContact FROM devices WHERE device_id = ? " , array ( $result [ " device_id " ]));
2015-07-13 20:10:26 +02:00
}
2016-10-14 02:14:02 +01:00
if ( ! empty ( $tmpa )) {
2017-12-18 15:03:33 +00:00
$contacts [ $tmpa ] = '' ;
2016-10-14 02:14:02 +01:00
}
2015-07-13 20:10:26 +02:00
}
2018-09-05 07:34:50 -05:00
$tmpa = dbFetchRows ( " SELECT user_id FROM devices_perms WHERE device_id = ? " , array ( $result [ " device_id " ]));
2016-08-28 12:32:58 -05:00
foreach ( $tmpa as $tmp ) {
2015-07-13 20:10:26 +02:00
$uids [ $tmp [ 'user_id' ]] = $tmp [ 'user_id' ];
}
}
}
2016-08-28 12:32:58 -05:00
foreach ( $users as $user ) {
if ( empty ( $user [ 'email' ])) {
2017-03-29 08:22:02 -05:00
continue ; // no email, skip this user
}
if ( empty ( $user [ 'realname' ])) {
2015-07-13 20:10:26 +02:00
$user [ 'realname' ] = $user [ 'username' ];
}
2017-03-29 08:22:02 -05:00
if ( empty ( $user [ 'level' ])) {
2018-09-11 07:51:35 -05:00
$user [ 'level' ] = LegacyAuth :: get () -> getUserlevel ( $user [ 'username' ]);
2017-03-29 08:22:02 -05:00
}
2017-05-15 23:35:26 +01:00
if ( $config [ 'alert' ][ 'globals' ] && ( $user [ 'level' ] >= 5 && $user [ 'level' ] < 10 )) {
2015-07-13 20:10:26 +02:00
$contacts [ $user [ 'email' ]] = $user [ 'realname' ];
2017-05-15 23:35:26 +01:00
} elseif ( $config [ 'alert' ][ 'admins' ] && $user [ 'level' ] == 10 ) {
2015-07-13 20:10:26 +02:00
$contacts [ $user [ 'email' ]] = $user [ 'realname' ];
2017-05-15 23:35:26 +01:00
} elseif ( $config [ 'alert' ][ 'users' ] == true && in_array ( $user [ 'user_id' ], $uids )) {
2015-07-13 20:10:26 +02:00
$contacts [ $user [ 'email' ]] = $user [ 'realname' ];
}
}
2016-07-26 22:29:04 +01:00
$tmp_contacts = array ();
foreach ( $contacts as $email => $name ) {
if ( strstr ( $email , ',' )) {
2017-03-17 16:29:23 -05:00
$split_contacts = preg_split ( '/[,\s]+/' , $email );
2016-07-26 22:29:04 +01:00
foreach ( $split_contacts as $split_email ) {
2016-08-28 12:32:58 -05:00
if ( ! empty ( $split_email )) {
2016-07-28 20:28:23 +01:00
$tmp_contacts [ $split_email ] = $name ;
}
2016-07-26 22:29:04 +01:00
}
} else {
$tmp_contacts [ $email ] = $name ;
}
}
2017-12-01 05:27:04 +00:00
if ( ! empty ( $tmp_contacts )) {
// Validate contacts so we can fall back to default if configured.
$mail = new PHPMailer ();
foreach ( $tmp_contacts as $tmp_email => $tmp_name ) {
if ( $mail -> validateAddress ( $tmp_email ) != true ) {
unset ( $tmp_contacts [ $tmp_email ]);
}
}
}
2018-02-05 09:25:24 +01:00
# Copy all email alerts to default contact if configured.
if ( ! isset ( $tmp_contacts [ $config [ 'alert' ][ 'default_mail' ]]) && ( $config [ 'alert' ][ 'default_copy' ])) {
$tmp_contacts [ $config [ 'alert' ][ 'default_mail' ]] = '' ;
}
2017-03-14 18:22:43 -05:00
# Send email to default contact if no other contact found
if (( count ( $tmp_contacts ) == 0 ) && ( $config [ 'alert' ][ 'default_if_none' ]) && ( ! empty ( $config [ 'alert' ][ 'default_mail' ]))) {
2017-12-18 15:03:33 +00:00
$tmp_contacts [ $config [ 'alert' ][ 'default_mail' ]] = '' ;
2017-03-14 18:22:43 -05:00
}
2016-07-26 22:29:04 +01:00
return $tmp_contacts ;
2012-05-16 16:26:19 +00:00
}
2017-05-13 12:46:08 +01:00
/**
* Populate variables
* @ param string $txt Text with variables
* @ param boolean $wrap Wrap variable for text - usage ( default : true )
* @ return string
*/
function populate ( $txt , $wrap = true )
{
preg_match_all ( '/%([\w\.]+)/' , $txt , $m );
foreach ( $m [ 1 ] as $tmp ) {
$orig = $tmp ;
$rep = false ;
if ( $tmp == 'key' || $tmp == 'value' ) {
$rep = '$' . $tmp ;
} else {
if ( strstr ( $tmp , '.' )) {
$tmp = explode ( '.' , $tmp , 2 );
$pre = '$' . $tmp [ 0 ];
$tmp = $tmp [ 1 ];
} else {
$pre = '$obj' ;
}
$rep = $pre . " [' " . str_replace ( '.' , " '][' " , $tmp ) . " '] " ;
if ( $wrap ) {
$rep = '{' . $rep . '}' ;
}
}
$txt = str_replace ( '%' . $orig , $rep , $txt );
} //end foreach
return $txt ;
} //end populate()
/**
* Describe Alert
* @ param array $alert Alert - Result from DB
* @ return array | boolean
*/
function DescribeAlert ( $alert )
{
$obj = array ();
$i = 0 ;
2018-11-29 13:04:11 -06:00
$device = dbFetchRow ( 'SELECT hostname, sysName, sysDescr, sysContact, os, type, ip, hardware, version, purpose, notes, uptime, status, status_reason, locations.location FROM devices LEFT JOIN locations ON locations.id = devices.location_id WHERE device_id = ?' , array ( $alert [ 'device_id' ]));
2018-05-16 02:30:59 +01:00
$attribs = get_dev_attribs ( $alert [ 'device_id' ]);
2018-07-14 22:15:43 +01:00
2018-11-19 15:58:59 +00:00
$obj [ 'hostname' ] = $device [ 'hostname' ];
$obj [ 'sysName' ] = $device [ 'sysName' ];
$obj [ 'sysDescr' ] = $device [ 'sysDescr' ];
$obj [ 'sysContact' ] = $device [ 'sysContact' ];
$obj [ 'os' ] = $device [ 'os' ];
$obj [ 'type' ] = $device [ 'type' ];
$obj [ 'ip' ] = inet6_ntop ( $device [ 'ip' ]);
$obj [ 'hardware' ] = $device [ 'hardware' ];
$obj [ 'version' ] = $device [ 'version' ];
$obj [ 'location' ] = $device [ 'location' ];
$obj [ 'uptime' ] = $device [ 'uptime' ];
2019-03-18 03:09:58 +01:00
$obj [ 'uptime_short' ] = Time :: formatInterval ( $device [ 'uptime' ], 'short' );
$obj [ 'uptime_long' ] = Time :: formatInterval ( $device [ 'uptime' ]);
2018-11-19 15:58:59 +00:00
$obj [ 'description' ] = $device [ 'purpose' ];
$obj [ 'notes' ] = $device [ 'notes' ];
$obj [ 'alert_notes' ] = $alert [ 'note' ];
$obj [ 'device_id' ] = $alert [ 'device_id' ];
$obj [ 'rule_id' ] = $alert [ 'rule_id' ];
$obj [ 'status' ] = $device [ 'status' ];
$obj [ 'status_reason' ] = $device [ 'status_reason' ];
2018-05-16 02:30:59 +01:00
if ( can_ping_device ( $attribs )) {
2018-11-19 15:58:59 +00:00
$ping_stats = DevicePerf :: where ( 'device_id' , $alert [ 'device_id' ]) -> latest ( 'timestamp' ) -> first ();
$obj [ 'ping_timestamp' ] = $ping_stats -> template ;
$obj [ 'ping_loss' ] = $ping_stats -> loss ;
$obj [ 'ping_min' ] = $ping_stats -> min ;
$obj [ 'ping_max' ] = $ping_stats -> max ;
$obj [ 'ping_avg' ] = $ping_stats -> avg ;
$obj [ 'debug' ] = json_decode ( $ping_stats -> debug , true );
2018-05-16 02:30:59 +01:00
}
2017-05-13 12:46:08 +01:00
$extra = $alert [ 'details' ];
2018-07-14 22:15:43 +01:00
$tpl = new Template ;
$template = $tpl -> getTemplate ( $obj );
2017-05-13 12:46:08 +01:00
if ( $alert [ 'state' ] >= 1 ) {
2018-07-14 22:15:43 +01:00
$obj [ 'title' ] = $template -> title ? : 'Alert for device ' . $device [ 'hostname' ] . ' - ' . ( $alert [ 'name' ] ? $alert [ 'name' ] : $alert [ 'rule' ]);
2017-05-13 12:46:08 +01:00
if ( $alert [ 'state' ] == 2 ) {
$obj [ 'title' ] .= ' got acknowledged' ;
} elseif ( $alert [ 'state' ] == 3 ) {
$obj [ 'title' ] .= ' got worse' ;
} elseif ( $alert [ 'state' ] == 4 ) {
$obj [ 'title' ] .= ' got better' ;
}
foreach ( $extra [ 'rule' ] as $incident ) {
$i ++ ;
$obj [ 'faults' ][ $i ] = $incident ;
2018-07-14 22:15:43 +01:00
$obj [ 'faults' ][ $i ][ 'string' ] = null ;
2017-05-13 12:46:08 +01:00
foreach ( $incident as $k => $v ) {
if ( ! empty ( $v ) && $k != 'device_id' && ( stristr ( $k , 'id' ) || stristr ( $k , 'desc' ) || stristr ( $k , 'msg' )) && substr_count ( $k , '_' ) <= 1 ) {
2018-07-14 22:15:43 +01:00
$obj [ 'faults' ][ $i ][ 'string' ] .= $k . ' = ' . $v . '; ' ;
2017-05-13 12:46:08 +01:00
}
}
}
$obj [ 'elapsed' ] = TimeFormat ( time () - strtotime ( $alert [ 'time_logged' ]));
if ( ! empty ( $extra [ 'diff' ])) {
$obj [ 'diff' ] = $extra [ 'diff' ];
}
} elseif ( $alert [ 'state' ] == 0 ) {
2018-03-22 17:38:16 +00:00
// Alert is now cleared
2017-05-13 12:46:08 +01:00
$id = dbFetchRow ( 'SELECT alert_log.id,alert_log.time_logged,alert_log.details FROM alert_log WHERE alert_log.state != 2 && alert_log.state != 0 && alert_log.rule_id = ? && alert_log.device_id = ? && alert_log.id < ? ORDER BY id DESC LIMIT 1' , array ( $alert [ 'rule_id' ], $alert [ 'device_id' ], $alert [ 'id' ]));
if ( empty ( $id [ 'id' ])) {
return false ;
}
2018-08-29 15:34:23 +01:00
$extra = [];
if ( ! empty ( $id [ 'details' ])) {
$extra = json_decode ( gzuncompress ( $id [ 'details' ]), true );
}
2018-03-22 17:38:16 +00:00
// Reset count to 0 so alerts will continue
$extra [ 'count' ] = 0 ;
dbUpdate ( array ( 'details' => gzcompress ( json_encode ( $id [ 'details' ]), 9 )), 'alert_log' , 'id = ?' , array ( $alert [ 'id' ]));
2018-07-14 22:15:43 +01:00
$obj [ 'title' ] = $template -> title_rec ? : 'Device ' . $device [ 'hostname' ] . ' recovered from ' . ( $alert [ 'name' ] ? $alert [ 'name' ] : $alert [ 'rule' ]);
2017-05-13 12:46:08 +01:00
$obj [ 'elapsed' ] = TimeFormat ( strtotime ( $alert [ 'time_logged' ]) - strtotime ( $id [ 'time_logged' ]));
$obj [ 'id' ] = $id [ 'id' ];
foreach ( $extra [ 'rule' ] as $incident ) {
$i ++ ;
$obj [ 'faults' ][ $i ] = $incident ;
foreach ( $incident as $k => $v ) {
if ( ! empty ( $v ) && $k != 'device_id' && ( stristr ( $k , 'id' ) || stristr ( $k , 'desc' ) || stristr ( $k , 'msg' )) && substr_count ( $k , '_' ) <= 1 ) {
$obj [ 'faults' ][ $i ][ 'string' ] .= $k . ' => ' . $v . '; ' ;
}
}
}
} else {
return 'Unknown State' ;
} //end if
2018-07-14 22:15:43 +01:00
$obj [ 'builder' ] = $alert [ 'builder' ];
2017-05-13 12:46:08 +01:00
$obj [ 'uid' ] = $alert [ 'id' ];
2018-03-13 17:19:57 -05:00
$obj [ 'alert_id' ] = $alert [ 'alert_id' ];
2017-05-13 12:46:08 +01:00
$obj [ 'severity' ] = $alert [ 'severity' ];
$obj [ 'rule' ] = $alert [ 'rule' ];
$obj [ 'name' ] = $alert [ 'name' ];
$obj [ 'timestamp' ] = $alert [ 'time_logged' ];
$obj [ 'contacts' ] = $extra [ 'contacts' ];
$obj [ 'state' ] = $alert [ 'state' ];
2018-07-14 22:15:43 +01:00
$obj [ 'template' ] = $template ;
2017-05-13 12:46:08 +01:00
return $obj ;
} //end DescribeAlert()
/**
* Format Elapsed Time
* @ param integer $secs Seconds elapsed
* @ return string
*/
function TimeFormat ( $secs )
{
$bit = array (
'y' => $secs / 31556926 % 12 ,
'w' => $secs / 604800 % 52 ,
'd' => $secs / 86400 % 7 ,
'h' => $secs / 3600 % 24 ,
'm' => $secs / 60 % 60 ,
's' => $secs % 60 ,
);
$ret = array ();
foreach ( $bit as $k => $v ) {
if ( $v > 0 ) {
$ret [] = $v . $k ;
}
}
if ( empty ( $ret )) {
return 'none' ;
}
return join ( ' ' , $ret );
} //end TimeFormat()
function ClearStaleAlerts ()
{
$sql = " SELECT `alerts`.`id` AS `alert_id`, `devices`.`hostname` AS `hostname` FROM `alerts` LEFT JOIN `devices` ON `alerts`.`device_id`=`devices`.`device_id` RIGHT JOIN `alert_rules` ON `alerts`.`rule_id`=`alert_rules`.`id` WHERE `alerts`.`state`!=0 AND `devices`.`hostname` IS NULL " ;
foreach ( dbFetchRows ( $sql ) as $alert ) {
if ( empty ( $alert [ 'hostname' ]) && isset ( $alert [ 'alert_id' ])) {
dbDelete ( 'alerts' , '`id` = ?' , array ( $alert [ 'alert_id' ]));
echo " Stale-alert: # { $alert [ 'alert_id' ] } " . PHP_EOL ;
}
}
}
/**
* Re - Validate Rule - Mappings
2018-03-15 11:03:45 -05:00
* @ param integer $device_id Device - ID
2017-05-13 12:46:08 +01:00
* @ param integer $rule Rule - ID
* @ return boolean
*/
2018-03-15 11:03:45 -05:00
function IsRuleValid ( $device_id , $rule )
2017-05-13 12:46:08 +01:00
{
global $rulescache ;
2018-03-15 11:03:45 -05:00
if ( empty ( $rulescache [ $device_id ]) || ! isset ( $rulescache [ $device_id ])) {
foreach ( GetRules ( $device_id ) as $chk ) {
$rulescache [ $device_id ][ $chk [ 'id' ]] = true ;
2017-05-13 12:46:08 +01:00
}
}
2018-03-15 11:03:45 -05:00
if ( $rulescache [ $device_id ][ $rule ] === true ) {
2017-05-13 12:46:08 +01:00
return true ;
}
return false ;
} //end IsRuleValid()
/**
* Issue Alert - Object
* @ param array $alert
* @ return boolean
*/
function IssueAlert ( $alert )
{
global $config ;
if ( dbFetchCell ( 'SELECT attrib_value FROM devices_attribs WHERE attrib_type = "disable_notify" && device_id = ?' , array ( $alert [ 'device_id' ])) == '1' ) {
return true ;
}
if ( $config [ 'alert' ][ 'fixed-contacts' ] == false ) {
if ( empty ( $alert [ 'query' ])) {
2018-03-14 20:25:19 +00:00
$alert [ 'query' ] = GenSQL ( $alert [ 'rule' ], $alert [ 'builder' ]);
2017-05-13 12:46:08 +01:00
}
$sql = $alert [ 'query' ];
$qry = dbFetchRows ( $sql , array ( $alert [ 'device_id' ]));
$alert [ 'details' ][ 'contacts' ] = GetContacts ( $qry );
}
$obj = DescribeAlert ( $alert );
if ( is_array ( $obj )) {
2018-11-10 21:06:51 +00:00
echo 'Issuing Alert-UID #' . $alert [ 'id' ] . '/' . $alert [ 'state' ] . ':' . PHP_EOL ;
2018-08-29 15:44:29 +01:00
ExtTransports ( $obj );
2017-05-13 12:46:08 +01:00
echo " \r \n " ;
}
return true ;
} //end IssueAlert()
/**
* Issue ACK notification
* @ return void
*/
function RunAcks ()
{
2018-03-14 20:25:19 +00:00
2018-03-13 17:19:57 -05:00
foreach ( loadAlerts ( 'alerts.state = 2 && alerts.open = 1' ) as $alert ) {
2017-05-13 12:46:08 +01:00
IssueAlert ( $alert );
dbUpdate ( array ( 'open' => 0 ), 'alerts' , 'rule_id = ? && device_id = ?' , array ( $alert [ 'rule_id' ], $alert [ 'device_id' ]));
}
} //end RunAcks()
/**
* Run Follow - Up alerts
* @ return void
*/
function RunFollowUp ()
{
2018-09-19 23:38:01 +01:00
foreach ( loadAlerts ( 'alerts.state > 0 && alerts.open = 0' ) as $alert ) {
if ( $alert [ 'state' ] != 2 || ( $alert [ 'info' ][ 'until_clear' ] === false )) {
$rextra = json_decode ( $alert [ 'extra' ], true );
if ( $rextra [ 'invert' ]) {
continue ;
}
2017-05-13 12:46:08 +01:00
2018-09-19 23:38:01 +01:00
if ( empty ( $alert [ 'query' ])) {
$alert [ 'query' ] = GenSQL ( $alert [ 'rule' ], $alert [ 'builder' ]);
2017-05-13 12:46:08 +01:00
}
2018-09-19 23:38:01 +01:00
$chk = dbFetchRows ( $alert [ 'query' ], array ( $alert [ 'device_id' ]));
//make sure we can json_encode all the datas later
$cnt = count ( $chk );
for ( $i = 0 ; $i < $cnt ; $i ++ ) {
if ( isset ( $chk [ $i ][ 'ip' ])) {
$chk [ $i ][ 'ip' ] = inet6_ntop ( $chk [ $i ][ 'ip' ]);
}
}
$o = sizeof ( $alert [ 'details' ][ 'rule' ]);
$n = sizeof ( $chk );
$ret = 'Alert #' . $alert [ 'id' ];
$state = 0 ;
if ( $n > $o ) {
$ret .= ' Worsens' ;
$state = 3 ;
$alert [ 'details' ][ 'diff' ] = array_diff ( $chk , $alert [ 'details' ][ 'rule' ]);
} elseif ( $n < $o ) {
$ret .= ' Betters' ;
$state = 4 ;
$alert [ 'details' ][ 'diff' ] = array_diff ( $alert [ 'details' ][ 'rule' ], $chk );
2017-05-13 12:46:08 +01:00
}
2018-09-19 23:38:01 +01:00
if ( $state > 0 && $n > 0 ) {
$alert [ 'details' ][ 'rule' ] = $chk ;
if ( dbInsert ( array (
'state' => $state ,
'device_id' => $alert [ 'device_id' ],
'rule_id' => $alert [ 'rule_id' ],
'details' => gzcompress ( json_encode ( $alert [ 'details' ]), 9 )
), 'alert_log' )) {
dbUpdate ( array ( 'state' => $state , 'open' => 1 , 'alerted' => 1 ), 'alerts' , 'rule_id = ? && device_id = ?' , array ( $alert [ 'rule_id' ], $alert [ 'device_id' ]));
}
echo $ret . ' (' . $o . '/' . $n . " ) \r \n " ;
}
2017-05-13 12:46:08 +01:00
}
} //end foreach
} //end RunFollowUp()
2018-03-13 17:19:57 -05:00
function loadAlerts ( $where )
{
$alerts = [];
2018-09-19 23:38:01 +01:00
foreach ( dbFetchRows ( " SELECT alerts.id, alerts.device_id, alerts.rule_id, alerts.state, alerts.note, alerts.info FROM alerts WHERE $where " ) as $alert_status ) {
2018-03-13 17:19:57 -05:00
$alert = dbFetchRow (
2018-05-08 15:35:21 -05:00
'SELECT alert_log.id,alert_log.rule_id,alert_log.device_id,alert_log.state,alert_log.details,alert_log.time_logged,alert_rules.rule,alert_rules.severity,alert_rules.extra,alert_rules.name,alert_rules.builder FROM alert_log,alert_rules WHERE alert_log.rule_id = alert_rules.id && alert_log.device_id = ? && alert_log.rule_id = ? && alert_rules.disabled = 0 ORDER BY alert_log.id DESC LIMIT 1' ,
2018-03-13 17:19:57 -05:00
array ( $alert_status [ 'device_id' ], $alert_status [ 'rule_id' ])
);
if ( empty ( $alert [ 'rule_id' ]) || ! IsRuleValid ( $alert_status [ 'device_id' ], $alert_status [ 'rule_id' ])) {
echo 'Stale-Rule: #' . $alert_status [ 'rule_id' ] . '/' . $alert_status [ 'device_id' ] . " \r \n " ;
// Alert-Rule does not exist anymore, let's remove the alert-state.
dbDelete ( 'alerts' , 'rule_id = ? && device_id = ?' , [ $alert_status [ 'rule_id' ], $alert_status [ 'device_id' ]]);
} else {
$alert [ 'alert_id' ] = $alert_status [ 'id' ];
$alert [ 'state' ] = $alert_status [ 'state' ];
2018-08-27 15:02:36 -05:00
$alert [ 'note' ] = $alert_status [ 'note' ];
2018-08-29 15:34:23 +01:00
if ( ! empty ( $alert [ 'details' ])) {
$alert [ 'details' ] = json_decode ( gzuncompress ( $alert [ 'details' ]), true );
}
2018-09-19 23:38:01 +01:00
$alert [ 'info' ] = json_decode ( $alert_status [ 'info' ], true );
2018-03-13 17:19:57 -05:00
$alerts [] = $alert ;
}
}
return $alerts ;
}
2017-05-13 12:46:08 +01:00
/**
* Run all alerts
* @ return void
*/
function RunAlerts ()
{
global $config ;
2018-03-13 17:19:57 -05:00
foreach ( loadAlerts ( 'alerts.state != 2 && alerts.open = 1' ) as $alert ) {
2017-05-13 12:46:08 +01:00
$noiss = false ;
$noacc = false ;
$updet = false ;
$rextra = json_decode ( $alert [ 'extra' ], true );
2018-03-22 17:38:16 +00:00
if ( ! isset ( $rextra [ 'recovery' ])) {
// backwards compatibility check
$rextra [ 'recovery' ] = true ;
}
2017-05-13 12:46:08 +01:00
$chk = dbFetchRow ( 'SELECT alerts.alerted,devices.ignore,devices.disabled FROM alerts,devices WHERE alerts.device_id = ? && devices.device_id = alerts.device_id && alerts.rule_id = ?' , array ( $alert [ 'device_id' ], $alert [ 'rule_id' ]));
2018-03-14 20:25:19 +00:00
2017-05-13 12:46:08 +01:00
if ( $chk [ 'alerted' ] == $alert [ 'state' ]) {
$noiss = true ;
}
if ( ! empty ( $rextra [ 'count' ]) && empty ( $rextra [ 'interval' ])) {
// This check below is for compat-reasons
if ( ! empty ( $rextra [ 'delay' ])) {
if (( time () - strtotime ( $alert [ 'time_logged' ]) + $config [ 'alert' ][ 'tolerance_window' ]) < $rextra [ 'delay' ] || ( ! empty ( $alert [ 'details' ][ 'delay' ]) && ( time () - $alert [ 'details' ][ 'delay' ] + $config [ 'alert' ][ 'tolerance_window' ]) < $rextra [ 'delay' ])) {
continue ;
} else {
$alert [ 'details' ][ 'delay' ] = time ();
$updet = true ;
}
}
if ( $alert [ 'state' ] == 1 && ! empty ( $rextra [ 'count' ]) && ( $rextra [ 'count' ] == - 1 || $alert [ 'details' ][ 'count' ] ++ < $rextra [ 'count' ])) {
if ( $alert [ 'details' ][ 'count' ] < $rextra [ 'count' ]) {
$noacc = true ;
}
$updet = true ;
$noiss = false ;
}
} else {
// This is the new way
if ( ! empty ( $rextra [ 'delay' ]) && ( time () - strtotime ( $alert [ 'time_logged' ]) + $config [ 'alert' ][ 'tolerance_window' ]) < $rextra [ 'delay' ]) {
continue ;
}
if ( ! empty ( $rextra [ 'interval' ])) {
if ( ! empty ( $alert [ 'details' ][ 'interval' ]) && ( time () - $alert [ 'details' ][ 'interval' ] + $config [ 'alert' ][ 'tolerance_window' ]) < $rextra [ 'interval' ]) {
continue ;
} else {
$alert [ 'details' ][ 'interval' ] = time ();
$updet = true ;
}
}
2018-09-19 23:38:01 +01:00
if ( in_array ( $alert [ 'state' ], [ 1 , 3 , 4 ]) && ! empty ( $rextra [ 'count' ]) && ( $rextra [ 'count' ] == - 1 || $alert [ 'details' ][ 'count' ] ++ < $rextra [ 'count' ])) {
2017-05-13 12:46:08 +01:00
if ( $alert [ 'details' ][ 'count' ] < $rextra [ 'count' ]) {
$noacc = true ;
}
$updet = true ;
$noiss = false ;
}
} //end if
if ( $chk [ 'ignore' ] == 1 || $chk [ 'disabled' ] == 1 ) {
$noiss = true ;
$updet = false ;
$noacc = false ;
}
if ( IsMaintenance ( $alert [ 'device_id' ]) > 0 ) {
$noiss = true ;
$noacc = true ;
}
if ( $updet ) {
dbUpdate ( array ( 'details' => gzcompress ( json_encode ( $alert [ 'details' ]), 9 )), 'alert_log' , 'id = ?' , array ( $alert [ 'id' ]));
}
if ( ! empty ( $rextra [ 'mute' ])) {
echo 'Muted Alert-UID #' . $alert [ 'id' ] . " \r \n " ;
$noiss = true ;
}
2017-12-20 17:17:52 +03:00
if ( IsParentDown ( $alert [ 'device_id' ])) {
$noiss = true ;
log_event ( 'Skipped alerts because all parent devices are down' , $alert [ 'device_id' ], 'alert' , 1 );
}
2018-03-22 17:38:16 +00:00
if ( $alert [ 'state' ] == 0 && $rextra [ 'recovery' ] == false ) {
// Rule is set to not send a recovery alert
$noiss = true ;
}
2017-05-13 12:46:08 +01:00
if ( ! $noiss ) {
IssueAlert ( $alert );
dbUpdate ( array ( 'alerted' => $alert [ 'state' ]), 'alerts' , 'rule_id = ? && device_id = ?' , array ( $alert [ 'rule_id' ], $alert [ 'device_id' ]));
}
if ( ! $noacc ) {
dbUpdate ( array ( 'open' => 0 ), 'alerts' , 'rule_id = ? && device_id = ?' , array ( $alert [ 'rule_id' ], $alert [ 'device_id' ]));
}
} //end foreach
} //end RunAlerts()
/**
* Run external transports
* @ param array $obj Alert - Array
* @ return void
*/
function ExtTransports ( $obj )
{
2018-07-14 22:15:43 +01:00
$type = new Template ;
2018-08-03 14:56:22 -05:00
2018-07-21 13:34:59 -06:00
// If alert transport mapping exists, override the default transports
$transport_maps = AlertUtil :: getAlertTransports ( $obj [ 'alert_id' ]);
if ( ! $transport_maps ) {
$transport_maps = AlertUtil :: getDefaultAlertTransports ();
2019-02-15 13:58:59 +00:00
}
// alerting for default contacts, etc
if ( Config :: get ( 'alert.transports.mail' ) === true && ! empty ( $obj [ 'contacts' ])) {
$transport_maps [] = [
'transport_id' => null ,
'transport_type' => 'mail' ,
'opts' => $obj ,
];
2018-07-21 13:34:59 -06:00
}
foreach ( $transport_maps as $item ) {
$class = 'LibreNMS\\Alert\\Transport\\' . ucfirst ( $item [ 'transport_type' ]);
if ( class_exists ( $class )) {
2018-11-10 21:06:51 +00:00
//FIXME remove Deprecated transport
2019-02-15 13:58:59 +00:00
$transport_title = " Transport { $item [ 'transport_type' ] } " ;
2018-07-21 13:34:59 -06:00
$obj [ 'transport' ] = $item [ 'transport_type' ];
2018-11-05 07:56:16 +00:00
$obj [ 'transport_name' ] = $item [ 'transport_name' ];
2018-07-21 13:34:59 -06:00
$obj [ 'alert' ] = new AlertData ( $obj );
2018-07-14 22:15:43 +01:00
$obj [ 'title' ] = $type -> getTitle ( $obj );
$obj [ 'alert' ][ 'title' ] = $obj [ 'title' ];
$obj [ 'msg' ] = $type -> getBody ( $obj );
2018-11-10 21:06:51 +00:00
c_echo ( " :: $transport_title => " );
2018-07-21 13:34:59 -06:00
$instance = new $class ( $item [ 'transport_id' ]);
$tmp = $instance -> deliverAlert ( $obj , $item [ 'opts' ]);
AlertLog ( $tmp , $obj , $obj [ 'transport' ]);
unset ( $instance );
2018-11-10 21:06:51 +00:00
echo PHP_EOL ;
2017-05-13 12:46:08 +01:00
}
}
2018-07-21 13:34:59 -06:00
if ( count ( $transport_maps ) === 0 ) {
echo 'No configured transports' ;
}
2017-05-13 12:46:08 +01:00
} //end ExtTransports()
2017-12-20 17:17:52 +03:00
2018-07-21 13:34:59 -06:00
// Log alert event
function AlertLog ( $result , $obj , $transport )
{
$prefix = [
0 => " recovery " ,
1 => $obj [ 'severity' ] . " alert " ,
2 => " acknowledgment "
];
$prefix [ 3 ] = & $prefix [ 0 ];
$prefix [ 4 ] = & $prefix [ 0 ];
if ( $result === true ) {
echo 'OK' ;
log_event ( 'Issued ' . $prefix [ $obj [ 'state' ]] . " for rule ' " . $obj [ 'name' ] . " ' to transport ' " . $transport . " ' " , $obj [ 'device_id' ], 'alert' , 1 );
} elseif ( $result === false ) {
echo 'ERROR' ;
log_event ( 'Could not issue ' . $prefix [ $obj [ 'state' ]] . " for rule ' " . $obj [ 'name' ] . " ' to transport ' " . $transport . " ' " , $obj [ 'device_id' ], null , 5 );
} else {
echo " ERROR: $result\r\n " ;
log_event ( 'Could not issue ' . $prefix [ $obj [ 'state' ]] . " for rule ' " . $obj [ 'name' ] . " ' to transport ' " . $transport . " ' Error: " . $result , $obj [ 'device_id' ], 'error' , 5 );
}
return ;
} //end AlertLog()
2017-12-20 17:17:52 +03:00
/**
* Check if a device ' s all parent are down
* Returns true if all parents are down
* @ param int $device Device - ID
* @ return bool
*/
function IsParentDown ( $device )
{
$parent_count = dbFetchCell ( " SELECT count(*) from `device_relationships` WHERE `child_device_id` = ? " , array ( $device ));
if ( ! $parent_count ) {
return false ;
}
$down_parent_count = dbFetchCell ( " SELECT count(*) from devices as d LEFT JOIN devices_attribs as a ON d.device_id=a.device_id LEFT JOIN device_relationships as r ON d.device_id=r.parent_device_id WHERE d.status=0 AND d.ignore=0 AND d.disabled=0 AND r.child_device_id=? AND (d.status_reason='icmp' OR (a.attrib_type='override_icmp_disable' AND a.attrib_value=true)) " , array ( $device ));
if ( $down_parent_count == $parent_count ) {
return true ;
}
return false ;
} //end IsParentDown()