DEV Community

Olivier Miossec
Olivier Miossec

Posted on

Using PowerShell to rename, move or reconnect an Azure VM

Sometimes you need to change something on a VM. You may want to rename it for compliance reasons, change the network, change the disk name, etc

Once you create a VM in Azure there is no way to rename it or one of its components. Also, if you want to reconnect a VM to a different Virtual Network, you can’t. You can look in the portal, you can search the Azure PowerShell Cmdlet list or try with AZ CLI, you can’t.

Some will say that you can use a backup vault to recreate the VM but it takes times and it doesn’t scale. You can’t manage multiple VM like this.

We can automate this with PowerShell and the Azure PowerShell module.

Imagine if you need to rename a VM and its disk in the same resource group and the same Azure region

The first step is to create an object with the current VM configuration

$SourceVmObject = get-azvm -Name dsc-dns01 -ResourceGroupName MyRG 
Enter fullscreen mode Exit fullscreen mode

If the VM uses Azure Backup Vault, before continuing we need to remove the VM's recovery point.

When you create a Backup Vault, Azure will add an extra resource group named AzureBackupRF_RegionName_1, there is nothing visible inside (if you use the portal), but this where you can find the VM recovery point.

There are named after the VM name, AzureBackup_vmname_XXXXXXX and it needs to be deleted before any copy operation on the VM.

The problem is that it may fail sometime and you may need to do it again.

$LoopCondition = $false
$Count = 0
do { 
    try {
        Remove-AzResource -ResourceId $SourceVmRecoveryPoint.ResourceId -Force
        $LoopCondition = $true
    }
    catch {
        write-debug "Fail to delete recovery point $($SourceVmRecoveryPoint.Name) after $($Count) attentds"
    }
    $count +=1 
    if ($count -gt 5) { 
        $LoopCondition = $true
    }
} until ($LoopCondition)
Enter fullscreen mode Exit fullscreen mode

We need to make sure the VM is deallocated.

$SourceVmPowerStatus = (get-azvm -Name $SourceVmObject.Name -ResourceGroupName $SourceVmObject.ResourceGroupName -Status).Statuses | where-object code -like "PowerState*"

if ($SourceVmPowerStatus -ne "VM deallocated") {
    stop-azVm -Name $SourceVmObject.Name -ResourceGroupName $SourceVmObject.ResourceGroupName -Force
    Start-Sleep -Seconds 30
}
Enter fullscreen mode Exit fullscreen mode

Let’s define the VM new name

$vmNewName = "dsc-lab-dns01" 
Enter fullscreen mode Exit fullscreen mode

One thing I love with the Azure PowerShell module is you can create a VM object and later, use this object to create a VM.

$NewVmObject = New-AzVMConfig -VMName $vmNewName -VMSize $SourceVmObject.HardwareProfile.VmSize 
Enter fullscreen mode Exit fullscreen mode

We can now create VM components.

We need to create a new network interface for the VM. We can attach it to the original network or to any other available network.

$subnetID = (Get-AzNetworkInterface -ResourceId $SourceVmObject.NetworkProfile.NetworkInterfaces[0].id).IpConfigurations.Subnet.id

$nic = New-AzNetworkInterface -Name "$($vmNewName.ToLower())-0-nic" -ResourceGroupName $SourceVmObject.ResourceGroupName  -Location $SourceVmObject.Location -SubnetId $SubnetId 

Add-AzVMNetworkInterface -VM $NewVmObject -Id $nic.Id
Enter fullscreen mode Exit fullscreen mode

Now we have to deal with disks. In the VM Object perspective there two types of disks, OS and data disk. Information about disks is located in the StorageProfile property.

To copy the VM, we need to create a snapshot for each disk and use snapshots to create new disks.

Let's start with the OS disk.

$SourceOsDiskSku = (get-azdisk -ResourceGroupName $SourceVmObject.ResourceGroupName -DiskName $SourceVmObject.StorageProfile.OsDisk.name).Sku.Name

$SourceOsDiskSnapConfig =  New-AzSnapshotConfig  -SourceUri $SourceVmObject.StorageProfile.OsDisk.ManagedDisk.Id -Location $SourceVmObject.Location -CreateOption copy

$SourceOsDiskSnap = New-AzSnapshot -Snapshot $SourceOsDiskSnapConfig  -SnapshotName "$($SourceVmObject.Name)-os-snap"  -ResourceGroupName $SourceVmObject.ResourceGroupName

$TargetOsDiskConfig = New-AzDiskConfig -AccountType $SourceOsDiskSku -Location $SourceVmObject.Location -CreateOption Copy -SourceResourceId $SourceOsDiskSnap.Id

$TargetOsDisk = New-AzDisk -Disk $TargetOsDiskConfig -ResourceGroupName $SourceVmObject.ResourceGroupName -DiskName "$($vmNewName.ToLower())-os-vhd"

Set-AzVMOSDisk -VM $NewVmObject -ManagedDiskId $TargetOsDisk.Id -CreateOption Attach -Windows

Enter fullscreen mode Exit fullscreen mode

We can now copy data disks. An Azure VM can have 0 to multiple data disk (it depends on de VM Size).

For that, we need to parse the DataDisks List. We need to take care of the Lun number so we will not run into problems after the restart

Foreach ($SourceDataDisk in $SourceVmObject.StorageProfile.DataDisks) { 

    $SourceDataDiskSku = (get-azdisk -ResourceGroupName $SourceVmObject.ResourceGroupName -DiskName $SourceDataDisk.name).Sku.Name

    $SourceDataDiskSnapConfig =  New-AzSnapshotConfig  -SourceUri $SourceDataDisk.ManagedDisk.Id -Location $SourceVmObject.Location -CreateOption copy

    $SourceDataDiskSnap = New-AzSnapshot -Snapshot $SourceDataDiskSnapConfig  -SnapshotName "$($SourceVmObject.Name)-$($SourceDataDisk.name)-snap"  -ResourceGroupName $SourceVmObject.ResourceGroupName

    $TargetDataDiskConfig = New-AzDiskConfig -AccountType $SourceDataDiskSku -Location $SourceVmObject.Location -CreateOption Copy -SourceResourceId $SourceDataDiskSnap.Id

    $TargetDataDisk = New-AzDisk -Disk $TargetDataDiskConfig -ResourceGroupName $SourceVmObject.ResourceGroupName -DiskName "$($vmNewName.ToLower())-$($SourceDataDisk.lun)-vhd"


    Add-AzVMDataDisk -VM $NewVmObject -Name "$($vmNewName.ToLower())-$($SourceDataDisk.lun)-vhd" -ManagedDiskId $TargetDataDisk.Id -Lun $SourceDataDisk.lun -CreateOption "Attach"

}
Enter fullscreen mode Exit fullscreen mode

Now that we have completed the VM configuration, we can create the VM.

 New-AzVM -VM $NewVmObject -ResourceGroupName $SourceVmObject.ResourceGroupName -Location $SourceVmObject.Location 
Enter fullscreen mode Exit fullscreen mode

This is one of the methods to rename a VM. You can use it also to reconnect a VM from one virtual network to another.

Top comments (1)

Collapse
 
mundayn profile image
mundayn

FYI I just tried this without deleting the backup vault for a VM and it seemed to work without error. Obviously we'll need to set up a new backup job for the new VM though, and delete the old one once I've verified everything is functioning as expected.