The Azure Drive feature gives you access to data contained in an an NTFS-formatted virtual hard disk (VHD) persisted as a page blob in Azure Storage. Important to notice is that although you can access the drive using normal IO code, it is NOT a shared disk between all your Windows Azure instances. Only a single Azure instance can mount a page blob for read/write access as an Azure Drive. However, multiple Azure instances can mount a snapshot of a page blob for read-only access as an Azure Drive.
Mounting a VHD as an Azure drive
The VHD for an Azure Drive must be a fixed hard disk image formatted as a single NTFS volume. It must be between 16MB and 1TB in size. A VHD is a single file comprising a data portion followed by a 512 byte footer. When uploading a VHD it is consequently important to remember to upload the footer. Furthermore, since pages of a page blob are initialized to 0 it is not necessary to upload pages in which all the bytes are 0. This could save a significant amount of time when uploading a large VHD.
The Disk Management component of the Windows Server Manager can be used to create and format a VHD by performing the following steps:
- Right click on Disk Management and select Create VHD
- Specify a fixed size VHD and provide a location and the size in MB
- Right click on the disk icon and select Initialize Disk
- Specify MBR (Master Boot Record)
- Right click on the unallocated space and select New Simple Volume
- Follow the Wizard choosing the defaults - specifically including the quick format with NTFS
The VHD is now created and accessible as a new drive using Windows Explorer. It can be used just like any other drive. The Detach VHD entry on the Disk Management right-click menu can be used to detach the VHD making it no longer accessible as a drive. This does not delete the VHD file. Similarly, the Attach VHD menu item can be used to once again make the VHD accessible as a file system.
Once created and detached, this VHD can be uploaded as a page blob to Azure Storage. Not all tools support uploading page blobs, but the Azure storage explorer should do the trick.
Using the Azure drive on an instance
To access the drive, we need a CloudDrive object. This object can be created using either the constructor or the CreateCloudDrive extension method to CloudStorageAccount.
CloudStorageAccount cloudStorageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString"); CloudDrive cloudDrive = cloudStorageAccount.CreateCloudDrive(cloudDriveUri.AbsoluteUri);
These assume that the CloudStorageAccount.SetConfigurationSettingPublisher() as has been invoked previously. Note that these only create an in-memory representation of the Azure Drive which still needs to be mounted before it can be used.
Some important considerations:
- A VHD page blob can be mounted on only one instance at a time.
- A VHD snapshot can be mounted readonly to an unlimited number of instances.
Before a VHD page blob can be mounted it is necessary to allocate some cache space in the local storage of the instance. This is necessary even if caching is not going to be used. This caching is a read cache. Local storage must be defined in the Azure Service Definition file as explained in this post and should be configured with cleanOnRoleRecycle set to false.
<LocalResources> <LocalStorage name="CloudDrives" cleanOnRoleRecycle="false" sizeInMB="50" /> </LocalResources>
InitializeCache() must be invoked to initialize the cache with a specific size and location.
public static void InitializeCache() { LocalResource localCache = RoleEnvironment.GetLocalResource("CloudDrives"); CloudDrive.InitializeCache(localCache.RootPathlocalCache.MaximumSizeInMegabytes); }
An instance mounts a writeable Azure Drive by invoking Mount() on a VHD page blob. The Azure Storage Service uses the page blob leasing functionality to guarantee exclusive access to the VHD page blob. An instance mounts a read-only Azure Drive by invoking mount() on a VHD snapshot. Since it is read-only it is possible for multiple instances to mount the VHD snapshot simultaneously. An instance invokes the Unmount() method to release the Azure Drive and for VHD page blobs allow other instances to mount the blob for write access.
The cacheSize parameter to Mount() specifies how much of the cache is dedicated to this Azure Drive. The cacheSize should be set to 0 if caching is not desired for the drive. Different Azure Drives mounted on the same instance can specify different cache sizes and care must be taken that the total cache size allocated for the drives does not exceed the amount of cache available in local storage. The options parameter takes an DriveMountOptions flag enumeration that can be used to force the mounting of a drive – for example, when an instance has crashed while holding the lease to a VHD page blob – or to fix the file system. Mount() returns the drive letter, or LocalPath, to the Azure Drive - for example, "d:" - which can be used to access any path on the drive.
public void WriteToDrive( Uri cloudDriveUri ) { CloudStorageAccount cloudStorageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString"); cloudDrive = cloudStorageAccount.CreateCloudDrive(cloudDriveUri.AbsoluteUri); String driveLetter = cloudDrive.Mount(CacheSizeInMegabytes, DriveMountOptions.None); String path = String.Format("{0}\\hellodrives.txt", driveLetter); FileStream fileStream = new FileStream(path, FileMode.OpenOrCreate); StreamWriter streamWriter = new StreamWriter(fileStream); streamWriter.Write("that you have but slumbered here"); streamWriter.Close(); cloudDrive.Unmount(); }
GetMountedDrives() provides access to a list of drive letters for all Azure Drives mounted in the instance. It is used as follows:
public static void EnumerateDrives() { IDictionary<String,Uri> listDrives = CloudDrive.GetMountedDrives(); foreach (KeyValuePair<String,Uri> drive in listDrives) { String driveInformation = String.Format("drive: {0} - uri: {1}", drive.Key, drive.Value.AbsoluteUri); Trace.WriteLine(driveInformation, "Information"); } }