mirror of
				https://github.com/librenms/librenms.git
				synced 2024-10-07 16:52:45 +00:00 
			
		
		
		
	Component Update - Status
- Align the component status field with the Nagios standard 0=ok, 1=warning, 2=critical - Modify existing modules to report these status' (Cisco-OTV) - Add/Modify Alerting Macros to use these status' - Add the a component status widget - update edit page to report these status'
This commit is contained in:
		@@ -23,7 +23,7 @@ Table of Content:
 | 
			
		||||
The Component extension provides a generic database storage mechanism for discovery and poller modules.
 | 
			
		||||
The Driver behind this extension was to provide the features of ports, in a generic manner to discovery/poller modules.
 | 
			
		||||
 | 
			
		||||
It provides a status (Normal or Alert), the ability to Disable (do not poll), or Ignore (do not Alert).
 | 
			
		||||
It provides a status (Nagios convention), the ability to Disable (do not poll), or Ignore (do not Alert).
 | 
			
		||||
 | 
			
		||||
# <a name="database">Database Structure</a>
 | 
			
		||||
 | 
			
		||||
@@ -282,18 +282,23 @@ Please see the [API-Docs](http://docs.librenms.org/API/API-Docs/#api-route-25) f
 | 
			
		||||
## <a name="alert">Alerting</a>
 | 
			
		||||
 | 
			
		||||
It is intended that discovery/poller modules will detect the status of a component during the polling cycle.
 | 
			
		||||
If you are creating a poller module which can detect a fault condition simply set STATUS to 0 and ERROR to a message that indicates the problem.
 | 
			
		||||
Status is logged using the Nagios convention for status codes, where:
 | 
			
		||||
    0 = Ok,
 | 
			
		||||
    1 = Warning,
 | 
			
		||||
    2 = Critical
 | 
			
		||||
 | 
			
		||||
If you are creating a poller module which can detect a fault condition simply set STATUS to something other than 0 and ERROR to a message that indicates the problem.
 | 
			
		||||
 | 
			
		||||
To actually raise an alert, the user will need to create an alert rule. To assist with this several Alerting Macro's have been created:
 | 
			
		||||
 | 
			
		||||
- ```%macro.component_alert``` - A component that is not disabled or ignored and in alert state.
 | 
			
		||||
- ```%macro.component_normal``` - A component that is not disabled or ignored and NOT in alert state.
 | 
			
		||||
- ```%macro.component_normal``` - A component that is not disabled or ignored and in a Normal state.
 | 
			
		||||
- ```%macro.component_warning``` - A component that is not disabled or ignored and NOT in a Warning state.
 | 
			
		||||
- ```%macro.component_critical``` - A component that is not disabled or ignored and NOT in a Critical state.
 | 
			
		||||
 | 
			
		||||
To raise alerts for components, the following rules could be created:
 | 
			
		||||
 | 
			
		||||
- ```%macros.component_alert = "1"``` - To alert on all components
 | 
			
		||||
- ```%macros.component_alert = "1" && %component.type = "<Type of Component>"``` - To alert on all components of a particular type.
 | 
			
		||||
- ```%macros.component_critical = "1"``` - To alert on all Critical components
 | 
			
		||||
- ```%macros.component_critical = "1" && %component.type = "<Type of Component>"``` - To alert on all Critical components of a particular type.
 | 
			
		||||
 | 
			
		||||
If there is a particular component you would like excluded from alerting, simply set the ignore field to 1.
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										41
									
								
								html/includes/common/component-status.inc.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								html/includes/common/component-status.inc.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
require_once "../includes/component.php";
 | 
			
		||||
$OBJCOMP = new component();
 | 
			
		||||
 | 
			
		||||
$common_output[] = '
 | 
			
		||||
<div>
 | 
			
		||||
    <table id="component-status" class="table table-hover table-condensed table-striped">
 | 
			
		||||
        <thead>
 | 
			
		||||
            <tr>
 | 
			
		||||
                <th data-column-id="status" data-order="desc">Status</th>
 | 
			
		||||
                <th data-column-id="count">Count</th>
 | 
			
		||||
            </tr>
 | 
			
		||||
        </thead>
 | 
			
		||||
        <tbody>
 | 
			
		||||
';
 | 
			
		||||
foreach ($OBJCOMP->getComponentStatus() as $k => $v) {
 | 
			
		||||
    if ($k == 0) {
 | 
			
		||||
        $status = 'Ok';
 | 
			
		||||
        $color = 'green';
 | 
			
		||||
    }
 | 
			
		||||
    elseif ($k == 1) {
 | 
			
		||||
        $status = 'Warning';
 | 
			
		||||
        $color = 'grey';
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        $status = 'Critical';
 | 
			
		||||
        $color = 'red';
 | 
			
		||||
    }
 | 
			
		||||
    $common_output[] .= '
 | 
			
		||||
            <tr>
 | 
			
		||||
                <td><p class="text-left '.$color.'">'.$status.'</p></td>
 | 
			
		||||
                <td><p class="text-left '.$color.'">'.$v.'</p></td>
 | 
			
		||||
            </tr>
 | 
			
		||||
';
 | 
			
		||||
}
 | 
			
		||||
$common_output[] .= '
 | 
			
		||||
        </tbody>
 | 
			
		||||
    </table>
 | 
			
		||||
</div>
 | 
			
		||||
';
 | 
			
		||||
@@ -34,17 +34,30 @@ $COMPONENTS = $OBJCOMP->getComponents($device_id,$options);
 | 
			
		||||
$response[] = array(
 | 
			
		||||
    'id' => '<button type="submit" id="save-form" class="btn btn-success btn-sm" title="Save current component disable/ignore settings">Save</button><button type="submit" id="form-reset" class="btn btn-danger btn-sm" title="Reset form to when the page was loaded">Reset</button>',
 | 
			
		||||
    'label' => ' ',
 | 
			
		||||
    'status' => '<button type="submit" id="alert-select" class="btn btn-default btn-sm" title="Disable alerting on all currently-alerting components">Alerting</button>',
 | 
			
		||||
    'status' => '<button type="submit" id="warning-select" class="btn btn-default btn-sm" title="Disable alerting on all currently warning components">Warning</button> <button type="submit" id="critical-select" class="btn btn-default btn-sm" title="Disable alerting on all currently critical components">Critical</button>',
 | 
			
		||||
    'disable' => '<button type="submit" id="disable-toggle" class="btn btn-default btn-sm" title="Toggle polling for all components">Toggle</button><button type="button" id="disable-select" class="btn btn-default btn-sm" title="Disable polling on all components">Select All</button>',
 | 
			
		||||
    'ignore' => '<button type="submit" id="ignore-toggle" class="btn btn-default btn-sm" title="Toggle alerting for all components">Toggle</button><button type="button" id="ignore-select" class="btn btn-default btn-sm" title="Disable alerting on all components">Select All</button>',
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
foreach ($COMPONENTS[$device_id] as $ID => $AVP) {
 | 
			
		||||
    if ($AVP['status'] == 0) {
 | 
			
		||||
        $class = "green";
 | 
			
		||||
        $status = "Ok";
 | 
			
		||||
    }
 | 
			
		||||
    elseif ($AVP['status'] == 1) {
 | 
			
		||||
        $class = "grey";
 | 
			
		||||
        $status = "Warning";
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        // Critical
 | 
			
		||||
        $class = "red";
 | 
			
		||||
        $status = "Critical";
 | 
			
		||||
    }
 | 
			
		||||
    $response[] = array(
 | 
			
		||||
        'id' => $ID,
 | 
			
		||||
        'type' => $AVP['type'],
 | 
			
		||||
        'label' => $AVP['label'],
 | 
			
		||||
        'status' => ($AVP['status'] ? "<span name='status_".$ID."' class='green'>Normal</span>" : "<span name='status_".$ID."' class='red'>Alert</span>"),
 | 
			
		||||
        'status' => "<span name='status_".$ID."' class='".$class."'>".$status."</span>",
 | 
			
		||||
        'disable' => '<input type="checkbox" class="disable-check" name="dis_'.$ID.'"'.($AVP['disabled'] ? 'checked' : '').'>',
 | 
			
		||||
        'ignore' => '<input type="checkbox" class="ignore-check" name="ign_'.$ID.'"'.($AVP['ignore'] ? 'checked' : '').'>',
 | 
			
		||||
    );
 | 
			
		||||
 
 | 
			
		||||
@@ -44,13 +44,27 @@
 | 
			
		||||
                event.preventDefault();
 | 
			
		||||
                $('.ignore-check').prop('checked', true);
 | 
			
		||||
            });
 | 
			
		||||
            $('#alert-select').click(function (event) {
 | 
			
		||||
                // select ignore buttons for all ports which are down
 | 
			
		||||
            $('#warning-select').click(function (event) {
 | 
			
		||||
                // select ignore button for all components that are in a warning state.
 | 
			
		||||
                event.preventDefault();
 | 
			
		||||
                $('[name^="status_"]').each(function () {
 | 
			
		||||
                    var name = $(this).attr('name');
 | 
			
		||||
                    var text = $(this).text();
 | 
			
		||||
                    if (name && text == 'Alert') {
 | 
			
		||||
                    if (name && text == 'Warning') {
 | 
			
		||||
                        // get the component number from the object name
 | 
			
		||||
                        var id = name.split('_')[1];
 | 
			
		||||
                        // find its corresponding checkbox and toggle it
 | 
			
		||||
                        $('input[name="ign_' + id + '"]').trigger('click');
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
            $('#critical-select').click(function (event) {
 | 
			
		||||
                // select ignore button for all components that are in a critical state.
 | 
			
		||||
                event.preventDefault();
 | 
			
		||||
                $('[name^="status_"]').each(function () {
 | 
			
		||||
                    var name = $(this).attr('name');
 | 
			
		||||
                    var text = $(this).text();
 | 
			
		||||
                    if (name && text == 'Critical') {
 | 
			
		||||
                        // get the component number from the object name
 | 
			
		||||
                        var id = name.split('_')[1];
 | 
			
		||||
                        // find its corresponding checkbox and toggle it
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@ global $config;
 | 
			
		||||
// Loop over each component, pulling out the Overlays.
 | 
			
		||||
foreach ($components as $oid => $overlay) {
 | 
			
		||||
    if ($overlay['otvtype'] == 'overlay') {
 | 
			
		||||
        if ($overlay['status'] == 1) {
 | 
			
		||||
        if ($overlay['status'] == 0) {
 | 
			
		||||
            $overlay_status = "<span class='green pull-right'>Normal</span>";
 | 
			
		||||
            $gli = "";
 | 
			
		||||
        }
 | 
			
		||||
@@ -33,7 +33,7 @@ foreach ($components as $oid => $overlay) {
 | 
			
		||||
<?php
 | 
			
		||||
        foreach ($components as $aid => $adjacency) {
 | 
			
		||||
            if (($adjacency['otvtype'] == 'adjacency') && ($adjacency['index'] == $overlay['index'])) {
 | 
			
		||||
                if ($adjacency['status'] == 1) {
 | 
			
		||||
                if ($adjacency['status'] == 0) {
 | 
			
		||||
                    $adj_status = "<span class='green pull-right'>Normal</span>";
 | 
			
		||||
                    $gli = "";
 | 
			
		||||
                }
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@ foreach ($COMPONENTS as $DEVICE_ID => $COMP) {
 | 
			
		||||
        // Loop over each component, pulling out the Overlays.
 | 
			
		||||
        foreach ($COMP as $OID => $OVERLAY) {
 | 
			
		||||
            if ($OVERLAY['otvtype'] == 'overlay') {
 | 
			
		||||
                if ($OVERLAY['status'] == 1) {
 | 
			
		||||
                if ($OVERLAY['status'] == 0) {
 | 
			
		||||
                    $OVERLAY_STATUS = "<span class='green pull-right'>Normal</span>";
 | 
			
		||||
                    $GLI = "";
 | 
			
		||||
                }
 | 
			
		||||
@@ -33,7 +33,7 @@ foreach ($COMPONENTS as $DEVICE_ID => $COMP) {
 | 
			
		||||
                    <?php
 | 
			
		||||
                    foreach ($COMP as $AID => $ADJACENCY) {
 | 
			
		||||
                        if (($ADJACENCY['otvtype'] == 'adjacency') && ($ADJACENCY['index'] == $OVERLAY['index'])) {
 | 
			
		||||
                            if ($ADJACENCY['status'] == 1) {
 | 
			
		||||
                            if ($ADJACENCY['status'] == 0) {
 | 
			
		||||
                                $ADJ_STATUS = "<span class='green pull-right'>Normal</span>";
 | 
			
		||||
                                $GLI = "";
 | 
			
		||||
                            }
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ class component {
 | 
			
		||||
    private $reserved = array(
 | 
			
		||||
        'type'      => '',
 | 
			
		||||
        'label'     => '',
 | 
			
		||||
        'status'    => 1,
 | 
			
		||||
        'status'    => 0,
 | 
			
		||||
        'ignore'    => 0,
 | 
			
		||||
        'disabled'  => 0,
 | 
			
		||||
        'error'     => '',
 | 
			
		||||
@@ -148,6 +148,69 @@ class component {
 | 
			
		||||
        return $RESULT;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getComponentStatus($device=null) {
 | 
			
		||||
        $sql_query = "SELECT status, count(status) as count FROM component WHERE";
 | 
			
		||||
        $sql_param = array();
 | 
			
		||||
        $add = 0;
 | 
			
		||||
 | 
			
		||||
        if (!is_null($device)) {
 | 
			
		||||
            // Add a device filter to the SQL query.
 | 
			
		||||
            $sql_query .= " `device_id` = ?";
 | 
			
		||||
            $sql_param[] = $device;
 | 
			
		||||
            $add++;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($add == 0) {
 | 
			
		||||
            // No filters, remove " WHERE" -6
 | 
			
		||||
            $sql_query = substr($sql_query, 0, strlen($sql_query)-6);
 | 
			
		||||
        }
 | 
			
		||||
        $sql_query .= " GROUP BY status";
 | 
			
		||||
        d_echo("SQL Query: ".$sql_query);
 | 
			
		||||
 | 
			
		||||
        // $service is not null, get only what we want.
 | 
			
		||||
        $result = dbFetchRows($sql_query, $sql_param);
 | 
			
		||||
 | 
			
		||||
        // Set our defaults to 0
 | 
			
		||||
        $count = array(0 => 0, 1 => 0, 2 => 0);
 | 
			
		||||
        // Rebuild the array in a more convenient method
 | 
			
		||||
        foreach ($result as $v) {
 | 
			
		||||
            $count[$v['status']] = $v['count'];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        d_echo("Component Count by Status: ".print_r($count,TRUE)."\n");
 | 
			
		||||
        return $count;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getComponentStatusLog($component=null,$start=null,$end=null) {
 | 
			
		||||
        if ( ($component == null) || ($start == null) || ($end == null) ) {
 | 
			
		||||
            // Error...
 | 
			
		||||
            d_echo("Required arguments are missing. Component: ".$component.", Start: ".$start.", End: ".$end."\n");
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Create our return array.
 | 
			
		||||
        $return = array();
 | 
			
		||||
 | 
			
		||||
        // 1. find the previous value, this is the value when $start occurred.
 | 
			
		||||
        $sql_query = "SELECT status FROM component_statuslog WHERE `component` = ? AND time < ? ORDER BY `id` desc LIMIT 1";
 | 
			
		||||
        $sql_param = array($component,$start);
 | 
			
		||||
        $result = dbFetchRow($sql_query, $sql_param);
 | 
			
		||||
        if ($result == false) {
 | 
			
		||||
            $return['initial'] = false;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            $return['initial'] = $result['status'];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 2. Then we just need a list of all the entries for the time period.
 | 
			
		||||
        $sql_query = "SELECT status, time, message FROM component_statuslog WHERE `component` = ? AND time >= ? AND time < ? ORDER BY `time`";
 | 
			
		||||
        $sql_param = array($component,$start,$end);
 | 
			
		||||
        $return['data'] = dbFetchRows($sql_query, $sql_param);
 | 
			
		||||
 | 
			
		||||
        d_echo("Status Log Data: ".print_r($return,TRUE)."\n");
 | 
			
		||||
        return $return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function createComponent ($device_id,$TYPE) {
 | 
			
		||||
        // Prepare our default values to be inserted.
 | 
			
		||||
        $DATA = $this->reserved;
 | 
			
		||||
@@ -159,6 +222,9 @@ class component {
 | 
			
		||||
        // Insert a new component into the database.
 | 
			
		||||
        $id = dbInsert($DATA, 'component');
 | 
			
		||||
 | 
			
		||||
        // Add a default status log entry - we always start ok.
 | 
			
		||||
        $this->createStatusLogEntry($id,0,'Component Created');
 | 
			
		||||
 | 
			
		||||
        // Create a default component array based on what was inserted.
 | 
			
		||||
        $ARRAY = array();
 | 
			
		||||
        $ARRAY[$id] = $DATA;
 | 
			
		||||
@@ -166,6 +232,17 @@ class component {
 | 
			
		||||
        return $ARRAY;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function createStatusLogEntry($component,$status,$message) {
 | 
			
		||||
        // Add an entry to the statuslog table for a particular component.
 | 
			
		||||
        $DATA = array(
 | 
			
		||||
            'component'     => $component,
 | 
			
		||||
            'status'        => $status,
 | 
			
		||||
            'message'       => $message,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        return dbInsert($DATA, 'component_statuslog');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function deleteComponent ($id) {
 | 
			
		||||
        // Delete a component from the database.
 | 
			
		||||
        return dbDelete('component', "`id` = ?",array($id));
 | 
			
		||||
@@ -187,6 +264,12 @@ class component {
 | 
			
		||||
            // Ignore type, we cant change that.
 | 
			
		||||
            unset($AVP['type'],$OLD[$device_id][$COMPONENT]['type']);
 | 
			
		||||
 | 
			
		||||
            // If the Status has changed we need to add a log entry
 | 
			
		||||
            if ($AVP['status'] != $OLD[$device_id][$COMPONENT]['status']) {
 | 
			
		||||
                d_echo("Status Changed - Old: ".$OLD[$device_id][$COMPONENT]['status'].", New: ".$AVP['status']."\n");
 | 
			
		||||
                $this->createStatusLogEntry($COMPONENT,$AVP['status'],$AVP['error']);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Process our reserved components first.
 | 
			
		||||
            $UPDATE = array();
 | 
			
		||||
            foreach ($this->reserved as $k => $v) {
 | 
			
		||||
@@ -239,7 +322,7 @@ class component {
 | 
			
		||||
                    log_event("Component: ".$AVP[$COMPONENT]['type']."(".$COMPONENT."). Attribute: ".$ATTR.", was modified from: ".$OLD[$COMPONENT][$ATTR].", to: ".$VALUE,$device_id,'component',$COMPONENT);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            } // End Foreach COMPONENT
 | 
			
		||||
            } // End Foreach AVP
 | 
			
		||||
 | 
			
		||||
            // Process our Deletes.
 | 
			
		||||
            $DELETE = array_diff_key($OLD[$device_id][$COMPONENT], $AVP);
 | 
			
		||||
 
 | 
			
		||||
@@ -116,11 +116,11 @@ if ($device['os_group'] == 'cisco') {
 | 
			
		||||
            // If we have set a message, we have an error, activate alert.
 | 
			
		||||
            if ($message !== false) {
 | 
			
		||||
                $result['error'] = $message;
 | 
			
		||||
                $result['status'] = 0;
 | 
			
		||||
                $result['status'] = 2;
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                $result['error'] = "";
 | 
			
		||||
                $result['status'] = 1;
 | 
			
		||||
                $result['status'] = 0;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Let's log some debugging
 | 
			
		||||
@@ -154,11 +154,11 @@ if ($device['os_group'] == 'cisco') {
 | 
			
		||||
            // If we have set a message, we have an error, activate alert.
 | 
			
		||||
            if ($message !== false) {
 | 
			
		||||
                $result['error'] = $message;
 | 
			
		||||
                $result['status'] = 0;
 | 
			
		||||
                $result['status'] = 1;
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                $result['error'] = "";
 | 
			
		||||
                $result['status'] = 1;
 | 
			
		||||
                $result['status'] = 0;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Set a default name, if for some unknown reason we cant find the parent VPN.
 | 
			
		||||
 
 | 
			
		||||
@@ -106,11 +106,11 @@ if ($device['os_group'] == "cisco") {
 | 
			
		||||
                // If we have set a message, we have an error, activate alert.
 | 
			
		||||
                if ($message !== false) {
 | 
			
		||||
                    $array['error'] = $message;
 | 
			
		||||
                    $array['status'] = 0;
 | 
			
		||||
                    $array['status'] = 2;
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    $array['error'] = "";
 | 
			
		||||
                    $array['status'] = 1;
 | 
			
		||||
                    $array['status'] = 0;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Time to graph the count of the active VLAN's on this overlay.
 | 
			
		||||
@@ -154,11 +154,11 @@ if ($device['os_group'] == "cisco") {
 | 
			
		||||
                // If we have set a message, we have an error, activate alert.
 | 
			
		||||
                if ($message !== false) {
 | 
			
		||||
                    $array['error'] = $message;
 | 
			
		||||
                    $array['status'] = 0;
 | 
			
		||||
                    $array['status'] = 1;
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    $array['error'] = "";
 | 
			
		||||
                    $array['status'] = 1;
 | 
			
		||||
                    $array['status'] = 0;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Let's log some debugging
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user