PowerCLI 4.1 brings the New-VIProperty cmdlet

In the new PowerCLI 4.1 build 264274 there are two new cmdlets, called New-VIProperty and Remove-VIProperty, that deserve your special attention.

The New-VIProperty cmdlet allows you to add a new properties to any PowerCLI object (InventoryItem, HostSystem, VirtualMachine…). And it’s up to you to define what the value of this new property will !

The Remove-VIProperty cmdlet allows you to remove such a new property.

These new cmdlets, combined with the new Extension property, will change several of the well established ways that you use in your PowerCLI scripts. And besides adding a lot of flexibility, the extension property will make your scripts considerably faster (if used wisely).

What is an extension property?

In short, it’s a new property you add to any of the PowerCLI objects. You select the name of the property and also what will be the value of the new property.

An example will perhaps make it clearer.

Let’s take the PowerCLI Datastore object. It’s returned by the Get-Datastore cmdlet and has the following properties.

Notice the FreeSpaceMB and CapacityMB properties, which are both giving the values in MB.

You are now tasked to create a report containing the name of the datastore and the free space in GB.

Till now you had to do something like this:

And if you wanted this in a nicer format, you could do:

But with the New-VIProperty cmdlet this can be done differently now.

First you define the new property. You specify a Name for the property, the PowerCLI object on which you want to add the new property and how the value of the new property shall be obtained/calculated.

And from now on you can use the new FreeSpaceGB property for example in a Select-Object cmdlet like this.

No more need to remember the tedious expression from before. You compose your New-VIProperty cmdlet and the new property will be there each time you retrieve a Datastore object.

Note that an extension property defined this way, will only exist for as long as you have your PowerCLI environment running.  If you restart your PowerCLI environment, the new property will not be there anymore.

If you want to have some of these new properties available each time you start your PowerCLI environment, you could for example place the New-VIProperty statements in your profile.

How to get a value in a new property?

Properties from the PowerCLI object.

In the previous example we populated the new property with a recalculated value of an existing property of the PowerCLI object. But there are other ways of setting the value of a new property.

In the sample script I used the $args[0] variable to refer to the PowerCLI object itself. You can also define the current PowerCLI object with the param statement.

New-VIProperty -Name FreeSpaceGB -ObjectType Datastore -Value {
	"{0:f1}" -f ($Args[0].FreeSpaceMB/1KB)
}

is equivalent to

New-VIProperty -Name FreeSpaceGB -ObjectType Datastore -Value {
	param($ds)

	"{0:f1}" -f ($ds.FreeSpaceMB/1KB)
}

Properties from the API object.

Suppose we are asked to provide per datastore how many guests are stored on that datastore. As always with PowerShell/PowerCLI there are many ways of doing this, but in this case we are going for the New-VIProperty cmdlet.

In the API Datastore object there is a property, called VM, that holds a MoRef to each guests stored on that datastore. If we count the number of entries in this property, we will have the number of guests.

In the latest PowerCLI build the complete API object is accessible under the ExtensionData propery. That will allow us to do something like this.

New-VIProperty -Name VMcount -ObjectType Datastore -Value {
	param($ds)

	$ds.ExtensionData.Vm.Count
}

Great, we now have access to the complete API object. No more need to do a Get-View everytime we need the API object.
But the tradeoff is that the mapping of the API object takes resources.

Your scripts will run longer when the API object has to be fetched and mapped each time a PowerCLI object is fetched.
Luckily the PowerCLI Dev Team came up with a great solution!
The ExtensionData property will only map to the API object when you access the property or any of the subproperties.
And to make it even more optimal, the Dev Team introduced the -BasedOnExtensionProperty parameter.

This parameter allows you to specify which specific properties of the API object you are going to use in the -Value script block.

That way access can even be more optimised. In our sample this would become.

New-VIProperty -Name VMcount -ObjectType Datastore -Value {
	param($ds)

	$ds.ExtensionData.Vm.Count
} -BasedOnExtensionProperty 'vm'

When you now run the Get-Datastore cmdlet against a fair number of datastores, you will notice that the execution time will have improved dramatically.

Properties from the API object with aggregation functions.

Quite often the actions you have to take for the -Value parameter are simple one-to-one mappings or any of the following aggregation functions: SUM, AVERAGE or AVG, MIN, MAX, UNIQUE, COUNT.

With the -ValueFromExtensionProperty parameter you can use a simple mapping or one of the aggregation functions without setting up a complete script block.
Our example would become

New-VIProperty -Name VMcount -ObjectType Datastore -ValueFromExtensionProperty 'COUNT vm'

This concludes my short review of the New-VIProperty and Remove-VIProperty cmdlets.

Play around with these new cmdlets and feel free to post some of the amazing use cases you will no doubt come up with.

26 thoughts on “PowerCLI 4.1 brings the New-VIProperty cmdlet

  1. Pingback: Let’s Make New-VIProperty Easier | VMware PowerCLI Blog - VMware Blogs

  2. Hello, I know VBScript fairly well and have not yet wet my feet with PowerShell. Seems that for VMWare it is becoming the de-facto scripting tool with PowerCLI.

    Can some one please elaborate on the cmdlet example to generate WebShortcut described above. It is exactly what I need; but I would like to understand the details of this line of code before I try it out.

    Also do I need to connect PowerCLI to the ESX server with the root account? Or can I use a Windows account?

    Thanks!

    • @Arkady.
      The WebShortcutURL is primarily doing string manipulation to construct the URL. It’s not your typical PowerCLI script.
      William gives a description of the procedure to generate such an URL in his generateVMRemoteConsoleURL.pl post.
      Btw the URL is constructed differently for API 4 and API 5.

  3. Pingback: Number of Physical & Virtual CPU’s per host & Cluster « « Virtu-AlVirtu-Al

  4. Pingback: Características avanzadas de la powerCLI | El Blog de Virtualizacion en español

  5. Hi LucD,

    I’m trying to use the New-VIProperty cmdlt to add a new property to a vdisk object (let’s call it “scsiID” that contains a string like “scsix:x” for each of the vDisks of a VM so I can filter the performance data of each vdisk on a datastore

    $DS | get-harddisk | foreach {

    $disk=$_

    get-stat -entity $_.parent -stat virtualDisk.read.average -realtime | where {$disk.scsiID -eq $_.instance}

    }

    Thanks !

    • Hi Harkamal.
      No it doesn’t, in fact it doesn’t survive a PowerCLI session.
      The definitions you create with the New-VIProperty cmdlet are only known in your PowerCLI session. If you stop/start your PowerCLI session (the prompt), the definitions are gone.
      Best way, in my opinion, to have them permanent would be to have them defined in your PowerShell profile.

  6. Pingback: PowerCLI 4.1 New-VIProperty Performance test | Arnim van Lieshout

  7. Pingback: Episode 119 – Adam Driscoll on PowerGUI Visual Studio Extensions « PowerScripting Podcast

  8. Another nice property is the WebShortcut URL that you can generate from vSphere Web Access with the “Generate Virtual Machine Shortcut” command. With this URL you can access the virtual machine’s console via a web browser. Now you don’t have to go into vSphere Web Access anymore to generate the URL.

    # Add the WebShortcut URL to virtual machines.
    New-VIProperty -Name WebShortcut -ObjectType VirtualMachine -Value {
    $vCenterServer = $Args[0].Uid.Split(“:”)[0].Split(“@”)[1]
    $Id = $Args[0].Id.Replace(“e-v”,”e|v”)
    “https://$vCenterServer/ui/?wsUrl=http://localhost:80/sdk&mo=$Id&inventory=none&tabs=hide_”
    }

  9. Pingback: Collect VMware ESX Host PCI Device Information | Arnim van Lieshout

  10. Another interesting property:

    # Add the name of the vCenter Server to virtual machines.
    New-VIProperty -Name vCenterServer -ObjectType VirtualMachine -Value {$Args[0].Uid.Split(“:”)[0].Split(“@”)[1]}

  11. Here is a property that I think is interesting:

    # Add the BootTime to VMs
    New-VIProperty -ObjectType VirtualMachine -name BootTime -ValueFromExtensionProperty Summary.Runtime.BootTime -Force

  12. Hi Luc,

    This is great. I can see many possibilties with this facility.

    One thing. Might be easy for a guru… :) The example you give above with the FreeSpace GB. The “nice” output ie ….{“0:f1″} -f … bit produces the output in a string format. That way, I can’t check for a less than or I can’t order by size etc, in reports. Can we produce that ouptut as a number that can be manipulated ?

    Thanks

    • Sure you can.
      If you want a number you can use the Round function.
      Something like this:


      New-VIProperty -Name FreeSpaceGB -ObjectType Datastore -Value {
      param($ds)

      [Math]::Round($ds.FreeSpaceMB/1KB,1)
      }

      The value will be rounded to 1 decimal digit but it will stay a Double.

  13. So much nicer than before :)

    Time to go rewrite a handful of my favorite scripts/reports. :)

  14. I really love this blog…

    I grabbed Powercli 4.1 this morning and wondered what new things I could play with and already a post on it !

    Great work LucD!

  15. Here are some properties I think are interesting:

    # Add the tools version to VMs.
    New-VIProperty -ObjectType VirtualMachine -name ToolsVersion `
    -ValueFromExtensionProperty ‘config.tools.ToolsVersion’ -Force

    # Add the number of VMs per host to the host object.
    New-VIProperty -ObjectType VMHost -name NumberOfVMs `
    -Value { ($args[0] | Get-VM | Measure-Object).Count } -Force

    # Host average CPU usage last 24 hours.
    New-VIProperty -ObjectType VMHost -name AvgCPUUsage24Hr `
    -Value {
    “{0:f2}” -f
    ($args[0] |
    Get-Stat -stat cpu.usage.average |
    Where { $_.Instance -eq “” } |
    Measure-Object -Property Value -Average
    ).Average } -Force

  16. Pingback: vSphere 4.1 released « TheSaffaGeek

  17. Awesome blogpost Luc! And so quick after the release of PowerCLI 4.1. It looks like we can rewrite a lot of scripts to make them easier and faster.

    • Thanks Robert.
      I’m not that fast, I had access to a preview ;-)

      But you’re right, this cmdlet opens a lot of new possibilities. Many scripts can be rewritten and streamlined.

  18. Pingback: Tweets that mention PowerCLI 4.1 brings the New-VIProperty cmdlet | LucD notes -- Topsy.com

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>