Import the IP history plugin from the demo server.
[racktables-contribs] / snmplive.php
1 <?php
2
3 /********************************************
4 *
5 * RackTables 0.20.x snmp live extension
6 *
7 * displays SNMP port status
8 *
9 *
10 * needs PHP >= 5.4.0
11 * saved SNMP settings ( see snmpgeneric.php extension )
12 * also RT port names and SNMP port names must be the same ( should work fine with snmpgeneric.php created ports )
13 *
14 * (c)2015 Maik Ehinger <m.ehinger@ltur.de>
15 */
16
17 /****
18 * INSTALL
19 * just place file in plugins directory
20 *
21 */
22
23 /**
24 * The newest version of this plugin can be found at:
25 *
26 * https://github.com/github138/myRT-contribs/tree/develop-0.20.x
27 *
28 */
29
30 /* TODOs
31 *
32 * - code cleanup
33 */
34
35 /* RackTables Debug Mode */
36 //$debug_mode=1;
37
38 $tab['object']['snmplive'] = 'SNMP Live';
39 $tabhandler['object']['snmplive'] = 'snmplive_tabhandler';
40 $trigger['object']['snmplive'] = 'snmplive_tabtrigger';
41
42 $ophandler['object']['snmplive']['ajax'] = 'snmplive_opajax';
43
44 function snmplive_tabtrigger() {
45 // display tab only on IPv4 Objects
46 return considerConfiguredConstraint (spotEntity ('object', getBypassValue()), 'IPV4OBJ_LISTSRC') ? 'std' : '';
47 } /* snmplive_tabtrigger */
48
49 function snmplive_tabhandler($object_id)
50 {
51
52 addCSS(<<<ENDCSS
53 .ifoperstatus-default { background-color:#ddd; }
54 .ifoperstatus-1, .ifoperstatus-up { background-color:#00ff00; }
55 .ifoperstatus-2, .ifoperstatus-down { background-color:#ff0000; }
56 .ifoperstatus-3, .ifoperstatus-testing { background-color:#ffff66; }
57 .ifoperstatus-4, .ifoperstatus-unknown { background-color:#ffffff; }
58 .ifoperstatus-5, .ifoperstatus-dormant { background-color:#90bcf5; }
59 .ifoperstatus-6, .ifoperstatus-notPresent { }
60 .ifoperstatus-7, .ifoperstatus-lowerLayerDown { }
61
62 .port-groups { border-spacing:1px;display:table; }
63 .port-group { display:table-cell;border:3px solid #000;background-color:#c0c0c0; }
64
65 .port-column { display:table-cell;position:relative; }
66
67 .port { position:relative;width:42px;height:100px;border:2px solid #000;overflow:hidden; }
68 .port-pos-1 { margin-bottom:1px; }
69 .port-pos-2 { }
70 .port-pos-0 { margin-top:1px; }
71
72 .port-header { position:absolute }
73 .port-header-pos-1 { top:0px; }
74 .port-header-pos-0 { bottom:0px; }
75
76 .port-status { position:absolute;min-width:42px;text-align:center;font-size:10pt; }
77
78 .port-status-pos-1 { top:35px; }
79 .port-status-pos-0 { bottom:35px; }
80
81 .port-info { position:absolute;width:90%;background-color:#ddd;overflow:hidden; }
82 .port-info-pos-1 { top: 80px; }
83 .port-info-pos-0 { bottom: 80px;}
84
85 .port-name { font-size:10pt;margin:0px auto;width:40px;text-align:center; }
86 .port-number { font-size:8pt;color:#eee; }
87
88 .port-detail { position:fixed;z-index:1000;top:0px;right:0px;border:3px solid #000;background-color:#fff }
89 .port-detail-links { background-color:#ccc }
90 .hidden { visibility:hidden; }
91 .info-footer { }
92
93 ENDCSS
94 , TRUE);
95
96 echo "<div id=\"info\"></div>";
97
98 if(isset($_GET['debug']))
99 $debug = $_GET['debug'];
100 else
101 $debug = 0;
102
103 $object = spotEntity('object', $object_id);
104 amplifyCell($object);
105
106 if(isset($_GET['modules']))
107 $modules = $_GET['modules'];
108 else
109 $modules = false;
110
111 if($modules)
112 unset($_GET['modules']);
113 else
114 $_GET['modules'] = 1;
115
116 echo "<a href=".makeHref($_GET).">".($modules ? "Hide" : "Show" )." Modules</a>";
117
118 pl_layout_default($object, 0, false, $modules);
119
120 addJS(<<<ENDJS
121 function togglevisibility(elem, hide)
122 {
123 if(hide)
124 elem.css('visibility', 'hidden');
125 else
126 elem.css('visibility', 'visible');
127 //a.show();
128 //a.hide();
129 }
130
131 function setdetail(elem, hide)
132 {
133 var a = $( "#port" + elem.id + "-detail");
134
135 togglevisibility(a, hide);
136 }
137
138 function setports( data, textStatus, jqHXR ) {
139 if(data.debug)
140 $( "#info" ).html($( "#info" ).html() + "DEBUG: " + data.name + ": " + data.debug);
141
142 for(var index in data.ports)
143 {
144 setport(data, data.ports[index]);
145 }
146 }
147
148 function setportstatus( obj, port , id , detail)
149 {
150
151 tagidsuffix = "";
152
153 if(detail)
154 tagidsuffix = tagidsuffix + "-detail";
155
156 if(!detail)
157 {
158 $( "#port" + id + "-status" + tagidsuffix ).html("<table class=\"ifoperstatus-" + port.snmpinfos.
159 operstatus + "\"><tr><td>"
160 + port.snmpinfos.operstatus + "<br>" + port.snmpinfos.speed
161 + ( port.snmpinfos.vlan ? "<br>" + port.snmpinfos.vlan : "" )
162 + "</td></tr></table>");
163 return;
164 }
165
166 $( "#port" + id + "-status" + tagidsuffix ).html(port.snmpinfos.alias
167 + "<table class=\"ifoperstatus-" + port.snmpinfos.operstatus + "\"><tr><td>"
168 + (port.snmpinfos.ipv4 ? port.snmpinfos.ipv4 : "")
169 + "<br>" + port.snmpinfos.operstatus
170 + ( port.snmpinfos.vlan ? "<br>" + port.snmpinfos.vlan_name + " (" + port.snmpinfos.vlan + ")" : "" )
171 + "</td></tr></table>");
172 }
173
174 function setport( obj, port ) {
175
176 if(port.debug)
177 $( "#info" ).html($( "#info" ).html() + port.name + " " + port.debug);
178
179 if(port.snmpinfos)
180 {
181 setportstatus(obj, port, port.id, false);
182 setportstatus(obj, port, port.id, true);
183 }
184
185 }
186
187 function ajaxerror(jqHXR, textStatus, qXHR, errorThrown)
188 {
189 $( "#info" ).html($( "#info" ).html() + "<br>" + textStatus + " " + qXHR + " " + errorThrown);
190 }
191
192 $.ajax({
193 dataType: "json",
194 url: "index.php",
195 data: {
196 page: "object",
197 tab: "snmplive",
198 module: "redirect",
199 op: "ajax",
200 json: "get",
201 object_id: "$object_id",
202 debug: $debug
203 },
204 error: ajaxerror,
205 success: setports
206 });
207
208 ENDJS
209 , TRUE);
210
211 } /* snmplive_tabhandler */
212
213 /* -------------------------------------------------- */
214
215 function snmplive_opajax()
216 {
217
218 ob_start();
219 $object_id = $_REQUEST['object_id'];
220 $object = spotEntity('object', $object_id);
221
222 $object['ports'] = getObjectPortsAndLinks ($object_id);
223
224 if(isset($_GET['debug']))
225 $debug = $_GET['debug'];
226 else
227 $debug = 0;
228
229 $object['iftable'] = sl_getsnmp($object, $debug);
230
231 if($object['iftable'])
232 foreach($object['ports'] as $key => &$port)
233 {
234 // snmpinfos
235 $port['snmpinfos'] = sl_getportsnmp($object, $port, $debug);
236
237 if(!$port['snmpinfos'])
238 unset($object['ports'][$key]);
239 }
240
241 /* not needed anymore */
242 unset($object['iftable']);
243
244 /* set debug output */
245 if(ob_get_length())
246 $object['debug'] = ob_get_contents();
247
248 ob_end_clean();
249
250 echo json_encode($object);
251 exit;
252
253 } /* snmpgeneric_opcreate */
254
255 /* -------------------------------------------------- */
256
257 function pl_layout_default(&$object, $groupports = 8, $bottomstart = false, $modules = false, $portrows = 2)
258 {
259 $i = 0;
260 $portcolumn = "";
261 $linkcount = 0;
262
263 $lastmodule = null;
264 $nomodul = array();
265
266 echo "<div class=\"port-groups\">";
267 foreach($object['ports'] as $key => $port)
268 {
269
270 $object['portnames'][$port['name']] = $port;
271
272 $port_id = $port['id'];
273 $port_name = $port['name'];
274
275 $pname = $port_name;
276 $module = "";
277 $pport = "";
278 // split name in name, module, port
279 if(preg_match('/^([a-zA-Z]+)?(?:[\W]?([\d]+)?[\W])?([\d]+)?$/', $port_name, $match))
280 if(count($match) == 4)
281 list($tmp,$pname,$module,$pport) = $match;
282
283 if($port['linked'])
284 $linkcount++;
285
286 if($module == "")
287 {
288 $nomodul[] = pl_layout_port($port, count($nomodul) + 1, 1);
289 continue;
290 }
291
292 if($modules)
293 {
294 // port modules
295 if($module != $lastmodule)
296 {
297 if(($i % $portrows) != 0)
298 echo "$portcolumn</div>"; // port-column
299
300 if($groupports)
301 if(($i % $groupports) != 0)
302 echo "</div>"; // port-group
303
304 echo "</div>"; // port-groups
305
306 $i = 0;
307 $portcolumn = "";
308 echo "Modul: $module";
309 echo "<br><div class=\"port-groups\">";
310 }
311
312 $lastmodule = $module;
313 }
314
315 $i++;
316
317 if($groupports)
318 if(($i % $groupports) == 1)
319 echo "<div class=\"port-group\">";
320
321 if($portrows == 2)
322 {
323 // print each row different
324 if(($i % $portrows) == 1)
325 $pos = ($bottomstart ? 0 : 1); // 0 = bottom; 1 = top
326 else
327 $pos = ($bottomstart ? 1 : 0); // 0 = bottom; 1 = top
328 }
329 else
330 $pos = ($bottomstart ? 0 : 1); // 0 = bottom; 1 = top
331
332 $portdiv = pl_layout_port($port, $i, $pos);
333
334 if(!$bottomstart)
335 $portcolumn = "$portcolumn$portdiv";
336 else
337 $portcolumn = "$portdiv$portcolumn";
338
339 if(($i % $portrows) == 0)
340 {
341 echo "<div class=\"port-column\">";
342 echo "$portcolumn</div>";
343 $portcolumn = "";
344 }
345
346 if($groupports)
347 if(($i % $groupports) == 0)
348 echo "</div>";
349 }
350
351 if(($i % $portrows) != 0)
352 {
353 $fillcount = $portrows - ($i % $portrows);
354
355 $fill = "";
356 for($f=0;$f<$fillcount;$f++)
357 $fill .= "<div class=\"port\"></div>";
358
359 if(!$bottomstart)
360 $portcolumn .= $fill;
361 else
362 $portcolumn = "$fill$portcolumn";
363
364 echo "<div class=\"port-column\">";
365 echo "$portcolumn</div>"; // port-column
366 }
367
368 if($groupports)
369 if(($i % $groupports) != 0)
370 echo "</div>"; // port-group
371
372 echo "</div>"; // port-groups
373
374 /* Port without modul */
375 if($nomodul)
376 {
377 echo "Other Ports:<br><div id=\"nomodule\" class=\"port-groups\">";
378 foreach($nomodul as $portdiv)
379 echo "<div class=\"port-column\">$portdiv</div>";
380 echo "</div>";
381 }
382
383 return $linkcount;
384
385 } // layout_default
386
387 function pl_layout_port($port, $number, $pos)
388 {
389
390 $port_id = $port['id'];
391 $port_name = $port['name'];
392
393 $title = "Name: $port_name - No: $number - ID: $port_id";
394
395 $portdiv = "<div id=\"$port_id\" class=\"port port-pos-$pos\" onmouseover=\"setdetail(this,false);\" onmouseout=\"setdetail(this,true);\">";
396 $portheader = "<div class=\"port-header port-header-pos-$pos\">";
397 $portlabel = "<div class=\"port-number\">$number</div>";
398 $portname = "<div class=\"port-name\">$port_name</div>";
399
400 $details = "<table><tr><td>No.: $number (ID: ".$port['id'].")<br>".$port['object_name']."<br>".$port['name']."<br>"
401 .$port['label']."<br>".$port['reservation_comment']
402 ."<div id=\"port${port_id}-status-detail\">No Status</div></td>";
403
404 if($port['linked'])
405 $details .= "<td>Remote:<br>".$port['cableid']."<br>".$port['remote_object_name']."<br>".$port['remote_name']."<div id=\"port${port_id}-status-detail-remote\">No Remote Status</div></td>";
406
407 $details .= "</tr></table>";
408
409
410 $portdetail = "<div id=\"port${port_id}-detail\" class=\"port-detail hidden\" onclick=\"togglevisibility(this,true);\">$details</div>";
411
412 $portstatus = "<div id=\"port${port_id}-status\" class=\"port-status port-status-pos-$pos\" title=\"$title\">-</div>";
413
414 if($pos) {
415 $portheader .= "$portlabel$portname</div>";
416 $portdiv .= "$portheader$portstatus<div class=\"port-info port-info-pos-$pos\"></div></div>$portdetail";
417 }
418 else
419 {
420 $portheader .= "$portname$portlabel</div>";
421 $portdiv .= "<div class=\"port-info port-info-pos-$pos\"></div>$portstatus$portheader</div>$portdetail";
422 }
423
424 return $portdiv;
425 }
426 /* ------------------------------------------------------- */
427
428 function sl_getportsnmp(&$object, $port, $debug = false)
429 {
430 $ipv4 = $object['SNMP']['IP'];
431
432 $port_name = $port['name'];
433
434 // SNMP up / down
435 if(!isset($object['iftable'][$port_name]))
436 return false;
437
438 $ifoperstatus = $object['iftable'][$port_name]['status'];
439
440 $ifspeed = $object['iftable'][$port_name]['speed'];
441
442 $ifalias = $object['iftable'][$port_name]['alias'];
443
444 $vlan="";
445 $vlan_name="";
446
447 if(isset($object['iftable'][$port_name]['vlan']))
448 {
449 $vlan = $object['iftable'][$port_name]['vlan'];
450 $vlan_name = $object['iftable'][$port_name]['vlan_name'];
451 }
452
453 return array(
454 'ipv4' => $ipv4,
455 'operstatus' => $ifoperstatus,
456 'alias' => $ifalias,
457 'speed' => $ifspeed,
458 'name' => $port_name,
459 'vlan' => $vlan,
460 'vlan_name' => $vlan_name,
461 );
462
463 } // sl_getportsnmp
464
465 function sl_getsnmp(&$object, $debug = false)
466 {
467 $object_id = $object['id'];
468 $object_name = $object['name'];
469
470 if(isset($object['SNMP']))
471 {
472 if($debug)
473 echo "INFO: No SNMP Object \"$object_name\" ID: $object_id<br>";
474 return null;
475 }
476
477 if(!considerConfiguredConstraint($object, 'IPV4OBJ_LISTSRC'))
478 {
479 if($debug)
480 echo "INFO: No IPv4 Object \"$object_name\" ID: $object_id<br>";
481
482 return False;
483 }
484
485 /* get object saved SNMP settings */
486 $snmpconfig = explode(':', strtok($object['comment'],"\n\r"));
487
488 if($snmpconfig[0] != "SNMP")
489 {
490
491 if($debug)
492 echo "INFO: No saved SNMP Settings for \"$object_name\" ID: $object_id<br>";
493
494 return False;
495 }
496
497 /* set objects SNMP ip address */
498 $ipv4 = $snmpconfig[1];
499
500 if(0)
501 var_dump_html($snmpconfig);
502
503 if(!$ipv4)
504 {
505 echo "ERROR: no ip for \"$object_name!!\"<br>";
506
507 return False;
508 }
509
510 $object['SNMP']['IP'] = $ipv4;
511
512 if(count($snmpconfig) < 4 )
513 {
514 echo "SNMP Error: Missing Setting for $object_name ($ipv4)";
515
516 return False;
517 }
518
519 /* SNMP prerequisites successfull */
520
521 $s = new sl_ifxsnmp($snmpconfig[2], $ipv4, $snmpconfig[3], $snmpconfig);
522
523 if(!$s->error)
524 {
525
526 /* get snmp data */
527 $iftable = $s->getiftable();
528
529 if($debug && $s->error)
530 echo $s->getError();
531
532 if($iftable)
533 return $iftable;
534 else
535 {
536
537 echo "SNMP Error: ".$s->getError()." for $object_name ($ipv4)<br>";
538 return False;
539 }
540
541 }
542 else
543 {
544 echo "SNMP Config Error: ".$s->error." for \"$object_name\"<br>";
545 return False;
546 }
547
548 return null;
549
550 } // sl_getsnmp
551 /* ------------------ */
552 class sl_ifxsnmp extends SNMP
553 {
554
555 public $error = false;
556
557 function __construct($version, $hostname, $community, $security = null)
558 {
559
560 switch($version)
561 {
562 case "1":
563 case "v1":
564 $version = parent::VERSION_1;
565 break;
566 case "2":
567 case "2c":
568 case "v2c":
569 $version = parent::VERSION_2c;
570 break;
571 case "3":
572 case "v3":
573 $version = parent::VERSION_3;
574 break;
575 }
576
577 parent::__construct($version, $hostname, $community);
578
579 if($version == SNMP::VERSION_3)
580 {
581 if($security !== null && count($security) == 9)
582 {
583 $auth_passphrase = base64_decode($security[6]);
584 $priv_passphrase = base64_decode($security[8]);
585
586 if(!$this->setsecurity($security[4], $security[5], $auth_passphrase, $security[7], $priv_passphrase))
587 {
588
589 $this->error = "Security Error for v3 ($hostname)";
590 return;
591 }
592
593 }
594 else
595 {
596 $this->error = "Missing security settings for v3 ($hostname)";
597 return;
598 }
599 }
600
601 $this->quick_print = 1;
602 $this->oid_output_format = SNMP_OID_OUTPUT_NUMERIC;
603 }
604
605 function getiftable()
606 {
607 $oid_ifindex = '.1.3.6.1.2.1.2.2.1.1'; // iftable
608 $oid_ifoperstatus = '.1.3.6.1.2.1.2.2.1.8'; //iftable
609 $oid_ifspeed = '.1.3.6.1.2.1.2.2.1.5'; //iftable
610 $oid_ifdescr = '.1.3.6.1.2.1.2.2.1.2'; //iftable
611 $oid_ifhighspeed = '.1.3.6.1.2.1.31.1.1.1.15'; //ifXtable
612 $oid_ifname = '.1.3.6.1.2.1.31.1.1.1.1'; //ifXtable
613 $oid_ifalias = '.1.3.6.1.2.1.31.1.1.1.18'; //ifXtable
614
615 $ifindex = $this->walk($oid_ifindex); // iftable
616
617 if($ifindex === FALSE)
618 {
619 return FALSE;
620 exit;
621 }
622
623 $ifname = $this->walk($oid_ifname, TRUE); //ifXtable
624
625 if($ifname == false)
626 $ifname = $this->walk($oid_ifdescr, TRUE); //ifXtable
627
628 $ifalias = $this->walk($oid_ifalias, TRUE); //ifXtable
629
630 $ifspeed = $this->walk($oid_ifspeed, TRUE); //iftable
631 $ifhighspeed = $this->walk($oid_ifhighspeed, TRUE); //ifXtable
632
633 $this->enum_print = false;
634 $ifoperstatus = $this->walk($oid_ifoperstatus, TRUE); //iftable
635
636 $retval = array();
637 foreach($ifindex as $index)
638 {
639 $retval[$ifname[$index]]['ifindex'] = $index;
640
641 $retval[$ifname[$index]]['status'] = $ifoperstatus[$index];
642
643 $retval[$ifname[$index]]['alias'] = $ifalias[$index];
644
645 $highspeed = $ifhighspeed[$index];
646 if($highspeed)
647 $speed = $highspeed;
648 else
649 $speed = $ifspeed[$index];
650
651 if($speed >= 1000000) // 1Mbit
652 $speed /= 1000000;
653
654 $speed = ($speed >= 1000 ? ($speed / 1000)."Gb" : $speed."Mb" );
655
656 $retval[$ifname[$index]]['speed'] = "$speed";
657
658 }
659
660 $this->get8021qvlan($retval);
661
662 if(0)
663 sl_var_dump_html($retval);
664
665 return $retval;
666 }
667
668 /* append vlan to each port in retval */
669 function get8021qvlan(&$retval)
670 {
671 //$oid_dot1dBasePort = '.1.3.6.1.2.1.17.1.4.1.1';
672 $oid_dot1dBasePortIfIndex = '.1.3.6.1.2.1.17.1.4.1.2'; // dot1 index -> if index
673 $oid_dot1qPvid = '.1.3.6.1.2.1.17.7.1.4.5.1.1';
674 $oid_dot1qVlanStaticName = '.1.3.6.1.2.1.17.7.1.4.3.1.1';
675
676 // @ supprress warning
677 $dot1dbaseportifindex = @$this->walk($oid_dot1dBasePortIfIndex, TRUE);
678
679 if($dot1dbaseportifindex === false)
680 {
681 $this->error = true;
682 return;
683 }
684
685 $dot1qpvid = $this->walk($oid_dot1qPvid, TRUE);
686 $dot1qvlanstaticname = $this->walk($oid_dot1qVlanStaticName, TRUE);
687
688 $ifindexdot1dbaseport = array_flip($dot1dbaseportifindex);
689
690 $ret = array();
691 foreach($retval as $ifname => &$port)
692 {
693 if(!isset($ifindexdot1dbaseport[$port['ifindex']]))
694 continue;
695
696 $dot1index = $ifindexdot1dbaseport[$port['ifindex']];
697 $vlan = $dot1qpvid[$dot1index];
698 $retval[$ifname]['vlan'] = $vlan;
699 $retval[$ifname]['vlan_name'] = $dot1qvlanstaticname[$vlan];
700 }
701
702 }
703 } // sl_ifxsnmp
704
705 /* ------------------------------------------------------- */
706 /* for debugging */
707 function sl_var_dump_html(&$var, $text = '') {
708
709 echo "<pre>------------------Start Var Dump - $text -----------------------\n";
710 var_dump($var);
711 echo "\n---------------------END Var Dump - $text -----------------------</pre>";
712 }
713 ?>