2011-04-06 15:25:35 +00:00
< ? php
2017-09-11 15:26:41 -05:00
use LibreNMS\Config ;
2012-05-25 12:24:34 +00:00
// FIXME should do the deletion etc in a common file perhaps? like for the sensors
2015-07-13 20:10:26 +02:00
// Try to discover Libvirt Virtual Machines.
2017-09-11 15:26:41 -05:00
if ( Config :: get ( 'enable_libvirt' ) && $device [ 'os' ] == 'linux' ) {
2015-07-13 20:10:26 +02:00
$libvirt_vmlist = array ();
2011-04-06 15:25:35 +00:00
2015-07-13 20:10:26 +02:00
$ssh_ok = 0 ;
2011-04-06 15:25:35 +00:00
2016-01-09 14:20:57 +01:00
$userHostname = $device [ 'hostname' ];
2017-09-11 15:26:41 -05:00
if ( Config :: has ( 'libvirt_username' )) {
$userHostname = Config :: get ( 'libvirt_username' ) . '@' . $userHostname ;
2016-01-09 14:20:57 +01:00
}
2017-09-11 15:26:41 -05:00
foreach ( Config :: get ( 'libvirt_protocols' ) as $method ) {
if ( str_contains ( $method , 'qemu' )) {
2016-01-09 14:20:57 +01:00
$uri = $method . '://' . $userHostname . '/system' ;
2016-08-28 12:32:58 -05:00
} else {
2016-01-09 14:20:57 +01:00
$uri = $method . '://' . $userHostname ;
2015-07-13 20:10:26 +02:00
}
2011-04-10 19:56:24 +00:00
2017-09-11 15:26:41 -05:00
if ( str_contains ( $method , 'ssh' ) && ! $ssh_ok ) {
2015-07-13 20:10:26 +02:00
// 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 ;-)
2016-01-09 14:20:57 +01:00
exec ( 'ssh -o "StrictHostKeyChecking no" -o "PreferredAuthentications publickey" -o "IdentitiesOnly yes" ' . $userHostname . ' echo -e' , $out , $ret );
2015-07-13 20:10:26 +02:00
if ( $ret != 255 ) {
$ssh_ok = 1 ;
2011-04-20 16:48:33 +00:00
}
}
2011-04-06 15:25:35 +00:00
2017-09-11 15:26:41 -05:00
if ( $ssh_ok || ! str_contains ( $method , 'ssh' )) {
2015-07-13 20:10:26 +02:00
// Fetch virtual machine list
unset ( $domlist );
2017-09-11 15:26:41 -05:00
exec ( Config :: get ( 'virsh' ) . ' -rc ' . $uri . ' list' , $domlist );
2015-07-13 20:10:26 +02:00
foreach ( $domlist as $dom ) {
list ( $dom_id ,) = explode ( ' ' , trim ( $dom ), 2 );
if ( is_numeric ( $dom_id )) {
// Fetch the Virtual Machine information.
unset ( $vm_info_array );
2017-09-11 15:26:41 -05:00
exec ( Config :: get ( 'virsh' ) . ' -rc ' . $uri . ' dumpxml ' . $dom_id , $vm_info_array );
2015-07-13 20:10:26 +02:00
2016-10-06 18:58:21 +02:00
// Example xml:
2015-07-13 20:10:26 +02:00
// <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/>
// (...)
2016-10-06 18:58:21 +02:00
// See spec at https://libvirt.org/formatdomain.html
2015-07-13 20:10:26 +02:00
// Convert array to string
unset ( $vm_info_xml );
foreach ( $vm_info_array as $line ) {
$vm_info_xml .= $line ;
}
$xml = simplexml_load_string ( '<?xml version="1.0"?> ' . $vm_info_xml );
2015-08-20 15:59:43 +02:00
d_echo ( $xml );
2015-07-13 20:10:26 +02:00
$vmwVmDisplayName = $xml -> name ;
$vmwVmGuestOS = '' ;
// libvirt does not supply this
2017-09-11 15:26:41 -05:00
exec ( Config :: get ( 'virsh' ) . ' -rc ' . $uri . ' domstate ' . $dom_id , $vm_state );
2015-07-13 20:10:26 +02:00
$vmwVmState = ucfirst ( $vm_state [ 0 ]);
2016-09-29 13:35:14 +02:00
2016-10-06 18:58:21 +02:00
$vmwVmCpus = $xml -> vcpu [ 'current' ];
if ( ! isset ( $vmwVmCpus )) {
2016-09-29 13:35:14 +02:00
$vmwVmCpus = $xml -> vcpu ;
}
2016-10-06 18:58:21 +02:00
$vmwVmMemSize = $xml -> memory ;
// Convert memory size to MiB
switch ( $vmwVmMemSize [ 'unit' ]) {
case 'T' :
case 'TiB' :
$vmwVmMemSize = $vmwVmMemSize * 1048576 ;
break ;
case 'TB' :
$vmwVmMemSize = $vmwVmMemSize * 1000000 ;
break ;
case 'G' :
case 'GiB' :
$vmwVmMemSize = $vmwVmMemSize * 1024 ;
break ;
case 'GB' :
$vmwVmMemSize = $vmwVmMemSize * 1000 ;
break ;
case 'M' :
case 'MiB' :
break ;
case 'MB' :
$vmwVmMemSize = $vmwVmMemSize * 1000000 / 1048576 ;
break ;
case 'KB' :
$vmwVmMemSize = $vmwVmMemSize / 1000 ;
break ;
case 'b' :
case 'bytes' :
$vmwVmMemSize = $vmwVmMemSize / 1048576 ;
break ;
default :
// KiB or k or no value
$vmwVmMemSize = $vmwVmMemSize / 1024 ;
break ;
}
2015-07-13 20:10:26 +02:00
// Check whether the Virtual Machine is already known for this host.
$result = dbFetchRow ( " SELECT * FROM `vminfo` WHERE `device_id` = ? AND `vmwVmVMID` = ? AND `vm_type` = 'libvirt' " , array ( $device [ 'device_id' ], $dom_id ));
if ( count ( $result [ 'device_id' ]) == 0 ) {
$inserted_id = dbInsert ( array ( 'device_id' => $device [ 'device_id' ], 'vm_type' => 'libvirt' , 'vmwVmVMID' => $dom_id , 'vmwVmDisplayName' => mres ( $vmwVmDisplayName ), 'vmwVmGuestOS' => mres ( $vmwVmGuestOS ), 'vmwVmMemSize' => mres ( $vmwVmMemSize ), 'vmwVmCpus' => mres ( $vmwVmCpus ), 'vmwVmState' => mres ( $vmwVmState )), 'vminfo' );
echo '+' ;
2017-02-14 00:32:02 +02:00
log_event ( " Virtual Machine added: $vmwVmDisplayName ( $vmwVmMemSize MB) " , $device , 'vm' , 3 , $inserted_id );
2016-08-28 12:32:58 -05:00
} else {
2015-07-13 20:10:26 +02:00
if ( $result [ 'vmwVmState' ] != $vmwVmState
|| $result [ 'vmwVmDisplayName' ] != $vmwVmDisplayName
|| $result [ 'vmwVmCpus' ] != $vmwVmCpus
|| $result [ 'vmwVmGuestOS' ] != $vmwVmGuestOS
|| $result [ 'vmwVmMemSize' ] != $vmwVmMemSize
) {
dbUpdate ( array ( 'vmwVmState' => mres ( $vmwVmState ), 'vmwVmGuestOS' => mres ( $vmwVmGuestOS ), 'vmwVmDisplayName' => mres ( $vmwVmDisplayName ), 'vmwVmMemSize' => mres ( $vmwVmMemSize ), 'vmwVmCpus' => mres ( $vmwVmCpus )), 'vminfo' , " device_id=? AND vm_type='libvirt' AND vmwVmVMID=? " , array ( $device [ 'device_id' ], $dom_id ));
echo 'U' ;
// FIXME eventlog
2016-08-28 12:32:58 -05:00
} else {
2015-07-13 20:10:26 +02:00
echo '.' ;
}
}
// Save the discovered Virtual Machine.
$libvirt_vmlist [] = $dom_id ;
} //end if
} //end foreach
} //end if
// If we found VMs, don't cycle the other protocols anymore.
if ( count ( $libvirt_vmlist )) {
break ;
}
} //end foreach
2011-04-06 15:25:35 +00:00
2015-07-13 20:10:26 +02:00
// Get a list of all the known Virtual Machines for this host.
$sql = " SELECT id, vmwVmVMID, vmwVmDisplayName FROM vminfo WHERE device_id = ' " . $device [ 'device_id' ] . " ' AND vm_type='libvirt' " ;
2011-04-06 15:25:35 +00:00
2015-07-13 20:10:26 +02:00
foreach ( dbFetchRows ( $sql ) as $db_vm ) {
// Delete the Virtual Machines that are removed from the host.
if ( ! in_array ( $db_vm [ 'vmwVmVMID' ], $libvirt_vmlist )) {
dbDelete ( 'vminfo' , '`id` = ?' , array ( $db_vm [ 'id' ]));
echo '-' ;
2017-02-14 00:32:02 +02:00
log_event ( 'Virtual Machine removed: ' . $db_vm [ 'vmwVmDisplayName' ], $device , 'vm' , 4 , $db_vm [ 'id' ]);
2015-07-13 20:10:26 +02:00
}
2011-04-06 15:25:35 +00:00
}
2015-07-13 20:10:26 +02:00
echo " \n " ;
} //end if