1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* LibreNMS |
5
|
|
|
* |
6
|
|
|
* This file is part of LibreNMS |
7
|
|
|
* |
8
|
|
|
* @author LibreNMS Contributors <[email protected]> |
9
|
|
|
* @copyright (C) 2006 - 2012 Adam Armstrong (as Observium) |
10
|
|
|
* @copyright (C) 2013 LibreNMS Group |
11
|
|
|
*/ |
12
|
|
|
|
13
|
|
|
use LibreNMS\Config; |
14
|
|
|
use LibreNMS\Util\Debug; |
15
|
|
|
use LibreNMS\Util\Number; |
16
|
|
|
use LibreNMS\Util\Rewrite; |
17
|
|
|
|
18
|
|
|
/** |
19
|
|
|
* Compare $t with the value of $vars[$v], if that exists |
20
|
|
|
* |
21
|
|
|
* @param string $v Name of the var to test |
22
|
|
|
* @param string $t Value to compare $vars[$v] to |
23
|
|
|
* @return bool true, if values are the same, false if $vars[$v] |
24
|
|
|
* is unset or values differ |
25
|
|
|
*/ |
26
|
|
|
function var_eq($v, $t) |
27
|
|
|
{ |
28
|
|
|
global $vars; |
29
|
|
|
if (isset($vars[$v]) && $vars[$v] == $t) { |
30
|
|
|
return true; |
31
|
|
|
} |
32
|
|
|
|
33
|
|
|
return false; |
34
|
|
|
} |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* Get the value of $vars[$v], if it exists |
38
|
|
|
* |
39
|
|
|
* @param string $v Name of the var to get |
40
|
|
|
* @return string|bool The value of $vars[$v] if it exists, false if it does not exist |
41
|
|
|
*/ |
42
|
|
|
function var_get($v) |
43
|
|
|
{ |
44
|
|
|
global $vars; |
45
|
|
|
if (isset($vars[$v])) { |
46
|
|
|
return $vars[$v]; |
47
|
|
|
} |
48
|
|
|
|
49
|
|
|
return false; |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
function toner2colour($descr, $percent) |
53
|
|
|
{ |
54
|
|
|
$colour = \LibreNMS\Util\Colors::percentage(100 - $percent, null); |
55
|
|
|
|
56
|
|
|
if (substr($descr, -1) == 'C' || stripos($descr, 'cyan') !== false) { |
57
|
|
|
$colour['left'] = '55D6D3'; |
58
|
|
|
$colour['right'] = '33B4B1'; |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
if (substr($descr, -1) == 'M' || stripos($descr, 'magenta') !== false) { |
62
|
|
|
$colour['left'] = 'F24AC8'; |
63
|
|
|
$colour['right'] = 'D028A6'; |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
if (substr($descr, -1) == 'Y' || stripos($descr, 'yellow') !== false |
67
|
|
|
|| stripos($descr, 'giallo') !== false |
68
|
|
|
|| stripos($descr, 'gul') !== false |
69
|
|
|
) { |
70
|
|
|
$colour['left'] = 'FFF200'; |
71
|
|
|
$colour['right'] = 'DDD000'; |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
if (substr($descr, -1) == 'K' || stripos($descr, 'black') !== false |
75
|
|
|
|| stripos($descr, 'nero') !== false |
76
|
|
|
) { |
77
|
|
|
$colour['left'] = '000000'; |
78
|
|
|
$colour['right'] = '222222'; |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
return $colour; |
82
|
|
|
}//end toner2colour() |
83
|
|
|
|
84
|
|
|
/** |
85
|
|
|
* Find all links in some text and turn them into html links. |
86
|
|
|
* |
87
|
|
|
* @param string $text |
88
|
|
|
* @return string |
89
|
|
|
*/ |
90
|
|
|
function linkify($text) |
91
|
|
|
{ |
92
|
|
|
$regex = "#(http|https|ftp|ftps)://[a-z0-9\-.]*[a-z0-9\-]+(/\S*)?#i"; |
93
|
|
|
|
94
|
|
|
return preg_replace($regex, '<a href="$0">$0</a>', $text); |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
function generate_link($text, $vars, $new_vars = []) |
98
|
|
|
{ |
99
|
|
|
return '<a href="' . \LibreNMS\Util\Url::generate($vars, $new_vars) . '">' . $text . '</a>'; |
100
|
|
|
}//end generate_link() |
101
|
|
|
|
102
|
|
|
function escape_quotes($text) |
103
|
|
|
{ |
104
|
|
|
return str_replace('"', "\'", str_replace("'", "\'", $text)); |
105
|
|
|
}//end escape_quotes() |
106
|
|
|
|
107
|
|
|
function generate_overlib_content($graph_array, $text) |
108
|
|
|
{ |
109
|
|
|
$overlib_content = '<div class=overlib><span class=overlib-text>' . $text . '</span><br />'; |
110
|
|
|
foreach (['day', 'week', 'month', 'year'] as $period) { |
111
|
|
|
$graph_array['from'] = Config::get("time.$period"); |
112
|
|
|
$overlib_content .= escape_quotes(\LibreNMS\Util\Url::graphTag($graph_array)); |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
$overlib_content .= '</div>'; |
116
|
|
|
|
117
|
|
|
return $overlib_content; |
118
|
|
|
}//end generate_overlib_content() |
119
|
|
|
|
120
|
|
|
function generate_device_link($device, $text = null, $vars = [], $start = 0, $end = 0, $escape_text = 1, $overlib = 1) |
121
|
|
|
{ |
122
|
|
|
$deviceModel = DeviceCache::get((int) $device['device_id']); |
123
|
|
|
|
124
|
|
|
return \LibreNMS\Util\Url::deviceLink($deviceModel, $text, $vars, $start, $end, $escape_text, $overlib); |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
function bill_permitted($bill_id) |
128
|
|
|
{ |
129
|
|
|
if (Auth::user()->hasGlobalRead()) { |
130
|
|
|
return true; |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
return \Permissions::canAccessBill($bill_id, Auth::id()); |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
function port_permitted($port_id, $device_id = null) |
137
|
|
|
{ |
138
|
|
|
if (! is_numeric($device_id)) { |
139
|
|
|
$device_id = get_device_id_by_port_id($port_id); |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
if (device_permitted($device_id)) { |
143
|
|
|
return true; |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
return \Permissions::canAccessPort($port_id, Auth::id()); |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
function application_permitted($app_id, $device_id = null) |
150
|
|
|
{ |
151
|
|
|
if (! is_numeric($app_id)) { |
152
|
|
|
return false; |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
if (! $device_id) { |
156
|
|
|
$device_id = get_device_id_by_app_id($app_id); |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
return device_permitted($device_id); |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
function device_permitted($device_id) |
163
|
|
|
{ |
164
|
|
|
if (Auth::user() && Auth::user()->hasGlobalRead()) { |
165
|
|
|
return true; |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
return \Permissions::canAccessDevice($device_id, Auth::id()); |
169
|
|
|
} |
170
|
|
|
|
171
|
|
|
function alert_layout($severity) |
172
|
|
|
{ |
173
|
|
|
switch ($severity) { |
174
|
|
|
case 'critical': |
175
|
|
|
$icon = 'exclamation'; |
176
|
|
|
$color = 'danger'; |
177
|
|
|
$background = 'danger'; |
178
|
|
|
break; |
179
|
|
|
case 'warning': |
180
|
|
|
$icon = 'warning'; |
181
|
|
|
$color = 'warning'; |
182
|
|
|
$background = 'warning'; |
183
|
|
|
break; |
184
|
|
|
case 'ok': |
185
|
|
|
$icon = 'check'; |
186
|
|
|
$color = 'success'; |
187
|
|
|
$background = 'success'; |
188
|
|
|
break; |
189
|
|
|
default: |
190
|
|
|
$icon = 'info'; |
191
|
|
|
$color = 'info'; |
192
|
|
|
$background = 'info'; |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
return ['icon' => $icon, |
196
|
|
|
'icon_color' => $color, |
197
|
|
|
'background_color' => $background, ]; |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
function generate_dynamic_graph_tag($args) |
201
|
|
|
{ |
202
|
|
|
$urlargs = []; |
203
|
|
|
$width = 0; |
204
|
|
|
foreach ($args as $key => $arg) { |
205
|
|
|
switch (strtolower($key)) { |
206
|
|
|
case 'width': |
207
|
|
|
$width = $arg; |
208
|
|
|
$value = '{{width}}'; |
209
|
|
|
break; |
210
|
|
|
case 'from': |
211
|
|
|
$value = '{{start}}'; |
212
|
|
|
break; |
213
|
|
|
case 'to': |
214
|
|
|
$value = '{{end}}'; |
215
|
|
|
break; |
216
|
|
|
default: |
217
|
|
|
$value = $arg; |
218
|
|
|
break; |
219
|
|
|
} |
220
|
|
|
$urlargs[] = $key . '=' . $value; |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
return '<img style="width:' . $width . 'px;height:100%" class="graph img-responsive" data-src-template="graph.php?' . implode('&', $urlargs) . '" border="0" />'; |
224
|
|
|
}//end generate_dynamic_graph_tag() |
225
|
|
|
|
226
|
|
|
function generate_dynamic_graph_js($args) |
227
|
|
|
{ |
228
|
|
|
$from = (is_numeric($args['from']) ? $args['from'] : '(new Date()).getTime() / 1000 - 24*3600'); |
229
|
|
|
$range = (is_numeric($args['to']) ? $args['to'] - $args['from'] : '24*3600'); |
230
|
|
|
|
231
|
|
|
$output = '<script src="js/RrdGraphJS/q-5.0.2.min.js"></script> |
232
|
|
|
<script src="js/RrdGraphJS/moment-timezone-with-data.js"></script> |
233
|
|
|
<script src="js/RrdGraphJS/rrdGraphPng.js"></script> |
234
|
|
|
<script type="text/javascript"> |
235
|
|
|
q.ready(function(){ |
236
|
|
|
var graphs = []; |
237
|
|
|
q(\'.graph\').forEach(function(item){ |
238
|
|
|
graphs.push( |
239
|
|
|
q(item).rrdGraphPng({ |
240
|
|
|
canvasPadding: 120, |
241
|
|
|
initialStart: ' . $from . ', |
242
|
|
|
initialRange: ' . $range . ' |
243
|
|
|
}) |
244
|
|
|
); |
245
|
|
|
}); |
246
|
|
|
}); |
247
|
|
|
// needed for dynamic height |
248
|
|
|
window.onload = function(){ window.dispatchEvent(new Event(\'resize\')); } |
249
|
|
|
</script>'; |
250
|
|
|
|
251
|
|
|
return $output; |
252
|
|
|
}//end generate_dynamic_graph_js() |
253
|
|
|
|
254
|
|
|
function generate_graph_js_state($args) |
255
|
|
|
{ |
256
|
|
|
// we are going to assume we know roughly what the graph url looks like here. |
257
|
|
|
// TODO: Add sensible defaults |
258
|
|
|
$from = (is_numeric($args['from']) ? $args['from'] : 0); |
259
|
|
|
$to = (is_numeric($args['to']) ? $args['to'] : 0); |
260
|
|
|
$width = (is_numeric($args['width']) ? $args['width'] : 0); |
261
|
|
|
$height = (is_numeric($args['height']) ? $args['height'] : 0); |
262
|
|
|
$legend = str_replace("'", '', $args['legend']); |
263
|
|
|
|
264
|
|
|
$state = <<<STATE |
265
|
|
|
<script type="text/javascript" language="JavaScript"> |
266
|
|
|
document.graphFrom = $from; |
267
|
|
|
document.graphTo = $to; |
268
|
|
|
document.graphWidth = $width; |
269
|
|
|
document.graphHeight = $height; |
270
|
|
|
document.graphLegend = '$legend'; |
271
|
|
|
</script> |
272
|
|
|
STATE; |
273
|
|
|
|
274
|
|
|
return $state; |
275
|
|
|
}//end generate_graph_js_state() |
276
|
|
|
|
277
|
|
|
function print_percentage_bar($width, $height, $percent, $left_text, $left_colour, $left_background, $right_text, $right_colour, $right_background) |
278
|
|
|
{ |
279
|
|
|
return \LibreNMS\Util\Html::percentageBar($width, $height, $percent, $left_text, $right_text, null, null, [ |
280
|
|
|
'left' => $left_background, |
281
|
|
|
'left_text' => $left_colour, |
282
|
|
|
'right' => $right_background, |
283
|
|
|
'right_text' => $right_colour, |
284
|
|
|
]); |
285
|
|
|
} |
286
|
|
|
|
287
|
|
|
function generate_entity_link($type, $entity, $text = null, $graph_type = null) |
288
|
|
|
{ |
289
|
|
|
global $entity_cache; |
290
|
|
|
|
291
|
|
|
if (is_numeric($entity)) { |
292
|
|
|
$entity = get_entity_by_id_cache($type, $entity); |
293
|
|
|
} |
294
|
|
|
|
295
|
|
|
switch ($type) { |
296
|
|
|
case 'port': |
297
|
|
|
$link = generate_port_link($entity, $text, $graph_type); |
298
|
|
|
break; |
299
|
|
|
|
300
|
|
|
case 'storage': |
301
|
|
|
if (empty($text)) { |
302
|
|
|
$text = $entity['storage_descr']; |
303
|
|
|
} |
304
|
|
|
|
305
|
|
|
$link = generate_link($text, ['page' => 'device', 'device' => $entity['device_id'], 'tab' => 'health', 'metric' => 'storage']); |
306
|
|
|
break; |
307
|
|
|
|
308
|
|
|
default: |
309
|
|
|
$link = $entity[$type . '_id']; |
310
|
|
|
} |
311
|
|
|
|
312
|
|
|
return $link; |
313
|
|
|
}//end generate_entity_link() |
314
|
|
|
|
315
|
|
|
/** |
316
|
|
|
* Extract type and subtype from a complex graph type, also makes sure variables are file name safe. |
317
|
|
|
* |
318
|
|
|
* @param string $type |
319
|
|
|
* @return array [type, subtype] |
320
|
|
|
*/ |
321
|
|
|
function extract_graph_type($type): array |
322
|
|
|
{ |
323
|
|
|
preg_match('/^(?P<type>[A-Za-z0-9]+)_(?P<subtype>.+)/', $type, $graphtype); |
324
|
|
|
$type = basename($graphtype['type']); |
325
|
|
|
$subtype = basename($graphtype['subtype']); |
326
|
|
|
|
327
|
|
|
return [$type, $subtype]; |
328
|
|
|
} |
329
|
|
|
|
330
|
|
|
function generate_port_link($port, $text = null, $type = null, $overlib = 1, $single_graph = 0) |
331
|
|
|
{ |
332
|
|
|
$graph_array = []; |
333
|
|
|
|
334
|
|
|
if (! $text) { |
335
|
|
|
$text = Rewrite::normalizeIfName($port['label'] ?? $port['ifName']); |
336
|
|
|
} |
337
|
|
|
|
338
|
|
|
if ($type) { |
339
|
|
|
$port['graph_type'] = $type; |
340
|
|
|
} |
341
|
|
|
|
342
|
|
|
if (! isset($port['graph_type'])) { |
343
|
|
|
$port['graph_type'] = 'port_bits'; |
344
|
|
|
} |
345
|
|
|
|
346
|
|
|
$class = ifclass($port['ifOperStatus'], $port['ifAdminStatus']); |
347
|
|
|
|
348
|
|
|
if (! isset($port['hostname'])) { |
349
|
|
|
$port = array_merge($port, device_by_id_cache($port['device_id'])); |
350
|
|
|
} |
351
|
|
|
|
352
|
|
|
$content = '<div class=list-large>' . $port['hostname'] . ' - ' . Rewrite::normalizeIfName(addslashes(\LibreNMS\Util\Clean::html($port['label'], []))) . '</div>'; |
353
|
|
|
if ($port['port_descr_descr']) { |
354
|
|
|
$content .= addslashes(\LibreNMS\Util\Clean::html($port['port_descr_descr'], [])) . '<br />'; |
355
|
|
|
} elseif ($port['ifAlias']) { |
356
|
|
|
$content .= addslashes(\LibreNMS\Util\Clean::html($port['ifAlias'], [])) . '<br />'; |
357
|
|
|
} |
358
|
|
|
|
359
|
|
|
$content .= "<div style=\'width: 850px\'>"; |
360
|
|
|
$graph_array['type'] = $port['graph_type']; |
361
|
|
|
$graph_array['legend'] = 'yes'; |
362
|
|
|
$graph_array['height'] = '100'; |
363
|
|
|
$graph_array['width'] = '340'; |
364
|
|
|
$graph_array['to'] = Config::get('time.now'); |
365
|
|
|
$graph_array['from'] = Config::get('time.day'); |
366
|
|
|
$graph_array['id'] = $port['port_id']; |
367
|
|
|
$content .= \LibreNMS\Util\Url::graphTag($graph_array); |
368
|
|
|
if ($single_graph == 0) { |
369
|
|
|
$graph_array['from'] = Config::get('time.week'); |
370
|
|
|
$content .= \LibreNMS\Util\Url::graphTag($graph_array); |
371
|
|
|
$graph_array['from'] = Config::get('time.month'); |
372
|
|
|
$content .= \LibreNMS\Util\Url::graphTag($graph_array); |
373
|
|
|
$graph_array['from'] = Config::get('time.year'); |
374
|
|
|
$content .= \LibreNMS\Util\Url::graphTag($graph_array); |
375
|
|
|
} |
376
|
|
|
|
377
|
|
|
$content .= '</div>'; |
378
|
|
|
|
379
|
|
|
$url = generate_port_url($port); |
380
|
|
|
|
381
|
|
|
if ($overlib == 0) { |
382
|
|
|
return $content; |
383
|
|
|
} elseif (port_permitted($port['port_id'], $port['device_id'])) { |
384
|
|
|
return \LibreNMS\Util\Url::overlibLink($url, $text, $content, $class); |
385
|
|
|
} else { |
386
|
|
|
return Rewrite::normalizeIfName($text); |
387
|
|
|
} |
388
|
|
|
}//end generate_port_link() |
389
|
|
|
|
390
|
|
|
function generate_sensor_link($args, $text = null, $type = null) |
391
|
|
|
{ |
392
|
|
|
if (! $text) { |
393
|
|
|
$text = $args['sensor_descr']; |
394
|
|
|
} |
395
|
|
|
|
396
|
|
|
if (! $type) { |
397
|
|
|
$args['graph_type'] = 'sensor_' . $args['sensor_class']; |
398
|
|
|
} else { |
399
|
|
|
$args['graph_type'] = 'sensor_' . $type; |
400
|
|
|
} |
401
|
|
|
|
402
|
|
|
if (! isset($args['hostname'])) { |
403
|
|
|
$args = array_merge($args, device_by_id_cache($args['device_id'])); |
404
|
|
|
} |
405
|
|
|
|
406
|
|
|
$content = '<div class=list-large>' . $text . '</div>'; |
407
|
|
|
|
408
|
|
|
$content .= "<div style=\'width: 850px\'>"; |
409
|
|
|
$graph_array = [ |
410
|
|
|
'type' => $args['graph_type'], |
411
|
|
|
'legend' => 'yes', |
412
|
|
|
'height' => '100', |
413
|
|
|
'width' => '340', |
414
|
|
|
'to' => Config::get('time.now'), |
415
|
|
|
'from' => Config::get('time.day'), |
416
|
|
|
'id' => $args['sensor_id'], |
417
|
|
|
]; |
418
|
|
|
$content .= \LibreNMS\Util\Url::graphTag($graph_array); |
419
|
|
|
|
420
|
|
|
$graph_array['from'] = Config::get('time.week'); |
421
|
|
|
$content .= \LibreNMS\Util\Url::graphTag($graph_array); |
422
|
|
|
|
423
|
|
|
$graph_array['from'] = Config::get('time.month'); |
424
|
|
|
$content .= \LibreNMS\Util\Url::graphTag($graph_array); |
425
|
|
|
|
426
|
|
|
$graph_array['from'] = Config::get('time.year'); |
427
|
|
|
$content .= \LibreNMS\Util\Url::graphTag($graph_array); |
428
|
|
|
|
429
|
|
|
$content .= '</div>'; |
430
|
|
|
|
431
|
|
|
$url = \LibreNMS\Util\Url::generate(['page' => 'graphs', 'id' => $args['sensor_id'], 'type' => $args['graph_type'], 'from' => \LibreNMS\Config::get('time.day')], []); |
432
|
|
|
|
433
|
|
|
return \LibreNMS\Util\Url::overlibLink($url, $text, $content); |
434
|
|
|
}//end generate_sensor_link() |
435
|
|
|
|
436
|
|
|
function generate_port_url($port, $vars = []) |
437
|
|
|
{ |
438
|
|
|
return \LibreNMS\Util\Url::generate(['page' => 'device', 'device' => $port['device_id'], 'tab' => 'port', 'port' => $port['port_id']], $vars); |
439
|
|
|
}//end generate_port_url() |
440
|
|
|
|
441
|
|
|
function generate_sap_url($sap, $vars = []) |
442
|
|
|
{ |
443
|
|
|
return \LibreNMS\Util\Url::graphPopup(['device' => $sap['device_id'], 'page' => 'graphs', 'type' => 'device_sap', 'tab' => 'routing', 'proto' => 'mpls', 'view' => 'saps', 'traffic_id' => $sap['svc_oid'] . '.' . $sap['sapPortId'] . '.' . $sap['sapEncapValue']], $vars); |
444
|
|
|
}//end generate_sap_url() |
445
|
|
|
|
446
|
|
|
function generate_port_image($args) |
447
|
|
|
{ |
448
|
|
|
if (! $args['bg']) { |
449
|
|
|
$args['bg'] = 'FFFFFF00'; |
450
|
|
|
} |
451
|
|
|
|
452
|
|
|
return "<img src='graph.php?type=" . $args['graph_type'] . '&id=' . $args['port_id'] . '&from=' . $args['from'] . '&to=' . $args['to'] . '&width=' . $args['width'] . '&height=' . $args['height'] . '&bg=' . $args['bg'] . "'>"; |
453
|
|
|
}//end generate_port_image() |
454
|
|
|
|
455
|
|
|
/** |
456
|
|
|
* Create image to output text instead of a graph. |
457
|
|
|
* |
458
|
|
|
* @param string $text |
459
|
|
|
* @param int[] $color |
460
|
|
|
*/ |
461
|
|
|
function graph_error($text, $color = [128, 0, 0]) |
462
|
|
|
{ |
463
|
|
|
global $vars; |
464
|
|
|
|
465
|
|
|
$type = Config::get('webui.graph_type'); |
466
|
|
|
if (! Debug::isEnabled()) { |
467
|
|
|
header('Content-type: ' . get_image_type($type)); |
468
|
|
|
} |
469
|
|
|
|
470
|
|
|
$width = (int) ($vars['width'] ?? 150); |
471
|
|
|
$height = (int) ($vars['height'] ?? 60); |
472
|
|
|
|
473
|
|
|
if ($type === 'svg') { |
474
|
|
|
$rgb = implode(', ', $color); |
475
|
|
|
echo <<<SVG |
476
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" |
477
|
|
|
xmlns:xhtml="http://www.w3.org/1999/xhtml" |
478
|
|
|
viewBox="0 0 $width $height" |
479
|
|
|
preserveAspectRatio="xMinYMin"> |
480
|
|
|
<foreignObject x="0" y="0" width="$width" height="$height" transform="translate(0,0)"> |
481
|
|
|
<xhtml:div style="display:table; width:{$width}px; height:{$height}px; overflow:hidden;"> |
482
|
|
|
<xhtml:div style="display:table-cell; vertical-align:middle;"> |
483
|
|
|
<xhtml:div style="color:rgb($rgb); text-align:center; font-family:sans-serif; font-size:0.6em;">$text</xhtml:div> |
484
|
|
|
</xhtml:div> |
485
|
|
|
</xhtml:div> |
486
|
|
|
</foreignObject> |
487
|
|
|
</svg> |
488
|
|
|
SVG; |
489
|
|
|
} else { |
490
|
|
|
$img = imagecreate($width, $height); |
491
|
|
|
imagecolorallocatealpha($img, 255, 255, 255, 127); // transparent background |
492
|
|
|
|
493
|
|
|
$px = ((imagesx($img) - 7.5 * strlen($text)) / 2); |
494
|
|
|
$font = $width < 200 ? 3 : 5; |
495
|
|
|
imagestring($img, $font, $px, ($height / 2 - 8), $text, imagecolorallocate($img, ...$color)); |
496
|
|
|
|
497
|
|
|
// Output the image |
498
|
|
|
imagepng($img); |
499
|
|
|
imagedestroy($img); |
500
|
|
|
} |
501
|
|
|
} |
502
|
|
|
|
503
|
|
|
/** |
504
|
|
|
* Output message to user in image format. |
505
|
|
|
* |
506
|
|
|
* @param string $text string to display |
507
|
|
|
*/ |
508
|
|
|
function graph_text_and_exit($text) |
509
|
|
|
{ |
510
|
|
|
global $vars; |
511
|
|
|
|
512
|
|
|
if ($vars['showcommand'] == 'yes') { |
513
|
|
|
echo $text; |
514
|
|
|
|
515
|
|
|
return; |
516
|
|
|
} |
517
|
|
|
|
518
|
|
|
graph_error($text, [13, 21, 210]); |
519
|
|
|
exit; |
520
|
|
|
} |
521
|
|
|
|
522
|
|
|
function print_port_thumbnail($args) |
523
|
|
|
{ |
524
|
|
|
echo generate_port_link($args, generate_port_image($args)); |
525
|
|
|
}//end print_port_thumbnail() |
526
|
|
|
|
527
|
|
|
function print_optionbar_start($height = 0, $width = 0, $marginbottom = 5) |
528
|
|
|
{ |
529
|
|
|
echo ' |
530
|
|
|
<div class="panel panel-default"> |
531
|
|
|
<div class="panel-heading"> |
532
|
|
|
'; |
533
|
|
|
}//end print_optionbar_start() |
534
|
|
|
|
535
|
|
|
function print_optionbar_end() |
536
|
|
|
{ |
537
|
|
|
echo ' |
538
|
|
|
</div> |
539
|
|
|
</div> |
540
|
|
|
'; |
541
|
|
|
}//end print_optionbar_end() |
542
|
|
|
|
543
|
|
|
function devclass($device) |
544
|
|
|
{ |
545
|
|
|
if (isset($device['status']) && $device['status'] == '0') { |
546
|
|
|
$class = 'list-device-down'; |
547
|
|
|
} else { |
548
|
|
|
$class = 'list-device'; |
549
|
|
|
} |
550
|
|
|
|
551
|
|
|
if (isset($device['disable_notify']) && $device['disable_notify'] == '1') { |
552
|
|
|
$class = 'list-device-ignored'; |
553
|
|
|
if (isset($device['status']) && $device['status'] == '1') { |
554
|
|
|
$class = 'list-device-ignored-up'; |
555
|
|
|
} |
556
|
|
|
} |
557
|
|
|
|
558
|
|
|
if (isset($device['disabled']) && $device['disabled'] == '1') { |
559
|
|
|
$class = 'list-device-disabled'; |
560
|
|
|
} |
561
|
|
|
|
562
|
|
|
return $class; |
563
|
|
|
}//end devclass() |
564
|
|
|
|
565
|
|
|
function getlocations() |
566
|
|
|
{ |
567
|
|
|
if (Auth::user()->hasGlobalRead()) { |
568
|
|
|
return dbFetchRows('SELECT id, location FROM locations ORDER BY location'); |
569
|
|
|
} |
570
|
|
|
|
571
|
|
|
return dbFetchRows('SELECT id, L.location FROM devices AS D, locations AS L, devices_perms AS P WHERE D.device_id = P.device_id AND P.user_id = ? AND D.location_id = L.id ORDER BY location', [Auth::id()]); |
572
|
|
|
} |
573
|
|
|
|
574
|
|
|
/** |
575
|
|
|
* Get the recursive file size and count for a directory |
576
|
|
|
* |
577
|
|
|
* @param string $path |
578
|
|
|
* @return array [size, file count] |
579
|
|
|
*/ |
580
|
|
|
function foldersize($path) |
581
|
|
|
{ |
582
|
|
|
$total_size = 0; |
583
|
|
|
$total_files = 0; |
584
|
|
|
|
585
|
|
|
foreach (glob(rtrim($path, '/') . '/*', GLOB_NOSORT) as $item) { |
586
|
|
|
if (is_dir($item)) { |
587
|
|
|
[$folder_size, $file_count] = foldersize($item); |
588
|
|
|
$total_size += $folder_size; |
589
|
|
|
$total_files += $file_count; |
590
|
|
|
} else { |
591
|
|
|
$total_size += filesize($item); |
592
|
|
|
$total_files++; |
593
|
|
|
} |
594
|
|
|
} |
595
|
|
|
|
596
|
|
|
return [$total_size, $total_files]; |
597
|
|
|
} |
598
|
|
|
|
599
|
|
|
function generate_ap_link($args, $text = null, $type = null) |
600
|
|
|
{ |
601
|
|
|
$args = cleanPort($args); |
602
|
|
|
if (! $text) { |
603
|
|
|
$text = Rewrite::normalizeIfName($args['label']); |
604
|
|
|
} |
605
|
|
|
|
606
|
|
|
if ($type) { |
607
|
|
|
$args['graph_type'] = $type; |
608
|
|
|
} |
609
|
|
|
|
610
|
|
|
if (! isset($args['graph_type'])) { |
611
|
|
|
$args['graph_type'] = 'port_bits'; |
612
|
|
|
} |
613
|
|
|
|
614
|
|
|
if (! isset($args['hostname'])) { |
615
|
|
|
$args = array_merge($args, device_by_id_cache($args['device_id'])); |
616
|
|
|
} |
617
|
|
|
|
618
|
|
|
$content = '<div class=list-large>' . $args['text'] . ' - ' . Rewrite::normalizeIfName($args['label']) . '</div>'; |
619
|
|
|
if ($args['ifAlias']) { |
620
|
|
|
$content .= \LibreNMS\Util\Clean::html($args['ifAlias'], []) . '<br />'; |
621
|
|
|
} |
622
|
|
|
|
623
|
|
|
$content .= "<div style=\'width: 850px\'>"; |
624
|
|
|
$graph_array = []; |
625
|
|
|
$graph_array['type'] = $args['graph_type']; |
626
|
|
|
$graph_array['legend'] = 'yes'; |
627
|
|
|
$graph_array['height'] = '100'; |
628
|
|
|
$graph_array['width'] = '340'; |
629
|
|
|
$graph_array['to'] = Config::get('time.now'); |
630
|
|
|
$graph_array['from'] = Config::get('time.day'); |
631
|
|
|
$graph_array['id'] = $args['accesspoint_id']; |
632
|
|
|
$content .= \LibreNMS\Util\Url::graphTag($graph_array); |
633
|
|
|
$graph_array['from'] = Config::get('time.week'); |
634
|
|
|
$content .= \LibreNMS\Util\Url::graphTag($graph_array); |
635
|
|
|
$graph_array['from'] = Config::get('time.month'); |
636
|
|
|
$content .= \LibreNMS\Util\Url::graphTag($graph_array); |
637
|
|
|
$graph_array['from'] = Config::get('time.year'); |
638
|
|
|
$content .= \LibreNMS\Util\Url::graphTag($graph_array); |
639
|
|
|
$content .= '</div>'; |
640
|
|
|
|
641
|
|
|
$url = generate_ap_url($args); |
642
|
|
|
if (port_permitted($args['interface_id'], $args['device_id'])) { |
643
|
|
|
return \LibreNMS\Util\Url::overlibLink($url, $text, $content); |
644
|
|
|
} else { |
645
|
|
|
return Rewrite::normalizeIfName($text); |
646
|
|
|
} |
647
|
|
|
}//end generate_ap_link() |
648
|
|
|
|
649
|
|
|
function generate_ap_url($ap, $vars = []) |
650
|
|
|
{ |
651
|
|
|
return \LibreNMS\Util\Url::generate(['page' => 'device', 'device' => $ap['device_id'], 'tab' => 'accesspoints', 'ap' => $ap['accesspoint_id']], $vars); |
652
|
|
|
}//end generate_ap_url() |
653
|
|
|
|
654
|
|
|
// Find all the files in the given directory that match the pattern |
655
|
|
|
|
656
|
|
|
function get_matching_files($dir, $match = '/\.php$/') |
657
|
|
|
{ |
658
|
|
|
$list = []; |
659
|
|
|
if ($handle = opendir($dir)) { |
660
|
|
|
while (false !== ($file = readdir($handle))) { |
661
|
|
|
if ($file != '.' && $file != '..' && preg_match($match, $file) === 1) { |
662
|
|
|
$list[] = $file; |
663
|
|
|
} |
664
|
|
|
} |
665
|
|
|
|
666
|
|
|
closedir($handle); |
667
|
|
|
} |
668
|
|
|
|
669
|
|
|
return $list; |
670
|
|
|
}//end get_matching_files() |
671
|
|
|
|
672
|
|
|
// Include all the files in the given directory that match the pattern |
673
|
|
|
|
674
|
|
|
function include_matching_files($dir, $match = '/\.php$/') |
675
|
|
|
{ |
676
|
|
|
foreach (get_matching_files($dir, $match) as $file) { |
677
|
|
|
include_once $file; |
678
|
|
|
} |
679
|
|
|
}//end include_matching_files() |
680
|
|
|
|
681
|
|
|
function generate_pagination($count, $limit, $page, $links = 2) |
682
|
|
|
{ |
683
|
|
|
$end_page = ceil($count / $limit); |
684
|
|
|
$start = (($page - $links) > 0) ? ($page - $links) : 1; |
685
|
|
|
$end = (($page + $links) < $end_page) ? ($page + $links) : $end_page; |
686
|
|
|
$return = '<ul class="pagination">'; |
687
|
|
|
$link_class = ($page == 1) ? 'disabled' : ''; |
688
|
|
|
$return .= "<li><a href='' onClick='changePage(1,event);'>«</a></li>"; |
689
|
|
|
$return .= "<li class='$link_class'><a href='' onClick='changePage($page - 1,event);'><</a></li>"; |
690
|
|
|
|
691
|
|
|
if ($start > 1) { |
692
|
|
|
$return .= "<li><a href='' onClick='changePage(1,event);'>1</a></li>"; |
693
|
|
|
$return .= "<li class='disabled'><span>...</span></li>"; |
694
|
|
|
} |
695
|
|
|
|
696
|
|
|
for ($x = $start; $x <= $end; $x++) { |
697
|
|
|
$link_class = ($page == $x) ? 'active' : ''; |
698
|
|
|
$return .= "<li class='$link_class'><a href='' onClick='changePage($x,event);'>$x </a></li>"; |
699
|
|
|
} |
700
|
|
|
|
701
|
|
|
if ($end < $end_page) { |
702
|
|
|
$return .= "<li class='disabled'><span>...</span></li>"; |
703
|
|
|
$return .= "<li><a href='' onClick='changePage($end_page,event);'>$end_page</a></li>"; |
704
|
|
|
} |
705
|
|
|
|
706
|
|
|
$link_class = ($page == $end_page) ? 'disabled' : ''; |
707
|
|
|
$return .= "<li class='$link_class'><a href='' onClick='changePage($page + 1,event);'>></a></li>"; |
708
|
|
|
$return .= "<li class='$link_class'><a href='' onClick='changePage($end_page,event);'>»</a></li>"; |
709
|
|
|
$return .= '</ul>'; |
710
|
|
|
|
711
|
|
|
return $return; |
712
|
|
|
}//end generate_pagination() |
713
|
|
|
|
714
|
|
|
function demo_account() |
715
|
|
|
{ |
716
|
|
|
print_error("You are logged in as a demo account, this page isn't accessible to you"); |
717
|
|
|
}//end demo_account() |
718
|
|
|
|
719
|
|
|
function get_client_ip() |
720
|
|
|
{ |
721
|
|
|
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { |
722
|
|
|
$client_ip = $_SERVER['HTTP_X_FORWARDED_FOR']; |
723
|
|
|
} else { |
724
|
|
|
$client_ip = $_SERVER['REMOTE_ADDR']; |
725
|
|
|
} |
726
|
|
|
|
727
|
|
|
return $client_ip; |
728
|
|
|
}//end get_client_ip() |
729
|
|
|
|
730
|
|
|
function clean_bootgrid($string) |
731
|
|
|
{ |
732
|
|
|
$output = str_replace(["\r", "\n"], '', $string); |
733
|
|
|
$output = addslashes($output); |
734
|
|
|
|
735
|
|
|
return $output; |
736
|
|
|
}//end clean_bootgrid() |
737
|
|
|
|
738
|
|
|
function get_url() |
739
|
|
|
{ |
740
|
|
|
// http://stackoverflow.com/questions/2820723/how-to-get-base-url-with-php |
741
|
|
|
// http://stackoverflow.com/users/184600/ma%C4%8Dek |
742
|
|
|
return sprintf( |
743
|
|
|
'%s://%s%s', |
744
|
|
|
isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' ? 'https' : 'http', |
745
|
|
|
$_SERVER['SERVER_NAME'], |
746
|
|
|
$_SERVER['REQUEST_URI'] |
747
|
|
|
); |
748
|
|
|
}//end get_url() |
749
|
|
|
|
750
|
|
|
function alert_details($details) |
751
|
|
|
{ |
752
|
|
|
if (! is_array($details)) { |
753
|
|
|
$details = json_decode(gzuncompress($details), true); |
754
|
|
|
} |
755
|
|
|
|
756
|
|
|
$fault_detail = ''; |
757
|
|
|
foreach ($details['rule'] as $o => $tmp_alerts) { |
758
|
|
|
$fallback = true; |
759
|
|
|
$fault_detail .= '#' . ($o + 1) . ': '; |
760
|
|
|
if ($tmp_alerts['bill_id']) { |
761
|
|
|
$fault_detail .= '<a href="' . \LibreNMS\Util\Url::generate(['page' => 'bill', 'bill_id' => $tmp_alerts['bill_id']], []) . '">' . $tmp_alerts['bill_name'] . '</a>; '; |
762
|
|
|
$fallback = false; |
763
|
|
|
} |
764
|
|
|
|
765
|
|
|
if ($tmp_alerts['port_id']) { |
766
|
|
|
$tmp_alerts = cleanPort($tmp_alerts); |
767
|
|
|
$fault_detail .= generate_port_link($tmp_alerts) . '; '; |
768
|
|
|
$fallback = false; |
769
|
|
|
} |
770
|
|
|
|
771
|
|
|
if ($tmp_alerts['accesspoint_id']) { |
772
|
|
|
$fault_detail .= generate_ap_link($tmp_alerts, $tmp_alerts['name']) . '; '; |
773
|
|
|
$fallback = false; |
774
|
|
|
} |
775
|
|
|
|
776
|
|
|
if ($tmp_alerts['sensor_id']) { |
777
|
|
|
if ($tmp_alerts['sensor_class'] == 'state') { |
778
|
|
|
// Give more details for a state (textual form) |
779
|
|
|
$details = 'State: ' . $tmp_alerts['state_descr'] . ' (numerical ' . $tmp_alerts['sensor_current'] . ')<br> '; |
780
|
|
|
} else { |
781
|
|
|
// Other sensors |
782
|
|
|
$details = 'Value: ' . $tmp_alerts['sensor_current'] . ' (' . $tmp_alerts['sensor_class'] . ')<br> '; |
783
|
|
|
} |
784
|
|
|
$details_a = []; |
785
|
|
|
|
786
|
|
|
if ($tmp_alerts['sensor_limit_low']) { |
787
|
|
|
$details_a[] = 'low: ' . $tmp_alerts['sensor_limit_low']; |
788
|
|
|
} |
789
|
|
|
if ($tmp_alerts['sensor_limit_low_warn']) { |
790
|
|
|
$details_a[] = 'low_warn: ' . $tmp_alerts['sensor_limit_low_warn']; |
791
|
|
|
} |
792
|
|
|
if ($tmp_alerts['sensor_limit_warn']) { |
793
|
|
|
$details_a[] = 'high_warn: ' . $tmp_alerts['sensor_limit_warn']; |
794
|
|
|
} |
795
|
|
|
if ($tmp_alerts['sensor_limit']) { |
796
|
|
|
$details_a[] = 'high: ' . $tmp_alerts['sensor_limit']; |
797
|
|
|
} |
798
|
|
|
$details .= implode(', ', $details_a); |
799
|
|
|
|
800
|
|
|
$fault_detail .= generate_sensor_link($tmp_alerts, $tmp_alerts['name']) . '; <br>' . $details; |
801
|
|
|
$fallback = false; |
802
|
|
|
} |
803
|
|
|
|
804
|
|
|
if ($tmp_alerts['bgpPeer_id']) { |
805
|
|
|
// If we have a bgpPeer_id, we format the data accordingly |
806
|
|
|
$fault_detail .= "BGP peer <a href='" . |
807
|
|
|
\LibreNMS\Util\Url::generate([ |
808
|
|
|
'page' => 'device', |
809
|
|
|
'device' => $tmp_alerts['device_id'], |
810
|
|
|
'tab' => 'routing', |
811
|
|
|
'proto' => 'bgp', |
812
|
|
|
]) . |
813
|
|
|
"'>" . $tmp_alerts['bgpPeerIdentifier'] . '</a>'; |
814
|
|
|
$fault_detail .= ', AS' . $tmp_alerts['bgpPeerRemoteAs']; |
815
|
|
|
$fault_detail .= ', State ' . $tmp_alerts['bgpPeerState']; |
816
|
|
|
$fallback = false; |
817
|
|
|
} |
818
|
|
|
|
819
|
|
|
if ($tmp_alerts['type'] && $tmp_alerts['label']) { |
820
|
|
|
if ($tmp_alerts['error'] == '') { |
821
|
|
|
$fault_detail .= ' ' . $tmp_alerts['type'] . ' - ' . $tmp_alerts['label'] . '; '; |
822
|
|
|
} else { |
823
|
|
|
$fault_detail .= ' ' . $tmp_alerts['type'] . ' - ' . $tmp_alerts['label'] . ' - ' . $tmp_alerts['error'] . '; '; |
824
|
|
|
} |
825
|
|
|
$fallback = false; |
826
|
|
|
} |
827
|
|
|
|
828
|
|
|
if (in_array('app_id', array_keys($tmp_alerts))) { |
829
|
|
|
$fault_detail .= "<a href='" . |
830
|
|
|
\LibreNMS\Util\Url::generate([ |
831
|
|
|
'page' => 'device', |
832
|
|
|
'device' => $tmp_alerts['device_id'], |
833
|
|
|
'tab' => 'apps', |
834
|
|
|
'app' => $tmp_alerts['app_type'], |
835
|
|
|
]) . "'>"; |
836
|
|
|
$fault_detail .= $tmp_alerts['app_type']; |
837
|
|
|
$fault_detail .= '</a>'; |
838
|
|
|
|
839
|
|
|
if ($tmp_alerts['app_status']) { |
840
|
|
|
$fault_detail .= ' => ' . $tmp_alerts['app_status']; |
841
|
|
|
} |
842
|
|
|
if ($tmp_alerts['metric']) { |
843
|
|
|
$fault_detail .= ' : ' . $tmp_alerts['metric'] . ' => ' . $tmp_alerts['value']; |
844
|
|
|
} |
845
|
|
|
$fallback = false; |
846
|
|
|
} |
847
|
|
|
|
848
|
|
|
if ($fallback === true) { |
849
|
|
|
$fault_detail_data = []; |
850
|
|
|
foreach ($tmp_alerts as $k => $v) { |
851
|
|
|
if (in_array($k, ['device_id', 'sysObjectID', 'sysDescr', 'location_id'])) { |
852
|
|
|
continue; |
853
|
|
|
} |
854
|
|
|
if (! empty($v) && str_i_contains($k, ['id', 'desc', 'msg', 'last'])) { |
855
|
|
|
$fault_detail_data[] = "$k => '$v'"; |
856
|
|
|
} |
857
|
|
|
} |
858
|
|
|
$fault_detail .= count($fault_detail_data) ? implode('<br>  ', $fault_detail_data) : ''; |
859
|
|
|
|
860
|
|
|
$fault_detail = rtrim($fault_detail, ', '); |
861
|
|
|
} |
862
|
|
|
|
863
|
|
|
$fault_detail .= '<br>'; |
864
|
|
|
}//end foreach |
865
|
|
|
|
866
|
|
|
return $fault_detail; |
867
|
|
|
}//end alert_details() |
868
|
|
|
|
869
|
|
|
function dynamic_override_config($type, $name, $device) |
870
|
|
|
{ |
871
|
|
|
$attrib_val = get_dev_attrib($device, $name); |
872
|
|
|
if ($attrib_val == 'true') { |
873
|
|
|
$checked = 'checked'; |
874
|
|
|
} else { |
875
|
|
|
$checked = ''; |
876
|
|
|
} |
877
|
|
|
if ($type == 'checkbox') { |
878
|
|
|
return '<input type="checkbox" id="override_config" name="override_config" data-attrib="' . $name . '" data-device_id="' . $device['device_id'] . '" data-size="small" ' . $checked . '>'; |
879
|
|
|
} elseif ($type == 'text') { |
880
|
|
|
return '<input type="text" id="override_config_text" name="override_config_text" data-attrib="' . $name . '" data-device_id="' . $device['device_id'] . '" value="' . $attrib_val . '">'; |
881
|
|
|
} |
882
|
|
|
}//end dynamic_override_config() |
883
|
|
|
|
884
|
|
|
/** |
885
|
|
|
* Return the rows from 'ports' for all ports of a certain type as parsed by port_descr_parser. |
886
|
|
|
* One or an array of strings can be provided as an argument; if an array is passed, all ports matching |
887
|
|
|
* any of the types in the array are returned. |
888
|
|
|
* |
889
|
|
|
* @param $types mixed String or strings matching 'port_descr_type's. |
890
|
|
|
* @return array Rows from the ports table for matching ports. |
891
|
|
|
*/ |
892
|
|
|
function get_ports_from_type($given_types) |
893
|
|
|
{ |
894
|
|
|
// Make the arg an array if it isn't, so subsequent steps only have to handle arrays. |
895
|
|
|
if (! is_array($given_types)) { |
896
|
|
|
$given_types = [$given_types]; |
897
|
|
|
} |
898
|
|
|
|
899
|
|
|
// Check the config for a '_descr' entry for each argument. This is how a 'custom_descr' entry can |
900
|
|
|
// be key/valued to some other string that's actually searched for in the DB. Merge or append the |
901
|
|
|
// configured value if it's an array or a string. Or append the argument itself if there's no matching |
902
|
|
|
// entry in config. |
903
|
|
|
$search_types = []; |
904
|
|
|
foreach ($given_types as $type) { |
905
|
|
|
if (Config::has($type . '_descr')) { |
906
|
|
|
$type_descr = Config::get($type . '_descr'); |
907
|
|
|
if (is_array($type_descr)) { |
908
|
|
|
$search_types = array_merge($search_types, $type_descr); |
909
|
|
|
} else { |
910
|
|
|
$search_types[] = $type_descr; |
911
|
|
|
} |
912
|
|
|
} else { |
913
|
|
|
$search_types[] = $type; |
914
|
|
|
} |
915
|
|
|
} |
916
|
|
|
|
917
|
|
|
// Using the full list of strings to search the DB for, build the 'where' portion of a query that |
918
|
|
|
// compares 'port_descr_type' with entry in the list. Also, since '@' is the convential wildcard, |
919
|
|
|
// replace it with '%' so it functions as a wildcard in the SQL query. |
920
|
|
|
$type_where = ' ('; |
921
|
|
|
$or = ''; |
922
|
|
|
$type_param = []; |
923
|
|
|
|
924
|
|
|
foreach ($search_types as $type) { |
925
|
|
|
if (! empty($type)) { |
926
|
|
|
$type = strtr($type, '@', '%'); |
927
|
|
|
$type_where .= " $or `port_descr_type` LIKE ?"; |
928
|
|
|
$or = 'OR'; |
929
|
|
|
$type_param[] = $type; |
930
|
|
|
} |
931
|
|
|
} |
932
|
|
|
$type_where .= ') '; |
933
|
|
|
|
934
|
|
|
// Run the query with the generated 'where' and necessary parameters, and send it back. |
935
|
|
|
$ports = dbFetchRows("SELECT * FROM `ports` as I, `devices` AS D WHERE $type_where AND I.device_id = D.device_id ORDER BY I.ifAlias", $type_param); |
936
|
|
|
|
937
|
|
|
return $ports; |
938
|
|
|
} |
939
|
|
|
|
940
|
|
|
/** |
941
|
|
|
* @param $filename |
942
|
|
|
* @param $content |
943
|
|
|
*/ |
944
|
|
|
function file_download($filename, $content) |
945
|
|
|
{ |
946
|
|
|
$length = strlen($content); |
947
|
|
|
header('Content-Description: File Transfer'); |
948
|
|
|
header('Content-Type: text/plain'); |
949
|
|
|
header("Content-Disposition: attachment; filename=$filename"); |
950
|
|
|
header('Content-Transfer-Encoding: binary'); |
951
|
|
|
header('Content-Length: ' . $length); |
952
|
|
|
header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); |
953
|
|
|
header('Expires: 0'); |
954
|
|
|
header('Pragma: public'); |
955
|
|
|
echo $content; |
956
|
|
|
} |
957
|
|
|
|
958
|
|
|
function get_rules_from_json() |
959
|
|
|
{ |
960
|
|
|
return json_decode(file_get_contents(Config::get('install_dir') . '/misc/alert_rules.json'), true); |
961
|
|
|
} |
962
|
|
|
|
963
|
|
|
function search_oxidized_config($search_in_conf_textbox) |
964
|
|
|
{ |
965
|
|
|
if (! Auth::user()->hasGlobalRead()) { |
966
|
|
|
return false; |
967
|
|
|
} |
968
|
|
|
|
969
|
|
|
$oxidized_search_url = Config::get('oxidized.url') . '/nodes/conf_search?format=json'; |
970
|
|
|
$postdata = http_build_query( |
971
|
|
|
[ |
972
|
|
|
'search_in_conf_textbox' => $search_in_conf_textbox, |
973
|
|
|
] |
974
|
|
|
); |
975
|
|
|
$opts = ['http' => [ |
976
|
|
|
'method' => 'POST', |
977
|
|
|
'header' => 'Content-type: application/x-www-form-urlencoded', |
978
|
|
|
'content' => $postdata, |
979
|
|
|
], |
980
|
|
|
]; |
981
|
|
|
$context = stream_context_create($opts); |
982
|
|
|
|
983
|
|
|
$nodes = json_decode(file_get_contents($oxidized_search_url, false, $context), true); |
984
|
|
|
// Look up Oxidized node names to LibreNMS devices for a link |
985
|
|
|
foreach ($nodes as &$n) { |
986
|
|
|
$dev = device_by_name($n['node']); |
987
|
|
|
$n['dev_id'] = $dev ? $dev['device_id'] : false; |
988
|
|
|
} |
989
|
|
|
|
990
|
|
|
/* |
991
|
|
|
// Filter nodes we don't have access too |
992
|
|
|
$nodes = array_filter($nodes, function($device) { |
993
|
|
|
return \Permissions::canAccessDevice($device['dev_id'], Auth::id()); |
994
|
|
|
}); |
995
|
|
|
*/ |
996
|
|
|
|
997
|
|
|
return $nodes; |
998
|
|
|
} |
999
|
|
|
|
1000
|
|
|
/** |
1001
|
|
|
* @param $data |
1002
|
|
|
* @return bool|mixed |
1003
|
|
|
*/ |
1004
|
|
|
function array_to_htmljson($data) |
1005
|
|
|
{ |
1006
|
|
|
if (is_array($data)) { |
1007
|
|
|
$data = htmlentities(json_encode($data)); |
1008
|
|
|
|
1009
|
|
|
return str_replace(',', ',<br />', $data); |
1010
|
|
|
} else { |
1011
|
|
|
return false; |
1012
|
|
|
} |
1013
|
|
|
} |
1014
|
|
|
|
1015
|
|
|
/** |
1016
|
|
|
* @param int $eventlog_severity |
1017
|
|
|
* @return string $eventlog_severity_icon |
1018
|
|
|
*/ |
1019
|
|
|
function eventlog_severity($eventlog_severity) |
1020
|
|
|
{ |
1021
|
|
|
switch ($eventlog_severity) { |
1022
|
|
|
case 1: |
1023
|
|
|
return 'label-success'; //OK |
1024
|
|
|
case 2: |
1025
|
|
|
return 'label-info'; //Informational |
1026
|
|
|
case 3: |
1027
|
|
|
return 'label-primary'; //Notice |
1028
|
|
|
case 4: |
1029
|
|
|
return 'label-warning'; //Warning |
1030
|
|
|
case 5: |
1031
|
|
|
return 'label-danger'; //Critical |
1032
|
|
|
default: |
1033
|
|
|
return 'label-default'; //Unknown |
1034
|
|
|
} |
1035
|
|
|
} // end eventlog_severity |
1036
|
|
|
|
1037
|
|
|
/** |
1038
|
|
|
* Get the http content type of the image |
1039
|
|
|
* |
1040
|
|
|
* @param string $type svg or png |
1041
|
|
|
* @return string |
1042
|
|
|
*/ |
1043
|
|
|
function get_image_type(string $type) |
1044
|
|
|
{ |
1045
|
|
|
return $type === 'svg' ? 'image/svg+xml' : 'image/png'; |
1046
|
|
|
} |
1047
|
|
|
|
1048
|
|
|
function get_oxidized_nodes_list() |
1049
|
|
|
{ |
1050
|
|
|
$context = stream_context_create([ |
1051
|
|
|
'http' => [ |
1052
|
|
|
'header' => 'Accept: application/json', |
1053
|
|
|
], |
1054
|
|
|
]); |
1055
|
|
|
|
1056
|
|
|
$data = json_decode(file_get_contents(Config::get('oxidized.url') . '/nodes?format=json', false, $context), true); |
1057
|
|
|
|
1058
|
|
|
foreach ($data as $object) { |
1059
|
|
|
$device = device_by_name($object['name']); |
1060
|
|
|
if (! device_permitted($device['device_id'])) { |
1061
|
|
|
//user cannot see this device, so let's skip it. |
1062
|
|
|
continue; |
1063
|
|
|
} |
1064
|
|
|
|
1065
|
|
|
echo '<tr> |
1066
|
|
|
<td>' . $device['device_id'] . '</td> |
1067
|
|
|
<td>' . $object['name'] . '</td> |
1068
|
|
|
<td>' . $device['sysName'] . '</td> |
1069
|
|
|
<td>' . $object['status'] . '</td> |
1070
|
|
|
<td>' . $object['time'] . '</td> |
1071
|
|
|
<td>' . $object['model'] . '</td> |
1072
|
|
|
<td>' . $object['group'] . '</td> |
1073
|
|
|
<td></td> |
1074
|
|
|
</tr>'; |
1075
|
|
|
} |
1076
|
|
|
} |
1077
|
|
|
|
1078
|
|
|
/** |
1079
|
|
|
* Get the fail2ban jails for a device... just requires the device ID |
1080
|
|
|
* an empty return means either no jails or fail2ban is not in use |
1081
|
|
|
* |
1082
|
|
|
* @param $device_id |
1083
|
|
|
* @return array |
1084
|
|
|
*/ |
1085
|
|
|
function get_fail2ban_jails($device_id) |
1086
|
|
|
{ |
1087
|
|
|
$options = [ |
1088
|
|
|
'filter' => [ |
1089
|
|
|
'type' => ['=', 'fail2ban'], |
1090
|
|
|
], |
1091
|
|
|
]; |
1092
|
|
|
|
1093
|
|
|
$component = new LibreNMS\Component(); |
1094
|
|
|
$f2bc = $component->getComponents($device_id, $options); |
1095
|
|
|
|
1096
|
|
|
if (isset($f2bc[$device_id])) { |
1097
|
|
|
$id = $component->getFirstComponentID($f2bc, $device_id); |
1098
|
|
|
|
1099
|
|
|
return json_decode($f2bc[$device_id][$id]['jails']); |
1100
|
|
|
} |
1101
|
|
|
|
1102
|
|
|
return []; |
1103
|
|
|
} |
1104
|
|
|
|
1105
|
|
|
/** |
1106
|
|
|
* Get the Postgres databases for a device... just requires the device ID |
1107
|
|
|
* an empty return means Postres is not in use |
1108
|
|
|
* |
1109
|
|
|
* @param $device_id |
1110
|
|
|
* @return array |
1111
|
|
|
*/ |
1112
|
|
|
function get_postgres_databases($device_id) |
1113
|
|
|
{ |
1114
|
|
|
$options = [ |
1115
|
|
|
'filter' => [ |
1116
|
|
|
'type' => ['=', 'postgres'], |
1117
|
|
|
], |
1118
|
|
|
]; |
1119
|
|
|
|
1120
|
|
|
$component = new LibreNMS\Component(); |
1121
|
|
|
$pgc = $component->getComponents($device_id, $options); |
1122
|
|
|
|
1123
|
|
|
if (isset($pgc[$device_id])) { |
1124
|
|
|
$id = $component->getFirstComponentID($pgc, $device_id); |
1125
|
|
|
|
1126
|
|
|
return json_decode($pgc[$device_id][$id]['databases']); |
1127
|
|
|
} |
1128
|
|
|
|
1129
|
|
|
return []; |
1130
|
|
|
} |
1131
|
|
|
|
1132
|
|
|
/** |
1133
|
|
|
* Return stacked graphs information |
1134
|
|
|
* |
1135
|
|
|
* @param string $transparency value of desired transparency applied to rrdtool options (values 01 - 99) |
1136
|
|
|
* @return array containing transparency and stacked setup |
1137
|
|
|
*/ |
1138
|
|
|
function generate_stacked_graphs($transparency = '88') |
1139
|
|
|
{ |
1140
|
|
|
if (Config::get('webui.graph_stacked') == true) { |
1141
|
|
|
return ['transparency' => $transparency, 'stacked' => '1']; |
1142
|
|
|
} else { |
1143
|
|
|
return ['transparency' => '', 'stacked' => '-1']; |
1144
|
|
|
} |
1145
|
|
|
} |
1146
|
|
|
|
1147
|
|
|
/** |
1148
|
|
|
* Parse AT time spec, does not handle the entire spec. |
1149
|
|
|
* |
1150
|
|
|
* @param string|int $time |
1151
|
|
|
* @return int |
1152
|
|
|
*/ |
1153
|
|
|
function parse_at_time($time) |
1154
|
|
|
{ |
1155
|
|
|
if (is_numeric($time)) { |
1156
|
|
|
return $time < 0 ? time() + $time : intval($time); |
1157
|
|
|
} |
1158
|
|
|
|
1159
|
|
|
if (preg_match('/^[+-]\d+[hdmy]$/', $time)) { |
1160
|
|
|
$units = [ |
1161
|
|
|
'm' => 60, |
1162
|
|
|
'h' => 3600, |
1163
|
|
|
'd' => 86400, |
1164
|
|
|
'y' => 31557600, |
1165
|
|
|
]; |
1166
|
|
|
$value = substr($time, 1, -1); |
1167
|
|
|
$unit = substr($time, -1); |
1168
|
|
|
|
1169
|
|
|
$offset = ($time[0] == '-' ? -1 : 1) * $units[$unit] * $value; |
1170
|
|
|
|
1171
|
|
|
return time() + $offset; |
1172
|
|
|
} |
1173
|
|
|
|
1174
|
|
|
return (int) strtotime($time); |
1175
|
|
|
} |
1176
|
|
|
|
1177
|
|
|
/** |
1178
|
|
|
* Get the ZFS pools for a device... just requires the device ID |
1179
|
|
|
* an empty return means ZFS is not in use or there are currently no pools |
1180
|
|
|
* |
1181
|
|
|
* @param $device_id |
1182
|
|
|
* @return array |
1183
|
|
|
*/ |
1184
|
|
|
function get_zfs_pools($device_id) |
1185
|
|
|
{ |
1186
|
|
|
$options = [ |
1187
|
|
|
'filter' => [ |
1188
|
|
|
'type' => ['=', 'zfs'], |
1189
|
|
|
], |
1190
|
|
|
]; |
1191
|
|
|
|
1192
|
|
|
$component = new LibreNMS\Component(); |
1193
|
|
|
$zfsc = $component->getComponents($device_id, $options); |
1194
|
|
|
|
1195
|
|
|
if (isset($zfsc[$device_id])) { |
1196
|
|
|
$id = $component->getFirstComponentID($zfsc, $device_id); |
1197
|
|
|
|
1198
|
|
|
return json_decode($zfsc[$device_id][$id]['pools']); |
1199
|
|
|
} |
1200
|
|
|
|
1201
|
|
|
return []; |
1202
|
|
|
} |
1203
|
|
|
|
1204
|
|
|
/** |
1205
|
|
|
* Get the ports for a device... just requires the device ID |
1206
|
|
|
* an empty return means portsactivity is not in use or there are currently no ports |
1207
|
|
|
* |
1208
|
|
|
* @param $device_id |
1209
|
|
|
* @return array |
1210
|
|
|
*/ |
1211
|
|
|
function get_portactivity_ports($device_id) |
1212
|
|
|
{ |
1213
|
|
|
$options = [ |
1214
|
|
|
'filter' => [ |
1215
|
|
|
'type' => ['=', 'portsactivity'], |
1216
|
|
|
], |
1217
|
|
|
]; |
1218
|
|
|
|
1219
|
|
|
$component = new LibreNMS\Component(); |
1220
|
|
|
$portsc = $component->getComponents($device_id, $options); |
1221
|
|
|
|
1222
|
|
|
if (isset($portsc[$device_id])) { |
1223
|
|
|
$id = $component->getFirstComponentID($portsc, $device_id); |
1224
|
|
|
|
1225
|
|
|
return json_decode($portsc[$device_id][$id]['ports']); |
1226
|
|
|
} |
1227
|
|
|
|
1228
|
|
|
return []; |
1229
|
|
|
} |
1230
|
|
|
|
1231
|
|
|
/** |
1232
|
|
|
* Returns the sysname of a device with a html line break prepended. |
1233
|
|
|
* if the device has an empty sysname it will return device's hostname instead |
1234
|
|
|
* And finally if the device has no hostname it will return an empty string |
1235
|
|
|
* |
1236
|
|
|
* @param array device |
1237
|
|
|
* @return string |
1238
|
|
|
*/ |
1239
|
|
|
function get_device_name($device) |
1240
|
|
|
{ |
1241
|
|
|
$ret_str = ''; |
1242
|
|
|
|
1243
|
|
|
if (format_hostname($device) !== $device['sysName']) { |
1244
|
|
|
$ret_str = $device['sysName']; |
1245
|
|
|
} elseif ($device['hostname'] !== $device['ip']) { |
1246
|
|
|
$ret_str = $device['hostname']; |
1247
|
|
|
} |
1248
|
|
|
|
1249
|
|
|
return $ret_str; |
1250
|
|
|
} |
1251
|
|
|
|
1252
|
|
|
/** |
1253
|
|
|
* Returns state generic label from value with optional text |
1254
|
|
|
*/ |
1255
|
|
|
function get_state_label($sensor) |
1256
|
|
|
{ |
1257
|
|
|
$state_translation = dbFetchRow('SELECT * FROM state_translations as ST, sensors_to_state_indexes as SSI WHERE ST.state_index_id=SSI.state_index_id AND SSI.sensor_id = ? AND ST.state_value = ? ', [$sensor['sensor_id'], $sensor['sensor_current']]); |
1258
|
|
|
|
1259
|
|
|
switch ($state_translation['state_generic_value']) { |
1260
|
|
|
case 0: // OK |
1261
|
|
|
$state_text = $state_translation['state_descr'] ?: 'OK'; |
1262
|
|
|
$state_label = 'label-success'; |
1263
|
|
|
break; |
1264
|
|
|
case 1: // Warning |
1265
|
|
|
$state_text = $state_translation['state_descr'] ?: 'Warning'; |
1266
|
|
|
$state_label = 'label-warning'; |
1267
|
|
|
break; |
1268
|
|
|
case 2: // Critical |
1269
|
|
|
$state_text = $state_translation['state_descr'] ?: 'Critical'; |
1270
|
|
|
$state_label = 'label-danger'; |
1271
|
|
|
break; |
1272
|
|
|
case 3: // Unknown |
1273
|
|
|
default: |
1274
|
|
|
$state_text = $state_translation['state_descr'] ?: 'Unknown'; |
1275
|
|
|
$state_label = 'label-default'; |
1276
|
|
|
} |
1277
|
|
|
|
1278
|
|
|
return "<span class='label $state_label'>$state_text</span>"; |
1279
|
|
|
} |
1280
|
|
|
|
1281
|
|
|
/** |
1282
|
|
|
* Get sensor label and state color |
1283
|
|
|
* |
1284
|
|
|
* @param array $sensor |
1285
|
|
|
* @param string $type sensors or wireless |
1286
|
|
|
* @return string |
1287
|
|
|
*/ |
1288
|
|
|
function get_sensor_label_color($sensor, $type = 'sensors') |
1289
|
|
|
{ |
1290
|
|
|
$label_style = 'label-success'; |
1291
|
|
|
if (is_null($sensor)) { |
1292
|
|
|
return 'label-unknown'; |
1293
|
|
|
} |
1294
|
|
|
if (! is_null($sensor['sensor_limit_warn']) && $sensor['sensor_current'] > $sensor['sensor_limit_warn']) { |
1295
|
|
|
$label_style = 'label-warning'; |
1296
|
|
|
} |
1297
|
|
|
if (! is_null($sensor['sensor_limit_low_warn']) && $sensor['sensor_current'] < $sensor['sensor_limit_low_warn']) { |
1298
|
|
|
$label_style = 'label-warning'; |
1299
|
|
|
} |
1300
|
|
|
if (! is_null($sensor['sensor_limit']) && $sensor['sensor_current'] > $sensor['sensor_limit']) { |
1301
|
|
|
$label_style = 'label-danger'; |
1302
|
|
|
} |
1303
|
|
|
if (! is_null($sensor['sensor_limit_low']) && $sensor['sensor_current'] < $sensor['sensor_limit_low']) { |
1304
|
|
|
$label_style = 'label-danger'; |
1305
|
|
|
} |
1306
|
|
|
$unit = __("$type.{$sensor['sensor_class']}.unit"); |
1307
|
|
|
if ($sensor['sensor_class'] == 'runtime') { |
1308
|
|
|
$sensor['sensor_current'] = \LibreNMS\Util\Time::formatInterval($sensor['sensor_current'] * 60); |
1309
|
|
|
|
1310
|
|
|
return "<span class='label $label_style'>" . trim($sensor['sensor_current']) . '</span>'; |
1311
|
|
|
} |
1312
|
|
|
if ($sensor['sensor_class'] == 'frequency' && $sensor['sensor_type'] == 'openwrt') { |
1313
|
|
|
return "<span class='label $label_style'>" . trim($sensor['sensor_current']) . ' ' . $unit . '</span>'; |
1314
|
|
|
} |
1315
|
|
|
|
1316
|
|
|
return "<span class='label $label_style'>" . trim(Number::formatSi($sensor['sensor_current'], 2, 3, $unit)) . '</span>'; |
1317
|
|
|
} |
1318
|
|
|
|
1319
|
|
|
/** |
1320
|
|
|
* @params int unix time |
1321
|
|
|
* @params int seconds |
1322
|
|
|
* |
1323
|
|
|
* @return int |
1324
|
|
|
* |
1325
|
|
|
* Rounds down to the nearest interval. |
1326
|
|
|
* |
1327
|
|
|
* The first argument is required and it is the unix time being |
1328
|
|
|
* rounded down. |
1329
|
|
|
* |
1330
|
|
|
* The second value is the time interval. If not specified, it |
1331
|
|
|
* defaults to 300, or 5 minutes. |
1332
|
|
|
*/ |
1333
|
|
|
function lowest_time($time, $seconds = 300) |
1334
|
|
|
{ |
1335
|
|
|
return $time - ($time % $seconds); |
1336
|
|
|
} |
1337
|
|
|
|
1338
|
|
|
/** |
1339
|
|
|
* @params int |
1340
|
|
|
* |
1341
|
|
|
* @return string |
1342
|
|
|
* |
1343
|
|
|
* This returns the subpath for working with nfdump. |
1344
|
|
|
* |
1345
|
|
|
* 1 value is taken and that is a unix time stamp. It will be then be rounded |
1346
|
|
|
* off to the lowest five minutes earlier. |
1347
|
|
|
* |
1348
|
|
|
* The return string will be a path partial you can use with nfdump to tell it what |
1349
|
|
|
* file or range of files to use. |
1350
|
|
|
* |
1351
|
|
|
* Below ie a explanation of the layouts as taken from the NfSen config file. |
1352
|
|
|
* 0 no hierachy levels - flat layout - compatible with pre NfSen version |
1353
|
|
|
* 1 %Y/%m/%d year/month/day |
1354
|
|
|
* 2 %Y/%m/%d/%H year/month/day/hour |
1355
|
|
|
* 3 %Y/%W/%u year/week_of_year/day_of_week |
1356
|
|
|
* 4 %Y/%W/%u/%H year/week_of_year/day_of_week/hour |
1357
|
|
|
* 5 %Y/%j year/day-of-year |
1358
|
|
|
* 6 %Y/%j/%H year/day-of-year/hour |
1359
|
|
|
* 7 %Y-%m-%d year-month-day |
1360
|
|
|
* 8 %Y-%m-%d/%H year-month-day/hour |
1361
|
|
|
*/ |
1362
|
|
|
function time_to_nfsen_subpath($time) |
1363
|
|
|
{ |
1364
|
|
|
$time = lowest_time($time); |
1365
|
|
|
$layout = Config::get('nfsen_subdirlayout'); |
1366
|
|
|
|
1367
|
|
|
if ($layout == 0) { |
|
|
|
|
1368
|
|
|
return 'nfcapd.' . date('YmdHi', $time); |
1369
|
|
|
} elseif ($layout == 1) { |
1370
|
|
|
return date('Y\/m\/d\/\n\f\c\a\p\d\.YmdHi', $time); |
1371
|
|
|
} elseif ($layout == 2) { |
1372
|
|
|
return date('Y\/m\/d\/H\/\n\f\c\a\p\d\.YmdHi', $time); |
1373
|
|
|
} elseif ($layout == 3) { |
1374
|
|
|
return date('Y\/W\/w\/\n\f\c\a\p\d\.YmdHi', $time); |
1375
|
|
|
} elseif ($layout == 4) { |
1376
|
|
|
return date('Y\/W\/w\/H\/\n\f\c\a\p\d\.YmdHi', $time); |
1377
|
|
|
} elseif ($layout == 5) { |
1378
|
|
|
return date('Y\/z\/\n\f\c\a\p\d\.YmdHi', $time); |
1379
|
|
|
} elseif ($layout == 6) { |
1380
|
|
|
return date('Y\/z\/H\/\n\f\c\a\p\d\.YmdHi', $time); |
1381
|
|
|
} elseif ($layout == 7) { |
1382
|
|
|
return date('Y\-m\-d\/\n\f\c\a\p\d\.YmdHi', $time); |
1383
|
|
|
} elseif ($layout == 8) { |
1384
|
|
|
return date('Y\-m\-d\/H\/\n\f\c\a\p\d\.YmdHi', $time); |
1385
|
|
|
} |
1386
|
|
|
} |
1387
|
|
|
|
1388
|
|
|
/** |
1389
|
|
|
* @params string hostname |
1390
|
|
|
* |
1391
|
|
|
* @return string |
1392
|
|
|
* |
1393
|
|
|
* Takes a hostname and transforms it to the name |
1394
|
|
|
* used by nfsen. |
1395
|
|
|
*/ |
1396
|
|
|
function nfsen_hostname($hostname) |
1397
|
|
|
{ |
1398
|
|
|
$nfsen_hostname = str_replace('.', Config::get('nfsen_split_char'), $hostname); |
1399
|
|
|
|
1400
|
|
|
if (! is_null(Config::get('nfsen_suffix'))) { |
1401
|
|
|
$nfsen_hostname = str_replace(Config::get('nfsen_suffix'), '', $nfsen_hostname); |
1402
|
|
|
} |
1403
|
|
|
|
1404
|
|
|
return $nfsen_hostname; |
1405
|
|
|
} |
1406
|
|
|
|
1407
|
|
|
/** |
1408
|
|
|
* @params string hostname |
1409
|
|
|
* |
1410
|
|
|
* @return string |
1411
|
|
|
* |
1412
|
|
|
* Takes a hostname and returns the path to the nfsen |
1413
|
|
|
* live dir. |
1414
|
|
|
*/ |
1415
|
|
|
function nfsen_live_dir($hostname) |
1416
|
|
|
{ |
1417
|
|
|
$hostname = nfsen_hostname($hostname); |
1418
|
|
|
|
1419
|
|
|
foreach (Config::get('nfsen_base') as $base_dir) { |
1420
|
|
|
if (file_exists($base_dir) && is_dir($base_dir)) { |
1421
|
|
|
return $base_dir . '/profiles-data/live/' . $hostname; |
1422
|
|
|
} |
1423
|
|
|
} |
1424
|
|
|
} |
1425
|
|
|
|
1426
|
|
|
/** |
1427
|
|
|
* Get the ZFS pools for a device... just requires the device ID |
1428
|
|
|
* an empty return means ZFS is not in use or there are currently no pools |
1429
|
|
|
* |
1430
|
|
|
* @param $device_id |
1431
|
|
|
* @return array |
1432
|
|
|
*/ |
1433
|
|
|
function get_chrony_sources($device_id) |
1434
|
|
|
{ |
1435
|
|
|
$options = [ |
1436
|
|
|
'filter' => [ |
1437
|
|
|
'type' => ['=', 'chronyd'], |
1438
|
|
|
], |
1439
|
|
|
]; |
1440
|
|
|
|
1441
|
|
|
$component = new LibreNMS\Component(); |
1442
|
|
|
$chronyd_cpnt = $component->getComponents($device_id, $options); |
1443
|
|
|
|
1444
|
|
|
if (isset($chronyd_cpnt[$device_id])) { |
1445
|
|
|
$id = $component->getFirstComponentID($chronyd_cpnt, $device_id); |
1446
|
|
|
|
1447
|
|
|
return json_decode($chronyd_cpnt[$device_id][$id]['sources']); |
1448
|
|
|
} |
1449
|
|
|
|
1450
|
|
|
return []; |
1451
|
|
|
} |
1452
|
|
|
|