In Azure you can set a default action when deleting a virtual machine. This could be to delete the disks and NICs along with the VM, or to keep them.

Today we will look into how to find the current setting for all machines and update it as needed.

Find the setting from the portal

For any VM, you can find this setting by heading to the JSON View and look for the deleteOptions property under storageProfile > osDisk or dataDisks and under networkProfile > networkInterfaces > properties > deleteOptions.

alt text

Find the setting using PowerShell

Let’s find the current setting for all VMs in a subscription. We will use PowerShell for this.

Get-AzVM | Select-Object Name, @{label='OSDiskDeleteOption';expression={$_.StorageProfile.OsDisk.DeleteOption}}, @{label='NICDeleteOption';expression={$_.NetworkProfile.NetworkInterfaces[0].DeleteOption}} | Format-Table

This is great, but limited to one subscription. We can leverage Azure Resource Graph to query this across all subscriptions.

Find the setting using Azure Resource Graph Explorer

We can use the below KQL query,

resources
| where ['type'] == 'microsoft.compute/virtualmachines'
| extend DiskDeleteOption = properties.storageProfile.osDisk.deleteOption
| extend NICDeleteOption = properties.networkProfile.networkInterfaces[0].properties.deleteOption
| project ['id'], name, resourceGroup, subscriptionId, DiskDeleteOption, NICDeleteOption

Update the setting using PowerShell

Now how do we use the above query to update all VMs?

If we are targeting a single VM, we can use the below PowerShell command,

$vm = Get-AzVM -ResourceGroupName "MyResourceGroup" -Name "MyVM"
$vm.StorageProfile.OsDisk.DeleteOption = "Delete"
$vm.NetworkProfile.NetworkInterfaces[0].DeleteOption = "Delete"
$vm | Update-AzVM

We can expand on the above command to update all VMs using the below PowerShell script, let us say we want to switch from Delete to Detach,

$kqlQeury = @"
resources
| where ['type'] == 'microsoft.compute/virtualmachines'
| extend DiskDeleteOption = properties.storageProfile.osDisk.deleteOption
| extend NICDeleteOption = properties.networkProfile.networkInterfaces[0].properties.deleteOption
| where DiskDeleteOption == 'Delete' or NICDeleteOption  == 'Delete'
| project ['id'], name, resourceGroup, subscriptionId, DiskDeleteOption, NICDeleteOption
"@
$vmsWithDeleteOption = Search-AzGraph -Query $kqlQeury
$vmsWithDeleteOption | ForEach-Object {$_.name;$null = Set-AzContext -SubscriptionId $_.subscriptionId;$vm = Get-azvm -ResourceId $_.id; $vm.StorageProfile.OsDisk.DeleteOption = 'Detach'; $vm | Update-AzVM -NoWait}

This script will go through all VMs and update the delete options as needed. Bear in mind that this is just an example and could be optimized in different ways, such as checking if we are already in the right context, sorting by subscription, or even switching to REST API so we can use parallel processing without the need to switch contexts. If your organization has a policy to keep or delete disks and NICs, you can enforce this using an Azure Policy with a remediation task.

In conclusion, we are able to query and update the delete options to quickly change the behavior. We have different tools for the job so select the proper one according to how many VMs and how complex the environment is.