legacy/Move-VM-from-AvSet-to-AvZone/Move-VM-from-AvSet-to-AvZone.ps1 (179 lines of code) (raw):

<# .SYNOPSIS Moves a VM into an Availability Zone .DESCRIPTION The script deletes the VM and recreates it preserving networking and storage configuration. THe script will snapshot each disk, create a new disk from the snapshot, and create the new VM with the new disks attached. There is no need to reinstall the operating system. IMPORTANT: the script does not VM extensions or any identities assigned to the Virtual Machine. Also, the script will not work for VMs with public IP addresses. VM has to be up and running, otherwise it will not collect all the needed information, like StorageAccountType. .EXAMPLE ./Move-VM-from-AvSet-to-AvZone.ps1 -SubscriptionName testsubscription -ResourceGroupName test-rg -VirtualMachineName vm1 -newAvailabilityZoneNumber 2 -proximityPlacementGroupID "resourceID" .LINK https://github.com/Azure/SAP-on-Azure-Scripts-and-Utilities .NOTES v0.1 - Initial version #> #Requires -Modules Az.Compute #Requires -Modules Az.Network #Requires -Version 5.1 param( #Azure Subscription Name [Parameter(Mandatory = $true)][string]$SubscriptionName, #Resource Group Name that will be created [Parameter(Mandatory = $true)][string]$ResourceGroupName, #Virtual Machine name [Parameter(Mandatory = $true)][string]$VirtualMachineName, #Number of Availability Zone [Parameter(Mandatory = $true)][string]$newAvailabilityZoneNumber, #Proximity placement group [Parameter(Mandatory = $false)][string]$proximityPlacementGroupID ) # select subscription Write-Verbose "setting azure subscription" $Subscription = Get-AzSubscription -SubscriptionName $SubscriptionName if (-Not $Subscription) { Write-Host -ForegroundColor Red -BackgroundColor White "Sorry, it seems you are not connected to Azure or don't have access to the subscription. Please use Connect-AzAccount to connect." exit } Select-AzSubscription -Subscription $SubscriptionName -Force # Get the details of the VM to be moved to the Availability Set Write-Verbose "" Write-Verbose "getting VM config" $destzone = [int]$newAvailabilityZoneNumber Write-Verbose $destzone if ($destzone -lt 1 -or $destzone -gt 3) { Write-Host -ForegroundColor Red "Sorry, the value for avalability zones is 1,2 or 3" exit } $originalVM = Get-AzVM -ResourceGroupName $ResourceGroupName -Name $VirtualMachineName # We don't support moving machines with public IPs, since those are zone specific. check for that here. foreach ($nic in $originalVM.NetworkProfile.NetworkInterfaces) { $thenic = $nic.id $nicname = $thenic.substring($thenic.LastIndexOf("/") + 1) $othernic = Get-AzNetworkInterface -Name $nicname -ResourceGroupName $ResourceGroupName foreach ($ipc in $othernic.IpConfigurations) { $pip = $ipc.PublicIpAddress if ($pip) { Write-Host -ForegroundColor Red "Sorry, machines with public IPs are not supported by this script" exit } } } [string]$osType = $originalVM.StorageProfile.OsDisk.OsType [string]$location = $originalVM.Location [string]$storageType = $originalVM.StorageProfile.OsDisk.ManagedDisk.StorageAccountType $tags = $originalVM.Tags # Create the basic configuration for the replacement VM if ($VerbosePreference -eq "Continue") { if ($proximityPlacementGroupID -ne "") { $newVM = New-AzVMConfig -VMName $VirtualMachineName -VMSize $originalVM.HardwareProfile.VmSize -zone $destzone -Tags $tags -ProximityPlacementGroupId $proximityPlacementGroupID -Verbose } else { $newVM = New-AzVMConfig -VMName $VirtualMachineName -VMSize $originalVM.HardwareProfile.VmSize -zone $destzone -Tags $tags -Verbose } } else { if ($proximityPlacementGroupID -ne "") { $newVM = New-AzVMConfig -VMName $VirtualMachineName -VMSize $originalVM.HardwareProfile.VmSize -zone $destzone -Tags $tags -ProximityPlacementGroupId $proximityPlacementGroupID } else { $newVM = New-AzVMConfig -VMName $VirtualMachineName -VMSize $originalVM.HardwareProfile.VmSize -zone $destzone -Tags $tags } } # Stop the VM, snap and copy the os disk Stop-AzVM -ResourceGroupName $ResourceGroupName -Name $VirtualMachineName -force Write-Verbose "snapshotting disks" $snapshotcfg = New-AzSnapshotConfig -Location $location -CreateOption copy -SourceResourceId $originalVM.StorageProfile.OsDisk.ManagedDisk.Id $osdiskname = $originalVM.StorageProfile.OsDisk.Name $snapshotName = $osdiskname + "-snap" $snapshot = New-AzSnapshot -Snapshot $snapshotcfg -SnapshotName $snapshotName -ResourceGroupName $ResourceGroupName $newdiskConfig = New-AzDiskConfig -AccountType $storageType -Location $location -CreateOption Copy -SourceResourceId $snapshot.Id -zone $destzone $newdiskName = $osdiskname + "-z" + $destzone $newdisk = New-AzDisk -Disk $newdiskConfig -ResourceGroupName $ResourceGroupName -DiskName $newdiskName Write-Verbose ("new disk info {0}" -f $newdisk.ManagedDisk.Id) Write-Verbose ("newdisk {0}" -f $newdisk ) Write-Verbose ("newdisk.manageddisk {0}" -f $newdisk.ManagedDisk) Write-Verbose ("newdisk.manageddisk.id {0}" -f $newdisk.ManagedDisk.Id) Write-Verbose ("the newdisk value is {0}" -f $newdisk) Write-Verbose ("the newdisk.Id value is {0}" -f $newdisk.Id) Write-Verbose ("the newVM.Name value is {0}" -f $newVM.Name) if ($osType -eq "Linux") { Write-Verbose "OS Type is Linux" if ($VerbosePreference -eq "Continue") { Set-AzVMOSDisk -VM $newVM -CreateOption Attach -ManagedDiskId $newdisk.Id -Name $newdisk.Name -Linux } else { Set-AzVMOSDisk -VM $newVM -CreateOption Attach -ManagedDiskId $newdisk.Id -Name $newdisk.Name -Linux } } if ($osType -eq "Windows") { Write-Verbose "OS Type is Windows" if ($VerbosePreference -eq "Continue") { Set-AzVMOSDisk -VM $newVM -CreateOption Attach -ManagedDiskId $newdisk.Id -Name $newdisk.Name -Windows -Verbose } else { Set-AzVMOSDisk -VM $newVM -CreateOption Attach -ManagedDiskId $newdisk.Id -Name $newdisk.Name -Windows } } # Snapshot & copy all of the drives foreach ($disk in $originalVM.StorageProfile.DataDisks) { #snapshot & copy the data disk $snapshotcfg = New-AzSnapshotConfig -Location $location -CreateOption copy -SourceResourceId $disk.ManagedDisk.Id $snapshotName = $disk.Name + "-snap" $snapshot = New-AzSnapshot -Snapshot $snapshotcfg -SnapshotName $snapshotName -ResourceGroupName $ResourceGroupName $diskName = $disk.Name + "-z" + $destzone $diskConfig = New-AzDiskConfig -AccountType $storageType -Location $location -CreateOption Copy -SourceResourceId $snapshot.Id -zone $destzone $newdisk = New-AzDisk -Disk $diskConfig -ResourceGroupName $ResourceGroupName -DiskName $diskName if ($VerbosePreference -eq "Continue") { Add-AzVMDataDisk -VM $newVM -Name $newdisk.Name ` -ManagedDiskId $newdisk.Id ` -Caching $disk.Caching ` -Lun $disk.Lun ` -DiskSizeInGB $newdisk.DiskSizeGB ` -CreateOption Attach ` -Verbose } else { Add-AzVMDataDisk -VM $newVM ` -Name $newdisk.Name ` -ManagedDiskId $newdisk.Id ` -Caching $disk.Caching ` -Lun $disk.Lun ` -DiskSizeInGB $newdisk.DiskSizeGB ` -CreateOption Attach } } foreach ($nic in $originalVM.NetworkProfile.NetworkInterfaces) { if ($nic.Primary -eq $true) { if ($VerbosePreference -eq "Continue") { Add-AzVMNetworkInterface -VM $newVM -Id $nic.Id -Primary -Verbose } else { Add-AzVMNetworkInterface -VM $newVM -Id $nic.Id -Primary } Write-Verbose ("Primary nic {0}" -f $nic.Id) } else { if ($VerbosePreference -eq "Continue") { Add-AzVMNetworkInterface -VM $newVM -Id $nic.Id -Verbose } else { Add-AzVMNetworkInterface -VM $newVM -Id $nic.Id } Write-Verbose ("nic {0}" -f $nic.Id) } } # Shutdown or remove the original VM # Stop-AzVM -ResourceGroupName $ResourceGroupName -Name $VirtualMachineName -force Write-Verbose "removing existing VM" Remove-AzVM -ResourceGroupName $ResourceGroupName -Name $VirtualMachineName -force Write-Verbose "creating zonal VM" if ($VerbosePreference -eq "Continue") { New-AzVM -ResourceGroupName $ResourceGroupName -Location $originalVM.Location -VM $newVM -DisableBginfoExtension -zone $destzone -Verbose } else { New-AzVM -ResourceGroupName $ResourceGroupName -Location $originalVM.Location -VM $newVM -DisableBginfoExtension -zone $destzone }