例外処理 [タスクが取り消されました。]

クラウドサービスに対して PowerShell で何かしらの処理を大量に実行しようとすると、ネットワークや一時的な高負荷、スロットリングなど、何かしらの要因で一定の割合で失敗することがあります。

このため PowerShell で処理を行う場合においては例外処理をきちんと書いておくことが重要です。

例えば、CSP顧客のAzureサブスクリプションの使用量を取得する Get-PartnerCustomerSubscriptionMeterUsage を実行すると、以下の様な [タスクが取り消されました。] というエラーが返ることがあります。

Continue reading

CSPのAzure明細をPowerShellで整形する

新年度になりましたね。私も業務の所掌範囲とか変わって色々と新しいことに取り組み始めようと思います。

早速、MicrosoftのCSP事業者向けに毎月発行される請求書の明細のCSVファイルをExcelで加工するということを業務マニュアル見ながらしたのですが、面倒くさい上にピボットで集計したところ何かおかしい。

主に以下の点がおかしいという結論に。

  1. 調整ファイルのCSVの中に2種類の情報が入っていて、途中でカラムが変わる
  2. 調整ファイルの合計額が請求書の額と微妙に一致しない

前者に関しては単に分割すれば良いだけですが、後者に関しては過去の請求書も含めて調べた結果、以下のロジックであることが分かりました。

  • 税抜利用額において、小数点以下が存在するレコードが有るが、実際それは利用されない。
  • 2019年の秋くらいまでは多くの小数点以下の値があったが、以降は1円未満の利用(つまり0円請求)の場合にのみ小数点以下が存在
  • 税抜利用額の各項目に対して消費税が計算され、それが切り捨て
  • 切り捨てされた税抜合計額+消費税合計額がCSP事業者への請求

明細書のCSVが請求書と合わないのは問題なので、補正した値を経理処理上作成しないといけないのですが、数十万レコードとか有るとExcelでやるのも一苦労なので、PowerShellでやっちゃうことにしました。

PowerShellのImportExcelモジュールを使うと、PowerShellからxlsxファイルをそのまま作れます。アウトプットが複数シート必要なExcelなので今回はこれを利用します。

自分用のスクリプトなので汚いですが…。

$inputcsv = ".\AzureBillingUsage.csv"
$outxlsx = ".\CSPAzureBill.xlsx"
$tempfile = $env:TMP + "\_" + (Get-Date -Format yyyyMMddHHmmss) + ".csv"

### CSP請求書を上部のSummaryと下部のDaily Usageの2つのCSVに分ける ###
$bills = Get-Content $inputcsv -Encoding UTF8
$lines = $bills.Count

# Daily Usageの前の行まで出力
for ($i=1;$i -lt $lines;$i++){
    if($bills[$i] -eq "Daily Usage"){
        break
    }
    if($bills[$i] -ne ""){
        $bills[$i] | Out-File $tempfile -append
    }
}
$usages = Import-csv $tempfile
Remove-Item $tempfile

# Daily Usageの次の行から出力
for ($i++;$i -lt $lines;$i++){
    if($bills[$i] -ne ""){
        $bills[$i] | Out-File $tempfile -append
    }
}

### [Summary]シートの作成 ###
# PretaxChargesに小数点以下が存在するが、請求書上は切り捨てた額の総額で計算されているので、
# それを考慮したPreTax、PostTaxを計算
foreach ($usage in $usages){
    $pre  = [Math]::Truncate($usage.PretaxCharges)
    $post = $pre + $usage.TaxAmount
    $usage | Add-Member PreTax  $pre -force
    $usage | Add-Member PostTax $post -force
}

$usages | Export-Excel -Path $outxlsx -WorksheetName Summary

### [Daily_Usage]シートの作成 ###
# Subscription ID毎にマージして、PostTaxとPreTaxの値を合計する
Import-csv $tempfile | Export-Excel -Path $outxlsx -WorksheetName Daily_Usage
$subs = $usages | group "SubscriptionId" | select `
  @{Name="DomainName";Expression={($_.group | select -first 1).DomainName}}, `
  @{Name="CustomerCompanyName";Expression={($_.group | select -first 1).CustomerCompanyName}}, `
  @{Name="CustomerId";Expression={($_.group | select -first 1).CustomerId}}, `
  @{Name="SubscriptionId";Expression={($_.group | select -first 1).SubscriptionId}}, `
  @{Name="TotalPostTax";Expression={($_.group | Measure-Object -sum "PostTax").sum}}, `
  @{Name="TotalPreTax";Expression={($_.group | Measure-Object -sum "PreTax").sum}} `

# 新規開通分に関して DomainName が空欄なケースがあり、その場合の対応。
# (事前に Install-Module -Name PartnerCenter -AllowClobber が必要)
if((($subs | ? {$_.DomainName -eq ""}) | measure).count -gt 0){
	Connect-PartnerCenter
	foreach ($sub in $subs){
		if($sub.DomainName -eq ""){
			$sub.DomainName = (Get-PartnerCustomer -CustomerId $sub.CustomerId).Domain
		}
	}
}

### [Subscriptions]シートの作成 ###
$subs | sort DomainName | Export-Excel -Path $outxlsx -WorksheetName Subscriptions -AutoSize -Show

### テンポラリファイル削除 ###
Remove-Item $tempfile
2020/05/07修正(2020年04月利用分の明細ファイルに対応)
・既定のファイル名を変更
・細かいフォーマット変更に対応
・文字コード変更

最初はPivotで作ろうかと思ったのですが、[小計の非表示]や[表として表示]が上手くいかなかったので、そのままPowerShellで整形させちゃいました。

PowerShellを利用してレポート用のCSVを作ってExcelで整形という業務って結構あるかと思いますが、Import-Excelモジュールを使うとその部分までコードで書けるようになるのでとても便利です。

皆さんも是非試してみて下さい。

Express Route従量制プランのススメ

Office 365やAzureとインターネットを経由せずに接続できる Express Route ですが、料金プランは無制限データプランを選ばれてますか? それとも従量制課金データプランですか?

私の知っているユーザーですと、9割以上が無制限データプランを選択されているように感じます。主な理由としては「従量制だと料金がいくら課金されるか分からないし、試算するにも実際にどれくらいデータ転送量が分からない」「毎月課金がぶれると予算措置をするのが大変」というケースがほとんどです。

ただ、敢えて私は個人的に従量制プランの方を強くお勧めさせて頂きます。理由は主に以下の3つからです。

Continue reading

Terraform Bootcampに参加しました

Azure Infrastructure as Code 隊 Terraform Bootcampに参加してきました。

(当日の資料はこちら

会場は渋谷のヒカリエの8階にあるAzure Antenna、こんな格好いいフロアの奥の方にあります。スケジュールが提示されているので見てみると、何と、通年でここのスペースを借りているようです。(成果が出るかどうかで続くかどうかが決まるそうなので、是非これからも色々と活用していきたいと思います)
  

4名掛けのテーブルが2つ。こんな感じの場所でMicrosoftの真壁さんのハンズオンという、何とも贅沢な内容でした。

さて、ここから本題。

私自身はTerraformはマルチクラウド対応のInfrastructure as Codeのツールとして、回りで使っている人がいるので、「概要くらいは知っているけど使った事は無い」という感じでした。自分的にもなかなかこういったハンズオンとか無いと触るきっかけがないので、今回のハンズオンは正に渡りに船という感じでしたので、案内を見た瞬間に申込みをさせて頂きました。

ハンズオン受講前はTerraformに対する印象として「便利そうだけど、本当に商用で本格的に使っていって大丈夫なのだろうか…」という漠然とした不安を頂いておりましたが、受講後の感想は…

絶対来る、間違いない。
AzureのIaaSのエンジニアとしては習得必須の技術。

まあ、理由はあの真壁さんが言っているのだから…という一言に尽きるのですが、少しだけ言うなら以下の理由により、今後Azure管理のデファクトになっていくだろうな、と感じました。

  • マルチクラウド環境実現できるOpen Sourceだが、AWSとAzureはかなり動きが活発
  • Cloud Shellを立ち上げるだけで認証が済んだ状態でTerraformが使える
  • HashiCorpの日本法人もできて、Microsoftとも協業を発表している
  • ARMからTerraformリソースプロバイダ経由でAzure外のリソースをいじれるなど連携している

ちなみに、「ファイルの分割規則」「ARMテンプレートとの使い分け」「認証方式は?」とか、色々選択肢がある中でどれを選択すれば良いのかという疑問に関しては、ほとんどがスライド中で述べられていました。

真壁さん自身も、日本語のまとまった情報が殆ど無く、この資料を作成していく中で自分の中でも色々と整理することができたというコメントが有ったのですが、本当にTerraformはまとまったドキュメントが少ないので、当日のスライドはとても有意義な内容でした。

CSPパートナーがユーザーのAzureテナントにPowerShellで接続する

CSPパートナーがテナントを新規作成してAzureサブスクリプションを払い出した場合、CSPはユーザーテナントに対する代理管理者の権限を与えられます。この権限により、CSPはユーザーテナントの全体管理者として各種作業を代行することができます。

パートナーポータルからAzureポータルやOffice 365ポータルにも接続することができますが、PowerShellからも接続ができます。

通常アカウントと同じように、Login-AzureRmAccountでログインした後、Select-AzureRmSubscriptionにTenantIDとSubscriptionIDを指定しただけだと、Your Azure credentials have not been set up or have expired, please run Login-AzureRmAccount to set up your Azure Credentials.とエラーが表示されてしまいます。

よくよく見ると、Select-AzureRmSubscriptionの結果のContextにSubscriptionIDは入っていますが、SubscriptionNameが入っていないですね。正しく接続先の情報が渡せていないことが分かります。ここは、

Get-AzureRmSubscription -TenantId $TenantID -SubscriptionId $SubscriptionID | Set-AzureRmContext

としてあげれば、正しく接続することができるようになります。