Creating an Image

Prepare the Virtual Machine for Image Capture

This section shows you how to generalize your Windows virtual machine. This removes all your personal account information, among other things. You will typically want to do this when you want to use this Virtual Machine image to quickly deploy similar virtual machines.

Please note that the virtual machine cannot be logged into via Remote Desktop Protocol once it is generalized, since the process removes all user accounts. This is an irreversible change.

  1. Sign in to your Windows virtual machine. In the Azure portal, navigate through Browse >Virtual machines > Your Windows virtual machine > Connect.
  2. Open a Command Prompt window as an administrator.
  3. Change the directory to %windir%\system32\sysprep, and then run sysprep.exe. Failure to do this will result in the inability for nodes to communicate.
  4. In the System Preparation Tool dialog box, do the following:
    • In System Cleanup Action, select Enter System Out-of-Box Experience (OOBE) and make sure that Generalize is checked. For more information about using Sysprep, see How to Use Sysprep: An Introduction.
    • In Shutdown Options, selectShutdown
    • Click OK.

Sysprep shuts down the virtual machine. Its status changes to Stopped in the Azure portal.

Capture the Virtual Machine

The following details are required for this section:

  • Resource Group
  • Virtual Machine Name to create image from

Depending on your Azure setup you may require your Azure Subscription ID. This can be found by navigating through Browse > Subscriptions.

You can capture the generalized Windows VM by using Azure PowerShell. This section will show you the steps.

Using PowerShell

This article assumes that you have installed Azure PowerShell version 1.0.x. We recommend using this version since new Resource Manager features will not be added to older PowerShell versions. Read Azure PowerShell 1.0 to know more about the version differences.

  1. Open Azure PowerShell 1.0.x and sign in to your Azure account.

     Login-AzureRmAccount

    or open Windows Powershell

    Import-Module AzureRM.Compute
    Login-AzureRmAccount
  2. If the subscription ID that is selected by default is different from the one you want to work in, use either of the following to set the right subscription.
    Set-AzureRmContext -SubscriptionId "xxxx-xxxx-xxxx-xxxx"

    or

    Select-AzureRmSubscription -SubscriptionId "xxxx-xxxx-xxxx-xxxx"

    You can find the subscriptions that your Azure account has by using the command:

    Get-AzureRmSubscription
  3. Now you will need to deallocate the resources that are used by this virtual machine by using this command:
    Stop-AzureRmVM -ResourceGroupName YourResourceGroup -Name YourWindowsVM

    You will see that the Status for the VM on the Azure portal has changed from "Stopped" to "Stopped (deallocated)"

    You can also find out the status of your virtual machine in PowerShell by using:

    $vm = Get-AzureRmVM -ResourceGroupName YourResourceGroup -Name YourWindowsVM -status
    $vm.Statuses

    The DisplayStatus field corresponds to the Status shown in the Azure portal.

  4. Next, you need to set the status of the virtual machine to "Generalized". Note that you will need to do this because the generalization step above (sysprep) does not do it in a way that Azure can understand.

    Set-AzureRmVm -ResourceGroupName YourResourceGroup -Name YourWindowsVM -Generalized

    The generalized state as set above will not be shown on the portal. However, you can verify it by using the Get-AzureRmVM command as shown in the tip above.

  5. Capture the virtual machine image to a destination storage container by using this command.

    Container names must be 3-63 characters in length and may contain only lower-case alphanumeric characters and hyphen. Hyphen must be preceded and followed by an alphanumeric character
    Save-AzureRmVMImage -ResourceGroupName YourResourceGroup -VMName YourWindowsVM -DestinationContainerName YourImagesContainer -VHDNamePrefix YourTemplatePrefix -Path Yourlocalfilepath\Filename.json

    The -Path variable is optional. You can use it to save the JSON template locally. The -DestinationContainerName variable is the name of the container that you want to hold your images in. The URL of the image that is stored will be similar to

     https://YourStorageAccountName.blob.core.windows.net/system/Microsoft.Compute/Images/YourImagesContainer/YourTemplatePrefix-osDisk.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.vhd 

    It will be created in the same storage account as that of the original virtual machine.

    To find the location of your image, open the local JSON file template. Go to the resources > storageProfile > osDisk > image > uri0 section for the complete path of your image. As of now, there is no easy way to check these images on the portal, since the system container in the storage account is hidden. For this reason, although the -Path variable is optional, you definitely want to use it to save the template locally and to easily find out the image URL. Alternatively, you can find this out using a tool called the Azure Storage Explorer which is explained in the steps in the next section

    The following configuration items need to be updated in the script:

  • $vmImageName = "YourWindowsVM";
  • $resourceGroupName = "YourResourceGroup";
  • $destinationContainerName = "YourImagesContainer";
  • $vhdNamePrefix = "YourTemplatePrefix"
  • $jsonImagePath = "Yourlocalfilepath\Filename.json";

Creating a Windows Image - Complete Script

Import-Module AzureRM.Compute
Login-AzureRmAccount

#Name of the machine being used to create image
$vmImageName = "YourWindowsVM";
#Resource group name created in 'Setting Up a Virtual Network and Virtual Machine in Windows Azure'
$resourceGroupName = "YourResourceGroup";
#Container to store image. Container names must be 3-63 characters in length and may contain only lower-case alphanumeric characters and hyphen. 
#Hyphen must be preceded and followed by an alphanumeric character 
$destinationContainerName = "YourImagesContainer";
#Prefix for image name
$vhdNamePrefix = "YourTemplatePrefix"
#Location to output json file containing image details
$jsonImagePath = "Yourlocalfilepath\Filename.json";

Write-Host "Stopping VM :" $vmImageName
Stop-AzureRmVM -ResourceGroupName $resourceGroupName -Name $vmImageName -Force
Write-Host "Stopped VM :" $vmImageName

Write-Host "Generalizing VM :" $vmImageName
Set-AzureRmVm -ResourceGroupName $resourceGroupName -Name $vmImageName -Generalized
Write-Host "Generalized VM :" $vmImageName

Write-Host "Save VM Image JSON :" $vmImageName " - " $jsonImagePath
Save-AzureRmVMImage -ResourceGroupName $resourceGroupName -VMName $vmImageName -DestinationContainerName $destinationContainerName -VHDNamePrefix $vhdNamePrefix -Path $jsonImagePath -Overwrite
Was this article helpful?
0 out of 0 found this helpful