Introduction
One of the great features in the Azure Storage Blobs Service is the ability to create snapshots for a given blob.
Snapshots add robustness to the application by providing a “transaction” like behavior when manipulating the blob data (upon point of failure rollback to the base blob version). Another useful case is to create a snapshot to a cloud drive (you can mount an NTFS drive to a blob) and restore to the blob drive.
Blob Snapshots in Azure Storage
Snapshots are basically offer version control capabilities in the Azure cloud.
Snapshots can be created on the fly and treated like a regular blob but with an exception,
Snapshot created for a given blob are a read only blob therefore any attempt to modify the snapshot will fail.
Snapshots created is linked with base blob data as well as with the base blob metadata and the other blob properties (such as content type, length etc..).
Currently there is not straight forwards way for getting all the snapshots for a given blob.
You will need to use the following fields in the snapshot type blobs:
- DateTime property named SnapshotTime - on snapshot blob this property is not null.
The property represents the snapshot creation time so you can filter relevant snapshots based on this field. - Blob snapshot URI - we can use it to verify that the snapshot has the same URI as our base blob.
Below I will demonstrate how to exploit those fields in order to traverse the snapshots for a given blob.
Before diving into the code you may be wondering how you are charged for the snapshot blobs ?
Duplicating a blob could affect the monthly bill. i.e. a block blob can reach up 200 GB and with rate of 0.14$ per month each snapshot could cost 28$!!!.
Since snapshots only hold the blob pages that are different from the original blob, you are charged only for those unique pages or blocks in the snapshot blob and any identical pages/blocks are shared among the blob’s snapshots.
Using the code
(Code is available for download below)
We would like to accomplish the following tasks on snapshots:
- Create a snapshot for a blob
- Retrieving a specific snapshot
- List all snapshots for a blob
- Restoring from a snapshot
please note that in order to manage snapshots and other blobs api's will be using the Microsoft.WindowsAzure.StorageClient namespace.
Creating a snapshot
First let's connect to the azure storage service using the storage client API’s
string connectionString = String.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}", storageName, privateKey);
CloudStorageAccount account = CloudStorageAccount.Parse(connectionString);
blobClient = account.CreateCloudBlobClient(); Now lets create a blob container that is populated with simple text file.
CloudBlobContainer testcontainer = new CloudBlobContainer("testcontainer", blobClient);
testcontainer.CreateIfNotExist(new BlobRequestOptions()
{
UseFlatBlobListing = true
});
var blobRef = testcontainer.GetBlobReference("testblob");
blobRef.DeleteIfExists(new BlobRequestOptions()
{
DeleteSnapshotsOption = DeleteSnapshotsOption.IncludeSnapshots
});
blobRef.UploadFile(@"..\..\..\TestBlobSnapshots\Files\simpleText.txt");
blobRef.Metadata.Add("first", "1");
blobRef.SetMetadata();
By default, you cannot delete a blob that has associated snapshots unless explicitly forcing deletion.
Lets view the blob we created using using Cloud Storage Manager:

Now we are now ready to create a snapshot.
I've added a small verification to check that the metadata of the snapshot was copied from the base blob as well.
CloudBlob snapshotRef1 = blobRef.CreateSnapshot();
Assert.IsTrue(snapshotRef1.Metadata != null && snapshotRef1.Metadata.Count > 0 && snapshotRef1.Metadata["first"].Equals(blobRef.Metadata["first"]));
Retrieving a specific snapshot
As mentioned above, when creating a snapshot, the blob returned holds a SnapshotTime property of type DateTime.
I can use this property in order to get a reference for a specific blob snapshot.
CloudBlob snapshotRef2 = new CloudBlob(blobRef.Uri.AbsoluteUri, snapshotRef1.SnapshotTime, blobClient);
try
{
snapshotRef2.FetchAttributes();
}
catch (Exception e)
{
Assert.Fail("snapshot does not exist {0}", e.Message);
}
List all snapshot for a blob
Getting all the snapshot for given blob is a bit more tricky since the api does not expose a method that get all the snapshots for a given blob.
The only hint is the property SnapshotTime as discuss earlier in the CloudBlob object that can indicate if the blob is snapshot or not.
So lets use this field and also check that the blob snapshot referred to my base blob by comparing its URI address.
var snapshots = testcontainer.ListBlobs(new BlobRequestOptions()
{
BlobListingDetails = BlobListingDetails.Snapshots,
UseFlatBlobListing = true
}).Where(item => ((CloudBlob)item).SnapshotTime.HasValue && item.Uri.Equals(blobRef.Uri)).ToList<IListBlobItem>();
Assert.IsTrue(snapshots.Count == 1, "snapshot was not created");
snapshots.ForEach(item => Console.WriteLine(String.Format("{0} {1}", ((CloudBlob)item).Name, ((CloudBlob)item).SnapshotTime)));
Lets see the snapshot created using Cloud Storage Manger
Restoring from a snapshot
Restoring can be easily achieved by using the CopyFromBlob method (CloudBlob class).
I will only need to specify the snapshot as the source.
blobRef.UploadText("blob test was modified");
blobRef.CopyFromBlob(snapshotRef1);
Assert.IsFalse(blobRef.DownloadText() == "blob test was modified");
Points of Interest
In Quest Software we develop a great tool named Cloud Storage Manager that enables browsing and manipulating data in azure very easily.
One of the neat features is handling snapshots:
- You can create and view all the snapshot for a blob.
- Create a snapshots for an entire blob directory.
- Restore a snapshot for a specific blob.
- Restore an entire blob directory.

Download TestBlobSnapshots.zip - 14.06 KB