move systeminformation to api call in pvemodinstead of handling install script

This commit is contained in:
Meliox 2026-06-07 03:53:16 +02:00
parent d98916a2a5
commit 3bec403df5
4 changed files with 126 additions and 27 deletions

View File

@ -0,0 +1,96 @@
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;

View File

@ -60,6 +60,10 @@ our %config = (
enabled => 1, enabled => 1,
device_name => 'ups@192.168.3.2', device_name => 'ups@192.168.3.2',
}, },
system_info => {
enabled => 1,
type => 1, # 1 = System (dmidecode -t 1), 2 = Baseboard/Motherboard (dmidecode -t 2)
},
paths => { paths => {
working_dir => '/run/pveproxy/pve-mod', working_dir => '/run/pveproxy/pve-mod',
}, },

View File

@ -6,11 +6,13 @@ use warnings;
use PVE::PVEMod::Config qw(%config $VERSION $stats_dir $sensors_state_file $ups_state_file); use PVE::PVEMod::Config qw(%config $VERSION $stats_dir $sensors_state_file $ups_state_file);
use PVE::PVEMod::Utils qw(debug safe_read_json); use PVE::PVEMod::Utils qw(debug safe_read_json);
use PVE::PVEMod::ProcessManager qw(pve_mod_starter notify_pve_mod_worker); use PVE::PVEMod::ProcessManager qw(pve_mod_starter notify_pve_mod_worker);
use PVE::PVEMod::Collector::SystemInformation qw(get_system_information_data);
# Per-endpoint state caches (module-level, reset on worker restart) # Per-endpoint state caches (module-level, reset on worker restart)
my $graphics_cache = { data => {}, mtime => 0 }; my $graphics_cache = { data => {}, mtime => 0 };
my $sensors_cache = { data => '{}', mtime => 0 }; my $sensors_cache = { data => '{}', mtime => 0 };
my $ups_cache = { data => '{}', mtime => 0 }; my $ups_cache = { data => '{}', mtime => 0 };
my $system_info_cache = undef;
# ============================================================================ # ============================================================================
@ -197,5 +199,17 @@ sub get_pve_mod_version {
return $VERSION; return $VERSION;
} }
sub get_system_information {
debug(__LINE__, "get_system_information called");
if (defined $system_info_cache) {
debug(__LINE__, "Returning cached system information");
return $system_info_cache;
}
$system_info_cache = get_system_information_data();
return $system_info_cache;
}
1; 1;

View File

@ -526,7 +526,6 @@ function install_mod {
msgb "\n=== Installing sensor info module ===" msgb "\n=== Installing sensor info module ==="
install_sensor_monitor_module install_sensor_monitor_module
insert_sensor_monitor_into_pve insert_sensor_monitor_into_pve
insert_system_info_into_pve
## Historical GPU data ## ## Historical GPU data ##
if [[ "$ENABLE_GPU_HISTORY" == true ]]; then if [[ "$ENABLE_GPU_HISTORY" == true ]]; then
@ -607,6 +606,7 @@ install_sensor_monitor_module() {
"PVEMod_Collectors/LmSensors.pm:$PVEMOD_COLLECTOR_DIR/LmSensors.pm" "PVEMod_Collectors/LmSensors.pm:$PVEMOD_COLLECTOR_DIR/LmSensors.pm"
"PVEMod_Collectors/Amd.pm:$PVEMOD_COLLECTOR_DIR/Amd.pm" "PVEMod_Collectors/Amd.pm:$PVEMOD_COLLECTOR_DIR/Amd.pm"
"PVEMod_Collectors/Ups.pm:$PVEMOD_COLLECTOR_DIR/Ups.pm" "PVEMod_Collectors/Ups.pm:$PVEMOD_COLLECTOR_DIR/Ups.pm"
"PVEMod_Collectors/systemInformation.pm:$PVEMOD_COLLECTOR_DIR/SystemInformation.pm"
) )
for entry in "${module_files[@]}"; do for entry in "${module_files[@]}"; do
local src="$PVEMOD_SOURCES_DIR/${entry%%:*}" local src="$PVEMOD_SOURCES_DIR/${entry%%:*}"
@ -622,6 +622,8 @@ install_sensor_monitor_module() {
intel_enabled=$([[ "$ENABLE_INTEL_GPU_INFO" = true ]] && echo 1 || echo 0) intel_enabled=$([[ "$ENABLE_INTEL_GPU_INFO" = true ]] && echo 1 || echo 0)
nvidia_enabled=$([[ "$ENABLE_NVIDIA_GPU_INFO" = true ]] && echo 1 || echo 0) nvidia_enabled=$([[ "$ENABLE_NVIDIA_GPU_INFO" = true ]] && echo 1 || echo 0)
ups_enabled=$([[ "$ENABLE_UPS" = true ]] && echo 1 || echo 0) ups_enabled=$([[ "$ENABLE_UPS" = true ]] && echo 1 || echo 0)
system_info_enabled=$([[ "$ENABLE_SYSTEM_INFO" = true ]] && echo 1 || echo 0)
system_info_type="${SYSTEM_INFO_TYPE:-1}"
# Determine UPS device name # Determine UPS device name
local ups_device="${upsConnection:-ups@localhost}" local ups_device="${upsConnection:-ups@localhost}"
@ -633,6 +635,11 @@ install_sensor_monitor_module() {
/enabled =>/ s/=> [01],/=> $ups_enabled,/ /enabled =>/ s/=> [01],/=> $ups_enabled,/
/device_name =>/ s|=> '[^']*',|=> '$ups_device',| /device_name =>/ s|=> '[^']*',|=> '$ups_device',|
" "$PVEMOD_CONFIG_FILE" " "$PVEMOD_CONFIG_FILE"
# Patch system_info config block
sed -i "
/system_info/,/}/{/enabled =>/ s/=> [01],/=> $system_info_enabled,/}
/type[[:space:]]*=>/ s/=> [12],/=> $system_info_type,/
" "$PVEMOD_CONFIG_FILE"
if [[ $? -eq 0 ]]; then if [[ $? -eq 0 ]]; then
info "Config.pm patched successfully." info "Config.pm patched successfully."
@ -653,34 +660,12 @@ insert_sensor_monitor_into_pve() {
$res->{PveMod_JsonSensorInfo} = PVE::API2::PVEMod_SensorInfo::get_sensors_info();\ $res->{PveMod_JsonSensorInfo} = PVE::API2::PVEMod_SensorInfo::get_sensors_info();\
$res->{PveMod_graphicsInfo} = PVE::API2::PVEMod_SensorInfo::get_pve_mod_version();\ $res->{PveMod_graphicsInfo} = PVE::API2::PVEMod_SensorInfo::get_pve_mod_version();\
$res->{PveMod_upsInfo} = PVE::API2::PVEMod_SensorInfo::get_ups_info();\ $res->{PveMod_upsInfo} = PVE::API2::PVEMod_SensorInfo::get_ups_info();\
$res->{pveMod_sensorInfo_systemInfo} = PVE::API2::PVEMod_SensorInfo::get_system_information();\
' "$NODES_PM_FILE" ' "$NODES_PM_FILE"
#endregion PveSensorInfoMod heredoc #endregion PveSensorInfoMod heredoc
info "Sensor data retriever added to \"$NODES_PM_FILE\"." info "Sensor data retriever added to \"$NODES_PM_FILE\"."
} }
# Collect system information
insert_system_info_into_pve() {
local output_file="$1"
local systemInfoCmd
if [[ $ENABLE_SYSTEM_INFO == false ]]; then
return
fi
systemInfoCmd=$(dmidecode -t "${SYSTEM_INFO_TYPE}" \
| awk -F': ' '/Manufacturer|Product Name|Serial Number/ {print $1": "$2}' \
| awk '{$1=$1};1' \
| sed 's/$/ |/' \
| paste -sd " " - \
| sed 's/ |$//')
#region system info heredoc
sed -i "/my \$dinfo = df('\/', 1);/i\\
# Add system information to response\\
\$res->{pveMod_sensorInfo_systemInfo} = \"$(echo "$systemInfoCmd")\";\\
" "$NODES_PM_FILE"
#endregion system info heredoc
info "System information retriever added to \"$output_file\"."
}
#endregion node info insertion #endregion node info insertion
#region UI Module Installation #region UI Module Installation