Recently I had to change the name of a few Azure virtual machines (VMs) and was quite surprised that there is no way to rename a VM in the Azure Portal or with a PowerShell cmdlet. Thus, I had to write a PowerShell script for the task.
Avatar

Please note: I'm providing the script below as is. Use it at your own risk. It removes and then recreates the VM.

[CmdletBinding()]
Param(
  [Parameter(Mandatory=$True)]
   [string]$SvcName,
  [Parameter(Mandatory=$True)]
   [string]$SourceVMName,
  [Parameter(Mandatory=$True)]
   [string]$NewVMName,
  [Parameter(Mandatory=$True)]
   [string]$Subscription
           
)

$file = "c:\temp\Renaming_Azure__VM_$SourceVMName{0:MMddyyyy_HHmm}.log" -f (Get-Date)
new-item -path $file -type file -force

$dt = Get-Date -UFormat %c
Write-Host "Renaming VM $SourceVMName in ServiceName $Svcname" -ForegroundColor Yellow
Write-Output "Cloning VM $SourceVMName in ServiceName $Svcname timestamt: $dt" >> $file

$vm = Get-AzureVM -ServiceName $SvcName -Name $SourceVMName

$OSDisk = $vm | Get-AzureOSDisk

$StorageAccountName = $OSDisk.MediaLink.Host.Split('.')[0]

Set-AzureSubscription –SubscriptionName $Subscription –CurrentStorageAccountName $StorageAccountName

$dt = Get-Date -UFormat %c
Write-Host "Stopping and Deallocating the VM $vmName" -ForegroundColor Yellow
Write-Output "Stopping and Deallocating VM $vmName, timestamp: $dt" >> $file

$vm | Stop-Azurevm -Force -Verbose

do{
      sleep 5
     $status = (get-azurevm -ServiceName $SvcName -Name $vmName).InstanceStatus
     }
   until($status -eq "StoppedDeallocated")

sleep 30

$vmxml = "C:\temp\$SourceVMName.xml"
$vm | Export-AzureVM -Path $vmxml


if(Test-Path $vmxml){
   $xml = [xml](Get-Content $vmxml)
   $xml.ChildNodes[1].RoleName = $NewVMName
   $xml.Save($vmxml)
  }

$vm | Remove-AzureVM -Verbose
sleep 30
Import-AzureVM -Path $vmxml | New-AzureVm -ServiceName $SvcName

To understand better how the script works, consider the components an Azure VM comprises. Essentially, an Azure VM is just a set of virtual hard disk (VHD) files plus a configuration file in XML. Thus, all I need to do is export the configuration, create a new VM, and then import the configuration.

Note that even though the VM name changes, everything underneath it stays the same. Hence, if you named your Azure drives after the VM, the script won't change those names.

Let's go through the script:

[CmdletBinding()]
Param(
  [Parameter(Mandatory=$True)]
   [string]$SvcName,
  [Parameter(Mandatory=$True)]
   [string]$SourceVMName,
  [Parameter(Mandatory=$True)]
   [string]$NewVMName,
  [Parameter(Mandatory=$True)]
   [string]$Subscription
)

As inputs for my script, I just need the cloud service name, the source VM name, the new VM name, and the subscription name. I think the variable names speak for themselves.

$file = "c:\temp\Renaming_Azure__VM_$SourceVMName{0:MMddyyyy_HHmm}.log" -f (Get-Date)
new-item -path $file -type file -force
$dt = Get-Date -UFormat %c
Write-Host "Renaming VM $SourceVMName in ServiceName $Svcname" -ForegroundColor Yellow
Write-Output "Cloning VM $SourceVMName in ServiceName $Svcname timestamt: $dt" >> $file

This part creates a log file ($file variable) to keep track of what the script is doing. I'm getting the date and time into the $dt variable and updating the console and log file using Write-Host and Write-Output.

$vm = Get-AzureVM -ServiceName $SvcName -Name $SourceVMName
$OSDisk = $vm | Get-AzureOSDisk
$StorageAccountName = $OSDisk.MediaLink.Host.Split('.')[0]
Set-AzureSubscription –SubscriptionName $Subscription –CurrentStorageAccountName $StorageAccountName

Here I'm getting the VM object and storing it in the $vm variable. After that, I'm getting the Azure disk information and storing it in the $OSDisk variable. I only need this to get the storage account name, which I'm doing in the next step. I'll have to configure this storage account as current for the subscription I'm using. This is required to create a new VM from a configuration file.

$dt = Get-Date -UFormat %c
Write-Host "Stopping and Deallocating the VM $vmName" -ForegroundColor Yellow
Write-Output "Stopping and Deallocating VM $vmName, timestamp: $dt" >> $file
$vm | Stop-Azurevm -Force -Verbose
do{
      sleep 5
     $status = (get-azurevm -ServiceName $SvcName -Name $vmName).InstanceStatus
     }
   until($status -eq "StoppedDeallocated")
sleep 30

Now I'm updating the log file and console again and then stopping the VM I'm going to rename. After that I'm just running a do-while loop to make sure the VM stops.

$vmxml = "C:\temp\$SourceVMName.xml"
$vm | Export-AzureVM -Path $vmxml

Next, I'm exporting the VM configuration into the XML file named in the same way as the source VM.

if(Test-Path $vmxml){
   $xml = [xml](Get-Content $vmxml)
   $xml.ChildNodes[1].RoleName = $NewVMName
   $xml.Save($vmxml)
  }
$vm | Remove-AzureVM -Verbose
sleep 30
Import-AzureVM -Path $vmxml | New-AzureVm -ServiceName $SvcName

Finally, after completing all preparation steps, the renaming part begins. First, I'm checking if the XML file already exists using Test-Path and if it does, I'm getting its content into the $xml variable. Then I replace the RoleName node in the XML to the value of $NewVMName and save the XML file.

This is how it looks like inside of the XML file:

VM configuration file

VM configuration file

And now comes the scary part: Before importing the VM into Azure with the new name, I need to remove the old one with Remove-AzureVM. If you omit the -DeleteVHD option, the script won't remove the VHD drives.

I then wait for 30 seconds just to be on the safe side and then import the XML file with the new VM name using Import-AzureVM. I pipe this to the New-AzureVM cmdlet, which will have the new name.

This is what you see on the console until the VM stops:

Stopping an Azure VM

Stopping an Azure VM

The next screenshot shows the rest of the procedure up until renaming the VM.

Subscribe to 4sysops newsletter!

Renaming an Azure VM

Renaming an Azure VM

2 Comments
  1. Avatar
    Jijo 7 years ago

    Is this supports Azure Arm VM and resource group instead of Cloud Service ?

    • Avatar Author

      No it doesn’t. Azure ARM handles VMs a bit differently, this script works only for classic Azure VMs.

Leave a reply

Please enclose code in pre tags: <pre></pre>

Your email address will not be published. Required fields are marked *

*

© 4sysops 2006 - 2023

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account