2016-02-06 20:08:28 +00:00
|
|
|
#!/usr/bin/perl -w
|
|
|
|
#
|
|
|
|
# ==========================================================================
|
|
|
|
#
|
|
|
|
# ZoneMinder Update Script, $Date$, $Revision$
|
|
|
|
# Copyright (C) 2001-2008 Philip Coombes
|
|
|
|
#
|
|
|
|
# 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 2
|
|
|
|
# of the License, or (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with this program; if not, write to the Free Software
|
|
|
|
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
#
|
|
|
|
# ==========================================================================
|
|
|
|
|
|
|
|
=head1 NAME
|
|
|
|
|
|
|
|
zmtelemetry.pl - Send usage information to the ZoneMinder development team
|
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
|
|
|
|
zmtelemetry.pl
|
|
|
|
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
|
|
|
|
This script collects usage information of the local system and sends it to the
|
|
|
|
ZoneMinder development team. This data will be used to determine things like
|
|
|
|
who and where our customers are, how big their systems are, the underlying
|
|
|
|
hardware and operating system, etc. This is being done for the sole purpoase of
|
|
|
|
creating a better product for our target audience. This script is intended to
|
|
|
|
be completely transparent to the end user, and can be disabled from the web
|
|
|
|
console under Options.
|
|
|
|
|
|
|
|
=head1 OPTIONS
|
|
|
|
|
|
|
|
none currently
|
|
|
|
|
|
|
|
=cut
|
|
|
|
use strict;
|
|
|
|
use bytes;
|
|
|
|
|
|
|
|
@EXTRA_PERL_LIB@
|
|
|
|
use ZoneMinder::Config qw(:all);
|
|
|
|
use ZoneMinder::Logger qw(:all);
|
|
|
|
use ZoneMinder::Database qw(:all);
|
|
|
|
use DBI;
|
|
|
|
use Getopt::Long;
|
|
|
|
use autouse 'Pod::Usage'=>qw(pod2usage);
|
2016-02-11 02:46:05 +00:00
|
|
|
use LWP::UserAgent;
|
|
|
|
use Sys::MemInfo;
|
|
|
|
use Sys::CPU;
|
2016-02-06 20:08:28 +00:00
|
|
|
|
|
|
|
$ENV{PATH} = '/bin:/usr/bin:/usr/local/bin';
|
|
|
|
$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
|
|
|
|
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
|
|
|
|
|
|
|
|
use constant CHECK_INTERVAL => (14*24*60*60); # Interval between version checks
|
|
|
|
|
|
|
|
# Setting these as contants for now.
|
|
|
|
# Alternatively, we can put these in the dB and then retrieve using the Config hash.
|
2016-02-09 19:49:09 +00:00
|
|
|
use constant ZM_TELEMETRY_SERVER_NAME => "38092a65757da3cb5f949b6b94aa8fc9.us-east-1.aws.found.io";
|
|
|
|
use constant ZM_TELEMETRY_SERVER_PORT => "9243";
|
2016-02-06 20:08:28 +00:00
|
|
|
|
|
|
|
if ( $Config{ZM_TELEMETRY_DATA} )
|
|
|
|
{
|
|
|
|
print( "Update agent starting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" );
|
|
|
|
|
|
|
|
my $lastCheck = $Config{ZM_TELEMETRY_LAST_CHECK};
|
|
|
|
|
|
|
|
while( 1 )
|
|
|
|
{
|
|
|
|
my $now = time();
|
|
|
|
if ( ($now-$lastCheck) > CHECK_INTERVAL) )
|
|
|
|
{
|
2016-02-11 02:46:05 +00:00
|
|
|
Info( "Colleting data to send to ZoneMinder Telemetry server." );
|
2016-02-06 20:08:28 +00:00
|
|
|
|
2016-02-11 02:46:05 +00:00
|
|
|
# Build the telemetry hash
|
2016-02-06 20:08:28 +00:00
|
|
|
# We should keep *BSD systems in mind when calling system commands
|
2016-02-11 02:46:05 +00:00
|
|
|
my %telemetry;
|
|
|
|
$telemetry{uuid} = getUUID();
|
|
|
|
$telemetry{ip} = getIP();
|
2016-02-11 14:10:16 +00:00
|
|
|
$telemetry{timestamp} = runSysCmd("date +%Y-%m-%dT%H:%M:%S%z");
|
2016-02-11 13:22:31 +00:00
|
|
|
$telemetry{monitor_count} = countQuery("Monitors");
|
|
|
|
$telemetry{event_count} = countQuery("Events");
|
2016-02-11 02:46:05 +00:00
|
|
|
$telemetry{distro} = runSysCmd("uname -a");
|
|
|
|
$telemetry{release} = runSysCmd("cat /etc/*{release,version}");
|
|
|
|
$telemetry{zm_version} = ZoneMinder::Base::ZM_VERSION;
|
|
|
|
$telemetry{system_memory} = totalmem() / (1024*1024);
|
|
|
|
$telemetry{processor_count} = cpu_count();
|
|
|
|
#$telemetry{monitors} = TO-DO
|
|
|
|
|
|
|
|
Info( "Sending data to ZoneMinder Telemetry server." );
|
|
|
|
|
|
|
|
my $result = jsonEncode( \%telemetry );
|
2016-02-06 20:08:28 +00:00
|
|
|
|
|
|
|
if ( sendData($result) ) {
|
|
|
|
$lastCheck = $now;
|
|
|
|
|
2016-02-10 19:04:14 +00:00
|
|
|
my $lc_sql = "update Config set Value = ? where Name = 'ZM_TELEMETRY_LAST_UPLOAD'";
|
2016-02-06 20:08:28 +00:00
|
|
|
my $lc_sth = $dbh->prepare_cached( $lc_sql ) or die( "Can't prepare '$lc_sql': ".$dbh->errstr() );
|
|
|
|
my $lc_res = $lc_sth->execute( $lastCheck ) or die( "Can't execute: ".$lc_sth->errstr() );
|
|
|
|
}
|
2016-02-11 02:46:05 +00:00
|
|
|
|
|
|
|
Info( "Telemetry data uploaded successfully." );
|
2016-02-06 20:08:28 +00:00
|
|
|
}
|
|
|
|
sleep( 3600 );
|
|
|
|
}
|
|
|
|
print( "Update agent exiting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" );
|
|
|
|
}
|
|
|
|
|
|
|
|
# Find, verify, then run the supplied system command
|
|
|
|
sub runSysCmd {
|
|
|
|
my $msg = shift;
|
|
|
|
my @arguments = split(/ /,$msg);
|
|
|
|
chomp($arguments[0]);
|
|
|
|
my $path = qx( which $arguments[0] );
|
|
|
|
|
|
|
|
my $status = $? >> 8;
|
|
|
|
my $result = "";
|
|
|
|
if ( !$path || $status ) {
|
|
|
|
Warning( "Cannot find the $arguments[0] executable." );
|
|
|
|
} else {
|
|
|
|
chomp($path);
|
|
|
|
$arguments[0] = $path;
|
|
|
|
my $cmd = join(" ",@arguments);
|
|
|
|
my $result = qx( $cmd );
|
|
|
|
}
|
|
|
|
return chomp($result);
|
|
|
|
}
|
|
|
|
|
|
|
|
# Upload message data to ZoneMinder telemetry server
|
|
|
|
sub sendData {
|
|
|
|
my $msg = shift;
|
|
|
|
|
|
|
|
my $ua = LWP::UserAgent->new;
|
2016-02-09 20:35:45 +00:00
|
|
|
my $server_endpoint = "https://".ZM_TELEMETRY_SERVER_NAME.":".ZM_TELEMETRY_SERVER_PORT."/zmtelemetry/testing/";
|
2016-02-06 20:08:28 +00:00
|
|
|
|
|
|
|
if ( $Config{ZM_UPDATE_CHECK_PROXY} ) {
|
2016-02-09 20:35:45 +00:00
|
|
|
$ua->proxy( "https", $Config{ZM_UPDATE_CHECK_PROXY} );
|
2016-02-06 20:08:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# set custom HTTP request header fields
|
|
|
|
my $req = HTTP::Request->new(POST => $server_endpoint);
|
2016-02-09 20:35:45 +00:00
|
|
|
$req->header('content-type' => 'application/x-www-form-urlencoded');
|
2016-02-06 20:08:28 +00:00
|
|
|
$req->header('content-length' => length($msg));
|
|
|
|
$req->header('connection' => 'Close');
|
|
|
|
|
|
|
|
$req->content($msg);
|
|
|
|
|
|
|
|
my $resp = $ua->request($req);
|
|
|
|
my success = 0;
|
|
|
|
if ($resp->is_success) {
|
|
|
|
my $message = $resp->decoded_content;
|
|
|
|
Info("Telemetry data successfully uploaded.");
|
2016-02-11 02:46:05 +00:00
|
|
|
Debug("Telemetry server upload success response message: $message");
|
2016-02-06 20:08:28 +00:00
|
|
|
$success = 1;
|
|
|
|
} else {
|
2016-02-11 02:46:05 +00:00
|
|
|
Warning("Telemetry server returned HTTP POST error code: $resp->code");
|
|
|
|
Debug("Telemetry server upload failure response message: $resp->message");
|
2016-02-06 20:08:28 +00:00
|
|
|
}
|
|
|
|
return $success;
|
|
|
|
}
|
|
|
|
|
2016-02-10 19:04:14 +00:00
|
|
|
# Retrieves the UUID from the database. Creates a new UUID if one does not exist.
|
|
|
|
sub getUUID {
|
|
|
|
my $uuid= "";
|
|
|
|
|
|
|
|
if ( $Config{ZM_TELEMETRY_UUID} ) {
|
|
|
|
$uuid = $Config{ZM_TELEMETRY_UUID};
|
|
|
|
} else {
|
|
|
|
use OSSSP::uuid;
|
|
|
|
my $uuidobj = OSSP::uuid->new;
|
|
|
|
$uuidobj -> make("v1");
|
2016-02-10 19:37:22 +00:00
|
|
|
$uuid = $Config{ZM_TELEMETRY_UUID} = $uuidobj->export("str");
|
2016-02-10 19:04:14 +00:00
|
|
|
|
|
|
|
my $sql = "update Config set Value = ? where Name = 'ZM_TELEMETRY_UUID'";
|
|
|
|
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
|
|
|
my $res = $sth->execute( $uuid ) or die( "Can't execute: ".$sth->errstr() );
|
|
|
|
}
|
|
|
|
|
|
|
|
return $uuid;
|
|
|
|
}
|
|
|
|
|
2016-02-10 20:05:34 +00:00
|
|
|
# Retrieves the local server's external IP address
|
|
|
|
sub getIP {
|
|
|
|
my $ipaddr = "0.0.0.0";
|
|
|
|
my $ua = LWP::UserAgent->new;
|
|
|
|
my $server_endpoint = "https://wiki.zoneminder.com/ip.php";
|
|
|
|
|
|
|
|
my $req = HTTP::Request->new(GET => $server_endpoint);
|
|
|
|
my $resp = $ua->request($req);
|
|
|
|
|
|
|
|
if ($resp->is_success) {
|
|
|
|
$ipaddr = $resp->decoded_content;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $ipaddr;
|
|
|
|
}
|
2016-02-10 19:04:14 +00:00
|
|
|
|
2016-02-11 13:22:31 +00:00
|
|
|
# As the name implies, just your average mysql count query
|
|
|
|
sub countQuery {
|
|
|
|
my $table = shift;
|
|
|
|
my $count = 0;
|
|
|
|
|
|
|
|
my $sql = "select count(*) from ?";
|
|
|
|
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
|
|
|
|
$count = $sth->execute( $table ) or die( "Can't execute: ".$sth->errstr() );
|
|
|
|
|
|
|
|
return $count
|
|
|
|
}
|
|
|
|
|