1package NetSNMP::manager; 2 3use strict (); 4use warnings; 5use Apache::Constants qw(:common); 6use CGI qw(:standard delete_all); 7use SNMP (); 8use DBI (); 9use NetSNMP::manager::displaytable qw(displaytable displaygraph); 10 11# globals 12$NetSNMP::manager::hostname = 'localhost'; # Host that serves the mSQL Database 13$NetSNMP::manager::dbname = 'snmp'; # mySQL Database name 14$NetSNMP::manager::user = 'root'; 15# $NetSNMP::manager::pass = "password"; 16$NetSNMP::manager::imagebase = "/home/hardaker/src/snmp/manager"; # <=== CHANGE ME ==== 17$NetSNMP::manager::redimage = "/graphics/red.gif"; 18$NetSNMP::manager::greenimage = "/graphics/green.gif"; 19#$NetSNMP::manager::verbose = 1; 20$NetSNMP::manager::tableparms = "border=1 bgcolor=\"#c0c0e0\""; 21$NetSNMP::manager::headerparms = "border=1 bgcolor=\"#b0e0b0\""; 22 23# init the snmp library 24$SNMP::save_descriptions=1; 25#SNMP::init_mib(); 26 27%NetSNMP::manager::myorder = qw(id 0 oidindex 1 host 2 updated 3); 28 29sub handler { 30 my $r = shift; 31 Apache->request($r); 32 33 # get info from handler 34 my $hostname = $r->dir_config('hostname') || $NetSNMP::manager::hostname; 35 my $dbname = $r->dir_config('dbname') || $NetSNMP::manager::dbname; 36 my $sqluser = $r->dir_config('user') || $NetSNMP::manager::user; 37 my $pass = $r->dir_config('pass') || $NetSNMP::manager::pass; 38 my $verbose = $r->dir_config('verbose') || $NetSNMP::manager::verbose; 39 40#=========================================================================== 41# Global defines 42#=========================================================================== 43 44my ($dbh, $query, $remuser); 45 46$remuser = $ENV{'REMOTE_USER'}; 47$remuser = "guest" if (!defined($remuser) || $remuser eq ""); 48 49#=========================================================================== 50# Connect to the mSQL database with the appropriate driver 51#=========================================================================== 52($dbh = DBI->connect("DBI:mysql:database=$dbname;host=$hostname", $sqluser, $pass)) 53 or die "\tConnect not ok: $DBI::errstr\n"; 54 55#=========================================================================== 56# stats Images, for inclusion on another page. (ie, slashdot user box) 57#=========================================================================== 58if (my $group = param('groupstat')) { 59 $r->content_type("image/gif"); 60 $r->send_http_header(); 61 my $cur = getcursor($dbh, "select host from usergroups as ug, hostgroups as hg where ug.groupname = '$group' and hg.groupname = '$group' and user = '$remuser'"); 62 while (my $row = $cur->fetchrow_hashref ) { 63 if (checkhost($dbh, $group, $row->{'host'})) { 64 open(I, "$NetSNMP::manager::imagebase$NetSNMP::manager::redimage"); 65 while(read(I, $_, 4096)) { print; } 66 close(I); 67 } 68 } 69 open(I, "$NetSNMP::manager::imagebase$NetSNMP::manager::greenimage"); 70 while(read(I, $_, 4096)) { print; } 71 close(I); 72 return OK(); 73} 74 75 76sub date_format { 77 my $time = shift; 78 my @out = localtime($time); 79 my $ret = $out[4] . "-" . $out[3] . "-" . $out[5] . " " . $out[2] . " " . $out[1]; 80# print STDERR "$time: $ret\n"; 81 return $ret; 82} 83 84 85# 86# Graphing of historical data 87# 88if ((param('displaygraph') || param('dograph')) && param('table')) { 89 my $host = param('host'); 90 my $group = param('group'); 91 if (!isuser($dbh, $remuser, $group)) { 92 $r->content_type("image/png"); 93 $r->send_http_header(); 94 print "Unauthorized access to that group ($group)\n"; 95 return Exit($dbh, $group); 96 } 97 my $table = param('table'); 98 my @columns; 99 100 if (!param('dograph')) { 101 $r->content_type("text/html"); 102 $r->send_http_header(); 103 print "<body bgcolor=\"#ffffff\">\n"; 104 print "<form>\n"; 105 print "<table border=1><tr><td>\n"; 106 107 print "<table>\n"; 108 print "<tr align=top><th></th><th>Select indexes<br>to graph</th></tr>\n"; 109 110 my $handle = getcursor($dbh, "SELECT sql_small_result distinct(oidindex) FROM $table where host = '$host'"); 111 my @cols; 112 while ( $row = $handle->fetchrow_hashref ) { 113 print "<tr><td>$row->{oidindex}</td><td><input type=checkbox value=1 name=" . 'graph_' . displaytable::to_unique_key($row->{'oidindex'}) . "></td></tr>\n"; 114 } 115 print "</table>\n"; 116 117 print "</td><td>\n"; 118 119 print "<table>\n"; 120 print "<tr align=top><th></th><th>Select Columns<br>to graph</th></tr>\n"; 121 my $handle = getcursor($dbh, "SELECT * FROM $table limit 1"); 122 my $row = $handle->fetchrow_hashref; 123 map { print "<tr><td>$_</td><td><input type=checkbox value=1 name=column_" . displaytable::to_unique_key($_) . "></td></tr>\n"; } keys(%$row); 124 print "</table>\n"; 125 126 print "</td></tr></table>\n"; 127 128 print "<br>Graph as a Rate: <input type=checkbox value=1 name=graph_as_rate><br>\n"; 129 print "<br>Maximum Y Value: <input type=text value=inf name=max_y><br>\n"; 130 print "<br>Minimum Y Value: <input type=text value=-inf name=min_y><br>\n"; 131 132 print "<input type=hidden name=table value=\"$table\">\n"; 133 print "<input type=hidden name=host value=\"$host\">\n"; 134 print "<input type=hidden name=dograph value=1>\n"; 135 print "<input type=hidden name=group value=\"$group\">\n"; 136 print "<input type=submit name=\"Make Graph\">\n"; 137 138 print "</form>\n"; 139 140 my $handle = getcursor($dbh, "SELECT distinct(oidindex) FROM $table where host = '$host' order by oidindex"); 141 return Exit($dbh, $group); 142 } 143 if (param('graph_all_data')) { 144 $clause = "host = '$host'"; 145 } else { 146 my $handle = getcursor($dbh, "SELECT distinct(oidindex) FROM $table where host = '$host'"); 147 $clause = "where ("; 148 while ( $row = $handle->fetchrow_hashref ) { 149# print STDERR "graph test: " . $row->{'oidindex'} . "=" . "graph_" . displaytable::to_unique_key($row->{'oidindex'}) . "=" . param("graph_" . displaytable::to_unique_key($row->{'oidindex'})) . "\n"; 150 if (param("graph_" . displaytable::to_unique_key($row->{'oidindex'}))) { 151 $clause .= " or oidindex = " . $row->{'oidindex'} . ""; 152 } 153 } 154 155 my $handle = getcursor($dbh, "SELECT * FROM $table limit 1"); 156 my $row = $handle->fetchrow_hashref; 157 map { push @columns, $_ if (param('column_' . displaytable::to_unique_key($_))) } keys(%$row); 158 159 $clause .= ")"; 160 $clause =~ s/\( or /\(/; 161 if ($clause =~ /\(\)/ || $#columns == -1) { 162 $r->content_type("text/html"); 163 $r->send_http_header(); 164 print "<body bgcolor=\"#ffffff\">\n"; 165 print "<h1>No Data to Graph</h1>\n"; 166 print STDERR "No data to graph: $clause, $#columns\n"; 167 return Exit($dbh, "$group"); 168 } 169 $clause .= " and host = '$host'"; 170 } 171 172# print STDERR "graphing clause: $clause\n"; 173 174 # all is ok, display the graph 175 176 $r->content_type("image/png"); 177 $r->send_http_header(); 178 179 print STDERR "graphing clause: $clause, columns: ", join(", ",@columns), "\n"; 180 my @args; 181 push (@args, '-rate', '60') if (param('graph_as_rate')); 182 push (@args, '-max', param('max_y')) if (param('max_y') && param('max_y') =~ /^[-.\d]+$/); 183 push (@args, '-min', param('min_y')) if (param('min_y') && param('min_y') =~ /^[-.\d]+$/); 184 185 my $ret = 186 displaygraph($dbh, $table, 187# '-xcol', "date_format(updated,'%m-%d-%y %h:%i')", 188 '-xcol', "unix_timestamp(updated)", 189 '-pngparms', [ 190 'x_labels_vertical', '1', 191 'x_tick_number', 6, 192 'x_number_format', \&date_format, 193 'y_label', 'Count/Min', 194 'title', $table, 195# 'y_min_value', 0, 196 ], 197 '-clauses', "$clause order by updated", 198 @args, 199 '-columns', \@columns, 200 '-indexes', ['oidindex']); 201 print STDERR "$ret rows graphed\n"; 202 return OK(); 203} 204 205#=========================================================================== 206# Start HTML. 207#=========================================================================== 208$r->content_type("text/html"); 209$r->send_http_header(); 210print "<body bgcolor=\"#ffffff\">\n"; 211print "<h1>UCD-SNMP Management Console</h1>\n"; 212print "<hr>\n"; 213 214#=========================================================================== 215# Display mib related data information 216#=========================================================================== 217if (param('displayinfo')) { 218 makemibtable(param('displayinfo')); 219 return Exit($dbh, ""); 220} 221 222#=========================================================================== 223# Display a generic sql table of any kind (debugging). 224#=========================================================================== 225# if (my $disptable = param('displaytable')) { 226# if (param('editable') == 1) { 227# print "<form submit=dont>\n"; 228# displaytable($disptable, -editable, 1); 229# print "</form>\n"; 230# } else { 231# displaytable($disptable); 232# } 233# return Exit($dbh, ""); 234# } 235 236#=========================================================================== 237# Get host and group from CGI query. 238#=========================================================================== 239my $host = param('host'); 240my $group = param('group'); 241 242#=========================================================================== 243# Editable user information 244#=========================================================================== 245 246if (param('setuponcall')) { 247 print "<title>oncall schedule for user: $remuser</title>\n"; 248 print "<h2>oncall schedule for user: $remuser</h2>\n"; 249 print "<p>Please select your oncall schedule and mailing addresses for your groups below:"; 250 if (!isexpert($remuser)) { 251 print "<ul>\n"; 252 print "<li>Values for the days/hours fields can be comma seperated lists of hours/days/ranges. EG: hours: 7-18,0-4.\n"; 253 print "</ul>\n"; 254 } 255 print "<form method=post><input type=hidden name=setuponcall value=1>\n"; 256 displaytable($dbh, 'oncall', 257 '-clauses',"where user = '$remuser' order by groupname", 258 '-select','id, user, groupname, email, pager, days, hours', 259 '-selectorder', 1, 260 '-notitle', 1, 261 '-editable', 1, 262 '-indexes', ['id','user','groupname'], 263 '-CGI', $CGI::Q 264 ); 265 print "<input type=submit value=\"submit changes\">\n"; 266 print "</form>\n"; 267 return Exit($dbh, $group); 268} 269 270#=========================================================================== 271# show the list of groups a user belongs to. 272#=========================================================================== 273if (!defined($group)) { 274 my @groups = getgroupsforuser($dbh, $remuser); 275 print "<title>Net-SNMP Group List</title>\n"; 276 print "<h2>Host groupings you may access:</h2>\n"; 277 if (!isexpert($remuser)) { 278 print "<ul>\n"; 279 print "<li>Click on a group to operate or view the hosts in that group.\n"; 280 print "<li>Click on a red status light below to list the problems found.\n"; 281 print "</ul>\n"; 282 } 283 284 if ($#groups > 0) { 285 displaytable($dbh, 'usergroups', 286 '-clauses', "where (user = '$remuser')", 287 '-select', 'distinct groupname', 288 '-notitle', 1, 289 '-printonly', ['groupname'], 290 '-datalink', sub { my $q = self_url(); 291 my $key = shift; 292 my $h = shift; 293 return if ($key ne "groupname"); 294 return addtoken($q,"group=$h"); 295 }, 296 '-beginhook', 297 sub { 298 my $q = self_url(); 299 my($dbh, $junk, $data) = @_; 300 if (!defined($data)) { 301 print "<th>Status</th>"; 302 return; 303 } 304 my ($cur, $row); 305 $cur = getcursor($dbh, "select host from hostgroups where groupname = '$data->{groupname}'"); 306 while ( $row = $cur->fetchrow_hashref ) { 307 if (checkhost($dbh, $data->{'groupname'}, 308 $row->{'host'})) { 309 print "<td><a href=\"" . addtoken($q,"group=$data->{groupname}&summarizegroup=1") . "\"><img border=0 src=$NetSNMP::manager::redimage></a></td>\n"; 310 return; 311 } 312 } 313 print "<td><img src=$NetSNMP::manager::greenimage></td>\n"; 314 } 315 ); 316 $dbh->disconnect(); 317 return Exit($dbh, $group); 318 } else { 319 if ($#groups == -1) { 320 print "You are not configured to use the Net-SNMP-manager, please contact your system administrator."; 321 return Exit($dbh, $group); 322 } 323 $group = $groups[0]; 324 } 325} 326 327#=========================================================================== 328# reject un-authorized people accessing a certain group 329#=========================================================================== 330if (!isuser($dbh, $remuser, $group)) { 331 print "Unauthorized access to that group ($group)\n"; 332 return Exit($dbh, $group); 333} 334 335#=========================================================================== 336# add a new host to a group 337#=========================================================================== 338if (defined(my $newhost = param('newhost'))) { 339 if (isadmin($dbh, $remuser, $group)) { 340 if ($dbh->do("select * from hostgroups where host = '$newhost' and groupname = '$group'") eq "0E0") { 341 $dbh->do("insert into hostgroups(host,groupname) values('$newhost','$group')") ; 342 } else { 343 print "<b>ERROR: host $newhost already in $group</b>\n"; 344 } 345 CGI::delete('newhost'); 346 } 347} 348 349#=========================================================================== 350# display setup configuration for a group 351#=========================================================================== 352if (defined(param('setupgroup'))) { 353 if (isadmin($dbh, $remuser, $group)) { 354 setupgroup($dbh, $group); 355 } else { 356 print "<h2>You're not able to perform setup operations for group $group\n"; 357 } 358 return Exit($dbh, $group); 359} 360 361#=========================================================================== 362# save configuration information submitted about a group 363#=========================================================================== 364if (defined(param('setupgroupsubmit')) && 365 isadmin($dbh, $remuser, $group)) { 366 setupgroupsubmit($dbh, $group); 367 delete_all(); 368 param(-name => 'group', -value => $group); 369 print "<a href=\"" . self_url() . "\">Entries submitted</a>"; 370 return Exit($dbh, $group); 371} 372 373#=========================================================================== 374# user preferences 375#=========================================================================== 376if (defined(param('userprefs'))) { 377 setupuserpreferences($dbh, $remuser, $group); 378 return Exit($dbh, $group); 379} 380 381#=========================================================================== 382# save submitted user preferences 383#=========================================================================== 384if (defined(param('setupuserprefssubmit')) && 385 isadmin($dbh, $remuser, $group)) { 386 setupusersubmit($dbh, $remuser, $group); 387 delete_all(); 388 param(-name => 'group', -value => $group); 389 print "<a href=\"" . self_url() . "\">Entries submitted</a>"; 390 return Exit($dbh, $group); 391} 392 393#=========================================================================== 394# summarize problems in a group 395#=========================================================================== 396if (defined(param('summarizegroup'))) { 397 print "<title>group problem summary: $group</title>\n"; 398 print "<h2>The following is a list of problems in the group \"$group\":</h2>\n"; 399 summarizeerrors($dbh, "where groupname = '$group'"); 400 return Exit($dbh, $group); 401} 402 403#=========================================================================== 404# summarize problems on a host 405#=========================================================================== 406if (defined($host) && defined(param('summarizehost'))) { 407 print "<title>host summary: $host</title>\n"; 408 print "<h2>The following is a list of problems for the host \"$host\":</h2>\n"; 409 summarizeerrors($dbh, "where groupname = '$group' and host = '$host'"); 410 return Exit($dbh, $group); 411} 412 413#=========================================================================== 414# display a list of hosts in a group 415#=========================================================================== 416if (!defined($host)) { 417 print "<title>Net-SNMP Host $host</title>\n"; 418 print "<h2>Hosts in the group \"$group\":</h2>\n"; 419 if (!isexpert($remuser)) { 420 print "<ul>\n"; 421 if (isadmin($dbh, $remuser, $group)) { 422 my $q = self_url(); 423 $q =~ s/\?.*//; 424 print "<li>Make sure you <a href=\"" . addtoken($q,"group=$group&setupgroup=1") . "\">set up the host</a> for the SNMP tables you want to monitor.\n"; 425 } 426 print "<li>Click on a hostname to operate on or view the information tables associated with that group.\n"; 427 print "<li>Click on a red status light below to list the problems found in with a particular host.\n"; 428 print "</ul>\n"; 429 } 430 displaytable($dbh, 'hostgroups', 431 '-notitle',0, 432 '-clauses', "where (groupname = '$group')", 433 '-select', 'distinct host, sysObjectId, sysDescr, sysUpTime, versionTag', 434 '-datalink', sub { my $q = self_url(); 435 my $key = shift; 436 my $h = shift; 437 return if ($key ne "host"); 438 return addtoken($q,"host=$h"); 439 }, 440 '-beginhook', 441 sub { 442 my $q = self_url(); 443 my($dbh, $junk, $data) = @_; 444 if (!defined($data)) { 445 print "<th>Status</th>"; 446 return; 447 } 448 if (checkhost($dbh, $group, $data->{'host'})) { 449 print "<td><a href=\"" . addtoken($q,"group=$group&summarizehost=1&host=$data->{host}") . "\"><img border=0 src=$NetSNMP::manager::redimage></a></td>\n"; 450 } else { 451 print "<td><img src=$NetSNMP::manager::greenimage></td>\n"; 452 } 453 } 454 ); 455 if (isadmin($dbh, $remuser, $group)) { 456 addhostentryform($group); 457 my $q = self_url(); 458 $q =~ s/\?.*//; 459 print "<a href=\"" . addtoken($q,"group=$group&setupgroup=1") . "\">setup group $group</a>\n"; 460 } 461 return Exit($dbh, $group); 462} 463 464#=========================================================================== 465# setup the host's history records 466#=========================================================================== 467if (param('setuphost')) { 468 print "<title>Net-SNMP history setup for host: $host</title>\n"; 469 print "<h2>Net-SNMP history setup for the host: \"$host\"</h2>\n"; 470 print "<p>Enter the number of days to keep the data for a given table for the host \"$host\":\n"; 471 if (!isexpert($remuser)) { 472 print "<ul>\n"; 473 print "<li>Numbers must be greater than or equal to 1 to enable history logging.\n"; 474 print "</ul>\n"; 475 } 476 print "<form method=post><input type=hidden name=setuphost value=1><input type=hidden name=host value=\"$host\"><input type=hidden name=group value=\"$group\">\n"; 477 displaytable($dbh, 'hosttables', 478 '-clauses',"where host = '$host' and groupname = '$group'", 479 '-select','groupname, host, tablename, keephistory', 480 '-selectorder', 1, 481 '-notitle', 1, 482 '-editable', 1, 483 '-indexes', ['groupname','host','tablename'], 484 '-CGI', $CGI::Q 485 ); 486 print "<input type=submit value=\"submit changes\">\n"; 487 print "</form>\n"; 488 return Exit($dbh, $group); 489} 490 491#=========================================================================== 492# display a huge table of history about something 493#=========================================================================== 494if (param('displayhistory')) { 495 if (!isuser($dbh, $remuser, $group)) { 496 print "Unauthorized access to that group ($group)\n"; 497 return Exit($dbh, $group); 498 } 499 displaytable($dbh, param('table'), 500 '-clauses', "where (host = '$host')", 501 '-dolink', \&linktodisplayinfo, 502 '-dontdisplaycol', "select * from userprefs where user = '$remuser' and groupname = '$group' and tablename = ? and columnname = ? and displayit = 'N'" 503 ); 504 return Exit($dbh, $group); 505} 506 507#=========================================================================== 508# display inforamation about a host 509# optionally add new collection tables 510#=========================================================================== 511showhost($dbh, $host, $group, $remuser); 512if (isadmin($dbh, $remuser, $group)) { 513 if (param('newtables')) { 514 my $x = param('newtables'); 515 $x =~ s/,/ /g; 516 if (/[^\w\s]/) { 517 print "<br>Illegal table names in addition list: $x<br>\n" 518 } else { 519 my @x = split(/\s+/,$x); 520 foreach my $i (@x) { 521 $dbh->do("insert into hosttables(host, groupname, tablename, keephistory) values('$host','$group','$i','0')"); 522 } 523 print "<br>adding: ",join(", ",@x),"<br>\n"; 524 } 525 } else { 526 print "<br>Add new MIB Tables or Groups that you want to collect for this host: <form><input type=hidden name=host value=\"$host\"><input type=hidden name=group value=\"$group\"><input name=\"newtables\" type=text><br><input type=submit value=\"add tables\"></form>\n"; 527 } 528 my $q = self_url(); 529 $q =~ s/\?.*//; 530 print "<a href=\"" . addtoken($q, "setuphost=1&host=$host&group=$group") . "\">setup host $host</a>\n"; 531} 532return Exit($dbh, $group); 533 534#=========================================================================== 535# END of handler 536#=========================================================================== 537 538} 539 540# add a token to a url string. Use either a ? or an & depending on 541# existence of ?. 542sub addtoken { 543 my $url = shift; 544 my $token = shift; 545 return "$url&$token" if ($url =~ /\?/); 546 return "$url?$token"; 547} 548 549# 550# summarizeerrors(DB-HANDLE, CLAUSE): 551# summarize the list of errors in a given CLAUSE 552# 553sub summarizeerrors { 554 my $dbh = shift; 555 my $clause = shift; 556 $clause = "where" if ($clause eq ""); 557 my $clause2 = $clause; 558 $clause2 =~ s/ host / hosterrors.host /; 559 560 # Major errors 561 displaytable($dbh, 'hosterrors, hostgroups', # , hostgroups 562 '-select', "hosterrors.host as host, errormsg", 563 '-notitle', 1, 564 '-title', "Fatal Errors", 565 '-clauses', "$clause2 and hosterrors.host = hostgroups.host", 566 '-beginhook', sub { 567 if ($#_ < 2) { 568 #doing header; 569 print "<td></td>"; 570 } else { 571 print "<td><img src=\"$NetSNMP::manager::redimage\"></td>\n"; 572 }}); 573 574 my $tabletop = "<br><table $NetSNMP::manager::tableparms><tr $NetSNMP::manager::headerparms><th><b>Host</b></th><th><b>Table</b></th><th><b>Description</b></th></tr>\n"; 575 my $donetop = 0; 576 my $cursor = 577 getcursor($dbh, "SELECT * FROM hosttables $clause"); 578 579 while (my $row = $cursor->fetchrow_hashref ) { 580 581 my $exprs = getcursor($dbh, "SELECT * FROM errorexpressions where (tablename = '$row->{tablename}')"); 582 583 while (my $expr = $exprs->fetchrow_hashref ) { 584 my $errors = getcursor($dbh, "select * from $row->{tablename} where $expr->{expression} and host = '$row->{host}'"); 585 while (my $error = $errors->fetchrow_hashref ) { 586 print $tabletop if ($donetop++ == 0); 587 print "<tr><td>$row->{host}</td><td>$row->{tablename}</td><td>$expr->{returnfield}: $error->{$expr->{returnfield}}</td></tr>"; 588 } 589 } 590 } 591 print "</table>"; 592} 593 594# 595# getcursor(CMD): 596# genericlly get a cursor for a given sql command, displaying and 597# printing errors where necessary. 598# 599sub getcursor { 600 my $dbh = shift; 601 my $cmd = shift; 602 my $cursor; 603 ( $cursor = $dbh->prepare( $cmd )) 604 or print "\nnot ok: $DBI::errstr\n"; 605 ( $cursor->execute ) 606 or print( "\tnot ok: $DBI::errstr\n" ); 607 return $cursor; 608} 609 610# 611# mykeysort($a, $b) 612# sorts $a and $b against the order in the mib or against the hard 613# coded special list. 614# 615sub mykeysort { 616 my $a = $displaytable::a; 617 my $b = $displaytable::b; 618 my $mb = $SNMP::MIB{SNMP::translateObj($b)}; 619 my $ma = $SNMP::MIB{SNMP::translateObj($a)}; 620 621 return $NetSNMP::manager::myorder{$a} <=> $NetSNMP::manager::myorder{$b} if ((defined($NetSNMP::manager::myorder{$a}) || !defined($ma->{'subID'})) && (defined($NetSNMP::manager::myorder{$b}) || !defined($mb->{'subID'}))); 622 return 1 if (defined($NetSNMP::manager::myorder{$b}) || !defined($mb->{'subID'})); 623 return -1 if (defined($NetSNMP::manager::myorder{$a}) || !defined($ma->{'subID'})); 624 625 $ma->{'subID'} <=> $mb->{'subID'}; 626} 627 628# 629# checkhost(GROUP, HOST): 630# if anything in a host is an error, as defined by the 631# errorexpressions table, return 1, else 0 632# 633sub checkhost { 634 my $dbh = shift; 635 my $group = shift; 636 my $host = shift; 637 my ($tblh); 638 639 return 2 if ($dbh->do("select * from hosterrors where host = '$host'") ne "0E0"); 640 641 # get a list of tables we want to display 642 $tblh = getcursor($dbh, "SELECT * FROM hosttables where (host = '$host' and groupname = '$group')"); 643 644 # table data 645 my($exprs, $tablelist); 646 while ( $tablelist = $tblh->fetchrow_hashref ) { 647 $exprs = getcursor($dbh, "SELECT * FROM errorexpressions where (tablename = '$tablelist->{tablename}')"); 648 while(my $expr = $exprs->fetchrow_hashref) { 649 if ($dbh->do("select * from $tablelist->{tablename} where $expr->{expression} and host = '$host'") ne "0E0") { 650 return 1; 651 } 652 } 653 } 654 return 0; 655} 656 657# 658# showhost(HOST): 659# 660# display all the tables monitored for a given host (in a group). 661# 662sub showhost { 663 my $dbh = shift; 664 my $host = shift; 665 my $group = shift; 666 my $remuser = shift; 667 my $q = self_url(); 668 $q =~ s/\?.*//; 669 # host header 670 print "<title>Net-SNMP manager report for host: $host</title>\n"; 671 print "<h2>Monitored information for the host $host</h2>\n"; 672 if (!isexpert($remuser)) { 673 print "<ul>\n"; 674 print "<li>Click on a column name for information about the data in that column.\n"; 675 print "<li>Click on a column name or table name for information about the data in the table.\n"; 676 print "<li>If you are <a href=\"" . addtoken($q, "setuphost=1&host=$host&group=$group") . "\">collecting past history</a> for a data set, links will appear below the table that allow you to view and/or graph the historic data.\n"; 677 print "</ul>\n"; 678 } 679 680 # does the host have a serious error? 681 682 my $errlist = getcursor($dbh, "SELECT * FROM hosterrors where (host = '$host')"); 683 if ( $dbh->do("SELECT * FROM hosterrors where (host = '$host')") ne "0E0") { 684 displaytable($dbh, 'hosterrors', 685 '-clauses', "where (host = '$host')", 686 '-dontdisplaycol', "select * from userprefs where user = '$remuser' and groupname = '$group' and tablename = ? and columnname = ? and displayit = 'N'", 687 '-beginhook', sub { 688 if ($#_ < 2) { 689 #doing header; 690 print "<td></td>"; 691 } else { 692 print "<td><img src=\"$NetSNMP::manager::redimage\"></td>\n"; 693 }}); 694 } 695 696 # get a list of tables we want to display 697 my $tblh = getcursor($dbh, "SELECT * FROM hosttables where (host = '$host' and groupname = '$group')"); 698 699 # table data 700 my($tablelist); 701 while ( $tablelist = $tblh->fetchrow_hashref ) { 702 703 displaytable($dbh, $tablelist->{'tablename'}, 704 '-clauses', "where (host = '$host') order by oidindex", 705 '-dontdisplaycol', "select * from userprefs where user = '$remuser' and groupname = '$group' and tablename = ? and columnname = ? and displayit = 'N'", 706 '-sort', \&mykeysort, 707 '-dolink', \&linktodisplayinfo, 708 '-beginhook', \&printredgreen); 709 if ($tablelist->{'keephistory'}) { 710 my $q = self_url(); 711 $q =~ s/\?.*//; 712 print "history: "; 713 print "<a href=\"" . addtoken($q, "displayhistory=1&host=$host&group=$group&table=$tablelist->{'tablename'}hist") . "\">[table]</a>\n"; 714 print "<a href=\"" . addtoken($q, "displaygraph=1&host=$host&group=$group&table=$tablelist->{'tablename'}hist") . "\">[graph]</a>\n"; 715 print "<br>\n"; 716 } 717 } 718} 719 720# 721# linktodisplayinfo(STRING): 722# 723# returns a url to the appropriate displayinfo link if STRING is a 724# mib node. 725# 726sub linktodisplayinfo { 727 return if (exists($NetSNMP::manager::myorder{shift})); 728 return self_url() . "&displayinfo=" . shift; 729} 730 731# printredgreen(TABLENAME, DATA): 732# 733# display a red or a green dot in a table dependent on the table's 734# values and associated expression 735# 736# DATA is NULL when in a header row (displaying header names). 737# 738sub printredgreen { 739 my $dbh = shift; 740 my $tablename = shift; 741 my $data = shift; 742 my ($exprs, $expr, $img); 743 744 if (!defined($data)) { 745 #doing header; 746 print "<td></td>"; 747 return; 748 } 749 750 my $cmd = "SELECT * FROM errorexpressions where (tablename = '$tablename')"; 751 print " $cmd\n" if ($NetSNMP::manager::verbose); 752 ( $exprs = $dbh->prepare( $cmd ) ) 753 or die "\nnot ok: $DBI::errstr\n"; 754 ( $exprs->execute ) 755 or print( "\tnot ok: $DBI::errstr\n" ); 756 757 $img = $NetSNMP::manager::greenimage; 758 while($expr = $exprs->fetchrow_hashref) { 759 if ($dbh->do("select oidindex from $tablename where host = '$data->{host}' and oidindex = '$data->{oidindex}' and $expr->{expression}") ne "0E0") { 760 $img = $NetSNMP::manager::redimage; 761 } 762 } 763 print "<td><img src=$img></td>"; 764} 765 766# 767# display information about a given mib node as a table. 768# 769sub makemibtable { 770 my $dispinfo = shift; 771 # display information about a data type in a table 772 my $mib = $SNMP::MIB{SNMP::translateObj($dispinfo)}; 773 print "<table $NetSNMP::manager::tableparms><tr><td>\n"; 774 foreach my $i (qw(label type access status units hint moduleID description enums)) { 775# foreach my $i (keys(%$mib)) { 776 next if (!defined($$mib{$i}) || $$mib{$i} eq ""); 777 next if (ref($$mib{$i}) eq "HASH" && $#{keys(%{$$mib{$i}})} == -1); 778 print "<tr><td>$i</td><td>"; 779 if (ref($$mib{$i}) eq "HASH") { 780 print "<table $NetSNMP::manager::tableparms><tr><td>\n"; 781 foreach my $j (sort { $$mib{$i}{$a} <=> $$mib{$i}{$b} } keys(%{$$mib{$i}})) { 782 print "<tr><td>$$mib{$i}{$j}</td><td>$j</td></tr>"; 783 } 784 print "</table>\n"; 785 } else { 786 print "$$mib{$i}"; 787 } 788 print "</td></tr>\n"; 789 } 790 print "</table>\n"; 791} 792 793# given a user, get all the groups he belongs to. 794sub getgroupsforuser { 795 my (@ret, $cursor, $row); 796 my ($dbh, $remuser) = @_; 797 ( $cursor = $dbh->prepare( "SELECT * FROM usergroups where (user = '$remuser')")) 798 or die "\nnot ok: $DBI::errstr\n"; 799 ( $cursor->execute ) 800 or print( "\tnot ok: $DBI::errstr\n" ); 801 802 while ( $row = $cursor->fetchrow_hashref ) { 803 push(@ret, $row->{'groupname'}); 804 } 805 @ret; 806} 807 808# given a host, get all the groups it belongs to. 809sub gethostsforgroup { 810 my (@ret, $cursor, $row); 811 my ($dbh, $group) = @_; 812 ( $cursor = $dbh->prepare( "SELECT * FROM hostgroups where (groupname = '$group')")) 813 or die "\nnot ok: $DBI::errstr\n"; 814 ( $cursor->execute ) 815 or print( "\tnot ok: $DBI::errstr\n" ); 816 817 while ( $row = $cursor->fetchrow_hashref ) { 818 push(@ret, $row->{'host'}); 819 } 820 @ret; 821} 822 823# display the host add entry box 824sub addhostentryform { 825 my $group = shift; 826 print "<form method=\"get\" action=\"" . self_url() . "\">\n"; 827 print "Add a new host to the group \"$group\": <input type=\"text\" name=\"newhost\"><br>"; 828 print "<input type=\"hidden\" name=\"group\" value=\"$group\">"; 829 print "<input type=submit value=\"Add Hosts\">\n"; 830 print "</form>"; 831} 832 833#is an expert user? 834sub isexpert { 835 return 0; 836} 837 838#is remuser a admin? 839sub isadmin { 840 my ($dbh, $remuser, $group) = @_; 841 return 0 if (!defined($remuser) || !defined($group)); 842 return 1 if ($dbh->do("select * from usergroups where user = '$remuser' and groupname = '$group' and isadmin = 'Y'") ne "0E0"); 843 return 0; 844} 845 846#is user a member of this group? 847sub isuser { 848 my ($dbh, $remuser, $group) = @_; 849 return 0 if (!defined($remuser) || !defined($group)); 850 return 1 if ($dbh->do("select * from usergroups where user = '$remuser' and groupname = '$group'") ne "0E0"); 851 return 0; 852} 853 854# displayconfigarray(HOSTS, NAMES, CONFIG): 855# 856# displays an array of generic check buttons to turn on/off certain 857# variables. 858sub displayconfigarray { 859 my $dbh = shift; 860 my $hosts = shift; 861 my $names = shift; 862 my %config = @_; 863 864 my $cmd; 865 if ($config{'-check'}) { 866 ( $cmd = $dbh->prepare( $config{'-check'} ) ) 867 or die "\nnot ok: $DBI::errstr\n"; 868 } 869 870 print "<table $NetSNMP::manager::tableparms>\n"; 871 print "<tr><td></td>"; 872 my ($i, $j); 873 foreach $j (@$names) { 874 my $nj = $j; 875 $nj = $j->[0] if ($config{'-arrayrefs'} || $config{'-arrayref2'}); 876 print "<td>$nj</td>"; 877 } 878 foreach my $i (@$hosts) { 879 my $ni = $i; 880 $ni = $i->[0] if ($config{'-arrayrefs'} || $config{'-arrayref1'}); 881 print "<tr><td>$ni</td>"; 882 foreach $j (@$names) { 883 my $nj = $j; 884 $nj = $j->[0] if ($config{'-arrayrefs'} || $config{'-arrayref2'}); 885 my $checked = "checked" if (defined($cmd) && $cmd->execute($ni,$nj) ne "0E0"); 886 print "<td><input type=checkbox $checked value=y name=" . $config{prefix} . $ni . $nj . "></td>\n"; 887 } 888 print "</tr>\n"; 889 } 890 print "</tr>"; 891 print "</table>"; 892} 893 894sub adddefaulttables { 895 my ($dbh, $names) = @_; 896 my $row; 897 # add in known expression tables. 898 my $handle = getcursor($dbh, "SELECT * FROM errorexpressions"); 899 900 expr: 901 while($row = $handle->fetchrow_hashref) { 902 foreach $i (@$names) { 903 if ($i->[0] eq $row->{tablename}) { 904 next expr; 905 } 906 } 907 push @$names, [$row->{tablename}]; 908 } 909} 910 911# 912# display the setup information page for a given group. 913# 914sub setupgroup { 915 my $dbh = shift; 916 my $group = shift; 917 918 my ($hosts, $names) = gethostandgroups($dbh, $group); 919 adddefaulttables($dbh, $names); 920 921 print "<form method=\"post\" action=\"" . self_url() . "\">\n"; 922 print "<input type=hidden text=\"setupgroupsubmit\" value=\"y\">"; 923 displayconfigarray($dbh, $hosts, $names, 924 -arrayrefs, 1, 925 -check, "select * from hosttables where (host = ? and tablename = ? and groupname = '$group')"); 926 print "<input type=hidden name=group value=\"$group\">\n"; 927 print "<input type=submit value=submit name=\"setupgroupsubmit\">\n"; 928 print "</form>"; 929} 930 931# a wrapper around fetching arrays of everything in a table. 932sub getarrays { 933 my $dbh = shift; 934 my $table = shift; 935 my %config = @_; 936 my $selectwhat = $config{'-select'} || "*"; 937 my $handle; 938 939 $handle = getcursor($dbh, "SELECT $selectwhat FROM $table $config{-clauses}"); 940 return $handle->fetchall_arrayref; 941} 942 943# 944# get a list of all tablenames and hostnames for a given group. 945# 946sub gethostandgroups { 947 my $dbh = shift; 948 my $group = shift; 949 my ($tbnms); 950 951 my $names = getarrays($dbh, 'hosttables', 952 "-select", 'distinct tablename', 953 "-clauses", "where groupname = '$group'"); 954 955 my $hosts = getarrays($dbh, 'hostgroups', 956 "-select", 'distinct host', 957 "-clauses", "where groupname = '$group'"); 958 959 return ($hosts, $names); 960} 961 962sub setupgroupsubmit { 963 my $dbh = shift; 964 my $group = shift; 965 966 my ($hosts, $names) = gethostandgroups($dbh, $group); 967 adddefaulttables($dbh, $names); 968 969 foreach my $i (@$hosts) { 970 $dbh->do("delete from hosttables where host = '${$i}[0]' and groupname = '$group'"); 971 } 972 my $rep = $dbh->prepare("insert into hosttables(host,tablename,groupname) values(?,?,'$group')"); 973 974 foreach my $i (@$hosts) { 975 foreach my $j (@$names) { 976 if (param("${$i}[0]" . "${$j}[0]")) { 977 print "test: ","${$i}[0] : ${$j}[0]<br>\n"; 978 $rep->execute("${$i}[0]", "${$j}[0]") || print "$! $DBI::errstr<br>\n"; 979 } 980 } 981 } 982 983} 984 985# 986# save user pref data submitted by the user 987# 988sub setupusersubmit { 989 my ($dbh, $remuser, $group) = @_; 990 my $tables = getarrays($dbh, 'hosttables', 991 "-select", 'distinct tablename', 992 "-clauses", "where groupname = '$group'"); 993 994 $dbh->do("delete from userprefs where user = '$remuser' and groupname = '$group'"); 995 my $rep = $dbh->prepare("insert into userprefs(user, groupname, tablename, columnname, displayit) values('$remuser', '$group', ?, ?, 'N')"); 996 997 my ($i, $j); 998 foreach my $i (@$tables) { 999 my $sth = $dbh->prepare("select * from ${$i}[0] where 1 = 0"); 1000 $sth->execute(); 1001 1002 foreach $j (@{$sth->{NAME}}) { 1003 if (param("${$i}[0]" . "$j")) { 1004 $rep->execute("${$i}[0]", "$j"); 1005 } 1006 } 1007 } 1008} 1009 1010sub Exit { 1011 my ($dbh, $group) = @_; 1012 my $tq = self_url(); 1013 $tq =~ s/\?.*//; 1014 print "<hr>\n"; 1015 print "<a href=\"$tq\">[TOP]</a>\n"; 1016 print "<a href=\"$tq?userprefs=1&group=$group\">[display options]</a>\n"; 1017 print "<a href=\"$tq?setuponcall=1\">[setup oncall schedule]</a>\n"; 1018 if (defined($group)) { 1019 print "<a href=\"$tq?group=$group\">[group: $group]</a>\n"; 1020 print "<a href=\"$tq?group=$group&summarizegroup=1\">[summarize errors]</a>\n"; 1021 } 1022 $dbh->disconnect() if (defined($dbh)); 1023 return OK(); 1024# exit shift; 1025} 1026 1027# 1028# setup user preferences by displaying a configuration array of 1029# checkbuttons for each table. 1030# 1031sub setupuserpreferences { 1032 my ($dbh, $remuser, $group) = @_; 1033 my $tables = getarrays($dbh, 'hosttables', 1034 "-select", 'distinct tablename', 1035 "-clauses", "where groupname = '$group'"); 1036 1037 print "<h3>Select the columns from the tables that you want to <b>hide</b> below and click on submit:</h3>\n"; 1038 print "<form method=\"post\" action=\"" . self_url() . "\">\n"; 1039 1040 my ($i, $j); 1041 foreach my $i (@$tables) { 1042 my $sth = $dbh->prepare("select * from ${$i}[0] where 1 = 0"); 1043 $sth->execute(); 1044 displayconfigarray($dbh, [${$i}[0]], $sth->{NAME}, 1045 -check, "select * from userprefs where (tablename = ? and columnname = ? and user = '$remuser' and groupname = '$group' and displayit = 'N')"); 1046 print "<br>\n"; 1047 } 1048 print "<input type=hidden name=group value=\"$group\">\n"; 1049 print "<input type=submit value=submit name=\"setupuserprefssubmit\">\n"; 1050 print "</form>"; 1051} 1052