Skip to content

Commit

Permalink
Merge pull request #768 from laf/callback
Browse files Browse the repository at this point in the history
Callback system for stats
  • Loading branch information
f0o committed Apr 12, 2015
2 parents 09522e8 + 0db0dd3 commit 7d478c0
Show file tree
Hide file tree
Showing 13 changed files with 248 additions and 3 deletions.
101 changes: 101 additions & 0 deletions callback.php
@@ -0,0 +1,101 @@
<?php

/*
* LibreNMS
*
* Copyright (c) 2014 Neil Lathwood <https://github.com/laf/ http://www.lathwood.co.uk/fa>
*
* 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. Please see LICENSE.txt at the top level of
* the source code distribution for details.
*/

$enabled = dbFetchCell("SELECT `value` FROM `callback` WHERE `name` = 'enabled'");
if ($enabled == 1) {

if (dbFetchCell("SELECT `value` FROM `callback` WHERE `name` = 'uuid'") == '') {
dbInsert(array('name'=>'uuid','value'=>guidv4(openssl_random_pseudo_bytes(16))),'callback');
}
$uuid = dbFetchCell("SELECT `value` FROM `callback` WHERE `name` = 'uuid'");

$queries = array(
'alert_rules'=>'SELECT COUNT(`severity`) AS `total`,`severity` FROM `alert_rules` WHERE `disabled`=0 GROUP BY `severity`',
'alert_templates'=>'SELECT COUNT(`id`) AS `total` FROM `alert_templates`',
'api_tokens'=>'SELECT COUNT(`id`) AS `total` FROM `api_tokens` WHERE `disabled`=0',
'applications'=>'SELECT COUNT(`app_type`) AS `total`,`app_type` FROM `applications` GROUP BY `app_type`',
'bgppeer_state'=>'SELECT COUNT(`bgpPeerState`) AS `total`,`bgpPeerState` FROM `bgpPeers` GROUP BY `bgpPeerState`',
'bgppeer_status'=>'SELECT COUNT(`bgpPeerAdminStatus`) AS `total`,`bgpPeerAdminStatus` FROM `bgpPeers` GROUP BY `bgpPeerAdminStatus`',
'bills'=>'SELECT COUNT(`bill_type`) AS `total`,`bill_type` FROM `bills` GROUP BY `bill_type`',
'cef'=>'SELECT COUNT(`device_id`) AS `total` FROM `cef_switching`',
'cisco_asa'=>'SELECT COUNT(`oid`) AS `total`,`oid` FROM `ciscoASA` WHERE `disabled` = 0 GROUP BY `oid`',
'mempool'=>'SELECT COUNT(`cmpName`) AS `total`,`cmpName` FROM `cmpMemPool` GROUP BY `cmpName`',
'current'=>'SELECT COUNT(`current_type`) AS `total`,`current_type` FROM `current` GROUP BY `current_type`',
'dbschema'=>'SELECT COUNT(`version`) AS `total`, `version` FROM `dbSchema`',
'snmp_version'=>'SELECT COUNT(`snmpver`) AS `total`,`snmpver` FROM `devices` GROUP BY `snmpver`',
'os'=>'SELECT COUNT(`os`) AS `total`,`os` FROM `devices` GROUP BY `os`',
'type'=>'SELECT COUNT(`type`) AS `total`,`type` FROM `devices` GROUP BY `type`',
'full_type'=>'SELECT COUNT(`device_id`) AS `total`, CONCAT_WS(', ', `os`,`hardware`,`type`) FROM `devices` GROUP BY `os`,`hardware`,`type`',
'ipsec'=>'SELECT COUNT(`device_id`) AS `total` FROM `ipsec_tunnels`',
'ipv4_addresses'=>'SELECT COUNT(`ipv4_address_id`) AS `total` FROM `ipv4_addresses`',
'ipv4_macaddress'=>'SELECT COUNT(`port_id`) AS `total` FROM ipv4_mac',
'ipv4_networks'=>'SELECT COUNT(`ipv4_network_id`) AS `total` FROM ipv4_networks',
'ipv6_addresses'=>'SELECT COUNT(`ipv6_address_id`) AS `total` FROM `ipv6_addresses`',
'ipv6_networks'=>'SELECT COUNT(`ipv6_network_id`) AS `total` FROM `ipv6_networks`',
'xdp'=>'SELECT COUNT(`id`) AS `total`,`protocol` FROM `links` GROUP BY `protocol`',
'ospf'=>'SELECT COUNT(`device_id`) AS `total`,`ospfVersionNumber` FROM `ospf_instances` GROUP BY `ospfVersionNumber`',
'ospf_links'=>'SELECT COUNT(`device_id`) AS `total`,`ospfIfType` FROM `ospf_ports` GROUP BY `ospfIfType`',
'arch'=>'SELECT COUNT(`pkg_id`) AS `total`,`arch` FROM `packages` GROUP BY `arch`',
'pollers'=>'SELECT COUNT(`id`) AS `total` FROM `pollers`',
'port_type'=>'SELECT COUNT(`port_id`) AS `total`,`ifType` FROM `ports` GROUP BY `ifType`',
'port_ifspeed'=>'SELECT COUNT(`ifSpeed`) AS `total`,ROUND(`ifSpeed`/1000/1000) FROM `ports` GROUP BY `ifSpeed`',
'port_vlans'=>'SELECT COUNT(`device_id`) AS `total`,`state` FROM `ports_vlans` GROUP BY `state`',
'processes'=>'SELECT COUNT(`device_id`) AS `total` FROM `processes`',
'processors'=>'SELECT COUNT(`processor_id`) AS `total`,`processor_type` FROM `processors` GROUP BY `processor_type`',
'pseudowires'=>'SELECT COUNT(`pseudowire_id`) AS `total` FROM `pseudowires`',
'sensors'=>'SELECT COUNT(`sensor_id`) AS `total`,`sensor_class` FROM `sensors` GROUP BY `sensor_class`',
'storage'=>'SELECT COUNT(`storage_id`) AS `total`,`storage_type` FROM `storage` GROUP BY `storage_type`',
'toner'=>'SELECT COUNT(`toner_id`) AS `total`,`toner_type` FROM `toner` GROUP BY `toner_type`',
'vlans'=>'SELECT COUNT(`vlan_id`) AS `total`,`vlan_type` FROM `vlans` GROUP BY `vlan_type`',
'vminfo'=>'SELECT COUNT(`id`) AS `total`,`vm_type` FROM `vminfo` GROUP BY `vm_type`',
'vmware'=>'SELECT COUNT(`id`) AS `total` FROM `vmware_vminfo`',
'vrfs'=>'SELECT COUNT(`vrf_id`) AS `total` FROM `vrfs`');


foreach ($queries as $name => $query) {
$data = dbFetchRows($query);
$response[$name] = $data;
}
$output = array('uuid'=>$uuid,'data'=>$response);
$data = json_encode($output);
$submit = array('data'=>$data);

$fields = '';
foreach($submit as $key => $value) {
$fields .= $key . '=' . $value . '&';
}
rtrim($fields, '&');

$post = curl_init();
curl_setopt($post, CURLOPT_URL, $config['callback_post']);
curl_setopt($post, CURLOPT_POST, count($submit));
curl_setopt($post, CURLOPT_POSTFIELDS, $fields);
curl_setopt($post, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($post);
} elseif ($enabled == 2) {

$uuid = dbFetchCell("SELECT `value` FROM `callback` WHERE `name` = 'uuid'");
$fields = "uuid=$uuid";

$clear = curl_init();
curl_setopt($clear, CURLOPT_URL, $config['callback_clear']);
curl_setopt($clear, CURLOPT_POST, count($clear));
curl_setopt($clear, CURLOPT_POSTFIELDS, $fields);
curl_setopt($clear, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($clear);
dbDelete('callback','`name`="uuid"',array());
dbUpdate(array('value' => '0'), 'callback', '`name` = "enabled"', array());
}

?>
3 changes: 3 additions & 0 deletions daily.php
Expand Up @@ -55,5 +55,8 @@
}
}
}
if ($options['f'] === 'callback') {
require_once "callback.php";
}

?>
1 change: 1 addition & 0 deletions daily.sh
Expand Up @@ -11,3 +11,4 @@ php daily.php -f syslog
php daily.php -f eventlog
php daily.php -f authlog
php daily.php -f perf_times
php daily.php -f callback
32 changes: 32 additions & 0 deletions doc/General/Callback-Stats-and-Privacy.md
@@ -0,0 +1,32 @@
## Stats data and your privacy ##

This document has been put together to explain what LibreNMS does when it calls back home to report some anonymous statistics.

Let's start off by saying, all of the code that processes the data and submits it is included in the standard LibreNMS branch you've installed, the code that accepts this data and in turn generates some pretty graphs is all open source and available on Git Hub. Please feel free to review the code, comment on it and suggest changes / improvements. Also, don't forget - by default installations DO NOT call back home, you need to opt into this.

Above all we respect users privacy which is why this system has been designed like it has.

Now onto the bit you're interested in, what is submitted and what we do with that data.

#### What is submitted ####
- All data is anonymous.
- Generic statistics are taken from the database, these include things like device total, type and os, port types, speeds and total, total bgp peers. Take a look at the code for full details.
- A random UUID is generated on your own install.
- That's it!
- Your IP isn't logged, even via our web service accepting the data. We don't need to know who you are so don't ask.

#### What we do with the data ####
- We store it, not for long - 3 months at the moment although this could change.
- We use it to generate pretty graphs for people to see.
- We use it to help prioritise issues and features that need to be worked on.

#### Questions? ####
- Q. How often is data submitted? A. We submit the data once a day according to running daily.sh via cron. If you disable this then opting in will not have any affect.
- Q. Where can I see the data I submitted? A. You can't see the data raw, but we collate all of the data together and provide a dynamic site so you can see the results of all contributed stats [here](https://stats.librenms.org)
- Q. I want my data removed. A. That's easy, simply press 'Clear remote stats' in the About LibreNMS page of your control panel, the next time the call back script is run it will remove all the data we have.
- Q. I clicked the 'Clear remote stats' button by accident. A. No problem, before daily.sh runs again - just opt back in, all of your existing data will stay.

Hopefully this answers the questions you might have on why and what we are doing here, if not, please pop into our irc channel or google mailing list and ask any questions you like.

If you're happy with all of this - please consider switching the call back system on, you can do this within the About LibreNMS page within your control panel. In the Statistics section you will find a toggle switch to enable / disable the feature. If you've previously had it switched on and want to opt out and remove your data, click the 'Clear remote stats' button and on the next submission all the data you've sent us will be removed!

2 changes: 1 addition & 1 deletion doc/Installation/Installation-(Debian-Ubuntu).md
Expand Up @@ -42,7 +42,7 @@ This host is where the web server and SNMP poller run. It could be the same mac

Install the required software:

apt-get install libapache2-mod-php5 php5-cli php5-mysql php5-gd php5-snmp php-pear snmp graphviz php5-mcrypt php5-json apache2 fping imagemagick whois mtr-tiny nmap python-mysqldb snmpd mysql-client php-net-ipv4 php-net-ipv6 rrdtool git
apt-get install libapache2-mod-php5 php5-cli php5-mysql php5-gd php5-snmp php-pear php5-curl snmp graphviz php5-mcrypt php5-json apache2 fping imagemagick whois mtr-tiny nmap python-mysqldb snmpd mysql-client php-net-ipv4 php-net-ipv6 rrdtool git

The packages listed above are an all-inclusive list of packages that were necessary on a clean install of Ubuntu 12.04/14.04.

Expand Down
2 changes: 1 addition & 1 deletion doc/Installation/Installation-(RHEL-CentOS).md
Expand Up @@ -47,7 +47,7 @@ Install necessary software. The packages listed below are an all-inclusive list
Note if not using HTTPd (Apache): RHEL requires `httpd` to be installed regardless of of `nginx`'s (or any other web-server's) presence.

rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm
yum install php php-cli php-gd php-mysql php-snmp php-pear httpd net-snmp graphviz graphviz-php mysql ImageMagick jwhois nmap mtr rrdtool MySQL-python net-snmp-utils vixie-cron php-mcrypt fping git
yum install php php-cli php-gd php-mysql php-snmp php-pear php-curl httpd net-snmp graphviz graphviz-php mysql ImageMagick jwhois nmap mtr rrdtool MySQL-python net-snmp-utils vixie-cron php-mcrypt fping git
pear install Net_IPv4-1.3.4
pear install Net_IPv6-1.2.2b2

Expand Down
2 changes: 1 addition & 1 deletion doc/Installation/Installation-Lighttpd-(Debian-Ubuntu).md
Expand Up @@ -37,7 +37,7 @@ Change `127.0.0.1` to the IP address that your MySQL server should listen on. R

Install necessary software. The packages listed below are an all-inclusive list of packages that were necessary on a clean install of Debian 7.

apt-get install lighttpd php5-cli php5-mysql php5-gd php5-snmp php5-cgi php-pear snmp graphviz mysql-server mysql-client rrdtool sendmail fping imagemagick whois mtr-tiny nmap ipmitool php5-mcrypt php5-json python-mysqldb snmpd php-net-ipv4 php-net-ipv6 rrdtool git
apt-get install lighttpd php5-cli php5-mysql php5-gd php5-snmp php5-cgi php-pear php5-curl snmp graphviz mysql-server mysql-client rrdtool sendmail fping imagemagick whois mtr-tiny nmap ipmitool php5-mcrypt php5-json python-mysqldb snmpd php-net-ipv4 php-net-ipv6 rrdtool git

### Cloning ###

Expand Down
15 changes: 15 additions & 0 deletions html/forms/callback-clear.inc.php
@@ -0,0 +1,15 @@
<?php

/*
* LibreNMS
*
* Copyright (c) 2014 Neil Lathwood <https://github.com/laf/ http://www.lathwood.co.uk/fa>
*
* 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. Please see LICENSE.txt at the top level of
* the source code distribution for details.
*/

dbUpdate(array('value' => '2'), 'callback', '`name` = "enabled"', array());
25 changes: 25 additions & 0 deletions html/forms/callback-statistics.inc.php
@@ -0,0 +1,25 @@
<?php

/*
* LibreNMS
*
* Copyright (c) 2014 Neil Lathwood <https://github.com/laf/ http://www.lathwood.co.uk/fa>
*
* 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. Please see LICENSE.txt at the top level of
* the source code distribution for details.
*/

if ($_POST['state'] == 'true') {
$state = 1;
} elseif ($_POST['state'] == 'false') {
$state = 0;
} else {
$state = 0;
}

if( dbUpdate(array('value' => $state), 'callback', '`name` = "enabled"', array()) == 0) {
dbInsert(array('value' => $state,'name' => 'enabled'), 'callback');
}
52 changes: 52 additions & 0 deletions html/pages/about.inc.php
Expand Up @@ -67,10 +67,30 @@
$stat_vrf = dbFetchCell("SELECT COUNT(vrf_id) FROM `vrfs`");
$stat_vlans = dbFetchCell("SELECT COUNT(vlan_id) FROM `vlans`");

$callback_status = dbFetchCell("SELECT `value` FROM `callback` WHERE `name` = 'enabled'");
if ($callback_status == 1) {
$stats_checked = 'checked';
} else {
$stats_checked = '';
}
$callback = 'Opt in to send anonymous usage statistics to LibreNMS? <input type="checkbox" data-on-text="Yes" data-off-text="No" data-size="mini" name="statistics" '.$stats_checked.'>';

echo("
<div class='table-responsive'>
<table class='table table-condensed'>
<tr>
<td colspan='4'><span class='bg-danger'>$callback</span></td>
<tr>");

if (dbFetchCell("SELECT `value` FROM `callback` WHERE `name` = 'uuid'") != '' && $callback_status != 2) {
echo("
<tr>
<td colspan='4'><button class='btn btn-danger btn-xs' type='submit' name='clear-stats' id='clear-stats'>Clear remote stats</button></td>
</tr>
");
}

echo("
<td><img src='images/icons/device.png' class='optionicon'> <b>Devices</b></td><td align=right>$stat_devices</td>
<td><img src='images/icons/port.png' class='optionicon'> <b>Ports</b></td><td align=right>$stat_ports</td>
</tr>
Expand Down Expand Up @@ -175,3 +195,35 @@

</div>
</div>

<script>
$("[name='statistics']").bootstrapSwitch('offColor','danger','size','mini');
$('input[name="statistics"]').on('switchChange.bootstrapSwitch', function(event, state) {
event.preventDefault();
$.ajax({
type: 'POST',
url: '/ajax_form.php',
data: { type: "callback-statistics", state: state},
dataType: "html",
success: function(data){
},
error:function(){
return $("#switch-state").bootstrapSwitch("toggle");
}
});
});
$('#clear-stats').click(function(event) {
event.preventDefault();
$.ajax({
type: 'POST',
url: '/ajax_form.php',
data: { type: "callback-clear"},
dataType: "html",
success: function(data){
location.reload(true);
},
error:function(){
}
});
});
</script>
4 changes: 4 additions & 0 deletions includes/defaults.inc.php
Expand Up @@ -599,4 +599,8 @@
$config['distributed_poller_memcached_host'] = 'example.net';
$config['distributed_poller_memcached_port'] = '11211';

// Stats callback system
$config['callback_post'] = 'https://stats.librenms.org/log.php';
$config['callback_clear'] = 'https://stats.librenms.org/clear.php';

?>
11 changes: 11 additions & 0 deletions includes/functions.php
Expand Up @@ -1129,4 +1129,15 @@ function convert_delay($delay) {
return($delay_sec);
}

function guidv4($data) {
// http://stackoverflow.com/questions/2040240/php-function-to-generate-v4-uuid#15875555
// From: Jack http://stackoverflow.com/users/1338292/ja%CD%A2ck
assert(strlen($data) == 16);

$data[6] = chr(ord($data[6]) & 0x0f | 0x40); // set version to 0100
$data[8] = chr(ord($data[8]) & 0x3f | 0x80); // set bits 6-7 to 10

return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}

?>
1 change: 1 addition & 0 deletions sql-schema/046.sql
@@ -0,0 +1 @@
CREATE TABLE `librenms`.`callback` ( `callback_id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY , `name` CHAR( 64 ) NOT NULL , `value` CHAR( 64 ) NOT NULL ) ENGINE = INNODB;

0 comments on commit 7d478c0

Please sign in to comment.