I use the clone_vm sdk way to deploy vm's.
Thanks to luc sample code, i have a way of checken the clone task, so i can log when there is an error:
#CHECK THE TASK
while ($task.info.state -eq "running" -or $task.info.state -eq "queued")
{
sleep 2
$task = Get-View $taskMoref
}
But now i am facing a problem, i wan't to clone 2 vm's at once. So i can speed up deployment. I created a counter to do that, but the while statement waits until it's loop has finished.
Is there a way to keep the while statement and have 2 clone jobs?
Rob, great. Here is my version for VITK 1.5 and a few fixes:
1) there was 1 flaw in that the loop would allow $maxTask + 1 tasks to be running. The test was changed from -gt to -ge
2) there is an extra while loop after the main loop. This should allow you to perform the logging for the last tasks
$tasks = @{} $maxTask = 2 # Main loop .. foreach($vmmorview in ...){ .... # Start task $taskMoref = $vmmorview.CloneVM_Task($targetview.MoRef,$vmname, $vmcSpec ) # Store the Task object in the hash table with the key Task.value $tasks[http://$taskMoRef.value|http://$taskMoRef.value] = $taskMoRef # Do we have $maxTask tasks running ? while($tasks.Count -ge $maxTask){ # Put all Task object on the pipe as (Name,Value) where Value is the actual Task object $tasks.GetEnumerator() | % { $task = Get-View $_.Value # Check if the task is not queued nor running. if($task.Info.State -ne "running" -and $task.Info.State -ne "queued"){ # Remove the task from the hash table $tasks.Remove($_.Value.Value) # Jump out of the foreach loop continue } } sleep 5 } } while($tasks.Count -gt 0){ # Put all Task object on the pipe as (Name,Value) where Value is the actual Task object $tasks.GetEnumerator() | % { $task = Get-View $_.Value # Check if the task is not queued nor running. if($task.Info.State -ne "running" -and $task.Info.State -ne "queued"){ # Remove the task from the hash table $tasks.Remove($_.Value.Value) # Jump out of the foreach loop continue } } sleep 5 }
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Rob, I think we can do this with a hash table ($tasks) and maximum number of tasks variable ($maxTask).
Have a look at the following skeleton code and let me know if it works for you
$tasks = @{} $maxTask = 2 # Main loop .... # Start clone task $task = Get-View ($vm.CloneVM_Task(...)) $tasks[http://$task.value|http://$task.value] = $task #CHECK THE TASK while($tasks.Count -gt $maxTask){ $tasks.GetEnumerator() | %{ $_.Value.UpdateViewData("Info.State") if($_.Value.Info.State -ne "running" -and $_.Value.Info.State -ne "queued"){ $tasks.Remove($_.Name) continue } } sleep 5 }
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Hi Luc,
Thanks for the input. I do not quit understand the code.
Is http:// in the code corrent?
No, it's not. Stupid forum SW did this.
Attached the code.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Oke that makes things more clear.
Except the $task = Get-View ($vm.CloneVM_Task(...))
At the moment i use this:
$taskMoref = $vmmorview.CloneVM_Task($targetview.MoRef,$vmname, $vmcSpec )
$task = Get-View $taskMoref
Can i use that?
There is no need to use the MoRef directly anymore.
The script uses the Task object directly.
The hash table uses the MoRef.Value property (the "task-9999" part) as the key in the hash table.
I have added some annotations to the attached script.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Hi luc,
Thanks for the update. At the moment i am to busy to change the script.
I still use the vitoolkit 1.5, and that will stay a whil untill our next major infrastructure release.
No problem Rob.
The script should also work with VITK 1.5 since it doesn't use anything specific from PowerCLI v4 (afaik).
Let me know when you encounter a problem.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Hi Luc,
I am testing the code, but when 2 clone tasks are in progress, it starts a third one and the script fails.
I get the following error.
Rob, I can't see the error message in your last post.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Luc,
This is what i get:
cmdlet % at command pipeline position 1
Supply values for the following parameters:
I got it working.
Here is the code:
#START CLONE TASK
$taskMoref = $vmmorview.CloneVM_Task($targetview.MoRef,$vmname, $vmcSpec )
#GET THE TASK OBJECT
$task = Get-View $taskMoref
#STORE THE TASK OBJECT IN THE HASH TABLE WITH THE KEY TASK.VALUE
$tasks[$vmname] = $taskMoref
#CHECK THE TASK
#DO WE HAVE MORE THAN $MAXTASK TASKS RUNNING ?
while($tasks.Count -gt $maxTask)
{
#PUT ALL TASK OBJECT ON THE PIPE AS (NAME,VALUE) WHERE VALUE IS THE ACTUAL TASK OBJECT
$tasks.GetEnumerator() | % {
#GET THE LATEST STATUS OF THE TASK
$gettaskstate = get-view $_.value
$taskstate = $gettaskstate.info.state
$taskname = $_.Name
#CHECK IF THE TASK IS NOT QUEUED NOR RUNNING
if($taskstate -ne "running" -and $taskstate -ne "queued")
{
#REMOVE THE TASK FROM THE HASH TABLE
WRITE_LOG "[SUCCESS] DEPLOYING: $taskname"
$tasks.Remove($_.Key)
#JUMP OUT OF THE FOREACH LOOP
continue
}
}
sleep 5
}
{/noformat}
Only i have one problem remaining.
When the last jobs is in progress the while loop is gone. Which means i can't log it when the clone task is ready.
Who has a smart solution for that?
Rob, great. Here is my version for VITK 1.5 and a few fixes:
1) there was 1 flaw in that the loop would allow $maxTask + 1 tasks to be running. The test was changed from -gt to -ge
2) there is an extra while loop after the main loop. This should allow you to perform the logging for the last tasks
$tasks = @{} $maxTask = 2 # Main loop .. foreach($vmmorview in ...){ .... # Start task $taskMoref = $vmmorview.CloneVM_Task($targetview.MoRef,$vmname, $vmcSpec ) # Store the Task object in the hash table with the key Task.value $tasks[http://$taskMoRef.value|http://$taskMoRef.value] = $taskMoRef # Do we have $maxTask tasks running ? while($tasks.Count -ge $maxTask){ # Put all Task object on the pipe as (Name,Value) where Value is the actual Task object $tasks.GetEnumerator() | % { $task = Get-View $_.Value # Check if the task is not queued nor running. if($task.Info.State -ne "running" -and $task.Info.State -ne "queued"){ # Remove the task from the hash table $tasks.Remove($_.Value.Value) # Jump out of the foreach loop continue } } sleep 5 } } while($tasks.Count -gt 0){ # Put all Task object on the pipe as (Name,Value) where Value is the actual Task object $tasks.GetEnumerator() | % { $task = Get-View $_.Value # Check if the task is not queued nor running. if($task.Info.State -ne "running" -and $task.Info.State -ne "queued"){ # Remove the task from the hash table $tasks.Remove($_.Value.Value) # Jump out of the foreach loop continue } } sleep 5 }
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Luc thanks.
This statement does not work:
foreach($vmmorview in ...)
That was just a sample to indicate the main loop.
I don't know how you do in your main loop so you will have to replace it with your code.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks Luc,
My Loop starts somewhere else. First a lot of checks are being done.
The cloning part is put in a different section.
I have to look into the foreach loop
Luc,
I have a little problem with the foreach.
This is done somewhere else.
And only one is past to the clone task at a time.
Now i don't have a clue to create a smart foreach statement.
Luc,
Thanks for the tips (also from the PM's)
I created a function with a second while loop, that get's kicked off almost at the end of the script.
It does the last error handling for the tasks.
Here is the code:
#CHECK THE TASK
#DO WE HAVE MORE THAN $MAXTASK TASKS RUNNING ?
while($tasks.Count -ge $maxTask)
{
#PUT ALL TASK OBJECT ON THE PIPE AS (NAME,VALUE) WHERE VALUE IS THE ACTUAL TASK OBJECT
$tasks.GetEnumerator() | % {
#GET THE LATEST STATUS OF THE TASK
$gettaskstate = get-view $_.value
$taskstate = $gettaskstate.info.state
$taskname = $_.Name
#CHECK IF THE TASK IS NOT QUEUED NOR RUNNING
if($taskstate -ne "running" -and $taskstate -ne "queued")
{
#CHECK THE OUTCOME OF THE TASK
if ($taskstate -eq "error")
{
WRITE_LOG "[ERROR] DEPLOYING: $taskname"
$tasks.Remove($_.Key)
#JUMP OUT OF THE FOREACH LOOP
continue
}
else
{
WRITE_LOG "[SUCCESS] DEPLOYING: $taskname"
$tasks.Remove($_.Key)
#JUMP OUT OF THE FOREACH LOOP
continue
}
}
}
sleep 5
}
And the code for the last task in the hash array:
Function CHECK_TASKS
{
#CHECK THE TASK
#DO WE HAVE MORE THAN $MAXTASK TASKS RUNNING ?
while($tasks.Count -gt 0)
{
#PUT ALL TASK OBJECT ON THE PIPE AS (NAME,VALUE) WHERE VALUE IS THE ACTUAL TASK OBJECT
$tasks.GetEnumerator() | % {
#GET THE LATEST STATUS OF THE TASK
$gettaskstate = get-view $_.value
$taskstate = $gettaskstate.info.state
$taskname = $_.Name
#CHECK IF THE TASK IS NOT QUEUED NOR RUNNING
if($taskstate -ne "running" -and $taskstate -ne "queued")
{
#CHECK THE OUTCOME OF THE TASK
if ($taskstate -eq "error")
{
WRITE_LOG "[ERROR] DEPLOYING: $taskname"
$tasks.Remove($_.Key)
#JUMP OUT OF THE FOREACH LOOP
continue
}
else
{
WRITE_LOG "[SUCCESS] DEPLOYING: $taskname"
$tasks.Remove($_.Key)
#JUMP OUT OF THE FOREACH LOOP
continue
}
}
}
sleep 5
}
}
The case is closed :smileysilly:
Hi Rob and all,
Just want to mension that the newly released PowerCLI 4.0 Update 1 supports virtual machine cloning with the New-Vm cmdlet using the -Vm parameter! For more info see the examples provided in the help for New-Vm cmdlet! Enjoy it!
\Yavor