VMware Cloud Community
Dharzhak
Enthusiast
Enthusiast
Jump to solution

Variance in VM Object Type

This isn't a question, so much as pointing out a current issue with Get-VM. Depending on how you use it to query VM objects (by name only or by location (via pipeline or -Location <object>), you get a different object type. (Note that this only applies to VMs. I didn't observe the same type of issue with other objects, such as VMHosts or Clusters.)

The following was done using VMware.VimAutomation.Core 12.6.0.19601570 on vCenter 7.0.3:

> $VMObjs = Get-VM -Server $VIConnection
> $VMObjs[0].GetType().Name
UniversalVirtualMachineImpl
> $VMObjs[0] | Get-Member
TypeName: VMware.VimAutomation.ViCore.Impl.V1.VM.UniversalVirtualMachineImpl
<snip>

> $VMObjs = Get-VM -Server $VIConnection -Location (Get-VMHost -Server $VIConnection)
> $VMObjs[0].GetType().Name
VirtualMachineImpl
> $VMObjs[0] | Get-Member
TypeName: VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl
<snip>

> $VMObjs = Get-VMHost -Server $VIConnection | Get-VM
> $VMObjs[0].GetType().Name
VirtualMachineImpl
> $VMObjs[0] | Get-Member
TypeName: VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl
<snip>

As such, I would suggest that anyone writing a function that requires a -VM parameter save themselves some frustration and do something like this:

param (
    [Parameter (
        ValueFromPipeline = $true,
        ValueFromPipelineByPropertyName = $true,
        Mandatory = $true
    )]
    [ValidateScript(
        {
            $_.GetType().Name -in "VirtualMachineImpl", "UniversalVirtualMachineImpl"
        }
    )]
    [ValidateNotNullOrEmpty()]
    [Object[]]$VM
)

Reply
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

Not if you use that type, but have a look at PowerCLI Best Practice: Correct Use of Strong Typing

Following those guidelines, my test function works in both cases.

function Invoke-Test {
param(
  [VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine]$vm
)

$vm.Name
}

Invoke-Test -VM (Get-VM -Name MyVM)
Invoke-Test -VM (Get-VM -Name MyVM -Location (get-VMHost -Name MyEsx))

 


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

View solution in original post

7 Replies
LucD
Leadership
Leadership
Jump to solution

Why the validation script?
You can just define the type, one is a subclass of the other, so you should be fine.


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

Reply
0 Kudos
Dharzhak
Enthusiast
Enthusiast
Jump to solution

Alas, that is not the case, @LucD 

> $VMObjs[0].GetType().Name
VirtualMachineImpl
> function Invoke-TestFunction {
>> [CmdletBinding()]
>>
>> Param (
>> [Parameter (
>> ValueFromPipeline = $true,
>> ValueFromPipelineByPropertyName = $true,
>> Mandatory = $true
>> )]
>> [ValidateNotNullOrEmpty()]
>> [VMware.VimAutomation.ViCore.Impl.V1.VM.UniversalVirtualMachineImpl[]]$VM
>> )
>>
>> process {
>> foreach ($VMObj in $VM) {
>> Write-Output $VMObj.Name
>> }
>> }
>> }
> Invoke-TestFunction -VM $VMObjs
Invoke-TestFunction : Cannot process argument transformation on parameter 'VM'. Cannot convert the
"vCLS-<random chars>" value of type
"VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl" to type
"VMware.VimAutomation.ViCore.Impl.V1.VM.UniversalVirtualMachineImpl".
At line:1 char:25

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Not if you use that type, but have a look at PowerCLI Best Practice: Correct Use of Strong Typing

Following those guidelines, my test function works in both cases.

function Invoke-Test {
param(
  [VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine]$vm
)

$vm.Name
}

Invoke-Test -VM (Get-VM -Name MyVM)
Invoke-Test -VM (Get-VM -Name MyVM -Location (get-VMHost -Name MyEsx))

 


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

Dharzhak
Enthusiast
Enthusiast
Jump to solution

...and yes, the same thing in reverse produces the same error, @LucD 

> function Invoke-TestFunction {
>> [CmdletBinding()]
>>
>> Param (
>> [Parameter (
>> ValueFromPipeline = $true,
>> ValueFromPipelineByPropertyName = $true,
>> Mandatory = $true
>> )]
>> [ValidateNotNullOrEmpty()]
>> [VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl[]]$VM
>> )
>>
>> process {
>> foreach ($VMObj in $VM) {
>> Write-Output $VMObj.Name
>> }
>> }
>> }
> $VMObjs[0].GetType().Name
UniversalVirtualMachineImpl
> Invoke-TestFunction -VM $VMObjs
Invoke-TestFunction : Cannot process argument transformation on parameter 'VM'. Cannot convert the
"VMNAME" value of type "VMware.VimAutomation.ViCore.Impl.V1.VM.UniversalVirtualMachineImpl"
to type "VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl".
At line:1 char:25
+ Invoke-TestFunction -VM $VMObjs
+ ~~~~~~~
+ CategoryInfo : InvalidData: (:) [Invoke-TestFunction], ParameterBindingArgumentTransformationException
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,Invoke-TestFunction

What version of PowerCLI (VMware.VimAutomation.Core) and PowerShell are you using? While, this could be an issue with Windows PowerShell vs. PowerShell Core, I am a bit concerned that Get-VM produces multiple object types.

 

 

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Did you read my last reply?


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

Reply
0 Kudos
Dharzhak
Enthusiast
Enthusiast
Jump to solution

I did, @LucD  I just didn't catch that the difference between 
VMware.VimAutomation.ViCore.Types.V1.Inventory.VirtualMachine
and 
VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl

All right. That works. Much cleaner parameter definition.

I note that the linked blog article only discusses VM Objects. I suppose that's fine since this is only an issue for them. In all other cases, just getting the type from Get-Member works just fine. That said, a full list of object types would probably be a good resource to have for folks. (Not suggesting you do it; just musing.)

Thanks for the assist.

Edit: Apparently, VMware has actually provided such a resource already:
https://developer.vmware.com/docs/powercli/latest/products/vmwarevsphereandvsan/all-structures/

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

That strong type rule works for most objects, replace Impl by Types and drop the Impl suffix.


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

Reply
0 Kudos