Change the Temporary Drive in a Azure VM and Use D: for Persistent Data Disks

Quite often people want to use the D: drive in a Windows Azure VM for their apps or data. For example, you might want to migrate an existing Windows application to the cloud without change and this app is relying on data being stored on the D: drive. Or your corporate policy mandates installing applications on D:.

By default, Windows VMs in Windows Azure host their operating system on drive C: as a persistent data disk located in blob storage. Additionally, each VM gets a scratch disk labeled as D: which is NOT persisted in blob storage. It’s rather disk space provided by the specific Hyper-V host of your VM. Data on this scratch disk is volatile in a sense that it will get lost whenever your VM will be relocated to another physical host (e.g. because you changed the VM size in the portal).

So if you want to use D: as a persistent data disk, read on…


Overview

The basic idea is to change the drive letter of the temporary drive from D: to something else. This will allow us to attach an additional data disk to the VM and use D: for it. Sounds simple? Well, there’s a couple of things we have to consider:

  • By default the temporary D: drive hosts the Windows page file, so we will have to relocate that before we can change the drive letter.
  • We have to find out what the Azure provisioning process will do when it finds a data disk is already using the D: drive letter.
  • By default there is also a DVD drive mounted as E: that we will have to get out of our way.

So here’s what we are trying to achieve:

overview

Setup

In order to automate the procedure of setting up a virtual machine with a persistent D: drive we are going to use PowerShell. You can download the cmdlets for Windows Azure here. You could also use the Windows Azure Portal and configure the VM within a RDP session.

Create VM

First, we need to create the virtual machine in Windows Azure. We can either start from one of the standard Windows images in the Gallery or use a VHD we have created before. We will start with the latest Windows Server 2012 R2 image. In PowerShell you need to execute the following statements:

$imgname = 'a699494373c04fc0bc8f2bb1389d6106__Windows-Server-2012-R2-201312.01-en.us-127GB.vhd'
$cloudsvc = 'mycloudsvc'
$vmname = 'myvm'
$user = 'myuser'
$pwd = 'mypwd'
$location = 'North Europe'
$size = 'Small'

# create new VM
New-AzureVMConfig -Name $vmname -InstanceSize $size -ImageName $imgname |
 Add-AzureProvisioningConfig -Windows -AdminUsername $user -Password $pwd |
  New-AzureVM -ServiceName $cloudsvc -Location $location -WaitForBoot

Note that you will have to change the parameters to fit your needs and find a DNS name for the cloud service that’s still available. You can retrieve the current Windows images in the gallery using the following statement:


Get-AzureVMImage | select ImageName | where ImageName -like '*Windows*'

Now we have deployed a small VM in the North Europe datacenter. When you RDP into the machine you will see the default disk configuration that looks like this:

default

Relocate Windows Page File

By default a Windows VM in Azure has configured a single page file on the scratch disk (‘Temporary Storage’) D:.

Pagefile

Before we can change the drive letter of the temporary disk we need to move the page file to the OS drive C: and reboot the VM. We can do that via Remote PowerShell from our local machine. Michael Washam provides a good explanation about Remote PowerShell and Windows Azure on his blog.

# Install the WinRM Certificate 
# Needs to run elevated
.\InstallWinRMCert.ps1

InstallWinRMCert $cloudsvc $vmname
$winrmuri = Get-AzureWinRMUri -ServiceName $cloudsvc -Name $vmname
$securepassword = ConvertTo-SecureString $pwd -AsPlainText -Force
$credentials = New-Object System.Management.Automation.PSCredential($user, $securepassword)

# move pagefile to OS disk
Invoke-Command -ConnectionUri $winrmuri.ToString() -Credential $credentials -ScriptBlock {
    $CurrentPageFile = Get-WmiObject -Query 'select * from Win32_PageFileSetting'
    $CurrentPageFile.delete()
    Set-WMIInstance -Class Win32_PageFileSetting -Arguments @{name='c:\pagefile.sys';InitialSize = 0; MaximumSize = 0}

    # disable DVD drive
    Set-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Services\cdrom -Name Start -Value 4 -Type DWord
}

# restart the VM (required by AD installation)
Restart-AzureVM -ServiceName $cloudsvc -name $vmname

What this script also does is disabling the DVD drive by changing its corresponding registry value (set ‘Start’ to ‘4’). By default the DVD drive is mounted as E: initially, but might actually vanish after a VM is shutdown (de-provisioned) and re-started. This means that if we took F: for the scratch disk initially, it would move down to E: in case the DVD drive is going away. Reason for this is that the fabric obviously mounts the temporary drive as the next ‘available’ drive letter. In this case the updated page file configuration (pointing to F:) would be screwed, resulting in an error and creation of a temporary page file, which we have to avoid. Anyway, we can obviously fix this by disabling the DVD altogether and thus get a stable setup.

Change Drive Letter of Scratch Disk

After we have moved the page file away from the temporary drive, we can now change its drive letter. As the DVD drive is gone we can now use E: for our scratch disk. Again we’ll do that using Remote PowerShell:

# change drive letter of scratch disk
Invoke-Command -ConnectionUri $winrmuri.ToString() -Credential $credentials -ScriptBlock {
    $drive = Get-WmiObject -Class win32_volume -Filter "DriveLetter = 'd:'"
    Set-WmiInstance -input $drive -Arguments @{ DriveLetter='e:' }
}

Attach Persistent Data Disk

Now we can add the data disk to the VM that will hold our data or applications. The following script will add an empty disk and format it with NTFS:

# add data disk
Get-AzureVM -ServiceName $cloudsvc -Name $vmname | 
    Add-AzureDataDisk -CreateNew -DiskSizeInGB 1 -DiskLabel 'Apps' -LUN 0 |
        Update-AzureVM

# initialize & format data disk
Invoke-Command -ConnectionUri $winrmuri.ToString() -Credential $credentials -ScriptBlock {
    # initialize data disk
    Get-Disk | Where partitionstyle -eq 'raw'|
        Initialize-Disk -PartitionStyle MBR -PassThru |
            New-Partition -AssignDriveLetter -UseMaximumSize |
                Format-Volume -FileSystem NTFS -NewFileSystemLabel 'Apps' -Confirm:$false 
}

Actually we could add more than one disk to the VM and push the temporary disk further back in terms of its drive letter. Just be aware that you have to use the next available letter for the scratch disk without any gaps.

Move Page File Back to Temporary Storage

Finally we need to move the page file back to where it belongs, which is to the scratch disk. Again, changing the page file configuration requires a reboot.

# move pagefile back to scratch disk
Invoke-Command -ConnectionUri $winrmuri.ToString() -Credential $credentials -ScriptBlock {
    $CurrentPageFile = Get-WmiObject -Query 'select * from Win32_PageFileSetting'
    $CurrentPageFile.delete()
    Set-WMIInstance -Class Win32_PageFileSetting -Arguments @{name='e:\pagefile.sys';InitialSize = 0; MaximumSize = 0}
}

# restart the VM (required by AD installation)
Restart-AzureVM -ServiceName $cloudsvc -name $vmname

Testing

The approach described in this post seems to work fine as long as you ‘comply’ with the Windows Azure provisioning process for VMs. The provisioning engine will take the first available drive letter and use it for the scratch disk, starting with D:. If you consider that you can attach as many disks as the VM size allows. You just have to make sure to use the corresponding drive letter for the scratch disk.

I validated the scenario with the following test cases:

  • Shutdown the VM (so it gets into stopped/de-allocated state, which means de-provisioned) and restart it again.
  • Changed the VM size to a smaller or larger configuration.
  • Bluescreened the machine (using Sysinternals NotMyFault utility).

In all cases above your VM will get re-deployed with its specific disk configuration, the scratch disk will be wiped, and your machine will potentially be brought up on a different Hyper-V host.

I tested the scenario with Windows images from the Gallery and attached empty data disks. Using VHDs that have been uploaded from on-premises and also attaching existing disks containing data shouldn’t be any problem. You would just have to tweak the PowerShell cmdlets a bit.

Warning: the method described in this post works fine today with the current provisioning architecture of the Windows Azure fabric. This might change in the future.

5 comments on “Change the Temporary Drive in a Azure VM and Use D: for Persistent Data Disks
  1. We have recently updated Azure VMs so the temp drive letter will be maintained regardless of which drive letter is used. So you can set the temp drive letter to something like T: or Z:, and it will be maintained through stop/start operations or Azure healing operations which used to cause the drive letter to reset back to the first available drive letter. This change applies to both Classic and ARM virtual machines.

Leave a Reply to Carsten Lemm Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>