Sun Microsystems Sun Cluster Data Services Developer Guide
Below you will find brief information for Sun Cluster Data Services. This guide provides information on developing data services for Sun Cluster, allowing applications to be managed as highly available and scalable resources. It covers resource management APIs, resource types, callback methods, and implementation examples. Key areas include analyzing application suitability, setting up the development environment, and implementing fault monitors.
Advertisement
Advertisement
Sun Cluster 数据服务开发者指南
(适用于 Solaris OS)
Sun Microsystems, Inc.
4150 Network Circle
Santa Clara, CA 95054
U.S.A.
文件号码 819–2070–10
2005 年 8 月,修订版 A
版权所有 2005 Sun Microsystems, Inc.
4150 Network Circle, Santa Clara, CA 95054 U.S.A.
本产品或文档受版权保护,其使用、复制、发行和反编译均受许可证限制。未经 Sun 及其许可方(如果有)的事先书面许可,不得以任何形式、任何手
段复制本产品或文档的任何部分。第三方软件,包括字体技术,均已从 Sun 供应商处获得版权和使用许可。
本产品的某些部分可能是从 Berkeley BSD 系统衍生出来的,并获得了加利福尼亚大学的许可。UNIX 是 X/Open Company, Ltd. 在美国和其他国家/地
区独家许可的注册商标。
Sun、Sun Microsystems、Sun 徽标、docs.sun.com、AnswerBook、AnswerBook2、 Java、NetBeans、SunPlex 和 Solaris 是 Sun Microsystems, Inc.
在美国和其他国家/地区的商标或注册商标。所有 SPARC 商标的使用均已获得许可,它们是 SPARC International, Inc. 在美国和其他国家/地区的商标或
注册商标。标有 SPARC 商标的产品均基于由 Sun Microsystems, Inc. 开发的体系结构。 Adobe 是 Adobe Systems, Incorporated 的注册商标。
PostScript 徽标是 Adobe Systems, Incorporated 的商标或注册商标,可能在某项司法系统管辖区注册。ORACLE 是 Oracle Corporation 的注册商标。
OPEN LOOK 和 Sun™ 图形用户界面是 Sun Microsystems, Inc. 为其用户和许可证持有者开发的。Sun 感谢 Xerox 在研究和开发可视或图形用户界面的
概念方面为计算机行业所做的开拓性贡献。Sun 已从 Xerox 获得了对 Xerox 图形用户界面的非独占性许可证,该许可证还适用于实现 OPEN LOOK GUI
和在其他方面遵守 Sun 书面许可协议的 Sun 许可证持有者。
美国政府权利 - 商业用途。政府用户应遵循 Sun Microsystems, Inc. 的标准许可协议,以及 FAR(Federal Acquisition Regulations,即“联邦政府采购
法规”)的适用条款及其补充条款。
本文档按“原样”提供,对于所有明示或默示的条件、陈述和担保,包括对适销性、适用性和非侵权性的默示保证,均不承担任何责任,除非此免责声明
的适用范围在法律上无效。
050817@12762
目录
前言
1
2
13
资源管理概述
19
Sun Cluster 应用程序环境
19
资源组管理器模型
20
资源类型
21
资源
21
资源组
22
资源组管理器
22
回调方法
23
编程接口
23
Resource Management API(资源管理 API)
数据服务开发库
24
SunPlex Agent Builder
24
资源组管理器管理接口
25
SunPlex Manager
25
scsetup 实用程序
25
管理命令
26
24
30
3
32
34
37
39
39
39
40
40
40
Init、Fini 和 Boot 方法
监视资源
42
43
44
44
44
45
46
47
48
48
3
49
51
51
RMAPI Shell 命令
C 函数
51
53
RMAPI 回调方法
55
57
58
58
59
61
61
56
56
4
48
62
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
5
Update 方法的工作方式
6
7
8
98
104
设计资源类型
105
资源类型注册文件
105
Validate 方法
106
Start 方法
107
Stop 方法
108
Monitor_start 方法
109
Monitor_stop 方法
110
Monitor_check 方法
110
Update 方法
110
Init、Fini 和 Boot 方法的说明
设计故障监视器守护进程
111
DSDL 资源类型实现样例
X Font Server
111
115
115
X Font Server 配置文件
TCP 端口号
116
116
SUNW.xfnts RTR 文件
116
117
scds_initialize() 函数
xfnts_start 方法
117
118
启动 X Font Server 之前验证服务
使用 svc_start() 启动服务
从 svc_start() 返回
xfnts_stop 方法
120
122
xfnts_monitor_start 方法
xfnts_monitor_stop 方法
6
118
118
123
124
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
xfnts_monitor_check 方法
SUNW.xfnts 故障监视器
125
xfonts_probe 主循环
svc_probe() 函数
126
127
130
xfnts_validate 方法
130
xfnts_update 方法
9
125
133
SunPlex Agent Builder
Agent Builder 概述
135
135
Agent Builder 使用前须知
使用 Agent Builder
分析应用程序
136
136
137
安装和配置 Agent Builder
Agent Builder 屏幕
138
启动 Agent Builder
138
浏览 Agent Builder
137
139
142
144
使用 Agent Builder 基于 Korn Shell 的 $hostnames 变量
使用属性变量
重复使用使用 Agent Builder 创建的代码
▼ 克隆现有的资源类型的方法
Agent Builder 创建的目录结构
Agent Builder 的输出
149
149
▼ 使用 Agent Builder 的命令行版本的方法
150
151
152
152
Sun Agent Builder 创建的实用程序脚本和手册页
Agent Builder 创建的支持文件
Agent Builder 创建的软件包目录
rtconfig 文件
146
147
153
154
154
154
Agent Builder 的 Cluster Agent 模块
155
▼ 安装和设置 Cluster Agent 模块的方法
▼ 启动 Cluster Agent 模块的方法
使用 Cluster Agent 模块
155
156
158
Cluster Agent 模块和 Agent Builder 之间的区别
159
7
10
161
161
162
162
162
163
163
164
使用 Agent Builder 创建使用 GDS 的服务
创建和配置基于 GDS 的脚本
167
167
▼ 如何启动 Agent Builder 和创建脚本
▼ 如何配置脚本
167
170
Agent Builder 的输出
172
使用 Sun Cluster 管理命令创建使用 GDS 的服务
173
▼ 如何使用 Sun Cluster 管理命令来创建使用 GDS 且具有高可用性的服务
▼ 如何使用 Sun Cluster 管理命令来创建使用 GDS 的可伸缩服务
Agent Builder 的命令行界面
174
▼ 如何使用命令行版本的 Agent Builder 创建使用 GDS 的服务
11
DSDL API 函数
通用函数
179
179
179
180
180
主机名函数
181
181
181
181
使用 TCP 连接进行故障监视
PMF 函数
8
183
183
182
182
12
180
180
174
185
185
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
175
173
CRNP 的工作原理
CRNP 语义学
186
186
188
189
189
189
191
192
192
193
193
194
196
198
198
199
200
206
208
211
标准属性
205
213
220
B
204
213
195
195
A
189
190
233
240
243
243
Start 方法代码列表
Stop 方法代码列表
246
249
9
gettime 实用程序代码列表
251
PROBE 程序代码列表
252
Monitor_start 方法代码列表
257
Monitor_stop 方法代码列表
259
Monitor_check 方法代码列表
260
Validate 方法代码列表
262
Update 方法代码列表
266
C
DSDL 样例资源类型代码列表
269
xfnts.c 文件列表
269
xfnts_monitor_check 方法代码列表
281
xfnts_monitor_start 方法代码列表
282
xfnts_monitor_stop 方法代码列表
283
xfnts_probe 方法代码列表
284
xfnts_start 方法代码列表
287
xfnts_stop 方法代码列表
288
xfnts_update 方法代码列表
289
xfnts_validate 方法代码列表
291
D
E
F
10
CRNP 的文档类型定义
301
SC_CALLBACK_REG XML DTD
NVPAIR XML DTD
303
SC_REPLY XML DTD
304
293
299
301
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
SC_EVENT XML DTD
G
305
CrnpClient.java 应用程序
CrnpClient.java 的内容
索引
307
307
329
11
12
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
前言
《Sun Cluster 数据服务开发者指南(适用于 Solaris OS)》包含有关使用资源管理 API
在基于 SPARC® 和 x86 的系统上开发 Sun™ Cluster 数据服务的信息。
注 – 在本文档中,术语“x86”指 Intel 32 位微处理器芯片系列和 AMD 制造的兼容微处理
器芯片。
相关文档
有关相关 Sun Cluster 主题的信息,可从下表列出的文档中获得。Sun Cluster 文档可在
http://docs.sun.com 获得。
14
主题
文档
概述
《Sun Cluster 概述(适用于 Solaris OS)》
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
主题
文档
概念
《Sun Cluster 概念指南(适用于 Solaris OS)》
《Sun Cluster 3.0-3.1 Hardware Administration Manual for
Solaris OS》
单个硬件管理指南
软件安装
《Sun Cluster 软件安装指南(适用于 Solaris OS)》
《Sun Cluster Data Services Planning and Administration
Guide for Solaris OS》
单个数据服务指南
《Sun Cluster 数据服务开发者指南(适用于 Solaris OS)》
系统管理
《Sun Cluster 系统管理指南(适用于 Solaris OS)》
错误消息
《Sun Cluster Error Messages Guide for Solaris OS》
《Sun Cluster Reference Manual for Solaris OS》
有关 Sun Cluster 文档的完整列表,请参见适用于您的 Sun Cluster 软件版本的发行说
明,网址为:http://docs.sun.com。
功能
prtconf -v
psrinfo -v
15
命令
功能
showrev -p
SPARC:prtdiag -v
/usr/cluster/bin/scinstall -pv
显示 Sun Cluster 发行版本和软件包版本信息
还请提供 /var/adm/messages 文件的内容。
URL
说明
文档
http://www.sun.com/documentation/
支持和培训
http://www.sun.com/supportraining/
含义
示例
AaBbCc123
编辑 .login 文件。
使用 ls -a 列出所有文件。
machine_name% you have
mail.
AaBbCc123
16
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
machine_name% su
Password:
(续)
字体*
含义
示例
AaBbCc123
《书名》
书名
命令示例中的 shell 提示符
下表显示了
C shell、Bourne shell 和 Korn shell 的缺省系统提示符和超级用户提示符。
表 P–2 Shell 提示符
Shell
提示符
C shell 提示符
machine_name%
C shell 超级用户提示符
machine_name#
Bourne shell 和 Korn shell 提示符
$
Bourne shell 和 Korn shell 超级用户提示符
#
17
18
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
第1章
资源管理概述
本书提供了为 Oracle®、Sun Java™ System Web Server(以前的 Sun ONE Web
Server)或 DNS 等软件应用程序创建资源类型的指导信息。因此本书面向的是资源类型
的开发者。
本章概述了开发数据服务需要了解的概念。本章包括以下主题:
■
■
■
■
■
■
■
资源管理 API (RMAPI) 是一组低级 API 命令和函数,可用于编写回调方法。这些
API 是在 libscha.so 库中实现的。
■
■
图 1–1
Sun Cluster 应用环境的编程体系结构
20
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
21
■
■
22
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
■
■
■
Monitor_start 和 Monitor_stop 用于启动或停止资源的监视器。
Monitor_check 用于在将资源组移至节点之前评估该节点的可靠性。
23
libscha.so。低级资源管理 API。
■
■
hatimerun。在超时的情况下运行程序的工具。请参见 hatimerun(1M) 手册页。
SunPlex Agent Builder
Agent Builder 是自动创建数据服务的工具。您输入有关目标应用程序和要创建的数据
服务的基本信息。Agent Builder 将生成一个数据服务,其中包括源代码和可执行代码
(C 或 Korn shell)、自定义的 RTR 文件和 Solaris 软件包。
对于多数应用程序,都可以使用 Agent Builder 生成完整的数据服务,且只需您进行很
少的手动更改。具有较复杂要求(例如,对附加属性添加验证检查)的应用程序可能需
要执行 Agent Builder 无法完成的操作。但是,即使在这些情况下,您也可以使用
Agent Builder 生成代码的主体,然后再手动编写剩余代码。至少,您可以使用 Agent
Builder 生成 Solaris 软件包。
24
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
SunPlex Manager
SunPlex Manager 是基于 Web 的工具,您可以通过它执行以下任务:
■
■
■
■
有关如何安装 SunPlex Manager 以及如何使用 SunPlex Manager 安装群集软件的说
明,请参见《Sun Cluster 软件安装指南(适用于 Solaris OS)》。SunPlex Manager 为
多数唯一的管理任务提供了联机帮助。
scsetup 实用程序
大多数 Sun Cluster 管理任务都可与 scsetup(1M) 实用程序交互执行。
可以使用 scsetup 实用程序管理以下 Sun Cluster 元素:
■
■
■
■
■
■
■
■
25
■
■
删除资源组
清除资源的 Stop_failed 错误标志
26
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
第2章
■
■
■
■
■
■
■
■
■
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
资源管理 API (RMAPI) ,一组低层次函数(在 libscha.so 库中)
■
数据服务开发库 (DSDL),一组较高层次函数(在 libdsdev.so 库中)可以封装
RMAPI 的功能并提供一些附加功能
■
■
口。因此,如果在 Agent Builder 中指定 Korn shell (ksh) 输出,生成的源代码将调用
RMAPI,因为没有 DSDL ksh 命令。
29
对于 Sun Cluster 3.0 和早期版本,请使用兼容模式。
对于 Sun Cluster 3.1 和更高版本,请使用标准模式。
Distribution 软件组。
■
▼
安装 Sun Cluster 开发软件包 (SUNWscdev) 以及设置正确的编译器和链接程序选
项。
将数据服务传送到群集。
步骤
1. 成为超级用户或作为等效角色。
2. 将目录更改为所需的 CD-ROM 目录。
# cd cd-rom-directory
3. 在当前目录下安装 SUNWscdev 软件包。
30
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
■
针对区环境中的 Solaris 10 操作系统,在全局区域中以全局管理员身份键入以下
命令:
# pkgadd -G -d . SUNWscdev
针对非区环境中的 Solaris 操作系统的其他任何版本或 Solaris 10 操作系统,键
入以下命令:
# pkgadd -d . SUNWscdev
4. 在 makefile 中,指定用于标识数据服务代码的库文件和其他文件的编译器和链接
程序选项。
指定 -I 选项用于标识 Sun Cluster 头文件、-L 选项用于指定开发系统上的编译时库
搜索路径、-R 选项用于指定群集中运行时链接程序的库搜索路径。
# Makefile for sample data service
...
-I /usr/cluster/include
-L /usr/cluster/lib
-R /usr/cluster/lib
...
所有群集节点上。请注意,Agent Builder 将自动创建此软件包。
31
资源类型声明的语法如下所示:
property-name = value;
以下是 RTR 文件中用于样例 (smpl) 数据服务的资源类型声明:
# Sun Cluster Data Services Builder template version 1.0
# Registration information and resources for smpl
#
#NOTE: Keywords are case insensitive, i.e., you can use
#any capitalization style you prefer.
#
Resource_type = "smpl";
Vendor_id = SUNW;
RT_description = "Sample Service on Sun Cluster";
RT_version ="1.0";
API_version = 2;
Failover = TRUE;
32
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
Init_nodes = RG_PRIMARIES;
RT_basedir=/opt/SUNWsmpl/bin;
Start
Stop
=
=
smpl_svc_start;
smpl_svc_stop;
Validate
Update
=
=
smpl_validate;
smpl_update;
Monitor_start
Monitor_stop
Monitor_check
=
=
=
smpl_monitor_start;
smpl_monitor_stop;
smpl_monitor_check;
RT_description
简要地介绍资源类型。
RT_version
用于标识数据服务样例的版本。
API_version
用于标识 API 的版本。例如,API_version = 2 表明数据服务可以安装在从 Sun
Cluster 3.0 开始的 Sun Cluster 的所有版本上;API_version = 5 表明数据服务可
以安装在从 Sun Cluster 3.1 9/04 开始的 Sun Cluster 的所有版本上。但是,
API_version = 5 还表明数据服务无法安装在 Sun Cluster 3.1 9/04 发行之前的
Sun Cluster 的所有版本上。有关该属性的详细信息,请参见第 213 页中的 “资源类
型属性”中有关 API_version 条目下的内容。
第 2 章 • 开发数据服务
33
Failover = TRUE
表明数据服务无法在可同时在多个节点上联机的资源组中运行。换句话说,该声明指
定了一个故障转移数据服务。有关该属性的详细信息,请参见第 213 页中的 “资源
类型属性”中有关 Failover 条目下的内容。
Start、Stop 和 Validate
提供由 RGM 调用的各个回调方法程序的路径。这些路径是 RT_basedir 所指定的
目录的相对路径。
其余的资源类型声明提供了配置信息。
Init_nodes = RG_PRIMARIES
指定 RGM 仅在可以主控数据服务的节点上调用 Init、Boot、Fini 和 Validate
方法。RG_PRIMARIES 所指定的节点是安装有数据服务的所有节点的一个子集。将
值设置为 RT_INSTALLED_NODES 可指定 RGM 在安装有数据服务的所有节点上调用
这些方法。
RT_basedir
指向 /opt/SUNWsample/bin,作为指向完整相对路径(例如回调方法路径)的目
录路径。
Start、Stop 和 Validate
提供指向由 RGM 调用的各个回调方法程序的路径。这些路径是 RT_basedir 所指
定的目录的相对路径。
声明资源属性
与资源类型属性一样,资源属性也在 RTR 文件中声明。按照惯例,在 RTR 文件中资源
属性声明位于资源类型声明之后。资源声明的语法是一组用花括号括起来的属性值对:
{
attribute = value;
attribute = value;
.
.
.
attribute = value;
}
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
#
#
#
#
#
{
entries after the resource type declarations. The property
name declaration must be the first attribute after the open
curly bracket of a resource property entry.
Set minimum and default for method timeouts.
PROPERTY = Start_timeout;
MIN=60;
DEFAULT=300;
}
{
PROPERTY = Stop_timeout;
MIN=60;
DEFAULT=300;
}
{
PROPERTY = Validate_timeout;
MIN=60;
DEFAULT=300;
}
{
PROPERTY = Update_timeout;
MIN=60;
DEFAULT=300;
}
{
PROPERTY = Monitor_Start_timeout;
MIN=60;
DEFAULT=300;
}
{
PROPERTY = Monitor_Stop_timeout;
MIN=60;
DEFAULT=300;
{
PROPERTY = Monitor_Check_timeout;
MIN=60;
DEFAULT=300;
}
属性名称 (PROPERTY = value) 必须是每个资源属性声明的第一个属性。您可以在由
RTR 文件中属性的属性定义的限制内配置资源属性。例如,样例中每个方法超时的缺省
值都是 300 秒。群集管理员可以更改此值。但是,由 MIN 属性指定的最小允许值是 60
秒。第 240 页中的 “资源特性属性”中包含资源属性的属性列表。
下一组资源属性用于定义在数据服务中有特定用法的属性。
{
PROPERTY = Failover_mode;
DEFAULT=SOFT;
TUNABLE = ANYTIME;
}
{
PROPERTY = Thorough_Probe_Interval;
第 2 章 • 开发数据服务
35
MIN=1;
MAX=3600;
DEFAULT=60;
TUNABLE = ANYTIME;
}
# The number of retries to be done within a certain period before concluding
# that the application cannot be successfully started on this node.
{
PROPERTY = Retry_count;
MAX=10;
DEFAULT=2;
TUNABLE = ANYTIME;
}
#
#
#
#
{
Set Retry_interval as a multiple of 60 since it is converted from seconds
to minutes, rounding up. For example, a value of 50 (seconds)
is converted to 1 minute. Use this property to time the number of
retries (Retry_count).
PROPERTY = Retry_interval;
MAX=3600;
DEFAULT=300;
TUNABLE = ANYTIME;
}
{
PROPERTY = Network_resources_used;
TUNABLE = WHEN_DISABLED;
DEFAULT = "";
}
{
PROPERTY = Scalable;
DEFAULT = FALSE;
TUNABLE = AT_CREATION;
}
{
PROPERTY = Load_balancing_policy;
DEFAULT = LB_WEIGHTED;
TUNABLE = AT_CREATION;
}
{
PROPERTY = Load_balancing_weights;
DEFAULT = "";
TUNABLE = ANYTIME;
}
{
PROPERTY = Port_list;
TUNABLE = ANYTIME;
DEFAULT = ;
}
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
对于这些属性中的大多数,您可以接受由 Agent Builder 生成的默认值,除非您有理由
更改它们。以下是有关这些属性的信息。有关附加信息,请参见第 220 页中的 “资源属
性”或 r_properties(5) 手册页。
Failover_mode
表明在 Start 或 Stop 方法失败的情况下,RGM 是应重新查找资源组还是应异常中
止节点。
Thorough_probe_interval、Retry_count 和 Retry_interval
用于故障监视器。Tunable 等于 ANYTIME,因此如果故障监视器不能发挥最佳工作
效果,群集管理员可以对它们进行调整。
Network_resources_used
数据服务使用的逻辑主机名或共享地址资源的列表。Agent Builder 将声明该属性,
以便群集管理员对数据服务进行配置时,可以指定资源列表(如果有)。
Scalable
设置为 FALSE 以表明该资源没有使用群集网络(共享地址)设备。如果将该属性设
置为 FALSE,资源类型属性 Failover 必须设置为 TRUE 以表明故障转移服务。有
关如何使用该属性的附加信息,请参见第 31 页中的 “将数据服务传送到群集”和第
39 页中的 “实现回调方法”。
Load_balancing_policy 和 Load_balancing_weights
自动声明这些属性。但是,这些属性在故障转移资源类型中不起作用。
Port_list
标识服务器侦听的端口的列表。Agent Builder 将声明该属性,以便群集管理员对数
据服务进行配置时,可以指定端口列表。
声明扩展属性
扩展属性位于样例 RTR 文件的结尾处。
# Extension Properties
#
#
#
#
#
{
The cluster administrator must set the value of this property to point to the
directory that contains the configuration files used by the application.
For this application, smpl, specify the path of the configuration file on
PXFS (typically named.conf).
PROPERTY = Confdir_list;
EXTENSION;
STRINGARRAY;
TUNABLE = AT_CREATION;
DESCRIPTION = "The Configuration Directory Path(s)";
}
# The following two properties control restart of the fault monitor.
{
PROPERTY = Monitor_retry_count;
EXTENSION;
第 2 章 • 开发数据服务
37
INT;
DEFAULT = 4;
TUNABLE = ANYTIME;
DESCRIPTION = "Number of PMF restarts allowed for fault monitor.";
}
{
PROPERTY = Monitor_retry_interval;
EXTENSION;
INT;
DEFAULT = 2;
TUNABLE = ANYTIME;
DESCRIPTION = "Time window (minutes) for fault monitor restarts.";
}
# Time out value in seconds for the probe.
{
PROPERTY = Probe_timeout;
EXTENSION;
INT;
DEFAULT = 120;
TUNABLE = ANYTIME;
DESCRIPTION = "Time out value for the probe (seconds)";
}
#
#
#
#
{
Child process monitoring level for PMF (-C option of pmfadm).
Default of -1 means to not use the -C option of pmfadm.
A value of 0 or greater indicates the desired level of child-process.
monitoring.
PROPERTY = Child_mon_level;
EXTENSION;
INT;
DEFAULT = -1;
TUNABLE = ANYTIME;
DESCRIPTION = “Child monitoring level for PMF";
}
# User added code -- BEGIN VVVVVVVVVVVV
# User added code -- END
^^^^^^^^^^^^
Agent Builder 将创建以下扩展属性,这些属性对于大多数数据服务来说都有用。
Confdir_list
指定应用程序配置目录的路径,这对于很多应用程序是有用的信息。当群集管理员对
数据服务进行配置时,可以提供该目录的位置。
Monitor_retry_count、Monitor_retry_interval 和 Probe_timeout
控制故障监视器本身的重新启动操作,而非服务器守护进程。
Child_mon_level
设置 PMF 要执行的监视级别。有关更多信息,请参见 pmfadm(1M) 手册页。
您可以在由 User added code 注释分界的区域内创建其他扩展属性。
38
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
访问资源和资源组属性信息
通常,回调方法需要访问资源属性。RMAPI 同时提供了可在回调方法中使用的 shell 命
令和 C 函数,以访问系统定义的资源属性和扩展资源属性。请参见
scha_resource_get(1HA) 和 scha_resource_get(3HA) 手册页。
DSDL 提供一组用于访问系统定义的属性的 C 函数(每种属性一个函数)和一个用于访
问扩展属性的函数。请参见 scds_property_functions(3HA) 和
scds_get_ext_property(3HA) 手册页。
您无法使用属性机制存储数据服务的动态状态信息,因为没有 API 函数可用于设置
Status 和 Status_msg 以外的资源属性。您应该将动态状态信息存储在全局文件中。
注 – 群集管理员可以使用 scrgadm 命令或通过图形管理命令或界面来设置特定资源属
性。但是,请勿从任何回调方法中调用 scrgadm,这是因为在群集重新配置期间(即
RGM 调用方法时)scrgadm 将失败。
等性。
39
40
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
41
100248。这些编号分别专用于 Sun Cluster 守护进程 rgmd_receptionist、fed 和
pmfd。如果您安装的 RPC 服务使用上述程序号之一,请更改该 RPC 服务的程序号。
与使用 Prenet_start 和 Postnet_stop 方法相比,决定使用 Start 和 Stop 方法
时,或者决定同时使用这两套方案,必须考虑服务器和客户机的要求和行为。
Init、Fini 和 Boot 方法
Init、Fini 和 Boot 这三种可选方法可启用 RGM 对资源执行初始化和终止代码。
当资源受管理后出现以下一种情况时,RGM 将运行 Init 方法对该资源执行一次性初
始化:
■
■
42
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
要获得使用 RMAPI 实现的故障监视器的示例,请参见第 86 页中的 “定义故障监视器
”。要获得使用 DSDL 实现的故障监视器的示例,请参见第 125 页中的 “SUNW.xfnts
故障监视器”。有关在 Sun 提供的数据服务中内置的故障监视器的信息,请参见《Sun
Cluster Data Services Planning and Administration Guide for Solaris OS》。
43
提供进程管理
RMAPI 和 DSDL 提供了进程管理工具来实现资源监视器及资源控制回调。RMAPI 定义
了以下工具:
进程监视工具 (PMF):pmfadm 和 rpc.pmfd
提供了监视进程及其子进程以及在失败后重新启动进程的方法。该工具由 pmfadm 命
令(用于启动和控制受监视的进程)和 rpc.pmfd 守护进程组成。
DSDL 提供一组用于实现 PMF 功能的函数(以 scds_pmf_ 名称开头)。有关
DSDL PMF 功能的概述和各个函数的列表,请参见第 182 页中的 “PMF 函数”。
有关该命令和守护进程的详细信息,请参见 pmfadm(1M) 和 rpc.pmfd(1M) 手册
页。
halockrun
一种用于在保留文件锁定时运行子程序的程序。此命令在 shell 脚本中使用很方便。
有关此命令的详细信息,请参见 halockrun(1M) 手册页。
hatimerun
用于在超时控制下运行子程序的程序。此命令在 shell 脚本中使用很方便。
DSDL 提供了用于实现 hatimerun 功能的 scds_hatimerun() 函数。
有关此命令的详细信息,请参见 hatimerun(1M) 手册页。
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
实现故障切换资源
故障转移资源组包含网络地址(例如内置资源类型 LogicalHostname 和
SharedAddress)和故障转移资源(例如用于故障转移数据服务的数据服务应用程序
资源)。当数据服务进行故障转移或切换时,网络地址资源及其依赖的数据服务资源在
群集节点之间移动。RGM 提供了多个支持故障切换资源实现的属性。
将布尔 Failover 资源类型属性设置为 TRUE,以限制资源在可同时在多个节点上联机
的资源组中进行配置。该属性的默认值为 FALSE,因此您必须在 RTR 文件中将其声明
为 TRUE,以用于故障转移资源。
Scalable 资源属性用于确定资源是否使用群集共享地址工具。对于故障转移资源,请
将 Scalable 设置为 FALSE,这是因为故障转移资源不使用共享地址。
RG_mode 资源组属性允许群集管理员将资源组标识为故障转移或可伸缩。如果
RG_mode 的值为 FAILOVER,则 RGM 将资源组的 Maximum_primaries 属性设置为
1,并将该资源组限制为由单个节点主控。RGM 不允许在其 RG_mode 的值为
SCALABLE 的资源组中创建其 Failover 属性的值为 TRUE 的资源。
Implicit_network_dependencies 资源组属性用于指定 RGM 应该在资源组内的
所有网络地址资源(LogicalHostname 和 SharedAddress)上强制执行非网络地址
资源的隐含强依赖性。其结果是,在资源组中的网络地址配置为启用之前,将不会调用
该组中的非网络地址(数据服务)资源的 Start 方法。
Implicit_network_dependencies 属性的默认值为 TRUE。
45
实现可伸缩资源
可伸缩资源可以同时在多个节点上联机。可伸缩资源包括数据服务,例如,Sun Cluster
HA for Sun Java System Web Server(以前称为 Sun Cluster HA for Sun ONE Web
Server)和 Sun Cluster HA for Apache。
RGM 提供了许多支持可伸缩资源实现的属性。
将布尔 Failover 资源类型属性设置为 FALSE,将允许在可同时在多个节点上联机的
资源组中配置资源。
Scalable 资源属性用于确定资源是否使用群集共享地址工具。将该属性设置为
TRUE,这是因为可伸缩服务使用共享地址资源,以将该可伸缩服务的多个实例显示为客
户机的单个服务。
RG_mode 属性使群集管理员可以将资源组标识为故障切换或可伸缩。如果 RG_mode 的
值为 SCALABLE,RGM 将允许 Maximum_primaries 的值大于 1,这意味着该组可以
同时由多个节点主控。RGM 将允许其 Failover 属性的值为 FALSE 的资源在其
RG_mode 的值为 SCALABLE 的资源组中实例化。
群集管理员将创建一个用于包含可伸缩服务资源的可伸缩资源组,以及一个用于包含可
伸缩资源所依赖的共享地址资源的独立故障转移资源组。
群集管理员使用 RG_dependencies 资源组属性来指定在节点上使资源组联机和脱机
的顺序。此顺序对于可伸缩服务很重要,因为可伸缩资源和其依赖的共享地址资源位于
不同的资源组中。可伸缩数据服务需要在启动前将其网络地址(共享地址)资源配置为
启用。因此,群集管理员必须设置包含可伸缩服务的资源组的 RG_dependencies 属
性,以包括含有共享地址资源的资源组。
当您在 RTR 文件中为资源声明 Scalable 属性时,RGM 将自动为该资源创建以下一组
可伸缩属性。
Network_resources_used
标识该资源所使用的共享地址资源。此属性默认为空字符串,因此群集管理员必须在
创建资源时提供可伸缩服务使用的共享地址的实际列表。scsetup 命令和 SunPlex
Manager 为可伸缩服务提供了自动设置所需资源和组的功能。
Load_balancing_policy
为资源指定负载平衡策略。您可以在 RTR 文件中明确设置该策略,或允许使用默认
值 LB_WEIGHTED。无论是以上哪种情况,群集管理员都可以在创建资源时更改该值
(除非您在 RTR 文件中将 Load_balancing_policy 的 Tunable 设置为 NONE 或
FALSE)。以下是您可以使用的合法值:
LB_WEIGHTED
根据在 Load_balancing_weights 属性中设置的权重在不同的节点间分配负
载。
LB_STICKY
可伸缩服务的给定客户机(由客户机的 IP 地址标识)总是发送到同一群集节点。
46
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
Network_resources_used 属性必须为非空,并且包含现有共享地址资源的名
称。包含可伸缩资源的资源组 Nodelist 中的每个节点都必须显示在每个已命名的
共享地址资源的 NetIfList 属性或 AuxNodeList 属性中。
■
包含可伸缩资源的资源组的 RG_dependencies 属性必须包括在可伸缩资源的
Network_resources_used 属性中列出的所有共享地址资源的资源组。
■
47
Port_list=80/tcp6,40/udp6
tcp,用于 TCP IPv4
tcp6(适用于 TCP IPv6)
udp,用于 UDP IPv4
udp6(适用于 UDP IPv6)
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
49
50
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
第3章
第 51 页中的 “RMAPI 访问方法” – 以 shell 脚本命令和 C 函数的形式
第 55 页中的 “RMAPI 回调方法” – rt_callbacks(1HA) 手册页中进行介绍
51
RMAPI 资源命令
使用这些命令,您可以访问关于资源的信息或设置资源的 Status 和 Status_msg 属
性。
scha_resource_get
访问有关 RGM 控制下的资源或资源类型的信息。此命令提供的信息与
scha_resource_get() C 函数相同。有关详细信息,请参见
scha_resource_get(1HA) 手册页。
scha_resource_setstatus
设置 RGM 控制下的资源的 Status 和 Status_msg 属性。资源的监视器使用此命
令来指明监视器识别出的资源状态。此命令提供与 scha_resource_setstatus()
C 函数相同的功能。scha_resource_setstatus(1HA) 手册页中对此命令进行了
详细介绍。
注 – 虽然对于资源监视器来说 scha_resource_setstatus() 有特定用途,但是
资源类型命令
scha_resourcetype_get
访问有关向 RGM 注册的资源类型的信息。此命令提供与
scha_resourcetype_get() C 函数相同的功
能。scha_resourcetype_get(1HA) 手册页中对此命令进行了详细介绍。
资源组命令
您可以使用这些命令访问关于资源组的信息或重新启动资源组。
scha_resourcegroup_get
访问关于 RGM 控制下的资源组的信息。此命令提供与
scha_resourcetype_get() C 函数相同的功
能。scha_resourcegroup_get(1HA) 手册页中对此命令进行了详细介绍。
scha_control
请求重新启动 RGM 控制下的资源组或将其重定位到其他节点。此命令提供与
scha_control() C 函数相同的功能。scha_control(1HA) 手册页中对此命令进
行了详细介绍。
群集命令
scha_cluster_get
访问关于群集的信息,例如群集名称、节点名称、ID、状态和资源组。此命令提供的
信息与 scha_cluster_get() C 函数相同。scha_cluster_get(1HA) 手册页中
对此命令进行了详细介绍。
52
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
资源函数
这些函数用于访问有关 RGM 所管理的资源的信息,或指明监视器识别出的资源状态。
scha_resource_open()、scha_resource_get() 和 scha_resource_close()
这些函数用于访问关于由 RGM 管理的资源的信息。scha_resource_open() 函数
将对资源的访问进行初始化,并为 scha_resource_get()(该函数用于访问资源
信息)返回句柄。scha_resource_close() 函数将使该句柄无效,并释放为
scha_resource_get() 返回值分配的内存。
当 scha_resource_open() 返回资源的句柄之后,可以通过群集重新配置或者管
理操作更改资源。因此,scha_resource_get() 通过该句柄获取的信息就可能不
准确。在对资源进行群集重新配置或管理操作的情况下,RGM 将把
scha_err_seqid 错误代码返回给 scha_resource_get(),以指明关于资源的
信息可能已更改。此错误消息不是致命的。函数将成功返回。您可以选择忽略此消息
并接受返回的信息,也可以关闭当前句柄并打开新句柄以访问关于资源的信息。
有一个手册页介绍了这三个函数。您可以通过
scha_resource_open(3HA)、scha_resource_get(3HA) 或
scha_resource_close(3HA) 中的任何一个函数访问此手册页。
scha_resource_setstatus()
设置 RGM 控制下的资源的 Status 和 Status_msg 属性。资源的监视器使用此函
数指示该资源的状态。
注 – 虽然对于资源监视器来说 scha_resource_setstatus() 有特定用途,但是
53
scha_resourcetype_open()、scha_resourcetype_get() 和
scha_resourcetype_close()
scha_resourcetype_open() 函数将对资源的访问进行初始化,并为
scha_resourcetype_get()(该函数用于访问资源类型信息)返回句柄。
scha_resourcetype_close() 函数将使句柄无效,并释放为
scha_resourcetype_get() 返回值分配的内存。
当 scha_resourcetype_open() 返回资源类型的句柄之后,可以通过群集重新配
置或管理操作更改资源类型。因此,scha_resourcetype_get() 通过该句柄获取
的信息可能不准确。在对资源类型进行群集重新配置或管理操作的情况下,RGM 将
把 scha_err_seqid 错误代码返回给 scha_resourcetype_get(),以指明关于
资源类型的信息可能已更改。此错误消息不是致命的。函数将成功返回。您可以选择
忽略此消息并接受返回的信息,也可以关闭当前句柄并打开新句柄以访问关于资源类
型的信息。
有一个手册页介绍了这三个函数。您可以通过任一单个函数
scha_resourcetype_open(3HA)、scha_resourcetype_get(3HA) 或
scha_resourcetype_close(3HA) 访问此手册页。
资源组函数
您可以使用这些函数访问关于资源组的信息或重新启动资源组。
scha_resourcegroup_open()、scha_resourcegroup_get() 和
scha_resourcegroup_close()
这些函数用于访问关于由 RGM 管理的资源组的信息。
scha_resourcegroup_open() 函数用来初始化对资源组的访问并返回
scha_resourcegroup_get () 的句柄,用于访问资源组信息。
scha_resourcegroup_close() 函数将使句柄无效,并释放为
scha_resourcegroup_get() 返回值分配的内存。
当 scha_resourcegroup_open() 返回资源组句柄之后,可以通过群集重新配置
或管理操作更改资源组。因此,scha_resourcegroup_get() 通过该句柄获取的
信息可能不准确。在对资源组进行群集重新配置或管理操作的情况下,RGM 将把
scha_err_seqid 错误代码返回给 scha_resourcegroup_get(),以指明关于
资源组的信息可能已更改。此错误消息不是致命的。函数将成功返回。您可以选择忽
略此消息并接受返回的信息,也可以关闭当前句柄并打开新句柄以访问关于资源组的
信息。
有一个手册页介绍了这三个函数。您可以通过任一单个函数
scha_resourcegroup_open(3HA)、scha_resourcegroup_get(3HA) 和
scha_resourcegroup_close(3HA) 访问此手册页。
scha_control()
请求重新启动 RGM 控制下的资源组或将其重定位到其他节
点。scha_control(3HA) 手册页中对此函数进行了详细介绍。
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
scha_cluster_open()、scha_cluster_get() 和 scha_cluster_close()
这些函数用于访问关于群集的信息,例如群集名称、节点名称、ID、状态和资源组。
当 scha_cluster_open() 返回群集的句柄之后,可以通过重新配置或管理操作更
改群集。因此,scha_cluster_get() 通过该句柄获取的信息可能不准确。在对群
集进行重新配置或管理操作的情况下,RGM 将把 scha_err_seqid 错误代码返回
给 scha_cluster_get(),以指明关于群集的信息可能已更改。此错误消息不是致
命的。函数将成功返回。您可以选择忽略此消息并接受返回的信息,也可以关闭当前
句柄并打开新句柄以访问关于群集的信息。
有一个手册页介绍了这三个函数。您可以通过任一单个函数
scha_cluster_open(3HA)、scha_cluster_get(3HA) 和
scha_cluster_close(3HA) 访问此手册页。
scha_cluster_getlogfacility()
返回用作群集日志的系统日志工具的编号。将返回值与 syslog() Solaris 函数结合
使用可以将事件和状态消息记录到群集日志
中。scha_cluster_getlogfacility(3HA) 手册页中对此函数进行了详细介绍。
scha_cluster_getnodename()
返回在其上调用该函数的群集节点的名称。scha_cluster_getnodename(3HA)
手册页中对此函数进行了详细介绍。
公用程序函数
此函数将把错误代码转换为错误消息。
scha_strerror()
将某个 scha_ 函数返回的错误代码转换为相应的错误消息。将此函数与 logger 命
令结合使用可以将消息记录到 Solaris 系统日志 (syslog)
中。scha_strerror(3HA) 手册页中对此函数进行了详细介绍。
55
■
■
■
■
可以提供给回调方法的参数
RGM 将运行回调方法,如下所示:
method -R resource-name -T type-name -G group-name
56
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
57
时,将调用 Boot 方法。
注 – Init、Fini 或 Boot 方法的失败将导致 syslog() 函数生成错误消息。但是,
RGM 对资源的管理不受其他方面的影响。
58
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
59
60
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
第4章
■
■
资源类型属性的属性
声明的资源属性(包括标准属性和扩展属性)集
资源属性的属性,例如 default、min、max、arraymin、arraymax 或
tunability
声明的方法集
方法或监视器的实现
61
设置资源类型注册文件的内容
资源类型名称
资源类型名称的三个部分分别是在 RTR 文件中指定为 vendor-id、resource-type 和
rt-version 的属性。scrgadm 命令插入句号和冒号分界符来创建资源类型的名称:
vendor-id.resource-type:rt-version
vendor-id 前缀用来区别不同公司提供的具有相同名称的两个注册文件。为确保 vendor-id
是唯一的,请在创建资源类型时使用公司的股票代号。rt-version 用于区别相同基本资源
类型的多个注册版本(升级)。
可以通过键入以下命令来获取全限定资源类型名称:
# scha_resource_get -O Type -R resource-name -G resource-group-name
使用 Sun Cluster 3.1 以前的版本注册的资源类型名称则继续使用以下语法:
vendor-id.resource-type
指定 #$upgrade 和 #$upgrade_from 指令
要确保您正在修改的资源类型是支持升级的,请在该资源类型的 RTR 文件中加入
#$upgrade 指令。在 #$upgrade 指令后面,为要支持的资源类型的每个早期版本添
加零个或多于零个 #$upgrade_from 指令。
#$upgrade 和 #$upgrade_from 指令必须位于 RTR 文件中的资源类型属性声明和资
源声明部分之间。请参见 rt_reg(4) 手册页。
示例 4–1
RTR 文件中的 #$upgrade_from 指令
#$upgrade_from
#$upgrade_from
#$upgrade_from
62
"1.1"
"1.2"
"1.3"
WHEN_OFFLINE
WHEN_OFFLINE
WHEN_OFFLINE
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
示例 4–1
RTR 文件中的 #$upgrade_from 指令
#$upgrade_from
#$upgrade_from
#$upgrade_from
"2.0"
"2.1"
""
(续)
WHEN_UNMONITORED
ANYTIME
WHEN_UNMANAGED
#$upgrade_from 指令的格式如下所示:
#$upgrade_from version tunability
Update、Stop、Monitor_check 和 Postnet_stop 方法兼容以前的资源
类型版本的启动方法(Prenet_stop 和 Start)
Fini 方法兼容以前版本的 Init 方法
群集管理员必须在升级之前仅停止资源监视器程序。
WHEN_OFFLINE
当新资源类型版本的 Update、Stop、Monitor_check 或 Postnet_stop 方法
满足以下条件时使用:
■
■
兼容以前版本的 Init 方法
不兼容以前资源类型版本的启动方法(Prenet_stop 和 Start)
63
从 Sun Cluster 3.1 开始,RT_version 属性已成为强制属性(在 Sun Cluster 3.0 中为
可选属性)。
Sun Cluster 早期版本中的资源类型名称
Sun Cluster 3.0 中的资源类型名称不包含版本后缀,如下所示:
vendor-id.resource-type
即使在群集管理员将群集软件升级到 Sun Cluster 3.1 或更高版本之后,原来在 Sun
Cluster 3.0 下注册的资源类型仍将继续具有遵循此语法的名称。与此相似,如果 RTR 文
件是在运行 Sun Cluster 3.1 或更高版本的群集上注册的,则该文件中缺少 #$upgrade
指令的资源类型将被指定 Sun Cluster 3.0 格式的名称(不具有版本后缀)。
群集管理员可以在 Sun Cluster 3.0 中使用 #$upgrade 指令或 #$upgrade_from 指令
来注册 RTR 文件。但是,Sun Cluster 3.0 不支持将现有资源升级到新资源类型。
64
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
■
■
■
■
实现资源类型监视器代码
群集管理员可以在 Sun Cluster 3.0 中注册支持升级的资源类型。但是,Sun Cluster 将
记录无版本后缀的资源类型名称。为了可以在 Sun Cluster 3.0 和 Sun Cluster 3.1 中正常
运行,此资源类型的监视器代码必须能够处理这两种命名约定:
vendor-id.resource-type:rt-version
vendor-id.resource-type
第 294 页中的 “资源类型名称的格式”中介绍了资源类型名称的格式。
群集管理员不能以两个不同的名称注册相同的资源类型版本两次。为了使监视器代码可
以确定正确的名称,请在监视器代码中调用以下命令:
scha_resourcetype_get -O RT_VERSION -T VEND.myrt
scha_resourcetype_get -O RT_VERSION -T VEND.myrt:vers
■
65
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
可调性值
封包方案
ANYTIME
更新方法。
ANYTIME
WHEN_UNMONITORED
更新方法。
WHEN_OFFLINE
WHEN_DISABLED
ANYTIME
WHEN_UNMANAGED
67
针对已修改的资源类型提供的文档信息
《Sun Cluster Data Services Planning and Administration Guide for Solaris OS》中
的“Upgrading a Resource Type”为群集管理员提供了可以用于如何升级资源类型的说
明。为使群集管理员可以升级您修改的资源类型,本节中介绍了其他信息来作为以上说
明的补充。
通常,创建新资源类型时,您需要提供具有以下用途的文档信息:
■
■
■
■
■
■
■
示例 4–2 #$upgrade_from 定义群集管理员何时可以进行升级的方式
此示例显示了 #$upgrade_from 指令的可调性是如何影响群集管理员可以将资源升级
到新版本资源类型的条件的。
#$upgrade_from
#$upgrade_from
#$upgrade_from
68
"1.1"
"1.2"
"1.3"
WHEN_OFFLINE
WHEN_OFFLINE
WHEN_OFFLINE
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
示例 4–2 #$upgrade_from 定义群集管理员何时可以进行升级的方式
#$upgrade_from
#$upgrade_from
#$upgrade_from
"2.0"
"2.1"
""
(续)
WHEN_UNMONITORED
ANYTIME
WHEN_UNMANAGED
版本
1.1、1.2 或 1.3
2.0
2.1
任何时候
■
■
■
■
更改诸如 min、max、arraymin、arraymax、default 和 tunability 之类的
资源属性的属性
■
■
69
70
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
第5章
■
通过 RGM 运行的 Start 回调方法,用来在包含 HA-DAS 数据服务的资源组联机时
启动 in.named 守护进程。
■
通过 RGM 运行的 Stop 回调方法,用来在包含 HA-DNS 的资源组脱机时停止
in.named 守护进程。
■
用于通过检验 DNS 服务器是否正在运行来检查服务的可用性的故障监视器。故障监
视器通过用户定义的 PROBE 方法实现,并通过 Monitor_start 和
Monitor_stop 回调方法启动和停止。
■
■
72
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
注 – 资源组、资源和资源类型的属性名称不区分大小写。在指定属性名称时,您可以使
用大小写字母的任意组合。
#
# Copyright (c) 1998-2005 by Sun Microsystems, Inc.
# All rights reserved.
#
# Registration information for Domain Name Service (DNS)
#
#pragma ident
“@(#)SUNW.sample
1.1
00/05/24 SMI”
Resource_type = “sample”;
Vendor_id = SUNW;
RT_description = “Domain Name Service on Sun Cluster”;
RT_version =”1.0”;
API_version = 2;
Failover = TRUE;
RT_basedir=/opt/SUNWsample/bin;
Pkglist = SUNWsample;
Start
Stop
=
=
dns_svc_start;
dns_svc_stop;
Validate
Update
=
=
dns_validate;
dns_update;
Monitor_start =
Monitor_stop =
Monitor_check =
dns_monitor_start;
dns_monitor_stop;
dns_monitor_check;
■
■
API_version 属性用于标识 Sun Cluster 的版本。例如,API_version = 2 表明
数据服务可以在从 Sun Cluster 3.0 开始的 Sun Cluster 的所有版本上运行
;API_version = 5 表明数据服务可以安装在从 Sun Cluster 3.1 9/04 开始的 Sun
第 5 章 • 数据服务样例
73
Cluster 的所有版本上。但是,API_version = 5 还表明数据服务无法安装在 Sun
Cluster 3.1 9/04 发行之前的 Sun Cluster 的所有版本上。有关该属性的详细信息,
请参见第 213 页中的 “资源类型属性”中有关 API_version 条目下的内容。
■
■
RT_basedir 指向 /opt/SUNWsample/bin,将其作为完善相关路径(例如回调方
法路径)的目录路径。
■
Start、Stop 和 Validate 提供了通过 RGM 运行的回调方法程序的相应路径。这
些路径是 RT_basedir 所指定的目录的相对路径。
■
Pkglist 将 SUNWsample 标识为包含数据服务样例安装的软件包。
在此 RTR 文件中没有指定的资源类型属性(例如 Single_instance、Init_nodes
和 Installed_nodes 被设置为其默认值。第 213 页中的 “资源类型属性”包含资源
类型属性(包括其默认值)的完整列表。
群集管理员不能更改 RTR 文件中资源类型属性的值。
RTR 文件中的系统定义的属性
以下列表显示了某个样例 RTR 文件中系统定义的属性。
# A list of bracketed resource property declarations follows the
# resource type declarations. The property-name declaration must be
# the first attribute after the open curly bracket of each entry.
# The <method>_timeout properties set the value in seconds after which
# the RGM concludes invocation of the method has failed.
#
#
#
#
#
#
#
{
The MIN value for all method timeouts is set to 60 seconds. This
prevents administrators from setting shorter timeouts, which do not
improve switchover/failover performance, and can lead to undesired
RGM actions (false failovers, node reboot, or moving the resource group
to ERROR_STOP_FAILED state, requiring operator intervention). Setting
too-short method timeouts leads to a *decrease* in overall availability
of the data service.
PROPERTY = Start_timeout;
MIN=60;
DEFAULT=300;
}
74
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
{
PROPERTY = Stop_timeout;
MIN=60;
DEFAULT=300;
}
{
PROPERTY = Validate_timeout;
MIN=60;
DEFAULT=300;
}
{
PROPERTY = Update_timeout;
MIN=60;
DEFAULT=300;
}
{
PROPERTY = Monitor_Start_timeout;
MIN=60;
DEFAULT=300;
}
{
PROPERTY = Monitor_Stop_timeout;
MIN=60;
DEFAULT=300;
}
{
PROPERTY = Thorough_Probe_Interval;
MIN=1;
MAX=3600;
DEFAULT=60;
TUNABLE = ANYTIME;
}
# The number of retries to be done within a certain period before concluding
# that the application cannot be successfully started on this node.
{
PROPERTY = Retry_count;
MIN=0;
MAX=10;
DEFAULT=2;
TUNABLE = ANYTIME;
}
#
#
#
#
{
Set Retry_interval as a multiple of 60 since it is converted from seconds
to minutes, rounding up. For example, a value of 50 (seconds)
is converted to 1 minute. Use this property to time the number of
retries (Retry_count).
PROPERTY = Retry_interval;
MIN=60;
MAX=3600;
DEFAULT=300;
TUNABLE = ANYTIME;
}
75
{
PROPERTY = Network_resources_used;
TUNABLE = AT_CREATION;
DEFAULT = ““;
}
■
属性 Thorough_probe_interval、Retry_count 和 Retry_interval 的
TUNABLE 属性被设置为 ANYTIME。这些设置表示群集管理员可以更改这些属性的
值,即使数据服务正在运行。这些属性由通过数据服务样例实现的故障监视器使用。
数据服务样例将实现 Update 方法,以在通过管理操作更改这些或其它资源属性后
停止和重启故障监视器。请参见第 98 页中的 “Update 方法的工作方式”。
■
数据服务样例的故障监视器使用 Thorough_probe_interval、Retry_count、
Retry_interval 和 Network_resources_used 条件属性,因此需要在 RTR 文
件中对它们进行声明。有关如何给属性分类的信息,请参见 r_properties(5) 手册
页或第 220 页中的 “资源属性”。
RTR 文件中的扩展属性
样例 RTR 文件的结尾处是扩展属性,如该列表所示。
# Extension Properties
#
#
#
#
{
The cluster administrator must set the value of this property to point to the
directory that contains the configuration files used by the application.
For this application, DNS, specify the path of the DNS configuration file on
PXFS (typically named.conf).
PROPERTY = Confdir;
EXTENSION;
STRING;
TUNABLE = AT_CREATION;
DESCRIPTION = “The Configuration Directory Path”;
}
76
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
# Time out value in seconds before declaring the probe as failed.
{
PROPERTY = Probe_timeout;
EXTENSION;
INT;
DEFAULT = 120;
TUNABLE = ANYTIME;
DESCRIPTION = “Time out value for the probe (seconds)”;
}
样例 RTR 文件定义两种扩展属性,Confdir 和 Probe_timeout。Confdir 属性指定
DNS 配置目录的路径。该目录包含 DNS 正常操作所需的 in.named 文件。数据服务样
例的 Start 和 Validate 方法使用该属性验证启动 DNS 之前配置目录和 in.named
文件是否可访问。
配置数据服务之后,Validate 方法将检验新目录是否可以访问。
数据服务样例的 PROBE 方法不是 Sun Cluster 回调方法,而是用户定义的方法。因此,
Sun Cluster 没有为其提供 Probe_timeout 属性。要使群集管理员可以配置
Probe_timeout 值,需要在 RTR 文件中定义扩展属性。
77
export PATH=/bin:/usr/bin:/usr/cluster/bin:/usr/sbin:/usr/proc/bin:$PATH
声明 PMF_TAG 和 SYSLOG_TAG 变量
所有方法脚本(除了 Validate)都使用 pmfadm来启动或停止数据服务或监视器,并
传递资源名称。每个脚本都定义一个 PMF_TAG 变量,该变量可以传递至 pmfadm 以标
识数据服务或监视器。
同样地,每个方法脚本都使用 logger 命令将消息记录到系统日志中。每个脚本都定义
一个 SYSLOG_TAG 变量,该变量可以和 -t 选项一起传递至 logger,以标识正在为其
记录消息的资源的资源类型、资源名称和资源组。
所有方法都以同一种方式定义 SYSLOG_TAG,如以下样例代码所示。dns_probe、
dns_svc_start、dns_svc_stop 和 dns_monitor_check 方法按如下所示定义
PMF_TAG(pmfadm 和 logger 的用法来自 dns_svc_stop 方法)。
#########################################################################
# MAIN
#########################################################################
PMF_TAG=$RESOURCE_NAME.named
SYSLOG_TAG=$RESOURCETYPE_NAME,$RESOURCEGROUP_NAME,$RESOURCE_NAME
# Send a SIGTERM signal to the data service and wait for 80% of the
# total timeout value.
pmfadm -s $PMF_TAG.named -w $SMOOTH_TIMEOUT TERM
if [ $? -ne 0 ]; then
logger -p ${SYSLOG_FACILITY}.info \
-t [$SYSLOG_TAG] \
“${ARGV0} Failed to stop HA-DNS with SIGTERM; Retry with \
SIGKILL”
dns_monitor_start、dns_monitor_stop 和 dns_update 方法按以下方式定义
PMF_TAG(pmfadm 的用法来自 dns_monitor_stop 方法):
#####################################################################
# MAIN
#####################################################################
PMF_TAG=$RESOURCE_NAME.monitor
SYSLOG_TAG=$RESOURCETYPE_NAME,$RESOURCEGROUP_NAME,$RESOURCE_NAME
...
# See if the monitor is running, and if so, kill it.
if pmfadm -q $PMF_TAG.monitor; then
pmfadm -s $PMF_TAG.monitor KILL
分析函数参数
RGM 运行所有的回调方法(除了 Validate),如下所示:
method-name -R resource-name -T resource-type-name -G resource-group-name
78
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
方法名是实现回调方法的程序的路径名。数据服务指定 RTR 文件中各个方法的路径名。
这些路径名与 RT_basedir 属性(也在 RTR 文件中)指定的目录有关。例如,在数据
服务样例的 RTR 文件中,基目录和方法名按以下方式指定:
RT_basedir=/opt/SUNWsample/bin;
Start = dns_svc_start;
Stop = dns_svc_stop;
...
每个回调方法都需要一个函数来解析传递该函数的参数。因为所有回调方法都传送相同
的参数,所以数据服务提供了一个用于应用程序中所有回调方法的分析函数。
以下样例显示了样例应用程序中的回调方法所使用的 parse_args() 函数。
#########################################################################
# Parse program arguments.
#
function parse_args # [args ...]
{
typeset opt
while getopts ’R:G:T:’ opt
do
case "$opt" in
R)
# Name of the DNS resource.
RESOURCE_NAME=$OPTARG
;;
G)
# Name of the resource group in which the resource is
# configured.
RESOURCEGROUP_NAME=$OPTARG
;;
T)
# Name of the resource type.
RESOURCETYPE_NAME=$OPTARG
;;
*)
logger -p ${SYSLOG_FACILITY}.err \
-t [$RESOURCETYPE_NAME,$RESOURCEGROUP_NAME,$RESOURCE_NAME] \
"ERROR: Option $OPTARG unknown"
exit 1
;;
esac
第 5 章 • 数据服务样例
79
done
}
分析函数在 MAIN 中调用,如下所示:
parse_args “$@”
生成错误消息
回调方法应使用 syslog() 函数将错误消息输出到最终用户。数据服务样例中的所有回
调方法都使用 scha_cluster_get 命令检索用于群集日志的 syslog() 函数的数目,
如下所示:
SYSLOG_FACILITY=‘scha_cluster_get -O SYSLOG_FACILITY‘
该值存储在 shell 变量 SYSLOG_FACILITY 中,可以用作 logger 命令在群集日志中记
录消息的工具。例如,数据服务样例中的 Start 方法检索 syslog() 函数并记录已启
动数据服务的消息,如下所示:
SYSLOG_FACILITY=‘scha_cluster_get -O SYSLOG_FACILITY‘
...
if [ $? -eq 0 ]; then
logger -p ${SYSLOG_FACILITY}.err \
-t [$SYSLOG_TAG] \
"${ARGV0} HA-DNS successfully started"
fi
有关更多信息,请参见 scha_cluster_get(1HA) 手册页。
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
RT_BASEDIR=‘scha_resource_get -O RT_basedir -R $RESOURCE_NAME -G \
$RESOURCEGROUP_NAME‘
对于扩展属性,必须使用 -O 选项指定某属性为扩展属性。您还必须提供属性的名称,
将其作为最后一个参数。对于扩展属性,命令将同时返回属性的类型和值。例如,在数
据服务样例中,探测程序检索 Probe_timeout 扩展属性的类型和值并使用 awk 命令
将值仅放于 PROBE_TIMEOUT shell 变量中,如下所示:
probe_timeout_info=‘scha_resource_get -O Extension \
-R $RESOURCE_NAME -G $RESOURCEGROUP_NAME Probe_timeout‘
PROBE_TIMEOUT=‘echo $probe_timeout_info | awk ’{print $2}’‘
控制数据服务
数据服务必须提供 Start 或 Prenet_start 方法以在群集中激活应用程序守护进程,
还必须提供 Stop 或 Postnet_stop 方法以在群集中停止应用程序守护进程。数据服
务样例中实现了 Start 和 Stop 方法。有关何时改为使用 Prenet_start 和
Postnet_stop 的信息,请参见第 41 页中的 “确定使用哪种 Start 或 Stop 方法
”。
81
检验配置
要进行操作,DNS 需要位于配置目录下的 named.conf 文件中的信息。因此,Start
方法在尝试启动 DNS 之前,将执行一些完整性检查,以验证目录和文件是否可访问。
Confdir 扩展属性提供了指向配置目录的路径。属性本身是在 RTR 文件中定义的,但
是,群集管理员在配置数据服务时需指定实际位置。
在数据服务样例中,Start 方法通过使用 scha_resource_get() 函数检索配置目录
的位置。
注 – 因为 Confdir 是扩展属性,所以 scha_resource_get() 将同时返回类型和
值。awk 命令仅检索值并将该值放入 shell 变量 CONFIG_DIR 中。
# find the value of Confdir set by the cluster administrator at the time of
# adding the resource.
config_info=‘scha_resource_get -O Extension -R $RESOURCE_NAME \
-G $RESOURCEGROUP_NAME Confdir‘
# scha_resource_get returns the "type" as well as the "value" for the
# extension properties. Get only the value of the extension property
CONFIG_DIR=‘echo $config_info | awk ’{print $2}’‘
Start 方法使用 CONFIG_DIR 的值来验证目录是否可访问。如果该目录不可访问,则
Start 将记录一条错误消息,并在出错状态下退出。请参见第 83 页中的 “Start 退
出状态”。
# Check if $CONFIG_DIR is accessible.
if [ ! -d $CONFIG_DIR ]; then
logger -p ${SYSLOG_FACILITY}.err \
-t [$SYSLOG_TAG] \
"${ARGV0} Directory $CONFIG_DIR is missing or not mounted"
exit 1
fi
在启动应用程序守护进程之前,此方法将执行 final 检查,以检验 named.conf 文件是
否存在。如果该文件不存在,则 Start 将记录一条错误消息,并在出错状态下退出。
# Change to the $CONFIG_DIR directory in case there are relative
# pathnames in the data files.
cd $CONFIG_DIR
# Check that the named.conf file is present in the $CONFIG_DIR directory
if [ ! -s named.conf ]; then
logger -p ${SYSLOG_FACILITY}.err \
-t [$SYSLOG_TAG] \
"${ARGV0} File $CONFIG_DIR/named.conf is missing or empty"
exit 1
fi
82
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
启动应用程序
该方法使用进程管理器工具 (pmfadm) 来启动应用程序。使用 pmfadm 命令,可以设置
在指定时间范围内尝试重新启动应用程序的次数。RTR 文件包含两种属性
:Retry_count 指定尝试重新启动应用程序的次数,Retry_interval 指定执行此
操作的时间间隔。
Start 方法使用 scha_resource_get() 函数检索 Retry_count 和
Retry_interval 的值,并将其值存储于 shell 变量中。Start 方法使用 -n 和 -t 选
项将这些值传递给 pmfadm。
# Get the value for retry count from the RTR file.
RETRY_CNT=‘scha_resource_get -O Retry_count -R $RESOURCE_NAME \
-G $RESOURCEGROUP_NAME‘
# Get the value for retry interval from the RTR file. This value is in seconds
# and must be converted to minutes for passing to pmfadm. Note that the
# conversion rounds up; for example, 50 seconds rounds up to 1 minute.
((RETRY_INTRVAL=‘scha_resource_get -O Retry_interval -R $RESOURCE_NAME \
-G $RESOURCEGROUP_NAME‘ / 60))
# Start the in.named daemon under the control of PMF. Let it crash and restart
# up to $RETRY_COUNT times in a period of $RETRY_INTERVAL; if it crashes
# more often than that, PMF will cease trying to restart it.
# If there is a process already registered under the tag
# <$PMF_TAG>, then PMF sends out an alert message that the
# process is already running.
pmfadm -c $PMF_TAAG -n $RETRY_CNT -t $RETRY_INTRVAL \
/usr/sbin/in.named -c named.conf
# Log a message indicating that HA-DNS has been started.
if [ $? -eq 0 ]; then
logger -p ${SYSLOG_FACILITY}.err \
-t [$SYSLOG_TAG] \
"${ARGV0} HA-DNS successfully started"
fi
exit 0
83
停止应用程序
Stop 方法提供了用来停止数据服务的双重方法:顺序或平稳方法通过 pmfadm 使用
SIGTERM 信号,突然或强硬方法使用 SIGKILL 信号。Stop 方法获取 Stop_timeout
值(时间量,Stop 方法必须在该期间返回)。Stop 将此时间的 80% 分配给平稳停
止,15% 分配给突然停止(5% 保留),如以下样例代码所示。
STOP_TIMEOUT=’scha_resource_get -O STOP_TIMEOUT -R $RESOURCE_NAME \
-G $RESOURCEGROUP_NAME’
((SMOOTH_TIMEOUT=$STOP_TIMEOUT * 80/100))
84
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
((HARD_TIMEOUT=$STOP_TIMEOUT * 15/100))
Stop 方法将使用 pmfadm -q 检验 DNS 守护进程是否正在运行。如果 DNS 守护进程
正在运行,Stop 首先使用 pmfadm -s 发送 TERM 信号终止 DNS 进程。如果经过超时
值的 80% 后该信号还无法终止进程,Stop 将发送 SIGKILL 信号。如果该信号在超时
值的 15% 范围内仍无法终止进程,方法将记录一条错误消息并以出错状态退出。
如果 pmfadm 终止了该进程,该方法将记录一条说明该进程已停止并在成功状态下退出
的消息。
如果 DNS 进程未运行,该方法将记录一条说明该进程未运行并仍在成功状态下退出的
消息。以下样例代码说明了 Stop 如何使用 pmfadm 停止 DNS 进程。
# See if in.named is running, and if so, kill it.
if pmfadm -q $PMF_TAG; then
# Send a SIGTERM signal to the data service and wait for 80% of the
# total timeout value.
pmfadm -s $RESOURCE_NAME.named -w $SMOOTH_TIMEOUT TERM
if [ $? -ne 0 ]; then
logger -p ${SYSLOG_FACILITY}.err \
-t [$RESOURCETYPE_NAME,$RESOURCEGROUP_NAME,$RESOURCE_NAME] \
“${ARGV0} Failed to stop HA-DNS with SIGTERM; Retry with \
SIGKILL”
# Since the data service did not stop with a SIGTERM signal, use
# SIGKILL now and wait for another 15% of the total timeout value.
pmfadm -s $PMF_TAG -w $HARD_TIMEOUT KILL
if [ $? -ne 0 ]; then
logger -p ${SYSLOG_FACILITY}.err \
-t [$SYSLOG_TAG] \
“${ARGV0} Failed to stop HA-DNS; Exiting UNSUCCESSFUL”
exit 1
fi
fi
else
# The data service is not running as of now. Log a message and
# exit success.
logger -p ${SYSLOG_FACILITY}.err \
-t [$SYSLOG_TAG] \
“HA-DNS is not started”
# Even if HA-DNS is not running, exit success to avoid putting
# the data service resource in STOP_FAILED State.
exit 0
fi
# Could successfully stop DNS. Log a message and exit success.
logger -p ${SYSLOG_FACILITY}.err \
-t [$RESOURCETYPE_NAME,$RESOURCEGROUP_NAME,$RESOURCE_NAME] \
“HA-DNS successfully stopped”
exit 0
85
■
dns_monitor_start,启动 dns_probe 的回调方法。如果启用了监视,RGM 将
在数据服务样例联机之后自动调用 dns_monitor_start。
■
dns_monitor_stop,停止 dns_probe 的回调方法。使数据服务样例脱机之前,
RGM 自动调用 dns_monitor_stop。
■
dns_monitor_check,一种回调方法,当 PROBE 程序将数据服务故障转移到新节
点时该方法调用 Validate 方法,以验证配置目录是否可用。
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
Thorough_probe_interval – 用来设置探测程序休眠的时间段
Probe_timeout??在执行探测的 nslookup 命令上强制执行探测的超时值
Network_resources_used — 用来获取 DNS 服务器的 IP 地址
Retry_count 和 Retry_interval??确定尝试重新启动的次数以及计算这些次数
的时间段
RT_basedir??获取包含 PROBE 程序和 gettime 实用程序的目录
scha_resource_get() 函数获取这些属性的值并将其存储于 shell 变量中,如下所示
:
PROBE_INTERVAL=‘scha_resource_get -O Thorough_probe_interval \
-R $RESOURCE_NAME -G $RESOURCEGROUP_NAME‘
PROBE_TIMEOUT_INFO=‘scha_resource_get -O Extension -R $RESOURCE_NAME \
-G $RESOURCEGROUP_NAME Probe_timeout‘
Probe_timeout=‘echo $probe_timeout_info | awk ’{print $2}’‘
DNS_HOST=‘scha_resource_get -O Network_resources_used -R $RESOURCE_NAME \
-G $RESOURCEGROUP_NAME‘
RETRY_COUNT=‘scha_resource_get -O Retry_count -R $RESOURCE_NAME -G \
$RESOURCEGROUP_NAME‘
RETRY_INTERVAL=‘scha_resource_get -O Retry_interval -R $RESOURCE_NAME -G \
$RESOURCEGROUP_NAME‘
RT_BASEDIR=‘scha_resource_get -O RT_basedir -R $RESOURCE_NAME -G \
$RESOURCEGROUP_NAME‘
注 – 对于系统定义的属性,例如 Thorough_probe_interval,
scha_resource_get() 函数仅返回值。对于扩展属性,例如 Probe_timeout,
scha_resource_get() 函数返回类型和值。使用 awk 命令仅获取值。
检查服务的可靠性
探测本身是 nslookup 命令的无限 while 循环。while 循环之前,将设置一个临时文
件以放置 nslookup 回复。probefail 和 retries 变量均初始化为 0。
第 5 章 • 数据服务样例
87
# Set up a temporary file for the nslookup replies.
DNSPROBEFILE=/tmp/.$RESOURCE_NAME.probe
probefail=0
retries=0
while 循环执行以下任务:
■
■
使用 hatimerun 启动 nslookup,传递 Probe_timeout 值并标识目标主机
■
根据 nslookup 返回码成功与否设置 probefail 变量
■
如果 probefail 设置为 1(失败),验证对 nslookup 的回复来自于数据服务样
例,而不是某一其他 DNS 服务器
下面是 while 循环代码。
while :
do
# The interval at which the probe needs to run is specified in the
# property THOROUGH_PROBE_INTERVAL. Therefore, set the probe to sleep
# for a duration of THOROUGH_PROBE_INTERVAL.
sleep $PROBE_INTERVAL
# Run an nslookup command of the IP address on which DNS is serving.
hatimerun -t $PROBE_TIMEOUT /usr/sbin/nslookup $DNS_HOST $DNS_HOST \
> $DNSPROBEFILE 2>&1
retcode=$?
if [ $retcode -ne 0 ]; then
probefail=1
fi
# Make sure that the reply to nslookup comes from the HA-DNS
# server and not from another nameserver mentioned in the
# /etc/resolv.conf file.
if [ $probefail -eq 0 ]; then
# Get the name of the server that replied to the nslookup query.
SERVER=‘ awk ’ $1=="Server:" { print $2 }’ \
$DNSPROBEFILE | awk -F. ’ { print $1 } ’ ‘
if [ -z "$SERVER" ]; then
probefail=1
else
if [ $SERVER != $DNS_HOST ]; then
probefail=1
fi
fi
fi
88
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
比较重新启动和故障转移
如果 probefail 变量是非 0 值(成功),则 nslookup 命令超时,或回复来自于服务
样例的 DNS 以外的服务器。在每种情况下,DNS 服务器都不能按照预期的情况发挥作
用,且故障监视器将调用 decide_restart_or_failover() 函数以确定是在本地重
启数据服务,还是请求 RGM 将数据服务重定位到其它节点。如果 probefail 变量为
0,将生成探测成功的消息。
if [ $probefail -ne 0 ]; then
decide_restart_or_failover
else
logger -p ${SYSLOG_FACILITY}.err\
-t [$SYSLOG_TAG]\
"${ARGV0} Probe for resource HA-DNS successful"
fi
decide_restart_or_failover() 函数使用时间窗口 (Retry_interval) 和故障
计数 (Retry_count) 来确定是在本地重新启动 DNS,还是请求 RGM 将数据服务重新
定位到其他节点。该函数执行以下条件逻辑。第 252 页中的 “PROBE 程序代码列表”
中 decide_restart_or_failover() 的代码列表包含代码。
■
■
■
■
gettime 实用程序用来跟踪两次重启操作之间的时间。这是一个 C 程序,位于
(RT_basedir) 目录中。
■
■
■
scha_control() API 函数带有 GIVEOVER 选项使包含数据服务样例的资源组脱机
并在其他节点上使其重新联机。
重启数据服务
decide_restart_or_failover() 调用 restart_service() 函数,以尝试在同
一节点上重新启动数据服务。 该函数执行以下逻辑:
第 5 章 • 数据服务样例
89
■
■
为数据服务获取 Stop 方法名称和 Stop_timeout 值
使用 hatimerun 为数据服务启动 Stop 方法,传递 Stop_timeout 值
如果数据服务成功停止,则为数据服务获取 Start 方法名称和
Start_timeout 值
使用 hatimerun 为数据服务启动 Start 方法,传递 Start_timeout 值
function restart_service
{
# To restart the data service, first verify that the
# data service itself is still registered under PMF.
pmfadm -q $PMF_TAG
if [[ $? -eq 0 ]]; then
# Since the TAG for the data service is still registered under
# PMF, first stop the data service and start it back up again.
# Obtain the Stop method name and the STOP_TIMEOUT value for
# this resource.
STOP_TIMEOUT=`scha_resource_get -O STOP_TIMEOUT \
-R $RESOURCE_NAME -G $RESOURCEGROUP_NAM?
STOP_METHOD=`scha_resource_get -O STOP \
-R $RESOURCE_NAME -G $RESOURCEGROUP_NAM?
hatimerun -t $STOP_TIMEOUT $RT_BASEDIR/$STOP_METHOD \
-R $RESOURCE_NAME -G $RESOURCEGROUP_NAME \
-T $RESOURCETYPE_NAME
if [[ $? -ne 0 ]]; then
logger-p ${SYSLOG_FACILITY}.err -t [$SYSLOG_TAG] \
“${ARGV0} Stop method failed.”
return 1
fi
# Obtain the START method name and the START_TIMEOUT value for
# this resource.
START_TIMEOUT=`scha_resource_get -O START_TIMEOUT \
-R $RESOURCE_NAME -G $RESOURCEGROUP_NAM?
START_METHOD=`scha_resource_get -O START \
-R $RESOURCE_NAME -G $RESOURCEGROUP_NAM?
hatimerun -t $START_TIMEOUT $RT_BASEDIR/$START_METHOD \
-R $RESOURCE_NAME -G $RESOURCEGROUP_NAME \
-T $RESOURCETYPE_NAME
if [[ $? -ne 0 ]]; then
logger-p ${SYSLOG_FACILITY}.err -t [$SYSLOG_TAG] \
“${ARGV0} Start method failed.”
return 1
fi
90
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
else
# The absence of the TAG for the dataservice
# implies that the data service has already
# exceeded the maximum retries allowed under PMF.
# Therefore, do not attempt to restart the
# data service again, but try to failover
# to another node in the cluster.
scha_control -O GIVEOVER -G $RESOURCEGROUP_NAME \
-R $RESOURCE_NAME
fi
return 0
}
Monitor_start 方法的工作方式
RGM 调用 Monitor_start 方法,以在使数据服务样例联机之后启动 dns_probe 方
法。
本节介绍样例应用程序的 Monitor_start 方法的主要方面。本节没有介绍所有回调方
法通用的功能,例如 parse_args() 函数。本节也没有介绍 syslog() 函数的使用。
通用功能在第 77 页中的 “为所有方法提供通用功能”中进行介绍。
有关 Monitor_start 方法的完整列表,请参见第 257 页中的 “Monitor_start 方
法代码列表”。
Monitor_start 方法的用途
该方法使用 PMF (pmfadm) 来启动探测。
启动探测程序
Monitor_start 方法获取 RT_basedir 属性的值,用来为 PROBE 程序构造完整的路
径名。该方法通过使用 pmfadm 的无限重试选项(-n -1、-t -1)启动探测,意味着
如果探测无法启动,PMF 将在无限时间期限内无限次地启动探测。
# Find where the probe program resides by obtaining the value of the
# RT_basedir property of the resource.
RT_BASEDIR=‘scha_resource_get -O RT_basedir -R $RESOURCE_NAME -G \
第 5 章 • 数据服务样例
91
$RESOURCEGROUP_NAME‘
# Start the probe for the data service under PMF. Use the infinite retries
# option to start the probe. Pass the resource name, type, and group to the
# probe program.
pmfadm -c $RESOURCE_NAME.monitor -n -1 -t -1 \
$RT_BASEDIR/dns_probe -R $RESOURCE_NAME -G $RESOURCEGROUP_NAME \
-T $RESOURCETYPE_NAME
Monitor_stop 方法的工作方式
数据服务样例脱机时,RGM 调用 Monitor_stop 方法以停止 dns_probe 的执行。
本节介绍样例应用程序的 Monitor_stop 方法的主要方面。本节没有介绍所有回调方
法通用的功能,例如 parse_args() 函数。本节也没有介绍 syslog() 函数的使用。
通用功能在第 77 页中的 “为所有方法提供通用功能”中进行介绍。
有关 Monitor_stop 方法的完整列表,请参见第 259 页中的 “Monitor_stop 方法代
码列表”。
Monitor_stop 方法的用途
该方法使用 PMF (pmfadm),以检查探测是否正在运行,如果是则将其停止。
如 TERM)。否则,Monitor_stop 方法可能会无限期挂起并最终超时。原因是 PROBE
方法在必须重新启动或故障转移数据服务时调用 scha_control()。作为使数据服务
脱机过程的一部分,当 scha_control() 调用 Monitor_stop 时,如果
Monitor_stop 使用可以屏蔽的信号,则 Monitor_stop 将挂起,等待
scha_control() 完成,并且 scha_control() 将挂起等待 Monitor_stop 完成。
# See if the monitor is running, and if so, kill it.
if pmfadm -q $PMF_TAG; then
pmfadm -s $PMF_TAG KILL
if [ $? -ne 0 ]; then
logger -p ${SYSLOG_FACILITY}.err \
-t [$SYSLOG_TAG] \
"${ARGV0} Could not stop monitor for resource " \
$RESOURCE_NAME
92
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
exit 1
else
# could successfully stop the monitor. Log a message.
logger -p ${SYSLOG_FACILITY}.err \
-t [$SYSLOG_TAG] \
"${ARGV0} Monitor for resource " $RESOURCE_NAME \
" successfully stopped"
fi
fi
exit 0
Monitor_stop 退出状态
如果 Monitor_stop 方法无法停止 PROBE 方法,它将记录一条错误消息。RGM 使数
据服务样例在主节点上进入 MONITOR_FAILED 状态,这样可以应急该节点。
在探测程序停止之前,Monitor_stop 不应退出。
Monitor_check 方法的工作方式
无论 PROBE 方法何时尝试将包含数据服务的资源组故障转移到新节点上,RGM 都将调
用 Monitor_check 方法。
本节介绍样例应用程序的 Monitor_check 方法的主要方面。本节没有介绍所有回调方
法通用的功能,例如 parse_args() 函数。本节也没有介绍 syslog() 函数的使用。
通用功能在第 77 页中的 “为所有方法提供通用功能”中进行介绍。
有关 Monitor_check 方法的完整列表,请参见第 260 页中的 “Monitor_check 方
法代码列表”。
Monitor_check 方法必须执行,因此它不会与并发运行的其他方法发生冲突。
Monitor_check 方法调用 Validate 方法以验证 DNS 配置目录在新节点上是否可
用。Confdir 扩展属性指向 DNS 配置目录。因此,Monitor_check 获取 Validate
方法的路径和名称以及 Confdir 的值。它将把此值传送到 Validate,如下所示。
# Obtain the full path for the Validate method from
# the RT_basedir property of the resource type.
RT_BASEDIR=`scha_resource_get -O RT_basedir -R $RESOURCE_NAME \
-G $RESOURCEGROUP_NAM?
# Obtain the name of the Validate method for this resource.
VALIDATE_METHOD=`scha_resource_get -O Validate \
-R $RESOURCE_NAME -G $RESOURCEGROUP_NAM?
# Obtain the value of the Confdir property in order to start the
# data service. Use the resource name and the resource group entered to
# obtain the Confdir value set at the time of adding the resource.
config_info=`scha_resource_get -O Extension -R $RESOURCE_NAME \
第 5 章 • 数据服务样例
93
-G $RESOURCEGROUP_NAME Confdir`
# scha_resource_get returns the type as well as the value for extension
# properties. Use awk to get only the value of the extension property.
CONFIG_DIR=`echo $config_info | awk ‘{print $2}’`
# Call the validate method so that the dataservice can be failed over
# successfully to the new node.
$RT_BASEDIR/$VALIDATE_METHOD -R $RESOURCE_NAME -G $RESOURCEGROUP_NAME \
-T $RESOURCETYPE_NAME -x Confdir=$CONFIG_DIR
Validate 方法的工作方式
创建资源时以及通过管理操作更新资源或其资源组的属性时,RGM 将调用 Validate
方法。在进行创建或更新之前,RGM 将调用 Validate,如果从任何节点上的方法返
回失败出口代码都将导致创建或更新操作取消。
仅当群集管理员更改资源或资源组属性时 RGM 才调用 Validate,RGM 设置属性或
监视器设置资源属性 Status 和 Status_msg 时 RGM 不执行该调用。
注 – 只要 PROBE 方法尝试将数据服务故障转移到新节点,Monitor_check 方法也会明
确调用 Validate 方法。
94
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
注 – 由于在 DNS 运行时不能更改配置目录,所以 Confdir 属性在 RTR 文件中被声明
为 TUNABLE = AT_CREATION。因此,更新后系统从不调用 Validate 方法来验证
Confdir 属性,仅在创建数据服务资源时执行该操作。
如果 Confdir 是 RGM 传递给 Validate 的属性之一,parse_args() 函数将检索并
保存其值。Validate 验证 Confdir 的新值所指向的目录是否可访问,以及该目录中
是否存在 named.conf 文件并且该文件是否包含数据。
如果 parse_args() 函数无法从由 RGM 传递的命令行参数中检索 Confdir 的值,
Validate 仍会尝试验证 Confdir 属性。Validate 使用 scha_resource_get()
从静态配置中获取 Confdir 的值。Validate 执行同样的检查,验证配置目录是否可
访问并且是否包含非空文件 named.conf。
如果 Validate 在失败状态下退出,所有属性(而不仅仅是 Confdir)的更新或创建
操作都将失败。
Validate 方法分析函数
由于 RGM 向 Validate 方法传递了一组与其他回调方法不同的参数,因此 Validate
需要与其他方法不同的函数来解析这些参数。有关传递给 Validate 和其他回调方法的
参数的更多信息,请参见 rt_callbacks(1HA) 手册页。以下样例代码显示了
Validate 的 parse_args() 函数。
#########################################################################
# Parse Validate arguments.
#
function parse_args # [args...]
{
typeset opt
while getopts ’cur:x:g:R:T:G:’ opt
do
case "$opt" in
R)
# Name of the DNS resource.
RESOURCE_NAME=$OPTARG
;;
G)
# Name of the resource group in which the resource is
# configured.
RESOURCEGROUP_NAME=$OPTARG
;;
T)
# Name of the resource type.
RESOURCETYPE_NAME=$OPTARG
;;
r)
# The method is not accessing any system defined
第 5 章 • 数据服务样例
95
# properties so this is a no-op
;;
g)
# The method is not accessing any resource group
# properties, so this is a no-op
;;
c)
# Indicates the Validate method is being called while
# creating the resource, so this flag is a no-op.
;;
u)
# Indicates the updating of a property when the
# resource already exists. If the update is to the
# Confdir property then Confdir should appear in the
# command-line arguments. If it does not, the method must
# look for it specifically using scha_resource_get.
UPDATE_PROPERTY=1
;;
x)
# Extension property list. Separate the property and
# value pairs using "=" as the separator.
PROPERTY=‘echo $OPTARG | awk -F= ’{print $1}’‘
VAL=‘echo $OPTARG | awk -F= ’{print $2}’‘
# If the Confdir extension property is found on the
# command line, note its value.
if [ $PROPERTY == "Confdir" ]; then
CONFDIR=$VAL
CONFDIR_FOUND=1
fi
;;
*)
logger -p ${SYSLOG_FACILITY}.err \
-t [$SYSLOG_TAG] \
"ERROR: Option $OPTARG unknown"
exit 1
;;
esac
done
}
验证 Confdir
在其 MAIN 函数中,Validate 首先将 CONFDIR 变量设置为空字符串,并将
UPDATE_PROPERTY 和 CONFDIR_FOUND 设置为 0。
96
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
CONFDIR=""
UPDATE_PROPERTY=0
CONFDIR_FOUND=0
Validate 调用 parse_args() 解析由 RGM 传递的参数。
parse_args “$@”
Validate 检查 Validate 是否因属性更新而被调用。Validate 还会检查 Confdir
扩展属性是否在命令行中。Validate 验证 Confdir 属性是否有值,如果没有,则以
失败状态退出并显示错误消息。
if ( (( $UPDATE_PROPERTY == 1 )) && (( CONFDIR_FOUND == 0 )) ); then
config_info=‘scha_resource_get -O Extension -R $RESOURCE_NAME \
-G $RESOURCEGROUP_NAME Confdir‘
CONFDIR=‘echo $config_info | awk ’{print $2}’‘
fi
# Verify that the Confdir property has a value. If not there is a failure
# and exit with status 1
if [[ -z $CONFDIR ]]; then
logger -p ${SYSLOG_FACILITY}.err \
"${ARGV0} Validate method for resource "$RESOURCE_NAME " failed"
exit 1
fi
注 – 特别地,上述代码检查是否因更新而调用 Validate ($UPDATE_PROPERTY == 1)
以及是否未在命令行中找到该属性 (CONFDIR_FOUND == 0)。在这种情况下,代码将使
用 scha_resource_get() 检索 Confdir 的现有值。如果在命令行中找到了
Confdir (CONFDIR_FOUND == 1),则 CONFDIR 的值来自于 parse_args() 函数,
而不是来自于 scha_resource_get()。
Validate 方法使用 CONFDIR 的值来验证目录是否可访问。如果目录不可访问,
Validate 将记录一条错误消息并以出错状态退出。
# Check if $CONFDIR is accessible.
if [ ! -d $CONFDIR ]; then
logger -p ${SYSLOG_FACILITY}.err \
-t [$SYSLOG_TAG] \
"${ARGV0} Directory $CONFDIR missing or not mounted"
exit 1
fi
在验证 Confdir 属性的更新之前,Validate 将执行 final 检查来检验 named.conf
文件是否存在。如果文件不存在,该方法将记录一条错误消息并以出错状态退出。
# Check that the named.conf file is present in the Confdir directory
if [ ! -s $CONFDIR/named.conf ]; then
logger -p ${SYSLOG_FACILITY}.err \
-t [$SYSLOG_TAG] \
"${ARGV0} File $CONFDIR/named.conf is missing or empty"
exit 1
第 5 章 • 数据服务样例
97
fi
如果通过了最终检查,Validate 将记录表示成功的消息并以成功状态退出。
# Log a message indicating that the Validate method was successful.
logger -p ${SYSLOG_FACILITY}.err \
-t [$SYSLOG_TAG] \
"${ARGV0} Validate method for resource "$RESOURCE_NAME \
" completed successfully"
exit 0
Validate 退出状态
如果 Validate 以成功状态退出 (0),系统将用新值创建 Confdir。如果 Validate
以失败状态退出 (1),则不会创建 Confdir 和其他任何属性,并生成指出原因的消息。
使用 Update 停止监视器
Update 方法使用 pmfadm -q 验证监视器是否正在运行,如果是,则使用 pmfadm -s
TERM 中止它。如果监视器成功终止,将会向群集管理员发送一条描述该结果的消息。
如果无法停止监视器,Update 将以失败状态退出并向群集管理员发送一条错误消息。
if pmfadm -q $RESOURCE_NAME.monitor; then
# Kill the monitor that is running already
pmfadm -s $PMF_TAG TERM
if [ $? -ne 0 ]; then
logger -p ${SYSLOG_FACILITY}.err \
-t [$SYSLOG_TAG] \
98
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
"${ARGV0} Could not stop the monitor"
exit 1
else
# could successfully stop DNS. Log a message.
logger -p ${SYSLOG_FACILITY}.err \
-t [$RESOURCETYPE_NAME,$RESOURCEGROUP_NAME,$RESOURCE_NAME] \
"Monitor for HA-DNS successfully stopped"
fi
重启监视器
要重新启动监视器,Update 方法必须定位实现探测程序的脚本。探测程序位于数据服
务的基目录中,RT_basedir 属性指向该基目录。Update 检索 RT_basedir 的值并
将其存储于 RT_BASEDIR 变量中,如下所示。
RT_BASEDIR=‘scha_resource_get -O RT_basedir -R $RESOURCE_NAME -G \
$RESOURCEGROUP_NAME‘
Update 使用 RT_BASEDIR 的值和 pmfadm 重新启动 dns_probe 程序。如果成功,
Update 将以成功状态退出并向群集管理员发送一条描述该结果的消息。如果 pmfadm
无法启动探测程序,Update 将以失败状态退出并记录一条错误消息。
99
100
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
第6章
scds_initialize() 函数必须在每个回调方法的开头进行调用,它执行以下操作:
■
■
■
注 – 对于 Validate 方法,scds_initialize() 将解析通过命令行传递的属性值,
而无需写入 Validate 的解析函数。
每个函数仅使用一个句柄参数(scds_initialize() 返回)。
■
■
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
scds_fm_sleep() 函数使用 Thorough_probe_interval 属性来确定探测之间
的时间间隔。在此时间间隔内被 PMF 检测到的任何应用程序进程失败都将导致重新
启动资源。
■
■
探测返回值被发送给 scds_action() 函数,该函数保留在 Retry_interval 属
性的时间间隔内累积的失败历史记录。
■
■
■
如果在 Retry_interval 指定的时间内重新启动的次数超出 Retry_count 属
性的值,则将数据服务故障转移。
103
调试资源类型实现
DSDL 有一些内置功能,可用于帮助调试数据服务。
DSDL 公用程序 scds_syslog_debug() 提供了一个基本框架,可用来向资源类型实
现添加调试语句。可以在每个群集节点上为每个资源类型实现动态设置调试级别(级别
范围从 1 到 9)。所有资源类型回调方法都读取名为
/var/cluster/rgm/rt/rtname/loglevel 的文件,该文件仅包含一个 1 至 9 之间
的整数。DSDL 函数 scds_initialize() 将读取此文件并在内部将调试级别设置为
指定级别。默认的调试级别 0 用于指定数据服务不记录调试消息。
scds_syslog_debug() 函数将在 LOG_DEBUG 优先级上使用
scha_cluster_getlogfacility() 函数所返回的工具。可以在
/etc/syslog.conf 文件中配置这些调试消息。
可以使用 scds_syslog() 函数将一些调试消息转换为资源类型的常规操作的信息型消
息(可能属于 LOG_INFO 优先级)。请注意,第 8 章中的样例 DSDL 应用程序大量使
用了 scds_syslog_debug() 和 scds_syslog() 函数。
启用具有高可用性的本地文件系统
可以使用 HAStoragePlus 资源类型使本地文件系统在 Sun Cluster 环境中具有高可用
性。本地文件系统分区必须位于全局磁盘组中。必须启用关联切换转移,并且必须针对
故障转移配置 Sun Cluster 环境。此设置使群集管理员可以通过任何直接连接到多主机
磁盘的主机访问位于那些多主机磁盘上的任何文件系统。对于一些 I/O 增强数据服务,
强烈建议使用具有高可用性的本地文件系统。《Sun Cluster Data Services Planning
and Administration Guide for Solaris OS》中的“Enabling Highly Available Local File
Systems”包含关于配置 HAStoragePlus 资源类型的信息。
104
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
第7章
第 105 页中的 “资源类型注册文件”
第 106 页中的 “Validate 方法”
第 107 页中的 “Start 方法”
第 108 页中的 “Stop 方法”
第 109 页中的 “Monitor_start 方法”
第 110 页中的 “Monitor_stop 方法”
第 110 页中的 “Monitor_check 方法”
第 110 页中的 “Update 方法”
第 111 页中的 “Init、Fini 和 Boot 方法的说明”
第 111 页中的 “设计故障监视器守护进程”
■
■
■
这两种情况可以通过传递给资源的 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_dependencies 或 Resource_dependencies_weak 系统属性获得的。
有关 scds_hasp_check() 函数返回的状态代码的完整列表,请参见
scds_hasp_check(3HA) 手册页。
DSDL 函数 scds_initialize() 按照以下方式处理这些情况:
■
106
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
■
假设实现资源属性验证的函数名为 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 章包含更实际的
验证函数处理),可以实现更简单的示例 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() 函数的实现。
107
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));
}
108
■
■
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
因此,必须设计 Stop 方法让此方法一定要停止应用程序。如果采用其他方法无法终
止应用程序,您甚至可能需要采用 SIGKILL 突然中止应用程序。
您还必须确保此方法能够及时停止应用程序,因为框架将 Stop_timeout 属性的终
止视为停止失败,并因而将资源置入 STOP_FAILED 状态。
DSDL 实用程序 scds_pmf_stop() 在第一次尝试使用 SIGTERM 软停止应用程序时应
当足以用于大多数应用程序。此函数随后将 SIGKILL 传递给进程。此函数假定应用程
序是使用 scds_pmf_start() 在 PMF 下启动的。有关此实用程序的详细信息,请参
见第 182 页中的 “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 方法也应当尝试在此节点上停止应用程序。
109
Monitor_stop 方法
RGM 将调用 Monitor_stop 方法来停止通过使用 Monitor_start 方法启动的故障
监视器守护进程。处理此回调方法失败与处理 Stop 方法失败的方式刚好相同。因此,
Monitor_stop 方法必须是幂等的并且要像 Stop 方法一样强健。
如果您使用 scds_pmf_start() 公用程序启动故障监视器守护进程序,则请使用
scds_pmf_stop() 公用程序停止该守护进程。
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
Thorough_probe_interval
Retry_count
Retry_interval
Monitor_retry_count
Monitor_retry_interval
Probe_timeout
■
使用资源属性 Retry_interval 和 Retry_count 跟踪应用程序遇到的问题。应
用程序完全失败时,故障监视器需要确定 PMF 操作脚本是否应当重新启动服务,或
者应用程序失败是否累积得太快需要执行故障转移。DSDL 实用程序
scds_fm_action() 和 scds_fm_sleep() 可以帮助实现这种机制。
第 7 章 • 设计资源类型
111
■
■
■
■
■
实用程序 scds_fm_action() 将根据失败历史记录将资源状态更新为
SCHA_RSSTATUS_OK、SCHA_RSSTATUS_DEGRADED 或
SCHA_RSSTATUS_FAULTED。从而使此状态可用于群集系统管理。
在大多数情况下,您可以在独立的实用程序中(例如,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.
*/
112
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
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 */
113
114
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
第8章
第 115 页中的 “X Font Server”
第 116 页中的 “SUNW.xfnts RTR 文件”
第 117 页中的 “函数和回调方法的命名约定”
第 117 页中的 “scds_initialize() 函数”
第 118 页中的 “xfnts_start 方法”
第 122 页中的 “xfnts_stop 方法”
第 123 页中的 “xfnts_monitor_start 方法”
第 124 页中的 “xfnts_monitor_stop 方法”
第 125 页中的 “xfnts_monitor_check 方法”
第 125 页中的 “SUNW.xfnts 故障监视器”
第 130 页中的 “xfnts_validate 方法”
第 133 页中的 “xfnts_update 方法”
X Font Server
X Font Server 是基于 TCP/IP 的服务,该服务向其客户机提供字体文件。客户机将连接
该服务器,请求提供字体集,该服务器将从磁盘读取相应的字体文件并将它们提供给客
户机。X Font Server 守护进程包含位于 /usr/openwin/bin/xfs 的服务器二进制文
件。该守护进程通常通过 inetd 启动。但是,对于当前的样例,假定
/etc/inetd.conf 文件中的正确条目已被禁用(例如,通过使用 fsadmin -d 命
令),以使守护进程处于 Sun Cluster 软件的单独控制下。
115
X Font Server 配置文件
默认情况下,X Font Server 从 /usr/openwin/lib/X11/fontserver.cfg 文件中
读取其配置信息。此文件中的目录条目包含可用于守护进程提供服务的字体目录列表。
群集管理员可以在群集文件系统中找到字体目录。通过在系统的字体数据库中维护一个
单独的副本,此位置优化了 X Font Server 在 Sun Cluster 上的使用。如果群集管理员需
要更改此位置,则必须编辑 fontserver.cfg 以反映新的字体目录路径。
为了简化配置,群集管理员还可以将配置文件本身置于群集文件系统中。xfs 守护进程
提供了覆盖该文件默认的内置位置的命令行参数。SUNW.xfnts 资源类型使用以下命令
启动在 Sun Cluster 软件控制下的守护进程。
/usr/openwin/bin/xfs -config location-of-configuration-file/fontserver.cfg \
-port port-number
在 SUNW.xfnts 资源类型实现中,可以使用 Confdir_list 属性来管理
fontserver.cfg 配置文件的位置。
TCP 端口号
xfs 服务器守护进程侦听的 TCP 端口号通常为 “fs” 端口,该端口在 /etc/services
文件中通常定义为 7100。但是,群集管理器附带的 xfs 命令的 -port 选项使群集管
理器可以覆盖默认设置。
可以使用 SUNW.xfnts 资源类型中的 Port_list 属性设置默认值并使群集管理器可以
将 -port 选项与 xfs 命令结合使用。在 RTR 文件中您需要将此属性的缺省值定义为
7100/tcp。在 SUNW.xfnts Start 方法中,可以将 Port_list 传递给 xfs 命令行
上的 -port 选项。因此,此资源类型的用户无需指定端口号(默认端口为
7100/tcp)。群集管理员在配置资源类型时,可以指定其他 Port_list 属性值。
SUNW.xfnts RTR 文件
本节介绍了 SUNW.xfnts RTR 文件中的几个主要属性。本节并未介绍该文件中每个属
性的作用,对于此类说明,请参见“第 31 页中的 “设置资源和资源类型属性””。
Confdir_list 扩展属性用于标识配置目录(或目录列表),如下所示:
{
PROPERTY = Confdir_list;
EXTENSION;
STRINGARRAY;
TUNABLE = AT_CREATION;
DESCRIPTION = "The Configuration Directory Path(s)";
}
116
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
Confdir_list 属性未指定缺省值。创建资源时,群集管理员必须指定目录名称。该值
以后不能更改,因为可调性被限制为 AT_CREATION。
Port_list 属性用于标识服务器守护进程进行侦听的端口,如下所示:
{
PROPERTY = Port_list;
DEFAULT = 7100/tcp;
TUNABLE = ANYTIME;
}
RMAPI 函数以 scha_ 开头。
DSDL 函数以 scds_ 开头。
回调方法以 xfnts_ 开头。
用户编写的函数以 svc_ 开头。
scds_initialize() 函数
DSDL 要求每个回调方法在方法的开头都要调用 scds_initialize() 函数。此函数
可执行以下操作:
■
■
■
■
使用 scds_close() 函数可以收回由 scds_initialize() 分配的资源。
117
xfnts_start 方法
当包含数据服务资源的资源组在群集节点上联机或启用资源时,RGM 将在该群集节点
上运行 Start 方法。在资源类型样例 SUNW.xfnts 中,xfnts_start 方法将激活该
节点上的 xfs 守护进程。
xfnts_start 方法将调用 scds_pmf_start() 以启动 PMF 下的守护进程。PMF 提
供了自动失败通知和重新启动功能,并集成了故障监视器。
注 – xfnts_start 将首先调用执行一些必要的内务处理函数的
scds_initialize()。第 117 页中的 “scds_initialize() 函数”和
scds_initialize(3HA) 手册页包含更多信息。
启动 X Font Server 之前验证服务
在 xfnts_start 方法尝试启动 X Font Server 之前,它将调用 svc_validate() 来
验证正确配置是否已就位以支持 xfs 守护进程。
rc = svc_validate(scds_handle);
if (rc != 0) {
scds_syslog(LOG_ERR,
"Failed to validate configuration.");
return (rc);
}
有关详细信息,请参见“第 130 页中的 “xfnts_validate 方法””。
使用 svc_start() 启动服务
xfnts_start 方法将调用在 xfnts.c 文件中定义的 svc_start() 方法来启动 xfs
守护进程。本节将介绍 svc_start ()。
用于启动 xfs 守护进程的命令如下:
# xfs -config config-directory/fontserver.cfg -port port-number
Confdir_list 扩展属性用于标识 config-directory,Port_list 系统属性用于标识
port-number。当群集管理员配置数据服务时,将提供这些属性的具体值。
xfnts_start 方法将这些属性声明为字符串数组。xfnts_start 方法使用
scds_get_ext_confdir_list() 和 scds_get_port_list() 函数获取由群集管
理员设置的值。scds_property_functions(3HA) 手册页中介绍了这些函数。
scha_str_array_t *confdirs;
scds_port_list_t
*portlist;
118
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
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);
}
请注意,confdirs 变量指向数组的第一个元素 (0)。
xfnts_start 方法将使用 sprintf() 来设置 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);
请注意,输出被重定向到 /dev/null 以抑制由守护进程生成的消息。
xfnts_start 方法将 xfs 命令行传递给 scds_pmf_start() 以启动在 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 ");
}
关于对 scds_pmf_start() 的调用,请注意以下几点:
■
■
SCDS_PMF_SINGLE_INSTANCE 参数将此标识为单实例资源。
■
■
返回前,svc_pmf_start() 将释放为 portlist 结构分配的内存。
scds_free_port_list(portlist);
return (err);
第 8 章 • DSDL 资源类型实现样例
119
从 svc_start() 返回
即使 svc_start() 成功返回,底层应用程序也可能无法启动。因此,svc_start()
必须探测应用程序以验证在返回成功消息前运行了此应用程序。探测还必须考虑到应用
程序可能无法立即可用,因为它需要一些时间才能启动。svc_start() 方法将调用在
xfnts.c 文件中定义的 svc_wait() 以验证应用程序是否正在运行。
/* 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.");
}
svc_wait() 函数将调用 scds_get_netaddr_list() 以获取探测应用程序所需的
网络地址资源。
/* 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);
}
svc_wait() 函数用于获取 Start_timeout 和 Stop_timeout 值。
svc_start_timeout = scds_get_rs_start_timeout(scds_handle)
probe_timeout = scds_get_ext_probe_timeout(scds_handle)
为了计算启动服务器可能需要的时间,svc_wait() 将调用 scds_svc_wait() 并传
递相当于 Start_timeout 值百分之三的超时值。svc_wait() 函数将调用
svc_probe() 函数来验证应用程序是否已启动。svc_probe() 方法用来建立指定端
口上服务器的简单套接字连接。如果无法连接端口,svc_probe() 将返回一个值
100,该值表示完全失败。如果连接成功但从端口断开连接时失败,svc_probe() 将返
回一个值 50。
120
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
svc_probe() 失败或部分失败时,svc_wait() 使用超时值 5 调用
scds_svc_wait()。scds_svc_wait() 方法将探测频率限制为每五秒钟一次。此方
法也可用来计算尝试启动该服务的次数。如果在资源的 Retry_interval 属性指定的
时间内,尝试次数超出了资源的 Retry_count 属性的值,scds_svc_wait() 函数将
返回失败。在这种情况下,svc_start() 函数也返回失败。
#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);
注 – 退出前,xfnts_start 方法将调用 scds_close() 来收回由
scds_initialize() 分配的资源。第 117 页中的 “scds_initialize() 函数”和
scds_close(3HA) 手册页包含更多信息。
121
xfnts_stop 方法
由于 xfnts_start 方法使用 scds_pmf_start() 启动 PMF 下的服务,因此,
xfnts_stop 将使用 scds_pmf_stop() 来停止该服务。
注 – xfnts_stop 将首先调用执行一些必要的内务处理函数的
scds_initialize()。第 117 页中的 “scds_initialize() 函数”和
scds_initialize(3HA) 手册页包含更多信息。
xfnts_stop 方法将调用在 xfnts.c 文件中定义的 svc_stop() 方法,如下所示:
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 */
关于在 svc_stop() 中对 scds_pmf_stop() 函数的调用,请注意以下几点:
■
■
SCDS_PMF_SINGLE_INSTANCE 参数用于标识信号。
■
SIGTERM 参数将标识用于停止资源实例的信号。如果此信号无法停止该实例,
scds_pmf_stop() 将发送 SIGKILL 来停止该实例,如果仍然失败,则会返回超时
错误。有关详细信息,请参见 scds_pmf_stop(3HA) 手册页。
■
超时值即该资源的 Stop_timeout 属性的值。
注 – 退出前,xfnts_stop 方法将调用 scds_close() 来收回由
scds_initialize() 分配的资源。第 117 页中的 “scds_initialize() 函数”和
scds_close(3HA) 手册页包含更多信息。
122
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
xfnts_monitor_start 方法
在节点上启动资源后,RGM 将在该节点上调用 Monitor_start 方法以启动故障监视
器。xfnts_monitor_start 方法将使用 scds_pmf_start() 来启动 PMF 下的监视
器守护进程。
注 – xfnts_monitor_start 将首先调用执行一些必要的内务处理函数的
scds_initialize()。第 117 页中的 “scds_initialize() 函数”和
scds_initialize(3HA) 手册页包含更多信息。
xfnts_monitor_start 方法用于调用在 xfnts.c 文件中定义的 mon_start 方法,
如下所示:
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 */
}
关于在 svc_mon_start() 中对 scds_pmf_start() 函数的调用,请注意以下几点
:
■
■
SCDS_PMF_SINGLE_INSTANCE 参数将此标识为单实例资源。
■
■
123
注 – 退出前,xfnts_monitor_start 方法将调用 scds_close() 以收回由
scds_initialize() 分配的资源。第 117 页中的 “scds_initialize() 函数”和
scds_close(3HA) 手册页包含更多信息。
xfnts_monitor_stop 方法
由于 xfnts_monitor_start 方法使用 scds_pmf_start() 来启动 PMF 下的监视
器守护进程,xfnts_monitor_stop 将使用 scds_pmf_stop() 来停止监视器守护
进程。
注 – xfnts_monitor_stop 将首先调用执行一些必要的内务处理函数的
scds_initialize()。第 117 页中的 “scds_initialize() 函数”和
scds_initialize(3HA) 手册页包含更多信息。
xfnts_monitor_stop 方法用于调用在 xfnts.c 文件中定义的 mon_stop() 方法,
如下所示:
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 */
}
关于在 svc_mon_stop() 中对 scds_pmf_stop() 函数的调用,请注意以下几点:
124
■
■
SCDS_PMF_SINGLE_INSTANCE 参数将此标识为单实例资源。
■
SIGKILL 参数将标识用于停止资源实例的信号。如果此信号无法停止该实例,则
scds_pmf_stop() 将会返回超时错误。有关详细信息,请参见
scds_pmf_stop(3HA) 手册页。
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
■
超时值是资源的 Monitor_stop_timeout 属性的值。
注 – 退出前,xfnts_monitor_stop 方法将调用 scds_close() 以收回由
scds_initialize() 分配的资源。第 117 页中的 “scds_initialize() 函数”和
scds_close(3HA) 手册页包含更多信息。
xfnts_monitor_check 方法
只要故障监视器尝试将包含该资源的资源组故障转移到其他节点,RGM 就将调用
Monitor_check 方法。xfnts_monitor_check 方法将调用 svc_validate() 方
法以验证正确配置是否已就位以支持 xfs 守护进程。有关详细信息,请参见“第 130 页
中的 “xfnts_validate 方法””。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);
}
SUNW.xfnts 故障监视器
在节点上启动资源后,RGM 不直接调用 PROBE 方法,而是调用 Monitor_start 方法
来启动监视器。xfnts_monitor_start 方法用于启动在 PMF 控制下的故障监视器。
xfnts_monitor_stop 方法用于停止故障监视器。
SUNW.xfnts 故障监视器可以执行以下操作:
■
125
■
跟踪应用程序在时间窗口内遇到的问题(使用 Retry_count 和 Retry_interval
属性),并在应用程序完全失败时决定是重新启动还是故障转移数据服务。
scds_fm_action() 和 scds_fm_sleep() 函数为此跟踪和决定机制提供了内置
支持。
■
使用 scds_fm_action() 实现故障转移或重新启动决策。
■
xfonts_probe 主循环
xfonts_probe 方法用于实现循环。实现循环前,xfonts_probe 将执行以下操作:
■
检索 xfnts 资源的网络地址资源,如下所示:
/* Get the ip addresses available for this resource */
if (scds_get_netaddr_list(scds_handle, &netaddr)) {
scds_syslog(LOG_ERR,
"No network address resource in resource group.");
scds_close(&scds_handle);
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);
}
■
调用 scds_fm_sleep() 并将 Thorough_probe_interval 的值作为超时值传
递。探测将根据探测之间的 Thorough_probe_interval 值进行休眠,如下所示
:
timeout = scds_get_ext_probe_timeout(scds_handle);
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));
xfnts_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;
/*
126
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
* 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 */
svc_probe() 函数
svc_probe() 函数通过调用 scds_fm_tcp_connect() 建立与指定端口的简单套接
字连接。如果连接失败,svc_probe() 将返回一个值 100,该值表示完全失败。如果
连接成功,但是断开连接失败,svc_probe() 将返回一个值 50,该值表示部分失败。
如果连接和断开连接都成功,svc_probe() 将返回一个值 0,该值表示成功。
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;
127
/*
* 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.
128
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
*/
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.
第 8 章 • DSDL 资源类型实现样例
129
*/
(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);
}
完成时,svc_probe() 将返回一个值,来表示操作是成功 (0)、是部分失败 (50) 还是
完全失败 (100)。xfnts_probe 方法将把此值传送到 scds_fm_action()。
确定故障监视器操作
xfnts_probe 方法将调用 scds_fm_action() 来确定要执行的操作。
scds_fm_action() 的逻辑如下:
■
保留 Retry_interval 属性值内的累积失败历史记录。
■
■
如果在 Retry_interval 指定的时间内,重新启动次数超出了 Retry_count 属
性的值,则故障转移该数据服务。
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
仅当群集管理员更改资源或资源组属性,或当监视器设置 Status 和 Status_msg 资
源属性时,RGM 才会调用 Validate。RGM 在设置属性时不调用 Validate。
注 – 只要 PROBE 方法尝试将数据服务故障转移到新节点上,Monitor_check 方法还将
显式调用 Validate 方法。
RGM 将对传递给其他方法的那些正被更新的属性和值调用 Validate 和其他参数。在
xfnts_validate 的开头调用 scds_initialize() 将解析 RGM 传递给
xfnts_validate 所有参数和存储在 scds_handle 参数中的信息。
xfnts_validate 调用的子例行程序将使用此信息。
xfnts_validate 方法将调用 svc_validate() 以验证以下条件:
■
已经为该资源设置了 Confdir_list 属性并定义了一个目录。
scha_str_array_t *confdirs;
confdirs = scds_get_ext_confdir_list(scds_handle);
/* Return error if there is no confdir_list extension property */
if (confdirs == NULL || confdirs->array_cnt != 1) {
scds_syslog(LOG_ERR,
"Property Confdir_list is not set properly.");
return (1); /* Validation failure */
}
■
Confdir_list 所指定的目录包含 fontserver.cfg 文件。
(void) sprintf(xfnts_conf, "%s/fontserver.cfg", confdirs->str_array[0]);
if (stat(xfnts_conf, &statbuf) != 0) {
/*
* suppress lint error because errno.h prototype
* is missing void arg
*/
scds_syslog(LOG_ERR,
"Failed to access file <%s> : <%s>",
xfnts_conf, strerror(errno));
/*lint !e746 */
return (1);
}
■
该服务器守护进程二进制文件可以在该群集节点上访问。
if (stat("/usr/openwin/bin/xfs", &statbuf) != 0) {
scds_syslog(LOG_ERR,
"Cannot access XFS binary : <%s> ", strerror(errno));
return (1);
}
■
Port_list 属性将指定单个端口。
scds_port_list_t
*portlist;
err = scds_get_port_list(scds_handle, &portlist);
if (err != SCHA_ERR_NOERR) {
scds_syslog(LOG_ERR,
第 8 章 • DSDL 资源类型实现样例
131
"Could not access property Port_list: %s.",
scds_error_string(err));
return (1); /* Validation Failure */
}
#ifdef TEST
if (portlist->num_ports != 1) {
scds_syslog(LOG_ERR,
"Property Port_list must have only one value.");
scds_free_port_list(portlist);
return (1); /* Validation Failure */
}
#endif
■
包含数据服务的资源组还至少包含一个网络地址资源。
scds_net_resource_list_t *snrlp;
if ((err = scds_get_rs_hostnames(scds_handle, &snrlp))
!= SCHA_ERR_NOERR) {
scds_syslog(LOG_ERR,
"No network address resource in resource group: %s.",
scds_error_string(err));
return (1); /* Validation Failure */
}
/* Return an error if there are no network address resources */
if (snrlp == NULL || snrlp->num_netresources == 0) {
scds_syslog(LOG_ERR,
"No network address resource in resource group.");
rc = 1;
goto finished;
}
在返回之前,svc_validate() 将释放所有分配的资源。
finished:
scds_free_net_list(snrlp);
scds_free_port_list(portlist);
return (rc); /* return result of validation */
注 – 退出前,xfnts_validate 方法将调用 scds_close() 以收回由
scds_initialize() 分配的资源。第 117 页中的 “scds_initialize() 函数”和
scds_close(3HA) 手册页包含更多信息。
132
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
xfnts_update 方法
RGM 将调用 Update 方法以通知正在运行的资源其属性已更改。唯一可为 xfnts 数据
服务更改的属性与故障监视器有关。因此,只要更新了属性,xfnts_update 方法就将
调用 scds_pmf_restart_fm() 以重新启动故障监视器。
/* 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.");
注 – 如果故障监视器有多个实例,则 scds_pmf_restart_fm() 的第二个参数将唯一
133
134
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
第9章
SunPlex Agent Builder
本章介绍了 SunPlex Agent Builder 和 Agent Builder 的 Cluster Agent 模块。两种工具
均可以自动创建在资源组管理器 (Resource Group Manager, RGM) 的控制下运行的资源
类型或数据服务。资源类型是包裹在应用程序外围的封装程序,使应用程序可以在
RGM 的控制下运行于群集环境中。
本章包括以下主题:
■
■
■
■
■
■
第 135 页中的 “Agent Builder 概述”
第 136 页中的 “Agent Builder 使用前须知”
第 136 页中的 “使用 Agent Builder”
第 151 页中的 “Agent Builder 创建的目录结构”
第 152 页中的 “Agent Builder 的输出”
第 155 页中的 “Agent Builder 的 Cluster Agent 模块”
Agent Builder 概述
Agent Builder 提供了图形用户界面 (GUI),用于指定关于要创建的应用程序和要创建资
源类型的种类的信息。Agent Builder 支持网络可识别的应用程序和非网络可识别的应
用程序。网络可识别的应用程序使用网络与客户机通信。非网络可识别的应用程序是独
立的应用程序。
注 – 如果无法访问 Agent Builder 的 GUI 版本,可以通过命令行界面访问 Agent
Builder。请参见第 150 页中的 “使用 Agent Builder 的命令行版本的方法”。
根据您指定的信息,Agent Builder 将生成以下软件:
■
■
定制的资源类型注册 (RTR) 文件(如果您生成的是 C 或 Korn shell 源代码)。
■
■
使用 Agent Builder
本节介绍了如何使用 Agent Builder。此外,本节还包括使用 Agent Builder 之前您必须
完成的任务。本节还介绍了在生成资源类型代码之后充分利用 Agent Builder 的方法。
包括以下主题:
136
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
■
■
■
■
■
■
■
■
■
■
■
第 137 页中的 “分析应用程序”
第 137 页中的 “安装和配置 Agent Builder”
第 138 页中的 “Agent Builder 屏幕”
第 138 页中的 “启动 Agent Builder”
第 139 页中的 “浏览 Agent Builder”
第 142 页中的 “使用“创建”屏幕”
第 144 页中的 “使用“配置”屏幕”
第 146 页中的 “使用 Agent Builder 基于 Korn Shell 的 $hostnames 变量”
第 147 页中的 “使用属性变量”
第 149 页中的 “重复使用使用 Agent Builder 创建的代码”
第 150 页中的 “使用 Agent Builder 的命令行版本的方法”
安装和配置 Agent Builder
Agent Builder 不需要专门进行安装。SUNWscdev 软件包中包含 Agent Builder,默认
情况下,安装 Sun Cluster 软件时安装此软件包。《Sun Cluster 软件安装指南(适用于
Solaris OS)》中介绍了这方面的更多信息。
使用 Agent Builder 之前,请检验是否满足以下要求:
■
$PATH 变量中包含 Java 运行时环境。Agent Builder 基于 Java 开发工具包(不低于
1.3.1 版)进行工作。如果 $PATH 变量中未包含 Java 开发工具包,Agent Builder 命
令 (scdsbuilder) 将返回并显示错误消息。
■
■
$PATH 变量中包含 cc 编译器。Agent Builder 使用 $PATH 变量中第一处 cc 来识别
用于生成资源类型的 C 二进制代码的编译器。如果 $PATH 中未包含 cc,则 Agent
Builder 将禁用生成 C 代码的选项。请参见第 142 页中的 “使用“创建”屏幕”。
第 9 章 • SunPlex Agent Builder
137
注 – 除了标准 cc 编译器,您还可以在 Agent Builder 中使用其他编译器。要使用其他编
译器,请在 $PATH 中将符号链接 cc 更改为其他编译器的符号链接,例如 gcc。或者,
将 make 程序的描述文件中的编译器定义(当前为 CC=cc)更改为其他编译器的完整路
径。例如,在 Agent Builder 生成的 make 程序的描述文件中,将 CC=cc 更改为
CC=pathname/gcc。此种情况下,您不能直接运行 Agent Builder。而必须使用 make
和 make pkg 命令来生成数据服务代码和软件包。
■
■
要生成的代码的类型(C、Korn shell [ksh] 或 GDS)
启动 Agent Builder
注 – 如果无法访问 Agent Builder 的 GUI 版本,可以通过命令行界面访问 Agent
Builder。请参见第 150 页中的 “使用 Agent Builder 的命令行版本的方法”。
如果从现有资源类型的工作目录启动 Agent Builder,则 Agent Builder 将以现有资源类
型的值初始化“创建”和“配置”屏幕。
通过键入以下命令启动 Agent Builder:
% /usr/cluster/bin/scdsbuilder
138
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
图 9–1
Agent Builder 的“创建”屏幕
■
■
■
第 9 章 • SunPlex Agent Builder
139
140
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
目的
Agent Builder 菜单
Agent Builder 提供了“文件”和“编辑”下拉式菜单。
Agent Builder “文件”菜单
“文件”菜单包含以下两个选项:
■
■
“退出”选项。退出 Agent Builder。您也可以单击“创建”或“配置”屏幕上的“取消”来
退出 Agent Builder。
第 9 章 • SunPlex Agent Builder
141
Agent Builder “编辑”菜单
“编辑”菜单包含以下两个选项:
■
■
图 9–2
键入信息后的 Agent Builder“创建”屏幕
142
■
■
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
■
■
■
■
■
■
第 9 章 • SunPlex Agent Builder
143
注 – 如果 $PATH 变量中不包含 cc 编译器,则 Agent Builder 将灰显 C 单选按钮并允许
您选择 ksh 单选按钮。要指定其他编译器,请参见第 137 页中的 “安装和配置 Agent
Builder”结尾处的注释。
如果 Agent Builder 不能完成此步骤,请查看输出日志中的详细信息。
■
退出 Agent Builder,您已指定的信息或 Agent Builder 已完成的工作并不会丢失。请参
见第 149 页中的 “重复使用使用 Agent Builder 创建的代码”。
144
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
图 9–3
Agent Builder 的“配置”屏幕
第 9 章 • SunPlex Agent Builder
145
■
■
■
■
■
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
注 – $hostnames 变量只适用于基于 Korn shell 的服务。不支持对基于 C 和 GDS 的服
务使用 $hostnames 变量。
指定 $hostnames 变量的方法就像指定实际主机名一样,例如:
% /opt/network_aware/echo_server -p port-no -l $hostnames
当目标资源类型的资源在群集上运行时,将用为资源配置的 LogicalHostname 或
SharedAddress 主机名替换 $hostnames 变量的值。为资源配置的主机名位于资源
的 Network_resources_used 资源属性中。
如果配置的 Network_resources_used 属性具有多个主机名,则 $hostnames 变量
将包含所有主机名,并用逗号将其隔开。
HOSTNAMES
RS_CHEAP_PROBE_INTERVAL
RS_MONITOR_START_TIMEOUT
RS_MONITOR_STOP_TIMEOUT
RS_NAME
RS_NUM_RESTARTS
RS_RESOURCE_DEPENDENCIES
RS_RESOURCE_DEPENDENCIES_WEAK
RS_RETRY_COUNT
RS_RETRY_INTERVAL
RS_SCALABLE
RS_START_TIMEOUT
第 9 章 • SunPlex Agent Builder
147
■
■
■
RS_STOP_TIMEOUT
RS_THOROUGH_PROBE_INTERVAL
SCHA_STATUS
RT_API_VERSION
RT_BASEDIR
RT_FAILOVER
RT_INSTALLED_NODES
RT_NAME
RT_RT_VERSION
RT_SINGLE_INSTANCE
RG_DESIRED_PRIMARIES
RG_GLOBAL_RESOURCES_USED
RG_IMPLICIT_NETWORK_DEPENDENCIES
RG_MAXIMUM_PRIMARIES
RG_NAME
RG_NODELIST
RG_NUM_RESTARTS
RG_PATHPREFIX
RG_PINGPONG_INTERVAL
RG_RESOURCE_LIST
属性变量的语法
您可以在属性名称前面加百分号 (%) 来表示属性变量,如下例所示:
/opt/network_aware/echo_server -t %RS_STOP_TIMEOUT -n %RG_NODELIST
根据上面的示例,Agent Builder 可以解释这些属性变量,并使用以下值启动
echo_server 脚本:
/opt/network_aware/echo_server -t 300 -n phys-node-1,phys-node-2,phys-node-3
Agent Builder 替换属性变量的方式
Agent Builder 将按如下方式解释属性变量的类型:
148
■
■
■
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
■
将字符串型列表替换为列表中的所有成员,每个字符串由逗号隔开(例如,
phys-node-1,phys-node-2,phys-node-3)。
■
■
重复使用使用 Agent Builder 创建的代码
Agent Builder 使您可以通过以下方式重复使用已完成的工作:
■
■
您可以克隆使用 Agent Builder 创建的现有资源类型。
您可以编辑 Agent Builder 生成的源代码,并重新编译该代码来创建新的软件包。
1. 使用以下方法之一可将现有资源类型装入到 Agent Builder 中:
■
在使用 Agent Builder 创建的现有资源类型的工作目录中启动 Agent Builder。确
保工作目录中包含 rtconfig 文件。Agent Builder 将在“创建”和“配置”屏幕装
入该资源类型的值。
■
装入现有的 Korn shell 资源类型。
将输出语言更改为 C。
单击“创建”以使 Agent Builder 生成该资源类型的 C 版本。
第 9 章 • SunPlex Agent Builder
149
编辑已生成的源代码
为了简化创建资源类型的过程,Agent Builder 限制您可以指定的信息量,从而限制了
生成的资源类型的范围。因此,要添加更多的复杂功能,您需要修改已生成的源代码或
RTR 文件。其他功能的示例包括添加其他属性的验证检查的代码,或调谐 Agent
Builder 不显示的参数的代码。
源文件位于 install-directory/rt-name/src 目录中。Agent Builder 将注释嵌入在源代码
中,您可以在这些注释中添加代码。这些注释的格式如下(针对 C 代码):
/* User added code -- BEGIN vvvvvvvvvvvvvvv */
/* User added code -- END
^^^^^^^^^^^^^^^ */
例如,rt-name.h 声明了不同程序使用的所有实用程序函数。声明列表的结尾处是注
释,通过这些注释您可以声明已添加到代码中的其他函数。
Agent Builder 还可以使用相应的目标在 install_directory/rt_name/src 目录中生成
make 程序的描述文件。使用 make 命令重新编译源代码。使用 make pkg 命令重新生
成资源类型软件包。
RTR 文件位于 install-directory/rt-name/etc 目录中。您可以使用标准的文本编辑器编辑
RTR 文件。有关 RTR 文件的更多信息,请参见第 31 页中的 “设置资源和资源类型属性
”。有关属性的信息,请参见附录 A。
▼
使用 Agent Builder 的命令行版本的方法
Agent Builder 的命令行版本的使用过程与 GUI 相同。但是,与在 GUI 中键入信息不
同,您需要把参数传送到 scdscreate 和 scdsconfig 命令。有关更多信息,请参见
scdscreate(1HA) 和 scdsconfig(1HA) 手册页。
请按照以下步骤使用 Agent Builder 的命令行版本。
步骤
1. 使用 scdscreate 来创建 Sun Cluster 资源类型模板,以便使应用程序具有高可用
性和可伸缩性。
2. 使用 scdsconfig 配置您用 scdscreate 创建的资源类型模板。
您可以指定属性变量。第 147 页中的 “使用属性变量”中介绍了属性变量。
3. 将目录更改为工作目录中的 pkg 子目录。
4. 使用 pkgadd 命令来安装用 scdscreate 创建的软件包。
■
对于区环境中的 Solaris 10 OS,请做为全局区域中的全局管理员键入以下命令:
# pkgadd -G -d . package-name
150
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
对于任何其他版本的 Solaris OS 或非区环境中的 Solaris 10 OS,请键入以下命
令:
# pkgadd -d . package-name
内容
bin
etc
包含 RTR 文件。Agent Builder 并置供应商名称和应用程序名称,两者之间用句点
(.) 进行分隔,从而构成 RTR 文件名。例如,如果供应商名为 SUNW 同时资源类型的
名称为 ftp,则 RTR 文件的名称为 SUNW.ftp。
man
将包含 start、stop 和 remove 实用程序脚本的定制手册页,例如
startftp(1M)、stopftp(1M) 和 removeftp(1M)。
要查看这些手册页,请在指定相应路径时使用 man -M 选项。例如:
% man -M install-directory/SUNWftp/man removeftp
pkg
src
包含 Agent Builder 生成的源文件。
util
包含 Agent Builder 生成的 start、stop 和 remove 实用程序脚本。请参见第
153 页中的 “Sun Agent Builder 创建的实用程序脚本和手册页”。Agent Builder
将应用程序名称附加到以上各个脚本名称上;例如,startftp、stopftp 和
removeftp。
第 9 章 • SunPlex Agent Builder
151
Agent Builder 的输出
源文件和二进制文件
用来管理群集上的资源组并最终管理资源的资源组管理器 (RGM)。RGM 基于回调模型
进行工作。特定事件发生时(例如节点故障),RGM 将为在受影响的节点上运行的每
个资源调用资源类型的方法。例如,RGM 将调用 Stop 方法来停止在受影响节点上运
行的资源,然后再调用该资源的 Start 方法以在其它节点上启动该资源。有关此模型
的更多信息,请参见第 20 页中的 “资源组管理器模型”、第 23 页中的 “回调方法”
和 rt_callbacks(1HA) 手册页。
为了支持该模型,Agent Builder 将在 install-directory/rt-name/bin 目录中生成八个可
执行的 C 程序或 Korn shell 脚本。这些程序或 shell 脚本做为回调方法。
注 – 严格地说,实现故障监视器的 rt-name_probe 程序不是回调程序。RGM 并不直接
调用 rt-name_probe,而是调用 rt-name_monitor_start 和
rt-name_monitor_stop。然后这两种方法通过调用 rt-name_probe 来启动和停止故障
监视器。
下面是 Agent Builder 生成的八种方法:
■
■
■
■
■
■
■
■
rt-name_monitor_check
rt-name_monitor_start
rt-name_monitor_stop
rt-name_probe
rt-name_svc_start
rt-name_svc_stop
rt-name_update
rt-name_validate
有关每种方法的特定信息,请参见 rt_callbacks(1HA) 手册页。
在 install-directory/rt-name/src 目录(C 输出)中,Agent Builder 将生成以下文件:
■
■
■
■
■
头文件 (rt-name.h)
包含所有方法都通用的代码的源文件 (rt-name.c)
通用代码的对象文件 (rt-name.o)
每种方法的源文件 (*.c)
每种方法的对象文件 (*.o)
Agent Builder 将 rt-name.o 文件链接至每个方法 .o 文件以在
install-directory/rt-name/bin 目录中创建可执行文件。
152
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
对于 Korn shell 输出,install-directory/rt-name/bin 和 install-directory/rt-name/src 目
录相同。每个目录都包含八个可执行脚本,分别对应七个回调方法和 Probe 方法。
注 – Korn shell 输出包括两个已编译的实用程序,gettime 和 gethostnames。特殊
回调方法需要使用这些方法来获取时间和进行探测。
■
■
Agent Builder 通过将应用程序名称附加到脚本名称来命名这些脚本。例如,如果应用
程序名为 ftp,则脚本名分别为 startftp、stopftp 和 removeftp。
在 install-directory/rt-name/man/man1m 中,Agent Builder 为每个实用程序脚本都提供
了手册页。启动这些脚本之前,应阅读这些手册页,由于它们记录了需要传送给脚本的
参数。
要查看这些手册页,请通过使用 -M 选项和 man 命令来指定此 man 目录的路径。例如,
如果 SUNW 为供应商,ftp 为应用程序名,则键入以下命令以查看 startftp(1M) 手册
页:
% man -M install-directory/SUNWftp/man startftp
第 9 章 • SunPlex Agent Builder
153
手册页公用程序脚本也可供群集管理员使用。如果 Agent Builder 生成的软件包已安装
在群集上,则实用程序脚本的手册页将位于 /opt/rt-name/man 目录中。例如,键入以
下命令可以查看 startftp(1M) 手册页:
% man -M /opt/SUNWftp/man startftp
Agent Builder 创建的支持文件
Agent Builder 将支持文件(例如 pkginfo、postinstall、postremove 和
preremove)置于 install-directory/rt-name/etc 目录中。此目录还包含资源类型注册
(RTR) 文件。RTR 文件将声明目标资源类型可用的资源和资源类型属性,并在群集中注
册资源时初始化属性值。有关更多信息,请参见第 31 页中的 “设置资源和资源类型属
性”。RTR 文件被命名为 vendor-name.resource-type-name,例如,SUNW.ftp。
您可以在不重新编译源代码的情况下使用标准的文本编辑器编辑此文件并进行更改,但
是,您必须使用 make pkg 命令重建软件包。
Agent Builder 创建的软件包目录
install-directory/rt-name/pkg 目录包含 Solaris 软件包。软件包的名称是供应商名和应用
程序名的串联,例如 SUNWftp。在 install-directory/rt-name/src 中的 make 程序的描
述文件支持新软件包的创建。例如,如果您对源文件进行了更改并重新编译了其代码,
或对软件包实用程序脚本进行了更改,则可以使用 make pkg 命令创建新软件包。
如果您尝试从多个节点同时运行 pkgrm 命令来从群集中删除一个软件包,则该命令将
失败。您可以采用以下两种方法之一来解决此问题:
■
在群集的一个节点上运行 remove rt-name 脚本,然后在任意节点上运行 pkgrm 命
令。
■
rtconfig 文件
如果在工作目录中生成 C 或 Korn shell 源代码,则 Agent Builder 将生成名为
rtconfig 的配置文件。此文件包含您在“创建”和“配置”屏幕上指定的信息。如果从现
有资源类型的工作目录启动 Agent Builder,则 Agent Builder 将读取 rtconfig 文
件。Agent Builder 将把您为现有资源类型提供的信息填充到“创建”和“配置”屏幕中。
如果您通过从“文件”下拉式菜单中选择“装入资源类型”来装入现有资源类型,则 Agent
Builder 将以相似的方式进行工作。当克隆现有资源类型时,此功能非常有用。请参见
第 149 页中的 “重复使用使用 Agent Builder 创建的代码”。
154
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
Agent Builder 的 Cluster Agent 模块
Agent Builder 的 Cluster Agent 模块为 NetBeans™ 模块。此模块提供了 GUI,使用此
GUI 和 Sun Java Studio(以前的 Sun ONE Studio)产品可以为 Sun Cluster 软件创建
资源类型。
注 – Sun Java Studio 文档中包含有关如何设置、安装和使用 Sun Java Studio 产品的信
息。可以在
http://wwws.sun.com/software/sundev/jde/documentation/index.html
Web 站点找到此文档。
▼
安装和设置 Cluster Agent 模块的方法
安装 Sun Cluster 软件时会同时安装 Cluster Agent 模块。Sun Cluster 安装工具将
Cluster Agent 模块文件 scdsbuilder.jar 置于
/usr/cluster/lib/scdsbuilder 中。要将 Cluster Agent 模块与 Sun Java Studio
软件配套使用,您需要创建指向此文件的符号链接。
注 – 在要运行 Cluster Agent 模块的系统上,必须已安装 Sun Cluster 和 Sun Java
Studio 产品以及 Java 1.4,并确保可用。
步骤
1. 允许所有用户或只有您能够使用 Cluster Agent 模块。
■
要使所有用户均能使用该模块,您需要成为超级用户或与此相当的身份,然后在
全局模块目录中创建符号链接。
# cd /opt/s1studio/ee/modules
# ln -s /usr/cluster/lib/scdsbuilder/scdsbuilder.jar
注 – 如果已将 Sun Java Studio 软件安装在 /opt/s1studio/ee 之外的目录,请
用您所用目录的路径代替此目录路径。
■
如果希望只有您自己可以使用该模块,请在您的 modules 子目录中创建符号链
接。
% cd ~your-home-dir/ffjuser40ee/modules
% ln -s /usr/cluster/lib/scdsbuilder/scdsbuilder.jar
2. 停止并重新启动 Sun Java Studio 软件。
第 9 章 • SunPlex Agent Builder
155
▼
启动 Cluster Agent 模块的方法
以下各个步骤介绍了如何从 Sun Java Studio 软件启动 Cluster Agent 模块。
注 – Sun Java Studio 文档中包含有关如何设置、安装和使用 Sun Java Studio 产品的信
息。可以在
http://wwws.sun.com/software/sundev/jde/documentation/index.html
Web 站点找到此文档。
步骤
156
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
3. 从“其他”文件夹中选择 "Sun Cluster Agent Builder" 然后单击“下一步”。
Sun Java Studio 的 Cluster Agent 模块将启动。将显示第一个“新建向导 - Sun
Cluster Agent Builder”屏幕。
第 9 章 • SunPlex Agent Builder
157
使用 Cluster Agent 模块
Cluster Agent 模块的使用方法与 Agent Builder 软件的使用方法相同,而且它们的界面
也是相同的。例如,以下各图分别显示了 Agent Builder 软件的“创建”屏幕和 Cluster
Agent 模块中的第一个“新建向导 - Sun Cluster Agent Builder”屏幕,它们包含有相同
的字段和选项。
158
图 9–4
Agent Builder 软件中的“创建”屏幕
图 9–5
Cluster Agent 模块中的“新建向导 - Sun Cluster Agent Builder”屏幕
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
Cluster Agent 模块和 Agent Builder 之间的区别
虽然 Cluster Agent 模块和 Agent Builder 很相似,但是两者之间仍然存在微小的区别:
■
在 Cluster Agent 模块中,仅在您单击位于第二个“新建向导 - Sun Cluster Agent
Builder”屏幕上的“完成”按钮之后才能创建和配置资源类型。当您单击位于第一
个“新建向导 - Sun Cluster Agent Builder”屏幕上的“下一步”后,该资源类型实际上
并没有创建。
在 Agent Builder 中,在“创建”屏幕上单击“创建”时将立即创建资源类型。此外,
在“配置”屏幕上单击“配置”时,将立即配置资源类型。
■
在 Sun Java Studio 产品中,显示在 Agent Builder 的“输出记录”区域中的信息将显
示在一个单独的窗口中。
第 9 章 • SunPlex Agent Builder
159
160
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
第 10 章
普通数据服务
本章提供有关普通数据服务 (GDS) 方面的信息和说明如何创建使用 GDS 的服务。您可
以使用 SunPlex Agent Builder 或者 Sun Cluster 管理命令创建此服务。
本章包括以下主题:
■
■
■
■
第 161 页中的 “普通数据服务概念”
第 167 页中的 “使用 Agent Builder 创建使用 GDS 的服务”
第 173 页中的 “使用 Sun Cluster 管理命令创建使用 GDS 的服务”
第 174 页中的 “Agent Builder 的命令行界面”
161
预编译的资源类型
SUNWscgds 软件包中包含普通数据服务资源类型 SUNW.gds。scinstall 实用程序将
在群集安装过程中安装此软件包。请参见 scinstall(1M) 手册页。SUNWscgds 软件
包中包含下列文件:
# pkgchk -v SUNWscgds
/opt/SUNWscgds
/opt/SUNWscgds/bin
/opt/SUNWscgds/bin/gds_monitor_check
/opt/SUNWscgds/bin/gds_monitor_start
/opt/SUNWscgds/bin/gds_monitor_stop
/opt/SUNWscgds/bin/gds_probe
/opt/SUNWscgds/bin/gds_svc_start
/opt/SUNWscgds/bin/gds_svc_stop
/opt/SUNWscgds/bin/gds_update
/opt/SUNWscgds/bin/gds_validate
/opt/SUNWscgds/etc
/opt/SUNWscgds/etc/SUNW.gds
使用 GDS 的优点与不足
使用 GDS 与使用 Agent Builder 源代码(请参见 scdscreate(1HA) 手册页)或者
Sun Cluster 管理命令相比,具有以下优点:
■
■
■
■
Agent Builder
Sun Cluster 管理命令
GDS 和 Agent Builder
使用 Agent Builder 并选择 GDS 作为生成源代码的类型。使用用户输入的内容生成一组
脚本,以便为给定的应用程序配置资源。
162
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
GDS 和 Sun Cluster 管理命令
此方法使用 SUNWscgds 中的预编译数据服务代码。但是,群集管理员必须使用 Sun
Cluster 管理命令来创建和配置资源。请参见 scrgadm(1M) 和 scswitch(1M) 手册
页。
选择创建基于 GDS 的服务时所应使用的方法
发布正确的 scrgadm 和 scswitch 命令需要键入大量内容。例如,请参见第 173 页中
的 “如何使用 Sun Cluster 管理命令来创建使用 GDS 且具有高可用性的服务”和第 174
页中的 “如何使用 Sun Cluster 管理命令来创建使用 GDS 的可伸缩服务”。
将 GDS 与 Agent Builder 结合使用可以简化此进程,因为它将为您生成用于发布
scrgadm 和 scswitch 命令的脚本。
GDS 日志文件
以下两个 GDS 日志文件放置于
/var/cluster/logs/DS/resource-group-name/resource-name 目录下:
■
■
start_stop_log.txt,包含由资源启动和停止方法生成的消息
probe_log.txt,包含由资源监视器生成的消息
以下示例显示了 start_stop_log.txt 包含的信息类型:
10/20/2005 12:38:05 phys-node-1 START-INFO> Start succeeded. [/home/brianx/sc/start_cmd]
10/20/2005 12:42:11 phys-node-1 STOP-INFO> Successfully stopped the application
以下示例显示了 probe_log.txt 包含的信息类型:
10/20/2005
10/20/2005
10/20/2005
10/20/2005
12:38:15
12:39:15
12:40:15
12:41:15
phys-node-1
phys-node-1
phys-node-1
phys-node-1
PROBE-INFO>
PROBE-INFO>
PROBE-INFO>
PROBE-INFO>
The
The
The
The
GDS monitor (gds_probe) has been started
probe result is 0
probe result is 0
probe result is 0
163
Start_command 扩展属性
您在 Start_command 扩展属性中指定的 start 命令将启动应用程序。此命令必须为可
直接传递给 shell 启动应用程序的带参数的 UNIX 命令。
Port_list 属性
Port_list 属性将标识应用程序进行侦听的端口列表。Port_list 属性必须根据由
Agent Builder 创建的启动脚本指定,或是根据 scrgadm 命令指定(如果使用的是 Sun
Cluster 管理命令)。
Network_resources_used 属性
Stop_command 扩展属性
Probe_command 扩展属性
Start_timeout 属性
Stop_timeout 属性
Probe_timeout 扩展属性
Child_mon_level 扩展属性(只与管理命令一起使用)
Failover_enabled 扩展属性
Stop_signal 扩展属性
Log_level 扩展属性
Network_resources_used 属性
此属性的默认值为 Null。如果应用程序需要绑定到一个或多个特定的地址,则必须指定
此属性。如果忽略此属性或将其指定为 Null,则应用程序会被认为是侦听所有地址。
创建 GDS 资源之前,必须已配置 LogicalHostname 或 SharedAddress 资源。有关
如何配置 LogicalHostname 或 SharedAddress 资源的信息,请参见《Sun Cluster
Data Services Planning and Administration Guide for Solaris OS》。
要指定一个值,请指定一个或多个资源名称。每个资源名称可以包含一个或多个
LogicalHostname 资源或 SharedAddress 资源。有关详细信息,请参见
r_properties(5) 手册页。
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
Start_timeout 属性
此属性用于指定 start 命令的启动超时。有关附加信息,请参见第 164 页中的
“Start_command 扩展属性”。Start_timeout 的默认值为 300 秒。
Stop_timeout 属性
此属性用于指定 stop 命令的停止超时。有关附加信息,请参见第 164 页中的
“Stop_command 属性”。Stop_timeout 的默认值为 300 秒。
Probe_timeout 属性
此属性用于指定 probe 命令的超时值。有关附加信息,请参见第 165 页中的
“Probe_command 属性”。Probe_timeout 的默认值为 30 秒。
第 10 章 • 普通数据服务
165
Child_mon_level 属性
注 – 如果使用 Sun Cluster 管理命令,则可以使用 Child_mon_level 属性。如果使用
Agent Builder,则不能使用此属性。
Failover_enabled 属性
此 Boolean 扩展属性用于控制资源的故障转移行为。如果将该扩展属性设置为 TRUE,
则当应用程序在 Retry_interval 秒内重新启动的次数超出 Retry_count 次,此应
用程序就将故障转移。
如果将此扩展属性设置为 FALSE,则当应用程序在 Retry_interval 秒内重新启动的
次数超出 Retry_count 次,此应用程序将不重新启动或故障转移至其他节点上。
您可以使用此属性禁止应用程序资源启动资源组故障转移。此属性的默认值为 TRUE。
Stop_signal 属性
GDS 使用整数扩展属性值来确定用于通过 PMF 停止应用程序的信号。有关可以指定的
整数值列表,请参见 signal(3HEAD) 手册页。默认值为 15 (SIGTERM)。
166
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
使用 Agent Builder 创建使用 GDS 的服
务
可以使用 Agent Builder 创建使用 GDS 的服务。第 9 章中对 Agent Builder 进行了详细
介绍。
创建和配置基于 GDS 的脚本
▼ 如何启动 Agent Builder 和创建脚本
步骤
1. 成为超级用户或作为等效角色。
2. 启动 Agent Builder。
# /usr/cluster/bin/scdsbuilder
3. 将显示 Agent Builder 的“创建”屏幕。
167
168
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
169
170
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
将创建该脚本的软件包,并将其放置在以下目录中:
working-dir/vendor-name-application/pkg
对于分区域环境中的 Solaris 10 OS,请以全局区域中的全局管理员身份键入以下
命令:
# cd /export/wdir/NETapp/pkg
# pkgadd -G -d . NETapp
指定的软件包将被添加到全局区域中,前提为软件包的内容不影响与非全局区域
共享的全局区域的任何一部分。
以下是 pkgadd 安装的文件:
/opt/NETapp
/opt/NETapp/README.app
/opt/NETapp/man
/opt/NETapp/man/man1m
/opt/NETapp/man/man1m/removeapp.1m
/opt/NETapp/man/man1m/startapp.1m
/opt/NETapp/man/man1m/stopapp.1m
/opt/NETapp/man/man1m/app_config.1m
/opt/NETapp/util
/opt/NETapp/util/removeapp
/opt/NETapp/util/startapp
/opt/NETapp/util/stopapp
/opt/NETapp/util/app_config
■
对于非区域环境中其他版本的 Solaris OS 或 Solaris 10 OS,请键入以下命令:
# cd /export/wdir/NETapp/pkg
# pkgadd -d . NETapp
以下是 pkgadd 安装的文件:
/opt/NETapp
/opt/NETapp/README.app
/opt/NETapp/man
/opt/NETapp/man/man1m
/opt/NETapp/man/man1m/removeapp.1m
/opt/NETapp/man/man1m/startapp.1m
/opt/NETapp/man/man1m/stopapp.1m
/opt/NETapp/man/man1m/app_config.1m
/opt/NETapp/util
/opt/NETapp/util/removeapp
/opt/NETapp/util/startapp
/opt/NETapp/util/stopapp
/opt/NETapp/util/app_config
171
名称之后(例如 startapp)。
8. 在群集的一个节点上,配置资源并启动应用程序。
# /opt/NETapp/util/startapp -h logicalhostname -p port-and-protocol-list
带任何参数以显示用法语句。
若要查看手册页,需要指定手册页的路径。例如,要查看 startapp(1M) 手册页,
请键入:
# man -M /opt/NETapp/man startapp
要显示用法语句,请键入:
# /opt/NETapp/util/startapp
The resource name of LogicalHostname or SharedAddress must be
specified. For failover services:
Usage: startapp -h logicalhostname
-p port-and-protocol-list
[-n ipmpgroup-adapter-list]
For scalable services:
Usage: startapp -h shared-address-name
-p port-and-protocol-list
[-l load-balancing-policy]
[-n ipmpgroup/adapter-list]
[-w load-balancing-weights]
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
▼
步骤
如何使用 Sun Cluster 管理命令来创建使用 GDS 且
具有高可用性的服务
1. 成为超级用户或作为等效角色。
2. 注册资源类型 SUNW.gds。
# scrgadm -a -t SUNW.gds
3. 创建资源组,其中包含 LogicalHostname 资源和故障转移服务本身。
# scrgadm -a -g haapp_rg
4. 为 LogicalHostname 资源创建资源。
# scrgadm -a -L -g haapp_rs -l hhead
5. 为故障转移服务本身创建资源。
# scrgadm -a -j haapp_rs -g haapp_rg -t SUNW.gds \
-y Scalable=false -y Start_timeout=120 \
-y Stop_timeout=120 -x Probe_timeout=120 \
-y Port_list="2222/tcp" \
-x Start_command="/export/ha/appctl/start" \
-x Stop_command="/export/ha/appctl/stop" \
-x Probe_command="/export/app/bin/probe" \
-x Child_mon_level=0 -y Network_resources_used=hhead \
-x Failover_enabled=TRUE -x Stop_signal=9
6. 将资源组 haapp_rg 联机。
# scswitch -Z -g haapp_rg
173
▼
步骤
如何使用 Sun Cluster 管理命令来创建使用 GDS 的
可伸缩服务
1. 成为超级用户或作为等效角色。
2. 注册资源类型 SUNW.gds。
# scrgadm -a -t SUNW.gds
3. 为 SharedAddress 资源创建资源组。
# scrgadm -a -g sa_rg
4. 在 sa_rg 上创建 SharedAddress 资源。
# scrgadm -a -S -g sa_rg -l hhead
5. 为可伸缩服务创建资源组。
# scrgadm -a -g app_rg -y Maximum_primaries=2 \
-y Desired_primaries=2 -y RG_dependencies=sa_rg
6. 为可伸缩服务创建资源。
# scrgadm
-y
-y
-y
-x
-x
-x
-x
-x
-a -j app_rs -g app_rg -t SUNW.gds \
Scalable=TRUE -y Start_timeout=120 \
Stop_timeout=120 -x Probe_timeout=120 \
Port_list="2222/tcp" \
Start_command="/export/app/bin/start" \
Stop_command="/export/app/bin/stop" \
Probe_command="/export/app/bin/probe" \
Child_mon_level=0 -y Network_resource_used=hhead \
Failover_enabled=TRUE -x Stop_signal=9
7. 将包含网络资源的资源组联机。
# scswitch -Z -g sa_rg
8. 将资源组 app_rg 联机。
# scswitch -Z -g app_rg
Agent Builder 的命令行界面
Agent Builder 集成了一个命令行界面,该命令行界面与 GUI 提供的功能相同。此界面
由 scdscreate 和 scdsconfig 命令组成。请参见 scdscreate(1HA) 和
scdsconfig(1HA) 手册页。
174
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
▼
如何使用命令行版本的 Agent Builder 创建使用
GDS 的服务
本节介绍了如何使用命令行界面执行第 167 页中的 “使用 Agent Builder 创建使用 GDS
的服务”中所示的同一组步骤。
步骤
对于故障转移服务,请键入:
# scdscreate -g -V NET -T app -d /export/wdir
■
对于可伸缩服务,请键入:
# scdscreate -g -s -V NET -T app -d /export/wdir
3. 配置服务。
# scdsconfig -s "/export/app/bin/start" -t "/export/app/bin/stop" \
-m "/export/app/bin/probe" -d /export/wdir
对于分区域环境中的 Solaris 10 OS,请以全局区域中的全局管理员身份键入以下
命令:
# cd /export/wdir/NETapp/pkg
# pkgadd -G -d . NETapp
指定的软件包将被添加到全局区域中,前提为软件包的内容不影响与非全局区域
共享的全局区域的任何一部分。
以下是 pkgadd 安装的文件:
/opt/NETapp
/opt/NETapp/README.app
/opt/NETapp/man
/opt/NETapp/man/man1m
/opt/NETapp/man/man1m/removeapp.1m
/opt/NETapp/man/man1m/startapp.1m
/opt/NETapp/man/man1m/stopapp.1m
/opt/NETapp/man/man1m/app_config.1m
第 10 章 • 普通数据服务
175
/opt/NETapp/util
/opt/NETapp/util/removeapp
/opt/NETapp/util/startapp
/opt/NETapp/util/stopapp
/opt/NETapp/util/app_config
■
对于非区域环境中其他版本的 Solaris OS 或 Solaris 10 OS,请键入以下命令:
# cd /export/wdir/NETapp/pkg
# pkgadd -d . NETapp
以下是 pkgadd 安装的文件:
/opt/NETapp
/opt/NETapp/README.app
/opt/NETapp/man
/opt/NETapp/man/man1m
/opt/NETapp/man/man1m/removeapp.1m
/opt/NETapp/man/man1m/startapp.1m
/opt/NETapp/man/man1m/stopapp.1m
/opt/NETapp/man/man1m/app_config.1m
/opt/NETapp/util
/opt/NETapp/util/removeapp
/opt/NETapp/util/startapp
/opt/NETapp/util/stopapp
/opt/NETapp/util/app_config
名称之后(例如 startapp)。
5. 在群集的一个节点上,配置资源并启动应用程序。
# /opt/NETapp/util/startapp -h logicalhostname -p port-and-protocol-list
176
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
若要查看手册页,需要指定手册页的路径。例如,要查看 startapp(1M) 手册页,
请键入:
# man -M /opt/NETapp/man startapp
要显示用法语句,请键入:
# /opt/NETapp/util/startapp
The resource name of LogicalHostname or SharedAddress must be specified.
For failover services:
Usage: startapp -h logicalhostname
-p port-and-protocol-list
[-n ipmpgroup/adapter-list]
For scalable services:
Usage: startapp -h shared-address-name
-p port-and-protocol-list
[-l load-balancing-policy]
[-n ipmpgroup/adapter-list]
[-w load-balancing-weights]
177
178
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
第 11 章
scds_initialize(3HA) – 分配资源和初始化 DSDL 环境。
scds_close(3HA) – 释放由 scds_initialize() 分配的资源。
179
scds_get_resource_type_name(3HA) – 检索用于调用程序的资源类型的名称。
scds_get_resource_name(3HA) – 检索用于调用程序的资源的名称。
scds_get_resource_group_name(3HA) – 检索用于调用程序的资源组的名称。
scds_get_ext_property(3HA) – 检索指定扩展属性的值。
scds_free_ext_property(3HA) – 释放由 scds_get_ext_property() 分配
的内存。
以下函数用于检索关于资源所使用的 SUNW.HAStoragePlus 资源的状态信息:
scds_hasp_check(3HA) – 检索关于资源所使用的 SUNW.HAStoragePlus 资源的状
态信息。此信息来自资源所依赖的所有 SUNW.HAStoragePlus 资源的状态(联机或脱
机),是通过使用为该资源定义的 Resource_dependencies 或
Resource_dependencies_weak 系统属性获得的。有关更多信息,请参见
SUNW.HAStoragePlus(5) 手册页。
scds_failover_rg(3HA) – 故障转移资源组。
scds_restart_rg(3HA) – 重新启动资源组。
scds_restart_resource(3HA) – 重新启动资源。
scds_timerun(3HA) – 在超时值定义的时间内执行命令。
scds_error_string(3HA) – 将错误代码翻译为错误字符串。
180
scds_get_rt_property-name
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
■
■
■
scds_get_rs_property-name
scds_get_rg_property-name
scds_get_ext_property-name
网络资源访问函数
本节列出的函数用于检索、打印和释放由资源和资源组使用的网络资源。本节中的
scds_get_ 函数提供了一种便捷的检索网络资源的方法,该方法无需使用 RMAPI 函
数即可查询具体属性(例如 Network_resources_used 和 Port_list)。
scds_print_name() 函数用于打印来自 scds_get_name () 函数所返回的数据结构
的值。scds_free_name () 函数用于释放 scds_get_ name() 函数所分配的内存。
scds_get_rs_hostnames(3HA) – 检索由资源使用的主机名列表。
■
scds_get_rg_hostnames(3HA) – 检索由资源组中的网络资源使用的主机名列
表。
■
scds_print_net_list(3HA) – 打印由 scds_get_rs_hostnames() 函数或
scds_get_rg_hostnames() 函数返回的主机名列表的内容。
■
scds_free_net_list(3HA) – 释放由 scds_get_rs_hostnames() 函数或
scds_get_rg_hostnames() 函数分配的内存。
scds_get_port_list(3HA) – 检索由资源使用的端口-协议对列表。
■
scds_print_port_list(3HA) – 打印由 scds_get_port_list() 返回的端
口-协议对列表的内容。
■
scds_free_port_list(3HA) – 释放由 scds_get_port_list() 分配的内存。
scds_get_netaddr_list(3HA) – 检索由资源使用的网络地址列表。
第 11 章 • DSDL API 函数
181
■
scds_print_netaddr_list(3HA) – 打印由 scds_get_netaddr_list() 返回
的网络地址列表的内容。
■
scds_free_netaddr_list(3HA) – 释放由 scds_get_netaddr_list() 分配
的内存。
scds_fm_tcp_connect(3HA) – 与仅使用 IPv4 寻址的进程建立 TCP 连接。
■
scds_fm_net_connect(3HA) – 与使用 IPv4 或 IPv6 寻址的进程建立 TCP 连接。
■
scds_fm_tcp_read(3HA) – 使用 TCP 连接从被监视的进程中读取数据。
■
scds_fm_tcp_write(3HA) – 使用 TCP 连接向被监视的进程写入数据。
■
scds_simple_probe(3HA) – 通过建立和终止与进程的 TCP 连接来探测进程。此
函数只能处理 IPv4 地址。
■
scds_simple_net_probe(3HA) – 通过建立和终止与进程的 TCP 连接来探测进
程。此函数可以处理 IPv4 或 IPv6 地址。
■
scds_fm_tcp_disconnect(3HA) – 终止与被监视进程的连接。此函数只能处理
IPv4 地址。
■
scds_fm_net_disconnect(3HA) – 终止与被监视进程的连接。此函数可以处理
IPv4 或 IPv6 地址。
PMF 函数
这些函数封装了进程监视器工具 (PMF) 的功能。通过 PMF 进行监视的 DSDL 模型用于
创建和使用 pmfadm 的隐含 tag 值。有关更多信息,请参见 pmfadm(1M) 手册页。
PMF 工具还使用 Restart_interval、Retry_count 和 action_script
(pmfadm 的 -t、-n 和 -a 选项)的隐含值。最重要的是,DSDL 将由 PMF 确定的进
程故障历史记录与由故障监视器检测到的应用程序故障历史记录相结合,来确定重新启
动或故障转移决策。
此函数集包括以下函数:
■
■
182
scds_pmf_get_status(3HA) – 确定指定实例是否正在 PMF 的控制下受到监视。
scds_pmf_restart_fm(3HA) – 使用 PMF 来重新启动故障监视器。
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
■
■
■
■
scds_pmf_signal(3HA) – 向在 PMF 的控制下运行的进程树发送指定信号。
scds_pmf_start(3HA) – 执行在 PMF 的控制下的指定程序(包括故障监视器)。
scds_pmf_stop(3HA) – 终止在 PMF 的控制下运行的进程。
scds_pmf_stop_monitoring(3HA) – 停止监视在 PMF 的控制下运行的进程。
scds_fm_sleep(3HA) – 等待关于故障监视器控制套接字的消息。
scds_fm_action(3HA) – 探测完成后采取措施。
scds_fm_print_probes(3HA) – 向系统日志写入探测状态信息。
scds_syslog(3HA) – 向系统日志写入消息。
scds_syslog_debug(3HA) – 向系统日志写入调试消息。
第 11 章 • DSDL API 函数
183
184
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
第 12 章
185
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
187
说明
188
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
189
类和子类
名称和值对
说明
EC_Cluster
必需:无
ESC_cluster_membership
可选:无
EC_Cluster
ESC_cluster_rg_state
rg_name
值类型:字符串
可选:无
EC_Cluster
ESC_cluster_r_state
r_name
值类型:字符串
可选:无
EC_Cluster
必需:无
无
可选:无
注册所有 Sun Cluster 事件
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
1.
2.
3.
4.
5.
6.
7.
说明
OK
RETRY
LOW_RESOURCE
SYSTEM_ERROR
FAIL
MALFORMED
INVALID
VERSION_TOO_HIGH
VERSION_TOO_LOW
191
■
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
193
类和子类
名称和值对
EC_Cluster
发行商:rgm
名称:node_list
ESC_cluster_membership 卖主:SUNW
EC_Cluster
发行商:rgm
名称:rg_name
ESC_cluster_rg_state
卖主:SUNW
值类型:字符串
名称:node_list
值类型:字符串数组
名称:state_list
state_list 包含资源组状态的字符串表示。有效值为
可用 scha_cmds(1HA) 命令检索到的值。
值类型:字符串数组
EC_Cluster
发行商:rgm
名称:r_name
ESC_cluster_r_state
卖主:SUNW
值类型:字符串
名称:node_list
值类型:字符串数组
名称:state_list
state_list 包含资源状态的字符串表示。有效值为可
用 scha_cmds(1HA) 命令检索到的值。
值类型:字符串数组
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
▼
步骤
■
样例应用程序将使用 JAXP(用于 XML 处理的 Java API)生成和解析 XML。此示例
不显示如何使用 JAXP。http://java.sun.com/xml/jaxp/index.html 中对
JAXP 进行了详细介绍。
■
■
■
如何设置环境
1. 下载并安装 JAXP 以及 Java 编译器和虚拟机的正确版本。
可在 http://java.sun.com/xml/jaxp/index.html 中找到说明。
注 – 此示例至少要使用 Java 1.3.1。
195
2. 在资源文件所在的目录中键入:
% javac -classpath jaxp-root/dom.jar:jaxp-rootjaxp-api. \
jar:jaxp-rootsax.jar:jaxp-rootxalan.jar:jaxp-root/xercesImpl \
.jar:jaxp-root/xsltc.jar -sourcepath . source-filename.java
其中,jaxp-root 为 JAXP jar 文件所在目录的绝对路径或相对路径,source-filename 为
Java 资源文件的名称。
编译命令行中的 classpath 用于确保编译器可以找到 JAXP 类。
3. 运行应用程序时,请指定 classpath 以使应用程序可以加载正确的 JAXP 类文件
(注意,classpath 中的第一个路径是当前目录):
% java -cp .:jaxp-root/dom.jar:jaxp-rootjaxp-api. \
jar:jaxp-rootsax.jar:jaxp-rootxalan.jar:jaxp-root/xercesImpl \
.jar:jaxp-root/xsltc.jar source-filename arguments
▼
步骤
以下实例显示了 CrnpClient 类的骨架代码。本章稍后将列出在构造函数和关闭方
法中引用的四个帮助器方法的实现。请注意,将列出导入所需的所有软件包的代码。
import
import
import
import
import
import
import
import
import
import
javax.xml.parsers.*;
javax.xml.transform.*;
javax.xml.transform.dom.*;
javax.xml.transform.stream.*;
org.xml.sax.*;
org.xml.sax.helpers.*;
org.w3c.dom.*;
java.net.*;
java.io.*;
java.util.*;
class CrnpClient
{
public static void main(String []args)
{
InetAddress regIp = null;
196
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
int regPort = 0, localPort = 0;
try {
regIp = InetAddress.getByName(args[0]);
regPort = (new Integer(args[1])).intValue();
localPort = (new Integer(args[2])).intValue();
} catch (UnknownHostException e) {
System.out.println(e);
System.exit(1);
}
CrnpClient client = new CrnpClient(regIp, regPort,
localPort, args);
System.out.println("Hit return to terminate demo...");
try {
System.in.read();
} catch (IOException e) {
System.out.println(e.toString());
}
client.shutdown();
System.exit(0);
}
public CrnpClient(InetAddress regIpIn, int regPortIn,
int localPortIn, String []clArgs)
{
try {
regIp = regIpIn;
regPort = regPortIn;
localPort = localPortIn;
regs = clArgs;
setupXmlProcessing();
createEvtRecepThr();
registerCallbacks();
} catch (Exception e) {
System.out.println(e.toString());
System.exit(1);
}
}
public void shutdown()
{
try {
unregister();
} catch (Exception e) {
System.out.println(e);
System.exit(1);
}
}
private InetAddress regIp;
private int regPort;
private EventReceptionThread evtThr;
private String regs[];
public int localPort;
public DocumentBuilderFactory dbf;
}
第 12 章 • 群集重新配置通知协议
197
▼
步骤
▼
步骤
1. 在代码中,将定义名为 EventReceptionThread 的 Thread 子类,它用于创建
ServerSocket 和等待事件到达套接字。
在实例代码的这一部分,既没有读取事件也没有处理事件。本章稍后将讨论如何读取
和处理事件。EventReceptionThread 用于在通配符网络互联协议地址上创建
ServerSocket。EventReceptionThread 还引用了 CrnpClient 对象,以使
EventReceptionThread 能够向 CrnpClient 对象发送要处理的事件。
class EventReceptionThread extends Thread
{
public EventReceptionThread(CrnpClient clientIn) throws IOException
{
client = clientIn;
listeningSock = new ServerSocket(client.localPort, 50,
InetAddress.getLocalHost());
}
public void run()
{
try {
DocumentBuilder db = client.dbf.newDocumentBuilder();
db.setErrorHandler(new DefaultHandler());
while(true) {
Socket sock = listeningSock.accept();
// Construct event from the sock stream and process it
sock.close();
}
// UNREACHABLE
} catch (Exception e) {
System.out.println(e);
198
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
System.exit(1);
}
}
/* private member variables */
private ServerSocket listeningSock;
private CrnpClient client;
}
2. 构造 createEvtRecepThr 对象。
private void createEvtRecepThr() throws Exception
{
evtThr = new EventReceptionThread(this);
evtThr.start();
}
▼
步骤
1. 创建实现上述逻辑的 Java 代码。
以下示例代码显示了 CrnpClient 类(由 CrnpClient 构造函数调用)的
registerCallbacks 方法的实现。本章稍后将对
createRegistrationString() 和 readRegistrationReply() 的调用进行
详细介绍。
regIp 和 regPort 是由构造函数设置的对象成员。
private void registerCallbacks() throws Exception
{
Socket sock = new Socket(regIp, regPort);
String xmlStr = createRegistrationString();
PrintStream ps = new
PrintStream(sock.getOutputStream());
ps.print(xmlStr);
readRegistrationReply(sock.getInputStream();
sock.close();
}
2. 实现 unregister 方法。
此方法由 CrnpClient 的 shutdown 方法调用。本章稍后将对
createUnregistrationString 的实现进行详细介绍。
private void unregister() throws Exception
{
第 12 章 • 群集重新配置通知协议
199
Socket sock = new Socket(regIp, regPort);
String xmlStr = createUnregistrationString();
PrintStream ps = new PrintStream(sock.getOutputStream());
ps.print(xmlStr);
readRegistrationReply(sock.getInputStream());
sock.close();
}
▼
如何生成 XML
至此,已设置应用程序的结构并写入了所有联网代码,您需要写入生成和解析 XML 的
代码。开始先写入生成 SC_CALLBACK_REG XML 注册消息的代码。
SC_CALLBACK_REG 消息包括注册类型(ADD_CLIENT、REMOVE_CLIENT、
ADD_EVENTS 或 REMOVE_EVENTS)、回调端口和感兴趣的事件列表。每个事件都包括
一个类和一个子类,后跟一个名称和值对列表。
在实例的这一部分,需要编写一个存储注册类型、回调端口和注册事件列表的
CallbackReg 类。此类还可将自身序列化为 SC_CALLBACK_REG XML 消息。
此类中有一个有趣的方法,即 convertToXml 方法,它可以从类成员中创建一个
SC_CALLBACK_REG XML 消息字符
串。http://java.sun.com/xml/jaxp/index.html 中的 JAXP 文档详细说明了
此方法中的代码。
以下示例代码中显示了 Event 类的实现。请注意,CallbackReg 类使用了 Event
类,该类用于存储一个事件并可将该事件转换为 XML Element。
步骤
class CallbackReg
{
public static
public static
public static
public static
final
final
final
final
int
int
int
int
ADD_CLIENT = 0;
ADD_EVENTS = 1;
REMOVE_EVENTS = 2;
REMOVE_CLIENT = 3;
public CallbackReg()
{
port = null;
regType = null;
regEvents = new Vector();
}
public void setPort(String portIn)
{
port = portIn;
}
public void setRegType(int regTypeIn)
200
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
{
switch (regTypeIn) {
case ADD_CLIENT:
regType = "ADD_CLIENT";
break;
case ADD_EVENTS:
regType = "ADD_EVENTS";
break;
case REMOVE_CLIENT:
regType = "REMOVE_CLIENT";
break;
case REMOVE_EVENTS:
regType = "REMOVE_EVENTS";
break;
default:
System.out.println("Error, invalid regType " +
regTypeIn);
regType = "ADD_CLIENT";
break;
}
}
public void addRegEvent(Event regEvent)
{
regEvents.add(regEvent);
}
public String convertToXml()
{
Document document = null;
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
try {
DocumentBuilder builder = factory.newDocumentBuilder();
document = builder.newDocument();
} catch (ParserConfigurationException pce) {
// Parser with specified options can’t be built
pce.printStackTrace();
System.exit(1);
}
// Create the root element
Element root = (Element) document.createElement("SC_CALLBACK_REG");
// Add the attributes
root.setAttribute("VERSION", "1.0");
root.setAttribute("PORT", port);
root.setAttribute("regType", regType);
// Add the events
for (int i = 0; i < regEvents.size(); i++) {
Event tempEvent = (Event)
(regEvents.elementAt(i));
root.appendChild(tempEvent.createXmlElement(document));
}
第 12 章 • 群集重新配置通知协议
201
document.appendChild(root);
// Convert the whole thing to a string
DOMSource domSource = new DOMSource(document);
StringWriter strWrite = new StringWriter();
StreamResult streamResult = new StreamResult(strWrite);
TransformerFactory tf = TransformerFactory.newInstance();
try {
Transformer transformer = tf.newTransformer();
transformer.transform(domSource, streamResult);
} catch (TransformerException e) {
System.out.println(e.toString());
return ("");
}
return (strWrite.toString());
}
private String port;
private String regType;
private Vector regEvents;
}
2. 实现 Event 和 NVPair 类。
请注意,CallbackReg 类使用了 Event 类,而该类自身使用了 NVPair 类。
class Event
{
public Event()
{
regClass = regSubclass = null;
nvpairs = new Vector();
}
public void setClass(String classIn)
{
regClass = classIn;
}
public void setSubclass(String subclassIn)
{
regSubclass = subclassIn;
}
public void addNvpair(NVPair nvpair)
{
nvpairs.add(nvpair);
}
public Element createXmlElement(Document doc)
{
Element event = (Element)
doc.createElement("SC_EVENT_REG");
event.setAttribute("CLASS", regClass);
if (regSubclass != null) {
202
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
event.setAttribute("SUBCLASS", regSubclass);
}
for (int i = 0; i < nvpairs.size(); i++) {
NVPair tempNv = (NVPair)
(nvpairs.elementAt(i));
event.appendChild(tempNv.createXmlElement(doc));
}
return (event);
}
private String regClass, regSubclass;
private Vector nvpairs;
}
class NVPair
{
public NVPair()
{
name = value = null;
}
public void setName(String nameIn)
{
name = nameIn;
}
public void setValue(String valueIn)
{
value = valueIn;
}
public Element createXmlElement(Document doc)
{
Element nvpair = (Element)
doc.createElement("NVPAIR");
Element eName = doc.createElement("NAME");
Node nameData = doc.createCDATASection(name);
eName.appendChild(nameData);
nvpair.appendChild(eName);
Element eValue = doc.createElement("VALUE");
Node valueData = doc.createCDATASection(value);
eValue.appendChild(valueData);
nvpair.appendChild(eValue);
return (nvpair);
}
private String name, value;
}
203
▼
如何创建注册消息和取消注册消息
请注意,创建生成 XML 消息的帮助器类之后,您可以向
createRegistrationString 方法的实现写入数据。此方法由
registerCallbacks 方法(第 199 页中的 “如何注册和取消注册回调”中介绍了该
方法)调用。
createRegistrationString 构造一个 CallbackReg 对象并设置其注册类型和端
口。然后,createRegistrationString 通过使用 createAllEvent、
createMembershipEvent、createRgEvent 和 createREvent 帮助器方法构造各
种事件。创建 CallbackReg 对象后,每个事件都被添加到该对象中。最后,
createRegistrationString 对 CallbackReg 对象调用 convertToXml 方法,以
便在 String 表单中检索 XML 消息。
请注意,regs 成员变量用于存储用户提供给应用程序的命令行参数。第五个参数及后
续参数用于指定应用程序应该注册的事件。第四个参数用于指定注册的类型,但本实例
中忽略了该参数。附录 G 中的完整代码显示了如何使用第四个参数。
步骤
private String createRegistrationString() throws Exception
{
CallbackReg cbReg = new CallbackReg();
cbReg.setPort("" + localPort);
cbReg.setRegType(CallbackReg.ADD_CLIENT);
// add the events
for (int i = 4; i < regs.length; i++) {
if (regs[i].equals("M")) {
cbReg.addRegEvent(createMembershipEvent());
} else if (regs[i].equals("A")) {
cbReg.addRegEvent(createAllEvent());
} else if (regs[i].substring(0,2).equals("RG")) {
cbReg.addRegEvent(createRgEvent(regs[i].substring(3)));
} else if (regs[i].substring(0,1).equals("R")) {
cbReg.addRegEvent(createREvent(regs[i].substring(2)));
}
}
String xmlStr = cbReg.convertToXml();
return (xmlStr);
}
private Event createAllEvent()
{
Event allEvent = new Event();
allEvent.setClass("EC_Cluster");
return (allEvent);
}
private Event createMembershipEvent()
204
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
{
Event membershipEvent = new Event();
membershipEvent.setClass("EC_Cluster");
membershipEvent.setSubclass("ESC_cluster_membership");
return (membershipEvent);
}
private Event createRgEvent(String rgname)
{
Event rgStateEvent = new Event();
rgStateEvent.setClass("EC_Cluster");
rgStateEvent.setSubclass("ESC_cluster_rg_state");
NVPair rgNvpair = new NVPair();
rgNvpair.setName("rg_name");
rgNvpair.setValue(rgname);
rgStateEvent.addNvpair(rgNvpair);
return (rgStateEvent);
}
private Event createREvent(String rname)
{
Event rStateEvent = new Event();
rStateEvent.setClass("EC_Cluster");
rStateEvent.setSubclass("ESC_cluster_r_state");
NVPair rNvpair = new NVPair();
rNvpair.setName("r_name");
rNvpair.setValue(rname);
rStateEvent.addNvpair(rNvpair);
return (rStateEvent);
}
2. 创建撤销注册字符串。
创建取消注册字符串比创建注册字符串容易,因为您不必提供事件。
private String createUnregistrationString() throws Exception
{
CallbackReg cbReg = new CallbackReg();
cbReg.setPort("" + localPort);
cbReg.setRegType(CallbackReg.REMOVE_CLIENT);
String xmlStr = cbReg.convertToXml();
return (xmlStr);
}
▼
如何设置 XML 解析器
现在已经为应用程序创建了联网和 XML 生成代码。CrnpClient 构造函数将调用
setupXmlProcessing 方法。此方法将创建 DocumentBuilderFactory 对象,并
在该对象上设置各种解析属性。JAXP 文档详细介绍了此方法。请参见
http://java.sun.com/xml/jaxp/index.html。
第 12 章 • 群集重新配置通知协议
205
步骤
● 创建实现上述逻辑的 Java 代码。
private void setupXmlProcessing() throws Exception
{
dbf = DocumentBuilderFactory.newInstance();
// We don’t need to bother validating
dbf.setValidating(false);
dbf.setExpandEntityReferences(false);
// We want to ignore comments and whitespace
dbf.setIgnoringComments(true);
dbf.setIgnoringElementContentWhitespace(true);
// Coalesce CDATA sections into TEXT nodes.
dbf.setCoalescing(true);
}
▼
如何解析注册回复
要解析 SC_REPLY XML 消息(CRNP 服务器发送的响应注册或取消注册消息),需要
使用 RegReply 帮助器类。可以从 XML 文档构造此类。此类提供了状态代码和状态消
息的访问程序。要解析来自服务器的 XML 流,需要创建新的 XML 文档并使用该文档的
解析方法。http://java.sun.com/xml/jaxp/index.html 中的 JAXP 文档详细
介绍了此方法。
步骤
1. 创建实现上述逻辑的 Java 代码。
请注意,readRegistrationReply 方法使用新的 RegReply 类。
private void readRegistrationReply(InputStream stream) throws Exception
{
// Create the document builder
DocumentBuilder db = dbf.newDocumentBuilder();
db.setErrorHandler(new DefaultHandler());
//parse the input file
Document doc = db.parse(stream);
RegReply reply = new RegReply(doc);
reply.print(System.out);
}
2. 实现 RegReply 类。
请注意,retrieveValues 方法将检索 XML 文档中的 DOM 树,并提取状态代码
和状态消息。http://java.sun.com/xml/jaxp/index.html 中的 JAXP 文档
包含详细说明。
class RegReply
{
public RegReply(Document doc)
206
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
{
retrieveValues(doc);
}
public String getStatusCode()
{
return (statusCode);
}
public String getStatusMsg()
{
return (statusMsg);
}
public void print(PrintStream out)
{
out.println(statusCode + ": " +
(statusMsg != null ? statusMsg : ""));
}
private void retrieveValues(Document doc)
{
Node n;
NodeList nl;
String nodeName;
// Find the SC_REPLY element.
nl = doc.getElementsByTagName("SC_REPLY");
if (nl.getLength() != 1) {
System.out.println("Error in parsing: can’t find "
+ "SC_REPLY node.");
return;
}
n = nl.item(0);
// Retrieve the value of the statusCode attribute
statusCode = ((Element)n).getAttribute("STATUS_CODE");
// Find the SC_STATUS_MSG element
nl = ((Element)n).getElementsByTagName("SC_STATUS_MSG");
if (nl.getLength() != 1) {
System.out.println("Error in parsing: can’t find "
+ "SC_STATUS_MSG node.");
return;
}
// Get the TEXT section, if there is one.
n = nl.item(0).getFirstChild();
if (n == null || n.getNodeType() != Node.TEXT_NODE) {
// Not an error if there isn’t one, so we just silently return.
return;
}
// Retrieve the value
statusMsg = n.getNodeValue();
}
第 12 章 • 群集重新配置通知协议
207
private String statusCode;
private String statusMsg;
}
▼
步骤
1. 创建实现上述逻辑的 Java 代码。
请注意,此代码与“第 206 页中的 “如何解析注册回复””中说明的 RegReply 类的
代码类似。
public Event(Document doc)
{
nvpairs = new Vector();
retrieveValues(doc);
}
public void print(PrintStream out)
{
out.println("\tCLASS=" + regClass);
out.println("\tSUBCLASS=" + regSubclass);
out.println("\tVENDOR=" + vendor);
out.println("\tPUBLISHER=" + publisher);
for (int i = 0; i < nvpairs.size(); i++) {
NVPair tempNv = (NVPair)
(nvpairs.elementAt(i));
out.print("\t\t");
tempNv.print(out);
}
}
private void retrieveValues(Document doc)
{
Node n;
NodeList nl;
String nodeName;
// Find the SC_EVENT element.
nl = doc.getElementsByTagName("SC_EVENT");
if (nl.getLength() != 1) {
System.out.println("Error in parsing: can’t find "
+ "SC_EVENT node.");
return;
}
208
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
n = nl.item(0);
//
// Retrieve the values of the CLASS, SUBCLASS,
// VENDOR and PUBLISHER attributes.
//
regClass = ((Element)n).getAttribute("CLASS");
regSubclass = ((Element)n).getAttribute("SUBCLASS");
publisher = ((Element)n).getAttribute("PUBLISHER");
vendor = ((Element)n).getAttribute("VENDOR");
// Retrieve all the nv pairs
for (Node child = n.getFirstChild(); child != null;
child = child.getNextSibling())
{
nvpairs.add(new NVPair((Element)child));
}
}
public String getRegClass()
{
return (regClass);
}
public String getSubclass()
{
return (regSubclass);
}
public String getVendor()
{
return (vendor);
}
public String getPublisher()
{
return (publisher);
}
public Vector getNvpairs()
{
return (nvpairs);
}
private String vendor, publisher;
2. 实现用于支持 XML 解析的 NVPair 类的其他构造函数和方法。
对 Event 类的更改(如步骤 1 所述)需要对 NVPair 类进行类似的更改。
public NVPair(Element elem)
{
retrieveValues(elem);
}
public void print(PrintStream out)
{
第 12 章 • 群集重新配置通知协议
209
out.println("NAME=" + name + " VALUE=" + value);
}
private void retrieveValues(Element elem)
{
Node n;
NodeList nl;
String nodeName;
// Find the NAME element
nl = elem.getElementsByTagName("NAME");
if (nl.getLength() != 1) {
System.out.println("Error in parsing: can’t find "
+ "NAME node.");
return;
}
// Get the TEXT section
n = nl.item(0).getFirstChild();
if (n == null || n.getNodeType() != Node.TEXT_NODE) {
System.out.println("Error in parsing: can’t find "
+ "TEXT section.");
return;
}
// Retrieve the value
name = n.getNodeValue();
// Now get the value element
nl = elem.getElementsByTagName("VALUE");
if (nl.getLength() != 1) {
System.out.println("Error in parsing: can’t find "
+ "VALUE node.");
return;
}
// Get the TEXT section
n = nl.item(0).getFirstChild();
if (n == null || n.getNodeType() != Node.TEXT_NODE) {
System.out.println("Error in parsing: can’t find "
+ "TEXT section.");
return;
}
// Retrieve the value
value = n.getNodeValue();
}
public String getName()
{
return (name);
}
public String getValue()
{
return (value);
}
}
210
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
3. 实现 EventReceptionThread 中的 while 循环,它将等待事件回调。
“第 198 页中的 “如何定义事件接收线程””中介绍了 EventReceptionThread。
while(true) {
Socket sock = listeningSock.accept();
Document doc = db.parse(sock.getInputStream());
Event event = new Event(doc);
client.processEvent(event);
sock.close();
}
▼
步骤
如何运行应用程序
1. 成为超级用户或作为等效角色。
2. 运行应用程序。
# java CrnpClient crnpHost crnpPort localPort ...
附录 G 中列出了 CrnpClient 应用程序的完整代码。
211
212
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
附录 A
■
■
■
■
API_version (integer)
支持此资源类型实现所需的资源管理 API 的最低版本。
以下信息汇总了 Sun Cluster 的每个版本所支持的最高 API_version。
3.1 版或更低版本
2
3.1 10/03
3
3.1 4/04
4
3.1 9/04
5
3.1 8/05
6
在 RTR 文件中为 API_version 声明一个大于 2 的值将可防止资源类型被安装到支
持低于最高版本的 Sun Cluster 版本上。例如,如果您为某个资源类型声明了
API_version=5,该资源类型将不能安装在 3.1 9/04 之前发行的任何版本的 Sun
Cluster 上。
注 – 如果不将此属性声明或设置为默认值 (2),则可将数据服务安装到 Sun Cluster
3.0 以后的任何版本的 Sun Cluster 上。
类别:
可选
缺省值:
2
可调:
无
214
类别:
缺省值:
无缺省值
可调:
无
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
Failover (boolean)
True 用于指明不能在可同时在多个节点上联机的任何组中配置此类资源。
下表显示了如何将此资源类型属性与 Scalable 资源属性结合使用。
Failover 资源类型的值
Scalable 资源的值
说明
TRUE
TRUE
TRUE
FALSE
FALSE
TRUE
可为使用 SharedAddress 资源进行网络负
载平衡的可伸缩服务指定此组合。
《Sun Cluster 概念指南(适用于 Solaris
OS)》详细介绍了 SharedAddress。
FALSE
FALSE
r_properties(5) 手册页中的对 Scalable 的说明和《Sun Cluster 概念指南(适
用于 Solaris OS)》中的第 3 章 “适用于系统管理员和应用程序开发者的关键概念”包
含附加信息。
类别:
可选
缺省值:
FALSE
可调:
无
缺省值:
无缺省值
可调:
无
缺省值:
无缺省值
可调:
无
Init_nodes (enum)
指明 RGM 对哪些节点调用 Init、Fini、Boot 和 Validate 方法。值可为
RG_PRIMARIES(仅为可以控制资源的节点)或 RT_INSTALLED_NODES(安装了该
资源类型的所有节点)。
附录 A • 标准属性
215
类别:
可选
缺省值:
RG_PRIMARIES
可调:
无
Installed_nodes (string_array)
可运行资源类型的群集节点名称的列表。RGM 将自动创建此属性。群集管理员可以
设置此值。不能在 RTR 文件中声明该属性。
类别:
缺省值:
可调:
ANYTIME
Is_logical_hostname (boolean)
TRUE 表明此资源类型是用来管理故障转移 Internet 协议 (IP) 地址的
LogicalHostname 资源类型的某个版本。
类别:
仅限于查询
缺省值:
无缺省值
可调:
无
Is_shared_address (boolean)
TRUE 表明该资源类型是管理故障转移 Internet 协议 (IP) 地址的 SharedAddress 资
源类型的某个版本。
类别:
仅限于查询
缺省值:
无缺省值
可调:
无
缺省值:
无缺省值
可调:
无
Monitor_start (string)
一种可选的回调方法:RGM 为启动此类资源的故障监视器所运行的程序的路径。
类别:
缺省值:
无缺省值
可调:
无
Monitor_stop (string)
设置 Monitor_start 后需要的回调方法:RGM 为停止此类资源的故障监视器所运
行的程序的路径。
216
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
类别:
缺省值:
无缺省值
可调:
无
Pkglist (string_array)
包含在资源类型安装中的软件包的可选列表。
类别:
缺省值:
无缺省值
可调:
无
缺省值:
无缺省值
可调:
无
缺省值:
无缺省值
可调:
无
仅限于查询
缺省值:
空列表
可调:
无
Resource_type (string)
资源类型的名称。要查看当前已注册的资源类型的名称,请使用:
scrgadm -p
在 Sun Cluster 3.1 及更高版本中,资源类型名称必须包含版本:
vendor-id.resource-type:rt-version
217
资源类型名称的三个组成部分是在 RTR 文件中指定为 vendor-id、resource-type 和
rt-version 的属性。scrgadm 命令用于插入句点 (.) 和冒号 (:)分界符。资源类型名称
的 rt-version 后缀的值与 RT_version 属性的值相同。要确保 vendor-id 唯一,请使
用要创建资源类型的公司的股票代号。在 Sun Cluster 3.1 之前的版本中创建的资源类
型名称继续采用以下语法:
vendor-id.resource-type
类别:
必需的
缺省值:
空字符串
可调:
无
缺省值:
无缺省值
可调:
无
RT_description (string)
资源类型的简单说明。
类别:
有条件的
缺省值:
空字符串
可调:
无
RT_system (boolean)
如果资源类型的 RT_system 属性为 TRUE,则不能删除该资源类型 (scrgadm -r
-t resource-type-name)。此属性用于防止意外删除资源资源类型,例如用于支持群集
基础结构的 LogicalHostname。但是,您可以将 RT_system 属性应用于任何资源
类型。
要删除 RT_system 属性设置为 TRUE 的资源类型,必须先将此属性设置为 FALSE。
删除其资源支持群集服务的资源类型时需谨慎。
类别:
可选
缺省值:
FALSE
可调:
ANYTIME
RT_version (string)
从 Sun Cluster 3.1 开始,实施该资源类型必需版本字符串。RT_version 是完整资
源类型名称的后缀部分。曾在 Sun Cluster 3.0 中为可选属性的 RT_version 属性在
Sun Cluster 3.1 及更高版本中是必需属性。
218
类别:
缺省值:
无缺省值
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
可调:
无
Single_instance (boolean)
如果将其设置为 TRUE,则表明在群集中只能存在一个此类型的资源。RGM 仅允许
在群集中一次只运行此类型的一个资源。
类别:
可选
缺省值:
FALSE
可调:
无
Start (string)
一种回调方法:RGM 为启动此类资源所运行的程序的路径。
类别:
必需的(除非在 RTR 文件中声明了 Prenet_start 方法)
缺省值:
无缺省值
可调:
无
必需的(除非在 RTR 文件中声明了 Postnet_stop 方法)
缺省值:
无缺省值
可调:
无
缺省值:
无缺省值
可调:
无
Validate (string)
一种可选的回调方法:RGM 为检查此类资源的属性值所运行的程序的路径。
类别:
缺省值:
无缺省值
可调:
无
Vendor_ID (string)
请参见 Resource_type 属性。
类别:
有条件的
缺省值:
无缺省值
可调:
无
219
■
■
■
永远不
TRUE 或 ANYTIME
任何时候
AT_CREATION
WHEN_DISABLED
首先列出的是属性名称,后面是对该属性的说明。
Affinity_timeout (integer)
以秒表示的时间长度,在此期间,对于资源中的任何服务,来自给定客户机IP 地址的
连接均被发送到同一服务器节点。
仅当 Load_balancing_policy 的值为 Lb_sticky 或 Lb_sticky_wild 时,此
属性才适用。另外,必须将 Weak_affinity 设置为 FALSE。
此属性只用于可伸缩服务。
类别:
可选
缺省值:
无缺省值
可调:
ANYTIME
220
类别:
缺省值:
可调:
ANYTIME
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
Cheap_probe_interval (integer)
在两次资源故障快速探测的调用之间的秒数。该属性由 RGM 创建,并且仅当在 RTR
文件中声明此属性后,群集管理员才可以使用此属性。如果在 RTR 文件中指定了缺
省值,则此属性是可选的。
如果在 RTR 文件中未指定 Tunable 属性,则该属性的 Tunable 值为
WHEN_DISABLED。
类别:
有条件的
缺省值:
无缺省值
可调:
WHEN_DISABLED
有条件的
缺省值:
无缺省值
可调:
Failover_mode (enum)
修改在出现以下情况时 RGM 所采取的恢复操作:当资源无法成功启动或停止时,或
者在资源监视器发现资源运行不正常并因而请求重新启动或故障转移时。
NONE、SOFT 或 HARD(方法失败)
当启动或停止方法(Prenet_start、Start、Monitor_stop、Stop、
Postnet_stop)失败时,这些设置仅影响故障转移行为。成功启动资源之后,
NONE、SOFT 和 HARD 将不会对资源监视器使用 scha_control 命令或
scha_control() 函数启动的后续资源重新启动或停止行为有任何影响。请参见
scha_control(1HA) 和 scha_control(3HA) 手册页。NONE 表示当先前列出的
某个启动或停止方法失败时,RGM 将不执行任何恢复操作。SOFT 或 HARD 表示如果
Start 或 Prenet_start 方法失败,RGM 会将资源的组重定位到其他节点上。对
于 Start 或 Prenet_start 失败,SOFT 与 HARD 相同。
对于 stop 方法(Monitor_stop、Stop 或 Postnet_stop)的失败,SOFT 与
NONE 相同。如果 Failover_mode 设置为 HARD,当这些停止方法之一失败时,
RGM 将重新引导节点以强制资源组脱机。然后,RGM 可能尝试在其他节点上启动
该组。
RESTART_ONLY 或 LOG_ONLY
与 NONE、SOFT 和 HARD 不同,它们影响的是在启动或停止方法失败时的故障转移行
为,而 RESTART_ONLY 和 LOG_ONLY 将影响所有故障转移行为。故障转移行为包括
由监视器启动的 (scha_control) 资源和资源组重新启动,以及由资源监视器
(scha_control) 启动的停止。RESTART_ONLY 表示监视器可以运行
scha_control 来重新启动资源或资源组。RGM 允许在 Retry_interval 指定的
221
时间间隔内重新启动 Retry_count 次。如果超出 Retry_count 次,则不允许再进
行重新启动。如果 Failover_mode 设置为 LOG_ONLY,则不允许进行资源重新启
动或停止。将 Failover_mode 设置为 LOG_ONLY 相当于将 Failover_mode 设置
为 RESTART_ONLY 并将 Retry_count 设置为零。
RESTART_ONLY 或 LOG_ONLY(方法失败)
如果 Prenet_start、Start、Monitor_stop、Stop 或 Postnet_stop 方法失
败,则 RESTART_ONLY 和 LOG_ONLY 与 NONE 相同。即,既不故障转移也不重新引
导节点。
Failover_mode 设置对数据服务的影响
Failover_mode 的每个设置对数据服务的影响取决于数据服务是受监视还是不受监
视,数据服务是否基于数据服务开发库 (DSDL)。
■
■
■
222
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
可选
缺省值:
无
可调:
ANYTIME
缺省值:
可调:
ANYTIME
223
类别:
缺省值:
可调:
ANYTIME
Load_balancing_policy (string)
定义所使用的负载平衡策略的字符串。此属性仅用于可伸缩服务。如果在 RTR 文件
中声明了 Scalable 属性,则 RGM 将自动创建此属性。
Load_balancing_policy 可以取以下值:
Lb_weighted(缺省值)。根据在 Load_balancing_weights 属性中设置的权
重在各个节点间分配负载。
Lb_sticky。可伸缩服务的给定客户机(由客户机的 IP 地址标识)总是发送到同一
群集节点。
Lb_sticky_wild。连接到用通配符表示的粘滞服务的 IP 地址的给定客户机 IP 地
址总是被发送到相同的群集节点,而忽略此 IP 地址的目标端口号。
类别:
缺省值:
Lb_weighted
可调:
AT_CREATION
缺省值:
可调:
ANYTIME
缺省值:
可调:
ANYTIME
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
类别:
缺省值:
可调:
ANYTIME
缺省值:
可调:
ANYTIME
Monitored_switch (enum)
如果群集管理员通过管理公用程序启用或禁止监视器,则 RGM 将把此属性设置为
Enabled 或 Disabled。如果设置为 Disabled,那么虽然资源本身仍保持联机,
但将停止对资源的监视。仅当重新启用监视之后,才会调用 Monitor_start 方
法。如果资源没有监视器回调方法,则此属性不存在。
类别:
仅限于查询
缺省值:
无缺省值
可调:
无
Network_resources_used (string_array)
资源所使用的逻辑主机名或共享地址网络资源的列表。对于可缩放服务,此属性必须
是指存在于单独资源组的共享地址资源。对于失败转移服务,此属性是指存在于相同
的资源组的逻辑主机名或共享地址资源。如果在 RTR 文件中声明了 Scalable 属
性,则 RGM 将自动创建此属性。如果在 RTR 文件中没有声明 Scalable,
Network_resources_used 将不可用,除非在 RTR 文件中显式声明。
如果在 RTR 文件中未指定 Tunable 属性,则此属性的 Tunable 值为
AT_CREATION。
注 – SUNW.Event(5) 手册页介绍了如何为 CRNP 设置此属性。
类别:
缺省值:
无缺省值
可调:
AT_CREATION
每个群集节点上的 Num_resource_restarts (integer)
不能直接设置此属性。RGM 将把此属性设置为在过去的 n 秒内对此节点上的此资源
执行 scha_control、Resource_restart 或 Resource_is_restarted 调用
的次数。n 为资源的 Retry_interval 属性的值。只要此资源执行了
scha_control 停止,无论停止尝试成功与否,RGM 都会将资源重新启动计数器重
置为零 (0)。
附录 A • 标准属性
225
如果某个资源类型不声明 Retry_interval 属性,则该类资源的
Num_resource_restarts 属性不可用。
类别:
仅限于查询
缺省值:
无缺省值
可调:
无
每个群集节点上的 Num_rg_restarts (integer)
不能直接设置此属性。RGM 将把此属性设置为在过去的 n 秒内资源已对其在此节点
上的包含资源组执行 scha_control Restart 调用的次数。n 为此资源的
Retry_interval 属性的值。如果资源类型不声明 Retry_interval 属性,则该
类资源的 Num_rg_restarts 属性不可用。
类别:
请参阅说明
缺省值:
无缺省值
可调:
无
On_off_switch (enum)
如果群集管理员通过管理公用程序启用或禁止资源,则 RGM 将把此属性设置成
Enabled 或 Disabled。如果设置为 Disabled,资源将被脱机并且仅在重新启用该
资源后才能运行回调。
类别:
仅限于查询
缺省值:
无缺省值
可调:
无
Port_list (string_array)
端口(服务器在其上进行侦听)号列表。每个端口号后附加斜杠 (/),斜杠后接该端
口所使用的协议,例如 Port_list=80/tcp 或
Port_list=80/tcp6,40/udp6。您可以指定以下协议值:
■
■
■
■
tcp,用于 TCP IPv4
tcp6(适用于 TCP IPv6)
udp,用于 UDP IPv4
udp6(适用于 UDP IPv6)
如果在 RTR 文件中声明了 Scalable 属性,则 RGM 将自动创建 Port_list。否
则,此属性将不可用,除非在 RTR 文件中显式声明。
《Sun Cluster Data Service for Apache Guide for Solaris OS》中介绍了如何为
Apache 设置此属性。
类别:
缺省值:
无缺省值
可调:
ANYTIME
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
类别:
缺省值:
可调:
ANYTIME
缺省值:
可调:
ANYTIME
R_description (string)
资源的简单说明。
类别:
可选
缺省值:
空字符串
可调:
ANYTIME
可选
缺省值:
空列表
可调:
ANYTIME
227
Resource_dependencies_restart (string_array)
在同一组或不同组中与 Resource_dependencies_restart 资源具有重新启动依
赖性的资源的列表。
此属性的功能与 Resource_dependencies 相同,以下情况除外:如果重新启动依
赖性列表中的任何资源被重新启动,则重新启动此资源。RGM 将在列表中的资源重
新联机之后重新启动此资源。
类别:
可选
缺省值:
空列表
可调:
ANYTIME
Resource_dependencies_weak (string_array)
在同一组或不同组中与 Resource_dependencies_weak 资源具有弱依赖性的资源
的列表。弱依赖性用于确定方法调用的顺序。RGM 将先调用此列表中资源的 Start
方法,再调用此资源的 Start 方法。RGM 将先调用此资源的 Stop 方法,再调用列
表中那些资源的 Stop 方法。如果列表中的资源启动失败或保持脱机状态,该资源将
仍然可以启动。
如果此资源与其 Resource_dependencies_weak 列表中的资源同时启动,则
RGM 将一直等到该列表中的资源启动之后再启动此资源。如果列表中的资源不启动
(例如列表中资源的资源组仍然保持脱机状态或者列表中的资源处于
START_FAILED 状态时),此资源将启动。当此资源的
Resource_dependencies_weak 列表中的资源启动时,此资源的资源组可能会临
时进入 PENDING_ONLINE_BLOCKED 状态。当所有资源已启动或无法启动时,此资
源将启动并且此资源的组将重新进入 PENDING_ONLINE 状态。
如果将该资源与列表中的资源同时脱机,则该资源将在列表中的资源停止之前停止。
如果该资源保持联机或无法停止,列表中的资源仍会停止。您不能禁用列表中的资
源,除非先禁用此资源。
在资源组中,按照依赖顺序,Prenet_start 方法将先于 Start 方法运行。按照依
赖顺序,Postnet_stop 方法将在运行 Stop 方法后运行。在不同的资源组中,依
赖资源将等待被依赖资源完成 Prenet_start 和 Start 之后再运行
Prenet_start。被依赖资源将等待依赖资源完成 Stop 和 Postnet_stop 之后再
运行 Stop。
类别:
可选
缺省值:
空列表
可调:
ANYTIME
228
类别:
必需的
缺省值:
无缺省值
可调:
无
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
Resource_project_name (string)
与资源关联的 Solaris 项目名称。使用该属性可以将 Solaris 资源的管理功能(例如
CPU 共享和资源池)应用于群集数据服务。当 RGM 使资源联机时,它将启动此项目
名称下的相关进程。如果未指定此属性,将通过包含资源的资源组的
RG_project_name 属性获取项目名称(请参见 rg_properties(5) 手册页)。如
果也未指定 RG_project_name 属性,RGM 将使用预定义的项目名称 default。指
定的项目名称必须已在项目数据库中(请参见 projects(1) 手册页和《System
Administration Guide: Solaris Containers-Resource Management and Solaris
Zones》)。
仅从 Solaris 9 开始支持此属性。
注 – 对此属性的更改将在下次资源被启动时生效。
类别:
可选
缺省值:
空
可调:
ANYTIME
每个群集节点上的 Resource_state (enum)
每个群集节点上由 RGM 确定的资源状态。可能的状态包括 ONLINE、OFFLINE、
START_FAILED、STOP_FAILED、MONITOR_FAILED、
ONLINE_NOT_MONITORED、STARTING 和 STOPPING。
不能配置该属性。
类别:
仅限于查询
缺省值:
无缺省值
可调:
无
Retry_count (integer)
如果资源失败,监视器尝试重新启动该资源的次数。如果超出 Retry_count,则根
据特定数据服务和 Failover_mode 属性的设置,监视器可能执行以下操作之一:
■
■
类别:
229
缺省值:
可调:
WHEN_DISABLED
Retry_interval (integer)
尝试重新启动失败的资源前计算的秒数。资源监视器将此属性与 Retry_count 一起
使用。该属性由 RGM 创建,并且仅当在 RTR 文件中声明此属性后,群集管理员才
可以使用此属性。如果在 RTR 文件中指定了缺省值,则此属性是可选的。
如果在 RTR 文件中未指定 Tunable 属性,则此属性的 Tunable 值为
When_disabled。
类别:
有条件的
缺省值:
可调:
WHEN_DISABLED
Scalable (boolean)
指明资源是不是可伸缩资源,即资源是否使用 Sun Cluster 软件的网络负载平衡功
能。
如果在 RTR 文件中声明了此属性,则 RGM 将为该类型的资源自动创建以下可伸缩
服务属性:Affinity_timeout、Load_balancing_policy、
Load_balancing_weights、Network_resources_used、Port_list、
UDP_affinity 和 Weak_affinity。这些属性具有缺省值,除非在 RTR 文件中对
它们进行了显式声明。Scalable 的默认值(在 RTR 文件中声明时)为 TRUE。
如果在 RTR 文件中声明此属性,则不能其指定给除了 AT_CREATION 以外的任何
Tunable 属性。
如果未在 RTR 文件中声明此属性,该资源将不具有可伸缩性,您不能调节此属性,
并且 RGM 也不会设置任何可伸缩服务属性。但是,您可以在 RTR 文件中显式声明
Network_resources_used 和 Port_list 属性。这些属性对不可伸缩服务和可
伸缩服务都会非常有用。
r_properties(5) 手册页中详细介绍了如何将此资源属性与 Failover 资源类型属
性结合使用。
类别:
可选
缺省值:
无缺省值
可调:
AT_CREATION
230
类别:
缺省值:
可调:
ANYTIME
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
每个群集节点上的 Status (enum)
由资源监视器使用 scha_resource_setstatus 命令或
scha_resource_setstatus() 函数设置。可能的值包括 OK、degraded、
faulted、unknown 和 offline。当资源进入联机或脱机状态时,如果资源的监视
器或方法未设置 Status 值,则 RGM 将自动设置 Status 值。
类别:
仅限于查询
缺省值:
无缺省值
可调:
无
仅限于查询
缺省值:
无缺省值
可调:
无
缺省值:
可调:
ANYTIME
Thorough_probe_interval (integer)
在两次资源高开销故障探测的调用之间的秒数。该属性由 RGM 创建,并且仅当在
RTR 文件中声明此属性后,群集管理员才可以使用此属性。如果在 RTR 文件中指定
了缺省值,则此属性是可选的。
如果在 RTR 文件中未指定 Tunable 属性,则该属性的 Tunable 值为
When_disabled。
类别:
有条件的
缺省值:
无缺省值
可调:
WHEN_DISABLED
必需的
缺省值:
无缺省值
可调:
无
231
资源类型的当前版本
RTR 文件中的 #$upgrade_from 指令
类别:
请参阅说明
缺省值:
无缺省值
可调:
请参阅说明
UDP_affinity (boolean)
如果将此属性设置为 TRUE,则将来自给定客户机的所有 UDP 通信流量都发送给当
前为该客户机处理所有 TCP 通信流量的同一个服务器节点。
仅当 Load_balancing_policy 的值为 Lb_sticky 或 Lb_sticky_wild 时,此
属性才适用。另外,必须将 Weak_affinity 设置为 FALSE。
此属性只用于可伸缩服务。
类别:
可选
缺省值:
无缺省值
可调:
WHEN_DISABLED
缺省值:
可调:
ANYTIME
缺省值:
可调:
ANYTIME
232
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
就内存消耗和处理器周期而言,不采用缺省形式而启用较弱的关联性所使用的系统开
销较低。
仅当 Load_balancing_policy 的值为 Lb_sticky 或 Lb_sticky_wild 时,此
属性才适用。
此属性只用于可伸缩服务。
类别:
可选
缺省值:
无缺省值
可调:
WHEN_DISABLED
可选
缺省值:
TRUE
可调:
ANYTIME
Desired_primaries (integer)
可同时运行组的首选节点数目。
默认值为 1。如果 RG_mode 属性为 Failover,则此属性的值必须不大于 1。如果
RG_mode 属性为 Scalable,则值大于 1 是允许的。
类别:
可选
缺省值:
233
可调:
ANYTIME
可选
缺省值:
FALSE
可调:
ANYTIME
可选
缺省值:
可调:
ANYTIME
可选
缺省值:
TRUE
可调:
ANYTIME
Maximum_primaries (integer)
组一次可以联机的最大节点数。
如果 RG_mode 属性为 Failover,则此属性的值必须不大于 1。如果 RG_mode 属
性为 Scalable,则值大于 1 是允许的。
类别:
可选
缺省值:
1
可调:
ANYTIME
234
类别:
可选
缺省值:
可调:
ANYTIME
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
可选
缺省值:
空字符串
可调:
ANYTIME
Pingpong_interval (integer)
非负整数值(以秒为单位),RGM 使用此属性值确定使以下实例中的资源组联机到
何处:
■
■
在重新配置的情况下
导致执行 scha_control GIVEOVER 命令或函数
在重新配置的情况下,资源组在过去 Pingpong_interval 秒内在特定节点上多次
联机失败。此失败的原因在于资源的 Start 或 Prenet_start 方法在非零状态下或
超时后退出。因此,此节点被认为不适于托管资源组,RGM 将查找其他主控节点。
如果资源在给定节点上执行 scha_control 命令或 scha_control GIVEOVER 命
令,因而导致其资源组故障转移到其他节点上,则第一个节点(在其上运行过
scha_control)不能作为同一资源执行另一个 scha_control GIVEOVER 的目标
节点,直至经过 Pingpong_interval 秒之后。
类别:
可选
缺省值:
3600(一小时)
可调:
ANYTIME
仅限于查询
缺省值:
无缺省值
可调:
无
例如,RG_affinities=+RG2,--RG3 表示此资源组具有与 RG2 的较弱正关联和
RG3 的较强负关联。
附录 A • 标准属性
235
《Sun Cluster Data Services Planning and Administration Guide for Solaris OS》中
的第 2 章 “Administering Data Service Resources”中介绍了如何使用
RG_affinities。
类别:
可选
缺省值:
空字符串
可调:
ANYTIME
RG_dependencies (string_array)
可选资源组列表,用于指明在同一节点上使其他组联机或脱机的优先顺序。所有强
RG_dependencies 和 RG_affinities(正负)的图形都不允许包含循环。
例如,假定资源组 RG1 的 RG_dependencies 列表中列有资源组 RG2,即 RG1 与
RG2 具有资源组依赖性。以下列表汇总了此资源组依赖性的影响:
■
■
■
■
■
■
当某个节点加入群集时,必须等该节点上的所有 Boot 方法在 RG2 中的资源上运
行完之后,才能在 RG1 中的资源上运行该节点的 Boot 方法。
如果 RG1 和 RG2 同时在同一个节点上处于 PENDING_ONLINE 状态,则在 RG2
中的所有资源运行完其启动方法之后,RG1 中的资源才运行启动方法
(Prenet_start 或 Start)。
如果 RG1 和 RG2 同时在同一个节点上处于 PENDING_OFFLINE 状态,则在 RG1
中的所有资源运行完其停止方法之后,RG2 中的资源才运行停止方法(Stop 或
Postnet_stop)。
如果切换主节点会使 RG1 在任意一个节点上保持联机而使 RG2 在所有节点上都
保持脱机,则尝试切换 RG1 或 RG2 的主节点将会失败。scswitch(1M) 和
scsetup(1M) 手册页包含更多信息。
如果在 RG2 上将 Desired_primaries 设置为零,则不允许在 RG1 上将
Desired_primaries 属性设置为大于零的值。
如果在 RG2 上将 Auto_start_on_new_cluster 属性设置为 FALSE,则不允
许在 RG1 上将 Auto_start_on_new_cluster 属性设置为 TRUE。
类别:
可选
缺省值:
空列表
可调:
ANYTIME
RG_description (string)
资源组的简单说明。
类别:
可选
缺省值:
空字符串
可调:
ANYTIME
RG_is_frozen (boolean)
一个布尔值,指示是否正在切换转移资源组所依赖的全局设备。如果将此属性设置为
TRUE,则将切换转移全局设备。如果将此属性设置为 FALSE,则表明没有切换转移
全局设备。资源组依赖于其 Global_resources_used 属性中指定的全局设备。
请不要直接设置 RG_is_frozen 属性。RGM 将在全局设备的状态发生更改时更新
RG_is_frozen 属性。
236
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
类别:
可选
缺省值:
无缺省值
可调:
无
RG_mode (enum)
指明资源组是故障转移资源组还是可伸缩资源组。如果值为 Failover,则 RGM 将
把该组的 Maximum_primaries 属性设置为 1 并将资源组限制为由单个节点控制。
如果此属性的值为 Scalable,则 RGM 允许为 Maximum_primaries 属性设置大
于 1 的值,因此,该组可同时受多个节点控制。RGM 不允许将 Failover 属性为
True 的资源添加到 RG_mode 为 Scalable 的资源组中。
如果 Maximum_primaries 为 1,则默认值为 Failover。如果
Maximum_primaries 的值大于 1,则缺省值为 Scalable。
类别:
可选
缺省值:
取决于 Maximum_primaries 的值。
可调:
无
必需的
缺省值:
无缺省值
可调:
无
RG_project_name (string)
与资源组相关的 Solaris 项目名称(请参见 projects(1) 手册页)。使用该属性可以
将 Solaris 资源的管理功能(例如 CPU 共享和资源池)应用于群集数据服务。RGM
使资源组联机时,将为不具有 Resource_project_name 属性集的资源启动此项目
名称下的相关进程(请参见 r_properties(5) 手册页)。指定的项目名称必须已在
项目数据库中(请参见 projects(1) 手册页和《System Administration Guide:
Solaris Containers-Resource Management and Solaris Zones》)。
仅从 Solaris 9 开始支持此属性。
注 – 对此属性的更改将在下次资源被启动时生效。
类别:
可选
缺省值:
文本字符串 "default"
可调:
ANYTIME
237
每个群集节点上的 RG_state (enum)
由 RGM 将其设置为 UNMANAGED、ONLINE、OFFLINE、PENDING_ONLINE、
PENDING_OFFLINE、ERROR_STOP_FAILED、ONLINE_FAULTED 或
PENDING_ONLINE_BLOCKED,以说明每个群集节点上的组的状态。
不能配置该属性。不过,您可以通过运行 scswitch 命令或者使用等效的 scsetup
或 SunPlex Manager 命令间接设置此属性。如果组不在 RGM 的控制下,可以处于
UNMANAGED 状态。
以下说明汇总了所有状态。
注 – 状态仅适于单个节点,UNMANAGED 状态除外,该状态适于所有节点。例如,资
源组可能在节点 A 上 OFFLINE,但在节点 B 上 PENDING_ONLINE。
UNMANAGED
238
ONLINE
已在节点上启动资源组。换言之,适于每
个资源的启动方法 Prenet_start、
Start 和 Monitor_start 已在组中所
有已启用的资源上成功执行。
OFFLINE
PENDING_ONLINE
正在节点上启动资源组。适于每个资源的
启动方法 Prenet_start、Start 和
Monitor_start 正在组中已启用的资源
上执行。
PENDING_OFFLINE
正在节点上停止资源组。适于每个资源的
停止方法 Monitor_stop、Stop 和
Postnet_stop 正在组中已启用的资源
上执行。
ERROR_STOP_FAILED
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
必须使用管理命令(例如
scswitch -c)手动中止 Stop_failed
资源并将其状态重置为 OFFLINE。
ONLINE_FAULTED
资源组曾处于 PENDING_ONLINE 状态,
并已在此节点上启动。但是,一个或多个
资源在 Start_failed 状态或 Faulted
状态下停止。
PENDING_ONLINE_BLOCKED
类别:
仅限于查询
缺省值:
无缺省值
可调:
无
示例
删除资源组
scrgadm -r -g RG1
编辑资源组属性(RG_system 除外)
scrgadm -c -t RG1 -y nodelist=...
scrgadm -a -j R1 -g RG1
scrgadm -r -j R1 -g RG1
scrgadm -c -j R1
scswitch -F -g RG1
管理资源组
scswitch -o -g RG1
scswitch -u -g RG1
启用资源
scswitch -e -j R1
scswitch -e -M -j R1
239
操作
示例
禁用资源
scswitch -n -j R1
scswitch -n -M -j R1
如果资源组的 RG_system 属性为 TRUE,则能编辑的该资源组属性只有 RG_system
属性本身。换言之,编辑 RG_system 属性永不受限制。
类别:
可选
缺省值:
FALSE
可调:
ANYTIME
首先列出的是属性名称,后面是对该属性的说明。
Array_maxsize
对于 stringarray 类型所允许的数组元素的最大数。
Array_minsize
对于 stringarray 类型所允许的数组元素的最小数。
Default
表明属性的缺省值。
Description
一个字符串注释,用于对属性作简单说明。对于系统定义的属性,不能在 RTR 文件
中设置 Description 属性。
Enumlist
对于 enum 类型,为该属性所允许的一组字符串值。
Extension
如果使用该属性,则表明 RTR 文件条目声明了一个由资源类型的实现所定义的扩展
属性,否则,此项为系统定义的属性。
Max
对于 int 类型所允许的属性的最大值。
240
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
Maxlength
对于 string 和 stringarray 类型所允许的最大字符串长度。
Min
对于 int 类型所允许的属性的最小值。
Minlength
对于 string 和 stringarray 类型所允许的最小字符串长度。
Property
资源属性的名称。
Tunable
表明群集管理员何时可以设置某个资源中的此属性值。设置为 NONE 或 FALSE 可以
防止群集管理员设置属性。允许群集管理员调节属性的值为 TRUE、ANYTIME(随
时)、AT_CREATION(仅在创建资源时)或 WHEN_DISABLED(禁用资源时)。要
建立其他条件(例如“禁用监视时”或“脱机时”),请将此属性设置为 ANYTIME 并在
Validate 方法中验证资源的状态。
不同的标准资源属性有不同的默认值,如下面的条目所示。如果没有在 RTR 文件中
进行指定,则调节扩展属性的默认设置为 TRUE (ANYTIME)。
属性的类型
允许的类型为 string、boolean、integer、enum 和 stringarray。对于系统
定义的属性,您不能在 RTR 文件条目中设置类型属性。类型决定了可接受的属性值
和在 RTR 文件项中允许的特定于类型的属性。enum 类型是一组字符串值。
241
242
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
附录 B
第 243 页中的 “资源类型注册文件列表”
第 246 页中的 “Start 方法代码列表”
第 249 页中的 “Stop 方法代码列表”
第 251 页中的 “gettime 实用程序代码列表”
第 252 页中的 “PROBE 程序代码列表”
第 257 页中的 “Monitor_start 方法代码列表”
第 259 页中的 “Monitor_stop 方法代码列表”
第 260 页中的 “Monitor_check 方法代码列表”
第 262 页中的 “Validate 方法代码列表”
第 266 页中的 “Update 方法代码列表”
SUNW.Sample RTR 文件
#
# Copyright (c) 1998-2005 by Sun Microsystems, Inc.
# All rights reserved.
#
# Registration information for Domain Name Service (DNS)
#
243
示例 B–1
SUNW.Sample RTR 文件
#pragma ident
(续)
“@(#)SUNW.sample
1.1
00/05/24 SMI”
Resource_type = “sample”;
Vendor_id = SUNW;
RT_description = “Domain Name Service on Sun Cluster”;
RT_version =”1.0”;
API_version = 2;
Failover = TRUE;
RT_basedir=/opt/SUNWsample/bin;
Pkglist = SUNWsample;
Start
Stop
= dns_svc_start;
= dns_svc_stop;
Validate
Update
= dns_validate;
= dns_update;
Monitor_start
Monitor_stop
Monitor_check
= dns_monitor_start;
= dns_monitor_stop;
= dns_monitor_check;
#
#
#
#
#
#
A list of bracketed resource property declarations follows the
resource type declarations. The property-name declaration must be
the first attribute after the open curly bracket of each entry.
#
#
#
#
#
#
#
{
The MIN value for all method timeouts is set to 60 seconds. This
prevents administrators from setting shorter timeouts, which do not
improve switchover/failover performance, and can lead to undesired
RGM actions (false failovers, node reboot, or moving the resource group
to ERROR_STOP_FAILED state, requiring operator intervention). Setting
too-short method timeouts leads to a *decrease* in overall availability
of the data service.
The <method>_timeout properties set the value in seconds after which
the RGM concludes invocation of the method has failed.
PROPERTY = Start_timeout;
MIN=60;
DEFAULT=300;
}
{
PROPERTY = Stop_timeout;
MIN=60;
DEFAULT=300;
}
{
PROPERTY = Validate_timeout;
MIN=60;
DEFAULT=300;
}
{
244
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
示例 B–1
SUNW.Sample RTR 文件
(续)
PROPERTY = Update_timeout;
MIN=60;
DEFAULT=300;
}
{
PROPERTY = Monitor_Start_timeout;
MIN=60;
DEFAULT=300;
}
{
PROPERTY = Monitor_Stop_timeout;
MIN=60;
DEFAULT=300;
}
{
PROPERTY = Thorough_Probe_Interval;
MIN=1;
MAX=3600;
DEFAULT=60;
TUNABLE = ANYTIME;
}
# The number of retries to be done within a certain period before concluding
# that the application cannot be successfully started on this node.
{
PROPERTY = Retry_count;
MIN=0;
MAX=10;
DEFAULT=2;
TUNABLE = ANYTIME;
}
#
#
#
#
{
Set Retry_interval as a multiple of 60 since it is converted from seconds
to minutes, rounding up. For example, a value of 50 (seconds)
is converted to 1 minute. Use this property to time the number of
retries (Retry_count).
PROPERTY = Retry_interval;
MIN=60;
MAX=3600;
DEFAULT=300;
TUNABLE = ANYTIME;
}
{
PROPERTY = Network_resources_used;
TUNABLE = AT_CREATION;
DEFAULT = ““;
}
#
# Extension Properties
#
附录 B • 数据服务样例代码列表
245
示例 B–1
#
#
#
#
{
SUNW.Sample RTR 文件
(续)
The cluster administrator must set the value of this property to point to the
directory that contains the configuration files used by the application.
For this application, DNS, specify the path of the DNS configuration file on
PXFS (typically named.conf).
PROPERTY = Confdir;
EXTENSION;
STRING;
TUNABLE = AT_CREATION;
DESCRIPTION = “The Configuration Directory Path”;
}
# Time out value in seconds before declaring the probe as failed.
{
PROPERTY = Probe_timeout;
EXTENSION;
INT;
DEFAULT = 30;
TUNABLE = ANYTIME;
DESCRIPTION = “Time out value for the probe (seconds)”;
}
#!/bin/ksh
#
# Start Method for HA-DNS.
#
# This method starts the data service under the control of PMF. Before starting
# the in.named process for DNS, it performs some sanity checks. The PMF tag for
# the data service is $RESOURCE_NAME.named. PMF tries to start the service a
# specified number of times (Retry_count) and if the number of attempts exceeds
# this value within a specified interval (Retry_interval) PMF reports a failure
# to start the service. Retry_count and Retry_interval are both properties of the
# resource set in the RTR file.
#pragma ident
“@(#)dns_svc_start
1.1
00/05/24 SMI”
###############################################################################
246
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
示例 B–2 dns_svc_start 方法
(续)
# Parse program arguments.
#
function parse_args # [args ...]
{
typeset opt
while getopts ‘R:G:T:’ opt
do
case “$opt” in
R)
# Name of the DNS resource.
RESOURCE_NAME=$OPTARG
;;
G)
# Name of the resource group in which the resource is
# configured.
RESOURCEGROUP_NAME=$OPTARG
;;
T)
# Name of the resource type.
RESOURCETYPE_NAME=$OPTARG
;;
*)
logger -p ${SYSLOG_FACILITY}.err \
-t [$RESOURCETYPE_NAME,$RESOURCEGROUP_NAME,$RESOURCE_NAME] \
“ERROR: Option $OPTARG unknown”
exit 1
;;
esac
done
}
###############################################################################
# MAIN
#
##############################################################################
export PATH=/bin:/usr/bin:/usr/cluster/bin:/usr/sbin:/usr/proc/bin:$PATH
# Obtain the syslog facility to use to log messages.
SYSLOG_FACILITY=`scha_cluster_get -O SYSLOG_FACILITY`
# Parse the arguments that have been passed to this method
parse_args “$@”
PMF_TAG=$RESOURCE_NAME.named
SYSLOG_TAG=$RESOURCETYPE_NAME,$RESOURCEGROUP_NAME,$RESOURCE_NAME
附录 B • 数据服务样例代码列表
247
示例 B–2 dns_svc_start 方法
(续)
# Get the value of the Confdir property of the resource in order to start
# DNS. Using the resource name and the resource group entered, find the value of
# Confdir value set by the cluster administrator when adding theresource.
config_info=scha_resource_get -O Extension -R $RESOURCE_NAME \
-G $RESOURCEGROUP_NAME Confdir`
# scha_resource_get returns the “type” as well as the “value” for the extension
# properties. Get only the value of the extension property.
CONFIG_DIR=`echo $config_info | awk ‘{print $2}’`
# Check if $CONFIG_DIR is accessible.
if [ ! -d $CONFIG_DIR ]; then
logger -p ${SYSLOG_FACILITY}.err -t [$SYSLOG_TAG] \
“${ARGV0} Directory $CONFIG_DIR missing or not mounted”
exit 1
fi
# Change to the $CONFIG_DIR directory in case there are relative
# path names in the data files.
cd $CONFIG_DIR
# Check that the named.conf file is present in the $CONFIG_DIR directory.
if [ ! -s named.conf ]; then
logger -p ${SYSLOG_FACILITY}.err -t [$SYSLOG_TAG] \
“${ARGV0} File $CONFIG_DIR/named.conf is missing or empty”
exit 1
fi
# Get the value for Retry_count from the RTR file.
RETRY_CNT=`scha_resource_get -O Retry_count -R $RESOURCE_NAME \
-G $RESOURCEGROUP_NAM?
# Get the value for Retry_interval from the RTR file. Convert this value, which is in
# seconds, to minutes for passing to pmfadm. Note that this is a conversion with
# round-up, for example, 50 seconds rounds up to one minute.
((RETRY_INTRVAL = `scha_resource_get -O Retry_interval -R $RESOURCE_NAME \
-G $RESOURCEGROUP_NAM? 60))
# Start the in.named daemon under the control of PMF. Let it crash and restart
# up to $RETRY_COUNT times in a period of $RETRY_INTERVAL; if it crashes
# more often than that, PMF will cease trying to restart it. If there is a
# process already registered under the tag <$PMF_TAG>, then, PMF sends out
# an alert message that the process is already running.
echo “Retry interval is “$RETRY_INTRVAL
pmfadm -c $PMF_TAG.named -n $RETRY_CNT -t $RETRY_INTRVAL \
/usr/sbin/in.named -c named.conf
# Log a message indicating that HA-DNS has been started.
if [ $? -eq 0 ]; then
logger -p ${SYSLOG_FACILITY}.info -t [$SYSLOG_TAG] \
“${ARGV0} HA-DNS successfully started”
fi
exit 0
248
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
Stop 方法代码列表
当包含 HA-DNS 资源的资源组在群集节点上被脱机后或者该资源被禁用时,RGM 将在
该群集节点上运行 Stop 方法。此方法将停止该节点上的 in.named (DNS) 守护进程。
示例 B–3 dns_svc_stop 方法
#!/bin/ksh
#
# Stop method for HA-DNS
#
# Stop the data service using PMF. If the service is not running the
# method exits with status 0 as returning any other value puts the resource
# in STOP_FAILED state.
#pragma ident
“@(#)dns_svc_stop
1.1
00/05/24 SMI”
###############################################################################
# Parse program arguments.
#
function parse_args # [args ...]
{
typeset opt
while getopts ‘R:G:T:’ opt
do
case “$opt” in
R)
# Name of the DNS resource.
RESOURCE_NAME=$OPTARG
;;
G)
# Name of the resource group in which the resource is
# configured.
RESOURCEGROUP_NAME=$OPTARG
;;
T)
# Name of the resource type.
RESOURCETYPE_NAME=$OPTARG
;;
*)
logger -p ${SYSLOG_FACILITY}.err \
-t [$RESOURCETYPE_NAME,$RESOURCEGROUP_NAME,$RESOURCE_NAME] \
“ERROR: Option $OPTARG unknown”
exit 1
;;
esac
done
}
249
示例 B–3 dns_svc_stop 方法
(续)
###############################################################################
# MAIN
#
###############################################################################
export PATH=/bin:/usr/bin:/usr/cluster/bin:/usr/sbin:/usr/proc/bin:$PATH
# Obtain the syslog facility to use to log messages.
SYSLOG_FACILITY=`scha_cluster_get -O SYSLOG_FACILITY`
# Parse the arguments that have been passed to this method
parse_args “$@”
PMF_TAG=$RESOURCE_NAME.named
SYSLOG_TAG=$RESOURCETYPE_NAME,$RESOURCEGROUP_NAME,$RESOURCE_NAME
# Obtain the Stop_timeout value from the RTR file.
STOP_TIMEOUT=`scha_resource_get -O STOP_TIMEOUT -R $RESOURCE_NAME -G \
$RESOURCEGROUP_NAM?
# Attempt to stop the data service in an orderly manner using a SIGTERM
# signal through PMF. Wait for up to 80% of the Stop_timeout value to
# see if SIGTERM is successful in stopping the data service. If not, send SIGKILL
# to stop the data service. Use up to 15% of the Stop_timeout value to see
# if SIGKILL is successful. If not, there is a failure and the method exits with
# non-zero status. The remaining 5% of the Stop_timeout is for other uses.
((SMOOTH_TIMEOUT=$STOP_TIMEOUT * 80/100))
((HARD_TIMEOUT=$STOP_TIMEOUT * 15/100))
# See if in.named is running, and if so, kill it.
if pmfadm -q $PMF_TAG.named; then
# Send a SIGTERM signal to the data service and wait for 80% of the
# total timeout value.
pmfadm -s $PMF_TAG.named -w $SMOOTH_TIMEOUT TERM
if [ $? -ne 0 ]; then
logger -p ${SYSLOG_FACILITY}.info -t [SYSLOG_TAG] \
“${ARGV0} Failed to stop HA-DNS with SIGTERM; Retry with \
SIGKILL”
# Since the data service did not stop with a SIGTERM signal, use
# SIGKILL now and wait for another 15% of the total timeout value.
pmfadm -s $PMF_TAG.named -w $HARD_TIMEOUT KILL
if [ $? -ne 0 ]; then
logger -p ${SYSLOG_FACILITY}.err -t [SYSLOG_TAG] \
“${ARGV0} Failed to stop HA-DNS; Exiting UNSUCCESSFUL”
exit 1
fi
fi
else
# The data service is not running as of now. Log a message and
# exit success.
250
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
示例 B–3 dns_svc_stop 方法
(续)
logger -p ${SYSLOG_FACILITY}.info -t [SYSLOG_TAG] \
“HA-DNS is not started”
# Even if HA-DNS is not running, exit success to avoid putting
# the data service in STOP_FAILED State.
exit 0
fi
# Successfully stopped DNS. Log a message and exit success.
logger -p ${SYSLOG_FACILITY}.info -t [$SYSLOG_TAG] \
“HA-DNS successfully stopped”
exit 0
#
#
#
#
This utility program, used by the probe method of the data service, tracks
the elapsed time in seconds from a known reference point (epoch point). It
must be compiled and placed in the same directory as the data service callback
methods (RT_basedir).
#pragma ident
“@(#)gettime.c
1.1
00/05/24 SMI”
#include <stdio.h>
#include <sys/types.h>
#include <time.h>
main()
{
printf(“%d\n”, time(0));
exit(0);
}
251
PROBE 程序代码列表
PROBE 程序使用 nslookup 命令检查数据服务的可用性(请参见 nslookup(1M) 手册
页)。Monitor_start 回调方法用于启动此程序,Monitor_stop 回调方法用于停
止此程序。
示例 B–5 dns_probe 程序
#!/bin/ksh
#pragma ident
“@(#)dns_probe
1.1
00/04/19 SMI”
#
# Probe method for HA-DNS.
#
# This program checks the availability of the data service using nslookup, which
# queries the DNS server to look for the DNS server itself. If the server
# does not respond or if the query is replied to by some other server,
# then the probe concludes that there is some problem with the data service
# and fails the service over to another node in the cluster. Probing is done
# at a specific interval set by THOROUGH_PROBE_INTERVAL in the RTR file.
#pragma ident
“@(#)dns_probe
1.1
00/05/24 SMI”
###############################################################################
# Parse program arguments.
function parse_args # [args ...]
{
typeset opt
while getopts ‘R:G:T:’ opt
do
case “$opt” in
R)
# Name of the DNS resource.
RESOURCE_NAME=$OPTARG
;;
G)
# Name of the resource group in which the resource is
# configured.
RESOURCEGROUP_NAME=$OPTARG
;;
T)
# Name of the resource type.
RESOURCETYPE_NAME=$OPTARG
;;
*)
logger -p ${SYSLOG_FACILITY}.err \
-t [$RESOURCETYPE_NAME,$RESOURCEGROUP_NAME,$RESOURCE_NAME] \
“ERROR: Option $OPTARG unknown”
exit 1
;;
esac
252
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
示例 B–5 dns_probe 程序
(续)
done
}
###############################################################################
# restart_service ()
#
# This function tries to restart the data service by calling the Stop method
# followed by the Start method of the dataservice. If the dataservice has
# already died and no tag is registered for the dataservice under PMF,
# then this function fails the service over to another node in the cluster.
#
function restart_service
{
# To restart the dataservice, first, verify that the
# dataservice itself is still registered under PMF.
pmfadm -q $PMF_TAG
if [[ $? -eq 0 ]]; then
# Since the TAG for the dataservice is still registered under
# PMF, first stop the dataservice and start it back up again.
# Obtain the Stop method name and the STOP_TIMEOUT value for
# this resource.
STOP_TIMEOUT=`scha_resource_get -O STOP_TIMEOUT \
-R $RESOURCE_NAME -G $RESOURCEGROUP_NAM?
STOP_METHOD=`scha_resource_get -O STOP \
-R $RESOURCE_NAME -G $RESOURCEGROUP_NAM?
hatimerun -t $STOP_TIMEOUT $RT_BASEDIR/$STOP_METHOD \
-R $RESOURCE_NAME -G $RESOURCEGROUP_NAME \
-T $RESOURCETYPE_NAME
if [[ $? -ne 0 ]]; then
logger-p ${SYSLOG_FACILITY}.err -t [$SYSLOG_TAG] \
“${ARGV0} Stop method failed.”
return 1
fi
# Obtain the Start method name and the START_TIMEOUT value for
# this resource.
START_TIMEOUT=`scha_resource_get -O START_TIMEOUT \
-R $RESOURCE_NAME -G $RESOURCEGROUP_NAM?
START_METHOD=`scha_resource_get -O START \
-R $RESOURCE_NAME -G $RESOURCEGROUP_NAM?
hatimerun -t $START_TIMEOUT $RT_BASEDIR/$START_METHOD \
-R $RESOURCE_NAME -G $RESOURCEGROUP_NAME \
-T $RESOURCETYPE_NAME
if [[ $? -ne 0 ]]; then
logger-p ${SYSLOG_FACILITY}.err -t [$SYSLOG_TAG] \
“${ARGV0} Start method failed.”
return 1
fi
else
# The absence of the TAG for the dataservice
附录 B • 数据服务样例代码列表
253
示例 B–5 dns_probe 程序
(续)
# implies that the dataservice has already
# exceeded the maximum retries allowed under PMF.
# Therefore, do not attempt to restart the
# dataservice again, but try to failover
# to another node in the cluster.
scha_control -O GIVEOVER -G $RESOURCEGROUP_NAME \
-R $RESOURCE_NAME
fi
return 0
}
###############################################################################
# decide_restart_or_failover ()
#
# This function decides the action to be taken upon the failure of a probe:
# restart the data service locally or fail over to another node in the cluster.
#
function decide_restart_or_failover
{
# Check if this is the first restart attempt.
if [ $retries -eq 0 ]; then
# This is the first failure. Note the time of
# this first attempt.
start_time=`$RT_BASEDIR/gettimè
retries=`expr $retries + 1`
# Because this is the first failure, attempt to restart
# the data service.
restart_service
if [ $? -ne 0 ]; then
logger -p ${SYSLOG_FACILITY}.err -t [$SYSLOG_TAG] \
“${ARGV0} Failed to restart data service.”
exit 1
fi
else
# This is not the first failure
current_time=`$RT_BASEDIR/gettimè
time_diff=`expr $current_time - $start_timè
if [ $time_diff -ge $RETRY_INTERVAL ]; then
# This failure happened after the time window
# elapsed, so reset the retries counter,
# slide the window, and do a retry.
retries=1
start_time=$current_time
# Because the previous failure occurred more than
# Retry_interval ago, attempt to restart the data service.
restart_service
if [ $? -ne 0 ]; then
logger -p ${SYSLOG_FACILITY}.err -t [$SYSLOG_TAG \
“${ARGV0} Failed to restart HA-DNS.”
exit 1
fi
254
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
示例 B–5 dns_probe 程序
(续)
elif [ $retries -ge $RETRY_COUNT ]; then
# Still within the time window,
# and the retry counter expired, so fail over.
retries=0
scha_control -O GIVEOVER -G $RESOURCEGROUP_NAME \
-R $RESOURCE_NAME
if [ $? -ne 0 ]; then
logger -p ${SYSLOG_FACILITY}.err -t [$SYSLOG_TAG] \
“${ARGV0} Failover attempt failed.”
exit 1
fi
else
# Still within the time window,
# and the retry counter has not expired,
# so do another retry.
retries=`expr $retries + 1`
restart_service
if [ $? -ne 0 ]; then
logger -p ${SYSLOG_FACILITY}.err -t [$SYSLOG_TAG] \
“${ARGV0} Failed to restart HA-DNS.”
exit 1
fi
fi
fi
}
###############################################################################
# MAIN
###############################################################################
export PATH=/bin:/usr/bin:/usr/cluster/bin:/usr/sbin:/usr/proc/bin:$PATH
# Obtain the syslog facility to use to log messages.
SYSLOG_FACILITY=`scha_cluster_get -O SYSLOG_FACILITY`
# Parse the arguments that have been passed to this method
parse_args “$@”
PMF_TAG=$RESOURCE_NAME.named
SYSLOG_TAG=$RESOURCETYPE_NAME,$RESOURCEGROUP_NAME,$RESOURCE_NAME
# The interval at which probing is to be done is set in the system defined
# property THOROUGH_PROBE_INTERVAL. Obtain the value of this property with
# scha_resource_get
PROBE_INTERVAL=scha_resource_get -O THOROUGH_PROBE_INTERVAL \
-R $RESOURCE_NAME -G $RESOURCEGROUP_NAM?
# Obtain the timeout value allowed for the probe, which is set in the
# PROBE_TIMEOUT extension property in the RTR file. The default timeout for
# nslookup is 1.5 minutes.
probe_timeout_info=`scha_resource_get -O Extension -R $RESOURCE_NAME \
-G $RESOURCEGROUP_NAME Probe_timeout`
PROBE_TIMEOUT=`echo $probe_timeout_info | awk ‘{print $2}’`
附录 B • 数据服务样例代码列表
255
示例 B–5 dns_probe 程序
(续)
# Identify the server on which DNS is serving by obtaining the value
# of the NETWORK_RESOURCES_USED property of the resource.
DNS_HOST=`scha_resource_get -O NETWORK_RESOURCES_USED -R $RESOURCE_NAME \
-G $RESOURCEGROUP_NAM?
# Get the retry count value from the system defined property Retry_count
RETRY_COUNT =`scha_resource_get -O RETRY_COUNT -R $RESOURCE_NAME \
-G $RESOURCEGROUP_NAM?
# Get the retry interval value from the system defined property
Retry_interval
RETRY_INTERVAL=scha_resource_get -O RETRY_INTERVAL -R $RESOURCE_NAME \
-G $RESOURCEGROUP_NAM?
# Obtain the full path for the gettime utility from the
# RT_basedir property of the resource type.
RT_BASEDIR=scha_resource_get -O RT_basedir -R $RESOURCE_NAME \
-G $RESOURCEGROUP_NAM?
# The probe runs in an infinite loop, trying nslookup commands.
# Set up a temporary file for the nslookup replies.
DNSPROBEFILE=/tmp/.$RESOURCE_NAME.probe
probefail=0
retries=0
while :
do
# The interval at which the probe needs to run is specified in the
# property THOROUGH_PROBE_INTERVAL. Therefore, set the probe to sleep for a
# duration of <THOROUGH_PROBE_INTERVAL>
sleep $PROBE_INTERVAL
# Run the probe, which queries the IP address on
# which DNS is serving.
hatimerun -t $PROBE_TIMEOUT /usr/sbin/nslookup $DNS_HOST $DNS_HOST \
> $DNSPROBEFILE 2>&1
retcode=$?
if [ retcode -ne 0 ]; then
probefail=1
fi
# Make sure that the reply to nslookup command comes from the HA-DNS
# server and not from another name server listed in the
# /etc/resolv.conf file.
if [ $probefail -eq 0 ]; then
# Get the name of the server that replied to the nslookup query.
SERVER=` awk ‘ $1==”Server:” {print $2 }’ \
$DNSPROBEFILE | awk -F. ‘ { print $1 } ‘ `
if [ -z “$SERVER” ];
then
probefail=1
256
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
示例 B–5 dns_probe 程序
(续)
else
if [ $SERVER != $DNS_HOST ]; then
probefail=1
fi
fi
fi
#
#
#
#
#
#
If the probefail variable is not set to 0, either the nslookup command
timed out or the reply to the query was came from another server
(specified in the /etc/resolv.conf file). In either case, the DNS server is
not responding and the method calls decide_restart_or_failover,
which evaluates whether to restart the data service or to fail it over
to another node.
if [ $probefail -ne 0 ]; then
decide_restart_or_failover
else
logger -p ${SYSLOG_FACILITY}.info -t [$SYSLOG_TAG] \
“${ARGV0} Probe for resource HA-DNS successful”
fi
done
Monitor_start 方法代码列表
此方法用来启动数据服务的 PROBE 程序。
示例 B–6 dns_monitor_start 方法
#!/bin/ksh
#
# Monitor start Method for HA-DNS.
#
# This method starts the monitor (probe) for the data service under the
# control of PMF. The monitor is a process that probes the data service
# at periodic intervals and if there is a problem restarts it on the same node
# or fails it over to another node in the cluster. The PMF tag for the
# monitor is $RESOURCE_NAME.monitor.
#pragma ident
“@(#)dns_monitor_start
1.1
00/05/24 SMI”
###############################################################################
# Parse program arguments.
#
function parse_args # [args ...]
{
typeset opt
257
示例 B–6 dns_monitor_start 方法
(续)
while getopts ‘R:G:T:’ opt
do
case “$opt” in
R)
# Name of the DNS resource.
RESOURCE_NAME=$OPTARG
;;
G)
# Name of the resource group in which the resource is
# configured.
RESOURCEGROUP_NAME=$OPTARG
;;
T)
# Name of the resource type.
RESOURCETYPE_NAME=$OPTARG
;;
*)
logger -p ${SYSLOG_FACILITY}.err \
-t [$RESOURCETYPE_NAME,$RESOURCEGROUP_NAME,$RESOURCE_NAME] \
“ERROR: Option $OPTARG unknown”
exit 1
;;
esac
done
}
###############################################################################
# MAIN
#
###############################################################################
export PATH=/bin:/usr/bin:/usr/cluster/bin:/usr/sbin:/usr/proc/bin:$PATH
# Obtain the syslog facility to use to log messages.
SYSLOG_FACILITY=`scha_cluster_get -O SYSLOG_FACILITY`
# Parse the arguments that have been passed to this method
parse_args “$@”
PMF_TAG=$RESOURCE_NAME.monitor
SYSLOG_TAG=$RESOURCETYPE_NAME,$RESOURCEGROUP_NAME,$RESOURCE_NAME
# Find where the probe method resides by obtaining the value of the
# RT_basedir property of the data service.
RT_BASEDIR=`scha_resource_get -O RT_basedir -R $RESOURCE_NAME \
-G $RESOURCEGROUP_NAM?
# Start the probe for the data service under PMF. Use the infinite retries
# option to start the probe. Pass the resource name, group, and type to the
# probe method.
pmfadm -c $PMF_TAG.monitor -n -1 -t -1 \
$RT_BASEDIR/dns_probe -R $RESOURCE_NAME -G $RESOURCEGROUP_NAME \
258
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
示例 B–6 dns_monitor_start 方法
(续)
-T $RESOURCETYPE_NAME
# Log a message indicating that the monitor for HA-DNS has been started.
if [ $? -eq 0 ]; then
logger -p ${SYSLOG_FACILITY}.info -t [$SYSLOG_TAG] \
“${ARGV0} Monitor for HA-DNS successfully started”
fi
exit 0
Monitor_stop 方法代码列表
此方法用来停止数据服务的 PROBE 程序。
示例 B–7 dns_monitor_stop 方法
#!/bin/ksh
# Monitor stop method for HA-DNS
# Stops the monitor that is running using PMF.
#pragma ident
“@(#)dns_monitor_stop
1.1
00/05/24 SMI”
###############################################################################
# Parse program arguments.
#
function parse_args # [args ...]
{
typeset opt
while getopts ‘R:G:T:’ opt
do
case “$opt” in
R)
# Name of the DNS resource.
RESOURCE_NAME=$OPTARG
;;
G)
# Name of the resource group in which the resource is
# configured.
RESOURCEGROUP_NAME=$OPTARG
;;
T)
# Name of the resource type.
RESOURCETYPE_NAME=$OPTARG
;;
*)
logger -p ${SYSLOG_FACILITY}.err \
-t [$RESOURCETYPE_NAME,$RESOURCEGROUP_NAME,$RESOURCE_NAME] \
附录 B • 数据服务样例代码列表
259
示例 B–7 dns_monitor_stop 方法
(续)
“ERROR: Option $OPTARG unknown”
exit 1
;;
esac
done
}
###############################################################################
# MAIN
#
###############################################################################
export PATH=/bin:/usr/bin:/usr/cluster/bin:/usr/sbin:/usr/proc/bin:$PATH
# Obtain the syslog facility to use to log messages.
SYSLOG_FACILITY=`scha_cluster_get -O SYSLOG_FACILITY`
# Parse the arguments that have been passed to this method
parse_args “$@”
PMF_TAG=$RESOURCE_NAME.monitor
SYSLOG_TAG=$RESOURCETYPE_NAME,$RESOURCEGROUP_NAME,$RESOURCE_NAME
# See if the monitor is running, and if so, kill it.
if pmfadm -q $PMF_TAG.monitor; then
pmfadm -s $PMF_TAG.monitor KILL
if [ $? -ne 0 ]; then
logger -p ${SYSLOG_FACILITY}.err -t [$SYSLOG_TAG] \
“${ARGV0} Could not stop monitor for resource “ \
$RESOURCE_NAME
exit 1
else
# Could successfully stop the monitor. Log a message.
logger -p ${SYSLOG_FACILITY}.info -t [$SYSLOG_TAG] \
“${ARGV0} Monitor for resource “ $RESOURCE_NAME \
“ successfully stopped”
fi
fi
exit 0
Monitor_check 方法代码列表
此方法用于验证 Confdir 属性指向的目录是否存在。只要 PROBE 方法将数据服务故障
转移到新节点上,以及要检查节点是不是潜在主控节点时,RGM 都将调用
Monitor_check。
示例 B–8 dns_monitor_check 方法
#!/bin/ksh#
# Monitor check
260
Method for DNS.
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
示例 B–8 dns_monitor_check 方法
(续)
#
# The RGM calls this method whenever the fault monitor fails the data service
# over to a new node. Monitor_check calls the Validate method to verify
# that the configuration directory and files are available on the new node.
#pragma ident
“@(#)dns_monitor_check 1.1
00/05/24 SMI”
###############################################################################
# Parse program arguments.
function parse_args # [args ...]
{
typeset opt
while getopts ‘R:G:T:’ opt
do
case “$opt” in
R)
# Name of the DNS resource.
RESOURCE_NAME=$OPTARG
;;
G)
# Name of the resource group in which the resource is
# configured.
RESOURCEGROUP_NAME=$OPTARG
;;
T)
# Name of the resource type.
RESOURCETYPE_NAME=$OPTARG
;;
*)
logger -p ${SYSLOG_FACILITY}.err \
-t [$RESOURCETYPE_NAME,$RESOURCEGROUP_NAME,$RESOURCE_NAME] \
“ERROR: Option $OPTARG unknown”
exit 1
;;
esac
done
}
###############################################################################
# MAIN
###############################################################################
export PATH=/bin:/usr/bin:/usr/cluster/bin:/usr/sbin:/usr/proc/bin:$PATH
# Obtain the syslog facility to use to log messages.
SYSLOG_FACILITY=`scha_cluster_get -O SYSLOG_FACILITY`
261
示例 B–8 dns_monitor_check 方法
(续)
# Parse the arguments that have been passed to this method.
parse_args “$@”
PMF_TAG=$RESOURCE_NAME.named
SYSLOG_TAG=$RESOURCETYPE_NAME,$RESOURCEGROUP_NAME,$RESOURCE_NAME
# Obtain the full path for the Validate method from
# the RT_basedir property of the resource type.
RT_BASEDIR=`scha_resource_get -O RT_basedir -R $RESOURCE_NAME \
-G $RESOURCEGROUP_NAM?
# Obtain the name of the Validate method for this resource.
VALIDATE_METHOD=`scha_resource_get -O VALIDATE -R $RESOURCE_NAME \
-G $RESOURCEGROUP_NAM?
# Obtain the value of the Confdir property in order to start the
# data service. Use the resource name and the resource group entered to
# obtain the Confdir value set at the time of adding the resource.
config_info=`scha_resource_get -O Extension -R $RESOURCE_NAME \
-G $RESOURCEGROUP_NAME Confdir`
# scha_resource_get returns the type as well as the value for extension
# properties. Use awk to get only the value of the extension property.
CONFIG_DIR=`echo $config_info | awk ‘{print $2}’`
# Call the validate method so that the dataservice can be failed over
# successfully to the new node.
$RT_BASEDIR/$VALIDATE_METHOD -R $RESOURCE_NAME -G $RESOURCEGROUP_NAME \
-T $RESOURCETYPE_NAME -x Confdir=$CONFIG_DIR
# Log a message indicating that monitor check was successful.
if [ $? -eq 0 ]; then
logger -p ${SYSLOG_FACILITY}.info -t [$SYSLOG_TAG] \
“${ARGV0} Monitor check for DNS successful.”
exit 0
else
logger -p ${SYSLOG_FACILITY}.err -t [$SYSLOG_TAG] \
“${ARGV0} Monitor check for DNS not successful.”
exit 1
fi
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
示例 B–9 dns_validate 方法
#!/bin/ksh
# Validate method for HA-DNS.
# This method validates the Confdir property of the resource. The Validate
# method gets called in two scenarios. When the resource is being created and
# when a resource property is getting updated. When the resource is being
# created, this method gets called with the -c flag and all the system-defined
# and extension properties are passed as command-line arguments. When a resource
# property is being updated, the Validate method gets called with the -u flag,
# and only the property/value pair of the property being updated is passed as a
# command-line argument.
#
# ex: When the resource is being created command args will be
#
# dns_validate -c -R <..> -G <...> -T <..> -r <sysdef-prop=value>...
#
-x <extension-prop=value>.... -g <resourcegroup-prop=value>....
#
# when the resource property is being updated
#
# dns_validate -u -R <..> -G <...> -T <..> -r <sys-prop_being_updated=value>
#
OR
# dns_validate -u -R <..> -G <...> -T <..> -x <extn-prop_being_updated=value>
#pragma ident
“@(#)dns_validate
1.1
00/05/24 SMI”
###############################################################################
# Parse program arguments.
#
function parse_args # [args ...]
{
typeset opt
while getopts ‘cur:x:g:R:T:G:’ opt
do
case “$opt” in
R)
# Name of the DNS resource.
RESOURCE_NAME=$OPTARG
;;
G)
# Name of the resource group in which the resource is
# configured.
RESOURCEGROUP_NAME=$OPTARG
;;
T)
# Name of the resource type.
RESOURCETYPE_NAME=$OPTARG
;;
r)
#The method is not accessing any system defined
#properties, so this is a no-op.
;;
g)
# The method is not accessing any resource group
附录 B • 数据服务样例代码列表
263
示例 B–9 dns_validate 方法
(续)
# properties, so this is a no-op.
;;
c)
# Indicates the Validate method is being called while
# creating the resource, so this flag is a no-op.
;;
u)
# Indicates the updating of a property when the
# resource already exists. If the update is to the
# Confdir property then Confdir should appear in the
# command-line arguments. If it does not, the method must
# look for it specifically using scha_resource_get.
UPDATE_PROPERTY=1
;;
x)
# Extension property list. Separate the property and
# value pairs using “=” as the separator.
PROPERTY=`echo $OPTARG | awk -F= ‘{print $1}’`
VAL=echo $OPTARG | awk -F= ‘{print $2}’`
# If the Confdir extension property is found on the
# command line, note its value.
if [ $PROPERTY == “Confdir” ];
then
CONFDIR=$VAL
CONFDIR_FOUND=1
fi
;;
*)
logger -p ${SYSLOG_FACILITY}.err \
-t [$SYSLOG_TAG] \
“ERROR: Option $OPTARG unknown”
exit 1
;;
esac
done
}
###############################################################################
# MAIN
#
###############################################################################
export PATH=/bin:/usr/bin:/usr/cluster/bin:/usr/sbin:/usr/proc/bin:$PATH
# Obtain the syslog facility to use to log messages.
SYSLOG_FACILITY=`scha_cluster_get -O SYSLOG_FACILITY`
# Set the Value of CONFDIR to null. Later, this method retrieves the value
# of the Confdir property from the command line or using scha_resource_get.
CONFDIR=””
UPDATE_PROPERTY=0
CONFDIR_FOUND=0
264
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
示例 B–9 dns_validate 方法
(续)
# Parse the arguments that have been passed to this method.
parse_args “$@”
# If the validate method is being called due to the updating of properties
# try to retrieve the value of the Confdir extension property from the command
# line. Otherwise, obtain the value of Confdir using scha_resource_get.
if ( (( $UPDATE_PROPERTY == 1 )) && (( CONFDIR_FOUND == 0 )) ); then
config_info=scha_resource_get -O Extension -R $RESOURCE_NAME \
-G $RESOURCEGROUP_NAME Confdir`
CONFDIR=`echo $config_info | awk ‘{print $2}’`
fi
# Verify that the Confdir property has a value. If not there is a failure
# and exit with status 1.
if [[ -z $CONFDIR ]]; then
logger -p ${SYSLOG_FACILITY}.err \
“${ARGV0} Validate method for resource “$RESOURCE_NAME “ failed”
exit 1
fi
# Now validate the actual Confdir property value.
# Check if $CONFDIR is accessible.
if [ ! -d $CONFDIR ]; then
logger -p ${SYSLOG_FACILITY}.err -t [$SYSLOG_TAG] \
“${ARGV0} Directory $CONFDIR missing or not mounted”
exit 1
fi
# Check that the named.conf file is present in the Confdir directory.
if [ ! -s $CONFDIR/named.conf ]; then
logger -p ${SYSLOG_FACILITY}.err -t [$SYSLOG_TAG] \
“${ARGV0} File $CONFDIR/named.conf is missing or empty”
exit 1
fi
# Log a message indicating that the Validate method was successful.
logger -p ${SYSLOG_FACILITY}.info -t [$SYSLOG_TAG] \
“${ARGV0} Validate method for resource “$RESOURCE_NAME \
“ completed successfully”
exit 0
265
Update 方法代码列表
RGM 调用 Update 方法通知正在运行的资源其属性已更改。
示例 B–10 dns_update 方法
#!/bin/ksh
# Update method for HA-DNS.
# The actual updates to properties are done by the RGM. Updates affect only
# the fault monitor so this method must restart the fault monitor.
#pragma ident
“@(#)dns_update
1.1
00/05/24 SMI”
###############################################################################
# Parse program arguments.
#
function parse_args # [args ...]
{
typeset opt
while getopts ‘R:G:T:’ opt
do
case “$opt” in
R)
# Name of the DNS resource.
RESOURCE_NAME=$OPTARG
;;
G)
# Name of the resource group in which the resource is
# configured.
RESOURCEGROUP_NAME=$OPTARG
;;
T)
# Name of the resource type.
RESOURCETYPE_NAME=$OPTARG
;;
*)
logger -p ${SYSLOG_FACILITY}.err \
-t [$RESOURCETYPE_NAME,$RESOURCEGROUP_NAME,$RESOURCE_NAME] \
“ERROR: Option $OPTARG unknown”
exit 1
;;
esac
done
}
###############################################################################
# MAIN
###############################################################################
export PATH=/bin:/usr/bin:/usr/cluster/bin:/usr/sbin:/usr/proc/bin:$PATH
# Obtain the syslog facility to use to log messages.
SYSLOG_FACILITY=`scha_cluster_get -O SYSLOG_FACILITY`
266
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
示例 B–10 dns_update 方法
(续)
# Parse the arguments that have been passed to this method
parse_args “$@”
PMF_TAG=$RESOURCE_NAME.monitor
SYSLOG_TAG=$RESOURCETYPE_NAME,$RESOURCEGROUP_NAME,$RESOURCE_NAME
# Find where the probe method resides by obtaining the value of the
# RT_basedir property of the resource.
RT_BASEDIR=`scha_resource_get -O RT_basedir -R $RESOURCE_NAME \
-G $RESOURCEGROUP_NAM?
# When the Update method is called, the RGM updates the value of the property
# being updated. This method must check if the fault monitor (probe)
# is running, and if so, kill it and then restart it.
if pmfadm -q $PMF_TAG.monitor; then
# Kill the monitor that is running already
pmfadm -s $PMF_TAG.monitor TERM
if [ $? -ne 0 ]; then
logger -p ${SYSLOG_FACILITY}.err -t [$SYSLOG_TAG] \
“${ARGV0} Could not stop the monitor”
exit 1
else
# Could successfully stop DNS. Log a message.
logger -p ${SYSLOG_FACILITY}.info -t [$SYSLOG_TAG] \
“Monitor for HA-DNS successfully stopped”
fi
# Restart the monitor.
pmfadm -c $PMF_TAG.monitor -n -1 -t -1 $RT_BASEDIR/dns_probe \
-R $RESOURCE_NAME -G $RESOURCEGROUP_NAME -T $RESOURCETYPE_NAME
if [ $? -ne 0 ]; then
logger -p ${SYSLOG_FACILITY}.err -t [$SYSLOG_TAG] \
“${ARGV0} Could not restart monitor for HA-DNS “
exit 1
else
logger -p ${SYSLOG_FACILITY}.info -t [$SYSLOG_TAG] \
“Monitor for HA-DNS successfully restarted”
fi
fi
exit 0
267
268
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
附录 C
第 269 页中的 “xfnts.c 文件列表”
第 281 页中的 “xfnts_monitor_check 方法代码列表”
第 282 页中的 “xfnts_monitor_start 方法代码列表”
第 283 页中的 “xfnts_monitor_stop 方法代码列表”
第 284 页中的 “xfnts_probe 方法代码列表”
第 287 页中的 “xfnts_start 方法代码列表”
第 288 页中的 “xfnts_stop 方法代码列表”
第 289 页中的 “xfnts_update 方法代码列表”
第 291 页中的 “xfnts_validate 方法代码列表”
xfnts.c 文件列表
此文件用于实现由 SUNW.xfnts 方法调用的子例行程序。
示例 C–1 xfnts.c
/*
*
*
*
*
*
*
*
*
Copyright (c) 1998-2005 by Sun Microsystems, Inc.
All rights reserved.
xfnts.c - Common utilities for HA-XFS
This utility has the methods for performing the validation, starting and
stopping the data service and the fault monitor. It also contains the method
to probe the health of the data service. The probe just returns either
269
示例 C–1 xfnts.c
(续)
* success or failure. Action is taken based on this returned value in the
* method found in the file xfnts_probe.c
*
*/
#pragma ident “@(#)xfnts.c 1.47 01/01/18 SMI”
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
<stdio.h>
<stdlib.h>
<strings.h>
<unistd.h>
<sys/types.h>
<sys/stat.h>
<sys/socket.h>
<sys/wait.h>
<netinet/in.h>
<scha.h>
<rgm/libdsdev.h>
<errno.h>
“xfnts.h”
/*
* The initial timeout allowed for the HAXFS data service to
* be fully up and running. We will wait for 3 % (SVC_WAIT_PCT)
* of the start_timeout time before probing the service.
*/
#define
SVC_WAIT_PCT
3
/*
* We need to use 95% of probe_timeout to connect to the port and the
* remaining time is used to disconnect from port in the svc_probe function.
*/
#define
SVC_CONNECT_TIMEOUT_PCT
95
/*
* SVC_WAIT_TIME is used only during starting in svc_wait().
* In svc_wait() we need to be sure that the service is up
* before returning, thus we need to call svc_probe() to
* monitor the service. SVC_WAIT_TIME is the time between
* such probes.
*/
#define
SVC_WAIT_TIME
5
/*
* This value will be used as disconnect timeout, if there is no
* time left from the probe_timeout.
*/
#define
SVC_DISCONNECT_TIMEOUT_SECONDS
2
/*
* svc_validate():
*
270
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
示例 C–1 xfnts.c
(续)
* Do HA-XFS specific validation of the resource configuration.
*
* svc_validate will check for the following
* 1. Confdir_list extension property
* 2. fontserver.cfg file
* 3. xfs binary
* 4. port_list property
* 5. network resources
* 6. other extension properties
*
* If any of the above validation fails then, Return > 0 otherwise return 0 for
* success
*/
int
svc_validate(scds_handle_t scds_handle)
{
char
xfnts_conf[SCDS_ARRAY_SIZE];
scha_str_array_t *confdirs;
scds_net_resource_list_t *snrlp;
int rc;
struct stat statbuf;
scds_port_list_t
*portlist;
scha_err_t
err;
/*
* Get the configuration directory for the XFS dataservice from the
* confdir_list extension property.
*/
confdirs = scds_get_ext_confdir_list(scds_handle);
/* Return an error if there is no confdir_list extension property */
if (confdirs == NULL || confdirs->array_cnt != 1) {
scds_syslog(LOG_ERR,
“Property Confdir_list is not set properly.”);
return (1); /* Validation failure */
}
/*
* Construct the path to the configuration file from the extension
* property confdir_list. Since HA-XFS has only one configuration
* we will need to use the first entry of the confdir_list property.
*/
(void) sprintf(xfnts_conf, “%s/fontserver.cfg”, confdirs->str_array[0]);
/*
* Check to see if the HA-XFS configuration file is in the right place.
* Try to access the HA-XFS configuration file and make sure the
* permissions are set properly
*/
if (stat(xfnts_conf, &statbuf) != 0) {
/*
* suppress lint error because errno.h prototype
附录 C • DSDL 样例资源类型代码列表
271
示例 C–1 xfnts.c
(续)
* is missing void arg
*/
scds_syslog(LOG_ERR,
“Failed to access file <%s> : <%s>”,
xfnts_conf, strerror(errno));
/*lint !e746 */
return (1);
}
/*
* Make sure that xfs binary exists and that the permissions
* are correct. The XFS binary are assumed to be on the local
* File system and not on the Global File System
*/
if (stat(“/usr/openwin/bin/xfs”, &statbuf) != 0) {
scds_syslog(LOG_ERR,
“Cannot access XFS binary : <%s> “, strerror(errno));
return (1);
}
/* HA-XFS will have only port */
err = scds_get_port_list(scds_handle, &portlist);
if (err != SCHA_ERR_NOERR) {
scds_syslog(LOG_ERR,
“Could not access property Port_list: %s.”,
scds_error_string(err));
return (1); /* Validation Failure */
}
#ifdef TEST
if (portlist->num_ports != 1) {
scds_syslog(LOG_ERR,
“Property Port_list must have only one value.”);
scds_free_port_list(portlist);
return (1); /* Validation Failure */
}
#endif
/*
* Return an error if there is an error when trying to get the
* available network address resources for this resource
*/
if ((err = scds_get_rs_hostnames(scds_handle, &snrlp))
!= SCHA_ERR_NOERR) {
scds_syslog(LOG_ERR,
“No network address resource in resource group: %s.”,
scds_error_string(err));
return (1); /* Validation Failure */
}
/* Return an error if there are no network address resources */
if (snrlp == NULL || snrlp->num_netresources == 0) {
scds_syslog(LOG_ERR,
“No network address resource in resource group.”);
272
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
示例 C–1 xfnts.c
(续)
rc = 1;
goto finished;
}
/* Check to make sure other important extension props are set */
if (scds_get_ext_monitor_retry_count(scds_handle) <= 0)
{
scds_syslog(LOG_ERR,
“Property Monitor_retry_count is not set.”);
rc = 1; /* Validation Failure */
goto finished;
}
if (scds_get_ext_monitor_retry_interval(scds_handle) <= 0) {
scds_syslog(LOG_ERR,
“Property Monitor_retry_interval is not set.”);
rc = 1; /* Validation Failure */
goto finished;
}
/* All validation checks were successful */
scds_syslog(LOG_INFO, “Successful validation.”);
rc = 0;
finished:
scds_free_net_list(snrlp);
scds_free_port_list(portlist);
return (rc); /* return result of validation */
}
/*
* svc_start():
*
* Start up the X font server
* Return 0 on success, > 0 on failures.
*
* The XFS service will be started by running the command
* /usr/openwin/bin/xfs -config <fontserver.cfg file> -port <port to listen>
* XFS will be started under PMF. XFS will be started as a single instance
* service. The PMF tag for the data service will be of the form
* <resourcegroupname,resourcename,instance_number.svc>. In case of XFS, since
* there will be only one instance the instance_number in the tag will be 0.
*/
int
svc_start(scds_handle_t scds_handle)
{
char
xfnts_conf[SCDS_ARRAY_SIZE];
char
cmd[SCDS_ARRAY_SIZE];
scha_str_array_t *confdirs;
scds_port_list_t
*portlist;
scha_err_t
err;
273
示例 C–1 xfnts.c
(续)
/* 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);
}
/*
* Construct the command to start HA-XFS.
* NOTE: XFS daemon prints the following message while stopping the XFS
* “/usr/openwin/bin/xfs notice: terminating”
* In order to suppress the daemon message,
* the output is redirected to /dev/null.
*/
(void) sprintf(cmd,
“/usr/openwin/bin/xfs -config %s -port %d 2>/dev/null”,
xfnts_conf, portlist->ports[0].port);
/*
* Start HA-XFS under PMF. Note that HA-XFS is started as a single
* instance service. The last argument to the scds_pmf_start function
* denotes the level of children to be monitored. A value of -1 for
* this parameter means that all the children along with the original
* process are to be monitored.
*/
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 “);
}
scds_free_port_list(portlist);
return (err); /* return Success/failure status */
}
/*
* svc_stop():
*
* Stop the XFS server
* Return 0 on success, > 0 on failures.
274
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
示例 C–1 xfnts.c
(续)
*
* svc_stop will stop the server by calling the toolkit function:
* scds_pmf_stop.
*/
int
svc_stop(scds_handle_t scds_handle)
{
scha_err_t
err;
/*
* The timeout value for the stop method to succeed is set in the
* Stop_Timeout (system defined) property
*/
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 */
}
/*
* svc_wait():
*
* wait for the data service to start up fully and make sure it is running
* healthy
*/
int
svc_wait(scds_handle_t scds_handle)
{
int rc, svc_start_timeout, probe_timeout;
scds_netaddr_list_t
*netaddr;
/* 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.”);
附录 C • DSDL 样例资源类型代码列表
275
示例 C–1 xfnts.c
(续)
return (1);
}
/*
* Get the Start method timeout, port number on which to probe,
* the Probe timeout value
*/
svc_start_timeout = scds_get_rs_start_timeout(scds_handle);
probe_timeout = scds_get_ext_probe_timeout(scds_handle);
/*
* sleep for SVC_WAIT_PCT percentage of start_timeout time
* before actually probing the dataservice. This is to allow
* the dataservice to be fully up in order to reply to the
* probe. NOTE: the value for SVC_WAIT_PCT could be different
* for different data services.
* Instead of calling sleep(),
* call scds_svc_wait() so that if service fails too
* many times, we give up and return early.
*/
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);
}
/*
* Dataservice is still trying to come up. Sleep for a while
* before probing again. Instead of calling sleep(),
* call scds_svc_wait() so that if service fails too
* many times, we give up and return early.
*/
if (scds_svc_wait(scds_handle, SVC_WAIT_TIME)
!= SCHA_ERR_NOERR) {
scds_syslog(LOG_ERR, “Service failed to start.”);
return (1);
}
276
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
示例 C–1 xfnts.c
(续)
/* We rely on RGM to timeout and terminate the program */
} while (1);
}
/*
* This function starts the fault monitor for a HA-XFS resource.
* This is done by starting the probe under PMF. The PMF tag
* is derived as <RG-name,RS-name,instance_number.mon>. The restart option
* of PMF is used but not the “infinite restart”. Instead
* interval/retry_time is obtained from the RTR file.
*/
int
mon_start(scds_handle_t scds_handle)
{
scha_err_t
err;
scds_syslog_debug(DBG_LEVEL_HIGH,
“Calling MONITOR_START method for resource <%s>.”,
scds_get_resource_name(scds_handle));
/*
* The probe xfnts_probe is assumed to be available in the same
* subdirectory where the other callback methods for the RT are
* installed. The last parameter to scds_pmf_start denotes the
* child monitor level. Since we are starting the probe under PMF
* we need to monitor the probe process only and hence we are using
* a value of 0.
*/
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 */
}
/*
* This function stops the fault monitor for a HA-XFS resource.
* This is done via PMF. The PMF tag for the fault monitor is
* constructed based on <RG-name_RS-name,instance_number.mon>.
*/
int
附录 C • DSDL 样例资源类型代码列表
277
示例 C–1 xfnts.c
(续)
mon_stop(scds_handle_t scds_handle)
{
scha_err_t
err;
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 */
}
/*
* svc_probe(): Do data service specific probing. Return a float value
* between 0 (success) and 100(complete failure).
*
* The probe does a simple socket connection to the XFS server on the specified
* port which is configured as the resource extension property (Port_list) and
* pings the dataservice. If the probe fails to connect to the port, we return
* a value of 100 indicating that there is a total failure. If the connection
* goes through and the disconnect to the port fails, then a value of 50 is
* returned indicating a partial failure.
*/
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;
/*
*
*
*
*
*
278
probe the dataservice by doing a socket connection to the port
specified in the port_list property to the host that is
serving the XFS dataservice. 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
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
示例 C–1 xfnts.c
(续)
* 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 “
附录 C • DSDL 样例资源类型代码列表
279
示例 C–1 xfnts.c
(续)
“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”,
280
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
示例 C–1 xfnts.c
(续)
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);
}
xfnts_monitor_check 方法代码列表
此方法用来检验基本资源类型的配置是否有效。
示例 C–2 xfnts_monitor_check.c
/*
* Copyright (c) 1998-2005 by Sun Microsystems, Inc.
* All rights reserved.
*
* xfnts_monitor_check.c - Monitor Check method for HA-XFS
*/
#pragma ident “@(#)xfnts_monitor_check.c 1.11 01/01/18
SMI”
#include <rgm/libdsdev.h>
#include “xfnts.h”
/*
* just make a simple validate check on the service
*/
int
main(int argc, char *argv[])
{
scds_handle_t
scds_handle;
int
rc;
/* 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.”);
附录 C • DSDL 样例资源类型代码列表
281
示例 C–2 xfnts_monitor_check.c
(续)
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);
}
xfnts_monitor_start 方法代码列表
此方法用于启动 xfnts_probe 方法。
示例 C–3 xfnts_monitor_start.c
/*
* Copyright (c) 1998-2005 by Sun Microsystems, Inc.
* All rights reserved.
*
* xfnts_monitor_start.c - Monitor Start method for HA-XFS
*/
#pragma ident “@(#)xfnts_monitor_start.c 1.10 01/01/18
SMI”
#include <rgm/libdsdev.h>
#include “xfnts.h”
/*
* This method starts the fault monitor for a HA-XFS resource.
* This is done by starting the probe under PMF. The PMF tag
* is derived as RG-name,RS-name.mon. The restart option of PMF
* is used but not the “infinite restart”. Instead
* interval/retry_time is obtained from the RTR file.
*/
int
main(int argc, char *argv[])
{
scds_handle_t
scds_handle;
int
rc;
282
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
示例 C–3 xfnts_monitor_start.c
(续)
/* Process 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 = mon_start(scds_handle);
/* Free up all the memory allocated by scds_initialize */
scds_close(&scds_handle);
/* Return the result of monitor_start method */
return (rc);
}
xfnts_monitor_stop 方法代码列表
此方法用来停止 xfnts_probe 方法。
示例 C–4 xfnts_monitor_stop.c
/*
* Copyright (c) 1998-2005 by Sun Microsystems, Inc.
* All rights reserved.
*
* xfnts_monitor_stop.c - Monitor Stop method for HA-XFS
*/
#pragma ident “@(#)xfnts_monitor_stop.c 1.9 01/01/18 SMI”
#include <rgm/libdsdev.h>
#include “xfnts.h”
/*
* This method stops the fault monitor for a HA-XFS resource.
* This is done via PMF. The PMF tag for the fault monitor is
* constructed based on RG-name_RS-name.mon.
*/
int
main(int argc, char *argv[])
{
scds_handle_t
int
rc;
scds_handle;
283
示例 C–4 xfnts_monitor_stop.c
(续)
/* Process 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 = mon_stop(scds_handle);
/* Free up all the memory allocated by scds_initialize */
scds_close(&scds_handle);
/* Return the result of monitor stop method */
return (rc);
}
xfnts_probe 方法代码列表
xfnts_probe 方法用于检查应用程序的可用性并确定是故障转移还是重新启动数据服
务。xfnts_monitor_start 回调方法用于启动此程序,xfnts_monitor_stop 回
调方法用于停止此程序。
示例 C–5 xfnts_probe.c
/*
* Copyright (c) 1998-2005 by Sun Microsystems, Inc.
* All rights reserved.
*
* xfnts_probe.c - Probe for HA-XFS
*/
#pragma ident “@(#)xfnts_probe.c 1.26 01/01/18 SMI”
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
<stdio.h>
<stdlib.h>
<strings.h>
<unistd.h>
<signal.h>
<sys/time.h>
<sys/socket.h>
<strings.h>
<rgm/libdsdev.h>
“xfnts.h”
/*
* main():
284
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
示例 C–5 xfnts_probe.c
(续)
* Just an infinite loop which sleep()s for sometime, waiting for
* the PMF action script to interrupt the sleep(). When interrupted
* It calls the start method for HA-XFS to restart it.
*
*/
int
main(int argc, char *argv[])
{
int
timeout;
int
port, ip, probe_result;
scds_handle_t
scds_handle;
hrtime_t
ht1, ht2;
unsigned long
dt;
scds_netaddr_list_t *netaddr;
char
*hostname;
if (scds_initialize(&scds_handle, argc, argv) != SCHA_ERR_NOERR)
{
scds_syslog(LOG_ERR, “Failed to initialize the handle.”);
return (1);
}
/* Get the ip addresses available for this resource */
if (scds_get_netaddr_list(scds_handle, &netaddr)) {
scds_syslog(LOG_ERR,
“No network address resource in resource group.”);
scds_close(&scds_handle);
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);
}
/*
* Set the timeout from the X props. This means that each probe
* iteration will get a full timeout on each network resource
* without chopping up the timeout between all of the network
* resources configured for this resource.
*/
timeout = scds_get_ext_probe_timeout(scds_handle);
for (;;) {
/*
* sleep for a duration of thorough_probe_interval between
* successive probes.
附录 C • DSDL 样例资源类型代码列表
285
示例 C–5 xfnts_probe.c
(续)
*/
(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 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);
}
286
/*
* Compute failure history and take
* action if needed
*/
(void) scds_fm_action(scds_handle,
probe_result, (long)dt);
}
/* Each net resource */
/* Keep probing forever */
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
示例 C–5 xfnts_probe.c
(续)
}
xfnts_start 方法代码列表
当包含数据服务资源的资源组在群集节点上被联机或者该资源已启用时,RGM 将在该
群集节点上运行 Start 方法。xfnts_start 方法将激活该节点上的 xfs 守护进程。
示例 C–6 xfnts_start.c
/*
* Copyright (c) 1998-2005 by Sun Microsystems, Inc.
* All rights reserved.
*
* xfnts_svc_start.c - Start method for HA-XFS
*/
#pragma ident “@(#)xfnts_svc_start.c 1.13 01/01/18 SMI”
#include <rgm/libdsdev.h>
#include “xfnts.h”
/*
* The start method for HA-XFS. Does some sanity checks on
* the resource settings then starts the HA-XFS under PMF with
* an action script.
*/
int
main(int argc, char *argv[])
{
scds_handle_t
scds_handle;
int rc;
/*
* Process all the arguments that have been passed to us from RGM
* and do some initialization for syslog
*/
if (scds_initialize(&scds_handle, argc, argv) != SCHA_ERR_NOERR)
{
scds_syslog(LOG_ERR, “Failed to initialize the handle.”);
return (1);
}
/* Validate the configuration and if there is an error return back */
rc = svc_validate(scds_handle);
if (rc != 0) {
附录 C • DSDL 样例资源类型代码列表
287
示例 C–6 xfnts_start.c
(续)
scds_syslog(LOG_ERR,
“Failed to validate configuration.”);
return (rc);
}
/* Start the data service, if it fails return with an error */
rc = svc_start(scds_handle);
if (rc != 0) {
goto finished;
}
/* 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.”);
}
finished:
/* Free up the Environment resources that were allocated */
scds_close(&scds_handle);
return (rc);
}
xfnts_stop 方法代码列表
包含 HA-XFS 资源的资源组在群集节点上脱机或禁用资源后,RGM 将在该节点上运行
Stop 方法。此方法将停止该节点上的 xfs 守护进程。
示例 C–7 xfnts_stop.c
/*
* Copyright (c) 1998-2005 by Sun Microsystems, Inc.
* All rights reserved.
*
* xfnts_svc_stop.c - Stop method for HA-XFS
*/
288
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
示例 C–7 xfnts_stop.c
(续)
#pragma ident “@(#)xfnts_svc_stop.c 1.10 01/01/18 SMI”
#include <rgm/libdsdev.h>
#include “xfnts.h”
/*
* Stops the HA-XFS process using PMF
*/
int
main(int argc, char *argv[])
{
scds_handle_t
int
rc;
scds_handle;
/* 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_stop(scds_handle);
/* Free up all the memory allocated by scds_initialize */
scds_close(&scds_handle);
/* Return the result of svc_stop method */
return (rc);
}
xfnts_update 方法代码列表
RGM 调用 Update 方法通知运行资源其属性已被更改。设置资源或资源组的管理操作
成功后,RGM 将运行 Update。
示例 C–8 xfnts_update.c
#pragma ident "@(#)xfnts_update.c
1.10
01/01/18 SMI"
/*
* Copyright (c) 1998-2005 by Sun Microsystems, Inc.
* All rights reserved.
*
* xfnts_update.c - Update method for HA-XFS
附录 C • DSDL 样例资源类型代码列表
289
示例 C–8 xfnts_update.c
(续)
*/
#include
#include
#include
#include
<stdio.h>
<stdlib.h>
<signal.h>
<rgm/libdsdev.h>
/*
* Some of the resource properties might have been updated. All such
* updatable properties are related to the fault monitor. Hence, just
* restarting the monitor should be enough.
*/
int
main(int argc, char *argv[])
{
scds_handle_t
scds_handle;
scha_err_t
result;
/* 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);
}
/*
* 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.”);
/* Free up all the memory allocated by scds_initialize */
scds_close(&scds_handle);
return (0);
}
290
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
xfnts_validate 方法代码列表
此方法将验证 Confdir_list 属性所指向的目录是否存在。当创建数据服务以及群集
管理员更新数据服务属性时,RGM 都将调用此方法。只要故障监视器将数据服务故障
转移到新节点上,Monitor_check 方法就将调用此方法。
示例 C–9 xfnts_validate.c
/*
* Copyright (c) 1998-2005 by Sun Microsystems, Inc.
* All rights reserved.
*
* xfnts_validate.c - validate method for HA-XFS
*/
#pragma ident “@(#)xfnts_validate.c 1.9 01/01/18 SMI”
#include <rgm/libdsdev.h>
#include “xfnts.h”
/*
* Check to make sure that the properties have been set properly.
*/
int
main(int argc, char *argv[])
{
scds_handle_t
scds_handle;
int
rc;
/* Process 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);
/* Free up all the memory allocated by scds_initialize */
scds_close(&scds_handle);
/* Return the result of validate method */
return (rc);
}
291
292
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
附录 D
293
如果资源类型的资源类型注册 (RTR) 文件包含 #$upgrade 指令,则其格式如下:
vendor-id.base-rt-name:rt-version
■
如果资源类型的 RTR 文件不包含 #$upgrade 指令,则其格式如下:
vendor-id.base-rt-name
句号将 vendor-id 和 base-rt-name 隔开。冒号将 base-rt-name 和 rt-version 隔开。
此格式中的变量元素的作用如下所示:
vendor-id
base-rt-name
指定基本资源类型名称,其值为 RTR 文件中 Resource_type 资源类
型属性的值。
rt-version
指定版本后缀,其值为 RTR 文件中 RT_version 资源类型属性的值。
如果 RTR 文件包含 #$upgrade 指令,则版本后缀仅是完整资源类型名
称的一部分。Sun Cluster 产品的 3.1 版中引入了 #$upgrade 指令。
包含 #$upgrade 指令的资源类型的完整名称
Vendor_id=SUNW
Resource_type=sample
RT_version=2.0
由此 RTR 文件所定义的资源类型的完整名称如下:
SUNW.sample:2.0
示例 D–2
294
Vendor_id=SUNW
Resource_type=nfs
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
示例 D–2
(续)
由此 RTR 文件所定义的资源类型的完整名称如下:
SUNW.nfs
■
■
295
296
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
附录 E
298
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
299
300
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
附录 F
第 301 页中的 “SC_CALLBACK_REG XML DTD”
第 303 页中的 “NVPAIR XML DTD”
第 304 页中的 “SC_REPLY XML DTD”
第 305 页中的 “SC_EVENT XML DTD”
SC_CALLBACK_REG XML DTD
注 – 由 SC_CALLBACK_REG 和 SC_EVENT 使用的 NVPAIR 数据结构仅被定义一次。
<!— SC_CALLBACK_REG XML format specification
Copyright 2001-2005 Sun Microsystems, Inc. All rights reserved.
Use is subject to license terms.
Intended Use:
A client of the Cluster Reconfiguration Notification Protocol should use this xml format
to register initially with the service, to subsequently register for more events, to
subsequently remove registration of some events, or to remove itself from the service
entirely.
A client is uniquely identified by its callback IP and port. The port is defined in the
SC_CALLBACK_REG element, and the IP is taken as the source IP of the registration
connection. The final attribute of the root SC_CALLBACK_REG element is either an
ADD_CLIENT, ADD_EVENTS, REMOVE_CLIENT, or REMOVE_EVENTS, depending on which form of the
message the client is using.
The SC_CALLBACK_REG contains 0 or more SC_EVENT_REG sub-elements.
301
One SC_EVENT_REG is the specification for one event type. A client may specify only the
CLASS (an attribute of the SC_EVENT_REG element), or may specify a SUBCLASS (an optional
attribute) for further granularity. Also, the SC_EVENT_REG has as subelements 0 or more
NVPAIRs, which can be used to further specify the event.
Thus, the client can specify events to whatever granularity it wants. Note that a client
cannot both register for and unregister for events in the same message. However a client
can subscribe to the service and sign up for events in the same message.
Note on versioning: the VERSION attribute of each root element is marked "fixed", which
means that all message adhering to these DTDs must have the version value specified. If a
new version of the protocol is created, the revised DTDs will have a new value for this
fixed" VERSION attribute, such that all message adhering to the new version must have the
new version number.
—>
<!— SC_CALLBACK_REG definition
The root element of the XML document is a registration message. A registration message
consists of the callback port and the protocol version as attributes, and either an
ADD_CLIENT, ADD_EVENTS, REMOVE_CLIENT, or REMOVE_EVENTS attribute, specifying the
registration type. The ADD_CLIENT, ADD_EVENTS, and REMOVE_EVENTS types should have one or
more SC_EVENT_REG subelements. The REMOVE_CLIENT should not specify an SC_EVENT_REG
subelement.
ATTRIBUTES:
VERSION
The CRNP protocol version of the message.
PORT
The callback port.
REG_TYPE
The type of registration. One of:
ADD_CLIENT, ADD_EVENTS, REMOVE_CLIENT, REMOVE_EVENTS
CONTENTS:
SUBELEMENTS: SC_EVENT_REG (0 or more)
—>
<!ELEMENT SC_CALLBACK_REG (SC_EVENT_REG*)>
<!ATTLIST SC_CALLBACK_REG
VERSION
NMTOKEN
PORT
NMTOKEN
REG_TYPE
(ADD_CLIENT|ADD_EVENTS|REMOVE_CLIENT|REMOVE_EVENTS)
#FIXED
#REQUIRED
#REQUIRED
>
<!— SC_EVENT_REG definition
The SC_EVENT_REG defines an event for which the client is either registering or
unregistering interest in receiving event notifications. The registration can be for any
level of granularity, from only event class down to specific name/value pairs that must be
present. Thus, the only required attribute is the CLASS. The SUBCLASS attribute, and the
NVPAIRS sub-elements are optional, for higher granularity.
Registrations that specify name/value pairs are registering interest in notification of
messages from the class/subclass specified with ALL name/value pairs present.
Unregistrations that specify name/value pairs are unregistering interest in notifications
that have EXACTLY those name/value pairs in granularity previously specified.
Unregistrations that do not specify name/value pairs unregister interest in ALL event
notifications of the specified class/subclass.
ATTRIBUTES:
302
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
CLASS:
SUBCLASS:
The event class for which this element is registering
or unregistering interest.
The subclass of the event (optional).
CONTENTS:
SUBELEMENTS: 0 or more NVPAIRs.
—>
<!ELEMENT SC_EVENT_REG (NVPAIR*)>
<!ATTLIST SC_EVENT_REG
CLASS
CDATA
SUBCLASS
CDATA
>
#REQUIRED
#IMPLIED
NVPAIR XML DTD
<!— NVPAIR XML format specification
Copyright 2001-2005 Sun Microsystems, Inc. All rights reserved.
Use is subject to license terms.
Intended Use:
An nvpair element is meant to be used in an SC_EVENT or SC_CALLBACK_REG
element.
—>
<!— NVPAIR definition
The NVPAIR is a name/value pair to represent arbitrary name/value combinations.
It is intended to be a direct, generic, translation of the Solaris nvpair_t
structure used by the sysevent framework. However, there is no type information
associated with the name or the value (they are both arbitrary text) in this xml
element.
The NVPAIR consists simply of one NAME element and one or more VALUE elements.
One VALUE element represents a scalar value, while multiple represent an array
VALUE.
ATTRIBUTES:
CONTENTS:
SUBELEMENTS: NAME(1), VALUE(1 or more)
—>
<!ELEMENT NVPAIR (NAME,VALUE+)>
<!— NAME definition
The NAME is simply an arbitrary length string.
ATTRIBUTES:
CONTENTS:
附录 F • CRNP 的文档类型定义
303
Arbitrary text data.
parsing inside.
Should be wrapped with <![CDATA[...]]> to prevent XML
—>
<!ELEMENT NAME (#PCDATA)>
<!— VALUE definition
The VALUE is simply an arbitrary length string.
ATTRIBUTES:
CONTENTS:
Arbitrary text data.
parsing inside.
Should be wrapped with <![CDATA[...]]> to prevent XML
—>
<!ELEMENT VALUE (#PCDATA)>
SC_REPLY XML DTD
<!— SC_REPLY XML format specification
Copyright 2001-2005 Sun Microsystems, Inc. All rights reserved.
Use is subject to license terms.
—>
<!— SC_REPLY definition
The root element of the XML document represents a reply to a message.
contains a status code and a status message.
ATTRIBUTES:
VERSION:
STATUS_CODE:
The reply
The CRNP protocol version of the message.
The return code for the message. One of the
following: OK, RETRY, LOW_RESOURCES, SYSTEM_ERROR, FAIL,
MALFORMED, INVALID_XML, VERSION_TOO_HIGH, or
VERSION_TOO_LOW.
CONTENTS:
SUBELEMENTS: SC_STATUS_MSG(1)
—>
<!ELEMENT SC_REPLY (SC_STATUS_MSG)>
<!ATTLIST SC_REPLY
VERSION
NMTOKEN
#FIXED
"1.0"
STATUS_CODE
OK|RETRY|LOW_RESOURCE|SYSTEM_ERROR|FAIL|MALFORMED|INVALID,\
VERSION_TOO_HIGH, VERSION_TOO_LOW) #REQUIRED
>
<!— SC_STATUS_MSG definition
The SC_STATUS_MSG is simply an arbitrary text string elaborating on the status
code. Should be wrapped with <![CDATA[...]]> to prevent XML parsing inside.
ATTRIBUTES:
304
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
CONTENTS:
Arbitrary string.
—>
<!ELEMENT SC_STATUS_MSG (#PCDATA)>
SC_EVENT XML DTD
注 – 由 SC_CALLBACK_REG 和 SC_EVENT 使用的 NVPAIR 数据结构仅被定义一次。
<!— SC_EVENT XML format specification
Copyright 2001-2005 Sun Microsystems, Inc. All rights reserved.
Use is subject to license terms.
The root element of the XML document is intended to be a direct, generic,
translation of the Solaris syseventd message format. It has attributes to
represent the class, subclass, vendor, and publisher, and contains any number of
NVPAIR elements.
ATTRIBUTES:
VERSION:
The
CLASS:
The
SUBCLASS:
The
VENDOR:
The
PUBLISHER:
The
CONTENTS:
SUBELEMENTS: NVPAIR
—>
<!ELEMENT SC_EVENT (NVPAIR*)>
<!ATTLIST SC_EVENT
VERSION
NMTOKEN
CLASS
CDATA
SUBCLASS
CDATA
VENDOR
CDATA
PUBLISHER
CDATA
>
CRNP protocol version of the message.
sysevent class of the event
subclass of the event
vendor associated with the event
publisher of the event
(0 or more)
#FIXED "1.0"
#REQUIRED
#REQUIRED
#REQUIRED
#REQUIRED
305
306
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
附录 G
CrnpClient.java 应用程序
本附录介绍了完整的 CrnpClient.java 应用程序,第 12 章中对该应用程序进行了详
细讨论。
CrnpClient.java 的内容
/*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
CrnpClient.java
================
Note regarding XML parsing:
This program uses the Sun Java Architecture for XML Processing (JAXP) API.
See http://java.sun.com/xml/jaxp/index.html for API documentation and
availability information.
This program was written for Java 1.3.1 or higher.
Program overview:
The main thread of the program creates a CrnpClient object, waits for the
user to terminate the demo, then calls shutdown on the CrnpClient object
and exits the program.
The CrnpClient constructor creates an EventReceptionThread object,
opens a connection to the CRNP server (using the host and port specified
on the command line), constructs a registration message (based on the
command-line specifications), sends the registartion message, and reads
and parses the reply.
The EventReceptionThread creates a listening socket bound to
the hostname of the machine on which this program runs, and the port
specified on the command line. It waits for an incoming event callback,
307
* at which point it constructs an XML Document from the incoming socket
* stream, which is then passed back to the CrnpClient object to process.
*
* The shutdown method in the CrnpClient just sends an unregistration
* (REMOVE_CLIENT) SC_CALLBACK_REG message to the crnp server.
*
* Note regarding error handling: for the sake of brevity, this program just
* exits on most errors. Obviously, a real application would attempt to handle
* some errors in various ways, such as retrying when appropriate.
*/
// JAXP packages
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
import org.w3c.dom.*;
// standard packages
import java.net.*;
import java.io.*;
import java.util.*;
/*
* class CrnpClient
* ----------------* See file header comments above.
*/
class CrnpClient
{
/*
* main
* ---* The entry point of the execution, main simply verifies the
* number of command-line arguments, and constructs an instance
* of a CrnpClient to do all the work.
*/
public static void main(String []args)
{
InetAddress regIp = null;
int regPort = 0, localPort = 0;
/* Verify the number of command-line arguments */
if (args.length < 4) {
System.out.println(
"Usage: java CrnpClient crnpHost crnpPort "
+ "localPort (-ac | -ae | -re) "
+ "[(M | A | RG=name | R=name) [...]]");
System.exit(1);
}
/*
308
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
* We expect the command line to contain the ip/port of the
* crnp server, the local port on which we should listen, and
* arguments specifying the type of registration.
*/
try {
regIp = InetAddress.getByName(args[0]);
regPort = (new Integer(args[1])).intValue();
localPort = (new Integer(args[2])).intValue();
} catch (UnknownHostException e) {
System.out.println(e);
System.exit(1);
}
// Create the CrnpClient
CrnpClient client = new CrnpClient(regIp, regPort, localPort,
args);
// Now wait until the user wants to end the program
System.out.println("Hit return to terminate demo...");
// read will block until the user enters something
try {
System.in.read();
} catch (IOException e) {
System.out.println(e.toString());
}
// shutdown the client
client.shutdown();
System.exit(0);
}
/*
* ======================
* public methods
* ======================
*/
/*
* CrnpClient constructor
* ----------------------* Parses the command line arguments so we know how to contact
* the crnp server, creates the event reception thread, and starts it
* running, creates the XML DocumentBuilderFactory obect, and, finally,
* registers for callbacks with the crnp server.
*/
public CrnpClient(InetAddress regIpIn, int regPortIn, int localPortIn,
String []clArgs)
{
try {
regIp = regIpIn;
regPort = regPortIn;
localPort = localPortIn;
regs = clArgs;
附录 G • CrnpClient.java 应用程序
309
/*
* Setup the document builder factory for
* xml processing.
*/
setupXmlProcessing();
/*
* Create the EventReceptionThread, which creates a
* ServerSocket and binds it to a local ip and port.
*/
createEvtRecepThr();
/*
* Register with the crnp server.
*/
registerCallbacks();
} catch (Exception e) {
System.out.println(e.toString());
System.exit(1);
}
}
/*
* processEvent
* --------------* Callback into the CrnpClient, used by the EventReceptionThread
* when it receives event callbacks.
*/
public void processEvent(Event event)
{
/*
* For demonstration purposes, simply print the event
* to System.out. A real application would obviously make
* use of the event in some way.
*/
event.print(System.out);
}
/*
* shutdown
* ------------* Unregister from the CRNP server.
*/
public void shutdown()
{
try {
/* send an unregistration message to the server */
unregister();
} catch (Exception e) {
System.out.println(e);
System.exit(1);
}
}
310
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
/*
* ======================
* private helper methods
* ======================
*/
/*
* setupXmlProcessing
* -------------------* Create the document builder factory for
* parsing the xml replies and events.
*/
private void setupXmlProcessing() throws Exception
{
dbf = DocumentBuilderFactory.newInstance();
// We don’t need to bother validating
dbf.setValidating(false);
dbf.setExpandEntityReferences(false);
// We want to ignore comments and whitespace
dbf.setIgnoringComments(true);
dbf.setIgnoringElementContentWhitespace(true);
// Coalesce CDATA sections into TEXT nodes.
dbf.setCoalescing(true);
}
/*
* createEvtRecepThr
* ------------------* Creates a new EventReceptionThread object, saves the ip
* and port to which its listening socket is bound, and
* starts the thread running.
*/
private void createEvtRecepThr() throws Exception
{
/* create the thread object */
evtThr = new EventReceptionThread(this);
/*
* Now start the thread running to begin listening
* for event delivery callbacks.
*/
evtThr.start();
}
/*
*
*
*
*
registerCallbacks
-----------------Creates a socket connection to the crnp server and sends
an event registration message.
附录 G • CrnpClient.java 应用程序
311
*/
private void registerCallbacks() throws Exception
{
System.out.println("About to register");
/*
* Create a socket connected to the registration ip/port
* of the crnp server and send the registration information.
*/
Socket sock = new Socket(regIp, regPort);
String xmlStr = createRegistrationString();
PrintStream ps = new PrintStream(sock.getOutputStream());
ps.print(xmlStr);
/*
* Read the reply
*/
readRegistrationReply(sock.getInputStream());
/*
* Close the socket connection.
*/
sock.close();
}
/*
* unregister
* ---------* As in registerCallbacks, we create a socket connection to
* the crnp server, send the unregistration message, wait for
* the reply from the server, then close the socket.
*/
private void unregister() throws Exception
{
System.out.println("About to unregister");
/*
* Create a socket connected to the registration ip/port
* of the crnp server and send the unregistration information.
*/
Socket sock = new Socket(regIp, regPort);
String xmlStr = createUnregistrationString();
PrintStream ps = new PrintStream(sock.getOutputStream());
ps.print(xmlStr);
/*
* Read the reply
*/
readRegistrationReply(sock.getInputStream());
/*
* Close the socket connection.
*/
sock.close();
}
312
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
/*
* createRegistrationString
* -----------------* Constructs a CallbackReg object based on the command line arguments
* to this program, then retrieves the XML string from the CallbackReg
* object.
*/
private String createRegistrationString() throws Exception
{
/*
* create the actual CallbackReg class and set the port.
*/
CallbackReg cbReg = new CallbackReg();
cbReg.setPort("" + localPort);
// set the registration type
if (regs[3].equals("-ac")) {
cbReg.setRegType(CallbackReg.ADD_CLIENT);
} else if (regs[3].equals("-ae")) {
cbReg.setRegType(CallbackReg.ADD_EVENTS);
} else if (regs[3].equals("-re")) {
cbReg.setRegType(CallbackReg.REMOVE_EVENTS);
} else {
System.out.println("Invalid reg type: " + regs[3]);
System.exit(1);
}
// add the events
for (int i = 4; i < regs.length; i++) {
if (regs[i].equals("M")) {
cbReg.addRegEvent(createMembershipEvent());
} else if (regs[i].equals("A")) {
cbReg.addRegEvent(createAllEvent());
} else if (regs[i].substring(0,2).equals("RG")) {
cbReg.addRegEvent(createRgEvent(regs[i].substring(3)));
} else if (regs[i].substring(0,1).equals("R")) {
cbReg.addRegEvent(createREvent(regs[i].substring(2)));
}
}
String xmlStr = cbReg.convertToXml();
System.out.println(xmlStr);
return (xmlStr);
}
/*
* createAllEvent
* ---------------* Creates an XML registartion event with class EC_Cluster, and no
* subclass.
*/
private Event createAllEvent()
{
Event allEvent = new Event();
附录 G • CrnpClient.java 应用程序
313
allEvent.setClass("EC_Cluster");
return (allEvent);
}
/*
* createMembershipEvent
* ---------------------* Creates an XML registration event with class EC_Cluster, subclass
* ESC_cluster_memberhip.
*/
private Event createMembershipEvent()
{
Event membershipEvent = new Event();
membershipEvent.setClass("EC_Cluster");
membershipEvent.setSubclass("ESC_cluster_membership");
return (membershipEvent);
}
/*
* createRgEvent
* ---------------* Creates an XML registration event with class EC_Cluster,
* subclass ESC_cluster_rg_state, and one "rg_name" nvpair (based
* on input parameter).
*/
private Event createRgEvent(String rgname)
{
/*
* Create a Resource Group state change event for the
* rgname Resource Group. Note that we supply
* a name/value pair (nvpair) for this event type, to
* specify in which Resource Group we are interested.
*/
/*
* Construct the event object and set the class and subclass.
*/
Event rgStateEvent = new Event();
rgStateEvent.setClass("EC_Cluster");
rgStateEvent.setSubclass("ESC_cluster_rg_state");
/*
* Create the nvpair object and add it to the Event.
*/
NVPair rgNvpair = new NVPair();
rgNvpair.setName("rg_name");
rgNvpair.setValue(rgname);
rgStateEvent.addNvpair(rgNvpair);
return (rgStateEvent);
}
/*
* createREvent
* ---------------* Creates an XML registration event with class EC_Cluster,
314
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
* subclass ESC_cluster_r_state, and one "r_name" nvpair (based
* on input parameter).
*/
private Event createREvent(String rname)
{
/*
* Create a Resource state change event for the
* rgname Resource. Note that we supply
* a name/value pair (nvpair) for this event type, to
* specify in which Resource Group we are interested.
*/
Event rStateEvent = new Event();
rStateEvent.setClass("EC_Cluster");
rStateEvent.setSubclass("ESC_cluster_r_state");
NVPair rNvpair = new NVPair();
rNvpair.setName("r_name");
rNvpair.setValue(rname);
rStateEvent.addNvpair(rNvpair);
return (rStateEvent);
}
/*
* createUnregistrationString
* -----------------* Constructs a REMOVE_CLIENT CallbackReg object, then retrieves
* the XML string from the CallbackReg object.
*/
private String createUnregistrationString() throws Exception
{
/*
* Crate the CallbackReg object.
*/
CallbackReg cbReg = new CallbackReg();
cbReg.setPort("" + localPort);
cbReg.setRegType(CallbackReg.REMOVE_CLIENT);
/*
* we marshall the registration to the OutputStream
*/
String xmlStr = cbReg.convertToXml();
// Print the string for debugging purposes
System.out.println(xmlStr);
return (xmlStr);
}
/*
*
*
*
*
*
readRegistrationReply
-----------------------Parse the xml into a Document, construct a RegReply object
from the document, and print the RegReply object. Note that
a real application would take action based on the status_code
附录 G • CrnpClient.java 应用程序
315
* of the RegReply object.
*/
private void readRegistrationReply(InputStream stream)
throws Exception
{
// Create the document builder
DocumentBuilder db = dbf.newDocumentBuilder();
//
// Set an ErrorHandler before parsing
// Use the default handler.
//
db.setErrorHandler(new DefaultHandler());
//parse the input file
Document doc = db.parse(stream);
RegReply reply = new RegReply(doc);
reply.print(System.out);
}
/* private member variables */
private InetAddress regIp;
private int regPort;
private EventReceptionThread evtThr;
private String regs[];
/* public member variables */
public int localPort;
public DocumentBuilderFactory dbf;
}
/*
* class EventReceptionThread
* ---------------------------* See file header comments above.
*/
class EventReceptionThread extends Thread
{
/*
* EventReceptionThread constructor
* ---------------------------------* Creates a new ServerSocket, bound to the local hostname and
* a wildcard port.
*/
public EventReceptionThread(CrnpClient clientIn) throws IOException
{
/*
* keep a reference to the client so we can call it back
* when we get an event.
*/
client = clientIn;
/*
* Specify the IP to which we should bind.
316
It’s
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
* simply the local host ip. If there is more
* than one public interface configured on this
* machine, we’ll go with whichever one
* InetAddress.getLocalHost comes up with.
*
*/
listeningSock = new ServerSocket(client.localPort, 50,
InetAddress.getLocalHost());
System.out.println(listeningSock);
}
/*
* run
* --* Called by the Thread.Start method.
*
* Loops forever, waiting for incoming connections on the ServerSocket.
*
* As each incoming connection is accepted, an Event object
* is created from the xml stream, which is then passed back to
* the CrnpClient object for processing.
*/
public void run()
{
/*
* Loop forever.
*/
try {
//
// Create the document builder using the document
// builder factory in the CrnpClient.
//
DocumentBuilder db = client.dbf.newDocumentBuilder();
//
// Set an ErrorHandler before parsing
// Use the default handler.
//
db.setErrorHandler(new DefaultHandler());
while(true) {
/* wait for a callback from the server */
Socket sock = listeningSock.accept();
// parse the input file
Document doc = db.parse(sock.getInputStream());
Event event = new Event(doc);
client.processEvent(event);
/* close the socket */
sock.close();
}
// UNREACHABLE
附录 G • CrnpClient.java 应用程序
317
} catch (Exception e) {
System.out.println(e);
System.exit(1);
}
}
/* private member variables */
private ServerSocket listeningSock;
private CrnpClient client;
}
/*
* class NVPair
* ----------* This class stores a name/value pair (both Strings). It knows how to
* construct an NVPAIR XML message from its members, and how to parse
* an NVPAIR XML Element into its members.
*
* Note that the formal specification of an NVPAIR allows for multiple values.
* We make the simplifying assumption of only one value.
*/
class NVPair
{
/*
* Two constructors: the first creates an empty NVPair, the second
* creates an NVPair from an NVPAIR XML Element.
*/
public NVPair()
{
name = value = null;
}
public NVPair(Element elem)
{
retrieveValues(elem);
}
/*
* Public setters.
*/
public void setName(String nameIn)
{
name = nameIn;
}
public void setValue(String valueIn)
{
value = valueIn;
}
/*
* Prints the name and value on a single line.
*/
public void print(PrintStream out)
{
318
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
out.println("NAME=" + name + " VALUE=" + value);
}
/*
* createXmlElement
* -----------------* Constructs an NVPAIR XML Element from the member variables.
* Takes the Document as a parameter so that it can create the
* Element.
*/
public Element createXmlElement(Document doc)
{
// Create the element.
Element nvpair = (Element)
doc.createElement("NVPAIR");
//
// Add the name. Note that the actual name is
// a separate CDATA section.
//
Element eName = doc.createElement("NAME");
Node nameData = doc.createCDATASection(name);
eName.appendChild(nameData);
nvpair.appendChild(eName);
//
// Add the value. Note that the actual value is
// a separate CDATA section.
//
Element eValue = doc.createElement("VALUE");
Node valueData = doc.createCDATASection(value);
eValue.appendChild(valueData);
nvpair.appendChild(eValue);
return (nvpair);
}
/*
* retrieveValues
* ---------------* Parse the XML Element to retrieve the name and value.
*/
private void retrieveValues(Element elem)
{
Node n;
NodeList nl;
//
// Find the NAME element
//
nl = elem.getElementsByTagName("NAME");
if (nl.getLength() != 1) {
System.out.println("Error in parsing: can’t find "
+ "NAME node.");
return;
}
附录 G • CrnpClient.java 应用程序
319
//
// Get the TEXT section
//
n = nl.item(0).getFirstChild();
if (n == null || n.getNodeType() != Node.TEXT_NODE) {
System.out.println("Error in parsing: can’t find "
+ "TEXT section.");
return;
}
// Retrieve the value
name = n.getNodeValue();
//
// Now get the value element
//
nl = elem.getElementsByTagName("VALUE");
if (nl.getLength() != 1) {
System.out.println("Error in parsing: can’t find "
+ "VALUE node.");
return;
}
//
// Get the TEXT section
//
n = nl.item(0).getFirstChild();
if (n == null || n.getNodeType() != Node.TEXT_NODE) {
System.out.println("Error in parsing: can’t find "
+ "TEXT section.");
return;
}
// Retrieve the value
value = n.getNodeValue();
}
/*
* Public accessors
*/
public String getName()
{
return (name);
}
public String getValue()
{
return (value);
}
// Private member vars
private String name, value;
}
320
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
/*
* class Event
* ----------* This class stores an event, which consists of a class, subclass, vendor,
* publisher, and list of name/value pairs. It knows how to
* construct an SC_EVENT_REG XML Element from its members, and how to parse
* an SC_EVENT XML Element into its members. Note that there is an assymetry
* here: we parse SC_EVENT elements, but construct SC_EVENT_REG elements.
* That is because SC_EVENT_REG elements are used in registration messages
* (which we must construct), while SC_EVENT elements are used in event
* deliveries (which we must parse). The only difference is that SC_EVENT_REG
* elements don’t have a vendor or publisher.
*/
class Event
{
/*
* Two constructors: the first creates an empty Event; the second
* creates an Event from an SC_EVENT XML Document.
*/
public Event()
{
regClass = regSubclass = null;
nvpairs = new Vector();
}
public Event(Document doc)
{
nvpairs = new Vector();
//
// Convert the document to a string to print for debugging
// purposes.
//
DOMSource domSource = new DOMSource(doc);
StringWriter strWrite = new StringWriter();
StreamResult streamResult = new StreamResult(strWrite);
TransformerFactory tf = TransformerFactory.newInstance();
try {
Transformer transformer = tf.newTransformer();
transformer.transform(domSource, streamResult);
} catch (TransformerException e) {
System.out.println(e.toString());
return;
}
System.out.println(strWrite.toString());
// Do the actual parsing.
retrieveValues(doc);
}
/*
* Public setters.
附录 G • CrnpClient.java 应用程序
321
*/
public void setClass(String classIn)
{
regClass = classIn;
}
public void setSubclass(String subclassIn)
{
regSubclass = subclassIn;
}
public void addNvpair(NVPair nvpair)
{
nvpairs.add(nvpair);
}
/*
* createXmlElement
* -----------------* Constructs an SC_EVENT_REG XML Element from the member variables.
* Takes the Document as a parameter so that it can create the
* Element. Relies on the NVPair createXmlElement ability.
*/
public Element createXmlElement(Document doc)
{
Element event = (Element)
doc.createElement("SC_EVENT_REG");
event.setAttribute("CLASS", regClass);
if (regSubclass != null) {
event.setAttribute("SUBCLASS", regSubclass);
}
for (int i = 0; i < nvpairs.size(); i++) {
NVPair tempNv = (NVPair)
(nvpairs.elementAt(i));
event.appendChild(tempNv.createXmlElement(doc));
}
return (event);
}
/*
* Prints the member vars on multiple lines.
*/
public void print(PrintStream out)
{
out.println("\tCLASS=" + regClass);
out.println("\tSUBCLASS=" + regSubclass);
out.println("\tVENDOR=" + vendor);
out.println("\tPUBLISHER=" + publisher);
for (int i = 0; i < nvpairs.size(); i++) {
NVPair tempNv = (NVPair)
(nvpairs.elementAt(i));
out.print("\t\t");
tempNv.print(out);
}
}
322
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
/*
* retrieveValues
* ---------------* Parse the XML Document to retrieve the class, subclass, vendor,
* publisher, and nvpairs.
*/
private void retrieveValues(Document doc)
{
Node n;
NodeList nl;
//
// Find the SC_EVENT element.
//
nl = doc.getElementsByTagName("SC_EVENT");
if (nl.getLength() != 1) {
System.out.println("Error in parsing: can’t find "
+ "SC_EVENT node.");
return;
}
n = nl.item(0);
//
// Retrieve the values of the CLASS, SUBCLASS,
// VENDOR and PUBLISHER attributes.
//
regClass = ((Element)n).getAttribute("CLASS");
regSubclass = ((Element)n).getAttribute("SUBCLASS");
publisher = ((Element)n).getAttribute("PUBLISHER");
vendor = ((Element)n).getAttribute("VENDOR");
//
// Retrieve all the nv pairs
//
for (Node child = n.getFirstChild(); child != null;
child = child.getNextSibling())
{
nvpairs.add(new NVPair((Element)child));
}
}
/*
* Public accessor methods.
*/
public String getRegClass()
{
return (regClass);
}
public String getSubclass()
{
return (regSubclass);
}
附录 G • CrnpClient.java 应用程序
323
public String getVendor()
{
return (vendor);
}
public String getPublisher()
{
return (publisher);
}
public Vector getNvpairs()
{
return (nvpairs);
}
// Private member vars.
private String regClass, regSubclass;
private Vector nvpairs;
private String vendor, publisher;
}
/*
* class CallbackReg
* ----------* This class stores a port and regType (both Strings), and a list of Events.
* It knows how to construct an SC_CALLBACK_REG XML message from its members.
*
* Note that this class does not need to be able to parse SC_CALLBACK_REG
* messages, because only the CRNP server must parse SC_CALLBACK_REG
* messages.
*/
class CallbackReg
{
// Useful defines for the setRegType method
public static final int ADD_CLIENT = 0;
public static final int ADD_EVENTS = 1;
public static final int REMOVE_EVENTS = 2;
public static final int REMOVE_CLIENT = 3;
public CallbackReg()
{
port = null;
regType = null;
regEvents = new Vector();
}
/*
* Public setters.
*/
public void setPort(String portIn)
{
port = portIn;
}
324
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
public void setRegType(int regTypeIn)
{
switch (regTypeIn) {
case ADD_CLIENT:
regType = "ADD_CLIENT";
break;
case ADD_EVENTS:
regType = "ADD_EVENTS";
break;
case REMOVE_CLIENT:
regType = "REMOVE_CLIENT";
break;
case REMOVE_EVENTS:
regType = "REMOVE_EVENTS";
break;
default:
System.out.println("Error, invalid regType " +
regTypeIn);
regType = "ADD_CLIENT";
break;
}
}
public void addRegEvent(Event regEvent)
{
regEvents.add(regEvent);
}
/*
* convertToXml
* -----------------* Constructs an SC_CALLBACK_REG XML Document from the member
* variables. Relies on the Event createXmlElement ability.
*/
public String convertToXml()
{
Document document = null;
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
try {
DocumentBuilder builder = factory.newDocumentBuilder();
document = builder.newDocument();
} catch (ParserConfigurationException pce) {
// Parser with specified options can’t be built
pce.printStackTrace();
System.exit(1);
}
Element root = (Element) document.createElement("SC_CALLBACK_REG");
root.setAttribute("VERSION", "1.0");
root.setAttribute("PORT", port);
root.setAttribute("REG_TYPE", regType);
for (int i = 0; i < regEvents.size(); i++) {
Event tempEvent = (Event)
附录 G • CrnpClient.java 应用程序
325
(regEvents.elementAt(i));
root.appendChild(tempEvent.createXmlElement(document));
}
document.appendChild(root);
//
// Now convert the document to a string.
//
DOMSource domSource = new DOMSource(document);
StringWriter strWrite = new StringWriter();
StreamResult streamResult = new StreamResult(strWrite);
TransformerFactory tf = TransformerFactory.newInstance();
try {
Transformer transformer = tf.newTransformer();
transformer.transform(domSource, streamResult);
} catch (TransformerException e) {
System.out.println(e.toString());
return ("");
}
return (strWrite.toString());
}
// private member vars
private String port;
private String regType;
private Vector regEvents;
}
/*
* class RegReply
* ----------* This class stores a status_code and status_msg (both Strings).
* It knows how to parse an SC_REPLY XML Element into its members.
*/
class RegReply
{
/*
* The only constructor takes an XML Document and parses it.
*/
public RegReply(Document doc)
{
//
// Now convert the document to a string.
//
DOMSource domSource = new DOMSource(doc);
StringWriter strWrite = new StringWriter();
StreamResult streamResult = new StreamResult(strWrite);
TransformerFactory tf = TransformerFactory.newInstance();
try {
Transformer transformer = tf.newTransformer();
transformer.transform(domSource, streamResult);
} catch (TransformerException e) {
System.out.println(e.toString());
return;
326
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
}
System.out.println(strWrite.toString());
retrieveValues(doc);
}
/*
* Public accessors
*/
public String getStatusCode()
{
return (statusCode);
}
public String getStatusMsg()
{
return (statusMsg);
}
/*
* Prints the info on a single line.
*/
public void print(PrintStream out)
{
out.println(statusCode + ": " +
(statusMsg != null ? statusMsg : ""));
}
/*
* retrieveValues
* ---------------* Parse the XML Document to retrieve the statusCode and statusMsg.
*/
private void retrieveValues(Document doc)
{
Node n;
NodeList nl;
//
// Find the SC_REPLY element.
//
nl = doc.getElementsByTagName("SC_REPLY");
if (nl.getLength() != 1) {
System.out.println("Error in parsing: can’t find "
+ "SC_REPLY node.");
return;
}
n = nl.item(0);
// Retrieve the value of the STATUS_CODE attribute
statusCode = ((Element)n).getAttribute("STATUS_CODE");
//
// Find the SC_STATUS_MSG element
附录 G • CrnpClient.java 应用程序
327
//
nl = ((Element)n).getElementsByTagName("SC_STATUS_MSG");
if (nl.getLength() != 1) {
System.out.println("Error in parsing: can’t find "
+ "SC_STATUS_MSG node.");
return;
}
//
// Get the TEXT section, if there is one.
//
n = nl.item(0).getFirstChild();
if (n == null || n.getNodeType() != Node.TEXT_NODE) {
// Not an error if there isn’t one, so we
// just silently return.
return;
}
// Retrieve the value
statusMsg = n.getNodeValue();
}
// private member vars
private String statusCode;
private String statusMsg;
}
328
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
索引
数字和符号
#$upgrade_from 指令, 62, 64
ANYTIME, 63
AT_CREATION, 63
WHEN_DISABLED, 63
WHEN_OFFLINE, 63
WHEN_UNMANAGED, 63
WHEN_UNMONITORED, 63
可调性值, 63
#$upgrade 指令, 62, 294
“创建”屏幕, Agent Builder, 142
“配置”屏幕, Agent Builder, 144
A
Affinity_timeout, 资源属性, 220
Agent Builder
“创建”屏幕, 142
“配置”屏幕, 144
Cluster Agent 模块, 155
区别, 159
rtconfig 文件, 154
安装, 137
编辑已生成的源代码, 150
二进制文件, 152
分析应用程序, 137
脚本, 153
克隆现有资源类型, 149
浏览, 139
“编辑”菜单, 142
“文件” 菜单, 141
菜单, 141
Agent Builder, 浏览 (续)
浏览, 140
描述, 24
命令行版本, 150
目录结构, 151
配置, 137
启动, 167
软件包目录, 154
使用某个命令行版本创建使用 GDS 的服
务, 174
使用以创建 GDS, 162
手册页, 153
输出, 172
说明, 20
用于创建使用 GDS 的服务, 167
源文件, 152
支持文件, 154
重复使用代码, 149
ANYTIME, #$upgrade_from 指令, 63
API, 资源管理, 请参见RMAPI
API_version, 资源类型属性, 214
Array_maxsize, 资源属性, 240
Array_minsize, 资源属性, 240
arraymax, 资源类型升级, 61
arraymin, 资源类型升级, 61
AT_CREATION, #$upgrade_from 指令, 63
Auto_start_on_new_cluster, 资源组属
性, 233
B
Boot, 资源类型属性, 214
329
Boot_timeout, 资源属性, 220
Boot 方法, 使用, 42, 57
C
C 程序函数, RMAPI, 53
Cheap_probe_interval, 资源属性, 220
Cluster Agent 模块
Agent Builder 区别, 159
安装, 155
启动, 156
设置, 155
使用, 158
说明, 155
CRNP(群集重新配置通知协议)
SC_CALLBACK_REG 消息, 189
SC_EVENT, 192, 193
SC_REPLY, 190, 191
错误状态, 192
的函数, 186
服务器, 189
服务器回复, 190
服务器事件传送, 192
概念, 185
客户机, 189
客户机标识进程, 189
客户机和服务器注册, 189
示例 Java 应用程序, 195
说明, 186
通信, 187
消息类型, 188
协议的语义学, 186
验证, 194
D
Default, 资源属性, 240
Description, 资源属性, 240
Desired_primaries, 资源组属性, 233
DSDL 代码样例
scds_initialize() 函数, 117
SUNW.xfnts RTR 文件, 116
SUNW.xfnts 故障监视器, 125
svc_probe() 函数, 127
TCP 端口号, 116
X Font Server, 115
330
DSDL 代码样例 (续)
X Font Server 配置文件, 116
xfnts_monitor_check 方法, 125
xfnts_monitor_start 方法, 123
xfnts_monitor_stop 方法, 124
xfnts_probe 主循环, 126
xfnts_start 方法, 118
xfnts_stop 方法, 122
xfnts_update 方法, 133
xfnts_validate 方法, 130
从 svc_start() 返回, 120
启动服务, 118
确定故障监视器操作, 130
验证服务, 118
DSDL(数据服务开发库)
libdsdev.so, 19
调试资源类型, 104
访问网络地址, 103
概述, 19
故障监视, 182
故障监视器函数, 183
进程监视器工具 (PMF) 函数, 182
启动数据服务, 102
启用 HA 本地文件系统, 104
实现故障监视器, 103
实现位置, 19
实用程序函数, 183
属性函数, 180
说明, 101
停止数据服务, 102
通用函数, 179
网络资源访问函数, 181
资源类型实现样例
scds_initialize() 函数, 117
SUNW.xfnts RTR 文件, 116
SUNW.xfnts 故障监视器, 125
svc_probe() 函数, 127
TCP 端口号, 116
X Font Server, 115
X Font Server 配置文件, 116
xfnts_monitor_check 方法, 125
xfnts_monitor_start 方法, 123
xfnts_monitor_stop 方法, 124
xfnts_probe 主循环, 126
xfnts_start 方法, 118
xfnts_stop 方法, 122
xfnts_update 方法, 133
xfnts_validate 方法, 130
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
GDS(普通数据服务) (续)
使用方法, 162
使用命令创建服务,该服务使用, 173
使用原因, 162
说明, 161
与 Sun Cluster 管理命令一起使用, 163
与 SunPlex Agent Builder 一起使用, 162
Global_resources_used, 资源组属性, 234
E
Enumlist, 资源属性, 240
Extension, 资源属性, 240
H
HA 数据服务, 测试, 48
halockrun, 说明, 44
hatimerun, 说明, 44
F
Failback, 资源组属性, 234
Failover, 资源类型属性, 214
Failover_mode, 资源属性, 221
Fini, 资源类型属性, 215
Fini_timeout, 资源属性, 223
Fini 方法, 使用, 42, 57
G
GDS(普通数据服务)
Child_mon_level 属性, 166
Failover_enabled 属性, 166
Log_level 属性, 166
Network_resources_used 属性, 164
Port_list 属性, 164
Probe_command 属性, 165
Probe_timeout 属性, 165
Start_command 扩展属性, 164
Start_timeout 属性, 165
Stop_command 属性, 164
Stop_signal 属性, 166
Stop_timeout 属性, 165
SUNW.gds 资源类型, 162
必需的属性, 163
定义, 40
何时使用, 162
使用 Agent Builder 的命令行版本创建服
务, 174
使用 SunPlex Agent Builder 创建服务,该服
务使用, 167
I
Implicit_network_dependencies, 资源组
属性, 234
Init, 资源类型属性, 215
Init_nodes, 资源类型属性, 215
Init_timeout, 资源属性, 223
Init 方法, 使用, 57
Init方法, 使用, 42
Installed_nodes, 资源类型属性, 216
Is_logical_hostname, 资源类型属性, 216
Is_shared_address, 资源类型属性, 216
J
Java, 使用 CRNP 的样例应用程序, 195
L
libdsdev.so, DSDL, 19
libscha.so, RMAPI, 19
Load_balancing_policy, 资源属性, 224
Load_balancing_weights, 资源属性, 224
M
max, 资源类型升级, 61
Max, 资源属性, 240
331
Maximum_primaries, 资源组属性, 234
Maxlength, 资源属性, 240
min, 资源类型升级, 61
Min, 资源属性, 241
Minlength, 资源属性, 241
Monitor_check, 资源类型属性, 216
Monitor_check_timeout, 资源属性, 224
Monitor_check 方法
兼容, 63
使用, 59
Monitor_start, 资源类型属性, 216
Monitor_start_timeout, 资源属性, 224
Monitor_start 方法, 使用, 59
Monitor_stop, 资源类型属性, 216
Monitor_stop_timeout, 资源属性, 225
Monitor_stop 方法, 使用, 59
Monitored_switch, 资源属性, 225
N
Network_resources_used, 资源属性, 225
Nodelist, 资源组属性, 234
Num_resource_restarts, 资源属性, 225
Num_rg_restarts, 资源属性, 226
O
On_off_switch, 资源属性, 226
P
Pathprefix, 资源组属性, 234
Pingpong_interval, 资源组属性, 235
Pkglist, 资源类型属性, 217
PMF(进程监视工具), 用途, 44
PMF(进程监视器工具)
概述, 19
函数, DSDL, 182
Port_list, 资源属性, 226
Postnet_start 方法, 使用, 58
Postnet_stop
兼容, 63
资源类型属性, 217
Postnet_stop_timeout, 资源属性, 226
Prenet_start, 资源类型属性, 217
332
Prenet_start_timeout, 资源属性, 227
Prenet_start 方法, 使用, 58
Property, 资源属性, 241
R
R_description, 资源属性, 227
Resource_dependencies, 资源属性, 227
Resource_dependencies_restart, 资源属
性, 227
Resource_dependencies_weak, 资源属
性, 228
Resource_list
资源类型属性, 217
资源组属性, 235
Resource_name, 资源属性, 228
Resource_project_name, 资源属性, 228
Resource_state, 资源属性, 229
resource-type, 升级, 62
Resource_type, 资源类型属性, 217
Retry_count, 资源属性, 229
Retry_interval, 资源属性, 230
RG_affinities, 资源组属性, 235
RG_dependencies, 资源组属性, 236
RG_description, 资源组属性, 236
RG_is_frozen, 资源组属性, 236
RG_mode, 资源组属性, 237
RG_name, 资源组属性, 237
RG_project_name, 资源组属性, 237
RG_state, 资源组属性, 237
RG_system, 资源组属性, 239
RGM(资源组管理器), 293
管理接口, 25
说明, 22
用途, 20
值, 295
资源的处理, 20
资源类型的处理, 20
资源组的处理, 20
RMAPI(资源管理 API), 19
C 程序函数, 53
libscha.so, 19
shell 命令, 51
方法参数, 56
回调方法, 55
群集函数, 54
群集命令, 52
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
RMAPI(资源管理 API) (续)
实现位置, 19
实用程序函数, 55
退出代码, 56
资源函数, 53
资源类型函数, 53
资源类型命令, 52
资源命令, 52
资源组函数, 54
资源组命令, 52
组件, 24
RT_basedir, 资源类型属性, 218
RT_description, 资源类型属性, 218
RT_system, 资源类型属性, 218
RT_version
更改时间, 64
rt-version, 升级, 62
RT_version
用途, 64
资源类型属性, 218
rtconfig 文件, 154
RTR(资源类型注册)
说明, 23
文件
SUNW.xfnts, 116
更改, 66
升级, 62
说明, 105
S
SC_CALLBACK_REG, 内容, 190
SC_EVENT, 内容, 193
SC_REPLY, 内容, 191
Scalable, 资源属性, 230
scds_initialize() 函数, 117
scsetup, 说明, 25
shell 命令, RMAPI, 51
Single_instance, 资源类型属性, 219
Start, 资源类型属性, 219
Start_timeout, 资源属性, 230
Start 方法, 使用, 57
Start方法, 使用, 41
Status, 资源属性, 230
Status_msg, 资源属性, 231
Stop, 资源类型属性, 219
Stop_timeout, 资源属性, 231
Stop 方法
兼容, 63
使用, 41, 57
Sun Cluster
命令, 26
应用程序环境, 19
与 GDS 一起使用, 162
SunPlex Agent Builder, 请参见Agent Builder
SunPlex Manager, 说明, 25
SUNW.xfnts
RTR 文件, 116
故障监视器, 125
svc_probe() 函数, 127
T
TCP 连接, 使用 DSDL 故障监视, 182
Thorough_probe_interval, 资源属性, 231
Tunable, 资源属性, 241
Type, 资源属性, 231
Type_version, 资源属性, 231
U
UDP_affinity, 资源属性, 232
Update, 资源类型属性, 219
Update_timeout, 资源属性, 232
Update 方法
兼容, 63
使用, 44, 58
V
Validate, 资源类型属性, 219
Validate_timeout, 资源属性, 232
Validate 方法
使用, 44, 58
vendor-id
区别, 62
升级, 62
Vendor_ID, 资源类型属性, 219
W
Weak_affinity, 资源属性, 232
333
WHEN_DISABLED, #$upgrade_from 指令, 63
WHEN_OFFLINE, #$upgrade_from 指令, 63
WHEN_UNMANAGED, #$upgrade_from 指令, 63
WHEN_UNMONITORED, #$upgrade_from 指
令, 63
菜
X
参
X Font Server
定义, 115
配置文件, 116
xfnts_monitor_check, 125
xfnts_monitor_start, 123
xfnts_monitor_stop, 124
xfnts_start, 118
xfnts_stop, 122
xfnts_update, 133
xfnts_validate, 130
xfs 服务器, 端口号, 116
参数, RMAPI 方法, 56
菜单
Agent Builder, 141
Agent Builder“编辑”, 142
Agent Builder“文件”, 141
安
安装 Agent Builder, 137
安装要求, 资源类型软件包, 65
错
错误状态, CRNP, 192
334
多
多个注册的版本间的区别, rt-version, 62
二
二进制文件, Agent Builder, 152
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
方
方法
Boot, 42, 57, 111
Fini, 42, 57, 111
Init, 42, 57, 111
Monitor_check, 59, 110
Monitor_check 回调, 59
Monitor_start, 59, 109
Monitor_start 回调, 59
Monitor_stop, 59, 110
Monitor_stop 回调, 59
Postnet_start, 58
Postnet_start 回调, 58
Prenet_start, 58
Prenet_start 回调, 58
Start, 41, 57, 107
Stop, 41, 57, 108
Update, 44, 58, 110
Update 回调, 58
Validate, 44, 58, 106
Validate 回调, 58
xfnts_monitor_check, 125
xfnts_monitor_start, 123
xfnts_monitor_stop, 124
xfnts_start, 118
xfnts_stop, 122
xfnts_update, 133
xfnts_validate, 130
回调, 44
初始化, 57
控制, 57
幂等性, 39
方法参数, RMAPI, 56
方法代码, 更改, 66
服
服务器
CRNP, 189
X Font
定义, 115
配置文件, 116
供
供应商间的区别, vendor-id, 62
故
故障监视器
SUNW.xfnts, 125
函数, DSDL, 183
守护进程
设计, 111
故障转移资源, 实现, 45
335
函
检
函数
DSDL 故障监视器, 183
DSDL 进程监视器工具 (PMF), 182
DSDL 实用程序, 183
DSDL 属性, 180
DSDL 网络资源访问, 181
RMAPI C 程序, 53
RMAPI 群集, 54
RMAPI 实用程序, 55
RMAPI 资源, 53
RMAPI 资源类型, 53
RMAPI 资源组, 54
scds_initialize(), 117
svc_probe(), 127
命名约定, 117
通用 DSDL, 179
脚
脚本
Agent Builder, 153
创建, 167
配置, 170
回
回调方法
Monitor_check, 59
Monitor_start, 59
Monitor_stop, 59
Postnet_start, 58
Prenet_start, 58
RMAPI, 55
Update, 58
Validate, 58
初始化, 57
概述, 19
控制, 57
命名约定, 117
使用, 44
说明, 23
可
可调性选项, 63
ANYTIME, 63
AT_CREATION, 63
WHEN_DISABLED, 63
WHEN_OFFLINE, 63
WHEN_UNMANAGED, 63
WHEN_UNMONITORED, 63
可调性约束, 文档信息要求, 68
可伸缩服务, 验证, 47
可伸缩资源, 实现, 46
克
克隆现有资源类型, Agent Builder, 149
336
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
扩
默
默认属性值
Sun Cluster 3.0, 65
继承, 65
用于升级的新值, 65
目
目录, Agent Builder, 154
目录结构, Agent Builder, 151
浏
浏览, Agent Builder, 140
浏览 Agent Builder, 139
配
配置, Agent Builder, 137
屏
幂
命
启
命令
halockrun, 44
hatimerun, 44
RMAPI 资源类型, 52
scsetup, 25
Sun Cluster, 26
使用以创建 GDS, 163
用于创建使用 GDS 的服务, 173
命令行
Agent Builder, 150
命令, 26
命名约定
函数, 117
回调方法, 117
启动, Agent Builder, 138
337
日
守
软
手
软件包目录, Agent Builder, 154
手册页, Agent Builder, 153
升
属
属性
Child_mon_level, 166
Failover_enabled, 166
GDS, 必需, 166
Log_level, 166
Network_resources_used, 164
Port_list, 164
Probe_command, 165
Probe_timeout, 165
Start_command 扩展, 164
Start_timeout, 165
Stop_command, 164
Stop_signal, 166
Stop_timeout, 165
更改资源, 44
设置资源, 31, 44
设置资源类型, 31
声明扩展, 37
声明资源, 34
声明资源类型, 32
资源, 220, 240
资源类型, 213
资源属性, 240
资源组, 233
属性变量, 147
Agent Builder 替换类型的方式, 148
列表, 147
语法, 148
资源类型列表, 148
资源列表, 147
资源组列表, 148
属性函数, DSDL, 19
属性名称, 规则, 293
属性值
规则, 295
默认值, 65
使
使用 Agent Builder, 136
使用 DSDL 调试资源类型, 104
使用 DSDL 启动数据服务, 102
使用 DSDL 启用 HA 本地文件系统, 104
使用 DSDL 停止数据服务, 102
338
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
数
退
数据服务
编写, 48
测试, 48
测试 HA, 48
创建
分析适用性, 27
确定接口, 29
设置开发环境, 30
样例, 71
Monitor_check 方法, 93
Monitor_start 方法, 91
Monitor_stop 方法, 92
RTR 文件, 72
RTR 文件中的扩展属性, 76
RTR 文件中的资源属性, 74
Start 方法, 81
Stop 方法, 84
Update 方法, 98
Validate 方法, 94
处理属性更新, 94
定义故障监视器, 86
获取属性信息, 80
控制数据服务, 81
生成错误消息, 80
探测程序, 86
通用功能, 77
传送到群集以进行测试, 31
数据服务开发库, 请参见DSDL
数据服务样例
Monitor_check 方法, 93
Monitor_start 方法, 91
Monitor_stop 方法, 92
RTR 文件, 72
RTR 文件中的扩展属性, 76
RTR 文件中的样例属性, 74
Start 方法, 81
Stop 方法, 84
Update 方法, 98
Validate 方法, 94
处理属性更新, 94
定义故障监视器, 86
获取属性信息, 80
控制数据服务, 81
生成错误消息, 80
探测程序, 86
通用功能, 77
退出代码, RMAPI, 56
文
文档信息要求
可调性约束, 68
升级, 68-69
文件
Agent Builder 中的二进制, 152
Agent Builder 中的源文件, 152
Agent Builder 中的支持, 154
rtconfig, 154
消
消息
SC_CALLBACK_REG CRNP, 189, 190
SC_EVENT CRNP, 192, 193
SC_REPLY CRNP, 190, 191
消息日志, 添加到资源, 44
应
应用程序环境, Sun Cluster, 19
重
重复使用代码, Agent Builder, 149
源
源代码, 编辑生成的 Agent Builder, 149
源文件, Agent Builder, 152
注
约
资
支
支持升级, 已定义, 62
支持文件, Agent Builder, 154
指
指令
#$upgrade, 62, 294
#$upgrade_from, 63, 64
RT_version, 63
340
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A
资源类型名称
Sun Cluster 3.0, 64
版本后缀, 62
规则, 294
获取全限定, 62
实现, 65
无版本后缀, 64
限制, 64, 143
资源类型软件包, 安装要求, 65
资源类型属性, 213
API_version, 214
Boot, 214
Failover, 214
Fini, 215
Init, 215
Init_nodes, 215
Installed_nodes, 216
Is_logical_hostname, 216
Is_shared_address, 216
Monitor_check, 216
Monitor_start, 216
Monitor_stop, 216
Pkglist, 217
Postnet_stop, 217
Prenet_start, 217
Resource_list, 217
Resource_type, 217
RT_basedir, 218
RT_description, 218
RT_system, 218
RT_version, 218
Single_instance, 219
Start, 219
Stop, 219
Update, 219
Validate, 219
Vendor_ID, 219
设置, 31
声明, 32
资源类型注册, 请参见RTR
资源名称, 规则, 293
资源命令, RMAPI, 52
资源属性, 220, 240
Affinity_timeout, 220
Array_maxsize, 240
Array_minsize, 240
Boot_timeout, 220
Cheap_probe_interval, 220
资源属性 (续)
Default, 240
Description, 240
Enumlist, 240
Extension, 240
Failover_mode, 221
Fini_timeout, 223
Init_timeout, 223
Load_balancing_policy, 224
Load_balancing_weights, 224
Max, 240
Maxlength, 240
Min, 241
Minlength, 241
Monitor_check_timeout, 224
Monitor_start_timeout, 224
Monitor_stop_timeout, 225
Monitored_switch, 225
Network_resources_used, 225
Num_resource_restarts, 225
Num_rg_restarts, 226
On_off_switch, 226
Port_list, 226
Postnet_stop_timeout, 226
Prenet_start_timeout, 227
Property, 241
R_description, 227
Resource_dependencies, 227
Resource_dependencies_restart, 227
Resource_dependencies_weak, 228
Resource_name, 228
Resource_project_name, 228
Resource_state, 229
Retry_count, 229
Retry_interval, 230
Scalable, 230
Start_timeout, 230
Status, 230
Status_msg, 231
Stop_timeout, 231
Thorough_probe_interval, 231
Tunable, 241
Type, 231
Type_version, 231
UDP_affinity, 232
Update_timeout, 232
Validate_timeout, 232
Weak_affinity, 232
341
资源属性 (续)
访问有关信息, 39
更改, 44
扩展, 221
类型, 241
设置, 31, 44
声明, 34
资源依赖性, 协调, 49
资源组
故障转移, 22
可伸缩, 22
描述, 22
属性, 22
资源组管理器, 请参见RGM
资源组函数, RMAPI, 54
资源组名称, 规则, 293
资源组命令, RMAPI, 52
资源组属性, 233
Auto_start_on_new_cluster, 233
Desired_primaries, 233
Failback, 234
Global_resources_used, 234
Implicit_network_dependencies, 234
Maximum_primaries, 234
Nodelist, 234
Pathprefix, 234
Pingpong_interval, 235
Resource_list, 235
RG_affinities, 235
RG_dependencies, 236
RG_description, 236
RG_is_frozen, 236
RG_mode, 237
RG_name, 237
RG_project_name, 237
RG_state, 237
RG_system, 239
访问有关信息, 39
组
组件, RMAPI, 24
342
Sun Cluster 数据服务开发者指南(适用于 Solaris OS) • 2005 年 8 月,修订版 A">
Download
Advertisement
Key features
Resource Management API
Callback Method Implementation
Fault Monitors
Process Management
Frequently asked questions
The RGM provides high availability and scalability mechanisms for managing applications in a cluster.
The RTR file is used to define the initial configuration of a data service.
Use a failover resource group that includes network addresses and failover resources.