From 14d9d66529bcec2a9f2963a31df09d3eb1e196d1 Mon Sep 17 00:00:00 2001 From: Tony Murray Date: Sun, 8 Oct 2023 18:37:33 -0500 Subject: [PATCH] Agent: Packages fixes (+pacman) (#15415) * Agent: Packages fixes Don't try to save invalid packages, probably due to script failure on device. Add pacman support * Apply fixes from StyleCI * Add version * cast to number * Update includes/polling/unix-agent/packages.inc.php Co-authored-by: Jellyfrog --------- Co-authored-by: StyleCI Bot Co-authored-by: Jellyfrog --- LibreNMS/Util/Number.php | 13 ++++++++++++ app/Models/Package.php | 5 +++++ includes/polling/unix-agent/dmi.inc.php | 6 ++++-- includes/polling/unix-agent/packages.inc.php | 21 ++++++++++++++++++++ 4 files changed, 43 insertions(+), 2 deletions(-) diff --git a/LibreNMS/Util/Number.php b/LibreNMS/Util/Number.php index 078d0a41c5..a0a6541f18 100644 --- a/LibreNMS/Util/Number.php +++ b/LibreNMS/Util/Number.php @@ -86,6 +86,19 @@ class Number return self::cast(number_format(round($value, $round), $sf, '.', '')) . " $ext$suffix"; } + /** + * Convert an Si or Bi formatted value to bytes (or bits) + */ + public static function toBytes(string $formatted): int|float + { + preg_match('/^([\d.]+)([KMGTPEZY]?)(\w?)\w?$/', $formatted, $matches); + [, $number, $magnitude, $baseIndicator] = $matches; + $base = $baseIndicator == 'i' ? 1024 : 1000; + $exponent = ['K' => 1, 'M' => 2, 'G' => 3, 'T' => 4, 'P' => 5, 'E' => 6, 'Z' => 7, 'Y' => 8]; + + return self::cast($number) * pow($base, $exponent[$magnitude] ?? 0); + } + /** * Cast string to int or float. * Returns 0 if string is not numeric diff --git a/app/Models/Package.php b/app/Models/Package.php index 582e6b91a9..b4e552e697 100644 --- a/app/Models/Package.php +++ b/app/Models/Package.php @@ -50,4 +50,9 @@ class Package extends DeviceRelatedModel implements Keyable { return $this->name . ' (' . $this->arch . ') version ' . $this->version . ($this->build ? "-$this->build" : ''); } + + public function isValid(): bool + { + return $this->name && $this->manager && $this->arch && $this->version; + } } diff --git a/includes/polling/unix-agent/dmi.inc.php b/includes/polling/unix-agent/dmi.inc.php index cdaca547e1..ffec1c581a 100644 --- a/includes/polling/unix-agent/dmi.inc.php +++ b/includes/polling/unix-agent/dmi.inc.php @@ -4,8 +4,10 @@ $dmi = $agent_data['dmi']; unset($agent_data['dmi']); foreach (explode("\n", $dmi) as $line) { - [$field,$contents] = explode('=', $line, 2); - $agent_data['dmi'][$field] = trim($contents); + if (str_contains($line, '=')) { + [$field,$contents] = explode('=', $line, 2); + $agent_data['dmi'][$field] = trim($contents); + } } unset($dmi); diff --git a/includes/polling/unix-agent/packages.inc.php b/includes/polling/unix-agent/packages.inc.php index b3da99276a..23093fdeab 100644 --- a/includes/polling/unix-agent/packages.inc.php +++ b/includes/polling/unix-agent/packages.inc.php @@ -38,6 +38,22 @@ $managers = [ ]); }, ], + 'pacman' => [ + 'name' => 'Pacman', + 'process' => function ($line) { + [$name, $version, $arch, $size] = explode(' ', $line); + + return new Package([ + 'manager' => 'pacman', + 'name' => $name, + 'arch' => $arch, + 'version' => $version, + 'build' => '', + 'size' => (int) \LibreNMS\Util\Number::toBytes($size), + 'status' => 1, + ]); + }, + ], ]; foreach ($managers as $key => $manager) { @@ -54,6 +70,11 @@ foreach ($managers as $key => $manager) { foreach (explode("\n", trim($agent_data[$key])) as $line) { /** @var \App\Models\Package $package */ $package = $manager['process']($line); + + if (! $package->isValid()) { + continue; // failed to parse + } + $package_key = $package->getCompositeKey(); if ($existing_package = $packages->get($package_key)) { $existing_package->fill($package->attributesToArray());