要約

  • RowStatus は、読み取れる active、notInService、notReady と、書き込むだけの createAndGo、createAndWait、destroy を区別する。要求した動作と、装置が確認した現在地は同じ値ではない。
  • 行を段階的に作れることは、排他的な予約や全体トランザクションを意味しない。エージェントは準備状態、整合性、資源、放置行の削除を判断し、単一 SetRequest の巻き戻しは複数回のやり取りや複数装置には広がらない。

表示された行を成功と呼ばない

設定の行が存在するなら、使えるはずだと思いやすい。データベースの画面では、レコードが表示されることと保存されたことがしばしば同じ成功の印になる。しかし管理プロトコルの行は、索引を確保しただけかもしれない。必須列が足りないかもしれず、値の組み合わせを装置がまだ受け入れていないかもしれない。

RFC 2579 の RowStatus は、その違いを一つの状態列で表しながら、すべてを同じ種類の値にはしなかった。active と notInService は読み書きできる状態である。notReady は読めるが書けない状態である。createAndGo、createAndWait、destroy は書ける動作であり、読み返されることはない。

管理側が createAndWait を書いたあと、同じ値を確認しようとしても、それは返らない。十分な情報がなければ notReady、利用を試せるだけの情報があれば notInService が返る。前者は作成要求が失敗したという意味ではない。行はすでに存在し、資源を使っている場合がある。後者も稼働成功ではない。装置が次の判断を試せる地点まで来た、という限定された証拠である。

この非対称性は、命令を履歴上の事実に見せかけない。管理側が何を求めたかと、エージェントがいま何を確認できるかを別に保つからである。

不足を読めることが復旧を可能にする

createAndWait を使う理由は、管理側が作成時点ですべての必須値を知らない場合に表れる。行が notReady なら、管理側は各列を読み、存在しない必須インスタンスに対する noSuchInstance を手掛かりに値を追加できる。必要な情報がそろえば、状態は notInService になる。

この方法では、未完成の状態が一つのクライアントのメモリだけに残らない。クライアントが再起動しても、別の運用者が行を読み直し、どこまで進んだかを判断できる。途中状態を可視化することが回復可能性を生む。

ただし、notInService は合格証ではない。管理側が active を求めたとき、エージェントは値の不整合を理由に inconsistentValue を返せる。資源が確保できない場合もある。必要項目が存在することと、その組み合わせを装置が受け入れて実際に使えることは別だからである。

どの列を稼働中に変更できるかも、RowStatus だけでは一律に決まらない。個々のオブジェクトの DESCRIPTION が、active のまま変更できるか、いったん notInService にする必要があるかを定める。共通規約は段階をそろえるが、すべての表の運用方針を奪わない。

戻らない相手に期限を設ける

段階的な作成には、管理側が途中で消える可能性がある。通信障害、プロセス停止、誤操作によって、行は利用されないまま資源だけを保持し続ける。

そのため RFC 2579 は、異常に長く notReady または notInService にある行をエージェントが検出し、削除する責任を置いた。時間は状態列の DESCRIPTION に記述すべきであり、記述がない場合に限って約 5 分が提案される。どの表にも固定された 5 分の規則があるわけではない。

この削除は新規行だけに限らず、以前 active だった行を notInService にしたまま放置した場合にも及ぶ。途中状態を長く保持すれば復旧の余地は増えるが、他の管理者が使える資源は減る。期限は単なる実装詳細ではなく、回復と競合の配分である。

一つの要求だけが持つ強い境界

複数列の書き込みが常にばらばらに適用されるわけではない。RFC 3416 の SetRequest 処理では、エージェントは変数バインディングを検証した後、同じ要求内の割り当てを互いに対して同時であるかのように行う。途中で割り当てが失敗すれば、他を元に戻して commitFailed を返す。完全に元へ戻せなければ undoFailed になる。

この規則により、一つの要求にまとめた列には明確な境界ができる。しかし createAndWait の後で列を補い、読み直し、別の要求で active にする過程全体は、一つの要求ではない。最初の応答後に起きた競合や障害を、後のロールバックが時間をさかのぼって取り消すことはない。

また、この同時性は一つの応答エンティティの一つの PDU に限られる。複数装置を一斉変更する分散トランザクションではない。undoFailed という名前自体が、巻き戻しにも観察と復旧が必要な場合を示している。

RMON から共通のライフサイクルへ

1990 年の RFC 1157 は、SNMP の管理機能を名前の付いた変数の取得と変更として扱った。装置ごとの命令を際限なく標準化するのではなく、小さな操作を多様な管理情報に適用する考え方だった。

その簡潔さは、行を作るときに新しい問いを生む。一つの概念行には、索引、既定値のない列、相互に関係する値、割り当てる資源がある。複数の管理システムが同じ表を操作することもある。変数を一度変更できるだけでは、途中まで作った行を誰が見つけ、どの時点で利用し、失敗した作業を誰が片づけるかは決まらない。

この問題を早くから具体化したのが RMON だった。1991 年の RFC 1271 は、監視資源を複数の管理者が共有する制御表について、競合や未完了の作成を扱った。EntryStatus には createRequest、underCreation、valid、invalid があり、所有者を示す文字列も使われた。

所有者文字列は、誰の設定かを他の管理者が理解する助けにはなるが、本人確認でも権限付与でもない。重要なのは、作成が瞬間ではなく、他者から見える期間を持つと認めた点だった。

1993 年の RFC 1443 は、この発想を汎用の RowStatus テキスト規約にした。文書自身が RMON の EntryStatus を起源として挙げている。1996 年の RFC 1903 を経て、1999 年の RFC 2579 で状態遷移とエラー処理が整理された。専門的な一つの制御表から、別の MIB でも再利用できるライフサイクルへ抽象化された歴史である。

待機中にも装置は動ける

行が notReady または notInService なら、受管装置はまだそれを利用していない。しかし、そのことは管理側が行を排他的に確保したという意味ではない。

RFC 2579 は、createAndWait の作成と、後の active 要求との間に、装置自身が同じインスタンスを作る可能性を明記する。その場合、エージェントが保持する値が管理側の値に優先することがある。作成した索引と最初の書き込みを保存しているだけでは、有効化時の内容を証明できない。

そこで、有効化前の再読が意味を持つ。複数管理者の環境では、最初の応答を所有権証明にせず、現在の列値と状態をもう一度確認する。競合はプロトコルの外へ消えたのではなく、観察して処理すべき境界として残っている。

破棄も同じ論理で理解できる。destroy は永続的な状態ではなく、行を消す動作である。成功すれば、その概念行に属する全インスタンスが取り除かれる。行が active、notInService、notReady のどこにあっても要求できる。削除後に destroy を読み返せないことは、状態の欠落ではなく、動作の結果である。

途中を隠さない管理

RowStatus が解決したのは、複雑な設定を完全に安全にすることではない。管理側は作成動作と値を送り、いつ有効化を試すかを決める。エージェントは行を作れるか、情報が足りるか、値が整合するか、資源を使えるかを判断し、放置行を片づける。個々の MIB は変更可能性と期限を説明する。

この分担では、「要求を受け取った」「行が存在する」「有効化を試せる」「実際に active になった」が別々の主張になる。見える行をすぐ成功と呼ばない代わりに、管理システムはどの段階で止まったかを示せる。

存在しても、まだ使えない行は、プロトコルの未完成部分ではなかった。完成までの責任を一つの曖昧な成功値に押し込まず、観察できる形で残したものだった。

出典