VMware Cloud Community
MCarrW
Contributor
Contributor
Jump to solution

Script to wait for Clone Task to complete

Good Day, As part of the post cloning process I run a command that Enables the Nic and sets the correct Port-Group. I have put a sleep command in and each environment is diferrent so I always end up changing this sleep time because the cloning process does not complete in the sleep time frame and the rest of the script fails. So in an effort to get rid of the sleep command I want to capture the CloneVM_Task and pass that parameter to Wait-Task which will force the completion of the ClonVM_Task. I could just ensure no other tasks are running but this task but as we all know that can not alays be the case. So this is what I have done.

I Start a Deploy of OVF to have another long task running. Then I run the script.

if ( (Get-PSSnapin -Name Vmware.VimAutomation.Core -ErrorAction SilentlyContinue) -eq $null ) {Add-PSSnapin "Vmware.VimAutomation.Core"}

# Virtual Center Details
$server_address = "MYvCenter Name or IP"

Connect-VIServer -server $server_Address -user username -pass password -WarningAction SilentlyContinue


#Create Master VM Templates
#
# Here we are Importing the CSV file with the Account information and Piping it into a Foreach-object
# Creating a Variable that imports the csv file that holds all the Virtual machine data

cd 'e:\Scripts'
$InputFile = Import-Csv "E:\scripts\mycloneinput.csv"
$InputFile | ForEach-Object {

  $ip = $_.VM_IPAddress
  $GName = $_.VM_Guestname
  $TName = $_.Template_Name
  $HName = Get-VMHost "myhostname" # Select First 1
  $Desc = $_.Description
  $Dstore = $_.Datastore_Name
  $Spec = $_.Customization
  $Folder = $_.Folder
  $Sfolder = $_.Subfolder
  $NIC = $_.NIC
  $NIC_Lable = $_.NIC_Label
  $Gateway = $_.NIC_Gateway
  $SubnetMask = "255.255.255.0"
  $DNS1 = $_.DNS1
  $DNS2 = $_.DNS2

Write-host "Creating:" $GName
Write-host "Template name is:" $TName

# This takes the variables and creates the Virtual machine
    Get-OSCustomizationSpec $Spec | Get-OSCustomizationNicMapping |`
    Set-OSCustomizationNicMapping -IpMode UseStaticIP -IpAddress $ip -SubnetMask $SubnetMask -DNS $DNS1,$DNS2 -DefaultGateway $Gateway
    New-VM -Name $GName -Location $Folder -Template $TName -Host $HName -Datastore $Dstore -Description $Desc -OSCustomizationSpec $Spec -RunAsync -Confirm:$false
          
    #######################################
    #Waiting for cloning Process to finish            #
    #######################################

     $$$  Below notes show a little history of how I got to this point.

     $$$Note1: The first attempt I just captured the Running tasks and passed them to the Wait-Task. Well since both Deploy-OVF and ClonVM_Task where running it would wait until both where completed before finishing."

     $$$Note2: So then I added the If Else loop below which failed because $RTask never equaled just CloneVM_Task but was an array of two.

     $$$Note3: I tried to us the following to split the two tasks using

          ### $RTask = Get-Task -Status Running (Which captured  the two running Tasks)

          ### $Array = $Rtask.Split(" ") (Which Errored with Method invocation failed because [System.Object[]] doesn't contain a method named 'Split'.)
                         ### So I Tried to split the array like this. ForEach ($Task in $Rtask.Name -Split(" ")) { Write-Host "My Tasks are:" $Task}


    Get-Task -Status Running | Export-CSV "E:\scripts\Current_Tasks.csv"
    $InputFile2 = Import-CSV "E:\scripts\mmca\mmca_Current_Tasks.csv"
    $InputFile2 | Foreach-Object {
        $RTask = $_.Name
        Write-Host "Current task is:" $RTask
    IF ($RTask -eq "CloneVM_Task") {
        Write-Host "Current Clonning task is:" $RTask
        Write-Host "Waiting for the cloning Process to complete"
        Wait-task -task $MyTask
    }
    Else {
        Write-Host "No Cloning processes are running"
    }
}  
    
# This enables the nic and set the correct Port Group
Get-VM -name $GName | Get-NetworkAdapter -Name $NIC | Set-NetworkAdapter -NetworkName $NIC_Lable -confirm:$false -StartConnected $true
     
}

When I run this I get the following:

####This shows the Clonning Task Starting#####

erverId        : /VIServer=root@10.79.19.22:443/
State           : Running
IsCancelable    : True
PercentComplete : 5
StartTime       : 05/03/2013 00:52:13
FinishTime      :
ObjectId        : VirtualMachine-vm-382
Result          :
Description     : Clone virtual machine
ExtensionData   : VMware.Vim.Task
Id              : Task-task-2070
Name            : CloneVM_Task
Uid             : /VIServer=root@10.79.19.22:443/Task=Task-task-2070/

#########################################################

####Runs through the Running Tasks###

Current task is: Deploy OVF template
No Cloning processes are running

##### Skips the Deploy Task#####

#####Matches the If Statement and continues to process####
Current task is: CloneVM_Task
Current Clonning task is: CloneVM_Task
Waiting for the cloning Process to complete

#####Error#####

Wait-Task : Cannot bind parameter 'Task'. Cannot convert the "CloneVM_Task" value of type "System.String" to type "VMware.VimAutomation.Sdk.Types.V1.Task".
At E:\scripts\Working_Create_Master_Templates.ps1:71 char:24
+         Wait-task -task <<<<  $RTask
    + CategoryInfo          : InvalidArgument: (:) [Wait-Task], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,VMware.VimAutomation.ViCore.Cmdlets.Commands.WaitTask

$$$  Below notes show a little history of how I got to this point.

Note1: The first attempt I just captured the Running tasks and passed them to the Wait-Task. Well since both Deploy-OVF and ClonVM_Task where running it would wait until both where completed before finishing."

Note2: So then I added the If Else loop below which failed because $RTask never equaled just CloneVM_Task but was an array of two tasks.

Note3: I tried to use the following to split the two tasks:

          $RTask = Get-Task -Status Running (Which captured  the two running Tasks)

          foreach ($Task in $Rtask -Split(" "))
         {
                  Write-Host "My Tasks are:" $Task}
                   IF ($Task -eq "CloneVM_Task") {
                            Write-Host "Current Clonning task is:" $Task
                            Write-Host "Waiting for the cloning Process to complete"
                            Wait-task -task $Task
                    }
                   Else {
                            Write-Host "No Cloning processes are running"
                       }

  
          }

####Output from the little script above###

Current task is: Deploy OVF template CloneVM_Task
My Tasks are: Deploy
My Tasks are: OVF
My Tasks are: template
My Tasks are: CloneVM_Task
Current Clonning task is: CloneVM_Task
Waiting for the cloning Process to complete
Wait-Task : Cannot bind parameter 'Task'. Cannot convert the "CloneVM_Task" value of type "System.String" to type "VMware.VimAutomation.Sdk.Types.V1.Task".
At line:11 char:24
+         Wait-task -task <<<<  $Task
    + CategoryInfo          : InvalidArgument: (:) [Wait-Task], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,VMware.VimAutomation.ViCore.Cmdlets.Commands.WaitTask

   I am new to Powercli and I have been scouring Google for a possible answer. I thought I might have had a solution that was posted on the VMware PowerCLI Forum but I could not get that to work. Any help would be greatly appreciated.

#########################################

    I wasn't worried about how the Tasks where split, Unless I was trying to track the import fo the OVF, so the script went into the If loop and since one of the names matched CloneVM_Task then it processed. But i received the same error as I did in the current version of the script above. That is why I have the curent version thinking if I exported and then imported the tasks it might make a difference.

   I am new to Powercli and would like a little help. I am either very close or off by a mile. 🙂

Thanks,

Mitch

1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

Why don't you store the Task object that is returned when you use the RunAsync switch ?

You can build a loop around the State, and wait till the clone job is done.

$task = New-VM -Name MyVM ... -RunAsync 

while($task.ExtensionData.Info.State -eq "running"){   sleep 1
  $task.ExtensionData.UpdateViewData('Info.State') }

The big difference with the Wait-Task cmdlet is that this will allow you to do some additional work in the While-loop.

With Wait-Task the cmdlet just waits till the task is finisned and you can't do anything else.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

View solution in original post

3 Replies
LucD
Leadership
Leadership
Jump to solution

Why don't you store the Task object that is returned when you use the RunAsync switch ?

You can build a loop around the State, and wait till the clone job is done.

$task = New-VM -Name MyVM ... -RunAsync 

while($task.ExtensionData.Info.State -eq "running"){   sleep 1
  $task.ExtensionData.UpdateViewData('Info.State') }

The big difference with the Wait-Task cmdlet is that this will allow you to do some additional work in the While-loop.

With Wait-Task the cmdlet just waits till the task is finisned and you can't do anything else.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

MCarrW
Contributor
Contributor
Jump to solution

   Very cool, I didn't know the runasync switch captured that information but it worked like a champ. There is a lot for me to learn in order to get anywhere proficient like you. I have found many tasty morsels in your answers to help me through this process so thanks for the quick reply. One other question, is there a way to pop up a status box that shows the percentage complete like Wait-Task cmdlet does?

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

You can do that with the Write-Progress cmdlet. For example

$count = 10 
1..$count | %{     Write-Progress -Activity "Demo..." -PercentComplete ($_/$count*100) -Status "Progress"
    sleep 1
}

But you will have to find a way to pass percentage to the PercentComplete parameter.

If you have 10 tasks, you could display the progress of the number of tasks complete.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference