Move a VM's Primary NIC from one VNET to another.

There is currently a limitation in Azure VMs that will not allow a NIC to be moved to a different VNET.  The ability for an Azure contributor to modify their cloud, just like they would modify their on premise datacenter is critical.  One of the common requirements on premise is the VLAN change request.

The AzureFoundation, https://aka.ms/azure/foundation, is my repository, and you will find in the ARM directory structure there are specific patterns that will deploy an enterprise pattern.  Often things get deployed that don't follow the enterprise pattern and have to be moved into it.

In this example, the powershell is hosted in the ARM/Compute/Utilities folder, with the name ModifyMVVNET.ps1.

My approach was to apply the VNET migration to an entire subscription, where you can go through all the VMs and individually assign the VM a new network.  This was a horrible way to test my script, basically had to manually fix all the VMs manually.  After testing this out, I can see how you may prefer to apply the utility VM by VM, to compromise, I limited the scope to a ResourceGroup.

Details for the PowerShell.

  1. Login.  Note the $Environment variable, as my customers often are using the Government CloudLogin-AzureRmAccount -Environment $Environment
  2. Focus on a Subscription.  One of my friends told me about the Out-GridView option!$subscription = Get-AzureRmSubscription | Out-GridView -PassThru
  3. Focus on a ResourceGroup.$ResouceGroup = Get-AzureRMResourceGroup | Out-GridView -PassThru
  4. Get the VMs in the ResourceGroup$VMs= Get-AzureRMVM -ResourceGroupName $ResouceGroup.ResourceGroupName
  5. Cycle through the VM and help the user select the To-Be VNET and Subnet, as well as the Static IP address.
    • Select the new Network, hopefully knowing the current network information will help guide what network to choose. $NewNetwork = Get-AzureRmVirtualNetwork |Select-Object -property Name,Location,ResourceGroupName,AddressSpacetext | Out-GridView -passthru $NewNetwork = Get-AzureRmVirtualNetwork -Name $NewNetwork.Name -ResourceGroupName $NewNetwork.ResourceGroupName
    • Select the new Subnet $NewSubnet = Get-AzureRmVirtualNetworkSubnetConfig -VirtualNetwork $NewNetwork | Select-Object -Property Name,AddressPrefix |Out-GridView -PassThru -Title $Title $NewSubnet = Get-AzureRmVirtualNetworkSubnetConfig -VirtualNetwork $NewNetwork -Name $NewSubnet.Name
    • Set the Private IP address variable $message = "current name: " + $vm.name + ", Current IP: " +$NIC[0].IpConfigurations.privateIPAddress+ ", New IP must be in this prefex: " + $NewSubnet.AddressPrefix $NewPrivateIP = Read-Host $message
    • Start a new IPConfiguration object $NewIPConfig = New-AzureRmNetworkInterfaceIpConfig -Subnet $NewSubnet -Name 'config1' -Primary -PrivateIpAddress $NewPrivateIP
    • Start a new NIC object $NewNic = New-AzureRmNetworkInterface -Name "$($NicName)1a" -ResourceGroupName $Nic.ResourceGroupName -Location $Nic.Location -IpConfiguration $NewIPConfig -Force
    • Since we are changing the Primary NIC, we need to remove the current NIC from the $VM. $VM = Remove-AzureRmVMNetworkInterface -VM $VM -NetworkInterfaceIDs $Nic.Id
    • Now the $VM doesn't have a NIC, so we can add the one in the new Subnet $vm = Add-AzureRmVMNetworkInterface -VM $VM -NetworkInterface $NewNic
    • OK, have your change tickets ready!  We will stop the current VM and we'll have to remove it since that is the only way to get our NIC associated to the VM. Stop-AzureRmVM -Name $VM.Name -ResourceGroupName $Vm.ResourceGroupName -Force Remove-AzureRmVM -Name $VM.Name -ResourceGroupName $Vm.ResourceGroupName -Force
    • Next we create the new VM, using the $VM we have in memory, with the only change to the definition of the $VM being the network interface.  This step has turned out to be challenging.  Some VMs have Data Disks, some don't.  Some VM's may be Linux, some Windows.   The best way to illustrate the work done is to look at the PowerShell. $NewVM = $newVMConfig | New-AzureRmVM -ResourceGroupName $vm.ResourceGroupName -Location $vm.Location

Some concepts to add:

  • Add Extensions, in other words if the VM has extensions, make sure they get added back. $vm.extensions

  • Clean up the old NICs by removing them