#!perl

=head1 NAME

hv_monitor - LibreNMS style JSON SNMP extend for hypervisor monitoring.

=head1 SYNOPSIS

hv_monitor [B<-c>] [B<-b> <backend>]

=head1 DESCRIPTION

For cron...

    */5 * * * * /usr/local/bin/hv_monitor -q

For snmpd...

    extend hv-monitor /bin/cat /var/cache/hv_monitor.json.snmp

=head1 FLAGS

=head2 -b <backend>

The backend to use.

Defaults are as below.

    FreeBSD: CBSD
    Linux: Libvirt

=head2 -c

Compress the output using gzip and base64 encoded so it
can be transmitted via SNMP with out issue.

This only reflects what is printed to STDOUT.

/var/cache/hv_monitor.json.snmp will always be created
as base64 encoded gzipped JSON.

=head2 -w

Write the data out to files as well.

Raw JSON: /var/cache/hv_monitor.json
For SNMP: /var/cache/hv_monitor.json.snmp

=head2 -o

Base file path to use to with -w.

".snmp" will be appended to this for the file containing the
SNMP return data.

Default: /var/cache/hv_monitor.json

=head2 -q

If combined with -w, this won't print the results.

Error messages will still be printed.

If not used with -w, this will error out.

=cut

use JSON qw( encode_json );
use strict;
use warnings;
use Getopt::Long qw( GetOptions );
use HV::Monitor;
use MIME::Base64       qw( encode_base64 );
use IO::Compress::Gzip qw(gzip $GzipError);
use Pod::Usage         qw( pod2usage );
use File::Slurp;

sub version {
	print 'hv_monitor v. ' . $HV::Monitor::VERSION . "\n";
}

my $backend;
if ( $^O eq 'freebsd' ) {
	$backend = 'CBSD';
} elsif ( $^O eq 'linux' ) {
	$backend = 'Libvirt';
}

# get the commandline options
my $help             = 0;
my $version          = 0;
my $compress         = 0;
my $output_file_base = '/var/cache/hv_monitor.json';
my $quiet;
my $write;
Getopt::Long::Configure('no_ignore_case');
Getopt::Long::Configure('bundling');
GetOptions(
	'version' => \$version,
	'v'       => \$version,
	'help'    => \$help,
	'h'       => \$help,
	'b=s'     => \$backend,
	'c'       => \$compress,
	'q'       => \$quiet,
	'w'       => \$write,
	'o'       => \$output_file_base,
);

if ($version) {
	print 'hv_monitor v. ' . $HV::Monitor::VERSION . "\n";
	exit 255;
}

if ($help) {
	pod2usage( -exitval => 255, -verbose => 2, -output => \*STDOUT, );
	exit 255;
}

if ( $quiet && !$write ) {
	die('-q must by used with -w');
}

my $hm = HV::Monitor->new( { backend => $backend } );

eval { $hm->load; };
if ($@) {
	print encode_json( { version => 1, data => {}, error => 1, errorString => 'load failed... ' . $@ } ) . "\n";
	exit 1;
}

my $data = encode_json( $hm->run );

if ( !$compress && !$quiet ) {
	print $data. "\n";
}

# compress and write to the cache file for it
my $compressed_string;
gzip \$data => \$compressed_string;
my $compressed = encode_base64($compressed_string);
$compressed =~ s/\n//g;
$compressed = $compressed . "\n";
if ( !$quiet ) {
	print $compressed;
}

if ($write) {
	write_file( $output_file_base . '.snmp', $compressed );
	write_file( $output_file_base,           $data );
}
