Home > PowerShell, vSphere > How many Powered On VMs are running on my host + Speed up your PowerCLI cmdlets!

How many Powered On VMs are running on my host + Speed up your PowerCLI cmdlets!

A rather simple script today, but we’ll discuss some nice improvements on our way…

 

Let’s say you want to know how many VMs are running on your host.  The following code will do the trick:

Get-VMHost "host" | Get-VM | Where-Object `

 {$_.PowerState -eq "PoweredOn"} | Measure-Object

It will give you a nice output like this:

image

Allright!  Script works…  but it’s rather slow.  Let’s use the Measure-Command cmdlet to see how long it actually takes in my environment.  The Measure-Command take a ScriptBlock argument at the –Expression parameter.  So pass the whole code as a scriptblock and you know how long it takes to run it.

Measure-Command -Expression {Get-VMHost "host" | `

 Get-VM | Where-Object {$_.PowerState -eq "PoweredOn"} | `

 Measure-Object}

image

3.119 seconds for this command.  Let’s see how we can optimize this.

The first piece of code is Get-VMHost “Host”.  This basically gives us an object representing our ESX Host.  If we take a look at the object returned, it contains a lot of properties.

image

All nice properties, but none of them are usefull for our script.  It would be better to fetch only the properties we need.  VMware invented the Get-View cmdlet for this.  We can specify the properties we need (which is only the ‘Name’ property in our case).

Get-View -ViewType "HostSystem" -Filter @{"Name"="Hostname"} -Property Name

The speed of both commands:

Get-VMHost

Get-View

1.80s 0.21s

Quite an improvement!

 

The second piece of code is Get-VM | Where-Object {$_.PowerState -eq “PoweredOn”}.  This looks for all Powered On VMs.  Performance-wise, this piece of code has 2 major drawbacks:

– Get-VM (as Get-VMHost) fetches a lot of properties we don’t need.

– We get a list of all VMs (which takes quite some time) and filter them afterwards.

 

A better way of doing this:

Get-View -ViewType "VirtualMachine" -Property Name `

 -Filter @{"Runtime.PowerState"="PoweredOn"}

The only ‘special’ argument is the –Filter.  This is a hashtable containing your filter of the form Key=Value.

Speed of both commands:

Get-VM

Get-View

3.76s 0.21s

An even bigger improvement!

 

Now it’s only a matter of combining these 2 cmdlets and we’re set!

Get-View -ViewType "VirtualMachine" -Property Name `

 -Filter @{"Runtime.PowerState"="PoweredOn"} `

 -SearchRoot $(Get-View -ViewType "HostSystem" `

 -Filter @{"Name"="Hostname"} -Property Name).MoRef | Measure-Object

The –SearchRoot argument is worth mentioning:

The Get-View gets all of the objects you need limited by the ViewType and the Filter.  By specifying the SearchRoot parameter, you can specify the level from where it needs to look at.  Compare it to the directory you are in at when you type the dir command.

So in our example, the SearchRoot argument contains the MoRef property of our ESX Host.  The MoRef property is the unique ID of the object which PowerCLI uses to fetch it quickly.

 

Running this script brings our execution time down from 3.119 seconds to 0.490 seconds.  This is 6 times faster!  3 Seconds in this example might already seem fast, but imagine you need to run it on several dozens of servers several times…

Advertisements
Categories: PowerShell, vSphere
  1. Mark Richter
    August 20, 2012 at 14:41

    Hi, I’d like to run a query against a specific VM to get it’s current power state using get-view to speed things up.
    Currently I do the following which is really slow:

    $vm = “servername”
    $waitVM = Get-vm $vm
    if ($waitVM.powerstate -eq “PoweredON”){
    #….some script…..
    }
    Else{
    # …..something else….
    }

    • August 27, 2012 at 08:26

      The faster way:

      $vm = “servername”
      $waitVM = Get-View -ViewType “VirtualMachine” -Filter @{“Name”=$vm} -Property @(“Runtime.PowerState”)
      if ($waitVM.runtime.powerstate -eq “PoweredON”){
      #….some script…..
      }
      Else{
      # …..something else….
      }

      Specify every property you need, because now only the runtime.powerstate will be loaded. This speeds up the cmdlet the most!
      Keep in mind that the properties of Get-VM and Get-View are all in there, they just are in different places, so you might have to search for them 🙂

      • Mark Richter
        August 28, 2012 at 10:18

        Thanks for taking the time to reply, however I seem to have found a problem with the way this works. I have 4 test servers namely
        WWWS-VM001387-Test
        WWWS-VM001387-Test2
        WWWS-VM001387-Test3
        WWWS-VM001387-Test4

        When I set $vm = “WWWS-VM001387-Test”

        and run $waitVM = Get-View -ViewType “VirtualMachine” -Filter @{“Name”=$vm} -Property @(“Runtime.PowerState”)

        I get the following from $waitVM (I’ve stripped the output to shorten the reply). It looks like the filter is querying all four servers, almost like it’s filtering using “LIKE” instead of “EQUALS”. Is this a known issue and what would be the way around it?

        Capability :
        Runtime : VMware.Vim.VirtualMachineRuntimeInfo
        GuestHeartbeatStatus : gray
        AlarmActionsEnabled : False
        MoRef : VirtualMachine-vm-17028
        Client : VMware.Vim.VimClient

        Capability :
        Runtime : VMware.Vim.VirtualMachineRuntimeInfo
        GuestHeartbeatStatus : gray
        AlarmActionsEnabled : False
        MoRef : VirtualMachine-vm-17091
        Client : VMware.Vim.VimClient

        Capability :
        Runtime : VMware.Vim.VirtualMachineRuntimeInfo
        GuestHeartbeatStatus : gray
        AlarmActionsEnabled : False
        MoRef : VirtualMachine-vm-17093
        Client : VMware.Vim.VimClient

        Capability :
        Runtime : VMware.Vim.VirtualMachineRuntimeInfo
        GuestHeartbeatStatus : gray
        AlarmActionsEnabled : False
        MoRef : VirtualMachine-vm-17095
        Client : VMware.Vim.VimClient

  2. Mark Richter
    August 28, 2012 at 10:25

    Further to this, I tried it on a server with quite a unique name, and received only that servers details which is a start, but only the data at the top level. It appears the -Property @(“Runtime.PowerState”) is being ignored. I then need to type $waitVM.Runtime.PowerState to see the powerstate.

  3. April 1, 2013 at 03:26

    wonderful put up, very informative. I ponder why the other
    experts of this sector do not realize this. You must proceed your writing.
    I am sure, you’ve a huge readers’ base already!

  1. February 27, 2013 at 18:52

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: