Openldap再起動に失敗した復旧試行錯誤

dockerコンテナ osixia/openldap を使っていたが、コンテナを再起動したら即落ちで正常起動しなくなった不具合調査と対応結果。

状況

docker ps -a で見ても EXITED となる。表示されるログは以下の通り。

[root@hoge ~]# docker logs openldap
*** CONTAINER_LOG_LEVEL = 3 (info)
*** Copy /container/service to /container/run/service
*** Search service in CONTAINER_SERVICE_DIR = /container/run/service :
*** link /container/run/service/:ssl-tools/startup.sh to /container/run/startup/:ssl-tools
*** link /container/run/service/slapd/startup.sh to /container/run/startup/slapd
*** link /container/run/service/slapd/process.sh to /container/run/process/slapd/run
*** Set environment for startup files
*** Environment files will be proccessed in this order :
Caution: previously defined variables will not be overriden.
/container/environment/99-default/default.yaml
/container/environment/99-default/default.startup.yaml
~中略~
TLS: could not use CA certificate file `/container/run/service/slapd/assets/certs/ca.crt': Error while reading file. (-64)
61909a9b main: TLS init def ctx failed: -1
61909a9b slapd stopped.
61909a9b connections_destroy: nothing to destroy.
*** /container/run/process/slapd/run exited with status 1
*** Killing all processes...

結論

結論としては問題は3つあった。

  • 設定の上書きを禁止していた
  • TLSを無効化していなかった ※実際に使っているなら残して良い。使っていないのに無効化してなかった
  • 何故かよくわからないがdockerのパラメータHOSTNAMEの扱いに何か変更があった様子

対策

以下の docker パラメータ修正で立ち上がるようになった。

追加

LDAP_TLS: "false"

削除

HOSTNAME: "example.com"
KEEP_EXISTING_CONFIG: "true"

調査経緯

読めぬなら読ませて見せよう…ということで、 /container/run/service/slapd/assets/certs/ca.crt を配置してみた。

するとca.crt以外にも公開鍵・秘密鍵・DHPARAMも不足している旨のエラーが順に表示されたのでそれらも足した。

でもそもそも内部用でTLSは使っていないから LDAP_TLS : “false”を足した。けれど直らなかった。

よくよく警告文言を見ると定義済み変数は上書きされないと書いてあったから KEEP_EXISTING_CONFIG: “true” を消した。そして docker logs openldap のエラー文言部分が以下に変わった。

61a19a26 slapd starting
61a19a26 daemon: listen(ldap://516808931dce:389, 5) failed errno=98 (Address already in use)
61a19a26 slapd stopped.
*** INFO | 2021-11-27 02:38:30 | /container/run/process/slapd/run exited with status 0
*** INFO | 2021-11-27 02:38:30 | Killing all processes…

このサーバー自体での問題だから、Address already in use はコンテナ内部の問題。

この辺の文言でググっていたところ、HOSTNAMEが怪しいぞという話があった。何か故あってHOSTNAMEのパラメータは消すべきとなった様子だが具体的な理由が知りたいわけではないからよしとする。

docker 起動パラメータから消したら正常表示されるようになった。

エクセルテーブルをデータ入力規則リストに使う

エクセルでプルダウンメニューから選択して入力するにはデータ入力規則でリスト入力設定にすればよい。リストの元の値(Source)にテーブルを指定すれば選択肢数を増減させても即選択肢に反映されるので柔軟に扱える。

設定するには3ステップを行う。

  1. テーブルの作成
  2. テーブル名の設定 ※省略可
  3. プルダウンメニュー化範囲にデータ入力規則を設定 ※ドロップダウンリストとも呼ばれる

1.テーブルの作成

図1.テーブル化

テーブル化するデータを入力してから、範囲を選択(図1のA1:B4)→メニュー『挿入』タブの『テーブル』を選択

図2.テーブルの作成

適宜『先頭行をテーブルの見出しとして使用する』にチェックを入れて、『OK』ボタンを選択

図3.テーブル化完了

2.テーブル名の設定

図4.テーブル名の変更

テーブル選択状態で、メニュー『テーブルデザイン』タブの『テーブル名:』で適宜テーブル名を変更する

※デフォルトの名前がついているのでテーブル名設定は省略出来るが、後で分かりやすいので変更推奨

図5.テーブル名を食べ物に変更した

3.プルダウンメニュー化範囲にデータ入力規則を設定

図6.データ入力規則

プルダウンメニューから選びたい範囲を選択後、メニュー『データ』タブの『データの入力規則』を選択

図7.データの入力規則の設定

『入力値の種類:』は『リスト』に変更し、『元の値:』は『=INDIRECT(“テーブル名[列名]”)』の書き方にして『OK』を選択。

※この例では元の値は=INDIRECT(“食べ物[フルーツ]”)=INDIRECT(“食べ物[やさい]”) となる。テーブルの定義に合うよう適宜変更する

※INDIRECTを省略したりダブルクォーテーション記号を省略したりすると正常に動作しないから注意して入力する

図8.プルダウンメニューから選択可能

SQLiteをVisual Basic .NET で使う

Visuual Basic .NET(VS .NET 2019, .NET Core 3.1)環境でSQLite3を使った。

  • SQLite3 関連のNuGetライブラリは乱立していて依存関係は複雑
  • 検索ではC#の記事が多く直接VB .NETで使えない

であったため備忘録を残す。

1.依存ライブラリのインストール

Visual Studio のメニューから『ツール→NuGetパッケージマネージャ→ソリューションのNuGetパッケージの管理 』を辿り、『sqlite-net-pcl』で検索してインストールする

※このライブラリは他に依存関係ダウンロードはなくとも正常に動作した

2.クラスの作成

メニューの『プロジェクト→クラスの追加』でTestTable.vb というデータ格納用のテーブルを作成する。

Imports SQLite
Public Class TestTable
<AutoIncrement, PrimaryKey>
Public Property id As Integer
Public Property description As String
Public Sub New(description As String)
_description = description
End Sub
Public Sub New() ‘引数なしのコンストラクタが必要
End Sub
End Class

気になるのは2点。

2.1.<AutoIncrement, PrimaryKey>の部分

SQLiteのDB向けアノテーションで、id フィールドがAutoIncrement, Primary Keyと手軽に設定出来てしまうので便利だ。

2.2.Public Sub New()の部分

引数を持たないPublic Sub Newの定義は必須となっている。SQLiteが自動的にインスタンスを生成するのに要る様子

3.DB・テーブル作成、INSERT、UPDATE、DELETE、SELECT

GUI上でボタンを作成し、ダブルクリックで後述の関数(ButtonDebug_Click)の中身を実装する。デモとして用意したボタンクリック時の処理フローは以下の通り。

3.1.ボタンクリック時の処理フロー

  1. Test.db DBを作成する
  2. テーブルを作成する
  3. 20件レコードINSERT
  4. ID>10のレコードのみ取得し、IDが5の倍数なら削除 or descriptionの末尾に”Updated”を付与する
  5. データ全件SELECT・出力

3.2.関数の中身

Private Sub ButtonDebug_Click(sender As Object, e As EventArgs) Handles ButtonDebug.Click
‘1.Test.db DBを作成する
Using connection = New SQLiteConnection(“Test.db”)
‘2.テーブルを作成する
connection.CreateTable(Of TestTable)()
‘3.20件レコードINSERT
For i As Integer = 1 To 20
Dim NewItem = New TestTable(“description” & i)
connection.Insert(NewItem)
Next
‘4.ID>10のレコードのみ取得し、IDが5の倍数なら削除 or descriptionの末尾に”Updated”を付与する
Dim Items = connection.Table(Of TestTable)().Where(Function(x) x.id > 10)
For Each Item In Items
If Item.id Mod 5 = 0 Then
‘IDが5の倍数の場合削除
connection.Delete(Item)
Debug.WriteLine(“DELETE: id:{0}”, Item.id)
Else
‘IDが5の倍数でなければ更新する
Item.description = Item.description & “Updated”
connection.Update(Item)
Debug.WriteLine(“UPDATE: id:{0}”, Item.id)
End If
Next
‘5.データ全件SELECT・出力
Items = connection.Table(Of TestTable)()
For Each Item In Items
Debug.WriteLine(“SELECT: id:{0}, description:{1}”, Item.id, Item.description)
Next
Debug.WriteLine(“done”)
End Using
End Sub

  • Test.db を指定している部分でDBファイル名を指定
  • CreateTableで型を指定すればその型のDBテーブルが生成される
  • インスタンスを引数に設定してInsert/Update/Deleteを呼び出せば手軽にレコードのCUDが可能
  • SELECTは更に簡単で、LinqでTable(Of ClassName)() を扱えば良い。ただし『WHEREでMod』のような条件は不可

SQLなしで手軽に作れるのがやりやすくて便利。※SQLで取得したい場合は以下のように取得すればよい

Dim x = connection.Query(Of TestTable)(“SELECT * FROM TestTable WHERE description=?”, “QueryCondition”)

3.3.実行結果出力

UPDATE: id:11
UPDATE: id:12
UPDATE: id:13
UPDATE: id:14
DELETE: id:15
UPDATE: id:16
UPDATE: id:17
UPDATE: id:18
UPDATE: id:19
DELETE: id:20
SELECT: id:1, description:description1
SELECT: id:2, description:description2
SELECT: id:3, description:description3
SELECT: id:4, description:description4
SELECT: id:5, description:description5
SELECT: id:6, description:description6
SELECT: id:7, description:description7
SELECT: id:8, description:description8
SELECT: id:9, description:description9
SELECT: id:10, description:description10
SELECT: id:11, description:description11Updated
SELECT: id:12, description:description12Updated
SELECT: id:13, description:description13Updated
SELECT: id:14, description:description14Updated
SELECT: id:16, description:description16Updated
SELECT: id:17, description:description17Updated
SELECT: id:18, description:description18Updated
SELECT: id:19, description:description19Updated
done

予定通りID:11~20のうち15,20のみDELETEされた

結果としてID:11~14,16~19のdescriptionにUpdatedが付与された

⇒想定通りの動作