How to find Disks that are not attached/used more than xx days?

Yahav Horev | CloudTeam.ai 136 Reputation points
2021-06-06T15:44:15.187+00:00

Hey guys i need your help please.

i need to find a way how to locate all my disks in my azure account that are not in used or not attached more than xx days ,
please help me to find the best way to do that ..

Azure Disk Storage
Azure Disk Storage
A high-performance, durable block storage designed to be used with Azure Virtual Machines and Azure VMware Solution.
575 questions
0 comments No comments
{count} votes

Accepted answer
  1. svijay-MSFT 5,206 Reputation points Microsoft Employee
    2021-06-09T18:54:09.15+00:00

    @Yahav Horev | CloudTeam.ai - I understand your requirement locating all the disks which have been unattached for a certain number of days.

    Unfortunately - Get-AzDisk / Rest API for getting the list doesn't return the last modified date - So, there is currently no direct way to find whether the disk was in use.

    There has been a feedback documented @ the below URL :
    https://feedback.azure.com/forums/34192--general-feedback/suggestions/40411429-managed-disk-last-modify-date

    Alternatively, you are looking for options to delete disks that have been unattached you can refer through the article :

    However, the above will not help in identifying the days for which it has been unattached.

    I did a quick testing at my end and found an alternative that may meet your requirement.

    Logic:

    When the disk is unattached there is an activity log created with Action Create / Update disk. You can view this in the Activity log of the disk.

    Note : I tested at my end - for all the unattached disks there was final **Create or Update ** Event like below around the same time when the disk was unattached. I'd recommend confirming the similar behavior at your end.

    103981-image.png

    So, once we identify the disks that are unattached (managed by eq null). We can query activity log of the unattached disks for the for say X days. if there is no logs created in the X days - we can safely assume the disk was unattached prior to those X days. If you find events/logs during the period X days - then the disk was unattached recently.

    Implementation :

    You can manually do this in the portal. Identify the disks by following this article (https://learn.microsoft.com/en-us/azure/virtual-machines/disks-find-unattached-portal#unmanaged-disks-find-and-delete-unattached-disks)

    103945-image.png

    Filter for the Timespan for an unattached disk
    103880-image.png

    Alternatively, I wrote a small snippet that makes use of the REST API to get the log activity which does the above activity programmatically.

    Note: I did try Get-Azlog commandlet did not return the results - possibility that it is making use of the Stable version of the API. This action is achievable only in the preview version of the API - Per my research.

    #Got the token by running Connect-AzAccount and running the below code. But you can use a better approach  
    $token = (Get-AzAccessToken).Token  
      
    $subscriptionid = "<YourSUBSID>"  
      
    #Getting all the disks in your Subscription  
    $disks = Invoke-RestMethod -Method Get -Uri "https://management.azure.com/subscriptions/$subscriptionid/providers/Microsoft.Compute/disks?api-version=2020-12-01" -Headers @{"Authorization"="Bearer $token"}  
      
    #Getting the unattached disks from the above list   
    $unattacheddisks = $disks.value |  ? {$_.managedBy -eq $null }  
      
    foreach ($disk in $unattacheddisks)  
    {  
    $resourceid = $disk.id  
      
    #eventTimestamp is between 2021-05-09 to 2021-06-09  - You can generate a time stamp dynamically for smaller or a larger time span.   
    $filter = "eventTimestamp ge '2021-05-09T17:59:08Z' and eventTimestamp le '2021-06-09T17:59:08Z' and eventChannels eq 'Admin, Operation' and resourceId eq '$resourceid' and levels eq 'Critical,Error,Warning,Informational'"  
      
    #Getting the Activity logs.This is the  preview API  
    $log= Invoke-RestMethod -Uri "https://management.azure.com/subscriptions/  $subscriptionid/providers/microsoft.insights/eventtypes/management/values?api-version=2017-03-01-preview&`$filter=$filter"  -Headers @{"Authorization"="Bearer $token"}  
      
    #if there is no log returned - no activity  
    if($log.value.Count -eq 0 )  
    {  
    Write-Host $disk.name + " : - There is no activitiy in 30 days" -ForegroundColor Yello  
    }  
    else  
    {  
    Write-Host $disk.name + " : - There is  activitiy in 30 days" -ForegroundColor Green  
    }  
    }  
    

    Output :
    103868-image.png

    ------------------------------------

    Please do not forget to "Accept the answer" wherever the information provided helps you. This will help others in the community as well.

    2 people found this answer helpful.
    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. Yahav Horev | CloudTeam.ai 136 Reputation points
    2021-06-13T11:55:12.273+00:00

    Hey !
    First of all i am so gradeful for your Detalied answers!!
    i have been out for a few days and my task was changed to :

    1. get the vms in deallocated state for more than x days ,
    2. if those VMs have a disk that is greater than 50GB size , tag the VMs and the disks
    3. delete the tagged resources.

    but anyway you answer to find those disks will help me now.
    i will give it a try and will let you know if it worked.
    ** sharing with you my code for this one :)

    $ids = New-Object System.Collections.ArrayList
    $mergedTags = @{"Candidate"="Delete Me"}
    $vms =  (Get-AzVM -Status)
        foreach ($vm in $vms ) {
           $getStatuses = Get-AzVM -ResourceGroupName $vm.ResourceGroupName -Name $vm.Name -Status  
           $getTodaysDate = Get-Date
           $ts = New-TimeSpan  -Start (($getStatuses.Statuses).Time).DateTime -End $getTodaysDate  
               [bool]$flag = 0
               if (($vm.PowerState -eq "VM deallocated") -AND ($ts.Days -gt 30)) {
               $ids.Add($vm.Id)
                    foreach ($disk in $getStatuses.Disks.Name) {
                        $diskSize = Get-AzDisk -ResourceGroupName $vm.ResourceGroupName -Name $disk
                        if ($diskSize.DiskSizeGB -gt 50) {
                            $flag = 1
                            $ids.Add($diskSize.Id)
                            if ($flag = 1) {
                                Update-AzTag -ResourceId $vm.Id -Tag $mergedTags -Operation Merge
                                Update-AzTag -ResourceId $diskSize.Id -Tag $mergedTags -Operation Merge
                            }
                        }
                    }
                }
            }
        } 
    
    0 comments No comments