<# hvvmbase.ps1 Written by Eric Siron (c) Altaro Software 2017 Version 1.0.2 May 24, 2017 Intended for use with the NSClient++ module from http://nsclient.org Provides reusable functions for other check scripts. #> if(-not $HVVMBaseIncluded) { $HVVMBaseIncluded = $true $UtilityBase = Join-Path -Path $PSScriptRoot -ChildPath 'anutilitybase.ps1' if(-not (Test-Path -Path $UtilityBase)) { Write-Host ('Required file {0} not found' -f $UtilityBase) exit 3 } . $UtilityBase function Get-ANVMBaseVersion { New-Object System.Version(1, 0, 2, 0) } function Get-ANVMsAll { param( [Parameter()][String]$ComputerName = $env:COMPUTERNAME ) Get-WmiObject -Namespace root\virtualization\v2 -Class Msvm_ComputerSystem -ComputerName $ComputerName } function Get-ANVMWmiObjectFromComputer { param( [Parameter(Position=1)][String]$ComputerName, [Parameter(ParameterSetName='By Name', Position=2)][String]$VMName, [Parameter(ParameterSetName='By ID')][String]$VMID ) if($VMName) { $Filter = 'ElementName="{0}"' -f $VMName } elseif($VMID) { $Filter = 'Name="{0}"' -f $VMID } else { return } $GWMIParams = @{Namespace = 'root\virtualization\v2'; Class = 'Msvm_ComputerSystem'; Filter = $Filter; ErrorAction = ([System.Management.Automation.ActionPreference]::SilentlyContinue) } if($ComputerName -and $ComputerName -ne $env:COMPUTERNAME) { $GWMIParams.Add('ComputerName', $ComputerName) } Get-WmiObject @GWMIParams # -ComputerName $ComputerName -Namespace 'root\virtualization\v2' -Class 'Msvm_ComputerSystem' -Filter $Filter -ErrorAction SilentlyContinue } # will find ANY VM on the local host and any HA VM in the same cluster. will NOT find non-HA VMs on other nodes # if multiple VMs have the same name, will return whichever one that it wants to. I'm not sure how it decides. #sorrynotsorry function Get-ANVMWmiObject { param( [Parameter(Position=1)][String]$VMName ) if(-not $VMName) { Write-Host 'No virtual machine name was supplied' Exit 2 } # look locally first $VM = Get-ANVMWmiObjectFromComputer -ComputerName '.' -VMName $VMName if((-not $VM) -band (ANIsClustered)) { $VMsOnOtherHosts = Get-WmiObject -Namespace root\MSCluster -Class MSCluster_Resource -Property OwnerNode, Id -Filter ('Type="Virtual Machine" AND NOT OwnerNode="{0}"' -f $env:COMPUTERNAME) $ClusterKey = $null try { $ClusterKey = [Microsoft.Win32.RegistryKey]::OpenBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine, [Microsoft.Win32.RegistryView]::Default) } catch [System.Security.SecurityException], [System.UnauthorizedAccessException] { Write-Host ('NSClient++ user "{0}" cannot access the registry on "{1}"' -f $env:USERNAME, $OtherHostVM.OwnerNode, $env:COMPUTERNAME) Exit 2 } catch { Write-Host ('Could not open registry on "{0}": {1}' -f $env:COMPUTERNAME, $_) Exit 2 } foreach($OtherHostVM in $VMsOnOtherHosts) { try { $Subkey = $ClusterKey.OpenSubKey(('Cluster\Resources\{0}\Parameters' -f $OtherHostVM.Id), $false) $VMId = $Subkey.GetValue('VmID') } catch { Write-Host ('Could not open a cluster parameters key on "{0}": {1}' -f $env:COMPUTERNAME, $_) Exit 2 } $Subkey.Close() $VM = Get-ANVMWmiObjectFromComputer -ComputerName $OtherHostVM.OwnerNode -VMID $VMId if($VM -ne $null -and $VM.ElementName -eq $VMName) { break } else { $VM = $null } } } if(-not $VM) { Write-Host ('Virtual machine "{0}" could not be found!' -f $VMName) Exit 2 } $VM } function Get-ANVMIsClustered { param([Parameter(Position=1)][System.Management.ManagementObject]$VM) $IsClustered = $false $VMHostData = $VM.GetRelated('Msvm_VirtualSystemSettingData').GetRelated('Msvm_KvpExchangeComponentSettingData').HostOnlyItems foreach ($XMLKVPItem in $VMHostData) { $KVPKey = ([XML]$XMLKVPItem).SelectSingleNode('/INSTANCE/PROPERTY[@NAME=''Name'']/VALUE/child::text()').Value if($KVPKey -eq 'VirtualMachineIsClustered') { $KVPValue = ([XML]$XMLKVPItem).SelectSingleNode('/INSTANCE/PROPERTY[@NAME=''Data'']/VALUE/child::text()').Value $IsClustered = $KVPValue -eq 'TRUE' } } $IsClustered } }