Sun Cluster: Guía del desarrollador de los servicios de datos del sistema operativo Solaris

Capítulo 8 Ejemplo de implementación del tipo de recurso con DSDL

Este capítulo describe el tipo de recurso de ejemplo, SUNW.xfnts, implementado con la Biblioteca de desarrollo del servicio de datos (DSDL). Este servicio de datos está escrito en C. La aplicación subyacente es el servidor de fuentes X, un servicio basado en TCP/IP. Apéndice C, Listados de código del tipo de recurso de ejemplo de DSDL contiene el código completo para cada método del tipo de recurso SUNW.xfnts .

En este capítulo se tratan los temas siguientes:

Servidor de fuentes X

El servidor de fuentes X es un servicio basado en TCP/IP que proporciona archivos de fuentes a los clientes. Éstos se conectan al servidor para solicitar un conjunto de fuentes y el servidor lee los archivos de fuentes del disco y se los sirve a los clientes. El daemon del servidor de fuentes X está formado por un archivo binario de servidor incluido en /usr/openwin/bin/xfs. Normalmente, el daemon se inicia desde inetd. Sin embargo, en el ejemplo actual, supondremos que se ha inhabilitado la entrada correcta del archivo /etc/inetd.conf (por ejemplo, mediante el comando fsadmin -d) para que el daemon sólo esté bajo el control del software de Sun Cluster.

Archivo de configuración del servidor de fuentes X

El servidor de fuentes X lee de forma predeterminada la información de configuración desde el archivo /usr/openwin/lib/X11/fontserver.cfg. La entrada de catálogo de este archivo contiene una lista de directorios de fuentes disponibles para que el daemon las sirva. El administrador del clúster puede ubicar estos directorios en el sistema de archivos del clúster. Esta ubicación optimiza el uso del servidor de fuentes X en Sun Cluster, ya que permite mantener una única copia de la base de datos de fuentes en el sistema. Si el administrador del clúster desea cambiar la ubicación, debe editar el archivo fontserver.cfg para especificar las nuevas rutas a los directorios de fuentes.

Para facilitar la configuración, el administrador puede incluir también el archivo de configuración en el sistema de archivos del clúster. El daemon xfs proporciona argumentos de línea de comandos que anulan la ubicación predeterminada de este archivo. El tipo de recurso SUNW.xfnts utiliza el siguiente comando para iniciar el daemon bajo el control del software de Sun Cluster.

/usr/openwin/bin/xfs -config location-of-configuration-file/fontserver.cfg \
-port port-number

En la implementación del tipo de recurso SUNW.xfnts, se puede utilizar la propiedad Confdir_list para administrar la ubicación del archivo de configuración fontserver.cfg.

Número del puerto de TCP

El número de puerto de TCP de escucha utilizado por el daemon del servidor xfs es normalmente el puerto “fs”, definido generalmente en el número 7100 en el archivo /etc/services. Sin embargo, la opción -port incluida por el administrador del clúster con el comando xfs permite a éste anular la configuración predeterminada.

Puede utilizar la propiedad Port_list del tipo de recurso SUNW.xfnts para establecer el valor predeterminado y permitir al administrador del clúster utilizar la opción -port con el comando xfs. Puede definir el valor predeterminado de esta propiedad como 7100/tcp en el archivo RTR. En el método Start de SUNW.xfnts, se pasa la propiedad Port_list a la opción -port en la línea de comandos de xfs. Por lo tanto, no es necesario que el usuario de este tipo de recurso especifique un número de puerto (se establece de forma predeterminada en 7100/tcp). El administrador del clúster puede especificar un valor diferente para la propiedad Port_list al configurar el tipo de recurso.

Archivo RTR de SUNW.xfnts

Esta sección describe varias de las propiedades principales del archivo RTR de SUNW.xfnts, pero no se explica el objetivo de todas ellas. Para obtener una descripción de las propiedades, consulte Establecimiento del recurso y las propiedades del tipo de recurso.

La propiedad de extensión Confdir_list identifica el directorio de configuración (o una lista de directorios) de la siguiente forma:

{
        PROPERTY = Confdir_list;
        EXTENSION;
        STRINGARRAY;
        TUNABLE = AT_CREATION;
        DESCRIPTION = "Las rutas de los directorios de configuración";
}

La propiedad Confdir_list no especifica un valor predeterminado. El administrador del clúster debe especificar un nombre de directorio al crearse el recurso. Esta valor no puede cambiarse más adelante, ya que la capacidad de ajuste se ha limitado a AT_CREATION .

La propiedad Port_list identifica el puerto de escucha utilizado por el daemon del servidor de la siguiente forma:

{
        PROPERTY = Port_list;
        DEFAULT = 7100/tcp;
        TUNABLE = ANYTIME;
}

Como la propiedad declara un valor predeterminado, el administrador del clúster puede especificar un nuevo valor o aceptar el predeterminado cuando se crea el recurso. No se puede cambiar este valor más adelante porque la capacidad de ajuste se ha limitado a AT_CREATION .

Convenciones de nomenclatura para las funciones y métodos de rellamada

Si conoce estas convenciones, podrá identificar las diversas partes del código de ejemplo:

Función scds_initialize()

DSDL requiere que cada método de rellamada invoque la función scds_initialize () al comienzo del método. Esta función realiza las operaciones siguientes:

Utilice la función scds_close() para reclamar los recursos asignados por scds_initialize().

Método xfnts_start

RGM ejecuta el método Start en un nodo del clúster cuando el grupo de recursos que contiene el recurso del servicio de datos se establece en línea en ese nodo o cuando se inhabilita el recurso. En el tipo de recurso de ejemplo SUNW.xfnts, el método xfnts_start activa el daemon de xfs en ese nodo.

El método xfnts_start llama a scds_pmf_start() para iniciar el daemon bajo el control de PMF. Esta utilidad proporciona funciones de notificación de fallos automática y de reinicio, así como integración con el supervisor de fallos.


Nota –

La primera llamada de xfnts_start va dirigida a scds_initialize (), que realiza algunas funciones de mantenimiento necesarias. Para obtener más información, consulte Función scds_initialize() y la página de comando man scds_initialize(3HA).


Validación del servicio antes de iniciar el servidor de fuentes X

Antes de que el método xfnts_start intente iniciar el servidor de fuentes X, llama a svc_validate() para comprobar que se ha establecido la configuración correcta para admitir el daemon de xfs.

rc = svc_validate(scds_handle);
   if (rc != 0) {
      scds_syslog(LOG_ERR,
          "No se ha podido validar la configuración.");
      return (rc);
   }

Consulte Método xfnts_validate para obtener información.

Inicio del servicio con svc_start()

El método xfnts_start llama al método svc_start(), definido en el archivo xfnts.c, para iniciar el daemon de xfs. Esta sección describe svc_start().

A continuación se muestra el comando que permite iniciar el daemon de xfs:


# xfs -config config-directory/fontserver.cfg -port port-number

La propiedad de extensión Confdir_list identifica el directorio de configuración, config-directory, mientras que la propiedad del sistema Port_list identifica el número de puerto, port-number. El administrador del clúster proporciona valores específicos para estas propiedades al configurar el servicio de datos.

El método xfnts_start declara estas propiedades en forma de matriz de cadenas. El método xfnts_start obtiene los valores establecidos por el administrador del clúster mediante el uso de las funciones scds_get_ext_confdir_list() y scds_get_port_list(). Estas funciones se describen en la página de comando man scds_property_functions(3HA).

scha_str_array_t *confdirs;
scds_port_list_t    *portlist;
scha_err_t   err;

   /* get the configuration directory from the confdir_list property */
   confdirs = scds_get_ext_confdir_list(scds_handle);

   (void) sprintf(xfnts_conf, "%s/fontserver.cfg", confdirs->str_array[0]);

   /* obtain the port to be used by XFS from the Port_list property */
   err = scds_get_port_list(scds_handle, &portlist);
   if (err != SCHA_ERR_NOERR) {
      scds_syslog(LOG_ERR,
          "Could not access property Port_list.");
      return (1);
   }

Observe que la variable confdirs señala al primer elemento (0) de la matriz.

El método xfnts_start utiliza sprintf() para formar la línea de comandos de xfs.

/* Construct the command to start the xfs daemon. */
   (void) sprintf(cmd,
       "/usr/openwin/bin/xfs -config %s -port %d 2>/dev/null",
       xfnts_conf, portlist->ports[0].port);

Tenga en cuenta que el resultado se redirige a /dev/null para suprimir los mensajes generados por el daemon.

El método xfnts_start pasa la línea de comandos de xfs a scds_pmf_start() para iniciar el servicio de datos bajo el control de PMF.

scds_syslog(LOG_INFO, "Issuing a start request.");
   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 command completed successfully.");
   } else {
      scds_syslog(LOG_ERR,
          "Failed to start HA-XFS ");
   }

Tenga en cuenta los siguientes puntos acerca de la llamada a scds_pmf_start():

Antes de volver, svc_pmf_start() libera la memoria asignada para la estructura portlist.

scds_free_port_list(portlist);
return (err);

Devolución de svc_start()

Aunque svc_start() devuelva un mensaje satisfactorio, es posible que la aplicación subyacente no haya podido ejecutarse. Por tanto, svc_start() debe analizar la aplicación para verificar si se está ejecutando antes de devolver un mensaje satisfactorio. El análisis debe tener en cuenta también que la aplicación puede no estar disponible inmediatamente, ya que el proceso de inicio tarda algún tiempo. El método svc_start() llama a svc_wait(), que se define en archivo xfnts.c, para verificar que la aplicación se esté ejecutando.

/* Wait for the service to start up fully */
   scds_syslog_debug(DBG_LEVEL_HIGH,
       "Calling svc_wait to verify that service has started.");

   rc = svc_wait(scds_handle);

   scds_syslog_debug(DBG_LEVEL_HIGH,
       "Returned from svc_wait");

   if (rc == 0) {
      scds_syslog(LOG_INFO, "Successfully started the service.");
   } else {
      scds_syslog(LOG_ERR, "Failed to start the service.");
   }

La función svc_wait() llama a scds_get_netaddr_list () para obtener el recurso de dirección de red necesario para analizar la aplicación.

/* obtain the network resource to use for probing */
   if (scds_get_netaddr_list(scds_handle, &netaddr)) {
      scds_syslog(LOG_ERR,
          "No network address resources found in resource group.");
      return (1);
   }

   /* Return an error if there are no network resources */
   if (netaddr == NULL || netaddr->num_netaddrs == 0) {
      scds_syslog(LOG_ERR,
          "No network address resource in resource group.");
      return (1);
   }

La función svc_wait() obtiene los valores de Start_timeout y Stop_timeout.

svc_start_timeout = scds_get_rs_start_timeout(scds_handle)
   probe_timeout = scds_get_ext_probe_timeout(scds_handle)

Para contabilizar el tiempo que necesita el servidor para iniciarse, svc_wait() llama a scds_svc_wait() y pasa un valor de tiempo de espera equivalente al tres por ciento del valor de Start_timeout. La función svc_wait() llama a svc_probe() para comprobar que la aplicación se ha iniciado. El método svc_probe() realiza una conexión de socket sencilla con el servidor en el puerto especificado. Si no se puede conectar al puerto, svc_probe() devuelve el valor 100, que indica un fallo completo. Si se establece la conexión, pero falla la desconexión del puerto, svc_probe() devuelve el valor 50.

Cuando se produce un fallo parcial o total de svc_probe(), svc_wait() invoca scds_svc_wait() con un valor de tiempo de espera de 5. El método scds_svc_wait() limita la frecuencia de los análisis a cada 5 segundos. Este método cuenta también el número de intentos hechos para iniciar el servicio. Si el número de intentos supera el valor de la propiedad Retry_count del recurso en el periodo especificado en la propiedad Retry_interval , la función scds_svc_wait() devuelve un fallo. En ese caso, la función svc_start() también devuelve un fallo.

#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, "Service failed to start.");
      return (1);
   }

   do {
      /*
       * probe the data service on the IP address of the
       * network resource and the portname
       */
      rc = svc_probe(scds_handle,
          netaddr->netaddrs[0].hostname,
          netaddr->netaddrs[0].port_proto.port, probe_timeout);
      if (rc == SCHA_ERR_NOERR) {
         /* Success. Free up resources and return */
         scds_free_netaddr_list(netaddr);
         return (0);
      }

       /* Call scds_svc_wait() so that if service fails too
      if (scds_svc_wait(scds_handle, SVC_WAIT_TIME)
         != SCHA_ERR_NOERR) {
         scds_syslog(LOG_ERR, "Service failed to start.");
         return (1);
      }

   /* Rely on RGM to timeout and terminate the program */
   } while (1);

Nota –

Antes de salir, el método xfnts_start llama a scds_close() para reclamar los recursos asignados por scds_initialize (). Para obtener más información, consulte Función scds_initialize() y la página de comando man scds_close(3HA).


Método xfnts_stop

Como el método xfnts_start utiliza scds_pmf_start() para iniciar el servicio bajo el control de PMF, xfnts_stop utiliza scds_pmf_stop() para detener el servicio.


Nota –

La primera llamada de xfnts_stop va dirigida a scds_initialize (), que realiza algunas funciones de mantenimiento necesarias. Para obtener más información, consulte Función scds_initialize() y la página de comando man scds_initialize(3HA).


El método xfnts_stop llama al método svc_stop(), que se define en el archivo xfnts.c, de la siguiente forma:

scds_syslog(LOG_ERR, "Issuing a stop request.");
   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,
          "Failed to stop HA-XFS.");
      return (1);
   }

   scds_syslog(LOG_INFO,
       "Successfully stopped HA-XFS.");
   return (SCHA_ERR_NOERR); /* Successfully stopped */

Tenga en cuenta los siguientes puntos acerca de la llamada de svc_stop() a la función scds_pmf_stop():


Nota –

Antes de salir, el método xfnts_stop llama a scds_close() para reclamar los recursos asignados por scds_initialize (). Para obtener más información, consulte Función scds_initialize() y la página de comando man scds_close(3HA).


Método xfnts_monitor_start

RGM llama al método Monitor_start en un nodo para iniciar el supervisor de fallos después de iniciar el recurso en ese nodo. El método xfnts_start utiliza scds_pmf_start() para iniciar el daemon del supervisor bajo el control de PMF.


Nota –

La primera llamada de xfnts_monitor_start va dirigida a scds_initialize(), que realiza algunas funciones de mantenimiento necesarias. Para obtener más información, consulte Función scds_initialize() y la página de comando man scds_initialize(3HA).


El método xfnts_monitor_start llama al método mon_start , que se define en el archivo xfnts.c, de la siguiente forma:

scds_syslog_debug(DBG_LEVEL_HIGH,
      "Calling Monitor_start method for resource <%s>.",
      scds_get_resource_name(scds_handle));

    /* Call scds_pmf_start and pass the name of the probe. */
   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,
          "Failed to start fault monitor.");
      return (1);
   }

   scds_syslog(LOG_INFO,
       "Started the fault monitor.");

   return (SCHA_ERR_NOERR); /* Successfully started Monitor */
}

Tenga en cuenta los siguientes puntos acerca de la llamada de svc_mon_start() a la función scds_pmf_start():


Nota –

Antes de salir, el método xfnts_monitor_start llama a scds_close() para reclamar los recursos asignados por scds_initialize (). Para obtener más información, consulte Función scds_initialize() y la página de comando man scds_close(3HA).


Método xfnts_monitor_stop

Como el método xfnts_monitor_start utiliza scds_pmf_start() para iniciar el daemon del supervisor bajo el control de PMF, xfnts_monitor_stop utiliza scds_pmf_stop() para detenerlo.


Nota –

La primera llamada de xfnts_monitor_stop va dirigida a scds_initialize(), que realiza algunas funciones de mantenimiento necesarias. Para obtener más información, consulte Función scds_initialize() y la página de comando man scds_initialize(3HA).


El método xfnts_monitor_stop() llama al método mon_stop , que se define en el archivo xfnts.c, de la siguiente forma:

scds_syslog_debug(DBG_LEVEL_HIGH,
      "Calling scds_pmf_stop method");

   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,
          "Failed to stop fault monitor.");
      return (1);
   }

   scds_syslog(LOG_INFO,
       "Stopped the fault monitor.");

   return (SCHA_ERR_NOERR); /* Successfully stopped monitor */
}

Tenga en cuenta los siguientes puntos acerca de la llamada de svc_mon_stop() a la función scds_pmf_stop():


Nota –

Antes de salir, el método xfnts_monitor_stop llama a scds_close() para reclamar los recursos asignados por scds_initialize (). Para obtener más información, consulte Función scds_initialize() y la página de comando man scds_close(3HA)


Método xfnts_monitor_check

RGM llama al método Monitor_check cada vez que el supervisor de fallos intenta realizar una recuperación ante fallos del grupo de recursos que contiene el recurso en otro nodo. El método xfnts_monitor_check llama a svc_validate() para comprobar si se ha establecido la configuración correcta para admitir el daemon de xfs. Consulte Método xfnts_validate para obtener información. A continuación se muestra el código de xfnts_monitor_check:

/* Process the arguments passed by RGM and initialize syslog */
   if (scds_initialize(&scds_handle, argc, argv) != SCHA_ERR_NOERR)
{
      scds_syslog(LOG_ERR, "Failed to initialize the handle.");
      return (1);
   }

   rc =  svc_validate(scds_handle);
   scds_syslog_debug(DBG_LEVEL_HIGH,
       "monitor_check method "
       "was called and returned <%d>.", rc);

   /* Free up all the memory allocated by scds_initialize */
   scds_close(&scds_handle);

   /* Return the result of validate method run as part of monitor check */
   return (rc);
}

Supervisor de fallos SUNW.xfnts

RGM no llama directamente al método PROBE, sino que llama a Monitor_start para iniciar el supervisor una vez iniciado un recurso en el nodo. El método xfnts_monitor_start inicia el supervisor de fallos bajo el control de PMF. El método xfnts_monitor_stop detiene el supervisor de fallos.

El supervisor de fallos SUNW.xfnts realiza las operaciones siguientes:

Bucle principal de xfonts_probe

El método xfonts_probe implementa un bucle. Antes de implementar el bucle, xfonts_probe realiza las siguientes operaciones:

El método xfnts_probe implementa el siguiente bucle:

for (ip = 0; ip < netaddr->num_netaddrs; ip++) {
         /*
          * Grab the hostname and port on which the
          * health has to be monitored.
          */
         hostname = netaddr->netaddrs[ip].hostname;
         port = netaddr->netaddrs[ip].port_proto.port;
         /*
          * HA-XFS supports only one port and
          * hence obtain the port value from the
          * first entry in the array of ports.
          */
         ht1 = gethrtime(); /* Latch probe start time */
         scds_syslog(LOG_INFO, "Probing the service on port: %d.", port);

         probe_result =
         svc_probe(scds_handle, hostname, port, timeout);

         /*
          * Update service probe history,
          * take action if necessary.
          * Latch probe end time.
          */
         ht2 = gethrtime();

         /* Convert to milliseconds */
         dt = (ulong_t)((ht2 - ht1) / 1e6);

         /*
          * Compute failure history and take
          * action if needed
          */
         (void) scds_fm_action(scds_handle,
             probe_result, (long)dt);
      }   /* Each net resource */
   }    /* Keep probing forever */

La función svc_probe() implementa la lógica del análisis. El valor de devolución de svc_probe() se pasa a scds_fm_action (), que determina si se debe reiniciar la aplicación, realizar una recuperación ante fallos del grupo de recurso o no realizar ninguna acción.

Función svc_probe()

La función svc_probe () establece una conexión de socket simple al puerto especificado mediante una llamada a scds_fm_tcp_connect(). Si falla la conexión, svc_probe() devuelve el valor 100, que indica la existencia de un fallo completo. Si la conexión se establece con éxito, pero falla la desconexión, svc_probe() devuelve el valor 50, que indica la existencia de un fallo parcial. Si la conexión y desconexión se realizan satisfactoriamente, svc_probe() devuelve el valor 0, que indica que no hay fallos.

A continuación se muestra el código de svc_probe():

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;


   /*
    * probe the data service by doing a socket connection to the port
    * specified in the port_list property to the host that is
    * serving the XFS data service. If the XFS service which is configured
    * to listen on the specified port, replies to the connection, then
    * the probe is successful. Else we will wait for a time period set
    * in probe_timeout property before concluding that the probe failed.
    */

   /*
    * Use the SVC_CONNECT_TIMEOUT_PCT percentage of timeout
    * to connect to the port
    */
   connect_timeout = (SVC_CONNECT_TIMEOUT_PCT * timeout)/100;
   t1 = (hrtime_t)(gethrtime()/1E9);

   /*
    * the probe makes a connection to the specified hostname and port.
    * The connection is timed for 95% of the actual probe_timeout.
    */
   rc = scds_fm_tcp_connect(scds_handle, &sock, hostname, port,
       connect_timeout);
   if (rc) {
      scds_syslog(LOG_ERR,
          "Failed to connect to port <%d> of resource <%s>.",
          port, scds_get_resource_name(scds_handle));
      /* this is a complete failure */
      return (SCDS_PROBE_COMPLETE_FAILURE);
   }

   t2 = (hrtime_t)(gethrtime()/1E9);

   /*
    * Compute the actual time it took to connect. This should be less than
    * or equal to connect_timeout, the time allocated to connect.
    * If the connect uses all the time that is allocated for it,
    * then the remaining value from the probe_timeout that is passed to
    * this function will be used as disconnect timeout. Otherwise, the
    * the remaining time from the connect call will also be added to
    * the disconnect timeout.
    *
    */

   time_used = (int)(t2 - t1);

   /*
    * Use the remaining time(timeout - time_took_to_connect) to disconnect
    */

   time_remaining = timeout - (int)time_used;

   /*
    * If all the time is used up, use a small hardcoded timeout
    * to still try to disconnect. This will avoid the fd leak.
    */
   if (time_remaining <= 0) {
      scds_syslog_debug(DBG_LEVEL_LOW,
          "svc_probe used entire timeout of "
          "%d seconds during connect operation and exceeded the "
          "timeout by %d seconds. Attempting disconnect with timeout"
          " %d ",
          connect_timeout,
          abs(time_used),
          SVC_DISCONNECT_TIMEOUT_SECONDS);

      time_remaining = SVC_DISCONNECT_TIMEOUT_SECONDS;
   }

   /*
    * Return partial failure in case of disconnection failure.
    * Reason: The connect call is successful, which means
    * the application is alive. A disconnection failure
    * could happen due to a hung application or heavy load.
    * If it is the later case, don't declare the application
    * as dead by returning complete failure. Instead, declare
    * it as partial failure. If this situation persists, the
    * disconnect call will fail again and the application will be
    * restarted.
    */
   rc = scds_fm_tcp_disconnect(scds_handle, sock, time_remaining);
   if (rc != SCHA_ERR_NOERR) {
      scds_syslog(LOG_ERR,
          "Failed to disconnect to port %d of resource %s.",
          port, scds_get_resource_name(scds_handle));
      /* this is a partial failure */
      return (SCDS_PROBE_COMPLETE_FAILURE/2);
   }

   t2 = (hrtime_t)(gethrtime()/1E9);
   time_used = (int)(t2 - t1);
   time_remaining = timeout - time_used;

   /*
    * If there is no time left, don't do the full test with
    * fsinfo. Return SCDS_PROBE_COMPLETE_FAILURE/2
    * instead. This will make sure that if this timeout
    * persists, server will be restarted.
    */
   if (time_remaining <= 0) {
      scds_syslog(LOG_ERR, "Probe timed out.");
      return (SCDS_PROBE_COMPLETE_FAILURE/2);
   }

   /*
    * The connection and disconnection to port is successful,
    * Run the fsinfo command to perform a full check of
    * server health.
    * Redirect stdout, otherwise the output from fsinfo
    * ends up on the console.
    */
   (void) sprintf(testcmd,
       "/usr/openwin/bin/fsinfo -server %s:%d > /dev/null",
       hostname, port);
   scds_syslog_debug(DBG_LEVEL_HIGH,
       "Checking the server status with %s.", testcmd);
   if (scds_timerun(scds_handle, testcmd, time_remaining,
      SIGKILL, &rc) != SCHA_ERR_NOERR || rc != 0) {

      scds_syslog(LOG_ERR,
         "Failed to check server status with command <%s>",
         testcmd);
      return (SCDS_PROBE_COMPLETE_FAILURE/2);
   }
   return (0);
}

Una vez finalizado, svc_probe() devuelve un valor que indica que el proceso se ha realizado con éxito (0), o que se ha producido un fallo parcial (50) o uno completo (100). El método xfnts_probe pasa este valor a scds_fm_action().

Selección de la acción del supervisor de fallos

El método xfnts_probe llama a scds_fm_action() para determinar la acción que debe realizarse. La lógica de scds_fm_action() es la siguiente:

Por ejemplo, supongamos que el análisis establece una conexión con el servidorxfs, pero no logra desconectarse satisfactoriamente. Esto indica que el servidor está en ejecución, pero que es posible que esté bloqueado o bajo una carga temporal. Al fallar la desconexión, se envía un fallo parcial ( 50) a scds_fm_action(). Este valor está por debajo del umbral para reiniciar el servicio de datos, pero se mantiene el valor en el historial de fallos.

Si, durante el siguiente análisis, el servidor no puede desconectarse otra vez, el valor 50 se agrega al historial de fallos que mantiene scds_fm_action (). El valor de fallo acumulativo es ahora de 100, por lo que scds_fm_action() reinicia el servicio de datos.

Método xfnts_validate

RGM llama al método Validate cuando se crea un recurso y el administrador del clúster actualiza las propiedades del recurso o del grupo que lo contiene. RGM invoca Validate antes de que se apliquen la creación o la actualización y un código de salida fallido del método en cualquier nodo provoque la cancelación de la creación o actualización.

RGM sólo llama a Validate cuando el administrador del clúster cambia las propiedades de un recurso o un grupo de recursos, o cuando un supervisor establece las propiedades de recursos Status y Status_msg. RGM no llama a Validate cuando esta herramienta establece las propiedades.


Nota –

El método Monitor_check también llama de forma explícita a Validate cada vez que el método PROBE intenta realizar una recuperación ante fallos del servicio de datos en un nuevo nodo.


RGM llama a Validate con argumentos adicionales a aquéllos transferidos a otros métodos, incluidos los valores y las propiedades que se están actualizando. La llamada a scds_initialize() al comienzo de xfnts_validate analiza todos los argumentos que RGM pasa a xfnts_validate y almacena la información en el argumento scds_handle. La subrutinas invocadas por xfnts_validate utilizan esta información.

El método xfnts_validate llama a svc_validate(), que comprueba las siguientes condiciones:

Antes de retornar, svc_validate() libera todos los recursos asignados.

finished:
   scds_free_net_list(snrlp);
   scds_free_port_list(portlist);

   return (rc); /* return result of validation */

Nota –

Antes de salir, el método xfnts_validate llama a scds_close() para reclamar los recursos asignados por scds_initialize (). Para obtener más información, consulte Función scds_initialize() y la página de comando man scds_close(3HA)


Método xfnts_update

RGM llama al método Update para notificar a un recurso en ejecución que sus propiedades han cambiado. Las únicas propiedades que se pueden cambiar para el servicio de datos de xfnts corresponden al supervisor de fallos. Por lo tanto, cada vez que se actualiza una propiedad, el método xfnts_update llama a scds_pmf_restart_fm() para reiniciar el supervisor de fallos.

  /* check if the Fault monitor is already running and if so stop
   * and restart it. The second parameter to scds_pmf_restart_fm()
   * uniquely identifies the instance of the fault monitor that needs
   * to be restarted.
   */

   scds_syslog(LOG_INFO, "Restarting the fault monitor.");
   result = scds_pmf_restart_fm(scds_handle, 0);
   if (result != SCHA_ERR_NOERR) {
      scds_syslog(LOG_ERR,
          "Failed to restart fault monitor.");
      /* Free up all the memory allocated by scds_initialize */
      scds_close(&scds_handle);
      return (1);
   }

   scds_syslog(LOG_INFO,
   "Completed successfully.");

Nota –

El segundo argumento de scds_pmf_restart_fm() identifica de forma exclusiva la instancia del supervisor de fallos que debe reiniciarse en caso de existir varias. El valor 0 del ejemplo indica que sólo hay una instancia del supervisor de fallos.