Migrate VMs between Azure subscriptions

Azure provide a very poor mechanism to share VM images between subscriptions, while Amazon could easily share images between account.

The following page provide enough PowerShell to automate the whole process, but it can’t work if we have VNet configuration for source VM.

http://blogs.msdn.com/b/microsoft_press/archive/2014/01/29/from-the-mvps-copying-a-virtual-machine-from-one-windows-azure-subscription-to-another-with-powershell.aspx

I revise and add support on VNet configuration, and package scripts to a file.

https://github.com/tombwu/AzureLab/blob/master/CopyVmBetweenSubscriptions.ps1

Just use a command as below, you may migrate VM to another subscription.

.\CopyVmBetweenSubscriptions.ps1 -SourceVmName SrcDevBox -SourceServiceName SrcDevBox -SourceSubscriptionName “Sub1” -TargetServiceName DevBox2 -TargetSubscriptionName “Sub2”

Enjoy it!

Advertisements

Migrate Windows Server from AWS EC2 to Azure

I need to migrate several Windows VMs from AWS EC2 to Windows Azure.

The general practice AWS provide is using EC2 Exporting service to export VHD for EC2 instance.

http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ExportingEC2Instances.html

After I set up many environment variables,S3 bucket and permission for VM export account, I am able to run export command on EC2 CLI. But it is disappointing that the error message “Only imported instances can be exported.” showed.

Then I head to another solution to make VHD inside the Windows server by using a tool Disk2vhd.

https://technet.microsoft.com/en-us/library/ee656415.aspx

It is pretty easy to export VHD by the tool.

With VHD ready, now I could use Azure Powershell to upload VHD file (Add-AzureVHD command will convert VHD to fix type automatically), create OS disk from VHD and create VM instance from the disk.

So far I suspect that it is most fast way to move VM from EC2 to Azure if you could log in the Windows Server.

Build complex cross Azure subscription Windows lab by using Azure Site to Site VPN

Azure Site to Site VPN (S2S VPN) started as a method to connect Azure VNet and on premise network. Now it appears as a good solution to connect Azure VNets as well.

https://azure.microsoft.com/zh-cn/documentation/articles/virtual-networks-configure-vnet-to-vnet-connection/

http://azure.microsoft.com/blog/2014/06/17/vnet-to-vnet-connecting-virtual-networks-in-azure-across-different-regions/

Equipped with Azure S2S VPN, we are able to build more complex Windows lab across Azure subscriptions. The diagram below show the idea. Compare to P2S VPN, S2S VPN is a much stable solution and could reserve static IP Address for DNS and Domain Controller.

Azure Site to Site VPN

The steps to make that happen are:

1. Create VNet per subscription.

2. Create gateway for each VNet. You may need to export VNetConfig, manually add local network and import config at first before that.

3. Create local network and build connection for each VNet. You must use VNetConfig file to do that. And gateway should be provisioned already as local network will need that.

4. Make all the VPN connection share the same gateway sharedkey.

Step 3 and step 4 will be very time-consuming as you need to create N*(N-1) local network if you have N VNet to connect together. I wrote a script to make step 2-4 automated.

All you need to do are step 1 + a .csv file to describe VNets + SharedKey.

The csv file looks like

Subscription,VNetName,AddressPrefix,GatewaySubnet
Sub-Center,centerVnet,10.0.2.0/24,10.0.2.32/27
Sub-West,westVnett,10.0.1.0/24,10.0.1.32/29
Sub-East,eastVnet,10.0.3.0/24,10.0.3.128/28
Sub-South,southVnet,192.168.0.0/24,192.168.0.160/28

AddressPrefix should not overlap with each other and GatewaySubnet not overlap the existed Subnet in the specific Vnet. You can find correct GatewaySubnet by adding a new subnet in Vnet config (don’t save).

Attach the code URL: https://github.com/tombwu/ConnectAzureVPN/blob/master/Site%20To%20Site/BuildSiteToSiteVPN.ps1

Build cross-subscription Windows lab by using Azure Point to Site VPN

We have several Azure subscriptions each of them has fixed budget, and we would like to build an united development lab base on those subscriptions. Unfortunately the Virtual Machine or Virtual Network in different subscription can’t communicate with each other under Azure policy.

To resolve the barrier, I explored and developed the following methodology which leverage Azure Point to Site VPN to connect Virtual Machines under multiple Azure subscriptions into a single Virtual Network. The diagram below show the idea by an Exchange lab.

P2S across subscription

The first step is setup Virtual Network and Point to Site VPN, you may follow the instruction from Azure: https://azure.microsoft.com/en-us/documentation/articles/vpn-gateway-point-to-site-create/

Next you can setup DNS server and Domain Controller in virtual network, those servers need static IP which it is hard to guarantee if you use P2S VPN to join virtual network.

After you create new VMs in other subscription and install VPN to connect to virtual network, you will need a method to connect P2S VPN automatically during start up before user log on. Here you may use the following script run when start up to make that happen.

https://github.com/TomWu1/ConnectAzureVPN

The major idea of the script is monitor whether the DNS server can be contacted and then try to resume VPN connection if failed. Also it will refresh route table and register DNS record via VPN connection.

Enjoy it and leverage multiple subscriptions to create an united lab.

The following link help me during the scripting.

http://feedback.azure.com/forums/217313-azure-networking/suggestions/5282432-auto-connect-for-point-to-site-vpn

http://www.diaryofaninja.com/blog/2013/11/27/deconstructing-the-azure-point-to-site-vpn-for-command-line-usage

Practice of migrate local Exchange testing labs to Azure

We need to migrate 5 local Exchange testing labs (15 VMs, 6 Domain Controllers) to Azure VM, and run Automation testing against those labs after migration complete. This blog elaborate the steps which I tried during the practice.

1. Prepare VM images and upload to Azure.

The local labs host on Hyper-V server. So we just use VHD file as our base images. Azure team provide a guideline to upload VHD and create VM: https://azure.microsoft.com/en-us/documentation/articles/virtual-machines-create-upload-vhd-windows-server/.

In the guideline the VM should be sysprepped before upload, but the VHDs we got are non-sysprepped because they are exported and uploaded to AWS S3 in advance.

For non-sysprepped VHDs, a necessary step for Azure is turning off Windows firewall on PowerShell and remote desktop port. Azure might failed to modify the firewall setting if your VHD is non-sysprepped, then you have no way to connect into your VM.

The VHDs need to be uploaded by Powershell Add-AzureVHD because Azure only support fixed disk type and the command will convert dynamic VHD in upload process. http://hindenes.com/trondsworking/2014/08/18/how-to-upload-vhd-files-to-azure/

2. Setup Virtual Network and create VM

The virtual network need to be setup at first, because we can’t modify VNet setting after VM is created.

As the VHD is non-sysprepped and we don’t want Azure to modify our OS settings, we need to create OS disk from VHD, then create VM from OS disk. In this way, we tell Azure just use OS in the disk rather than modify OS as Azure template. It is different with creating VM from image which will copy your VHD to a new one. So it would be better to backup your VHDs before you make major change on OS if you create VM from disk.

After the VM is created, Azure will try to install VM agent in your VM. The operation always fail in my experience, and I believe it is because Azure can’t get administration access in your OS. So you need to install VM agent manually once you could RDP to the VM.

https://msdn.microsoft.com/en-us/library/azure/dn832621.aspx

3. Resume Lab

DNS server should be the first VM resumed as other VMs depend on that. DNS server and Domain Controller will need static IP, a PowerShell command Set-AzureStaticVNetIP can be used.

Get-AzureVM ServiceName myvm -Name myvm | Set-AzureStaticVNetIP IPAddress ‘192.168.0.132’ | Update-AzureVM

Then you can set DNS server IP address in VNet configure so other VMs could use that DNS server for internal lookup.

Domain controllers should be resumed before Exchange servers. Here we need to discuss more about DNS server setting. I found a robust DNS setting on Azure is setup AD integrated DNS server on domain controller, then setup stub lookup zone on DNS server and point to domain controller. In this way, you don’t need to worry about time synchronization between DNS server and domain controller even you need to frequently shutdown and start up those servers.

For those Exchange servers, an important thing is reconnecting to domain controllers because the DC don’t know who is who after Exchange servers are recreated on Azure. We can reset computer account of the Exchange server on Active Directory Users and Computers, then quit and rejoin domain. Don’t attempt to quit and rejoin domain before reset computer account! That will make your Exchange server a new SID in Domain, it might break a lot of permission or relationship in lab.

It would be worth to rebuild trust if labs have trusts before, because I found some weird issue go away after I rebuild the trusts between domains.

Exchange is designed to start all the time, and have a lot services need to be running to keep Exchange work. But we need to stop and start those labs everyday for Automation Testing. For those services failed to start automatically because dependent service have not been started, we can put them into Automatic Start (Delay) status. Then those services have more chance to start automatically.

4. Azure limitation

Resume labs on Azure have some limitation.

Azure only support Server OS Windows 2008 and Windows 2012 series. So if your lab heavily need client OS or Windows 2003, Azure might not be your choice.

Azure Virtual Network don’t support broadcast. So you had better use FQDN in all your automation testing.

Azure Virtual Network can’t assign IP address per request, can only assign 1 IP address for 1 VM. So those features depends on new IP assignment like Exchange DAG can’t be deployed on Azure.

Use powershell to integrate fitnesse suite testing on Azure VM

I need to trigger Fitnesse test suite and get result in Teamcity build. But the Fitnesse server is different with Teamcity server and I don’t want to install Teamcity Agent on Fitnesse server. And both servers are on Azure VM.

My plan is using Powershell to trigger Fitnesse test suite and retrieve result through HTTP request. The HTTP Uri I used is like: http://%FitnesseServer%/%TestSuite%?suite&format=xml

At the beginning, I use Invoke-WebRequest to send http request. That works well in the suite which execute less than 5 minutes. But once the suite going longer, WebException: “The operation has timed out” is thrown and my Powershell scripting failed to complete.

After further investigation, I found the problem is that Fitnesse will not response anything before the whole suite test is complete. That will hit a lot of timeout mechanism in System.Net.

Then I rewrite my script by using System.Net objects directly, and set all the Timeout properties of HttpWebRequest and related ServicePoint to a proper time. But the ‘timed out’ issue still occur. That move my eye on server side rather than client side.

At last I find that Azure Load Balance has an ‘idle timeout’ setting of 4 minutes. That means if your connection is idle for 4 minutes, Azure may not maintain the connection between service and your application. So the solution is using $request.ServicePoint.SetTcpKeepAlive() to send keep-alive packet during idle time.

Please find the PowerShell script as below, hope that help you to handle similar scenario.


Param(
[parameter(Mandatory=$true)]
[string]
$Uri
)

[System.Net.ServicePointManager]::MaxServicePointIdleTime = 30*60*1000
$request = [System.Net.HttpWebRequest][System.Net.WebRequest]::Create($Uri)
$request.Method = “Get”
$request.KeepAlive = $true
$request.Timeout = 30*60*1000
$request.ReadWriteTimeout = 30*60*1000
$request.ProtocolVersion = [System.Net.HttpVersion]::Version11
$request.ServicePoint.ConnectionLeaseTimeout = 30*60*1000
$request.ServicePoint.MaxIdleTime = 30*60*1000
$request.ServicePoint.SetTcpKeepAlive($true,60*1000,30*1000)
try
{
$rp = [System.Net.HttpWebResponse]$request.GetResponse()
$stream = $rp.GetResponseStream()
$reader = New-Object System.IO.StreamReader($stream)
$ret = $reader.ReadToEnd()
$stream.Close()
$reader.Close()
$rp.Close()
}
finally
{
if ($null -ne $stream)
{
$stream.Close()
}
if ($null -ne $reader)
{
$stream.Close()
}
if ($null -ne $rp)
{
$stream.Close()
}
}
$ret

The link which help me:

http://azure.microsoft.com/blog/2014/08/14/new-configurable-idle-timeout-for-azure-load-balancer/

http://blogs.msdn.com/b/adarshk/archive/2005/01/02/345411.aspx