2012年10月10日

Windows Azure - 錯誤!! 當使用現有的Disk來建立新VM時產生A lease conflict occurred with the blob

其實這篇,是昨天在將做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的管理工具。

image

接下來,安裝程式會呼叫Web Platform Installer 4.0,當然,也沒甚麼好猶豫的…反正也只能安裝了= =…

image

安裝完後,就可以找到Windows Azure PowerShell。( 找不到的人,可以利用搜尋功能,搜尋Windows Azure PowerShell,通常裝完後,就可以從開始那邊找到。 ),另外,記得用administrator權限開啟!!

image

接下來,在管理工具裡面輸入Get-AzurePublishSettingsFile,他就會自動地開啟瀏覽器,並且提供publishsetting檔案給我們下載,我們當然就是下載啦!!( 建議存到預設的下載目錄,這樣等下就不需要再打路徑了。 )

image

那剛剛下載的Publishsetting是做甚麼的呢,當然就是給Windows Azure PowerShell用的,如果沒有這個檔案,Windows Azure PowerShell自然就沒有權限…,所以下一步,我們要把這個檔案給Windows Azure PowerShell來使用;我們要在Windows Azure PowerShell裡面下這個指令Import-AzurePublishSettingsfile $env:userprofile\downloads\*.publishsettings 很簡單吧!!所以剛剛才建議大家直接丟到下載目錄,這樣這時候就可以直接複製上面那個指令到Windows Azure PowserShell裡面了,如果不是放到下載目錄,而是放在其他目錄,則後面的路徑,就要記得自己改喔!!

image

接下來,我們要把下面這烙烙長的程式碼貼到記事本上面去!! ( 就不要問小弟我內容了= =|| ),並且取名為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"

如下圖,存完後的檔案。

image

接下來,因為要執行的shell,會牽涉到安全性,所以我們要先把Windows Azure PowserShell的安全性原則解除,輸入Set-ExecutionPolicy unrestricted,然後按下Y。

image

接下來,我們就要Run剛剛建立的Shell之後,就會要求我們填入一些資訊,第一個要填的是Blob的URL,我們可以回到Windows Azure的管理介面,Blob那邊找到 ( 也就是要刪除的那頁 ),我們把URL全部框起來,利用左鍵,並按下複製,其實就可以將全部的URL複製下來了喔!!如下圖,貼上去就可以了。

image

然後根據官方文件,就會吐出這些東西。

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;其實這個方法也滿簡單的,至於要用哪個做法就看看官如何選擇啦~~

參考網址

沒有留言:

張貼留言