Use PowerCLI to find the datastore from a disk name
June 3, 2012 13 Comments
Recently we get vSphere alarms in our environment that say for instance:
“[VMware vCenter – Alarm Host error] Issue detected on host in datastore: ScsiDeviceIO: 2368: Failed write command to write-quiesced partition naa.600a0b8000111155000021c53f97784e:1 (42:01:04:07.994 cpu7:5191)”
There seems to be a problem on a partition. But which datastore is on this partition? We can use PowerCLI to find the datastore involved.
List all datastores and disk names
We can use the PowerCLI script from listing 1 to list all datastores and the disk names of the partitions.
Get-Datastore | Where-Object {$_.ExtensionData.Info.GetType().Name -eq "VmfsDatastoreInfo"} | ForEach-Object { if ($_) { $Datastore = $_ $Datastore.ExtensionData.Info.Vmfs.Extent | Select-Object -Property @{Name="Name";Expression={$Datastore.Name}}, DiskName } }
Listing 1. PowerCLI script to list all datastores and the disk names of the partitions.
A sample output of this script is:
Name DiskName ---- -------- esxi01_boot naa.600a0b80001111550000fb9cf54f414d esxi02_boot naa.600a0b80001111550000850e884f414d cluster01_gold_001 naa.600a0b80001111550000778bc952494d cluster01_silver_001 naa.600a0b8000111155000074088c52494d cluster01_bronze_003 naa.600a0b80001111550000e451a8ed794e esxi03_boot naa.600508b4001078340000e00004c00000 esxi04_boot naa.600508b4001078340000e00002c60000 cluster02_gold_001 naa.600508b400055c680000800000dc0000 cluster02_silver_001 naa.600508b4001078340000e00004bb0000 cluster02_bronze_001 naa.600508b4001078340000e00002cb0000
Output 1. Sample output from the PowerCLI script from listing 1.
Of course you can try to find the diskname and the corresponding datastore in the list. But if the list is long this is not easy.
A better way is to let PowerCLI do the search.
Find a specific datastore
The PowerCLI from listing 2 shows returns only the datastore that contains the partition with the requested disk name.
Get-Datastore | Where-Object {$_.ExtensionData.Info.GetType().Name -eq "VmfsDatastoreInfo"} | ForEach-Object { if ($_) { $Datastore = $_ $Datastore.ExtensionData.Info.Vmfs.Extent | Where-Object {$_.DiskName -eq "naa.600a0b80001111550000fb9cf54f414d"} | ForEach-Object { if ($_) { $Datastore } } } }
Listing 2. PowerCLI script to get the datastore that contains the partion with the requested disk name.
Unfortunately the script from listing 2 is slow. In our environment with 138 datastores the script takes 43 seconds to run.
A faster script
I decided to make a PowerCLI advanced function that searches for the datastore as fast as possible. It uses the PowerCLI Get-View cmdlet to retrieve all the datastores. It then tries to match the datastores in this list with the given disk name.
function Get-DatastoreByDiskName { <# .SYNOPSIS Retrieves the datastore for a given disk name. .DESCRIPTION Retrieves the datastore for a given disk name. .PARAMETER DiskName Specify the disk name of the partition in the datastore to search for. .EXAMPLE Get-DatastoreByDiskName -DiskName naa.600a0b80001111550000a3fdfb4e6c4f Retrieves the datastore with disk name naa.600a0b80001111550000a3fdfb4e6c4f. .EXAMPLE "naa.600a0b800011115500006852e34d6c4f" | Get-DatastoreByDiskName Retrieves the datastore with disk name naa.600a0b800011115500006852e34d6c4f. .COMPONENT VMware vSphere PowerCLI .INPUTS String .OUTPUTS VmfsDatastoreImpl .NOTES Author: Robert van den Nieuwendijk Date: 1-6-2012 Version: 1.0 .LINK https://rvdnieuwendijk.com/ http://twitter.com/rvdnieuwendijk #> [CmdletBinding()] param( [parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [string[]] $DiskName ) begin { # Get all the datastores $DatastoresView = Get-View -ViewType Datastore -Property Name,Info } process { ForEach ($Datastore in $DatastoresView) { # Only objects of type VMware.Vim.DatastoreInfo.VmfsDatastoreInfo # have the Info.Vmfs property if ($Datastore.Info.GetType().Name -eq "VmfsDatastoreInfo") { ForEach ($Disk in $DiskName) { $Datastore.Info.Vmfs.Extent | ForEach-Object { if ($_ -and $_.Diskname -eq $Disk) { # Return the found datastore $Datastore | Get-VIObjectByVIView } } } } } } }
Listing 3. A PowerCLI advanced function that searches for the datastore as fast as possible.
This script finds one datastore in 1.5 seconds. That is 29 times faster than the script from listing 2.
You can use the advanced function to search for multiple datastores at once. Every extra datastore took me 1.1 seconds extra.
Annotations
Line 50: Get all the datastores.
Line 54-72: Loop through all the datastores.
Line 60-70: Loop through all the disk names.
Line 67: Return the found datastore.
Conclusion
We have not solved the issue from our vCenter alarm yet. But it least we now know which datastores are involved.
Writing PowerCLI code for maximum speed can make your code significantly faster.
Update Januari 2nd, 2013: Thanks to reader Brad S. who commented on a problem that was in the original script of listing 1, I could solve the bug in this script. I updated the scripts in listing 1 and listing 2 to work correctly with datastores that have multiple extents.
Hello Robert,
Did you find any solution for “Failed write command to write-quiesced partition” ?
We have same problem too and cant resolved yet.
Best Regards
Hi Yolte,
we did not find a solution to this problem yet. Although we found some more information.
Looking at the ESXi server’s /var/log/messages file, at the time of the problem, it shows a SCSI error D:0x28. That translates to the target device (the storage) says “task set full” or “queue full”. The storage in this case is a HP Enterprise Virtual Array (EVA) behind a HP SAN Virtualization Services Platform (SVSP). Unfortunately we can’t find any problem at SVSP or the EVA.
So we are still searching for a solution. If we find one, I will let you know. Please let me know if you find a solution before we do.
Regards, Robert
When i run your listing 1 script all i get back are the datastore names. Diskname is blank.
Hi Greg,
in our vSphere environment we have fibre channel and NFS datastores. The script in listing 1 returns name and diskname for all our fibre channel datastores only. The NFS datastores are not returned by the script at all. Maybe are you using iSCSI?
I tested my script using PowerCLI 5.1 Release 1, against a vCenter Server v5.1.0a.
Regards, Robert
Same as Greg.. and I am using PowerCLI 5.0.1 on vCenter 4.1
First I thought that problem was in the PowerCLI version. So I tested the script from listing 1 with PowerCLI 5.0.1. That works fine for me. When I wrote this blogpost we were still runnning vCenter 4.1. So that seems also not the problem. Are you sure you have Fibre Channel datastores and not iSCSI? Because we don’t have iSCSI so I can’t test against that.
This should work
“get-Datastore |
Where-Object {
$_.ExtensionData.Info.GetType().Name -eq “VmfsDatastoreInfo”} |
Select-Object -Property Name,
@{Name=”DiskName”;Expression={ $_.ExtensionData.Info.Vmfs.Extent[0].DiskName} }”
Not sure why we need to use the [0] but I saw other scripts use it and decided to give it a try
$_.ExtensionData.Info.Vmfs.Extent[0].DiskName
Hi Brad,
thank you very much for your reaction.
That you need to use Extent[0] means that you have datastores with multiple extents. With Extent[0] you specify the first extent. I never tested my script against datastores with multiple extents because all our datastores have only one extent.
I will modify the scripts in this blog post to let them work correctly with datastores with multiple extents.
Kind regards, Robert
Hello Robert,
Thank you for this!
Will this also search RDM’s? I know the NAA id, and am trying to see if it is presented anywhere in our environment whether as a datastore or an RDM.
Cheers
Hi Martin,
the scripts in this post will only search for datastores. You can search for RDM’s with a PowerCLI oneliner. For example:
Get-VM | Get-HardDisk |
Where-Object {$_.DiskType -like “raw*” -and $_.ScsiCanonicalName -eq “naa.600a0b80001111550000b43a08f4ae4d”} |
Select-Object -Property Parent,Name,DiskType,ScsiCanonicalName
this is very handy. is there anyway to get capacity as part of the output?
The Get-DatastoreByDiskName function returns standard PowerCLI datastore objects. By default these objects display the Name, FreeSpaceGB and CapacityGB properties. You can pipe the output to the Select-Object cmdlet to select other properties.
Pingback: List all datastores and disk names - Gkhan Tips