Book a Demo Free Trial

How to Snapshot and Restore Virtual Machines Running on Windows Azure

Matt Dickens

May 29, 2013

Category: Azure Storage

A couple of AMC users have recently asked us how to take snapshots of VMs in Azure and restore them. One of our colleagues dived in to this problem and figured out the details, so we thought we’d share what he learned.

Problem

You have a VM in Windows Azure and you want to take a snapshot of it, so you can revert back to it at a later date. Unfortunately, Azure doesn’t currently support this, although it does support snapshots of a blob, which gives us a possible option.

Solution

Following on from work here which uses our cmdlets, I’ve updated the steps to work with Azure now (April 2013). It seems that Microsoft changed something in Azure that means the method presented in that link no longer works (more on that in a minute) and probably means that my method will cease to work at some point in the future too.

There are two main sections to this process:

  1. Taking the Snapshot of your VM
  2. Restoring the Snapshot

Prerequisites

In order to follow through the rest of this post, you’ll need a few things:

  • The official Windows Azure Powershell cmdlets
  • Your Azure account information, as noted in the Azure cmdlets getting started guide here
  • Our Azure Management cmdlets
  • The name of your VM ($vmname)
  • The service name that your VM belongs to ($servicename)
  • The storage account name ($storageaccountname)
  • The storage account access key ($storageaccesskey)
  • The storage container name where the VHD resides ($containerName)
  • The Azure location of your VM ($location)
  • The URL of the blob representing the VD ($bloburl)

Snapshotting the VM

This is a relatively straightforward affair, but it would be a good idea to shut the VM down first. Remember, that the snapshot operation is performed on the blob storage object, so you’ll take a snapshot of whatever is persisted to disk. If you take the snapshot while the VM is running you won’t get the running state, so when you restore and start your VM it’ll come up in a crash-consistent state.

1
STOP-AZUREVM -SERVICENAME $SERVICENAME -NAME $VMNAME

Once the VM has stopped, you can use the Cerebrata cmdlet to take the snapshot.

1
$SNAPSHOTURL = CHECKPOINT-BLOB -BLOBURL $BLOBURL -ACCOUNTNAME $STORAGEACCOUNTNAME -ACCOUNTKEY $STORAGEACCESSKEY

Note that the Checkpoint-blob cmdlet returns the URL of the newly taken snapshot. You should keep this because we’ll need it later. I’ve stored it in a variable, $snapshoturl.

With all that done, you can start the VM again.

1
START-AZUREVM -SERVICENAME $SERVICENAME -NAME $VMNAME

Restoring the VM

The process of restoring the snapshot is somewhat more involved than actually taking the snapshot.

When a disk is attached to a VM, a lease is created which prevents access to that blob by everything else. This is also where my steps differ from the ones here. In order to perform the restore you must remove the entire VM and, as I’ve discovered, you also need to remove the disk (which is a separate entity to the blob) before you can perform the restore.

To start with, you’ll want to stop the VM

1
STOP-AZUREVM -SERVICENAME $SERVICENAME -NAME $VMNAME

Then, export the VM config somewhere safe

1
EXPORT-AZUREVM -SERVICENAME $SERVICENAME -NAME $VMNAME -PATH $CONFIGPATH

Where $configpath is some file path local to the machine where the script is running (e.g c:\temp\myvmconfig.xml).

Next, get and store the name of the disk that is attached to the VM (this assumes only one disk, so you may need to modify this if your VM has more than one).

1
$DISKNAME = GET-AZUREDISK | WHERE {$_.ATTACHEDTO.ROLENAME -EQ $VMNAME} | SELECT DISKNAME

Then you can remove the VM. If you remove the VM first, you’ll then have difficulty getting the name of the disk.

1
REMOVE-AZUREVM -SERVICENAME $SERVICENAME -NAME $VMNAME

Next, we need to wait for Azure to stop associating the disk with the VM. I’ve written a simple loop that does the waiting, you might want to tweak it to suit your needs, but this works well enough for me

1
2
3
4
5
6
7
$ATTACHED = GET-AZUREDISK | WHERE {$_.DISKNAME -EQ $DISKNAME.DISKNAME} | SELECT ATTACHEDTO

WHILE($ATTACHED.ATTACHEDTO -NE $NULL)
{
    START-SLEEP -S 20
    $ATTACHED = GET-AZUREDISK | WHERE {$_.DISKNAME -EQ $DISKNAME.DISKNAME} | SELECT ATTACHEDTO
}

It takes a while for the association to go away (in my experience), hence the 20 second sleep between checks.

Once this completes, you can remove the disk

1
REMOVE-AZUREDISK -DISKNAME $DISKNAME.DISKNAME

Then, you need to remove the service which releases the service name and then allows you to deploy the VM again.

1
REMOVE-AZURESERVICE -SERVICENAME $SERVICENAME -FORCE

Finally, we can perform the restore of the snapshot

1
$NEWBLOB = COPY-BLOB -BLOBURL $SNAPSHOTURL -TARGETBLOBCONTAINERNAME $CONTAINERNAME -ACCOUNTNAME $STORAGEACCOUNTNAME -ACCOUNTKEY $STORAGEACCESSKEY

Again, this cmdlet returns the URL to the ‘new’ blob. Keep this, we’ll need it in a second when we add a new disk

1
ADD-AZUREDISK -DISKNAME $DISKNAME.DISKNAME -MEDIALOCATION $NEWBLOB.BLOBURL -OS 'WINDOWS'

This creates a new disk in Azure which references the newly restored vhd. Change the OS to whatever OS you have, but make sure it’s an Azure recognised OS.

Finally, import the VM config we exported earlier and create a new VM

1
IMPORT-AZUREVM -PATH $CONFIGPATH | NEW-AZUREVM -SERVICENAME $SERVICENAME -LOCATION $LOCATION

And that’s it. You’ll need to wait a while for the VM to boot, and if you put all this together in a script, then the whole process can take quite some time (10 – 15minutes in my experience!).