Azure Storage 複数コンテナをコピー

日本DC引っ越しにあたって、複数のコンテナに対して AzCopy いっぱい並べなくても済むようにPowerShell スクリプトを作って転送しています。コンテナのアクセス権も保持。

# ================================================================
# 設定
# ================================================================
# 転送元
$srcacct="転送元ストレージアカウント名"
$srckey="転送元キー"

# 転送先
$destacct="転送先ストレージアカウント名"
$destkey="転送先キー"

# 転送したくないコンテナ名
$nontransfercontainers = "automated-sql-export", "backups", "mydeployments", "vsdeploy", "wad-control-container", "wad-iis-logfiles"

# コマンドラインへのパス
$azure="C:\Program Files (x86)\Microsoft SDKs\Windows Azure\CLI\wbin\azure.cmd"
$azcopy="C:\Program Files (x86)\Microsoft SDKs\Windows Azure\AzCopy\AzCopy.exe"

# ================================================================
# 実行
# ================================================================
$srccontainersjsonstr = & $azure storage container list --json -a $srcacct -k $srckey
$srccontainers = "{ root: " + $srccontainersjsonstr + " }" | ConvertFrom-Json |  Select-Object -ExpandProperty root

$srccontainersjsonstr

$destcontainersjsonstr = & $azure storage container list --json -a $destacct -k $destkey
$destcontainerslist = "{ root: " + $destcontainersjsonstr + " }" | ConvertFrom-Json | Select-Object -ExpandProperty root | Select-Object -ExpandProperty name

foreach ($item in $srccontainers) {
  $targetcontainer = $item.name

  if ($nontransfercontainers.Contains($targetcontainer)) { continue }

  if ($null -ne $destcontainerslist -and $destcontainerslist.Contains($targetcontainer)) {
    # $targetcontainer + " --permission " + $item.publicAccessLevel
    # & $azure storage container set $targetcontainer -a $destacct -k $destkey -p $item.publicAccessLevel
  } else {
    & $azure storage container create $targetcontainer -a $destacct -k $destkey -p $item.publicAccessLevel
    # "CONTAINER is created : " + $targetcontainer
  }

  $srcurl  = "https://" + $srcacct + ".blob.core.windows.net/" + $targetcontainer
  $desturl = "https://" + $destacct + ".blob.core.windows.net/" + $targetcontainer
  # /S : 再帰的
  # /XO : 古いファイルは更新しない
  # /L : 実行しないでリストだけ
  "COPY " + $srcurl + " to " + $desturl
  & $azcopy $srcurl $desturl /Y /S /XO /SourceKey:$srcKey /DestKey:$destkey
}

コンテナ作成のあたりは PowerShell だけで出来る方がスマートなんだろうけど、調べた当初はストレージのキーだけで作る方法が分からなかった。サブスクリプションをまたぐような状況ではストレージアカウントだけで済む方が便利。

Yamaha RTX810 / RTX1200 / RTX3000 Windows AzureとのIPsec接続

静的ルーティング (Static Routing) の場合

静的ルーティングであれば、RTX公式ページの 「Windows AzureとのIPsec接続 設定例」 の設定例に従って記述すれば接続できます。

ここで問題なのは設定例中の以下の部分

ipsec ike remote id 1 172.16.0.1

図を見ると “Gateway Instance” と書いたネットワーク1番目になっています。2014年5月10日現在、日本語の AzurePortal では、「ゲートウェイサブネットの追加」により出来るネットワークです。
名称は 「ゲートウェイ 」になっています。

QS_20140510-190655

ipsec ike remote id の引数にするアドレスの末尾は 1 になります。Yamahaのページでは 172.16.0.1 になってますね。ポータル画面にある 使用可能なアドレス範囲で示されているアドレスではないところに注意。

手元の環境では RTX1200 および RTX3000 で接続することができました。

動的ルーティング (Dynamic Routing) の場合

結論としては現在接続できていません。
つながることに興味ある人は以降読んでも役に立たないです。

About VPN Devices for Virtual Network

Azure のサイト間接続には Dynamic routing もあります。そして、 Point-to-Site (P2S)を利用する場合には、 動的ルーティング しか選択できません

RTX使いにとって、動的ルーティングという名称は全く混乱させる名称です。ここで重要なのは IKEv2 であることです。
改めて Yamaha RTシリーズ IKEv2 の解説ページ を参照します。

IKEv1からIKEv2への移行

これまでIPsec(IKEv1)を運用されてきた場合は、既存の設定を流用しながらIKEv2へ移行することができます。主な違いは、ipsec ike remote name コマンドと ipsec ike local name コマンドの設定が共に必須になっている点と、今回新設する ipsec ike version コマンドで明示的にIKEv2の使用を宣言(以下参照)する必要があるという点です。

実際に設定してみるとまさにこの通りで接続できました。 

Windows AzureとのIPsec接続 設定例 の 【IPsec VPN設定】 部分を動的ルーティング向けに書き換えると以下のようになります。
ipsec ike local name / ipsec ike remote name の末尾に ipv4-addr を指定するのがポイント。その他ほとんどのパラメータは既定値でOK。

tunnel select 1
 ipsec tunnel 1
# IKEv2 の指定
  ipsec ike version 1 2
  ipsec sa policy 1 1 esp anti-replay-check=off
  ipsec ike keepalive log 1 off
# local name の指定 (local address, local id の指定は不要)
  ipsec ike local name 1 (自ルータのグローバルアドレス) ipv4-addr
  ipsec ike nat-traversal 1 on
  ipsec ike pre-shared-key 1 text (WindowsAzureで作成された共有キー)
# remote name の指定 (remote address, local id の指定は不要)
  ipsec ike remote name 1 (WindowsAzureのゲートウェイIPアドレス) ipv4-addr
 ip tunnel tcp mss limit 1350
 tunnel enable 1
ipsec auto refresh on

結果、RTX 側では tunnel インターフェースが有効になります。しかし Azure 側は有効になりません。
show ipsec sa gateway 1 detail でSAを確認してみる。

----------------------------------------------------
SA[58] Status: Establised  Duration: 27694s
Protocol: IKEv2
Local Host: (自ルータ側グローバルIP):37905
Remote Host: (Azure側グローバルIP):37905
Encryption Algorithm    : 3DES               PRF     : HMAC_SHA1
Authentication Algorithm: HMAC_SHA1_96       DH Group: MODP_1024
SPI: ** ** ** ** **  (confidential)   ** ** ** ** **
Key: ** ** ** ** **  (confidential)   ** ** ** ** **
----------------------------------------------------
SA[59] Status: Establised  Duration: 27694s
Direction: send
Protocol: ESP (Mode: tunnel)
Local ID : (自ルータ側グローバルIP) (IPv4_ADDR)
Remote ID: (Azure側グローバルIP) (IPv4_ADDR)
Encryption Algorithm    : AES256_CBC
Authentication Algorithm: HMAC_SHA1_96       ESN: DISABLE
Source Traffic Selector (type / protocol / port / address)
 IPv6-range / any / 0-65535     / ::-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
 IPv4-range / any / 0-65535     / 0.0.0.0-255.255.255.255
Destination Traffic Selector (type / protocol / port / address)
 IPv6-range / any / 0-65535     / ::-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
 IPv4-range / any / 0-65535     / 0.0.0.0-255.255.255.255
SPI: ** ** ** **
Key: ** ** ** ** **  (confidential)   ** ** ** ** **
----------------------------------------------------
SA[60] Status: Establised  Duration: 27694s
Direction: receive
Protocol: ESP (Mode: tunnel)
Local ID : (自ルータ側グローバルIP) (IPv4_ADDR)
Remote ID: (Azure側グローバルIP) (IPv4_ADDR)
Encryption Algorithm    : AES256_CBC
Authentication Algorithm: HMAC_SHA1_96       ESN: DISABLE
SPI: ** ** ** **
Key: ** ** ** ** **  (confidential)   ** ** ** ** **
----------------------------------------------------

Phase1はともかく繋がっている。(AES256のつもりだったのが 3DES になっていたけど)

Phase2 のSAは Traffic Selector が違う。 send 側 (RTXが作ったもの) はネットワーク全域。誰がこんな設定をしたかと調べると、Yamaha RTシリーズ IKEv2 の解説ページ の注意事項

メッセージ交換で使用されるTS (トラフィックセレクタ) ペイロードに関して、イニシエータとして動作する場合は、常にIPv4/IPv6すべてのアドレス、プロトコル番号、ポート番号を許可する内容を送信します。またレスポンダとして動作する場合は、常に提案されたTSペイロードを受理します。
なお、TSは既存のルーティング処理に影響を与えません。ルーティングの結果、トンネル経路へ向けられたパケットに対してTSは適用されます。

IKEv2 では相互接続性が向上するというのは未だ夢のようであった。 About VPN Devices for Virtual Network に Traffic Selector という単語は出てこないのだが、ここに至って
Dynamic routing とは Traffic Selector を意味していたようだ という事に気づくのだった。

送信側だけでよいので RTX810 に Traffic Selector の値設定する機能がつく日を期待したい。

.NET Framework 4.0 の環境 (4.5以上にしていない環境) で ASP.NEt を IE11 対応にする

IE10 の時にもあったが、ブラウザの識別に失敗して _doPostBack が動作しない現象が発生した。

すべての Windows Update を適用しても改善せず、 http://support.microsoft.com/kb/2836939 の適用により改善した。再起動を要求する場合がある。

Azure Cross-platform Command line tools を使いながらBlobまるごとコピーする PowerShell スクリプト

# ================================================================
# 設定
# ================================================================
# 転送元
$srcacct=”AzureStorageアカウント名”
$srckey=”アクセスキー”

# 転送先
$destacct=”AzureStorageアカウント名”
$destkey=”アクセスキー”

# 転送したくないコンテナ名を列挙しとく
$nontransfercontainers = “automated-sql-export”, “backups”, “mydeployments”, “vsdeploy”, “wad-control-container”, “wad-iis-logfiles”

# コマンドラインへのパス
$azure=”C:\Program Files (x86)\Microsoft SDKs\Windows Azure\CLI\wbin\azure.cmd”
$azcopy=”C:\Program Files (x86)\Microsoft SDKs\Windows Azure\AzCopy\AzCopy.exe”

# ================================================================
# 実行
# ================================================================
$srccontainersjsonstr = & $azure storage container list –json -a $srcacct -k $srckey
$srccontainers = “{ root: ” + $srccontainersjsonstr + ” }” | ConvertFrom-Json |  Select-Object -ExpandProperty root

$srccontainersjsonstr

$destcontainersjsonstr = & $azure storage container list –json -a $destacct -k $destkey
$destcontainerslist = “{ root: ” + $destcontainersjsonstr + ” }” | ConvertFrom-Json | Select-Object -ExpandProperty root | Select-Object -ExpandProperty name

foreach ($item in $srccontainers) {
  $targetcontainer = $item.name

  if ($nontransfercontainers.Contains($targetcontainer)) { continue }

  if ($destcontainerslist.Contains($targetcontainer)) {
    # $targetcontainer + ” –permission ” + $item.publicAccessLevel
    # & $azure storage container set $targetcontainer -a $destacct -k $destkey -p $item.publicAccessLevel
  } else {
    & $azure storage container create $targetcontainer -a $destacct -k $destkey -p $item.publicAccessLevel
    # “CONTAINER is created : ” + $targetcontainer
  }

  $srcurl  = “https://” + $srcacct + “.blob.core.windows.net/” + $targetcontainer
  $desturl = “https://” + $destacct + “.blob.core.windows.net/” + $targetcontainer
  # /S : 再帰的
  # /XO : 古いファイルは更新しない
  # /L : 実行しないでリストだけ
  “COPY ” + $srcurl + ” to ” + $desturl
  & $azcopy $srcurl $desturl /Y /V /S /XO /SourceKey:$srcKey /DestKey:$destkey
}

 


Windows Azure Cross-platform Command Line Tools を入れたら Blobへのアクセスキーだけでコンテナを作ることができるし、 Azcopy もついてきていた。
とはいえ、スクリプト全体は PowerShell を使って JSON 経由でいろいろやってみた。

azure storage container list コマンドの結果は [ … ] というJSONの配列形式だったのだが、 ConvertFrom-Json cmdlet は直接この形式を扱えないため、1オブジェクトになるよう文字列を結合してから Select-Object –ExpandProperty を使ってリストに戻してあげている。

さくらのVPSでカスタムOSインストールができないとき

http://milk1000cc.hatenablog.com/entry/2014/01/19/123915
より

Windowsの場合の対処方法

  1. 最新版の Java をインストールする http://java.com/

  2. コントロールパネルの右上窓で java を検索する。 Javaコントロール・パネルを開く

  3. 「セキュリティ」タブの「例外サイト・リスト」に https://secure.sakura.ad.jp/ を追加

QS_20140121-173830

最近の Windows だとコントロールパネルのカテゴリ表示が既定表示なのでたどりつきにくい。

英語版 Windows Server 2012 で CGI を動かす時の地域設定

QS_20140114-105914

.NET アプリケーションであれば Web.config で設定が完結するところを、exeによる実行を伴う場合システムロケールが Japanese 以外(標準の English United States)のままであると ShiftJIS のファイルを読み込む際に失敗してしまい動作しなかった。

システムロケールを Japanese に変更することで動作するようになった。

Windows Azure の仮想マシンの場合、従来と異なり提供されているギャラリーから作成すると Engrish(United States) であり、日本語環境にする作業をサボっていて動作しない状況になったためにこのような作業をした次第。

Microsoft Sync Framework 2.1 で Azure SQL を同期する

Azure DataSync(プレビュー) が Silverlight インターフェースを終了した後、大きなスキーマを持つデータベースに対するスキーマ同期に失敗するようになったらしい。( http://social.msdn.microsoft.com/Forums/windowsazure/en-US/9c679a74-9a7c-48e7-b4c9-95f6f7cfafd9/sql-azure-data-sync-refresh-schema-not-working?forum=ssdsgetstarted によると 800KB以上)
自分のところではテーブル数が200未満であるが、テーブル名・フィールド名に日本語を使っており内部的な表現でバイト数が膨れる可能性が高かった。

Azure DataSync の中身は Sync Framework がベースになっている。ということで自力で Microsoft Sync Framework 2.1 での実装することになった。

行数が小さなテーブルを同期するだけであれば、 http://msdn.microsoft.com/en-us/library/ff928700.aspx “Synchronizing SQL Server and SQL Express” で動作する。

行数が大きなテーブルになると問題が発生する。この問題に対処するヒントが http://msdn.microsoft.com/en-us/library/hh882017.aspx “Differences between Synchronization Classes for SQL Azure and SQL Server”

このうち CommandTimeout は、環境に依存するものではなく単純にデータ量に対応してタイムアウトの秒数を増やす必要があるというだけのもの。

Azure 特有の問題は ApplicationTransactionSize の値。Azure には throttling 機構がある。これは、Azure SQL が共有で使う構成のため、1ユーザーのアクセスが他のユーザーに重大な影響を及ぼさないような制約が入っている。そのうちの一つが1回のバッチに対する容量制限だ。
http://blogs.msdn.com/b/sync/archive/2010/09/24/how-to-sync-large-sql-server-databases-to-sql-azure.aspx “How to Sync Large SQL Server Databases to SQL Azure” によると、 50000 から始めよ、とのこと。しかし自分の環境では 50000 では失敗。

ApplicationTransactionSize = 16384 で成功した。

そしてこの値は、同期が一方向 (Download) の場合であっても、両側に適用しなければならない。当初データ供給側には不要かもしれないと ApplicationTransactionScope の設定をしなかったらエラーが発生した。

Bulk command BulkInsertCommand failed with the following exception. Rows will be retried during single apply. System.Data.SqlClient.SqlException (0x80131904): サーバーから結果を受信しているときに、トランスポート レベルのエラーが発生しました。 (provider: TCP Provider, error: 0 – 既存の接続はリモート ホストに強制的に切断されました。) —> System.ComponentModel.Win32Exception (0x80004005): 既存の接続はリモート ホストに強制的に切断されました。
   場所 System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   場所 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   場所 System.Data.SqlClient.TdsParserStateObject.ReadSniError(TdsParserStateObject stateObj, UInt32 error)
   場所 System.Data.SqlClient.TdsParserStateObject.ReadSniSyncOverAsync()
   場所 System.Data.SqlClient.TdsParserStateObject.TryReadNetworkPacket()
   場所 System.Data.SqlClient.TdsParserStateObject.TryPrepareBuffer()
   場所 System.Data.SqlClient.TdsParserStateObject.TryReadByte(Byte& value)
   場所 System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   場所 System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
   場所 System.Data.SqlClient.SqlDataReader.get_MetaData()

データベース側の master.sys.event_log を見ると、 event_type = throttling_long_transaction , description は以下のようなエラーになっていた。

The session has been terminated because it has acquired too many locks. Try reading or modifying fewer rows in a single transaction.

データ同期の速度は、おおざっぱには 100万レコード/30分 ぐらい。

Azure 仮想マシン上の SQL Serverのパフォーマンスを改善するためにTEMPDBを D ドライブに移動する

http://social.technet.microsoft.com/wiki/contents/articles/16088.azure-sql-iaastempdb-ja-jp.aspx

Azure仮想マシンでは、Dドライブが物理マシンのローカルストレージに割り当てられていてBLOBからやってくるドライブよりも高速ということになっている。SQL Server においては tempdb が暗黙的に多く利用されており、tempdb をD:ドライブに割り当てると効率的。

ただし、「一時ドライブ」との名称の通り、再起動時に消えることがある。具体的にはマシンのサイズを変更するとほとんどの場合空になる。
tempdb ファイルは自動的に再作成されるのだが、作成先のフォルダまでは自動作成してくれない。またD:\直下に置くという選択肢もあるが、この場合は SQL Server のサービスに管理者に近い高い権限を付与しなければならず、できれば避けたい。

今回はバッチファイルを作成し、タスクスケジューラを利用してOS起動時に実行するようにして対応した。(PowerShell に慣れねば…)

 

C:\mkdirtempdb.cmd の内容

  mkdir D:\MSSQL\MSSQL10_50.MSSQLSERVER\MSSQL\Data
  icacls D:\ /restore C:\icaclstempdb.txt
  sc start mssqlserver

C:\icaclstempdb.txt の内容

  MSSQL
  D:(A;;FA;;;BA)(A;OICIID;FA;;;BA)(A;OICIID;FA;;;SY)(A;OICIIOID;GA;;;CO)(A;OICIID;0x1200a9;;;BU)(A;CIID;LC;;;BU)(A;CIID;DC;;;BU)
  MSSQL\MSSQL10_50.MSSQLSERVER
  D:(A;;FA;;;BA)(A;OICIID;FA;;;BA)(A;OICIID;FA;;;SY)(A;OICIIOID;GA;;;CO)(A;OICIID;0x1200a9;;;BU)(A;CIID;LC;;;BU)(A;CIID;DC;;;BU)
  MSSQL\MSSQL10_50.MSSQLSERVER\MSSQL
  D:(A;;FA;;;BA)(A;OICIID;FA;;;BA)(A;OICIID;FA;;;SY)(A;OICIIOID;GA;;;CO)(A;OICIID;0x1200a9;;;BU)(A;CIID;LC;;;BU)(A;CIID;DC;;;BU)
  MSSQL\MSSQL10_50.MSSQLSERVER\MSSQL\Data
  D:(A;;FA;;;BA)(A;OICIID;FA;;;BA)(A;OICIID;FA;;;SY)(A;OICIIOID;GA;;;CO)(A;OICIID;0x1200a9;;;BU)(A;CIID;LC;;;BU)(A;CIID;DC;;;BU)

 

# Windows 8 の WordPressアプリから投稿してみた

SpecFlow

http://devadjust.exblog.jp/16622584/

無料アプリだったら多少のやんちゃは出来ても、お金をいただこうという段になるとそういうわけにもいかず、新しいテストフレームワークの勉強。
以前より興味を持っていた SpecFlow 少し記事が出てきて、やっと理解できた。ツールとしては、テストコードのテンプレを作ってくれるものだったのね。

とはいえ BDD ビヘイビア駆動 というプロセスの方がもっと重要。特にTDD テスト駆動の場合、何もない状況で「じゃあどういうテスト作るの?」という状況には確かに自分も陥って進めなくなりがちだった。

仕様に対して「シナリオを書け」だったら自然だ。近い将来 Visio で書いた図をユーザーと共有しつつ、そのままテストコードのテンプレを作ってくれるというような感じになるのだろうか。(VisualStudio だけで完結する方が開発者的には嬉しいが)

jquery を 1.9.x に更新したら Microsoft jQuery Unobtrusive Ajax も更新する

http://stackoverflow.com/questions/14391867/unobtrusive-ajax-stopped-working-after-update-jquery-to-1-9-0/15539422#15539422

標準状態では NuGet パッケージ扱いになっていないので、jquery.unobtrusive-ajax.min.js, jquery.unobtrusive-ajax.js を削除してから NuGet 経由で Microsoft jQuery Unobtrusive Ajax をインストールする。

詳しく調査していないが、jquery.unobtrusive-ajax.min.js だと相変わらず失敗したため、現在 jquery.unobtrusive-ajax.js を利用している。ASP.NET MVC4 であれば Bundler 経由で圧縮する場合 min を利用せず、最適化してくれるので、 Bundler 使いましょうということで。