Automation

 View Only
Expand all | Collapse all

Problem with Wait-Task

  • 1.  Problem with Wait-Task

    Posted Aug 03, 2011 08:12 PM

    I have been trying to automate the reset of a lab environment with PowerCLI. This lab consists of 15 sets of 3 VMs. Each set contains one XP, one Server 2008, and one Linux appliance. The virtual machines are created from templates and are assigned to specific usernames. Automating this process would seriously help out the technicians whose responsibilities

    The script (which is listed below) has the following functions created and working:

    1) DeleteOldVMs - Stops the existing virtual machines and then deletes them from disk

    2) CreateVMSet - Creates each of the 3 virtual machines necessary for each user.

    3) StartNewVMs - Starts all newly created virtual machines

    4) AssignUserToVM - Assign rights to the virtual machine sets to each user

    My final problem is the overlap of the Start-VM task and the New-VM tasks. The New-VM task needs to complete before I assign rights to VMs and start them. I've tried using Wait-Task, but I haven't had any luck. I currently have the Wait-Task sections removed from the script. I'm looking for any suggestions as to how I can properly implement Wait-Task to force the script to wait until the VM sets are created before proceeding.

    My only other thought was using Start-Sleep for a predetermined amount of time.

    Any thoughts?

    Here is the script:

    Function  AssignUserToVM

    {    

          $xpvm = get-vm WinXP-$n

          $winvm = get-vm Win2008-$n

          $vistavm = get-vm OpenVista-$n

          #$emrvm = get-vm OpenEMR-$n

          New-VIPermission -Entity $xpvm -Principal "ehr$n" -Role EHR822VirtualMachineUser -Propagate $false

          New-VIPermission -Entity $WinVM -Principal "ehr$n" -Role EHR822VirtualMachineUser -Propagate $false

          New-VIPermission -Entity $vistavm -Principal "ehr$n" -Role EHR822VirtualMachineUser -Propagate $false

          #New-VIPermission -Entity $emrvm -Principal "ehr$n" -Role EHR822VirtualMachineUser -Propagate $false

    }

    Function CreateVMSet

    {

          #Create XP VM

          $XPTemplate = Get-Template -Name "Template-WinXPPro"

          $XPSpec = Get-OSCustomizationSpec -Name "Windows XP"

          $XPVMName = "WinXP-$n"

          New-VM -VMHost "$VMhost" -Name "$XPVMName" -Template "$XPTemplate" -OSCustomizationSpec $XPSpec -Location $VMLocation

        

          #Create 2008 VM

          $2008Template = Get-Template -Name "Template-Win2008-32"

          $2008VMName = "Win2008-$n"

          $2008Spec = Get-OSCustomizationSpec -Name "Windows Server 2008"

          $VMhost = Get-VMHost

          New-VM -VMHost $VMhost -Template $2008Template -Name $2008VMName -OSCustomizationSpec $2008Spec -Location $VMlocation          

          #Create OpenVistA VM

          $OpenVistATemplate = Get-Template -Name "Template-OpenVistA-Appliance"

          $OpenVistaVMName = "OpenVista-$n"

          New-VM -VMHost $VMhost -Name $OpenVistaVMName -Template $OpenVistATemplate -Location $VMlocation

    }

    Function StartNewVMs

    {

          Start-VM -VM "Win2008-*"

          Start-VM -VM "WinXP-*"

          Start-VM -VM "OpenVista-*"

    }

    Function DeleteOldVMs

    {

          Stop-VM -VM "Win2008-*"

          Stop-VM -VM "WinXP-*"

          Stop-VM     -VM "OpenVista-*"

          Remove-VM -VM "Win2008-*" -DeletePermanently

          Remove-VM -VM "WinXP-*" -DeletePermanently

          Remove-VM -VM "OpenVista-*" -DeletePermanently

    }

    Write-Host "Please enter your AD credentials: "

    $vCenterCredential = Get-Credential

    $VMhost = "hitecvsphere.ccbcmd.edu"

    $vCenter = "hitechvcenter.ccbc.ccbcmd.edu"

    $VMlocation = "AHL822"

    Connect-VIServer -Server $vCenter -Credential $vCenterCredential

    $NumVMsToCreate = Read-Host "Enter the number of virtual machine sets that you wish to create: "

    DeleteOldVMs

    $n = 1

    while ($n -le $NumVMsToCreate)

    {

          CreateVMSet

          $n++

    }

    StartNewVMs

    $n = 1

    while ($n -le $NumVMsToCreate)

    {

          AssignUserToVM

          $n++

    }



  • 2.  RE: Problem with Wait-Task

    Posted Aug 03, 2011 08:24 PM

    You encountered a classical problem, how to know when the OS customisation inside the VM is ready.

    There are several methods of doing that, but each of them has some flaws I'm afraid.

    Are these VMs added to an AD domain ?

    If yes, you could query AD to check if the VM entry is already there. The Quest AD snapin is ideal for that.

    The easiest way is indeed to use a Sleep statement and wait for long enough till the OS customisation is completely finished.

    Problem is that you probably have to waste time since the sleep time must be long enough to accomodate all situations.

    Another trick that can be used is to set a specific registry key or create a file at the end of the customisation process.

    You can then test if that eye-catcher is present.



  • 3.  RE: Problem with Wait-Task

    Posted Aug 03, 2011 08:30 PM

    No, these machines aren't added to a domain.

    The delay seems to actually be during the cloning process. The Start-VM section still trips up even if I do not use the customization. That implies to me that I would need either a significant sleep or to use Wait-Task.



  • 4.  RE: Problem with Wait-Task

    Posted Aug 03, 2011 08:41 PM

    The Wait-Task cmdlet will not work in my experience.

    Note that for specific Windows versions, the clone process will always schedule a SID change, and hence the sysprep.exe will run.

    Which specific message do you get from the Start-VM cmdlet ?

    VM not found or something similar ?



  • 5.  RE: Problem with Wait-Task

    Posted Aug 03, 2011 09:01 PM

    This is the test script I wrote to attempt to use Wait-Task.

    $n = Read-Host "Enter a number: "

    $iterator = 1

    $VMlocation = "AHL822Test"

    $TestTemplate = Get-Template -Name "Template-WinXPPro"

    $TestSpec = Get-OSCustomizationSpec -Name "Windows XP"

    $VMhost = Get-VMHost

    while ($iterator -le $n)

    {

          $TestVMName = "XPTest-$iterator"

          $Task1 = New-VM -VMHost $VMhost -Template "$TestTemplate" -Name "$TestVMName" -OSCustomizationSpec "$TestSpec" -Location "$VMlocation" -RunAsync

          Wait-Task -Task $Task1

          Write-Host "$TestVMName has been built."

          $iterator++

    }

    while ($iterator -le $n)

    {

          Start-VM -VM $TestVMName -RunAsync | Wait-Task

        

          $iterator++

    }

    $iterator = 1

    while ($iterator -le $n)

    {

          $TestVMName = "XPTest-$iterator"

        

          Stop-VM -VM $TestVMName

          Remove-VM -VM $TestVMName -DeletePermanently

        

          $iterator++

    }

    When I run this, I get the following error:

    Wait-Task : 8/3/2011 3:42:59 PM Wait-Task Operation is not valid due to the current state of the

    object.

    At \\cwfs\users\SDmccart\PS\wait-task-test.ps1:13 char:11

    + Wait-Task <<<< -Task $Task1

    + CategoryInfo : NotSpecified: (:) [Wait-Task], VimException

    + FullyQualifiedErrorId : Core_BaseCmdlet_UnknownError,VMware.VimAutomation.ViCore.Cmdlets.Commands.WaitTask



  • 6.  RE: Problem with Wait-Task

    Posted Aug 03, 2011 09:03 PM

    You'll note the core error: " Operation is not valid due to the current state of the object."

    This is the same error I get from Start-VM and Set-VIPermission



  • 7.  RE: Problem with Wait-Task
    Best Answer

    Posted Aug 03, 2011 09:10 PM

    Yes, that because the VM is still being created when the Wait-Task already get's the signal that the task has finished.

    Did you try inserting a 'Sleep 30' for example ?

    Btw, using -RunAsync on the New-VM, immediately followed by a Wait-Task for that New-VM cmdlet, is in my opinion the same as running New-VM without the RunAsync parameter and not using the Wait-Task cmdlet.

    The real value, imho, of using the RunAsync parameter, is when you launch a bunch of New-VM cmdlets, and once they are all executed you start a Wait-Task loop. See my About Async tasks, the Get-Task cmdlet and a hash table post for an example of what I'm trying to say here.



  • 8.  RE: Problem with Wait-Task

    Posted Aug 04, 2011 02:14 AM

    Hello, Brutilus-

    Luc had some helpful suggestions, but I think that the issue here is simpler than wanting to be sure that the OSCustomization completes -- it looks like you are just wanting to time the StartNewVMs and AssignUserToVM pieces to be sure that they come after the New-VM piece completes.  I typed up a few ways that you could handle this scenario.
    One, you could just pipe the New-VM cmds to Start-VM like:

    ## in the CreateVMSet() function, add inline Start-VM
    ...
    New-VM -VMHost "$VMhost" -Name "$XPVMName" -Template "$XPTemplate" -OSCustomizationSpec $XPSpec -Location $VMLocation | Start-VM -Confirm:$false
    ...

    Drawback:  this deploys the VMs in series, instead of in parallel, which can greatly increase the overall run time.  But, in this scenario, you do not have the separate StartNewVMs function and have the worry about the timing.

    Another way would be to run the New-VM cmds asynchronously (which continues on with the script after each VM clone begins), get the currently running CloneVM tasks, wait on them, and then start all of the VMs (might worry about a boot storm and performance, if many VMs), like:

    ## in the CreateVMSet() function 
    ...
    New-VM -VMHost "$VMhost" -Name "$XPVMName" -Template "$XPTemplate" -OSCustomizationSpec $XPSpec -Location $VMLocation -RunAsync
    ...

    And then, in the StartNewVMs function, add the part to wait on the CloneVM tasks:

    ## get all of the CloneVM_Task tasks that are still running and wait for them to complete
    Get-Task -Status Running | ?{$_.Name -eq "CloneVM_Task"} | Wait-Task
    ## start all of the now-deployed VMs (again, beware of boot storm)
    Start-VM -VM Win2008-*,WinXP-*,OpenVista-* -Confirm:$false

    Yet another way may be to use the method that Luc described in the link to his reply about another way to use Get-Task.

    How do these do for you?



  • 9.  RE: Problem with Wait-Task

    Posted Aug 04, 2011 01:24 PM

    Unfortunately, I get this error when I attempt to use the Get-Task | Wait-Task method.

    Wait-Task : 8/4/2011 8:50:25 AM    Wait-Task        Operation is not valid due to the current state of the
    object.   
    At \\cwfs\users\SDmccart\PS\wait-task-test.ps1:14 char:70
    +     Get-Task -Status Running | ?{$_.Name -eq "CloneVM_Task"} | Wait-Task <<<<
        + CategoryInfo          : NotSpecified: (:) [Wait-Task], VimException
        + FullyQualifiedErrorId : Core_BaseCmdlet_UnknownError,VMware.VimAutomation.ViCore.Cmdlets.Commands.Wa
       itTask

    When I put the in-line Start-VM, I get the following error:

    New-VM : 8/4/2011 9:18:48 AM    New-VM        Operation is not valid due to the current state of the object

    .   

    At \\cwfs\users\SDmccart\PS\wait-task-test.ps1:12 char:8

    +     New-VM <<<<  -VMHost $VMhost -Template "$TestTemplate" -Name "$TestVMName" -OSCustomizationSpec "$Tes

    tSpec" -Location "$VMlocation" | Start-VM

        + CategoryInfo          : NotSpecified: (:) [New-VM], VimException

        + FullyQualifiedErrorId : Core_BaseCmdlet_UnknownError,VMware.VimAutomation.ViCore.Cmdlets.Commands.Ne

       wVM

    On the upside, Start-Sleep works fine to balance everything out.



  • 10.  RE: Problem with Wait-Task

    Posted Aug 04, 2011 01:35 PM

    You might have run against the problem in this thread:

    New-VM error (Operation is not valid due to the current state of the object.).

    You can try the WaitTask.ps1 script that Vitali provides in that thread as a workaround.

    Regards, Robert



  • 11.  RE: Problem with Wait-Task

    Posted Aug 04, 2011 03:39 PM

    I've implemented the final script using a Start-Sleep method. No other suggested method was able to produce viable results. My most common error was "Operation is not valid due to the current state of the object."

    Even the suggested running of WaitTask.ps1 threw errors delaying the process.

    Using Start-Sleep, I initiate a 1 hour delay of processing immediately after beginning creation of all virtual machines. This delay will be reduced and tweaked after I determine how much time is actually need. This does allow for a "start it and walk away" approach that the technicians in lower tiers will need.

    Thanks to everyone for your help and suggestions!

    Here is the final script:

    Function  AssignUserToVM

    {

          $xpvm = get-vm WinXP-$n

          $winvm = get-vm Win2008-$n

          $vistavm = get-vm OpenVista-$n

          #$emrvm = get-vm OpenEMR-$n

          New-VIPermission -Entity $xpvm -Principal "ehr$n" -Role EHR822VirtualMachineUser -Propagate $false

          New-VIPermission -Entity $WinVM -Principal "ehr$n" -Role EHR822VirtualMachineUser -Propagate $false

          New-VIPermission -Entity $vistavm -Principal "ehr$n" -Role EHR822VirtualMachineUser -Propagate $false

          #New-VIPermission -Entity $emrvm -Principal "ehr$n" -Role EHR822VirtualMachineUser -Propagate $false

    }

    Function CreateVMSet

    {

          #Create XP VM

          $XPTemplate = Get-Template -Name "Template-WinXPPro"

          $XPSpec = Get-OSCustomizationSpec -Name "Windows XP"

          $XPVMName = "WinXP-$n"

          New-VM -VMHost "$VMhost" -Name "$XPVMName" -Template "$XPTemplate" -OSCustomizationSpec $XPSpec -Location $VMLocation

       

          #Create 2008 VM

          $2008Template = Get-Template -Name "Template-Win2008-32"

          $2008VMName = "Win2008-$n"

          $2008Spec = Get-OSCustomizationSpec -Name "Windows Server 2008"

          $VMhost = Get-VMHost

          New-VM -VMHost $VMhost -Template $2008Template -Name $2008VMName -OSCustomizationSpec $2008Spec -Location $VMlocation -ErrorAction Inquire

             

          #Create OpenVistA VM

          $OpenVistATemplate = Get-Template -Name "Template-OpenVistA-Appliance"

          $OpenVistaVMName = "OpenVista-$n"

          New-VM -VMHost $VMhost -Name $OpenVistaVMName -Template $OpenVistATemplate -Location $VMlocation

    }

    Function CreateOpenEMR

    {

          Stop-VM -VM "OpenEMR*"

          Remove-VM -VM "OpenEMR*"

          $OpenEMRTemplate = "Template-Open-EMR-3.2"

          $OpenEMRVMName = "OpenEMR-3.2"

          New-VM -VMHost $VMhost -Name $OpenEMRVMName -Template $OpenEMRTemplate -Location "HITECH"

    }

    Function StartNewVMs

    {

          Start-VM -VM "Win2008-*"

          Start-VM -VM "WinXP-*"

          Start-VM -VM "OpenVista-*"

    }

    Function DeleteOldVMs

    {

          Stop-VM -VM "Win2008-*"

          Stop-VM -VM "WinXP-*"

          Stop-VM     -VM "OpenVista-*"

          Remove-VM -VM "Win2008-*" -DeletePermanently

          Remove-VM -VM "WinXP-*" -DeletePermanently

          Remove-VM -VM "OpenVista-*" -DeletePermanently

    }

    Write-Host "Please enter your AD credentials: "

    $vCenterCredential = Get-Credential

    $VMhost = "hitecvsphere.ccbcmd.edu"

    $vCenter = "hitechvcenter.ccbc.ccbcmd.edu"

    $VMlocation = "AHL822"

    Connect-VIServer -Server $vCenter -Credential $vCenterCredential

    $NumVMsToCreate = Read-Host "Enter the number of virtual machine sets that you wish to create: "

    DeleteOldVMs

    $n = 1

    while ($n -le $NumVMsToCreate)

    {

          CreateVMSet

          $n++

    }

    #CreateOpenEMR

    Start-sleep -Seconds 3600

    StartNewVMs

    $n = 1

    while ($n -le $NumVMsToCreate)

    {

          AssignUserToVM

          $n++

    }



  • 12.  RE: Problem with Wait-Task

    Posted Aug 05, 2011 02:21 AM

    Hello, Brutilus-

    Interesting point in the thread that Robert posted -- the user having the "Operation is not valid due to the current state of the object" error was running his script from within PowerGUI, not directly in a PowerShell session (with the proper PSSnapin loaded, or in a "PowerCLI" session).

    And, when he ran the same code directly in a PowerCLI session, it worked without error (per his post at the bottom of the first page of replies).

    Are you, by chance, running the script/commands in something like PowerGUI or the PowerShell ISE, or are you running this straight in a PowerShell/PowerCLI session?  Just wondering if this is related...

    Message was edited by mattboren:  added info about the other user's success when running directly in PowerCLI session



  • 13.  RE: Problem with Wait-Task

    Posted Aug 05, 2011 12:58 PM

    I am running it in a PowerGUI session. I will have to test this in a PowerCLI session again. The last time I tried the script in a PowerCLI session, I was still getting the same errors, however.

    I'll try it again in 2 weeks (after the class has run) and post my results.