diff --git a/.gitignore b/.gitignore index 2f7c08a528..bf1e1e84af 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ patches rrd /vendor composer.phar +librenms_theme diff --git a/.travis.yml b/.travis.yml index 86c04a8549..9a9295b8c6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,4 @@ +sudo: required language: php matrix: fast_finish: true @@ -24,17 +25,29 @@ matrix: - php: hhvm cache: - directories: + - pip + - directories: - vendor - $HOME/.composer/cache -before_script: +before_install: + - sudo apt-get -qq update + - sudo apt-get install -y snmp + +install: - composer install --prefer-dist --no-interaction + - pip install --user snmpsim + +before_script: + - python2 $HOME/.local/bin/snmpsimd.py --data-dir=$TRAVIS_BUILD_DIR/tests/snmpsim --agent-udpv4-endpoint=127.0.0.1:11161 --logging-method=file:/tmp/snmpsimd.log --daemon --pid-file=/tmp/snmpsimd.pid after_success: - test $TRAVIS_PULL_REQUEST == "false" && test $TRAVIS_BRANCH == "master" && test $EXECUTE_BUILD_DOCS == "true" && bash scripts/deploy-docs.sh +after_failure: + - cat /tmp/snmpsimd.log + script: - - php scripts/pre-commit.php -p -l - - php scripts/pre-commit.php -p -s - - phpunit + - php scripts/pre-commit.php -l + - php scripts/pre-commit.php -s + - SNMPSIM=1 phpunit --stop-on-failure diff --git a/AUTHORS.md b/AUTHORS.md index 7625890b7d..70b46bf4a8 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -134,6 +134,7 @@ LibreNMS contributors: - Konrad Bechler (kbechler) - Florent Bruchez (ftbz) - Bartosz Radwan (bartoszradwan) +- Kate Gerry (kate66) [1]: http://observium.org/ "Observium web site" Observium was written by: diff --git a/LibreNMS/Proc.php b/LibreNMS/Proc.php index a588fdbf18..37e1b6019f 100644 --- a/LibreNMS/Proc.php +++ b/LibreNMS/Proc.php @@ -54,8 +54,18 @@ class Proc * @param bool $blocking set the output pipes to blocking (default: false) * @throws Exception the command was unable to execute */ - public function __construct($cmd, $descriptorspec, $cwd = null, $env = null, $blocking = false) - { + public function __construct( + $cmd, + $descriptorspec = array( + 0 => array("pipe", "r"), + 1 => array("pipe", "w"), + 2 => array("pipe", "w") + ), + $cwd = null, + $env = null, + $blocking = false + ) { + d_echo("Starting process: $cmd"); $this->_process = proc_open($cmd, $descriptorspec, $this->_pipes, $cwd, $env); if (!is_resource($this->_process)) { throw new Exception("Command failed: $cmd"); @@ -102,10 +112,7 @@ class Proc */ public function sendCommand($command) { - if (!ends_with($command, PHP_EOL)) { - $command .= PHP_EOL; - } - $this->sendInput($command); + $this->sendInput($this->checkAddEOL($command)); return $this->getOutput(); } @@ -139,23 +146,36 @@ class Proc return array(stream_get_contents($this->_pipes[1]), stream_get_contents($this->_pipes[2])); } + /** + * Close all pipes for this process + */ + private function closePipes() + { + foreach ($this->_pipes as $pipe) { + if (is_resource($pipe)) { + fclose($pipe); + } + } + } + /** * Attempt to gracefully close this process * optionally send one last piece of input * such as a quit command * - * @param string $cmd the final command to send + * ** Warning: this will block until the process closes. + * Some processes might not close on their own. + * + * @param string $command the final command to send (appends newline if one is ommited) * @return int the exit status of this process (-1 means error) */ - public function close($cmd = null) + public function close($command = null) { - if (isset($cmd)) { - $this->sendInput($cmd); + if (isset($command)) { + $this->sendInput($this->checkAddEOL($command)); } - fclose($this->_pipes[0]); - fclose($this->_pipes[1]); - fclose($this->_pipes[2]); + $this->closePipes(); return proc_close($this->_process); } @@ -172,8 +192,7 @@ class Proc { $status = $this->getStatus(); - fclose($this->_pipes[1]); - fclose($this->_pipes[2]); + $this->closePipes(); $closed = proc_terminate($this->_process, $signal); @@ -234,4 +253,19 @@ class Proc { $this->_synchronous = $synchronous; } + + /** + * Add and end of line character to a string if + * it doesn't already end with one + * + * @param $string + * @return string + */ + private function checkAddEOL($string) + { + if (!ends_with($string, PHP_EOL)) { + $string .= PHP_EOL; + } + return $string; + } } diff --git a/doc/API/API-Docs.md b/doc/API/API-Docs.md index 320c434285..5f759051c2 100644 --- a/doc/API/API-Docs.md +++ b/doc/API/API-Docs.md @@ -96,9 +96,9 @@ Output Input to the API is done in three different ways, sometimes a combination two or three of these. -- Passing parameters via the api route. For example when obtaining a devices details you will pass the hostname of the device in the route: `/api/v0/devices/:hostname`. -- Passing parameters via the query string. For example you can list all devices on your install but limit the output to devices that are currently down: `/api/v0/devices?type=down` -- Passing data in via JSON, this will mainly be used when adding or updating information via the API, for instance adding a new device: + - Passing parameters via the api route. For example when obtaining a devices details you will pass the hostname of the device in the route: `/api/v0/devices/:hostname`. + - Passing parameters via the query string. For example you can list all devices on your install but limit the output to devices that are currently down: `/api/v0/devices?type=down` + - Passing data in via JSON, this will mainly be used when adding or updating information via the API, for instance adding a new device: ```curl curl -X POST -d '{"hostname":"localhost.localdomain","version":"v1","community":"public"}'-H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices ``` @@ -107,8 +107,8 @@ curl -X POST -d '{"hostname":"localhost.localdomain","version":"v1","community": Output from the API currently is via two output types. -- JSON Most API responses will output json. As show in the example for calling the API endpoint. -- PNG This is for when the request is for an image such as a graph for a switch port. + - JSON Most API responses will output json. As show in the example for calling the API endpoint. + - PNG This is for when the request is for an image such as a graph for a switch port. # `Endpoints` [`top`](#top) @@ -120,11 +120,11 @@ Delete a given device. Route: /api/v0/devices/:hostname -- hostname can be either the device hostname or id + - hostname can be either the device hostname or id Input: - - + - Example: ```curl @@ -154,11 +154,11 @@ Get details of a given device. Route: /api/v0/devices/:hostname -- hostname can be either the device hostname or id + - hostname can be either the device hostname or id Input: - - + - Example: ```curl @@ -187,11 +187,11 @@ Get a list of available graphs for a device, this does not include ports. Route: /api/v0/devices/:hostname/graphs -- hostname can be either the device hostname or id + - hostname can be either the device hostname or id Input: - - + - Example: ```curl @@ -227,15 +227,15 @@ Get a specific graph for a device, this does not include ports. Route: /api/v0/devices/:hostname/:type -- hostname can be either the device hostname or id -- type is the type of graph you want, use [`get_graphs`](#api-route-5) to see the graphs available. Defaults to device_uptime. + - hostname can be either the device hostname or id + - type is the type of graph you want, use [`get_graphs`](#api-route-5) to see the graphs available. Defaults to device_uptime. Input: - - from: This is the date you would like the graph to start - See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more information. - - to: This is the date you would like the graph to end - See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more information. - - width: The graph width, defaults to 1075. - - height: The graph height, defaults to 300. + - from: This is the date you would like the graph to start - See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more information. + - to: This is the date you would like the graph to end - See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more information. + - width: The graph width, defaults to 1075. + - height: The graph height, defaults to 300. Example: ```curl @@ -252,11 +252,11 @@ Get a list of ports for a particular device. Route: /api/v0/devices/:hostname/ports -- hostname can be either the device hostname or id + - hostname can be either the device hostname or id Input: - - columns: Comma separated list of columns you want returned. + - columns: Comma separated list of columns you want returned. Example: ```curl @@ -290,11 +290,11 @@ Get a list of port mappings for a device. This is useful for showing physical p Route: /api/v0/devices/:hostname/port_stack -- hostname can be either the device hostname or id + - hostname can be either the device hostname or id Input: - - valid_mappings: Filter the result by only showing valid mappings ("0" values not shown). + - valid_mappings: Filter the result by only showing valid mappings ("0" values not shown). Example: ```curl @@ -331,16 +331,16 @@ Get a list of components for a particular device. Route: /api/v0/devices/:hostname/components -- hostname can be either the device hostname or id + - hostname can be either the device hostname or id Input: - - type: Filter the result by type (Equals). - - id: Filter the result by id (Equals). - - label: Filter the result by label (Contains). - - status: Filter the result by status (Equals). - - disabled: Filter the result by disabled (Equals). - - ignore: Filter the result by ignore (Equals). + - type: Filter the result by type (Equals). + - id: Filter the result by id (Equals). + - label: Filter the result by label (Contains). + - status: Filter the result by status (Equals). + - disabled: Filter the result by disabled (Equals). + - ignore: Filter the result by ignore (Equals). Example: ```curl @@ -395,8 +395,8 @@ Create a new component of a type on a particular device. Route: /api/v0/devices/:hostname/components/:type -- hostname can be either the device hostname or id -- type is the type of component to add + - hostname can be either the device hostname or id + - type is the type of component to add Example: ```curl @@ -429,7 +429,7 @@ Edit an existing component on a particular device. Route: /api/v0/devices/:hostname/components -- hostname can be either the device hostname or id + - hostname can be either the device hostname or id In this example we set the label and add a new field: TestField: ```curl @@ -454,8 +454,8 @@ Delete an existing component on a particular device. Route: /api/v0/devices/:hostname/components/:component -- hostname can be either the device hostname or id -- component is the component ID to be deleted. + - hostname can be either the device hostname or id + - component is the component ID to be deleted. Example: ```curl @@ -477,12 +477,12 @@ Get information about a particular port for a device. Route: /api/v0/devices/:hostname/ports/:ifname -- hostname can be either the device hostname or id -- ifname can be any of the interface names for the device which can be obtained using [`get_port_graphs`](#api-route-7). Please ensure that the ifname is urlencoded if it needs to be (i.e Gi0/1/0 would need to be urlencoded. + - hostname can be either the device hostname or id + - ifname can be any of the interface names for the device which can be obtained using [`get_port_graphs`](#api-route-7). Please ensure that the ifname is urlencoded if it needs to be (i.e Gi0/1/0 would need to be urlencoded. Input: - - columns: Comma separated list of columns you want returned. + - columns: Comma separated list of columns you want returned. Example: ```curl @@ -510,17 +510,17 @@ Get a graph of a port for a particular device. Route: /api/v0/devices/:hostname/ports/:ifname/:type -- hostname can be either the device hostname or id -- ifname can be any of the interface names for the device which can be obtained using [`get_port_graphs`](#api-route-7). Please ensure that the ifname is urlencoded if it needs to be (i.e Gi0/1/0 would need to be urlencoded. -- type is the port type you want the graph for, you can request a list of ports for a device with [`get_port_graphs`](#api-route-7). + - hostname can be either the device hostname or id + - ifname can be any of the interface names for the device which can be obtained using [`get_port_graphs`](#api-route-7). Please ensure that the ifname is urlencoded if it needs to be (i.e Gi0/1/0 would need to be urlencoded. + - type is the port type you want the graph for, you can request a list of ports for a device with [`get_port_graphs`](#api-route-7). Input: - - from: This is the date you would like the graph to start - See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more information. - - to: This is the date you would like the graph to end - See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more information. - - width: The graph width, defaults to 1075. - - height: The graph height, defaults to 300. - - ifDescr: If this is set to true then we will use ifDescr to lookup the port instead of ifName. Pass the ifDescr value you want to search as you would ifName. + - from: This is the date you would like the graph to start - See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more information. + - to: This is the date you would like the graph to end - See http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html for more information. + - width: The graph width, defaults to 1075. + - height: The graph height, defaults to 300. + - ifDescr: If this is set to true then we will use ifDescr to lookup the port instead of ifName. Pass the ifDescr value you want to search as you would ifName. Example: ```curl @@ -539,17 +539,17 @@ Route: /api/v0/devices Input: - - order: How to order the output, default is by hostname. Can be prepended by DESC or ASC to change the order. - - type: can be one of the following to filter or search by: - - all: All devices - - ignored: Only ignored devices - - up: Only devices that are up - - down: Only devices that are down - - disabled: Disabled devices - - mac: search by mac address - - ipv4: search by IPv4 address - - ipv6: search by IPv6 address (compressed or uncompressed) - - query: If searching by, then this will be used as the input. + - order: How to order the output, default is by hostname. Can be prepended by DESC or ASC to change the order. + - type: can be one of the following to filter or search by: + - all: All devices + - ignored: Only ignored devices + - up: Only devices that are up + - down: Only devices that are down + - disabled: Disabled devices + - mac: search by mac address + - ipv4: search by IPv4 address + - ipv6: search by IPv6 address (compressed or uncompressed) + - query: If searching by, then this will be used as the input. Example: ```curl curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/devices?order=hostname%20DESC&type=down @@ -604,25 +604,25 @@ Route: /api/v0/devices Input (JSON): - - hostname: device hostname - - port: SNMP port (defaults to port defined in config). - - transport: SNMP protocol (defaults to transport defined in config). - - version: SNMP version to use, v1, v2c or v3. Defaults to v2c. - - poller_group: This is the poller_group id used for distributed poller setup. Defaults to 0. - - force_add: Force the device to be added regardless of it being able to respond to snmp or icmp. + - hostname: device hostname + - port: SNMP port (defaults to port defined in config). + - transport: SNMP protocol (defaults to transport defined in config). + - version: SNMP version to use, v1, v2c or v3. Defaults to v2c. + - poller_group: This is the poller_group id used for distributed poller setup. Defaults to 0. + - force_add: Force the device to be added regardless of it being able to respond to snmp or icmp. - For SNMP v1 or v2c +For SNMP v1 or v2c - - community: Required for SNMP v1 or v2c. + - community: Required for SNMP v1 or v2c. - For SNMP v3 +For SNMP v3 - - authlevel: SNMP authlevel (NoAuthNoPriv, AuthNoPriv, AuthPriv). - - authname: SNMP Auth username - - authpass: SNMP Auth password - - authalgo: SNMP Auth algorithm (MD5, SHA) - - cryptopass: SNMP Crypto Password - - cryptoalgo: SNMP Crypto algorithm (AES, DES) + - authlevel: SNMP authlevel (NoAuthNoPriv, AuthNoPriv, AuthPriv). + - authname: SNMP Auth username + - authpass: SNMP Auth password + - authalgo: SNMP Auth algorithm (MD5, SHA) + - cryptopass: SNMP Crypto Password + - cryptoalgo: SNMP Crypto algorithm (AES, DES) Example: ```curl @@ -646,7 +646,7 @@ Route: /api/v0/oxidized Input (JSON): - - + - Examples: ```curl @@ -674,7 +674,7 @@ Update devices field in the database. Route: /api/v0/devices/:hostname -- hostname can be either the device hostname or id + - hostname can be either the device hostname or id Input (JSON): @@ -703,7 +703,7 @@ List the device groups that a device is matched on. Route: /api/v0/devices/:hostname/groups -- hostname can be either the device hostname or id + - hostname can be either the device hostname or id Input (JSON): @@ -775,7 +775,7 @@ List all devices matching the group provided. Route: /api/v0/devicegroups/:name -- name Is the name of the device group which can be obtained using [`get_devicegroups`](#api-route-get_devicegroups). Please ensure that the name is urlencoded if it needs to be (i.e Linux Servers would need to be urlencoded. + - name Is the name of the device group which can be obtained using [`get_devicegroups`](#api-route-get_devicegroups). Please ensure that the name is urlencoded if it needs to be (i.e Linux Servers would need to be urlencoded. Input (JSON): @@ -818,7 +818,7 @@ Route: /api/v0/bgp Input: - - hostname = either the devices hostname or id. + - hostname = either the devices hostname or id. Example: ```curl @@ -843,11 +843,11 @@ List the current IPSec tunnels which are active. Route: /api/v0/routing/ipsec/data/:hostname -- hostname can be either the device hostname or id + - hostname can be either the device hostname or id Input: - - + - Example: ```curl @@ -882,11 +882,11 @@ Get a list of all VLANs for a given device. Route: /api/v0/devices/:hostname/vlans -- hostname can be either the device hostname or id + - hostname can be either the device hostname or id Input: - - + - Example: ```curl @@ -918,11 +918,11 @@ Get details of an alert Route: /api/v0/alerts/:id -- id is the alert id, you can obtain a list of alert ids from [`list_alerts`](#api-route-14). + - id is the alert id, you can obtain a list of alert ids from [`list_alerts`](#api-route-14). Input: - - + - Example: ```curl @@ -955,11 +955,11 @@ Acknowledge an alert Route: /api/v0/alerts/:id -- id is the alert id, you can obtain a list of alert ids from [`list_alerts`](#api-route-14). + - id is the alert id, you can obtain a list of alert ids from [`list_alerts`](#api-route-14). Input: - - + - Example: ```curl @@ -981,11 +981,11 @@ Unmute an alert Route: /api/v0/alerts/unmute/:id -- id is the alert id, you can obtain a list of alert ids from [`list_alerts`](#api-route-14). + - id is the alert id, you can obtain a list of alert ids from [`list_alerts`](#api-route-14). Input: - - + - Example: ```curl @@ -1010,7 +1010,7 @@ Route: /api/v0/alerts Input: - - state: Filter the alerts by state, 0 = ok, 1 = alert, 2 = ack + - state: Filter the alerts by state, 0 = ok, 1 = alert, 2 = ack Example: ```curl @@ -1044,11 +1044,11 @@ Get the alert rule details. Route: /api/v0/rules/:id - - id is the rule id. + - id is the rule id. Input: - - + - Example: ```curl @@ -1081,11 +1081,11 @@ Delete an alert rule by id Route: /api/v0/rules/:id - - id is the rule id. + - id is the rule id. Input: - - + - Example: ```curl @@ -1107,11 +1107,11 @@ List the alert rules. Route: /api/v0/rules - - + - Input: - - + - Example: ```curl @@ -1143,20 +1143,19 @@ Add a new alert rule. Route: /api/v0/rules - - + - Input (JSON): - - device_id: This is either the device id or -1 for a global rule - - rule: The rule which should be in the format %entity $condition $value (i.e %devices.status != 0 for devices marked as down). - - severity: The severity level the alert will be raised against, Ok, Warning, Critical. - - disabled: Whether the rule will be disabled or not, 0 = enabled, 1 = disabled - - count: This is how many polling runs before an alert will trigger and the frequency. - - delay: Delay is when to start alerting and how frequently. The value is stored in seconds but you can specify minutes, hours or days by doing 5 m, 5 h, 5 d for each one. - - mute: If mute is enabled then an alert will never be sent but will show up in the Web UI (true or false). - - invert: This would invert the rules check. - - name: This is the name of the rule and is mandatory. - + - device_id: This is either the device id or -1 for a global rule + - rule: The rule which should be in the format %entity $condition $value (i.e %devices.status != 0 for devices marked as down). + - severity: The severity level the alert will be raised against, Ok, Warning, Critical. + - disabled: Whether the rule will be disabled or not, 0 = enabled, 1 = disabled + - count: This is how many polling runs before an alert will trigger and the frequency. + - delay: Delay is when to start alerting and how frequently. The value is stored in seconds but you can specify minutes, hours or days by doing 5 m, 5 h, 5 d for each one. + - mute: If mute is enabled then an alert will never be sent but will show up in the Web UI (true or false). + - invert: This would invert the rules check. + - name: This is the name of the rule and is mandatory. Example: ```curl @@ -1178,20 +1177,20 @@ Edit an existing alert rule Route: /api/v0/rules - - + - Input (JSON): - - rule_id: You must specify the rule_id to edit an existing rule, if this is absent then a new rule will be created. - - device_id: This is either the device id or -1 for a global rule - - rule: The rule which should be in the format %entity $condition $value (i.e %devices.status != 0 for devices marked as down). - - severity: The severity level the alert will be raised against, Ok, Warning, Critical. - - disabled: Whether the rule will be disabled or not, 0 = enabled, 1 = disabled - - count: This is how many polling runs before an alert will trigger and the frequency. - - delay: Delay is when to start alerting and how frequently. The value is stored in seconds but you can specify minutes, hours or days by doing 5 m, 5 h, 5 d for each one. - - mute: If mute is enabled then an alert will never be sent but will show up in the Web UI (true or false). - - invert: This would invert the rules check. - - name: This is the name of the rule and is mandatory. + - rule_id: You must specify the rule_id to edit an existing rule, if this is absent then a new rule will be created. + - device_id: This is either the device id or -1 for a global rule + - rule: The rule which should be in the format %entity $condition $value (i.e %devices.status != 0 for devices marked as down). + - severity: The severity level the alert will be raised against, Ok, Warning, Critical. + - disabled: Whether the rule will be disabled or not, 0 = enabled, 1 = disabled + - count: This is how many polling runs before an alert will trigger and the frequency. + - delay: Delay is when to start alerting and how frequently. The value is stored in seconds but you can specify minutes, hours or days by doing 5 m, 5 h, 5 d for each one. + - mute: If mute is enabled then an alert will never be sent but will show up in the Web UI (true or false). + - invert: This would invert the rules check. + - name: This is the name of the rule and is mandatory. Example: ```curl @@ -1215,12 +1214,12 @@ Retrieve the inventory for a device. If you call this without any parameters the Route: /api/v0/inventory/:hostname - - hostname can be either the device hostname or the device id + - hostname can be either the device hostname or the device id Input: - - entPhysicalClass: This is used to restrict the class of the inventory, for example you can specify chassis to only return items in the inventory that are labelled as chassis. - - entPhysicalContainedIn: This is used to retrieve items within the inventory assigned to a previous component, for example specifying the chassis (entPhysicalIndex) will retrieve all items where the chassis is the parent. + - entPhysicalClass: This is used to restrict the class of the inventory, for example you can specify chassis to only return items in the inventory that are labelled as chassis. + - entPhysicalContainedIn: This is used to retrieve items within the inventory assigned to a previous component, for example specifying the chassis (entPhysicalIndex) will retrieve all items where the chassis is the parent. Example: ```curl @@ -1321,9 +1320,9 @@ Route: /api/v0/bills/:id /api/v0/bills?ref=:ref /api/v0/bills?custid=:custid - - id is the specific bill id - - ref is the billing reference - - custid is the customer reference + - id is the specific bill id + - ref is the billing reference + - custid is the customer reference Input: @@ -1379,11 +1378,11 @@ Retrieve a specific ARP entry or all ARP enties for a device Route: /api/v0/resources/ip/arp/:ip - - ip is the specific IP you would like to query, if this is all then you need to pass ?device=_hostname_ (or device id) + - ip is the specific IP you would like to query, if this is all then you need to pass ?device=_hostname_ (or device id) Input: - - device if you specify all for the IP then you need to populate this with the hostname or id of the device. + - device if you specify all for the IP then you need to populate this with the hostname or id of the device. Example: ```curl @@ -1416,8 +1415,8 @@ Route: /api/v0/services Input: - - state: only which have a certain state (valid options are 0=Ok, 1=Warning, 2=Critical). - - type: service type, used sql LIKE to find services, so for tcp, use type=tcp for http use type=http + - state: only which have a certain state (valid options are 0=Ok, 1=Warning, 2=Critical). + - type: service type, used sql LIKE to find services, so for tcp, use type=tcp for http use type=http Example: ```curl @@ -1474,12 +1473,12 @@ Retrieve services for device Route: /api/v0/services/:hostname - - id or hostname is the specific device + - id or hostname is the specific device Input: - - state: only which have a certain state (valid options are 0=Ok, 1=Warning, 2=Critical). - - type: service type, used sql LIKE to find services, so for tcp, use type=tcp for http use type=http + - state: only which have a certain state (valid options are 0=Ok, 1=Warning, 2=Critical). + - type: service type, used sql LIKE to find services, so for tcp, use type=tcp for http use type=http Example: ```curl diff --git a/doc/Developing/Support-New-OS.md b/doc/Developing/Support-New-OS.md new file mode 100644 index 0000000000..efd04ea4d2 --- /dev/null +++ b/doc/Developing/Support-New-OS.md @@ -0,0 +1,476 @@ +source: Developing/Support-New-OS.md +This document will explain how to add basic and full support for a new OS. **Some knowledge in PHP is needed for the full support.** + + +#### BASIC SUPPORT FOR A NEW OS + +### MIB + +If we have the MIB, we can copy the file into the default directory: + +```bash +/opt/librenms/mibs +``` + +#### New OS definition +Let's begin to declare the new OS in LibreNMS. At first we modify the definition file located here: + +```bash +includes/definitions.inc.php +``` + +```php +// Pulse Secure OS definition +$os = 'pulse'; +$config['os'][$os]['text'] = 'Pulse Secure'; +$config['os'][$os]['type'] = 'firewall'; +$config['os'][$os]['icon'] = 'junos'; +$config['os'][$os]['over'][0]['graph'] = 'device_bits'; +$config['os'][$os]['over'][0]['text'] = 'Device Traffic'; +$config['os'][$os]['over'][1]['graph'] = 'device_processor'; +$config['os'][$os]['over'][1]['text'] = 'CPU Usage'; +$config['os'][$os]['over'][2]['graph'] = 'device_mempool'; +$config['os'][$os]['over'][2]['text'] = 'Memory Usage'; + +//The icon described before is the image we have to create and put in the directory html/images/os +``` + +#### Discovery OS + +We create a new file named as our OS definition and in this directory: + +```bash +includes/discovery/os/pulse.inc.php +``` +This file just sets the $os variable, done by checking the SNMP tree for a particular value that matches the OS you are adding. Typically, this will come from the presence of specific values in sysObjectID or sysDescr, or the existence of a particular enterprise tree. +Look at other files to get help in the code structure. + +```php + $users + ) + $tags = compact('rrd_def'); + data_update($device, 'pulse_users', $tags, $fields); + $graphs['pulse_users'] = true; +} + +$sessions = snmp_get($device, 'PULSESECURE-PSG-MIB::iveConcurrentUsers.0', '-OQv'); + +if (is_numeric($sessions)) { + $rrd_def = array( + 'DS:sessions:GAUGE:600:0:U', + } + $fields = array( + 'sessions' => $sessions + ); + $tags = compact('rrd_def'); + data_update($device, 'pulse_sessions', $tags, $fields); + $graphs['pulse_sessions'] = true; +} +``` +We finish in the declaration of the two graph types in the database: + +We can do that within a file to share our work and contribute in the development of LibreNMS. :-) + +```bash +sql-schema/xxx.sql +//check the file number in GitHub + +php includes/sql-schema/update.php +``` + +Or put the SQL commands directly in Mysql or PhpMyadmin for our tests: + +```php +INSERT INTO `graph_types`(`graph_type`, `graph_subtype`, `graph_section`, `graph_descr`, `graph_order`) VALUES ('device', 'pulse_users', 'firewall', 'Active Users', ''); +INSERT INTO `graph_types`(`graph_type`, `graph_subtype`, `graph_section`, `graph_descr`, `graph_order`) VALUES ('device', 'pulse_sessions', 'firewall', 'Active Sessions', ''); +``` + +#### Displaying + +The specific graphs are not displayed automatically so we need to write the following PHP code: + +**Pulse Sessions** + +```bash +html/includes/graphs/device/pulse_sessions.inc.php +``` + +```php +checkOS('nios'); + $this->checkOS('nios', 'nios-ipam'); + } +``` + + +We utilise [snmpsim](http://snmpsim.sourceforge.net/) to do unit testing for OS discovery. For this to work you need +to supply an snmprec file. This is pretty simple and using nios as the example again this would look like: +``` +1.3.6.1.2.1.1.1.0|4|Linux 3.14.25 #1 SMP Thu Jun 16 18:19:37 EDT 2016 x86_64 +1.3.6.1.2.1.1.2.0|6|1.3.6.1.4.1.7779.1.1402 +``` + +During testing LibreNMS will use any info in the snmprec file for snmp calls. This one provides +sysDescr (`.1.3.6.1.2.1.1.1.0`, 4 = Octet String) and sysObjectID (`.1.3.6.1.2.1.1.2.0`, 6 = Object Identifier), + which is the minimum that should be provided for new snmprec files. + +To look up the numeric OID and type of an string OID with snmptranslate: +```bash +snmptranslate -On -Td SNMPv2-MIB::sysDescr.0 +``` + +Common OIDs used in discovery: + +| String OID | Numeric OID | +| ----------------------------------- | --------------------------- | +| SNMPv2-MIB::sysDescr.0 | 1.3.6.1.2.1.1.1.0 | +| SNMPv2-MIB::sysObjectID.0 | 1.3.6.1.2.1.1.2.0 | +| ENTITY-MIB::entPhysicalDescr.1 | 1.3.6.1.2.1.47.1.1.1.1.2.1 | +| ENTITY-MIB::entPhysicalMfgName.1 | 1.3.6.1.2.1.47.1.1.1.1.12.1 | +| SML-MIB::product-Name.0 | 1.3.6.1.4.1.2.6.182.3.3.1.0 | + +List of SNMP data types: + +| Type | Value | +| ----------------- | ------------- | +| OCTET STRING | 4 | +| Integer32 | 2 | +| NULL | 5 | +| OBJECT IDENTIFIER | 6 | +| IpAddress | 64 | +| Counter32 | 65 | +| Gauge32 | 66 | +| TimeTicks | 67 | +| Opaque | 68 | +| Counter64 | 70 | + +You can run `./scripts/pre-commit.php -u` to run the unit tests to check your code. +If you would like to run tests locally against a full snmpsim instance, run `./scripts/pre-commit.php -u --snmpsim`. diff --git a/doc/Extensions/Applications.md b/doc/Extensions/Applications.md index 94661bc2d4..475bdc4094 100644 --- a/doc/Extensions/Applications.md +++ b/doc/Extensions/Applications.md @@ -22,6 +22,7 @@ Different applications support a variety of ways collect data: by direct connect 1. [TinyDNS/djbdns](#tinydns-aka-djbdns) - Agent 1. [Unbound](#unbound) - Agent 1. [UPS-nut](#ups-nut) - SNMP extend +1. [UPS-apcups](#ups-apcups) - SNMP extend 1. [Agent Setup](#agent-setup) @@ -38,8 +39,11 @@ wget https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/apach extend apache /etc/snmp/apache-stats.py ``` 4. Restart snmpd on your host -5. On the device page in Librenms, edit your host and check the `Apache` under the Applications tab. -(In some cases urlgrabber needs to be installed, in Debian it can be achieved by: apt-get install python-urlgrabber) +5. Verify it is working by running /usr/lib/check_mk_agent/local/apache +6. (In some cases urlgrabber needs to be installed, in Debian it can be achieved by: apt-get install python-urlgrabber) +7. (If you get error like "Can't locate LWP/Simple.pm". libwww-perl needs to be installed, apt-get install libwww-perl) +8. On the device page in Librenms, edit your host and check the `Apache` under the Applications tab. + ### BIND9 aka named @@ -323,6 +327,21 @@ extend ups-nut /etc/snmp/ups-nut.sh +### UPS-apcups +A small shell script that exports apcacess ups status. + +##### SNMP Extend +1. Copy the [ups apcups](https://github.com/librenms/librenms-agent/blob/master/snmp/ups-apcups.sh) to `/etc/snmp/` on your host. +2. Make the script executable (chmod +x /etc/snmp/ups-apcups.sh) +3. Edit your snmpd.conf file (usually /etc/snmp/snmpd.conf) and add: +``` +extend ups-apcups /etc/snmp/ups-apcups.sh +``` +4. Restart snmpd on your host +5. On the device page in Librenms, edit your host and check the `UPS apcups` under the Applications tab. + + + Agent Setup ----------- diff --git a/doc/Extensions/RRDCached.md b/doc/Extensions/RRDCached.md index f881e9c683..824713e994 100644 --- a/doc/Extensions/RRDCached.md +++ b/doc/Extensions/RRDCached.md @@ -8,7 +8,7 @@ If you have rrdcached 1.5.5 or above, we can also tune over rrdcached. To enable this set the following config: ```php -$config['rrdtool_version'] = 1.5.5; +$config['rrdtool_version'] = '1.5.5'; ``` ### Support matrix diff --git a/doc/General/Releases.md b/doc/General/Releases.md index 2e3636c4a4..1726522063 100644 --- a/doc/General/Releases.md +++ b/doc/General/Releases.md @@ -1,11 +1,25 @@ source: General/Releases.md # LibreNMS Releases +#### Introduction We try to ensure that breaking changes aren't introduced by utilising various automated code testing, syntax testing and unit testing along with manual code review. However bugs can and do get introduced as well as major refactoring to improve the quality of the code base. +#### Development branch +Our `master` branch is our dev branch, this is actively commited to and it's not uncommon +for multiple commits to be merged in daily. As such sometimes changes will be introduced +which will cause unintended issues. If this happens we are usually quick to fix or +revert those changes. + +We appreciate everyone that runs this branch as you are in essence secondary testers to +the automation and manually testing that is done during the merge stages. + +You can configure your install (this is the default) to use this branch by setting `$config['update_channel'] = 'master';` +in `config.php` and ensuring you switch to the master branch with `git checkout master`. + +#### Stable branch With this in mind, we provide a monthly stable release which is released on or around the last Sunday of the month. Code pull requests (aside from Bug fixes) are stopped days leading up to the release to ensure that we have a clean working branch at that point. @@ -14,3 +28,6 @@ The releases are titled after that month in the format `YYYYMM`, i.e `201608`. T Changelog is also updated and will reference the release number and date so you can see what changes have been made since the last release. +To switch to using stable branches you can set `$config['update_channel'] = 'release';` +in config.php and then switch to the latest release branch with `git fetch --tags && git checkout $(git describe --tags $(git rev-list --tags --max-count=1))`. + diff --git a/doc/Support/Configuration.md b/doc/Support/Configuration.md index a949d4d84c..322a18a4a2 100644 --- a/doc/Support/Configuration.md +++ b/doc/Support/Configuration.md @@ -95,11 +95,11 @@ $config['sfdp'] = "/usr/bin/sfdp"; #### Memcached -[Memcached](Extensions/Memcached.md] +[Memcached](../Extensions/Memcached.md] #### RRDCached -[RRDCached](Extensions/RRDCached.md] +[RRDCached](../Extensions/RRDCached.md] #### WebUI Settings @@ -260,7 +260,7 @@ The default v3 snmp details to use, you can expand this array with `[1]`, `[2]`, #### Auto discovery settings -[Auto-Discovery](Extensions/Auto-Discovery.md) +[Auto-Discovery](../Extensions/Auto-Discovery.md) #### Email configuration @@ -284,11 +284,11 @@ The varying options after that are to support the different transports. #### Alerting -[Alerting](Extensions/Alerting.md) +[Alerting](../Extensions/Alerting.md) #### Billing -[Billing](Extensions/Billing-Module.md) +[Billing](../Extensions/Billing-Module.md) #### Global module support @@ -303,7 +303,7 @@ $config['enable_sla'] = 0; # Enable Cisco SLA collection and d #### Port extensions -[Port-Description-Parser](Extensions/Port-Description-Parser.md) +[Port-Description-Parser](../Extensions/Port-Description-Parser.md) ```php $config['enable_ports_etherlike'] = 0; @@ -324,7 +324,7 @@ Setting `rancid_ignorecomments` will disable showing lines that start with # #### Oxidized -[Oxidized](Extensions/Oxidized.md) +[Oxidized](../Extensions/Oxidized.md) #### CollectD ```php @@ -339,11 +339,11 @@ Specify the location of the collectd unix socket. Using a socket allows the coll #### Smokeping -[Smokeping](Extensions/Smokeping.md) +[Smokeping](../Extensions/Smokeping.md) #### NFSen -[NFSen](Extensions/NFSen.md) +[NFSen](../Extensions/NFSen.md) #### Location mapping @@ -425,11 +425,11 @@ Mounted storage / mount points to ignore in discovery and polling. #### IRC Bot -[IRC Bot](Extensions/IRC-Bot.md) +[IRC Bot](../Extensions/IRC-Bot.md) #### Authentication -[Authentication](Extensions/Authentication.md) +[Authentication](../Extensions/Authentication.md) #### Cleanup options @@ -451,7 +451,7 @@ the rrd directory automatically - only enable this if you are comfortable with t #### Syslog options -[Syslog](Extensions/Syslog.md) +[Syslog](../Extensions/Syslog.md) #### Virtualization @@ -484,7 +484,7 @@ You can use this array to rewrite the description of ASes that you have discover #### Auto updates -[Updating](General/Updating.md) +[Updating](../General/Updating.md) #### IPMI Setup the types of IPMI protocols to test a host for and it what order. @@ -499,4 +499,4 @@ $config['ipmi']['type'][] = "open"; #### Distributed poller settings -[Distributed Poller](Extensions/Distributed-Poller.md) +[Distributed Poller](../Extensions/Distributed-Poller.md) diff --git a/doc/Support/Performance.md b/doc/Support/Performance.md index ef8e0382f1..66af33d48b 100644 --- a/doc/Support/Performance.md +++ b/doc/Support/Performance.md @@ -15,7 +15,7 @@ We absolutely recommend running this, it will save on IO load. [RRDCached](http: It's advisable after 24 hours of running MySQL that you run (MySQL Tuner)[https://raw.githubusercontent.com/major/MySQLTuner-perl/master/mysqltuner.pl] which will make suggestions on things you can change specific to your setup. -One recommendation we can make is that you set the following in my.cnf: +One recommendation we can make is that you set the following in my.cnf under a [mysqld] group: ```bash innodb_flush_log_at_trx_commit = 0 diff --git a/doc/Support/SNMP-Configuration-Examples.md b/doc/Support/SNMP-Configuration-Examples.md new file mode 100644 index 0000000000..351116d840 --- /dev/null +++ b/doc/Support/SNMP-Configuration-Examples.md @@ -0,0 +1,147 @@ +source: Support/SNMP-Configuration-Examples.md + +# SNMP configuration examples + +Table of Content: +- [Devices](#devices) + - [Cisco](#cisco) + - [Adaptive Security Appliance (ASA)](#adaptive-security-appliance-asa) + - [IOS / IOS XE / NX-OS](#ios--ios-xe--nx-os) + - [Wireless LAN Controller (WLC)](#wireless-lan-controller-wlc) + - [Infoblox](#infoblox) + - [NIOS 7.x](#nios-7x) + - [Juniper](#juniper) + - [Junos OS](#junos-os) + - [Palo Alto](#palo-alto) + - [PANOS 6.x/7.x](#panos-6x7x) +- [Operating systems](#operating-systems) + - [Linux (snmpd)](#linux-snmpd) + - [Windows Server 2008 R2](#windows-server-2008-r2) + - [Windows Server 2012 R2](#windows-server-2012-r2) + +## Devices + +### Cisco +#### Adaptive Security Appliance (ASA) +1. Launch ASDM and connect to your device +2. Go to Configuration > Management Access > SNMP +3. Add your community string +4. Add in the "SNMP Host Access List" section your LibreNMS server IP address +5. Click Apply and Save + +#### IOS / IOS XE / NX-OS + +``` +snmp-server community YOUR-COMMUNITY RO +snmp-server contact YOUR-CONTACT +snmp-server location YOUR-LOCATION +``` + +#### Wireless LAN Controller (WLC) +1. Access the web admin page and log in +2. If you are running version 8.1 and later, on the new dashboard click "Advanced" +3. Go to management Tab +4. On SNMP sub-menu, select "Communities" +5. Click "New..." +6. Add your community name and leave IP addresses empty +7. Click Apply and Save + +### Infoblox +#### NIOS 7.x +1. Access the web admin page and log in +2. Go to Grid tab > Grid Manager +3. In the right menu select "Grid properties" +4. Select "SNMP" menu +5. Click "Enable SNMPv1/SNMPv2 Queries" +6. Add your community +7. Click Save & Close + +### Juniper +#### Junos OS +``` +set snmp description description +set snmp location location +set snmp contact contact +set snmp community YOUR-COMMUNITY authorization read-only +``` + +### Palo Alto +#### PANOS 6.x/7.x +1. Access the web admin page and log in +2. Go to Device tab > Setup +3. Go to the sub-tab "Operations" +4. Click "SNMP Setup" +5. Enter your SNMP community and then click "OK" +6. Click Apply + +Note that you need to allow SNMP on the needed interfaces. To do that you need to create a network "Interface Mgmt" profile for standard interface and allow SNMP under "Device > Management > Management Interface Settings" for out of band management interface. + + +## Operating systems +### Linux (snmpd) + +Replace your snmpd.conf file by the example below and edit it with appropriate community in "RANDOMSTRINGGOESHERE". + +``` +vi /etc/snmp/snmpd.conf +``` + +``` +# Change RANDOMSTRINGGOESHERE to your preferred SNMP community string +com2sec readonly default RANDOMSTRINGGOESHERE + +group MyROGroup v2c readonly +view all included .1 80 +access MyROGroup "" any noauth exact all none none + +syslocation Rack, Room, Building, City, Country [GPSX,Y] +syscontact Your Name + +#Distro Detection +extend .1.3.6.1.4.1.2021.7890.1 distro /usr/bin/distro +``` +The LibreNMS server include a copy of this example here: + +``` +/opt/librenms/snmpd.conf.example +``` + +#### Restart the snmpd service: + +##### CentOS 6 / Red hat 6 +``` +service snmpd restart +``` +##### CentOS 7 / Red hat 7 +``` +systemctl restart snmpd +``` +##### Ubuntu +``` +service snmpd restart +``` + +### Windows Server 2008 R2 +1. Log in to your Windows Server 2008 R2 +2. Start "Server Manager" under "Administrative Tools" +3. Click "Features" and then click "Add Feature" +5. Check (if not checked) "SNMP Service", click "Next" until "Install" +6. Start "Services" under "Administrative Tools" +7. Edit "SNMP Service" properties +8. Go to the security tab +9. In "Accepted community name" click "Add" to add your community string and permission +10. In "Accept SNMP packets from these hosts" click "Add" and add your LibreNMS server IP address +11. Validate change by clicking "Apply" + +### Windows Server 2012 R2 +1. Log in to your Windows Server 2012 R2 +2. Start "Server Manager" under "Administrative Tools" +3. Click "Manage" and then "Add Roles and Features" +4. Continue by pressing "Next" to the "Features" menu +5. Install (if not installed) "SNMP Service" +6. Start "Services" under "Administrative Tools" +7. Edit "SNMP Service" properties +8. Go to the security tab +9. In "Accepted community name" click "Add" to add your community string and permission +10. In "Accept SNMP packets from these hosts" click "Add" and add your LibreNMS server IP address +11. Validate change by clicking "Apply" diff --git a/doc/Support/Support-New-OS.md b/doc/Support/Support-New-OS.md index 8cca183dfd..0ed013d0a2 100644 --- a/doc/Support/Support-New-OS.md +++ b/doc/Support/Support-New-OS.md @@ -1,454 +1,2 @@ source: Support/Support-New-OS.md -This document will explain how to add basic and full support for a new OS. **Some knowledge in PHP is needed for the full support.** - - -#### BASIC SUPPORT FOR A NEW OS - -### MIB - -If we have the MIB, we can copy the file into the default directory: - -```bash -/opt/librenms/mibs -``` - -#### New OS definition -Let's begin to declare the new OS in LibreNMS. At first we modify the definition file located here: - -```bash -includes/definitions.inc.php -``` - -```php -// Pulse Secure OS definition -$os = 'pulse'; -$config['os'][$os]['text'] = 'Pulse Secure'; -$config['os'][$os]['type'] = 'firewall'; -$config['os'][$os]['icon'] = 'junos'; -$config['os'][$os]['over'][0]['graph'] = 'device_bits'; -$config['os'][$os]['over'][0]['text'] = 'Device Traffic'; -$config['os'][$os]['over'][1]['graph'] = 'device_processor'; -$config['os'][$os]['over'][1]['text'] = 'CPU Usage'; -$config['os'][$os]['over'][2]['graph'] = 'device_mempool'; -$config['os'][$os]['over'][2]['text'] = 'Memory Usage'; - -//The icon described before is the image we have to create and put in the directory html/images/os -``` - -#### Discovery OS - -We create a new file named as our OS definition and in this directory: - -```bash -includes/discovery/os/pulse.inc.php -``` -This file just sets the $os variable, done by checking the SNMP tree for a particular value that matches the OS you are adding. Typically, this will come from the presence of specific values in sysObjectID or sysDescr, or the existence of a particular enterprise tree. -Look at other files to get help in the code structure. - -```php - $users - ) - $tags = compact('rrd_def'); - data_update($device, 'pulse_users', $tags, $fields); - $graphs['pulse_users'] = true; -} - -$sessions = snmp_get($device, 'PULSESECURE-PSG-MIB::iveConcurrentUsers.0', '-OQv'); - -if (is_numeric($sessions)) { - $rrd_def = array( - 'DS:sessions:GAUGE:600:0:U', - } - $fields = array( - 'sessions' => $sessions - ); - $tags = compact('rrd_def'); - data_update($device, 'pulse_sessions', $tags, $fields); - $graphs['pulse_sessions'] = true; -} -``` -We finish in the declaration of the two graph types in the database: - -We can do that within a file to share our work and contribute in the development of LibreNMS. :-) - -```bash -sql-schema/xxx.sql -//check the file number in GitHub - -php includes/sql-schema/update.php -``` - -Or put the SQL commands directly in Mysql or PhpMyadmin for our tests: - -```php -INSERT INTO `graph_types`(`graph_type`, `graph_subtype`, `graph_section`, `graph_descr`, `graph_order`) VALUES ('device', 'pulse_users', 'firewall', 'Active Users', ''); -INSERT INTO `graph_types`(`graph_type`, `graph_subtype`, `graph_section`, `graph_descr`, `graph_order`) VALUES ('device', 'pulse_sessions', 'firewall', 'Active Sessions', ''); -``` - -#### Displaying - -The specific graphs are not displayed automatically so we need to write the following PHP code: - -**Pulse Sessions** - -```bash -html/includes/graphs/device/pulse_sessions.inc.php -``` - -```php -checkOS('zxr10', 'ZTE Ethernet Switch ZXR10 5250-52TM-H, Version: V2.05.11B23'); - } -``` - -This test looks for the sysDescr of `ZTE Ethernet Switch ZXR10 5250-52TM-H, Version: V2.05.11B23` and if it matches -the `zxr10` OS discovery file then the check will pass. - -A slightly more complicated test would be: - -```php - public function testAiros() - { - $this->checkOS('airos', 'Linux', '.1.3.6.1.4.1.10002.1'); - $this->checkOS('airos', 'Linux', '.1.3.6.1.4.1.41112.1.4'); - - $mockSnmp = array( - 'dot11manufacturerName.5' => 'Ubiquiti', - ); - $this->checkOS('airos', 'Linux', '', $mockSnmp); - } -``` - -The first two `$this->checkOS` calls pass on both a `sysDescr` value (`Linux`) and a `sysObjectID`. - -The third call uses another snmp response (although fake) which the specific OS discovery for `airos` relies on. - -You can run `scripts/pre-commit.php -u` to run the unit tests to check your code. + diff --git a/html/ajax_output.php b/html/ajax_output.php index 0f518cc00f..00430b9b38 100644 --- a/html/ajax_output.php +++ b/html/ajax_output.php @@ -18,6 +18,7 @@ require_once '../includes/definitions.inc.php'; require_once 'includes/functions.inc.php'; require_once '../includes/functions.php'; require_once 'includes/authenticate.inc.php'; +require_once '../includes/alerts.inc.php'; set_debug($_REQUEST['debug']); $id = mres($_REQUEST['id']); diff --git a/html/css/styles.css b/html/css/styles.css index e7a5736cdd..fb0b49f5cf 100644 --- a/html/css/styles.css +++ b/html/css/styles.css @@ -315,6 +315,7 @@ A.purple:visited, a.purple, .purple { color: #740074; } .bluebg { background-color: #aaaaff; } .greenbg { background-color: #aaffaa; } .greybg { background-color: #DEEFEF; } +.blackbg { background-color: #000000; } .selector { width:275px; @@ -1763,22 +1764,56 @@ label { font-weight: normal; } -.nav>li>a.dropdown-toggle { - padding: 15px 6px; -} - -.badge-navbar-user{ - background:red; +.badge-navbar-user { border-radius: 40%; font-size: 65%; - height: auto; - margin: 0; - padding:5px; - position:absolute; - right:-3px; - top:5px; - width: auto; - } + padding: 5px; + position: relative; + top: -10px; + left: -5px; +} +.badge-default { + background-color: #777; +} +.badge-default[href]:hover, +.badge-default[href]:focus { + background-color: #5e5e5e; +} +.badge-primary { + background-color: #337ab7; +} +.badge-primary[href]:hover, +.badge-primary[href]:focus { + background-color: #286090; +} +.badge-success { + background-color: #5cb85c; +} +.badge-success[href]:hover, +.badge-success[href]:focus { + background-color: #449d44; +} +.badge-info { + background-color: #5bc0de; +} +.badge-info[href]:hover, +.badge-info[href]:focus { + background-color: #31b0d5; +} +.badge-warning { + background-color: #f0ad4e; +} +.badge-warning[href]:hover, +.badge-warning[href]:focus { + background-color: #ec971f; +} +.badge-danger { + background-color: #d9534f; +} +.badge-danger[href]:hover, +.badge-danger[href]:focus { + background-color: #c9302c; +} @media only screen and (max-width: 480px) { .thumbnail_graph_table b { font-size : 6px;} @@ -1872,7 +1907,6 @@ label { .device-availability, .service-availability { color:#000000; float:left; - width:163px; height:64px; margin:10px; padding:8px; @@ -1893,6 +1927,14 @@ label { border:1px solid #FFB733; } +.device-availability.ignored, .service-availability.ignored { + border:1px solid #36393D; +} + +.device-availability.disabled, .service-availability.disabled { + border:1px solid #000000; +} + .availability-label { float:right; margin:-8px; @@ -1916,13 +1958,13 @@ label { } .page-availability-title-left { - width:50%; + width:40%; float:left; height:40px; } .page-availability-title-right { - width:50%; + width:60%; float:left; text-align:right; } @@ -1991,3 +2033,7 @@ label { float:left; background-color: #D9534F; } + +.availability-map-widget-header { + line-height:30px; +} diff --git a/html/images/os/amazon.png b/html/images/os/amazon.png new file mode 100644 index 0000000000..e4deb8ef61 Binary files /dev/null and b/html/images/os/amazon.png differ diff --git a/html/includes/common/alerts.inc.php b/html/includes/common/alerts.inc.php index 5d0a84decf..23f9263100 100644 --- a/html/includes/common/alerts.inc.php +++ b/html/includes/common/alerts.inc.php @@ -227,7 +227,7 @@ var alerts_grid = $("#alerts_'.$unique_id.'").bootgrid({ return "

" + row.msg + "

"; }, "ack": function(column,row) { - return ""; + return ""; }, "proc": function(column,row) { return ""; @@ -248,7 +248,7 @@ var alerts_grid = $("#alerts_'.$unique_id.'").bootgrid({ }).on("click", function(e) { var target = $(this).data("target"); $(target).collapse(\'toggle\'); - $(this).toggleClass(\'glyphicon-plus glyphicon-minus\'); + $(this).toggleClass(\'fa-plus fa-minus\'); }); alerts_grid.find(".incident").each( function() { $(this).parent().addClass(\'col-lg-4 col-md-4 col-sm-4 col-xs-4\'); @@ -258,8 +258,8 @@ var alerts_grid = $("#alerts_'.$unique_id.'").bootgrid({ $(this).find(".incident-toggle").fadeOut(200); }).on("click", "td:not(.incident-toggle-td)", function() { var target = $(this).parent().find(".incident-toggle").data("target"); - if( $(this).parent().find(".incident-toggle").hasClass(\'glyphicon-plus\') ) { - $(this).parent().find(".incident-toggle").toggleClass(\'glyphicon-plus glyphicon-minus\'); + if( $(this).parent().find(".incident-toggle").hasClass(\'fa-plus\') ) { + $(this).parent().find(".incident-toggle").toggleClass(\'fa-plus fa-minus\'); $(target).collapse(\'toggle\'); } }); diff --git a/html/includes/common/availability-map.inc.php b/html/includes/common/availability-map.inc.php index 80cd4b38da..4df833aed5 100644 --- a/html/includes/common/availability-map.inc.php +++ b/html/includes/common/availability-map.inc.php @@ -12,76 +12,107 @@ * the source code distribution for details. */ +$sql = dbFetchRow('SELECT `settings` FROM `users_widgets` WHERE `user_id` = ? AND `widget_id` = ?', array($_SESSION["user_id"], '1')); +$widget_mode = json_decode($sql['settings'], true); + +if (isset($_SESSION["map_view"]) && is_numeric($_SESSION["map_view"])) { + $mode = $_SESSION["map_view"]; +} else { + $mode = $widget_mode['mode']; +} + $select_modes = array( '0' => 'only devices', '1' => 'only services', '2' => 'devices and services', ); +if ($config['webui']['availability_map_compact'] == 1) { + $compact_tile = $widget_mode['tile_width']; +} + +$show_disabled_ignored = $widget_mode['show_disabled_and_ignored']; + if (defined('SHOW_SETTINGS')) { - if (isset($widget_settings['mode'])) { - $mode = $widget_settings['mode']; - } else { - $mode = 0; + $common_output[] = ' +
+
+
+ +
+
+ +
+
'; + + if ($config['webui']['availability_map_compact'] == 1) { + $common_output[] = ' +
+
+ +
+
+ +
+
'; } - if (isset($widget_settings['tile_width'])) { - $current_width = $widget_settings['tile_width']; + if ($show_disabled_ignored == 1) { + $selected_yes = 'selected'; + $selected_no = ''; } else { - $current_width = 10; + $selected_yes = ''; + $selected_no = 'selected'; } $common_output[] = ' -
- -
- +
+
-
-
-
- + +
-
-
-
-
+
'; + + if ($config['webui']['availability_map_compact'] == 1) { + $common_outputp[] = ' +
+
+ +
+
+ +
+
+ '; + } + + + $common_output[] = ' +
+
+
+ +
+
'; } else { require_once 'includes/object-cache.inc.php'; - $sql = dbFetchRow('SELECT `settings` FROM `users_widgets` WHERE `user_id` = ? AND `widget_id` = ?', array($_SESSION["user_id"], '1')); - $widget_mode = json_decode($sql['settings']); - - if (isset($_SESSION["map_view"])) { - $mode = $_SESSION["map_view"]; - } else { - $mode = $widget_mode->{'mode'}; - } - $host_up_count = 0; $host_warn_count = 0; $host_down_count = 0; + $host_ignored_count = 0; + $host_disabled_count = 0; $service_up_count = 0; $service_warn_count = 0; $service_down_count = 0; + $service_ignored_count = 0; + $service_disabled_count = 0; if ($config['webui']['availability_map_sort_status'] == 1) { $deviceOrderBy = 'status'; @@ -103,7 +134,11 @@ if (defined('SHOW_SETTINGS')) { $in_devices = implode(',', $in_devices); } - $sql = 'SELECT `D`.`hostname`, `D`.`sysName`, `D`.`device_id`, `D`.`status`, `D`.`uptime`, `D`.`os`, `D`.`icon` FROM `devices` AS `D`'; + if ($show_disabled_ignored == 1) { + $disabled_ignored = ', `D`.`ignore`, `D`.`disabled`'; + } + + $sql = 'SELECT `D`.`hostname`, `D`.`sysName`, `D`.`device_id`, `D`.`status`, `D`.`uptime`, `D`.`os`, `D`.`icon` '.$disabled_ignored.' FROM `devices` AS `D`'; if (is_normal_user() === true) { $sql .= ' , `devices_perms` AS P WHERE D.`device_id` = P.`device_id` AND P.`user_id` = ? AND'; @@ -114,17 +149,26 @@ if (defined('SHOW_SETTINGS')) { $sql .= ' WHERE'; } - if ($config['webui']['availability_map_use_device_groups'] != 0 && isset($in_devices)) { - $sql .= " `D`.`ignore` = '0' AND `D`.`disabled` = '0' AND `D`.`device_id` IN (".$in_devices.") ORDER BY `".$deviceOrderBy."`"; + $sql .= " `D`.`device_id` IN (".$in_devices.")"; } else { - $sql .= " `D`.`ignore` = '0' AND `D`.`disabled` = '0' ORDER BY `".$deviceOrderBy."`"; + $sql .= " TRUE"; } + $sql .= " ORDER BY `".$deviceOrderBy."`"; + $temp_output = array(); foreach (dbFetchRows($sql, $param) as $device) { - if ($device['status'] == '1') { + if ($device['disabled'] == '1') { + $deviceState = "disabled"; + $deviceLabel = "blackbg"; + $host_disabled_count++; + } elseif ($device['ignore'] == '1') { + $deviceState = "ignored"; + $deviceLabel = "label-default"; + $host_ignored_count++; + } elseif ($device['status'] == '1') { if (($device['uptime'] < $config['uptime_warning']) && ($device['uptime'] != '0')) { $deviceState = 'warn'; $deviceLabel = 'label-warning'; @@ -143,25 +187,25 @@ if (defined('SHOW_SETTINGS')) { $host_down_count++; } - if ($config['webui']['old_availability_map'] == 0) { + if ($config['webui']['availability_map_compact'] == 0) { if ($directpage == "yes") { $deviceIcon = getImage($device); $temp_output[] = ' - -
- '.$deviceState.' - '.$deviceIcon.'
- '.shorthost(ip_to_sysname($device, $device['hostname'])).' +
+
+ ' . $deviceState . ' + ' . $deviceIcon . '
+ ' . shorthost(ip_to_sysname($device, $device['hostname'])) . '
'; } else { $temp_output[] = ' - - '.$deviceState.' + + ' . $deviceState . ' '; } } else { - $temp_output[] = '
'; + $temp_output[] = '
'; } } } @@ -188,26 +232,26 @@ if (defined('SHOW_SETTINGS')) { $service_down_count++; } - if ($config['webui']['old_availability_map'] == 0) { + if ($config['webui']['availability_map_compact'] == 0) { if ($directpage == "yes") { $deviceIcon = getImage($service); $temp_output[] = ' - -
- '.$service["service_type"].' - '.$serviceState.' - '.$deviceIcon.'
- '.shorthost(ip_to_sysname($service, $service['hostname'])).' +
+
+ ' . $service["service_type"] . ' + ' . $serviceState . ' + ' . $deviceIcon . '
+ ' . shorthost(ip_to_sysname($service, $service['hostname'])) . '
'; } else { $temp_output[] = ' - - '.$service['service_type'].' - '.$serviceState.' + + ' . $service['service_type'] . ' - ' . $serviceState . ' '; } } else { - $temp_output[] = '
'; + $temp_output[] = '
'; } } } else { @@ -230,7 +274,7 @@ if (defined('SHOW_SETTINGS')) { } else { $selected = ''; } - $temp_header[] = ''; + $temp_header[] = ''; } } @@ -252,7 +296,7 @@ if (defined('SHOW_SETTINGS')) { $temp_header[] = ' Device group '; } @@ -274,19 +318,26 @@ if (defined('SHOW_SETTINGS')) { $serviceClass = 'widget-availability-service'; } + if ($show_disabled_ignored == 1) { + $disabled_ignored_header = ' + ignored: '.$host_ignored_count.' + disabled: '.$host_disabled_count.''; + } + if ($mode == 0 || $mode == 2) { $temp_header[] = ' -
+
Total hosts up: '.$host_up_count.' warn: '.$host_warn_count.' down: '.$host_down_count.' + '.$disabled_ignored_header.'
'; } if (($mode == 1 || $mode == 2) && ($config['show_services'] != 0)) { $temp_header[] = ' -
+
Total services up: '.$service_up_count.' warn: '.$service_warn_count.' diff --git a/html/includes/forms/create-alert-item.inc.php b/html/includes/forms/create-alert-item.inc.php index 41c0a847fe..01ae19e728 100644 --- a/html/includes/forms/create-alert-item.inc.php +++ b/html/includes/forms/create-alert-item.inc.php @@ -17,8 +17,7 @@ if (is_admin() === false) { } $rule = implode(' ', $_POST['rules']); -$rule = rtrim($rule, '&&'); -$rule = rtrim($rule, '||'); +$rule = rtrim($rule, '&|'); $alert_id = $_POST['alert_id']; $count = mres($_POST['count']); $delay = mres($_POST['delay']); diff --git a/html/includes/functions.inc.php b/html/includes/functions.inc.php index 628e335b29..2594f55b12 100644 --- a/html/includes/functions.inc.php +++ b/html/includes/functions.inc.php @@ -91,6 +91,9 @@ function nicecase($item) case 'ups-nut': return 'UPS nut'; + case 'ups-apcups': + return 'UPS apcups'; + default: return ucfirst($item); } @@ -1209,7 +1212,7 @@ function generate_dynamic_config_panel($title, $config_groups, $items = array(), $output .= '
-
+
'; if ($item['type'] == 'checkbox') { @@ -1217,6 +1220,11 @@ function generate_dynamic_config_panel($title, $config_groups, $items = array(), } elseif ($item['type'] == 'text') { $output .= ' + + '; + } elseif ($item['type'] == 'numeric') { + $output .= ' + '; } elseif ($item['type'] == 'select') { @@ -1242,7 +1250,7 @@ function generate_dynamic_config_panel($title, $config_groups, $items = array(), } $output .=' - + '; } $output .= ' @@ -1336,22 +1344,20 @@ function ipmiSensorName($hardwareId, $sensorIpmi, $rewriteArray) } } -function get_auth_ad_user_filter($username) +/** + * @param $filename + * @param $content + */ +function file_download($filename, $content) { - global $config; - $user_filter = "(samaccountname=$username)"; - if ($config['auth_ad_user_filter']) { - $user_filter = "(&{$config['auth_ad_user_filter']}$user_filter)"; - } - return $user_filter; -} - -function get_auth_ad_group_filter($groupname) -{ - global $config; - $group_filter = "(samaccountname=$groupname)"; - if ($config['auth_ad_group_filter']) { - $group_filter = "(&{$config['auth_ad_group_filter']}$group_filter)"; - } - return $group_filter; + $length = strlen($content); + header('Content-Description: File Transfer'); + header('Content-Type: text/plain'); + header("Content-Disposition: attachment; filename=$filename"); + header('Content-Transfer-Encoding: binary'); + header('Content-Length: ' . $length); + header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); + header('Expires: 0'); + header('Pragma: public'); + echo $content; } diff --git a/html/includes/graphs/application/ups-apcups_charge.inc.php b/html/includes/graphs/application/ups-apcups_charge.inc.php new file mode 100644 index 0000000000..2272b2cda6 --- /dev/null +++ b/html/includes/graphs/application/ups-apcups_charge.inc.php @@ -0,0 +1,33 @@ +. +* +* @package LibreNMS +* @link http://librenms.org +* @copyright 2016 crcro +* @author Cercel Valentin +*/ +require 'includes/graphs/common.inc.php'; +$scale_min = 0; +$ds = 'charge'; +$colour_area = 'EEEEEE'; +$colour_line = 'FF3300'; +$colour_area_max = 'FFEE99'; +$graph_max = 0; +$unit_text = 'Percent'; +$ups_apcups = rrd_name($device['hostname'], array('app', 'ups-apcups', $app['app_id'])); +if (rrdtool_check_rrd_exists($ups_apcups)) { + $rrd_filename = $ups_apcups; +} +require 'includes/graphs/generic_simplex.inc.php'; diff --git a/html/includes/graphs/application/ups-apcups_load.inc.php b/html/includes/graphs/application/ups-apcups_load.inc.php new file mode 100644 index 0000000000..016e872c17 --- /dev/null +++ b/html/includes/graphs/application/ups-apcups_load.inc.php @@ -0,0 +1,33 @@ +. +* +* @package LibreNMS +* @link http://librenms.org +* @copyright 2016 crcro +* @author Cercel Valentin +*/ +require 'includes/graphs/common.inc.php'; +$scale_min = 0; +$ds = 'load'; +$colour_area = 'EEEEEE'; +$colour_line = 'FF3300'; +$colour_area_max = 'FFEE99'; +$graph_max = 0; +$unit_text = 'Percent'; +$ups_apcups = rrd_name($device['hostname'], array('app', 'ups-apcups', $app['app_id'])); +if (rrdtool_check_rrd_exists($ups_apcups)) { + $rrd_filename = $ups_apcups; +} +require 'includes/graphs/generic_simplex.inc.php'; diff --git a/html/includes/graphs/application/ups-apcups_remaining.inc.php b/html/includes/graphs/application/ups-apcups_remaining.inc.php new file mode 100644 index 0000000000..6b79e9a8e7 --- /dev/null +++ b/html/includes/graphs/application/ups-apcups_remaining.inc.php @@ -0,0 +1,33 @@ +. +* +* @package LibreNMS +* @link http://librenms.org +* @copyright 2016 crcro +* @author Cercel Valentin +*/ +require 'includes/graphs/common.inc.php'; +$scale_min = 0; +$ds = 'time_remaining'; +$colour_area = 'EEEEEE'; +$colour_line = '36393D'; +$colour_area_max = 'FFEE99'; +$graph_max = 0; +$unit_text = 'Minutes'; +$ups_apcups = rrd_name($device['hostname'], array('app', 'ups-apcups', $app['app_id'])); +if (rrdtool_check_rrd_exists($ups_apcups)) { + $rrd_filename = $ups_apcups; +} +require 'includes/graphs/generic_simplex.inc.php'; diff --git a/html/includes/graphs/application/ups-apcups_voltage_battery.inc.php b/html/includes/graphs/application/ups-apcups_voltage_battery.inc.php new file mode 100644 index 0000000000..3c02c62a3f --- /dev/null +++ b/html/includes/graphs/application/ups-apcups_voltage_battery.inc.php @@ -0,0 +1,49 @@ +. +* +* @package LibreNMS +* @link http://librenms.org +* @copyright 2016 crcro +* @author Cercel Valentin +*/ +require 'includes/graphs/common.inc.php'; +$scale_min = 0; +$colours = 'mixed'; +$unit_text = 'Volts'; +$unitlen = 10; +$bigdescrlen = 15; +$smalldescrlen = 15; +$dostack = 0; +$printtotal = 0; +$addarea = 1; +$transparency = 33; +$rrd_filename = rrd_name($device['hostname'], array('app', 'ups-apcups', $app['app_id'])); +$array = array( + 'battery_nominal' => array('descr' => 'Nominal','colour' => '630606',), + 'battery_voltage' => array('descr' => 'Current','colour' => '50C150',), +); +$i = 0; +if (rrdtool_check_rrd_exists($rrd_filename)) { + foreach ($array as $ds => $vars) { + $rrd_list[$i]['filename'] = $rrd_filename; + $rrd_list[$i]['descr'] = $vars['descr']; + $rrd_list[$i]['ds'] = $ds; + $rrd_list[$i]['colour'] = $vars['colour']; + $i++; + } +} else { + echo "file missing: $rrd_filename"; +} +require 'includes/graphs/generic_v3_multiline_float.inc.php'; diff --git a/html/includes/graphs/application/ups-apcups_voltage_input.inc.php b/html/includes/graphs/application/ups-apcups_voltage_input.inc.php new file mode 100644 index 0000000000..994f35ff55 --- /dev/null +++ b/html/includes/graphs/application/ups-apcups_voltage_input.inc.php @@ -0,0 +1,49 @@ +. +* +* @package LibreNMS +* @link http://librenms.org +* @copyright 2016 crcro +* @author Cercel Valentin +*/ +require 'includes/graphs/common.inc.php'; +$scale_min = 0; +$colours = 'mixed'; +$unit_text = 'Volts'; +$unitlen = 10; +$bigdescrlen = 15; +$smalldescrlen = 15; +$dostack = 0; +$printtotal = 0; +$addarea = 1; +$transparency = 33; +$rrd_filename = rrd_name($device['hostname'], array('app', 'ups-apcups', $app['app_id'])); +$array = array( + 'input_voltage' => array('descr' => 'Input','colour' => '630606',), + 'nominal_voltage' => array('descr' => 'Nominal','colour' => '50C150',), +); +$i = 0; +if (rrdtool_check_rrd_exists($rrd_filename)) { + foreach ($array as $ds => $vars) { + $rrd_list[$i]['filename'] = $rrd_filename; + $rrd_list[$i]['descr'] = $vars['descr']; + $rrd_list[$i]['ds'] = $ds; + $rrd_list[$i]['colour'] = $vars['colour']; + $i++; + } +} else { + echo "file missing: $rrd_filename"; +} +require 'includes/graphs/generic_v3_multiline_float.inc.php'; diff --git a/html/includes/graphs/application/ups-nut_charge.inc.php b/html/includes/graphs/application/ups-nut_charge.inc.php index 130ebdd62e..040d4c861b 100644 --- a/html/includes/graphs/application/ups-nut_charge.inc.php +++ b/html/includes/graphs/application/ups-nut_charge.inc.php @@ -31,5 +31,8 @@ $unit_text = 'Percent'; $ups_nut = rrd_name($device['hostname'], array('app', 'ups-nut', $app['app_id'])); if (rrdtool_check_rrd_exists($ups_nut)) { $rrd_filename = $ups_nut; +} else { + echo "file missing: $rrd_filename"; } + require 'includes/graphs/generic_simplex.inc.php'; diff --git a/html/includes/graphs/application/ups-nut_load.inc.php b/html/includes/graphs/application/ups-nut_load.inc.php index c678aa5ff8..2530f23d08 100644 --- a/html/includes/graphs/application/ups-nut_load.inc.php +++ b/html/includes/graphs/application/ups-nut_load.inc.php @@ -31,5 +31,8 @@ $unit_text = 'Percent'; $ups_nut = rrd_name($device['hostname'], array('app', 'ups-nut', $app['app_id'])); if (rrdtool_check_rrd_exists($ups_nut)) { $rrd_filename = $ups_nut; +} else { + echo "file missing: $rrd_filename"; } + require 'includes/graphs/generic_simplex.inc.php'; diff --git a/html/includes/graphs/application/ups-nut_remaining.inc.php b/html/includes/graphs/application/ups-nut_remaining.inc.php index 44c00b1ccd..16c3b3289d 100644 --- a/html/includes/graphs/application/ups-nut_remaining.inc.php +++ b/html/includes/graphs/application/ups-nut_remaining.inc.php @@ -17,6 +17,7 @@ * @link http://librenms.org * @copyright 2016 crcro * @author Cercel Valentin +* */ require 'includes/graphs/common.inc.php'; @@ -27,9 +28,12 @@ $colour_area = 'EEEEEE'; $colour_line = '36393D'; $colour_area_max = 'FFEE99'; $graph_max = 0; -$unit_text = 'Seconds'; +$unit_text = 'Minutes'; $ups_nut = rrd_name($device['hostname'], array('app', 'ups-nut', $app['app_id'])); if (rrdtool_check_rrd_exists($ups_nut)) { $rrd_filename = $ups_nut; +} else { + echo "file missing: $rrd_filename"; } + require 'includes/graphs/generic_simplex.inc.php'; diff --git a/html/includes/graphs/application/ups-nut_voltage_battery.inc.php b/html/includes/graphs/application/ups-nut_voltage_battery.inc.php index 08d2e18927..a00946c450 100644 --- a/html/includes/graphs/application/ups-nut_voltage_battery.inc.php +++ b/html/includes/graphs/application/ups-nut_voltage_battery.inc.php @@ -17,6 +17,7 @@ * @link http://librenms.org * @copyright 2016 crcro * @author Cercel Valentin +* */ require 'includes/graphs/common.inc.php'; @@ -33,7 +34,6 @@ $addarea = 1; $transparency = 33; $rrd_filename = rrd_name($device['hostname'], array('app', 'ups-nut', $app['app_id'])); $array = array( - 'battery_low' => array('descr' => 'Low','colour' => '630606',), 'battery_voltage' => array('descr' => 'Current','colour' => '50C150',), ); diff --git a/html/includes/graphs/device/cras_sessions.inc.php b/html/includes/graphs/device/cras_sessions.inc.php index a5bc233a33..5522215859 100644 --- a/html/includes/graphs/device/cras_sessions.inc.php +++ b/html/includes/graphs/device/cras_sessions.inc.php @@ -13,34 +13,43 @@ $rrd_options .= " DEF:lb=$rrd_filename:lb:AVERAGE"; $rrd_options .= " DEF:svc=$rrd_filename:svc:AVERAGE"; $rrd_options .= " DEF:webvpn=$rrd_filename:webvpn:AVERAGE"; -$rrd_options .= " COMMENT:'Sessions Current Average Maximum\\n'"; +$rrd_options .= " COMMENT:'Sessions Current Average Maximum\\n'"; -$rrd_options .= " AREA:svc#aa0000:'SSLVPN Tunnels'"; -$rrd_options .= " GPRINT:svc:LAST:'%6.2lf%s'"; -$rrd_options .= " GPRINT:svc:AVERAGE:' %6.2lf%s'"; -$rrd_options .= " GPRINT:svc:MAX:' %6.2lf%s\\\\n'"; +$rrd_options .= " AREA:svc#1985A1:'SSL VPN Client':STACK"; +$rrd_options .= " GPRINT:svc:LAST:'%8.2lf'"; +$rrd_options .= " GPRINT:svc:AVERAGE:' %8.2lf'"; +$rrd_options .= " GPRINT:svc:MAX:' %8.2lf\\\\n'"; -$rrd_options .= " AREA:webvpn#999999:'Clientless VPN'"; -$rrd_options .= " GPRINT:webvpn:LAST:'%6.2lf%s'"; -$rrd_options .= " GPRINT:webvpn:AVERAGE:' %6.2lf%s'"; -$rrd_options .= " GPRINT:webvpn:MAX:' %6.2lf%s\\\\n'"; +$rrd_options .= " AREA:webvpn#4C5C68:'Clientless VPN':STACK"; +$rrd_options .= " GPRINT:webvpn:LAST:'%8.2lf'"; +$rrd_options .= " GPRINT:webvpn:AVERAGE:' %8.2lf'"; +$rrd_options .= " GPRINT:webvpn:MAX:' %8.2lf\\\\n'"; -$rrd_options .= " AREA:ipsec#00aa00:'IPSEC '"; -$rrd_options .= " GPRINT:ipsec:LAST:'%6.2lf%s'"; -$rrd_options .= " GPRINT:ipsec:AVERAGE:' %6.2lf%s'"; -$rrd_options .= " GPRINT:ipsec:MAX:' %6.2lf%s\\\\n'"; +$rrd_options .= " AREA:ipsec#46494C:'IPSEC ':STACK"; +$rrd_options .= " GPRINT:ipsec:LAST:'%8.2lf'"; +$rrd_options .= " GPRINT:ipsec:AVERAGE:' %8.2lf'"; +$rrd_options .= " GPRINT:ipsec:MAX:' %8.2lf\\\\n'"; -$rrd_options .= " AREA:l2l#aaaa00:'Lan-to-Lan '"; -$rrd_options .= ' GPRINT:l2l:LAST:%6.2lf%s'; -$rrd_options .= " GPRINT:l2l:AVERAGE:' %6.2lf%s'"; -$rrd_options .= " GPRINT:l2l:MAX:' %6.2lf%s\\\\n'"; +$rrd_options .= " AREA:l2l#C5C3C6:'LAN-to-LAN ':STACK"; +$rrd_options .= ' GPRINT:l2l:LAST:%8.2lf'; +$rrd_options .= " GPRINT:l2l:AVERAGE:' %8.2lf'"; +$rrd_options .= " GPRINT:l2l:MAX:' %8.2lf\\\\n'"; -$rrd_options .= " AREA:email#0000aa:'Email '"; -$rrd_options .= ' GPRINT:email:LAST:%6.2lf%s'; -$rrd_options .= " GPRINT:email:AVERAGE:' %6.2lf%s'"; -$rrd_options .= " GPRINT:email:MAX:' %6.2lf%s\\\\n'"; +$rrd_options .= " AREA:email#DCDCDD:'Email ':STACK"; +$rrd_options .= ' GPRINT:email:LAST:%8.2lf'; +$rrd_options .= " GPRINT:email:AVERAGE:' %8.2lf'"; +$rrd_options .= " GPRINT:email:MAX:' %8.2lf\\\\n'"; -$rrd_options .= " AREA:lb#aa00aa:'Load Balancer '"; -$rrd_options .= ' GPRINT:lb:LAST:%6.2lf%s'; -$rrd_options .= " GPRINT:lb:AVERAGE:' %6.2lf%s'"; -$rrd_options .= " GPRINT:lb:MAX:' %6.2lf%s\\\\n'"; +$rrd_options .= " AREA:lb#FFFFFF:'Load Balancer ':STACK"; +$rrd_options .= ' GPRINT:lb:LAST:%8.2lf'; +$rrd_options .= " GPRINT:lb:AVERAGE:' %8.2lf'"; +$rrd_options .= " GPRINT:lb:MAX:' %8.2lf\\\\n'"; + +// Total +$rrd_options .= " 'CDEF:TOTAL=email,ipsec,l2l,lb,svc,webvpn,+,+,+,+,+'"; + +$rrd_options .= " 'LINE1:TOTAL#000000FF:Total '"; + +$rrd_options .= " 'GPRINT:TOTAL:LAST:%8.2lf'"; +$rrd_options .= " 'GPRINT:TOTAL:AVERAGE: %8.2lf'"; +$rrd_options .= " 'GPRINT:TOTAL:MAX: %8.2lf\\\\n'"; diff --git a/html/includes/graphs/device/runtime.inc.php b/html/includes/graphs/device/runtime.inc.php new file mode 100644 index 0000000000..186e51770a --- /dev/null +++ b/html/includes/graphs/device/runtime.inc.php @@ -0,0 +1,5 @@ +' + minDate: '', + icons: { + time: 'fa fa-clock-o', + date: 'fa fa-calendar', + up: 'fa fa-chevron-up', + down: 'fa fa-chevron-down', + previous: 'fa fa-chevron-left', + next: 'fa fa-chevron-right', + today: 'fa fa-calendar-check-o', + clear: 'fa fa-trash-o', + close: 'fa fa-close' + } + }); + $("#end").datetimepicker({ + icons: { + time: 'fa fa-clock-o', + date: 'fa fa-calendar', + up: 'fa fa-chevron-up', + down: 'fa fa-chevron-down', + previous: 'fa fa-chevron-left', + next: 'fa fa-chevron-right', + today: 'fa fa-calendar-check-o', + clear: 'fa fa-trash-o', + close: 'fa fa-close' + } }); - $("#end").datetimepicker(); $("#start").on("dp.change", function (e) { $("#end").data("DateTimePicker").minDate(e.date); }); diff --git a/html/includes/output/capture.inc.php b/html/includes/output/capture.inc.php index 61efdef9a1..1c702f98dc 100644 --- a/html/includes/output/capture.inc.php +++ b/html/includes/output/capture.inc.php @@ -78,16 +78,5 @@ if ($_GET['format'] == 'text') { $output = preg_replace('/\033\[[\d;]+m/', '', $output); - $length = strlen($output); - - header('Content-Description: File Transfer'); - header('Content-Type: text/plain'); - header("Content-Disposition: attachment; filename=$filename"); - header('Content-Transfer-Encoding: binary'); - header('Content-Length: ' . $length); - header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); - header('Expires: 0'); - header('Pragma: public'); - - echo $output; + file_download($filename, $output); } diff --git a/html/includes/output/query.inc.php b/html/includes/output/query.inc.php new file mode 100644 index 0000000000..8f89a90273 --- /dev/null +++ b/html/includes/output/query.inc.php @@ -0,0 +1,68 @@ +. + * + * @package LibreNMS + * @link http://librenms.org + * @copyright 2016 Neil Lathwood + * @author Neil Lathwood + */ + +if (!is_admin()) { + echo("Insufficient Privileges"); + exit(); +} + +$hostname = escapeshellcmd($_REQUEST['hostname']); +$type = $_REQUEST['type']; + +switch ($type) { + case 'alerts': + $filename = "alerts-$hostname.txt"; + $device_id = getidbyname($hostname); + $device = device_by_id_cache($device_id); + $rules = GetRules($device_id); + $output = ''; + foreach ($rules as $rule) { + $sql = GenSQL($rule['rule']); + $qry = dbFetchRow($sql, array($device_id)); + if (is_array($qry)) { + $response = 'matches'; + } else { + $response = 'no match'; + } + $output .= 'Rule name: ' . $rule['name'] . PHP_EOL; + $output .= 'Alert rule: ' . $rule['rule'] . PHP_EOL; + $output .= 'Rule match: ' . $response . PHP_EOL . PHP_EOL; + } + break; + default: + echo 'You must specify a valid type'; + exit(); +} + +// ---- Output ---- + +if ($_GET['format'] == 'text') { + header("Content-type: text/plain"); + header('X-Accel-Buffering: no'); + + echo $output; +} elseif ($_GET['format'] == 'download') { + file_download($filename, $output); +} diff --git a/html/includes/print-alert-rules.php b/html/includes/print-alert-rules.php index 2c240479f6..accf363ffb 100644 --- a/html/includes/print-alert-rules.php +++ b/html/includes/print-alert-rules.php @@ -162,13 +162,13 @@ $full_query = $full_query.$query." LIMIT $start,$results"; foreach (dbFetchRows($full_query, $param) as $rule) { $sub = dbFetchRows('SELECT * FROM alerts WHERE rule_id = ? ORDER BY `state` DESC, `id` DESC LIMIT 1', array($rule['id'])); - $ico = 'ok'; + $ico = 'check'; $col = 'success'; $extra = ''; if (sizeof($sub) == 1) { $sub = $sub[0]; if ((int) $sub['state'] === 0) { - $ico = 'ok'; + $ico = 'check'; $col = 'success'; } elseif ((int) $sub['state'] === 1 || (int) $sub['state'] === 2) { $ico = 'remove'; @@ -205,9 +205,9 @@ foreach (dbFetchRows($full_query, $param) as $rule) { echo ''.htmlentities($rule['rule']).''; echo ''.$rule['severity'].''; - echo " "; + echo " "; if ($rule_extra['mute'] === true) { - echo ""; + echo ""; } echo 'Max: '.$rule_extra['count'].'
Delay: '.$rule_extra['delay'].'
Interval: '.$rule_extra['interval'].'
'; @@ -219,8 +219,9 @@ foreach (dbFetchRows($full_query, $param) as $rule) { echo ''; echo ''; if ($_SESSION['userlevel'] >= '10') { - echo " "; - echo ""; + echo "
"; + echo " "; + echo ""; } echo ''; @@ -297,15 +298,15 @@ $('input[name="alert-rule"]').on('switchChange.bootstrapSwitch', function(event success: function(msg) { if(msg.indexOf("ERROR:") <= -1) { if(state) { - $('#alert-rule-'+alert_id).removeClass('glyphicon-pause'); - $('#alert-rule-'+alert_id).addClass('glyphicon-'+orig_state); + $('#alert-rule-'+alert_id).removeClass('fa-pause'); + $('#alert-rule-'+alert_id).addClass('fa-'+orig_state); $('#alert-rule-'+alert_id).removeClass('text-default'); $('#alert-rule-'+alert_id).addClass('text-'+orig_colour); $('#row_'+alert_id).removeClass('active'); $('#row_'+alert_id).addClass(orig_class); } else { - $('#alert-rule-'+alert_id).removeClass('glyphicon-'+orig_state); - $('#alert-rule-'+alert_id).addClass('glyphicon-pause'); + $('#alert-rule-'+alert_id).removeClass('fa-'+orig_state); + $('#alert-rule-'+alert_id).addClass('fa-pause'); $('#alert-rule-'+alert_id).removeClass('text-'+orig_colour); $('#alert-rule-'+alert_id).addClass('text-default'); $('#row_'+alert_id).removeClass('warning'); diff --git a/html/includes/print-alert-templates.php b/html/includes/print-alert-templates.php index 0af128a766..35f0fe6241 100644 --- a/html/includes/print-alert-templates.php +++ b/html/includes/print-alert-templates.php @@ -79,9 +79,11 @@ foreach (dbFetchRows($full_query, $param) as $template) { '.$template['name'].' '; if ($_SESSION['userlevel'] >= '10') { - echo " "; - echo " "; - echo ""; + echo "
"; + echo " "; + echo " "; + echo ""; + echo "
"; } echo ' diff --git a/html/includes/print-alerts.inc.php b/html/includes/print-alerts.inc.php index 8829f27c85..93911a212e 100644 --- a/html/includes/print-alerts.inc.php +++ b/html/includes/print-alerts.inc.php @@ -19,27 +19,27 @@ echo ''.htmlspecialchars($alert_entry['name']).''; if ($alert_state != '') { if ($alert_state == '0') { - $glyph_icon = 'ok'; - $glyph_color = 'green'; - $text = 'Ok'; + $fa_icon = 'check'; + $fa_color = 'success'; + $text = 'Ok'; } elseif ($alert_state == '1') { - $glyph_icon = 'remove'; - $glyph_color = 'red'; - $text = 'Alert'; + $fa_icon = 'remove'; + $fa_color = 'danger'; + $text = 'Alert'; } elseif ($alert_state == '2') { - $glyph_icon = 'info-sign'; - $glyph_color = 'lightgrey'; - $text = 'Ack'; + $fa_icon = 'info-circle'; + $fa_color = 'muted'; + $text = 'Ack'; } elseif ($alert_state == '3') { - $glyph_icon = 'arrow-down'; - $glyph_color = 'orange'; - $text = 'Worse'; + $fa_icon = 'arrow-down'; + $fa_color = 'warning'; + $text = 'Worse'; } elseif ($alert_state == '4') { - $glyph_icon = 'arrow-up'; - $glyph_color = 'khaki'; - $text = 'Better'; + $fa_icon = 'arrow-up'; + $fa_color = 'info'; + $text = 'Better'; }//end if - echo " $text"; + echo " $text"; }//end if echo ''; diff --git a/html/includes/print-date-selector.inc.php b/html/includes/print-date-selector.inc.php index 3333df0b6d..f7055b3a48 100644 --- a/html/includes/print-date-selector.inc.php +++ b/html/includes/print-date-selector.inc.php @@ -33,8 +33,8 @@ echo ' ("0"+strto.getHours()).slice(-2)+":"+ ("0"+strto.getMinutes()).slice(-2) ); - $("#dtpickerfrom").datetimepicker({useCurrent: true, sideBySide: true, useStrict: false}); - $("#dtpickerto").datetimepicker({useCurrent: true, sideBySide: true, useStrict: false}); + $("#dtpickerfrom").datetimepicker({useCurrent: true, sideBySide: true, useStrict: false, icons: {time: "fa fa-clock-o", date: "fa fa-calendar", up: "fa fa-chevron-up", down: "fa fa-chevron-down", previous: "fa fa-chevron-left", next: "fa fa-chevron-right", today: "fa fa-calendar-check-o", clear: "fa fa-trash-o", close: "fa fa-close"}}); + $("#dtpickerto").datetimepicker({useCurrent: true, sideBySide: true, useStrict: false, icons: {time: "fa fa-clock-o", date: "fa fa-calendar", up: "fa fa-chevron-up", down: "fa fa-chevron-down", previous: "fa fa-chevron-left", next: "fa fa-chevron-right", today: "fa fa-calendar-check-o", clear: "fa fa-trash-o", close: "fa fa-close"}}); }); '; diff --git a/html/includes/print-interface.inc.php b/html/includes/print-interface.inc.php index 414bdcf241..440dd80b94 100644 --- a/html/includes/print-interface.inc.php +++ b/html/includes/print-interface.inc.php @@ -232,7 +232,7 @@ if (strpos($port['label'], 'oopback') === false && !$graph_type) { }//end if if (count($int_links) > 3) { - echo '
+ echo '
'; } diff --git a/html/includes/print-menubar.php b/html/includes/print-menubar.php index a0f3683fd8..13b5040cdc 100644 --- a/html/includes/print-menubar.php +++ b/html/includes/print-menubar.php @@ -48,21 +48,21 @@ if ($config['title_image']) {