Vmware vminfo modernize (#15008)

* Vmware vminfo
Remove legacy file and migrate to OS discovery

* tighter

* ios_stp-vlans working correctly now

* Make vmwVmGuestOS nullable

* Discover os info too

* VM Info module

* Apply fixes from StyleCI

* Fix log severity

* Fix log severity (more)

* VM Info module

* Poll with ESXi too because it is lightweight
add test data

* poller data now too

---------

Co-authored-by: StyleCI Bot <bot@styleci.io>
This commit is contained in:
Tony Murray
2023-10-05 19:49:26 -05:00
committed by GitHub
parent bec7a9f449
commit 087d588102
38 changed files with 990 additions and 446 deletions

View File

@@ -25,9 +25,8 @@ namespace LibreNMS\OS;
use App\Models\Device;
use LibreNMS\Interfaces\Discovery\OSDiscovery;
use LibreNMS\OS;
class Beagleboard extends OS implements OSDiscovery
class Beagleboard extends Linux implements OSDiscovery
{
/**
* Retrieve basic information about the OS / device

54
LibreNMS/OS/Linux.php Normal file
View File

@@ -0,0 +1,54 @@
<?php
/*
* Linux.php
*
* -Description-
*
* 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 3 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 program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2023 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace LibreNMS\OS;
use Illuminate\Support\Collection;
use LibreNMS\Interfaces\Discovery\VminfoDiscovery;
use LibreNMS\OS\Traits\VminfoLibvirt;
use LibreNMS\OS\Traits\VminfoVmware;
class Linux extends Shared\Unix implements VminfoDiscovery
{
// NOTE: Only Linux specific stuff should go here, most things should be in Unix
use VminfoLibvirt, VminfoVmware {
VminfoLibvirt::discoverVminfo as discoverLibvirtVminfo;
VminfoVmware::discoverVmInfo as discoverVmwareVminfo;
}
public function discoverVmInfo(): Collection
{
$vms = $this->discoverLibvirtVminfo();
if ($vms->isNotEmpty()) {
return $vms;
}
echo PHP_EOL;
return $this->discoverVmwareVminfo();
}
}

View File

@@ -0,0 +1,166 @@
<?php
/*
* VminfoLibvirt.php
*
* -Description-
*
* 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 3 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 program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2023 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace LibreNMS\OS\Traits;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use LibreNMS\Config;
use LibreNMS\Enum\PowerState;
trait VminfoLibvirt
{
public function discoverVminfo(): Collection
{
echo 'LibVirt VM: ';
if (! Config::get('enable_libvirt')) {
echo 'not configured';
}
$vms = new Collection;
$ssh_ok = 0;
$userHostname = $this->getDevice()->hostname;
if (Config::has('libvirt_username')) {
$userHostname = Config::get('libvirt_username') . '@' . $userHostname;
}
foreach (Config::get('libvirt_protocols') as $method) {
if (Str::contains($method, 'qemu')) {
$uri = $method . '://' . $userHostname . '/system';
} else {
$uri = $method . '://' . $userHostname;
}
if (Str::contains($method, 'ssh') && ! $ssh_ok) {
// Check if we are using SSH if we can log in without password - without blocking the discovery
// Also automatically add the host key so discovery doesn't block on the yes/no question, and run echo so we don't get stuck in a remote shell ;-)
exec('ssh -o "StrictHostKeyChecking no" -o "PreferredAuthentications publickey" -o "IdentitiesOnly yes" ' . $userHostname . ' echo -e', $out, $ret);
if ($ret != 255) {
$ssh_ok = 1;
}
}
if ($ssh_ok || ! Str::contains($method, 'ssh')) {
// Fetch virtual machine list
unset($domlist);
exec(Config::get('virsh') . ' -rc ' . $uri . ' list', $domlist);
foreach ($domlist as $dom) {
[$dom_id] = explode(' ', trim($dom), 2);
if (is_numeric($dom_id)) {
// Fetch the Virtual Machine information.
unset($vm_info_array);
exec(Config::get('virsh') . ' -rc ' . $uri . ' dumpxml ' . $dom_id, $vm_info_array);
// Example xml:
// <domain type='kvm' id='3'>
// <name>moo.example.com</name>
// <uuid>48cf6378-6fd5-4610-0611-63dd4b31cfd6</uuid>
// <memory>1048576</memory>
// <currentMemory>1048576</currentMemory>
// <vcpu>8</vcpu>
// <os>
// <type arch='x86_64' machine='pc-0.12'>hvm</type>
// <boot dev='hd'/>
// </os>
// <features>
// <acpi/>
// (...)
// See spec at https://libvirt.org/formatdomain.html
// Convert array to string
$vm_info_xml = implode($vm_info_array);
$xml = simplexml_load_string('<?xml version="1.0"?> ' . $vm_info_xml);
Log::debug($xml);
// libvirt does not supply this
exec(Config::get('virsh') . ' -rc ' . $uri . ' domstate ' . $dom_id, $vm_state);
$vmwVmState = PowerState::STATES[strtolower($vm_state[0])] ?? PowerState::UNKNOWN;
$vmwVmMemSize = $xml->memory;
// Convert memory size to MiB
switch ($xml->memory['unit']) {
case 'T':
case 'TiB':
$vmwVmMemSize = $xml->memory * 1048576;
break;
case 'TB':
$vmwVmMemSize = $xml->memory * 1000000;
break;
case 'G':
case 'GiB':
$vmwVmMemSize = $xml->memory * 1024;
break;
case 'GB':
$vmwVmMemSize = $xml->memory * 1000;
break;
case 'M':
case 'MiB':
break;
case 'MB':
$vmwVmMemSize = $xml->memory * 1000000 / 1048576;
break;
case 'KB':
$vmwVmMemSize = $xml->memory / 1000;
break;
case 'b':
case 'bytes':
$vmwVmMemSize = $xml->memory / 1048576;
break;
default:
// KiB or k or no value
$vmwVmMemSize = $xml->memory / 1024;
break;
}
// Save the discovered Virtual Machine.
$vms->push(new \App\Models\Vminfo([
'vmtype' => 'libvirt',
'vmwVmVMID' => $dom_id,
'vmwVmState' => $vmwVmState,
'vmwVmGuestOS' => '',
'vmwVmDisplayName' => $xml->name,
'vmwVmMemSize' => $vmwVmMemSize,
'vmwVmCpus' => $xml->vcpu['current'] ?? $xml->vcpu,
]));
}
}
}
// If we found VMs, don't cycle the other protocols anymore.
if ($vms->isNotEmpty()) {
break;
}
}
return $vms;
}
}

View File

@@ -0,0 +1,67 @@
<?php
/*
* VminfoVmware.php
*
* -Description-
*
* 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 3 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 program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2023 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace LibreNMS\OS\Traits;
use App\Models\Vminfo;
use Illuminate\Support\Collection;
use LibreNMS\Enum\PowerState;
trait VminfoVmware
{
public function discoverVmInfo(): Collection
{
echo 'VMware VM: ';
/*
* Fetch the Virtual Machine information.
*
* VMWARE-VMINFO-MIB::vmwVmDisplayName.224 = STRING: My First VM
* VMWARE-VMINFO-MIB::vmwVmGuestOS.224 = STRING: windows7Server64Guest
* VMWARE-VMINFO-MIB::vmwVmMemSize.224 = INTEGER: 8192 megabytes
* VMWARE-VMINFO-MIB::vmwVmState.224 = STRING: poweredOn
* VMWARE-VMINFO-MIB::vmwVmVMID.224 = INTEGER: 224
* VMWARE-VMINFO-MIB::vmwVmCpus.224 = INTEGER: 2
*/
$vm_info = \SnmpQuery::hideMib()->walk('VMWARE-VMINFO-MIB::vmwVmTable');
return $vm_info->mapTable(function ($data, $vmwVmVMID) {
$data['vm_type'] = 'vmware';
$data['vmwVmVMID'] = $vmwVmVMID;
$data['vmwVmState'] = PowerState::STATES[$data['vmwVmState']] ?? PowerState::UNKNOWN;
/*
* If VMware Tools is not running then don't overwrite the GuestOS with the error
* message, but just leave it as it currently is.
*/
if (str_contains($data['vmwVmGuestOS'], 'tools not ')) {
unset($data['vmwVmGuestOS']);
}
return new Vminfo($data);
});
}
}

View File

@@ -0,0 +1,46 @@
<?php
/**
* VmwareEsxi.php
*
* -Description-
*
* 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 3 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 program. If not, see <https://www.gnu.org/licenses/>.
*
* @link https://www.librenms.org
*
* @copyright 2023 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace LibreNMS\OS;
use Illuminate\Support\Collection;
use LibreNMS\Interfaces\Discovery\VminfoDiscovery;
use LibreNMS\Interfaces\Polling\VminfoPolling;
use LibreNMS\OS\Traits\VminfoVmware;
class VmwareEsxi extends \LibreNMS\OS implements VminfoDiscovery, VminfoPolling
{
use VminfoVmware;
public function pollVminfo(Collection $vms): Collection
{
// no VMs, assume there aren't any
if ($vms->isEmpty()) {
return $vms;
}
return $this->discoverVmInfo(); // just do the same thing as discovery.
}
}