97 lines
2.6 KiB
Perl
97 lines
2.6 KiB
Perl
package PVE::PVEMod::Collector::SystemInformation;
|
|
|
|
use strict;
|
|
use warnings;
|
|
use Exporter 'import';
|
|
|
|
use PVE::PVEMod::Config qw(%config);
|
|
use PVE::PVEMod::Utils qw(debug);
|
|
|
|
our @EXPORT_OK = qw(
|
|
get_system_information_data
|
|
);
|
|
|
|
# ============================================================================
|
|
# System Information — one-time dmidecode call
|
|
# ============================================================================
|
|
|
|
sub get_system_information_data {
|
|
unless ($config{system_info}{enabled}) {
|
|
debug(__LINE__, "System information collection is disabled");
|
|
return {};
|
|
}
|
|
|
|
my $raw_type = $config{system_info}{type};
|
|
|
|
# Taint-safe: only allow type 1 (System) or 2 (Baseboard/Motherboard)
|
|
my $type;
|
|
if (defined $raw_type && $raw_type =~ /^([12])$/) {
|
|
$type = $1;
|
|
} else {
|
|
debug(__LINE__, "Invalid system_info type '${\($raw_type // 'undef')}', defaulting to 1");
|
|
$type = 1;
|
|
}
|
|
|
|
debug(__LINE__, "Collecting system information via dmidecode -t $type");
|
|
|
|
return _get_system_info($type);
|
|
}
|
|
|
|
# ============================================================================
|
|
# Internal — run dmidecode and parse output
|
|
# ============================================================================
|
|
|
|
sub _get_system_info {
|
|
my ($type) = @_;
|
|
|
|
my $output = `/usr/sbin/dmidecode -t $type 2>/dev/null`;
|
|
|
|
unless (defined $output && length($output) > 0) {
|
|
debug(__LINE__, "No output from dmidecode -t $type");
|
|
return {};
|
|
}
|
|
|
|
my %fields;
|
|
my @field_order;
|
|
|
|
for my $line (split /\n/, $output) {
|
|
if ($line =~ /^\s+(Manufacturer|Product Name|Serial Number):\s*(.+)$/) {
|
|
my ($key, $value) = ($1, $2);
|
|
$value =~ s/^\s+|\s+$//g;
|
|
|
|
my $field_key = lc($key);
|
|
$field_key =~ s/ /_/g;
|
|
|
|
unless (exists $fields{$field_key}) {
|
|
push @field_order, $field_key;
|
|
$fields{$field_key} = $value;
|
|
}
|
|
}
|
|
}
|
|
|
|
unless (%fields) {
|
|
debug(__LINE__, "No recognised fields found in dmidecode output");
|
|
return {};
|
|
}
|
|
|
|
# Build display string: "Manufacturer: X | Product Name: Y | Serial Number: Z"
|
|
my %pretty_key = (
|
|
manufacturer => 'Manufacturer',
|
|
product_name => 'Product Name',
|
|
serial_number => 'Serial Number',
|
|
);
|
|
|
|
my @parts;
|
|
for my $key (@field_order) {
|
|
my $label = $pretty_key{$key} // $key;
|
|
push @parts, "$label: $fields{$key}";
|
|
}
|
|
$fields{display_string} = join(' | ', @parts);
|
|
|
|
debug(__LINE__, "System information: $fields{display_string}");
|
|
|
|
return \%fields;
|
|
}
|
|
|
|
1;
|