Automation

 View Only
  • 1.  Variance in VM Object Type

    Posted May 31, 2022 03:31 PM

    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
    )



  • 2.  RE: Variance in VM Object Type

    Posted May 31, 2022 03:41 PM

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



  • 3.  RE: Variance in VM Object Type

    Posted May 31, 2022 03:52 PM

    Alas, that is not the case,  

    > $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



  • 4.  RE: Variance in VM Object Type
    Best Answer

    Posted May 31, 2022 04:01 PM

    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.

     



  • 5.  RE: Variance in VM Object Type

    Posted May 31, 2022 04:03 PM

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

    > 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.

     

     



  • 6.  RE: Variance in VM Object Type

    Posted May 31, 2022 04:05 PM

    Did you read my last reply?



  • 7.  RE: Variance in VM Object Type

    Posted May 31, 2022 04:23 PM

    I did,   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/



  • 8.  RE: Variance in VM Object Type

    Posted May 31, 2022 05:40 PM

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