<# hvdiskbase.ps1 Written by Eric Siron (c) Altaro Software 2017 Version 1.2.0 May 24, 2017 Intended for use with the NSClient++ module from http://nsclient.org Provides reusable functions for other check scripts. #> if(-not $HVDiskBaseIncluded) { $HVDiskBaseIncluded = $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 $VMBase = Join-Path -Path $PSScriptRoot -ChildPath 'hvvmbase.ps1' . $VMBase if(-not (Test-Path -Path $VMBase)) { Write-Host ('Required file {0} not found' -f $VMBase) exit 3 } $CurrentVMScriptVer = Get-ANVMBaseVersion $RequiredVMScriptVer = New-Object System.Version(1, 0, 2, 0) if($CurrentVMScriptVer -lt $RequiredVMScriptVer) { Write-Host ('Required VM base script version: {0}. Current version: {1}' -f $RequiredVMScriptVer, $CurrentVMScriptVer) exit(3) } function Get-ANDiskBaseVersion { New-Object System.Version(1, 2, 0, 0) } function Get-ANImageManagementService { param([Parameter(Position=1)][String]$ComputerName) if([String]::IsNullOrEmpty($ComputerName)) { $ComputerName = '.' } Get-WmiObject -ComputerName $ComputerName -Namespace root\virtualization\v2 -Class Msvm_ImageManagementService } function Get-ANVMDisk { param( [Parameter(Position=1)][String]$VMName = '', [Parameter(Position=2)][String]$ControllerType = 'i', [Parameter(Position=3)][UInt32]$ControllerNumber = '0', [Parameter(Position=4)][UInt32]$ControllerLocation = '0' ) $VM = Get-ANVMWmiObject -VMName $VMName if($VM) { if($ControllerType.Contains('s')) { $SearchType = 6 } else { $SearchType = 5 } $ComputerName = [String]::Empty if($VM.__SERVER -ne $env:COMPUTERNAME) { $ComputerName = $VM.__SERVER } $GwmiParams = @{Namespace = 'root\virtualization\v2'; Class = 'Msvm_ResourceAllocationSettingData'; Filter = ('InstanceID LIKE "%{0}%" AND ResourceType="{1}"' -f $VM.Name, $SearchType)} if($ComputerName) { $GwmiParams.Add('ComputerName', $ComputerName)} $VMRASD = Get-WmiObject @GwmiParams if($VMRASD -and $VMRASD.Count) { $VMRASD = $VMRASD[$ControllerNumber] } if($VMRASD) { $SearchPath = $VMRASD.Path.Path $SearchPath = $SearchPath.Substring(0, $SearchPath.Length - 1) $SearchPath += '\\{0}\\D"' -f $ControllerLocation $SearchPath = $SearchPath.Replace('\', '\\') $GwmiParams.Class = 'Msvm_StorageAllocationSettingData' $GwmiParams.Filter = ("Parent='{0}'" -f $SearchPath) $VMSASD = Get-WmiObject @GwmiParams if($VMSASD) { $VMSASD } else { 'No disk found at the specified controller location' exit 3 } } else { 'Specified controller was not found' exit 3 } } else { Write-Host ('Virtual machine "{0}" not found' -f $VMName) exit 3 } } function Get-ANVHDSettingData { param( [Parameter(Position=1)][System.Management.ManagementObject]$Disk ) if($Disk -and $Disk.HostResource[0].ToLower().Contains('.vhd')) { $ImageManagementService = Get-ANImageManagementService -ComputerName $Disk.__SERVER $SettingData = $ImageManagementService.GetVirtualHardDiskSettingData($Disk.HostResource[0]) if($SettingData.ReturnValue -eq 0) { try { $XMLData = [xml]$SettingData.SettingData if($XMLData.SelectSingleNode('/INSTANCE/@CLASSNAME').Value -ne 'Msvm_VirtualHardDiskSettingData') { throw('Data is not of type Msvm_VirtualHardDiskSettingData') } } catch { Write-Host ('Error parsing setting data for {0}: {1}' -f $Disk.HostResource[0], $_) Exit 2 } $RawBlockSize = $XMLData.SelectSingleNode('//PROPERTY[@NAME = ''BlockSize'']/VALUE/child::text()').Value $RawFormat = $XMLData.SelectSingleNode('//PROPERTY[@NAME = ''Format'']/VALUE/child::text()').Value $RawType = $XMLData.SelectSingleNode('//PROPERTY[@NAME = ''Type'']/VALUE/child::text()').Value $RawParentPath = $XMLData.SelectSingleNode('//PROPERTY[@NAME = ''ParentPath'']/VALUE/child::text()').Value $RawPath = $XMLData.SelectSingleNode('//PROPERTY[@NAME = ''Path'']/VALUE/child::text()').Value $RawLogicalSectorSize = $XMLData.SelectSingleNode('//PROPERTY[@NAME = ''LogicalSectorSize'']/VALUE/child::text()').Value $RawMaxInternalSize = $XMLData.SelectSingleNode('//PROPERTY[@NAME = ''MaxInternalSize'']/VALUE/child::text()').Value $RawPhysicalSectorSize = $XMLData.SelectSingleNode('//PROPERTY[@NAME = ''PhysicalSectorSize'']/VALUE/child::text()').Value $RawVirtualDiskId = $XMLData.SelectSingleNode('//PROPERTY[@NAME = ''VirtualDiskId'']/VALUE/child::text()').Value try { $WMISettingData = ([wmiclass]('\\{0}\root\virtualization\v2:Msvm_VirtualHardDiskSettingData' -f $Disk.__SERVER)).CreateInstance() } catch { Write-Host ('Unable to create a disk setting data object: {0}' -f $_) Exit 2 } $WmiSettingData.BlockSize = $RawBlockSize $WmiSettingData.Format = $RawFormat # Fixed = 2, Dynamic = 3, Differencing = 4 $WmiSettingData.Type = $RawType # VHD = 2, VHDX = 3 $WMISettingData.ParentPath = $RawParentPath $WmiSettingData.Path = $RawPath $WMISettingData.LogicalSectorSize = $RawLogicalSectorSize $WmiSettingData.MaxInternalSize = $RawMaxInternalSize $WmiSettingData.PhysicalSectorSize = $RawPhysicalSectorSize $WmiSettingData.VirtualDiskId = $RawVirtualDiskId $WmiSettingData } else { Write-Host ('Unable to retrieve setting data for {0}' -f $Disk.HostResource[0]) Exit 2 } } else { Write-Host 'Disk not found or is not a virtual hard disk' Exit 3 } } function Get-ANVHDState { param( [Parameter(Position=1)][System.Management.ManagementObject]$Disk ) $ImageManagementService = Get-ANImageManagementService -ComputerName $Disk.__SERVER $State = $ImageManagementService.GetVirtualHardDiskState($Disk.HostResource[0]) if($null -ne $State) { try { $XMLData = [xml]$State.State if($XmlData.SelectSingleNode('/INSTANCE/@CLASSNAME').Value -ne 'Msvm_VirtualHardDiskState') { throw('Data is not of type Msvm_VirtualHardDiskState') } } catch { Write-Host ('Error parsing state information for {0}: {1}' -f $Disk.HostResource[0], $_) Exit 2 } $RawAlignment = $XMLData.SelectSingleNode('//PROPERTY[@NAME = ''Alignment'']/VALUE/child::text()').Value $RawFileSize = $XMLData.SelectSingleNode('//PROPERTY[@NAME = ''FileSize'']/VALUE/child::text()').Value $RawFragmentationPercentage = $XMLData.SelectSingleNode('//PROPERTY[@NAME = ''FragmentationPercentage'']/VALUE/child::text()').Value $RawInUse = $XmlData.SelectSingleNode('//PROPERTY[@NAME = ''InUse'']/VALUE/child::text()').Value $RawMinInternalSize = $XMLData.SelectSingleNode('//PROPERTY[@NAME = ''MinInternalSize'']/VALUE/child::text()').Value $RawPhysicalSectorSize = $XMLData.SelectSingleNode('//PROPERTY[@NAME = ''PhysicalSectorSize'']/VALUE/child::text()').Value try { $WMIStateData = ([wmiclass]('\\{0}\root\virtualization\v2:Msvm_VirtualHardDiskState' -f $Disk.__SERVER)).CreateInstance() } catch { Write-Host ('Unable to create a disk state object: {0}' -f $_) Exit 2 } $WMIStateData.Alignment = $RawAlignment $WMIStateData.FileSize = $RawFileSize $WMIStateData.FragmentationPercentage = $RawFragmentationPercentage $WMIStateData.InUse = $RawInUse $WMIStateData.MinInternalSize = $RawMinInternalSize $WMIStateData.PhysicalSectorSize = $RawPhysicalSectorSize $WMIStateData } else { Write-Host ('Unable to retrieve state information for {0}' -f $Disk.HostResource[0]) Exit 2 } } }