Microsoft Virtualization Discussions

Cluster Shared Volume to LUN correlation?

Is there way with the NetApp Powershell toolkit to determine which CSV is on which LUN?  If not, can it be done from the other end (i.e. the Cluster Volume)


Re: Cluster Shared Volume to LUN correlation?

I assume you're using Hyper-V, since that's the principal application of CSV.  Try the Toolkit's Get-NaHyperV cmdlet.  It is obviously VM-centric, but it will display all of the relevant LUN and CSV info you seek.  I've also logged an enhancement suggestion to have the Toolkit return host-to-controller storage correlation info irrespective of Hyper-V.

Re: Cluster Shared Volume to LUN correlation?

Ah yes, that's very useful.  Just what I needed.  It would be useful if it was possible to run it against other Hyper-V hosts other than the local one though!

Re: Cluster Shared Volume to LUN correlation?

Hmm, been playing with it some more and have noticed some odd behaviour.  I have installed the DataOnTAP module on two cluster nodes.  On one node, the Get-NaHyperv cmdlet produces the correct results.  It lists the VMs running and the storage info.

I then installed the modules on another node and ran Get-NaHyperV again.  On this node there are about 5 or 6 VMs but the cmdlet lists nothing!

Edit: Ah, I think I understand what's happening.  The cmdlet will only enumerate the VMs IF the CSV they are stored on is currently mounted on the same node on which they are running.  This is a pretty big limitation when it comes to running it in a cluster as the CSVs and VMs move around the cluster all the time.  Any chance this can be made "cluster-aware" in a future release?

Re: Cluster Shared Volume to LUN correlation?

Right.  The cmdlet only lists VMs for which we can find NetApp storage on the local node.  You can use the -All switch to list all VMs irrespective of their storage.  I have logged an enhancement request to investigate adding more cluster awareness.

Re: Cluster Shared Volume to LUN correlation?

I had a similar issue in my environment with LUNs that service SQL servers.  My short-term solution was to create a function that accepts the lun path (which in my environment includes the name of the cluster to which it is assigned) and returns the drive letter and a description of the volume.  Then, I extracted the hostname from the volume name.  WIth the volume name and the drive letter, I could then use WMI to gather information about the LUN from the OS perspective.  Eventually, I hope to update my script to gather information dynamically from the DSM CLI on each server, but that enhancement is still quite a ways in the future.  Below is some sample code.  I hope you find it useful.  (The original code interfaced with MS-Excel to create a spreadsheet of data, but I have removed the Excel code for clarity.  I may have created a few bugs along the way.  Sorry.)

function Get-DriveInfo ([string] $lunPath) {
    switch ($lunPath) {
        "/vol/dbcluster1_systemdb/qtree1/dbcluster1_systemdb"     { return ("R", "Cluster1 SQL System Databases") }
        "/vol/cluster1_quorum/quorum"                             { return ("Q", "Cluster1 Witness Disk") }
        default                                                   { return ("Unknown", "Unknown") }

function Get-Disks ([string] $hostname) {
    return (get-wmiobject win32_logicaldisk -filter "drivetype=3" -computername $hostname -credential $windowsCredential | sort-object DeviceID)

function Get-DiskIndex ([System.Array] $diskList, [string] $letter) {
    if ($diskList -ne $null) {
        foreach ($disk in $disks) {
            if (($disk.DeviceID.ToLower()) -eq ($letter+":").tolower()) {
                return $index
    else {
        return $null

foreach ($netappName in $listOfNetAppNames) {

     $currentNetapp = Connect-NaController -name $netappName -credential $netappCredential

     $listOfLuns    = Get-NaLun -controller $currentNetapp | Sort-Object -Property "Path"
     if ($listOfLuns -ne $null) {
          foreach ($lun in $listOfLuns) {

               $hostname    = $lun.path.split("/_")[2]
               $driveLetter = Get-DriveInfo ($lun.path))[0]

               $disks       = Get-Disks ($hostname)
               if ($disks -ne $null) {
                    $diskIndex = Get-DiskIndex $disks ($driveLetter)
                    $diskSpaceAllocated  = $disks[$diskindex].size                    #Drive Space Allocated
                    $diskSpaceAvailable  = $disks[$diskindex].FreeSpace               #Drive Space Available