Friday 2 June 2017

Move Azure VM across Cloud Service

I came across a requirement of moving my azure VMs from one cloud service to another in same subscription. I had Azure VMs having same prefix like ‘MyProjectVM(N)’ where N is from 1..N. So here comes my blog providing such solution.
Below is the code to move a VM from one cloud service to another and then we will look later as to how we can reuse this code to move multiple VMs.
Prerequisites
Virtual Network, Affinity Group and Storage Account are already created.
Steps to move one VM
1. Manual Step from Microsoft Azure Portal – Create a New Cloud Service(destination cloud service), if not already exists. Create a TestVM in the new cloud service with required affinity group and virtual network information mentioned while creating. This step is required if you want to associate your destination cloud service with the virtual network. We can delete TestVM once at least one VM is moved to the destination cloud service.
2. Follow Below steps to move VM
a. Declare Variables
   1: #Step 1 : Declare Variables
   2: $CurrentCloudServiceName = "CurrentService"
   3: $NewCloudServiceName = "NewService"
   4: $StorageAccount = "MyProjectStoarge"
   5: $SubscriptionName = "My Project Subscription"
   6: $VMNameToMove = "MyProjectVM1"
   7: $SavedVMStateFilePath = "E:\XML\MyProjectVM1.xml"
b.  Set Storage Account
   1: #Step 2 : Set Azure Subscription
   2: Set-AzureSubscription -SubscriptionName $SubscriptionName -CurrentStorageAccountName $StorageAccount
   3: Select-AzureSubscription $SubscriptionName
c. Export VM
   1: #Step 3 : Export VM
   2: Get-AzureVM -ServiceName $CurrentCloudServiceName -Name $VMNameToMove
   3: Export-AzureVM -ServiceName $CurrentCloudServiceName -Name $VMNameToMove-path $SavedVMStateFilePath
d. Edit Azure VM Saved State XML File
This step is required to avoid conflicts in PowerShell endpoint public port.
Open XML File saved in step ‘Export-AzureVM’ above. Look for PowerShell Endpoint which ‘5986’ by default. Modify ‘Port””’ number which is the public port information. Keep ‘LocalPort’ as it is. Save file and close it.
   1: <InputEndpoint>
   2:   <LocalPort>5986</LocalPort>
   3:   <Name>PowerShell</Name>
   4:   <Port>61204</Port>
   5:   <Protocol>tcp</Protocol>
   6:   <Vip>**.**.**.***</Vip>
   7:   <EnableDirectServerReturn>false</EnableDirectServerReturn>
   8: </InputEndpoint>
e. Remove Azure VM
   1: #Step 5 : Remove VM
   2: Remove-AzureVM -ServiceName $CurrentCloudServiceName -Name $VMNameToMove
f. Import Azure VM into new Cloud Service
   1: #Step 6 : Import VM to new Cloud Service
   2: Import-AzureVM -Path $SavedVMStateFilePath | New-AzureVM -ServiceName $NewCloudServiceName
g. Delete TestVM manually from Microsoft Azure Portal.
The full script will look like below:-
   1: #Step 1 : Declare Variables
   2: $CurrentCloudServiceName = "CurrentService"
   3: $NewCloudServiceName = "NewService"
   4: $StorageAccount = "MyProjectStoarge"
   5: $SubscriptionName = "My Project Subscription"
   6: $VMNameToMove = "MyProjectVM1"
   7: $SavedVMStateFilePath = "E:\XML\MyProjectVM1.xml"
   8:
   9: #Step 2 : Set Azure Subscription
  10: Set-AzureSubscription -SubscriptionName $SubscriptionName -CurrentStorageAccountName $StorageAccount
  11: Select-AzureSubscription $SubscriptionName
  12:
  13: #Step 3 : Export VM
  14: Get-AzureVM -ServiceName $CurrentCloudServiceName -Name $VMNameToMove
  15: Export-AzureVM -ServiceName $CurrentCloudServiceName -Name $VMNameToMove -path $SavedVMStateFilePath
  16:
  17: #Step 4 : Edit Saved State (Manual Step)
  18:
  19: #Step 5 : Remove VM
  20: Remove-AzureVM -ServiceName $CurrentCloudServiceName -Name $VMNameToMove
  21:
  22: #Step 6 : Import VM to new Cloud Service
  23: Import-AzureVM -Path $SavedVMStateFilePath | New-AzureVM -ServiceName $NewCloudServiceName
Code to move multiple VMs
We can modify above script to move multiple VMs with similar names from one cloud service to another cloud service. In my case the VMs were named like MyProjectVM1, MyProjectVM2… The script will look like below:-
   1: #Step 1 : Declare Variables
   2: $CurrentCloudServiceName = "CurrentService"
   3: $NewCloudServiceName = "NewService"
   4: $StorageAccount = "MyProjectStoarge"
   5: $SubscriptionName = "My Project Subscription"
   6: $VMNamePrefix = "MyProjectVM"
   7: $VMCount = 5
   8: $SavedVMStateFilePath = "E:\XML\"
   9:
  10: #Step 2 : Set Azure Subscription
  11: Set-AzureSubscription -SubscriptionName $SubscriptionName -CurrentStorageAccountName $StorageAccount
  12: Select-AzureSubscription $SubscriptionName
  13:
  14: #Step 3 : Export VMs
  15: for($vmNum = 1; $i -le $VMCount; $vmNum++)
  16: {
  17:     $VMNameToMove = $VMNamePrefix + $vmNum
  18:     $SavedVMStateFilePathFull = $SavedVMStateFilePath + $VMNamePrefix + $vmNum + ".xml"
  19:     Get-AzureVM -ServiceName $CurrentCloudServiceName -Name $VMNameToMove
  20:     Export-AzureVM -ServiceName $CurrentCloudServiceName -Name $VMNameToMove -path $SavedVMStateFilePathFull
  21: }
  22:
  23: #Step 4 (Manual Step) : Edit Azure VM Saved State XML File - Change PowerShell endpoint Public Port (as different VMs should have different public ports)
  24:
  25: #Step 5 : Remove Azure VMs from current cloud service
  26: for($vmNum = 1; $i -le $VMCount; $vmNum++)
  27: {
  28:     $VMNameToMove = $VMNamePrefix + $vmNum
  29:     Remove-AzureVM -ServiceName $CurrentCloudServiceName -Name $VMNameToMove
  30: }
  31:
  32: #Step 6 : Import Azure VMs in new cloud service
  33: for($vmNum = 1; $i -le $VMCount; $vmNum++)
  34: {
  35:     $VMNameToMove = $VMNamePrefix + $vmNum
  36:     $SavedVMStateFilePathFull = $SavedVMStateFilePath + $VMNamePrefix + $vmNum + ".xml"
  37:     Import-AzureVM -Path $SavedVMStateFilePathFull | New-AzureVM -ServiceName $NewCloudServiceName
  38: }

Happy Coding!!!

Useful Info (Thanks Davis for this note)
If you get some warning like this “New-AzureVM : BadRequest: The virtual network ID cannot be null or empty.”
Is because you have a Site to Site VPN. You need to add -VNetName cmd like this: (include the ” “)
Import-AzureVM -Path $SavedVMStateFilePath | New-AzureVM -ServiceName $NewCloudServiceName -VNetName “NetAzure”

1 comment:

  1. This comment has been removed by a blog administrator.

    ReplyDelete