<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>64 Blog</title>
	<atom:link href="http://blogs.gine.jp/kusa/feed" rel="self" type="application/rss+xml" />
	<link>http://blogs.gine.jp/kusa</link>
	<description>PS C:\&#62;Write-なんやかんや</description>
	<lastBuildDate>Fri, 04 May 2012 09:11:52 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<item>
		<title>Hyper-V 2.0 で WMI を使った PowerShell の内容を Hyper-V 3.0 でやってみる</title>
		<link>http://blogs.gine.jp/kusa/archives/1838</link>
		<comments>http://blogs.gine.jp/kusa/archives/1838#comments</comments>
		<pubDate>Fri, 04 May 2012 09:00:33 +0000</pubDate>
		<dc:creator>kusakari</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[Hyper-V]]></category>
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://blogs.gine.jp/kusa/?p=1838</guid>
		<description><![CDATA[Hyper-V 2.0 を PowerShell で運用管理するには、WMI を頑張って利用するか、PowerShell Management Library for Hyper-V などのモジュールを利用する方法をとる &#8230; <a href="http://blogs.gine.jp/kusa/archives/1838">Read more <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Hyper-V 2.0 を PowerShell で運用管理するには、WMI を頑張って利用するか、<a href="http://pshyperv.codeplex.com/" target="_blank">PowerShell Management Library for Hyper-V</a> などのモジュールを利用する方法をとると思いますが、Hyper-V 3.0 では標準コマンドレットとして Windows Server 2012 に組み込まれています。 </p>
<p>今回は、どれだけ簡単になったか 過去 WMI を使った内容と比較して確認してみようと思います。（ベータ版での確認です。） <br />&nbsp;<br />&nbsp;<br /> <br />
<h3><strong>■ 仮想マシン一覧の取得</strong></h3>
<p><strong></strong>Hyper-V2.0 の際は、<a href="http://blogs.gine.jp/kusa/archives/76" target="_blank">続．PowerShellでHyper-V上の仮想マシンの一覧取得</a> で次のように書きました。
<pre class="brush:powershell">Get-WmiObject -Namespace root\virtualization -ComputerName "." -Class Msvm_Computersystem</pre>
<p>Hyper-V 3.0 では次のように書くことができます。</p>
<pre class="brush:powershell">Get-VM</pre>
<p>&nbsp;<br />&nbsp;</p>
<h3><strong>■ 仮想マシン状態の取得</strong></h3>
<p>Hyper-V2.0 の際は、<a href="http://blogs.gine.jp/kusa/archives/76" target="_blank">続．PowerShellでHyper-V上の仮想マシンの一覧取得</a> で次のように書きました。
<pre class="brush:powershell">function getStatus($i){
      switch ($i) {
          0 {"不明"}
          2 {"実行中（Enabled）"}
          3 {"停止（Disabled）"}
          32768 {"一時停止（Paused）"}
          32769 {"保存完了（Suspended）"}
          32770 {"復元（Starting）"}
          32771 {"スナップショット取得中（Snapshotting）"}
          32773 {"保存中（Saving）"}
          32774 {"停止中（Stopping）"}
          32776 {"一時停止中（Pausing）"}
          32777 {"再開中（Resuming）"}
          default {"不明"}
      }
}

Get-WmiObject -Namespace root\virtualization -Class Msvm_Computersystem |
      ForEach-Object {
          $_.ElementName
          $_.Caption
          getStatus($_.EnabledState)
          "`r`n"
      }</pre>
<p>Hyper-V 3.0 では次のように書くことができます。</p>
<pre class="brush:powershell">Get-VM | select Name, State, Status</pre>
<p>&nbsp;<br />&nbsp;</p>
<h3><strong>■ 特定の仮想マシンシャットダウン</strong></h3>
<p>Hyper-V2.0 の際は、<a href="http://blogs.gine.jp/kusa/archives/75" target="_blank">PowerShellでHyper-V上の仮想マシンをシャットダウン</a> で次のように書きました。
<pre class="brush:powershell">$vm_name = "&lt;仮想インスタンス名&gt;"

$vm = gwmi -Namespace root\virtualization -Class Msvm_ComputerSystem -Filter "ElementName = '$vm_name'"
$shutdown = gwmi -namespace root\virtualization -Query "Associators of {$vm} Where ResultClass = Msvm_ShutdownComponent"

return $shutdown.InitiateShutdown($true, "&lt;シャットダウンの理由&gt;")</pre>
<p>Hyper-V 3.0 では次のように書くことができます。</p>
<pre class="brush:powershell">Stop-VM -Name &lt;仮想マシン名&gt;</pre>
<p>&nbsp;<br />&nbsp;</p>
<h3><strong>■ Hyper-V上の全仮想マシンのシャットダウン</strong></h3>
<p>Hyper-V2.0 の際は、<a href="http://blogs.gine.jp/kusa/archives/75" target="_blank">PowerShellでHyper-V上の仮想マシンをシャットダウン</a> で次のように書きました。
<pre class="brush:powershell">$ns = "root\virtualization"

$vmCollection = gwmi -Namespace $ns Msvm_Computersystem -Filter "Description = 'Microsoft Virtual Machine'"
$vmCollection | foreach {
      if($_.EnabledState -ne "3") {
          $shutdown = gwmi -Namespace $ns -Query "Associators of {$_} Where ResultClass = Msvm_ShutdownComponent"
          $shutdown.InitiateShutdown($true, "定期メンテナンス") | Out-Null
          Start-Sleep -Milliseconds 1000
          }
      } </pre>
<p>Hyper-V 3.0 では次のように書くことができます。</p>
<pre class="brush:powershell">Get-VM | Stop-VM</pre>
<p>&nbsp;<br />&nbsp;</p>
<h3><strong>■ 特定の仮想マシンを起動</strong></h3>
<p>Hyper-V2.0 の際は、<a href="http://blogs.gine.jp/kusa/archives/74" target="_blank">PowerShellでHyper-V上の仮想マシンを起動させる</a> で次のように書きました。
<pre class="brush:powershell">$vm_name = "&lt;仮想インスタンス名&gt;"

$vm = gwmi -Namespace root\virtualization -Class Msvm_ComputerSystem -Filter "ElementName = '$vm_name'"
$vm_status = $vm.RequestStateChange(2)</pre>
<p>Hyper-V 3.0 では次のように書くことができます。</p>
<pre class="brush:powershell">Start-VM -Name &lt;仮想マシン名&gt;</pre>
<p>&nbsp;<br />&nbsp;</p>
<h3><strong>■ 仮想マシンのエクスポート</strong></h3>
<p>Hyper-V2.0 の際は、<a href="http://blogs.gine.jp/kusa/archives/73" target="_blank">PowerShellでHyper-V上の仮想マシンをエクスポート</a> で次のように書きました。
<pre class="brush:powershell">$ns = "root\virtualization"
$vm_target = "VM-1"
$vm_export_path = "c:\temp\"

$vm_manager = gwmi -Namespace $ns Msvm_VirtualSystemManagementService
$vm = gwmi -Namespace $ns Msvm_ComputerSystem -Filter "ElementName = '$vm_target'"

$vm_manager.ExportVirtualSystem($vm, $TRUE, $vm_export_path)</pre>
<p>Hyper-V 3.0 では次のように書くことができます。</p>
<pre class="brush:powershell">Get-VM -Name &lt;仮想マシン名&gt; | % { if($_.State -eq "Running"){ Stop-VM -Name $_.Name }; Export-VM -Name $_.Name -Path C:\temp }</pre>
<p>&nbsp;<br />&nbsp;</p>
<h3><strong>■ 仮想マシンのインポート</strong></h3>
<p>Hyper-V2.0 の際は、<a href="http://blogs.gine.jp/kusa/archives/72" target="_blank">PowerShellでHyper-V上の仮想マシンをインポート</a> で次のように書きました。
<pre class="brush:powershell">$ns = "root\virtualization"
$vm_import_path = "c:\temp\VM-1"

$vm_manager = gwmi -Namespace $ns Msvm_VirtualSystemManagementService
$vm_manager.ImportVirtualSystem($vm_import_path, $TRUE) | Out-Null</pre>
<p>Hyper-V 3.0 では次のように書くことができます。</p>
<pre class="brush:powershell">Import-VM -Path "エクスポート先フォルダパス\Virtual Machines\XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX.XML" -Copy –GenerateNewId</pre>
<p>&nbsp;<br />&nbsp;</p>
<h3><strong>■ 仮想マシンのスナップショット取得</strong></h3>
<p>Hyper-V2.0 の際は、<a href="http://blogs.gine.jp/kusa/archives/71" target="_blank">PowerShellでHyper-V上の仮想マシンのスナップショット取得</a> で次のように書きました。
<pre class="brush:powershell">$ns = "root\virtualization"
$target = "VM-1"

$vm = gwmi -Namespace $ns Msvm_Computersystem -Filter "ElementName = '$target'"
$manager = gwmi -Namespace $ns Msvm_VirtualSystemManagementService
$manager.CreateVirtualSystemSnapshot($vm.__Path)</pre>
<p>Hyper-V 3.0 では次のように書くことができます。</p>
<pre class="brush:powershell">Checkpoint-VM -Name <仮想マシン名> -SnapshotName "スナップショットテスト"</pre>
<p>&nbsp;<br />&nbsp;<br />ああ、なんということでしょう。 </p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.gine.jp/kusa/archives/1838/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Windows PowerShell Web Access を使って Azure のインスタンスにリモーティング</title>
		<link>http://blogs.gine.jp/kusa/archives/1782</link>
		<comments>http://blogs.gine.jp/kusa/archives/1782#comments</comments>
		<pubDate>Mon, 16 Apr 2012 19:20:09 +0000</pubDate>
		<dc:creator>kusakari</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://blogs.gine.jp/kusa/?p=1782</guid>
		<description><![CDATA[第69回CLR/H勉強会でライトニングトークしてきました。今回はそのネタです。 オンプレに Windows Server 8 （ベータ版）をインストールして、Windows PowerShell Web Access の &#8230; <a href="http://blogs.gine.jp/kusa/archives/1782">Read more <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>第69回<a href="http://clr-h.jp/" target="_blank">CLR/H勉強会</a>でライトニングトークしてきました。今回はそのネタです。</p>
<p>オンプレに Windows Server 8 （ベータ版）をインストールして、Windows PowerShell Web Access の設定を行います。<br />Windows Azure のインスタンスには、Startup タスクで ファイアウォールに WinRM を通すようにして、リモーティングを有効にします。 </p>
<p>対応しているスマートフォンからであれば、VPN を接続してオンプレの Windows PowerShell Web Access のゲートウェイサーバーに接続すれば、Azure のインスタンスに対して PowerShell のコマンドを実行できるという内容です。</p>
<p>&nbsp;</p>
<p>Windows PowerShell Web Access のインストールや設定に関しては下記をご覧ください。<br /><a href="http://technet.microsoft.com/en-us/library/hh831611.aspx" target="_blank">Deploy Windows PowerShell Web Access</a></p>
<p>&nbsp;<br /> 
<p>Azure インスタンスは 次の設定を行います。
<ul>
<li>■ osFamily は 2 （Windows Server 2008 R2）
<li>■ エンドポイントに Input で TCP 5985 を追加
<li>■ リモートデスクトップ接続を有効
<li>■ Startup タスクは elevated レベルで startup.cmd を実行するようして、下記の2つのファイルを作成</li>
</ul>
<p>&nbsp;<br />[startup.cmd]</p>
<pre class="brush:plain">@echo off
powershell -executionpolicy remotesigned -file startup.ps1</pre>
<p>&nbsp;</p>
<p>[startup.ps1]</p>
<pre class="brush:powershell"># アセンブリ追加
[Reflection.Assembly]::LoadWithPartialName("Microsoft.WindowsAzure.ServiceRuntime")
[Reflection.Assembly]::LoadWithPartialName("System.Security")

# .cscfg から ユーザー名・暗号化されたパスワード・サムプリントを取得
$username = [Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment]::GetConfigurationSettingValue("Microsoft.WindowsAzure.Plugins.RemoteAccess.AccountUsername")
$encpswd = [Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment]::GetConfigurationSettingValue("Microsoft.WindowsAzure.Plugins.RemoteAccess.AccountEncryptedPassword")
$thumbprint = [Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment]::GetConfigurationSettingValue("CertificateThumbprint")

# 復号化
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store My,CurrentUser
$store.Open("ReadOnly")
$ec = New-Object Security.Cryptography.Pkcs.EnvelopedCms
$ec.Decode([Convert]::FromBase64String($encpswd))
$ec.Decrypt($store.Certificates)
$pswd = [Text.Encoding]::UTF8.GetString($ec.ContentInfo.Content)

# FW設定
netsh advfirewall firewall add rule name="Windows Remote Management (HTTP-In)" dir=in program=system action=allow protocol=TCP localport=5985
$dt = [datetime]::now.addminutes(5).tostring("HH:mm:ss")
SCHTASKS /CREATE /TN "WinRM" /TR "powershell Enable-PSRemoting -Force" /SC ONCE /ST $dt /RU $username /RP $pswdSCHTASKS /RUN /TN "WinRM"</pre>
<p>&nbsp;</p>
<p>https で Windows PowerShell WebAccess にアクセスして、下記のような感じで必要な情報を入力します。<br /><a title="2012417457_062 by bakecat.64, on Flickr" href="http://www.flickr.com/photos/bakecat64/7084859839/"><img alt="2012417457_062" src="http://farm6.staticflickr.com/5156/7084859839_da815a73be_z.jpg" width="497" height="640"></a><br />ユーザー名とパスワードは、オンプレでの接続情報（AD などが立っていれば、AD ユーザー ID ）を入力して、コンピューター名は、Azure の DNS 名を入力します。<br />そして、オプション接続設定のユーザー名とパスワードは、リモートデスクトップ用の接続情報を入力します。</p>
<p>問題が無ければ下図のようになります。（図は ipconfig を入力した結果）<br /><a title="2012417493_063 by bakecat.64, on Flickr" href="http://www.flickr.com/photos/bakecat64/7084859925/"><img alt="2012417493_063" src="http://farm8.staticflickr.com/7063/7084859925_d8b6374909_z.jpg" width="513" height="582"></a></p>
<p>運用管理用の .ps1 ファイルを一緒にデプロイしてしまえば 多少は入力の手間も省けたりしそうです。ただ、この仕組みの場合、横スケールしている際の Azure 上のインスタンス狙い撃ちは出来ません。Azure で サポートする OS が増えてくれたり、あんなことやこんなことが出来るようになってくれれば…的な。</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.gine.jp/kusa/archives/1782/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Windows Azure の StartupTask で .cscfg ファイルを参照する</title>
		<link>http://blogs.gine.jp/kusa/archives/1775</link>
		<comments>http://blogs.gine.jp/kusa/archives/1775#comments</comments>
		<pubDate>Wed, 04 Apr 2012 09:19:00 +0000</pubDate>
		<dc:creator>kusakari</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://blogs.gine.jp/kusa/archives/1775</guid>
		<description><![CDATA[StartupTask を使って何か処理を行う際、あまりハードコードしたくない部分とかがありまして、例えば リモートデスクトップのユーザー名とかパスワードとか。 Windows Azure で Windows Serve &#8230; <a href="http://blogs.gine.jp/kusa/archives/1775">Read more <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>StartupTask を使って何か処理を行う際、あまりハードコードしたくない部分とかがありまして、例えば リモートデスクトップのユーザー名とかパスワードとか。<br />
<a href="http://blogs.gine.jp/kusa/archives/1725" target="_blank">Windows Azure で Windows Server AppFabric Caching を使ってみる</a> のスタートアップタスクでも、ユーザー名とパスワードをべた書きしていますし。</p>
<p>じゃあどうしようかと思ったところ、そもそも .cscfg にリモデを有効にするとユーザー名と暗号化されたパスワードとかも含まれてるんだから、それ使っちゃえばいいやと。<br />
ということで今回は、StartupTask で .cscfg ファイルのユーザー名とパスワードを参照するようにしてみたいと思います。<br />
<br />&nbsp;<br />
.csdef に下記の startup.cmd を実行するように StartupTask の設定を行います。<br />
[startup.cmd]</p>
<pre class="brush:plain">@echo off
powershell -executionpolicy remotesigned -file "%~dp0startup.ps1" %~dp0</pre>
<p>
startup.cmd で呼び出している .ps1 ファイルは次の通りです。<br />
[startup.ps1]</p>
<pre class="brush:powershell"># アセンブリ追加
[Reflection.Assembly]::LoadWithPartialName("Microsoft.WindowsAzure.ServiceRuntime")
[Reflection.Assembly]::LoadWithPartialName("System.Security")

# .cscfg から ユーザー名・暗号化されたパスワード・サムプリントを取得
$username = [Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment]::GetConfigurationSettingValue("Microsoft.WindowsAzure.Plugins.RemoteAccess.AccountUsername")
$encpswd = [Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment]::GetConfigurationSettingValue("Microsoft.WindowsAzure.Plugins.RemoteAccess.AccountEncryptedPassword")
$thumbprint = [Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment]::GetConfigurationSettingValue("CertificateThumbprint")

# 復号化
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store My,CurrentUser
$store.Open("ReadOnly")
$cer = $store.Certificates.Find(0,$thumbprint,0)
$ec = New-Object Security.Cryptography.Pkcs.EnvelopedCms
$ec.Decode([Convert]::FromBase64String($encpswd))
$ec.Decrypt($cer)
$pswd = [Text.Encoding]::UTF8.GetString($ec.ContentInfo.Content)

# 結果確認用
Add-Type -Language CSharpVersion3 -TypeDefinition @'
public class Account
{
     public string UserName {get; set;}
     public string Password {get; set;}
}
'@

$user = New-Object Account
$user.UserName = $username
$user.Password = $pswd
$ret = [System.IO.Path]::Combine([System.IO.Path]::GetPathRoot("$args[0]"), "sitesroot\0\index.htm")
$user | ConvertTo-Html &gt; $ret</pre>
<p>&nbsp;<br />Microsoft.WindowsAzure.ServiceRuntime を読み込んで GetConfigurationSettingValue で必要な項目を取り出しているだけです。<br />
ただ、.cscfg の Certificates の中の thumbprint を取得する方法が分からなかったので、ConfigurationSettings に CertificateThumbprint という名前でサムプリントの値を追加しています。<br />
<a title="2012441825_059 by bakecat.64, on Flickr" href="http://www.flickr.com/photos/bakecat64/7044454635/"><img src="http://farm8.staticflickr.com/7277/7044454635_236d97b13b_z.jpg" alt="2012441825_059" width="640" height="277" /></a><br />
<br />
あとは、取り出した内容を使って、パスワードの復号化をしているだけです。そして、結果はこんな感じです。<br />
<a title="201244181624_061 by bakecat.64, on Flickr" href="http://www.flickr.com/photos/bakecat64/7044454689/"><img src="http://farm8.staticflickr.com/7201/7044454689_4c94a040eb_z.jpg" alt="201244181624_061" width="640" height="95" /></a><br />
<br />&nbsp;<br />* 追記 2012/04/04 18:55 <br />たんたかさんに 今回のようなケースで証明書のところストア内を検索する必要ないよーって感じで教えてもらいました。それと、StoreLocation.LocalMachine でもいけることも。ということで、復号化のところは下記のような内容でも OK です。
<pre class="brush:powershell">$store = New-Object System.Security.Cryptography.X509Certificates.X509Store StoreLocation.LocalMachine
$store.Open("ReadOnly")
$ec = New-Object Security.Cryptography.Pkcs.EnvelopedCms
$ec.Decode([Convert]::FromBase64String("$encpswd"))
$ec.Decrypt($store.Certificates)
$pswd = [Text.Encoding]::UTF8.GetString($ec.ContentInfo.Content)</pre>
]]></content:encoded>
			<wfw:commentRss>http://blogs.gine.jp/kusa/archives/1775/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Windows Management Framework 3.0 &#946; で Azure の PowerShell を 3.0 にする。</title>
		<link>http://blogs.gine.jp/kusa/archives/1760</link>
		<comments>http://blogs.gine.jp/kusa/archives/1760#comments</comments>
		<pubDate>Tue, 13 Mar 2012 14:21:31 +0000</pubDate>
		<dc:creator>kusakari</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://blogs.gine.jp/kusa/?p=1760</guid>
		<description><![CDATA[Windows Management Framework 3.0 のベータが出たので Windows Azure に入れてみました。 &#160; ■1．Web でも Worker でもいいのでロールを1個 用意します。 &#8230; <a href="http://blogs.gine.jp/kusa/archives/1760">Read more <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<div>Windows Management Framework 3.0 のベータが出たので Windows Azure に入れてみました。</div>
<div></div>
<p>&nbsp;</p>
<div>■1．Web でも Worker でもいいのでロールを1個 用意します。</div>
<p>&nbsp;</p>
<div>■2．.csdef ファイルに elevated 権限で Startup タスクの設定をおこない、次の内容のファイルを用意します。<br />
[ startup.cmd ]</p>
<pre class="brush:plain">@echo off
sc config wuauserv start= demand
wusa.exe "%~dp0Resources\Windows6.1-KB2506143-x64.msu" /quiet
sc config wuauserv start= disabled</pre>
</div>
<p>&nbsp;</p>
<div>
■3．.cscfg ファイルで設定した osFamily の値に応じて、次のサイトから WMF 3.0 をダウンロードしてパッケージファイルに組み込みます。<br />
<a href="http://www.microsoft.com/download/en/details.aspx?id=28998" target="_blank">Windows Management Framework 3.0 &#8211; Beta</a></div>
<p>&nbsp;</p>
<div>
■4．デプロイ
</div>
<p>&nbsp;</p>
<div>
■5．確認<br />
PowerShell のバージョンを確認したり、Side by Side で PowerShell 2.0 で動かすことが出来ています。<br />
<a title="2012313231543_040 by bakecat.64, on Flickr" href="http://www.flickr.com/photos/bakecat64/6833131378/"><img src="http://farm8.staticflickr.com/7176/6833131378_b6ecb70b08_z.jpg" alt="2012313231543_040" width="640" height="496" /></a></div>
]]></content:encoded>
			<wfw:commentRss>http://blogs.gine.jp/kusa/archives/1760/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP から ODBC で SQL Azure に接続する</title>
		<link>http://blogs.gine.jp/kusa/archives/1743</link>
		<comments>http://blogs.gine.jp/kusa/archives/1743#comments</comments>
		<pubDate>Mon, 13 Feb 2012 09:00:30 +0000</pubDate>
		<dc:creator>kusakari</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://blogs.gine.jp/kusa/?p=1743</guid>
		<description><![CDATA[出来るかどうかの確認なので大抵の事は気にせず、まんま単純に PHP から SQL Azure に ODBC で接続をしてみたいと思います。 &#160; まずは、Azure に PHP が実行できる環境を作ります。方法は &#8230; <a href="http://blogs.gine.jp/kusa/archives/1743">Read more <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>出来るかどうかの確認なので大抵の事は気にせず、まんま単純に PHP から SQL Azure に ODBC で接続をしてみたいと思います。</p>
<p>&nbsp;</p>
<p>まずは、Azure に PHP が実行できる環境を作ります。<br />方法は色々ありますが、今回はパッケージに PHP をまるっと入れ、FastCGI などの設定は StartupTask で行う方法にしていますが、その辺の設定部分は省略しますので、必要に応じて <a href="http://blogs.gine.jp/kusa/archives/1407" target="_blank">Azure （Full IIS）で PHP を実行</a> などをご覧ください。</p>
<p>&nbsp;</p>
<p>で、ODBC 設定の続きです。PDO からの接続もあるので php.ini で 下記の Extension のコメントアウトを外します。（その他、Azure で PHP を実行できるために必要な設定をしておきます。）</p>
<pre class="brush:text">extension=php_pdo_odbc.dll</pre>
<p>&nbsp;</p>
<p>odbcconf.exe コマンドを使って DSN を作ってしまおうと考えましたが、SQL Server 認証に必要な UID とパスワードが（おそらく）セキュリティの関係で渡せないので、今回は下記のような DSN 構文を使うような感じで、簡単なクエリを投げて動作を確認してみます。</p>
<p>[ index.php ]</p>
<pre class="brush:php">&lt;?php

// PDOの場合
try {
    $connPdo = new PDO("odbc:DRIVER={SQL Server Native Client 10.0};SERVER={servername}.database.windows.net;PORT=1433;DATABASE={databasename};PROTOCOL=TCPIP;UID={userid}@{servername};PWD={password};");
} catch(PDOException $e){
    echo "FAILED：" . $e-&gt;getMessage() . "&lt;br /&gt;";
    exit;
}

$cursor = $connPdo-&gt;query('SELECT DATEADD(hh, 9, GETDATE())');
foreach ($cursor as $row) {
    echo "PDOの場合： " . $row[0] . "&lt;br /&gt;";
}
$connPdo = null;

// odbc_connectの場合
$conn = odbc_connect("DRIVER={SQL Server Native Client 10.0};SERVER={servername}.database.windows.net;DATABASE={databasename}","{userid}@{servername}","{password}");
$query = "SELECT DATEADD(hh, 9, GETDATE())";
$resultSet = odbc_exec($conn, $query);
odbc_fetch_row($resultSet);
echo "odbc_connectの場合： " . odbc_result($resultSet, "") . "&lt;br /&gt;";
odbc_close($conn);

?&gt;</pre>
<p>&nbsp;</p>
<p>以上です。デプロイして結果を確認するとこうなりました。<br /><a title="201221317477_012 by bakecat.64, on Flickr" href="http://www.flickr.com/photos/bakecat64/6868415383/"><img alt="201221317477_012" src="http://farm8.staticflickr.com/7067/6868415383_0433d0bbcb_z.jpg" width="504" height="114"></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.gine.jp/kusa/archives/1743/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Windows Azure で Windows Server AppFabric Caching を使ってみる</title>
		<link>http://blogs.gine.jp/kusa/archives/1725</link>
		<comments>http://blogs.gine.jp/kusa/archives/1725#comments</comments>
		<pubDate>Sat, 04 Feb 2012 06:00:54 +0000</pubDate>
		<dc:creator>kusakari</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://blogs.gine.jp/kusa/?p=1725</guid>
		<description><![CDATA[Windows Azure にはキャッシュサービスがありますが、今回やっているのは Windows Server AppFabric v1.1 のキャッシュ機能を Azure で使えるように設定してみましょう。という内容 &#8230; <a href="http://blogs.gine.jp/kusa/archives/1725">Read more <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Windows Azure にはキャッシュサービスがありますが、今回やっているのは Windows Server AppFabric v1.1 のキャッシュ機能を Azure で使えるように設定してみましょう。という内容です。</p>
<p>Windows Server AppFabric に関しては、<a href="http://www.microsoft.com/japan/windowsserver2008/r2/technologies/appfabric.mspx" target="_blank">Windows Server AppFabric のご紹介</a> などをご覧ください。</p>
<p>&nbsp;<br />
では、さっそく実装に関してです。用意するものは下記に列挙しているものが必要になります。<br />
■ Webロール　…　1つ。<br />
■ Workerロール　…　1つ。<br />
■ ntrights.exe　…　1つ。<br />
■ WindowsServerAppfabricSetup_x64.exe　…　1つ。</p>
<p>ntrigts.exe は、Appfabric のサービスを動かすのにログイン権限が必要なので利用します。exe ファイルは、下記のリンクから WindowsServer2003 のリソキツールを適当なマシンにインストールして exe ファイルをサルベージしてください。<br />
<a href="http://www.microsoft.com/download/en/details.aspx?DisplayLang=en&amp;id=17657" target="_blank">Windows Server 2003 Resource Kit Tools</a></p>
<p>WindowsServerAppfabricSetup_x64.exe は、下記のリンクから v1.1 を入手します。<br />
<a href="http://www.microsoft.com/download/en/details.aspx?id=27115" target="_blank">Microsoft AppFabric 1.1 for Windows Server</a></p>
<p>なお、今回ロールは2つのロールとも、Windows Server 2008 R2 を使っています。</p>
<p>&nbsp;<br />
それでは最初に、Worker ロールの設定から行います。</p>
<p style="font-size: 110%;"><strong>Worker ロール</strong></p>
<p>Worker ロールの役割としては 共有フォルダ の提供です。まず、SMB 用にエンドポイントの設定をします。<br />
<a title="2012130212558_006 by bakecat.64, on Flickr" href="http://www.flickr.com/photos/bakecat64/6788926153/"><img src="http://farm8.staticflickr.com/7014/6788926153_5b011b262e.jpg" alt="2012130212558_006" width="500" height="182" /></a><br />
<br />&nbsp;<br />
そして、Windowsファイアーウォールに穴をあけて共有フォルダの設定するように、WorkerRole.cs を設定します。</p>
<p>[ WorkerRole.cs ]</p>
<pre class="brush:csharp;">using System;
using System.Diagnostics;
using System.Net;
using System.IO;
using System.Threading;
using Microsoft.WindowsAzure.ServiceRuntime;

namespace SMBHost
{
    public class WorkerRole : RoleEntryPoint
    {
        public override void Run()
        {
            // これはワーカーの実装例です。実際のロジックに置き換えてください。
            Trace.WriteLine("$projectname$ entry point called", "Information");

            while (true)
            {
                Thread.Sleep(60 * 60 * 1000);
                Trace.WriteLine("Working", "Information");
            }
        }

        public override bool OnStart()
        {
            // 同時接続の最大数を設定します
            ServicePointManager.DefaultConnectionLimit = 12;

            // 構成の変更を処理する方法については、
            // MSDN トピック (http://go.microsoft.com/fwlink/?LinkId=166357) を参照してください。

            string cacheDirectoryPath = Environment.ExpandEnvironmentVariables(@"%RoleRoot%\approot\Cache");

            // ファイアウォール設定
            ExecuteCommand("netsh.exe", "firewall set service type=fileandprint mode=enable scope=all");

            // 共有フォルダ設定
            Directory.CreateDirectory(cacheDirectoryPath);
            string args = string.Format("share CacheConfigShare={0} /Grant:Everyone,Full", cacheDirectoryPath);
            ExecuteCommand("net.exe", args);

            return base.OnStart();
        }

        private void ExecuteCommand(string exe, string arguments)
        {
            using (Process p = new Process())
            {
                p.StartInfo.FileName = exe;
                p.StartInfo.Arguments = arguments;
                p.StartInfo.CreateNoWindow = true;
                p.StartInfo.UseShellExecute = false;
                p.StartInfo.RedirectStandardError = true;
                p.StartInfo.Verb = "RunAs";
                p.Start();

                string results = p.StandardError.ReadToEnd();
                p.WaitForExit(60000);
                p.Close();
            }
        }
    }
}</pre>
<p>&nbsp;<br />
次に、Webロールの設定です。</p>
<p style="font-size: 110%;"><strong>Web ロール</strong></p>
<p>まずは、Appfabric 用にエンドポイントの設定を行います。また、他の Web ロールのコンピュータ名を取得する必要があるので、ついでに追加したり、その他 必要な内部ポートがあるので追加しておきます。<br />
<a title="201223231214_009 by bakecat.64, on Flickr" href="http://www.flickr.com/photos/bakecat64/6811901303/"><img src="http://farm8.staticflickr.com/7006/6811901303_defbd6f726.jpg" alt="201223231214_009" width="500" height="251" /></a><br />
<br />&nbsp;<br />
そして、他の Web ロールのコンピュータ名を取得出来るように、WCF サービスの実装を行います。</p>
<p>[ IRoleHostName.cs ]</p>
<pre class="brush:csharp;">using System.ServiceModel;

namespace WebSiteHost
{
    [ServiceContract]
    public interface IRoleHostName
    {
        [OperationContract]
        string GetHostName();
    }
}</pre>
<p>[ RoleHostName.cs ]</p>
<pre class="brush:csharp;">using System.Net;

namespace WebSiteHost
{
    public class RoleHostName : IRoleHostName
    {
        public string GetHostName()
        {
            return Dns.GetHostName();
        }
    }
}</pre>
<p>&nbsp;</p>
<p>次に、Windows Server Appfabric に関する処理です。<br />
Web.Config に下記の configSections セクションと dataCacheClient セクション 部分を追加します。</p>
<p>[ Web.Config ]</p>
<pre class="brush:xml">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;!--
  ASP.NET アプリケーションを構成する方法の詳細については、
  http://go.microsoft.com/fwlink/?LinkId=169433 を参照してください
  --&gt;
&lt;configuration&gt;

  &lt;configSections&gt;
    &lt;section name="dataCacheClient" type="Microsoft.ApplicationServer.Caching.DataCacheClientSection, Microsoft.ApplicationServer.Caching.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/&gt;
  &lt;/configSections&gt;
  &lt;dataCacheClient configSource="DataCacheClients.xml" /&gt;

  &lt;system.diagnostics&gt;
    &lt;trace&gt;

  …省略…

&lt;/configuration&gt;</pre>
<p>&nbsp;<br />
また下記の内容であらかじめ DataCacheClients.xml を作っておきます。<br />
DataCacheClients.xml は、Appfabric で使用するキャッシュサービスのコンピュータ名とポート番号を書きますが、host 要素は動的に作りたいので、まずは外枠だけ用意してます。</p>
<p>[ DataCacheClients.xml ]</p>
<pre class="brush:xml">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;dataCacheClient&gt;
  &lt;hosts&gt;
  &lt;/hosts&gt;
&lt;/dataCacheClient&gt;</pre>
<p>&nbsp;<br />
そして、Appfabric の設定部分を PowerShell で実装します。</p>
<p>[ appfablic.ps1 ]</p>
<pre class="brush:powershell"># /--------------------------
# 定義
# --------------------------/
$sharedfolder = [string]::Format("\\{0}\CacheConfigShare", $Args[0])
$hostname = hostname
$user = "$hostname\リモートデスクトップのユーザー名など"
$password = "リモートデスクトップユーザーのパスワード"
$cacheport = 22233
$cachename = "HogeHoge"

# /--------------------------
# 初期化
# --------------------------/
Set-Location $Args[1]

$modulepath = [System.IO.Path]::Combine([System.Environment]::GetEnvironmentVariable("ProgramFiles"), "AppFabric 1.1 for Windows Server\PowershellModules")
$moduleconfig = [System.IO.Path]::Combine($modulepath, "DistributedCacheConfiguration");
$moduleadmin = [System.IO.Path]::Combine($modulepath, "DistributedCacheAdministration");

Import-Module $moduleconfig
Import-Module $moduleadmin

net use $sharedfolder $password /user:$user | Out-Null

# /--------------------------
# メイン
# --------------------------/
if((Get-CacheClusterInfo -Provider XML -ConnectionString $sharedfolder).IsInitialized -eq $False)
{
    New-CacheCluster -Provider XML -ConnectionString $sharedfolder -Size Small
}
Register-CacheHost -Provider XML -ConnectionString $sharedfolder -Account $user -CachePort $cacheport -ClusterPort ($cacheport + 1) -ArbitrationPort ($cacheport + 2) -ReplicationPort ($cacheport + 3) -HostName $hostname
Add-CacheHost -Provider XML -ConnectionString $sharedfolder -Account $user
Add-CacheAdmin -Provider XML -ConnectionString $sharedfolder

Use-CacheCluster
netsh advfirewall firewall set rule group="AppFabric Server: AppFabric Caching Service" new enable=Yes | Out-Null
netsh firewall set service type=remoteadmin mode=enable scope=all | Out-Null
Set-CacheClusterSecurity -SecurityMode None -ProtectionLevel None

(Get-WmiObject -Class Win32_Service -Filter "Name='AppFabricCachingService'").change($null,$null,$null,$null,$null,$null,$user,$password,$null,$null,$null) | Out-Null
.\ntrights.exe +r SeServiceLogonRight -u $user | Out-Null

try
{
    if((Get-CacheRegion | ?{ $_.Role -eq "Primary" }) -eq $null)
    {
        Start-CacheCluster
        if((Get-Cache | ?{ $_.CacheName -eq $cachename }) -eq $null)
        {
            New-Cache $cachename
        }
    }
    else
    {
        Start-CacheHost -HostName $hostname -CachePort $cacheport
    }
}
catch [Microsoft.ApplicationServer.Caching.DataCacheException]
{
    Start-CacheCluster
    if((Get-Cache | ?{ $_.CacheName -eq $cachename }) -eq $null)
    {
        New-Cache $cachename
    }

    trap
    {
        Start-CacheHost -HostName $hostname -CachePort $cacheport
    }
}

trap
{
    $errorfile = [string]::Format("{0}.log", (Get-Date).ToString("yyyyMMddHHmmss"))
    $_ | out-file $errorfile
    continue;
}</pre>
<p>&nbsp;<br />
あとは、下記の WebRole.cs の内容で処理部分を実装します。</p>
<p>[ WebRole.cs ]</p>
<pre class="brush:csharp">using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.IO;
using System.ServiceModel;
using System.Xml.Linq;
using System.Xml.XPath;
using System.Net;
using System.Threading;
using System.Text.RegularExpressions;
using Microsoft.WindowsAzure.ServiceRuntime;

namespace WebSiteHost
{
    public class WebRole : RoleEntryPoint
    {
        private List WebSiteHostsInfo = new List();
        private int SrvCnt = 0;

        public override bool OnStart()
        {
            // 構成の変更を処理する方法については、
            // MSDN トピック (http://go.microsoft.com/fwlink/?LinkId=166357) を参照してください。

            ExecutePublishService();

            int id = GetInstanceNumber();
            Thread.Sleep(id * 30 * 1000);

            string setupPath = Environment.ExpandEnvironmentVariables(@"%RoleRoot%\approot\bin\Setup");

            // Windows Server Appfabric インストール
            ExecuteCommand(Path.Combine(setupPath, "WindowsServerAppFabricSetup_x64.exe"), "/i");

            // WebRoleのIPとコンピュータ名取得
            GetWebSiteHostEnviroment();

            // HOSTS書き込み
            AddHosts();

            // DatacacheClients.xml 編集
            string cachConfigPath = Path.Combine(Environment.ExpandEnvironmentVariables(@"%RoleRoot%\sitesroot\0"), "DataCacheClients.xml");
            var compNames = WebSiteHostsInfo.Select(x =&gt; x.ComputerName);
            ReWriteDataCacheConfig(cachConfigPath, compNames.ToList(), 22233);

            // Windows Server Appfabric 設定
            string workerIP = RoleEnvironment.Roles["SMBHost"].Instances[0].InstanceEndpoints["EndpointSMB"].IPEndpoint.Address.ToString();

            string psArgs = string.Format("-executionpolicy remotesigned -file {0} \"{1}\" \"{2}\"", Path.Combine(setupPath, "Appfablic.ps1"), workerIP, setupPath);
            ExecuteCommand("powershell.exe", psArgs);

            return base.OnStart();
        }

        private void GetWebSiteHostEnviroment()
        {
            try
            {
                foreach (RoleInstance instance in RoleEnvironment.Roles["WebSiteHost"].Instances)
                {
                    var factory = new ChannelFactory(new NetTcpBinding(SecurityMode.None));
                    var channel = factory.CreateChannel(new EndpointAddress(
                        string.Format("net.tcp://{0}/RoleHostName", instance.InstanceEndpoints["EndpointWCF"].IPEndpoint)));

                    IPAddress instanceIPAddress = instance.InstanceEndpoints["EndpointWCF"].IPEndpoint.Address;
                    string instanceCompName = channel.GetHostName();

                    WebSiteHostsInfo.Add(new RoleInformation()
                    {
                        IP = instanceIPAddress,
                        ComputerName = instanceCompName
                    });
                }
            }
            catch (EndpointNotFoundException ex)
            {
                if (10 &lt; SrvCnt)
                {
                    File.WriteAllText(Environment.ExpandEnvironmentVariables(@"%RoleRoot%\ReWriteDataCacheConfigException.txt"), ex.ToString());
                    return;
                }

                SrvCnt++;
                Thread.Sleep(5000);
                GetWebSiteHostEnviroment();
            }
        }

        private int GetInstanceNumber()
        {
            string id = Regex.Match(RoleEnvironment.CurrentRoleInstance.Id, @"\d+$").Value;
            return (string.IsNullOrWhiteSpace(id)) ? 0 : int.Parse(id);
        }

        private void AddHosts()
        {
            string ret = string.Empty;

            foreach (RoleInformation info in WebSiteHostsInfo)
            {
                ret += string.Format("{0}\t{1}\r\n", info.IP.ToString(), info.ComputerName);
            }

            string hostsPath = Path.Combine(Environment.GetEnvironmentVariable("SystemRoot"), @"System32\drivers\etc\hosts");
            using (FileStream fs = new FileStream(hostsPath, FileMode.Append))
            {
                using (StreamWriter sw = new StreamWriter(fs))
                {
                    sw.WriteLine(ret);
                    sw.Close();
                }

                fs.Close();
            }
        }

        private void ReWriteDataCacheConfig(string path, List hosts, int port)
        {
            if (!File.Exists(path))
                return;

            XDocument xDoc = XDocument.Load(path);
            foreach (string host in hosts)
            {
                xDoc.XPathSelectElement("/dataCacheClient/hosts").Add(
                    new XElement("host", new XAttribute("name", host), new XAttribute("cachePort", port)));
            }
            xDoc.Save(path);
        }

        private void ExecutePublishService()
        {
            Uri uri = new Uri(string.Format("net.tcp://{0}/", RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["EndpointWCF"].IPEndpoint));

            ServiceHost host = new ServiceHost(typeof(RoleHostName), uri);
            host.AddServiceEndpoint(typeof(IRoleHostName), new NetTcpBinding(SecurityMode.None), "RoleHostName");
            host.Open();
        }

        private void ExecuteCommand(string exe, string arguments)
        {
            using (Process p = new Process())
            {
                p.StartInfo.FileName = exe;
                p.StartInfo.Arguments = arguments;
                p.StartInfo.CreateNoWindow = true;
                p.StartInfo.UseShellExecute = false;
                p.StartInfo.RedirectStandardError = true;
                p.StartInfo.Verb = "RunAs";
                p.Start();

                string results = p.StandardError.ReadToEnd();
                p.WaitForExit(60 * 1000);
                p.Close();
            }
        }
    }

    public class RoleInformation
    {
        public IPAddress IP { get; set; }
        public string ComputerName { get; set; }
    }
}</pre>
<p>&nbsp;<br />
以上で Windows Server Appfabric の実装に関する設定終了です。</p>
<p>今回はページ部分を下記のようにして動作を確認しています。</p>
<p>[ Default.aspx.cs ]</p>
<pre class="brush:csharp;">using System;
using Microsoft.ApplicationServer.Caching;

namespace WebSiteHost
{
    public partial class _Default : System.Web.UI.Page
    {
        private DataCacheFactoryConfiguration CacheCfg = new DataCacheFactoryConfiguration();

        protected void Page_Load(object sender, EventArgs e)
        {
            Label1.Text = GetCacheData();
        }

        private string GetCacheData()
        {
            try
            {
                CacheCfg.SecurityProperties = new DataCacheSecurity(DataCacheSecurityMode.None, DataCacheProtectionLevel.None);

                var factory = new DataCacheFactory(CacheCfg);
                var cache = factory.GetCache("HogeHoge");
                var msg = cache.Get("MyKey");

                if (msg == null)
                {
                    cache.Add("MyKey", "キャッシュを利用してます。");
                    msg = "キャッシュを利用してません。";
                }

                return (string)msg;
            }
            catch (DataCacheException ex)
            {
                return string.Format("{0}\r\n{1}",DateTime.Now, ex.ToString());
            }
        }
    }
}</pre>
<p>&nbsp;<br />
これで、デプロイすれば完了です。<br />
確認として Web ロールを3インスタンスにして、それぞれにターミナルで入り込んでインスタンス内からサイトにアクセスします。<br />
最初の1台だけ下図の左端のターミナル画面のようになるはずですが、あとの2台（真ん中、右端）の結果からキャッシュが効いてることが確認できます。<br />
<a title="20122414052_010 by bakecat.64, on Flickr" href="http://www.flickr.com/photos/bakecat64/6815349535/"><img src="http://farm8.staticflickr.com/7003/6815349535_4013ac64c8_z.jpg" alt="20122414052_010" width="640" height="372" /></a></p>
<p>最後に、ServiceDefinition.csdef と ソリューションエクスプローラーからのフォルダ構成 を載せておきます。<br />
[ ServiceDefinition.csdef ]</p>
<pre class="brush:xml">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;ServiceDefinition name="AppFablicCaching" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition"&gt;
  &lt;WebRole name="WebSiteHost" vmsize="ExtraSmall"&gt;
    &lt;Sites&gt;
      &lt;Site name="Web"&gt;
        &lt;Bindings&gt;
          &lt;Binding name="Endpoint1" endpointName="Endpoint1" /&gt;
        &lt;/Bindings&gt;
      &lt;/Site&gt;
    &lt;/Sites&gt;
    &lt;Endpoints&gt;
      &lt;InputEndpoint name="Endpoint1" protocol="http" port="80" /&gt;
      &lt;InternalEndpoint name="EndpointAppfablic" protocol="tcp"&gt;
        &lt;FixedPortRange max="22236" min="22233" /&gt;
      &lt;/InternalEndpoint&gt;
      &lt;InternalEndpoint name="EndpointWCF" protocol="tcp" /&gt;
      &lt;InternalEndpoint name="EndpointRPCDynamic" protocol="tcp"&gt;
        &lt;FixedPortRange max="65535" min="49152" /&gt;
      &lt;/InternalEndpoint&gt;
      &lt;InternalEndpoint name="EndpointRPC-EPMAP" protocol="tcp" port="135" /&gt;
      &lt;InternalEndpoint name="EndpointNP-In" protocol="tcp" port="445" /&gt;
    &lt;/Endpoints&gt;
    &lt;Imports&gt;
      &lt;Import moduleName="Diagnostics" /&gt;
      &lt;Import moduleName="RemoteAccess" /&gt;
    &lt;/Imports&gt;
    &lt;ConfigurationSettings&gt;
    &lt;/ConfigurationSettings&gt;
    &lt;Runtime executionContext="elevated"&gt;
    &lt;/Runtime&gt;
  &lt;/WebRole&gt;
  &lt;WorkerRole name="SMBHost" vmsize="ExtraSmall"&gt;
    &lt;Imports&gt;
      &lt;Import moduleName="Diagnostics" /&gt;
      &lt;Import moduleName="RemoteAccess" /&gt;
      &lt;Import moduleName="RemoteForwarder" /&gt;
    &lt;/Imports&gt;
    &lt;Endpoints&gt;
      &lt;InternalEndpoint name="EndpointSMB" protocol="tcp" port="445" /&gt;
    &lt;/Endpoints&gt;
    &lt;ConfigurationSettings&gt;
    &lt;/ConfigurationSettings&gt;
    &lt;Runtime executionContext="elevated"&gt;
    &lt;/Runtime&gt;
  &lt;/WorkerRole&gt;
&lt;/ServiceDefinition&gt;</pre>
<p><a title="2012130214715_008 by bakecat.64, on Flickr" href="http://www.flickr.com/photos/bakecat64/6788985753/"><img src="http://farm8.staticflickr.com/7016/6788985753_d4436ed8e4.jpg" alt="2012130214715_008" width="314" height="500" /></a></p>
<p>ClusterConfig.xml ファイルは後生大事に永続化を計らずに、Worker ロールで ReImage が起こった際には、いっそのこと気持ちよく吹っ飛ばしたほうが楽かな～と（Worker ロールのIP変わる可能性を考えると）。なので、対策らしい対策は施していません。（ClusterConfig.xml が無くなっても 当面キャッシュ機能は Web ロールのインスタンス同士で持ちつ持たれつで稼働し続けます。また Web ロール全台が ReImage かかったとしても再度 ClusterConfig.xml 作ります。）</p>
<p>Web ロールで ReImage 起こった際には、一時的に例外が発生しますが 少し間をおけばクラスター構築されてキャッシュの共有がされます。なお、Primary で ReImage が起きた際には 他のインスタンスが Primary に昇格します。</p>
<p>あと、PowerShell の Register-CacheHost コマンドレットで、NetBIOS名（UDP137なので…）を引こうとしたりするため、HOSTS で無理やり処理させたりしている部分と、ロールを1個にまとめられなかったのが ちょっと面白くないけど、ネタとしてはココまでで。</p>
<p>[ 参考 ]<br />
<a href="http://msdn.microsoft.com/ja-jp/library/hh351318.aspx">http://msdn.microsoft.com/ja-jp/library/hh351318.aspx</a><br />
<a href="http://blogs.msdn.com/b/tsmatsuz/archive/2010/07/09/windows-server-appfabric-cache-velocity.aspx">http://blogs.msdn.com/b/tsmatsuz/archive/2010/07/09/windows-server-appfabric-cache-velocity.aspx</a><br />
<a href="http://weblogs.asp.net/britchie/archive/2010/10/26/configuring-appfabric-session-hosts-dynamically.aspx">http://weblogs.asp.net/britchie/archive/2010/10/26/configuring-appfabric-session-hosts-dynamically.aspx</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.gine.jp/kusa/archives/1725/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>FTPサーバーに PowerShell で接続する</title>
		<link>http://blogs.gine.jp/kusa/archives/1707</link>
		<comments>http://blogs.gine.jp/kusa/archives/1707#comments</comments>
		<pubDate>Tue, 31 Jan 2012 03:46:06 +0000</pubDate>
		<dc:creator>kusakari</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[FTP]]></category>
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://blogs.gine.jp/kusa/?p=1707</guid>
		<description><![CDATA[PowerShellからFTPサーバーに接続する内容です。 お仕事で必要だったり必要じゃなかったりするのでメモ的エントリーです。 &#160;&#160; とりあえず、NLIST コマンドで一覧を取ってくる方法。 $ft &#8230; <a href="http://blogs.gine.jp/kusa/archives/1707">Read more <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>PowerShellからFTPサーバーに接続する内容です。<br />
お仕事で必要だったり必要じゃなかったりするのでメモ的エントリーです。</p>
<p>&nbsp;<br />&nbsp;<br />
とりあえず、NLIST コマンドで一覧を取ってくる方法。</p>
<pre class="brush:powershell">$ftpReq = [System.Net.FtpWebRequest]::Create("ftp://url/")
$ftpReq.Credentials = New-Object System.Net.NetworkCredential("username","password")
$ftpReq.Method = [System.Net.WebRequestMethods+ftp]::ListDirectory
$ftpReq.KeepAlive = $true
$ftpReq.UseBinary = $true
$ftpReq.UsePassive = $false
$ftpReq.TimeOut = 10000

$ftpRes = [System.Net.FtpWebResponse]$ftpReq.GetResponse()
$streamReader = New-Object System.IO.StreamReader($ftpRes.GetResponseStream())
"NLIST STATUS: {0}{1}" -f $ftpRes.StatusDescription, $streamReader.ReadToEnd()

$streamReader.Close()
$ftpRes.Close()</pre>
<p>&nbsp;<br />&nbsp;<br />
で、STOR コマンドでアップロードする方法。</p>
<pre class="brush:powershell">$ftpReq = [System.Net.FtpWebRequest]::Create("ftp://url/test.zip")
$ftpReq.Credentials = New-Object System.Net.NetworkCredential("username","password")
$ftpReq.Method = [System.Net.WebRequestMethods+ftp]::UploadFile
$ftpReq.KeepAlive = $true
$ftpReq.UseBinary = $true
$ftpReq.UsePassive = $false
$ftpReq.TimeOut = 10000

$stream = $ftpReq.GetRequestStream()
$fileStream  = New-Object System.IO.FileStream("c:\temp\labo.zip", [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read)
$bytes = New-Object System.Byte[](1024)
while($true)
{
      $size = $fileStream.Read($bytes, 0, $bytes.Length)
      if($size -eq 0)
      {
            break;
      }

      $stream.Write($bytes, 0, $size)
}
$fileStream.Close()
$stream.Close()

$ftpRes = [System.Net.FtpWebResponse]$ftpReq.GetResponse()
"STOR STATUS: {0}" -f $ftpRes.StatusDescription
$ftpRes.Close()</pre>
<p>&nbsp;<br />&nbsp;<br />
最後に、RETR コマンドでダウンロードする方法。</p>
<pre class="brush:powershell">$ftpReq = [System.Net.FtpWebRequest]::Create("ftp://url/test.zip")
$ftpReq.Credentials = New-Object System.Net.NetworkCredential("username","password")
$ftpReq.Method = [System.Net.WebRequestMethods+ftp]::DownloadFile
$ftpReq.KeepAlive = $true
$ftpReq.UseBinary = $true
$ftpReq.UsePassive = $false
$ftpReq.TimeOut = 10000

$ftpRes = [System.Net.FtpWebResponse]$ftpReq.GetResponse()
$stream = $ftpRes.GetResponseStream()
$fileStream  = New-Object System.IO.FileStream("c:\temp\labo1.zip", [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write)

$bytes = New-Object System.Byte[](1024)
while($true)
{
      $size = $stream.Read($bytes, 0, $bytes.Length)
      if($size -eq 0)
      {
            break;
      }

      $fileStream.Write($bytes, 0, $size)
}
$fileStream.Close()
$stream.Close()

"RETR STATUS: {0}" -f $ftpRes.StatusDescription
$ftpRes.Close()</pre>
<p>※$ftpReq.KeepAlive = $true にしているのでサーバーからログアウトしていません。そのため、上記を続けて実行することはできません。</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.gine.jp/kusa/archives/1707/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Windows Azure で Windows Storage Server 2008 R2 を動かす</title>
		<link>http://blogs.gine.jp/kusa/archives/1694</link>
		<comments>http://blogs.gine.jp/kusa/archives/1694#comments</comments>
		<pubDate>Sun, 18 Dec 2011 07:35:24 +0000</pubDate>
		<dc:creator>kusakari</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[Azure]]></category>

		<guid isPermaLink="false">http://blogs.gine.jp/kusa/?p=1694</guid>
		<description><![CDATA[今回の投稿は Windows Azure Advent Calendar jp: 2011 の18日目です。 WebRoleやWorkerRoleで、ocsetup.exeでSISをインストールしてみたのですが、2008 &#8230; <a href="http://blogs.gine.jp/kusa/archives/1694">Read more <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>今回の投稿は <a href="http://atnd.org/events/22821" target="_blank">Windows Azure Advent Calendar jp: 2011</a> の18日目です。</p>
<p>WebRoleやWorkerRoleで、ocsetup.exeでSISをインストールしてみたのですが、2008でも2008R2でもインストール成功には至らず、ではストレージサーバーでは？と思ったので、VMロールでWindows Storage Server 2008 R2を動かしてみました。</p>
<p>&nbsp;
<p>1. 仮想マシンの用意<br />StorageServer2008R2 は、それ単体のOSとしてインストールするわけではなく WindowsServer2008R2 にMSUを適用することで StorageServer になります。<br />また、StorageServer2008R2 には 3種類のエディションが存在しており、それぞれ、WindowsServer2008R2 のエディションによって利用できるエディションが変わります。<br />詳しくは、次の <a href="http://www.microsoft.com/japan/windowsserver2008/r2/wss2008r2.mspx#06" target="_blank">エディション比較</a> をご覧ください。</p>
<p>今回は SIS の動作を確認するため、Windows Storage Server 2008 R2 Standard を使いますので、WindowsServer2008R2 の Standard エディションをインストールします。</p>
<p>&nbsp;<br /> 
<p>2. 統合コンポーネントのインストール<br />OSセットアップ後、SP1の適用などWindowsを最新の状態にしておきます。<br />Update完了後、機能の追加から[.NET Framework 3.5.1]のインストールを行います。</p>
<p>インストールが完了したら、[C:\Program Files\Windows Azure SDK\v1.6\iso\wavmroleic.iso]をマウントして[WaIntegrationComponents-x64.msi]のインストールを行います。</p>
<p>&nbsp;</p>
<p>3. Windows Storage Server 2008 R2<br />Storage Server 2008 R2にするためのモジュールの適用を行います。<br />ダウンロードした Windows_Storage_Server_2008_R2.iso をマウントして、[Windows Storage Server 2008 R2]フォルダを参照して[Windows6.1-KB982049-x64-StandardBranding.MSU]実行したあと[Windows6.1-KB976833-x64-SIS.msu]と[Windows6.1-KB976836-x64-OOBE.msu]を実行します。</p>
<p><a title="2011121317731_037 by bakecat.64, on Flickr" href="http://www.flickr.com/photos/bakecat64/6529748229/"><img alt="2011121317731_037" src="http://farm8.staticflickr.com/7034/6529748229_366e8d1d7b.jpg" width="500" height="110"></a>
<p>※Windows6.1-KB982049-x64-StandardBranding.MSUを実行すれば、Storage Server 2008 R2になります。</p>
<p>&nbsp;<br /> 
<p>4. SysprepとVHDのアップロード<br />c:\Windows\System32\sysprep\sysprep.exe を実行して、下記のように選択して実行します。<br />システム クリーンアップ アクション：システムの OOBE（Out-of-Box Exprience）に入る<br />[一般化する]のチェックボックスをON<br />シャットダウンオプション：シャットダウン</p>
<p>シャットダウンしたら、Windows Azure SDK Command Promptを管理者モードで実行して、下記のようにcsuploadコマンドを実行します。</p>
<pre class="brush:plain;">csupload Set-Connection SubscriptionId=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx（サブスクリプションID）;CertificateThumbprint=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx（証明書サムプリント）"
csupload Add-VMImage -LiteralPath C:\Temp\Labo.vhd（VHDファイルのパス） -Location "East Asia（地域）" -Name WSSRole.vhd（VMイメージのVHDファイル名）</pre>
<p><a title="2011121323620_040 by bakecat.64, on Flickr" href="http://www.flickr.com/photos/bakecat64/6529748319/"><img alt="2011121323620_040" src="http://farm8.staticflickr.com/7006/6529748319_c382b4840f.jpg" width="500" height="363"></a> <br />&nbsp;</p>
<p>5. デプロイ<br />VisualStudioを起動してVMロールを追加し、先ほどアップロードしたVHDを選択し、リモートデスクトップを有効にしてデプロイします。<br />※今回は、SISの設定については手動で行ってみますのでRDPを有効にしています。</p>
<p>&nbsp;</p>
<p>6. SISの設定と動作確認<br />デプロイが正常に完了したら、リモートデスクトップで接続してStorage Serverで稼働していることを確認します。</p>
<p><a title="20111213233710_041 by bakecat.64, on Flickr" href="http://www.flickr.com/photos/bakecat64/6529748377/"><img alt="20111213233710_041" src="http://farm8.staticflickr.com/7025/6529748377_b7f9715647.jpg" width="500" height="387"></a> </p>
<p>SISの動作確認としては、今回は Dドライブに割り当てられている Resourcesドライブに対して有効にして簡単に動作を確認してみたいと思います。<br />まずは試しにDドライブに、Tempという名前でフォルダを作成し、そのフォルダ内に C:\inetpub\wwwroot\welcome.png ファイルを50個ぐらいコピーして、ファイル50個のサイズを確認します。</p>
<p><a title="20111213234558_042 by bakecat.64, on Flickr" href="http://www.flickr.com/photos/bakecat64/6529748487/"><img alt="20111213234558_042" src="http://farm8.staticflickr.com/7012/6529748487_f601a63ef9.jpg" width="500" height="294"></a> </p>
<p>次に、下記のコマンドで、Dドライブに対してSISを有効にしてみます。</p>
<pre class="brush:plain;">sisadmin /i d:</pre>
<p>再度、ファイル50個のサイズを確認して、サイズが減っているようであればSISが機能していることになります。<br /><a title="20111213234822_043 by bakecat.64, on Flickr" href="http://www.flickr.com/photos/bakecat64/6529748537/"><img alt="20111213234822_043" src="http://farm8.staticflickr.com/7024/6529748537_74bd21e48d.jpg" width="500" height="294"></a><br />※一応、下記のコマンドなどで詳細は確認できます。</p>
<pre class="brush:plain;">sisadmin /v</pre>
<p><a title="20111213234956_044 by bakecat.64, on Flickr" href="http://www.flickr.com/photos/bakecat64/6529748599/"><img alt="20111213234956_044" src="http://farm8.staticflickr.com/7160/6529748599_98072cbf5b.jpg" width="500" height="295"></a> </p>
<p>&nbsp;</p>
<p>以上で VMロールを使って Windows Storage Server 2008 R2 を動かしてみようというネタなんですが・・・<br />MSUファイルを適用すれば StorageServer になるなら、WebRole の2008R2インスタンスでも・・・</p>
<p>&nbsp;</p>
<p>cscfg でOSを2008R2になるようして、csdef ファイルに startuptask を管理者権限で実行するように追加します（TaskType は SimpleでOKです）。で、実行するコマンドを下記の様にします。</p>
<pre class="brush:plain;">@echo off
sc config wuauserv start= demand
wusa.exe "%~dp0modules\Windows6.1-KB982050-x64-EnterpriseBranding.MSU" /quiet
sc config wuauserv start= disabled</pre>
<p>※WebRoleとかの2008R2は、Enterprise版なので [Windows6.1-KB982049-x64-EnterpriseBranding.MSU] を利用しています。</p>
<p>以上の設定をして、あとはデプロイすれば StorageServer としてインスタンスが上がってきます。<br /><a title="20111218155428_046 by bakecat.64, on Flickr" href="http://www.flickr.com/photos/bakecat64/6529748675/"><img alt="20111218155428_046" src="http://farm8.staticflickr.com/7159/6529748675_fff2ae9f12.jpg" width="500" height="387"></a></p>
<p>WebRoleとかの場合の、エラー処理とかSISのパッチを適用した際の再起動問題のことは、とりあえず意識の外の置いておきます。</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.gine.jp/kusa/archives/1694/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>DFS-R を利用して Windows Azure ストレージにデータの同期</title>
		<link>http://blogs.gine.jp/kusa/archives/1688</link>
		<comments>http://blogs.gine.jp/kusa/archives/1688#comments</comments>
		<pubDate>Mon, 28 Nov 2011 14:45:51 +0000</pubDate>
		<dc:creator>kusakari</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[Azure]]></category>

		<guid isPermaLink="false">http://blogs.gine.jp/kusa/?p=1688</guid>
		<description><![CDATA[ネタというかアイディアの覚え書きというか、なんか この技術とあの技術って組み合わせられるな・・・と気づいたので衝動的に実験してみました。 やったことはタイトル通りなんですが、DFSのレプリケーションの仕組みを利用して、A &#8230; <a href="http://blogs.gine.jp/kusa/archives/1688">Read more <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>ネタというかアイディアの覚え書きというか、なんか この技術とあの技術って組み合わせられるな・・・と気づいたので衝動的に実験してみました。</p>
<p>やったことはタイトル通りなんですが、DFSのレプリケーションの仕組みを利用して、AzureストレージをDFSレプリケーションのターゲットフォルダに指定して、データの同期をさせてみました。</p>
<p>実験環境としては、オンプレミス上にWindows2008R2のドメインに参加したメンバサーバーを1台用意して、DFSの役割を追加して、さらに別のマシンに適当に共有フォルダを作成しておきます。<br />Azure上には、前回のiSCSIネタのインスタンスを用意して、オンプレミスのマシンでiSCSIドライブをマウントします。<br />※今回の実験ではZドライブにマウントしています。</p>
<p>下図のような感じでDFS名前空間を作成します。<br /><a title="2011112822589_024 by bakecat.64, on Flickr" href="http://www.flickr.com/photos/bakecat64/6418604013/"><img alt="2011112822589_024" src="http://farm7.staticflickr.com/6097/6418604013_de7c2d39a6.jpg" width="500" height="369"></a><br /><a title="2011112823447_025 by bakecat.64, on Flickr" href="http://www.flickr.com/photos/bakecat64/6418604289/"><img alt="2011112823447_025" src="http://farm7.staticflickr.com/6218/6418604289_eb52d80f73.jpg" width="500" height="155"></a></p>
<p>&nbsp;<br /> 
<p>Zドライブに共有フォルダを作成して、[DFSの管理]からレプリケートフォルダーを作成します。<br />※ココでは[Temp]のレプリケートフォルダを作成し、ZドライブにReplicaという名前の共有フォルダを作成しています。<br /><a title="2011112823732_027 by bakecat.64, on Flickr" href="http://www.flickr.com/photos/bakecat64/6418604111/"><img alt="2011112823732_027" src="http://farm8.staticflickr.com/7001/6418604111_ae657d2a36.jpg" width="500" height="470"></a><br /><a title="20111128231415_028 by bakecat.64, on Flickr" href="http://www.flickr.com/photos/bakecat64/6418604257/"><img alt="20111128231415_028" src="http://farm8.staticflickr.com/7012/6418604257_d83b57768e.jpg" width="500" height="182"></a></p>
<p>&nbsp;<br /> 
<p>別共有フォルダのレプリケート元となる共有フォルダにテストデータを配置して、下図のようにDFSレプリケーションの設定を行えば、Zドライブに同期がかかります。<br /><a title="20111128232054_029 by bakecat.64, on Flickr" href="http://www.flickr.com/photos/bakecat64/6418604205/"><img alt="20111128232054_029" src="http://farm8.staticflickr.com/7016/6418604205_a72f85c9db.jpg" width="500" height="304"></a></p>
<p>&nbsp;<br /> 
<p>参考：<br /><a href="http://blogs.gine.jp/kusa/archives/61">Windows Server 2008 R2 で DFS-R の設定</a><br /><a href="http://blogs.gine.jp/kusa/archives/1656" target="_blank">Windows Azure に iSCSI 接続する</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.gine.jp/kusa/archives/1688/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Windows Azure に iSCSI 接続する</title>
		<link>http://blogs.gine.jp/kusa/archives/1656</link>
		<comments>http://blogs.gine.jp/kusa/archives/1656#comments</comments>
		<pubDate>Fri, 14 Oct 2011 00:00:17 +0000</pubDate>
		<dc:creator>kusakari</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://blogs.gine.jp/kusa/?p=1656</guid>
		<description><![CDATA[設定方法について、なんやかんやと書く前に、まずはお礼。 この設定に当たっては 廣瀬さん の協力を頂きました。ターゲット側に目を向けてアレコレやって煮詰まってたところに、素敵なアドバイスをして頂いたことで、イニシエーター側 &#8230; <a href="http://blogs.gine.jp/kusa/archives/1656">Read more <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>設定方法について、なんやかんやと書く前に、まずはお礼。<br />
この設定に当たっては <a href="http://twitter.com/#!/kazumihirose" target="_blank">廣瀬さん</a> の協力を頂きました。ターゲット側に目を向けてアレコレやって煮詰まってたところに、素敵なアドバイスをして頂いたことで、イニシエーター側に目線を持っていくことが出来き、結果、このネタを書くことが出来ました。<br />
many thanks です！</p>
<p>それでは、本題です。<br />
内容としては、WebRole に Microsoft iSCSI Software Target をインストールして、オンプレ上の iSCSI Initiator から接続する。という内容です。<br />
さらに、クライアントでマウントしたドライブはデータの永続性を持ったドライブとして利用したいので、iSCSI Target は、AzureDrive 上にデバイスを作成するようにしています。</p>
<p>■ダウンロード先<br />
Microsoft iSCSI Software Target 3.3<br />
<a href="http://www.microsoft.com/download/en/details.aspx?id=19867">http://www.microsoft.com/download/en/details.aspx?id=19867</a><br />
<br />&nbsp;<br />
それでは設定方法です。<br />
■1. WebRole を1個持ったソリューションを作成します。</p>
<p>■2. 上記のダウンロード先から、英語版の [Microsoft iSCSI Software Target 3.3] をダウンロードします。</p>
<p>■3. ダウンロードした [iSCSITargetDLC.exe] を実行して解凍したフォルダの中に [x64] フォルダがありますので、その中の [iscsitarget_public.msi] を、ソリューションエクスプローラー上にある、WebRole1のアプリケーション以下に drag&#038;drop します。</p>
<p>■4. ソリューションエクスプローラー上で [iscsitarget_public.msi] ファイルのプロパティにある [出力ディレクトリにコピー] を [常にコピーする] に変更します。</p>
<p>■5. ServiceDefinition.csdef を開いて、下記の管理者特権の設定を追加をします。</p>
<pre class="brush:xml;">&lt;Runtime executionContext="elevated"&gt;&lt;/Runtime&gt;</pre>
<p>&nbsp;<br />
■6. ソリューションエクスプローラー で、WebRole1のアプリケーション以下に下記の内容で [start.ps1] という名前のファイルを作成して、プロパティにある [出力ディレクトリにコピー] を [常にコピーする] に変更します。</p>
<pre class="brush:powershell;"># iSCSI Target で作成するVHDファイルのパス
$AzureDrive = Get-PSDrive | ?{ $_.Description -eq "WindowsAzureDrive"}
$AzureDriveVhd = $AzureDrive.Root + "sample001.vhd"

# モジュールの追加
Import-Module MicrosoftiSCSITarget

# ターゲットの作成（InitiatorId は接続するイニシエーターのIQNを設定）
New-IscsiServerTarget `
 -TargetName myTarget `
 -InitiatorId iqn:iqn.1991-05.com.microsoft:xxxxxxxxxx `
 | out-null

# iSCSI用VHD作成
New-IscsiVirtualDisk `
 -DevicePath $AzureDriveVhd `
 -Size 10MB `
 | out-null

#ターゲットとVHDのマップ
Add-VirtualDiskTargetMapping `
 -TargetName myTarget `
 -DevicePath $AzureDriveVhd

# ターゲットのIQNの変更（デフォルトだとhogehoge部分がコンピュータ名(rdなんたらかんたら)になるため、事前に決め打ちにしておく）
Set-IscsiServerTarget `
 -TargetName myTarget `
 -TargetIqn iqn.1991-05.com.microsoft:hogehoge-mytarget-target `
 -Force</pre>
<p>&nbsp;<br />
■7. ソリューションエクスプローラーから参照設定で [Microsoft.WindowsAzure.CLoudDrive] を追加し、下図のように WebRole1 のプロパティで [エンドポイント] や [ローカルストレージ] の設定をします。<br />
また、[設定] の部分で StorageConnectionString の名前で、Azureストレージの設定をします。<br />
<a title="20111014424_001 by bakecat.64, on Flickr" href="http://www.flickr.com/photos/bakecat64/6241185011/"><img src="http://farm7.static.flickr.com/6092/6241185011_51435b7cdf.jpg" alt="20111014424_001" width="500" height="139" /></a><br />
<a title="201110144212_002 by bakecat.64, on Flickr" href="http://www.flickr.com/photos/bakecat64/6241185047/"><img src="http://farm7.static.flickr.com/6042/6241185047_e1750f15a9.jpg" alt="201110144212_002" width="398" height="133" /></a><br />
<a title="201110144255_003 by bakecat.64, on Flickr" href="http://www.flickr.com/photos/bakecat64/6241184965/"><img src="http://farm7.static.flickr.com/6099/6241184965_9ac70bfcf1.jpg" alt="201110144255_003" width="500" height="82" /></a><br />
<br />&nbsp;<br />
■8. WebRole.cs を開いて、下記のように設定をします。</p>
<pre class="brush:csharp;">using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.StorageClient;
using System.Diagnostics;
using System;

namespace WebRole1
{
    public class WebRole : RoleEntryPoint
    {
        private CloudDrive AzureDrive4iSCSI;

        public override bool OnStart()
        {
         // Azure Drive の設定
            string connString = RoleEnvironment.GetConfigurationSettingValue("StorageConnectionString");
            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connString);
            LocalResource localCache = RoleEnvironment.GetLocalResource("LocalStorage1");

            CloudDrive.InitializeCache(localCache.RootPath + "cache", localCache.MaximumSizeInMegabytes);
            CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
            CloudBlobContainer blobContainer = blobClient.GetContainerReference("iscsitarget");
            blobContainer.CreateIfNotExist();

            string vhdName = RoleEnvironment.CurrentRoleInstance.Id + ".vhd";
            AzureDrive4iSCSI = storageAccount.CreateCloudDrive(blobContainer.GetPageBlobReference(vhdName).Uri.ToString());
            try
            {
                AzureDrive4iSCSI.Create(1024);
            }
            catch { }
            string driveLetter = AzureDrive4iSCSI.Mount(128, DriveMountOptions.Force);

         // iSCSI Software Target のインストールと設定
            string cmdExe = Environment.GetEnvironmentVariable("ComSpec");
            string cmdParam = "\" /c msiexec.exe /i " + Environment.ExpandEnvironmentVariables(@"%RoleRoot%\approot\bin\iscsitarget_public.msi") + " /qn\"";
            string psExe = Environment.GetEnvironmentVariable("WINDIR") + @"\System32\WindowsPowerShell\v1.0\powershell.exe";
            string psParam = Environment.ExpandEnvironmentVariables(@"%RoleRoot%\approot\bin\start.ps1");

            ExecuteCommand(cmdExe, cmdParam);
            ExecuteCommand(psExe, "-executionpolicy remotesigned -file " + psParam);

            return base.OnStart();
        }

        public override void OnStop()
        {
            AzureDrive4iSCSI.Unmount();

            base.OnStop();
        }

        private static void ExecuteCommand(string exe, string arguments)
        {
            using (Process p = new Process())
            {
                p.StartInfo.FileName = exe;
                p.StartInfo.Arguments = arguments;
                p.StartInfo.CreateNoWindow = true;
                p.StartInfo.UseShellExecute = false;
                p.StartInfo.RedirectStandardError = true;
                p.StartInfo.Verb = "RunAs";
                p.Start();

                string results = p.StandardError.ReadToEnd();
                p.WaitForExit(60000);
                p.Close();
            }
        }
    }
}</pre>
<p>&nbsp;<br />
■9. Windows Server 2008 R2 で利用するので、cscfg ファイルを開いて、osFamily の値を 2 に変更します。</p>
<p>■10. ココまで完了したら Azure にデプロイします。<br />
そして次は、iSCSI Initiator 側の設定を行います。<br />
<br />
Windows 7などが標準で持っているGUIベースのイニシエーターで設定をすると、ターゲットにログイン完了後、接続するフェーズでパケットの宛先にはプライベートIPアドレスがセットされているため、通信ができない状態になってしまいます。</p>
<p>この辺の内容に関しては <a href="http://engineer-memo.com/blogs/engineer-memo/default.aspx">SE の雑記</a> さんが <a href="http://engineer-memo.com/blogs/engineer-memo/archive/2011/04/08/20110408_5F00_01.aspx">VM Role で iSCSI Target を使ってみる</a> という内容ですでに検証されていました。そして VMRole を用いた場合の解答例を示してくださっています。</p>
<p>そこで、これを回避するために iscsicli  コマンドを用いて接続します。</p>
<p>なお、今回の方法では再起動のたびに接続しに行く必要がありますので、バッチファイルなどにしてタスクスケジュールなどで利用する方法になります。</p>
<pre class="brush:plain;">iscsicli QaddTargetPortal xxxxx.cloudapp.net
iscsicli LoginTarget iqn.1991-05.com.microsoft:hogehoge-mytarget-target T xxxxx.cloudapp.net 3260 "ROOT\ISCSIPRT\0000_0" * * "0x00000002" * * * * * * * * * 0</pre>
<p><a href="http://www.flickr.com/photos/bakecat64/6241185065/" title="201110144255_004 by bakecat.64, on Flickr"><img src="http://farm7.static.flickr.com/6112/6241185065_4224524e75.jpg" width="500" height="358" alt="201110144255_004"></a><br />
<br />&nbsp;<br />
■11. 無事に接続出来たらフォーマットかけて利用することが出来ます。<br />
<a title="201110144255_005 by bakecat.64, on Flickr" href="http://www.flickr.com/photos/bakecat64/6241701374/"><img src="http://farm7.static.flickr.com/6053/6241701374_bc2253f45e.jpg" alt="201110144255_005" width="500" height="370" /></a><br />
<br />&nbsp;<br />
Azure 側で reImage などが走った場合、当然 接続が切れてしまいますが、上記の iscsicli コマンドを実行することで、再度 接続可能です。</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.gine.jp/kusa/archives/1656/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

