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
}
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
I am guessing this is what is causing the slow down since it uses get-scsilun over and over.
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?
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
Thank you for helping me out with this
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
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