From 1f1eda9764dbb161433350bd56eb8e1c33b950dd Mon Sep 17 00:00:00 2001 From: Adam Amstrong Date: Wed, 28 Oct 2009 13:49:37 +0000 Subject: [PATCH] Major updates on the road to 0.7 git-svn-id: http://www.observium.org/svn/observer/trunk@492 61d68cd4-352d-0410-923a-c4978735b2b8 --- 060-to-current.sql | 77 ++ CHANGELOG | 2 +- README | 93 +-- check-errors.php | 8 +- discover-cdp.php | 24 +- html/graph.php | 117 ++- html/includes/.confirm_login.php.swp | Bin 12288 -> 0 bytes html/includes/.login.inc.php.swo | Bin 159744 -> 0 bytes html/includes/.login.inc.php.swp | Bin 159744 -> 0 bytes .../graphs/cisco_entity_sensor.inc.php | 41 +- html/includes/graphs/common.inc.php | 4 +- html/includes/graphs/device_cpu.inc.php | 4 +- html/includes/graphs/device_memory.inc.php | 6 + html/includes/graphs/temperature.inc.php | 10 +- html/includes/print-device-graph.php | 16 +- ...phs.php => print-interface-graphs.inc.php} | 16 +- ...-interface.inc => print-interface.inc.php} | 43 +- html/includes/topnav.inc | 2 +- html/pages/customers.php | 11 +- html/pages/device/graphs.inc.php | 57 +- html/pages/device/graphs/netstats.inc.php | 8 +- html/pages/device/graphs/os-ios.inc.php | 6 +- html/pages/device/graphs/uptime.inc.php | 2 +- html/pages/device/health/temp.inc.php | 2 +- html/pages/device/interface.inc.php | 26 +- html/pages/device/port/macaccounting.inc.php | 94 ++- html/pages/device/ports.inc.php | 8 +- html/pages/front/jt.php | 6 +- html/pages/iftype.php | 4 +- html/pages/interfaces.php | 2 +- html/pages/vrf.php | 2 +- includes/common.php | 6 + includes/functions-poller.inc.php | 128 ++++ includes/functions.php | 20 +- includes/graphing.php | 692 +----------------- includes/graphing/unix.php | 96 +-- includes/polling/cisco-mac-accounting.inc.php | 86 +++ includes/polling/interfaces.inc.php | 6 +- includes/polling/ports.inc.php | 167 +++++ includes/procurve-graphing.php | 14 +- includes/static-config.php | 4 +- includes/unix-graphing.php | 100 +-- poll-device.php | 58 +- poll-mac_accounting.php | 91 --- poller.php | 84 +++ scripts/update-sql.php | 13 + test-poll.php | 13 +- 47 files changed, 1034 insertions(+), 1235 deletions(-) create mode 100644 060-to-current.sql delete mode 100644 html/includes/.confirm_login.php.swp delete mode 100644 html/includes/.login.inc.php.swo delete mode 100644 html/includes/.login.inc.php.swp rename html/includes/{print-interface-graphs.php => print-interface-graphs.inc.php} (53%) rename html/includes/{print-interface.inc => print-interface.inc.php} (83%) create mode 100644 includes/functions-poller.inc.php create mode 100755 includes/polling/cisco-mac-accounting.inc.php create mode 100755 includes/polling/ports.inc.php delete mode 100755 poll-mac_accounting.php create mode 100755 poller.php create mode 100755 scripts/update-sql.php diff --git a/060-to-current.sql b/060-to-current.sql new file mode 100644 index 000000000..f6e79a785 --- /dev/null +++ b/060-to-current.sql @@ -0,0 +1,77 @@ +ALTER TABLE `interfaces` ADD `pagpOperationMode` VARCHAR( 32 ) NULL; +ALTER TABLE `interfaces` ADD `pagpPortState` VARCHAR( 16 ) NULL; +ALTER TABLE `interfaces` ADD `pagpPartnerDeviceId` VARCHAR( 48 ) NULL; +ALTER TABLE `interfaces` ADD `pagpPartnerLearnMethod` VARCHAR( 16 ) NULL; +ALTER TABLE `interfaces` ADD `pagpPartnerIfIndex` INT NULL; +ALTER TABLE `interfaces` ADD `pagpPartnerGroupIfIndex` INT NULL; +ALTER TABLE `interfaces` ADD `pagpPartnerDeviceName` VARCHAR( 128 ) NULL; +ALTER TABLE `interfaces` ADD `pagpEthcOperationMode` VARCHAR( 16 ) NULL; +ALTER TABLE `interfaces` ADD `pagpDeviceId` VARCHAR( 48 ) NULL; +ALTER TABLE `interfaces` ADD `pagpGroupIfIndex` INT NULL; +ALTER TABLE `interfaces` ADD `portName` VARCHAR( 128 ) NULL DEFAULT NULL AFTER `ifName`; +ALTER TABLE `interfaces` ADD `ifHighSpeed` INT ( 11 ) NULL DEFAULT NULL AFTER `ifSpeed`; +ALTER TABLE `mac_accounting` ADD `cipMacHCSwitchedBytes_input` bigint(20) default NULL; +ALTER TABLE `mac_accounting` ADD `cipMacHCSwitchedBytes_input_prev` bigint(20) default NULL; +ALTER TABLE `mac_accounting` ADD `cipMacHCSwitchedBytes_input_delta` bigint(20) default NULL; +ALTER TABLE `mac_accounting` ADD `cipMacHCSwitchedBytes_input_rate` int(11) default NULL; +ALTER TABLE `mac_accounting` ADD `cipMacHCSwitchedBytes_output` bigint(20) default NULL; +ALTER TABLE `mac_accounting` ADD `cipMacHCSwitchedBytes_output_prev` bigint(20) default NULL; +ALTER TABLE `mac_accounting` ADD `cipMacHCSwitchedBytes_output_delta` bigint(20) default NULL; +ALTER TABLE `mac_accounting` ADD `cipMacHCSwitchedBytes_output_rate` int(11) default NULL; +ALTER TABLE `mac_accounting` ADD `cipMacHCSwitchedPkts_input` bigint(20) default NULL; +ALTER TABLE `mac_accounting` ADD `cipMacHCSwitchedPkts_input_prev` bigint(20) default NULL; +ALTER TABLE `mac_accounting` ADD `cipMacHCSwitchedPkts_input_delta` bigint(20) default NULL; +ALTER TABLE `mac_accounting` ADD `cipMacHCSwitchedPkts_input_rate` int(11) default NULL; +ALTER TABLE `mac_accounting` ADD `cipMacHCSwitchedPkts_output` bigint(20) default NULL; +ALTER TABLE `mac_accounting` ADD `cipMacHCSwitchedPkts_output_prev` bigint(20) default NULL; +ALTER TABLE `mac_accounting` ADD `cipMacHCSwitchedPkts_output_delta` bigint(20) default NULL; +ALTER TABLE `mac_accounting` ADD `cipMacHCSwitchedPkts_output_rate` int(11) default NULL; +ALTER TABLE `mac_accounting` ADD `poll_time` int(11) default NULL; +ALTER TABLE `mac_accounting` ADD `poll_prev` int(11) default NULL; +ALTER TABLE `mac_accounting` ADD `poll_period` int(11) default NULL; +ALTER TABLE `interfaces` ADD `ifInUcastPkts` bigint(20) default NULL; +ALTER TABLE `interfaces` ADD `ifInUcastPkts_prev` bigint(20) default NULL; +ALTER TABLE `interfaces` ADD `ifInUcastPkts_delta` bigint(20) default NULL; +ALTER TABLE `interfaces` ADD `ifInUcastPkts_rate` int(11) default NULL; +ALTER TABLE `interfaces` ADD `ifOutUcastPkts` bigint(20) default NULL; +ALTER TABLE `interfaces` ADD `ifOutUcastPkts_prev` bigint(20) default NULL; +ALTER TABLE `interfaces` ADD `ifOutUcastPkts_delta` bigint(20) default NULL; +ALTER TABLE `interfaces` ADD `ifOutUcastPkts_rate` int(11) default NULL; +ALTER TABLE `interfaces` ADD `ifInErrors` bigint(20) default NULL; +ALTER TABLE `interfaces` ADD `ifInErrors_prev` bigint(20) default NULL; +ALTER TABLE `interfaces` ADD `ifInErrors_delta` bigint(20) default NULL; +ALTER TABLE `interfaces` ADD `ifInErrors_rate` int(11) default NULL; +ALTER TABLE `interfaces` ADD `ifOutErrors` bigint(20) default NULL; +ALTER TABLE `interfaces` ADD `ifOutErrors_prev` bigint(20) default NULL; +ALTER TABLE `interfaces` ADD `ifOutErrors_delta` bigint(20) default NULL; +ALTER TABLE `interfaces` ADD `ifOutErrors_rate` int(11) default NULL; +ALTER TABLE `interfaces` ADD `ifInOctets` bigint(20) default NULL; +ALTER TABLE `interfaces` ADD `ifInOctets_prev` bigint(20) default NULL; +ALTER TABLE `interfaces` ADD `ifInOctets_delta` bigint(20) default NULL; +ALTER TABLE `interfaces` ADD `ifInOctets_rate` int(11) default NULL; +ALTER TABLE `interfaces` ADD `ifOutOctets` bigint(20) default NULL; +ALTER TABLE `interfaces` ADD `ifOutOctets_prev` bigint(20) default NULL; +ALTER TABLE `interfaces` ADD `ifOutOctets_delta` bigint(20) default NULL; +ALTER TABLE `interfaces` ADD `ifOutOctets_rate` int(11) default NULL; +ALTER TABLE `interfaces` ADD `poll_time` int(11) default NULL; +ALTER TABLE `interfaces` ADD `poll_prev` int(11) default NULL; +ALTER TABLE `interfaces` ADD `poll_period` int(11) default NULL; +ALTER TABLE `interfaces` ADD `pagpOperationMode` VARCHAR( 32 ) NULL ; +ALTER TABLE `interfaces` ADD `pagpPortState` VARCHAR( 16 ) NULL ; +ALTER TABLE `interfaces` ADD `pagpPartnerDeviceId` VARCHAR( 48 ) NULL ; +ALTER TABLE `interfaces` ADD `pagpPartnerLearnMethod` VARCHAR( 16 ) NULL ; +ALTER TABLE `interfaces` ADD `pagpPartnerIfIndex` INT NULL ; +ALTER TABLE `interfaces` ADD `pagpPartnerGroupIfIndex` INT NULL ; +ALTER TABLE `interfaces` ADD `pagpPartnerDeviceName` VARCHAR( 128 ) NULL ; +ALTER TABLE `interfaces` ADD `pagpEthcOperationMode` VARCHAR( 16 ) NULL ; +ALTER TABLE `interfaces` ADD `pagpDeviceId` VARCHAR( 48 ) NULL ; +ALTER TABLE `interfaces` ADD `pagpGroupIfIndex` INT NULL ; +ALTER TABLE `interfaces` ADD `ifPromiscuousMode` VARCHAR( 12 ) NULL DEFAULT NULL AFTER `ifSpeed`; +ALTER TABLE `interfaces` ADD `ifConnectorPresent` VARCHAR( 12 ) NULL DEFAULT NULL AFTER `ifSpeed`; +ALTER TABLE `interfaces` ADD `ifName` VARCHAR( 64 ) NULL DEFAULT NULL AFTER `ifDescr`; +ALTER TABLE `interfaces` ADD `portName` VARCHAR( 128 ) NULL DEFAULT NULL AFTER `ifName`; +ALTER TABLE `interfaces` ADD `ifHighSpeed` INT ( 11 ) NULL DEFAULT NULL AFTER `ifSpeed`; +ALTER TABLE `interfaces` DROP `in_rate`; +ALTER TABLE `interfaces` DROP `out_rate`; +ALTER TABLE `interfaces` DROP `in_errors`; +ALTER TABLE `interfaces` DROP `out_errors`; diff --git a/CHANGELOG b/CHANGELOG index e865506f3..f0475428d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,4 @@ -Release 0.6.0 ( ) +Release 0.6.0 ( 28th August 2009 ) Changed IPv6 database structure and discovery *** DATABASE CHANGE *** Added CollectD integration code diff --git a/README b/README index 963cc5c8f..ff3c33189 100644 --- a/README +++ b/README @@ -1,71 +1,48 @@ -README FOR JPGRAPH 3.0.x -======================== +Copyright (C) 2006-2009 Adam Armstrong -This package contains JpGraph, an Object Oriented PHP5 Graph Plotting library. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -The library is Copyright (C) 2001-2009 Aditus Consulting and -released under dual license QPL 1.0 for open source and educational -use and JpGraph Professional License for commercial use. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -Please see full license details at http://www.aditus.nu/jpgraph/ + You should have received a copy of the GNU General Public License + along with this program. If not, see . -* -------------------------------------------------------------------- -* PHP4 IS NOT SUPPORTED in the 2.x or 3.x series -* -------------------------------------------------------------------- - -Requirements: -------------- -Miminum: -* PHP 5.1.0 or higher -* GD 2.0.28 or higher -Note: Earlier versions might work but is unsupported. +Please see COPYING for usage requirements and restrictions. -Recommended: -* PHP >= 5.2.0 -* PHP Built-in GD library +Introduction +------------ + +Observer is an auto-discovering network monitoring system. + +It's designed to be an easily-navigable interface to the health of your network. + + + +Planned Features +---------------- + +* CollectD Integration * In Progress +* Full IPv6 capabilities * In Progress +* Pseudowire (MPLS/L2TP) tracking * In Progress +* MPLS IP-VPN tracking * In Progress +* 95th and metered usage tracking * In Progress +* Nagios Integration * Too scary for contempation Installation ------------ -0. Make sure that the PHP version is compatible with the stated requirements - and that the PHP installation has support for the GD library. - Please run phpinfo() to check if GD library - is supported in the installation. - If the GD library doesn't seem to be installed - please consult the PHP manual under section "Image" for - instructions on where to find this library. Please refer to - the manual section "Verifying your PHP installation" - -1. Unzip and copy the files to a directory of your choice where Your - httpd sever can access them. - For a global site installation you should copy the files to - somewhere in the PHP search path. -2. Check that the default directory paths in jpg-config.inc - for cache directory and TTF directory suits your installation. - Note1: The default directories are different depending on if - the library is running on Windows or UNIX. - Note2: Apache/PHP must have write permission to your cache - directory if you enable the cache feature. By default the cache - is disabled. +Installation of Observer is currently not for the faint of heart! There is no automated +install script, so it'll probably take quite a bit of fiddling! -3. Check that all rest of the DEFINE in jpg-config.inc - is setup to your preference. The default should be fine - for most users. +Please see http://www.observernms.org. -4. Read the chapters on installation in the manual. +Please email adama@memetic.org with any feature requests, bug reports or just to tell me +that you're using observer! -Documentation -------------- -The installation includes HTML documentation and reference guide for the -library. The portal page for all the documentation is -/docs/index.html - - -Bug reports and suggestions ---------------------------- -Should be reported using the the issue tracker at - -http://www.aditus.nu/bugtraq - - diff --git a/check-errors.php b/check-errors.php index 7dcd45c47..2e0af9baf 100755 --- a/check-errors.php +++ b/check-errors.php @@ -12,11 +12,9 @@ $i = '0'; $interface_query = mysql_query("SELECT * FROM `interfaces` AS I, `devices` AS D WHERE I.device_id = D.device_id $where"); while ($interface = mysql_fetch_array($interface_query)) { - $rrdfile = $config['rrd_dir'] . "/" . $interface['hostname'] . "/" . $interface['ifIndex'] . ".rrd"; - $errors = interface_errors($rrdfile); - mysql_query("UPDATE `interfaces` SET in_errors = '" . $errors['in'] . "', out_errors = '" . $errors['out'] . "' WHERE interface_id = '" . $interface['interface_id'] . "'"); - if($errors['in'] > '100' || $errors['out'] > '100') { - $errored[] = $interface['hostname'] . " - " . $interface['ifDescr'] . " - " . $interface['ifAlias'] . " - " . $errors['in'] . " - " . $errors['out']; + $errors = $interface['ifInErrors_delta'] + $interface['ifOutErrors_delta']; + if($errors > '1') { + $errored[] = $interface['hostname'] . " - " . $interface['ifDescr'] . " - " . $interface['ifAlias'] . " - " . $interface['ifInErrors_delta'] . " - " . $interface['ifOutErrors_delta']; } $i++; } diff --git a/discover-cdp.php b/discover-cdp.php index db0a22535..6ca754b0e 100755 --- a/discover-cdp.php +++ b/discover-cdp.php @@ -25,19 +25,23 @@ while ($device = mysql_fetch_array($device_query)) { $host = $id; echo("\nDetecting CDP neighbours on $device[1]...\n"); - $snmp = new snmpCDP($hostname, $community); - $ports = $snmp->getports(); - $cdp = $snmp->explore_cdp($ports); +# $snmp = new snmpCDP($hostname, $community); +# $ports = $snmp->getports(); +# $cdp = $snmp->explore_cdp($ports); - $cdp_links = ""; +# $cdp_links = ""; - foreach (array_keys($cdp) as $key) { - $port = $ports[$key]; - $link = $cdp[$key]; - $cdp_links .= $hostname . "," . $port['desc'] . "," . $link['host'] . "," . $link['port'] . "\n"; - } +# foreach (array_keys($cdp) as $key) { +# $port = $ports[$key]; +# $link = $cdp[$key]; +# $cdp_links .= $hostname . "," . $port['desc'] . "," . $link['host'] . "," . $link['port'] . "\n"; +# } - $cdp_links = trim($cdp_links); +# $cdp_links = trim($cdp_links); + + + + foreach ( explode("\n" ,$cdp_links) as $link ) { if ($link == "") { break; } diff --git a/html/graph.php b/html/graph.php index 9f5f72006..1178ae1f7 100644 --- a/html/graph.php +++ b/html/graph.php @@ -1,5 +1,6 @@ ".$config['rrdtool'] . " graph $graphfile $rrd_options"); + $thing = shell_exec($config['rrdtool'] . " graph $graphfile $rrd_options"); + if(is_file($graphfile)) { + header('Content-type: image/png'); + echo(`cat $graphfile`); + } else { + header('Content-type: image/png'); + $string = "Graph Generation Error"; + $im = imagecreate($width, $height); + $orange = imagecolorallocate($im, 255, 255, 255); + $px = (imagesx($im) - 7.5 * strlen($string)) / 2; + imagestring($im, 3, $px, $height / 2 - 8, $string, imagecolorallocate($im, 128, 0, 0)); + imagepng($im); + imagedestroy($im); + } + } else { + switch ($type) { case 'cisco_entity_sensor': $graph = graph_entity_sensor ($_GET['a'], $graphfile, $from, $to, $width, $height, $title, $vertical); @@ -79,7 +96,6 @@ if($_GET['debug']) { $groups = array($_GET['interfaces'], $_GET['interfaces_b'], $_GET['interfaces_c']); $graph = graph_multi_bits_trio ($groups, $graphfile, $from, $to, $width, $height, $title, $vertical, $inverse, $legend); break; - case 'adsl_rate': $graph = graph_adsl_rate ($hostname. "/adsl-4.rrd", $graphfile, $from, $to, $width, $height); break; @@ -102,21 +118,6 @@ if($_GET['debug']) { case 'mac_acc_bits': $graph = graph_mac_acc ($_GET['id'], $graphfile, $from, $to, $width, $height, $title, $vertical); break; - case 'bits': - $graph = graph_bits ($hostname . "/". $ifIndex . ".rrd", $graphfile, $from, $to, $width, $height, $title, $vertical, $inverse, $legend); - break; - case 'pkts': - $graph = pktsgraph ($hostname . "/". $ifIndex . ".rrd", $graphfile, $from, $to, $width, $height, $title, $vertical); - break; - case 'errors': - $graph = errorgraph ($hostname . "/". $ifIndex . ".rrd", $graphfile, $from, $to, $width, $height, $title, $vertical); - break; - case 'nupkts': - $graph = nucastgraph ($hostname . "/". $ifIndex . ".rrd", $graphfile, $from, $to, $width, $height, $title, $vertical); - break; - case 'uptime': - $graph = uptimegraph ($hostname . "/uptime.rrd", $graphfile, $from, $to, $width, $height, $title, $vertical); - break; case 'unixfs_dev': $graph = unixfsgraph_dev ($device_id, $graphfile, $from, $to, $width, $height, $title, $vertical); break; @@ -134,39 +135,6 @@ if($_GET['debug']) { case 'calls': $graph = callsgraphSNOM ($hostname . "/data.rrd", $graphfile, $from, $to, $width, $height, $title, $vertical); break; - case 'ip_graph': - $graph = ip_graph ($hostname . "/netinfo.rrd", $graphfile, $from, $to, $width, $height, $title, $vertical); - break; - case 'icmp_graph': - $graph = icmp_graph ($hostname . "/netinfo.rrd", $graphfile, $from, $to, $width, $height, $title, $vertical); - break; - case 'tcp_graph': - $graph = tcp_graph ($hostname . "/netinfo.rrd", $graphfile, $from, $to, $width, $height, $title, $vertical); - break; - case 'udp_graph': - $graph = udp_graph ($hostname . "/netinfo.rrd", $graphfile, $from, $to, $width, $height, $title, $vertical); - break; - case 'cpu': - if($os == "Linux" || $os == "NetBSD" || $os == "FreeBSD" || $os == "DragonFly" || $os == "OpenBSD" || $os == "Windows" || $os == "m0n0wall" || $os == "Voswall" || $os == "pfSense" || $os == "DragonFly" || $os == "OpenBSD") { - $graph = cpugraphUnix ($hostname . "/cpu.rrd", $graphfile, $from, $to, $width, $height, $title, $vertical); - } elseif($os == "IOS" || $os == "IOS XE") { - $graph = graph_device_cpmCPU ($device_id, $graphfile, $from, $to, $width, $height, $title, $vertical); - } elseif($os == "CatOS") { - $graph = cpugraph ($hostname . "/cpu.rrd", $graphfile, $from, $to, $width, $height, $title, $vertical); - } elseif($os == "Windows") { - $graph = cpugraphwin ($hostname . "/cpu.rrd", $graphfile, $from, $to, $width, $height, $title, $vertical); - } elseif($os == "ProCurve") { - $graph = cpugraphHP ($hostname . "/cpu.rrd", $graphfile, $from, $to, $width, $height, $title, $vertical); - } elseif($os == "Snom") { - $graph = callsgraphSNOM ($hostname . "/data.rrd", $graphfile, $from, $to, $width, $height, $title, $vertical); - } elseif($os == "ScreenOS") { - $graph = graph_netscreen_cpu ($hostname . "/netscreen-cpu.rrd", $graphfile, $from, $to, $width, $height, $title, $vertical); - } elseif($os == "Fortigate") { - $graph = graph_fortigate_cpu ($hostname . "/fortigate-cpu.rrd", $graphfile, $from, $to, $width, $height, $title, $vertical); - } elseif($os == "JunOS") { - $graph = graph_cpu_generic_single($hostname . "/junos-cpu.rrd", $graphfile, $from, $to, $width, $height, $title, $vertical); - } - break; case 'dev_cpmCPU': $graph = graph_device_cpmCPU ($device_id, $graphfile, $from, $to, $width, $height, $title, $vertical); break; @@ -250,18 +218,12 @@ if($_GET['debug']) { } break; default: - if(is_file($config['install_dir'] . "/html/includes/graphs/$type.inc.php")) { - include($config['install_dir'] . "/html/includes/graphs/$type.inc.php"); - } else { - echo("INCORRECT GRAPH TYPE"); - exit; - } break; - } + } // End SWITCH if($graph) { header('Content-type: image/png'); - echo(`cat graphs/$graphfile`); + echo(`cat $graphfile`); } else { header('Content-type: image/png'); $string = "Graph Generation Error"; @@ -273,6 +235,9 @@ if($_GET['debug']) { imagedestroy($im); } - $delete = `rm graphs/$graphfile`; + $delete = `rm $graphfile`; + + } // End IF + ?> diff --git a/html/includes/.confirm_login.php.swp b/html/includes/.confirm_login.php.swp deleted file mode 100644 index e542b03859a2183ebf7cf6b5b016d238079fcd63..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeHNOLH4V5FYagnD^rcq!Fn?R%AWw0xEGFmty2Zh3&XxnUpIPmeKA=JC)VW*6gl@ zC{CO>09SqhT&W`Dhj4=2AQUI=oI)z_%}DawAql>a+O2$%Jk!%N{dG_GChm6SgT@NI zQ>rpNuQ2xMpYi`2`k4woQw$R62H#z4lv z(G1MaR4Z@h-k{fC+c;V%o5>i+7|0mN7|0mN7|0mN7|0mN7xEV|Vb6|9eluApHK{{2#!b zml?YO_`pfvrh9QWOX%4uuWkA-%$@T3-Ql0St$oJ58^kt&34UvN+8d~O*XKxXJH?H0&Eg6$rl z`91SjE7#^G_X~)Rqd<8gpIgWk_eew8K3zL4LS2zKaq7Avj-7~iMgCNZV~4yau&P`p z%v0YNT2Nn*i(%?$)hkk*Xc%>Ge8+C)_5s=2edB<65EY}@ps+1e{k(D4}n!{}LA^sAbf<_O= z9WoeSy*4>dIia=EImFZv^Kshl$>cr)V@vNNG7dtBz@x_z8q>qr08hsMarjn(AVzSX zvgYgwSV|Px20BB=f}NiqiP<`o$OdP>w{9>InQd~4kq1ndx0kx*Tk9s0ZcNB44 zz6i>;FP>er9S-)s?HtFbSJz`oBXccr|FqF$PxRsb$L{fPe_2Hbx&VNS9zbENDgm4?W1NVY|4;BNoBLaS(5x+08`Fas5Kk#rJ&m`PDJ zG}nVU!X-i$DpFsYlj61$y+*qzPX>Fsqc6q%HZR_xkt(mZRWLg^)=}Mz@ z>GDR4YO9-crPgdh@8+B(USU>jiD9{th!P3*;9JeZ#PVl(u%@+4u^YL_lnf6wP)n%C zic!7uRb=+(wg%c_(iVhN+ew3AXdExuTSA*cPcx6+w(Mm8j^x8NeV~R{*#6E0l4=j~OMf@BI1nw|B8j`G{p7La8U@8DE2Ih<}uwT!- zylgw>$WXLg4;AevyJPNMJi2#t#w@%nh4vL_>;}Ge3zop_y6=^OKHZy{>cDjmrRM=u17~~_aMW&{4c}q*#}v2xXdvYq;m`4g#82aP=&An diff --git a/html/includes/.login.inc.php.swo b/html/includes/.login.inc.php.swo deleted file mode 100644 index e4331bcd51145a1c202d5b00a4eb94185c3284b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 159744 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

A71^sjx{`} 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 diff --git a/html/includes/graphs/common.inc.php b/html/includes/graphs/common.inc.php index 68b2d7ea7..a386a65ee 100644 --- a/html/includes/graphs/common.inc.php +++ b/html/includes/graphs/common.inc.php @@ -14,8 +14,8 @@ if($_GET['legend'] == "no") { $rrd_options = " -g"; } if(!$scale_min && !$scale_max) { $rrd_options .= " --alt-autoscale-max"; } -if($scale_min) { $rrd_options .= " -l $scale_min"; } -if($scale_max) { $rrd_options .= " -u $scale_max"; } +if(isset($scale_min)) { $rrd_options .= " -l $scale_min"; } +if(isset($scale_max)) { $rrd_options .= " -u $scale_max"; } $rrd_options .= " -E --start ".$from." --end " . ($to - 150) . " --width ".$width." --height ".$height." "; diff --git a/html/includes/graphs/device_cpu.inc.php b/html/includes/graphs/device_cpu.inc.php index ca509d4ca..35c1c64f9 100644 --- a/html/includes/graphs/device_cpu.inc.php +++ b/html/includes/graphs/device_cpu.inc.php @@ -1,6 +1,8 @@ diff --git a/html/includes/graphs/temperature.inc.php b/html/includes/graphs/temperature.inc.php index 6fb6895dd..7ec488eac 100644 --- a/html/includes/graphs/temperature.inc.php +++ b/html/includes/graphs/temperature.inc.php @@ -1,7 +1,12 @@ diff --git a/html/includes/print-device-graph.php b/html/includes/print-device-graph.php index be6aaef48..f6c2fb421 100644 --- a/html/includes/print-device-graph.php +++ b/html/includes/print-device-graph.php @@ -1,23 +1,23 @@ ', LEFT".$config['overlib_defaults'].");\" onmouseout=\"return nd();\"> diff --git a/html/includes/print-interface-graphs.php b/html/includes/print-interface-graphs.inc.php similarity index 53% rename from html/includes/print-interface-graphs.php rename to html/includes/print-interface-graphs.inc.php index 8990089bc..94b20b982 100644 --- a/html/includes/print-interface-graphs.php +++ b/html/includes/print-interface-graphs.inc.php @@ -6,17 +6,17 @@ if(!$device) { $device['device_id'] = getifhost($interface['interface_id']); } - $daily_traffic = $config['base_url'] . "/graph.php?if=" . $interface['interface_id'] . "&type=$graph_type&from=$day&to=$now&width=215&height=100"; - $daily_url = $config['base_url'] . "/graph.php?if=" . $interface['interface_id'] . "&type=$graph_type&from=$day&to=$now&width=500&height=150"; + $daily_traffic = $config['base_url'] . "/graph.php?port=" . $interface['interface_id'] . "&type=$graph_type&from=$day&to=$now&width=215&height=100"; + $daily_url = $config['base_url'] . "/graph.php?port=" . $interface['interface_id'] . "&type=$graph_type&from=$day&to=$now&width=500&height=150"; - $weekly_traffic = $config['base_url'] . "/graph.php?if=" . $interface['interface_id'] . "&type=$graph_type&from=$week&to=$now&width=215&height=100"; - $weekly_url = $config['base_url'] . "/graph.php?if=" . $interface['interface_id'] . "&type=$graph_type&from=$week&to=$now&width=500&height=150"; + $weekly_traffic = $config['base_url'] . "/graph.php?port=" . $interface['interface_id'] . "&type=$graph_type&from=$week&to=$now&width=215&height=100"; + $weekly_url = $config['base_url'] . "/graph.php?port=" . $interface['interface_id'] . "&type=$graph_type&from=$week&to=$now&width=500&height=150"; - $monthly_traffic = $config['base_url'] . "/graph.php?if=" . $interface['interface_id'] . "&type=$graph_type&from=$month&to=$now&width=215&height=100"; - $monthly_url = $config['base_url'] . "/graph.php?if=" . $interface['interface_id'] . "&type=$graph_type&from=$month&to=$now&width=500&height=150"; + $monthly_traffic = $config['base_url'] . "/graph.php?port=" . $interface['interface_id'] . "&type=$graph_type&from=$month&to=$now&width=215&height=100"; + $monthly_url = $config['base_url'] . "/graph.php?port=" . $interface['interface_id'] . "&type=$graph_type&from=$month&to=$now&width=500&height=150"; - $yearly_traffic = $config['base_url'] . "/graph.php?if=" . $interface['interface_id'] . "&type=$graph_type&from=$year&to=$now&width=215&height=100"; - $yearly_url = $config['base_url'] . "/graph.php?if=" . $interface['interface_id'] . "&type=$graph_type&from=$year&to=$now&width=500&height=150"; + $yearly_traffic = $config['base_url'] . "/graph.php?port=" . $interface['interface_id'] . "&type=$graph_type&from=$year&to=$now&width=215&height=100"; + $yearly_url = $config['base_url'] . "/graph.php?port=" . $interface['interface_id'] . "&type=$graph_type&from=$year&to=$now&width=500&height=150"; echo("', LEFT".$config['overlib_defaults'].");\" onmouseout=\"return nd();\"> "); diff --git a/html/includes/print-interface.inc b/html/includes/print-interface.inc.php similarity index 83% rename from html/includes/print-interface.inc rename to html/includes/print-interface.inc.php index 1be30d859..abaa17185 100644 --- a/html/includes/print-interface.inc +++ b/html/includes/print-interface.inc.php @@ -1,5 +1,9 @@ "); +#print_r($interface); +#echo(""); + # This file prints a table row for each interface $interface['device_id'] = $device['device_id']; @@ -11,8 +15,8 @@ if(!is_integer($i/2)) { $row_colour = $list_colour_a; } else { $row_colour = $list_colour_b; } - if($interface['in_errors'] > 0 || $interface['out_errors'] > 0) { - $error_img = generateiflink($interface,"Interface Errors",errors); + if($interface['ifInErrors_delta'] > 0 || $interface['ifOutErrors_delta'] > 0) { + $error_img = generateiflink($interface,"Interface Errors","port_errors"); } else { $error_img = ""; } if(mysql_result(mysql_query("SELECT count(*) FROM mac_accounting WHERE interface_id = '".$interface['interface_id']."'"),0)){ @@ -48,22 +52,24 @@ echo(""); if($port_details) { - $interface['graph_type'] = "bits"; - echo(generateiflink($interface, "")); - $interface['graph_type'] = "pkts"; - echo(generateiflink($interface, "")); - $interface['graph_type'] = "errors"; - echo(generateiflink($interface, "")); + $interface['graph_type'] = "port_bits"; + echo(generateiflink($interface, "")); + $interface['graph_type'] = "port_upkts"; + echo(generateiflink($interface, "")); + $interface['graph_type'] = "port_errors"; + echo(generateiflink($interface, "")); } echo(""); if($interface['ifOperStatus'] == "up") { + $interface['in_rate'] = $interface['ifInOctets_rate'] * 8; + $interface['out_rate'] = $interface['ifOutOctets_rate'] * 8; $in_perc = @round($interface['in_rate']/$interface['ifSpeed']*100); $out_perc = @round($interface['in_rate']/$interface['ifSpeed']*100); echo(" " . - formatRates($interface['in_rate']) . "
"); + formatRates($interface['in_rate']) . "
".format_bi($interface['ifInUcastPkts_rate'])."pps
"); echo(" " . - formatRates($interface['out_rate']) . ""); + formatRates($interface['out_rate']) . "
".format_bi($interface['ifOutUcastPkts_rate'])."pps"); } echo(""); @@ -198,7 +204,6 @@ echo(""); unset($int_links, $int_links_v6, $int_links_v4, $int_links_phys, $br); - echo(""); // If we're showing graphs, generate the graph and print the img tags @@ -206,17 +211,17 @@ echo(""); $type = $graph_type; - $daily_traffic = "graph.php?if=$if_id&type=" . $graph_type . "&from=$day&to=$now&width=210&height=100"; - $daily_url = "graph.php?if=$if_id&type=" . $graph_type . "&from=$day&to=$now&width=500&height=150"; + $daily_traffic = "graph.php?port=$if_id&type=" . $graph_type . "&from=$day&to=$now&width=210&height=100"; + $daily_url = "graph.php?port=$if_id&type=" . $graph_type . "&from=$day&to=$now&width=500&height=150"; - $weekly_traffic = "graph.php?if=$if_id&type=" . $graph_type . "&from=$week&to=$now&width=210&height=100"; - $weekly_url = "graph.php?if=$if_id&type=" . $graph_type . "&from=$week&to=$now&width=500&height=150"; + $weekly_traffic = "graph.php?port=$if_id&type=" . $graph_type . "&from=$week&to=$now&width=210&height=100"; + $weekly_url = "graph.php?port=$if_id&type=" . $graph_type . "&from=$week&to=$now&width=500&height=150"; - $monthly_traffic = "graph.php?if=$if_id&type=" . $graph_type . "&from=$month&to=$now&width=210&height=100"; - $monthly_url = "graph.php?if=$if_id&type=" . $graph_type . "&from=$month&to=$now&width=500&height=150"; + $monthly_traffic = "graph.php?port=$if_id&type=" . $graph_type . "&from=$month&to=$now&width=210&height=100"; + $monthly_url = "graph.php?port=$if_id&type=" . $graph_type . "&from=$month&to=$now&width=500&height=150"; - $yearly_traffic = "graph.php?if=$if_id&type=" . $graph_type . "&from=$year&to=$now&width=210&height=100"; - $yearly_url = "graph.php?if=$if_id&type=" . $graph_type . "&from=$year&to=$now&width=500&height=150"; + $yearly_traffic = "graph.php?port=$if_id&type=" . $graph_type . "&from=$year&to=$now&width=210&height=100"; + $yearly_url = "graph.php?port=$if_id&type=" . $graph_type . "&from=$year&to=$now&width=500&height=150"; echo(""); diff --git a/html/includes/topnav.inc b/html/includes/topnav.inc index 6b0463478..f7f65e7f7 100644 --- a/html/includes/topnav.inc +++ b/html/includes/topnav.inc @@ -13,7 +13,7 @@ $interfaces['up'] = mysql_result(mysql_query("SELECT count(*) FROM interfaces AS $interfaces['down'] = mysql_result(mysql_query("SELECT count(*) FROM interfaces AS I, devices AS D WHERE I.ifOperStatus = 'down' AND I.ifAdminStatus = 'up' AND I.ignore = '0' AND D.device_id = I.device_id AND D.ignore = '0'"),0); $interfaces['shutdown'] = mysql_result(mysql_query("SELECT count(*) FROM interfaces AS I, devices AS D WHERE I.ifAdminStatus = 'down' AND I.ignore = '0' AND D.device_id = I.device_id AND D.ignore = '0'"),0); $interfaces['ignored'] = mysql_result(mysql_query("SELECT count(*) FROM interfaces AS I, devices AS D WHERE D.device_id = I.device_id AND ( I.ignore = '1' OR D.ignore = '1')"),0); -$interfaces['errored'] = mysql_result(mysql_query("SELECT count(*) FROM interfaces AS I, devices AS D WHERE D.device_id = I.device_id AND ( I.ignore = '0' OR D.ignore = '0') AND (I.in_errors > '0' OR I.out_errors > '0')"),0); +$interfaces['errored'] = mysql_result(mysql_query("SELECT count(*) FROM interfaces AS I, devices AS D WHERE D.device_id = I.device_id AND ( I.ignore = '0' OR D.ignore = '0') AND (I.ifInErrors_delta > '0' OR I.ifOutErrors_delta > '0')"),0); $services['count'] = mysql_result(mysql_query("SELECT count(service_id) FROM services"),0); diff --git a/html/pages/customers.php b/html/pages/customers.php index 30985d393..be676011b 100644 --- a/html/pages/customers.php +++ b/html/pages/customers.php @@ -35,11 +35,20 @@ list(,$circuit) = preg_split("/[\{\}]/", $interface['ifAlias']); list(,$notes) = preg_split("/[\(\)]/", $interface['ifAlias']); list(,$speed) = preg_split("/[\[\]]/", $interface['ifAlias']); - + $customer = trim($customer); if ($customer == $prev_customer) { unset($customer); } else { + if(isset($prev_customer)) { + echo(" + + + + + "); + } + if(is_integer($customers/2)) { $bg_colour = $list_colour_a; } else { $bg_colour = $list_colour_b; } $customers++; $prev_customer = $customer; diff --git a/html/pages/device/graphs.inc.php b/html/pages/device/graphs.inc.php index fbc446bab..9acf0cc5b 100644 --- a/html/pages/device/graphs.inc.php +++ b/html/pages/device/graphs.inc.php @@ -15,10 +15,10 @@ while($device = mysql_fetch_array($device_query)) { switch ($device['os']) { case "JunOS": echo("

Processor Utilisation
"); - $graph_type = "cpu"; include ("includes/print-device-graph.php"); + $graph_type = "device_cpu"; include ("includes/print-device-graph.php"); if(mysql_result(mysql_query("SELECT count(*) FROM temperature WHERE temp_host = '" . $device['device_id'] . "'"),0)) { echo("
Temperatures
"); - $graph_type = "dev_temp"; include ("includes/print-device-graph.php"); + $graph_type = "dev_temperatures"; include ("includes/print-device-graph.php"); echo("
"); } @@ -73,18 +73,18 @@ while($device = mysql_fetch_array($device_query)) { case "ProCurve": echo("
Processor Utilisation
"); - $graph_type = "cpu"; include ("includes/print-device-graph.php"); + $graph_type = "device_cpu"; include ("includes/print-device-graph.php"); echo("
"); echo("
Memory Usage
"); - $graph_type = "mem"; include ("includes/print-device-graph.php"); + $graph_type = "device_memory"; include ("includes/print-device-graph.php"); echo("
"); echo("
Device Uptime
"); - $graph_type = "uptime"; include ("includes/print-device-graph.php"); break; + $graph_type = "device_uptime"; include ("includes/print-device-graph.php"); break; echo("
"); break; case "Windows": - $graph_type = "cpu"; + $graph_type = "device_cpu"; include ("includes/print-device-graph.php"); $memgraph = memgraphWin ($device[hostname] . "-mem.rrd", $device[hostname] . "-mem.png", $day, $now, 335, 100); @@ -106,31 +106,31 @@ while($device = mysql_fetch_array($device_query)) { case "OpenBSD": case "pfSense": echo("
Processor Utilisation
"); - $graph_type = "cpu"; include ("includes/print-device-graph.php"); + $graph_type = "device_cpu"; include ("includes/print-device-graph.php"); echo("
"); if($device[os] == "m0n0wall" || $device[os] == "pfSense" || $device[os] == "Voswall" || $device[monowall]) { echo("
IP Statistics
"); - $graph_type = "ip_graph"; include ("includes/print-device-graph.php"); + $graph_type = "device_ip"; include ("includes/print-device-graph.php"); echo("
"); echo("
Device Uptime
"); - $graph_type = "uptime"; include ("includes/print-device-graph.php"); + $graph_type = "device_uptime"; include ("includes/print-device-graph.php"); break; } if($device['os'] != "NetBSD") { echo("
Memory Utilisation
"); - $graph_type = "mem"; include ("includes/print-device-graph.php"); + $graph_type = "device_memory"; include ("includes/print-device-graph.php"); echo("
"); } if(mysql_result(mysql_query("SELECT count(storage_id) FROM storage WHERE host_id = '" . $device['device_id'] . "'"),0)) { echo("
Storage
"); - $graph_type = "unixfs_dev"; include ("includes/print-device-graph.php"); + $graph_type = "device_unixfs"; include ("includes/print-device-graph.php"); echo("
"); } if(mysql_result(mysql_query("SELECT count(*) FROM temperature WHERE temp_host = '" . $device['device_id'] . "'"),0)) { echo("
Temperatures
"); - $graph_type = "dev_temp"; include ("includes/print-device-graph.php"); + $graph_type = "device_temperatures"; include ("includes/print-device-graph.php"); echo("
"); } @@ -138,35 +138,14 @@ while($device = mysql_fetch_array($device_query)) { include("graphs/uptime.inc.php"); echo("
System Load
"); - $graph_type = "load"; include ("includes/print-device-graph.php"); + $graph_type = "device_load"; include ("includes/print-device-graph.php"); echo("
"); echo("
Users Logged On
"); - $graph_type = "users"; include ("includes/print-device-graph.php"); - echo("
"); + $graph_type = "device_users"; include ("includes/print-device-graph.php"); + echo("
"); echo("
Running Processes
"); - $graph_type = "procs"; include ("includes/print-device-graph.php"); - echo("
"); - if($device[postfix] == '1') { - echo("
Postfix Messages
"); - $graph_type = "postfix"; include ("includes/print-device-graph.php"); - echo("
"); - echo("
Postfix Errors
"); - $graph_type = "postfixerrors"; include ("includes/print-device-graph.php"); - echo("
"); - } - if($device[courier] == '1') { - echo("
Courier IMAP/POP3
"); - $graph_type = "courier"; include ("includes/print-device-graph.php"); - echo("
"); - } - if($device[apache] == '1') { - echo("
Apache Hits
"); - $graph_type = "apachehits"; include ("includes/print-device-graph.php"); - echo("
"); - echo("
Apache Traffic
"); - $graph_type = "apachebits"; include ("includes/print-device-graph.php"); - echo("
"); - } + $graph_type = "device_procs"; include ("includes/print-device-graph.php"); + echo("
"); break; case "CatOS": @@ -177,7 +156,7 @@ while($device = mysql_fetch_array($device_query)) { break; case "Snom": echo("
Calls
"); - $graph_type = "calls"; include ("includes/print-device-graph.php"); + $graph_type = "snom_calls"; include ("includes/print-device-graph.php"); } if($memgraph) { diff --git a/html/pages/device/graphs/netstats.inc.php b/html/pages/device/graphs/netstats.inc.php index 633d179a7..c73392ddc 100644 --- a/html/pages/device/graphs/netstats.inc.php +++ b/html/pages/device/graphs/netstats.inc.php @@ -1,16 +1,16 @@ IP Statistics"); - $graph_type = "ip_graph"; include ("includes/print-device-graph.php"); + $graph_type = "device_ip"; include ("includes/print-device-graph.php"); echo("
"); echo("
TCP Statistics
"); - $graph_type = "tcp_graph"; include ("includes/print-device-graph.php"); + $graph_type = "device_tcp"; include ("includes/print-device-graph.php"); echo("
"); echo("
UDP Statistics
"); - $graph_type = "udp_graph"; include ("includes/print-device-graph.php"); + $graph_type = "device_udp"; include ("includes/print-device-graph.php"); echo("
"); echo("
ICMP Statistics
"); - $graph_type = "icmp_graph"; include ("includes/print-device-graph.php"); + $graph_type = "device_icmp"; include ("includes/print-device-graph.php"); echo("
"); diff --git a/html/pages/device/graphs/os-ios.inc.php b/html/pages/device/graphs/os-ios.inc.php index dfd705925..a406a3c71 100644 --- a/html/pages/device/graphs/os-ios.inc.php +++ b/html/pages/device/graphs/os-ios.inc.php @@ -1,14 +1,14 @@ CPU Usage"); -$graph_type = "cpu"; include ("includes/print-device-graph.php"); +$graph_type = "device_cpu"; include ("includes/print-device-graph.php"); echo("
"); echo("
Memory Usage
"); -$graph_type = "mem"; include ("includes/print-device-graph.php"); +$graph_type = "device_memory"; include ("includes/print-device-graph.php"); echo("
"); if(mysql_result(mysql_query("SELECT count(*) FROM temperature WHERE temp_host = '" . $device['device_id'] . "'"),0)) { echo("
Temperatures
"); - $graph_type = "dev_temp"; include ("includes/print-device-graph.php"); + $graph_type = "device_temperatures"; include ("includes/print-device-graph.php"); echo("
"); } diff --git a/html/pages/device/graphs/uptime.inc.php b/html/pages/device/graphs/uptime.inc.php index db16d4757..d9564a1c0 100644 --- a/html/pages/device/graphs/uptime.inc.php +++ b/html/pages/device/graphs/uptime.inc.php @@ -1,7 +1,7 @@ Device Uptime"); - $graph_type = "uptime"; include ("includes/print-device-graph.php"); + $graph_type = "device_uptime"; include ("includes/print-device-graph.php"); echo("
"); diff --git a/html/pages/device/health/temp.inc.php b/html/pages/device/health/temp.inc.php index af3758e5d..4a8f24f85 100644 --- a/html/pages/device/health/temp.inc.php +++ b/html/pages/device/health/temp.inc.php @@ -19,7 +19,7 @@ while($temp = mysql_fetch_array($query)) { \n"); echo(""); - $graph_type = "temp"; + $graph_type = "temperature"; // start temperature graphs diff --git a/html/pages/device/interface.inc.php b/html/pages/device/interface.inc.php index 0219c3dc9..d333b0890 100644 --- a/html/pages/device/interface.inc.php +++ b/html/pages/device/interface.inc.php @@ -29,7 +29,7 @@ $interface = mysql_fetch_array($interface_query); echo("
"); - include("includes/print-interface.inc"); + include("includes/print-interface.inc.php"); echo("
"); @@ -89,26 +89,30 @@ if($_GET['optb']) { include("pages/device/port/".mres($_GET['optb']).".inc.php"); } else { - - if(file_exists("rrd/" . $hostname . "/". $ifIndex . ".rrd")) { + if(file_exists($config['rrd_dir'] . "/" . $hostname . "/". $ifIndex . ".rrd")) { $iid = $id; echo("
Interface Traffic
"); - $graph_type = "bits"; - include("includes/print-interface-graphs.php"); + $graph_type = "port_bits"; + include("includes/print-interface-graphs.inc.php"); echo("
Interface Packets
"); - $graph_type = "pkts"; - include("includes/print-interface-graphs.php"); + $graph_type = "port_upkts"; + include("includes/print-interface-graphs.inc.php"); echo("
Interface Non Unicast
"); - $graph_type = "nupkts"; - include("includes/print-interface-graphs.php"); + $graph_type = "port_nupkts"; + include("includes/print-interface-graphs.inc.php"); echo("
Interface Errors
"); - $graph_type = "errors"; - include("includes/print-interface-graphs.php"); + $graph_type = "port_errors"; + include("includes/print-interface-graphs.inc.php"); + if(is_file($config['rrd_dir'] . "/" . $device['hostname'] . "/etherlike-" . $interface['ifIndex'] . ".rrd")) { + echo("
Ethernet Errors
"); + $graph_type = "port_etherlike"; + include("includes/print-interface-graphs.inc.php"); + } } } diff --git a/html/pages/device/port/macaccounting.inc.php b/html/pages/device/port/macaccounting.inc.php index 91ad5d69f..61a278e57 100644 --- a/html/pages/device/port/macaccounting.inc.php +++ b/html/pages/device/port/macaccounting.inc.php @@ -17,7 +17,7 @@ $i = 1; $inf = fixifName($ifname); - $query = mysql_query("SELECT *, (M.bps_in + M.bps_out) as bps FROM `mac_accounting` AS M, `interfaces` AS I, `devices` AS D WHERE M.interface_id = '".$interface['interface_id']."' AND I.interface_id = M.interface_id AND I.device_id = D.device_id ORDER BY bps DESC"); + echo("
"); if($_GET['optd'] == "top10") { @@ -28,61 +28,103 @@ if($_GET['optc']) { $stat = $_GET['optc']; } else { $stat = "bits"; } + if($_GET['optf']) { + $sort = $_GET['optf']; + } else { $sort = "in"; } + echo("
-
+ -
+
+ Two Day
+ + + +
+
Week
- - + +
-
+
Month
- - + +
-
+
Year
- - + +
- +
-
+
Traffic
- - + +
-
+
Packets
- - + +
+
+ Top Input
+ + + +
+
+ Top Output
+ + + +
+
+ Top Aggregate
+ + + +
+
"); unset($query); - } + } else { + $query = mysql_query("SELECT *, (M.cipMacHCSwitchedBytes_input_rate + M.cipMacHCSwitchedBytes_output_rate) as bps FROM `mac_accounting` AS M, + `interfaces` AS I, `devices` AS D WHERE M.interface_id = '".$interface['interface_id']."' AND I.interface_id = M.interface_id + AND I.device_id = D.device_id ORDER BY bps DESC"); while($acc = mysql_fetch_array($query)) { if(!is_integer($i/2)) { $row_colour = $list_colour_a; } else { $row_colour = $list_colour_b; } $addy = mysql_fetch_array(mysql_query("SELECT * FROM ipv4_mac where mac_address = '".$acc['mac']."'")); - $name = gethostbyaddr($addy['ipv4_address']); - if($name == $addy['ipv4_address']) { unset ($name); } + #$name = gethostbyaddr($addy['ipv4_address']); + #if($name == $addy['ipv4_address']) { unset ($name); } if(mysql_result(mysql_query("SELECT count(*) FROM bgpPeers WHERE device_id = '".$acc['device_id']."' AND bgpPeerIdentifier = '".$addy['ipv4_address']."'"),0)) { $peer_query = mysql_query("SELECT * FROM bgpPeers WHERE device_id = '".$acc['device_id']."' AND bgpPeerIdentifier = '".$addy['ipv4_address']."'"); $peer_info = mysql_fetch_array($peer_query); @@ -122,8 +164,8 @@ ".mac_clean_to_readable($acc['mac'])." ".$addy['ipv4_address']." ".$name." - ".formatRates($acc['bps_in'])." - ".formatRates($acc['bps_out'])." + ".formatRates($acc['cipMacHCSwitchedBytes_input_rate'] / 8)." + ".formatRates($acc['cipMacHCSwitchedBytes_output_rate'] / 8)." "); @@ -154,4 +196,6 @@ } +} + ?> diff --git a/html/pages/device/ports.inc.php b/html/pages/device/ports.inc.php index 0cabd0b45..7cb232e67 100644 --- a/html/pages/device/ports.inc.php +++ b/html/pages/device/ports.inc.php @@ -7,8 +7,8 @@ echo("ARP Table | Graphs: Bits (Mini) | -Packets -(Mini) | +Packets +(Mini) | NU Packets (Mini) | Errors @@ -17,7 +17,7 @@ echo("
"); diff --git a/html/pages/front/jt.php b/html/pages/front/jt.php index a64355513..4a2046ac5 100644 --- a/html/pages/front/jt.php +++ b/html/pages/front/jt.php @@ -221,11 +221,11 @@ if($_SESSION['userlevel'] >= '5') if($interfaces['wave_broadband']) { echo(""); + "
"); } echo("
"); diff --git a/html/pages/iftype.php b/html/pages/iftype.php index d1493c881..0c378b846 100644 --- a/html/pages/iftype.php +++ b/html/pages/iftype.php @@ -25,7 +25,7 @@ echo(""); echo(""); @@ -52,7 +52,7 @@ echo("
"); $graph_type = "multi_bits"; $interface['interface_id'] = $if_list; - include("includes/print-interface-graphs.php"); + include("includes/print-interface-graphs.inc.php"); echo("
"); if(file_exists($config['rrd_dir'] . "/" . $interface['hostname'] . "/" . $interface['ifIndex'] . ".rrd")) { $graph_type = "bits"; - include("includes/print-interface-graphs.php"); + include("includes/print-interface-graphs.inc.php"); } echo(""); diff --git a/html/pages/interfaces.php b/html/pages/interfaces.php index 1654817eb..f24ffe992 100644 --- a/html/pages/interfaces.php +++ b/html/pages/interfaces.php @@ -102,7 +102,7 @@ if($_GET['type'] == "down" || $_POST['state'] == "down") { } elseif ($_GET['type'] == "admindown" || $_POST['state'] == "admindown") { $where .= "AND I.ifAdminStatus = 'down'"; } elseif ($_GET['type'] == "errors" || $_POST['state'] == "errors") { - $where .= "AND ( I.`out_errors` > '0' OR I.`in_errors` > '0' )"; + $where .= "AND ( I.`ifInErrors_delta` > '0' OR I.`ifOutErrors_delta` > '0' )"; } elseif ($_GET['type'] == "up" || $_POST['state'] == "up") { $where .= "AND I.ifOperStatus = 'up'"; } elseif ($_GET['type'] == "l2vlan" || $_POST['state'] == "l2vlan") { diff --git a/html/pages/vrf.php b/html/pages/vrf.php index 7a3e4117f..36612f791 100644 --- a/html/pages/vrf.php +++ b/html/pages/vrf.php @@ -51,7 +51,7 @@ if($_GET['opta'] == "details" ) { } else { if(is_integer($i/2)) { $int_colour = $list_colour_b_b; } else { $int_colour = $list_colour_b_a; } } - include("includes/print-interface.inc"); + include("includes/print-interface.inc.php"); $i++; } $x++; diff --git a/includes/common.php b/includes/common.php index 9e3a9f8dc..4c7145015 100644 --- a/includes/common.php +++ b/includes/common.php @@ -2,6 +2,12 @@ ## Common Functions +function truncate($substring, $max = 50, $rep = '...'){ + if(strlen($substring) < 1){ $string = $rep; } else { $string = $substring; } + $leave = $max - strlen ($rep); + if(strlen($string) > $max){ return substr_replace($string, $rep, $leave); } else { return $string; } +} + function mres($string) { // short function wrapper because the real one is stupidly long and ugly. aestetics. return mysql_real_escape_string($string); } diff --git a/includes/functions-poller.inc.php b/includes/functions-poller.inc.php new file mode 100644 index 000000000..66fe0c807 --- /dev/null +++ b/includes/functions-poller.inc.php @@ -0,0 +1,128 @@ + diff --git a/includes/functions.php b/includes/functions.php index 06effcceb..3b6b78235 100755 --- a/includes/functions.php +++ b/includes/functions.php @@ -215,13 +215,6 @@ function print_message($text) echo("
$text
"); } -function truncate($substring, $max = 50, $rep = '...') -{ - if(strlen($substring) < 1){ $string = $rep; } else { $string = $substring; } - $leave = $max - strlen ($rep); - if(strlen($string) > $max){ return substr_replace($string, $rep, $leave); } else { return $string; } -} - function interface_rates ($rrd_file) // Returns the last in/out value in RRD { global $config; @@ -283,10 +276,10 @@ function generateiflink($interface, $text=0,$type) $interface = ifNameDescr($interface); if(!$text) { $text = fixIfName($interface['label']); } if($type) { $interface['graph_type'] = $type; } - if(!$interface['graph_type']) { $interface['graph_type'] = 'bits'; } + if(!$interface['graph_type']) { $interface['graph_type'] = 'port_bits'; } $class = ifclass($interface['ifOperStatus'], $interface['ifAdminStatus']); - $graph_url = $config['base_url'] . "/graph.php?if=" . $interface['interface_id'] . "&from=$day&to=$now&width=400&height=100&type=" . $interface['graph_type']; - $graph_url_month = $config['base_url'] . "/graph.php?if=" . $interface['interface_id'] . "&from=$month&to=$now&width=400&height=100&type=" . $interface['graph_type']; + $graph_url = $config['base_url'] . "/graph.php?port=" . $interface['interface_id'] . "&from=$day&to=$now&width=400&height=100&type=" . $interface['graph_type']; + $graph_url_month = $config['base_url'] . "/graph.php?port=" . $interface['interface_id'] . "&from=$month&to=$now&width=400&height=100&type=" . $interface['graph_type']; $device_id = getifhost($interface['interface_id']); $link = "".$device['hostname']." - CPU Load
"; - $link .= "'".$config['overlib_defaults'].", LEFT);\" onmouseout=\"return nd();\">$text"; + $link .= "onmouseover=\"return overlib('
".$device['hostname']." - CPU & Memory Usage
"; + $link .= "
'".$config['overlib_defaults'].", LEFT);\" onmouseout=\"return nd();\">$text"; return $link; } diff --git a/includes/graphing.php b/includes/graphing.php index 5c7026f7f..dfe9273ec 100644 --- a/includes/graphing.php +++ b/includes/graphing.php @@ -7,7 +7,6 @@ include("graphing/unix.php"); function graph_multi_bits_trio ($interfaces, $graph, $from, $to, $width, $height, $title, $vertical, $inverse, $legend = '1') { global $config, $installdir; - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; $options = " --alt-autoscale-max -E --start $from --end " . ($to - 150) . " --width $width --height $height "; $options .= $config['rrdgraph_def_text']; if($height < "99") { $options .= " --only-graph"; } @@ -164,15 +163,14 @@ function graph_multi_bits_trio ($interfaces, $graph, $from, $to, $width, $height } if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal"; } -# echo($config['rrdtool'] . " graph $imgfile $options"); - $thing = shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; +# echo($config['rrdtool'] . " graph $graph $options"); + $thing = shell_exec($config['rrdtool'] . " graph $graph $options"); + return $graph; } function graph_multi_bits_duo ($interfaces, $graph, $from, $to, $width, $height, $title, $vertical, $inverse, $legend = '1') { global $config, $installdir; - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; $options = "--alt-autoscale-max -E --start $from --end " . ($to - 150) . " --width $width --height $height"; $options .= $config['rrdgraph_def_text']; if($height < "99") { $options .= " --only-graph"; } @@ -282,422 +280,13 @@ function graph_multi_bits_duo ($interfaces, $graph, $from, $to, $width, $height, } if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal"; } - $thing = shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; -} - -function temp_graph ($temp, $graph, $from, $to, $width, $height, $title, $vertical) { - global $config, $installdir; - $options = " -l 0 -E --start $from --end $to --width $width --height $height "; - $options .= $config['rrdgraph_def_text']; - if($width <= "300") { - $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; - } - $hostname = gethostbyid($device); - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; - $iter = "1"; - $sql = mysql_query("SELECT * FROM temperature where temp_id = '$temp'"); - $opts[] = "COMMENT: Cur Max"; - $temperature = mysql_fetch_array(mysql_query("SELECT * FROM temperature where temp_id = '$temp'")); - $hostname = mysql_result(mysql_query("SELECT hostname FROM devices WHERE device_id = '" . $temperature['temp_host'] . "'"),0); - - $temperature['temp_descr_fixed'] = str_pad($temperature['temp_descr'], 28); - $temperature['temp_descr_fixed'] = substr($temperature['temp_descr_fixed'],0,28); - - $filename = str_replace(")", "_", str_replace("(", "_", str_replace("/", "_", str_replace(" ", "_",$temperature['temp_descr'])))); - - $temprrd = $config['rrd_dir'] . "/$hostname/temp-" . $filename . ".rrd"; - $opts[] = "DEF:temp=$temprrd:temp:AVERAGE"; - $opts[] = "CDEF:tempwarm=temp,".$temperature[temp_limit].",GT,temp,UNKN,IF"; - $opts[] = "LINE1.5:temp#006600:" . quotemeta($temperature[temp_descr_fixed]); - $opts[] = "LINE1.5:tempwarm#cc0000"; - $opts[] = "GPRINT:temp:LAST:%3.0lf°C"; - $opts[] = "GPRINT:temp:MAX:%3.0lf°C\\\l"; - - foreach($opts as $opt) { - $opt = str_replace(" ","\ ", $opt); - $options .= " $opt"; - } -# echo($config['rrdtool'] . " graph $imgfile $options"); - $thing = shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; -} - -function graph_cpmCPU ($id, $graph, $from, $to, $width, $height, $title, $vertical) { - global $config, $installdir; - $options = "--start $from --end $to --width $width --height $height --vertical-label '$vertical' --alt-autoscale-max "; - $options .= " -l 0 -E -b 1024 --title '$title' "; - $options .= $config['rrdgraph_def_text']; - if($height < "99") { $options .= " --only-graph -u 100 -l 0 -r "; unset ($legend); } - if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } - $hostname = gethostbyid($device); - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; - $iter = "1"; - $sql = mysql_query("SELECT * FROM `cpmCPU` AS C, `devices` AS D where C.`cpmCPU_id` = '$id' AND C.device_id = D.device_id"); - $options .= "COMMENT:\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Cur\ \ \ \ Max\\\\n"; - while($proc = mysql_fetch_array($sql)) { - if($iter=="1") {$colour="CC0000";} elseif($iter=="2") {$colour="008C00";} elseif($iter=="3") {$colour="4096EE"; - } elseif($iter=="4") {$colour="73880A";} elseif($iter=="5") {$colour="D01F3C";} elseif($iter=="6") {$colour="36393D"; - } elseif($iter=="7") {$colour="FF0084"; unset($iter); } - $proc['descr_fixed'] = str_pad($proc['entPhysicalDescr'], 28); - $proc['descr_fixed'] = substr($proc['descr_fixed'],0,28); - $rrd = $config['rrd_dir'] . "/".$proc['hostname']."/cpmCPU-" . $proc['cpmCPU_oid'] . ".rrd"; - $options .= " DEF:proc" . $proc['cpmCPU_oid'] . "=$rrd:usage:AVERAGE "; - $options .= " LINE1:proc" . $proc['cpmCPU_oid'] . "#" . $colour . ":'" . $proc['descr_fixed'] . "' "; - $options .= " GPRINT:proc" . $proc['cpmCPU_oid'] . ":LAST:%3.0lf"; - $options .= " GPRINT:proc" . $proc['cpmCPU_oid'] . ":MAX:%3.0lf\\\l "; - $iter++; - } - $thing = shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; -} - - - -function graph_device_cpmCPU ($device, $graph, $from, $to, $width, $height, $title, $vertical) { - global $config, $installdir; - $options = "--start $from --end $to --width $width --height $height --vertical-label '$vertical' --alt-autoscale-max "; - $options .= " -l 0 -E -b 1024 --title '$title' "; - $options .= $config['rrdgraph_def_text']; - if($height < "99") { $options .= " --only-graph -u 100 -l 0 -r "; unset ($legend); } - if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } - $hostname = gethostbyid($device); - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; - $iter = "1"; - $sql = mysql_query("SELECT * FROM `cpmCPU` where `device_id` = '$device'"); - $options .= "COMMENT:\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Cur\ \ \ \ Max\\\\n"; - while($proc = mysql_fetch_array($sql)) { - if($iter=="1") {$colour="CC0000";} elseif($iter=="2") {$colour="008C00";} elseif($iter=="3") {$colour="4096EE"; - } elseif($iter=="4") {$colour="73880A";} elseif($iter=="5") {$colour="D01F3C";} elseif($iter=="6") {$colour="36393D"; - } elseif($iter=="7") {$colour="FF0084"; unset($iter); } - $proc['descr_fixed'] = str_pad($proc['entPhysicalDescr'], 28); - $proc['descr_fixed'] = substr($proc['descr_fixed'],0,28); - $rrd = $config['rrd_dir'] . "/$hostname/cpmCPU-" . $proc['cpmCPU_oid'] . ".rrd"; - $options .= " DEF:proc" . $proc['cpmCPU_oid'] . "=$rrd:usage:AVERAGE "; - $options .= " LINE1:proc" . $proc['cpmCPU_oid'] . "#" . $colour . ":'" . $proc['descr_fixed'] . "' "; - $options .= " GPRINT:proc" . $proc['cpmCPU_oid'] . ":LAST:%3.0lf"; - $options .= " GPRINT:proc" . $proc['cpmCPU_oid'] . ":MAX:%3.0lf\\\l "; - $iter++; - } - $thing = shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; -} - -function graph_device_cempMemPool ($device, $graph, $from, $to, $width, $height, $title, $vertical) { - global $config, $installdir; - $options = "--start $from --end $to --width $width --height $height --vertical-label '$vertical' --alt-autoscale-max "; - $options .= " -l 0 -E -b 1024 --title '$title' "; - $options .= $config['rrdgraph_def_text']; - if($height < "99") { $options .= " --only-graph -u 100 -l 0 -r "; unset ($legend); } - if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } - $hostname = gethostbyid($device); - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; - $iter = "1"; - $sql = mysql_query("SELECT * FROM `cempMemPool` where `device_id` = '$device'"); - $options .= "COMMENT:\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Cur\ \ \ \ Max\\\\n"; - while($mempool = mysql_fetch_array($sql)) { - $entPhysicalName = mysql_result(mysql_query("SELECT entPhysicalName from entPhysical WHERE device_id = '".$device."' - AND entPhysicalIndex = '".$mempool['entPhysicalIndex']."'"),0); - if($iter=="1") {$colour="CC0000";} elseif($iter=="2") {$colour="008C00";} elseif($iter=="3") {$colour="4096EE"; - } elseif($iter=="4") {$colour="73880A";} elseif($iter=="5") {$colour="D01F3C";} elseif($iter=="6") {$colour="36393D"; - } elseif($iter=="7") {$colour="FF0084"; unset($iter); } - $mempool['descr_fixed'] = $entPhysicalName . " " . $mempool['cempMemPoolName']; - $mempool['descr_fixed'] = str_replace("Routing Processor", "RP", $mempool['descr_fixed']); - $mempool['descr_fixed'] = str_replace("Switching Processor", "SP", $mempool['descr_fixed']); - $mempool['descr_fixed'] = str_replace("Processor", "Proc", $mempool['descr_fixed']); - $mempool['descr_fixed'] = str_pad($mempool['descr_fixed'], 28); - $mempool['descr_fixed'] = substr($mempool['descr_fixed'],0,28); - $oid = $mempool['entPhysicalIndex'] . "." . $mempool['Index']; - $rrd = $config['rrd_dir'] . "/$hostname/cempMemPool-$oid.rrd"; - $id = $mempool['entPhysicalIndex'] . "-" . $mempool['Index']; - $options .= " DEF:mempool" . $id . "free=$rrd:free:AVERAGE "; - $options .= " DEF:mempool" . $id . "used=$rrd:used:AVERAGE "; - $options .= " CDEF:mempool" . $id . "total=mempool" . $id . "used,mempool" . $id . "used,mempool" . $id . "free,+,/,100,* "; - $options .= " LINE1:mempool" . $id . "total#" . $colour . ":'" . $mempool['descr_fixed'] . "' "; - $options .= " GPRINT:mempool" . $id . "total:LAST:%3.0lf"; - $options .= " GPRINT:mempool" . $id . "total:MAX:%3.0lf\\\l "; - $iter++; - } - $thing = shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; -} - -function graph_cempMemPool ($id, $graph, $from, $to, $width, $height, $title, $vertical) { - global $config, $installdir; - $options = "--start $from --end $to --width $width --height $height --vertical-label '$vertical' --alt-autoscale-max "; - $options .= " -l 0 -E -b 1024 --title '$title' "; - $options .= $config['rrdgraph_def_text']; - if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } - $hostname = gethostbyid($device); - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; - $iter = "1"; - $sql = mysql_query("SELECT * FROM `cempMemPool` AS C, `devices` AS D where C.`cempMemPool_id` = '$id' AND C.device_id = D.device_id"); - $options .= "COMMENT:\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Cur\ \ \ \ Max\\\\n"; - while($mempool = mysql_fetch_array($sql)) { - $entPhysicalName = mysql_result(mysql_query("SELECT entPhysicalName from entPhysical WHERE device_id = '".$mempool['device_id']."' - AND entPhysicalIndex = '".$mempool['entPhysicalIndex']."'"),0); - if($iter=="1") {$colour="CC0000";} elseif($iter=="2") {$colour="008C00";} elseif($iter=="3") {$colour="4096EE"; - } elseif($iter=="4") {$colour="73880A";} elseif($iter=="5") {$colour="D01F3C";} elseif($iter=="6") {$colour="36393D"; - } elseif($iter=="7") {$colour="FF0084"; unset($iter); } - $mempool['descr_fixed'] = $entPhysicalName . " " . $mempool['cempMemPoolName']; - $mempool['descr_fixed'] = str_replace("Routing Processor", "RP", $mempool['descr_fixed']); - $mempool['descr_fixed'] = str_replace("Switching Processor", "SP", $mempool['descr_fixed']); - $mempool['descr_fixed'] = str_replace("Processor", "Proc", $mempool['descr_fixed']); - $mempool['descr_fixed'] = str_pad($mempool['descr_fixed'], 28); - $mempool['descr_fixed'] = substr($mempool['descr_fixed'],0,28); - $oid = $mempool['entPhysicalIndex'] . "." . $mempool['Index']; - $rrd = $config['rrd_dir'] . "/".$mempool['hostname']."/cempMemPool-$oid.rrd"; - $id = $mempool['entPhysicalIndex'] . "-" . $mempool['Index']; - $options .= " DEF:mempool" . $id . "free=$rrd:free:AVERAGE "; - $options .= " DEF:mempool" . $id . "used=$rrd:used:AVERAGE "; - $options .= " CDEF:mempool" . $id . "total=mempool" . $id . "used,mempool" . $id . "used,mempool" . $id . "free,+,/,100,* "; - $options .= " LINE1:mempool" . $id . "total#" . $colour . ":'" . $mempool['descr_fixed'] . "' "; - $options .= " GPRINT:mempool" . $id . "total:LAST:%3.0lf"; - $options .= " GPRINT:mempool" . $id . "total:MAX:%3.0lf\\\l "; - $iter++; - } - - $thing = shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; -} - - -function temp_graph_dev ($device, $graph, $from, $to, $width, $height, $title, $vertical) { - global $config, $installdir; - $options = "--start $from --end $to --width $width --height $height --vertical-label '$vertical' --alt-autoscale-max "; - $options .= " -l 0 -E -b 1024 --title '$title' "; - $options .= $config['rrdgraph_def_text']; - if($height < "99") { $options .= " --only-graph -u 100 -l 0 -r "; unset ($legend); } - if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } - $hostname = gethostbyid($device); - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; - $iter = "1"; - $sql = mysql_query("SELECT * FROM temperature where temp_host = '$device'"); - $options .= "COMMENT:\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Cur\ \ \ \ Max\\\\n"; - while($temperature = mysql_fetch_array($sql)) { - if($iter=="1") {$colour="CC0000";} elseif($iter=="2") {$colour="008C00";} elseif($iter=="3") {$colour="4096EE"; - } elseif($iter=="4") {$colour="73880A";} elseif($iter=="5") {$colour="D01F3C";} elseif($iter=="6") {$colour="36393D"; - } elseif($iter=="7") {$colour="FF0084"; unset($iter); } - $temperature['temp_descr_fixed'] = str_pad($temperature['temp_descr'], 28); - $temperature['temp_descr_fixed'] = substr($temperature['temp_descr_fixed'],0,28); - $temprrd = addslashes("rrd/$hostname/temp-" . str_replace("/", "_", str_replace(" ", "_",$temperature['temp_descr'])) . ".rrd"); - $temprrd = str_replace(")", "_", $temprrd); - $temprrd = str_replace("(", "_", $temprrd); - $options .= " DEF:temp" . $temperature[temp_id] . "=$temprrd:temp:AVERAGE "; - $options .= " LINE1:temp" . $temperature[temp_id] . "#" . $colour . ":'" . $temperature[temp_descr_fixed] . "' "; - $options .= " GPRINT:temp" . $temperature[temp_id] . ":LAST:%3.0lf\°C "; - $options .= " GPRINT:temp" . $temperature[temp_id] . ":MAX:%3.0lf\°C\\\l "; - $iter++; - } - $thing = shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; -} - -function graph_mac_acc ($id, $graph, $from, $to, $width, $height) { - global $config; - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; - $query = mysql_query("SELECT * FROM `mac_accounting` AS M, `interfaces` AS I, `devices` AS D WHERE M.ma_id = '".$id."' AND I.interface_id = M.interface_id AND I.device_id = D.device_id"); - $acc = mysql_fetch_array($query); - $database = $acc['hostname'] . "/mac-accounting/" . $acc['ifIndex'] . "-" . $acc['mac'] . ".rrd"; - return graph_bits ($database, $graph, $from, $to, $width, $height, $title, $vertical); - -} - -function graph_bits ($rrd, $graph, $from, $to, $width, $height, $title, $vertical, $inverse = '0', $legend = '1') { - global $config; - $database = $config['rrd_dir'] . "/" . $rrd; - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; - $period = $to - $from; - $options = "--alt-autoscale-max -E --start $from --end $to --width $width --height $height "; - $options .= $config['rrdgraph_def_text']; - if($height < "99") { $options .= " --only-graph"; unset ($legend); } - if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } - global $_GET; - if($_GET['bg']) { $options .= " -c CANVAS#" . $_GET['bg'] . " "; } - if($inverse) { - $in = 'out'; - $out = 'in'; - } else { - $in = 'in'; - $out = 'out'; - } - if(strstr($database, "mac-accounting")) { - $options .= " DEF:".$out."octets=$database:OUT:AVERAGE"; - $options .= " DEF:".$in."octets=$database:IN:AVERAGE"; - $options .= " DEF:".$out."octets_max=$database:OUT:MAX"; - $options .= " DEF:".$in."octets_max=$database:IN:MAX"; - } else { - $options .= " DEF:".$out."octets=$database:OUTOCTETS:AVERAGE"; - $options .= " DEF:".$in."octets=$database:INOCTETS:AVERAGE"; - $options .= " DEF:".$out."octets_max=$database:OUTOCTETS:MAX"; - $options .= " DEF:".$in."octets_max=$database:INOCTETS:MAX"; - } - - $options .= " CDEF:octets=inoctets,outoctets,+"; - $options .= " CDEF:doutoctets=outoctets,-1,*"; - $options .= " CDEF:inbits=inoctets,8,*"; - $options .= " CDEF:inbits_max=inoctets_max,8,*"; - $options .= " CDEF:outbits_max=outoctets_max,8,*"; - $options .= " CDEF:doutoctets_max=outoctets_max,-1,*"; - $options .= " CDEF:doutbits_max=doutoctets_max,8,*"; - $options .= " CDEF:outbits=outoctets,8,*"; - $options .= " CDEF:doutbits=doutoctets,8,*"; - $options .= " VDEF:totin=inoctets,TOTAL"; - $options .= " VDEF:totout=outoctets,TOTAL"; - $options .= " VDEF:tot=octets,TOTAL"; - $options .= " VDEF:95thin=inbits,95,PERCENT"; - $options .= " VDEF:95thout=outbits,95,PERCENT"; - $options .= " VDEF:d95thout=doutbits,5,PERCENT"; - if ($legend == "no") { - $options .= " AREA:inbits#CDEB8B"; - $options .= " LINE1.25:inbits#006600"; - $options .= " AREA:doutbits#C3D9FF"; - $options .= " LINE1.25:doutbits#000099"; - $options .= " LINE1:95thin#aa0000"; - $options .= " LINE1:d95thout#aa0000"; - } else { - $options .= " AREA:inbits_max#aDEB7B:"; - $options .= " AREA:inbits#CDEB8B:"; - $options .= " COMMENT:BPS\ \ \ \ Current\ \ \ Average\ \ \ \ \ \ Max\ \ \ 95th\ %\\\\n"; - $options .= " LINE1.25:inbits#006600:In\ "; - $options .= " GPRINT:inbits:LAST:%6.2lf%s"; - $options .= " GPRINT:inbits:AVERAGE:%6.2lf%s"; - $options .= " GPRINT:inbits_max:MAX:%6.2lf%s"; - $options .= " GPRINT:95thin:%6.2lf%s\\\\n"; - $options .= " AREA:doutbits_max#a3b9FF:"; - $options .= " AREA:doutbits#C3D9FF:"; - $options .= " LINE1.25:doutbits#000099:Out"; - $options .= " GPRINT:outbits:LAST:%6.2lf%s"; - $options .= " GPRINT:outbits:AVERAGE:%6.2lf%s"; - $options .= " GPRINT:outbits_max:MAX:%6.2lf%s"; - $options .= " GPRINT:95thout:%6.2lf%s\\\\n"; - $options .= " GPRINT:tot:Total\ %6.2lf%s"; - $options .= " GPRINT:totin:\(In\ %6.2lf%s"; - $options .= " GPRINT:totout:Out\ %6.2lf%s\)\\\\l"; - $options .= " LINE1:95thin#aa0000"; - $options .= " LINE1:d95thout#aa0000"; - } - $thing = shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; -} - -function pktsgraph ($rrd, $graph, $from, $to, $width, $height) { - global $config, $installdir; - $database = $config['rrd_dir'] . "/" . $rrd; - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; - $options = "--alt-autoscale-max -E --start $from --end $to --width $width --height $height "; - $options .= $config['rrdgraph_def_text']; - if($height < "99") { $options .= " --only-graph"; unset ($legend); } - if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } - global $_GET; - if($_GET['bg']) { $options .= " -c CANVAS#" . $_GET['bg'] . " "; } - $options .= " DEF:in=$database:INUCASTPKTS:AVERAGE"; - $options .= " DEF:out=$database:OUTUCASTPKTS:AVERAGE"; - $options .= " CDEF:dout=out,-1,*"; - $options .= " AREA:in#aa66aa:"; - $options .= " COMMENT:Packets\ \ \ \ Current\ \ \ \ \ Average\ \ \ \ \ \ Maximum\\\\n"; - $options .= " LINE1.25:in#330033:In\ \ "; - $options .= " GPRINT:in:LAST:%6.2lf%spps"; - $options .= " GPRINT:in:AVERAGE:%6.2lf%spps"; - $options .= " GPRINT:in:MAX:%6.2lf%spps\\\\n"; - $options .= " AREA:dout#FFDD88:"; - $options .= " LINE1.25:dout#FF6600:Out\ "; - $options .= " GPRINT:out:LAST:%6.2lf%spps"; - $options .= " GPRINT:out:AVERAGE:%6.2lf%spps"; - $options .= " GPRINT:out:MAX:%6.2lf%spps\\\\n"; - $thing = shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; -} - -function graph_mac_pkts ($id, $graph, $from, $to, $width, $height) { - global $config, $installdir; - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; - $query = mysql_query("SELECT * FROM `mac_accounting` AS M, `interfaces` AS I, `devices` AS D WHERE M.ma_id = '".$id."' AND I.interface_id = M.interface_id AND I.device_id = D.device_id"); - $acc = mysql_fetch_array($query); - $database = $config['rrd_dir'] ."/". $acc['hostname'] . "/mac-accounting/" . $acc['ifIndex'] . "-" . $acc['mac'] . "-pkts.rrd"; - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; - $options = "--alt-autoscale-max -E --start $from --end $to --width $width --height $height "; - $options .= $config['rrdgraph_def_text']; - if($height < "99") { $options .= " --only-graph"; unset ($legend); } - if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } - $options .= " DEF:in=$database:IN:AVERAGE"; - $options .= " DEF:out=$database:OUT:AVERAGE"; - $options .= " CDEF:dout=out,-1,*"; - $options .= " AREA:in#aa66aa:"; - $options .= " COMMENT:Packets\ \ \ \ Current\ \ \ \ \ Average\ \ \ \ \ \ Maximum\\\\n"; - $options .= " LINE1.25:in#330033:In\ \ "; - $options .= " GPRINT:in:LAST:%6.2lf%spps"; - $options .= " GPRINT:in:AVERAGE:%6.2lf%spps"; - $options .= " GPRINT:in:MAX:%6.2lf%spps\\\\n"; - $options .= " AREA:dout#FFDD88:"; - $options .= " LINE1.25:dout#FF6600:Out\ "; - $options .= " GPRINT:out:LAST:%6.2lf%spps"; - $options .= " GPRINT:out:AVERAGE:%6.2lf%spps"; - $options .= " GPRINT:out:MAX:%6.2lf%spps\\\\n"; - $thing = shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; -} - -function errorgraph ($rrd, $graph, $from, $to, $width, $height) { - global $config, $installdir; - $database = $config['rrd_dir'] . "/" . $rrd; - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; - $options = "--alt-autoscale-max -E --start $from --end $to --width $width --height $height "; - $options .= $config['rrdgraph_def_text']; - if($height < "99") { $options .= " --only-graph"; unset ($legend); } - if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } - global $_GET; - if($_GET['bg']) { $options .= " -c CANVAS#" . $_GET['bg'] . " "; } - $options .= " DEF:in=$database:INERRORS:AVERAGE"; - $options .= " DEF:out=$database:OUTERRORS:AVERAGE"; - $options .= " CDEF:dout=out,-1,*"; - $options .= " AREA:in#ff3300:"; - $options .= " COMMENT:Errors\ \ \ \ Current\ \ \ \ \ Average\ \ \ \ \ \ Maximum\\\\n"; - $options .= " LINE1.25:in#ff0000:In\ \ "; - $options .= " GPRINT:in:LAST:%6.2lf%spps"; - $options .= " GPRINT:in:AVERAGE:%6.2lf%spps"; - $options .= " GPRINT:in:MAX:%6.2lf%spps\\\\n"; - $options .= " AREA:dout#FF6633:"; - $options .= " LINE1.25:dout#cc3300:Out\ "; - $options .= " GPRINT:out:LAST:%6.2lf%spps"; - $options .= " GPRINT:out:AVERAGE:%6.2lf%spps"; - $options .= " GPRINT:out:MAX:%6.2lf%spps\\\\n"; - $thing = shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; -} - -function nucastgraph ($rrd, $graph, $from, $to, $width, $height) { - global $config, $installdir; - $database = $config['rrd_dir'] . "/" . $rrd; - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; - $options = "--alt-autoscale-max -E --start $from --end $to --width $width --height $height "; - $options .= $config['rrdgraph_def_text']; - if($height < "99") { $options .= " --only-graph"; unset ($legend); } - if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } - global $_GET; - if($_GET['bg']) { $options .= " -c CANVAS#" . $_GET['bg'] . " "; } - $options .= " DEF:in=$database:INNUCASTPKTS:AVERAGE"; - $options .= " DEF:out=$database:OUTNUCASTPKTS:AVERAGE"; - $options .= " CDEF:dout=out,-1,*"; - $options .= " AREA:in#aa66aa:"; - $options .= " COMMENT:Packets\ \ \ \ Current\ \ \ \ \ Average\ \ \ \ \ \ Maximum\\\\n"; - $options .= " LINE1.25:in#330033:In\ \ "; - $options .= " GPRINT:in:LAST:%6.2lf%spps"; - $options .= " GPRINT:in:AVERAGE:%6.2lf%spps"; - $options .= " GPRINT:in:MAX:%6.2lf%spps\\\\n"; - $options .= " AREA:dout#FFDD88:"; - $options .= " LINE1.25:dout#FF6600:Out\ "; - $options .= " GPRINT:out:LAST:%6.2lf%spps"; - $options .= " GPRINT:out:AVERAGE:%6.2lf%spps"; - $options .= " GPRINT:out:MAX:%6.2lf%spps\\\\n"; - $thing = shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; + $thing = shell_exec($config['rrdtool'] . " graph $graph $options"); + return $graph; } function graph_cbgp_prefixes ($rrd, $graph, $from, $to, $width, $height) { global $config; $database = $config['rrd_dir'] . "/" . $rrd; - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; $options = "--alt-autoscale-max -E --start $from --end $to --width $width --height $height "; $options .= $config['rrdgraph_def_text']; if($width <= "300") {$options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } @@ -718,16 +307,15 @@ function graph_cbgp_prefixes ($rrd, $graph, $from, $to, $width, $height) { #$options .= " GPRINT:Advertised:LAST:%6.2lf%s"; #$options .= " GPRINT:Advertised:MIN:%6.2lf%s"; #$options .= " GPRINT:Advertised:MAX:%6.2lf%s\\\\l"; - $thing = shell_exec($config['rrdtool'] . " graph $imgfile $options"); -# echo($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; + $thing = shell_exec($config['rrdtool'] . " graph $graph $options"); +# echo($config['rrdtool'] . " graph $graph $options"); + return $graph; } function bgpupdatesgraph ($rrd, $graph , $from, $to, $width, $height) { global $config, $installdir; $database = $config['rrd_dir'] . "/" . $rrd; - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; $options = "--alt-autoscale-max -E --start $from --end $to --width $width --height $height "; $options .= $config['rrdgraph_def_text']; if($width <= "300") {$options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } @@ -745,44 +333,13 @@ function bgpupdatesgraph ($rrd, $graph , $from, $to, $width, $height) { $options .= " GPRINT:out:LAST:%6.2lf%sU/s"; $options .= " GPRINT:out:AVERAGE:%6.2lf%sU/s"; $options .= " GPRINT:out:MAX:%6.2lf%sU/s\\\\n"; - $thing = shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; + $thing = shell_exec($config['rrdtool'] . " graph $graph $options"); + return $graph; } -function graph_entity_sensor ($sensor, $graph , $from, $to, $width, $height, $title, $vertical) { - global $config; - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; - $sensor = mysql_fetch_array(mysql_query("SELECT * FROM entPhysical as E, devices as D WHERE entPhysical_id = '$sensor' and D.device_id = E.device_id")); - $database = $config['rrd_dir'] . "/" . $sensor['hostname'] . "/ces-" . $sensor['entPhysicalIndex'] . ".rrd"; - $options = "--alt-autoscale-max -l 0 -E --start $from --end $to --width $width --height $height "; - $options .= $config['rrdgraph_def_text']; - if($height < "99") { $options .= " --only-graph -u 100 -l 0 -r "; unset ($legend); } - if($width <= "300") {$options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } - $type = str_pad($sensor['entSensorType'], 8); - $type = substr($type,0,8); - $options .= " DEF:avg=$database:value:AVERAGE"; - $options .= " DEF:min=$database:value:MIN"; - $options .= " DEF:max=$database:value:MAX"; - $options .= " COMMENT:' Last Min Max Ave\\n'"; - $options .= " AREA:max#a5a5a5"; - $options .= " AREA:min#ffffff"; - $options .= " LINE1.25:avg#aa2200:'".$type."'"; - - $options .= " GPRINT:avg:AVERAGE:%5.2lf%s"; - $options .= " GPRINT:max:MAX:%5.2lf%s"; - $options .= " GPRINT:max:MAX:%5.2lf%s"; - $options .= " GPRINT:avg:LAST:%5.2lf%s"; - - $thing = shell_exec($config['rrdtool'] . " graph $imgfile $options"); - #echo($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; -} - - function graph_cpu_generic_single ($rrd, $graph , $from, $to, $width, $height) { global $config; $database = $config['rrd_dir'] . "/" . $rrd; - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; $options = "--alt-autoscale-max -l 0 -E --start $from --end $to --width $width --height $height "; $options .= $config['rrdgraph_def_text']; if($width <= "300") {$options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } @@ -791,15 +348,14 @@ function graph_cpu_generic_single ($rrd, $graph , $from, $to, $width, $height) { $options .= " AREA:cpu#ffee99: LINE1.25:cpu#aa2200:Load\ %"; $options .= " GPRINT:cpu:LAST:%6.2lf\ GPRINT:cpu:AVERAGE:%6.2lf\ "; $options .= " GPRINT:cpu:MAX:%6.2lf\ GPRINT:cpu:AVERAGE:%6.2lf\\\\n"; - $thing = shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; + $thing = shell_exec($config['rrdtool'] . " graph $graph $options"); + return $graph; } function graph_adsl_rate ($rrd, $graph, $from, $to, $width, $height) { global $config, $installdir; $database = $config['rrd_dir'] . "/" . $rrd; - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; $options = "--alt-autoscale-max -l 0 -E --start $from --end $to --width $width --height $height "; $options .= $config['rrdgraph_def_text']; if($width <= "300") {$options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } @@ -814,14 +370,13 @@ function graph_adsl_rate ($rrd, $graph, $from, $to, $width, $height) { $options .= " LINE1.25:adslAturCurrAtt#22aa00:Down\ \ "; $options .= " GPRINT:dslAturCurrAtt:LAST:%5.0lfk\ GPRINT:dslAturCurrAtt:AVERAGE:%5.0lfk\ "; $options .= " GPRINT:dslAturCurrAtt:MAX:%5.0lfk\ GPRINT:dslAturCurrAtt:AVERAGE:%5.0lfk\\\\n"; - $thing = shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; + $thing = shell_exec($config['rrdtool'] . " graph $graph $options"); + return $graph; } function graph_adsl_snr ($rrd, $graph, $from, $to, $width, $height) { global $config, $installdir; $database = $config['rrd_dir'] . "/" . $rrd; - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; $options = "--alt-autoscale-max -l 0 -E --start $from --end $to --width $width --height $height "; $options .= $config['rrdgraph_def_text']; if($width <= "300") {$options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } @@ -836,14 +391,13 @@ function graph_adsl_snr ($rrd, $graph, $from, $to, $width, $height) { $options .= " LINE1.25:dslAturCurrSnr#22aa00:SNR\ Down"; $options .= " GPRINT:dslAturCurrSnr:LAST:%3.1lfdB GPRINT:dslAturCurrSnr:AVERAGE:%3.1lfdB\ "; $options .= " GPRINT:dslAturCurrSnr:MAX:%3.1lfdB GPRINT:dslAturCurrSnr:AVERAGE:%3.1lfdB\\\\n"; - $thing = shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; + $thing = shell_exec($config['rrdtool'] . " graph $graph $options"); + return $graph; } function graph_adsl_atn ($rrd, $graph, $from, $to, $width, $height) { global $config, $installdir; $database = $config['rrd_dir'] . "/" . $rrd; - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; $options = "--alt-autoscale-max -l 0 -E --start $from --end $to --width $width --height $height "; $options .= $config['rrdgraph_def_text']; if($width <= "300") {$options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } @@ -858,14 +412,13 @@ function graph_adsl_atn ($rrd, $graph, $from, $to, $width, $height) { $options .= " LINE1.25:dslAturCurrAtn#22aa00:Atten\ Down"; $options .= " GPRINT:dslAturCurrAtn:LAST:%3.1lfdB GPRINT:dslAturCurrAtn:AVERAGE:%3.1lfdb"; $options .= " GPRINT:dslAturCurrAtn:MAX:%3.1lfdB GPRINT:dslAturCurrAtn:AVERAGE:%3.1lfdb\\\\n"; - $thing = shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; + $thing = shell_exec($config['rrdtool'] . " graph $graph $options"); + return $graph; } function cpugraph ($rrd, $graph , $from, $to, $width, $height) { global $config, $installdir; $database = $config['rrd_dir'] . "/" . $rrd; - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; $options = "--alt-autoscale-max -l 0 -E --start $from --end $to --width $width --height $height "; $options .= $config['rrdgraph_def_text']; if($width <= "300") {$options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } @@ -875,32 +428,13 @@ function cpugraph ($rrd, $graph , $from, $to, $width, $height) { $options .= " AREA:5m#ffee99: LINE1.25:5m#aa2200:Load\ %"; $options .= " GPRINT:5m:LAST:%6.2lf\ GPRINT:5m:AVERAGE:%6.2lf\ "; $options .= " GPRINT:5m:MAX:%6.2lf\ GPRINT:5m:AVERAGE:%6.2lf\\\\n"; - $thing = shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; -} - -function uptimegraph ($rrd, $graph , $from, $to, $width, $height, $title, $vertical) { - global $config, $installdir; - $database = $config['rrd_dir'] . "/" . $rrd; - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; - $options = "--alt-autoscale-max -E --start $from --end $to --width $width --height $height "; - $options .= $config['rrdgraph_def_text']; - if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } - $options .= " DEF:uptime=$database:uptime:AVERAGE"; - $options .= " CDEF:cuptime=uptime,86400,/"; - $options .= " COMMENT:Days\ \ \ \ \ \ Current\ \ Minimum\ \ Maximum\ \ Average\\\\n"; - $options .= " AREA:cuptime#EEEEEE:Uptime"; - $options .= " LINE1.25:cuptime#36393D:"; - $options .= " GPRINT:cuptime:LAST:%6.2lf\ GPRINT:cuptime:AVERAGE:%6.2lf\ "; - $options .= " GPRINT:cuptime:MAX:%6.2lf\ GPRINT:cuptime:AVERAGE:%6.2lf\\\\n"; - $thing = shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; + $thing = shell_exec($config['rrdtool'] . " graph $graph $options"); + return $graph; } function memgraph ($rrd, $graph , $from, $to, $width, $height, $title, $vertical) { global $config, $installdir; $database = $config['rrd_dir'] . "/" . $rrd; - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; $period = $to - $from; $options = "-l 0 --alt-autoscale-max -E --start $from --end $to --width $width --height $height "; $options .= $config['rrdgraph_def_text']; @@ -925,190 +459,8 @@ function memgraph ($rrd, $graph , $from, $to, $width, $height, $title, $vertical $options .= " GPRINT:FREE:MAX:%6.2lf%s"; $options .= " GPRINT:FREE:AVERAGE:%6.2lf%s\\\\l"; $options .= " LINE1:MEMTOTAL#000000:"; - $thing = shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; + $thing = shell_exec($config['rrdtool'] . " graph $graph $options"); + return $graph; } -function ip_graph ($rrd, $graph, $from, $to, $width, $height) { - global $config, $installdir; - $database = $config['rrd_dir'] . "/" . $rrd; - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; - $period = $to - $from; - $options = "--alt-autoscale-max -E --start $from --end $to --width $width --height $height "; - $options .= $config['rrdgraph_def_text']; - if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } - $options .= " DEF:ipForwDatagrams=$database:ipForwDatagrams:AVERAGE"; - $options .= " DEF:ipInDelivers=$database:ipInDelivers:AVERAGE"; - $options .= " DEF:ipInReceives=$database:ipInReceives:AVERAGE"; - $options .= " DEF:ipOutRequests=$database:ipOutRequests:AVERAGE"; - $options .= " DEF:ipInDiscards=$database:ipInDiscards:AVERAGE"; - $options .= " DEF:ipOutDiscards=$database:ipOutDiscards:AVERAGE"; - $options .= " DEF:ipOutNoRoutes=$database:ipInDiscards:AVERAGE"; - $options .= " COMMENT:Packets/sec\ \ \ \ Current\ \ \ Average\ \ \ Maximum\\\n"; - $options .= " LINE1.25:ipForwDatagrams#cc0000:ForwDgrams\ "; - $options .= " GPRINT:ipForwDatagrams:LAST:%6.2lf%s"; - $options .= " GPRINT:ipForwDatagrams:AVERAGE:\ %6.2lf%s"; - $options .= " GPRINT:ipForwDatagrams:MAX:\ %6.2lf%s\\\\n"; - $options .= " LINE1.25:ipInDelivers#00cc00:InDelivers\ "; - $options .= " GPRINT:ipInDelivers:LAST:%6.2lf%s"; - $options .= " GPRINT:ipInDelivers:AVERAGE:\ %6.2lf%s"; - $options .= " GPRINT:ipInDelivers:MAX:\ %6.2lf%s\\\\n"; - $options .= " LINE1.25:ipInReceives#006600:InReceives\ "; - $options .= " GPRINT:ipInReceives:LAST:%6.2lf%s"; - $options .= " GPRINT:ipInReceives:AVERAGE:\ %6.2lf%s"; - $options .= " GPRINT:ipInReceives:MAX:\ %6.2lf%s\\\\n"; - $options .= " LINE1.25:ipOutRequests#0000cc:OutRequests"; - $options .= " GPRINT:ipOutRequests:LAST:%6.2lf%s"; - $options .= " GPRINT:ipOutRequests:AVERAGE:\ %6.2lf%s"; - $options .= " GPRINT:ipOutRequests:MAX:\ %6.2lf%s\\\\n"; - $options .= " LINE1.25:ipInDiscards#cccc00:InDiscards\ "; - $options .= " GPRINT:ipInDiscards:LAST:%6.2lf%s"; - $options .= " GPRINT:ipInDiscards:AVERAGE:\ %6.2lf%s"; - $options .= " GPRINT:ipInDiscards:MAX:\ %6.2lf%s\\\\n"; - $options .= " LINE1.25:ipOutDiscards#330033:OutDiscards"; - $options .= " GPRINT:ipOutDiscards:LAST:%6.2lf%s"; - $options .= " GPRINT:ipOutDiscards:AVERAGE:\ %6.2lf%s"; - $options .= " GPRINT:ipOutDiscards:MAX:\ %6.2lf%s\\\\n"; - $options .= " LINE1.25:ipOutNoRoutes#660000:OutNoRoutes"; - $options .= " GPRINT:ipOutNoRoutes:LAST:%6.2lf%s"; - $options .= " GPRINT:ipOutNoRoutes:AVERAGE:\ %6.2lf%s"; - $options .= " GPRINT:ipOutNoRoutes:MAX:\ %6.2lf%s\\\\n"; - $thing = shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; -} - -function icmp_graph ($rrd, $graph, $from, $to, $width, $height) { - global $config, $installdir; - $database = $config['rrd_dir'] . "/" . $rrd; - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; - $period = $to - $from; - $options = "--alt-autoscale-max -E --start $from --end $to --width $width --height $height "; - $options .= $config['rrdgraph_def_text']; - if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } $options .= "DEF:icmpInMsgs=$database:icmpInMsgs:AVERAGE"; - $options .= " DEF:icmpOutMsgs=$database:icmpOutMsgs:AVERAGE"; - $options .= " DEF:icmpInErrors=$database:icmpInErrors:AVERAGE"; - $options .= " DEF:icmpOutErrors=$database:icmpOutErrors:AVERAGE"; - $options .= " DEF:icmpInEchos=$database:icmpInEchos:AVERAGE"; - $options .= " DEF:icmpOutEchos=$database:icmpOutEchos:AVERAGE"; - $options .= " DEF:icmpInEchoReps=$database:icmpInEchoReps:AVERAGE"; - $options .= " DEF:icmpOutEchoReps=$database:icmpOutEchoReps:AVERAGE"; - $options .= " COMMENT:Packets/sec\ \ \ \ Current\ \ \ \ Average\ \ \ Maximum\\\\n"; - $options .= " LINE1.25:icmpInMsgs#00cc00:InMsgs "; - $options .= " GPRINT:icmpInMsgs:LAST:\ \ \ \ \ %6.2lf%s"; - $options .= " GPRINT:icmpInMsgs:AVERAGE:\ \ %6.2lf%s"; - $options .= " GPRINT:icmpInMsgs:MAX:\ %6.2lf%s\\\\n"; - $options .= " LINE1.25:icmpOutMsgs#006600:OutMsgs "; - $options .= " GPRINT:icmpOutMsgs:LAST:\ \ \ \ %6.2lf%s"; - $options .= " GPRINT:icmpOutMsgs:AVERAGE:\ \ %6.2lf%s"; - $options .= " GPRINT:icmpOutMsgs:MAX:\ %6.2lf%s\\\\n"; - $options .= " LINE1.25:icmpInErrors#cc0000:InErrors "; - $options .= " GPRINT:icmpInErrors:LAST:\ \ \ %6.2lf%s"; - $options .= " GPRINT:icmpInErrors:AVERAGE:\ \ %6.2lf%s"; - $options .= " GPRINT:icmpInErrors:MAX:\ %6.2lf%s\\\\n"; - $options .= " LINE1.25:icmpOutErrors#660000:OutErrors "; - $options .= " GPRINT:icmpOutErrors:LAST:\ \ %6.2lf%s"; - $options .= " GPRINT:icmpOutErrors:AVERAGE:\ \ %6.2lf%s"; - $options .= " GPRINT:icmpOutErrors:MAX:\ %6.2lf%s\\\\n"; - $options .= " LINE1.25:icmpInEchos#0066cc:InEchos "; - $options .= " GPRINT:icmpInEchos:LAST:\ \ \ \ %6.2lf%s"; - $options .= " GPRINT:icmpInEchos:AVERAGE:\ \ %6.2lf%s"; - $options .= " GPRINT:icmpInEchos:MAX:\ %6.2lf%s\\\\n"; - $options .= " LINE1.25:icmpOutEchos#003399:OutEchos "; - $options .= " GPRINT:icmpOutEchos:LAST:\ \ \ %6.2lf%s"; - $options .= " GPRINT:icmpOutEchos:AVERAGE:\ \ %6.2lf%s"; - $options .= " GPRINT:icmpOutEchos:MAX:\ %6.2lf%s\\\\n"; - $options .= " LINE1.25:icmpInEchoReps#cc00cc:InEchoReps "; - $options .= " GPRINT:icmpInEchoReps:LAST:\ %6.2lf%s"; - $options .= " GPRINT:icmpInEchoReps:AVERAGE:\ \ %6.2lf%s"; - $options .= " GPRINT:icmpInEchoReps:MAX:\ %6.2lf%s\\\\n"; - $options .= " LINE1.25:icmpOutEchoReps#990099:OutEchoReps"; - $options .= " GPRINT:icmpOutEchoReps:LAST:%6.2lf%s"; - $options .= " GPRINT:icmpOutEchoReps:AVERAGE:\ %6.2lf%s"; - $options .= " GPRINT:icmpOutEchoReps:MAX:\ %6.2lf%s\\\\n"; - $thing = shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; -} - -function tcp_graph ($rrd, $graph, $from, $to, $width, $height) { - global $config, $installdir; - $database = $config['rrd_dir'] . "/" . $rrd; - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; - $period = $to - $from; - $options = "--alt-autoscale-max -E --start $from --end $to --width $width --height $height "; - $options .= $config['rrdgraph_def_text']; - if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } $options .= "DEF:icmpInMsgs=$database:icmpInMsgs:AVERAGE"; - $options .= " DEF:tcpActiveOpens=$database:tcpActiveOpens:AVERAGE"; - $options .= " DEF:tcpPassiveOpens=$database:tcpPassiveOpens:AVERAGE"; - $options .= " DEF:tcpAttemptFails=$database:tcpAttemptFails:AVERAGE"; - $options .= " DEF:tcpEstabResets=$database:tcpEstabResets:AVERAGE"; - $options .= " DEF:tcpInSegs=$database:tcpInSegs:AVERAGE"; - $options .= " DEF:tcpOutSegs=$database:tcpOutSegs:AVERAGE"; - $options .= " DEF:tcpRetransSegs=$database:tcpRetransSegs:AVERAGE"; - $options .= " COMMENT:Packets/sec\ \ \ \ Current\ \ \ \ Average\ \ \ Maximum\\\n"; - $options .= " LINE1.25:tcpActiveOpens#00cc00:ActiveOpens\ "; - $options .= " GPRINT:tcpActiveOpens:LAST:%6.2lf%s"; - $options .= " GPRINT:tcpActiveOpens:AVERAGE:\ %6.2lf%s"; - $options .= " GPRINT:tcpActiveOpens:MAX:\ %6.2lf%s\\\\n"; - $options .= " LINE1.25:tcpPassiveOpens#006600:PassiveOpens"; - $options .= " GPRINT:tcpPassiveOpens:LAST:%6.2lf%s"; - $options .= " GPRINT:tcpPassiveOpens:AVERAGE:\ %6.2lf%s"; - $options .= " GPRINT:tcpPassiveOpens:MAX:\ %6.2lf%s\\\\n"; - $options .= " LINE1.25:tcpAttemptFails#cc0000:AttemptFails"; - $options .= " GPRINT:tcpAttemptFails:LAST:%6.2lf%s"; - $options .= " GPRINT:tcpAttemptFails:AVERAGE:\ %6.2lf%s"; - $options .= " GPRINT:tcpAttemptFails:MAX:\ %6.2lf%s\\\\n"; - $options .= " LINE1.25:tcpEstabResets#660000:EstabResets\ "; - $options .= " GPRINT:tcpEstabResets:LAST:%6.2lf%s"; - $options .= " GPRINT:tcpEstabResets:AVERAGE:\ %6.2lf%s"; - $options .= " GPRINT:tcpEstabResets:MAX:\ %6.2lf%s\\\\n"; - $options .= " LINE1.25:tcpInSegs#0066cc:InSegs\ \ \ \ \ \ "; - $options .= " GPRINT:tcpInSegs:LAST:%6.2lf%s"; - $options .= " GPRINT:tcpInSegs:AVERAGE:\ %6.2lf%s"; - $options .= " GPRINT:tcpInSegs:MAX:\ %6.2lf%s\\\\n"; - $options .= " LINE1.25:tcpOutSegs#003399:OutSegs\ \ \ \ \ "; - $options .= " GPRINT:tcpOutSegs:LAST:%6.2lf%s"; - $options .= " GPRINT:tcpOutSegs:AVERAGE:\ %6.2lf%s"; - $options .= " GPRINT:tcpOutSegs:MAX:\ %6.2lf%s\\\\n"; - $options .= " LINE1.25:tcpRetransSegs#cc00cc:RetransSegs\ "; - $options .= " GPRINT:tcpRetransSegs:LAST:%6.2lf%s"; - $options .= " GPRINT:tcpRetransSegs:AVERAGE:\ %6.2lf%s"; - $options .= " GPRINT:tcpRetransSegs:MAX:\ %6.2lf%s\\\\n"; - $thing = shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; -} - -function udp_graph ($rrd, $graph, $from, $to, $width, $height) { - global $config, $installdir; - $database = $config['rrd_dir'] . "/" . $rrd; - $imgfile = $config['install_dir'] . "/graphs/" . "$graph"; - $period = $to - $from; - $options = "--alt-autoscale-max -E --start $from --end $to --width $width --height $height "; - $options .= $config['rrdgraph_def_text']; - if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } $options .= "DEF:icmpInMsgs=$database:icmpInMsgs:AVERAGE"; - $options .= " DEF:udpInDatagrams=$database:udpInDatagrams:AVERAGE"; - $options .= " DEF:udpOutDatagrams=$database:udpOutDatagrams:AVERAGE"; - $options .= " DEF:udpInErrors=$database:udpInErrors:AVERAGE"; - $options .= " DEF:udpNoPorts=$database:udpNoPorts:AVERAGE"; - $options .= " COMMENT:Packets/sec\ \ \ \ Current\ \ \ \ Average\ \ \ Maximum\\\\n"; - $options .= " LINE1.25:udpInDatagrams#00cc00:InDatagrams\ "; - $options .= " GPRINT:udpInDatagrams:LAST:%6.2lf%s"; - $options .= " GPRINT:udpInDatagrams:AVERAGE:\ %6.2lf%s"; - $options .= " GPRINT:udpInDatagrams:MAX:\ %6.2lf%s\\\\n"; - $options .= " LINE1.25:udpOutDatagrams#006600:OutDatagrams"; - $options .= " GPRINT:udpOutDatagrams:LAST:%6.2lf%s"; - $options .= " GPRINT:udpOutDatagrams:AVERAGE:\ %6.2lf%s"; - $options .= " GPRINT:udpOutDatagrams:MAX:\ %6.2lf%s\\\\n"; - $options .= " LINE1.25:udpInErrors#cc0000:InErrors\ \ \ \ "; - $options .= " GPRINT:udpInErrors:LAST:%6.2lf%s"; - $options .= " GPRINT:udpInErrors:AVERAGE:\ %6.2lf%s"; - $options .= " GPRINT:udpInErrors:MAX:\ %6.2lf%s\\\\n"; - $options .= " LINE1.25:udpNoPorts#660000:NoPorts\ \ \ \ \ "; - $options .= " GPRINT:udpNoPorts:LAST:%6.2lf%s"; - $options .= " GPRINT:udpNoPorts:AVERAGE:\ %6.2lf%s"; - $options .= " GPRINT:udpNoPorts:MAX:\ %6.2lf%s\\\\n"; - $thing = shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; -} - - ?> diff --git a/includes/graphing/unix.php b/includes/graphing/unix.php index a5ed4e9de..d7e53b271 100755 --- a/includes/graphing/unix.php +++ b/includes/graphing/unix.php @@ -1,9 +1,9 @@ $b_in:$b_out:$p_in:$p_out ");} + $rrdfile = $host_rrd . "/cip-" . $acc['ifIndex'] . "-" . $acc['mac'] . ".rrd"; + + if(!is_file($rrdfile)) { + $woo = shell_exec($config['rrdtool'] ." create $rrdfile \ + DS:IN:COUNTER:600:0:12500000000 \ + DS:OUT:COUNTER:600:0:12500000000 \ + DS:PIN:COUNTER:600:0:12500000000 \ + DS:POUT:COUNTER:600:0:12500000000 \ + RRA:AVERAGE:0.5:1:600 \ + RRA:AVERAGE:0.5:6:700 \ + RRA:AVERAGE:0.5:24:775 \ + RRA:AVERAGE:0.5:288:797 \ + RRA:MAX:0.5:1:600 \ + RRA:MAX:0.5:6:700 \ + RRA:MAX:0.5:24:775 \ + RRA:MAX:0.5:288:797"); + } + $woo = "N:".($b_in+0).":".($b_out+0).":".($p_in+0).":".($p_out+0); + if($debug) {echo("\n rrdtool update $rrdfile $woo");} + $ret = rrdtool_update("$rrdfile", $woo); + + if ($update) { /// Do Updates + $update_query = "UPDATE `mac_accounting` SET ".$update." WHERE `ma_id` = '" . $acc['ma_id'] . "'"; + @mysql_query($update_query); $mysql++; + if($debug) {echo("\nMYSQL : [ $update_query ]");} + } /// End Updates + unset($update_query); unset($update); + + } +} + +if($mac_entries) { echo("$mac_entries mac accounting entries updated\n"); } + +?> diff --git a/includes/polling/interfaces.inc.php b/includes/polling/interfaces.inc.php index cee6eb951..5c72bbcf6 100644 --- a/includes/polling/interfaces.inc.php +++ b/includes/polling/interfaces.inc.php @@ -3,7 +3,7 @@ if($device['os'] == "CatOS" || $device['os'] == "IOS") { $portifIndex = array(); $cmd = $config['snmpwalk'] . " -CI -m CISCO-STACK-MIB -O q -" . $device['snmpver'] . " -c " . $device['community'] . " " . $device['hostname'].":".$device['port'] . " portIfIndex"; - echo("$cmd"); + #echo("$cmd"); $portifIndex_output = trim(shell_exec($cmd)); foreach(explode("\n", $portifIndex_output) as $entry){ $entry = str_replace("CISCO-STACK-MIB::portIfIndex.", "", $entry); @@ -118,7 +118,7 @@ while ($interface = mysql_fetch_array($interface_query)) { $update_query = "UPDATE `interfaces` SET "; $update_query .= $update; $update_query .= " WHERE `interface_id` = '" . $interface['interface_id'] . "'"; - echo("Updating : " . $device['hostname'] . " $ifDescr\nSQL :$update_query\n\n"); + #echo("Updating : " . $device['hostname'] . " $ifDescr\nSQL :$update_query\n\n"); $update_result = mysql_query($update_query); } else { # echo("Not Updating : " . $device['hostname'] ." $ifDescr ( " . $interface['ifDescr'] . " )\n\n"); @@ -147,7 +147,7 @@ while ($interface = mysql_fetch_array($interface_query)) { $ret = rrdtool_update("$rrdfile", $woo); } else { - echo("Interface " . $device['hostname'] . " " . $interface['ifDescr'] . " is down\n"); + #echo("Interface " . $device['hostname'] . " " . $interface['ifDescr'] . " is down\n"); } } diff --git a/includes/polling/ports.inc.php b/includes/polling/ports.inc.php new file mode 100755 index 000000000..02f5dd894 --- /dev/null +++ b/includes/polling/ports.inc.php @@ -0,0 +1,167 @@ + (count($ports)*2.5)) { /// If there are 2.5x more interfaces than OIDs, do per-OID + $sub_start = utime(); + echo("Caching Ports: "); + foreach($ports as $port) { echo("$port "); $array = snmp_cache_port_oids($ifmib_oids, $port, $device, $array, "IF-MIB"); } + $end = utime(); $run = $end - $sub_start; $proctime = substr($run, 0, 5); + #echo("\n$proctime secs\n"); + } else { + $sub_start = utime(); + echo("Caching Oids: "); + foreach ($ifmib_oids as $oid) { echo("$oid "); $array = snmp_cache_oid($oid, $device, $array, "IF-MIB"); } + $end = utime(); $run = $end - $sub_start; $proctime = substr($run, 0, 5); + #echo("\n$proctime secs\n"); + } + + #foreach ($etherlike_oids as $oid) { $array = snmp_cache_oid($oid, $device, $array, "EtherLike-MIB"); } + #foreach ($cisco_oids as $oid) { $array = snmp_cache_oid($oid, $device, $array, "OLD-CISCO-INTERFACES-MIB"); } + #foreach ($pagp_oids as $oid) { $array = snmp_cache_oid($oid, $device, $array, "CISCO-PAGP-MIB"); } + + if($device['os'] == "IOS" || $device['os'] == "CatOS" || $device['os'] == "IOS XE") { + #$array = snmp_cache_portIfIndex ($device, $array); + #$array = snmp_cache_portName ($device, $array); + #$array = snmp_cache_oid("vmVlan", $device, $array, "CISCO-VLAN-MEMBERSHIP-MIB"); + #$array = snmp_cache_oid("vlanTrunkPortEncapsulationOperType", $device, $array, "CISCO-VTP-MIB"); + #$array = snmp_cache_oid("vlanTrunkPortNativeVlan", $device, $array, "CISCO-VTP-MIB"); + } + + $polled = time(); + + /// End Building SNMP Cache Array + + if($debug) { print_r($array); } + + /// New interface detection + ///// TO DO + /// End New interface detection + + /// Loop interfaces in the DB and update where necessary + $port_query = mysql_query("SELECT * FROM `interfaces` WHERE `device_id` = '".$device['device_id']."'"); + while ($port = mysql_fetch_array($port_query)) { + + echo(" --> " . $port['ifDescr'] . " "); + if($array[$device[device_id]][$port[ifIndex]]) { // Check to make sure Port data is cached. + + $this_port = &$array[$device[device_id]][$port[ifIndex]]; + + $polled_period = $polled - $port['poll_time']; + + $update .= "`poll_time` = '".$polled."'"; + $update .= ", `poll_prev` = '".$port['poll_time']."'"; + $update .= ", `poll_period` = '".$polled_period."'"; + + /// Copy ifHC[In|Out]Octets values to non-HC if they exist + if(isset($this_port['ifHCInOctets']) && isset($this_port['ifHCOutOctets'])) { + echo("HC "); + $this_port['ifInOctets'] = $this_port['ifHCInOctets']; + $this_port['ifOutOctets'] = $this_port['ifHCOutOctets']; + } + + /// Update IF-MIB data + foreach ($data_oids as $oid) { + if ( $port[$oid] != $this_port[$oid]) { + $update .= ", `$oid` = '".mysql_real_escape_string($this_port[$oid])."'"; + #mysql_query("INSERT INTO eventlog (`host`, `interface`, `datetime`, `message`) VALUES ('" . $port['device_id'] . "', '" . $port['interface_id'] . "', NOW(), '".$oid . ": ".$port[$oid]." -> " . $this_port[$oid]."')"); + #eventlog($device['device_id'], 'interface', $port['interface_id'], $oid . ": ".$port[$oid]." -> " . $this_port[$oid]); + echo($oid . " "); + } + } + + /// Update IF-MIB metrics + foreach ($stat_oids_db as $oid) { + $update .= ", `$oid` = '".$this_port[$oid]."'"; + $update .= ", `".$oid."_prev` = '".$port[$oid]."'"; + $oid_prev = $oid . "_prev"; + if($port[$oid]) { + $oid_diff = $this_port[$oid] - $port[$oid]; + $oid_rate = $oid_diff / $polled_period; + $update .= ", `".$oid."_rate` = '".$oid_rate."'"; + $update .= ", `".$oid."_delta` = '".$oid_diff."'"; + #echo("\n $oid ($oid_diff B) $oid_rate Bps $polled_period secs\n"); + } + } + + /// Update RRDs + $rrdfile = $host_rrd . "/" . $port['ifIndex'] . ".rrd"; + if(!is_file($rrdfile)) { + $woo = shell_exec($config['rrdtool'] . " create $rrdfile -s 300 \ + DS:INOCTETS:DERIVE:600:0:12500000000 \ + DS:OUTOCTETS:DERIVE:600:0:12500000000 \ + DS:INERRORS:DERIVE:600:0:12500000000 \ + DS:OUTERRORS:DERIVE:600:0:12500000000 \ + DS:INUCASTPKTS:DERIVE:600:0:12500000000 \ + DS:OUTUCASTPKTS:DERIVE:600:0:12500000000 \ + DS:INNUCASTPKTS:DERIVE:600:0:12500000000 \ + DS:OUTNUCASTPKTS:DERIVE:600:0:12500000000 \ + RRA:AVERAGE:0.5:1:600 \ + RRA:AVERAGE:0.5:6:700 \ + RRA:AVERAGE:0.5:24:775 \ + RRA:AVERAGE:0.5:288:797 \ + RRA:MAX:0.5:1:600 \ + RRA:MAX:0.5:6:700 \ + RRA:MAX:0.5:24:775 \ + RRA:MAX:0.5:288:797"); + } + + foreach ($stat_oids as $oid) { /// Copy values from array to global variables and force numeric. + $$oid = $this_port[$oid]; + $$oid = $$oid+0; + } + + $woo = "$polled:$ifInOctets:$ifOutOctets:$ifInErrors:$ifOutErrors:$ifInUcastPkts:$ifOutUcastPkts:$ifInNUcastPkts:$ifOutNUcastPkts"; + echo("\n rrdtool update $rrdfile $woo\n"); + $ret = rrdtool_update("$rrdfile", $woo); + + /// End Update IF-MIB + + /// Update PAgP + if($this_port['pagpOperationMode']) { + foreach ($pagp_oids as $oid) { // Loop the OIDs + if ( $this_port[$oid] != $port[$oid] ) { // If data has changed, build a query + $update .= ", `$oid` = '".mres($this_port[$oid])."'"; + echo("PAgP "); + } + } + } + // End Update PAgP + + if ($update) { /// Do Updates + $update_query = "UPDATE `interfaces` SET ".$update." WHERE `interface_id` = '" . $port['interface_id'] . "'"; + @mysql_query($update_query); $mysql++; + if($debug) {echo("\nMYSQL : [ $update_query ]");} + } /// End Updates + + unset($update_query); unset($update); + } else { + echo("Port Deleted?"); // Port missing from SNMP cache? + } + echo("\n"); + } + +?> diff --git a/includes/procurve-graphing.php b/includes/procurve-graphing.php index 637220999..eb854c552 100755 --- a/includes/procurve-graphing.php +++ b/includes/procurve-graphing.php @@ -2,10 +2,8 @@ function cpugraphHP ($rrd, $graph , $from, $to, $width, $height) { - global $config, $installdir; + global $config; $database = "rrd/" . $rrd; - $imgfile = "graphs/" . "$graph"; - $optsa = array( "--start", $from, "--width", $width, "--height", $height, "--vertical-label", $vertical, "--alt-autoscale-max", "-l 0", "-E", @@ -23,14 +21,14 @@ function cpugraphHP ($rrd, $graph , $from, $to, $width, $height) "--font-render-mode", "normal");} $opts = array_merge($config['rrdgraph_defaults'], $$optsa, $optsb); - $ret = rrd_graph("$imgfile", $opts, count($opts)); + $ret = rrd_graph("$graph", $opts, count($opts)); if( !is_array($ret) ) { $err = rrd_error(); #echo "rrd_graph() ERROR: $err\n"; return FALSE; } else { - return $imgfile; + return $graph; } } @@ -38,7 +36,7 @@ function memgraphHP ($rrd, $graph , $from, $to, $width, $height, $title, $vertic { global $config, $installdir; $database = "rrd/" . $rrd; - $imgfile = "graphs/" . "$graph"; + $memrrd = $database; $opts = array("--start", "$from", "--alt-autoscale-max", "--width", "$width", "--height", "$height", "-l", "0", "-E", "-b", "1024", @@ -55,14 +53,14 @@ function memgraphHP ($rrd, $graph , $from, $to, $width, $height, $title, $vertic $opts = array_merge($config['rrdgraph_defaults'], $$opts, $optsb); - $ret = rrd_graph("$imgfile", $opts, count($opts)); + $ret = rrd_graph("$graph", $opts, count($opts)); if( !is_array($ret) ) { $err = rrd_error(); #echo "rrd_graph() ERROR: $err\n"; return FALSE; } else { - return $imgfile; + return $graph; } } diff --git a/includes/static-config.php b/includes/static-config.php index f102adc04..08907315b 100644 --- a/includes/static-config.php +++ b/includes/static-config.php @@ -68,8 +68,8 @@ $year = time() - (365 * 24 * 60 * 60); ### Update Database between 0.6.0 and 0.6.1 (slight slowdown) $exists = false; -$columns = mysql_query("SHOW columns FROM `interfaces`"); -while($c = mysql_fetch_assoc($columns)){ +$columns = @mysql_query("SHOW columns FROM `interfaces`"); +while($c = @mysql_fetch_assoc($columns)){ if($c['Field'] == "pagpOperationMode"){ $db_pagp = true; } diff --git a/includes/unix-graphing.php b/includes/unix-graphing.php index a3bf53d33..c98aa52e7 100755 --- a/includes/unix-graphing.php +++ b/includes/unix-graphing.php @@ -3,7 +3,6 @@ function mailerrorgraphUnix ($rrd, $graph, $from, $to, $width, $height, $title, $vertical) { global $config, $installdir; $database = $config['rrd_dir'] . "/" . $rrd; - $imgfile = "graphs/" . "$graph"; $period = $to - $from; $options = "--alt-autoscale-max -E --start $from --end $to --width $width --height $height "; if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } @@ -55,14 +54,14 @@ function mailerrorgraphUnix ($rrd, $graph, $from, $to, $width, $height, $title, $options .= " GPRINT:sspam:MAX:\ %6.0lf"; $options .= " GPRINT:rspam:AVERAGE:\ \ %5.2lf/min"; $options .= " GPRINT:rmspam:MAX:\ %5.2lf/min\\\\l"; - shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; + shell_exec($config['rrdtool'] . " graph $graph $options"); + return $graph; } function mailsgraphUnix ($rrd, $graph, $from, $to, $width, $height, $title, $vertical) { global $config, $installdir; $database = $config['rrd_dir'] . "/" . $rrd; - $imgfile = "graphs/" . "$graph"; + $period = $to - $from; $options = "--alt-autoscale-max -E --start $from --end $to --width $width --height $height "; if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } @@ -93,14 +92,14 @@ function mailsgraphUnix ($rrd, $graph, $from, $to, $width, $height, $title, $ver $options .= " GPRINT:srecv:MAX:\ \ %6.0lf"; $options .= " GPRINT:rrecv:AVERAGE:\ \ %5.2lf/min"; $options .= " GPRINT:rmrecv:MAX:\ %5.2lf/min\\\\l"; - shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; + shell_exec($config['rrdtool'] . " graph $graph $options"); + return $graph; } function memgraphUnix ($rrd, $graph, $from, $to, $width, $height, $title, $vertical) { global $config, $installdir; $database = $config['rrd_dir'] . "/" . $rrd; - $imgfile = "graphs/" . "$graph"; + $options = "--alt-autoscale-max -E --start $from --end $to --width $width --height $height -b 1024"; if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } $options .= " DEF:atotalswap=$database:totalswap:AVERAGE"; @@ -158,14 +157,14 @@ function memgraphUnix ($rrd, $graph, $from, $to, $width, $height, $title, $verti $options .= " LINE1:totalreal#050505:total"; $options .= " GPRINT:totalreal:AVERAGE:\ \ %7.2lf%sB"; - shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; + shell_exec($config['rrdtool'] . " graph $graph $options"); + return $graph; } function loadgraphUnix ($rrd, $graph, $from, $to, $width, $height, $title, $vertical) { global $config, $installdir; $database = $config['rrd_dir'] . "/" . $rrd; - $imgfile = "graphs/" . "$graph"; + $period = $to - $from; $options = "--alt-autoscale-max -E --start $from --end $to --width $width --height $height "; if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } @@ -190,15 +189,15 @@ function loadgraphUnix ($rrd, $graph, $from, $to, $width, $height, $title, $vert $options .= " GPRINT:c:LAST:\ \ \ %7.2lf"; $options .= " GPRINT:c:AVERAGE:\ \ %7.2lf"; $options .= " GPRINT:c:MAX:\ \ %7.2lf\\\\n"; - shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; + shell_exec($config['rrdtool'] . " graph $graph $options"); + return $graph; } function usersgraphUnix ($rrd, $graph, $from, $to, $width, $height, $title, $vertical) { global $config, $installdir; $database = $config['rrd_dir'] . "/" . $rrd; - $imgfile = "graphs/" . "$graph"; + $period = $to - $from; $options = "--alt-autoscale-max -E --start $from --end $to --width $width --height $height -l 0"; if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } @@ -210,14 +209,13 @@ function usersgraphUnix ($rrd, $graph, $from, $to, $width, $height, $title, $ver $options .= " GPRINT:users:AVERAGE:%6.2lf"; $options .= " GPRINT:users:MIN:%6.2lf"; $options .= " GPRINT:users:MAX:%6.2lf\\\\n"; - shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; + shell_exec($config['rrdtool'] . " graph $graph $options"); + return $graph; } function procsgraphUnix ($rrd, $graph, $from, $to, $width, $height, $title, $vertical) { global $config, $installdir; $database = $config['rrd_dir'] . "/" . $rrd; - $imgfile = "graphs/" . "$graph"; $period = $to - $from; $options = "--alt-autoscale-max -E --start $from --end $to --width $width --height $height -l 0"; if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } @@ -229,17 +227,15 @@ function procsgraphUnix ($rrd, $graph, $from, $to, $width, $height, $title, $ver $options .= " GPRINT:procs:AVERAGE:%6.2lf"; $options .= " GPRINT:procs:MIN:%6.2lf"; $options .= " GPRINT:procs:MAX:%6.2lf\\\\n"; - shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; - + shell_exec($config['rrdtool'] . " graph $graph $options"); + return $graph; } function cpugraphUnix ($rrd, $graph, $from, $to, $width, $height, $title, $vertical) { - global $config, $installdir; + global $config; $database = $config['rrd_dir'] . "/" . $rrd; - $imgfile = "graphs/" . "$graph"; $period = $to - $from; $options = "-l 0 --alt-autoscale-max -E --start $from --end $to --width $width --height $height "; if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } @@ -269,14 +265,13 @@ function cpugraphUnix ($rrd, $graph, $from, $to, $width, $height, $title, $verti $options .= " GPRINT:idle_perc:LAST:\ \ \ \ \ %5.2lf%%"; $options .= " GPRINT:idle_perc:AVERAGE:\ \ \ %5.2lf%%"; $options .= " GPRINT:idle_perc:MAX:\ \ \ %5.2lf%%\\\\n"; - shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; + shell_exec($config['rrdtool'] . " graph $graph $options"); + return $graph; } function couriergraphUnix ($rrd, $graph, $from, $to, $width, $height, $title, $vertical) { global $config, $installdir; - $database = $config['rrd_dir'] . "/" . $rrd; - $imgfile = "graphs/" . "$graph"; + $database = $config['rrd_dir'] . "/" . $rrd; $period = $to - $from; $options = "--alt-autoscale-max -E --start $from --end $to --width $width --height $height "; if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } @@ -319,14 +314,14 @@ function couriergraphUnix ($rrd, $graph, $from, $to, $width, $height, $title, $v $options .= " GPRINT:vimapd_ssl_login:AVERAGE:\ %6.0lf"; $options .= " GPRINT:rimapd_ssl_login:AVERAGE:%5.2lf/min"; $options .= " GPRINT:rmimapd_ssl_login:MAX:%5.2lf/min\\\\l"; - shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; + shell_exec($config['rrdtool'] . " graph $graph $options"); + return $graph; } function apachehitsgraphUnix ($rrd, $graph, $from, $to, $width, $height, $title, $vertical) { global $config, $installdir; $database = $config['rrd_dir'] . "/" . $rrd; - $imgfile = "graphs/" . "$graph"; + $options = "--alt-autoscale-max -E --start $from --end $to --width $width --height $height -l 0"; if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } $options .= " DEF:hits=$database:hits:AVERAGE"; @@ -336,13 +331,13 @@ function apachehitsgraphUnix ($rrd, $graph, $from, $to, $width, $height, $title, $options .= " GPRINT:hits:LAST:\ %6.2lf/sec"; $options .= " GPRINT:hits:AVERAGE:%6.2lf/sec"; $options .= " GPRINT:hits:MAX:%6.2lf/sec\\\\n"; - shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; + shell_exec($config['rrdtool'] . " graph $graph $options"); + return $graph; } function unixfsgraph ($id, $graph, $from, $to, $width, $height, $title, $vertical) { global $config, $installdir; - $imgfile = "graphs/" . "$graph"; + $options = "--alt-autoscale-max -E --start $from --end $to --width $width --height $height -b 1024 -l 0"; if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } $hostname = gethostbyid($device); @@ -367,47 +362,14 @@ function unixfsgraph ($id, $graph, $from, $to, $width, $height, $title, $vertica $options .= " GPRINT:$fs[storage_id]p:LAST:%5.2lf%%\\\\l"; $iter++; } - shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; + shell_exec($config['rrdtool'] . " graph $graph $options"); + return $graph; } -function unixfsgraph_dev ($device, $graph, $from, $to, $width, $height, $title, $vertical) { - global $config, $installdir; - $database = $config['rrd_dir'] . "/" . $rrd; - $imgfile = "graphs/" . "$graph"; - $options = "--alt-autoscale-max -E --start $from --end $to --width $width --height $height -b 1024 -l 0"; - if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } - $hostname = gethostbyid($device); - $iter = "1"; - $sql = mysql_query("SELECT * FROM storage where host_id = '$device'"); - $options .= "COMMENT:\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Size\ \ \ \ \ \ Used\ \ \ \ %age\l"; - while($fs = mysql_fetch_array($sql)) { - if($iter=="1") {$colour="CC0000";} elseif($iter=="2") {$colour="008C00";} elseif($iter=="3") {$colour="4096EE"; - } elseif($iter=="4") {$colour="73880A";} elseif($iter=="5") {$colour="D01F3C";} elseif($iter=="6") {$colour="36393D"; - } elseif($iter=="7") {$colour="FF0084"; $iter = "0"; } - - $descr = str_pad($fs[hrStorageDescr], 14); - $descr = substr($descr,0,14); - $text = str_replace("/", "_", $fs['hrStorageDescr']); - $rrd = $config['rrd_dir'] . "/$hostname/storage-$text.rrd"; - $options .= " DEF:$fs[storage_id]=$rrd:used:AVERAGE"; - $options .= " DEF:$fs[storage_id]s=$rrd:size:AVERAGE"; - $options .= " DEF:$fs[storage_id]p=$rrd:perc:AVERAGE"; - $options .= " LINE1.25:$fs[storage_id]p#" . $colour . ":'$descr'"; - $options .= " GPRINT:$fs[storage_id]s:LAST:%6.2lf%SB"; - $options .= " GPRINT:$fs[storage_id]:LAST:%6.2lf%SB"; - $options .= " GPRINT:$fs[storage_id]p:LAST:%5.2lf%%\\\\l"; - $iter++; - } - shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; -} - function apachebitsgraphUnix ($rrd, $graph, $from, $to, $width, $height, $title, $vertical) { global $config, $installdir; - $database = $config['rrd_dir'] . "/" . $rrd; - $imgfile = "graphs/" . "$graph"; + $database = $config['rrd_dir'] . "/" . $rrd; $options = "--alt-autoscale-max -E --start $from --end $to --width $width --height $height -l 0"; if($width <= "300") { $options .= " --font LEGEND:7:".$config['mono_font']." --font AXIS:6:".$config['mono_font']." --font-render-mode normal "; } $options .= " DEF:bits=$database:bits:AVERAGE"; @@ -417,6 +379,6 @@ function apachebitsgraphUnix ($rrd, $graph, $from, $to, $width, $height, $title, $options .= " GPRINT:bits:LAST:\ %6.2lf/sec"; $options .= " GPRINT:bits:AVERAGE:%6.2lf/sec"; $options .= " GPRINT:bits:MAX:%6.2lf/sec\\\\n"; - shell_exec($config['rrdtool'] . " graph $imgfile $options"); - return $imgfile; + shell_exec($config['rrdtool'] . " graph $graph $options"); + return $graph; } diff --git a/poll-device.php b/poll-device.php index 5295ae0dd..b2b3d30b3 100755 --- a/poll-device.php +++ b/poll-device.php @@ -3,33 +3,33 @@ include("config.php"); include("includes/functions.php"); +include("includes/functions-poller.inc.php"); + +$poller_start = utime(); echo("Observer Poller v".$config['version']."\n\n"); -if($argv[1] == "--device" && $argv[2]) { - $where = "AND `device_id` = '".$argv[2]."'"; -} elseif ($argv[1] == "--odd") { +$options = getopt("h:t:i:n:d::a::"); + +if ($options['h'] == "odd") { $where = "AND MOD(device_id,2) = 1"; -} elseif ($argv[1] == "--even") { + $doing = $options['h']; +} elseif ($options['h'] == "even") { $where = "AND MOD(device_id,2) = 0"; -} elseif ($argv[1] == "--odd3") { - $where = "AND MOD(device_id,2) = 1 AND device_id NOT LIKE '%1'"; -} elseif ($argv[1] == "--even3") { - $where = "AND MOD(device_id,2) = 0 AND device_id NOT LIKE '%2'"; -} elseif ($argv[1] == "--other3") { - $where = "AND (device_id LIKE '%1' OR device_id LIKE '%2')"; - -} elseif ($argv[1] == "--all") { - -} else { - echo("--device Poll single device\n"); - echo("--all Poll all devices\n\n"); - echo("No polling type specified!\n"); - exit; + $doing = $options['h']; +} elseif($options['h']) { + $where = "AND `device_id` = '".$options['h']."'"; + $doing = "Host ".$options['h']; +} elseif ($options['i'] && isset($options['n'])) { + $where = "AND MOD(device_id,".$options['i'].") = '" . $options['n'] . "'"; + $doing = "Proc ".$options['n'] ."/".$options['i']; +} elseif ($options['h'] == "all") { + $where = " "; + $doing = "all"; } echo("Starting polling run:\n\n"); - +$i = 0; $device_query = mysql_query("SELECT * FROM `devices` WHERE `ignore` = '0' $where ORDER BY `device_id` ASC"); while ($device = mysql_fetch_array($device_query)) { @@ -154,10 +154,15 @@ while ($device = mysql_fetch_array($device_query)) { echo("Polling temperatures\n"); include("includes/polling/temperatures.inc.php"); include("includes/polling/device-netstats.inc.php"); - echo("Polling interfaces\n"); - $where = "WHERE device_id = '" . $device['device_id'] . "' AND deleted = '0'"; - include("includes/polling/interfaces.inc.php"); +# echo("Polling interfaces\n"); +# $where = "WHERE device_id = '" . $device['device_id'] . "' AND deleted = '0'"; +# include("includes/polling/interfaces.inc.php"); + + include("includes/polling/ports.inc.php"); + include("includes/polling/ports-etherlike.inc.php"); + include("includes/polling/cisco-mac-accounting.inc.php"); + $update_uptime_attrib = mysql_query("UPDATE devices_attribs SET attrib_value = NOW() WHERE `device_id` = '" . $device['device_id'] . "' AND `attrib_type` = 'polled'"); @@ -276,9 +281,16 @@ while ($device = mysql_fetch_array($device_query)) { } else { echo("No Changes to " . $device['hostname'] . "\n"); } - + $i++; echo("\n"); } +$poller_end = utime(); $poller_run = $poller_end - $poller_start; $poller_time = substr($poller_run, 0, 5); + +$string = $argv[0] . " $doing " . date("F j, Y, G:i") . " - $i devices polled in $poller_time secs"; +echo("$string\n"); +shell_exec("echo '".$string."' >> /opt/observer/observer.log"); + + ?> diff --git a/poll-mac_accounting.php b/poll-mac_accounting.php deleted file mode 100755 index cf484cb76..000000000 --- a/poll-mac_accounting.php +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/php - $rrdfile \n"); }; - $pkts_rrdfile = $acc_rrd . "/" . $acc['ifIndex'] . "-" . $acc['mac'] . "-pkts.rrd"; - - if(!is_file($pkts_rrdfile)) { - $woo = shell_exec($config['rrdtool'] ." create $pkts_rrdfile \ - DS:IN:COUNTER:600:0:12500000000 \ - DS:OUT:COUNTER:600:0:12500000000 \ - RRA:AVERAGE:0.5:1:600 \ - RRA:AVERAGE:0.5:6:700 \ - RRA:AVERAGE:0.5:24:775 \ - RRA:AVERAGE:0.5:288:797 \ - RRA:MAX:0.5:1:600 \ - RRA:MAX:0.5:6:700 \ - RRA:MAX:0.5:24:775 \ - RRA:MAX:0.5:288:797"); - } - - if(!is_file($rrdfile)) { - $woo = shell_exec($config['rrdtool'] ." create $rrdfile \ - DS:IN:COUNTER:600:0:12500000000 \ - DS:OUT:COUNTER:600:0:12500000000 \ - RRA:AVERAGE:0.5:1:600 \ - RRA:AVERAGE:0.5:6:700 \ - RRA:AVERAGE:0.5:24:775 \ - RRA:AVERAGE:0.5:288:797 \ - RRA:MAX:0.5:1:600 \ - RRA:MAX:0.5:6:700 \ - RRA:MAX:0.5:24:775 \ - RRA:MAX:0.5:288:797"); - } - - $woo = "N:".($in+0).":".($out+0); - $ret = rrdtool_update("$rrdfile", $woo); - - $woo = "N:".($pktin+0).":".($pktout+0); - $ret = rrdtool_update("$pkts_rrdfile", $woo); - -# $rates = interface_rates ($rrdfile); - -# $pkt_rates = interface_rates ($pkts_rrdfile); - - $pkt_rate['in'] = round($pkt_rate['in'] / 8); - $pkt_rate['out'] = round($pkt_rate['out'] / 8); - -# mysql_query("UPDATE `mac_accounting` SET bps_in = '" . $rates['in'] . "', bps_out = '" . $rates['out'] . "', pps_in = '" . $pkt_rates['in'] . "', pps_out = '" . $pkt_rates['out'] . "' WHERE ma_id= '" . $acc['ma_id'] . "'"); - -# echo(formatRates($rates['in']) . " (" . $pkt_rates['in'] . "pps) in " . formatRates($rates['out']) . " (" . $pkt_rates['out'] . "pps) out \n"); - - } -?> diff --git a/poller.php b/poller.php new file mode 100755 index 000000000..255b9b45e --- /dev/null +++ b/poller.php @@ -0,0 +1,84 @@ +#!/usr/bin/php + Poll single device\n"); + echo("-h odd Poll odd numbered devices (same as -i 2 -n 0)\n"); + echo("-h even Poll even numbered devices (same as -i 2 -n 1)\n"); + echo("-a Poll all devices\n\n"); + echo("-i -n Poll as instance of \n\n"); + echo("-d Enable some debugging output\n"); + echo("\n"); + echo("No polling type specified!\n"); + exit; + } + +if(isset($options['d'])) { echo("DEBUG!\n"); $debug = 1; } + +$i = 0; +$device_query = mysql_query("SELECT * FROM `devices` WHERE `ignore` = '0' AND `disabled` = '0' AND `status` = '1' $where ORDER BY device_id DESC"); +while ($device = mysql_fetch_array($device_query)) { + + echo("-> " . $device['hostname'] . "\n"); + + $device_start = utime(); // Start counting device poll time + + $host_rrd = $config['rrd_dir'] . "/" . $device['hostname']; + if(!is_dir($host_rrd)) { mkdir($host_rrd); echo("Created directory : $host_rrd\n"); } + $i++; + + $device['pingable'] = isPingable($device['hostname']); + if($device['pingable']) { + $device['snmpable'] = isSNMPable($device['hostname'], $device['community'], $device['snmpver'], $device['port']); + } + + if($device['pingable'] && $device['snmpable']) { // Reachability Check + if($options['t']) { + include("includes/polling/".$options['t'].".inc.php"); + } else { + include("includes/polling/ports.inc.php"); + include("includes/polling/ports-etherlike.inc.php"); + include("includes/polling/cisco-mac-accounting.inc.php"); + } + } else { echo(" Unreachable"); } // End Reachability Check + + unset($array); // Clear $array SNMP cache + + $device_end = utime(); $device_run = $device_end - $device_start; $device_time = substr($device_run, 0, 5); + + echo("Polled in $device_time seconds\n"); + #shell_exec("echo 'Polled ".$device['hostname']." in $device_time seconds' >> /opt/observer/observer.log"); +} + + +$poller_end = utime(); $poller_run = $poller_end - $poller_start; $poller_time = substr($poller_run, 0, 5); + +$string = $argv[0] . " " . date("F j, Y, G:i") . " - $i devices polled in $poller_time secs"; +echo("$string\n"); + +shell_exec("echo '".$string."' >> /opt/observer/observer.log"); + +?> diff --git a/scripts/update-sql.php b/scripts/update-sql.php new file mode 100755 index 000000000..a6665db00 --- /dev/null +++ b/scripts/update-sql.php @@ -0,0 +1,13 @@ +#!/usr/bin/php + diff --git a/test-poll.php b/test-poll.php index 3d0389e66..57c683c7b 100755 --- a/test-poll.php +++ b/test-poll.php @@ -4,7 +4,7 @@ include("config.php"); include("includes/functions.php"); -$start = utime(); +$poller_start = utime(); ### Observer Device Polling Test @@ -43,16 +43,17 @@ $device_query = mysql_query("SELECT * FROM `devices` WHERE status = '1' $where O while ($device = mysql_fetch_array($device_query)) { echo("\n" . $device['hostname'] ."\n"); - + $host_rrd = $config['rrd_dir'] . "/" . $device['hostname']; + $where = "WHERE device_id = '" . $device['device_id'] . "' AND deleted = '0'"; include("includes/polling/".$type.".inc.php"); echo("\n"); $devices_polled++; } -$end = utime(); $run = $end - $start; -$proctime = substr($run, 0, 5); - -echo("$devices_polled devices polled in $proctime secs\n"); +$poller_end = utime(); $poller_run = $poller_end - $poller_start; $poller_time = substr($poller_run, 0, 5); +$string = $argv[0] . " " . date("F j, Y, G:i") . " - $i devices polled in $poller_time secs"; +echo("$string\n"); +shell_exec("echo '".$string."' >> /opt/observer/observer.log"); ?>