Wednesday 14 January 2015

Parallel and background server operations with PowerShell jobs


One of the requests that I get internally is the ability to create CaaS servers on the background.
Imagine the scenario:

We need to create 4 CaaS servers, set 4 vCPUs and 8GB RAM, add an additional disk, create a VIP (virtual interface) and load balance the requests on port 443 on these servers.

One approach for this would be invoke each server cmdlet (New-CaasServer, Set-CaasServer, Set-CaasServerDiskSpeed) and use the Get-CaasDeployedServer to check the status and state of each server before calling the next command.

Another is to use the -PassThru and Out-CaasWaitForOperation on the server cmdlets so you can execute a sequence of commands against the same server as described on the batch operation blog post. But you would need to wait each server to be created one-by-one.

PowerShell provides native support for background jobs from version 3 up. These jobs run on a separate runspace (or thread) therefore all the variables and objects that are required to run the operation will have to be available at the thread level.
So, combining the batch operations and PowerShell jobs will provide a very efficient automation approach, saving time when creating CaaS servers.

The script below will create 4 CaaS server at the same time.

#import Caas Module
Import-Module CaaS

#capture the Caas credentials and create a new Caas conneciton
$cred = Get-Credential
$networkname = "Network1"


#create a simple function to create a Caas Server passing some parameters from the host script
Function CreateVMBackground
{
param(
[pscredential]$login,
[string]$servername,
[string]$networkname

)

#create a script block that will be executed on the background
$scriptblock = { `

    $osimagename = "Win2012 DC 64-bit 2 CPU"
    $administratorPassword= "password123"
    $serverRAM = 8192
    $serverCPUCount = 4

    #create connection for the background job
    New-CaasConnection -Name "AU" -ApiCredentials $args[0] -Vendor DimensionData -Region Australia_AU


    #Get the network with a specific name
    $network=Get-CaasNetworks -Name $args[2]

    #Get a OS image with a specific name
    $os=Get-CaasOsImages -Network $network -Name $osimagename

    #create a new server details configuration
    $serverdetails = New-CaasServerDetails -Name $args[1] -AdminPassword $administratorPassword -IsStarted $false -OsServerImage $os -Network $network

    # create new server, change memory to 8GB and 4 vCPU, start the server
     New-CaasServer -ServerDetails $serverdetails -PassThru | Out-CaasWaitForOperation | Set-CaasServer -CPUCount $serverCPUCount -MemoryInMB $serverRAM -PassThru | Out-CaasWaitForOperation | Set-CaasServerState -Action PowerOn

 }


 $jobname = "CreateServer-{0}" -f $servername
 #start a job executing the scriptblock and passing the variables from the ArgumentList to the $args parameter
 Start-Job -Name $jobname -ScriptBlock $scriptblock -ArgumentList $login,$servername,$networkname

}


#create VMTest1
CreateVMBackground -login $cred -servername "VMTest1" -networkname $networkname

Start-Sleep 3
#create VMTest2
CreateVMBackground -login $cred -servername "VMTest2" -networkname $networkname

Start-Sleep 3
#create VMTest3
CreateVMBackground -login $cred -servername "VMTest3" -networkname $networkname

Start-Sleep 3
#create VMTest4
CreateVMBackground -login $cred -servername "VMTest4" -networkname $networkname

#Get any message generated by the jobs
#Get-Job | Where-Object {$_.Name -like 'CreateServer-*'} | Receive-Job

Write-Host -ForegroundColor Yellow "Waiting the jobs to finish..."
#wait the jobs to complete before continue the script
Get-Job | Where-Object {$_.Name -like 'CreateServer-*'} | Wait-Job

Write-Host -ForegroundColor Yellow "All Jobs completed"


#remove completed jobs
Get-Job | Where-Object {$_.Name -like 'CreateServer-*'} | Remove-Job




The remaining of the script below will create and configure the network components to create the VIP and load balance the requests



#create connection
New-CaasConnection -Name "AU" -ApiCredentials $login -Vendor DimensionData -Region Australia_AU

#get the network
$network=Get-CaasNetworks -Name $networkname

#get each server into a variable
$server1 = Get-CaasDeployedServer -Name "VMTest1"
$server2 = Get-CaasDeployedServer -Name "VMTest2"
$server3 = Get-CaasDeployedServer -Name "VMTest3"
$server4 = Get-CaasDeployedServer -Name "VMTest4"

#create antiaffinity rules

New-CaasServerAntiAffinityRule -Server1 $server1 -Server2 $server2
New-CaasServerAntiAffinityRule -Server1 $server3 -Server2 $server4

#create 4 real servers
$rserver1=New-CaasRealServer -Network $network -Server $server1 -Name $server1.name -InService $true -PassThru
$rserver2=New-CaasRealServer -Network $network -Server $server2 -Name $server2.name -InService $true -PassThru
$rserver3=New-CaasRealServer -Network $network -Server $server3 -Name $server3.name -InService $true -PassThru
$rserver4=New-CaasRealServer -Network $network -Server $server4 -Name $server4.name -InService $true -PassThru

#create a new probe (optional)
#$probe = New-CaasProbe -Network $network -Name "test" -Type TCP -Port 555
#use a existing probe
$probe = Get-CaasProbe -Network $network -Name "tcp"

$serverfarm = New-CaasServerFarm -Network $network -Name "VMTestGroup" -Predictor LEAST_CONNECTIONS -RealServer $rserver1 -Probe $probe -PassThru
#add the second server to the server farm
Add-CaasToServerFarm -Network $network -ServerFarm $serverfarm -RealServer $rserver2
Add-CaasToServerFarm -Network $network -ServerFarm $serverfarm -RealServer $rserver3
Add-CaasToServerFarm -Network $network -ServerFarm $serverfarm -RealServer $rserver4

#add a probe to the server farm
#Add-CaasToServerFarm -Network $network -ServerFarm $serverfarm -Probe $probe

#create new persistence profile
$persprofile=New-CaasPersistenceProfile -Network $network -Name "PersProfileVMTest" -ServerFarm $serverfarm -TimeoutMinutes 30 -CookieName "VMCookie" -CookieType COOKIE_INSERT -PassThru

#create vip
New-CaasVip -Network $network -Name "VMTestVip" -PersistenceProfile $persprofile -Port 443 -Protocol TCP -InService $true -ReplyToIcmp $true


#get Vip created
$vip = Get-CaasVip -Network $network -Name "VMTestVip"

#create an IP Address with vip ipaddress
$vipIpAddress =[IPAddress]$vip.ipAddress

#create ACL rule to permit any connection to the VIP ip address on port 443
New-CaasAclRule -Network $network -AclRuleName "VMTestVip443" -Position 321 -Action PERMIT -Protocol TCP -DestinationIpAddress $vipIpAddress -PortRangeType EQUAL_TO -Port1 443


If you have any feedback please let us know!



No comments:

Post a Comment