In my Automate test environment with azure virtual machines post I’ve written about my Azure setup script. To improve readability and making the creation of a new machine easier I decided to rewrite some parts to functions.
The customscript extension had me puzzled some time, but the logs got me sorted out. Make sure to host your file in Azure Storage or some other “direct access” location; dropbox-link shares contain illegal characters (the questionmark).
$subnet= "subnet-1" $redundancy = "Standard_LRS" $size = "Small" #"ExtraSmall" "Small" "Medium" "Large" "ExtraLarge" $location = "West Europe" $service = "YOUR_SERVICE_HERE" $un = "Someone" $pwd = "*****" $configurewebserver = "http://url_to_your_powershell/script.ps1" $configurewebserverrun = "script.ps1" # Create the storage account if needed, remove old (running) instance and # name the new VHD function Prepare { param([string] $storage, [string] $machine) New-AzureStorageAccount -StorageAccountName $storage -Location $location -Type $redundancy -ErrorAction Ignore Get-AzureVm -ServiceName $service -Name $machine -WarningAction Ignore | Remove-AzureVM -DeleteVHD $context = (New-AzureStorageContext -StorageAccountName $storage -Anonymous).BlobEndPoint Write-Output "$context/vhds/$machine$((Get-Date).Ticks).vhd" } # Create a VM to host the web role on loadbalanced ports (80 and 443) and # install some IIS features using the customscript extension function CreateWebVM { param([string] $storage, [string] $machine) $webLocation = Prepare -storage $storage -machine $machine Write-Host "Creating $machine" $vmWeb = New-AzureVMConfig -Name $machine -InstanceSize $size -ImageName $image.ImageName -MediaLocation $webLocation | Add-AzureProvisioningConfig -Windows -AdminUsername $un -Password $pwd | Add-AzureEndpoint -Protocol tcp -LocalPort 80 -PublicPort 80 -Name 'web' -LBSetName 'web' -DefaultProbe | Add-AzureEndpoint -Protocol tcp -LocalPort 443 -PublicPort 443 -Name 'https' -LBSetName 'https' -DefaultProbe | Set-AzureSubnet $subnet | Set-AzureVMCustomScriptExtension -FileUri $configurewebserver -Run $configurewebserverrun | New-AzureVm -ServiceName $service }
After the creation of the VM some custom software had to be installed. For this I’ve used a download with Invoke-WebRequest. The file can be hosted on dropbox now since I don’t check for illegal characters. Some (very basic) retry logic is in place to make sure the file exists before installation can start.
$download = "https://download_msi_from/dropbox/file.msi?dl=1" # Install custom software in a remote session function InstallSoftwareForWeb { param([System.Management.Automation.Runspaces.PSSession[]] $sessions) Invoke-Command -Session $sessions -ScriptBlock { param([String]$file) $msi = "c:\custominstall.msi" $completed = Test-Path $msi while($completed -ne $true) { Invoke-WebRequest $file -OutFile $msi | Write-Debug $completed = Test-Path $msi if ($completed -ne $true) { Write-Host "Retry downloading MSI" } } Unblock-File $msi Start-Process -FilePath $msi -ArgumentList /qn, /L!V, c:\\install.txt -Wait } -ArgumentList $download -AsJob }
After all functions are defined the script calls them in the correct order. This way adding an extra machine looks like this.
$webstorage = "MyWebStorageInAzure" $webMachine3 = "WebMachine3" CreateWebVM $webstorage $webMachine3 $sessionToWebMachine3 = StartRemoteSession $webMachine3 ConfigureFirewall $sessionToWebMachine3 InstallSoftwareForWeb $sessionToWebMachine3 GenerateCertificates $sessionToWebMachine3 RegisterCertificates $sessionToWebMachine3 RegisterHttpsCertificate $sessionToWebMachine3 RegisterNode $sessionAdmin $webMachine3
Everyone with a technical background and a basic understanding of English should be able to guess what would happen if we run this.
Pingback: Powershell optimization | .NET Development by Eric