前面说到整机快照,这一节做一下快照的删除。分为两个脚本,删除单个快照和删除全部快照,思路稍有不同,所以分别来做。
删除单个快照相对比较复杂,我们在前面说过,制作整机快照的时候,我们会先做 OS Disk 的快照,做好后再做 Data Disk 的快照,这样我们就可以从 OS Disk 的时间作为基准点来把 Data Disk 的快照找到。
脚本中的 FindMatchSnapshot 方法就是用来根据 OS Disk 的快照时间找到匹配的 Data Disk 的快照的,这个方法里设定了一个时间:120s,即认为在 OS Disk 快照做完之后且相差时间小于120s的第一个 Data Disk 的快照与这个 OS Disk 的快照是一组,之所以加这个判定的原因是,很可能我们通过其他工具在其他时间单独做了系统盘或者某些数据盘的快照,这样就会与我们脚本中制作的快照的时间线产生互相影响,但是这个影响并不要紧,哪怕不使用前面整机快照的脚本,我们就使用其他工具在接近的时间为虚拟机做了快照,那么也能够使用这个删除脚本来管理这一组快照。
先来看删除单组快照的脚本:
param(
[Parameter(Mandatory = $true)]
[string]$SubscriptionName,
[Parameter(Mandatory = $true)]
[string]$ResourceGroupName,
[Parameter(Mandatory = $true)]
[string]$VMName
)
Function PrepareBlobContext($vhdAbsoluteUri)
{
$StorageAccountName = $vhdAbsoluteUri.Substring(8, $vhdAbsoluteUri.IndexOf(".blob.core.chinacloudapi.cn") - 8); #length of "https://" is 8
$ContainerPathIndex = $vhdAbsoluteUri.IndexOf("blob.core.chinacloudapi.cn/") + 27;
$ContainerName = $vhdAbsoluteUri.SubString($ContainerPathIndex, $vhdAbsoluteUri.IndexOf('/', $ContainerPathIndex) - $ContainerPathIndex);
$BlobName = $vhdAbsoluteUri.SubString($vhdAbsoluteUri.LastIndexOf('/') + 1);
$storageAccount = Get-AzureRmStorageAccount -ResourceGroupName $ResourceGroupName -Name $StorageAccountName;
$storageContext = $storageAccount.Context;
$blobClient = $storageContext.Context.StorageAccount.CreateCloudBlobClient();
$blobContainer = $blobClient.GetContainerReference($ContainerName);
$blob = $blobContainer.GetBlockBlobReference($BlobName);
return $blob;
}
Function DeleteSnapshot($rgName, $vmName)
{
$vm = Get-AzureRmVM -ResourceGroupName $rgName -Name $vmName -WarningAction Ignore;
$osDiskUri = $vm.StorageProfile.OsDisk.Vhd.Uri;
$blob = PrepareBlobContext $osDiskUri;
$osDiskSnapshotList += @(GetSnapshotListByBlob $blob);
$osDiskSnapshotPropertiesList += @(GetSnapshotPropertiesList $osDiskSnapshotList $blob);
$dataDiskSnapshotLists = @();
$dataDiskSnapshotPropertiesLists = @();
foreach($dataDiskUri in $vm.StorageProfile.DataDisks.Vhd.Uri)
{
$blob = PrepareBlobContext $dataDiskUri;
$dataDiskSnapshotList = @(GetSnapshotListByBlob $blob);
$dataDiskSnapshotPropertiesList = @(GetSnapshotPropertiesList $dataDiskSnapshotList $blob);
$dataDiskSnapshotLists += $null;
$dataDiskSnapshotLists[$dataDiskSnapshotLists.Count - 1] = $dataDiskSnapshotList;
$dataDiskSnapshotPropertiesLists += $null;
$dataDiskSnapshotPropertiesLists[$dataDiskSnapshotPropertiesLists.Count - 1] = $dataDiskSnapshotPropertiesList;
}
$resultList = @();
$count = $osDiskSnapshotPropertiesList.Count;
for ($i = 0; $i -lt $count; $i++)
{
$findMatch = $true;
$result = @();
$osDiskSnapshotTime = $osDiskSnapshotPropertiesList[$i].SnapshotTime;
$result += $i;
foreach ($dataDiskSnapshotPropertiesList in $dataDiskSnapshotPropertiesLists)
{
$matchIndex = FindMatchSnapshot $osDiskSnapshotTime $dataDiskSnapshotPropertiesList;
if ($matchIndex -eq -1)
{
$findMatch = $false;
break;
} else {
$result += $matchIndex;
}
}
if ($findMatch)
{
$resultList += $null;
$resultList[$resultList.Count - 1] = $result;
}
}
$resultCount = $resultList.Count;
if ($resultCount -eq 0)
{
Write-Host "Virtual Machine has no snapshots." -ForegroundColor Yellow;
return;
}
Write-Host "Virtual Machine has the following snapshots:" -ForegroundColor Yellow;
Write-Host ("{0, -10}{1}" -f "Index", "Snapshot Time") -ForegroundColor Green;
for ($i = 0; $i -lt $resultCount; $i++)
{
Write-Host ("{0, -10}{1}" -f ($i+1), $osDiskSnapshotPropertiesList[$resultList[$i][0]].SnapshotTime) -ForegroundColor Green;
}
$selection = $resultList[(Read-Host "Please select the snapshot you want to delete") - 1];
Write-Host "The following snapshots will be deleted:" -ForegroundColor Yellow;
Write-Host ("{0}({1})" -f $osDiskSnapshotPropertiesList[$selection[0]].SnapshotUri, $osDiskSnapshotPropertiesList[$selection[0]].SnapshotTime) -ForegroundColor Red;
$dataDiskCount = $dataDiskSnapshotLists.Count;
for ($i = 0; $i -lt $dataDiskCount; $i++)
{
Write-Host ("{0}({1})" -f $dataDiskSnapshotPropertiesLists[$i][$selection[$i+1]].SnapshotUri, $dataDiskSnapshotPropertiesLists[$i][$selection[$i+1]].SnapshotTime) -ForegroundColor Red;
}
If ($PSCmdlet.ShouldContinue("Confirm?", "=== Confirm delete Opeartion ==="))
{
$osDiskSnapshotList[$selection[0]].Delete();
for ($i = 0; $i -lt $dataDiskCount; $i++)
{
$dataDiskSnapshotLists[$i][$selection[$i+1]].Delete();
}
Write-Host "Done";
} else {
Write-Host "Canceled";
}
}
Function FindMatchSnapshot($osDiskSnapshotTime, $snapshotPropertiesList)
{
$count = $snapshotPropertiesList.Count;
for ($i = 0; $i -lt $count; $i++)
{
if ($osDiskSnapshotTime -gt $snapshotPropertiesList[$i].SnapshotTime)
{
continue;
}
# wo consider snapshots for different data disks within 2 minutes (120 sec) should be related
if (($snapshotPropertiesList[$i].SnapshotTime - $osDiskSnapshotTime).TotalSeconds -lt 120)
{
return $i;
} else {
return -1;
}
}
return -1;
}
Function GetSnapshotListByBlob($blob)
{
return $blob.Container.ListBlobs($blob.Name, $true, "Snapshots") | Where {$_.SnapshotTime -ne $null};
}
Function GetSnapshotPropertiesList($Snapshots, $blob)
{
$Index = 0
$SnapshotPropertiesList = @()
Foreach($Snapshot in $Snapshots)
{
$Index++
$SnapshotPropertiesList += [PSCustomObject]@{ID = $Index
BlobName = $blob.Name
SnapshotTime = $Snapshot.SnapshotTime
SnapshotUri = $Snapshot.Uri}
}
return $SnapshotPropertiesList;
}
#$Cred = New-Object System.Management.Automation.PSCredential("XXXXXXXX@XXXXXXXX.partner.onmschina.cn", (ConvertTo-SecureString "XXXXXXXX" -AsPlainText -Force));
#[void](Login-AzureRmAccount -EnvironmentName AzureChinaCloud -Credential $Cred);
[void](Select-AzureRmSubscription -SubscriptionName $SubscriptionName);
DeleteSnapshot $ResourceGroupName $VMName;
调用方法:
PS> &.\[ARM]delete_snapshot_for_VM.ps1 -SubscriptionName <Subscription Name> -ResourceGroupName <Resource Group Name> -VMName <VM Name>
脚本执行结果:
限于篇幅,删除全部快照的脚本放到下一小节介绍。