VMware Cloud Community
Bane58
Contributor
Contributor

Help speeding up this Vmware Netapp script i wrote - Rdm are mapped to what netapp filer/lun

I wrote this script to figure out what netapp lun is used on each vm via ISCSI. Currently on about around 200 VM and 8 hosts it takes 40 Mins to run. This being my 3rd powershell script i am sure I could speed up its processing and was hoping someone could point me in the right direction.

This generates a csv file with the following header.

Hostname     DiskID     CapacityG     HD Path     ScsiCanonicalName LunID  Netapp Path

Also in function searchfilers i didn't know if anyone knew how to dynamically get this information, i have looked for hours/days and couldn't find a way besides hard coding it. This function is needed to know what netapp filer to connect to.

param([string]$VC)
Import-Module DataONTAP
#################Functions##############################################
function GetNetappPath([string]$VMHost,[string]$VMHDLunID,[string]$RuntimeName) {
$stor = get-view (Get-VMHostStorage -VMHost $VMHost)
$IscsiWWN = $stor.StorageDeviceInfo.HostBusAdapter | where {$_.GetType().Name -eq "HostInternetScsiHba"} | Select -First 1 -expandproperty IScsiName
Write-Host "Found ISCSI NAME: $IscsiWWN on Host $VMHost"
$c = SearchFilers $IscsiWWN $RuntimeName
Write-Host "Netapp path: $c"
return $c
}
function SearchFilers([string]$IscsiWWN,[string]$RuntimeName){
switch -wildcard ($RuntimeName)
    {
       #Add all you vmware runtime names here with what filer
        "vmhba40:C0:T0*" {$NetappFiler = "x.x.x.x"}#ip address
       
        default {Write-host "Error! determining filer - $RuntimeName not found";read-host}
    }
Write-host "Connecting to $NetappFiler"
connect-nacontroller $NetappFiler | out-null
$Igroup = get-nalun | Get-Nalunmap | Select Name,Initiators | Where {$_.Initiators -like $IscsiWWN} | Select -First 1 -expandproperty Name
$a = get-nalunbyigroup $Igroup $VMHDLunID | Select -ExpandProperty Path
#Write-Host "SearchFilers function: $a"
$a = "$NetappFiler$a"#filerip\lunpath
return $a
}
function GetScsiTarget([string]$VMHost,[string]$SCSICanonicalName) {
$Lun = Get-SCSILun $SCSICanonicalName -VMHost $VMHost #(Get-VM $VMName).VMHost
$RuntimeName = $Lun | Select -ExpandProperty RuntimeName
  return $RuntimeName
}
#################Functions##############################################
########################
$PathtoCSV = "C:\temp\VMlunIDNetappPath.csv"
########################
If ($VC){$strVC = $VC}
ELSE{$strVC = Read-Host "What is the Vcenter hostname?"}
If (!$strVC){Write-Host "Error: Vcenter not entered";exit}
Connect-VIServer -Server $strVC  #Enter your vCenter Server
#Create Header
"Hostname,DiskID,CapacityG,HD Path,ScsiCanonicalName,LunID,ESX Host,Netapp Path" > $PathtoCSV
Write-Host "Getting VM Information from Vcenter. This can take awhile based on how many VM you have"
$Disks = Get-VM | Get-HardDisk | Where {$_.DiskType -eq "RawPhysical"}
Write-Host "Completed getting VM Information from Vcenter"
Foreach ($Disk in $Disks) {
$VMName = $_.Parent
write-host "VM Name: $VMName"
$VMHDname = $_.Name
write-host "Hard drive ID: $VMHDname"
$VMCapacityGB = $_.capacityGB
write-host "Lun Capacity(GB): $VMCapacityGB"
$VMHDPath = $_.filename
write-host "RAW VMDK Path: $VMHDPath"
$VMScsiCanonicalName = $_.ScsiCanonicalName
write-host "$ScsiCanonicalName: $VMScsiCanonicalName"
$VMHost = Get-VM $VMName | Select -ExpandProperty Host
write-host "ESX Host: $VMHost"
$RuntimeName = GetScsiTarget $VMHost $Disk.SCSICanonicalName
write-host "RuntimeName: $RuntimeName"
$VMHDLunID = $RuntimeName.Substring($RuntimeName.LastIndexof(“L”)+1)
Write-Host "LunID: $VMHDLunID"
$NetappPath = GetNetappPath $VMHost $VMHDLunID $RuntimeName
Write-host "PathtoNetapp: $NetappPath"
$Combine = $VMName,$VMHDname,$VMCapacityGB,$VMHDPath,$VMScsiCanonicalName,$VMHDLunID,$VMHost,$NetappPath
Write-Host "Writing to $PathtoCSV"
$Combine -join "," >> $PathtoCSV
}

0 Kudos
6 Replies
LucD
Leadership
Leadership

Do you know if the majority of the execution time is spend in the Ontap cmdlets (the SearchFilers function) or in the other functions ?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
Bane58
Contributor
Contributor

I am guessing this is what is causing the slow down since it uses get-scsilun over and over.

Function GetScsiTarget([string]$VMHost,[string]$SCSICanonicalName) {
$Lun = Get-SCSILun $SCSICanonicalName -VMHost $VMHost
$RuntimeName = $Lun | Select -ExpandProperty RuntimeName
  return $RuntimeName

Would it be better to load get-scsilun for all hosts into a $string and search within that?

and i guess the same would be for function SearchFilers. Loading all the filers and their luns into a $string instead of connecting over and over

So you would recommend doing this to speed it up?

0 Kudos
LucD
Leadership
Leadership

You can try to store the infor a hash table and then lookup the RuntimeName from that hash table

To initialise the table you can do

$lunTab = @{}
Get-VMHost  | Get-ScsiLun | %{
  $lunTab.Add($_.VMHost.Name + $_.CanonicalName, $_.RuntimeName)
}

To find the RuntimeName you should then be able to do

$RuntimeName = $lunTab[$VMHost.Name + $Disk.SCSICanonicalName]

That should be at least a bit faster compared to executing the Get-ScsiLun cmdlet each time.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
Bane58
Contributor
Contributor

Thank you for helping me out with this

0 Kudos
Bane58
Contributor
Contributor

This change decreased the running time from 37mins to 22mins. I am sure doing the same thing for the other functions will improve the running time even more

0 Kudos
LucD
Leadership
Leadership

There are a couple of changes that can be done, but do you have any idea in which function/part of the script the majority of the time is spent ?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos