[pmg-devel] [PATCH pmg-api 1/3] close #1917: add pmg-system-report command

Stoiko Ivanov s.ivanov at proxmox.com
Fri Feb 8 12:35:46 CET 2019


pmg-system-report gathers information about a PMG installation, like
pvereport does for PVE.

The name was chosen because pmgreport is already taken (for the daily
reportmails).

The DNS resolution check uses SpamAssassin's internal DnsResolver, since
SpamAssassin has a few pecularities, e.g. only using the first entry in
/etc/resolv.conf - see [0] and Mail::SpamAssassin::DnsResolver and
spam-detection is abysmal if SpamAssassin cannot resolve RBL-entries.
The SpamAssassin initialization is taken from pmg-smtp-filter (except that
local_tests_only is unconditionally disabled (otherwise it would not do DNS
Resolution).

[0] https://wiki.apache.org/spamassassin/DnsBlocklists

Signed-off-by: Stoiko Ivanov <s.ivanov at proxmox.com>
---
 PMG/Report.pm         | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++
 bin/pmg-system-report |  23 +++++++++
 2 files changed, 156 insertions(+)
 create mode 100644 PMG/Report.pm
 create mode 100755 bin/pmg-system-report

diff --git a/PMG/Report.pm b/PMG/Report.pm
new file mode 100644
index 0000000..0fe742b
--- /dev/null
+++ b/PMG/Report.pm
@@ -0,0 +1,133 @@
+package PMG::Report;
+
+use strict;
+use warnings;
+use PVE::Tools;
+use Mail::SpamAssassin::DnsResolver;
+
+$ENV{'PATH'} = '/sbin:/bin:/usr/sbin:/usr/bin';
+
+my $cmd_timeout = 10; # generous timeout
+
+# NOTE: always add new sections to the report_order array!
+my $report_def = {
+    general => {
+	title => 'general system info',
+	cmds => [
+	    'hostname',
+	    'pmgversion --verbose',
+	    'cat /etc/hosts',
+	    'cat /etc/resolv.conf',
+	    'top -b -n 1  | head -n 15',
+	    'pmgsubscription get',
+	    sub { check_dns_resolution() },
+	],
+    },
+    storage => [
+	'cat /etc/fstab',
+	'findmnt --ascii',
+	'df --human',
+	'lsblk --ascii',
+    ],
+    network => [
+	'ip -details -statistics address',
+	'cat /etc/network/interfaces',
+    ],
+    firewall => [
+	'iptables-save',
+    ],
+    cluster => [
+	'pmgcm status',
+    ],
+    pmg => [
+	'pmgconfig dump',
+	sub { dir2text('/etc/pmg/','(?:domains|mynetworks|tls_policy|transport)' ) },
+	sub { dir2text('/etc/pmg/templates/', '[^.].*' ) },
+	'pmgdb dump',
+    ],
+};
+
+my @report_order = ('general', 'storage', 'network', 'firewall', 'cluster', 'pmg');
+
+my $report = '';
+
+# output the content of all the files of a directory
+sub dir2text {
+    my ($target_dir, $regexp) = @_;
+
+    PVE::Tools::dir_glob_foreach($target_dir, $regexp, sub {
+	my ($file) = @_;
+	$report .=  "\n# cat $target_dir$file\n";
+	$report .= PVE::Tools::file_get_contents($target_dir.$file)."\n";
+    });
+}
+
+# command -v is the posix equivalent of 'which'
+sub cmd_exists { system("command -v '$_[0]' > /dev/null 2>&1") == 0 }
+
+sub generate {
+
+    my $record_output = sub {
+	$report .= shift . "\n";
+    };
+
+    my $run_cmd_params = {
+	outfunc => $record_output,
+	errfunc => $record_output,
+	timeout => $cmd_timeout,
+	noerr => 1, # avoid checking programs exit code
+    };
+
+    foreach my $section (@report_order) {
+	my $s = $report_def->{$section};
+
+	my $title = "info about $section";
+	my $commands = $s;
+
+	if (ref($s) eq 'HASH') {
+	    $commands = $s->{cmds};
+	    $title = $s->{title} if defined($s->{title});
+	} elsif (ref($s) ne 'ARRAY') {
+	    die "unknown report definition in section '$section'!";
+	}
+
+	$report .= "\n==== $title ====\n";
+	foreach my $command (@$commands) {
+	    eval {
+		if (ref $command eq 'CODE') {
+		    PVE::Tools::run_with_timeout($cmd_timeout, $command);
+		} else {
+		    $report .= "\n# $command\n";
+		    PVE::Tools::run_command($command, %$run_cmd_params);
+		}
+	    };
+	    $report .= "\nERROR: $@\n" if $@;
+	}
+    }
+
+    return $report;
+}
+
+# using SpamAssassin's resolver, since the SA configuration can change which
+# resolver is used and it uses only one resolver.
+sub check_dns_resolution {
+
+    my $sa = Mail::SpamAssassin->new ({
+	debug => 0,
+	local_tests_only => 0,
+	home_dir_for_helpers => '/root',
+	userstate_dir => '/root/.spamassassin',
+	dont_copy_prefs   => 1,
+	stop_at_threshold => 0,
+    });
+    $sa->init();
+
+    my $packet = $sa->{resolver}->send('www.proxmox.com');
+    my $answer = $packet->{answer}->[0];
+    my $answertext = defined($answer) ? $answer->plain() : 'NXDOMAIN';
+
+    $report .= "\n# resolve www.proxmox.com\n";
+    $report .= $answertext . "\n";
+}
+
+1;
diff --git a/bin/pmg-system-report b/bin/pmg-system-report
new file mode 100755
index 0000000..5618448
--- /dev/null
+++ b/bin/pmg-system-report
@@ -0,0 +1,23 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use PMG::Report;
+
+($> == 0 ) || die "please run as root\n";
+
+print PMG::Report::generate();
+
+__END__
+
+=head1 NAME
+
+pmg-system-report - Proxmox MailGateway system report tool
+
+=head1 SYNOPSIS
+
+pvereport
+
+=head1 DESCRIPTION
+
+Display various information related to a Proxmox MailGateway system
-- 
2.11.0




More information about the pmg-devel mailing list