#!/usr/bin/perl

# imvirt - I'm virtualized?
#
# $Id: imvirt-report 605 2012-05-17 18:28:34Z liske $
#
# Authors:
#   Thomas Liske <liske@ibh.de>
#
# Copyright Holder:
#   2012 (C) IBH IT-Service GmbH [http://www.ibh.de/]
#
# License:
#   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 package; if not, write to the Free Software
#   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
#

use strict;
use warnings;
use MIME::Lite;
use ImVirt;

$|++;

eval 'use File::Which;';
my $nowhich = $@;


print <<EOH;
This script collects data about the running system (i.e. CPU, DMI table,
content of various files from /proc or /sys). This might help to improve
the heuristic of imvirt on detecting virtualization containers in future
releases.

This script will ask you for each dataset which is collected. Before
sending any data, you will be able to review the collection. You need a
working e-mail setup to be able to send the report.
EOH


my $from;
print <<FROM;

Please provide an email address which might be used by the author of
imvirt to get in contact with you if there are any queries or
uncertainness about your setup (you might leave it blank):
FROM
chomp($from = <STDIN>);


my $comment;
do {
    print <<CMT;

Please provide a short but complete description of your virtualization
setup (i.e. VMware ESXi 5.0 U1):
CMT

    chomp($comment = <STDIN>);
} while(length($comment) < 3);


my $qa;
do {
    print <<QA;

Would you like to be asked for each dataset which is to be collected
(saying no will skip any further confirmation except the data review)? [Y/n]
QA

    chomp($qa = <STDIN>);
} while(!($qa =~ /^[yn]?$/i));

$qa = (lc($qa) ne 'n' ? 1 : 0);


my $to = 'imvirt-report@lists.sourceforge.net';
my $hostname = `hostname -f`;
chomp($hostname);
my $ivout = imv_get(IMV_PROB_DEFAULT);

my $msg = MIME::Lite->new(
    To		=> $to,
    From	=> $from,
    Subject	=> $hostname,
    Type	=> 'multipart/mixed',
);

$msg->attach(
    Type	=> 'TEXT',
    Data	=> "Hostname: $hostname\nImVirt Version: $ImVirt::VERSION\nImVirt Output: $ivout\nUser Comment: $comment\n",
);

sub attach_path($$) {
    my ($msg, $glob) = @_;

    foreach my $path (glob $glob) {
	my $fn = $path;
	$fn =~ s@/@_@g;

	unless (-r $path) {
	    $msg->attach(
		Type => 'TEXT',
		Data => "File $path not readable!",
		Filename => $fn,
	    );
	}
	else {
	    my $allow = 1;
	    if($qa) {
		my $q;
		do {
		    print "Attach the content of '$path'? [Y/n]: ";
		    chomp($q = <STDIN>);
		} while(!($q =~ /^[yn]?$/i));
		$allow = (lc($q) ne 'n');
	    }

	    if ($allow) {
		print " Attaching '$path'.\n";
		$msg->attach(
		    Type => 'TEXT',
		    Path => $path,
		    Filename => $fn,
		);
	    }
	}
    }
}

sub attach_cmd($$$) {
    my ($msg, $cmd, $params) = @_;
    my $run = ($nowhich ne '' ? $cmd : which($cmd));

    unless (defined($run)) {
	$msg->attach(
	    Type => 'TEXT',
	    Data => "Command $cmd not available!",
	    Filename => $cmd,
	);

	return;
    }

    my $allow = 1;
    if($qa) {
	my $q;
	do {
	    print "Attach the output of `$run $params`? [Y/n]: ";
	    chomp($q = <STDIN>);
	} while(!($q =~ /^[yn]?$/i));
	$allow = (lc($q) ne 'n');
    }

    if ($allow) {
	print " Attaching `$cmd $params`.\n";
	$msg->attach(
	    Type => 'TEXT',
	    Data => scalar `$run $params 2>&1`,
	    Filename => $cmd,
	);
    }
}

attach_path($msg, '/proc/1/cgroup');
attach_path($msg, '/proc/1/environ');
attach_path($msg, '/proc/cmdline');
attach_path($msg, '/proc/cpuinfo');
attach_path($msg, '/proc/mounts');
attach_path($msg, '/proc/modules');
attach_path($msg, '/proc/bus/input/devices');
attach_path($msg, '/sys/devices/system/clocksource/clocksource*/available_clocksource');
attach_path($msg, '/sys/devices/system/cpu/cpu*/cpufreq/scaling_driver');
attach_path($msg, '/var/log/dmesg');

attach_cmd($msg, 'dmesg', '');
attach_cmd($msg, 'dmidecode', '');
attach_cmd($msg, 'find', '/dev');
attach_cmd($msg, 'find', '/proc');
attach_cmd($msg, 'find', '/sys');
attach_cmd($msg, 'imvirt', '-d');
attach_cmd($msg, 'lsb_release', '-a');
attach_cmd($msg, 'lspci', '');
attach_cmd($msg, 'uname', '-a');

my $spager;
do {
    print <<PAGER;

Would you like to review the data? [Y/n]
PAGER

    chomp($spager = <STDIN>);
} while(!($spager =~ /^[yn]?$/i));

if(lc($spager) ne 'n') {
    my $tempfile = `mktemp --tmpdir imvirt.XXXXXXXXXX`;
    open(HTEMP, '>', $tempfile) || die;
    $msg->print(\*HTEMP);
    close(HTEMP);

    my $pager = ($nowhich ne '' ? ($ENV{PAGER} || 'less') : which( ($ENV{PAGER} || 'less') ));
    system($pager, $tempfile);
    unlink($tempfile);
}

my $send;
do {
    print <<SEND;

Would you like to send this data? You need to have a working MTA
configuration on this host. You might say 'n' to forbid
imvirt-report to send any data or send it yourself. [y/n]
SEND

    chomp($send = <STDIN>);
} while(!($send =~ /^[yn]$/i));

if(lc($send) eq 'y') {
    $msg->send() unless($msg->last_send_successful());

    die "Sorry, failed to send mail!\n" unless($msg->last_send_successful());

    print <<THX;

The report has been send, thank you for contribution!

THX
}
else {
    my $save;
    print <<SAVE;

Please enter a filename to save the data to. You might send the file
to $to by yourself.
Filename: [imvirt-report_${hostname}_$$.eml]
SAVE

    chomp($save = <STDIN>);
    $save = "imvirt-report_${hostname}_$$.eml" if($save eq '');

    open(HSAVE, '>', $save) || die;
    $msg->print(\*HSAVE);
    close(HSAVE);

    print <<SAVED;

Data saved to '$save'.

SAVED
}
