第2章 プログラミングに関する問題と考慮事項
2.1 一般的なプログラミングに関する考慮事項
プログラマは、Web Services APIに対して開発する際に考慮する必要があります。 この項では、APIのユーザーが遭遇する一般的な障害の概要と、それらの処理方法について説明します。
2.1.1 オブジェクトの変更
オブジェクトをクライアント・アプリケーションに読み込むとき、そのオブジェクトは実際にOracle VM Manager内に含まれるオブジェクトのコピーと見なす必要があります。 オブジェクトのクライアント側表現の変更は、オブジェクトの変更メソッドを呼び出して、クライアント・アプリケーション内でローカルに変更したオブジェクトの更新されたコピーを渡すまで、何も影響を与えません。 getオブジェクト・メソッドから返されたデータをローカル・オブジェクトに取り込むと、ローカル・オブジェクトは実際のオブジェクトのコピーに過ぎません。 ローカル・オブジェクトを変更すると、サーバー側オブジェクトは変更されません。 サーバー・サイドのオブジェクトが実際に影響を受けるオブジェクトを変更するメソッドを呼び出すときだけです。
Oracle VM Managerはいつでも複数のユーザーまたはクライアントからアクセスできるため、常に2人のユーザーが同時にオブジェクトを変更しようとしている可能性があります。 APIは競合条件を処理しますが、変更しているオブジェクトが既に別の操作で変更されていて、オブジェクトの期限が切れている場合、APIは例外を生成します。 したがって、オブジェクトの変更を実行するときは、オブジェクトの変更メソッドを呼び出す前に、そのオブジェクトが常に最新であることを確認する必要があります。
この動作により、意図しないランダムな変更が防止されます。 たとえば、説明を変更するオブジェクトがありますが、オブジェクトの内容が古い場合は、他の人がそのオブジェクトにさまざまな変更を加えた可能性があります。 例外がスローされなかった場合、オブジェクトは呼び出し元の意図ではないにもかかわらず、他のすべての属性の以前の状態に戻ります。
これを達成する可能性のあるメソッドがある場合でも、オブジェクトIDは変更できません。 これらのメソッドが存在する理由の詳細については、2.1.3項、「読取り専用メソッドとオブジェクトのプロパティ」を参照してください。 オブジェクトIDはOracle VM Manager内で生成され、オブジェクト関係全体の整合性を維持するために使用され、一意のままでなければなりません。 したがって、クライアント・アプリケーションがオブジェクトIDを直接変更することはできません。
2.1.2 オブジェクトの関連付け
関連付けは、オブジェクトのsetterを呼び出してからmodifyを呼び出すことで変更されません。 関連付けは、明示的なAPI呼び出しで変更されます。 例には、serverPoolAddServer、networkAddEthernetPortなどがあります。
関連付けは一方向にのみ変更されます - 典型的には親からのものです。 上記のケースを使用してサーバーをサーバー・プールに追加すると、serverPoolIdはサーバー・オブジェクトのプロパティとして表示されますが、サーバーには設定されません。 これらのプロパティと、それらがすべてのオブジェクトに存在する理由については、2.1.3項、「読取り専用メソッドとオブジェクトのプロパティ」を参照してください。
以前に2.1.1項、「オブジェクトの変更」で述べたように、親オブジェクトとの関連付けを持つオブジェクトのIDは、これを実現するようなメソッドがあっても変更できません。 親オブジェクトのプロパティとして表示されるこれらの関連付けられたオブジェクトIDは、直接変更できず、関連付けメソッドがAPIから呼び出されると自動的に関連付けられます。
2.1.3 読み取り専用のメソッドとオブジェクトのプロパティ
モデル・オブジェクトには読み取り専用として文書化されたメソッドがあります。 たとえば、Server.setServerPoolIdのAPIドキュメントを見ると、serverPoolIdが読み取り専用であることが明示的に記載されています。 これらのメソッドを呼び出すか、オブジェクトのこれらのプロパティを変更しようとすると、設定しようとする値は、modify呼び出しがAPIに送信されたときにAPIによって単純に無視されます。 これらのメソッドのいずれかを呼び出すか、オブジェクト修正API呼び出しを使用してそのようなプロパティの値を変更しようとしても、例外はスローされません。 これは、クライアント側で読み取り専用セッター・メソッドを呼び出すことができ、クライアント側オブジェクトの値に変更が反映されている可能性があることを意味し、オブジェクトがOracle VM Managerにサブミットされ、変更。
これらのメソッドが存在する理由は、特定のWebサービス・フレームワーク(JacksonやJerseyライブラリなど)がこれらのオブジェクトを逆シリアル化できるようにするためです。 したがって、これらのメソッドとプロパティはクライアント側で使用可能である必要がありますが、オブジェクトのマネージャ表現には影響しません。
2.1.4 ジョブの操作
ジョブは子ジョブを持つことができます。 操作が完全に完了するためには、子ジョブも同様に完了する必要があります。 ただし、子ジョブが完了するまでに非常に時間がかかり、完了しないジョブもあります。 これは、子ジョブが各サーバーを処理するために生成されたときに発生します。 ただし、サーバーがオフラインの場合、その子ジョブはサーバーがオンラインに戻るまでアクティブのままです。
ジョブには、親ジョブが完了したかどうか、そして親ジョブによって生成されたすべての子ジョブも完了しているかどうかを示すプロパティがあります。 doneプロパティは親ジョブに関連し、summaryDoneプロパティは親ジョブおよび生成されたすべての子ジョブに関連します。 場合によっては、doneプロパティをチェックすると親ジョブが完了したように見えることがありますが、summaryDoneプロパティは子ジョブがまだ実行中であることを示します。 したがって、ジョブの完了を待っているときは、summaryDoneプロパティの値をチェックする方が通常は良い方法です。
ジョブの完了後(変更を含む)にオブジェクトの更新を表示するには、オブジェクトのクライアント・ビューを更新する必要があります。
2.1.5 例外処理
Oracle VM Managerは多層アプリケーションです。 そのため、Oracle VM Managerコア内のさまざまなレベルで操作の合法性のチェックが行われます。 いくつかのエラーは、Webサービス層自体の中で捕らえられるかもしれませんが、他のものはコア・ルール評価によってのみ引き起こされるかもしれません。 これはアプリケーション自体の中で何の違いもありません。 例外は、どこから発生したかにかかわらず、そのように扱われるべきです。
たとえば、Webサービス・リクエストのJobエラーとして返される次の例外は、Coreによって返されたルール例外と同じくらい例外です:
ovm.mgr.ws.model.WsException: NETWORK_000008: Cannot perform operation Modify Role List on a Server local Network: Modify Role List
同様に、コア内からのルール例外も、Webサービス・レイヤーで生成されるエラーと同じくらい重要です:
com.oracle.ovm.mgr.api.exception.RuleException: OVMRU_002043E Cannot release ownership of Repository: MyRepo. Virtual Disks/CDroms: [0004fb0000120000eb8cd3defdc71ba5.img on 0004fb0000060000e3ea97cd6b8d45bd, 0004fb0000120000f2ba448c46f4fc12.img on 0004fb0000060000e3ea97cd6b8d45bd], are still assigned to VMs/Templates that have configuration files in another repository.
また、APIから返される例外は、SOAP APIまたはREST APIのどちらを使用しているかによって返されるエラー・メッセージまたは例外コードの点で異なる可能性があります。 いずれかのAPIを使用できるアプリケーションをコーディングする場合は、使用されているAPIに関係なく、これらの例外を処理するコードの一貫性を確保する必要があります。
2.1.6 オブジェクト名と説明のXMLタグ
Oracle VM Manager内のオブジェクト名または説明に使用できるコンテンツに制限はありませんが、Oracle VM Manager内のオブジェクトのXMLタグが名前または説明フィールドに存在し、WS-APIクライアントがREST APIをXMLメディア・タイプの場合、エラーが発生する可能性があります。
一般に、Oracle VM Manager内の名前フィールドと説明フィールドにXMLを挿入しないでください。 ただし、この問題が既に存在する場合は、次のようなエラーが表示されることがあります:
javax.xml.stream.XMLStreamException: ParseError at [row,col]:[1,432983] Message: The character sequence "]]>" must not appear in content unless used to mark the end of a CDATA section.]
Oracle VM Manager内のすべてのオブジェクトの名前と説明からXMLタグを削除するか、JSONメディア・タイプでREST APIを使用してください。
SDK Javaクライアントで定義されているデフォルトの動作は、RestClientを使用するときにメディア・タイプとしてJSONを使用することです。 さらに、サンプルWsDevClient.properties
ファイルのデフォルト設定は、JSONでRESTに設定されています。
2.2 Sudsユーザーの注目すべき問題
この項では、Suds SOAPライブラリを使用している場合にPythonユーザーが持つ可能性のある問題について説明します。 SOAP APIはOracle VM Manager 3.4では非推奨されており、Sudsライブラリを使用している場合は、今後REST APIを使用するようにコードを変更することを検討する必要があります。
2.2.1 外部にホストされているXSDを扱う
SOAP APIは、外部でホストされるXSDを参照します:
<xs:import namespace="http://www.w3.org/2005/08/addressing" schemaLocation="http://www.w3.org/2006/03/addressing/ws-addr.xsd"/>
クライアント・アプリケーションがインターネットに直接アクセスできない環境では、Sudsライブラリに問題が発生する可能性があります。 この場合、https://fedorahosted.org/suds/wiki/Documentation#BindingSchemaLocationsURLtoNamespacesで説明されているように、このXSDのローカライズされたコピーをホストし、名前空間の新しいスキーマのロケーションをバインドする必要があります。 一時的なディレクトリにローカルにホストされているXSDに名前空間をバインドする方法を示す関数の例を次に示します:
from suds.xsd.sxbasic import Import def bind_schema_locations(): Import.bind( 'http://www.w3.org/2005/08/addressing', 'file:///tmp/xsd/www.w3.org/2006/03/addressing/ws-addr.xsd')
2.2.2 nullプロパティと空のリスト
インスタンスにnullプロパティまたは空のリストがある場合、Sudsのインスタンスはそのプロパティを削除します。 たとえば、インスタンスに名前がない場合は次のようになります:
instance.name = None
Sudsインスタンスはnameプロパティを削除します。 したがって、nameプロパティを確認するには、まずそのインスタンスに実際にプロパティが含まれていることを確認する必要があります:
if 'name' in instance and instance.name == 'foo': # do something
同様に、空のリストの場合、Sudsがプロパティを削除する同様の動作になります。 リストを含むプロパティを反復処理するには、まずプロパティが存在することを確認する必要があります:
if 'ethernetPortIds' in server: for ethernet_port_id in server.ethernetPortIds: # do something
空のリストを含むプロパティを反復しようとすると、プロパティがインスタンスから削除されるため、例外が発生します。 結果として、それが利用可能であることを期待するプロパティに対して単純に反復しようとするのは良い考えではありません:
for ethernet_port_id in server.ethernetPortIds: # do something
上記の例では、ethernetPortIds
プロパティが空のリストである場合、Sudsはそれをserver
インスタンスのプロパティとしてアタッチしません。 結果は、次のような例外です:
AttributeError: server instance has no attribute ‘ethernetPortIds’ exception.
2.2.3 OvmWsUtilitiesエンドポイントにアクセスできない
SudsのOvmWsUtilitiesエンドポイントのWSDLをロードすることは可能ですが、このエンドポイントの認証はできません。 これは、認証がOvmWsApiエンドポイントによって公開されるloginメソッドを使用して処理されるためです。
技術的には、ユーティリティ・エンドポイントへのアクセスは、OvmWsApiエンドポイントからgetOvmWsUtilitiesEndpoint
メソッドを呼び出すことによって実現されるように設計されていますが、このメソッドはエンドポイント参照を返します。 Sudsライブラリは、この機能を簡単に補うことはできません。
したがって、OvmWsUtilitiesエンドポイントによって公開されているメソッドを使用する場合は、APIへのRESTインタフェースを使用することをお勧めします。
2.3 JacksonとJerseyライブラリ・ユーザーの注目すべき問題
2.3.1 nullプロパティと空のリスト
空リストは、Webサービスを介してシリアライズまたは直列化復元されると、JacksonおよびJerseyライブラリによってnullに変換されます。 したがって、コードでは、空のリストの代わりにnullプロパティを取得する必要があります。 また、WebサービスAPIに渡される空のリストをnullに変換することもできます。 したがって、apiはそれらを等価として扱います。
nullプロパティのチェックを示す例は、SDKに付属のサンプル・クライアントのWsDevClientクラスに含まれています。