Coffee Break – keeping stuff in the cloud

In the last few Coffee Break posts we have been looking at virtual hard disks (VHDs) and virtual machines (VMs). Now let’s combine the two in the cloud.

Coffee Break 11 – Provisioning – Using Microsoft Azure storage to keep VHDs and other useful stuff in the cloud

Provisioning a new instance of Microsoft Dynamics NAV is like putting individual bits together. In this Coffee Break post, we will prepare some of these bits by building a VHD up front and then upload it to Azure. Then every new virtual machine (VM) can pick a copy of this disk. A VHD like this can contain anything such as the Microsoft Dynamics NAV product DVD, application objects, add-on databases, documents, and so on. And we can save a bit of time and bandwidth compared to uploading a new DVD, for example, every time we provision a new VM in the cloud.

Customer Story:

The customer is frequently creating new VMs. And every new VM they create will need access to common data, such as the Microsoft Dynamics NAV product DVD.

Prerequisites:

1 VHD (local) and 1 VM (In Azure):

Create a VHD: Coffee Break – Windows PowerShell and creating a Hyper-V disk

Create a VM: Coffee Break – Using Windows PowerShell to provision virtual machines

Get the VHD to the VM

Once we have a VHD (locally) and a VM in Azure (whether this was created manually or via PowerShell), let’s combine the two. First, upload the VHD to Azure. Connect your ISE PowerShell environment to your Azure subscription:
Add-AzureAccount

Create a new storage account to hold our VHD:

$SourceStorageAccount = “mysharedstuff

First test that the storage name is actually available:

Test-AzureNameStorage $SourceStorageAccount

If it is (the line above returns False), then create it:

New-AzureStorageAccountStorageAccountName $SourceStorageAccountLocation “West Europe”

 

Optionally we can add containers to this storage, just to keep things organized. First, let’s create a context that includes access information for our new storage:

$Key = (Get-AzureStorageKeyStorageAccountName $SourceStorageAccount).Primary
$Context = New-AzureStorageContextStorageAccountName $SourceStorageAccountStorageAccountKey $Key

This $Context variable gives us access to the storage, and is one we will use a couple of times.

Create a container in our storage to store vhds:

New-AzureStorageContainerContext $ContextName vhds

Upload the VHD

Let’s say you have a local VHD here: C:\temp\mydisctest.vhd. Then copy that up to your storage:
Add-AzurevhdLocalFilePath C:\temp\mydisctest.vhd -Destination “https://$SourceStorageAccount.blob.core.windows.net/vhds/mydisk.vhd”

If you get this error: “The process cannot access the file ‘C:\temp\mydisctest.vhd’ because it is being used by another process.” then make sure that the disk is not already mounted to your local machine. Note that if you happen to double-click on the VHD, Windows may automatically mount it. You can dismount it like this:

Dismount-VHDPath C:\temp\mydisctest.vhd

(side note:) If you should ever need to copy it back, use  Save-AzureVhd.

The Add-Azurevhd cmdlet does a clever copy by checking that this is a valid VHD, and by copying only actual data. So if the disk itself is 3GB but is only 5% full, then only a file the size of the 5% will actually be copied.

Make a copy

Every time we want a new disk, then we can make a new copy of this VHD, rather than attaching it directly in which case we could only use it for one VM. First create a new container for our copy. This container could relate somehow to the VM that we will be attaching the VHD to:

New-AzureStorageContainerContext $ContextName myvm

Then copy mydisk.vdh from vhds to myvm:

$SourceURI = “https://$SourceStorageAccount.blob.core.windows.net/vhds/mydisk.vhd

$State = Start-AzureStorageBlobCopyAbsoluteUri $SourceURIDestContainer myvm -DestBlob NewVHD.vhd -Context $Context

 

This will start an asynchronous copy. To check status before using the copy:

$state | Get-AzureStorageBlobCopyState

 

Get it together

Now we have a fresh copy of the VHD in Azure, let’s attach it to a VM, using the cmdlet Add-AzureDataDisk. The two main ways we can use this cmdlet are:

  • ImportFrom – to import an existing VHD – the one we will use here
  • CreateNew – to create a new raw disk

The syntax of the cmdlet is:
$vm | Add-AzureDataDisk | Update-AzureVM

So, we need to get the VM, then pipe it through in that way. First check that you have the right VM. See which ones you have available:

Get-AzureVM
Then pick one:
$VM = get-azurevmServiceName mytestserviceabcdefName NAVPC

Check that you still have the location for your VHD and then store that in another new variable:
$NewVHD = “https://$SourceStorageAccount.blob.core.windows.net/myvm/NewVHD.vhd”

Then put $VM through the pipe (or edit the line above if you want to have it all in just one line):
$VM | Add-AzureDataDiskImportFromDiskLabelMyStuff” –MediaLocation $NewVHDLUN  3 | Update-AzureVM

If you want to watch as it is happening, connect (RDC) to one of your Azure VMs and run File Explorer. Leave that in the background – it will update automatically and you can see when the disk is added. The disk is ready to use, and the files you put on it back when the disk was still on your local machine, are available now in your VM.

To remove it again, run this:

$VM | Remove-AzureDataDiskLUN 3 -DeleteVHD | Update-AzureVM

Check what disks (if any) are still attached:

$VM | Get-AzureDataDisk

 

Note:

If you attach and then detach the disk, Azure may still hold a lease on this disk, and it may not be free to use yet or even to be deleted. This is the error you may get when trying to attach the disk again or delete it: “The MyDisk VHD is already registered with image repository as the resource with ID XYZ”. In this case we may not be able to delete the disk automatically, which is why in the example above, if we remove the disk, then delete the disk as part of that operation.

So, just to avoid problems like this: When we detach a disk, then just to keep things clean, use -DeleteVHD to remove the disk completely.

 

 

Jasminka Thunes, Escalation Engineer Dynamics NAV EMEA

Lars Lohndorf-Larsen, Escalation Engineer Dynamics NAV EMEA

Bas Graaf, Senior Software Engineer Dynamics NAV