loading...

Using PowerShell to rename, move or reconnect an Azure VM

omiossec profile image Olivier Miossec ・3 min read

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 

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)

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
}

Let’s define the VM new name

$vmNewName = "dsc-lab-dns01" 

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 

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

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

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"

}

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

 New-AzVM -VM $NewVmObject -ResourceGroupName $SourceVmObject.ResourceGroupName -Location $SourceVmObject.Location 

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.

Posted on by:

omiossec profile

Olivier Miossec

@omiossec

Microsoft Azure MVP, Passionate about Cloud and DevOps. Co-organizers of the French PowerShell UG and Paris PowerShell & WinOps UG. I live in Paris.

Discussion

markdown guide