其實這篇,是昨天在將做VM轉Image的練習,當作完刪除Disk後,準備要刪除Blob裡面的VHD,卻出現錯誤,後來查了一下MSDN,後來有找到一篇類似的解決方式 (雖然案例和我的狀況完全不同),但感覺滿好玩的,就順便邊做邊翻譯。
根據原文,主要是在寫當,我們要使用VHD來創建不同的VM時,會收到這個錯誤
A lease conflict occurred with the blob <blob url>
當然,一般人應該不會無聊到把一個VHD拿去建立很多個VM,所以根據官方的說法,這個問題是出現在,當合約超過額度,時間等等,而造成系統自動把服務停止;當我們恢復合約( 繼續繳錢 )後,要使用之前的VHD來重建VM,卻建立不起來的情況。
所以官方,就使用了傳說中的命令列模式!! ( 老實說,真不喜歡用… ),也就是使用Windows Azure PowerShell…來處理,根據原文文件指出,可以使用 Lease Blob API來把契約關連給斷開,至於要怎麼用呢?,就是使用Windows Azure PowerShell來載入Microsoft.WindowsAzure.StorageClient.dll,並使用LeaseAction Enumeration.
神奇吧!?沒錯,我也是覺得很神奇,要不是找到官方這篇文章XDD,誰知道可以這樣搞呢~~
開始!!
我們先要下載Windows Azure管理工具,因為小弟是Windows環境,就使用Windows的管理工具。
接下來,安裝程式會呼叫Web Platform Installer 4.0,當然,也沒甚麼好猶豫的…反正也只能安裝了= =…
安裝完後,就可以找到Windows Azure PowerShell。( 找不到的人,可以利用搜尋功能,搜尋Windows Azure PowerShell,通常裝完後,就可以從開始那邊找到。 ),另外,記得用administrator權限開啟!!
接下來,在管理工具裡面輸入Get-AzurePublishSettingsFile,他就會自動地開啟瀏覽器,並且提供publishsetting檔案給我們下載,我們當然就是下載啦!!( 建議存到預設的下載目錄,這樣等下就不需要再打路徑了。 )
那剛剛下載的Publishsetting是做甚麼的呢,當然就是給Windows Azure PowerShell用的,如果沒有這個檔案,Windows Azure PowerShell自然就沒有權限…,所以下一步,我們要把這個檔案給Windows Azure PowerShell來使用;我們要在Windows Azure PowerShell裡面下這個指令Import-AzurePublishSettingsfile $env:userprofile\downloads\*.publishsettings 很簡單吧!!所以剛剛才建議大家直接丟到下載目錄,這樣這時候就可以直接複製上面那個指令到Windows Azure PowserShell裡面了,如果不是放到下載目錄,而是放在其他目錄,則後面的路徑,就要記得自己改喔!!
接下來,我們要把下面這烙烙長的程式碼貼到記事本上面去!! ( 就不要問小弟我內容了= =|| ),並且取名為BreakLease.ps1 ( 副檔名是ps1阿!不是txt喔,所以要用另存新檔的方式喔!! )
Param([string]$Uri = $(Read-Host -prompt "Please specify a blob URL")) $ProgressPreference = 'SilentlyContinue' echo "Processing $Uri" echo "Reading storage account information..." $acct = Get-AzureStorageAccount | ? { (new-object System.Uri($_.Endpoints[0])).Host -eq (new-object System.Uri($Uri)).Host } if(-not $acct) { write-host "The supplied URL does not appear to correspond to a storage account associated with the current subscription." -foregroundcolor "red" break } $acctKey = Get-AzureStorageKey ($acct.StorageAccountName) $creds = "DefaultEndpointsProtocol=http;AccountName=$($acctKey.StorageAccountName);AccountKey=$($acctKey.Primary)" $acctobj = [Microsoft.WindowsAzure.CloudStorageAccount]::Parse($creds) $uri = $acctobj.Credentials.TransformUri($uri) echo "Confirmed - storage account '$($acct.StorageAccountName)'." $blobclient = New-Object Microsoft.WindowsAzure.StorageClient.CloudBlobClient($acctobj.BlobEndpoint, $acctobj.Credentials) $blobclient.Timeout = (New-TimeSpan -Minutes 1) $blob = New-Object Microsoft.WindowsAzure.StorageClient.CloudPageBlob($uri, $blobclient) echo "Checking whether the blob is currently registered as a disk or image..." $disk = Get-AzureDisk | ? { (new-object System.Uri($_.MediaLink)) -eq $blob.Uri } if($disk) { write-host "The blob is still registered as a disk with name '$($disk.DiskName)'. Please delete the disk first." -foregroundcolor "red" break } $image = Get-AzureVMImage | ? { $_.MediaLink -eq $blob.Uri.AbsoluteUri } if($image) { write-host "The blob is still registered as an OS image with name '$($image.ImageName)'. Please delete the OS image first." -foregroundcolor "red" break } echo "Confirmed - the blob is not in use by the Windows Azure platform." echo "Inspecting the blob's lease status..." try { $blob.FetchAttributes() } catch [System.Management.Automation.MethodInvocationException] { write-host $_.Exception.InnerException.Message -foregroundcolor "red" break } echo "Current lease status: $($blob.Properties.LeaseStatus)" if($blob.Properties.LeaseStatus -ne [Microsoft.WindowsAzure.StorageClient.LeaseStatus]::Locked) { write-host "Success - the blob is unlocked." -foregroundcolor "green" break } echo "Unlocking the blob..." $request = [Microsoft.WindowsAzure.StorageClient.Protocol.BlobRequest]::Lease($uri, 0, [Microsoft.WindowsAzure.StorageClient.Protocol.LeaseAction]::Break, $null) $request.Timeout = $blobclient.Timeout.TotalMilliseconds $acctobj.Credentials.SignRequest($request) try { $response = $request.GetResponse() $response.Close() } catch { write-host "The blob could not be unlocked:" -foregroundcolor "red" write-host $_.Exception.InnerException.Message -foregroundcolor "red" break } $blob.FetchAttributes() echo "Current lease status: $($blob.Properties.LeaseStatus)" write-host "Success - the blob is unlocked." -foregroundcolor "green"
如下圖,存完後的檔案。
接下來,因為要執行的shell,會牽涉到安全性,所以我們要先把Windows Azure PowserShell的安全性原則解除,輸入Set-ExecutionPolicy unrestricted,然後按下Y。
接下來,我們就要Run剛剛建立的Shell之後,就會要求我們填入一些資訊,第一個要填的是Blob的URL,我們可以回到Windows Azure的管理介面,Blob那邊找到 ( 也就是要刪除的那頁 ),我們把URL全部框起來,利用左鍵,並按下複製,其實就可以將全部的URL複製下來了喔!!如下圖,貼上去就可以了。
然後根據官方文件,就會吐出這些東西。
BreakLease.ps1 -Uri 'http://clstorage.blob.core.windows.net/vhds/testvm1-testvm1-2012-06-26.vhd'
Processing http://clstorage.blob.core.windows.net/vhds/testvm1-testvm1-2012-06-26.vhd
Reading storage account information...
Confirmed - storage account 'clstorage'.
Checking whether the blob is currently registered as a disk or image...
Confirmed - the blob is not in use by the Windows Azure platform.
Inspecting the blob's lease status...
Current lease status: Locked
Unlocking the blob...
Current lease status: Unlocked
Success - the blob is unlocked.
到這邊,就算完成了!!
後記
而官方也提供了另外一個方法,是利用CloudXplorer工具,利用此工具的Rename功能來複製VHD ( 沒錯,就是Rename功能- -.. ),然後再用新的VHD來建立Disk;其實這個方法也滿簡單的,至於要用哪個做法就看看官如何選擇啦~~