VMware Cloud Community
sddunne
Contributor
Contributor

Kicking off a clone, then waiting for it to finish in Primal Forms...

Hi Guys,

Here's my problem. I'm writing a Virtual Server Provisioning GUI using Primal Forms... It's all going well (primal forms is excellent!) however i'm stuck at the actual deployment part. Basically, when i click the Build Button, this runs a function which clones a vm using New-VM. Following this, i wanted to edit the memory, cpu and possibly add another Disk using further commands. The bit i'm stuck at is that as soon as i click Build and run the function, the new-vm works as expected but the Primal Form freezes and show's (Not Responding).

This is kind of expected behaviour as it is waiting for the New-VM command to complete but doesn't exactly look great as an interface as the new-vm takes about 20mins to complete and the GUI just looks like it has hung...

So... what i'm trying to work out how to do is to ideally either;

A. Call the function and use a progress bar within the primal form to show that something is indeed happening

or

B. Somehow schedule the task, either in vCenter (which seems clunky) or by scheduling a mini-script using Windows Task Scheduler to progress the script without tying up the interface (again feels clunky)

or

C. The easy one!! Just running the function asyncronously so that the GUI doesn't have to wait for it to complete?

Any help would be much appreciated (and i'm thinking C may be the easy answer!)

Cheers,

Sean.

Function BuildWindows2003Server() {

if ($Global:vmbits -eq "IOC-Deploy-32bit")

{

$OutputWin.Text += "`r`nBuilding $($Global:vmtemplate) ..."

$OutputWin.Text += "`r`nDeploy Host is $($Global:deployhost) ..."

New-VM -Name $servernamebox.Text -Template $Global:vmTemplate -VMhost $deployhost -Datastore $datastorebox.SelectedItem

} elseif ($Global:vmbits = "IOC-Deploy-64bit")

{

$OutputWin.Text += "`r`nBuilding $($Global:vmtemplate) ..."

} else

{ $OutputWin.Text += "`r`nBuild Error has occured ..."}

0 Kudos
7 Replies
LucD
Leadership
Leadership

Why don't you use the -RunAsync parameter with the New-VM cmdlet.

That way you script will continue.

With the help of the Get-Task cmdlet you can then follow the task running in the background.

Let me know if you need a sample script of this.

____________

Blog: LucD notes

Twitter: lucd22


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

0 Kudos
sddunne
Contributor
Contributor

Hi Luc,

I was just reading the post on your blog that says exactly that! (http://www.lucd.info/2010/02/21/about-async-tasks-the-get-task-cmdlet-and-a-hash-table/)

Once again, thanks mate, that is the way to do it!!

The other bit that i'm stuck on is our Windows 2008 builds. Basically, our legacy 2003 builds are just VM Template clones with a customisation after. Our new deployment mechanism for Server 2008 is using SCCM. What i want to try and do is this;

1. Create new blank vm to spec (doing this by cloning an empty vm that has no hard drives attached, that way i can set default reservations etc...)

2. add a hard drive dependant on size specified in form (again, easy)

3. change network vlan (easy)

4. retrieve MAC address of new vm

5. Now the hard bit. Wait 10 minutes, then send the MAC address to SCCM. Microsoft have a sample script to do this, but the bit i'm unsure of is how to run a script in 10 mins time, i.e. how to schedule a script? Do you know of any way to do this? The best i can come up with is to write a bit of powershell to add itself to windows task scheduler, then delete itself when it has run but seem very clunky!!

Thanks again!!

Sean.

0 Kudos
LucD
Leadership
Leadership

I would suggest using a System.Windows.Forms.Timer object.

You can even add it to your form with PrimalForms.

On the Timer object you specify an interval (10 mins in your case) and define a function that should be called when the interval expires.

Have a look at my Script-O-Mania submission called PSTop and look for the ClockTimer object.

The timer calls the function every second and in the function I update the time field on the form.

But you could just as well do something else like firing of another script.

____________

Blog: LucD notes

Twitter: lucd22


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

0 Kudos
sddunne
Contributor
Contributor

HI Luc,

Great, thanks. The Get-Task doesn't seem to be able to differentiate which task it follows, is there a way of tracking a particular task? We quite often have multiple tasks running, sometimes multiple clone tasks too?

Many thanks,

Sean.

0 Kudos
sddunne
Contributor
Contributor

This looks like it would work well! Excellent, i'll give this and the get-task combination a go!!

Thanks!

Sean.

0 Kudos
LucD
Leadership
Leadership

When you run a cmdlet with the -RunAsync parameter, it returns a TaskImpl object.

In that object is an ID property whose value uniquely identifies the task.

$myTask = New-VM .... -RunAsync
$myTask | Select *

When you run the Get-Task cmdlet it returns the same type of objects.

You can use the ID property to filter out your specific task

Get-Task | where {$_.ID -eq $myTask.ID)

I hope this helps.

____________

Blog: LucD notes

Twitter: lucd22


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

0 Kudos
sddunne
Contributor
Contributor

Hi Luc,

Excellent, once again you've fixed the problem!!

I've attached the code i used to get it working, probably not the best but does the job!

Now it just remains for me to add this into massage this into the timer function!

Thanks again,

Sean.

$servername = "poo23"

$vmtemplate = "Windows 2003 Standard 32 Bit Template"

$deployhost = Get-VMHost -name "ukdc119101.uk.xxxxxx.com"

$datastore = Get-Datastore -name "ukdc128001:vmvol5:fc"

$myTask = New-VM -Name $servername -Template $vmtemplate -VMhost $deployhost -Datastore $datastore -RunAsync

$currentstate = $myTask.State

$currentpercent = $myTask.PercentComplete

Write-Host "Current State is $($currentstate)"

Write-Host "Percent Complete is $($currentpercent)"

while($currentpercent -le 99){

Get-Task | % {

if($_.Id -eq $myTask.Id -and $_.State -eq "Success"){

Write-Host "Successfully Finished!!! Woohoo!!!"

}

elseif($_.Id -eq $myTask.Id -and $_.State -eq "Running"){

$currentpercent = $_.PercentComplete

Write-Host "Current Percent is $($currentpercent)"

}

elseif($_.Id -eq $myTask.Id -and $_.State -eq "Error"){

$currentpercent = $_.PercentComplete

Write-Host "Fatal Error Occurred..."

end

}

}

Start-Sleep -Seconds 10

}

0 Kudos