hello everyone
i am designing some simple script to retrieve VM Hard Disk information with PowerCli and i got some pretty weird issue: i ocasionally get runtime execution errors with vc server disconnection, but after the error, i can retrieve info on the same vcenter with simple commands (like Get-VM for instance). The vc farms still available over viclient and powercli all the time, so it must be something on the code
the steps i use to reproduce the strange behavior:
(Using Powercli 5.5 and Powershell 3.0. Error still happens with Powercli 5.1)
- Connect to vcenter (multiple servers)
- run the command and it eventually gets stuck in line 12 ($ghd = Get-HardDisk (Get-VIObjectByVIView $VMView)) with the error 'Server XXXX is disconnected'
- Run some other command (like get-vm) to certify that server is still connected
sample script is below
Function Get-VMDiskInfo {
[CmdletBinding()]
Param (
[Parameter(Mandatory=$true,
ValueFromPipeline=$True,
ValueFromPipelineByPropertyName=$true)]
[Alias('Name')]
$VM
)
PROCESS{
$VMView = Get-View -ViewType VirtualMachine -Filter @{"Name" = $VM}
$ghd = Get-HardDisk (Get-VIObjectByVIView $VMView)
$output = @()
ForEach ($VirtualSCSIController in ($VMView.Config.Hardware.Device | Where {$_.DeviceInfo.Label -match “SCSI Controller”})){
ForEach ($VirtualDiskDevice in ($VMView.Config.Hardware.Device | Where {$_.ControllerKey -eq $VirtualSCSIController.Key})){
$VMSummary = “” | Select VM,Disk, SCSI, DiskType, DiskFormat, DiskSizeGB, DiskFile
$VMSummary.VM = $VM
$VMSummary.SCSI = [string]::Concat($VirtualSCSIController.BusNumber,":",$VirtualDiskDevice.UnitNumber)
$VMSummary.Disk = $VirtualDiskDevice.DeviceInfo.Label
#pegando info do Get-Harddisks
$d = $ghd | ? {$_.Name -match $VirtualDiskDevice.DeviceInfo.Label}
$VMSummary.DiskType = $d.DiskType
$VMSummary.DiskSizeGB = [Math]::Round($d.capacityGB,2)
$VMSummary.DiskFile = $d.filename
if($d.Disktype -eq "Flat"){
$VMSummary.DiskFormat = $d.StorageFormat
}
$output += $VMSummary
}
}
Write-Output $output
}
}
does anyone have any idea whats going on ?
almost forgot, sorry about the messy code and the poor english...
thanks in advance
Try like this
Function Get-VMDiskInfo {
[CmdletBinding()]
Param (
[Parameter(Mandatory=$true,
ValueFromPipeline=$True,
ValueFromPipelineByPropertyName=$true)]
[Alias('Name')]
$VM
)
PROCESS{
$VMView = Get-View -ViewType VirtualMachine -Filter @{"Name" = $VM}
$output = @()
ForEach ($VirtualSCSIController in ($VMView.Config.Hardware.Device | Where {$_.DeviceInfo.Label -match “SCSI Controller”})){
ForEach ($VirtualDiskDevice in ($VMView.Config.Hardware.Device | Where {$_.ControllerKey -eq $VirtualSCSIController.Key})){
$VMSummary = “” | Select VM,Disk, SCSI, DiskType, DiskFormat, DiskSizeGB, DiskFile
$VMSummary.VM = $VM
$VMSummary.SCSI = [string]::Concat($VirtualSCSIController.BusNumber,":",$VirtualDiskDevice.UnitNumber)
$VMSummary.Disk = $VirtualDiskDevice.DeviceInfo.Label
#pegando info do Get-Harddisks
$VMSummary.DiskType = &{
switch -regex ($VirtualDiskDevice.Backing.GetType().Name){
"Flat" {
"Flat"
if($VirtualDiskDevice.Backing.ThinProvisioned){$VMSummary.DiskFormat = "Thin"}
else{$VMSummary.DiskFormat = "Thick"}}
"Raw" {
"Raw" + $VirtualDiskDevice.Backing.CompatibilityMode.TrimEnd("Mode")
}
Default {"Unknown"}
}
}
$VMSummary.DiskSizeGB = [Math]::Round(($VirtualDiskDevice.CapacityInKb/1MB),2)
$VMSummary.DiskFile = $VirtualDiskDevice.Backing.FileName
$output += $VMSummary
}
}
Write-Output $output
}
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
You mention that you have multiple connections to vSphere servers open.
Are these all vCenters, or are they ESXi servers ?
Could it be that 1 such connection was dropped after the error ?
You could insert a
$global:DefaultVIServers.Count
before and after line 12 to check if that is the case.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
these are all vcenters, multiple versions (4.1, 5.0 and 5.1)
its really odd that i can use Get-VM on the same server that it claimed disconnection with no errors, something like this:
1) Connected to 3 vCenters: vc01, vc02 and vc03
2) Run script and i get the error 'vc01 is not connected'
3) Get-VM vm01 (which happens to be at 'vc01', that just disconnected) and it retrieves it normally
edit:
ran the command with the modifications to troubleshoot disconnection like you said, and no disconnections at all ! All the 15 vCenters still connected while running the command
The exception is below
Get-VIObjectByVIView : 25/09/2013 11:25:27 Get-VIObjectByVIView Server XXXXX is not connected.
I suspect it might be an issue with the Get-VIObjectByVIView cmdlet.
Do you also get the error when you replace line 12 by
$ghd = Get-HardDisk -VM $VM
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
the issue does not occur when i substitute the command parameter, however, the execution time went thru the roof, as i expected.
Seconds : 24
Milliseconds : 93
(Measure-Command Statistic)
I believe thats because of the string parameter, that forces get-harddisk cmdlet to create a VirtualMachine object (i believe it calls Get-VM, which is very, VERY slow. Thats why i used the Get-View with -ViewType in the first place).
Luc, is there anyway i can make this quickier without the Get-VIObjectByVIView? I tested many options while creating this script and this proved to be the most efficient one, with runtimes around 1 to 2 seconds in the same environment (as i said, the script randomly fails with the disconnection issue, sometimes i can make it work and its pretty fast )
Try like this
Function Get-VMDiskInfo {
[CmdletBinding()]
Param (
[Parameter(Mandatory=$true,
ValueFromPipeline=$True,
ValueFromPipelineByPropertyName=$true)]
[Alias('Name')]
$VM
)
PROCESS{
$VMView = Get-View -ViewType VirtualMachine -Filter @{"Name" = $VM}
$output = @()
ForEach ($VirtualSCSIController in ($VMView.Config.Hardware.Device | Where {$_.DeviceInfo.Label -match “SCSI Controller”})){
ForEach ($VirtualDiskDevice in ($VMView.Config.Hardware.Device | Where {$_.ControllerKey -eq $VirtualSCSIController.Key})){
$VMSummary = “” | Select VM,Disk, SCSI, DiskType, DiskFormat, DiskSizeGB, DiskFile
$VMSummary.VM = $VM
$VMSummary.SCSI = [string]::Concat($VirtualSCSIController.BusNumber,":",$VirtualDiskDevice.UnitNumber)
$VMSummary.Disk = $VirtualDiskDevice.DeviceInfo.Label
#pegando info do Get-Harddisks
$VMSummary.DiskType = &{
switch -regex ($VirtualDiskDevice.Backing.GetType().Name){
"Flat" {
"Flat"
if($VirtualDiskDevice.Backing.ThinProvisioned){$VMSummary.DiskFormat = "Thin"}
else{$VMSummary.DiskFormat = "Thick"}}
"Raw" {
"Raw" + $VirtualDiskDevice.Backing.CompatibilityMode.TrimEnd("Mode")
}
Default {"Unknown"}
}
}
$VMSummary.DiskSizeGB = [Math]::Round(($VirtualDiskDevice.CapacityInKb/1MB),2)
$VMSummary.DiskFile = $VirtualDiskDevice.Backing.FileName
$output += $VMSummary
}
}
Write-Output $output
}
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
simple code and trully brilliant... less than 1 second execution time
didnt know about the &{} construct... will look closely to this
Thanks really much for the PCLI lesson, Mr Dekens.. going back to study book ![]()
The & is the call operator, it executes the scriptblock that follows (everything between the curly braces).
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
