Start Virtual Machines in Order and Wait for Stabilization


Summary: Microsoft Scripting Guy, Ed Wilson, talks about using a Windows PowerShell workflow to ensure that virtual machines start in order and stabilize.

Microsoft Scripting Guy, Ed Wilson, is here. Last month, I wrote the following blog post: Use PowerShell to Start or Stop Virtual Machines in Order. The workflow worked great. The problem is that some of the virtual machines take a while to stabilize after they are running. This means that when I start virtual machines in a specific order, there needs to be a bit of a delay from the time the virtual machine is running to the time that I can sign in or connect to it from a remote machine.

I spent a lot of time working on a modification to the script. After I finished my script, I sent it to some people on the Windows PowerShell team to see if I was on the right track. Although my script worked great, it was…well…somewhat of a FrankenScript. I thought the code was confusing and downright ugly.

In a few minutes, Lee Holmes had cleaned up the script by simplifying it dramatically.

The main problem with my previous script is that when a virtual machine starts, it takes a while (depending on the machine) before it is actually usable. However, as far as Start-VM and the Windows PowerShell workflow are concerned, when the virtual machine is started, the particular activity is completed.

In my playing around, I noticed that there is a property called Heartbeat from the virtual machine object. If it has a value of OkApplicationsHealthy, the virtual machine is perfectly usable.

Note  This value is not present on a virtual machine running Windows 7 unless Virtual Machine Integration Services is updated to the latest bits.

To check for changes to the Heartbeat property, I need to do a bit of polling. However, directly inside a Windows PowerShell workflow, I cannot use a While loop. So I solved the problem by using an InlineScript activity.

This creates a new problem due to variable scoping. I had to solve that problem by using the $Using directive., and then things really get ugly. Here is the code I wrote:

  InlineScript { while (

                (Get-VM -Name $using:dc1).Heartbeat -ne 'OkApplicationsHealthy')

                { "$using:dc1 not ready…"; sleep 1}}

Like I said, it worked, but it was pretty ugly. What Lee did instead, was create a function inside the Windows PowerShell workflow. It is nice and elegant.

The other thing I had done in my workflow was use Sequence because I wanted the virtual machines to start in a specific order. Lee suggested that it would be simpler to create an array and iterate over the array. Again, the code is cleaner.

That represents the changes to my script, and here is the complete current script:

workflow Start-ScenarioVM

{

    function Wait-VM

    {

        param($Name)

        while((Get-VM -Name $Name).HeartBeat -ne  'OkApplicationsHealthy')

        {

            Start-Sleep -Seconds 1

            Write-Verbose "$name not ready. Waiting"

        }

    }

 

    foreach($vm in 'dc1_nwt', 's1_nwt', 's2_nwt', 'c1_nwt')

    {

        Start-VM -Name $vm

        Wait-VM -Name $vm

    }

} 

 

Start-ScenarioVM 

When I run the workflow, I see that the script pauses on the Wait-VM function in my status bar. This indicates that I am polling for a specific virtual machine. After the virtual machine starts, the script starts the next virtual machine, and once again, it will wait.

Image of command output

That is all there is to using Windows PowerShell workflow to start virtual machines in order. Join me tomorrow when I will talk about more cool Windows PowerShell stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

Comments (3)

  1. ratty67 says:

    I was recently trying to write a script to enable shutdown/restart/startup of our VMs. I’m sure the above will be useful when I revisit the script. Although I was testing in our LAB environment this still equated to 42 servers ! I wouldn’t like to continually
    update the server list in your script as servers were added/removed.

    There was also the issue of order. DC’s were to be shutdown last and obviously started first. To get around both of these issues I added some text to the ‘notes’ section in VM specifying an order number. Used Get-VM to get all my machiines, produced a menu
    with shutdown/restart guest options, along with power on/off options. Selected machines were then filtered on the order number and depending on which option was selected (shutdown, restarted or whatever) they were processed in the correct order. As long as
    the note was added this would work. I guess it’s even possible to create templates already containing this info so they can be selected at build time.

    The only issue I had was that all these were processed sequentially. It takes a little over an hour to process my LAB fully. I hate to think how long this would be in PROD. I think I need to investigate powershell JOBs.

  2. Anders says:

    Thx!
    Theres a typo in the While condition: ‘OkAppicationsHealthy’

  3. Wojciech Sciesinski says:

    For some A Linux based appliances (e.g. Kemp LoadMaster VLM-2000) you can also see the Heartbeat status "OkApplicationsUnknown" .

Skip to main content