core/Resources/Scripts/create_environment.ps1
Param( [Parameter(Mandatory)] $EnvironmentName, [Parameter(Mandatory)] $Location, [string]$NetworkCidr = "33.7.0.0/26", [Parameter(Mandatory)] $VmCount, [Parameter(Mandatory)] $Zone, [Parameter(Mandatory)] $Version, [Parameter(Mandatory)] $OS, [string]$StorageAccountType = "Standard_LRS", [Parameter(Mandatory)] $VmSizeName, [Parameter(Mandatory)] $FirstName, [Parameter(Mandatory)] $LastName, [Parameter(Mandatory)] $EvaluationKey, [Parameter(Mandatory)] $Email, [string]$CompanyName = "", [string]$UserName = "ncadmin", [Parameter(Mandatory)] $Password, $PrivateIps, [bool]$isEvalKey, [bool]$CreatePublicIp, [string]$RuleType, [string[]]$WhiteListIps, [string]$LicenseDuration, [string]$Publisher = "ncache", [string]$Offer = "ent-linux-536", [string]$Sku = "ent-linux-53", [string]$ImageVersion, [string]$ArmTemplatePath = ".\CreateResourceGroup.json", [Parameter(Mandatory)] [string]$SetupUrl, [switch]$UseNCacheImage, [string]$ServerPlan, [string]$LicenseKey, [string]$Edition, [string]$ScriptsFolderPath = ".\Resources\Scripts" ) . "$ScriptsFolderPath\dashboard_common.ps1" $nc_resource_group = "NC-$EnvironmentName" $arrayList = [System.Collections.ArrayList]@() $VerbosePreference = "continue" function Enable-SystemAssignedIdentity { param( [Parameter(Mandatory)][string]$VmName ) Write-Host "$((Get-Date).ToString()) - Enabling system-assigned managed identity on $VmName" $vm = Get-AzVM -ResourceGroupName $nc_resource_group -Name $VmName Update-AzVM -ResourceGroupName $nc_resource_group -VM $vm -IdentityType SystemAssigned } function CommaSepratedIps { $commaSepratedIps = "" foreach ($ip in $PrivateIps) { $commaSepratedIps += $ip + "," } $commaSepratedIps.TrimEnd(',') return $commaSepratedIps | Out-Null } function CreateStartupCommand { param( [string]$Key, [string]$firstName, [string]$lastName, [string]$email, [string]$company, [string]$environment ) $cloudType = "azs" $evalFlag = [int]$isEvalKey $StartupScriptUrl = "https://ncachedeployments.s3.us-east-1.amazonaws.com/5.3.6-tools/StartupScriptLinux.sh" $paramStr = "-InstallType $cloudType -Key $Key -FirstName $FirstName -LastName $LastName -Email $Email -Environment $EnvironmentName -IsEvalKey $evalFlag " if (-not $isEvalKey) { $paramStr += "-LicenseDuration $LicenseDuration " } if (![string]::IsNullOrWhiteSpace($company)) { $paramStr += "-Company $company " } if ($OS -eq "Windows") { $ips = CommaSepratedIps $paramStr += "-PrivateIps $ips -Username $UserName -Password $Password " return ("Invoke-WebRequest -Uri https://ncachedeployments.s3.us-east-1.amazonaws.com/5.3.6-tools/StartupScriptWin_v6.ps1 -OutFile C:/StartupScriptWin_v6.ps1;Unblock-File -Path C:/StartupScriptWin_v6.ps1; C:/StartupScriptWin_v6.ps1 $paramStr") } $paramStr += " -PrivateIps $PrivateIps " return ("#!/bin/sh sleep 30; wget -O /tmp/StartupScriptLinux.sh $StartupScriptUrl; chmod +x /tmp/StartupScriptLinux.sh; /tmp/StartupScriptLinux.sh $paramStr" -replace "`r`n", "`n") } function EncryptStartupCommand { param( [string]$StartupCommand ) $bytes = [System.Text.Encoding]::UTF8.GetBytes($StartupCommand) $encoded = [Convert]::ToBase64String($bytes) return $encoded } function Test-CIDR { param ([string]$CIDR) $cidrPattern = '^((25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})\.){3}(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})\/(3[0-2]|[1-2]?[0-9])$' return $CIDR -match $cidrPattern } function ValidateCIDRBlocks { param ( [string]$CidrBlocks ) $result = @{ valid = $false errors = @() validCIDRs = @() } if (-not $CidrBlocks.Trim()) { $result.errors += "CIDR block cannot be empty" return $result } $multipleSpaces = "/\\s{2,}/" $missingComma = "/[^,\\s]+\\s+[^,\\s]+/" $cidrList = $CidrBlocks -split "," | ForEach-Object { $_.Trim() } | Where-Object { $_.Length -gt 0 } if ($cidrList.Count -eq 0) { $result.errors += "No valid CIDR blocks provided" return $result } $seen = @{} foreach ($cidr in $cidrList) { if (-not (Test-CIDR $cidr)) { $result.errors += "Invalid CIDR format: $cidr" } elseif ($seen.ContainsKey($cidr)) { $result.errors += "Duplicate CIDR blocks are not allowed" } else { $seen[$cidr] = $true } } $result.valid = ($result.errors.Count -eq 0) $result.validCIDRs = $seen.Keys return $result } function ValidateFields() { param( [string]$environmentName, [string]$location, [string]$firstName, [string]$lastName, [string]$licenseKey, [string]$email, [string]$password, [string]$companyName, [string]$vmSizeName ) if ([string]::IsNullOrWhiteSpace($EnvironmentName)) { throw "Environment Name cannot be empty" } if ([string]::IsNullOrWhiteSpace($Location)) { throw "Location cannot be empty" } if ($VmCount -lt 1) { throw "Vm Count Name cannot be less than 0" } if ([string]::IsNullOrWhiteSpace($FirstName)) { throw "First name is required" } if ([string]::IsNullOrWhiteSpace($LastName)) { throw "Last Name is required" } if ([string]::IsNullOrWhiteSpace($Email)) { throw "Email is required" } if ([string]::IsNullOrWhiteSpace($Password)) { throw "Password is required" } if ([string]::IsNullOrWhiteSpace($VmSizeName)) { throw "VmSize Is Required is required" } if ([string]::IsNullOrEmpty($vmSizeName)) { throw "InCorrect Vm Size Provided" } } function AddTags { $dict = @{ "EvaluationKey" = $EvaluationKey "FirstName" = $FirstName "LastName" = $LastName "Email" = $Email "UserName" = $UserName "EnvironmentName" = $EnvironmentName "Sku" = $Sku "VmSize" = $VmSizeName "Offer" = $Offer "Publisher" = $Publisher "Version" = $Version "StorageAccountType" = $StorageAccountType "OsType" = $OS "Location" = $Location "Zone" = $Zone "IsEvalKey" = $isEvalKey "CreatePublicIp" = $CreatePublicIp "SetupUrl" = $SetupUrl "ImageVersion" = $ImageVersion "UseNCacheImage" = $UseNCacheImage.ToBool() "ServerProfile" = $ServerPlan "Edition" = $Edition "LicenseDuration" = $LicenseDuration "RuleType" = $RuleType } if (![string]::IsNullOrWhiteSpace($LicenseDuration)) { $dict["LicenseDuration"] = $LicenseDuration } if (![string]::IsNullOrWhiteSpace($CompanyName)) { $dict["Company"] = $CompanyName } if (![string]::IsNullOrWhiteSpace($LicenseKey)) { $dict["LicenseKey"] = $LicenseKey } return $dict } function CheckQuota { (Get-AzComputeResourceSku -Location $Location | Where-Object { $_.ResourceType -eq "virtualMachines" -and $_.Name -eq $VmSizeName }).Capabilities | Where-Object { $_.Name -eq "vCPUs" } | Select-Object -ExpandProperty Value $sku = Get-AzComputeResourceSku -Location $Location ` | Where-Object { $_.ResourceType -eq "virtualMachines" -and $_.Name -eq $VmSizeName } $family = $sku.Family $vcpus = ($sku.Capabilities | Where-Object { $_.Name -eq "vCPUs" }).Value $info = [PSCustomObject]@{ Name = $sku.Name Family = $family vCPUs = $vcpus } $Usage = Get-AzVMUsage -Location $Location | Where-Object { $_.Name.Value -eq $family } ValidateQuota -currentQuota $($Usage.CurrentValue) -limitQuota $($Usage.Limit) -vCpus $vcpus } function ValidateQuota() { param( [int]$currentQuota, [int]$limitQuota, [int]$vCpus ) $myQuota = $VmCount * $vCpus if ($myQuota -gt $limitQuota) { throw "Quota limit exceeded" } } function ValidateFieldsFunction { ValidateFields -environmentName $EnvironmentName -location $Location -firstName $FirstName -lastName $LastName -licenseKey $LicenseKey -email $Email -password $Password -companyName $CompanyName -vmsizeName $VmSizeName $result = ValidateCIDRBlocks -CidrBlocks $NetworkCidr if (-not [string]::IsNullOrEmpty($result.errors) ) { throw $result.errors } } function CreateServersList { for ($i = 1; $i -le $VmCount; $i++) { $arrayList.Add("NC-Server-$i") | Out-Null } return $arrayList } function CreateAndEncodeScript { $scriptCode = CreateStartupCommand -key $LicenseKey -firstName $FirstName -lastname $LastName -email $Email -company $CompanyName -environment $EnvironmentName $encodedScript = EncryptStartupCommand -StartupCommand $scriptCode return $encodedScript } function ShowDeployedEvs { $vms = Get-AzVM -ResourceGroupName $nc_resource_group -Status $results = foreach ($vm in $vms) { $nicId = $vm.NetworkProfile.NetworkInterfaces[0].Id $nicName = ($nicId -split '/')[8] $nic = Get-AzNetworkInterface -ResourceGroupName $nc_resource_group -Name $nicName $privateIp = $nic.IpConfigurations[0].PrivateIpAddress $publicIp = $null $managementLink = $null if ($nic.IpConfigurations[0].PublicIpAddress) { $publicIpId = $nic.IpConfigurations[0].PublicIpAddress.Id $publicIpName = ($publicIpId -split '/')[8] $publicIpObj = Get-AzPublicIpAddress -ResourceGroupName $nc_resource_group -Name $publicIpName $publicIp = $publicIpObj.IpAddress if ($publicIp) { $managementLink = "http://$publicIp`:8251" } } [PSCustomObject]@{ VMName = $vm.Name PrivateIP = $privateIp PublicIP = $publicIp ManagementLink = $managementLink } } $results | Format-Table -AutoSize } function GetRestrictedOnes { # Pull only SKUs for the given region $skus = Get-AzComputeResourceSku -Location $Location | Where-Object { $_.ResourceType -eq "virtualMachines" -and $_.Restrictions } foreach ($sku in $skus) { Write-Output "VM Size: $($sku.Name)" Write-Output "Location: $($sku.Locations)" foreach ($restriction in $sku.Restrictions) { Write-Output " Restriction Type : $($restriction.Type)" Write-Output " Reason : $($restriction.ReasonCode)" if ($restriction.RestrictionInfo.Zones) { Write-Output " Restricted Zones : $($restriction.RestrictionInfo.Zones -join ', ')" } } Write-Output "-----------------------------" } } function GetAzureRestictionCapacity { $skus = Get-AzComputeResourceSku -Location $Location | Where-Object { $_.ResourceType -eq "virtualMachines" -and $_.Name -eq $VmSizeName } foreach ($sku in $skus) { if ($sku.Restrictions) { $restriction = $sku.Restrictions $restrictedZones = $restriction.RestrictionInfo.Zones if ($($restriction.ReasonCode) -eq "NotAvailableForSubscription" -and $restrictedZones -contains $Zone) { throw "VmSize $VmSizeName is $($restriction.ReasonCode) in Zones $($restriction.RestrictionInfo.Zones -join ', ')" } } } } function BlastFromThePast([switch]$EndOfLine) { $EscChar = "`r" if ($EndOfLine) { $EscChar = "`b" } if (!$tickcounter) { Set-Variable -Name "tickcounter" -Scope global -Value 0 -Force -Option AllScope } if (!$tickoption) { Set-Variable -Name "tickoption" -Scope global -Value 0 -Force -Option AllScope } $chance = Get-Random -Minimum 1 -Maximum 10 if ($chance -eq 5) { if ($tickoption -eq 1) { $tickoption = 0 }else { $tickoption = 1 } } switch ($tickoption) { 0 { switch ($tickcounter) { 0 { Write-Host "$EscChar|" -NoNewline } 1 { Write-Host "$EscChar/" -NoNewline } 2 { Write-Host "$EscChar-" -NoNewline } 3 { Write-Host "$EscChar\" -NoNewline } } break; } 1 { switch ($tickcounter) { 0 { Write-Host "$EscChar|" -NoNewline } 1 { Write-Host "$EscChar\" -NoNewline } 2 { Write-Host "$EscChar-" -NoNewline } 3 { Write-Host "$EscChar/" -NoNewline } } break; } } if ($tickcounter -eq 3) { $tickcounter = 0 } else { $tickcounter++ } } function ExecuteCommands { $zoneList = @($Zone) ValidateFieldsFunction $allVms = CreateServersList # CheckQuota # GetAzureRestictionCapacity $encodedScript = CreateAndEncodeScript Get-AzResourceGroup -Name $nc_resource_group -ErrorVariable notPresent -ErrorAction SilentlyContinue | Out-Null if (!$notPresent) { throw "Environment with same name already exists" } $AzresourceGroup = New-AzResourceGroup -Name $nc_resource_group -Location $Location -ErrorAction Stop $tags = AddTags Write-Host "Deploying Resources..." New-AzResourceGroupDeployment -ResourceGroupName $nc_resource_group -TemplateFile $ArmTemplatePath -location $Location -resource_group_name $EnvironmentName -address_prefixes $NetworkCidr -vm_names $allVms -zone_name $zoneList -publisher_name $Publisher -offer_name $Offer -sku_name $Sku -version_name $Version -os_name $OS -storage_account_type $StorageAccountType -vm_size $VmSizeName -custom_data $encodedScript -userName $UserName -password $Password -privateIps $PrivateIps -create_public_ip $CreatePublicIp -rule_type $RuleType -white_list_ips $WhiteListIps -image_version $ImageVersion -use_ncache_image $UseNCacheImage.ToBool() -DeploymentDebugLogLevel All -Verbose -ErrorVariable MyError | Out-Null if ($MyError) { throw "Exception $($MyError.Exception.Message)" } New-AzTag -ResourceId $AzresourceGroup.ResourceId -Tag $tags | Out-Null } $script:ScriptWindows = $null $script:resourceGroupName = $null $script:scriptLinux = $null function EnableCacheServerPublicIp { if ($RuleType -eq "Data" -or $RuleType -eq "All") { return $true } return $false } function InvokeCommandOnServerWindows { $LogFile = "C:\Temp\InstallLog.txt" $enableCacheServerIp = EnableCacheServerPublicIp $commaSepratedIps = ($PrivateIps -join ",") $script = @" New-Item -ItemType Directory -Force -Path "C:\Temp" | Out-Null wget "https://ncachedeployments.s3.us-east-1.amazonaws.com/5.3.6-tools/InstallScript_Win_Server.ps1" -OutFile "C:\Temp\InstallScript_Win_Server.ps1" C:\Temp\InstallScript_Win_Server.ps1 -Key $EvaluationKey -UserName $UserName -Company $CompanyName -FirstName $FirstName -LastName $LastName -Password $Password -Email $Email -PrivateIps $commaSepratedIps -SetupUrl $SetupUrl -LicenseKey '$LicenseKey' -EnableCacheServerPublicIp `$$enableCacheServerIp -Environment '$EnvironmentName' -LicenseDuration '$LicenseDuration' "@ foreach ($server in $arrayList) { Write-Host "$((Get-Date).ToString()) - Downloading and Installing NCache on $server" } $jobs = foreach ($server in $arrayList) { Start-Job -ScriptBlock { param($rg, $vm, $script) Invoke-AzVMRunCommand -ResourceGroupName $rg -VMName $vm -CommandId 'RunPowerShellScript' -ScriptString $script Write-Host "$((Get-Date).ToString()) - Installed NCache on server $vm" } -ArgumentList $nc_resource_group, $server, $script } $dots = "" while (@($jobs | Where-Object { $_.State -eq "Running" }).Count -gt 0) { $dots += "." Write-Host -NoNewline "`r$dots" Start-Sleep -Seconds 5 $jobs = $jobs | Get-Job } # Clear dots line $clearLine = " " * $dots.Length Write-Host -NoNewline "`r$clearLine`r" # while (@($jobs | Where-Object { $_.State -eq "Running" }).Count -gt 0) { # BlastFromThePast; # Start-Sleep -Milliseconds 100 # } # BlastFromThePast -Finished; $jobs | Wait-Job $jobs | Receive-Job } function InvokeCommandOnServerLinux { foreach ($server in $arrayList) { Write-Host "$((Get-Date).ToString()) - Downloading and Installing NCache on $server" } $enableCacheServerIp = EnableCacheServerPublicIp $command = CreateScriptBlockLinux $jobs = foreach ($server in $arrayList) { Start-Job -ScriptBlock { param($rg, $vm, $script) Invoke-AzVMRunCommand -ResourceGroupName $rg -VMName $vm -CommandId 'RunShellScript' -ScriptString $script Write-Host "$((Get-Date).ToString()) - Installed NCache on server $vm" } -ArgumentList $nc_resource_group, $server, $command } $jobs | Wait-Job $jobs | Receive-Job } function CreateScriptBlockLinux { return "sudo wget -O /tmp/InstallScript_Lin_Server.sh https://ncachedeployments.s3.us-east-1.amazonaws.com/5.3.6-tools/InstallScript_Lin_Server.sh; chmod +x /tmp/InstallScript_Lin_Server.sh; /tmp/InstallScript_Lin_Server.sh -FirstName $FirstName -LastName $LastName -Email $Email -Key $EvaluationKey -Company $CompanyName -PrivateIps $PrivateIps -SetupUrl '$SetupUrl' -LicenseKey '$LicenseKey' -Environment '$EnvironmentName' -EnableCacheServerPublicIp $enableCacheServerIp -LicenseDuration '$LicenseDuration'" } function InstallClient { If ($OS -eq "Windows") { InvokeCommandOnServerWindows } else { InvokeCommandOnServerLinux } } function InstallNCache { foreach ($server in $arrayList) { Enable-SystemAssignedIdentity -VmName $server } if (-not $UseNCacheImage) { InstallClient } Update-NcAzDashboards -ScriptsFolderPath $ScriptsFolderPath -ResourceGroupName $nc_resource_group -CacheName "demoCache" -SkipClient } function CheckIfSizeIsAvailable { $restricted = Get-AzComputeResourceSku -Location $Location | Where-Object { $_.Name -eq $VmSizeName } | Select-Object Name, Restrictions if ($restricted.Restrictions[0].ReasonCode -eq "NotAvailableForSubscription") { throw "Specified vmSize is restricted in $location for your subscription" } } try { $stopwatch = [System.Diagnostics.Stopwatch]::StartNew() if (-not (Get-AzContext)) { Connect-AzAccount if ((Get-AzContext)) { ExecuteCommands InstallNCache ShowDeployedEvs } } else { ExecuteCommands InstallNCache ShowDeployedEvs } $stopwatch.Stop() Write-Host "Execution Time: $($stopwatch.Elapsed.ToString())" } catch { if ($MyError) { Write-Host "An error occurred: $($MyError.Exception.Message)" } Write-Error "Error: $($_.Exception.Message)" if ($($_.Exception.Message) -ne "Environment with same name already exists") { Write-Error "Resource group creation failed. Rolling back changes....." Remove-AzResourceGroup -Name $nc_resource_group -Force -ErrorAction SilentlyContinue } } |