Powershell Functions in my Azure setup script

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 {
        $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.

About erictummers

Working in a DevOps team is the best thing that happened to me. I like challenges and sharing the solutions with others. On my blog I’ll mostly post about my work, but expect an occasional home project, productivity tip and tooling review.
This entry was posted in Development and tagged . Bookmark the permalink.

1 Response to Powershell Functions in my Azure setup script

  1. Pingback: Powershell optimization | .NET Development by Eric

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.