2012年9月28日

[Azure] There is currently a lease on the blob and no lease ID was specified in the request.

在使用Windows Azure 3 month Free trial到達免費限制之後, 系統會自動刪除已經發布的服務及VM, 之後當重新啟用帳號並想要建立VM時, 有時會發現VHD被指向不存在的VM並且無法刪除. 當嘗試刪除時會遇到這個錯誤.

準備工作

1. 到這裡下載並安裝Windows Azure SDK

2. 下載並安裝Windows Azure Power Shell

3. 下載並安裝CloudXplorer

備份VHD

1. 啟動Cloud Xplorer並新增Storage Account

image

2. 瀏覽到Storage Accoung, 打開vhds container後, 右鍵點選需要備份的VHD檔案, 點Rename, 並給予檔案一個新的名稱

3. 因為這個VHD的lease未被刪除, 所以會跳出一個錯誤訊息, 請按Yes繼續

image

4. 這邊會看到新的檔案被建立

image

5. 回到Azure Management Portal, 選Virtual Machines, Disk點選下方Create Disk

6. 在這裡填上正確的資料, VHD URL就是剛剛我們建立出來的新的VHD的位置

image

刪除Lease

1. 以系統管理員身分執行Windows Azure Powershell

2. 在Powershell中輸入cd C:\temp以切換目前工作目錄到C:\temp下

3. 在Powershell中執行下列命令, 並按Y確定

set-executionpolicy remotesigned

image

4. 在Powershell中執行

get-azurepublishsettingsfile

這會打開瀏覽器下載publish setting, 請將檔案儲存到C:\Temp以避免後續產生權限問題

5. 如果看到以下這個錯誤訊息, 請到舊版Management Portal刪除不必要的憑證

You have reached your quota of 10 management certificates and cannot add any more. Visit the Management Portal to delete any unneeded certificates.

image

8. 在Powershell中執行

Import-AzurePublishSettingsFile

並輸入剛剛下載的檔案位置

9. 在Powershell中執行

Get-AzureSubscription並複製您的Subscription Name

image

10. 在Powershell中執行

Set-AzureSubscription –DefaultSubscription [剛剛複製的Subscription Name]

11. 在Powershell中執行這一段powershell script

並輸入您的VHD的URL

如果沒有看到錯誤訊息, 表示lease已經被刪除, 可以回到Azure Management Portal刪除這個Blob

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)"

2012年9月20日

[Azure][ASP.Net]Publish to Azure with config transformation

* This only works for Web Roles with single APS.Net web site, if you have additional web project configured as a Virtual Application, you should first publish it to a folder other then your source code folder, then configure @physicalDictory of <VirtualApplication>ServiceDefinition.csdef point to that folder

Config transformation was first introduced in VS2010 and has become a very helpful feature when develop/deploy in various environment, however, this feature seem not works fine with Azure SDK when developing Cloud Services. You’ll find even if you’ve configured the transformation, it just doesn’t work when publish/package your Azure projects.

To fix that, we need to do some little modify on project files. First we are going to download and install a useful VS add-in SlowCheetah.

Once installed, let’s unload our Azure project file from solution. NOTE, unload Azure project, not the ASP.Net Web project.

image

Then edit project file.

image

Add the following codes to the project file

<Target Name="BeforeBuild">
<Copy SourceFiles="web.config" DestinationFiles="Web.Original.Config">
</Copy>
<TransformXml Source="Web.Original.Config"
Transform="Web.$(Configuration).config"
Destination="Web.Config"/>
</Target>


The updated file should look like this



image



Reload the project and verify it with your Azure publish.

2012年9月17日

[Azure][IIS]Enable IIS Failed Request Log

It is easy to enable IIS Failed request log on IIS 7+. First we need to enable Health and Diagnostic feature in Web Server Role via Server manager. Note that the feature is enabled by default on Windows Azure Role instances.

image

Once enabled, open IIS management console and navigate to Site node. There is a [Failed Request Tracing] link in Action panel, click on it to bring up Failed Request Tracing dialog box

image

Enable this feature, specify desired log directory and max. files then close it.

image

Now we can set Site leave or Application level trace files, in my example, I am going to enable Application level trace. So navigate to my web application, in content panel, a [Failed Request Tracing Rule] allows us to configure our desired rules for tracing this application.

Note that default log file path on Windows Azure is set to C:\Resources\directory\$DEPLOYMENT ID$.$RoleName$.DiagnosticStore\FailedReqLogFiles\$ProjecName$\$WCSVC ID$\

image

Open it and click on [Add…] link in Action panel to bring up configuration dialog box, we have several options here, in my example, I am going to enable trace files for ASPX requests.

image

Log status codes start from 400 to 599.

image

Her I just accept the defaults.

image

Once completed, a new rule is created.

image

2012年9月13日

[Azure]Deploy two web applications in one WebRole (Full IIS Mode)

在開發Cloud Service的時候, 最常用的方式就是新增一到多個Web Role, 然後統一發布. 這樣的發布方式, 會在Azure的虛擬機器上產生多個Web Site.

image

這時我們必須透過不同的port來存取這兩個網站(預設是80和8080)

如果我想要在同一個Web Role裡, 發布多個Web Application該怎麼做呢?

首先打開ServiceDefinition.csdef檔, 正常來說會長這樣子. 可以看到定義了兩個Role, 每個Role各有一個Web Site, 第一個Site的Endpoint port是80, 另一個是8081

image

接著我們要來修改這個檔案. 首先把第二個<WebRole>刪掉, 這樣我們就會只有一個WebRole了.

然後我把第一個Site的physicalDirectory設為我的網站的專案目錄的絕對路徑, 這樣VS就知道這個網站的project file在哪裡.

image

接下來, 我想把第二個Web Application放到這個Site下成為一個Web Application. 因此, 在<Site>下新增一個<VirtualApplication> tag如下

<VirtualApplication name="GPServices" physicalDirectory="{Project Folder}"/>


同樣的, 這邊的physicalDirectory指的是第二個網站(GPServices)的專案目錄路徑



image



最後完成的檔案如下



image



這邊我仍然保留了第二個Site, 因此發布到Azure上時, IIS上仍然會看到兩個WebSite. 但是, 因為我已經將GPServices發布成一個Web Application, 因此, 我就可以用http://{url}/GPServices 的網址來存取第二個網站了.



連線到機器上看一下IIS, 確實就如我們所想要的方式.












image

2012年9月12日

[Azure VM]SSMS to connect to SQL Server on Azure VM

透過Windows Azure VM Role建立一台雲端上的SQL Server是相當簡單的, 只要登入Windows Azure管理介面新增一台VM, 並且由Gallery選擇SQL 2012的template來產生虛擬機器即可 (這邊目前似乎必須是在預覽版的管理網站才看得到這個功能)

image

image

不過建立完畢後, 我卻一直無法透過SSMS連線. 一開始以為是防火牆的問題, 所以就先把本機電腦的防火牆關掉, 然後遠端連線到VM上把防火牆也關掉, 但是卻仍然收到”A connection attempt failed…”的錯誤訊息.

仔細回想了一下, 既然VM的FQDN是以cloudapp.net結尾, 表示VM應該一樣有著Cloud Service的Endpoint機制, 因此試著到管理介面加入一個Endpoint看看.

按這裡新增一個Endpoint

image

直接按下一步

image

填上想要開放的port number, public port就是該VM對外開放的port, 也就是實際上我們要從本機連線到VM時需要指定的port number. private port則是遠端VM上對應的port number, 由於我要連線的是SSMS, 因此這邊一定是1433.

image

填完之後按下確定, 等個幾分鐘, Endpoint就建立完成了.

但是這時再連線卻遇到Login Fail的錯誤. 不過, 收到這錯誤至少表示我們可以連線到遠端的SQL Server了! 接下來花了一點時間檢查一下遠端電腦上的SQL Server設定, 將驗證模式改為Windows與SQL驗證, 並且設定遠端電腦的防火牆允許1433連線.

image

就大功告成了!

image

2012年9月8日

[Windows Azure Service Bus]我的Azure Service Bus初探

Windows Azure Service Bus是Windows Azure平台提供的一個訊息溝通管道, 可以讓企業內的服務透過簡單的設定輕易的部屬到網際網路上. 在開接觸他之前, 我也著實幻想過怎麼樣能夠簡單的在不修改, 或是小部分修改程式, 且不需要動到公司內部網路架構的情況下就能把我的服務佈署到網際網路上. 不過如果沒有一個成熟的雲端平台, 基本上都會遇到很大的問題, 例如, 把服務搬到網際網路上意味著服務網址會改變, 那麼所有的內部使用這個服務的程式都必須配合修改. 把服務放到網路上, 也代表著我必須要有一個穩定的平台來host我的服務, 並且從此我都必須要把程式直接放到網路上, 這服務如果有存取到內部的資料庫(大部分的情況下一定是如此), 那麼我的服務顯然必須要做大幅度的修改.

幸好, 有了Windows Azure Service Bus, 我們可以簡單的把服務的端點註冊到網際網路上, 透過Windows Azure Service Bus幫我們讓網際網路上的使用者也能簡單的呼叫到我們企業內部的服務.

要使用Windows Azure Service Bus, 首先必須要先到Windows Azure管理介面上新增一個namespace.

image

按下建立之後, 就會建立這個namespace

image

接下來就可以開始寫程式啦~

首先要先建立一個WCF 服務, 這邊我用Windows Form來host一個服務回傳執行這個服務個體的機器名稱.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace WinFormHost
{
[ServiceContract]
public interface IWinSvc
{
[OperationContract]
string DoWork();
}
public class WinSvc : IWinSvc
{
public string DoWork()
{
return string.Format("Returned from {0}",System.Environment.MachineName);
}
}
}





服務的config, 首先只是簡單的使用HTTP提供介面給使用者呼叫.



    </system.serviceModel>
<services>
<service name="WinFormHost.WinSvc">
<endpoint address="" binding="basicHttpBinding" name="WinSvcHttp"
bindingName="basicHttpBinding" contract="WinFormHost.IWinSvc">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8733/services/WinSvcHttp/" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>


然後是服務的host


using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WinFormHost
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
System.ServiceModel.ServiceHost host = null;
private void button1_Click(object sender, EventArgs e)
{
host = new System.ServiceModel.ServiceHost(typeof(WinFormHost.WinSvc));
host.Open();

MessageBox.Show(string.Format("Service opened at {0}", host.Description.Endpoints[0].Address));
}

private void button2_Click(object sender, EventArgs e)
{
host.Close();
}
}
}



測試結果, 證明這是一個跑在本機上的WCF服務.


image


接下來我們要把服務透過Windows Azure Service Bus發布給網際網路上的程式呼叫了.


首先要從管理介面上取得我們剛剛建立的namespace的金鑰, 所有要存取我們的服務的客戶端都需要都會需要在呼叫服務時指定這組金鑰才能順利的存取到我們的服務.


image


接著將Microsoft.ServiceBus這個assembly加入原本WCF程式的reference中, 然後修改WCF的app.config檔, 讓他使用Windows Azure service bus提供的binding.


首先加入必要的extension


image


設定新的endpoint behavior


image


加入新的Service Endpoint, 這邊的位址的schema要指定為sb, 另外使用NetTcpRelayBinding作為傳輸方式


image










接下來是呼叫端, 這邊我用一個Web Role來呼叫, 並將得到的回傳結果顯示到畫面上



        protected void testButton_Click(object sender, EventArgs e)
{
Microsoft.ServiceBus.ServiceBusEnvironment.SystemConnectivity.Mode = ConnectivityMode.Http;//Force HTTP mode

var url = Microsoft.ServiceBus.ServiceBusEnvironment.CreateServiceUri("sb", "michi-sb-test01", "WinSvc");
var epBehavior = new Microsoft.ServiceBus.TransportClientEndpointBehavior(Microsoft.ServiceBus.SharedSecretTokenProvider.CreateSharedSecretTokenProvider(
"issuerName", "issuerSecret"));

var factory = new System.ServiceModel.ChannelFactory<WinFormHost.IWinSvc>("WinSvc", new System.ServiceModel.EndpointAddress(url));
status.Text = string.Format("invoking {0}", factory.Endpoint.Address.ToString());
var proxy = factory.CreateChannel();
using (proxy as IDisposable)
{
status.Text = proxy.DoWork();
}
}



接下來修改呼叫端的config檔



image



到這裡就算是大功告成了! 接下來只要測試就可以了! 首先執行Service host 確定服務已經註冊到Azure Service Bus上



image



然後執行測試程式! 大功告成!



image

Blog Archive

About Me