割と普通なブログ

Microsoft Azure や ASP.NET、Java EE 系の話題を記載します

WindowsAzureToolkitForEclipseWithJava / StarterKit / CSPackAntTask を修正する

Microsoft Azure のクラウドサービス向けの Eclipse Plugin として Windows Azure Toolkit For Eclipse With Java があるのはご存知だと思う(未だに Windows Azure なのは置いといて)。こちらを利用して Eclipse 上からリモートデスクトップ、セッションアフィニティ、デプロイするロース数の設定等が可能だ。

ずいぶん進化が進んだもので、JBoss AS, Tomcat, Jetty はもちろん WebSphere も対応したそうだが、The Azure Toolkit for Eclipse now Includes WebSphere Liberty and Application InsightsIBM 社の WebSphere にも対応したらしいが、試してみたところうまく動かなかったので自身でプラグインをリコンパイルして確認をしてみた。ノウハウを死蔵してもしかたないので、今回は Windows Azure Toolkit For Eclipse With Java のリコンパイルの TIPS を紹介する。

修正箇所/内容

今回私が修正した個所は WindowsAzureToolkitForEclipseWithJava / StarterKit / CSPackAntTask であり、Eclipse プロジェクト内に .cspack.jar という隠しファイル名で格納されている個所だ。ソースコードを確認したところpackage.xml 設定ファイルから *.cspkg ファイルを作成する処理を担っている様だ。
こちらに対して「*.cspkg を作成する際の引数をログとして出力する処理」を追加する。

まずは Github から以下の定番コマンドでソースコードを取得する。

>git clone https://github.com/MSOpenTech/WindowsAzureToolkitForEclipseWithJava.git

上記に CSPackAntTask が含まれているので、Eclipse の既存プロジェクトのインポートから WindowsAzureToolkitForEclipseWithJava\StarterKit\CSPackAntTask を選択する。

ソースコードをインポート後、ビルドが通らないがどうやら org.apache.ant と com.microsoft.azure が足りないようなので、以下の pom.xml をダミーで作成して mvn eclipse:eclipse で依存 jar を取得する*1

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.microsoft.azure</groupId>
	<version>0.7.0</version>
	<artifactId>azure-cspack-anttask</artifactId>
	<packaging>jar</packaging>

	<dependencies>
		<dependency>
			<groupId>org.apache.ant</groupId>
			<artifactId>ant</artifactId>
			<version>1.8.2</version>
		</dependency>
		<dependency>
			<groupId>com.microsoft.azure</groupId>
			<artifactId>azure-storage</artifactId>
			<version>2.0.0</version>
		</dependency>
	</dependencies>
</project>

次に *.cspack ファイル作成時のコマンド引数をログとして出力する処理を追加するため com.microsoftopentechnologies.windowsazure.tools.build.WindowsAzurePackage.java に以下の様に処理を追加する。ソースコードを見ればわかるが、中身に cspack.exe を利用している様だ。

	public void execute() throws BuildException {
		// <中略>

		// Run cspack.exe
		this.log("Starting package generation...");
		try {
			if (getSdkDir() != null) {
				// Get cspack.exe cmd-line
				List<String> csPackCmdLine = this.createCSPackCommandLine();

				//追加処理ここから
 				for (int i = 1; i < csPackCmdLine.size(); i++) {
					this.log("arg" + i + ": " + csPackCmdLine.get(i));
				}
				//追加処理ここまで

				this.runCommandLine(csPackCmdLine);
			} else {
				throw new IllegalArgumentException(
						"Azure SDK not found, cannot build non-CTP package");
			}
		} catch (Exception e) {
			reportBuildError(e);
		}

修正後、Ant を利用して備え付けの build.xml をたたくことで Eclipse プロジェクト内の jar フォルダに .cspack.jar が作成される。この時点での Eclipse プロジェクトの Package Explorer は以下のようになる。

最後に、CSPackAntTask\jar\.cspack.jar フォルダを Azure Eclipse プロジェクト内に含まれる .cspack.jar に上書きしてクラウドサービス上へのデプロイを試すと以下の様に追加処理のログが出力されている*2

Buildfile: D:\opt\workspace\HelloAzure\package.xml

checkResetScript:

resetEmulator:

waitForReset:

createwapackage:
       [mkdir] Created dir: D:\opt\workspace\HelloAzure\deploy
      [delete] Deleting directory D:\opt\workspace\HelloAzure\deploy.old
[windowsazurepackage] Verified attributes.
[windowsazurepackage] Role "WorkerRole1": Verifying the approot "D:\opt\workspace\HelloAzure\WorkerRole1\approot"
[windowsazurepackage] Role "WorkerRole1": Importing components...
[windowsazurepackage] 	Imported as 'jdk1.8.0_25' from "C:\Program Files\Java\jdk1.8.0_25"
[windowsazurepackage] 	Imported as 'jboss-as-7.1.1.Final.zip' from "D:\opt\jboss\jboss-as-7.1.1.Final"
[windowsazurepackage] Role "WorkerRole1": Finished importing components
[windowsazurepackage] Role "WorkerRole1": Generating component deployment script...
[windowsazurepackage] Role "WorkerRole1": Created internal startup script
[windowsazurepackage] Starting package generation...
[windowsazurepackage] arg1: D:\opt\workspace\HelloAzure\ServiceDefinition.csdef
[windowsazurepackage] arg2: /role:WorkerRole1;D:\opt\workspace\HelloAzure\WorkerRole1\approot
[windowsazurepackage] arg3: /rolePropertiesFile:WorkerRole1;D:\opt\workspace\HelloAzure\.rolePropertiesOS3
[windowsazurepackage] arg4: /out:D:\opt\workspace\HelloAzure\deploy\WindowsAzurePackage.cspkg
[windowsazurepackage] Executing '[C:\Program Files\Microsoft SDKs\Azure\.NET SDK\v2.5\bin\cspack.exe, D:\opt\workspace\HelloAzure\ServiceDefinition.csdef, /role:WorkerRole1;D:\opt\workspace\HelloAzure\WorkerRole1\approot, /rolePropertiesFile:WorkerRole1;D:\opt\workspace\HelloAzure\.rolePropertiesOS3, /out:D:\opt\workspace\HelloAzure\deploy\WindowsAzurePackage.cspkg]'...
[windowsazurepackage] Process started
[windowsazurepackage] Microsoft(R) Azure(TM) Packaging Tool version 2.5.0.0
[windowsazurepackage] for Microsoft(R) .NET Framework 4.0
[windowsazurepackage] Copyright c Microsoft Corporation. All rights reserved.
[windowsazurepackage] D:\opt\workspace\HelloAzure\ServiceDefinition.csdef: Warning  CloudServices040 : The 'schemaVersion' attribute is unspecified. Please set the attribute to avoid this warning.

このように必要な場合はソースを修正して動作を確認することがご理解いただけたと思う。

*1:ここの pom.xml は公開してほしいところ

*2: Executing 行の ... 部分が気になったので処理を追加したが、特に見切れてたのはなさそう

Microsoft Azure の Premium Storage を利用してみた

Azure: Premium Storage, RemoteApp, SQL Database Update, Live Media Streaming, Search and More の記事で2014年12月に発表された Premium Storage だが、漸く利用可能になったのでさっそく検証してみた。
Premium Storage を利用することにより「仮想マシンの IOPS がイマチイなんだよねぇ…」というケースの解として提案可能になるが、2015年2月15日現在はプレビュー期間中であり日本リージョンでは利用できない(West US, East US 2, West Europe で利用可能)点に注意が必要だ。

最初に今回のまとめ

Premium Storage: High-Performance Storage for Azure Virtual Machine Workloads に詳しい記載があるが、注意が必要な点は以下になる。

  • 2015年2月15日現在、プレビュー期間中であり日本リージョンでは利用できない(West US, East US 2, West Europe で利用可能
  • PowerShell コマンドと portal.azure.com 側で作成可能(※注 manage.windowsazure.com 側ポータルでは作成できない
  • 作成するディスクサイズによって IOPS 上限が異なる(※注 5000 IOPS がほしければ 512GB より大きなディスクを作成する必要がある
  • Premium Storage を利用できるインスタンスサイズは STANDARD_DS シリーズのみ(※注 manage.windowsazure.com 側ポータルでは作成できない
  • STANDARD_DS シリーズのサイズにより IOPS 上限が異なる(※注 STANDARD_DS1 だと 3200 IOPS 上限になってしまう

DS シリーズのインスタンスサイズによる IOPS 制限は以下になる。お金をケチって STANDARD_DS1 にすると、Premium Storage の旨味をそこまで引き出せなくなることが分かる。

VM Size CPU cores Max. IOPS Max. Disk Bandwidth
STANDARD_DS1 1 3,200 32 MB per second
STANDARD_DS2 2 6,400 64 MB per second
STANDARD_DS3 4 12,800 128 MB per second
STANDARD_DS4 8 25,600 256 MB per second
STANDARD_DS11 2 6,400 64 MB per second
STANDARD_DS12 4 12,800 128 MB per second
STANDARD_DS13 8 25,600 256 MB per second
STANDARD_DS14 16 50,000 512 MB per second

更に、Premium Storage を利用するディスクサイズによっては 500 IOPS 程度に抑えられる場合がある点も注意。公式ドキュメントのサンプルが 128GB なので、うっかりすると 500 IOPS 程度になる。。。。

Premium Storage Disk Type P10 P20 P30
Disk size 128 GB 512 GB 1024 GB (1 TB)
IOPS per disk 500 2300 5000
Throughput per disk 100 MB per second * 150 MB per second * 200 MB per second *

インスタンスサイズ、ディスクサイズによる制限に注意すれば Premium Storage を活用できる(はず)。次から実際に Premium Storage を利用してみる。

まずは簡単に Premium Storage を使ってみる - STANDARD_DS2 & P10

Premium Storage を利用するためには専用のストレージアカウントを作成する必要がある。以下の様に Type に Premium_LRS と指定する。

# Create Premium Storage
New-AzureStorageAccount -StorageAccountName "<accout name>" -Location "West US" -Type "Premium_LRS"

更に現在 Premium Storage を利用できるインスタンスは STANDARD_DS シリーズのみとなる(つまり、現在は G シリーズのインスタンスと併用できない)。以下の様に InstanceSize に DS シリーズであることを指定して仮想マシンを作成する(まずは STANDARD_DS2 で作成した)。

# Create Instance using Premium Storage 
$image = Get-AzureVMImage | Where-Object {$_.label -like “Windows Server 2012 R2*”} | Sort-Object -Descending PublishedDate | Select-Object -Index 0
$storageAccount = "daisamipremiumaccount"
$adminName = "<username>"
$adminPassword = "<password>"
$vmName ="<vmname>"
$location = "West US"
$vmSize ="Standard_DS2"
$OSDiskPath = "https://" + $storageAccount + ".blob.core.windows.net/vhds/" + $vmName + "_OS_PIO.vhd"
$vm = New-AzureVMConfig -Name $vmName -ImageName $image.ImageName -InstanceSize $vmSize -MediaLocation $OSDiskPath
Add-AzureProvisioningConfig -Windows -VM $vm -AdminUsername $adminName -Password $adminPassword
New-AzureVM -ServiceName $vmName -VMs $VM -Location $location

更に、ディスクをアタッチしてみる。まずは以下の様に 128GB のディスクとしてアタッチしてみた。

# Attach Premium Storage to VM Instance
$vm = Get-AzureVM -ServiceName $vmName -Name $vmName
$LunNo = 1
$path = "http://" + $storageAccount + ".blob.core.windows.net/vhds/" + "myDataDisk_" + $LunNo + "_PIO.vhd"
$label = "Disk " + $LunNo
Add-AzureDataDisk -CreateNew -MediaLocation $path -DiskSizeInGB 128 -DiskLabel $label -LUN $LunNo -HostCaching ReadOnly -VM $vm | Update-AzureVm

こちらに対する CrystalDiskMark の実行結果は以下になった。ご覧のとおり、ディスクサイズが小さいと 500 IOPS 制限に引っかかっている。

-----------------------------------------------------------------------
CrystalDiskMark 3.0.3 x64 (C) 2007-2013 hiyohiyo
                           Crystal Dew World : http://crystalmark.info/
-----------------------------------------------------------------------
* MB/s = 1,000,000 byte/s [SATA/300 = 300,000,000 byte/s]

           Sequential Read :    66.587 MB/s
          Sequential Write :    39.150 MB/s
         Random Read 512KB :    67.051 MB/s
        Random Write 512KB :    34.970 MB/s
    Random Read 4KB (QD=1) :     2.097 MB/s [   511.9 IOPS]
   Random Write 4KB (QD=1) :     1.664 MB/s [   406.2 IOPS]
   Random Read 4KB (QD=32) :     2.089 MB/s [   510.1 IOPS]
  Random Write 4KB (QD=32) :     2.089 MB/s [   510.1 IOPS]

  Test : 100 MB [F: 0.1% (0.1/128.0 GB)] (x5)
  Date : 2015/02/14 5:14:31
    OS : Windows Server 2012 R2 Datacenter (Full installation) [6.3 Build 9600] (x64)
    afasdfadfadsfa

STANDARD_DS2 & P30 で Premium Storage を使ってみる

ディスクサイズ P10 の制限に引っかかったことが分かったので、次は 1023 GB のディスクを作成してみた。

# Attach Premium Storage to VM Instance
$vm = Get-AzureVM -ServiceName $vmName -Name $vmName
$LunNo = 2
$path = "http://" + $storageAccount + ".blob.core.windows.net/vhds/" + "myDataDisk_" + $LunNo + "_PIO.vhd"
$label = "Disk " + $LunNo
Add-AzureDataDisk -CreateNew -MediaLocation $path -DiskSizeInGB 1023 -DiskLabel $label -LUN $LunNo -HostCaching ReadOnly -VM $vm | Update-AzureVm

結果は以下の通り、5000 IOPS 程度出ている。

-----------------------------------------------------------------------
CrystalDiskMark 3.0.3 x64 (C) 2007-2013 hiyohiyo
                           Crystal Dew World : http://crystalmark.info/
-----------------------------------------------------------------------
* MB/s = 1,000,000 byte/s [SATA/300 = 300,000,000 byte/s]

           Sequential Read :    66.587 MB/s
          Sequential Write :    40.273 MB/s
         Random Read 512KB :    67.040 MB/s
        Random Write 512KB :    35.620 MB/s
    Random Read 4KB (QD=1) :    20.947 MB/s [  5114.0 IOPS]
   Random Write 4KB (QD=1) :     1.670 MB/s [   407.7 IOPS]
   Random Read 4KB (QD=32) :    20.896 MB/s [  5101.6 IOPS]
  Random Write 4KB (QD=32) :    20.943 MB/s [  5113.1 IOPS]

  Test : 100 MB [G: 0.0% (0.2/1023.0 GB)] (x5)
  Date : 2015/02/14 5:57:24
    OS : Windows Server 2012 R2 Datacenter (Full installation) [6.3 Build 9600] (x64)

念のため 600GB のディスクサイズだとどうなるか確かめた。

# Attach Premium Storage to VM Instance
$vm = Get-AzureVM -ServiceName $vmName -Name $vmName
$LunNo = 3
$path = "http://" + $storageAccount + ".blob.core.windows.net/vhds/" + "myDataDisk_" + $LunNo + "_PIO.vhd"
$label = "Disk " + $LunNo
Add-AzureDataDisk -CreateNew -MediaLocation $path -DiskSizeInGB 600 -DiskLabel $label -LUN $LunNo -HostCaching ReadOnly -VM $vm | Update-AzureVM

こちらでも P30 の 5000 IOPS が出ている。

-----------------------------------------------------------------------
CrystalDiskMark 3.0.3 x64 (C) 2007-2013 hiyohiyo
                           Crystal Dew World : http://crystalmark.info/
-----------------------------------------------------------------------
* MB/s = 1,000,000 byte/s [SATA/300 = 300,000,000 byte/s]

           Sequential Read :    66.576 MB/s
          Sequential Write :    40.191 MB/s
         Random Read 512KB :    67.040 MB/s
        Random Write 512KB :    35.677 MB/s
    Random Read 4KB (QD=1) :    20.940 MB/s [  5112.3 IOPS]
   Random Write 4KB (QD=1) :     1.616 MB/s [   394.4 IOPS]
   Random Read 4KB (QD=32) :    20.893 MB/s [  5100.9 IOPS]
  Random Write 4KB (QD=32) :    20.892 MB/s [  5100.5 IOPS]

  Test : 100 MB [H: 0.0% (0.2/600.0 GB)] (x5)
  Date : 2015/02/14 6:57:53
    OS : Windows Server 2012 R2 Datacenter (Full installation) [6.3 Build 9600] (x64)
  

Storage Pool の利用

更に、Storage Pool を利用して Premium Storage のディスクを束ねて利用してみた。まずは STANDARD_DS2 のまま P30x2 での速度を確認した。8000 IOPS 以上出ているが、こちらは STANDARD_DS2 のインスタンスサイズによる IOPS 制限を受けている。

-----------------------------------------------------------------------
CrystalDiskMark 3.0.3 x64 (C) 2007-2013 hiyohiyo
                           Crystal Dew World : http://crystalmark.info/
-----------------------------------------------------------------------
* MB/s = 1,000,000 byte/s [SATA/300 = 300,000,000 byte/s]

           Sequential Read :    67.109 MB/s
          Sequential Write :    66.905 MB/s
         Random Read 512KB :    67.040 MB/s
        Random Write 512KB :    57.867 MB/s
    Random Read 4KB (QD=1) :    33.477 MB/s [  8173.0 IOPS]
   Random Write 4KB (QD=1) :     1.588 MB/s [   387.6 IOPS]
   Random Read 4KB (QD=32) :    33.525 MB/s [  8184.7 IOPS]
  Random Write 4KB (QD=32) :    33.420 MB/s [  8159.2 IOPS]

  Test : 100 MB [F: 0.0% (0.2/1197.9 GB)] (x5)
  Date : 2015/02/14 8:03:39
    OS : Windows Server 2012 R2 Datacenter (Full installation) [6.3 Build 9600] (x64)

以下のコマンドを利用して Standard_DS14 サイズに変更した。

# Standard_DS14 に変更
Get-AzureVM -ServiceName <service name> -Name <instance name> | Set-AzureVMSize -InstanceSize Standard_DS14 | Update-AzureVM

再度 IOPS を計測すると、今度は 10000 IOPS 以上出ており 5000 IOPSx2 を束ねた速度が出ていることが分かる。

-----------------------------------------------------------------------
CrystalDiskMark 3.0.3 x64 (C) 2007-2013 hiyohiyo
                           Crystal Dew World : http://crystalmark.info/
-----------------------------------------------------------------------
* MB/s = 1,000,000 byte/s [SATA/300 = 300,000,000 byte/s]

           Sequential Read :   408.735 MB/s
          Sequential Write :   106.377 MB/s
         Random Read 512KB :   408.468 MB/s
        Random Write 512KB :    56.950 MB/s
    Random Read 4KB (QD=1) :    40.708 MB/s [  9938.4 IOPS]
   Random Write 4KB (QD=1) :     1.469 MB/s [   358.6 IOPS]
   Random Read 4KB (QD=32) :    41.542 MB/s [ 10142.2 IOPS]
  Random Write 4KB (QD=32) :    41.382 MB/s [ 10103.0 IOPS]

  Test : 100 MB [F: 0.0% (0.2/1197.9 GB)] (x5)
  Date : 2015/02/15 1:45:38
    OS : Windows Server 2012 R2 Datacenter (Full installation) [6.3 Build 9600] (x64)

Storage Pool で束ねるディスクをさらに増やすことで IOPS は増すことができそうなので、他の方にもチャレンジしてほしい。

Microsoft Azure SDK for Java の Management Library を利用する

以前に Windows Azure SDK for .NET の Management Library を利用して Webサイト を動的に作成してみる を記載したが、今回は JavaSDK で Management API を操作する。

証明書の準備

まず、 C:\Program Files (x86)\Windows Kits\8.1\bin\x86 以下に存在する makecert コマンドを利用して cer ファイルを作成する。以下のコマンドを利用したので、ファイル名等は適宜変更してほしい。

>makecert -r -pe -a sha1 -n "CN=For Java SDK Certification" -ss my -len 2048 -sp "Microsoft Enhanced RSA and AES Cryptographic Provider" -sy 24 ManagementJavaSDK.cer

次に、作成した *.cer ファイルをダブルクリックし、証明書のエクスポートを実施して *.pfx ファイル(今回は ManagementJavaSDK.pfx )を作成する。
f:id:waritohutsu:20150208023553p:plain

更に、以下のコマンドにて Java で利用する keystore の *.jks ファイル(今回は ManagementJavaSDK.jks )を作成する。

>keytool -importkeystore -srckeystore c:\Temp\ManagementJavaSDK.pfx -dest keystore ManagementJavaSDK.jks -srcstoretype pkcs12 -deststoretype JKS

最後に、作成した *.cer ファイルを管理ポータルに以下の様にアップロードしておく(設定 - 管理証明書 以下に配置する点に注意)。
f:id:waritohutsu:20150208023602p:plain

Java アプリケーションの作成

こちらはシンプルに Maven プロジェクトを作成すれば対応可能だ。それぞれコードを記載する。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.mycompany</groupId>
	<artifactId>HelloAzureSDK</artifactId>
	<version>1.0-SNAPSHOT</version>
	<packaging>jar</packaging>
	<dependencies>
		<dependency>
			<groupId>com.microsoft.azure</groupId>
			<artifactId>azure-management-network</artifactId>
			<version>0.7.0</version>
		</dependency>
	</dependencies>
</project>
package com.mycompany;

import java.io.IOException;
import java.net.InetAddress;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;

import org.xml.sax.SAXException;

import com.microsoft.windowsazure.Configuration;
import com.microsoft.windowsazure.core.utils.KeyStoreType;
import com.microsoft.windowsazure.exception.ServiceException;
import com.microsoft.windowsazure.management.configuration.ManagementConfiguration;
import com.microsoft.windowsazure.management.network.NetworkManagementClient;
import com.microsoft.windowsazure.management.network.NetworkManagementService;
import com.microsoft.windowsazure.management.network.StaticIPOperations;

public class Main {

	public static void main(String args[]) throws IOException,
			URISyntaxException, ServiceException, ParserConfigurationException,
			SAXException {

		// キーストア等々もろもろ
		String subscriptionId = "120a0546-b790-4979-84da-09d671c0c376";
		String keyStorePath = "C:\\Temp\\ManagementJavaSDK.jks";
		String keyStorePassword = "P@ssw0rd00";

		Configuration config = ManagementConfiguration.configure(null,
				subscriptionId, //
				keyStorePath, //
				keyStorePassword, //
				KeyStoreType.fromString("jks"));
		NetworkManagementClient networkManagementClient = NetworkManagementService
				.create(config);

		// 仮想ネットワーク内の静的IP利用チェック
		StaticIPOperations so = networkManagementClient
				.getStaticIPsOperations();

		List<String> ipList = new ArrayList<String>();
		ipList.add("10.0.0.21"); // 利用可能な IP
		ipList.add("10.20.0.21"); // サブネット範囲外の IP

		String vnetName = "vnet-alwayson";

		for (String ip : ipList) {
			try {
				boolean isAvailable = so.check(vnetName,
						InetAddress.getByName(ip)).isAvailable();
				System.out.println(ip + " is " + isAvailable + " on "
						+ vnetName);
			} catch (ServiceException ex) {
				System.out.println(ip + " is false on " + vnetName);
				ex.printStackTrace();
			}
		}
	}
}

上記の実行結果は以下な感じ。

log4j:WARN No appenders could be found for logger (org.apache.http.client.protocol.RequestAddCookies).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
10.0.0.1 is false on vnet-alwayson
10.20.0.21 is false on vnet-alwayson
com.microsoft.windowsazure.exception.ServiceException: BadRequest: The address 10.20.0.21 is not contained in any of the subnets in the virtual network.
	at com.microsoft.windowsazure.exception.ServiceException.createFromXml(ServiceException.java:216)
	at com.microsoft.windowsazure.management.network.StaticIPOperationsImpl.check(StaticIPOperationsImpl.java:165)
	at com.mycompany.Main.main(Main.java:52)

Linux の仮想マシンを PowerShell で作成し、パスワードのみで SSH 接続する

普段、Linux仮想マシンは管理ポータルで作成 → Set-AzureStaticVNetIP で private ip 固定を行っている身にはちょっとハマったので情報共有したい。
Linux 仮想マシンSSH ログインを実行時、Putty クライアントで SSH ログインする際に「Disconnected: No supported authentication methods available」のエラーが発生した。
f:id:waritohutsu:20150207110833p:plain

実行した PowerShell スクリプトは以下だが、まぁ、ちゃんと鍵ファイルを置けということの様だ…。

# よしなに Linux イメージを選択し、Linux 仮想マシンの作成
$imageName = "0b11de9248dd4d87b18621318e037d37__RightImage-CentOS-6.6-x64-v13.5.5"
New-AzureVMConfig -Name "MyLinuxVM" -InstanceSize "Large" -Image $imageName |
Add-AzureProvisioningConfig -Linux -LinuxUser "azureuser" -Password "P@ssw0rd00" |
Set-AzureStaticVNetIP -IPAddress "192.168.0.10" |
Set-AzureSubnet -SubnetNames "Subnet-AP" |
New-AzureVM -ServiceName "powershelllinux" -VNetName "vnet-test"

が、テスト環境等で鍵ファイルをいちいち用意をするのが面倒という場合もあると思うので、今回はパスワードのみでSSH疎通が可能な Linux 仮想マシン作成の備忘録を記載する。

New-AzureVM で Linux インスタンスを作成し、パスワードをリセットする

まずは無難に仮想マシンインスタンスを作成し、その後にパスワードのリセットを実行する。

# ①よしなに Linux イメージを選択し、仮想マシンの作成
$imageName = "0b11de9248dd4d87b18621318e037d37__RightImage-CentOS-6.6-x64-v13.5.5"
New-AzureVMConfig -Name "MyLinuxVM" -InstanceSize "Large" -Image $imageName |
Add-AzureProvisioningConfig -Linux -LinuxUser "azureuser" -Password "P@ssw0rd00" |
Set-AzureStaticVNetIP -IPAddress "192.168.0.10" |
Set-AzureSubnet -SubnetNames "Subnet-AP" |
New-AzureVM -ServiceName "powershelllinux" -VNetName "vnet-test"

# ②パスワードのリセット
$vm = Get-AzureVM -ServiceName "powershelllinux"
$PrivateConfig = '{"reset_ssh": "True"}'
$ExtensionName = 'VMAccessForLinux'
$Publisher = 'Microsoft.OSTCExtensions'
$Version =  '1.1'
Set-AzureVMExtension -ExtensionName $ExtensionName -VM  $vm -Publisher $Publisher -Version $Version -PrivateConfiguration $PrivateConfig | Update-AzureVM

②の実行後、クラウドサービスの証明書を確認すると以下のような証明書が登録されている。こちらに対して SSH を実行するとログイン可能だが、リセットしてから1分程度の時間待つことに注意してほしい(ここで早まると設定に失敗したと勘違いし、インスタンスを再作成する羽目になる)。
f:id:waritohutsu:20150207110845p:plain

しかして、証明書がよくわかりませんな。。。。(汗

Azure Websites 上の Java アプリをリモートデバッグする

最近の投稿は Java 成分が多めになっているが、昨今の職種と役割のせいだと信じたいところ。さて、今回は Azure Websites 上の Java アプリにリモートデバッグを行う。当然ながらローカル環境と Azure Websites 上では少なからず差異があるため、今回紹介するリモートデバッグの機能は有用な人が多いはずだ。

こちらは既に Microsoft からソースコードを含めた利用方法が GitHub/Azure/azure-websites-java-remote-debugging に公開されている。今回はこちらを利用して実際に Azure Websites 上の Java アプリをリモートデバッグする。上記のソースコードを一読すると理解できると思うが、リモートデバッグ自体は既存の JDWP‐Java Debug Wire Protocol を利用しているので、こちらを理解している人であればとっかかりはあまり難しくないだろう。

リモートデバッグを試す

以下がリモートデバッグを試すまでの全体の流れになる。初回の疎通を通すまでは以下を参考にした方が楽にできるだろう。

  1. Websites を作成して「構成」タブから WebSocket を有効化する(おすすめはギャラリーからの Tomcat 7.x 作成
  2. Web.config に追記を行う
  3. 自作アプリの配置
  4. https://github.com/Azure/azure-websites-java-remote-debugging をダウンロードして DebugSession.bat の実行
  5. ブラウザから Azure Websites の自作アプリにアクセス

まず、新規に Websites を作成するが、こちらは 無料 モードでも 標準 モードでも問題ない。次に編集する Web.config があらかじめ配置されるギャラリーから「Apache Tomcat 7」がお勧めだ。
f:id:waritohutsu:20150125075205p:plain:w400
Websites 作成後、以下を参考に構成タブから WebSocket を有効化する。
f:id:waritohutsu:20150125075249p:plain

次に、kudu( https://<サイト名>.scm.azurewebsites.net/)にアクセスして D:\home\site\wwwroot\web.config を以下の様に編集する。デバッグオプションが追加していることが確認できるだろう。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <handlers>
            <add name="httpPlatformHandler" path="*" verb="*" 
                 modules="httpPlatformHandler" resourceType="Unspecified" />
        </handlers>
        <httpPlatform processPath="d:\home\site\wwwroot\bin\apache-tomcat-7.0.52\bin\startup.bat">
            <environmentVariables>
                <environmentVariable name="CATALINA_OPTS" value="-Dport.http=%HTTP_PLATFORM_PORT%" />
                <environmentVariable name="CATALINA_HOME" value="d:\home\site\wwwroot\bin\apache-tomcat-7.0.52" />                
                <environmentVariable name="JAVA_OPTS" value="-Djava.net.preferIPv4Stack=true -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=127.0.0.1:%HTTP_PLATFORM_DEBUG_PORT%" />
            </environmentVariables>
        </httpPlatform>
    </system.webServer>
</configuration>

更に、自作アプリを Websites 上に配置する。Eclipse から新規プロジェクト作成を選択し、Dynamic Web Project を選択して以下の様に index.jsp を配置する。
f:id:waritohutsu:20150125075109p:plain

上記でも紹介した Kudu の Debug console を利用して D:\home\site\wwwroot\bin\apache-tomcat-7.0.52\webapps\ROOT 以下のバックアップを取得したうえで作成した Java アプリを配置する。

次にリモートデバッグ用のツールを実行する。azure-websites-java-remote-debugging から取得したファイルの bin\DebugSession.bat を以下の実行例に沿って実行する。

>DebugSession.bat -p 8000 -s <sitename>.scm.azurewebsites.net -u <username> -w <password> -t
1 25, 2015 7:57:37 午前 org.azure.waws.DebugSession startSession
情報: Waiting for debugger to connect on 8000 ...

ここでの注意として、username には sitename\username を指定してはいけない点だ(例:normalian)。

Eclipse から [Debug As]-[Debug Configurations..] を選択し、以下の実行例に沿ってアプリケーションをデバッグ実行する。
f:id:waritohutsu:20150125075929p:plain

最後にブラウザからサイトにアクセスすると、以下の様に Eclipse 上からリモートデバッグが可能となる。
f:id:waritohutsu:20150125080600p:plain

最後に注意点として、Azure Websites を無料モードで利用している場合にCPU使用制限に引っかかってインスタンスが再起動される場合があるので、長時間放置する場合には WebSocket のコネクションが切れている場合があるので注意が必要だ。

Azure Websites で Tomcat や Jetty を運用する場合の注意点

Websites は Java にも対応しており、工夫次第では Java EE アプリも稼働させることのできることができることは本ブログで紹介済みだ。今回は Websites で Java アプリケーションを運用する際の注意を記載する(というよりは httpPlatformHandler を使ってるアプリは全部な気もするが)。

まず、Websites には 無料, 共有, 基本, 標準 と呼ばれる動作モードがあるが、この際に無料を使う場合にいくつか制限が存在している。Windows Azure Web サイトのスケール アップとスケール アウト に記載があるが、特に注意すべきは以下の記載だ。

無料モードは、他の無料モードや共有モードのサイトと同じコンピューティング リソース
で実行されます。また、一定のクォータ期間のサイト (およびサブスクリプション内の他
の無料サイト) の CPU 使用時間が制限されています。使用時間が制限に達した場合、その
サイトおよびサブスクリプション内にある他の無料モードのサイトで、次のクォータ期間
までコンテンツおよびデータのサービスが停止されます。また、無料モードではサイトが
クライアントへサービスを提供する際のデータ量 (データ送信) の制限があります

上記の記載は「無料で使ってしばらく運用してる場合、ほっとくと Tomcat や Jetty のプロセス落とすから気を付けて」といっている。
実際、数時間放置して TomcatEE 等をデプロイした無料の Azure Websites にアクセスすると、以下の様にレスポンスが帰ってこずにエラーとなる(2回目、3回目のアクセスは再度プロセスが起動しなおされているので瞬時にレスポンスが来る)。
f:id:waritohutsu:20150122212936p:plain:w500

こちらを回避する方法はいたってシンプルで、Websites の「常時接続」機能を利用すればよい。Azure Websites でバックグラウンド タスクを実行して Web ジョブを使用する方法 に以下の記載がある。

[WACOM.NOTE] 連続的に実行するタスクについては、Web サイトの [構成] ページで 
[常時接続] を有効にすることをお勧めします。[常時接続] は [基本] と [標準] の
モードで使用できる機能であり、この機能を有効にすると、アイドル状態がしばらく
続いても Web サイトがアンロードされなくなります。Web サイトが常に読み込まれ
ていれば、連続的に実行するタスクをより高い信頼性で実行できます。

残念ながら「無料」モードでは利用できないが、「スケール」タブから[基本]か[標準]を選択して保存した後、「構成」タブから以下を参考に 常時接続 を選択する。
f:id:waritohutsu:20150122213049p:plain

実際に「無料」モードと「標準&常時接続」モードの運用結果を比べてみた。
f:id:waritohutsu:20150122213147p:plain

上記で分かる通り、無料側では catalina.xxxxxxxx.log が大量に作成されている(もちろん標準&常時接続側にも日次リクエストは投げている)。中身は Tomcat の起動ログであり、CPU 使用時間の制限でサービスが停止された後、リクエストが来た際に Tomcat が再起動したものが出力されている。

Web サイト上の JavaEE アプリからVPN経由で Oracle DB を参照する!

最近記載した以下の記事により、Web サイト上で Java EE のアプリケーションが稼働することは理解できたと思う。

しかし、これだけでは肝心のデータベースに接続する方法を記載していない。そのため、今回は仮想マシン上に Oracle DB を作成して Web サイトからデータを参照する方法を紹介する。

大枠の流れは以下になる。

  1. 仮想ネットワークとゲートウェイを作成する
  2. Azure 上に仮想マシンOracle DB を作成してセットアップする
  3. クライアント端末の NetBeansJavaEE のアプリケーションを作成する
  4. Web サイトと仮想ネットワークを VPN で接続する
  5. Web サイトを作成し、Tomcat EE をデプロイする

上記で作成されるアプリケーションの構成は以下になる。
f:id:waritohutsu:20150111034103p:plain

今回は上記の構成を目指した JavaEE アプリケーションを作成する。

仮想ネットワークとゲートウェイを作成する

まずは管理ポータルから仮想ネットワークを新規し、チュートリアル: サイト間クロスプレミス接続用の仮想ネットワークの作成を参考に「ゲートウェイの起動」までを参考にゲートウェイを作成する。以下のような画面になればOKだ。
f:id:waritohutsu:20150111034401p:plain

Azure 上に仮想マシンOracle DB を作成してセットアップする

仮想ネットワークとゲートウェイを作成した後、仮想ネットワーク上に配置する形で Oracle DB の仮想マシンインスタンスを作成する。このあたりについては私がちまちま情報を書くよりは Creating an Oracle Database 12c virtual machine in Azure を参照していただいた方がいいだろう。
こちらで注意が必要な点は三つだ。その一は Oracle Listener を立ち上げること(デフォルトだと立ち上がっていなかった)だ。こちらは以下を参考に管理ツールを弄れば簡単だろう。
f:id:waritohutsu:20150111034155p:plain:w400

その二は、Windows ファイヤウォールのポートを Oracle DB 向けにあけること(今回はオフにしたが、本番環境では 1521 ポートのみ有効にする)。
f:id:waritohutsu:20150111034222p:plain:w400

その三は、NetBeans 上でアプリケーションを開発するために Oracle DB のエンドポイントで 1521 をオープンにする。
f:id:waritohutsu:20150111034308p:plain:w400

クライアント端末の NetBeansJavaEE のアプリケーションを作成する

次に JavaEEのアプリケーションを作成する。まずは NetBeans 8.0.1 で JavaEE7 な CDI を利用する際の注意点 を参考にして JavaEE のアプリケーションを作成し、更に JavaEE の実行環境を Microsoft Azure の Web サイト上で稼働させる を参考に NetBeans に TomcatEE を導入する。

以上の下準備が済んだ後、NetBeasn 以下の画面より作成した JavaeEE アプリケーションから [新規接続] を選択する。
f:id:waritohutsu:20150111034957p:plain

ここからは以下の新規接続ウィザードが起動するので、Oracle Thin を選んで[次 >]を押下するが、ojdbc6.jar or ojdbc7.jar が存在しない場合は別途取得して[追加]ボタンからドライバファイルを追加する。
f:id:waritohutsu:20150111035302p:plain:w300f:id:waritohutsu:20150111035306p:plain:w300

また、Microsoft Azure 上に配置された Oracle DB への接続文字列を以下を参考に記載する。この際、Oracle の SID は「Azure 上に仮想マシンOracle DB を作成してセットアップする」にて自身で作成したものになるはずなのでご留意頂きたい。
f:id:waritohutsu:20150111035349p:plain:w400

最後にスキーマを選択するが、今回は伝統のある SCOTT スキーマのデータを参照したいので以下を参考に接続文字列の終了を確認する。
f:id:waritohutsu:20150111035400p:plain:w400

また、以下の様に ojdbc7.jar を WEB-INF/lib 以下の配置して、アプリケーションが Oracle DB に接続する準備をすること。
f:id:waritohutsu:20150111035542p:plain

次に、以下の画面から [新規]-[その他]メニューを選択し、[持続性]-[データベースからのエンティティ・クラス]を選択する。
f:id:waritohutsu:20150111035456p:plain:w300f:id:waritohutsu:20150111035500p:plain:w300

ここから以下のウィザードが表示され、SCOTT スキーマのテーブルを選択できるので、DEPT と EMP を療法選択する。
f:id:waritohutsu:20150111035632p:plain:w400

ウィザードから XHTMLJava クラスが全て自動生成されるので、この時点で一度ローカルで TomcatEE を起動して疎通を確認するといいだろう。

Web サイトと仮想ネットワークを VPN で接続する

こちらは新管理ポータルである https://portal.azure.com/ にアクセスし、以下の画面を参考に仮想ネットワークと接続する(この際、Web サイトが無料の構成では設定できない点に注意すること)。
f:id:waritohutsu:20150111035921p:plain

この際、仮想ネットワークのゲートウェイ作成が完了していないと以下のようなエラーメッセージがでるので注意してほしい。
f:id:waritohutsu:20150111040216p:plain

Web サイトを作成し、Tomcat EE をデプロイする

こちらについては JavaEE の実行環境を Microsoft Azure の Web サイト上で稼働させる を参照して TomcatEE をデプロイする。デプロイ前に、META-INF/persistence.xml を編集し、接続先を以下の様に仮想マシン上のローカルIPとする。

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
    <persistence-unit name="com.mycompany_MavenWebApp_war_1.0-SNAPSHOTPU" transaction-type="JTA">
        <jta-data-source>exampledb</jta-data-source>
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
        <properties>
            <property name="javax.persistence.jdbc.driver"   value="oracle.jdbc.OracleDriver"/>
            <property name="javax.persistence.jdbc.url"      value="jdbc\:oracle\:thin\:@10.0.1.4\:1521\:example" />
            <!-- 
            <property name="javax.persistence.jdbc.url"      value="jdbc\:oracle\:thin\:@winoracledb12c.cloudapp.net\:1521\:example" />
            -->
            <property name="javax.persistence.jdbc.user"     value="SCOTT" />
            <property name="javax.persistence.jdbc.password" value="<password>" />
        </properties>
    </persistence-unit>
</persistence>

以下を実施した後、NetBeans で作成した war ファイルを Web サイト上の TomcatEE 上にデプロイしよう。正しくアプリケーションが動作していれば以下のようになる。
f:id:waritohutsu:20150111040600p:plain