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