Sun Cluster 3.0 12/01 データサービス開発ガイド

第 6 章 リソースタイプの設計

この章では、リソースタイプの設計や実装で DSDL を通常どのように使用するかについて説明します。この章では、特に、リソース構成を検証したり、リソースの開始、停止、および監視を行なったりするためのリソースタイプの設計について説明します。 そして、最後に、リソースタイプのコールバックメソッドを DSDL を使って導入する方法を説明します。詳細は、rt_callbacks(1HA) のマニュアルページを参照してください。

リソースタイプの開発者がこのような作業を行うためには、リソースのプロパティ設定値にアクセスできなければなりません。プログラマは DSDL のユーティリティー scds_initialize() を使うことで、統一された方法でこのようなリソースプロパティにアクセスできます。この機能は、各コールバックメソッドの始めの部分で呼び出す必要があります。このユーティリティー関数は、クラスタフレームワークからリソースのすべてのプロパティを取り出します。これによって、これらのプロパティは、scds_get() 関数群からアクセスできるようになります。

RTR ファイル

RTR (Resource Type Registration 、リソースタイプ登録) ファイルは、リソースタイプのとても重要なコンポーネントです。Sun Cluster は、リソースタイプの詳細な情報をこのファイルから取得します。この情報には、この実装に必要なプロパティや、それらのデータタイプやデフォルト値、リソースタイプの実装に必要なコールバックメソッドのファイルシステムパス、システム定義プロパティのさまざまな設定値などがあります。

ほとんどのリソースタイプ実装では、DSDL に添付されるサンプル RTR ファイルだけで十分なはずです。ただし、リソースタイプの名前やリソースタイプのコールバックメソッドのパス名など、いくつかの基本的な要素は編集する必要があります。リソースタイプを実装する際に新しいプロパティが必要な場合は、そのプロパティをリソースタイプ実装のリソースタイプ登録 (RTR) ファイルに拡張プロパティとして宣言します。新しいプロパティには、DSDL の scds_get_ext_property() ユーティリティーを使ってアクセスできます。

VALIDATE メソッド

リソースタイプ実装の VALIDATE メソッドは、 1) リソースタイプの新しいリソースが作成されているときや、2) リソースまたはリソースグループのプロパティが更新されているときにそれぞれ RGM から呼び出されます。この 2 つの操作は、リソースの VALIDATE メソッドに渡されるコマンド行オプション -c (作成) と -u (更新) によって区別されます。

VALIDATE メソッドは、リソースタイププロパティ INIT_NODES の値で定義されるノード群の各ノードに対して呼び出されます。たとえば、INIT_NODESRG_PRIMARIES が設定されている場合、VALIDATE は、そのリソースのリソースグループを収容できる (その主ノードになりうる) 各ノードに対して呼び出されます。INIT_NODESRT_INSTALLED_NODES に設定されている場合、 VALIDATE は、リソースタイプソフトウェアがインストールされている各ノード (通常は、クラスタのすべてのノード) に対して呼び出されます。INIT_NODES のデフォルト値は RG_PRIMARIES です (rt_reg(4) を参照)。VALIDATE メソッドが呼び出される時点では、RGM はまだリソースを作成していません (作成コールバックの場合)。あるいは、更新するプロパティの更新値をまだ適用していません (更新コールバックの場合)。リソースタイプ実装の VALIDATE コールバックメソッドの目的は、リソースの新しい設定値 (リソースに対して指定された新しいプロパティ設定値) がそのリソースタイプにとって有効であるかどうかを検査することにあります。

DSDL 関数 scds_initialize() は、リソースの作成や更新をそれぞれ次のように処理します。

次の図に示す svc_validate() は、リソースプロパティの検証を実装する関数です。この関数は、scds_get_*() 関数群を使って、検証しようとするプロパティを検査します。リソースの設定が有効ならこの関数から戻りコード 0 が返されるとすると、リソースタイプの VALIDATE メソッドは、次のコード部分のようになります。


int
main(int argc, char *argv[])
{
		scds_handle_t handle;
		int rc;	
	
		if (scds_initialize(&handle, argc, argv)!= SCHA_ERR_NOERR) {
		return (1);/* 初期設定のエラー */	
		}
		rc = svc_validate(handle);
		scds_close(&handle);
		return (rc);
}

さらに、検証関数は、リソースの設定が有効でない場合は、その理由を記録する必要があります。svc_validate() ルーチンの例 (詳細は省略) は、次のようになります (実際的な検証ルーチンについては、次の章を参照してください)。


int
svc_validate(scds_handle_t handle)
{
		scha_str_array_t *confdirs;	
		struct stat statbuf;	
		confdirs = scds_get_confdir_list(handle);	
		if (stat(confdirs->str_array[0], &statbuf) == -1) {		
		return (1);	/* リソースプロパティの設定が無効 */	
		}	
		return (0);	/* 設定が有効 */
}

このように、リソースタイプの開発者は、svc_validate() ルーチンの実装だけに集中できます。リソースタイプ実装の典型的な例としては、app.conf というアプリケーション構成ファイルを Confdir_list プロパティの下に置く処理があります。 この処理は、Confdir_list プロパティから取り出した適切なパス名に対して stat() システム呼び出しを実行することによって実装できます。

START メソッド

リソースタイプ実装の START コールバックメソッドは、特定のクラスタノードのリソースを開始するときに RGM によって呼び出されます。リソースグループ名とリソース名、およびリソースタイプ名はコマンド行から渡されます。START メソッドは、クラスタノードでデータサービスリソースを開始するために必要なアクションを行います。通常、このようなアクションには、リソースプロパティの取得や、アプリケーション固有の実行可能ファイルと構成ファイル (または、どちらか) の場所の特定、適切なコマンド行引数を使用したアプリケーションの起動などがあります。

DSDL では、リソース構成ファイルが scds_initialize() ユーティリティーによってすでに取得されています。アプリケーションの起動アクションは、svc_start() ルーチンに指定できます。 さらに、アプリケーションが実際に起動されたかどうかを確認するために、svc_wait() ルーチンを呼び出すことができます。START メソッドのコード (詳細は省略) は、次のようになります。


intmain(int argc, char *argv[])
{
		scds_handle_t handle;
		
		if (scds_initialize(&handle, argc, argv)!= SCHA_ERR_NOERR) {
		return (1);	/* 初期設定のエラー */	
		}
		if (svc_validate(handle) != 0) {
		return (1);	/* 設定値が無効 */	
		}
		if (svc_start(handle) != 0) {
		return (1);	/* 起動に失敗 */	
		}
		return (svc_wait(handle));
}

この起動メソッドの実装では、svc_validate() を呼び出してリソース構成を検証します。検証結果が正しくない場合は、リソース構成とアプリケーション構成が一致していないか、このクラスタノードのシステムに関して何らかの問題があることを示しています。たとえば、リソースに必要な広域ファイルシステムが現在このクラスタノードで使用できないのかもしれません。その場合には、このクラスタノードでこのリソースを起動しても意味がないので、RGM を使って別のノードのリソースを起動すべきです。ただし、この場合、svc_validate() は十分に限定的であるものとします (その場合、このルーチンは、アプリケーションが必要とするリソースがあるかどうかをそのクラスタノードだけで検査します)。そうでないと、このリソースはすべてのクラスタノードで起動に失敗し、START_FAILED の状態になる可能性があります。リソースのこの状態については、scswitch(1M) と『Sun Cluster 3.0 12/01 データサービスのインストールと構成』を参照してください。

svc_start() ルーチンは、このノードでリソースの起動に成功したら戻りコード 0 を、問題を検出したら 0 以外の戻りコードをそれぞれ返す必要があります。 このルーチンから 0 以外の値が返されると、RGM は、このリソースを別のクラスタノードで起動しようと試みます。

DSDL を最大限に活用するには、svc_start() ルーチンで scds_pmf_start() ユーティリティーを使って、アプリケーションを PMF (プロセス管理機能) のもとで起動できます。このユーティリティーは、PMF の障害コールバックアクション機能 (pmfadm(1M)-a アクションフラグを参照) を使って、プロセス障害の検出を実装します。

STOP メソッド

リソースタイプ実装の STOP コールバックメソッドは、特定のクラスタノードでアプリケーションを停止するときに RGM によって呼び出されます。STOP メソッドのコールバックが有効であるためには、次の条件が必要です。

ほとんどのアプリケーションには、DSDL ユーティリティー scds_pmf_stop() で十分なはずです。このユーティリティーは、まず、アプリケーションが PMF の scds_pmf_start() で起動されたものとみなして、アプリケーションを SIGTERM で「静かに」停止しようとします。これで停止しない場合は、プロセスに対して SIGKILL を適用します。このユーティリティーの詳細については、「PMF 関数」を参照してください。

アプリケーションを停止するそのアプリケーション固有のルーチンを svc_stop() とし、これまで使用してきたコードモデルに従うとするなら、STOP メソッドは、次のように実装できます。svc_stop() の実装で scds_pmf_stop() が使用されているかどうかは、ここでは関係ありません。それが使用されているかどうかは、アプリケーションが PMF のもとで START メソッドによって起動されているかどうかに依存します。

if (scds_initialize(&handle, argc, argv)!= SCHA_ERR_NOERR)
{
	return (1);	/* 初期設定のエラー */
}
return (svc_stop(handle));

STOP メソッドの実装では、svc_validate() メソッドは使用されません。システムに問題があったとしても、STOP メソッドは、このノードでこのアプリケーションを STOP すべきだからです。

MONITOR_START メソッド

RGM は、MONITOR_START メソッドを呼び出して、リソースに対する障害モニターを起動します。障害モニターは、このリソースによって管理されているアプリケーションの状態を監視します。リソースタイプの実装では、通常、障害モニターはバックグラウンドで動作する独立したデーモンとして実装されます。このデーモンの起動には、適切な引数をもつ MONITOR_START コールバックメソッドが使用されます。

モニターデーモン自体は障害が発生しやすいため (たとえば、モニターは、アプリケーションを、監視されない状態にしたまま停止することがある)、モニターデーモンは、PMF を使って起動すべきです。DSDL ユーティリティー scds_pmf_start() には、障害モニターを起動する機能が組み込まれています。このユーティリティーは、モニターデーモンプログラムの相対パス名 (リソースタイプコールバックメソッド実装の場所を表す RT_basedir との相対パス) を使用します。さらに、ユーティリティーは、DSDL によって管理される Monitor_retry_intervalMonitor_retry_count 拡張プロパティを使って、デーモンが際限なく再起動されるのを防止します。モニターデーモンのコマンド行構文には、コールバックメソッドに対して定義されたコマンド行構文と同じものが使用されます (-R resource -G resource_group -T resource_type)。ただし、モニターデーモンが RGM から直接呼び出されることはありません。 このユーティリティーでは、モニターデーモン実装自体が scds_initialize() ユーティリティーを使って独自の環境を設定できます。したがって、主な作業は、モニターデーモン自体を設計することです。

MONITOR_STOP メソッド

RGM は、MONITOR_STOP メソッドを使って、MONITOR_START メソッドで起動された障害モニターデーモンを停止します。このコールバックメソッドの失敗は、STOP メソッドの失敗とまったく同じように処理されます。したがって、MONITOR_STOP メソッドは、STOP メソッドと同じように強固なものでなければなりません。

障害モニターデーモンを scds_pmf_start() ユーティリティーを使って起動したら、scds_pmf_stop() ユーティリティーで停止する必要があります。

MONITOR_CHECK メソッド

クラスタノードが特定のリソースを支配できるかどうかを確認するために (つまり、そのリソースによって管理されるアプリケーションがそのノードで正常に動作するかどうかを確認するために)、そのリソースの MONITOR_CHECK コールバックメソッドがそのリソースのノードで呼び出されます。 通常、この呼び出しでは、アプリケーションに必要なすべてのシステムリソースが本当にクラスタノードで使用可能かどうかが確認されます。「VALIDATE メソッド」 で述べたように、開発者が実装する svc_validate() ルーチンでは、少なくともこの確認が行われなければなりません。

リソースタイプ実装によって管理されているアプリケーションによっては、MONITOR_CHECK メソッドでその他の作業を行うことがあります。DSDL を使用する場合には、リソースプロパティに対するアプリケーション固有の検証を実装するために作成された svc_validate() ルーチンを MONITOR_CHECK メソッドで活用することをお勧めします。

UPDATE メソッド

RGM は、リソースタイプ実装の UPDATE メソッドを呼び出して、システム管理者が行なったすべての変更をアクティブリソースの構成に適用します。UPDATE メソッドは、そのリソースがオンラインになっているすべてのノードに対して呼び出されます。

リソースの構成に対して行われた変更は、リソースタイプ実装にとって必ず有効なものです。RGM は、リソースタイプの UPDATE メソッドを呼び出す前に VALIDATE メソッドを呼び出すからです。 VALIDATE メソッドは、リソースやリソースグループのプロパティが変更される前に呼び出されます。したがって、VALIDATE メソッドは新しい変更を拒否できます。 変更が適用されると、UPDATE メソッドが呼び出され、新しい設定値がアクティブ (オンライン) リソースに通知されます。

リソースタイプの開発者は、どのプロパティを動的に変更できるようにするかを慎重に決定し、RTR ファイルでこれらのプロパティに TUNABLE=ANYTIME を設定する必要があります。通常、リソースタイプ実装の障害モニターデーモンによって使用されるすべてのプロパティは、動的に変更できるように設定できます。ただし、UPDATE メソッドの実装が少なくともモニターデーモンを再起動できなければなりません。

このようなプロパティの候補には次のものがあります。

これらのプロパティは、障害モニターデーモンがサービスの状態検査をどのような頻度でどのように行うかや、どのような履歴間隔でエラーを追跡するか、PMF によってどのような再起動しきい値が設定されるかなどに影響します。DSDL には、これらのプロパティの更新を実装するための scds_pmf_restart() ユーティリティーが備わっています。

リソースプロパティを動的に更新可能に設定する必要があるが、プロパティの変更によって動作中のアプリケーションに影響が及ぶ可能性がある、とリソースタイプの開発者が判断した場合は、適切なアクションを実装することによって、プロパティに対する変更がアプリケーションの動作中のインスタンスに正しく適用されるようにしなければなりません。 DSDL には、現在のところ、この問題をサポートする機能はありません。変更されたプロパティをコマンド行から UPDATE に渡すことはできません (VALIDATE に渡すことはできます)。

INITFINI、および BOOT メソッド

これらのメソッドは、「1 度だけのアクション」を行なうためのものです (リソース管理 API 仕様の定義を参照)。DSDL のサンプル実装には、これらのメソッドの使い方は示されていません。しかし、これらのメソッドを使用する必要がある場合には、DSDL のすべての機能をこれらのメソッドでも使用できます。通常、「1 度だけのアクション」を実装するリソースタイプ実装では、INIT メソッドと BOOT メソッドはまったく同じように機能します。FINI メソッドは、一般に、INIT メソッドや BOOT メソッドのアクションを「取り消す」ためのアクションに使用されます。

障害モニターデーモンの設計

DSDL を使用したリソースタイプ実装の障害モニターデーモンには、通常、次の役割があります。

DSDL ユーティリティーの設計では、障害モニターデーモンの主要ループは次のようになっています。

DSDL を使って実装された障害モニターでは、

ほとんどの場合、アプリケーション固有の状態検査アクションは、スタンドアロンの別個のユーティリティー (たとえば、svc_probe()) として実装してから、この汎用的なメインループに統合できます。


for (;;) {
	 	/ * 正常な検証と検証の間の thorough_probe_interval 
		*  だけスリープする。*/
		(void) scds_fm_sleep(scds_handle,
		scds_get_rs_thorough_probe_interval(scds_handle));
		/* 使用するすべての ipaddress を検証する。次の各要素を繰り返し検証する。
		* 1. 使用するすべてのネットリソース
		* 2. 特定のリソースのすべての ipaddresses
		* 検証する ipaddress ごとに
		* 障害履歴を計算する。 */
		probe_result = 0;
/* すべてのリソースを繰り返し調べて、
* svc_probe()  の呼び出しに使用する各 IP アドレスを取得する。 */
for (ip = 0; ip < netaddr->num_netaddrs; ip++) {	
		/* 状態を検証する必要があるホスト名とポート	
		* を取得する。
		*/
		hostname = netaddr->netaddrs[ip].hostname;
		port = netaddr->netaddrs[ip].port_proto.port;
		/*	
		* HA-XFS は 1 つのポートしかサポートしないため、
		* ポート配列の最初のエントリから	
		* ポート値を取得する。
		*/
		ht1 = gethrtime();   /* 検証開始時刻を保存する。*/
		probe_result = svc_probe(scds_handle, 
		               hostname, port, timeout);
		/*	
		* サービス検証履歴を更新し、		
		* 必要に応じてアクションを実行する。
		* 検証終了時刻を保存する。
		*/
		ht2 = gethrtime();
		/* ミリ秒に変換する。 */
		dt = (ulong_t)((ht2 - ht1) / 1e6);
						
		/*		
		* 障害履歴を計算し、
		* 必要に応じてアクションを実行する。
		*/	
		(void) scds_fm_action(scds_handle,
		probe_result, (long)dt);
		}            /* 各ネットリソース */	
		}       /* 検証を続ける。 */