2016-08-21 08:07:14 -05:00
< ? php
/**
* Component . php
*
* LibreNMS module to Interface with the Component System
*
* 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 .
*
* 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 .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http :// www . gnu . org / licenses />.
*
* @ package LibreNMS
* @ link http :// librenms . org
* @ copyright 2015 Aaron Daniels < aaron @ daniels . id . au >
* @ author Aaron Daniels < aaron @ daniels . id . au >
*/
namespace LibreNMS ;
2016-08-28 17:32:55 -05:00
class Component
{
2016-08-21 08:07:14 -05:00
/*
* These fields are used in the component table . They are returned in the array
* so that they can be modified but they can not be set as user attributes . We
* also set their default values .
*/
private $reserved = array (
'type' => '' ,
'label' => '' ,
'status' => 0 ,
'ignore' => 0 ,
'disabled' => 0 ,
'error' => '' ,
);
2016-08-28 17:32:55 -05:00
public function getComponentType ( $TYPE = null )
{
2016-08-21 08:07:14 -05:00
if ( is_null ( $TYPE )) {
$SQL = " SELECT DISTINCT `type` as `name` FROM `component` ORDER BY `name` " ;
$row = dbFetchRow ( $SQL , array ());
2016-08-28 17:32:55 -05:00
} else {
2016-08-21 08:07:14 -05:00
$SQL = " SELECT DISTINCT `type` as `name` FROM `component` WHERE `type` = ? ORDER BY `name` " ;
$row = dbFetchRow ( $SQL , array ( $TYPE ));
}
if ( ! isset ( $row )) {
// We didn't find any component types
return false ;
2016-08-28 17:32:55 -05:00
} else {
2016-08-21 08:07:14 -05:00
// We found some..
return $row ;
}
}
2016-08-28 17:32:55 -05:00
public function getComponents ( $device_id = null , $options = array ())
{
2016-08-21 08:07:14 -05:00
// Define our results array, this will be set even if no rows are returned.
$RESULT = array ();
$PARAM = array ();
// Our base SQL Query, with no options.
$SQL = " SELECT `C`.`id`,`C`.`device_id`,`C`.`type`,`C`.`label`,`C`.`status`,`C`.`disabled`,`C`.`ignore`,`C`.`error`,`CP`.`attribute`,`CP`.`value` FROM `component` as `C` LEFT JOIN `component_prefs` as `CP` on `C`.`id`=`CP`.`component` WHERE " ;
// Device_id is shorthand for filter C.device_id = $device_id.
if ( ! is_null ( $device_id )) {
$options [ 'filter' ][ 'device_id' ] = array ( '=' , $device_id );
}
// Type is shorthand for filter type = $type.
if ( isset ( $options [ 'type' ])) {
$options [ 'filter' ][ 'type' ] = array ( '=' , $options [ 'type' ]);
}
// filter field => array(operator,value)
// Filters results based on the field, operator and value
$COUNT = 0 ;
if ( isset ( $options [ 'filter' ])) {
$COUNT ++ ;
$validFields = array ( 'device_id' , 'type' , 'id' , 'label' , 'status' , 'disabled' , 'ignore' , 'error' );
$SQL .= " ( " ;
foreach ( $options [ 'filter' ] as $field => $array ) {
// Only add valid fields to the query
2016-08-28 17:32:55 -05:00
if ( in_array ( $field , $validFields )) {
2016-08-21 08:07:14 -05:00
if ( $array [ 0 ] == 'LIKE' ) {
$SQL .= " ` " . $field . " ` LIKE ? AND " ;
$array [ 1 ] = " % " . $array [ 1 ] . " % " ;
2016-08-28 17:32:55 -05:00
} else {
2016-08-21 08:07:14 -05:00
// Equals operator is the default
$SQL .= " ` " . $field . " ` = ? AND " ;
}
2016-08-28 17:32:55 -05:00
array_push ( $PARAM , $array [ 1 ]);
2016-08-21 08:07:14 -05:00
}
}
// Strip the last " AND " before closing the bracket.
2016-08-28 17:32:55 -05:00
$SQL = substr ( $SQL , 0 , - 5 ) . " ) " ;
2016-08-21 08:07:14 -05:00
}
if ( $COUNT == 0 ) {
// Strip the " WHERE " that we didn't use.
2016-08-28 17:32:55 -05:00
$SQL = substr ( $SQL , 0 , - 7 );
2016-08-21 08:07:14 -05:00
}
// sort column direction
// Add SQL sorting to the results
if ( isset ( $options [ 'sort' ])) {
$SQL .= " ORDER BY " . $options [ 'sort' ];
}
// Get our component records using our built SQL.
$COMPONENTS = dbFetchRows ( $SQL , $PARAM );
// if we have no components we need to return nothing
if ( count ( $COMPONENTS ) == 0 ) {
return $RESULT ;
}
// Add the AVP's to the array.
foreach ( $COMPONENTS as $COMPONENT ) {
if ( $COMPONENT [ 'attribute' ] != " " ) {
// if this component has attributes, set them in the array.
$RESULT [ $COMPONENT [ 'device_id' ]][ $COMPONENT [ 'id' ]][ $COMPONENT [ 'attribute' ]] = $COMPONENT [ 'value' ];
}
}
// Populate our reserved fields into the Array, these cant be used as user attributes.
foreach ( $COMPONENTS as $COMPONENT ) {
foreach ( $this -> reserved as $k => $v ) {
$RESULT [ $COMPONENT [ 'device_id' ]][ $COMPONENT [ 'id' ]][ $k ] = $COMPONENT [ $k ];
}
// Sort each component array so the attributes are in order.
ksort ( $RESULT [ $RESULT [ $COMPONENT [ 'device_id' ]][ $COMPONENT [ 'id' ]]]);
ksort ( $RESULT [ $RESULT [ $COMPONENT [ 'device_id' ]]]);
}
// limit array(start,count)
if ( isset ( $options [ 'limit' ])) {
$TEMP = array ();
$COUNT = 0 ;
// k = device_id, v = array of components for that device_id
foreach ( $RESULT as $k => $v ) {
// k1 = component id, v1 = component array
foreach ( $v as $k1 => $v1 ) {
2016-08-28 17:32:55 -05:00
if (( $COUNT >= $options [ 'limit' ][ 0 ]) && ( $COUNT < $options [ 'limit' ][ 0 ] + $options [ 'limit' ][ 1 ])) {
2016-08-21 08:07:14 -05:00
$TEMP [ $k ][ $k1 ] = $v1 ;
}
// We are counting components.
$COUNT ++ ;
}
}
$RESULT = $TEMP ;
}
return $RESULT ;
}
2016-08-28 17:32:55 -05:00
public function getComponentStatus ( $device = null )
{
2016-08-21 08:07:14 -05:00
$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' ];
}
2016-08-28 17:32:55 -05:00
d_echo ( " Component Count by Status: " . print_r ( $count , true ) . " \n " );
2016-08-21 08:07:14 -05:00
return $count ;
}
2016-08-28 17:32:55 -05:00
public function getComponentStatusLog ( $component = null , $start = null , $end = null )
{
if (( $component == null ) || ( $start == null ) || ( $end == null )) {
2016-08-21 08:07:14 -05:00
// 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 ;
2016-08-28 17:32:55 -05:00
} else {
2016-08-21 08:07:14 -05:00
$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 );
2016-08-28 17:32:55 -05:00
d_echo ( " Status Log Data: " . print_r ( $return , true ) . " \n " );
2016-08-21 08:07:14 -05:00
return $return ;
}
2016-08-28 17:32:55 -05:00
public function createComponent ( $device_id , $TYPE )
{
2016-08-21 08:07:14 -05:00
// Prepare our default values to be inserted.
$DATA = $this -> reserved ;
// Add the device_id and type
$DATA [ 'device_id' ] = $device_id ;
$DATA [ 'type' ] = $TYPE ;
// Insert a new component into the database.
$id = dbInsert ( $DATA , 'component' );
// Add a default status log entry - we always start ok.
2016-08-28 17:32:55 -05:00
$this -> createStatusLogEntry ( $id , 0 , 'Component Created' );
2016-08-21 08:07:14 -05:00
// Create a default component array based on what was inserted.
$ARRAY = array ();
$ARRAY [ $id ] = $DATA ;
2016-08-28 17:32:55 -05:00
unset ( $ARRAY [ $id ][ 'device_id' ]); // This doesn't belong here.
2016-08-21 08:07:14 -05:00
return $ARRAY ;
}
2016-08-28 17:32:55 -05:00
public function createStatusLogEntry ( $component , $status , $message )
{
2016-08-21 08:07:14 -05:00
// Add an entry to the statuslog table for a particular component.
$DATA = array (
'component' => $component ,
'status' => $status ,
'message' => $message ,
);
return dbInsert ( $DATA , 'component_statuslog' );
}
2016-08-28 17:32:55 -05:00
public function deleteComponent ( $id )
{
2016-08-21 08:07:14 -05:00
// Delete a component from the database.
2016-08-28 17:32:55 -05:00
return dbDelete ( 'component' , " `id` = ? " , array ( $id ));
2016-08-21 08:07:14 -05:00
}
2016-08-28 17:32:55 -05:00
public function setComponentPrefs ( $device_id , $ARRAY )
{
2016-08-21 08:07:14 -05:00
// Compare the arrays. Update/Insert where necessary.
$OLD = $this -> getComponents ( $device_id );
// Loop over each component.
foreach ( $ARRAY as $COMPONENT => $AVP ) {
// Make sure the component already exists.
if ( ! isset ( $OLD [ $device_id ][ $COMPONENT ])) {
// Error. Component doesn't exist in the database.
continue ;
}
// 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 " );
2016-08-28 17:32:55 -05:00
$this -> createStatusLogEntry ( $COMPONENT , $AVP [ 'status' ], $AVP [ 'error' ]);
2016-08-21 08:07:14 -05:00
}
// Process our reserved components first.
$UPDATE = array ();
foreach ( $this -> reserved as $k => $v ) {
// does the reserved field exist, if not skip.
if ( isset ( $AVP [ $k ])) {
// Has the value changed?
if ( $AVP [ $k ] != $OLD [ $device_id ][ $COMPONENT ][ $k ]) {
// The value has been modified, add it to our update array.
$UPDATE [ $k ] = $AVP [ $k ];
}
// Unset the reserved field. We don't want to insert it below.
unset ( $AVP [ $k ], $OLD [ $device_id ][ $COMPONENT ][ $k ]);
}
}
// Has anything changed, do we need to update?
if ( count ( $UPDATE ) > 0 ) {
// We have data to update
dbUpdate ( $UPDATE , 'component' , '`id` = ?' , array ( $COMPONENT ));
// Log the update to the Eventlog.
$MSG = " Component " . $COMPONENT . " has been modified: " ;
foreach ( $UPDATE as $k => $v ) {
$MSG .= $k . " => " . $v . " , " ;
}
2016-08-28 17:32:55 -05:00
$MSG = substr ( $MSG , 0 , - 1 );
log_event ( $MSG , $device_id , 'component' , $COMPONENT );
2016-08-21 08:07:14 -05:00
}
// Process our AVP Adds and Updates
foreach ( $AVP as $ATTR => $VALUE ) {
// We have our AVP, lets see if we need to do anything with it.
if ( ! isset ( $OLD [ $device_id ][ $COMPONENT ][ $ATTR ])) {
// We have a newly added attribute, need to insert into the DB
$DATA = array ( 'component' => $COMPONENT , 'attribute' => $ATTR , 'value' => $VALUE );
dbInsert ( $DATA , 'component_prefs' );
// Log the addition to the Eventlog.
2016-08-28 17:32:55 -05:00
log_event ( " Component: " . $AVP [ $COMPONENT ][ 'type' ] . " ( " . $COMPONENT . " ). Attribute: " . $ATTR . " , was added with value: " . $VALUE , $device_id , 'component' , $COMPONENT );
} elseif ( $OLD [ $device_id ][ $COMPONENT ][ $ATTR ] != $VALUE ) {
2016-08-21 08:07:14 -05:00
// Attribute exists but the value is different, need to update
$DATA = array ( 'value' => $VALUE );
dbUpdate ( $DATA , 'component_prefs' , '`component` = ? AND `attribute` = ?' , array ( $COMPONENT , $ATTR ));
// Add the modification to the Eventlog.
2016-08-28 17:32:55 -05:00
log_event ( " Component: " . $AVP [ $COMPONENT ][ 'type' ] . " ( " . $COMPONENT . " ). Attribute: " . $ATTR . " , was modified from: " . $OLD [ $COMPONENT ][ $ATTR ] . " , to: " . $VALUE , $device_id , 'component' , $COMPONENT );
2016-08-21 08:07:14 -05:00
}
} // End Foreach AVP
// Process our Deletes.
$DELETE = array_diff_key ( $OLD [ $device_id ][ $COMPONENT ], $AVP );
foreach ( $DELETE as $KEY => $VALUE ) {
// As the Attribute has been removed from the array, we should remove it from the database.
2016-08-28 17:32:55 -05:00
dbDelete ( 'component_prefs' , " `component` = ? AND `attribute` = ? " , array ( $COMPONENT , $KEY ));
2016-08-21 08:07:14 -05:00
// Log the addition to the Eventlog.
2016-08-28 17:32:55 -05:00
log_event ( " Component: " . $AVP [ $COMPONENT ][ 'type' ] . " ( " . $COMPONENT . " ). Attribute: " . $KEY . " , was deleted. " , $COMPONENT );
2016-08-21 08:07:14 -05:00
}
}
return true ;
}
}