Part 4: Restore Virtual Machine Endpoints And Virtual Network Settings

Last week I briefly mentioned you have to re-configure all the settings on your VM when you restore it from a VHD image, you basically only get the hard disk back. Today I’m going to show you a few more details around restoring your VM endpoints and virtual network settings.

If you are completely new to Azure Virtual Networks please read the intro here. Among other things you use them to assign DHCP pools, create VPN connections and setup security groups. The feature I found the most useful was connecting VMs from different cloud services to the same internal network by putting them all on the same VNet. It is a lot simpler than having multiple VMs in the same cloud service and mapping all those external endpoints with different port numbers to the VMs inside the cloud service. By using different cloud services you can also give each VM its own public DNS name.

You can add and remove endpoints after creating your VM but I could not find a way to change the VNet of a VM after it was created, apart from recreating the VM , so it is important to specify the VNet when you create the VM. For example in this script I pipe the VM config, subnet name and static IP address to the New-AzureVM command and I pass the -VNetName parameter with the name of my VNet.

New-AzureVMConfig -Name "TestVM" -InstanceSize "Standard_D2" -ImageName "VMImage" |
Set-AzureSubnet -SubnetNames "Subnet-1" |
Set-AzureStaticVNetIP -IPAddress "10.0.0.10" |
New-AzureVM -ServiceName "NewService" -VNetName "Test VNet"

If you don’t need a static IP you can omit the Set-AzureStaticVNetIP line.

Next up I’m going to map some endpoints to my VM.

Get-AzureVM -ServiceName "NewService" -Name "TestVM" |
Add-AzureEndpoint -Name "Remote Desktop" -Protocol "tcp" -PublicPort 3389 -LocalPort 3389 |
Add-AzureEndpoint -Name "PowerShell" -Protocol "tcp" -PublicPort 5986 -LocalPort 5986 |
Update-AzureVM

I used known port numbers but for a very small amount of extra security you can use different ports. This is a very simple example, I didn’t use load balancing for instance, if you read the documentation you will see how to do that.

Tip: In my environment while I was deleting the existing VM and creating a new one from the imaged VHD I sometimes received this error:

New-AzureVM : Networking.DeploymentVNetAddressAllocationFailure : Unable to allocate the required address spaces for the deployment in a new or predefined subnet that is contained within the specified virtual network.

It happened intermittently and it turned out sometimes Azure took a while to release the static IP address. To try and avoid the problem I stop and deprovision the VM first before deleting it and I also added a retry loop in my PowerShell script. I didn’t have time to test it exhaustively so I can’t confirm that it is working but it looks that way.

Keep in mind this can also happen if another VM is using the same IP address as the one you are trying to assign to your VM. If you look at the list of IP address assigned to your running VMs in the portal you can see if it is already in use.

I didn’t experience this one myself but when I was investigating this error message I came across posts where users received this error but the IP was not in use when they looked at the portal. It turned out that the static IP was assigned at the OS level, never do that, always assign the static IP in the Azure. Just out of interest, you will notice when you assign a static IP to the VM in Azure it doesn’t show in your NIC settings in Windows control panel, everything happens in Azure not the OS.

Francois Delport

Copying Files To And From Azure Blob Storage

I had a situation today where I had to copy a file from a build server on premise to a location where a VM in Azure could access it as part of an automated process.

You have a few options that I know about, some of which are:

  • Ideally you would connect to Azure using VPN and then treat the VMs like any other machine on the network and copy to a share but that was not a possible at the moment.
  • Next best option seemed like Azure File Service but the subscription I was using had to join the preview program first and I couldn’t know for sure how long it would take to activate.
  • Next option I looked at was using Azure Blob Storage. It turned out to work pretty well.

If you are going to copy files on an ad hoc basis or you want to avoid rolling your own PowerShell script and you don’t mind installing extra tools on your build server AzCopy is pretty straight forward to use. You can download the latest version of it here. AzCopy can be used with Azure File Storage, Blob Storage and Table Storage.

In Blob Storage your blobs are stored in containers, you can think of it almost like a folder/directory, to create one is pretty easy using PowerShell.

New-AzureStorageContainer -Name testfiles -Permission -Off

Note the container name must be lower case. In this example I set the permissions to the owner of the storage account only, but you can make it public if you have the requirement. In this case I’m copying all the files from a folder on my local machine “C:\TestUpload” to the “testfiles” container.

AzCopy /Source:C:\TestUpload
/Dest:https://YourStorageAccount.blob.core.windows.net/testfiles /DestKey:YourStorageKey

You can get your Blob URL and storage key the from the Azure Portal under the Storage tab.

In the end I went with PowerShell to avoid installing tools on the build servers plus the build process already used PowerShell. In my case the build process created the artifact we needed as a single zip file, thus the script was very simple.

Set-AzureStorageBlobContent -Container testfiles
-File C:\TestUpload\TestCases.zip -Blob TestCases.zip

If you wanted to copy all the files in a folder you would have to iterate over them and call Set-AzureStorageBlobContent on each one, a quick Google search showed multiple examples on how to do that. Using AzCopy makes this scenario easier since you can tell it to copy a folder and do it recursively as well.

On the Azure VM I had to download the file again as part of the script running the tests.

Get-AzureStorageBlobContent -Blob TestCases.zip -Container testfiles -Destination TestCases.zip

Very easy to do and it worked very well in this situation.

Note: if you have a large number of files to upload it is better to do them in parallel since it can be a bit slow.

Francois Delport

Part 3: How To Snapshot And Restore Azure Virtual Machines

UPDATE: For Azure Resource Manager virtual machine snapshots using managed disks read this post and for unmanaged disks read this post.

This post covers Azure Service Manager (ASM) virtual machines.

If you are familiar with VMWare and Hyper-V you’ll know how easy and handy it is to snapshot a VM and return to that snapshot later on. I use it especially when testing installers and automated deployments where you have to run them multiple times on a clean machine.

In this post I’m going to show you how to “snapshot” a VM in Azure and then revert back to that snapshot. I refer to it as a snaphot but Azure doesn’t support snapshots, this is more a workaround that involves capturing the VM virtual hard disk image and storing it in BLOB storage.

In other virtualisation platforms a snapshot captures the disk at that point in time, when you make changes to the file system in your VM your changes are written to a delta file that contains only the modifications from the previous snapshot. This way you can quickly revert back or roll forward between snapshots. This is a very simplified explanation, there is lots more if you want to read. In Azure it is not so quick since the whole VM image is captured and then restored when you revert back to it.

Something else I want to point out before we get started is the difference between generalised and specialised VM images. You can read the whole explanation here. In short you should not clone new VMs from a specialised image since it can lead to problems if your VM is in a domain. It also causes problems with other software like Octopus Deploy since every machine gets a unique certificate when the Tentacle is configured. If you are capturing a VM image to clone it, run SysPrep first to generalise it.

Now on to the fun part, the script. If this is your first time running PowerShell against Azure refer to this post to setup your environment. In PowerShell run the following to capture your image.

Save-AzureVMImage -ServiceName "YourServiceName" -Name "YourVmName" -ImageName "DescriptiveImageName" -OSState Specialized

If you open up the Cloud Explorer in Visual Studio you will see your new VHD image under:
Storage Accounts -> YourStorageAccountName -> Blob Containers -> vhds

Or you can see it in the portal under your storage account.

To revert back to this image you have to delete your existing VM and its disk and  create a new one from this saved VHD image. First make sure your image was created successfully before deleting your VM.

Remove-AzureVM -Name "YourVMName" -ServiceName "YourServiceName" -DeleteVHD

Then create a new VM from the image into your existing service.

New-AzureQuickVM -Name "YourVMName" -ImageName "DescriptiveImageName" -Windows -ServiceName "YourServiceName"  -InstanceSize "Basic_A2" -WaitForBoot

Since this is a new VM your previous Azure configuration will be gone, you have to create the endpoints for this VM again and so on. If you use a virtual network be sure to specify your Vnet when you create the VM as far as I am aware you can’t change it afterwards.

Tip: If you get a “CurrentStorageAccountName is not accessible” error you have to set your default storage account for the subscription by running:

Get-AzureStorageAccount

Take note of the storage account name then run:

Set-AzureSubscription -SubscriptionName "YourSubscriptionName" -CurrentStorageAccountName "YourStorageAccountName" -PassThru

Francois Delport

Part 2: Creating Azure Virtual Machines Using Powershell – The Actual Script

In my previous post I explained what a cloud service is in relation to virtual machines in Azure. I want to mention virtual networks quickly as well since it ties in with your cloud service and virtual machine network configuration before we create a VM.

If you want VMs from multiple cloud services to connect to each other via the internal network instead of public IP addresses you can add them to a virtual network. You also need a virtual network to connect your on-premise infrastructure to Azure via VPN. I will cover the details of virtual networks and VPN in a future post.

When you create a new VM you can choose to add it to an existing virtual network or you can create a new virtual network or you can create it without a virtual network. Is this screenshot I am creating a new VM and using an existing virtual network called “demo”. You will see why this matters when you run the script to create a VM.

VNET

Finally I can get to the actual demo to create a VM in Azure.

You can download Azure PowerShell modules using the Microsoft Web Platform installer. Before you can run PowerShell scripts against your Azure VMs you have to import your publish settings file. Open up PowerShell and run the following command.

Get-AzurePublishSettingsFile

This will launch the Azure Portal in your default browser, sign in and follow the instructions to download your publish settings. Remember to save the file with a .publishsettings extension and put in a directory where you can reach it easily. Back in PowerShell execute the following command to import your file that was downloaded in the previous step.

Import-AzurePublishSettingsFile PathToPublishSettingsFile.publishsettings

And here is the PowerShell script to create a new VM:

$ImageName = "a699494373c04fc0bc8f2bb1389d6106__Windows-Server-2012-R2-20150726-en.us-127GB.vhd"
$VmName = "NewVMName"
$InstanceSize = "Standard_D1"
$AdminUsername = "MyNewAdmin"
$Password = "MyNewPassword"
$Location = "West US"
$ServiceName = $VmName

#Set the image
$Img = Get-AzureVMImage -ImageName $ImageName

#Create the config
$NewVM = New-AzureVMConfig -Name $VmName -InstanceSize $InstanceSize -ImageName $Img.ImageName | Add-AzureProvisioningConfig -Windows -AdminUsername $AdminUsername -Password $Password

#Create the vm
New-AzureVM -VMs $NewVM -WaitForBoot -Verbose -Location $Location -ServiceName $ServiceName

This is a bare bones example, if you look at the documentation there are lots more you can do: Link to MSDN

Parameters Explained

$ImageName: is the name of the image you are using to create this VM. To see which VM images are available, including your own images you created, you can run: Get-AzureVMImage
$VmName: The name for you new VM.
$InstanceSize: The size of the hardware for your VM. To see which instance sizes are available use this link.
$AdminUsername and $Password is the username and password for the administrator user that will be created on this new VM.
$Location: Is the location for this new VM, to get the list of locations run: Get-AzureLocation

NOTE: If you specify the -Location or -AffinityGroup parameters Azure will create a new cloud service for this VM. In this script it will create a new cloud service with the same name as the VM, it is stored in $ServiceName. To add this VM to an existing cloud service specify the -ServiceName parameter but leave out -Location.

I didn’t specify a virtual network for this VM but you can use the -VNetName parameter to do that.

Tip: Make sure your password is valid according to Azure standards. The first one I used wasn’t and the PowerShell script didn’t fail, it happily created the VM but the admin user wasn’t valid and I had to reset the password before I was able to RDP into the machine.
Secondly when you create the storage account you can’t use zone redundant storage for VM disks.

Francois Delport