Microsoft Virtualization Discussions
Microsoft Virtualization Discussions
I have been hacking together this script to query all Vcenter VMs raw iscsi disks and return the following in a nice little csv file which my script sort of does. I know there is some optimization needed but I will get to that later. I am pretty new to powershell so i hope i am just overlooking something
Hostname | DiskID | CapacityG | HD Path | ScsiCanonicalName | LunID | Netapp Path) | |
server name | Hard disk 3 | 40.00255108 | [VMFS_RDM] servername\servername.vmdk | naa.60 | 3 | /vol/volname/data.lun |
I have one issue i hope is simple
1. When returning the GetNetappPath function value i am getting System.Object you can see that i am calling that function at the bottom of this script $NetappPath = GetNetappPath $VMHost $VMHDLunID When i call function SearchFilers from the GetNetappPath function it seems to return the correct value and i put in Write-Host "GetNetappPath Function: $c" in the getnetapppath function and it seems to have the correct value. It looks like i returning the value from each function correctly, does anyone see something i did wrong to cause this?
I wrote in the SearchFilers function to search each filer then return a value. I have not put in that logic yet because I have the issue with problem 1
param([string]$VC)
#################Functions##############################################
function GetNetappPath([string]$VMHost,[string]$VMHDLunID) {
$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
Write-Host "GetNetappPath Function: $c" <-------- this value contains the name of the filer which shouldn't be returning along with the path
return $c <-----------------------This return is where i am having the issue
}
function SearchFilers([string]$IscsiWWN){
connect-nacontroller servername
$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"
return $a
}
function GetLunInfo([string]$VMHost,[string]$SCSICanonicalName) {
$Lun = Get-SCSILun $SCSICanonicalName -VMHost $VMHost #(Get-VM $VMName).VMHost
$VMHDLunID = $Lun.RuntimeName.Substring($Lun.RuntimeName.LastIndexof(“L”)+1)
return $VMHDLunID
}
#################Functions##############################################
########################
Import-Module DataONTAP
########################
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
$PathtoCSV = "C:\temp\VMlunID.csv"
"Hostname,DiskID,CapacityG,HD Path,ScsiCanonicalName,LunID,Netapp Path)" > $PathtoCSV
Write-Host "This will take a bit to run"
$Disks = Get-VM | Get-HardDisk | Where {$_.DiskType -eq "RawPhysical"}
Write-Host "Finished getting disk info"
Write-Host ""
Write-Host "Figuring out lun information"
Foreach ($Disk in $Disks) {
$VMName = $Disk.Parent
$VMHDname = $Disk.Name
$VMCapacityGB = $Disk.capacityGB
$VMHDPath = $Disk.filename
$VMScsiCanonicalName = $Disk.ScsiCanonicalName
$VMHost = Get-VM $VMName | Select -ExpandProperty Host
#Write-Host $VMName,$VMHDname,$VMCapacityGB,$VMHDPath,$VMScsiCanonicalName
#LunID
Write-Host "Figuring out lun ID"
$VMHDLunID = GetLunInfo $VMHost $Disk.SCSICanonicalName
Write-Host "Figuring out Netapp Igroup Information and Path"
$NetappPath = GetNetappPath $VMHost $VMHDLunID
$Combine = $VMName,$VMHDname,$VMCapacityGB,$VMHDPath,$VMScsiCanonicalName,$VMHDLunID,$NetappPath
Write-Host "Writing $Combine"
$Combine -join "," >> $PathtoCSV
}
Solved! See The Solution
Hi, i think your issue is in your SearchFilers function:
Change this:
connect-nacontroller servername
To this:
connect-nacontroller servername | out-null
Connect-NaController returns an object of type NetApp.Ontapi.Filer.NaController. One thing that is very different about Powershell is how it handles output. In a function, if any command you issue returns output, then the function returns it, regardless of whether you include the "return" keyword or not. You can avoid this when it happens by either piping it to Out-Null or assigning it to a variable (e.g. $x = Connect-NaController ...)
So your SearchFilers is actually (and I'm sure unexpectedly) returning an array of two values:
1) THe NaController object output from your Connect-NaController cmdlet call
2) $a, from your return $a call
Hi, i think your issue is in your SearchFilers function:
Change this:
connect-nacontroller servername
To this:
connect-nacontroller servername | out-null
Connect-NaController returns an object of type NetApp.Ontapi.Filer.NaController. One thing that is very different about Powershell is how it handles output. In a function, if any command you issue returns output, then the function returns it, regardless of whether you include the "return" keyword or not. You can avoid this when it happens by either piping it to Out-Null or assigning it to a variable (e.g. $x = Connect-NaController ...)
So your SearchFilers is actually (and I'm sure unexpectedly) returning an array of two values:
1) THe NaController object output from your Connect-NaController cmdlet call
2) $a, from your return $a call
Thank for the great explanation on functions, worked like a charm.
now i just have to add the logic for the scsi target.
Here is my working script, It is a mess and you have to hardcode runtimes names to filers in the SearchFilers function (unless someone knows how to get that from vcenter) and it is slow but it works at least for my purposes.One thing you may have to do is edit the searchfilers function to handle credentials based on your setup
I have not tested the new way i am getting the lunids but i assume it will work
param([string]$VC)
Import-Module DataONTAP
#########################
####Tony Unger
####Run from Vsphere PowerCLI
#########################
#################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 runtime names here with what filer
"vmhba40:C0:T0*" {$NetappFiler = "x.x.x.x"}
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"
return $a
}
function GetScsiTarget([string]$VMHost,[string]$SCSICanonicalName) {
$Lun = Get-SCSILun $SCSICanonicalName -VMHost $VMHost #(Get-VM $VMName).VMHost
$RuntimeName = $Lun | Select -ExpandProperty RuntimeName
#$VMHDLunID = $Lun.RuntimeName.Substring($Lun.RuntimeName.LastIndexof(“L”)+1)
return $RuntimeName
}
#################Functions##############################################
########################
$PathtoCSV = "C:\temp\VMlunID.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 = $Disk.Parent
write-host "VM Name: $VMName"
$VMHDname = $Disk.Name
write-host "Hard drive ID: $VMHDname"
$VMCapacityGB = $Disk.capacityGB
write-host "Lun Capacity(GB): $VMCapacityGB"
$VMHDPath = $Disk.filename
write-host "RAW VMDK Path: $VMHDPath"
$VMScsiCanonicalName = $Disk.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
}