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

Capítulo 7 Diseño de tipos de recurso

En este capítulo se explica la utilización habitual de DSDL para diseñar e implementar tipos de recursos. Se presta especial atención al diseño de los tipos de recursos para validar la configuración del recurso, así como iniciar, detener y supervisar éste. Finalmente, se describe cómo utilizar DSDL para implementar los métodos de rellamada del tipo de recurso.

Consulte la página de comando man rt_callbacks(1HA) para obtener información adicional.

Para realizar estas tareas deberá acceder a la configuración de la propiedad del recurso. La utilidad scds_initialize() de DSDL permite acceder de modo uniforme a las propiedades de los recursos. Esta función esta diseñada para invocarse al principio de los métodos de rellamada; permite recuperar las propiedades de un recurso desde la estructura del clúster y lo pone a disposición de la familia de funciones scds_getnombre().

En este capítulo se tratan los temas siguientes:

El archivo RTR

El archivo de registro del tipo de recurso (RTR) es un componente importante de un tipo de recurso. Este archivo especifica los detalles del tipo de recurso para Sun Cluster que incluyen información, como las propiedades necesarias para la implementación, los tipos de datos y los valores predeterminados de esas propiedades, la ruta del sistema de archivos para los métodos de rellamada de la implementación del tipo de recurso y varios valores de las propiedades definidas por el sistema.

El archivo RTR de ejemplo que se incluye con DSDL debería bastar para la mayoría de las implementaciones del tipo de recurso. Sólo hay que editar algunos elementos básicos, como los nombres del tipo de recurso y de la ruta de los métodos de rellamada del tipo de recurso. Si se necesita una nueva propiedad para implementar el tipo de recurso, puede declararla como propiedad de extensión en el archivo de registro del tipo de recurso (RTR) de la implementación del tipo de recurso y acceder después a la nueva propiedad con la utilidad scds_get_ext_property() de DSDL.

El método Validate

RGM llama al método Validate de una implementación de tipo de recurso en dos situaciones: 1) cuando se crea un nuevo recurso del tipo de recurso y 2) cuando se actualiza una propiedad del recurso o grupo de recursos. Estas dos situaciones se pueden distinguir por la presencia de la opción de la línea de órdenes -c (creación) o -u (actualización) que se pasa al método Validate del recurso.

El método Validate se invoca en todos los nodos de un conjunto definido por el valor de la propiedad del tipo de recurso INIT_NODES. Si se establece INIT_NODES en RG_PRIMARIES, Validate se invoca en todos los nodos que puedan alojar (ser principales de) el grupo de recursos que contiene el recurso en cuestión. Si se establece INIT_NODES en RT_INSTALLED_NODES, Validate se invoca en todos los nodos en los que está instalado el software del tipo de recurso, que suelen ser todos los nodos del clúster. El valor predeterminado de INIT_NODES es RG_PRIMARIES (consulte rt_reg(4). En el momento en que se invoca el método Validate, RGM no ha creado aún el recurso (en el caso de una rellamada de creación) o todavía no ha aplicado el o los valor(es) actualizado(s) de las propiedades que se van a actualizar (en el caso de una rellamada de actualización). El objetivo del método Validate de una implementación de tipo de recurso es comprobar que los valores propuestos para el recurso (tal como indica la configuración de la propiedad propuesta en el recurso) son aceptables para el tipo de recurso.


Nota –

Si está utilizando sistemas de archivo locales gestionados por HAStoragePlus, utilizará scds_hasp_check para comprobrar el estado del recurso HAStoragePlus. Esta información se obtiene del estado (en línea u otro) de todos los recursos SUNW.HAStoragePlus(5) de los que depende éste al utilizar las propiedades del sistema Resource_dependencies o Resource_dependencies_weak definidas para el mismo. Consulte scds_hasp_check(3HA) para obtener una lista completa de códigos de estado devueltos de la llamada scds_hasp_check.


La función scds_initialize() de DSDL se encarga de estas situaciones como sigue:

Supongamos que la función que implementa la validación de las propiedades de un recurso se llama svc_validate() y utiliza la familia de funciones scds_get_nombre() para ver la propiedad que interesa validar. Suponiendo que un valor de recurso aceptable se represente con un código de retorno 0 de esta función, el método Validate del tipo de recurso se puede representar con el siguiente fragmento de código:


int
main(int argc, char *argv[])
{
   scds_handle_t handle;
   int rc;

   if (scds_initialize(&handle, argc, argv)!= SCHA_ERR_NOERR) {
   return (1);   /* Error de inicialización*/
   }
   rc = svc_validate(handle);
   scds_close(&handle);
   return (rc);
}

La función de validación debe también registrar el motivo del fallo en la validación del recurso. Dejando a un lado los detalles (si desea ver un tratamiento más realista de una función de validación, consulte el capítulo siguiente), un ejemplo sencillo de función svc_validate() se puede implementar como:


int
svc_validate(scds_handle_t handle)
{
   scha_str_array_t *confdirs;
   struct stat    statbuf;
   confdirs = scds_get_confdir_list(handle);
   if (stat(confdirs->str_array[0], &statbuf) == -1) {
   return (1);   /* Valor de propiedad de recurso no válido */
   }
   return (0);   /* Valor de configuración aceptable */
}

El desarrollador de tipos de recursos se debe encargar sólo de la implementación de la función svc_validate(). Un ejemplo típico de implementación de un tipo de recurso podría ser garantizar que un archivo de configuración de una aplicación denominado app.conf existiera dependiente de la propiedad Confdir_list. Esto se puede implementar convenientemente con una llamada de sistema stat() en el nombre de ruta adecuado, derivado de la propiedad Confdir_list.

El método Start

RGM invoca el método de rellamada Start de una implementación de tipo de recursos en un nodo del clúster seleccionado para iniciar el recurso. En la línea de órdenes se pasan los nombres del grupo de recurso, del recurso y del tipo de recurso. Se espera que el método Start realice las acciones necesarias para iniciar un recurso de servicio de datos en el nodo del clúster. Generalmente, esto implica recuperar las propiedades del recurso, ubicar los ejecutables específicos de la aplicación y los archivos de configuración y ejecutar la aplicación con los argumentos de línea de órdenes adecuados.

Con DSDL, la configuración del recurso ya la recupera la utilidad scds_initialize(). La acción de inicio de la aplicación se puede contener en una función svc_start(). Se puede llamar a otra función, svc_wait(), para verificar que la aplicación se inicie realmente. El código simplificado para el método Start se convierte en:


int
main(int argc, char *argv[])
{
   scds_handle_t handle;

   if (scds_initialize(&handle, argc, argv)!= SCHA_ERR_NOERR) {
   return (1);   /* Error de inicialización */
   }
   if (svc_validate(handle) != 0) {
   return (1);   /* Valores de configuración no válidos */
   }
   if (svc_start(handle) != 0) {
   return (1);   /* Inicio no realizado */
   }
   return (svc_wait(handle));
}

Esta implementación de método de inicio llama a svc_validate() para validar la configuración del recurso. Si falla, o bien la configuración del recurso o la configuración de la aplicación no coinciden o bien hay actualmente un problema relacionado con el sistema en el nodo del clúster. Por ejemplo, es posible que un sistema de archivos global necesario para el recurso no esté disponible actualmente en este nodo del clúster. En tal caso, es inútil intentar siquiera iniciar el recurso en este nodo del clúster, es mejor que RGM intente iniciar el recurso en otro nodo. Tenga en cuenta en todo caso que lo anterior asume que svc_validate () es lo bastante conservador (de forma que sólo compruebe los recursos del nodo del clúster que son absolutamente necesarios para la aplicación) o de lo contrario el recurso podría no iniciarse en todos los nodos del clúster y por tanto terminar con un estado START_FAILED. Consulte scswitch( 1M) y Sun Cluster Data Services Planning and Administration Guide for Solaris OS para ver una explicación sobre este estado.

La función svc_start() debe devolver 0 para que el inicio del recurso en el nodo sea satisfactorio. Si la función de inicio ha encontrado algún problema, devolverá un valor distinto de cero. Si esta función falla, RGM intenta iniciar el recurso en otro nodo del clúster.

Para aprovechar DSDL en lo posible, la función svc_start() puede utilizar la utilidad scds_pmf_start() para iniciar la aplicación bajo la Prestación del supervisor de procesos (PMF). Esta utilidad aprovecha también la función de acción de rellamada en caso de fallo de PMF (consulte el indicador de acción -a en pmfadm(1M)) para implementar la detección de fallos de procesos.

El método Stop

RGM invoca el método de rellamada Stop de una implementación del tipo de recurso en un nodo del clúster para detener la aplicación. La semántica de la rellamada del método Stop requiere estas condiciones:

La utilidad scds_pmf_stop() de DSDL debería bastar para casi todas las aplicaciones ya que en primer lugar intenta detenerlas de forma no drástica (a través de SIGTERM) (asume que se inició con PMF mediante scds_pmf_start()) seguido por el envío de SIGKILL al proceso. Consulte Funciones de PMF para obtener más detalles sobre esta utilidad.

Siguiendo el modelo del código que hemos utilizado hasta ahora, presuponiendo que la función específica de la aplicación para detener la aplicación se denomine svc_stop() (que la implementación de svc_stop() utilice scds_pmf_stop() no es relevante en este momento y dependerá de que la aplicación se haya iniciado bajo PMF con el método Start), el método Stop se puede implementar de la manera siguiente:

if (scds_initialize(&handle, argc, argv)!= SCHA_ERR_NOERR)
{
   return (1);   /* Error de inicialización */
}
return (svc_stop(handle));

El método svc_validate() no se utiliza en la implementación del método Stop, porque aunque el sistema tenga actualmente un problema, el método Stop debería intentar detener la aplicación en este nodo.

El método Monitor_start

RGM invoca el método Monitor_start para iniciar un supervisor de fallos para el recurso. Los supervisores de fallos controlan el estado de la aplicación que gestiona el recurso. Las implementaciones del tipo de recurso se suelen realizar en un supervisor de fallos como daemon separado, que se ejecuta en segundo plano. El método de rellamada Monitor_start se usa para ejecutar este daemon con los argumentos apropiados.

Dado que el daemon del supervisor está sujeto, también, a sufrir fallos (por ejemplo, podría terminarse inesperadamente, dejando la aplicación sin supervisión), se debería iniciar PMF para iniciar el daemon del supervisor. La utilidad scds_pmf_start() de DSDL incorpora soporte integrado para iniciar supervisores de fallos. Esta utilidad emplea el nombre de ruta relativo (relativo a RT_basedir para la ubicación de las implementaciones de métodos de rellamada de tipo de recurso) del programa daemon del supervisor. Emplea las propiedades de extensión Monitor_retry_interval y Monitor_retry_count gestionadas por DSDL para impedir que se produzca un número ilimitado de reinicios del daemon. Impone la misma sintaxis de línea de órdenes definida para todos los métodos de rellamada (es decir, -R recurso -G grupo_recursos -T tipo_recurso) al daemon del supervisor, aunque RGM no lo invoca nunca directamente. Permite que la implementación del daemon del supervisor aproveche la utilidad scds_initialize() para configurar su propio entorno. El esfuerzo principal se destina a diseñar el propio daemon del supervisor.

El método Monitor_stop

RGM invoca el método Monitor_stop para detener el daemon del supervisor de fallos iniciado mediante el método Monitor_start. El fallo de este método de retrollamada se considera de la misma forma como el de Stop; por tanto el método Monitor_stop debe tener la misma potencia y robustez que Stop.

Si emplea scds_pmf_start() para iniciar el daemon del supervisor de fallos, utilice scds_pmf_stop() para detenerlo.

El método Monitor_check

El método de rellamada Monitor_check en un recurso se invoca en un nodo para que el recurso especificado pueda determinar si el nodo del clúster es capaz de controlar el recurso (es decir, ¿pueden ejecutarse satisfactoriamente en el nodo las aplicaciones que está gestionando el recurso?). Generalmente, esta situación implica asegurarse de que todos los recursos del sistema que necesita la aplicación estén de hecho disponibles en el nodo del clúster. Como se explica en El método Validate, la función svc_validate() que implementa el desarrollador está destinada a realizar por lo menos esta comprobación.

Según la aplicación concreta que esté gestionando la implementación del tipo de recurso, el método Monitor_check se puede escribir para que realice otras tareas. El método Monitor_check debe implementarse de forma que no entre en conflicto con otros métodos que funcionen simultáneamente. Para los desarrolladores que utilizan DSDL es recomendable que el método Monitor_check aproveche la función svc_validate() escrita para implementar una validación de las propiedades de recurso específicas de la aplicación.

El método Update

RGM invoca el método Update de una implementación del tipo de recurso para aplicar cualquier cambio realizado por el administrador del sistema en la configuración del recurso activo. El método Update sólo se invoca en los nodos en los que el recurso está en línea en este momento (si los hubiera).

Los cambios que se acaban de realizar en la configuración del recurso serán aceptables para la implementación del tipo de recurso porque RGM ejecuta el método Validate del tipo de recurso antes de ejecutar el método Update. El método Validate se invoca antes de que las propiedades del recurso o grupo de recursos sean modificadas y de que el método Validate pueda vetar los cambios propuestos. El método Update se invoca después de que los cambios se hayan aplicado para darle al recurso activo (en línea) la oportunidad de notar los nuevos valores.

Como desarrollador del tipo de recurso, tiene que decidir con mucho cuidado las propiedades que desea poder actualizar dinámicamente y marcarlas con el valor TUNABLE = ANYTIME en el archivo RTR. Generalmente se puede especificar si se desea poder actualizar dinámicamente cualquier propiedad de una implementación del tipo de recurso que utilice el daemon del supervisor de fallos, siempre que la implementación del método Update reinicie al menos el daemon del supervisor.

Las candidatas posibles son las siguientes:

Estas propiedades afectan al modo en que un daemon del supervisor de fallos realiza la comprobación del estado del servicio, la frecuencia de las comprobaciones, el intervalo de historial que utiliza para mantener un seguimiento de los errores y los umbrales de reinicio que ha establecido PMF. Para implementar las actualizaciones de estas propiedades se incluye la utilidad scds_pmf_restart() en DSDL.

Si necesita poder actualizar dinámicamente una propiedad de recurso, cuya modificación puede afectar a la aplicación en curso, deberá emplear las acciones necesarias para que las actualizaciones se apliquen correctamente a todas las instancias en ejecución de la aplicación. Actualmente no existe ninguna forma de facilitar esta tarea mediante DSDL. Update no recibe las propiedades modificadas en la línea de órdenes (como Validate).

Los métodos Init, Fini y Boot

Son métodos de acción única, como se indica en las especificaciones de la API de gestión de recursos. La implementación de ejemplo que se incluye con DSDL no ilustra la utilización de estos métodos. Sin embargo, todos los recursos de DSDL están también disponibles para estos métodos por si un desarrollador de tipo de recursos los necesita. Generalmente, los métodos Init y Boot serán exactamente iguales que los de una implementación del tipo de recurso para implementar una acción única. El método Fini normalmente realiza una acción para deshacer la acción de los métodos Init o Boot.

Diseño de un daemon del supervisor de fallos

Las implementaciones del tipo de recurso con DSDL suelen tener un daemon del supervisor de fallos con las responsabilidades siguientes.

Las utilidades de DSDL están diseñadas de modo que el bucle principal del daemon del supervisor de fallos se pueda representar con el siguiente pseudocódigo.

Para los supervisores de fallos implementados con DSDL:

En la mayoría de los casos, la acción de comprobación del estado específico de la aplicación se puede implementar en una utilidad autónoma separada (por ejemplo, svc_probe()) y se puede integrar con este bucle principal genérico.


for (;;) {

   / * reposo durante un intervalo thorough_probe_interval entre
   * análisis sucesivos. */
   (void) scds_fm_sleep(scds_handle,
   scds_get_rs_thorough_probe_interval(scds_handle));

   /* Analizar ahora todas las direcciones ip que se usan.
   * Recorrer:
   * 1. Todos los recursos de red que usamos.
   * 2. Todas las direcciones ip de un recurso determinado.
   * Para cada una de las direcciones ip analizadas,
   * calcular el historial de fallos. */
   probe_result = 0;
   /* Iterar todos los recursos para obtener todas las
    * direcciones IP para invocar svc_probe() */
   for (ip = 0; ip < netaddr->num_netaddrs; ip++) {
   /* Anotar el nombre del sistema y puerto en los que
   * se debe supervisar el estado.
   */
   hostname = netaddr->netaddrs[ip].hostname;
   port = netaddr->netaddrs[ip].port_proto.port;
   /*
   * HA-XFS sólo admite un puerto; por tanto,
   * obtener el valor de puerto de la primera
   * entrada de la matriz de puertos.
   */
   ht1 = gethrtime(); /* Bloquear tiempo de inicio de análisis */
   probe_result = svc_probe(scds_handle,

   hostname, port, timeout);
   /*
   * Actualizar historial de análisis,
   * tomar medidas si fuera necesario.
   * Bloquear tiempo de finalización de análisis.
   */
   ht2 = gethrtime();
   /* Convertir a milisegundos */
   dt = (ulong_t)((ht2 - ht1) / 1e6);

   /*
   * Calcular historial de fallos y tomar
   * medidas si fuera necesario
   */
   (void) scds_fm_action(scds_handle,
   probe_result, (long)dt);
   }       /* Cada recurso de red */
   }       /* Seguir analizando para siempre */