NonAttachedUnmanagedDisk.psm1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath 'Internal.Common.psm1' -Resolve)

<#
.SYNOPSIS
Get the unmanaged disks (VHDs/Blobs) that non-attached to any virtual machines from the entire subscription.

.DESCRIPTION
Get the unmanaged disks (VHDs/Blobs) that non-attached to any virtual machines from the entire subscription.

.PARAMETER ExcludeResourceGroup
This cmdlet is ignore the resource groups that provided by this parameter. This parameter is optional.

.EXAMPLE
    Get-AzureUtilNonAttachedUnmanagedDisk -Verbose

---- Example Description ----
In this example, it is to get the all non-attached unmanaged disks (VHDs/Blobs) in the current subscription.

.EXAMPLE
    Get-AzureUtilNonAttachedUnmanagedDisk -ExcludeResourceGroup 'TemplateStore-RG','securitydata' -Verbose

---- Example Description ----
In this example, it is to get the all non-attached unmanaged disks (VHDs/Blobs) in the current subscription except the storage accounts in the "TemplateStore-RG" and "securitydata" resource groups.

.EXAMPLE
    PS C:\>$disks = Get-AzureUtilNonAttachedUnmanagedDisk -ExcludeResourceGroup 'securitydata'
    PS C:\>$disks | Format-Table -Property @{ Label = 'Resource Group'; Expression = { $_.ResourceGroupName } },
                                           @{ Label = 'Storage Account'; Expression = { $_.StorageAccountName } },
                                           @{ Label = 'Location'; Expression = { $_.Location } },
                                           @{ Label = 'SKU'; Alignment = 'Left'; Expression = { $_.Sku.Name } },
                                           @{ Label = 'Container'; Expression = { $_.ContainerName } },
                                           @{ Label = 'VHD/Blob'; Expression = { $_.Name } },
                                           @{ Label = 'Size (GB)'; Expression = { [int] ($_.Length / 1GB) } },
                                           'LastModified'

    Resource Group Storage Account Location SKU Container VHD/Blob Size (GB) LastModified
    -------------- --------------- -------- --- --------- -------- --------- ------------
    ProjectA-RG vm1sa1055 japaneast StandardLRS vhd datadisk1.vhd 127 5/6/2017 11:05:14 AM +00:00
    ProjectB-RG vm2sa1310 japaneast StandardLRS vhd osdisk.vhd 127 5/5/2017 2:22:10 PM +00:00
    Test-RG premsa japaneast PremiumLRS vhd osdisk.vhd 127 5/5/2017 3:52:45 PM +00:00

---- Example Description ----
In this example, it is to get the all non-attached unmanaged disks (VHDs/Blobs) in the current subscription except the storage accounts in the "securitydata" resource group. The results is formatted as table style in this example.

.EXAMPLE
    Get-AzureUtilNonAttachedUnmanagedDisk -ExcludeResourceGroup 'securitydata' -Verbose | Remove-AzureStorageBlob -Verbose

---- Example Description ----
In this example, it is to remove the all non-attached unmanaged disks (VHDs/Blobs) in the current subscription except the storage accounts in the "securitydata" resource group.

.LINK
PowerShell Gallery: https://www.powershellgallery.com/packages/AzureUtil/

.LINK
GitHub: https://github.com/tksh164/AzureUtil-PowerShellModule

.LINK
Get-AzureUtilNonAttachedManagedDisk

.LINK
Get-AzureUtilEmptyResourceGroup
#>

function Get-AzureUtilNonAttachedUnmanagedDisk
{
    [CmdletBinding()]
    [OutputType([pscustomobject])]
    param (
        [Parameter(Mandatory = $false)][ValidateNotNullOrEmpty()]
        [string[]] $ExcludeResourceGroup
    )

    # Login check.
    PreventUnloggedExecution

    # Get the all attached VHD URIs from the VM configurations.
    Write-Verbose -Message ('Get all attached VHD URI...')
    $attachedVhdUris = GetAttachedVhdUri -ExcludeResourceGroup $ExcludeResourceGroup
    Write-Verbose -Message ('Found the {0} attached VHD in the current subscription.' -f $attachedVhdUris.Count)

    #
    # Enumerate the VHD blobs by scanning of all storage accounts.
    #

    Write-Verbose -Message ('Scanning all storage accounts.')

    Get-AzureRmStorageAccount |
        ForEach-Object -Process {

            # Exclude the non target resource groups.
            if ($ExcludeResourceGroup -notcontains $_.ResourceGroupName)
            {
                $storageAccount = $_
                $resourceGroupName = $storageAccount.ResourceGroupName
                $storageAccountName = $storageAccount.StorageAccountName
                Write-Verbose -Message ('Scanning SA:{0} in RG:{1}' -f $storageAccountName,$resourceGroupName)

                $storageAccountKey = (Get-AzureRmStorageAccountKey -ResourceGroupName $resourceGroupName -Name $storageAccountName).Value | Select-Object -First 1
                $context = New-AzureStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $storageAccountKey
                $nonAttachedVhdCount = 0

                # Get all containers in the storage account.
                Get-AzureStorageContainer -Context $context |
                    ForEach-Object -Process {
        
                        $containerName = $_.Name

                        # Get all blobs in the container.
                        Get-AzureStorageBlob -Context $context -Container $containerName |
                            ForEach-Object -Process {

                                $blobUri = $_.ICloudBlob.Uri.AbsoluteUri

                                # Verify that it is a non-attached VHD.
                                if ($blobUri.EndsWith('.vhd') -and ($attachedVhdUris -notcontains $blobUri))
                                {
                                    [pscustomobject] @{
                                        ResourceGroupName  = $resourceGroupName
                                        StorageAccountName = $storageAccountName
                                        Location           = $storageAccount.Location
                                        Sku                = $storageAccount.Sku
                                        ContainerName      = $containerName
                                        Name               = $_.Name
                                        ICloudBlob         = $_.ICloudBlob
                                        BlobType           = $_.BlobType
                                        Length             = $_.Length
                                        ContentType        = $_.ContentType
                                        LastModified       = $_.LastModified
                                        SnapshotTime       = $_.SnapshotTime
                                        ContinuationToken  = $_.ContinuationToken
                                        Context            = $_.Context
                                        StorageAccount     = $storageAccount
                                    }

                                    $nonAttachedVhdCount++
                                }
                            }
                    }

                Write-Verbose -Message ('Found {0} the non-attached VHD in SA:{1} in RG:{2}' -f $nonAttachedVhdCount,$storageAccountName,$resourceGroupName)
            }
        }
}

function GetAttachedVhdUri
{
    [CmdletBinding()]
    [OutputType([string])]
    param (
        [Parameter(Mandatory = $false)]
        [string[]] $ExcludeResourceGroup
    )

    Get-AzureRmVM |
        ForEach-Object -Process {

            # Exclude the non target resource groups.
            if ($ExcludeResourceGroup -notcontains $_.ResourceGroupName)
            {
                $storageProfile = $_.StorageProfile

                # Attached VHD URI as OS disk.
                if ($storageProfile.OsDisk.Vhd -ne $null) { $storageProfile.OsDisk.Vhd.Uri }

                # All attached VHD URIs as data disks.
                if ($storageProfile.DataDisks.Vhd -ne $null) { $storageProfile.DataDisks.Vhd.Uri }
            }
        }
}