I recently found myself in the need to copy a couple of Azure Virtual Machines from one subscription to another. Not having used Azure that much before, I figured there must be support to perform this kind of migration from inside the Azure portal itself.
Turns out there isn't, but that does not mean it is impossible, or even hard for that matter. Once you figure it out, it is actually quite frictionless and smooth.
The easy and, as it turns out, slow way it to go to the Azure Portal, click Storage, then the name of your storage, followed by Containers at the top. You should now see a container called Vhds. Clicking that will list all of the VHD file you have on your subscription.
By selecting one of the files the then clicking the Download button, at the bottom of the page, Azure will start a file download straight in the browser. I am on a 100 mbit connection and I was only getting around 4MB/s on average.
Normally that is a pretty OK download speed, but I was looking to transfer two VHD files that totalled at 150GB of data. Needless to say it would take quite a while to complete so I needed another solution.
Blob Service REST API
Microsoft was nice enough to create a nice Blob Service REST API that you can use to programatically access the content of your containers.
To do this, the API uses the concept of access keys. If you have the name and access key to a storage, then you can use that to access the files that are stored in it.
You find your keys by going to the Azure Portal, click on Storage then Manage Access Keys at the bottom of the page. There are two keys, the primary and the secondary. Both do the same thing, but Azure gives you a convinent way to have a personal key and a key you give to services etc. that you wish to gain access to your storage.
At anytime you can regenerate theys keys if you feel they've been compromised or if you have given them to some service and you no longer wish them to be valid. Just click the Regenerate button next to the key you wish to create a new one for.
AzCopy to the rescue
I tried a couple of different tools, that uses the Blob Service REST API, but they all suffered from the same problem as the browser download option - speed.
It just so happened that as of CTP2, AzCopy supports the Asynchronous Cross-Account Copy Blob feature of the Blob Service REST API.
NOTE: To use this feature, your storage account must have been created after June 7th 2012. Read more about this limitaion on the previous link
What this enables you to do is to copy from one store to another, without the need to first copying the data locally. This drastically improved the transfer speed. Using AzCopy I was getting speeds at around 45MB/s instead of 4MB/s!
I ended up using the following command
AzCopy https://<sourceaccount>.blob.core.windows.net/<sourcecontainer>/ https://<destaccount>.blob.core.windows.net/<destcontainer>/ /sourcekey:<key> /destkey:<key> /S
and it worked great!
A word of caution on Azure Disks vs Images
After I had copied the VHD files to my second subscription, I set out to re-create my virtual machines. This is where I messed up a bit. I went into Virtual Machines and then Images where I created images of the VHD files. What I should have done is gone into Virtual Machines followed by Disks
The difference between the two is that images are like templates. You use them to create a completley new VHD file, based on the image, that you then use as a disk for your virtual machine.
Since I was copying existing machines across, I just needed to create disks directly, that I then used to create my virtual machines from.
When I created a virtual machine from one of the images, it worked fine (I could login to the machine), except for Azure getting stuck while provisioning my machine. So even though the machine was functional, it was not sitting quite right with Azure. Once I changed to use a disk, it immediatly behaved as I expected.