第3章 Oracle VM Manager REST APIの使用
3.1 RESTベースURIへの接続
REST Webサービスにアクセスするには、次の基本URIを使用する必要があります:
https://hostname:port/ovm/core/wsapi/rest
このURIでは、hostnameをOracle VM Managerのホスト名またはIPアドレスに置き換え、portをREST Webサービスが使用可能なポート番号に置き換えます - デフォルトは7002 (SSL)です。
このURIを直接問合せすると情報が得られず、エラーが発生します。 このURIは、利用可能なURIマッピングに従ってRESTインタラクションが構築されるベースURIとしてのみ使用されます。 詳細については、3.3項、「どのURIマッピングが利用可能で、どのように機能するか」を参照してください。
3.2 認証方法
Oracle VM Managerにアクセスするには、クライアントが最初に正常に認証される必要があります。 Oracle VM Managerは、RESTのHTTP基本認証モードをサポートしています。 Oracle VM Managerがリクエストを認証するには、ユーザー名とパスワードを最初のリクエストのヘッダーの一部として送信する必要があります。 その後のリクエストでは、新しいリクエストごとにユーザー名とパスワードを送信し続けるのではなく、最初のレスポンスに添付されたセッションCookieを送信する必要があります。
OvmWsRestClientクラスのloginメソッドは、リクエスト・ヘッダーにユーザー名とパスワードを設定する方法の例を提供します。
RESTで必要とされるログイン・プロセスの例は、このドキュメントに含まれているサンプル・コードにも記載されています。 さらなる例については、3.6.2項、「認証」を参照してください。
REST APIは、証明書ベースの認証もサポートしています。 内部Oracle VM Manager CA証明書またはOracle VM Managerトラスト・ストアにCA証明書をインポートしたサードパーティCAで署名されて登録されている有効な証明書を持っている限り、証明書を使用して簡単に認証できます。あなたのコード内にユーザー名とパスワードの機能が含まれています。 内部Oracle VM Manager CA証明書に対する証明書の署名と登録は、提供された証明書管理ツール(「Oracle VM管理者ガイド」で「SSLの設定」を参照)を使用して達成することも、第4章、「WS-APIに公開されている追加ユーティリティ」で説明するOracle VM ManagerユーティリティREST APIを使用してプログラム的に実現することもできます。
3.3 利用可能なURIマッピングとその仕組み
すべてのREST APIは、GETやPOSTリクエストなどの既存のHTTPメソッドを使用して、さまざまな操作をトリガーします。 トリガーされる操作のタイプは、使用されるHTTPメソッドとURIパターンによって異なります。
Oracle VMでは、URIパターンは、ObjectType名の周りに構築され、ObjectTypeの特定のインスタンスの識別子です。 3つのケースでは、インスタンスの識別子は省略できます:
-
HTTP POSTメソッドを使用して、ObjectTypeの新しいインスタンスを作成します。
-
HTTP GETメソッドを使用した、ObjectTypeのすべてのインスタンスの完全なリスト。
-
HTTP GETメソッドを使用した、ObjectTypeのすべてのインスタンスの識別子のリスト。
APIを使用してアクセスできるさまざまなObjectTypeについては、SDKで提供されている全APIドキュメントを参照してください。 ObjectType名は、Oracle VM Manager Web InterfaceまたはOracle VM Managerコマンドライン・インタフェースで見たことのあるオブジェクトに完全にマッピングされない場合があることに注意してください。 たとえば、'resourceGroup'オブジェクトはUIまたはCLI命名法の'タグ'と同じものです。 これらの違いは、通常、SDKに付属のAPIドキュメントに記載されています。
Oracle VM Manager内の多くのオブジェクトには親子関係があるため、URIマッピングを使用してこれらの関係を作成、問合せ、および削除できます。
この表には、Oracle VM Managerによって制御される利用可能なオブジェクトと対話するための基本的なURIパターンが含まれています:
|
操作 |
HTTPメソッド |
URIパス |
渡されたエンティティ |
戻り値の型 |
|---|---|---|---|---|
|
作成 |
POST |
/ObjectType |
作成されるオブジェクト |
ジョブ |
|
すべて取得 |
GET |
/ObjectType |
List<ObjectType> |
|
|
すべてのIDを取得 |
GET |
/ObjectType/id |
List<SimpleId> |
|
|
IDで取得 |
GET |
/ObjectType/ |
ObjectType |
|
|
変更 |
PUT |
/ObjectType/ |
修正されるオブジェクト |
ジョブ |
|
削除 |
DELETE |
/ObjectType/ |
ジョブ |
|
|
アクション[a] |
PUT |
/ObjectType/ |
作成されるオブジェクト |
ジョブ |
|
子関連付けを追加 |
PUT |
/ObjectType/ |
子ID |
ジョブ |
|
子関連付けを削除 |
PUT |
/ObjectType/ |
子ID |
ジョブ |
|
子の関連付けを取得 |
GET |
/ObjectType/ |
List<ChildType> |
|
|
子の関連付けIDを取得 |
GET |
/ObjectType/ |
List<SimpleId> |
|
|
子オブジェクトの作成 |
POST |
/ParentType/ |
新しいChildTypeオブジェクト |
ジョブ |
|
子オブジェクトの削除 |
DELETE |
/ParentType/ |
ジョブ |
[a]アクション・スタイルのアクティビティの2つの良い例については、3.6.11項、「サーバー・プール内のサーバーの管理」を参照してください。
-
サンプルURIに示されているような大文字小文字は、実際のURIリクエストでは重要です:
ObjectTypeNamesは大文字で、actionsは大文字ではありません。 -
ObjectTypeに使用できる「行動」は、ObjectTypeに応じて異なります。 各ObjectTypeで使用できる各アクションについては、SDKに付属のマニュアルを参照してください。
-
「削除」操作を使用してトップレベルのオブジェクトのみが削除されます。 子オブジェクトの場合は、「子オブジェクトの削除」操作を使用します。
-
オブジェクトが親の関連付けの外に存在することができるオブジェクトは、通常のオブジェクトとして作成され、次に「子関連付けを追加」操作を使用して親に追加されます。 ServerPoolとServerオブジェクトの関係は、この例です。 親オブジェクトが削除されても、その子はまだ存在します。
-
子オブジェクトが親なしで存在できない場合は、「子オブジェクトの作成」操作によって作成されます。 VmとVmDiskMappingオブジェクトの関係は、この例です。 この場合、親オブジェクトが削除されると、その子も削除されます。
GETタイプのリクエストの場合、APIにアクセスするために必要なHTTP基本認証資格証明を含むようにHTTP要求ヘッダーを変更する手段がある限り、標準のWebブラウザを使用して直接REST APIをテストできます。 Mozilla Firefoxを使用している場合、Modify Headers Add-Onを試すことができます。Google ChromeユーザーはModHeaders Extensionを利用できます。
Authorizationヘッダーを含めるようにブラウザ・ヘッダーを変更します。 値をBASICに設定し、Base64でエンコードされた文字列をユーザー名とパスワードの形式で追加: username:password. これが完了したら、ブラウザにGETリクエストを受け入れるURLを指定するだけで済みます。 たとえば、サーバーIDのリストを取得するには、ブラウザをhttps://に設定してください。hostname:7002/ovm/core/wsapi/rest/Server/idhostnameは、Oracle VM ManagerホストのIPアドレスまたはFQDNです。
3.4 REST APIで使用されるインターネット・メディアのタイプ(JSONおよびXML)
REST APIは、XMLまたはJSONのいずれかを使用して、リクエストで送信されたデータまたはレスポンスで受信されたデータをエンコードできます。 返されるデータのインターネット・メディア・タイプは、各リクエストに対して適切なHTTPヘッダーを設定することによって制御されます。 Pythonなどの一部の言語では、XMLとは対照的に、JSON形式のデータを解析するためのライブラリが優れているため、すべてのリクエストに対してメディア・タイプをJSONに設定することがあります。
JSON形式のデータを返すようにOracle VM Managerに通知するには、Acceptヘッダーをapplication/jsonに設定する必要があります。
JSON形式でOracle VM Managerにデータを送信するには、Content-Typeヘッダーをapplication/jsonに設定する必要があります。
Oracle VM ManagerにXML形式のデータを返すように通知するには、Acceptヘッダーをapplication/xmlに設定するか、デフォルトのメディア・タイプを使用し、このパラメータをまったく設定しないでください。
XML形式のOracle VM Managerにデータを送信するには、Content-Typeヘッダーをapplication/xmlに設定するか、デフォルトのメディア・タイプを使用し、このパラメータをまったく設定しないでください。
データがHTTPリクエストの本文に含まれるすべてのPOSTおよびPUT操作では、要素名で大文字と小文字が区別されます。
3.5 良い例題: Oracle VM Managerの起動状態を確認
Oracle VM Manager起動プロセスには、完了までに数分かかることがあります。 起動時に、Oracle VM Managerはさまざまなデバッグ目的でWebサービスAPI呼び出しを受け入れることができますが、WebサービスAPIでリクエストされたジョブは起動時に開始されず、さまざまなモデル・オブジェクトの内容が起動過程様々なオブジェクトがリフレッシュされ、再検出されるときのプロセス。 このため、WebサービスAPIを使用するアプリケーションでは、APIリクエストを送信する前にOracle VM Managerの実行ステータスを確認することをお勧めします。
Oracle VM Managerの実行ステータスは、Oracle VM WebサービスAPIによって返されるManagerオブジェクトのmanagerRunStateプロパティまたは属性に含まれています。 起動時に、このプロパティの値は'STARTING'に設定されます。 すべての始動操作とサーバーの再検出が完了すると、このプロパティの値は実行中に変わります。
あなたのコードでは、Oracle VM Managerに対して認証を行い、それ以降の操作を実行する前にManagerオブジェクトのmanagerRunStateプロパティが'RUNNING'に設定されていることを確認する必要があります。 RESTインタフェースを使用してこれを行うには、次のURIに対してGET問合せを実行します:
https://hostname:port/ovm/core/wsapi/rest/Manager
この例と、Oracle VM Managerが実際に実行されるまで待機する方法の説明は、3.6.3項、「Oracle VM Managerの実行状態の確認」で提供されています。
3.6 RESTを使用したサンプル・コード
この項で提供されるサンプル・コードは、Oracle VM Manager内の多くの一般的な操作を実行します。 各例では、JavaとPythonの両方のコード・サンプルを提供しています。 本質的に、REST APIは言語に依存しないため、APIとのインタフェースには別のプログラミング言語を使用することができます。 コード・サンプルは、これらの2つの一般的な言語のいずれかを使用して異なる操作がどのように実行されるかを示すために提供されています。
このようなガイドでは、プログラミング・スタイルと使用するライブラリの選択は、使用する言語の作者とバージョンによって大きく異なります。 同じ言語内であっても、同じ結果を達成するためにはもっと多くの方法があります。 これらのサンプルは、アプローチにおいて信頼できるものではありませんが、独自のアプリケーションを開発するためのガイドラインとして使用できます。
3.6.1 提供されるサンプルについて
提供されているJavaサンプルについて
私たちのJavaサンプルは、Oracle VM ManagerにバンドルされているSDKで提供されているJavaコードとライブラリを中心に構築されています。 サンプル・コードでは、Java RESTサポートにJAX-RS仕様のJersey実装を使用しています。 Jerseyは、RESTサーバーとのREST通信を容易にするコア・クライアント・ライブラリを提供し、JAXBを介したXMLの自動作成および解析もサポートします。 JerseyはSDKには含まれておらず、https://eclipse-ee4j.github.io/jersey/とは別にダウンロードする必要があります。
複数のjerseyベースjarの依存関係管理を避けるには、Jersey Bundle Jarをダウンロードしてプロジェクトにインポートすることをお勧めします。
Jerseyライブラリに加えて、Java Sample ClientはJSONデータ・バインディングを容易にするためにJackson JSON Processorライブラリを利用しているため、JSONとPOJOの間の迅速な変換が可能です。 JacksonはSDKには含まれておらず、https://github.com/FasterXML/jacksonとは別にダウンロードする必要があります。
SDKに含まれているJavaサンプル・クライアントには、WS-APIでサポートされている対話の大半を実行するために必要なすべてのコードが含まれています。 コードは2つのパッケージに分かれています:
-
com.oracle.ovm.mgr.ws.client: APIへのRESTインタフェースのクラスを含みます。 特に、これらの例では、RestClient.javaファイルとOvmWs RestClient.javaファイルには、このガイドで参照されるコードの多くが含まれています。 このガイドでは、実際のクライアントAPIコードがどのように構築されているかを記述して、そうしなければならないREST呼び出しの多くを抽象化できるようにします。 実際には、これらのクラスを使用するには、基礎となるすべての仕組みをコードに知らなくてもかまいません。これについては、後述のWSDevClientクラスで説明しています。 このクラスのソース・ファイルは、SDK zipアーカイブのsourceフォルダ内のOvmWsClient_src.zipという名前のzipファイルに含まれています。 -
com.oracle.ovm.mgr.ws.sample: APIを使用して特定のアクションを実行し、サンプル・クライアントの実行時にメイン・クラスとして設定されるWsDevClientクラスが含まれます。 WsDevClientクラスは、クライアントAPIクラスを使用して、これらのクラスによって提供されるすべての抽象化で独自のアプリケーション描画を作成する方法の例です。 このガイドに従って、APIを使用して独自のアプリケーションを作成する方法を理解するだけであれば、WsDevClientクラスのコードに集中することができます。 このクラスのソース・ファイルは、SDK zipアーカイブのsourceフォルダ内のOvmWsClientSample_src.zipという名前のzipファイルに含まれています。
SDKには、OvmWsClient.jarというプリコンパイル済みjarファイルの形式でOracle VM Manager Web Services Clientライブラリも含まれています。 このライブラリには、APIを介して公開されているさまざまなObjectTypesのすべてのモデル・タイプと、API内のオブジェクトに対してさまざまなアクションを実行するのに便利なさまざまなユーティリティが含まれています。 典型的なOracle VM ObjectTypesで作業できるように、このライブラリをプロジェクトに組み込む必要があります。 ライブラリ・ファイルは、SDK zipアーカイブのlibフォルダに格納されています。
Javadocは、使用できるすべてのモデル・クラスの完全なリストを提供します。 これらのモデル・クラスをすべてインポートするには、次のimport文を使用します:
import com.oracle.ovm.mgr.ws.model.*;
特定のクラス(Serverなど)をインポートするには、次のimport文を使用します:
import com.oracle.ovm.mgr.ws.model.Server*;
独自のプロジェクト内でcom.oracle.ovm.mgr.ws.clientパッケージを使用すると、開発オーバーヘッドを削減できます。
これらの例では、RESTクライアントがcom.oracle.ovm.mgr.ws.clientパッケージ内でどのように実装されているか、WsDevClientクラスの特定のアクションにどのように使用されているかを示します。
ライブラリに含まれているコードは、JDK 7を使用していることを前提としています。 プロジェクトのソース/バイナリ形式がJDK7に設定され、プロジェクトにJDK7ライブラリがインポートされていることを確認してください。 JDK 6はサポートされていません。
提供されているPythonサンプルについて
私たちのPythonのサンプルは、Oracle VM Managerとの迅速なやりとりをスクリプト化する目的で、APIに直接アクセスできるようにするためのものです。 追加のライブラリを使用して抽象化は提供されません。
コードをシンプルにするために、私たちは、HTTPセッション管理、認証、JSONを扱うことができるPythonライブラリをいくつか使用することを選択しました。 これらのライブラリは、使いやすさと、使用できるコードの簡潔さに基づいて選択しました。 これらのライブラリに提供されているPythonのバージョンとサポートに応じて、REST APIとのやりとりを処理するために選択肢を使用することができます。 これらのサンプルで使用されるライブラリは次のとおりです:
-
リクエスト: HTTP基本認証とセッション処理を良好にサポートするHTTPライブラリ。 このライブラリはhttps://pypi.org/で使用できます。
-
time: 時間関連関数のPythonコア・ライブラリ。ジョブ・ステータス・チェックの迅速な継承を防ぐために、問合せ間の実行を一時停止するために使用できます。 このコア・ライブラリは、https://pypi.org/で記述されます。
-
json: Pythonデータ・オブジェクトをJSONに変換するためのPythonコア・ライブラリです。 このコア・ライブラリは、https://pypi.org/で記述されます。
できるだけシンプルにするため、このガイドではデフォルトのメディア・タイプとしてJSONを使用することにしました。 Pythonを使用してデフォルトXMLメディア・タイプを使用することも同様に可能です。 適切に書式設定されたXMLの構築に使用できる、ネイティブPythonオブジェクトへのXMLの解析に使用できる、lxmlの機能豊富なXMLツールキットの使用を検討する場合があります。 このツールキットはhttp://lxml.de/index.htmlで使用できます。
このガイドの例については、Pythonコードを次のインポートから開始する必要があります:
import requests import json from time import sleep
ライブラリの選択といくつかのサンプル・コードの構文により、あなたはPython 2.6以上を使用していることを前提としています。 ここに示した例は、Python 3と互換性がないかもしれませんが、このバージョンのPythonで簡単に操作できます。
このガイドのPythonの例は、お互いの上に構築されています。 多くの場合、前の例で定義した関数を例としています。 読者は、特定の例のために提供されたコードは、他の参照例で指定された機能のいくつかを定義しなければ機能しないことに注意する必要があります。
3.6.2 認証
REST APIを認証するには、最初にRFC 2617で説明されているHTTP基本認証を使用する必要があります。 後続のリクエストでは、最初のレスポンスで返されたセッション・クッキーが、新しいリクエストごとにユーザー名とパスワードの送信を続ける代わりに送信されます。
また、SSL証明書を使用して認証を実行することもできます。 Oracle VM Managerによって認識されるCAによって署名され、登録された証明書を使用する必要があります(4.3項、「RESTを使用した証明書ベースの認証のための証明書管理」の説明を参照)。
3.6.2.1 Java
JavaクライアントのREST APIに対する認証は、いくつかのJerseyユーティリティを使用します。 com.oracle.ovm.mgr.ws.clientで提供されるRestClientでは、ログイン・メソッドが定義されています:
...
public class RestClient
{
public static final String URI_BASE_PATH = "/ovm/core/wsapi/rest";
String SECURE_PROTOCOL = "https";
String INSECURE_PROTOCOL = "http";
private static final Map<Class, GenericType> genericTypeMap = new HashMap<Class, GenericType>();
private boolean debug = false;
private URI baseURI;
private Client webClient = null;
private List<NewCookie> cookies;
private String mediaType = MediaType.APPLICATION_XML;
private Locale locale = null;
private SSLSocketFactory sslSocketFactory = null;
...
public boolean login(final String username, final String password, final Locale locale,
final String path) throws WsException
{
try
{
// Make a dummy request to pass the authorization info to the server get the
// session id (which is returned in a cookie)
final WebResource resource = getWebClient().resource(getBuilder().path(path).build());
// Specify media type to accept
final Builder resourceBuilder = resource.accept(getMediaType());
// Append auth info
final String authHeader = getAuthorizationHeaderValue(username, password);
if (authHeader != null)
{
resourceBuilder.header("Authorization", authHeader);
}
if (locale != null)
{
resourceBuilder.acceptLanguage(locale);
}
final ClientResponse response = resourceBuilder.post(ClientResponse.class);
setCookies(response.getCookies());
if (response.getClientResponseStatus() != ClientResponse.Status.OK)
{
// If auth fails before reaching OVM Manager code, it is possible to receive
// a 401 error with HTML data instead of the expected WsErrorDetails object
if (!response.getType().toString().equals(getMediaType()))
{
throw createExceptionForUnexpectedResponse(response, null);
}
final WsErrorDetails errorDetails = response.getEntity(WsErrorDetails.class);
throw new WsException(errorDetails);
}
return true;
}
catch (final UniformInterfaceException ex)
{
throw convertException(ex);
}
}
private String getAuthorizationHeaderValue(final String username, String password)
{
// Username and password are optional if using cert auth. As long as we have username
// information, we'll pass that in an auth header.
if (username != null)
{
if (password == null)
{
password = "";
}
return "Basic " + new String(Base64.encode(username + ":" + password));
}
return null;
}
...
}
最初のリクエストが送信され、Authorizationヘッダーが添付されていることに注意してください。 Authorizationヘッダーの値は、HTTP基本認証に必要なBase64でエンコードされたユーザー名とパスワードを返すgetAuthorizationHeaderValueメソッドを呼び出すことによって取得されます。 セッション情報はサーバー・レスポンスのクッキーとして返され、このクッキーはすべての後続のリクエストに使用できます。
com.oracle.ovm.mgr.ws.clientのOvmWsRestClientクラスは、RestClientクラスを拡張します。 サンプル・アプリケーションで呼び出されるAPI関数を提供し、認証を達成するためにAPIに対して実行されるダミー問合せを定義します:
public class OvmWsRestClient extends RestClient implements OvmWsClient
{
public static final String URI_BASE_PATH = "/ovm/core/wsapi/rest";
public OvmWsRestClient()
{
super();
}
...
@Override
public boolean login(final String username, final String password,
final Locale locale, final String path) throws WsException
{
final boolean success = super.login(username, password, locale, path);
// In the case this is a second login request and the utilities endpoint is
// already initialized, update that endpoint to use the cookies returned
// from our new successful login. This means that the same OvmWsUtilitiesClient
// instance can continue to be used even if its session has expired, as
// long as the session is re-established on this primary endpoint.
if (success && utilitiesClient != null)
{
utilitiesClient.setCookies(getCookies());
}
return success;
}
...
}
WsDevClientクラス(サンプル・アプリケーション)では、このメソッドを呼び出すだけです:
...
public class WsDevClient
{
...
public void run()
{
try
{
...
api = OvmWsClientFactory.getOvmWsClient(wsimpl);
...
api.initialize(hostname, port, true);
// Authenticate with the OvmApi Service
api.login(username, password, Locale.getDefault());
...
}
...
}
これがサンプル・クライアントでどのように実装されているかについていくつか注意する必要があります。 最初のポイントは、OvmWsClientFactoryクラスを参照して、文字列変数'wsimpl'を使用してRESTクライアントまたはSOAPクライアントを使用しているかどうかを判断することです。 このクラスを使用すると、同じデモ・コードを使用して両方のAPIを表示できます。 適切なクライアント・オブジェクトを設定するswitch文が含まれています:
switch (implementation)
{
case SOAP:
return new OvmWsSoapClient();
case REST:
return new OvmWsRestClient();
}
SOAP APIは非推奨されており、可能であればREST APIを使用していることを確認する必要があります。
loginメソッドが呼び出される前に、initializeメソッドを使用して、Oracle VM Managerが実行されているホスト名とポート番号を設定します。 このメソッドは、最終的にRestClientクラスで定義され、基本URIを構成するすべてのコンポーネントを受け取り、その後使用されるベースURIを構築します。
注意すべき最後のことは、initializeメソッドとloginメソッドを呼び出すと、いくつかのリセット変数が提供されるということです。 実際、com.oracle.ovm.mgr.ws.sampleパッケージにはプロパティ・ファイルも含まれています: WsDevClient.properties。 このファイルには、このガイド全体で参照されている多くの変数のデフォルト値が含まれています。 サンプル・コードを自分の環境の仕様に従って動作させるには、これらの変数の多くをオーバーライドする必要があります。 変数のオーバーライドを処理する方法については、このプロパティ・ファイル自体のコメントに記載されています。
証明書ベースの認証はどうですか?
SDKのコードでは、ユーザー証明書を設定していることを前提としていないため、署名付きSSL証明書を使用した認証方法の例はありません。 ただし、これを実行するために必要なのは、セッション内のすべてのRESTリクエストに対して証明書を使用することだけです。 Javaでは、これを行う最も簡単な方法は、証明書とそれに関連付けられたキーをキーストア・ファイルに保存することです。 キーストアを使用して、すべての接続で使用されるSSLコンテキストを初期化するために使用できるキー・マネージャとトラスト・マネージャを読み込むことができます。
次のコード例は、あなたを始めるために役立ちます。 必要なものを難読化する可能性のあるエラー処理が取り除かれました。 このコードは、次の変数が初期化されることを期待しています:
File keystoreFile; // A file representing the location of the KeyStore
char[] keystorePassword; // The KeyStore password
char[] keyPassword; // The key password - if you didn't specify one when creating your
// key, then use the keystorePassword for this as well
このキーストアを使用してSSLコンテキストを初期化するために必要なコードは次のとおりです:
// Load your keystore
FileInputStream stream = new FileInputStream(keystoreFile);
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(stream, keystorePassword);
stream.close();
// Initialize the key manager from the keystore
KeyManagerFactory kmFactory =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmFactory.init(keystore, keyPassword);
KeyManager km[] = kmFactory.getKeyManagers();
// Initialize the trust manager from the keystore
TrustManagerFactory tmFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmFactory.init(keystore);
TrustManager tm[] = tmFactory.getTrustManagers();
// Initialize an SSL context and make it the default for all connections
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(km, tm, null);
SSLContext.setDefault(ctx);
このコードは、初期SSLコンテキストが設定されているWsDevClientクラスに置き換えることができます:
public void run() {
try {
// Configure the SSLContext with an insecure TrustManager
// This is done to avoid the need to use valid certificates in the
// development environment.
// This should not be done in a real / secure environment.
final SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(new KeyManager[0], new TrustManager[]{
new InsecureTrustManager()
}, new SecureRandom());
SSLContext.setDefault(ctx);
...
}
3.6.2.2 Python
Pythonには、Request、Urllib2、HTTPLibなどのRESTを使用してHTTPリクエスト処理を行うことができるさまざまなライブラリがあります。 この例では、認証およびセッション処理の優れたサポートを提供するため、Requestライブラリを使用します。
s=requests.Session()
s.auth=('user','password')
s.verify=False #disables SSL certificate verification
サンプル・コードでは、SSL証明書の検証を無効にするオプションを使用しています。 これは、デフォルトの自己署名証明書を使用したデモンストレーション環境に対してコードをテストするときに役立ちます。これらの証明書が正しく検証されず、HTTPリクエストが失敗する可能性があります。 本番環境では、この行は推奨されず、SSL証明書は完全に有効で認定された認証局によって署名されるように更新するか、Oracle VM Manager内部CA証明書が検証目的のためにローカルにインストールされていることを確認する必要があります。
JSONをAPIとのすべてのやり取りに使用したいので、セッション内のすべてのリクエストにヘッダーを追加するRequestsライブラリ機能を活用することは価値があることが分かります。 これを行うために、適切なヘッダーを設定して、私たちが行う各HTTPリクエストに対してこれを行う努力を省くことができます:
s.headers.update({'Accept': 'application/json', 'Content-Type': 'application/json'})
最後に、このガイド全体で、REST APIが配置できるBaseURIを参照します。 コードを比較的短くするために、変数を次のように設定することができます:
baseUri='https://127.0.0.1:7002/ovm/core/wsapi/rest'
上記で指定されたbaseUriは、3.1項、「RESTベースURIへの接続」で説明されている形式に従います。 あなたの環境やスクリプトを実行する場所によって異なります。 独自のアプリケーション要件に応じて、ホスト名とポートの値を置き換えることができます。 この例では、Oracle VM Managerがホストされているのと同じシステム上でPythonスクリプトを実行していると仮定しています。
証明書ベースの認証はどうですか?
すでに述べたように、REST APIを介してOracle VM Managerに対して認証するために、署名付きSSL証明書を使用することは可能です。 これにより、ユーザー名またはパスワードを入力して認証を実行するための要件を無効にすることができます。 これを行うには、アプリケーションで使用できる単一のPEMファイルに格納されている証明書とキーを取得する必要があります。 リクエスト・ライブラリでは、リクエストごとに証明書を送信したり、セッション内のリクエストごとに使用するように設定したりすることができます:
s.cert='/path/to/mycertificate.pem
証明書が有効で、Oracle VM Managerによって認証されている限り、セッションは自動的に証明書を使用してログインします。
3.6.3 Oracle VM Manager実行状態の確認
3.5項、「グッド・プラクティス: Oracle VM Managerの起動状態を確認」で説明したように、それ以降のAPI呼び出しを行う前に、Oracle VM Managerの実行ステータスを確認することをお勧めします。 これは、次のURIにGET問合せを送信することによって実現されます:
https://hostname:port/ovm/core/wsapi/rest/Manager
Oracle VM Managerの実行ステータスはmanagerRunStateプロパティによって示され、この問合せに対するレスポンスで戻されます。
これ以上の操作を許可する前に、managerRunStateプロパティの値が'RUNNING'と等しくなるまで、この問合せを繰り返すようにコードをループする必要があります。
3.6.3.1 Java
あなたのコードでOracle VM Manager Web Services Clientライブラリを使うことで、REST APIはほぼ完全に抽象化されています。 OvmWsRestClientクラスに示されているようにManagerオブジェクトを問合せするメソッドは、Jersey Builderを使用してGETリクエストを構成し、Managerオブジェクトを返す単純な呼び出しです:
public Manager managerGet() throws WsException
{
try
{
final Builder b = getResourceFromPathElements("Manager", "Manager");
final Manager manager = b.get(Manager.class);
return manager;
}
catch (final UniformInterfaceException ex)
{
throw convertException(ex);
}
}
Javaでマネージャ・ステータスを追跡するには、このmanagerGet()メソッドを使用してManagerオブジェクトにアクセスし、ManagerRunStateプロパティ値を問合せして、Oracle VM Managerインスタンスが実行時ステータスを実行中であるかどうかを判断するAPIを繰り返し問合せできます。 このコードは、ある期間にわたってOracle VM Managerインスタンスに送信されたリクエストの数を減らし、インスタンスが正常に起動する時間を許すリクエスト間でスリープする必要があります。 次のコードは、Javaクライアント・アプリケーションでManagerRunStateが'RUNNING'に設定されるまで待機するために必要なループの実行例を示しています:
// Wait for the manager to be in a running state before doing any work
// Refresh the manager object once every second to get the latest run state
final Manager manager = api.managerGet();
while (manager.getManagerRunState() != ManagerRunState.RUNNING){
try{
Thread.sleep(1000);
}
catch (final InterruptedException e){}
manager=OvmWsClientTools.refresh(api, manager);
}
このループでは、OvmWsClientTools.refreshの呼び出しがあります。OvmWsClientTools.refreshは、ループの各反復でマネージャ・モデル・オブジェクトをリフレッシュし、更新されたマネージャ・オブジェクトを返すために使用されます。 このコードは、他の操作が試行される前に認証の直後に実行する必要があります。
3.6.3.2 Python
Pythonでマネージャの状態を追跡するために、URIを使用してManagerオブジェクトにアクセスするAPIを繰り返しクエリーでき、managerRunStateプロパティの値をテストして、Oracle VM Managerインスタンスが実行時ステータスを実行中であるかどうかを判断できます。 スクリプトを礼儀正しくするために、timeライブラリを使用してリクエスト間でスリープします。 これはプログラム内のさまざまな段階で繰り返し使用できる機能なので、関数として定義する方がよい:
...
def check_manager_state(baseUri,s):
while True:
r=s.get(baseUri+'/Manager')
manager=r.json()
if manager[0]['managerRunState'].upper() == 'RUNNING':
break
time.sleep(1)
return;
この関数では、while True:ステートメントは無限ループを作成します。 リクエスト・ライブラリ・セッション・オブジェクトは、適切なURIにGETリクエストを送信するために使用され、レスポンス・コンテンツはJSONからPythonデータ・オブジェクトに変換されます。 オブジェクトは、すべてのManagerオブジェクトのプロパティをキーとするディクショナリを含むリストです。 ifステートメントを使用してmanagerRunStateプロパティをテストし、文字列値'RUNNING'と一致するかどうかを確認します。 一致するものが見つかると、無限ループが壊れて関数が返ることがあります。 一致するものが見つからない場合、time.sleepステートメントは、次のリクエストを送信する前にファンクションを1秒間待機させ、リクエストが合理的な期間にわたって行われるようにします。
通常、3.6.2項、「認証」で説明されているように、認証後すぐにこの関数の呼び出しを挿入します。 このコードを認証プロセスに組み込んで、アプリケーション内で認証リクエストが行われるたびに呼び出されるようにすることもできます。
3.6.4 サーバーの一覧表示
Web Services APIには、Oracle VM環境内ですでに検出されたサーバーをリストするためのさまざまなオプションが用意されています。
すべてのサーバーとその一意のIDのリストを取得
Oracle VM環境内で一意の識別子と共に検出された簡潔なサーバー・リストを取得できます。 この呼び出しは、すべてのサーバーの完全な詳細を取得するよりも、帯域幅が少なくなります。 これは、環境内のサーバーのIDを取得する簡単なメソッドを提供します。
次のURIを使用してGETリクエストを実行できます:
https://hostname:port/ovm/core/wsapi/rest/Server/id
このリクエストによって返されるIDには、後述するように、各サーバー・オブジェクトのすべての詳細を問合せするために使用できるURLが含まれています。 これにより、特定のサーバーの詳細を取得するために問合せするURLを簡単に検索することができます。
一意のIDに基づいてサーバーのすべての詳細を取得
固有のIDに基づいて、特定のサーバーのすべての詳細を取得することは可能です。
次のURIを使用してGETリクエストを実行できます:
https://hostname:port/ovm/core/wsapi/rest/Server/id
上記のURIに示されているidは、サーバーの実際の一意のIDの値に置き換えてください。 このURIは、すべてのサーバーIDの一覧に返されたIDオブジェクトの一部として返されることに注意してください。
すべてのサーバーのすべての詳細のリストを取得
環境内のすべてのサーバーの詳細を簡単に取得できます。 ご使用の環境に多数のサーバーがある場合、この呼び出しは帯域幅を大量に消費する可能性があります。
次のURIを使用してGETリクエストを実行できます:
https://hostname:port/ovm/core/wsapi/rest/Server
3.6.4.1 Java
特定のタイプのオブジェクトのリストを取得するHTTP問合せは、すべてのObjectTypeで本質的に同じであるため、RestClientはgetAllメソッドなど、これらの目的のための汎用メソッドを提供します:
/**
* Gets all objects of a given type.
*/
@SuppressWarnings("unchecked")
public <T> List<T> getAll(final Class<T> type) throws WsException
{
try
{
final Builder b = getResourceForType(type);
return (List) b.get(getGenericListType(type));
}
catch (final UniformInterfaceException ex)
{
throw convertException(ex);
}
}
これは、すべてのサーバーのリストを取得するために、serverGetAllメソッドがOvmWsRestClientクラスに定義されていて、次のようにServerクラスをgetAllメソッドに提示することを意味します:
...
@Override
public List<Server> serverGetAll() throws WsException
{
return getAll(Server.class);
}
WsDevClientコード(サンプル・アプリケーション)から、すべてのサーバーをリストする呼び出しは、OvmWsRestClientで定義されたserverGetAllメソッドを使用します:
final List<Server> servers = api.serverGetAll();
これによりリストが作成され、必要に応じてサーバーの詳細を処理できます:
for (final Server server : servers)
{
if (testServerName.equals(server.getName()))
{
testServer = server;
}
printServer(server);
}
サーバー・モデル・クラスによって公開されるメソッドを使用すると、サーバー固有のさまざまな属性を出力することができます。 サンプル・コードでは、WsDevClientクラスに含まれるprintServerメソッドを参照しています。 このメソッドは、さまざまなタスクを実行します。 Serverオブジェクトをどのように扱うことができるかを説明する目的で、次のコードを省略しています:
private void printServer(final Server server)
{
System.out.println("Server id: " + server.getId());
System.out.println("\tname: " + server.getName());
System.out.println("\tdescription: " + server.getDescription());
System.out.println("\tGeneration: " + server.getGeneration());
System.out.println("\tServerPool id: " + server.getServerPoolId());
System.out.println("\tCluster id: " + server.getClusterId());
...
}
3.6.4.2 Python
3.2項、「認証方法」で提供されている認証コードを基に、requests.Sessionオブジェクトを使用してGETリクエストを送信し、すべてのサーバーの詳細をREST APIに一覧表示します。 レスポンス内容はJSON形式です。 幸いにも、RequestsライブラリはJSONを自動的にデコードすることができます。 つまり、HTTPリクエストによって返されたコンテンツをネイティブのPythonデータ・オブジェクトとして扱うことができます:
...
r=s.get(baseUri+'/Server')
for i in r.json():
# do something with the content
print('{name} is {state}'.format(name=i['name'],state=i['serverRunState']))
...
上記で指定されたbaseUriは、3.2項、「認証方法」で説明されているように認証時に設定した変数に基づいており、リクエストしているデータ型をAPIに通知するためにServerオブジェクト型を追加しています。
3.6.5 サーバーの検出
「サーバー・プール」を作成するには、最初にプールに追加するサーバー・オブジェクトが必要です。 割り当てられていないOracle VM Serversを検出することによって、環境に追加します。 サーバーの検出では、REST APIはユーザー資格証明などの機密情報を除いて、URIにパラメータを渡す必要があります。
サーバーの検出を実行するには、要件に合わせて次のURLを変更し、POSTリクエストを送信します:
https://hostname:port/ovm/core/wsapi/rest/Server/discover?serverName=1.example.org\ &takeOwnershipIfUnowned=True
リクエストの本文にはOracle VM Agentパスワードが含まれているため、リクエストのURL文字列には含まれません。 URL自体はHTTPSによって保護されていますが、リクエストのHTTPコンポーネントを囲むTLSラッパーのために、多くのサーバー、プロキシおよびブラウザはログファイルにURLを格納します。 リクエストの本文にパスワードを送信することで、このリスクが軽減されます。
3.6.5.1 Java
OvmWsRestClientクラスは、サーバーの検出を処理するメソッドを提供します。 検出を実行するために使用される多くのパラメータは、POSTリクエストに使用する必要のあるURIを構成するために使用されるため、RestClientクラスで定義されたメソッドによってURI構築用に処理された後、これらのパラメータはJerseyビルダーに渡されます。 Oracle VM ManagerがOracle VM Agentに接続するために必要とするログイン資格証明は、単純な文字列としてPOSTリクエストの本文内に送信されます。
このガイドの例の多くは、RestClient.javaのRestClientクラスで定義されている基本的なメソッドを使用しています。 これらのメソッドはJerseyを使用してWebクライアントを設定し、JAXBを使用してURI構築やXML構築などのタスクを処理するコンストラクタも提供します。 これらの基本的なメソッドについては、このガイドで詳細には説明しませんが、さらなる理解が必要な場合は、読者が検討する必要があります。
@Override
public Job serverDiscover(final String serverName, final String agentPassword,
final boolean takeOwnership)
{
final Map<String, Object> queryParameters = new HashMap<String, Object>();
queryParameters.put("serverName", serverName);
queryParameters.put("takeOwnershipIfUnowned", takeOwnership);
final Builder b =
getResourceFromUriAndPathElementsWithQueryParameters(null,
queryParameters, Server.class.getSimpleName(), "discover");
return b.type(getMediaType()).post(Job.class, agentPassword);
}
サンプル・コードのWSDevClientクラスにはサーバー検出例は含まれていませんが、サーバーの検出はメイン・クラスのコードを次のように簡単に行うことができます:
final Job serverCreateJob = api.serverDiscover("1.example.com", "p4ssword", true);
System.out.println("create server job id: " + serverCreateJob.getId());
sid=waitForJobComplete(api, serverCreateJob, Server.class);
APIによって返されるXMLレスポンスには、リクエストされたプロセスを実行するために作成されたjobに関する情報が含まれています。 このため、serverDiscoverメソッドの出力を使用してJobオブジェクトを生成します。 このオブジェクトを使用すると、「waitForJobCompleteメソッドを使用してジョブのステータスを追跡」を簡単に実行できます。「waitForJobCompleteメソッドを使用してジョブのステータスを追跡」は、ジョブが成功した場合にサーバーIDオブジェクトも返します。
IDオブジェクトには、完全なオブジェクトを参照できるURIが含まれます。 Javaでは、IDオブジェクトに対してgetUriメソッドを使用してURIを素早く取得できます。
3.6.5.2 Python
前の例から引き続き、3.6.4項、「サーバーのリスト」では、セッション・オブジェクトを使用して、単純な文字列として指定されたエージェント・パスワードを含むPOSTリクエストを送信できます:
...
uri_params={'serverName':'1.example.com', 'takeOwnershipIfUnowned':'True'}
data='p4ssword'
r=s.post(baseUri+'/Server/discover', data, params=uri_params)
リクエストが正しくフォーマットされ、APIがそれを受け入れる場合、返されるJSONレスポンスには、リクエストされたプロセスを実行するために作成されたジョブに関する情報が含まれます。 レスポンス・データからジョブURIを簡単に取得してwait_for_job関数でジョブのステータスを追跡に使用できます:
job=r.json()
print('Job: {name} for {server}'.format(name=job['id']['name'],server='1.example.org'))
joburi=job['id']['uri']
wait_for_job(joburi,s)
IDオブジェクトには、完全なオブジェクトを参照できるURIが含まれます。 このURIを簡単に取得して、JobオブジェクトのAPIに対して別の問合せを実行して、ステータスを追跡できるようにします。 この例では定義されていないwait_for_job関数を参照しています。 この関数を使用する前に、3.6.6項、「ジョブを使用した作業」を参照して定義する方法を調べてください。
3.6.6 ジョブの操作
POST、PUTおよびDELETE HTTPメソッドを使用するほとんどの書き込みリクエストでは、APIからのレスポンスには、実行中のタスクのOracle VM Managerにキューイングされているプロセスに固有のジョブ・データのXMLまたはJSON表現が含まれています。 Oracle VM Manager内の多くのjobsは、それらが順番に実行され、各ジョブが完了するのに時間がかかる場合にのみ成功する可能性があるため、続行する前にジョブが完了しているかどうかを確認するのが一般的です。 また、ジョブの失敗のエラー・メッセージと共に、タスクが成功したか失敗したかを判断するためにジョブ情報を取得すると便利です。
次のURIにGETリクエストを送信することによって、特定のジョブの詳細を取得できます:
https://hostname:port/ovm/core/wsapi/rest/Job/id
URIのidをジョブ用に生成されたIDに置き換えます。 ジョブURIは、POST、PUT、またはDELETEリクエストに対して返されたXMLまたはJSONレスポンスで送信されることに注意してください。
ジョブの完了をチェックし、ジョブの失敗をチェックすることは必ずしも必要ではないことに注意してください。 たとえば、より複雑なアプリケーションでは、複数の独立した長期実行オペレーションを同時に生成することができ、ある期間にわたってステータスをチェックすることができます。 この方法は、インポートやクローンなどの作業で、操作が完了するまでにかなりの時間がかかる場合に役立ちます。 以下に説明するように、ジョブが完了するまで待機する関数は、相互に依存する一連の短い操作に、より便利です。
3.6.6.1 Java
ジョブ・ステータスのトラッキング
サンプル・コードのWSDevClientクラスには、ジョブのトラッキング状況を処理するサンプル・メソッドが含まれているため、ジョブが完了するまでアプリケーションが待機してから、ジョブの完了に依存する可能性のあるリクエストを続行できます。
このメソッドは、Jobオブジェクトが渡されることを期待しています。Jobオブジェクトは、Jobの完了の有無を検出するためにAPIに継続的に問合せを実行するために使用されます。 ジョブのsummaryDoneプロパティを調べて、doneプロパティとは対照的に、生成された子ジョブの状況をより完全に見ることができるので、ジョブが完了したかどうかを判別します。 詳細については、2.1.4項、「ジョブの処理」を参照してください。 通常、APIに対して書き込み型のリクエストを実行するときは、APIからのレスポンスでJobオブジェクトが返されます。 これにより、これらの繰り返し問合せを実行するためのジョブIDを取得できます。
...
@SuppressWarnings("unchecked")
public <T> Id<T> waitForJobComplete(final OvmWsClient api, Job job,
final Class<T> type) throws WsException
{
while (job.isSummaryDone() == false)
{
try
{
Thread.sleep(1000);
}
catch (final Exception e)
{
}
job = api.jobGetById(job.getId());
if (job.getJobRunState().equals(JobRunState.FAILURE))
{
final JobError error = job.getError();
if (error != null)
{
System.out.println(" error type: " + error.getType());
System.out.println(" error message: " + error.getMessage());
}
System.out.println(" transcript: " + api.jobGetDebugTranscript(job.getId()));
}
}
@SuppressWarnings("rawtypes")
final Id resultId = job.getResultId();
if (type == null)
{
return resultId;
}
else
{
final Id<T> typedResultId = resultId;
return typedResultId;
}
}
ジョブのステータスを追跡するには、次のコードを含むOvmWsRestClientクラスに公開されているjobGetByIdメソッドを呼び出します:
@Override
public Job jobGetById(final Id<Job> jobId) throws WsException
{
return getById(jobId, Job.class);
}
このガイドの前半では、OvmWsRestClientクラスで使用できるいくつかの一般的なメソッドがあり、Oracle VM Manager内の異なるObjectTypeを問合せするために再利用できると述べました。 getByIdメソッドは、これらのメソッドの1つです。 実際には、このメソッドはRestClientクラスで定義されたgetResourceByIdメソッドを呼び出します。このメソッドはgetResourceFromURIメソッドを呼び出します。 このメソッドは、最終的にJersey Builder APIを使用してREST GETリクエストを作成し、オブジェクトを返すことができます。 この一連のメソッドは、紛らわしいことがあります。 物事を単純にするために、以下のgetByIdメソッドのコードを示します:
public <T> T getById(final Id<T> id, final Class<T> type) throws WsException
{
try
{
final Builder b = getResourceById(id);
return b.get(type);
}
catch (final UniformInterfaceException ex)
{
throw convertException(ex);
}
}
URIとリクエストがどのように構築されているかを見るには、上記のコードで呼び出された各メソッドを引き続き読んでおくことをお勧めします。 ただし、ほとんどの開発者にとって、サンプル・クライアントですでに提供されているコードを再利用することは、REST APIのHTTPレベルを抽象化するのに役立ちます。
3.6.6.2 Python
ジョブのステータスを追跡
Pythonでジョブのステータスを追跡するために、各レスポンスで返されるジョブURIを使用してAPIを繰り返し問合せできます。 スクリプトを礼儀正しくするために、timeライブラリを使用してリクエスト間でスリープします。 これはさまざまなタスクに必要な機能性なので、関数として定義する方が良いでしょう:
...
def wait_for_job(joburi,s):
while True:
time.sleep(1)
r=s.get(joburi)
job=r.json()
if job['summaryDone']:
print('{name}: {runState}'.format(name=job['name'], runState=job['jobRunState']))
if job['jobRunState'].upper() == 'FAILURE':
raise Exception('Job failed: {error}'.format(error=job['error']))
elif job['jobRunState'].upper() == 'SUCCESS':
if 'resultId' in job:
return job['resultId']
break
else:
break
Oracle VM Managerでオブジェクトが作成されるアクションで構成される完了済みジョブには、作成されたオブジェクトのIDも含まれます。 ジョブのsummaryDoneプロパティを調べて、doneプロパティとは対照的に、生成された子ジョブの状況をより完全に見ることができるので、ジョブが完了したかどうかを判別します。 詳細については、2.1.4項、「ジョブの処理」を参照してください。 これらのタイプのアクティビティでは、ジョブが完了した後にこの値を戻すと、同じオブジェクトに関連する後続のタスクを実行するのがより簡単になります。 ジョブが成功し、エラーが戻されなかった場合にのみ、この値を戻します。
3.6.7 オブジェクトとIDの検索
REST APIの使用時に実行する可能性のある一般的な操作がいくつかあります。 既に見てきたように、次の基本的なGETリクエストを実行するだけで、特定のオブジェクト・タイプのすべてのオブジェクトのリストを取得するのは比較的簡単です:
https://hostname:port/ovm/core/wsapi/rest/ObjectType
ObjectTypeを、アイテムをリストするオブジェクト・タイプの名前に置き換えます。 たとえば、環境内のすべてのサーバーのリストを取得するには、単にObjectTypeを'Server'に置き換えます。
このようなリクエストのオーバーヘッドを減らすために、環境内の一致するすべてのオブジェクトのIDのリストをオブジェクト・タイプに問合せすることができます:
https://hostname:port/ovm/core/wsapi/rest/ObjectType/id
これらのリスティングをすばやく検索してオブジェクトまたはオブジェクトのIDを検索して、その特定のオブジェクトに対して後続の操作を実行できるようにする基本操作を提供するようにクライアントを設計する場合は、かなり一般的です。 この機能はAPIによって直接提供されるものではなく、ロジックは独自のアプリケーションにコーディングする必要があります。 この項では、一般的な検索スタイル操作を実行するためのツールの提供方法について説明します。 これらのツールの設計に対するあなたのアプローチは異なる場合があります。
3.6.7.1 Java
SDKに含まれるクライアントには、オブジェクトやIDの検索を実行するためのツールが多数含まれています。 これらのツールは、OvmWsClientToolsクラスで提供されています。 REST APIとインタフェースする検索ツールは、最初にオブジェクト・タイプのオブジェクトまたはIDのリストを問合せしなければなりません。そして、返されたリストを検索して一致するものを検索する必要があります。
名前でオブジェクトを検索
OvmWsClientToolsクラスでは、オブジェクト名と一致する文字列に基づいて、オブジェクト型(wsClassName)の一致を実行する次のメソッドが見つかります:
public static <T extends BaseObject<T>> List<T> findObjectsByName(final Object api, final String
wsClassName, final String name)
throws Exception
{
nullCheck(api, "api");
nullCheck(wsClassName, "wsClassName");
final List<T> resultList = new ArrayList<T>();
final List<Id<T>> ids = findIdsByName(api, wsClassName, name);
if (ids != null && ids.size() > 0)
{
final Class wsClass = getWsClass(wsClassName);
for (final Id<T> id : ids)
{
final Object object = getById(api, id, wsClass);
if (object != null)
{
resultList.add((T) object);
}
}
}
return resultList;
}
このメソッドは、実際には「名前によるオブジェクトIDの検索」で後述するfindIdsByNameメソッドを呼び出します。 このメソッドによって返されたIDを使用して、実際のオブジェクトを取得し、問合せ用に返すリストに追加します。
名前によるオブジェクトIDの検索
名前と一致するオブジェクトIDを検索するには、必要なオブジェクト・タイプのすべてのIDについてAPIに問合せを実行し、返された結果をループして、問合せ文字列に一致する名前値を持つエントリのリストを作成します。 OvmWsClientToolsクラスで定義されたfindIdsByNameメソッドでは、wsClassName文字列で表される異なるオブジェクト型ごとに呼び出す適切なクライアント・メソッドの名前を取得するために、いくつかの追加作業が実行されます。
public static <T extends BaseObject<T>> List<Id<T>> findIdsByName(final Object api,
final String wsClassName, final String name)
throws Exception
{
nullCheck(api, "api");
nullCheck(wsClassName, "wsClassName");
final Class wsClass = getWsClass(wsClassName);
final List<Id<T>> resultList = new ArrayList<Id<T>>();
final String wsModelClassName = wsClass.getSimpleName();
final String methodName = makeInitialLowerCase(wsModelClassName) + "GetIds";
final Method getMethod = api.getClass().getMethod(methodName);
final List<Id<T>> idList = (List<Id<T>>) getMethod.invoke(api);
if (idList != null && idList.size() > 0)
{
for (final Id<T> id : idList)
{
if (name != null && id.getName() != null && name.equals(id.getName()))
{
resultList.add(id);
}
// allow for getting all objects of a type with a null name
if (name == null && id.getName() == null)
{
resultList.add(id);
}
}
}
return resultList;
}
3.6.7.2 Python
名前でオブジェクトを検索
以下の例は、特定のオブジェクト・タイプ(リソース)に一致するオブジェクトの問合せをループし、オブジェクト名を照合する方法を示しています。 一致するものが見つかった場合、オブジェクト全体が返されます:
def get_obj_from_name(s,baseUri,resource,obj_name):
uri=baseUri+'/'+resource
r=s.get(uri)
for obj in r.json():
if 'name' in obj.keys():
if obj['name']==obj_name:
return obj
raise Exception('Failed to find object named {name}'.format(name=obj_name))
この例では、オブジェクトのオブジェクト名が一意であり、一致する最初のアイテムが期待しているオブジェクトIDであると仮定しています。 環境内に同じオブジェクト名を持つ複数のアイテムがある可能性があります。 このような場合は、この関数を変更して一致のリストを生成し、代わりにこれを返す必要があります。 これは、この関数のJavaの例で取られたアプローチです。
名前によるオブジェクトIDの検索
以下に示すコード例は、特定のオブジェクト・タイプ(リソース)のIDリストを問合せしてループし、オブジェクト名と一致する簡単な関数を提供しています。 一致するものが見つかった場合は、IDが返されます:
def get_id_from_name(s,baseUri,resource,obj_name):
uri=baseUri+'/'+resource+'/id'
r=s.get(uri)
for obj in r.json():
if 'name' in obj.keys():
if obj['name']==obj_name:
return obj
raise Exception('Failed to find id for {name}'.format(name=obj_name))
この例では、オブジェクトのオブジェクト名が一意であり、一致する最初のアイテムが期待しているオブジェクトIDであると仮定しています。 環境内に同じオブジェクト名を持つ複数のアイテムがある可能性があります。 このような場合は、この関数を変更して一致のリストを生成し、代わりにこれを返す必要があります。 これは、この関数のJavaの例で取られたアプローチです。
WS-APIに関して、オブジェクトのIDには、オブジェクト名、オブジェクトを定義するためにAPIによって使用されるモデル・タイプ、オブジェクトを問合せするために使用されるURI、およびユニークID値。 ID値は通常、特定のオブジェクトを識別するためにURIで使用されますが、IDは通常、POSTリクエストまたはPUTリクエストの本文内でXMLまたはJSONオブジェクトとして渡されます。 このため、このドキュメントではIDとIDの値を区別しています。 この場合、IDオブジェクト全体が返されます。必要な情報の完全なコレクションが含まれているからです。
3.6.8 ネットワーク・ファイル・サーバーの検出
この例では、REST APIを使用してネットワーク・ファイル・サーバーをdiscoverする方法を示します。 クラスタ・ハートビート・デバイスに使用されるプール・ファイル・システムの格納など、Oracle VM内のさまざまな目的で共有記憶域が必要です。
ネットワーク・ファイル・サーバーは、共有記憶域を提供するために頻繁に使用されますが、使用環境内で使用できる唯一の共有記憶域の形式ではありません。 このため、新しい記憶域リソースを追加するときに使用する「記憶域接続」プラグインを指定する必要があります。 この場合、Oracle VMのインストール時に構成されたOracle Generic Network File Systemプラグインを使用します。 このため、APIリクエストで送信されるパラメータの1つとして必要なので、ファイラを設定する前にプラグイン・オブジェクトIDを取得する必要があります。
さらに、ネットワーク・ファイル・サーバーでは、ファイラ上で管理タスクを処理するために少なくとも1つの「管理サーバー」が指定されている必要があります。 これは、ご使用の環境で既に検出したサーバーの1つのオブジェクトIDでなければなりません。
この情報を入手したら、次のURIにPOSTリクエストを送信して、ネットワーク上のネットワーク・ファイル・サーバーを検出できます:
https://hostname:port/ovm/core/wsapi/rest/FileServer
ファイル・サーバー検出が完了した後、ファイル・サーバーのエクスポートをOracle VMで使用できるようにするために、通常はファイル・サーバーの更新を実行します。 これは、新しく追加されたファイル・サーバーのID値を取得し、次のURIにPUTリクエストを送信することによって実現されます:
https://hostname:port/ovm/core/wsapi/rest/FileServer/id/refresh
Oracle VM内でファイル・サーバーのエクスポートを使用できるようにするには、ファイル・サーバーで使用可能な各ファイル・システムに対してファイル・システムのリフレッシュを実行することも重要です。 これは、ファイルシステムごとに次のURIにPUTリクエストを送信することによって実現されます:
https://hostname:port/ovm/core/wsapi/rest/FileServer/id/refresh
特定のファイル・サーバー上でエクスポートされたすべてのファイル・システムの一覧を、更新後に次のURIにGETリクエストを送信することで取得できます:
https://hostname:port/ovm/core/wsapi/rest/FileServer/id/FileSystem/id
3.6.8.1 Java
サンプル・コードに含まれているWsDevClientクラスには、ネットワーク・ファイル・サーバーを検出する例は含まれていません。 確かに、Network File ServerはOracle VM環境内ですでに検出されており、ファイル・システムはすでにリフレッシュされていることが予想されます。 ただし、サンプル・コードに含まれるOvmWsRestClientクラスには、ネットワーク・ファイル・サーバーを完全に設定および構成するために必要なすべてのメソッドが含まれています。 以下の例は、これらのタスクを実行するために必要なステップを示しています。
このプロセスはかなり集中しているため、OvmWsRestClientクラスで使用できるメソッドの使用に集中しています。 これらのメソッドのコードを参考にして、実際にJersey RESTクライアントがOracle VM Manager REST APIに対して各問合せを実行する方法を確認することをお勧めします。
ネットワーク・ファイル・サーバーの検出
FileServerオブジェクトには、作成する前にいくつかのパラメータを設定する必要があります。 重要な点は、FileServerオブジェクトで使用する必要があるFile ServerのOracle VM Storage ConnectプラグインIDを取得する必要があることです。 一般的なOracle VM Storage Connectプラグインはインストール時に作成されます。 つまり、適切なプラグインを選択するには、既存のプラグインIDをループしてIDを取得する必要があります。 この例では、ネットワーク・ファイル・サーバーへの接続に使用できるOracle汎用ネットワーク・ファイル・システムを検索します。 次のコードは、testfileServerPluginIdというFileServerPlugin Idオブジェクト・インスタンスを生成します:
...
// Get a list of all File Server Plug-ins
final List<Id<FileServerPlugin>> fileServerPluginIds = api.fileServerPluginGetIds();
for (final Id<FileServerPlugin> fileServerPluginId : fileServerPluginIds)
{
if (fileServerPluginId.getName().equals("Oracle Generic Network File System"))
{
testfileServerPluginId = fileServerPluginId;
}
}
オブジェクトの名前に基づいてIDを検索するこのプロセスは、コードを通じて頻繁に実行できる操作であるため、「名前によるオブジェクトIDの検索」で説明されているように、OvmWsClientToolsクラスのツールのいずれかを使用する典型的なシナリオです。
FileServerオブジェクトの作成には、ネットワーク・ファイル・サーバーの管理サーバーとして構成する各サーバーのサーバーIDオブジェクト・インスタンスのリストも必要です。 これを1つ以上の特定のサーバーに絞り込むことができます。 わかりやすくするために、管理サーバーとして使用されるすべてのサーバーIDを含むリストを作成します:
// Get a list of all Servers (to keep things simple, all servers are added) final List<Id<Server>> servIds = api.serverGetIds();
これで、FileServerオブジェクトを設定し、fileServerDiscoverメソッドを呼び出してFileServerオブジェクトを作成できます。 waitForJobCompleteメソッドからFileServer ID値を取得して、ネットワーク・ファイル・サーバーが検出された後に実行する必要がある更新タスクに使用できるようにします。
// Discover FileServer
FileServer fileserver = new FileServer();
// Set the Name for your FileServer object
fileserver.setName("MyNFSServer");
// Set the AccessHost to the IP address or Hostname of the FileServer
fileserver.setAccessHost("10.172.76.125");
// Set the Admin Server IDs, this is a list of ids
// In this example we are adding all servers in the environment
fileserver.setAdminServerIds(servIds);
// Set the Fileserver Type, can be LOCAL, NETWORK or UNKNOWN
fileserver.setFileServerType(FileServer.FileServerType.NETWORK);
// Set the Plugin ID
fileserver.setFileServerPluginId(testfileServerPluginId);
// Set the FileServer as having Uniform Exports
fileserver.setUniformExports(true);
final Job fileserverCreateJob = api.fileServerDiscover(fileserver);
System.out.println("create fileserver job id: " + fileserverCreateJob.getId());
fsid=waitForJobComplete(api, fileserverCreateJob, FileServer.class);
ネットワーク・ファイル・サーバーをリフレッシュ
ネットワーク・ファイル・サーバーが正常に検出されたら、Oracle VM Managerで使用する前にリフレッシュする必要があります。 これは、そのIDを取得してfileServerRefreshメソッドを呼び出すことで実現できます:
// Create a Job for FileServer Refreshing
final Job fileserverRefreshJob = api.fileServerRefresh(fsid);
System.out.println("refresh fileserver job id: " + fileserverRefreshJob.getId());
waitForJobComplete(api,fileserverRefreshJob);
ファイル・システムのリフレッシュ
最後に、Oracle VM環境で使用できるようにファイル・システムをリフレッシュする必要があります。 これを行うには、FileServerモデル・タイプによって公開されるgetFileSystemIdsメソッドを使用して、ファイル・システムIDのリストを設定することができます。 このリストをループして、各ファイル・システムIDのfileSystemRefreshメソッドを呼び出します:
// For all of the fileSystems on the FileServer, do a refresh
fileserver = api.fileServerGetById(fsid);
final List<Id<FileSystem>> fileSystemIds = fileserver.getFileSystemIds();
for (final Id<FileSystem> fileSystemId : fileSystemIds)
{
final Job filesystemRefreshJob = api.fileSystemRefresh(fileSystemId);
waitForJobComplete(api,file systemRefreshJob);
}
3.6.8.2 Python
ネットワーク・ファイル・サーバーの検出
この例では、いくつかのタスクを実行する必要があります。 POSTリクエストで送信する必要があるJSONオブジェクトには、ファイラで管理タスクを実行するために使用される管理サーバーのサーバーIDが含まれています。 Oracle VMがファイラに接続するために使用するOracle VM Storage ConnectプラグインのIDも含める必要があります。 これを処理するために、すべてのFileServerPluginオブジェクト型をループして一致を実行し、そこからIDを抽出できます:
r=s.get(baseUri+'/FileServerPlugin/id')
for id in r.json():
if id['name']=='Oracle Generic Network File System':
plugin_id=id
これは、指定された管理サーバーのIDを取得するなど、環境内の他のオブジェクトに対して繰り返す必要があるアクションのタイプであるため、名前でオブジェクトを検索するユーティリティを作成するのが一般的です。 このような状況では、単に名前によるオブジェクトIDの検索で定義したget_id_from_name関数を使用します:
pluginname="Oracle Generic Network File System" adminserver="1.example.org" plugin_id=get_id_from_name(s,baseUri,'FileServerPlugin',pluginname) admin_id=get_id_from_name(s,baseUri,'Server',adminserver)
これで、ネットワーク・ファイル・サーバー検出用のJSONオブジェクトを作成し、最初のPOSTリクエストを送信できます:
...
data={
'name': 'MyNFSFiler',
'accessHost': '10.172.76.125',
'fileServerType': 'NETWORK',
'fileServerPluginId': plugin_id,
'adminServerIds': [admin_id],
'uniformExports': True,
}
uri='{base}/FileServer'.format(base=baseUri)
r=s.post(uri,data=json.dumps(data))
job=r.json()
# wait for the job to complete
filer_id=wait_for_job(job['id']['uri'],s)
ネットワーク・ファイル・サーバーをリフレッシュ
ネットワーク・ファイル・サーバーによってエクスポートされたファイル・システムを使用するには、ネットワーク・ファイル・サーバーを更新する必要があります:
# get the idval for the nfs
uri='{base}/FileServer/{nfsid}/refresh'.format(base=baseUri,nfsid=filer_id['value'])
r=s.put(uri)
job=r.json()
# wait for the job to complete
wait_for_job(job['id']['uri'],s)
ファイル・システムのリフレッシュ
最後に、ネットワーク・ファイル・サーバーによってエクスポートされた各ファイル・システムのファイル・システムID値を取得し、それぞれのファイル・システムを更新する必要があります:
uri='{base}/FileServer/{nfsid}/FileSystem/id'.format(base=baseUri,nfsid=filer_id['value'])
r=s.get(uri)
fsids=r.json()
for id in fsids:
uri='{base}/FileSystem/{id}/refresh'.format(base=baseUri,id=id['value'])
r=s.put(uri)
job=r.json()
# wait for the job to complete
wait_for_job(job['id']['uri'],s)
3.6.9 サーバー・プールの作成
ご使用の環境内でOracle VM Serversを検出すると、サーバー・プールを作成できます。 「サーバー・プール」は、「仮想マシン」の移行、HAなどを実行する物理リソースと仮想リソースのdomainです。
サーバー・プールを作成するには、仮想IPアドレスをオプションで指定することができます(使いやすさの理由から、意味のある名前)。 仮想IPアドレスは、Oracle VM Managerの3.4リリースで非推奨されましたが、以前のリリースのOracle VM Serversをサーバー・プール内に組み込む場合は、下位互換性のために構成することができます。
HAの詳細については、『Oracle VM概要ガイド』を参照してください。
サーバー・プールは、POSTリクエストを次のURIに送信することによって作成されます:
https://hostname:port/ovm/core/wsapi/rest/ServerPool
POSTリクエストの本文には、セッション中に使用するインターネット・メディア・タイプ用に設定した形式で設定する属性の値が含まれている必要があります。 詳細については、3.4項、「REST APIで使用されるインターネット・メディア型(JSONおよびXML)」を参照してください。
3.6.9.1 Java
Javaでサーバー・プールを作成するのはかなり簡単です。 WsDevClientクラス(サンプル・アプリケーション)には、次の例が含まれています:
...
// Create a new server pool
ServerPool testPool = new ServerPool();
testPool.setName(testServerPoolName);
final Job serverPoolCreateJob = api.serverPoolCreate(testPool);
System.out.println("create server pool job id: " + serverPoolCreateJob.getId());
testPoolId = waitForJobComplete(api, serverPoolCreateJob, ServerPool.class);
この例では、SDKに含まれるOracle VM Managerクライアント・ライブラリによって提供されるServerPoolモデル・タイプを使用して、新しいServerPoolオブジェクトを作成します。 このモデル・タイプを使用して、オブジェクトに固有のさまざまなパラメータを設定します。 この場合、必要なサーバー・プール名パラメータを設定します。 このコード例では、WsDevClient.propertiesファイルで参照されているtestServerPoolName変数に定義されている値に設定されています。
前に説明したように、Jobオブジェクトは、serverPoolCreateメソッドによって提供される戻り値にすぐに取り込まれます。 このオブジェクトを使用してwaitForJobCompleteメソッドを呼び出します。これにより、サーバー・プール・オブジェクトが正常に作成されてから続行されます。 waitForJobCompleteメソッドの戻り値を使用してtestPoolId値を設定します。この値は、後で新しく作成したサーバー・プールの他のサーバー・プール関連のアクティビティを処理するために使用します。
serverPoolCreateメソッドは、次のコードが定義されているOvmWsRestClientクラスから呼び出されます:
@Override
public Job serverPoolCreate(final ServerPool serverPool) throws WsException
{
return create(serverPool);
}
ご覧のとおり、このアクションでは、OvmWsRestClient内で定義されたより汎用的なメソッドを使用して、ObjectTypeを作成するために適用できます。 このコードでは、Jersey Builderを使用して必要なRESTリクエストを作成し、メソッドに渡されるJavaオブジェクトを使用して必要なXMLを作成します:
public <T extends BaseObject<T>> Job create(final T newObject) throws WsException
{
try
{
final Builder b = getResourceForType(newObject.getClass());
return b.type(getMediaType()).post(Job.class, createJAXBElement(newObject));
}
catch (final UniformInterfaceException ex)
{
throw convertException(ex);
}
}
3.6.9.2 Python
前の例の3.6.5項、「サーバーの検出」と同様に、セッション・オブジェクトを使用してPOSTリクエストを送信することができます。ここでは、serverPoolオブジェクトが含まれています。このオブジェクトはPython辞書として記述され、送信時にJSON文字列に変換されます。 この場合、辞書には必要なサーバー・プール名だけが含まれますが、下位互換性のためにオプションの仮想IPアドレスなどの他の属性も等しく含めることができます。 コードの例を次に示します:
...
data = {
'name': 'MyServerPool',
}
uri='{base}/ServerPool'.format(base=baseUri)
r=s.post(uri, data=json.dumps(data))
job=r.json()
# wait for the job to complete
sp_id=wait_for_job(job['id']['uri'],s)
前と同じように、Oracle VM Managerによって返されるレスポンス・コンテンツには、サーバー・プールを追加するために作成されたジョブを記述するJSONオブジェクトが含まれています。 このコンテンツを処理する方法の詳細については、「ジョブのステータスを追跡」を参照してください。 このサーバー・プールが問題なく作成されていると仮定すると、wait_for_job関数は作成されたサーバー・プールのIDを返す必要があるため、wait_for_job関数によって返された内容でsp_id変数を設定します。 これにより、クラスタリングの設定などの他の即時アクションを簡単に実行することができます。
3.6.10 クラスタリング
HA機能を構成するには、クラスタを構成してクラスタ・ハートビート・デバイスを作成する必要があります。
クラスタは「サーバー・プール」のコンポーネントであり、POSTリクエストをサーバー・プールURIに送信することによって作成されます:
https://hostname:port/ovm/core/wsapi/rest/ServerPool/id/Cluster
クラスタ・ハートビート・デバイスは、クラスタ自体のコンポーネントであり、POSTリクエストをクラスタURIに送信することによって作成されます:
https://hostname:port/ovm/core/wsapi/rest/Cluster/id/ClusterHeartbeatDevice
3.6.10.1 Java
クラスタ・オブジェクトの作成
Oracle VMに関しては、クラスタはサーバー・プールの子オブジェクトです。 サンプル・コードのWsDevClientクラスには、前の例で作成したサーバー・プールに対してクラスタ・オブジェクトを作成する例が含まれています。 コードは簡単です:
...
// Create a new cluster
Cluster testCluster = new Cluster();
testCluster.setName(testClusterName);
final Job clusterCreateJob = api.serverPoolCreateCluster(testPoolId, testCluster);
System.out.println("create cluster job id: " + clusterCreateJob.getId());
testClusterId = waitForJobComplete(api, clusterCreateJob, Cluster.class);
クラスタ・オブジェクトでは、オブジェクト・インスタンスに名前が設定されている必要があります。 これが完了すると、serverPoolCreateClusterメソッドがOvmWsRestClientクラスから呼び出されます。 2つのパラメータがこのメソッドに渡されることに注意してください: サーバー・プールの作成中に取得されたサーバー・プールID値、およびクラスタ・オブジェクト自体です。 serverPoolCreateClusterメソッドのコードを以下に示します:
@Override
public Job serverPoolCreateCluster(final Id<ServerPool> serverPoolId,
final Cluster cluster)
throws WsException
{
return createChildObject(serverPoolId, cluster);
}
予想どおり、このメソッドは、より汎用的なメソッドを使用して、任意のObjectTypeの子オブジェクトを作成できるようにします。 このメソッドは、このガイドの後半で他のアクションで再利用されます。 再度、OvmWsRestClientのcreateChildObjectメソッドは、Jersey Builderを使用してXMLメッセージを作成します:
public <O extends BaseObject<O>, P extends BaseObject<P>> Job
createChildObject(final Id<P> parentId, final O newObject, final
Map<String, Object> queryParameters)
throws WsException
{
try
{
final Builder b = getResourceForCreateChild(parentId, newObject.getClass(),
queryParameters);
return b.type(getMediaType()).post(Job.class, createJAXBElement(newObject));
}
catch (final UniformInterfaceException ex)
{
throw convertException(ex);
}
}
クラスタ・ハートビート・デバイスを作成
クラスタには、サーバー・プールに追加されるすべてのサーバーにアクセスできる共有記憶域に配置できるハートビート・デバイスが必要です。 この目的のために、クラスタ・オブジェクトの子オブジェクトとしてハートビート・デバイスを作成する必要があります。 WsDevClientクラスには、次の例が含まれています:
ClusterHeartbeatDevice hbDevice = new ClusterHeartbeatDevice();
hbDevice.setName(clusterHeartbeatDeviceName);
hbDevice.setStorageType(clusterHeartbeatStorageDeviceType);
switch (clusterHeartbeatStorageDeviceType)
{
case NFS:
hbDevice.setNetworkFileSystemId(clusterHeartbeatNetworkFileSystem.getId());
break;
case STORAGE_ELEMENT:
hbDevice.setStorageElementId(clusterHeartbeatStorageElement.getId());
break;
default:
throw new Exception(
"Invalid cluster heartbeat storage device type: " +
clusterHeartbeatStorageDeviceType);
}
final Job hbDeviceCreateJob = api.clusterCreateHeartbeatDevice(testClusterId, hbDevice);
System.out.println("create cluster heartbeat device job id: " +
hbDeviceCreateJob.getId());
testHeartbeatDeviceId = waitForJobComplete(api, hbDeviceCreateJob,
ClusterHeartbeatDevice.class);
クラスタ・ハートビート・デバイスには、オブジェクトを作成する前に設定する必要があるいくつかのパラメータが必要です。 この例では、コードはWsDevClient.propertiesファイルで定義された変数に基づいてさまざまなパラメータを設定します。 これにより、NFS記憶域リポジトリを使用するか、ISCSI LUNなどの代替オプションを使用するかを定義するオプションを、サンプル・クライアントのユーザーに提供します。 選択した記憶域デバイスのタイプに応じて、Oracle VM Manager内の記憶域IDを示す適切なハートビート・デバイス・パラメータを設定する必要があります。
ハートビート・デバイス・オブジェクト・パラメータが設定されると、clusterCreateHeartbeatDeviceメソッドがOvmWsRestClientクラスから呼び出されます。 ハートビート・デバイスはクラスタの子オブジェクトであるため、ハートビート・デバイス・オブジェクトと同様に、親クラスタID値が必要です:
@Override
public Job clusterCreateHeartbeatDevice(final Id<Cluster> clusterId, final
ClusterHeartbeatDevice heartbeatDevice)
throws WsException
{
return createChildObject(clusterId, heartbeatDevice);
}
期待どおり、このメソッドは前述のより汎用的なcreateChildObjectを呼び出します。
3.6.10.2 Python
クラスタ・オブジェクトの作成
今度はクラスタを作成するために、我々はサーバー・プールIDを使用して構築するURIにPOSTリクエストを送信します。 サーバー・プールを作成したときからのサーバー・プールIDの値を引き続き取得できますが、「名前によるオブジェクトIDの検索」で定義したget_id_from_name関数を使用してこの値を取得することもできます :
...
data={'name':'MyServerPool_cluster'}
uri='{base}/ServerPool/{spid}/Cluster'.format(base=baseUri, spid=sp_id['value'])
r=s.post(uri,data=json.dumps(data))
job=r.json()
# wait for the job to complete
cluster_id=wait_for_job(job['id']['uri'],s)
このコードでは、sp_idにサーバー・プールID用に返されたディクショナリが設定されていることを前提としています。 投稿しているURLに、正しいサーバー・プールにクラスタをアタッチするために、サーバー・プールID値を指定します。 もう一度、前に定義した関数を使用してジョブが完了するのを待って、ジョブが正常に完了してクラスタIDを返すことを期待します。 この新しいクラスタ・オブジェクトにアタッチされたクラスタ・ハートビート・デバイスを作成できるように、これが必要です。
クラスタ・ハートビート・デバイスの作成
最後に、クラスタ・ハートビート・デバイスを作成するには、ハートビート・デバイスに使用できる共有記憶域リポジトリを選択する必要があります。 記憶域リポジトリをまだ設定していない場合は、続行する前に保存リポジトリを設定する必要があります。 詳細については、3.6.8項、「ネットワーク・ファイル・サーバーの検出」と3.6.12項、「記憶域リポジトリの作成」を参照してください。 この例では、すでにOracle VM Manager内で使用可能なNFSリポジトリを使用し、サーバー・プール・ファイル・システムとして機能するためにすでに予約しているファイル・システムのIDを取得します。 このために、前に[1]で定義したget_id_from_name関数を使用します :
... nfs_id=get_id_from_name(s,baseUri,'FileSystem','nfs on 10.172.76.125:/mnt/vol1/poolfs01') data={ 'name':'MyServerPool_cluster_heartbeat', 'networkFileSystemId': nfs_id, 'storageType':'NFS', } uri='{base}/Cluster/{cluster_id}/ClusterHeartbeatDevice'.format( base=baseUri, cluster_id=cluster_id['value']) r=s.post(uri,data=json.dumps(data)) job=r.json() # wait for the job to complete cl_hb_id=wait_for_job(job['id']['uri'],s)
3.6.11 サーバー・プール内のサーバーの管理
サーバー・プールが完全に設定されたら、サーバー・プールに属するサーバーを管理できます。
サーバー・プールにサーバーを追加するには、次のURIにPUTリクエストを送信します:
https://hostname:port/ovm/core/wsapi/rest/ServerPool/id/addServer
同様に、サーバーを削除するには、PUTリクエストを次の場所に送信します:
https://hostname:port/ovm/core/wsapi/rest/ServerPool/id/removeServer
どちらの場合でも、リクエストの本文には、管理しているサーバーを記述するXMLまたはJSONオブジェクトが含まれている必要があります。 これらの2つのリクエスト・タイプは、3.3項、「どのURIマッピングが利用可能で、どのように機能するか」で説明されているアクション・スタイルのアクティビティの良い例です。
これらの操作は、サーバー・オブジェクトとサーバー・プール・オブジェクトの間の関連付けを作成することに注意してください。 多くの点で、サーバーはサーバー・プールの子オブジェクトとして扱われるように見えるかもしれませんが、メソッドは同様に動作する可能性がありますが、厳密にはそうではありません。 子オブジェクトの操作と関連付けの操作を区別するために、APIは、関連付けを追加または削除するメソッドに対してadd/remove命名法を使用し、子オブジェクトを追加または削除するメソッドの作成/削除命名法を使用します。 以下の例を勉強すると、これはより明確になるかもしれません。
3.6.11.1 Java
WsDevClientクラスには、サーバーがテスト・サーバー・プールに追加される例が含まれています。 コードは、サーバーが既に別のサーバー・プールに属しているかどうかをチェックし、サーバー・プールからサーバー・プールを削除します。 その後、追加操作を実行します。 これは、両方のアクティビティの例を示しています。 簡単な説明のために、このガイドでは、各アクションの実行に必要な実際の操作に焦点を当てています。
サーバー・プールへのサーバーの追加。
サーバー・オブジェクトは技術的には子オブジェクトではありませんが、サーバーがサーバー・プールに追加された場合、このアクションの子オブジェクトであるかのように扱われます。 したがって、serverPoolAddServer関数にはサーバー・プールID値とサーバーIDオブジェクトの両方を渡す必要があります。 サンプル・コードのWsDevClientクラスから抽出した、これを行うコードは次のとおりです:
...
final Job job = api.serverPoolAddServer(testPoolId, testServer.getId());
System.out.println("add server to pool job id: " + job.getId());
waitForJobComplete(api, job);
アクションは親オブジェクトに子オブジェクトを追加するのと事実上同じであるため、OvmWsRestClientクラスのserverPoolAddServerメソッドは、より汎用的なaddChildObjectメソッドを使用します:
@Override
public Job serverPoolAddServer(final Id<ServerPool> serverPoolId,
final Id<Server> serverId)
throws WsException
{
return addChildObject(serverPoolId, serverId);
}
addChildObjectメソッド・コードは次のとおりです:
public Job addChildObject(final Id<?> parent, final Id<?> child) throws WsException
{
try
{
return action(parent, "add" + getSimpleName(child.getType()), child);
}
catch (final UniformInterfaceException ex)
{
throw convertException(ex);
}
}
サーバー・プールからのサーバーの削除。
Javaのサーバー・プールからサーバーを削除することは、サーバー・プールを追加するのと同じプロセスです。 サンプル・コードのWsDevClientクラスから抽出されたサンプル・コードは次のとおりです:
final Id<ServerPool> testServerPoolId = testServer.getServerPoolId();
Job job = api.serverPoolRemoveServer(testServerPoolId, testServer.getId());
System.out.println("remove server from pool job id: " + job.getId());
waitForJobComplete(api, job);
他のより一般的な操作と同様に、OvmWsRestClientクラスのserverPoolRemoveServerメソッドは、実際には汎用のremoveChildObjectメソッドを参照します:
public Job removeChildObject(final Id<?> parent, final Id<?> child)
throws WsException
{
try
{
return action(parent, "remove" + getSimpleName(child.getType()), child);
}
catch (final UniformInterfaceException ex)
{
throw convertException(ex);
}
}
サーバー・プールからサーバーを削除する動作は、基本的に親から子オブジェクトを削除する動作と同じですが、サーバーは実際には子オブジェクトではありません。 この区別は重要です。サーバー・プール・オブジェクトを削除してもサーバーが削除されないためです。 技術的には、Oracle VM Managerでは、すべてのサーバーがサーバー・プールから削除されるまでサーバー・プールを削除することはできませんが、区別は残ります。
3.6.11.2 Python
サーバー・プールへのサーバーの追加。
サーバー・プールに追加する各サーバー名のIDを検索することによって、作成したサーバー・プールにサーバーを追加するのは簡単です:
...
svrid=get_id_from_name(s,baseUri,'Server','1.example.org')
uri='{base}/ServerPool/{spid}/addServer'.format(base=baseUri,spid=sp_id['value'])
r=s.put(uri,data=json.dumps(svrid))
job=r.json()
# wait for the job to complete
wait_for_job(job['id']['uri'],s)
前の例のいずれかから、sp_id変数が設定されていることを前提としています。 このセットがない場合は、構成するサーバー・プールのIDを設定する必要があります。
サーバー・プールからのサーバーの削除。
サーバーの追加に使用したロジックと同じロジックを使用して、作成したサーバー・プールからサーバーを削除することも簡単です:
...
svrid=get_id_from_name(s,baseUri,'Server','1.example.org')
uri='{base}/ServerPool/{spid}/removeServer'.format(base=baseUri,spid=sp_id['value'])
r=s.put(uri,data=json.dumps(svrid))
job=r.json()
# wait for the job to complete
wait_for_job(job['id']['uri'],s)
前の例のいずれかから、sp_id変数が設定されていることを前提としています。 このセットがない場合は、構成するサーバー・プールのIDを設定する必要があります。
3.6.12 記憶域リポジトリの作成
ネットワーク・ファイル・サーバー上の公開ファイル・システムを検出し、選択したファイル・システムをリフレッシュした場合は、記憶域リポジトリを作成できます。 記憶域リポジトリは、作成されるファイル・システムの子オブジェクトです。 この例では、ネットワーク・ファイル・サーバー上のファイル・システムを使用していますが、ISCSI LUNなどの代替共有記憶域にリポジトリを作成することもできます。
次のURIにPOSTリクエストを送信して記憶域リポジトリを追加します:
https://hostname:port/ovm/core/wsapi/rest/FileSystem/id/Repository
3.6.12.1 Java
サンプル・コードのWsDevClientクラスには、リポジトリを作成する方法の例が含まれていません。 サンプル・コードでは、ご使用の環境内でリポジトリがすでに作成されており、その詳細がWsDevClient.propertiesファイルで提供されていると想定しています。
記憶域リポジトリの作成は複雑ではなく、他のサンプルやSDKに含まれているAPIドキュメントから外挿することもできます。 この例では、記憶域リポジトリを作成するために既に学んだ情報を使用します。
記憶域リポジトリは、FileSystemオブジェクトの子オブジェクトです。 したがって、記憶域リポジトリを作成する必要があるFileSystemオブジェクトのIDを取得する必要があります。 次のループを使用して、testfileSystemIdに、パス"10.172.76.125:/mnt/vol1/repo01":"にあるファイル・システムのIDを入力できます:
...
fileserver = api.fileServerGetById(fsid);
final List<Id<FileSystem>> fileSystemIds = fileserver.getFileSystemIds();
for (final Id<FileSystem> fileSystemId : fileSystemIds)
{
if (fileSystemId.getPath().equals("10.172.76.125:/mnt/vol1/repo01")){
testfileSystemId = fileSystemId;
}
}
OvmWsRestClientクラスによって提供されるfileSystemCreateRepositoryメソッドを使用して、ファイル・システムIDを取得したら、リポジトリを作成するのは簡単です:
// Create a repository
Repository myrepo = new Repository();
myrepo.setName("MyRepository");
final Job repositoryCreateJob = api.fileSystemCreateRepository(testfileSystemId,
myrepo);
System.out.println("create repository job id: " + repositoryCreateJob.getId());
myrepoId = waitForJobComplete(api, repositoryCreateJob, Repository.class);
fileSystemCreateRepositoryメソッドのコードを簡単に見れば、このメソッドでは「クラスタ・オブジェクトを作成しました」のときに最初に遭遇した汎用のcreateChildObjectメソッドが使用されていることが確認されます。
@Override
public Job fileSystemCreateRepository(final Id<FileSystem> fileSystemId,
final Repository repository) throws WsException
{
return createChildObject(fileSystemId, repository);
}
3.6.12.2 Python
パスからファイル・システムIDを取得
このガイドの前半では、オブジェクト名に基づいてオブジェクトのIDを取得する関数を作成する方法について説明しました。 状況によっては、オブジェクトの名前がOracle VM Manager内で変更可能であり、他の属性が変更できないため、これは最善の方法ではない可能性があります。 これが真実で、これが非常に役に立つ特別なケースは、FileSystemオブジェクトのpathです。 「名前によるオブジェクトIDの検索」で定義したget_id_from_name関数を変更することで、FileSystemオブジェクトでこの特定のマッチングを実行できる関数を作成することはかなり簡単です:
def get_fsid_from_path(s,baseUri,path):
uri=baseUri+'/FileSystem/id'
r=s.get(uri)
for obj in r.json():
if 'path' in obj.keys():
if obj['path']==path:
return obj
raise Exception('Failed to find id for {path}'.format(name=path))
リポジトリの作成
この例では、get_fsid_from_path関数を使用して、パス"10.172.76.125:/mnt/vol1/repo01""にあるNFSファイラ上のファイル・システムのファイル・システムID値を取得します。 この値を使用して、リポジトリの作成に必要なPOSTリクエストを送信する必要があるURIを構築します。
... fsid=get_fsid_from_path(s,baseUri,"10.172.76.125:/mnt/vol1/repo01") data={ 'name': 'MyRepository', } uri='{base}/FileSystem/{fsid}/Repository'.format(base=baseUri, fsid=fsid['value']) r=s.post(uri,data=json.dumps(data)) job=r.json() # wait for the job to complete repo_id=wait_for_job(job['id']['uri'],s)
3.6.13 記憶域リポジトリの提示
記憶域リポジトリを作成したら、それを提示するOracle VM Serversを決定する必要があります。
次のURIにPUTリクエストを送信して、リポジトリをサーバーに提示する:
https://hostname:port/ovm/core/wsapi/rest/Repository/id/present
メッセージの本文には、リポジトリを表示するServer IDオブジェクトのXML表現が含まれていなければなりません。
3.6.13.1 Java
WsDevClientクラスには、既に提示されていない場合に、サーバーにリポジトリを提示する方法を示す例があります。 リポジトリ・モデル・タイプを使用すると、getPresentedServerIdsメソッドを使用して、リポジトリがすでに提示されている場所を確認できます。
リポジトリをサーバーに提示することは、リポジトリに対して実行されるアクションです。 次のコードは、WsDevClientクラスから抽出されています:
...
final Repository testRepository = api.repositoryGetById(testRepoId);
if (testRepository.getPresentedServerIds() == null ||
!testRepository.getPresentedServerIds().contains(testServerId))
{
repoPresentJob = api.repositoryPresent(testRepoId, testServerId);
System.out.println("present repository job id: " + repoPresentJob.getId());
waitForJobComplete(api, repoPresentJob);
}
repositoryPresentメソッドは、OvmWsRestClientクラスから呼び出されます:
@Override
public Job repositoryPresent(final Id<Repository> repositoryId,
final Id<Server> serverId)
throws WsException
{
return action(repositoryId, "present", serverId);
}
このメソッドは、同じクラスのより汎用的なアクション・メソッドを呼び出します。 アクション・メソッドは、最終的には、RestClientクラスのactionWithQueryParametersメソッドを呼び出すことに解決されます。このメソッドを使用すると、アクション・イベントのAPIのObjectTypeに追加のパラメータを送信できます。
public Job actionWithQueryParameters(final Id<?> id, final String actionName, final
Map<String, Object> queryParameters, final Object argument)
throws WsException
{
if (argument instanceof List || argument instanceof Map)
{
throw new WsException(new WsErrorDetails(null,
"Invalid use of a list or map in argument"));
}
try
{
final Builder b = getResourceForAction(id, actionName, queryParameters);
if (argument != null)
{
b.type(getMediaType()).entity(createJAXBElement(argument));
}
return b.put(Job.class);
}
catch (final UniformInterfaceException ex)
{
throw convertException(ex);
}
}
actionWithQueryParametersメソッドは、Jersey Builderを使用して、照会する正しいURIを構成し、送信する必要があるXMLオブジェクトを作成し、HTTP PUTリクエストをセットURIに送信します。 最終的にレスポンスをJobオブジェクトとして返します。
3.6.13.2 Python
このリクエストでは、リポジトリを提示するサーバーのサーバーIDオブジェクトを取得する必要があります。 これを実現するには、「名前によるオブジェクトIDの検索」で定義したget_id_from_name関数を使用します。
...
servid=get_id_from_name(s,baseUri,'Server',"1.example.com")
uri='{base}/Repository/{rid}/present'.format(base=baseUri, rid=repo_id['value'])
r=s.put(uri,data=json.dumps(servid))
job=r.json()
# wait for the job to complete
wait_for_job(job['id']['uri'],s)
3.6.14 ネットワークの作成
Oracle VM Manager内で異なるネットワーク・タイプを作成することは可能です。 この例では、単一のサーバーに限定されたローカル・ネットワークと同様に、標準ネットワーク・オブジェクトを作成する方法を示します。
使用する環境用の標準ネットワークを作成するには、次のURIにPOSTリクエストを送信します:
https://hostname:port/ovm/core/wsapi/rest/Network
環境に適したローカル・ネットワークを作成するには、実行するOracle VM Serverにアタッチする必要があります。 これを行うには、次のURIにPOSTリクエストを送信します:
https://hostname:port/ovm/core/wsapi/rest/Server/id/Network
3.6.14.1 Java
ネットワークの作成
ネットワーク・オブジェクトはそれ自体で作成するのが簡単で、ネットワークのName属性以外が設定されている必要はありません。 WsDevClientには、次のサンプル・コードが含まれています:
...
Network network = new Network();
network.setName(testNetworkName);
network.setDescription("Creating a test network named " + testNetworkName);
final Job networkCreateJob = api.networkCreate(network);
System.out.println("create network job id: " + networkCreateJob.getId());
testNetworkId = waitForJobComplete(api, networkCreateJob, Network.class);
予想通り、OvmWsRestClientクラスのnetworkCreateメソッドであるREST APIの観点から、このガイドの他の例で説明するより汎用的なcreateメソッドを呼び出します:
@Override
public Job networkCreate(final Network network) throws WsException
{
return create(network);
}
サーバーのローカル・ネットワークの作成
ローカル・ネットワークは、別の種類のフラグが付けられており、アタッチされているサーバー・オブジェクトに対してAPI呼び出しを行う必要がある点で、他のネットワーク・タイプとは異なります。 これは、ローカル・ネットワークがサーバー・オブジェクトの真の子オブジェクトであるためです。 これは、それらが作成されたサーバーと常に関連しており、サーバーが削除されている場合は、サーバー上に作成されたすべてのローカル・ネットワークも同時に削除されることを意味します。 次のサンプル・コードは、SDKに含まれるWsDevClientクラス内に存在します:
// Create a new server local network
Network serverLocalNetwork = new Network();
serverLocalNetwork.setName("MyTestServerLocalNetwork");
testServerId = testServer.getId();
serverLocalNetwork.setServerId(testServerId);
final Job localNetworkCreateJob = api.serverCreateNetwork(testServerId, network);
System.out.println("create server local network job id: " +
networkCreateJob.getId());
testServerLocalNetworkId = waitForJobComplete(api, localNetworkCreateJob,
Network.class);
serverCreateNetworkは、ローカル・ネットワークが作成されているサーバーのIDを要求します。 OvmWsRestClientクラスのメソッドをチェックすると、メソッドがより汎用的なcreateChildObjectメソッドを使用して、POSTリクエストを実行するために必要なXMLとURIを構築することが確認されます。
3.6.14.2 Python
ネットワークの作成
Pythonでネットワークを作成するのは簡単です。 APIによって予期されるJSONオブジェクトは、ネットワーク名とオプションで説明で構成されます。 以下のコードは、前の例で構築されています:
...
data = {
'name':'MyNetwork',
'description': 'A test network using the REST API',
}
uri='{base}/Network'.format(base=baseUri)
r=s.post(uri,data=json.dumps(data))
job=r.json()
# wait for the job to complete
net_id=wait_for_job(job['id']['uri'],s)
サーバーのローカル・ネットワークの作成
特定のサーバーのローカル・ネットワークを作成するには、「名前によるオブジェクトIDの検索」で定義したget_id_from_name関数を使用して、特定のサーバーのIDオブジェクトを取得します。 POSTリクエストを送信するためのJSON本文を構築し、URIを構築してサーバーのローカル・ネットワークを作成することができます:
... svr_id=get_id_from_name(s,baseUri,'Server','1.example.com') data = { 'name': 'MyLocalNetwork', 'description': 'Test network for 1.example.com', } uri='{base}/Server/{sid}/Network'.format(base=baseUri,sid=svr_id['value']) r=s.post(uri,data=json.dumps(data)) job=r.json() # wait for the job to complete localnet_id=wait_for_job(job['id']['uri'],s)
3.6.15 仮想マシンの作成
この項では、「仮想マシン」を作成する方法について説明します。 仮想マシンの構成はさまざまで、独自の要件に合わせてAPIの他の側面を調べることができます。 与えられた例は、始めに基本的なガイドラインを示しています。
REST APIを使用して仮想マシンを作成するには、POSTリクエストを送信します:
https://hostname:port/ovm/core/wsapi/rest/Vm
リクエストの本文内容には、仮想マシン・オブジェクトのXML表現が含まれている必要があります。仮想マシンには、仮想マシンをホストするサーバー・プールIDも含める必要があります。
3.6.15.1 Java
WsDevClientクラスには、仮想マシンの作成例が含まれています:
...
Vm testVm = new Vm();
testVm.setVmDomainType(VmDomainType.XEN_HVM);
testVm.setName(testVmName);
testVm.setRepositoryId(testRepoId);
final Job vmCreateJob = api.vmCreate(testVm, testPoolId);
System.out.println("create vm job id: " + vmCreateJob.getId());
testVmId = waitForJobComplete(api, vmCreateJob, Vm.class);
このコードでは、仮想マシンの基本属性が作成される前に設定されています。 実際、仮想マシンに固有の多数の属性があり、仮想マシンの構成方法を制御するように設定できます。 ここでは最も基本的な属性が選択されて、Xenハードウェア仮想化を使用して仮想マシンを作成し、その構成はWsDevClient.propertiesファイルに定義されているリポジトリに配置されています。
また、vmCreateメソッドでは、仮想マシンが正しいサーバー・プール内に作成されるように、サーバー・プールIDを指定する必要があります。 実際、このメソッドは、より一般的なcreateメソッドを呼び出す前に、VMオブジェクトのServerPoolId属性の値を設定します:
@Override
public Job vmCreate(final Vm vm, final Id<ServerPool> serverPoolId) throws WsException
{
vm.setServerPoolId(serverPoolId);
return create(vm);
}
WsDevClientクラスは、サーバー・プールの関連付けの削除とリストア、属性の基本的な変更、VNICの割り当て、仮想マシンのkillなど、REST APIを使用して仮想マシン上で実行できる他の多くのアクションを示します。 読者は、これらの例と、OvmWsRestClientクラス内のメソッドとの関係を調べて、REST APIを通じて仮想マシンとのやりとりを拡張する方法を理解することをお勧めします。
3.6.15.2 Python
次のコードでは、仮想マシンの基本属性が作成される前に設定されています。 実際、仮想マシンに固有の多数の属性があり、仮想マシンの構成方法を制御するように設定できます。 ここでは最も基本的な属性が選択され、Xen準仮想化を使用して仮想マシンを作成し、その構成は'MyRepository'というリポジトリに配置されています。 仮想マシンは、'MyServerPool'というサーバー・プールにもアタッチされています。
... repo_id=get_id_from_name(s,baseUri,'Repository','MyRepository') sp_id=get_id_from_name(s,baseUri,'ServerPool','MyServerPool') data={ 'name': 'MyVirtualMachine', 'description': 'A virtual machine created using the REST API', 'vmDomainType': 'XEN_PVM', 'repositoryId': repo_id, 'serverPoolId': sp_id, } uri='{base}/Vm'.format(base=baseUri) r=s.post(uri,data=json.dumps(data)) job=r.json() # wait for the job to complete vm_id=wait_for_job(job['id']['uri'],s)
この例で作成されたVMは非常に単純で、構成された属性はほとんどありません。 このような仮想マシンを作成する場合は、APIのマニュアルを参照して、仮想マシンを完全に構成するために設定できる属性を調べることをお勧めします。
3.6.16 仮想アプライアンスのインポート
このガイドの最後の例は、「仮想ディスク」とそれらの間の相互接続を伴う1つ以上の仮想マシンの構成を含む「仮想アプライアンス」をインポートして、Oracle VM Manager内の仮想マシンの設定と作成を容易にする方法を示します。
以前のリリースのOracle VM Managerでは、仮想アプライアンスはアセンブリという名前でした。 下位互換性を維持するために、Oracle VM WebサービスAPIでは、コード全体でアセンブリという用語が使用されています。 ただし、Oracle VM Managerユーザー・インタフェースとコマンドライン・インタフェースでは、仮想アプライアンスという用語が使用されます。
仮想アプライアンスはリポジトリにインポートされ、そのインポートはリポジトリ上のアクション・リクエストによって処理されます。 仮想アプライアンスをリポジトリにインポートするには、次のURIにPUTリクエストを送信します:
https://hostname:port/ovm/core/wsapi/rest/Repository/id/importAssembly
PUTリクエストには、アプライアンスをダウンロードできるURLのリストを提供するデータ本文が含まれている必要があります。
仮想アプライアンスをリポジトリにインポートしたら、PUTリクエストを次のURIに送信して、仮想アプライアンス内から仮想マシンを環境にインポートできます:
https://hostname:port/ovm/core/wsapi/rest/Vm/createFromAssemblyVm/Assemblyid
3.6.16.1 Java
仮想アプライアンスのインポート
WsDevClientクラスには、仮想アプライアンスのインポートを処理する次のコードが含まれています:
...
// Test import Assembly
final Job importAssemblyJob = api.repositoryImportAssembly(testRepoId, assemblyUrl, null);
System.out.println("import assembly job id: " + importAssemblyJob.getId());
testAssemblyId = waitForJobComplete(api, importAssemblyJob, Assembly.class);
assemblyUrlは、WsDevClient.propertiesファイルで定義されています。 URLは、Oracle VM Managerがアクセスしてダウンロードできる有効な「仮想アプライアンス」パッケージを指している必要があります。 repositoryImportAssemblyメソッドはurlをより一般的なRepositoryImportに渡されるArrayListに追加します。 このメソッドはURIの構築を処理し、次にJersey Builderを使用してPUTリクエストを送信します:
@Override
public Job repositoryImportAssembly(final Id<Repository> repositoryId, final String url, final String proxy) throws WsException
{
final List<String> urls = new ArrayList<String>();
urls.add(url);
final RepositoryImport repositoryImport = new RepositoryImport(urls, proxy);
return action(repositoryId, "importAssembly", repositoryImport);
}
仮想アプライアンスからの仮想マシンのインポート
仮想アプライアンスをOracle VM Managerにインポートした後、仮想アプライアンス内から仮想マシンを環境にインポートすることができます。 まず、インポートする仮想マシンのassemblyVm IDを取得する必要があります。 このため、WsDevClientクラスには、仮想アプライアンス内のVm IDをループする次のコードが含まれています。 コードは単純で、ループ内で検出された最初のIDを選択します。
assemblyVms = api.assemblyVmGetListById(assembly.getAssemblyVmIds());
Id<AssemblyVm> testAssemblyVmId = null;
for (final AssemblyVm assemblyVm : assemblyVms)
{
if (testAssemblyVmId == null)
{
testAssemblyVmId = assemblyVm.getId();
}
assemblyVmIdが設定されると、vmCreateFromAssemblyVmメソッドはOvmWsRestClientから呼び出すことができます:
if (testAssemblyVmId != null)
{
final Job importVmFromAssemblyJob = api.vmCreateFromAssemblyVm(testAssemblyVmId);
System.out.println("import vm from assembly job id: " + importVmFromAssemblyJob.getId());
importedAssemblyVmId = waitForJobComplete(api, importVmFromAssemblyJob, Vm.class);
}
これはPUTリクエストを介して機能するアクション・リクエストですが、URI構成は、仮想アプライアンスをOracle VM Managerにインポートする際に使用した形式とは異なります。 このため、vmCreateFromAssemblyVmメソッドは、リクエストを構成するためのより一般的なメソッドに依存しません:
public Job vmCreateFromAssemblyVm(final Id<AssemblyVm> assemblyVmId)
throws WsException
{
try
{
final Builder b = getResourceFromPathElements(Vm.class.getSimpleName(),
"createFromAssemblyVm", assemblyVmId.getValue());
final Job job = b.put(Job.class);
return job;
}
catch (final UniformInterfaceException ex)
{
throw convertException(ex);
}
}
3.6.16.2 Python
仮想アプライアンスのインポート
REST APIを使用して仮想アプライアンスをOracle VM Managerにインポートする場合は、正しく構築されたURIにPUTリクエストを送信し、アプライアンスをダウンロードできるURLのリストを送信する必要があります。 次のPythonコードはこれを示しています:
assembly_url='http://example.com/assemblys/my_assembly.ovf
repo_id=get_id_from_name(s,baseUri,'Repository',"MyRepository")
uri='{base}/Repository/{repoid}/importAssembly'.format(
base=baseUri,
repoid=repo_id['value'],
)
data={'urls': [assembly_url] }
r=s.put(uri,data=data)
job=r.json()
# wait for the job to complete
assembly_id=wait_for_job(job['id']['uri'],s)
仮想アプライアンスからの仮想マシンのインポート
バーチャル・アプライアンスがインポートを完了すると、仮想アプライアンスに含まれるバーチャル・マシンのID値を取得するためにAPIに問合せを送信することができます。 ご使用の環境内で機能する仮想マシンとしてインポートするには、assemblyVmIdが必要です。 この例では、仮想アプライアンス内のすべての仮想マシンを環境にインポートします:
...
r=s.get('{base}/Assembly/{id}'.format(base=baseUri,id=assembly_id['value']))
assembly=r.json()
for i in assembly['assemblyVmIds']:
uri='{base}/Vm/createFromAssemblyVm/{id}'.format(base=baseUri,id=i['value'])
r=s.put(uri)
job=r.json()
# wait for the job to complete
wait_for_job(job['id']['uri'],s)
私たちが作業している仮想アプライアンスの詳細の完全なリストを取得するためにまずAPIにGETリクエストを送信することによって、それぞれのassemblyVmIdsをループすることができます。 このループでは、インポートをトリガーするために送信する必要があるPUTリクエストに必要なURIを作成できます。
[1]オブジェクト名は変更される可能性があるため、ファイルシステム・オブジェクトのpath属性を照合できる代替機能を作成する価値があります。そのため、不変のパス値でオブジェクトの一致を簡単に検索できます。 これを行う方法の詳細については、「パスからファイル・システムIDを取得」を参照してください。