Der S4-Connector auf dc-yoda ist frisch installiert. Der Dienst läuft. Das Log zeigt braves Polling:

sync UCS > AD: polling
sync AD > UCS: polling
Search S4 with filter: (|(uSNChanged>=6407)(uSNCreated>=6407))

Ein Test-User via UDM anlegen:

udm users/user create --set username=luke.skywalker --set lastname=Skywalker \
  --set password="UseTheForce42!" \
  --position "cn=users,dc=deathstar,dc=lan"

30 Sekunden warten. In Samba nachschauen:

samba-tool user show luke.skywalker
# ERROR: Unable to find user "luke.skywalker"

Nichts. Der User existiert in OpenLDAP, aber der Connector ignoriert ihn.


Die Spur: Leeres Listener-Verzeichnis

Der S4-Connector bekommt UCS-Änderungen nicht per Polling, sondern über den Listener. Der Listener schreibt Pickle-Dateien nach /var/lib/univention-connector/s4/, die der Connector dann verarbeitet.

ls -la /var/lib/univention-connector/s4/
# total 10
# drwxr-xr-x 3 root root 3 ...
# drwxr-xr-x 2 root nogroup 2 ... tmp

Leer. Keine Pickle-Files. Der Listener schreibt nichts rein.


Tiefer: Der Notifier steht still

Der Listener bekommt seine Daten vom Notifier. Der Notifier liest neue LDAP-Transaktionen und verteilt sie an Listener.

tail -3 /var/lib/univention-ldap/notify/transaction
# 6556 relativeDomainName=_ldap._tcp...  m
# 6557 zoneName=deathstar.lan...          m
# 6558 uid=c3po,cn=users,...              m

Transaction-ID 6558. Seit dem DC-Tausch. Jede UDM-Änderung danach? Fehlt.

# Test: UDM-Änderung machen, dann Transaction-Datei prüfen
udm users/user modify --dn "uid=c3po,cn=users,dc=deathstar,dc=lan" \
  --set description="test $(date +%s)"

sleep 5
tail -1 /var/lib/univention-ldap/notify/transaction
# 6558 uid=c3po,cn=users,...              m

Immer noch 6558. Der Notifier registriert keine neuen Transaktionen.


Die Ursache: ldap/translogfile ist leer

Auf einem UCS-System protokolliert das translog-Overlay von slapd jede LDAP-Änderung in eine Datei. Der Notifier liest diese Datei und schreibt sie in die Transaction-DB. Ohne translog-Overlay → kein Notifier → kein Listener → kein S4-Connector (UCS-Richtung).

Ob das Overlay aktiv ist, steuert eine einzige UCR-Variable:

ucr get ldap/translogfile
# (leer)

Das Template in /etc/univention/templates/files/etc/ldap/slapd.conf.d/40univention-ldap-server_database prüft:

if configRegistry.get('ldap/translogfile'):
    print("overlay\t\ttranslog")
    print("translog\t%(ldap/translogfile)s" % configRegistry)

Variable leer → kein Overlay → keine Transaktionen → gesamter Listener-Pfad tot.

Und weil das gleiche Template auch das Modul-Laden steuert:

# In 31modules:
if configRegistry.get('ldap/translogfile'):
    print("moduleload\ttranslog.so")

Wird translog.so auch gar nicht erst geladen. Bestätigung:

grep translog /etc/ldap/slapd.conf
# Nur die cn=translog Backend-DB, KEIN overlay

Warum fehlt die Variable?

Das System war mal dc-vader (Primary DC). Dort war ldap/translogfile gesetzt. Dann wurde dc-yoda als Backup-DC aufgesetzt, dc-vader demoted, und dc-yoda zum Master promoted.

Beim Promote von Backup → Master werden nicht alle UCR-Variablen automatisch gesetzt. ldap/translogfile ist eine davon. Auf einem Backup-DC wird das translog-Overlay nicht benötigt — der Backup bekommt seine Daten per Replikation vom Master. Erst als Master braucht er es.

Und es gibt keinen Fehler, keine Warnung. Der Notifier startet, findet keine neuen Transaktionen, wartet. Für immer.


Der Fix: Eine Zeile

ucr set ldap/translogfile=/var/lib/univention-ldap/listener/listener

Dann slapd.conf neu generieren und slapd neustarten:

univention-config-registry commit /etc/ldap/slapd.conf

# Verifizieren dass das Overlay jetzt da ist:
grep -n translog /etc/ldap/slapd.conf
# 110: moduleload  translog.so
# 135: overlay     translog
# 136: translog    /var/lib/univention-ldap/listener/listener

# slapd neustarten
systemctl restart slapd

Testen:

# Vorher
tail -1 /var/lib/univention-ldap/notify/transaction
# 6558 uid=c3po,cn=users,...

# Änderung machen
udm users/user modify --dn "uid=c3po,cn=users,dc=deathstar,dc=lan" \
  --set description="translog test"

sleep 3
tail -1 /var/lib/univention-ldap/notify/transaction
# 6559 uid=c3po,cn=users,...              m

6559. Die Transaction-Datei wächst wieder.

Notifier und Listener neustarten, damit sie die neuen Transaktionen abholen:

systemctl restart univention-directory-notifier
systemctl restart univention-directory-listener
systemctl restart univention-s4-connector

Bonus-Problem: Extension-Aktivierung und Server-Rolle

Auf dem gleichen System fielen noch zwei weitere Überbleibsel der DC-Migration auf:

univentionServerRole: backup statt master

Das LDAP-Computerobjekt des DCs hatte noch die alte Rolle:

univention-ldapsearch -xLLL "cn=dc-yoda" univentionServerRole
# univentionServerRole: backup

Obwohl ucr get server/role korrekt domaincontroller_master zeigt und alle FSMO-Rollen auf dem Host liegen. Das Joinscript des S4-Connectors schlägt mit exitcode 3 fehl, weil es versucht das Computerobjekt als computers/domaincontroller_master zu modifizieren.

Fix:

ldapmodify -x -H ldap://localhost:7389 \
  -D "cn=admin,dc=deathstar,dc=lan" -w "$(cat /etc/ldap.secret)" <<EOF
dn: cn=dc-yoda,cn=dc,cn=computers,dc=deathstar,dc=lan
changetype: modify
replace: univentionServerRole
univentionServerRole: master
EOF

Extension-Objekte bleiben auf FALSE

Das S4-Connector Joinscript registriert LDAP-Schema-Extensions und UDM-Module. Jede Registration wartet 180 Sekunden darauf, dass der Listener das Extension-Objekt auf Active=TRUE setzt. Auf diesem System passiert das nicht — der Listener-Handler für Extensions funktioniert nicht korrekt.

Workaround: Parallel zum Joinscript einen Aktivator laufen lassen:

# In einer zweiten Shell:
while true; do
  for filter in "univentionUDMSyntaxActive=FALSE" \
                "univentionUDMModuleActive=FALSE" \
                "univentionLDAPSchemaActive=FALSE"; do
    attr="${filter%%=*}"
    univention-ldapsearch -xLLL "($filter)" dn 2>/dev/null | \
      grep "^dn:" | while read -r line; do
      dn="${line#dn: }"
      ldapmodify -x -H ldap://localhost:7389 \
        -D "cn=admin,dc=deathstar,dc=lan" \
        -w "$(cat /etc/ldap.secret)" <<EOF 2>/dev/null
dn: $dn
changetype: modify
replace: $attr
$attr: TRUE
EOF
    done
  done
  sleep 2
done

Checkliste: Nach UCS Backup→Master Promote

  • ucr get ldap/translogfile → muss /var/lib/univention-ldap/listener/listener sein
  • grep "overlay.*translog" /etc/ldap/slapd.conf → Overlay muss geladen sein
  • univention-ldapsearch -xLLL "cn=<HOSTNAME>" univentionServerRole → muss master sein
  • tail -1 /var/lib/univention-ldap/notify/transaction → ID muss nach UDM-Änderungen wachsen
  • ucr get server/role → muss domaincontroller_master sein
  • Alle FSMO-Rollen auf diesem Host: samba-tool fsmo show
  • kerberos/adminserver auf allen Member Servern korrigiert
  • ldap/master auf allen Member Servern korrigiert
  • S4-Connector Sync bidirektional getestet (UDM→Samba UND Samba→UDM)

Lessons Learned

  1. Der UCS Backup→Master Promote setzt nicht alle UCR-Variablen. ldap/translogfile ist die kritischste — ohne sie ist der gesamte Listener-Stack tot. Es gibt keinen Fehler, keine Warnung, kein Monitoring-Alert.

  2. Der S4-Connector hat zwei Sync-Pfade. Samba→UCS geht per Polling (funktioniert immer). UCS→Samba geht über den Listener (braucht funktionierenden Notifier). Wenn nur eine Richtung synchronisiert: Notifier prüfen.

  3. univentionServerRole im LDAP ≠ server/role in UCR. Beides muss stimmen. Die UCR-Variable steuert das lokale Verhalten, das LDAP-Objekt steuert wie andere Systeme (Joinscripts, Listener) den Host sehen.

  4. Extension-Aktivierung kann kaputt sein. Wenn Joinscripts mit “did not mark the extension object active within 180 seconds” scheitern: manuell per ldapmodify auf TRUE setzen. Hässlich, funktioniert.