Create a VM from a specialized VHD in a storage account

Create a new VM by attaching a specialized unmanaged disk as the OS disk using Powershell. A specialized disk is a copy of VHD from an existing VM that maintains the user accounts, applications and other state data from your original VM.

You have two options:

Option 1: Upload a specialized VHD

You can upload the VHD from a specialized VM created with an on-premises virtualization tool, like Hyper-V, or a VM exported from another cloud.

Prepare the VM

You can upload a specialized VHD that was created using an on-premises VM or a VHD exported from another cloud. A specialized VHD maintains the user accounts, applications and other state data from your original VM. If you intend to use the VHD as-is to create a new VM, ensure the following steps are completed.

  • Prepare a Windows VHD to upload to Azure. Do not generalize the VM using Sysprep.
  • Remove any guest virtualization tools and agents that are installed on the VM (i.e. VMware tools).
  • Ensure the VM is configured to pull its IP address and DNS settings via DHCP. This ensures that the server obtains an IP address within the VNet when it starts up.

Get the storage account

You need a storage account in Azure to store the uploaded VM image. You can either use an existing storage account or create a new one.

To show the available storage accounts, type:

Get-AzStorageAccount

If you want to use an existing storage account, proceed to the Upload the VM image section.

If you need to create a storage account, follow these steps:

  1. You need the name of the resource group where the storage account should be created. To find out all the resource groups that are in your subscription, type:

    Get-AzResourceGroup
    

    To create a resource group named myResourceGroup in the West US region, type:

    New-AzResourceGroup -Name myResourceGroup -Location "West US"
    
  2. Create a storage account named mystorageaccount in this resource group by using the New-AzStorageAccount cmdlet:

    New-AzStorageAccount -ResourceGroupName myResourceGroup -Name mystorageaccount -Location "West US" `
        -SkuName "Standard_LRS" -Kind "Storage"
    

Upload the VHD to your storage account

Use the Add-AzVhd cmdlet to upload the image to a container in your storage account. This example uploads the file myVHD.vhd from "C:\Users\Public\Documents\Virtual hard disks\" to a storage account named mystorageaccount in the myResourceGroup resource group. The file will be placed into the container named mycontainer and the new file name will be myUploadedVHD.vhd.

$rgName = "myResourceGroup"
$urlOfUploadedImageVhd = "https://mystorageaccount.blob.core.windows.net/mycontainer/myUploadedVHD.vhd"
Add-AzVhd -ResourceGroupName $rgName -Destination $urlOfUploadedImageVhd `
    -LocalFilePath "C:\Users\Public\Documents\Virtual hard disks\myVHD.vhd"

If successful, you get a response that looks similar to this:

MD5 hash is being calculated for the file C:\Users\Public\Documents\Virtual hard disks\myVHD.vhd.
MD5 hash calculation is completed.
Elapsed time for the operation: 00:03:35
Creating new page blob of size 53687091712...
Elapsed time for upload: 01:12:49

LocalFilePath           DestinationUri
-------------           --------------
C:\Users\Public\Doc...  https://mystorageaccount.blob.core.windows.net/mycontainer/myUploadedVHD.vhd

Depending on your network connection and the size of your VHD file, this command may take a while to complete.

Option 2: Copy the VHD from an existing Azure VM

You can copy a VHD to another storage account to use when creating a new, duplicate VM.

Before you begin

Make sure that you:

  • Have information about the source and destination storage accounts. For the source VM, you need to have the storage account and container names. Usually, the container name will be vhds. You also need to have a destination storage account. If you don't already have one, you can create one using either the portal (All Services > Storage accounts > Add) or using the New-AzStorageAccount cmdlet.
  • Have downloaded and installed the AzCopy tool.

Deallocate the VM

Deallocate the VM, which frees up the VHD to be copied.

  • Portal: Click Virtual machines > myVM > Stop
  • Powershell: Use Stop-AzVM to stop (deallocate) the VM named myVM in resource group myResourceGroup.
Stop-AzVM -ResourceGroupName myResourceGroup -Name myVM

The Status for the VM in the Azure portal changes from Stopped to Stopped (deallocated).

Get the storage account URLs

You need the URLs of the source and destination storage accounts. The URLs look like: https://<storageaccount>.blob.core.windows.net/<containerName>/. If you already know the storage account and container name, you can just replace the information between the brackets to create your URL.

You can use the Azure portal or Azure Powershell to get the URL:

  • Portal: Click the > for All services > Storage accounts > storage account > Blobs and your source VHD file is probably in the vhds container. Click Properties for the container, and copy the text labeled URL. You'll need the URLs of both the source and destination containers.
  • Powershell: Use Get-AzVM to get the information for VM named myVM in the resource group myResourceGroup. In the results, look in the Storage profile section for the Vhd Uri. The first part of the Uri is the URL to the container and the last part is the OS VHD name for the VM.
Get-AzVM -ResourceGroupName "myResourceGroup" -Name "myVM"

Get the storage access keys

Find the access keys for the source and destination storage accounts. For more information about access keys, see About Azure storage accounts.

  • Portal: Click All services > Storage accounts > storage account > Access keys. Copy the key labeled as key1.
  • Powershell: Use Get-AzStorageAccountKey to get the storage key for the storage account mystorageaccount in the resource group myResourceGroup. Copy the key labeled key1.
Get-AzStorageAccountKey -Name mystorageaccount -ResourceGroupName myResourceGroup

Copy the VHD

You can copy files between storage accounts using AzCopy. For the destination container, if the specified container doesn't exist, it will be created for you.

To use AzCopy, open a command prompt on your local machine and navigate to the folder where AzCopy is installed. It will be similar to C:\Program Files (x86)\Microsoft SDKs\Azure\AzCopy.

To copy all of the files within a container, you use the /S switch. This can be used to copy the OS VHD and all of the data disks if they are in the same container. This example shows how to copy all of the files in the container mysourcecontainer in storage account mysourcestorageaccount to the container mydestinationcontainer in the mydestinationstorageaccount storage account. Replace the names of the storage accounts and containers with your own. Replace <sourceStorageAccountKey1> and <destinationStorageAccountKey1> with your own keys.

AzCopy /Source:https://mysourcestorageaccount.blob.core.windows.net/mysourcecontainer `
    /Dest:https://mydestinationatorageaccount.blob.core.windows.net/mydestinationcontainer `
    /SourceKey:<sourceStorageAccountKey1> /DestKey:<destinationStorageAccountKey1> /S

If you only want to copy a specific VHD in a container with multiple files, you can also specify the file name using the /Pattern switch. In this example, only the file named myFileName.vhd will be copied.

AzCopy /Source:https://mysourcestorageaccount.blob.core.windows.net/mysourcecontainer `
  /Dest:https://mydestinationatorageaccount.blob.core.windows.net/mydestinationcontainer `
  /SourceKey:<sourceStorageAccountKey1> /DestKey:<destinationStorageAccountKey1> `
  /Pattern:myFileName.vhd

When it is finished, you will get a message that looks something like:

Finished 2 of total 2 file(s).
[2016/10/07 17:37:41] Transfer summary:
-----------------
Total files transferred: 2
Transfer successfully:   2
Transfer skipped:        0
Transfer failed:         0
Elapsed time:            00.00:13:07

Troubleshooting

  • When you use AZCopy, if you see the error "Server failed to authenticate the request", make sure the value of the Authorization header is formed correctly including the signature. If you are using Key 2 or the secondary storage key, try using the primary or 1st storage key.

Create the new VM

You need to create networking and other VM resources to be used by the new VM.

Create the subNet and vNet

Create the vNet and subNet of the virtual network.

  1. Create the subNet. This example creates a subnet named mySubNet, in the resource group myResourceGroup, and sets the subnet address prefix to 10.0.0.0/24.

    $rgName = "myResourceGroup"
    $subnetName = "mySubNet"
    $singleSubnet = New-AzVirtualNetworkSubnetConfig -Name $subnetName -AddressPrefix 10.0.0.0/24
    
  2. Create the vNet. This example sets the virtual network name to be myVnetName, the location to West US, and the address prefix for the virtual network to 10.0.0.0/16.

    $location = "West US"
    $vnetName = "myVnetName"
    $vnet = New-AzVirtualNetwork -Name $vnetName -ResourceGroupName $rgName -Location $location `
        -AddressPrefix 10.0.0.0/16 -Subnet $singleSubnet
    

    Create the network security group and an RDP rule

    To be able to log in to your VM using RDP, you need to have an security rule that allows RDP access on port 3389. Because the VHD for the new VM was created from an existing specialized VM, after the VM is created you can use an existing account from the source virtual machine that had permission to log on using RDP. This needs to be completed prior to creating the network interface it will be associated with.
    This example sets the NSG name to myNsg and the RDP rule name to myRdpRule.

$nsgName = "myNsg"

$rdpRule = New-AzNetworkSecurityRuleConfig -Name myRdpRule -Description "Allow RDP" `
    -Access Allow -Protocol Tcp -Direction Inbound -Priority 110 `
    -SourceAddressPrefix Internet -SourcePortRange * `
    -DestinationAddressPrefix * -DestinationPortRange 3389
$nsg = New-AzNetworkSecurityGroup -ResourceGroupName $rgName -Location $location `
    -Name $nsgName -SecurityRules $rdpRule
	

For more information about endpoints and NSG rules, see Opening ports to a VM in Azure using PowerShell.

Create a public IP address and NIC

To enable communication with the virtual machine in the virtual network, you need a public IP address and a network interface.

  1. Create the public IP. In this example, the public IP address name is set to myIP.

    $ipName = "myIP"
    $pip = New-AzPublicIpAddress -Name $ipName -ResourceGroupName $rgName -Location $location `
        -AllocationMethod Dynamic
    
  2. Create the NIC. In this example, the NIC name is set to myNicName. This step also associates the Network Security Group created earlier with this NIC.

    $nicName = "myNicName"
    $nic = New-AzNetworkInterface -Name $nicName -ResourceGroupName $rgName `
     -Location $location -SubnetId $vnet.Subnets[0].Id -PublicIpAddressId $pip.Id -NetworkSecurityGroupId $nsg.Id
    

Set the VM name and size

This example sets the VM name to "myVM" and the VM size to "Standard_A2".

$vmName = "myVM"
$vmConfig = New-AzVMConfig -VMName $vmName -VMSize "Standard_A2"

Add the NIC

$vm = Add-AzVMNetworkInterface -VM $vmConfig -Id $nic.Id

Configure the OS disk

  1. Set the URI for the VHD that you uploaded or copied. In this example, the VHD file named myOsDisk.vhd is kept in a storage account named myStorageAccount in a container named myContainer.

    $osDiskUri = "https://myStorageAccount.blob.core.windows.net/myContainer/myOsDisk.vhd"
    
  2. Add the OS disk. In this example, when the OS disk is created, the term "osDisk" is appended to the VM name to create the OS disk name. This example also specifies that this Windows-based VHD should be attached to the VM as the OS disk.

    $osDiskName = $vmName + "osDisk"
    $vm = Set-AzVMOSDisk -VM $vm -Name $osDiskName -VhdUri $osDiskUri -CreateOption attach -Windows
    

Optional: If you have data disks that need to be attached to the VM, add the data disks by using the URLs of data VHDs and the appropriate Logical Unit Number (Lun).

$dataDiskName = $vmName + "dataDisk"
$vm = Add-AzVMDataDisk -VM $vm -Name $dataDiskName -VhdUri $dataDiskUri -Lun 1 -CreateOption attach

When using a storage account, the data and operating system disk URLs look something like this: https://StorageAccountName.blob.core.windows.net/BlobContainerName/DiskName.vhd. You can find this on the portal by browsing to the target storage container, clicking the operating system or data VHD that was copied, and then copying the contents of the URL.

Complete the VM

Create the VM using the configurations that we just created.

#Create the new VM
New-AzVM -ResourceGroupName $rgName -Location $location -VM $vm

If this command was successful, you'll see output like this:

RequestId IsSuccessStatusCode StatusCode ReasonPhrase
--------- ------------------- ---------- ------------
                         True         OK OK   

Verify that the VM was created

You should see the newly created VM either in the Azure portal, under All services > Virtual machines, or by using the following PowerShell commands:

$vmList = Get-AzVM -ResourceGroupName $rgName
$vmList.Name

Next steps

Sign in to your new virtual machine. For more information, see How to connect and log on to an Azure virtual machine running Windows.