Sun Cluster 数据服务开发者指南(适用于 Solaris OS)

第 7 章 设计资源类型

本章介绍了数据服务开发库 (DSDL) 在设计和实现资源类型方面的典型应用,还着重介绍了设计资源类型以验证资源配置以及启动、停止和监视该资源等内容。另外,本章介绍了如何使用 DSDL 来实现资源类型回调方法。

有关附加信息,请参见 rt_callbacks(1HA) 手册页。

要完成这些任务,您需要访问资源的属性设置。DSDL 实用程序 scds_initialize() 提供了访问这些资源属性的统一方法。本函数设计成在每个回调方法的开头部分进行调用。此实用程序函数用于从群集框架中检索资源的所有属性,并使其可用于 scds_getname() 函数系列。

本章包括以下主题:

资源类型注册文件

资源类型注册 (RTR) 文件指明有关 Sun Cluster 软件中的资源类型的详细信息。包括以下详细信息:

DSDL 附带的样例 RTR 文件对于大多数资源类型实现来说是足够的。您只需编辑一些基本元素,例如,资源类型回调方法的资源类型名称和路径名称。如果需要新属性才能实现资源类型,可以将其声明为资源类型实现的 RTR 文件中的扩展属性,并可通过 DSDL scds_get_ext_property() 实用程序访问该属性。

Validate 方法

资源类型实现的 Validate 回调方法用于检查提议的资源设置(由对资源提议的属性设置指定)对于资源类型来说是否可以接受。

在以下两种情况下,资源组管理器 (RGM) 将调用资源类型实现的 Validate 方法:

这两种情况可以通过传递给资源的 Validate 方法的命令行选项是 -c(创建)还是 -u(更新)进行区分。

Validate 方法在节点集的每个节点上都要调用,该节点集由资源类型属性 Init_nodes 的值定义。如果 Init_nodes 设置为 RG_PRIMARIES,则在可以托管包含资源的资源组的每个节点(主节点)上调用 Validate。如果 Init_nodes 设置为 RT_INSTALLED_NODES,则在安装资源类型软件的每个节点(通常是群集中的所有节点)上调用 Validate

Init_nodes 的默认值为 RG_PRIMARIES(请参见 rt_reg(4) 手册页)。在调用 Validate 方法时,RGM 尚未创建资源(在创建回调的情况下)或尚未应用正被更新的属性的更新值(在更新回调的情况下)。


注 –

如果使用的是由 HAStoragePlus 资源类型管理的本地文件系统,请使用 scds_hasp_check() 函数检查该资源类型的状态。此信息来自该资源所依赖的所有 SUNW.HAStoragePlus 资源的状态(联机或脱机),它是通过使用为该资源定义的 Resource_dependenciesResource_dependencies_weak 系统属性获得的。有关 scds_hasp_check() 函数返回的状态代码的完整列表,请参见 scds_hasp_check(3HA) 手册页。


DSDL 函数 scds_initialize() 按照以下方式处理这些情况:

假设实现资源属性验证的函数名为 svc_validate(),该函数使用 scds_get_name() 系列函数查看要验证的属性。假定可接受的资源设置由此函数的 0 返回代码表示,则资源类型的 Validate 方法可表示为以下代码段:

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

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

验证函数还应当记录资源验证失败的原因。不过,如果忽略细节(第 8 章,DSDL 资源类型实现样例包含更实际的验证函数处理),可以实现更简单的示例 svc_validate() 函数,如下所示:

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);   /* Invalid resource property setting */
   }
   return (0);   /* Acceptable setting */
}

因此,只需考虑 svc_validate() 函数的实现。

Start 方法

RGM 将对所选群集节点调用资源类型实现的 Start 回调方法,以启动该资源。通过命令行传送资源组名称、资源名称和资源类型名称。Start 方法用于执行在群集节点中启动数据服务资源所需的操作。通常,这涉及使用正确的命令行参数检索资源属性、找到应用程序特定的可执行文件和/或配置文件以及启动应用程序。

使用 DSDL,资源配置已经由 scds_initialize() 公用程序检索。应用程序的启动操作可以包含在函数 svc_start() 中。可以调用另一个函数 svc_wait() 来检验是否确实启动了应用程序。Start 方法的简化代码如下:

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

   if (scds_initialize(&handle, argc, argv)!= SCHA_ERR_NOERR) {
   return (1);   /* Initialization Error */
   }
   if (svc_validate(handle) != 0) {
   return (1);   /* Invalid settings */
   }
   if (svc_start(handle) != 0) {
   return (1);   /* Start failed */
   }
   return (svc_wait(handle));
}

该启动方法实现调用 svc_validate() 来验证资源配置。如果失败,其原因不是资源配置与应用程序配置不匹配,就是此群集节点上当前存在系统问题。例如,资源所需的群集文件系统当前可能无法在此群集节点上使用。在这种情况下,尝试在此群集节点上启动资源是毫无意义的。最好是让 RGM 在其它节点上启动该资源。

但是请注意,前述声明假定 svc_validate() 十分保守,它仅检查应用程序绝对需要的群集节点上的资源。否则,资源可能无法在所有群集节点上启动,并因此进入 START_FAILED 状态。有关此状态的说明,请参见 scswitch(1M) 手册页和《Sun Cluster Data Services Planning and Administration Guide for Solaris OS》

如果资源在节点上成功启动,则 svc_start() 函数必须返回 0。如果启动函数遇到问题,则该函数必须返回非零值。此函数失败后,RGM 将尝试在其它群集节点上启动该资源。

要尽量利用 DSDL,svc_start() 函数可以调用 scds_pmf_start() 实用程序以启动进程监视器工具 (PMF) 下的应用程序。此实用程序还使用 PMF 的故障回调操作功能来检测进程故障。有关更多信息,请参见 pmfadm(1M) 手册页中 -a 操作参数的说明。

Stop 方法

RGM 将对群集节点调用资源类型实现的 Stop 回调方法,以停止该应用程序。Stop 方法的回调语义学需要以下因素:

DSDL 实用程序 scds_pmf_stop() 在第一次尝试使用 SIGTERM 软停止应用程序时应当足以用于大多数应用程序。此函数随后将 SIGKILL 传递给进程。此函数假定应用程序是使用 scds_pmf_start() 在 PMF 下启动的。有关此实用程序的详细信息,请参见PMF 函数

假定停止应用程序的应用程序特定函数名为 svc_stop(),它采用以下代码实现了 Stop 方法:

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

前述 svc_stop() 函数的实现与是否包括 scds_pmf_stop() 函数是不相关的。确定是否包括 scds_pmf_stop() 函数取决于应用程序是否通过 Start 方法在 PMF 下启动。

Stop 方法的实现中没有使用 svc_validate() 方法,因为即使系统当前遇到问题,Stop 方法也应当尝试在此节点上停止应用程序。

Monitor_start 方法

RGM 将调用 Monitor_start 方法以启动资源的故障监视器。故障监视器将监视正受该资源管理的应用程序的运行状况。资源类型实现通常将故障监视器作为单独在后台运行的守护进程实现。Monitor_start 回调方法用于使用正确的参数启动此守护进程。

由于监视器守护进程本身很容易失败(例如,该守护进程可能会停止,而使应用程序处于不受监视的状态),因此您应当使用 PMF 启动监视器守护进程。DSDL 实用程序 scds_pmf_start() 内置了对启动故障监视器的支持。此实用程序使用相对于 RT_basedir 的路径名来确定监视器守护进程的资源类型回调方法实现的位置。此实用程序使用由 DSDL 管理的 Monitor_retry_intervalMonitor_retry_count 扩展属性防止无限制地重新启动守护进程。

此实用程序还将为所有回调方法定义的相同命令行语法(即,-R resource -G resource-group -T resource-type)强加到监视器守护进程上,尽管监视器守护进程决不会被 RGM 直接调用。最后,此实用程序还允许监视器守护进程实现自身启用 scds_initialize() 实用程序来设置自己的环境。主要用于设计监视器守护进程本身方面。

Monitor_stop 方法

RGM 将调用 Monitor_stop 方法来停止通过使用 Monitor_start 方法启动的故障监视器守护进程。处理此回调方法失败与处理 Stop 方法失败的方式刚好相同。因此,Monitor_stop 方法必须是幂等的并且要像 Stop 方法一样强健。

如果您使用 scds_pmf_start() 公用程序启动故障监视器守护进程序,则请使用 scds_pmf_stop() 公用程序停止该守护进程。

Monitor_check 方法

RGM 将在指定资源的节点上运行针对资源的 Monitor_check 回调方法以确定群集节点是否能够控制资源。换言之,RGM 运行此方法来确定正受资源管理的应用程序是否能够在节点上成功运行。

通常,这种情况涉及确保应用程序所需的所有系统资源在群集节点上确实可用。正如Validate 方法中所讨论的那样,实现的函数 svc_validate() 至少要确定该情况。

根据资源类型实现正在管理的特定应用程序,可以写入 Monitor_check 方法以执行其他任务。必须实现 Monitor_check 方法,这样此方法才能与同时运行的其他方法不发生冲突。如果使用的是 DSDL,则 Monitor_check 方法应该调用 svc_validate() 函数,该函数用于实现应用程序特定的资源属性验证。

Update 方法

RGM 将调用资源类型实现的 Update 方法将群集管理员所做的所有更改应用到活动资源的配置中。仅对资源当前处于联机状态的节点(如果有)调用 Update 方法。

必须保证资源类型实现可接受刚对资源配置所做的更改,因为 RGM 在运行 Update 方法之前先运行 Validate 方法。Validate 方法是在更改资源或资源组属性之前调用的,Validate 方法可以禁止提议更改。Update 方法在应用更改内容之后调用,以便有机会向活动(联机)资源通知这些新设置。

确定需要能够动态更新的属性时必须谨慎,并在 RTR 文件中用 TUNABLE = ANYTIME 标记那些属性。通常,您可以指定故障监视器守护进程使用的资源类型实现的哪些属性需要能够动态更新。但是,Update 方法的实现至少要重新启动监视器守护进程。

可以使用的可能属性包括:

这些属性的影响范围包括:故障监视器守护进程检查服务的运行状况的方法、守护进程执行检查的频率、守护进程用于跟踪错误的历史时间间隔,以及由 PMF 设置的重新启动阈值。为了实现这些属性的更新,DSDL 中提供了实用程序 scds_pmf_restart()

如果需要能够动态更新资源属性,但修改该属性可能会影响正在运行的应用程序,那么,您必须执行正确操作。必须确保对该属性的更新能够正确地应用到所有正在运行的应用程序实例。目前,您不能使用 DSDL 以这种方式动态更新资源属性。不能通过命令行将修改后的属性传递给 Update(而对于 Validate 则可以)。

InitFiniBoot 方法的说明

这些方法都是一次性操作方法,是由资源管理 API 规范定义的。DSDL 中附带的实现样例并未说明这些方法的用法。不过,DSDL 中的所有工具也可用于这些方法,您应当会需要这些方法。通常,对于资源类型实现来说,InitBoot 方法完全相同,都可以实现一次性操作。通常,Fini 方法将执行撤销操作,用于撤销 InitBoot 方法的操作。

设计故障监视器守护进程

使用 DSDL 的资源类型实现通常都有一个执行以下职责的故障监视器守护进程:

设计 DSDL 实用程序的目的在于使故障监视器守护进程的主循环可由本节末尾的伪代码表示。

实现使用 DSDL 的故障监视器时,请牢记以下因素:

在大多数情况下,您可以在独立的实用程序中(例如,svc_probe())实现应用程序特定的运行状况检查操作。您可以将其集成到以下通用主循环中。

for (;;) {
   /* sleep for a duration of thorough_probe_interval between
   *  successive probes.
   */
   (void) scds_fm_sleep(scds_handle,
   scds_get_rs_thorough_probe_interval(scds_handle));
   /* Now probe all ipaddress we use. Loop over
   * 1. All net resources we use.
   * 2. All ipaddresses in a given resource.
   * For each of the ipaddress that is probed,
   * compute the failure history. 
   */
   probe_result = 0;
   /* Iterate through the all resources to get each
   * IP address to use for calling svc_probe()
   */
   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 obtaint the port value from the
   * first entry in the array of ports.
   */
   ht1 = gethrtime();
   /* Latch probe start time */
   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 */