Recently I was in a situation where an aggregate in a multi HA pair cluster was low on space. While working to avert the impending disaster I was asked by an incident manager what VMs are on the aggregate that is low on space. Now there where alot of volumes/LUNs on that aggregate. Stopping to do that analysis would have been bad so we didn’t. But it was a valid question.
If you have your LUN names the same as your Datastore names then you could quickly(ish) get an answer. But what if you have allot of LUNs or the LUN name is not always the same name as the Datastore name.
So I put this script together. It will get all the LUNs on an aggregate and then find the VMWare datastores. then get all the VMs on those datastores.
The script uses the VMWare and DataONTAP modules.
# import needed modules
import-module VMware.VimAutomation.Core
import-module VMware.VimAutomation.Common
import-module DataONTAP
# FAS and vCenter locations
$FASName = "NetApp-FAS-Name or IP"
$vCenterName = "vCenter URL or IP"
# Prompt the user for creds
$FASCred = Get-Credential -Message "NetApp FAS"
$VCSACred = Get-Credential -Message "VMWare vCenter"
# connect to FAS and vCenter
connect-viserver $vCenterName -cred $VCSACred
Connect-NcController $FASName -Credential $FASCred
# used to convert the netapp sireal number to vmware NAA number
function ConvertTo-HexString([string]$iinput)
{
write-host $iinput -ForegroundColor Gray
[byte[]]$bytes = $iinput.ToCharArray()
$hexBytes = $bytes | % {$_.ToString("X2")}
$hexBytes -join ''
}
# get a lookup table of DS names, canonical names (naa number)
$DSlist1 = Get-Datastore |
Select Name,CapacityGB,
@{N='CanonicalName';E={$_.ExtensionData.Info.Vmfs.Extent[0].DiskName}},
@{N='LUN';E={
$esx = Get-View -Id $_.ExtensionData.Host[0].Key -Property Name
$dev = $_.ExtensionData.Info.Vmfs.Extent[0].DiskName
$esxcli = Get-EsxCli -VMHost $esx.Name -V2
$esxcli.storage.nmp.path.list.Invoke(@{'device'=$dev}).RuntimeName.Split(':')[-1].TrimStart('L')}
}
# display the non root aggregates
Get-NcAggr | where{$_.name -notmatch "aggr0"}
# prompt for the user to enter an aggregate name
$bob = read-host "enter the name of an aggregate"
# get the aggregate object, no user input checking (thats bad)
$aggToList = get-ncaggr $bob
# get the LUNs on the Volumes on that aggregate
$LUNsOnAgg = get-nclun -Volume (get-ncvol -Aggregate $aggToList)
$VMs = @()
# loop through each LUN
foreach ($LUNOnAgg in $LUNsOnAgg)
{
# Get the LUN serial number and convert (Hex to ASCII) it to the NAA name in VMWare
$LunSN = ConvertTo-HexString $LUNOnAgg.SerialNumber
$DS = $DSlist1 | where{$_.CanonicalName -match $LunSN} | sort name -Unique
# get Datastore object and VMs on the Datastore
$DSObj = get-datastore $DS.name
$VMsOnDS = get-vm -Datastore $DSobj
# Loop though the VMs
foreach ($VMOnDS in $VMsOnDS)
{
# Create the tmp VM outpou object
# get the VM name, DS name, VM sizes in GB and PowerState
$tmpVM = '' | select VM,DataStore,SizeGB,PSizeGB,PowerState
$tmpVM.VM = $VMOnDS.name
$tmpVM.DataStore = $DSObj.name
$tmpVM.SizeGB = [int]($VMOnDS.UsedSpaceGB)
$tmpVM.PSizeGB = [int]($VMOnDS.ProvisionedSpaceGB)
$tmpVM.PowerState = $VMOnDS.PowerState
# Add this VM to the VMs array
$VMs += $tmpVM
}
}
$VMs | ft -AutoSize
There you go. a quick script to get VMs on an aggregate.
This was knocked up quite quickly, it could use some code to check the user input (the aggregate name) and maybe a little more details of the VMs.