VMware Cloud Community
RobMokkink
Expert
Expert
Jump to solution

logic in powershell script

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?

Reply
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

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

View solution in original post

Reply
0 Kudos
18 Replies
LucD
Leadership
Leadership
Jump to solution

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

RobMokkink
Expert
Expert
Jump to solution

Hi Luc,

Thanks for the input. I do not quit understand the code.

Is http:// in the code corrent?

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

No, it's not. Stupid forum SW did this.

Attached the code.


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

Reply
0 Kudos
RobMokkink
Expert
Expert
Jump to solution

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?

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

RobMokkink
Expert
Expert
Jump to solution

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.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
RobMokkink
Expert
Expert
Jump to solution

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.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Rob, I can't see the error message in your last post.


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

Reply
0 Kudos
RobMokkink
Expert
Expert
Jump to solution

Luc,

This is what i get:

cmdlet % at command pipeline position 1

Supply values for the following parameters:

Reply
0 Kudos
RobMokkink
Expert
Expert
Jump to solution

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?

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
RobMokkink
Expert
Expert
Jump to solution

Luc thanks.

This statement does not work:

foreach($vmmorview in ...)

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
RobMokkink
Expert
Expert
Jump to solution

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

Reply
0 Kudos
RobMokkink
Expert
Expert
Jump to solution

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.

Reply
0 Kudos
RobMokkink
Expert
Expert
Jump to solution

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:

Reply
0 Kudos
yboychev
Hot Shot
Hot Shot
Jump to solution

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

Reply
0 Kudos