Identifying SAN disk usage using WMI – Powershell – Script of the Day
So I was commissioned with identifying the amount of actual disk space used by a bunch of Microsoft Servers that were attached to various SANs on our network. Unfortunately, despite us having a rather expensive vendoir supplied product for doing this reporting, the vendor product(s) is/are dependent on agents running on the servers to actually report back what the performance stats look like.
I fugured that the information must be accessible via WMI so I set about trying to identify something that identified disks as being remote / SAN attached.
I had a crack using several different WMI classes, thinking that I may need to tie the results from a hardware based query to identify physical disks, against the results of something like the win32_logicaldisk class – but was drawing a blank.
to identify similarities / differences betwen hosts I decided to just spit our the results of the Disk / Volume classes for a handful of hosts
I tried the following classes:
win32_logicaldisk
win32_DiskDrive
Win32_Volume
After interrogating a few hosts (some SAN attached, some not . I noticed a similarity in the device IDs returned in the following class win32_Volume.
you see all of our servers are set to have local disk for the C: and CDROM for the Z: (so I had a control group)
Executing the following however . . against a LONG list of server seemed to always return C: and Z: with device IDs in the format:
\\?\Volume{xxxxxxxx-xxxx-xxxx-xxxx-806e6f6e6963}\
Now I have looked around for an explanation as to why all the Local Disks and Local CD Roms appear with tat number at the end, but I can find no confirmation – but I figured I’d simply create a PowerShell script using this snippet of info to generate the report I require.
First of all, the wmi query that I would need :
gwmi -ComputerName <servername> -class win32_volume | select deviceid, driveletter
Now all I need to do is contruct a method to repeat the above and churn out a nice Excel style report to show disk utilisation . .
Here is the result
Function get-sandisks ([string]$InputFilename,[string]$OutputFilename) { $servers = gc $InputFilename $MyObj = @() # Cycle through the servers in the file foreach ($server in $servers) {Write-Host $server -ForegroundColor Green # first test if we can ping the server (quicker than trying WMI straight away) If (Test-Connection $server -Count 1) { if (Get-WmiObject -ComputerName $server Win32_LogicalDisk -ea 0) {$disks = gwmi -ComputerName $server -class win32_volume | ?{$_.driveletter} #| ?{$_.deviceid -notmatch "806e6f6e6963"} #| select deviceid, driveletter If ($disks) {foreach ($disk in $disks) { $rep = "" | select "Server Name", "Drive Letter", "Disk Space", "Used Space", "Free Space", "DeviceID", "Type" $Rep."Server Name" = $server $Rep."Drive Letter" = $disk."driveletter" $Rep."Disk Space" = $disk | %{$_.Capacity} $Rep."Free Space" = $disk | %{$_.Freespace} $Rep."Used Space" = $Rep."Disk Space" - $Rep."Free Space" If ($disk.deviceid -notmatch "806e6f6e6963"){$rep.Type = "SAN"} Else {$Rep.Type = "Local"} $Rep."DeviceID" = $disk | %{$_.deviceID} Write-Host $rep $MyObj += $Rep $rep = $null } } } Else { $rep = "" | select "Server Name", "Drive Letter", "Disk Space", "Used Space", "Free Space", "DeviceID", "Type" $Rep."Server Name" = $server $Rep."Drive Letter" = "WMI" Write-Host $rep "WMI" -ForegroundColor Yellow $MyObj += $Rep $rep = $null } } Else { $rep = "" | select "Server Name", "Drive Letter", "Disk Space", "Used Space", "Free Space", "DeviceID", "Type" $Rep."Server Name" = $server $Rep."Drive Letter" = "PING" Write-Host $rep "PING" -ForegroundColor Yellow $MyObj += $Rep $rep = $null } } $MyObj | sort | Export-Csv -Path $OutputFilename -NoTypeInformation }
While I appreciate that this is not 100% accurate, I simply wanted to report on space that is in use by the SAN and is no local disk, so the result is fit for my purpose.