Created
November 10, 2014 08:47
-
-
Save pvandervelde/349767f804a32195ee67 to your computer and use it in GitHub Desktop.
Syspreps an Azure VM and then creates an image from it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.SYNOPSIS | |
Syspreps an Azure VM and then creates an image from it. | |
.DESCRIPTION | |
The New-AzureSyspreppedVMImage function executes sysprep on a given Azure VM and then once the VM is shut down creates an image from it. | |
.PARAMETER session | |
The PSSession that provides the connection between the local machine and the remote machine. | |
.PARAMETER resourceGroupName | |
The name of the resource group in which the VM exists. | |
.PARAMETER vmName | |
The azure name of the VM. | |
.PARAMETER imageName | |
The name of the image. | |
.PARAMETER imageLabel | |
The label of the image. | |
.EXAMPLE | |
New-AzureSyspreppedVMImage | |
-session $session | |
-resourceGroupName 'jenkinsresource' | |
-vmName 'ajm-305-220615' | |
-imageName "jenkins-master-win2012R2_0.2.0" | |
-imageLabel "Jenkins master on Windows Server 2012 R2" | |
#> | |
function New-AzureSyspreppedVMImage | |
{ | |
[CmdletBinding()] | |
param( | |
[System.Management.Automation.Runspaces.PSSession] $session, | |
[string] $resourceGroupName, | |
[string] $vmName, | |
[string] $imageName, | |
[string] $imageLabel | |
) | |
# Stop everything if there are errors | |
$ErrorActionPreference = 'Stop' | |
$commonParameterSwitches = | |
@{ | |
Verbose = $PSBoundParameters.ContainsKey('Verbose'); | |
Debug = $PSBoundParameters.ContainsKey('Debug'); | |
ErrorAction = "Stop" | |
} | |
$cmd = 'Write-Verbose "Executing $sysPrepScript on VM"; & c:\Windows\system32\sysprep\sysprep.exe /oobe /generalize /shutdown' | |
$tempDir = Join-Path $env:TEMP ([System.Guid]::NewGuid().ToString()) | |
$sysprepCmd = Join-Path $tempDir 'sysprep.ps1' | |
$remoteDirectory = "c:\sysprep" | |
try | |
{ | |
if (-not (Test-Path $tempDir)) | |
{ | |
New-Item -Path $tempDir -ItemType Directory | Out-Null | |
} | |
Set-Content -Value $cmd -Path $sysprepCmd | |
Add-AzureFilesToVM -session $session -remoteDirectory $remoteDirectory -filesToCopy @( $sysprepCmd ) | |
} | |
finally | |
{ | |
Remove-Item -Path $tempDir -Force -Recurse | |
} | |
# Sysprep | |
# Note that apparently this can't be done just remotely because sysprep starts but doesn't actually | |
# run (i.e. it exits without doing any work). So this needs to be done from the local machine | |
# that is about to be sysprepped. | |
Write-Verbose "Starting sysprep ..." | |
Invoke-Command ` | |
-Session $session ` | |
-ArgumentList @( (Join-Path $remoteDirectory (Split-Path -Leaf $sysprepCmd)) ) ` | |
-ScriptBlock { | |
param( | |
[string] $sysPrepScript | |
) | |
& "$sysPrepScript" | |
} ` | |
-Verbose ` | |
-ErrorAction Continue | |
# Wait for machine to turn off. Wait for a maximum of 5 minutes before we fail it. | |
$isRunning = $true | |
$timeout = [System.TimeSpan]::FromMinutes(20) | |
$killTime = [System.DateTimeOffset]::Now + $timeout | |
$hasFailed = $false | |
Write-Verbose "SysPrep is shutting down machine. Waiting ..." | |
try | |
{ | |
while ($isRunning) | |
{ | |
$vm = Get-AzureVM -ServiceName $resourceGroupName -Name $vmName | |
Write-Verbose ("$vmName is status: " + $vm.Status) | |
if (($vm.Status -eq "StoppedDeallocated") -or ($vm.Status -eq "StoppedVM")) | |
{ | |
Write-Verbose "VM stopped" | |
$isRunning = $false | |
} | |
if ([System.DateTimeOffset]::Now -gt $killTime) | |
{ | |
Write-Verbose "VM failed to stop within time-out" | |
$isRunning = false; | |
$hasFailed = $true | |
} | |
} | |
} | |
catch | |
{ | |
Write-Verbose "Failed during time-out loop" | |
# failed. Just ignore it | |
} | |
if ($hasFailed) | |
{ | |
throw "Virtual machine Sysprep failed to complete within $timeout" | |
} | |
Write-Verbose "Sysprep complete. Starting image creation" | |
Write-Verbose "ServiceName: $resourceGroupName" | |
Write-Verbose "Name: $vmName" | |
Write-Verbose "ImageName: $imageName" | |
Write-Verbose "ImageLabel: $imageLabel" | |
Save-AzureVMImage -ServiceName $resourceGroupName -Name $vmName -ImageName $imageName -OSState Generalized -ImageLabel $imageLabel @commonParameterSwitches | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment