Reporting Unused Disks Space in Azure IaaS

If you’re using Azure VMs in your organization one of the common governance challenge is to identify the unused disk space that was just lying around in azure storage unused and cost company money unnecessarily. This usually happens when vms are deleted but vhds are kept so to make sure that data is not lost or just disks are marked for deletion but then no-one actually remembers/take care of that.

Whatever the reason is I’ve a simple solution for it: Create azure automation runbook that reports the unused disk space on periodic basis. You can do that by using automation schedule feature (I choose to run it weekly).I choose not to actually go ahead and delete these disks automatically since normally you would like to review details ( or let someone else do it) before deleting these disks but it is also simple to add logic to delete these used disks.

The script itself is rather trivial and for most part self-explanatory. You can download it from here

workflow Get-UnusedDisksDetails 
{ 
    param ( [string]$azureSubscriptionName , 
            [string]$azureOrgIdCredName  
          )  
 
 
$azureOrgIdCredential = Get-AutomationPSCredential -Name  $azureOrgIdCredName  
Write-Verbose ("[Information] Using account | " + $azureOrgIdCredential.UserName +" |") 
$discardOutput = Add-AzureAccount -Credential $azureOrgIdCredential  
$discardOutput = Select-AzureSubscription -SubscriptionName $azureSubscriptionName  
Write-Verbose "[Success] Azure subscription selected | $azureSubscriptionName |"   
 
  
 $disks = inlinescript {  
     $totalDisksSizeGB = 0 
     $totalDisksCount = 0; 
     $list = "DiskName,DiskSpace(GB),OS,AbsoulteUri" + "`n" 
      
     Get-AzureDisk | where { !$_.AttachedTo } | % { $totalDisksSizeGB = $totalDisksSizeGB + $_.DiskSizeInGB ; $totalDisksCount++;  
        $list +=  $_.DiskName + "," + $_.DiskSizeInGB + "," + $_.OS + "," + $_.MediaLink.AbsoluteUri + "`n";  
        } 
      
      
     if ($totalDisksSizeGB -igt 1000) { $list +="Total unused disks size: " + $totalDisksSizeGB / 1000 + "(TB)" + "`n"  } 
     else { $list +="Total unused disks size: " + $totalDisksSizeGB + "(GB)" + "`n" } 
     $list += "Total number of unused disks: $totalDisksCount" + "`n" 
      
      return $list 
 } 
  
$alldisks = $disks.Split("`n") 
    Write-Output $alldisks[$alldisks.Count-2] #Total number of unused disks 
    Write-Output $alldisks[$alldisks.Count-3] #Total unused disks size 
    $csvData = "" 
    for($count =0; $count -le $alldisks.Count -4 ; $count++)  
    { 
        $csvData += $alldisks[$count] + "`n" 
    }  
   Write-Output $csvData 
  
   return $disks; 
   
}

The actual work is done by Get-AzureDisk cmdlet that get all the disks that are not attached to any vms. Then it captures the relevant information about these disks including disk’s name, size etc and build a valid csv string. I mainly focus on three attributes “DiskName, DiskSpace(GB), OS, AbsoulteUri” as they make most sense but you can add more attributes as needed

That’s pretty much it! Rest is just formatting of string and pushing details on the output. You can also store the csv output (the $disks variable) as a file and send it via email attachment or upload it to azure storage for easy access.

You pass subscription name and azure organization account credential name as input parameters. You basically need to save the actual organization account in azure automation as PS Credential asset since script will read it using Get-AutomationPSCredential activity.