IMConnect DICOM-Router – Betriebshandbuch¶
Dieses Handbuch richtet sich an Anwenderinnen und Anwender, die den DICOM-Router
konfigurieren und betreiben – nicht an Entwickler. Es erklärt den Aufbau der
Konfigurationsdatei dicom-router.yaml Schritt für Schritt und den laufenden Betrieb.
Weiterführende Detail-Konfiguration einzelner Plugins: Plugin-Referenz.
1. Überblick¶
Der DICOM-Router nimmt eingehende DICOM-Verbindungen an und leitet sie anhand von Filter-Regeln an definierte Ziele weiter. Optional kann er unterwegs Nachrichten umschreiben, zu einem zusätzlichen Empfänger abzweigen oder mitprotokollieren.
Vier Kernbegriffe beschreiben, wie der Router arbeitet:
| Begriff | Bedeutung |
|---|---|
| Listener | Der Port und der AE-Titel, unter dem der Router selbst erreichbar ist. |
| Filter | Geordnete Regeln, die entscheiden, was mit einer Verbindung passiert. |
| Actions | Optionale Verarbeitungsschritte (Plugins), die eine Regel anstösst. |
| Destinations | Benannte Ziele: entweder weiterleiten oder die Verbindung ablehnen. |
Vereinfachter Datenfluss einer Verbindung:
Gerät (Modalität/PACS)
│ DICOM-Verbindung
▼
┌──────────────┐
│ Listener │ nimmt die Verbindung an
└──────┬───────┘
▼
┌──────────────┐
│ Filter │ erste passende Regel gewinnt
└──────┬───────┘
│
┌────┴─────┐
▼ ▼
Actions Destination
(optional) ┌──────────────┬───────────────┐
▼ ▼
forward reject
(an Ziel weiterleiten) (Verbindung ablehnen)
│
▼
Ziel-System (z.B. PACS)
Für jede Verbindung sucht der Router die erste passende Filter-Regel, führt deren Actions aus (falls konfiguriert) und leitet die Verbindung an die in der Regel genannte Destination weiter – oder lehnt sie sauber ab.
2. Installation & erste Schritte¶
Dieser Abschnitt ist bewusst kurz. Die vollständige Schritt-für-Schritt-Anleitung (dedizierter Benutzer, Verzeichnisse, Rechte) steht in der Kopfzeile der mitgelieferten systemd-Unit und in der Deployment-Doku.
Der Router wird als .tar.gz ausgeliefert. Grober Ablauf einer Erstinstallation:
- Entpacken in das App-Verzeichnis (z.B.
/opt/imconnect): - Konfiguration anlegen: Das Verzeichnis
config/gehört dem Betreiber und wird bei Updates nie überschrieben. Die Vorlagen liegen untershare/mit der Endung.exampleund werden einmalig kopiert:Danachmkdir -p /opt/imconnect/config cp /opt/imconnect/share/dicom-router.yaml.example /opt/imconnect/config/dicom-router.yaml cp /opt/imconnect/share/logback.xml.example /opt/imconnect/config/logback.xml cp /opt/imconnect/share/dicom-router.env.example /opt/imconnect/config/dicom-router.envdicom-router.yamlan die eigene Umgebung anpassen (siehe Abschnitt 3). Zugangsdaten zur Datenbank liegen indicom-router.env(chmod 600). - systemd-Unit installieren (Vorlage
dicom-router.service.example) und starten: - Prüfen, ob der Router läuft:
3. Die Konfigurationsdatei dicom-router.yaml¶
Die aktive Konfiguration liegt unter /opt/imconnect/config/dicom-router.yaml. Sie ist
in Abschnitte gegliedert. Für den normalen Betrieb sind vor allem router,
destinations, filter und actions relevant.
3.1 router – Listener und allgemeine Einstellungen¶
router:
listener:
host: 0.0.0.0
port: 11112
aet: IMCONNECT
tcplog: false
socketTimeout: 120000
connectTimeout: 10000
max-pdu-length: 131072
storage-path: /var/tmp/dicom-cache
log-folder: /var/log/imconnect/pdu-dumps
router.listener – so ist der Router selbst erreichbar:
| Feld | Bedeutung |
|---|---|
host |
Adresse, auf der gelauscht wird. 0.0.0.0 = alle Netzwerkkarten. |
port |
Port, auf dem DICOM-Verbindungen angenommen werden (Standard 11112). |
aet |
Der eigene AE-Titel des Routers. |
tcplog |
Schreibt jedes empfangene und gesendete TCP-Paket dieses Listeners vollständig ins Programm-Log (true/false, Vorlage: false). Nur zur Fehlersuche — siehe den Hinweis unter der Tabelle. |
socketTimeout |
Zeitlimit einer inaktiven Verbindung in Millisekunden (fehlt das Feld, gilt 60000; die Vorlagendatei setzt 120000). Derselbe Wert begrenzt auch, wie lange ein einzelner Schreibvorgang zum Client oder zum Ziel dauern darf — eine Gegenstelle, die nichts mehr abholt, blockiert den Router sonst unbegrenzt. |
connectTimeout |
Zeitlimit in Millisekunden für den Verbindungsaufbau zu einem Ziel — Namensauflösung und TCP-Handshake zusammen (fehlt das Feld, gilt 10000). Ist ein Ziel nicht erreichbar, gibt der Router nach dieser Zeit auf, statt auf das Zeitlimit des Betriebssystems zu warten (unter Linux bis zu zwei Minuten), während die Gegenstelle ohne Antwort wartet. |
tcplognur zur Fehlersuche einschalten. Die Ausgabe enthält den Paketinhalt vollständig und damit auch Patientendaten im Klartext (Name, Patienten-ID). Das Programm-Log wird nach Grösse und Alter rotiert und ist nicht als Ablage für Patientendaten gedacht; ausserdem füllt ein Eintrag pro TCP-Paket die Logdateien bei Last innerhalb von Minuten. Zum Analysieren einschalten, danach wieder ausschalten (beides ohne Neustart), und die Logdateien der Zeit dazwischen entsprechend behandeln. Für die dauerhafte Nachvollziehbarkeit ist der Datenbank-Audit-Trail da.
Weitere router-Einstellungen, die ein Betreiber ggf. anpasst:
| Feld | Bedeutung |
|---|---|
max-pdu-length |
Maximale DICOM-Paketgrösse (PDU), die der Router den Gegenstellen anbietet und durchsetzt. Erlaubt sind Werte von 4096 bis 4194304 (4 MB); die Vorlagendatei liefert 131072 (128 KB). Grössere Werte reduzieren den Protokoll-Overhead bei grossen Objekten; Werte über 1 MB sind nicht empfohlen (solche Pakete puffert der Router auf die Festplatte statt im Speicher). Die Gegenstelle handelt unabhängig davon ihr eigenes Maximum aus — effektiv gilt je Richtung der kleinere Wert. |
storage-path |
Verzeichnis für den internen Zwischenspeicher grosser Objekte. Muss beschreibbar sein. |
log-folder |
Verzeichnis für binäre PDU-Mitschnitte (nur bei aktiviertem logLevel 5/6/7, siehe Abschnitt 5). Nicht die normalen Anwendungslogs. |
Die übrigen router-Felder (Speicher-Schwellen usw.) sind technische Feinjustierung und
in der Vorlagendatei kommentiert – im Normalfall unverändert lassen.
3.2 destinations – Ziele¶
Ziele sind benannt und werden aus Filter-Regeln über ihren Namen referenziert. Es gibt zwei Typen.
Weiterleiten (type: forward) – der Regelfall. type darf weggelassen werden, da
forward der Standard ist:
| Feld | Bedeutung |
|---|---|
host |
Ziel-Rechner (Hostname oder IP). |
port |
Ziel-Port. |
aet |
AE-Titel des Ziel-Systems. |
Ablehnen (type: reject) – weist die Verbindung sauber mit einer DICOM-Ablehnung
(A-ASSOCIATE-RJ) zurück, statt sie weiterzuleiten:
destinations:
reject_unknown:
type: reject
result: 1 # rejected-permanent
source: 1 # service-user
reason: 7 # called-aet-not-recognized
message: "Unbekannter AE-Titel – Verbindung abgelehnt"
Die Felder result, source und reason sind DICOM-Codes. Für die meisten Fälle
genügt eine dieser gängigen Kombinationen:
| Zweck | result |
source |
reason |
|---|---|---|---|
| Unbekannter Ziel-AE-Titel (called AET) | 1 | 1 | 7 |
| Unbekannter Absender-AE-Titel (calling AET) | 1 | 1 | 3 |
| Generelle Ablehnung ohne näheren Grund | 1 | 1 | 1 |
| Vorübergehend keine Kapazität (transient) | 2 | 3 | 1 |
result:1= dauerhaft abgelehnt,2= vorübergehend abgelehnt.source:1= Service-User,2= ACSE,3= Presentation.reason: Bedeutung hängt vonsourceab (siehe Codes oben).message: freier Text, erscheint nur im Log.
Den reason passend zum Ablehnungsgrund wählen: Wird nach dem Absender
gefiltert (unbekanntes Gerät, Auffang-Regel über callingAET), ist reason: 3
der korrekte Code; reason: 7 passt, wenn der angefragte AE-Titel nicht
existiert; im Zweifel ist reason: 1 (kein näherer Grund) immer zulässig.
3.3 filter – Routing-Regeln¶
filter ist eine geordnete Liste. Der Router prüft die Regeln von oben nach unten und
wendet die erste an, die passt (first match wins). Danach wird nicht weitergesucht.
Deshalb: spezifische Regeln nach oben, eine Auffang-Regel ganz nach unten.
Die wichtigsten Felder einer Regel:
| Feld | Bedeutung |
|---|---|
callingAET |
AE-Titel des Absenders (Gerät). * oder weglassen = beliebig. |
calledAET |
Angefragter Ziel-AE-Titel. * oder weglassen = beliebig. |
logLevel |
Protokollierungsstufe für diese Verbindung (siehe Abschnitt 5). |
actions |
Liste von Action-Namen, die für diese Regel ausgeführt werden (optional). |
destination |
Das Ziel der Regel: ein Name aus destinations: (weiterleiten oder ablehnen). |
Hinweis: Das YAML-Feld
destinationnimmt formal eine Liste an, unterstützt aber genau ein Ziel — nur der erste Eintrag wird verwendet. Die Listenform existiert, damit die Konfigurationsstruktur stabil bleibt, falls künftig mehrere Ziele möglich werden. Also: immer genau einen Eintrag angeben, z.B.destination: ["pacs1"].
Zusätzlich lässt sich eine Regel über Netzwerk-Merkmale einschränken (clientLocalIp,
routerLocalPort usw.); ohne Angabe gilt jeweils „beliebig" (IP 0.0.0.0/0, Port 0).
AE-Titel-Vergleich: Werte werden standardmässig exakt verglichen
(Gross-/Kleinschreibung beachten); nur der Wert * bedeutet „beliebig". Mit dem Präfix
regex: wird der Wert stattdessen als regulärer Ausdruck ausgewertet und muss den
ganzen AE-Titel abdecken:
Ein ungültiger Ausdruck ist ein Konfigurationsfehler und verhindert Start bzw. reload.
Beispiel 1 – ein Gerät an ein PACS, alles andere ablehnen:
filter:
- callingAET: US1
calledAET: PACS
destination:
- "pacs1"
# Auffang-Regel: alles Übrige ablehnen
- callingAET: "*"
calledAET: "*"
destination:
- "reject_unknown"
Beispiel 2 – mehrere gleichartige Geräte über einen regulären Ausdruck:
filter:
- callingAET: "regex:^US[0-9]+$" # US1, US2, ...
calledAET: PACS
destination:
- "pacs1"
- callingAET: "*"
destination:
- "reject_unknown"
Beispiel 3 – Regel mit AE-Titel-Umschreibung vor dem Weiterleiten:
filter:
- callingAET: MRI1
calledAET: PACS
actions:
- "aetRewrite_mri" # in actions definiert, siehe unten
destination:
- "pacs1"
3.4 actions – Verarbeitungsschritte (Plugins)¶
Unter actions werden benannte Verarbeitungsschritte definiert. Ein Name verweist auf
eine Liste von Plugin-Einträgen; die Parameter eines Plugins stehen in seinem
config:-Block. Eine Regel aktiviert eine Action, indem sie deren Namen unter actions
nennt (siehe Beispiel 3 oben).
Grundaufbau:
actions:
aetRewrite_mri:
- plugin: <Plugin-Kennung – siehe Plugin-Referenz>
config:
# plugin-spezifische Parameter
enabled: true
Welche Plugins verfügbar sind und welche Parameter ihr config:-Block kennt (z.B.
AE-Titel-Umschreibung, Protokoll-Mitschnitt, Q/R-Feldanpassung), ist in der
Plugin-Referenz beschrieben. Für reines Weiterleiten ohne
Umschreiben werden keine Actions benötigt – dann genügt destination.
Eine Action läuft nur, wenn eine Regel sie nennt. Es gibt kein automatisches Laden:
Wird ein Action-Name von keiner Filter-Regel unter actions referenziert, passiert
nichts – die Definition allein genügt nicht. Der Router weist beim Start und bei jedem
reload mit einer Warnung im Log darauf hin und nennt den Namen. Zum Aktivieren also
immer beides tun: die Action definieren und sie in der passenden Regel eintragen.
3.5 management und audit¶
Diese beiden Abschnitte sind meist mit den Standardwerten korrekt und müssen selten angefasst werden.
management steuert die beiden Zusatz-Ports für Betrieb und Überwachung:
management:
enabled: true
agent-check-port: 8404 # Zustandsabfrage durch HAProxy (netzwerkerreichbar)
agent-check-bind-address: "0.0.0.0"
management-port: 8405 # Operator-Kommandos (nur lokal, 127.0.0.1)
management-bind-address: "127.0.0.1"
Der Management-Port ist bewusst nur lokal (127.0.0.1) erreichbar. Er ist ohne
zusätzliche Absicherung nicht authentifiziert – d.h. jeder lokale Prozess könnte den
Router stoppen. Optional lässt sich über eine Token-Datei ein Passwort verlangen; Details
dazu in der Management-Doku.
audit schreibt einen Prüf-/Nachweispfad in die Datenbank: je eine Zeile pro
Verbindung und pro DICOM-Operation, verlustfrei über einen lokalen Zwischenspeicher
(einzige Ausnahme: läuft der Zwischenspeicher über sein spool-max-mb-Limit, etwa bei
einem sehr langen Datenbank-Ausfall, werden weitere Einträge verworfen und gezählt). Ein
Datenbank-Ausfall führt nicht zu Datenverlust und beeinträchtigt das Routing nicht.
audit:
enabled: true
spool-path: /var/imconnect/audit-spool
spool-max-mb: 512
batch-size: 100
flush-interval: 1s
capture-patient-name: false # Patientenname (PHI!) – standardmässig aus
capture-patient-name sollte nur aus gutem Grund aktiviert werden, da es
Patientendaten (PHI) speichert.
3.6 Welche Änderungen ein reload übernimmt¶
Viele Änderungen greifen ohne Neustart über das Kommando reload (siehe Abschnitt 4):
Neue Verbindungen nutzen dann die neue Konfiguration, bereits laufende Verbindungen
behalten ihre bisherige. Einige grundlegende Felder werden dagegen erst beim Start
gebunden und verlangen einen Neustart.
Sofort per reload übernehmbar |
Nur mit Neustart wirksam |
|---|---|
filter (Routing-Regeln) |
router.listener.host / port / aet |
destinations (forward-/reject-/qr-bridge-Ziele) – Ausnahme: store: einer qr-bridge-Destination |
der gesamte management-Block |
actions (Plugins und deren config:) – Ausnahme: store: der CMoveTrackingStage |
der gesamte audit-Block – Ausnahme: capture-patient-name |
proxyprotocol |
store: einer CMoveTrackingStage-Action |
router.listener.socketTimeout / connectTimeout / tcplog |
store: einer qr-bridge-Destination |
audit.capture-patient-name |
|
die router-Speicher-Schwellen |
Bei den beiden store:-Einträgen gilt das nicht nur für den Wert: Verschwindet
ein solcher Eintrag (entfernt oder umbenannt) und rückt im selben reload kein
Eintrag mit demselben Store nach, ist der reload ebenfalls neustartpflichtig.
Die Speicher-Instanzen werden beim Start angelegt, und ein umbenannter Eintrag
ist von einem entfernten nicht zu unterscheiden. Reine Ergänzungen bleiben
übernehmbar.
Versucht ein reload ein neustartpflichtiges Feld zu ändern, wird er mit
requires restart abgelehnt und die bisherige Konfiguration bleibt aktiv. Die
vollständige Feldliste steht in der Management-Doku.
4. Betrieb¶
Gesteuert wird der laufende Router über das mitgelieferte CLI-Werkzeug
dicom-router-ctl (unter /opt/imconnect/bin/).
| Kommando | Wirkung |
|---|---|
dicom-router-ctl status |
Zustand, Anzahl aktiver Verbindungen, Laufzeit, Audit-Status. |
dicom-router-ctl connections |
Liste der aktiven DICOM-Verbindungen. |
dicom-router-ctl drain |
Keine neuen Verbindungen mehr annehmen; bestehende laufen weiter. |
dicom-router-ctl resume |
Nach einem drain wieder Verbindungen annehmen. |
dicom-router-ctl reload |
Konfiguration neu einlesen (siehe Abschnitt 3.6). |
dicom-router-ctl shutdown |
Sofortiger geordneter Stopp. |
dicom-router-ctl drain-and-shutdown |
Erst leeren, auf 0 Verbindungen warten, dann stoppen. |
Stopp: shutdown vs. drain-and-shutdown¶
Der Unterschied ist wichtig:
shutdownstoppt den Router sofort. Noch laufende Übertragungen werden dabei getrennt.drain-and-shutdownnimmt zuerst keine neuen Verbindungen mehr an, wartet, bis alle laufenden Übertragungen fertig sind, und stoppt erst danach. Das ist der schonende Weg für ein Wartungsfenster oder Update.
Neustart über systemd¶
Ein Neustart erfolgt über systemd:
Das ist automatisch schonend: Beim Stoppen ruft die systemd-Unit intern
drain-and-shutdown auf, wartet also erst alle laufenden Verbindungen ab, bevor sie
den Prozess beendet. Für die Wartezeit ist ein grosszügiges Zeitlimit gesetzt. Nach einem
unerwarteten Absturz startet der Dienst automatisch neu; ein sauberer Stopp bleibt
gestoppt.
Konfiguration ändern (Workflow)¶
/opt/imconnect/config/dicom-router.yamlbearbeiten.- Optional vorab prüfen, ganz ohne den laufenden Router anzufassen:
Meldet
OKoder listet die Fehler auf (gleiche Prüfung wie beim Reload). Dazu zählt jeder Schlüssel, den es nicht gibt: ein Tippfehler oder eine falsche Schreibweise (tokenFilestatttoken-file) lässt die Prüfung mit Abschnitt und Feldnamen fehlschlagen, statt die Einstellung stillschweigend zu verwerfen. Alle Fehler einer Datei werden in einem Durchgang gemeldet. Wichtig: den Befehl im Installationsverzeichnis ausführen (bzw. in Automatisierung wie Ansiblechdirsetzen) — Plugin-Klassen ausplugins/werden relativ zum Arbeitsverzeichnis gesucht; aus einem anderen Verzeichnis meldet die Prüfung sonst fälschlich Fehler, wenn die Konfiguration externe Plugins verwendet. - Übernehmen:
dicom-router-ctl reload. - Antwort prüfen:
OK config reloaded– Änderung ist aktiv.ERROR ... requires restart– ein neustartpflichtiges Feld wurde geändert; dann stattdessensystemctl restart dicom-router.- Andere
ERROR ...– die Konfiguration hat einen Fehler; die alte Konfiguration bleibt aktiv, bis der Fehler behoben und ein erneuterreloaderfolgreich ist.
Mehrere Hosts: Konfiguration verteilen (dicom-router-sync)¶
Läuft der Router auf mehreren Hosts (z. B. hinter HAProxy), wird die Konfiguration auf
einem Host bearbeitet und mit dicom-router-sync auf alle anderen verteilt:
- Die anderen Hosts einmalig in
/opt/imconnect/config/cluster-hostseintragen (Vorlage:share/cluster-hosts.example; eine Zeile pro Host,user@hosterlaubt). Voraussetzung ist passwortloser ssh-Zugang vom Bearbeitungs-Host zu jedem Ziel. - Nach dem Bearbeiten der YAML:
dicom-router-syncausführen. Das Tool - sichert den Stand automatisch in
config/config-history/(Historie für Rückfragen und Rollback — einfach einen alten Stand zurückkopieren und erneut verteilen), - reloaded zuerst den lokalen Router als Probe: Wird die Konfiguration abgelehnt, bricht das Tool ab, bevor irgendein anderer Host angefasst wird — überall bleibt die alte Konfiguration aktiv,
- kopiert die Datei dann auf alle Hosts, reloaded sie und prüft per Checksumme,
dass überall derselbe Stand liegt — wo der Router es meldet, zusätzlich gegen
den
config-hashausstatus, also den tatsächlich geladenen Stand (Ergebnis-Tabelle am Ende,MATCH (loaded)). - Meldet die Probe
requires restart, verteilt das Tool die Datei, überspringt die Reloads und zeigt die Anleitung für den rollierenden Neustart (systemctl restart dicom-router, Host für Host).
Weitere Modi: dicom-router-sync --check vergleicht nur die Stände aller Hosts
(nützlich als Drift-Kontrolle, ändert nichts); --no-reload verteilt nur.
Die Ergebnis-Tabelle unterscheidet dabei, woran es lag: UNREACHABLE heisst, der
Host war per ssh nicht erreichbar, MISSING dagegen, dass die ssh-Verbindung stand,
auf dem Host aber (noch) keine Konfigurationsdatei liegt — typisch für einen frisch
aufgesetzten Knoten. NO-SHA256SUM meldet einen Host ohne sha256sum-Kommando,
auf dem sich der Stand nicht prüfen lässt.
Neue Destination mit automatischem Return-Port (return-port: 0)¶
Wer HAProxy-Rückwege nutzt (haproxy-return mit konfigurierter port-range),
muss Return-Ports nicht mehr von Hand vergeben:
- Die neue Destination mit dem Marker
return-port: 0anlegen: - Den Marker lokal ersetzen lassen:
Das Subkommando vergibt den kleinsten freien Port der
cd /opt/imconnect java -jar dicom-router-core-*.jar --allocate-return-ports config/dicom-router.yamlport-rangeund zeigt die Zuordnung an (z. B.ct_neu: return-port 5014); bereits vergebene Ports anderer Destinations bleiben immer unverändert. (Vor Schritt 3 nötig —dicom-router-haproxy-syncbricht auf einem unallozierten Marker ab.) - Den neuen Rückweg auf den HAProxy-Hosts aktivieren:
dicom-router-haproxy-sync(nächster Abschnitt). - Erst jetzt die Router-Konfiguration verteilen:
dicom-router-sync. In dieser Reihenfolge wählt der Router nie einen Port an, den HAProxy noch nicht kennt. Ohne Cluster (Einzel-Host) stattdessendicom-router-ctl reload.
Ein vergessener Marker kann nie unbemerkt live gehen: Start, reload und
--validate-config lehnen eine Konfiguration mit return-port: 0 mit einer
klaren Fehlermeldung ab.
Rückwege, die von Hand in der HAProxy-Config stehen: Die generierte
HAProxy-Datei enthält nur Destinations, deren return-port innerhalb der
port-range liegt. Wer einen Rückweg selbst in seiner HAProxy-Konfiguration
führt (fester Port, abweichendes Backend-Setup, Alt-Eintrag), vergibt der
Destination einen return-port ausserhalb der Range. Der Router wählt sie
weiterhin über vip:return-port an, der Rückweg taucht aber nicht in der
generierten Datei auf — sonst gäbe es zwei listen-Blöcke auf demselben bind
und HAProxy startet nicht mehr. Übersprungene Destinations listet die generierte
Datei als Kommentar auf:
# skipped (return-port outside port-range 5000-5999 — manual HAProxy entry):
# ct_b bind 10.0.0.10:4711 -> 192.168.10.9:104
Beim Update auf diese Version gilt das rückwirkend: Wer eine port-range
konfiguriert hat und Destinations mit einem return-port ausserhalb davon
führt, verliert deren listen-Blöcke beim nächsten dicom-router-haproxy-sync
aus der generierten Datei. dicom-router-haproxy-sync --check zeigt das vorab an
und benennt die Blöcke ausdrücklich als weiterhin konfiguriert („target has
listen block(s) for destination(s) STILL in the YAML … do NOT remove them") —
sie gehören vorher in die eigene HAProxy-Konfiguration übernommen.
HAProxy-Rückwege verteilen (dicom-router-haproxy-sync)¶
Wer HAProxy-Rückwege nutzt, muss die generierte HAProxy-Datei nicht mehr von Hand auf die HAProxy-Hosts bringen:
- Die HAProxy-Hosts einmalig in
/opt/imconnect/config/haproxy-hostseintragen (Vorlage:share/haproxy-hosts.example; eine Zeile pro Host, optional mit Zielpfad, Standard/etc/haproxy/conf.d/dicom-return.cfg). Voraussetzungen: passwortloser ssh-Zugang, Schreibrecht auf den Zielpfad und eine sudo-Regel fürsystemctl reload haproxy(Details: Deployment-Doku). - Nach jeder Änderung an den Rückwegen:
dicom-router-haproxy-syncausführen. Das Tool generiert die Datei aus der YAML, kopiert sie auf alle Hosts (auf unveränderten Hosts entfallen Kopie und Prüfung, der Reload läuft trotzdem — so holt ein Wiederholungslauf einen zuvor gescheiterten Reload nach), prüft sie dort mithaproxy -c, bevor sie aktiv wird (bei einem Fehler bleibt auf dem Host der alte Stand unangetastet), reloaded HAProxy unterbrechungsfrei (laufende Übertragungen überleben) und prüft per Checksumme, dass überall derselbe Stand liegt (Ergebnis-Tabelle am Ende). Es verwaltet nur diese eine Datei — nie die Haupt-Konfiguration von HAProxy.
Reihenfolge-Regel:
- Destination hinzugefügt → erst
dicom-router-haproxy-sync, danndicom-router-sync— ein neuerlisten-Block ist harmlos, solange ihn niemand anwählt; umgekehrt würde der Router einen Port anwählen, den HAProxy noch nicht kennt. - Destination entfernt → umgekehrt: erst
dicom-router-sync, danndicom-router-haproxy-sync. return-portaus derport-rangeheraus geändert (der Rückweg wird von Hand geführt, siehe Abschnitt oben) → erst denlisten-Block in die eigene HAProxy-Konfiguration übernehmen, danndicom-router-haproxy-sync— sonst ist der Rückweg dazwischen nicht erreichbar.
Alle drei Regeln gibt das Tool auch selbst als Hinweis aus — auch die dritte: auf dem HAProxy-Host sieht sie aus wie eine entfernte Destination, das Skript erkennt sie aber an der Skip-Liste der generierten Datei und meldet dann ausdrücklich, dass der Block nicht verwaist ist und nicht entfernt werden darf. Der Abgleich läuft über den Blocknamen: wird eine solche Destination zusätzlich umbenannt, meldet das Skript den alten Block als verwaist, obwohl sein Rückweg weiter benutzt wird. Vor dem Entfernen eines gemeldeten Blocks deshalb die Skip-Liste der generierten Datei prüfen — der Hinweistext sagt das auch selbst.
Weitere Modi: dicom-router-haproxy-sync --check vergleicht nur die Stände
aller Hosts (ändert nichts); --no-reload verteilt und prüft, reloaded aber
nicht.
5. Fehlersuche¶
Wo liegen die Logs?¶
Es gibt zwei unabhängige Log-Mechanismen – leicht zu verwechseln:
| Was | Wo / wie | Inhalt |
|---|---|---|
| Anwendungslog | Datei dicom-router.log im Log-Verzeichnis (Standard /var/log/imconnect), konfiguriert über logback.xml |
normale Meldungen (INFO/WARN/ERROR) – die erste Anlaufstelle |
| Binäre PDU-Mitschnitte | Verzeichnis aus router.log-folder, aktiviert über logLevel 5/6/7 in einer Filter-Regel |
vollständige DICOM-Pakete als Binärdateien – nur zur Diagnose |
Das normale Anwendungslog wird automatisch rotiert. Die PDU-Mitschnitte sind ein
Diagnose-Werkzeug für schwierige Fälle: Sie enthalten vollständige Patientendaten (PHI),
werden nicht rotiert oder automatisch gelöscht und sollten nur vorübergehend aktiviert
werden. Nach der Analyse den logLevel zurücksetzen und die Mitschnitte entfernen.
Das Setzen von logLevel in der Filter-Regel genügt — die Mitschnitt-Funktion ist
fest eingebaut, es ist keine Action nötig. logLevel ist hot-reloadbar: Wert ändern,
dicom-router-ctl reload, fertig — und zum Abschalten genauso zurück auf 0. (Das
Plugin PduLoggingStage in der Plugin-Referenz fügt lediglich
zusätzliche benannte Logger hinzu.)
logLevel-Stufen in einer Filter-Regel:
| Wert | Bedeutung |
|---|---|
0 |
keine Protokollierung |
1 |
eingehend protokollieren |
2 |
ausgehend protokollieren |
3 |
ein- und ausgehend protokollieren |
5 |
eingehend als Datei mitschneiden |
6 |
ausgehend als Datei mitschneiden |
7 |
ein- und ausgehend als Datei mitschneiden |
Laufenden Zustand ansehen¶
dicom-router-ctl status # Zustand, Verbindungszahl, Laufzeit, Audit
dicom-router-ctl connections # welche Verbindungen gerade offen sind
Typische Fehlerbilder¶
-
Eine Verbindung wird abgelehnt. Zuerst
dicom-router-ctl statusprüfen: Steht der Router im Zustanddrain, nimmt er absichtlich keine neuen Verbindungen an (dicom-router-ctl resumebehebt das). Ist der Zustandready, greift wahrscheinlich einereject-Destination – meist die Auffang-Regel am Ende der Filter-Liste (derenmessageerscheint im Anwendungslog). Prüfen: Gibt es eine passende Regel vor der Auffang-Regel? StimmencallingAET/calledAETexakt (Gross-/Kleinschreibung, keine Leerzeichen)? Ist der richtigeportgemeint? -
Verbindungen werden abgebrochen, seit eine Action dazukam. Lässt sich ein in einer Regel eingetragenes Plugin nicht laden oder nicht mit seiner Konfiguration starten, bricht der Router die betroffene Association ab, statt sie ohne diesen Verarbeitungsschritt weiterzuleiten – eine Verbindung ohne ihre konfigurierte Anonymisierung oder Umschreibung soll nicht unbemerkt laufen. Im Anwendungslog steht eine
ERROR-Zeile mit Plugin und Action. Vorab findet man das mit--validate-config(siehe Abschnitt 4): die Prüfung lädt jede eingetragene Plugin-Klasse und jedenconfig:-Block. -
Ziel nicht erreichbar / Weiterleitung schlägt fehl.
host,portundaetderforward-Destination gegen das Ziel-System prüfen. Ist das Ziel-System über das Netz erreichbar und akzeptiert es den vom Router genutzten AE-Titel? -
reloadwird abgelehnt. requires restart: Es wurde ein neustartpflichtiges Feld geändert (Listener,management,auditoder einstore:— auch durch Entfernen bzw. Umbenennen eines Tracking-Eintrags oder einerqr-bridge-Destination, siehe Abschnitt 3.6) →systemctl restart dicom-router.- anderer
ERROR: Die YAML enthält einen Fehler (Tippfehler, ungültiger regulärer Ausdruck, unbekanntes Ziel) oder die Datei fehlt (dann wird nichts neu angelegt). Der Router läuft mit der alten Konfiguration weiter, bis einreloadfehlerfrei durchläuft.