forked from librenms/librenms
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathComponent.php
397 lines (342 loc) · 15.2 KB
/
Component.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
<?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 <[email protected]>
* @author Aaron Daniels <[email protected]>
*/
namespace LibreNMS;
class Component
{
/*
* 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' => '',
);
public function getComponentCount($device_id = null)
{
if (is_null($device_id)) {
// SELECT type, count(*) as count FROM component GROUP BY type
$SQL = "SELECT `type` as `name`, count(*) as count FROM `component` GROUP BY `type`";
$rows = dbFetchRows($SQL, array());
} else {
$SQL = "SELECT `type` as `name`, count(*) as count FROM `component` WHERE `device_id` = ? GROUP BY `type`";
$rows = dbFetchRows($SQL, array($device_id));
}
if (isset($rows)) {
// We found some, lets re-process to make more accessible
$result = array();
foreach ($rows as $value) {
$result[$value['name']] = $value['count'];
}
return $result;
}
// We didn't find any components
return false;
}
public function getComponentType($TYPE = null)
{
if (is_null($TYPE)) {
$SQL = "SELECT DISTINCT `type` as `name` FROM `component` ORDER BY `name`";
$row = dbFetchRow($SQL, array());
} else {
$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;
} else {
// We found some..
return $row;
}
}
public function getComponents($device_id = null, $options = array())
{
// 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
if (in_array($field, $validFields)) {
if ($array[0] == 'LIKE') {
$SQL .= "`".$field."` LIKE ? AND ";
$array[1] = "%".$array[1]."%";
} else {
// Equals operator is the default
$SQL .= "`".$field."` = ? AND ";
}
array_push($PARAM, $array[1]);
}
}
// Strip the last " AND " before closing the bracket.
$SQL = substr($SQL, 0, -5)." )";
}
if ($COUNT == 0) {
// Strip the " WHERE " that we didn't use.
$SQL = substr($SQL, 0, -7);
}
// 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) {
if (($COUNT >= $options['limit'][0]) && ($COUNT < $options['limit'][0]+$options['limit'][1])) {
$TEMP[$k][$k1] = $v1;
}
// We are counting components.
$COUNT++;
}
}
$RESULT = $TEMP;
}
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_id, $start, $end)
{
if (($component_id == null) || ($start == null) || ($end == null)) {
// Error...
d_echo("Required arguments are missing. Component ID: ".$component_id.", 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_id` = ? AND `timestamp` < ? ORDER BY `id` desc LIMIT 1";
$sql_param = array($component_id, $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, `timestamp`, message FROM `component_statuslog` WHERE `component_id` = ? AND `timestamp` >= ? AND `timestamp` < ? ORDER BY `timestamp`";
$sql_param = array($component_id, $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;
// 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.
$this->createStatusLogEntry($id, 0, 'Component Created');
// Create a default component array based on what was inserted.
$ARRAY = array();
$ARRAY[$id] = $DATA;
unset($ARRAY[$id]['device_id']); // This doesn't belong here.
return $ARRAY;
}
public function createStatusLogEntry($component_id, $status, $message)
{
// Add an entry to the statuslog table for a particular component.
$DATA = array(
'component_id' => $component_id,
'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));
}
public function setComponentPrefs($device_id, $ARRAY)
{
// 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");
$this->createStatusLogEntry($COMPONENT['id'], $AVP['status'], $AVP['error']);
}
// 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.",";
}
$MSG = substr($MSG, 0, -1);
log_event($MSG, $device_id, 'component', 3, $COMPONENT);
}
// 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.
log_event("Component: " . $AVP[$COMPONENT]['type'] . "(" . $COMPONENT . "). Attribute: " . $ATTR . ", was added with value: " . $VALUE, $device_id, 'component', 3, $COMPONENT);
} elseif ($OLD[$device_id][$COMPONENT][$ATTR] != $VALUE) {
// 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.
log_event("Component: " . $AVP[$COMPONENT]['type'] . "(" . $COMPONENT . "). Attribute: " . $ATTR . ", was modified from: " . $OLD[$COMPONENT][$ATTR] . ", to: " . $VALUE, $device_id, 'component', 3, $COMPONENT);
}
} // 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.
dbDelete('component_prefs', "`component` = ? AND `attribute` = ?", array($COMPONENT,$KEY));
// Log the addition to the Eventlog.
log_event("Component: " . $AVP[$COMPONENT]['type'] . "(" . $COMPONENT . "). Attribute: " . $KEY . ", was deleted.", 4, $COMPONENT);
}
}
return true;
}
/**
* Get the component id for the first component in the array
* Only set $device_id if using the array from getCompenents(), which is keyed by device_id
*
* @param array $component_array
* @param int $device_id
* @return int the component id
*/
public function getFirstComponentID($component_array, $device_id = null)
{
if (!is_null($device_id) && isset($component_array[$device_id])) {
$component_array = $component_array[$device_id];
}
foreach ($component_array as $id => $array) {
return $id;
}
return -1;
}
}