Dieses Kapitel beschreibt einen Beispielressourcentyp, SUNW.xfnts, der mit der DSDL implementiert wird. Der Datendienst ist in C geschrieben. Die zugrunde liegende Anwendung ist X Font Server, ein TCP/IP-basierter Dienst.
In diesem Kapitel finden Sie folgende Informationen:
X Font Server ist ein einfacher, TCP/IP-basierter Dienst, der seinen Clients Schriftdateien zustellt. Clients stellen eine Verbindung mit dem Server her, um einen Schriftsatz anzufordern. Der Server liest die Schriftdateien von der Platte und stellt sie den Clients zu. Der X Font Server-Dämon besteht aus einer Server-Binärdatei, /usr/openwin/bin/xfs. Der Dämon wird in der Regel von inetd aus gestartet. In diesem Beispiel wird jedoch angenommen, dass der entsprechende Eintrag in der /etc/inetd.conf-Datei deaktiviert wurde (zum Beispiel durch den Befehl fsadmin -d). Daher befindet sich der Dämon unter alleiniger Steuerung durch Sun Cluster.
Standardmäßig liest X Font Server die Konfigurationsinformationen aus der Datei /usr/openwin/lib/X11/fontserver.cfg. Der Katalogeintrag in diese Datei enthält eine Liste der Schriftverzeichnisse, die dem Dämon zur Verfügung stehen. Der Cluster-Verwalter kann die Schriftverzeichnisse im globalen Dateisystem ablegen. Dadurch wird die Verwendung von X Font Server unter Sun Cluster optimiert, da im System nur eine einzige Kopie der Schriftdatenbank verwaltet wird. Dann muss der Verwalter fontserver.cfg dahingehend bearbeiten, dass die neuen Pfade für die Schriftverzeichnisse enthalten sind.
Zur Vereinfachung der Konfiguration kann der Verwalter auch die Konfigurationsdatei selbst im globalen Dateisystem ablegen. Der xfs-Dämon stellt Befehlszeilenargumente bereit, mit denen der vorgegebene Standardspeicherort dieser Datei übersteuert wird. Der SUNW.xfnts-Ressourcentyp verwendet den folgenden Befehl zum Starten des Dämons unter Sun Cluster-Steuerung:
/usr/openwin/bin/xfs -config <Speicherort_der_CFG_Datei>/fontserver.cfg \ -port <Port-Nummer> |
In der SUNW.xfnts-Ressourcentypimplementierung können Sie die Confdir_list-Eigenschaft zum Verwalten des Speicherortes der fontserver.cfg-Konfigurationsdatei verwenden.
Die TCP-Port-Nummer, die der xfs-Serverdämon abhört, ist normalerweise der “fs”-Port (üblicherweise als 7100 in der /etc/services-Datei definiert). Mit der Option -port an der xfs-Befehlszeile kann der Systemverwalter jedoch die Standardeinstellung übersteuern. Sie können die Port_list-Eigenschaft im SUNW.xfnts-Ressourcentyp verwenden, um den Standardwert einzustellen und um die Verwendung der Option -port an der xfs-Befehlszeile zu unterstützen. Der Standardwert dieser Eigenschaft wird als 7100/tcp in der RTR-Datei definiert. In der SUNW.xfnts Start-Methode wird Port_list an die Option -port an der xfs-Befehlszeile übergeben. Daher muss der Benutzer dieses Ressourcentyps keine Port-Nummer angeben—der Standard-Port ist 7100/tcp—, er hat jedoch die Möglichkeit, bei der Konfiguration des Ressourcentyps einen anderen Port anzugeben, indem er einen anderen Wert für die Port_list-Eigenschaft angibt.
Sie können die verschiedenen Teile des Beispielcodes identifizieren, indem Sie auf folgende Konventionen achten.
RMAPI-Funktionen beginnen mit scha_.
DSDL-Funktionen beginnen mit scds_.
Rückmeldemethoden beginnen mit xfnts_.
Benutzergeschriebene Funktionen beginnen mit svc_.
Dieser Abschnitt beschreibt mehrere Schlüsseleigenschaften in der SUNW.xfnts-RTR-Datei. Der Zweck der einzelnen Eigenschaften in der Datei wird nicht beschrieben. Diese Beschreibung finden Sie unter Einstellen der Ressourcen- und Ressourcentypeigenschaften.
Die Confdir_list-Erweiterungseigenschaft identifiziert das Konfigurationsverzeichnis (bzw. eine Verzeichnisliste) folgendermaßen:
{ PROPERTY = Confdir_list; EXTENSION; STRINGARRAY; TUNABLE = AT_CREATION; DESCRIPTION = "Pfad(e) zum Konfigurationsverzeichnis; }
Die Confdir_list-Eigenschaft gibt keinen Standardwert an. Der Cluster-Verwalter muss zum Zeitpunkt der Ressourcenerstellung ein Verzeichnis angeben. Dieser Wert kann später nicht mehr geändert werden, da seine Einstellbarkeit auf AT_CREATION beschränkt ist.
Die Port_list-Eigenschaft identifiziert folgendermaßen den Port, den der Serverdämon abhört:
{ PROPERTY = Port_list; DEFAULT = 7100/tcp; TUNABLE = AT_CREATION; }
Da für die Eigenschaft ein Standardwert deklariert wird, kann der Cluster-Verwalter zum Zeitpunkt der Ressourcenerstellung entscheiden, ob er einen neuen Wert angibt oder den Standardwert akzeptiert. Dieser Wert kann später nicht mehr geändert werden, da seine Einstellbarkeit auf AT_CREATION beschränkt ist.
Die DSDL erfordert, dass jede Rückmeldemethode zu Methodenbeginn die scds_initialize(3HA)-Funktion aufruft. Diese Funktion führt folgende Vorgänge aus:
Sie prüft und verarbeitet die Befehlszeilenargumente (argc und argv), die das Framework an die Datendienstmethode übergibt. Die Methode muss keine weiteren Verarbeitungsschritte für die Befehlszeilenargumente ausführen.
Sie richtet interne Datenstrukturen ein, die von anderen DSDL-Funktionen verwendet werden können.
Sie initialisiert die Protokollierumgebung.
Sie validiert die Testsignaleinstellungen des Fehler-Monitors.
Sie verwendet die scds_close()-Funktion, um die Ressourcen zurückzufordern, die von scds_initialize() zugewiesen wurden.
RGM ruft die Start-Methode auf einem Cluster-Knoten auf, wenn die Ressourcengruppe mit der Datendienstressource auf diesem Knoten online gebracht wird bzw. wenn die Ressource aktiviert wird. Im SUNW.xfnts-Beispielressourcentyp aktiviert die xfnts_start-Methode den xfs-Dämon auf diesem Knoten.
Die xfnts_start-Methode ruft scds_pmf_start() auf, um den Dämon unter PMF zu starten. PMF verfügt über automatische Fehlerbenachrichtigungs- und Neustartfunktionen und ist in den Fehler-Monitor integriert.
Der erste Aufruf in xfnts_start erfolgt an scds_initialize(). Diese Funktion führt einige wichtige Systemverwaltungs-Funktionen aus (weitere Einzelheiten finden Sie unter scds_initialize()-Funktion und in der Online-Dokumentation unter scds_initialize(3HA)).
Vor dem Versuch, X Font Server zu starten, ruft die xfnts_start-Methode svc_validate() auf, um zu überprüfen, ob eine geeignete Konfiguration zur Unterstützung des xfs-Dämons eingerichtet ist (weitere Einzelheiten hierzu finden Sie unter xfnts_validate-Methode):
rc = svc_validate(scds_handle); if (rc != 0) { scds_syslog(LOG_ERR, "Konfigurationsvalidierung fehlgeschlagen."); return (rc); }
Die xfnts_start-Methode ruft die svc_start()-Methode auf, die in xfnts.c definiert ist, um den xfs-Dämon zu starten. Dieser Abschnitt beschreibt svc_start().
Folgender Befehl startet den xfs-Dämon:
xfs -config Konfig_verzeichnis/fontserver.cfg -port Port_Nummer |
Die Confdir_list-Erweiterungseigenschaft identifiziert Konfig_verzeichnis, während die Port_list-Systemeigenschaft Port_Nummer identifiziert. Beim Konfigurieren des Datendienstes stellt der Cluster-Verwalter spezifische Werte für diese Eigenschaften bereit.
Die xfnts_start-Methode deklariert diese Eigenschaften als Zeichenketten-Arrays und ruft die Werte ab, die der Verwalter mit den Funktionen scds_get_ext_confdir_list() und scds_get_port_list() einstellt (beschrieben unter scds_property_functions(3HA)):
scha_str_array_t *confdirs; scds_port_list_t *portlist; scha_err_t err; /* Konfigurationsverzeichnis aus der confdir_list-Eigenschaft abrufen */ confdirs = scds_get_ext_confdir_list(scds_handle); (void) sprintf(xfnts_conf, "%s/fontserver.cfg", confdirs->str_array[0]); /* Von XFS zu verwendenden Port aus der Port_list-Eigenschaft abrufen */ err = scds_get_port_list(scds_handle, &portlist); if (err != SCHA_ERR_NOERR) { scds_syslog(LOG_ERR, "Auf die Port_list-Eigenschaft konnte nicht zugegriffen werden."); return (1); }
Beachten Sie, dass die confdirs-Variable auf das erste Element (0) im Array zeigt.
Die xfnts_start-Methode verwendet sprintf, um die Befehlszeile für xfs zu bilden:
/* Befehl zum Starten des XFS-Dämons erstellen. */ (void) sprintf(cmd, "/usr/openwin/bin/xfs -config %s -port %d 2>/dev/null", xfnts_conf, portlist->ports[0].port);
Beachten Sie, dass die Ausgabe an dev/null umgeleitet wird, um die vom Dämon generierten Meldungen zu unterdrücken.
Die xfnts_start-Methode übergibt die xfs-Befehlszeile an scds_pmf_start(), um den Datendienst unter PMF-Steuerung zu starten:
scds_syslog(LOG_INFO, "Start-Anforderung wird ausgegeben."); err = scds_pmf_start(scds_handle, SCDS_PMF_TYPE_SVC, SCDS_PMF_SINGLE_INSTANCE, cmd, -1); if (err == SCHA_ERR_NOERR) { scds_syslog(LOG_INFO, "Start-Befehl erfolgreich beendet."); } else { scds_syslog(LOG_ERR, "HA-XFS konnte nicht gestartet werden "); }
Beachten Sie folgende Punkte bezüglich des Aufrufs an scds_pmf_start().
Der Parameter SCDS_PMF_TYPE_SVC identifiziert das zu startende Programm als Datendienstanwendung — mit dieser Methode kann auch ein Fehler-Monitor oder ein anderer Anwendungstyp gestartet werden.
Der Parameter SCDS_PMF_SINGLE_INSTANCE identifiziert eine Ressource mit einer einzigen Instanz.
Der cmd-Parameter ist die zuvor generierte Befehlszeile.
Der letzte Parameter, -1, gibt die untergeordnete Überwachungsebene an. Der Wert -1 gibt an, dass PMF neben dem Prozess selbst auch alle untergeordneten Prozesse überwacht.
Vor der Rückgabe gibt svc_pmf_start() den der portlist-Struktur zugewiesenen Speicherplatz frei:
scds_free_port_list(portlist); return (err); |
Auch wenn svc_start() Erfolg zurückgibt, kann es sein, dass die zugrunde liegende Anwendung nicht gestartet wurde. Daher muss svc_start() die Anwendung testen, um sicherzustellen, dass sie läuft, bevor eine Erfolgsmeldung zurückgegeben wird. Beim Testen muss beachtet werden, dass die Anwendung eventuell nicht sofort zur Verfügung steht, weil sie einige Zeit zum Starten benötigt. Die svc_start()-Methode ruft die in xfnts.c definierte svc_wait()-Funktion auf, um zu überprüfen, ob die Anwendung läuft:
/* Warten, bis der Dienst vollständig gestartet wurde */ scds_syslog_debug(DBG_LEVEL_HIGH, "svc_wait wird aufgerufen, um zu überprüfen, ob der Dienst gestartet wurde."); rc = svc_wait(scds_handle); scds_syslog_debug(DBG_LEVEL_HIGH, "Rückgabe von svc_wait"); if (rc == 0) { scds_syslog(LOG_INFO, "Dienst wurde erfolgreich gestartet."); } else { scds_syslog(LOG_ERR, "Dienst konnte nicht gestartet werden."); }
Die svc_wait()-Funktion ruft scds_get_netaddr_list(3HA) auf, um die für das Testen der Anwendung erforderlichen Netzwerkadressressourcen abzurufen:
/* Netzwerkressource für das Testsignal abrufen */ if (scds_get_netaddr_list(scds_handle, &netaddr)) { scds_syslog(LOG_ERR, "Keine Netzwerkadressressourcen in Ressourcengruppe gefunden."); return (1); } /* Fehler zurückgeben, wenn keine Netzwerkressourcen vorhanden sind */ if (netaddr == NULL || netaddr->num_netaddrs == 0) { scds_syslog(LOG_ERR, "Keine Netzwerkadressressource in Ressourcengruppe."); return (1); }
Dann ruft svc_wait() die start_timeout- und stop_timeout-Werte ab:
svc_start_timeout = scds_get_rs_start_timeout(scds_handle) probe_timeout = scds_get_ext_probe_timeout(scds_handle)
Um die Zeit zu berücksichtigen, die der Server zum Starten benötigt, ruft svc_wait() die scds_svc_wait()-Methode auf und übergibt einen Zeitüberschreitungswert, der drei Prozent des start_timeout-Wertes entspricht. Dann ruft svc_wait() die svc_probe()-Methode auf, um zu überprüfen, ob die Anwendung gestartet wurde. Die svc_probe()-Methode stellt eine einfache Socketverbindung mit dem Server auf dem angegebenen Port her. Wenn die Verbindung mit dem Port fehlschlägt, gibt svc_probe() den Wert 100 für Totalfehlschlag zurück. Wenn die Verbindung hergestellt werden kann, aber die Verbindungstrennung vom Port fehlschlägt, gibt svc_probe() den Wert 50 zurück.
Bei Fehlschlag oder Teilfehlschlag von svc_probe() ruft svc_wait() die scds_svc_wait()-Methode mit einem Zeitüberschreitungswert von 5 auf. Die scds_svc_wait()-Methode beschränkt die Testhäufigkeit auf ein Testsignal alle fünf Sekunden. Diese Methode zählt auch die Anzahl der Startversuche für den Dienst. Wenn die Anzahl der Versuche den Wert der Retry_count-Ressourceneigenschaft innerhalb des von der Retry_interval-Ressourceneigenschaft angegebenen Zeitraums überschreitet, gibt die scds_svc_wait()-Funktion Fehlschlag zurück. In diesem Fall gibt die svc_start()-Funktion ebenfalls Fehlschlag zurück.
#define SVC_CONNECT_TIMEOUT_PCT 95 #define SVC_WAIT_PCT 3 if (scds_svc_wait(scds_handle, (svc_start_timeout * SVC_WAIT_PCT)/100) != SCHA_ERR_NOERR) { scds_syslog(LOG_ERR, "Dienst konnte nicht gestartet werden."); return (1); } do { /* * Datendienst an der IP-Adresse der Netzwerkressource * sowie dem Port-Namen testen. */ rc = svc_probe(scds_handle, netaddr->netaddrs[0].hostname, netaddr->netaddrs[0].port_proto.port, probe_timeout); if (rc == SCHA_ERR_NOERR) { /* Erfolg. Ressourcen freigeben und Rückgabe */ scds_free_netaddr_list(netaddr); return (0); } /* scds_svc_wait() aufrufen, falls der Dienst zu oft if (scds_svc_wait(scds_handle, SVC_WAIT_TIME) != SCHA_ERR_NOERR) { scds_syslog(LOG_ERR, "Dienst konnte nicht gestartet werden."); return (1); } /* RGM die Zeitüberschreitung überlassen und Programm beenden */ } while (1);
Vor der Beendigung ruft die xfnts_start-Methode scds_close() auf, um die von scds_initialize () zugewiesenen Ressourcen zurückzufordern. Weitere Einzelheiten finden Sie unter scds_initialize()-Funktion und in der Online-Dokumentation unter scds_close(3HA).
Da die xfnts_start-Methode scds_pmf_start() verwendet, um den Dienst unter PMF zu starten, verwendet die xfnts_stop-Methode scds_pmf_stop() zum Stoppen des Dienstes.
Der erste Aufruf in xfnts_stop erfolgt an scds_initialize(), um einige erforderliche Systemverwaltungs-Funktionen auszuführen (weitere Einzelheiten finden Sie unter scds_initialize()-Funktion und in der Online-Dokumentation unter scds_initialize(3HA)).
Die xfnts_stop-Methode ruft die in xfnts.c definierte svc_stop()-Methode folgendermaßen auf.
scds_syslog(LOG_ERR, "Stop-Anforderung wird ausgegeben."); err = scds_pmf_stop(scds_handle, SCDS_PMF_TYPE_SVC, SCDS_PMF_SINGLE_INSTANCE, SIGTERM, scds_get_rs_stop_timeout(scds_handle)); if (err != SCHA_ERR_NOERR) { scds_syslog(LOG_ERR, "HA-XFS konnte nicht gestoppt werden."); return (1); } scds_syslog(LOG_INFO, "HA-XFS erfolgreich gestoppt."); return (SCHA_ERR_NOERR); /* Erfolgreich gestoppt */
Bezüglich des Aufrufs in svc_stop() an die scds_pmf_stop()-Funktion ist Folgendes zu beachten.
Der Parameter SCDS_PMF_TYPE_SVC identifiziert das zu stoppende Programm als Datendienstanwendung — mit dieser Methode kann auch ein Fehler-Monitor oder ein anderer Anwendungstyp gestoppt werden.
Der Parameter SCDS_PMF_SINGLE_INSTANCE identifiziert das Signal.
Der SIGTERM-Parameter identifiziert das Signal, mit dem die Ressourceninstanz gestoppt werden soll. Wenn dieses Signal die Instanz nicht stoppen kann, sendet scds_pmf_stop() das SIGKILL-Signal, um die Instanz zu stoppen. Wenn dieses Signal ebenfalls fehlschlägt, wird ein Zeitüberschreitungsfehler zurückgegeben. Weitere Einzelheiten finden Sie in der Online-Dokumentation unter scds_pmf_stop(3HA).
Der Zeitüberschreitungswert ist der Wert der Stop_timeout-Eigenschaft der Ressource.
Vor der Beendigung ruft die xfnts_stop-Methode scds_close() auf, um die von scds_initialize() zugewiesenen Ressourcen zurückzufordern. Weitere Einzelheiten finden Sie unter scds_initialize()-Funktion und in der Online-Dokumentation unter scds_close(3HA).
RGM ruft die Monitor_start-Methode auf einem Knoten auf, um den Fehler-Monitor zu starten, nachdem eine Ressource auf diesem Knoten gestartet wurde. Die xfnts_monitor_start-Methode verwendet scds_pmf_start(), um den Monitor-Dämon unter PMF zu starten.
Der erste Aufruf in xfnts_monitor_start erfolgt an scds_initialize(). Diese Funktion führt einige wichtige Systemverwaltungs-Funktionen aus (weitere Einzelheiten finden Sie unter scds_initialize()-Funktion und in der Online-Dokumentation unter scds_initialize(3HA)).
Die xfnts_monitor_start-Methode ruft die in xfnts.c definierte mon_start-Methode folgendermaßen auf:
scds_syslog_debug(DBG_LEVEL_HIGH, "Monitor_start-Methode für Ressource <%s> wird aufgerufen.", scds_get_resource_name(scds_handle)); /* scds_pmf_start aufrufen und den Testsignalnamen übergeben. */ err = scds_pmf_start(scds_handle, SCDS_PMF_TYPE_MON, SCDS_PMF_SINGLE_INSTANCE, "xfnts_probe", 0); if (err != SCHA_ERR_NOERR) { scds_syslog(LOG_ERR, "Fehler-Monitor konnte nicht gestartet werden."); return (1); } scds_syslog(LOG_INFO, "Fehler-Monitor gestartet."); return (SCHA_ERR_NOERR); /* Monitor erfolgreich gestartet */ }
Bezüglich des Aufrufs in svc_mon_start() an die scds_pmf_start()-Funktion ist Folgendes zu beachten.
Der Parameter SCDS_PMF_TYPE_MON identifiziert das zu startende Programm als Fehler-Monitor — mit dieser Methode kann auch ein Datendienst oder ein anderer Anwendungstyp gestartet werden.
Der Parameter SCDS_PMF_SINGLE_INSTANCE identifiziert eine Ressource mit einer einzigen Instanz.
Der xfnts_probe-Parameter identifiziert den zu startenden Monitor-Dämon. Es wird davon ausgegangen, dass der Monitor-Dämon sich in demselben Verzeichnis wie die anderen Rückmeldeprogramme befindet.
Der letzte Parameter, 0, gibt die untergeordnete Überwachungsebene an — in diesem Fall wird nur der Monitor-Dämon überwacht.
Vor der Beendigung ruft die xfnts_monitor_start-Methode scds_close() auf, um die von scds_initialize() zugewiesenen Ressourcen zurückzufordern. Weitere Einzelheiten finden Sie unter scds_initialize()-Funktion und in der Online-Dokumentation unter scds_close(3HA).
Da die xfnts_monitor_start-Methode scds_pmf_start() zum Starten des Monitor-Dämons unter PMF verwendet, setzt xfnts_monitor_stop die scds_pmf_stop()-Methode zum Stoppen des Monitor-Dämons ein.
Der erste Aufruf in xfnts_monitor_stop erfolgt an scds_initialize(). Diese Funktion führt einige wichtige Systemverwaltungs-Funktionen aus (weitere Einzelheiten finden Sie unter scds_initialize()-Funktion und in der Online-Dokumentation unter scds_initialize(3HA)).
Die xfnts_monitor_stop()-Methode ruft die in xfnts.c definierte mon_stop-Methode folgendermaßen auf:
scds_syslog_debug(DBG_LEVEL_HIGH, "scds_pmf_stop-Methode wird aufgerufen"); err = scds_pmf_stop(scds_handle, SCDS_PMF_TYPE_MON, SCDS_PMF_SINGLE_INSTANCE, SIGKILL, scds_get_rs_monitor_stop_timeout(scds_handle)); if (err != SCHA_ERR_NOERR) { scds_syslog(LOG_ERR, "Fehler-Monitor konnte nicht gestoppt werden."); return (1); } scds_syslog(LOG_INFO, "Fehler-Monitor gestoppt."); return (SCHA_ERR_NOERR); /* Monitor erfolgreich gestoppt */ }
Bezüglich des Aufrufs in svc_mon_stop() an die scds_pmf_stop()-Funktion ist Folgendes zu beachten.
Der Parameter SCDS_PMF_TYPE_MON identifiziert das zu stoppende Programm als Fehler-Monitor — mit dieser Methode kann auch ein Datendienst oder ein anderer Anwendungstyp gestoppt werden.
Der Parameter SCDS_PMF_SINGLE_INSTANCE identifiziert eine Ressource mit einer einzigen Instanz.
Der SIGKILL-Parameter identifiziert das Signal, mit dem die Ressourceninstanz gestoppt werden soll. Wenn dieses Signal die Instanz nicht stoppen kann, gibt scds_pmf_stop() einen Zeitüberschreitungsfehler zurück. Weitere Einzelheiten finden Sie in der Online-Dokumentation unter scds_pmf_stop(3HA).
Der Zeitüberschreitungswert ist der Wert der Monitor_stop_timeout-Eigenschaft der Ressource.
Vor der Beendigung ruft die xfnts_monitor_stop-Methode scds_close() auf, um die von scds_initialize() zugewiesenen Ressourcen zurückzufordern. Weitere Einzelheiten finden Sie unter scds_initialize()-Funktion und in der Online-Dokumentation unter scds_close(3HA).
RGM ruft die Monitor_check-Methode immer dann auf, wenn der Fehler-Monitor versucht, für die Ressourcengruppe der Ressorce ein Failover auf einen anderen Knoten auszuführen. Die xfnts_monitor_check-Methode ruft die svc_validate()-Methode auf, um zu überprüfen, ob eine geeignete Konfiguration zum Unterstützen des xfs-Dämons vorhanden ist (Einzelheiten finden Sie unter xfnts_validate-Methode). Der Code für xfnts_monitor_check sieht folgendermaßen aus:
/* Von RGM übergebene Argumente verarbeiten und syslog initialisieren */ if (scds_initialize(&scds_handle, argc, argv) != SCHA_ERR_NOERR) { scds_syslog(LOG_ERR, "Handle konnte nicht initialisiert werden."); return (1); } rc = svc_validate(scds_handle); scds_syslog_debug(DBG_LEVEL_HIGH, "monitor_check-Methode " "wurde aufgerufen und gab <%d> zurück.", rc); /* Gesamten von scds_initialize zugewiesenen Speicherplatz freigeben */ scds_close(&scds_handle); /* Ergebnis der validate-Methode zurückgeben, die als Teil der Monitor-Prüfung * ausgeführt wird return (rc); }
RGM ruft die PROBE-Methode nicht direkt auf. Es wird vielmehr die Monitor_start-Methode aufgerufen, um den Monitor zu starten, nachdem eine Ressource auf einem Knoten gestartet wurde. Die xfnts_monitor_start-Methode startet den Fehler-Monitor unter PMF-Steuerung. Die xfnts_monitor_stop-Methode stoppt den Fehler-Monitor.
Der SUNW.xfnts-Fehler-Monitor führt folgende Aufgaben aus:
Er überwacht in regelmäßigen Abständen die Fehlerfreiheit des xfs-Serverdämons mithilfe eigens zur Prüfung von einfachen TCP-basierten Diensten wie xfs entworfener Dienstprogramme.
Er verfolgt Probleme der Anwendung innerhalb eines bestimmten Zeitfensters unter Verwendung der Eigenschaften Retry_count und Retry_interval und entscheidet, ob der Datendienst im Fall eines Totalfehlschlags der Anwendung neu gestartet oder ein Failover ausgeführt wird. Die Funktionen scds_fm_action() und scds_fm_sleep() unterstützen diesen Verfolgungs- und Entscheidungsmechanismus.
Er implementiert die Failover- bzw. Neustartentscheidung mithilfe von scds_fm_action().
Er aktualisiert den Ressourcenzustand und stellt ihn den Verwaltungstools und grafischen Benutzeroberflächen zur Verfügung.
Die xfonts_probe-Methode implementiert eine Schleife. Vor dem Implementieren der Schleife führt xfonts_probe folgende Aktionen aus:
Sie ruft die Netzwerkadressressourcen für die xfnts-Ressource folgendermaßen ab:
/* Für diese Ressource verfügbare IP-Adressen abrufen */ if (scds_get_netaddr_list(scds_handle, &netaddr)) { scds_syslog(LOG_ERR, "Keine Netzwerkadressressource in Ressourcengruppe."); scds_close(&scds_handle); return (1); } /* Fehler zurückgeben, wenn keine Netzwerkressourcen vorhanden sind */ if (netaddr == NULL || netaddr->num_netaddrs == 0) { scds_syslog(LOG_ERR, "Keine Netzwerkadressressource in Ressourcengruppe."); return (1); }
Sie ruft scds_fm_sleep() auf und übergibt den Wert von Thorough_probe_interval als den Zeitüberschreitungswert. Das Testsignal ruht zwischen den einzelnen Testvorgängen für den Wert von Thorough_probe_interval.
timeout = scds_get_ext_probe_timeout(scds_handle); for (;;) { /* * Für die Dauer von thorough_probe_interval zwischen den * einzelnen Testsignalen ruhen. */ (void) scds_fm_sleep(scds_handle, scds_get_rs_thorough_probe_interval(scds_handle));
Die xfnts_probe-Methode implementiert die Schleife folgendermaßen:
for (ip = 0; ip < netaddr->num_netaddrs; ip++) { /* * Hostname und Port für Überwachung der * Fehlerfreiheit erfassen. */ hostname = netaddr->netaddrs[ip].hostname; port = netaddr->netaddrs[ip].port_proto.port; /* * HA-XFS unterstützt nur einen Port. Daher den Port-Wert * aus dem ersten Eintrag im Port-Array abrufen. */ ht1 = gethrtime(); /* Testsignal-Startzeit festhalten */ scds_syslog(LOG_INFO, "Dienst auf Port: %d. testen", port); probe_result = svc_probe(scds_handle, hostname, port, timeout); /* * Testsignalhistorie des Dienstes aktualisieren, * bei Bedarf Aktionen ausführen. * Testsignal-Endzeit festhalten. */ ht2 = gethrtime(); /* In Millisekunden konvertieren */ dt = (ulong_t)((ht2 - ht1) / 1e6); /* * Fehlschlaghistorie berechnen und * bei Bedarf Aktionen ausführen */ (void) scds_fm_action(scds_handle, probe_result, (long)dt); } /* Jede Netzressource */ } /* Endlos weitertesten */
Die svc_probe()-Funktion implementiert die Testsignallogik. Der Rückgabewert von svc_probe() wird an scds_fm_action() übergeben. Diese Funktion entscheidet, ob die Anwendung neu gestartet, ein Failover der Ressourcengruppe ausgeführt werden oder nichts geschehen soll.
Die svc_probe()-Funktion stellt eine einfache Socketverbindung mit dem angegebenen Port her, indem sie scds_fm_tcp_connect() aufruft. Wenn die Verbindung fehlschlägt, gibt svc_probe() den Wert 100 für Totalfehlschlag zurück. Wenn die Verbindung hergestellt werden kann, aber die Verbindungstrennung fehlschlägt, gibt svc_probe() den Wert 50 für Teilfehlschlag zurück. Wenn sowohl die Verbindung als auch die Verbindungstrennung erfolgreich verlaufen, gibt svc_probe() den Wert 0 für Erfolg zurück.
Der Code für svc_probe() sieht folgendermaßen aus:
int svc_probe(scds_handle_t scds_handle, char *hostname, int port, int timeout) { int rc; hrtime_t t1, t2; int sock; char testcmd[2048]; int time_used, time_remaining; time_t connect_timeout; /* * Den Datendienst anhand einer Socketverbindung über den Port, */ * der in der port_list-Eigenschaft angeben ist, zum Host für den XFS-Datendienst * testen. Wenn der XFS-Dienst, der zum Abhören des angegebenen * Ports konfiguriert ist, auf die Verbindung antwortet, ist der Test erfolgreich * verlaufen. Andernfalls wird für den in der probe_timeout-Eigenschaft * festgesetzten Zeitraum gewartet, bevor geschlossen wird, dass der Test * fehlgeschlagen ist. */ /* * Den Zeitüberschreitungs-Prozentsatz aus SVC_CONNECT_TIMEOUT_PCT * für die Verbindung mit dem Port verwenden */ connect_timeout = (SVC_CONNECT_TIMEOUT_PCT * timeout)/100; t1 = (hrtime_t)(gethrtime()/1E9); /* * Das Testsignal stellt eine Verbindung mit den angegebenen Hostnamen und * Port her. Die Zeitdauer für die Verbindung beträgt 95% des probe_timeout- * Wertes. */ rc = scds_fm_tcp_connect(scds_handle, &sock, hostname, port, connect_timeout); if (rc) { scds_syslog(LOG_ERR, "Verbindung mit Port <%d> für Ressource <%s> konnte nicht hergestellt werden.", port, scds_get_resource_name(scds_handle)); /* Dies ist ein Totalfehlschlag */ return (SCDS_PROBE_COMPLETE_FAILURE); } t2 = (hrtime_t)(gethrtime()/1E9); /* * Tatsächliche Zeit für die Verbindungsherstellung berechnen. Der Wert sollte * kleiner oder gleich connect_timeout sein, der dem Verbindungsversuch * zugewiesenen Zeit. Wenn der Verbindungsversuch die gesamte zugewiesene * Zeit verbraucht, wird der restliche Wert aus probe_timeout, der an diese Funktion * übergeben wird, als Verbindungstrennungs-Zeitüberschreitung verwendet. * Andernfalls wird die restliche Zeit aus dem Verbindungsaufruf ebenfalls der * Verbindungstrennungs-Zeitüberschreitung hinzugerechnet. * */ time_used = (int)(t2 - t1); /* * Restliche Zeit (timeout - time_took_to_connect) für die * Verbindungstrennung verwenden */ time_remaining = timeout - (int)time_used; /* * Wenn die gesamte Zeit verbraucht wurde, einen kleinen festen * Zeitüberschreitungswert für einen weiteren Trennversuch verwenden. * So wird fd-Leak vermieden. */ if (time_remaining <= 0) { scds_syslog_debug(DBG_LEVEL_LOW, "svc_probe hat die gesamte Zeitüberschreitung von " "%d Sekunden während des Verbindungsvorgangs verbraucht und die" "Zeitüberschreitung um %d Sekunden überschritten. Trennversuch mit" " Zeitüberschreitung %d ", connect_timeout, abs(time_used), SVC_DISCONNECT_TIMEOUT_SECONDS); time_remaining = SVC_DISCONNECT_TIMEOUT_SECONDS; } /* * Bei Fehlschlag der Verbindungstrennung Teilfehlschlag zurückgeben. * Grund: Der Verbindungsaufruf ist erfolgreich, was bedeutet, dass die * Anwendung läuft. Ein Verbindungstrennungsfehlschlag kann durch * eine hängende Anwendung oder hohe Belastung verursacht werden. * In letzterem Fall die Anwendung nicht durch Rückgabe von Totalfehlschlag * als ausgefallen deklarieren. Stattdessen Teilfehlschlag deklarieren. * Wenn diese Situation anhält, schlägt der Verbindungstrennungsaufruf * erneut fehl, und die Anwendung wird neu gestartet. */ rc = scds_fm_tcp_disconnect(scds_handle, sock, time_remaining); if (rc != SCHA_ERR_NOERR) { scds_syslog(LOG_ERR, "Verbindung mit Port %d von Ressource %s konnte nicht getrennt werden.", port, scds_get_resource_name(scds_handle)); /* Dies ist ein Teilfehlschlag */ return (SCDS_PROBE_COMPLETE_FAILURE/2); } t2 = (hrtime_t)(gethrtime()/1E9); time_used = (int)(t2 - t1); time_remaining = timeout - time_used; /* * Wenn keine Zeit übrig ist, nicht den vollständigen Test * mit fsinfo ausführen. Stattdessen SCDS_PROBE_COMPLETE_FAILURE/2 * zurückgeben. So wird sichergestellt, dass der Server bei * Weiterbestehen dieser Zeitüberschreitung neu gestartet wird. */ if (time_remaining <= 0) { scds_syslog(LOG_ERR, "Testsignal-Zeitüberschreitung."); return (SCDS_PROBE_COMPLETE_FAILURE/2); } /* * Die Verbindung und Verbindungstrennung zum Port sind erfolgreich. * Den fsinfo-Befehl für einen vollständigen Gesundheits-Check * des Servers ausführen. * stdout umleiten. Andernfalls gelangt die Ausgabe von fsinfo * an die Konsole. */ (void) sprintf(testcmd, "/usr/openwin/bin/fsinfo -server %s:%d> /dev/null", hostname, port); scds_syslog_debug(DBG_LEVEL_HIGH, "Prüfung des Serverstatus mit %s.", testcmd); if (scds_timerun(scds_handle, testcmd, time_remaining, SIGKILL, &rc) != SCHA_ERR_NOERR || rc != 0) { scds_syslog(LOG_ERR, "Serverstatus konnte mit Befehl <%s> nicht geprüft werden", testcmd); return (SCDS_PROBE_COMPLETE_FAILURE/2); } return (0); }
Nach Beendigung gibt svc_probe() einen Wert für Erfolg (0), Teilfehlschlag (50), oder Totalfehlschlag (100) zurück. Die xfnts_probe-Methode übergibt diesen Wert an scds_fm_action().
Die xfnts_probe-Methode ruft scds_fm_action() auf, um die auszuführende Aktion festzulegen. Die Logik in scds_fm_action() sieht folgendermaßen aus:
Kumulative Fehlschlaghistorie innerhalb des Wertes der Retry_interval-Eigenschaft verwalten
Wenn der kumulative Fehlschlag 100 (Totalfehlschlag) erreicht, wird der Datendienst neu gestartet. Wenn Retry_interval überschritten ist, wird die Historie zurückgesetzt.
Wenn die Anzahl der Neustarts den in der Retry_count-Eigenschaft angegebenen Wert innerhalb der in Retry_interval angegebenen Zeit überschreitet, wird für den Datendienst ein Failover ausgeführt.
Angenommen, das Testsignal stellt eine Verbindung mit dem XFS-Server her, kann die Verbindung jedoch nicht trennen. Das bedeutet, dass der Server läuft, aber vielleicht hängt oder nur momentan überlastet ist. Bei Fehlschlag der Verbindungstrennung wird ein Teilfehlschlag (50) an scds_fm_action() gesendet. Dieser Wert liegt unter dem Schwellenwert für das Neustarten des Datendienstes. Der Wert wird jedoch in der Fehlerhistorie festgehalten.
Wenn während des nächsten Tests die Verbindungstrennung vom Server erneut fehlschlägt, wird ein Wert von 50 der von scds_fm_action() verwalteten Fehlschlaghistorie hinzugefügt. Der kumulative Fehlschlagwert beträgt nun 100, so dass scds_fm_action() den Datendienst neu startet.
RGM ruft die Validate-Methode auf, wenn eine Ressource erstellt wird und wenn eine Verwaltungsaktion die Eigenschaften der Ressource bzw. deren Gruppe aktualisiert. RGM ruft Validate auf, bevor die Erstellung bzw. Aktualisierung angewendet wird. Ein Fehlerbeendigungscode der Methode auf einem Knoten führt zum Abbruch der Erstellung bzw. Aktualisierung.
RGM ruft Validate nur dann auf, wenn Ressourcen- bzw. Gruppeneigenschaften über eine Verwaltungsaktion geändert werden, und nicht, wenn RGM Eigenschaften einstellt oder wenn ein Monitor die Ressourceneigenschaften Status und Status_msg einstellt.
Die Monitor_check-Methode ruft auch ausdrücklich jedes Mal dann die Validate-Methode auf, wenn die PROBE-Methode versucht, ein Failover für den Datendienst auf einen neuen Knoten auszuführen.
RGM ruft Validate mit zusätzlichen Argumenten zu denjenigen auf, die von anderen Methoden übergeben wurden, einschließlich der aktualisierten Eigenschaften und Werte. Bei Aufruf von scds_initialize() zu Beginn von xfnts_validate werden alle Argumente analysiert, die RGM an xfnts_validate übergibt, und die Informationen werden im scds_handle-Parameter gespeichert. Die Unterroutinen, die xfnts_validate aufruft, verwenden diese Informationen.
Die xfnts_validate-Methode ruft svc_validate() auf, um Folgendes zu prüfen:
Die Confdir_list-Eigenschaft wurde für die Ressource eingestellt und definiert ein einziges Verzeichnis.
scha_str_array_t *confdirs; confdirs = scds_get_ext_confdir_list(scds_handle); /* Fehler zurückgeben, wenn keine confdir_list-Erweiterungseigenschaft * vorhanden ist if (confdirs == NULL || confdirs->array_cnt != 1) { scds_syslog(LOG_ERR, "Confdir_list-Eigenschaft ist nicht ordnungsgemäß eingestellt."); return (1); /* Validierungsfehlschlag */ }
Das von Confdir_list angegebene Verzeichnis enthält die fontserver.cfg-Datei.
(void) sprintf(xfnts_conf, "%s/fontserver.cfg", confdirs->str_array[0]); if (stat(xfnts_conf, &statbuf) != 0) { /* * lint-Fehler unterdrücken, da im errno.h-Prototyp * void-Argument fehlt */ scds_syslog(LOG_ERR, "Auf Datei <%s> konnte nicht zugegriffen werden: <%s>", xfnts_conf, strerror(errno)); /*lint !e746 */ return (1); }
Auf die Server-Dämon-Binärdatei kann auf dem Cluster-Knoten zugegriffen werden.
if (stat("/usr/openwin/bin/xfs", &statbuf) != 0) { scds_syslog(LOG_ERR, "Auf XFS-Binärdatei kann nicht zugegriffen werden: <%s> ", strerror(errno)); return (1); }
Die Port_list-Eigenschaft gibt einen einzigen Port an.
scds_port_list_t *portlist; err = scds_get_port_list(scds_handle, &portlist); if (err != SCHA_ERR_NOERR) { scds_syslog(LOG_ERR, "Auf Port_list-Eigenschaft: %s konnte nicht zugegriffen werden.", scds_error_string(err)); return (1); /* Validierungsfehlschlag */ } #ifdef TEST if (portlist->num_ports != 1) { scds_syslog(LOG_ERR, "Port_list-Eigenschaft darf nur einen Wert enthalten."); scds_free_port_list(portlist); return (1); /* Validierungsfehlschlag */ } #endif
Die Ressourcengruppe, die den Datendienst enthält, verfügt auch über mindestens eine Netzwerkadressressource.
scds_net_resource_list_t *snrlp; if ((err = scds_get_rs_hostnames(scds_handle, &snrlp)) != SCHA_ERR_NOERR) { scds_syslog(LOG_ERR, "Keine Netzwerkadressressource in Ressourcengruppe: %s.", scds_error_string(err)); return (1); /* Validierungsfehlschlag */ } /* Fehler zurückgeben, wenn keine Netzwerkadressressourcen vorhanden sind */ if (snrlp == NULL || snrlp->num_netresources == 0) { scds_syslog(LOG_ERR, "Keine Netzwerkadressressource in Ressourcengruppe."); rc = 1; goto finished; }
Vor der Rückgabe gibt svc_validate() alle zugewiesenen Ressourcen frei.
finished: scds_free_net_list(snrlp); scds_free_port_list(portlist); return (rc); /* Validierungsergebnis zurückgeben */
Vor der Beendigung ruft die xfnts_validate-Methode scds_close() auf, um die von scds_initialize() zugewiesenen Ressourcen zurückzufordern. Weitere Einzelheiten finden Sie unter scds_initialize()-Funktion und in der Online-Dokumentation unter scds_close(3HA).
RGM ruft die Update-Methode auf, um eine laufende Ressource darüber zu benachrichtigen, dass ihre Eigenschaften geändert wurden. Die einzigen Eigenschaften des xfnts-Datendienstes, die geändert werden können, betreffen den Fehler-Monitor. Wenn daher eine Eigenschaft aktualisiert wird, ruft die xfnts_update-Methode scds_pmf_restart_fm() auf, um den Fehler-Monitor neu zu starten.
* Prüfen, ob der Fehler-Monitor bereits läuft und ihn ggf. * stoppen und neu starten. Der zweite Parameter * von scds_pmf_restart_fm() identifiziert eindeutig die Instanz des * Fehler-Monitors, die neu gestartet werden muss. */ scds_syslog(LOG_INFO, "Fehler-Monitor wird neu gestartet."); result = scds_pmf_restart_fm(scds_handle, 0); if (result != SCHA_ERR_NOERR) { scds_syslog(LOG_ERR, "Fehler-Monitor konnte nicht neu gestartet werden."); /* Gesamten von scds_initialize zugewiesenen Speicher freigeben*/ scds_close(&scds_handle); return (1); } scds_syslog(LOG_INFO, "Erfolgreich beendet.");
Der zweite Parameter von scds_pmf_restart_fm() identifiziert eindeutig die Instanz des Fehler-Monitors, die neu gestartet werden muss, wenn mehrere Instanzen vorhanden sind. Der Wert 0 im Beispiel gibt an, dass nur eine Instanz des Fehler-Monitors vorhanden ist.