[ILM 2007] Creating a provisioning code (Already object exists でエラーになっちゃうよ)

こんにちは、ぴろとでございます。先日、Provision された Person Object (娘) が、Pending Export 状態であった旨、お伝えしておりました。この度、無事なんのエラーもなく、Export and Check 処理が完了しました。これからが、大変な毎日が待っていると重々覚悟をしているのですが、まずはほっと胸をなでおろす今日この頃です。

今回の記事は Provisioning をテーマに書いてみたいと思います。

とある一家が家族が増えたことを契機に、家庭にある Family ドメインの ID 管理を自動化したいと思いつき、ILM 2007 FP1 を用いて ID 同期を行うつもりのようです。はてさて、どうなることやら…。

パパ 「うちにも家族が増えたし、ID 管理を容易化したいと思うんだが…」
ママ 「え?そんなに家族がいないし、手作業でやればいいじゃん」
パパ 「子どもだって、今後もっと増えるかもしれないし、3 人以上いたら管理が必要なんだよ」
ママ 「どうせ、パパが管理しているわけだし好きにすればいいじゃない?」
… こんなすったもんだがあったかなかったかは、また別の話になりますが、以下のシステム要件で行うようです。

- システム要件

・CSV ファイルに管理されている家族人員の内容を元に、Family ドメインに Person を追加・変更を行う必要がある。
・Family ドメインは既存ドメインのため、すでに Father と Mother の Person オブジェクトが存在している。
・Daughter は、生まれたばかりなので CSV ファイルに追記したばかり。

Provisining ルールにて、以下のようなコードを書いてみました。

 

Public Sub Provision(ByVal mventry As MVEntry) Implements IMVSynchronization.Provision
       Dim targetContainer As String
       Dim cnAttribute As String
       Dim maName As String
       Dim objectType As String

       Select Case mventry.ObjectType.ToString
           Case "person"

               cnAttribute = "CN"
               maName = "AD-MA" 'MAの名前を定義
               targetContainer = ADUsersContainer
               objectType = "user"

               ProvisionObjectToActiveDirectory(mventry, cnAttribute, maName, targetContainer, objectType)

       End Select
   End Sub

 

Private Sub ProvisionObjectToActiveDirectory(ByVal mventry As MVEntry, ByVal cnAttribute As String, ByVal maName As String, ByVal targetContainer As String, ByVal objectType As String)

    Dim coNNectedMA As ConnectedMA
    Dim cnForObject As String
    Dim rdn As String
    Dim dn As ReferenceValue
    Dim numConnectors As Integer
    Dim csentry As CSEntry
    Dim myConnector As CSEntry
    Dim successful As Boolean = False

    '----------- プロビジョニングコード ------------
    'CN属性値のチェック
    If Not mventry(cnAttribute).IsPresent Then
        Throw New UnexpectedDataException("CN属性がありません")
    End If

    '接続するMAのオブジェクトを取得
    coNNectedMA = mventry.ConnectedMAs(maName)

    'メタバースエントリのCN属性値の取得
    cnForObject = mventry(cnAttribute).Value.ToString()

    Try
        rdn = "CN=" & cnForObject

        ' OUを含めた完全なDN属性値を生成
        dn = coNNectedMA.EscapeDNComponent(rdn).Concat(targetContainer)

        numConnectors = coNNectedMA.Connectors.Count
        If 0 = numConnectors Then
            'CSエントリを新規作成
            csentry = coNNectedMA.Connectors.StartNewConnector(objectType)
            csentry.DN = dn
            csentry.CommitNewConnector()

        ElseIf 1 = numConnectors Then
            '移動先のDN値をセット

            myConnector = coNNectedMA.Connectors.ByIndex(0) 
            myConnector.DN = dn
        Else
            Throw New UnexpectedDataException("コネクタが複数です")
        End If

        successful = True

    Catch ex As ObjectAlreadyExistsException

        Throw New UnexpectedDataException("オブジェクトは既にあります")

    Finally

    End Try

End Sub

 

そして、オペレーションは、次の流れで実施を行いました。

1. CSV-MA にて、Full Import (Stage Only)
2. AD-MA にて、Full Import (Stage Only)
3. CSV-MA にて、Full Synch ….

おや、3. CSV-MA にて Full Synch の処理にて、エラーが発生しました。イベントログをみると、”オブジェクトは既にあります” です。 エラーとなったオブジェクトは、Father と Mother で、いとしき愛娘は、正常に Provisioning されています。「おとーさん、うまく同期されなかったよ」 と寝ている娘にささやくのでした。気を取り直して、デバッグすることにしました。すると、ComittNewConnector にて、エラーになっていることがわかりました。そこで、パパは気がつきました。「あれ? provisioning では新しいコネクタスペースオブジェクトを作成する処理だよなぁ。けど、AD-MA にはすでに Father オブジェクトはあるはず…」 そうです、ここでは、ObjectAlreadyExistsException は無視し、Join ルールにて、処理させるべきです。それに伴い、MV ルールを変更することにしました。

- 変更点
・Throw New UnexpectedDataException をコメントアウト
・Run Profile の実行順序を以下のように変更

1. CSV-MA の Full Import (Stage Only)
2. AD-MA の Full Import (Stage Only)
3. CSV-MA の Full Synch (注) コメントアウトされたため、エラーにならない) 
4. AD-MA の Full SYnch (注) AD-MA のコネクタスペースオブジェクトと MV オブジェクトが Join 
------

ちなみに、2. の処理を実施せずに、1. –> 3. の順番で同期を行うと、同期オブジェクトの DN 名に指定される OU が未 Import 状態のため、MissingParentObject Exception が発生します。
このシステムを管理しているパパはきっと娘に、「おとーさんは、ここにいるよ」とささやくに違いありません。

~ ぴろと@娘の名前はやっぱり”ななみ” ~