[Azure]使用Azure Powershell清理ASM模式下未使用的Disk和vhd

时间:2022-08-02 21:48:30

如题,通过脚本清理账号下所有订阅的ASM模式下没有使用的磁盘(Disk)和vhd文件。


脚本如下:

$Cred = New-Object System.Management.Automation.PSCredential("XXXXXXXXX@XXXXXXXXX.partner.onmschina.cn",(ConvertTo-SecureString "XXXXXXXXX" -AsPlainText -Force));
$AzureRMCred = Get-Credential -Credential $Cred;
Add-AzureAccount -Environment AzureChinaCloud -Credential $AzureRMCred;

$usedVhds = New-Object System.Collections.ArrayList;

Function RemoveUnusedDisks()
{
    $disks = Get-AzureDisk;
    foreach ($disk in $disks)
    {
        if ($disk.AttachedTo -eq $NULL)
        {
            Write-Host "Deleting unused disk " $disk.DiskName;
            Remove-AzureDisk -DiskName $disk.DiskName -DeleteVHD;
        }
    }
}

Function FillVmMapping()
{
    $usedVhds.Clear();
    $vms = Get-AzureVM;

    foreach($vm in $vms)
    {   
        $osDiskUrl = $vm.VM.OSVirtualHardDisk.MediaLink.AbsoluteUri;
        [void]$usedVhds.Add($osDiskUrl);
        
        $dataDisks = $vm.VM.DataVirtualHardDisks;
        foreach($dataDisk in $dataDisks)
        {
            $dataDiskUrl = $dataDisk.MediaLink.AbsoluteUri;
            [void]$usedVhds.Add($dataDiskUrl);
        }
    }
}

Function RemoveUnusedVhds($subscriptionName)
{
    $storages = Get-AzureStorageAccount -WarningAction Ignore;
    $deletedVhds = New-Object System.Collections.ArrayList;  # to skip snapshots

    foreach($storage in $storages)
    {
        $storageAccountName = $storage.StorageAccountName;
        $blobs = Get-AzureStorageBlob -Context $storage.Context -Container vhds -ErrorAction Ignore;

        foreach ($blob in $blobs)
        {
            if ($blob.BlobType -eq "PageBlob")
            {
                $url = $blob.ICloudBlob.Uri.AbsoluteUri;
                if ($url.EndsWith(".vhd") -and !$usedVhds.Contains($url) -and !$deletedVhds.Contains($url))
                {
                    Write-Host "Deleting unused vhd " $url;
                    if ($blob.ICloudBlob.Properties.LeaseStatus -eq "Locked")
                    {
                        $blob.ICloudBlob.BreakLease();
                    }
                    Remove-AzureStorageBlob -Blob $blob.Name -Container vhds -Context $storage.Context -Force;
                    [void]$deletedVhds.Add($url);
                }
            }
        }
    }
}

Function RemoveAllUnusedDisksAndVhds()
{
    $subscriptions = Get-AzureSubscription;
    foreach($subscription in $subscriptions)
    {
        $subscriptionName = $subscription.SubscriptionName;
        Select-AzureSubscription -SubscriptionName $subscriptionName;
        RemoveUnusedDisks;
        FillVmMapping;
        RemoveUnusedVhds $subscriptionName;
    }
}

RemoveAllUnusedDisksAndVhds;


脚本中有几个小技巧:

1.通过在数组添加元素的语句前面添加 "[void]" 可以避免在 Powershell 控制台中输出数组长度,例如:[void]$arr.Add(<element>);,原因是 Add 方法会有一个返回值,返回添加元素后数组的长度,如果未处理这个返回值,这个返回值会被直接输出到 Powershell 控制台中。如果在循环中调用 Add 方法,就会在控制台里打出下面这种刷屏信息:

  1

  2

  3

  4

  5

  6

通过添加 "[void]" 会将返回值转换为空类型,不会再输出。


2.通过在部分 Azure Powershell 语句后面添加 -ErrorAction 和 -WarningAction 参数,可以指定当这条语句执行遇到 Error 或者 Warning 执行何种策略。例如: $blobs = Get-AzureStorageBlob -Context $storage.Context -Container vhds -ErrorAction Ignore ,这条语句执行时,对于有些存储账号,可能下面并没有创建过虚拟机,没有生成 vhds 容器,如果不加 -ErrorAction Ignore ,遇到这种情况就会报错,提示没有名为 vhds 的容器。加上 -ErrorAction Ignore 后,即使是这种情况,也会忽略报错信息。通过这种参数可以避免控制台中输出一大堆我们不希望看到的或者已经知道的可能报错或警告信息。