diff --git a/tools/ocft/ChangeLog b/tools/ocft/ChangeLog index 97559820d..8b0021038 100644 --- a/tools/ocft/ChangeLog +++ b/tools/ocft/ChangeLog @@ -1,54 +1,57 @@ 0.43: + - Add an option 'Agent' in 'CONFIG' + - Fix a bug about remote shell. - Add top level option 'VARIABLE'. - Add top level option 'CLEANUP-AGENT'. - Rename Var & Unvar to Env & Unenv. - Fix a bug about agent installation. - Modified configs of agent according the new syntax. 0.42: - Fix a bug about agent installation. - The tests stop early if the basic functionality it not there. - Fix a bug about 'config parser'. - Keep the resource stat between the runs to avoid there are multiple stop/start per run. - Add a function with warning output. - Adjust the sequence of cases running. - Change the default timeout. - Replace the crm_master command in Agent scripts, it is no use in testing, because the agent runs in local when test. - Support drbd testing if the configuration is correct. - Fix a 'Include' bug. - Fix a bug about configuration of 'mysql'. 0.41: - Fixed a remote shell bug. - Improved 'Include' option, now it supports remote shell, invoked just like 'Include@ip_address'. - Show line number, if syntax error occurs in config file. - Add a 'AgentRoot' sub-option. - Fix a bug with config parsing. - Rename ACTION "run" to "test". - Add a simple output mode for "test" ACTION. - Add a verbose ouput mode for "help" ACTION. - The output will be recorded to log file. - Add double stop and double start to tests. - Exit with 1 if test script failed. - The output of agents will be exposed if the test fails. - Run zypper with -q - Use 127.0.0.x(and lo for interface) for agents IP* 0.4: - Add a 'CASE-BLOCK' top option, it can be included by 'CASE' - - Add a 'SETUP-AGENT' top option, you can initialize agents before testing. - Add a 'Include' sub-option. + - Add a 'SETUP-AGENT' top option, you can initialize agents before testing. + - Add a 'Include' sub-option. - Add a 'Unvar' sub-option. - Rename 'GLOBAL' to 'CONFIG'. - Modify a part of syntax. - Imporve the 'InstallPackage' option, now it supports SUSE, Redhat and Debian. - Add README & README.zh_CN. 0.3: - All statements in CASE can be executed by remote shell. 0.2: - Implement options: BashAtExit, GLOBAL, HangTimeout, InstallPackage. - Delete option: Name. - Modify a part of syntax. - Fix some bugs. - Print testing message in human readable format. - Improve 'make' and 'run' option. - Add 'clean' option. 0.1: - Implement options: CASE, Bash, Run, Var, Name. diff --git a/tools/ocft/Filesystem b/tools/ocft/Filesystem index 65cab5831..47700a653 100644 --- a/tools/ocft/Filesystem +++ b/tools/ocft/Filesystem @@ -1,109 +1,110 @@ # Filesystem # by dejan@suse.de on # Tue Feb 15 18:50:04 CET 2011 CONFIG - #AgentRoot /usr/lib/ocf/resource.d/heartbeat + Agent Filesystem + AgentRoot /usr/lib/ocf/resource.d/heartbeat HangTimeout 20 VARIABLE OCFT_fs=/var/run/resource-agents/ocft-Filesystem-fs OCFT_loop=/dev/loop0 OCFT_dir=/var/run/resource-agents/ocft-Filesystem-mnt SETUP-AGENT losetup $OCFT_loop 2>/dev/null && exit 1 rmdir $OCFT_dir 2>/dev/null || true mkdir $OCFT_dir dd if=/dev/zero of=$OCFT_fs bs=1024k count=1 2>/dev/null mke2fs -Fq $OCFT_fs losetup $OCFT_loop $OCFT_fs CLEANUP-AGENT rmdir $OCFT_dir rm $OCFT_fs losetup -d $OCFT_loop CASE-BLOCK required_args Env OCF_RESKEY_device=$OCFT_loop Env OCF_RESKEY_fstype=ext2 Env OCF_RESKEY_directory=$OCFT_dir CASE-BLOCK default_status AgentRun stop CASE-BLOCK prepare Include required_args Include default_status CASE "check base env" Include prepare AgentRun start OCF_SUCCESS CASE "check base env: invalid 'OCF_RESKEY_device'" Include prepare Env OCF_RESKEY_device=/dev/no_such_device AgentRun start OCF_ERR_INSTALLED CASE "check base env: unset 'OCF_RESKEY_device'" Include prepare Unenv OCF_RESKEY_device AgentRun start OCF_ERR_CONFIGURED CASE "normal start" Include prepare AgentRun start OCF_SUCCESS CASE "normal stop" Include prepare AgentRun start AgentRun stop OCF_SUCCESS CASE "double start" Include prepare AgentRun start AgentRun start OCF_SUCCESS CASE "double stop" Include prepare AgentRun stop OCF_SUCCESS CASE "monitor when running" Include prepare AgentRun start AgentRun monitor OCF_SUCCESS CASE "monitor when not running" Include prepare AgentRun monitor OCF_NOT_RUNNING CASE "monitor depth 10 when running" Include prepare AgentRun start Env OCF_CHECK_LEVEL=10 AgentRun monitor OCF_SUCCESS CASE "monitor depth 20 with running" Include prepare AgentRun start Env OCF_CHECK_LEVEL=20 AgentRun monitor OCF_SUCCESS CASE "start insert failure (remove device)" Include prepare Bash losetup -d $OCFT_loop BashAtExit losetup $OCFT_loop $OCFT_fs AgentRun start OCF_ERR_GENERIC CASE "monitor depth 20 insert failure (r/o fs)" Include prepare AgentRun start Bash mount -o remount,ro $OCFT_dir BashAtExit mount -o remount,rw $OCFT_dir Env OCF_CHECK_LEVEL=20 AgentRun monitor OCF_ERR_GENERIC CASE "unimplemented command" Include prepare AgentRun no_cmd OCF_ERR_UNIMPLEMENTED diff --git a/tools/ocft/IPaddr2 b/tools/ocft/IPaddr2 index 3a0c3ea5a..71d71820f 100644 --- a/tools/ocft/IPaddr2 +++ b/tools/ocft/IPaddr2 @@ -1,91 +1,92 @@ # IPaddr2 CONFIG - #AgentRoot /usr/lib/ocf/resource.d/heartbeat + Agent IPaddr2 + AgentRoot /usr/lib/ocf/resource.d/heartbeat InstallPackage iproute2 HangTimeout 20 CASE-BLOCK required_args Env OCF_RESKEY_ip=127.0.0.3 CASE-BLOCK default_status AgentRun stop CASE-BLOCK prepare Include required_args Include default_status CASE "check base env" Include prepare AgentRun start OCF_SUCCESS CASE "check base env: unset 'OCF_RESKEY_ip'" Include prepare Unenv OCF_RESKEY_ip AgentRun start OCF_ERR_CONFIGURED CASE "check base env: set invalid 'OCF_RESKEY_ip'" Include prepare Env OCF_RESKEY_ip=not_ip_address AgentRun start OCF_ERR_CONFIGURED CASE "check base env: set 'OCF_RESKEY_cidr_netmask'" Include prepare Env OCF_RESKEY_cidr_netmask=8 AgentRun start OCF_SUCCESS CASE "check base env: set invalid 'OCF_RESKEY_cidr_netmask'" Include prepare Env OCF_RESKEY_cidr_netmask=not_netmask AgentRun start OCF_ERR_CONFIGURED CASE "check base env: set 'OCF_RESKEY_broadcast'" Include prepare Env OCF_RESKEY_broadcast=127.255.255.255 AgentRun start OCF_SUCCESS CASE "check base env: set invalid 'OCF_RESKEY_broadcast'" Include prepare Env OCF_RESKEY_broadcast=not_broadcast AgentRun start OCF_ERR_CONFIGURED CASE "check base env: set 'OCF_RESKEY_nic'" Include prepare Env OCF_RESKEY_nic=lo AgentRun start OCF_SUCCESS CASE "check base env: set invalid 'OCF_RESKEY_nic'" Include prepare Env OCF_RESKEY_nic=not_nic AgentRun start OCF_ERR_CONFIGURED CASE "normal start" Include prepare AgentRun start OCF_SUCCESS CASE "normal stop" Include prepare AgentRun start AgentRun stop OCF_SUCCESS CASE "double start" Include prepare AgentRun start AgentRun start OCF_SUCCESS CASE "double stop" Include prepare AgentRun stop OCF_SUCCESS CASE "monitor with running" Include prepare AgentRun start AgentRun monitor OCF_SUCCESS CASE "monitor with not running" Include prepare AgentRun monitor OCF_NOT_RUNNING CASE "unimplemented command" Include prepare AgentRun no_cmd OCF_ERR_UNIMPLEMENTED diff --git a/tools/ocft/IPsrcaddr b/tools/ocft/IPsrcaddr index cf3145b26..011407ce0 100644 --- a/tools/ocft/IPsrcaddr +++ b/tools/ocft/IPsrcaddr @@ -1,61 +1,62 @@ # IPsrcaddr CONFIG - #AgentRoot /usr/lib/ocf/resource.d/heartbeat + Agent IPsrcaddr + AgentRoot /usr/lib/ocf/resource.d/heartbeat InstallPackage iproute2 HangTimeout 20 CASE-BLOCK required_args Env OCF_RESKEY_ipaddress=127.0.0.3 CASE-BLOCK default_status AgentRun stop CASE-BLOCK prepare Include required_args Include default_status CASE "check base env" Include prepare AgentRun start OCF_SUCCESS CASE "check base env: unset 'OCF_RESKEY_ipaddress'" Include prepare Unenv OCF_RESKEY_ipaddress AgentRun start OCF_ERR_CONFIGURED CASE "check base env: set invalid 'OCF_RESKEY_ipaddress'" Include prepare Env OCF_RESKEY_ipaddress=not_ip_address AgentRun start OCF_ERR_CONFIGURED CASE "normal start" Include prepare AgentRun start OCF_SUCCESS CASE "normal stop" Include prepare AgentRun start AgentRun stop OCF_SUCCESS CASE "double start" Include prepare AgentRun start AgentRun start OCF_SUCCESS CASE "double stop" Include prepare AgentRun stop OCF_SUCCESS CASE "monitor with running" Include prepare AgentRun start AgentRun monitor OCF_SUCCESS CASE "monitor with not running" Include prepare AgentRun monitor OCF_NOT_RUNNING CASE "unimplemented command" Include prepare AgentRun no_cmd OCF_ERR_UNIMPLEMENTED diff --git a/tools/ocft/LVM b/tools/ocft/LVM index e5a41a4a6..f7154ae58 100644 --- a/tools/ocft/LVM +++ b/tools/ocft/LVM @@ -1,84 +1,85 @@ # LVM # by dejan@suse.de on # Wed Feb 16 13:15:01 CET 2011 CONFIG - #AgentRoot /usr/lib/ocf/resource.d/heartbeat + Agent LVM + AgentRoot /usr/lib/ocf/resource.d/heartbeat HangTimeout 20 VARIABLE OCFT_pv=/var/run/resource-agents/ocft-LVM-pv OCFT_vg=ocft-vg OCFT_lv=ocft-lv OCFT_loop=/dev/loop0 SETUP-AGENT losetup -d $OCFT_loop 2>/dev/null || true dd if=/dev/zero of=$OCFT_pv bs=1024k count=1 2>/dev/null losetup $OCFT_loop $OCFT_pv pvcreate $OCFT_loop vgcreate -s 4K $OCFT_vg $OCFT_loop lvcreate -n $OCFT_lv -L 600K $OCFT_vg CLEANUP-AGENT vgchange -an $OCFT_vg lvremove -f /dev/$OCFT_vg/$OCFT_lv vgremove -f $OCFT_vg losetup -d $OCFT_loop rm $OCFT_pv CASE-BLOCK required_args Env OCF_RESKEY_volgrpname=$OCFT_vg CASE-BLOCK default_status AgentRun stop CASE-BLOCK prepare Include required_args Include default_status CASE "check base env" Include prepare AgentRun start OCF_SUCCESS CASE "check base env: invalid 'OCF_RESKEY_volgrpname'" Include prepare Env OCF_RESKEY_volgrpname=/dev/no_such_device AgentRun start OCF_ERR_GENERIC CASE "check base env: unset 'OCF_RESKEY_volgrpname'" Include prepare Unenv OCF_RESKEY_volgrpname AgentRun start OCF_ERR_CONFIGURED CASE "normal start" Include prepare AgentRun start OCF_SUCCESS CASE "normal stop" Include prepare AgentRun start AgentRun stop OCF_SUCCESS CASE "double start" Include prepare AgentRun start AgentRun start OCF_SUCCESS CASE "double stop" Include prepare AgentRun stop OCF_SUCCESS CASE "monitor when running" Include prepare AgentRun start AgentRun monitor OCF_SUCCESS CASE "monitor when not running" Include prepare AgentRun monitor OCF_NOT_RUNNING CASE "unimplemented command" Include prepare AgentRun no_cmd OCF_ERR_UNIMPLEMENTED diff --git a/tools/ocft/MailTo b/tools/ocft/MailTo index f9beae268..875403584 100644 --- a/tools/ocft/MailTo +++ b/tools/ocft/MailTo @@ -1,56 +1,57 @@ # MailTo CONFIG - #AgentRoot /usr/lib/ocf/resource.d/heartbeat + Agent MailTo + AgentRoot /usr/lib/ocf/resource.d/heartbeat InstallPackage mailx HangTimeout 20 CASE-BLOCK required_args Env OCF_RESKEY_email=root@localhost CASE-BLOCK default_status AgentRun stop CASE-BLOCK prepare Include required_args Include default_status CASE "check base env" Include prepare AgentRun start OCF_SUCCESS CASE "check base env: unset 'OCF_RESKEY_email'" Include prepare Unenv OCF_RESKEY_email AgentRun start OCF_ERR_CONFIGURED CASE "normal start" Include prepare AgentRun start OCF_SUCCESS CASE "normal stop" Include prepare AgentRun start AgentRun stop OCF_SUCCESS CASE "double start" Include prepare AgentRun start AgentRun start OCF_SUCCESS CASE "double stop" Include prepare AgentRun stop OCF_SUCCESS CASE "monitor with running" Include prepare AgentRun start AgentRun monitor OCF_SUCCESS CASE "monitor with not running" Include prepare AgentRun monitor OCF_NOT_RUNNING CASE "unimplemented command" Include prepare AgentRun no_cmd OCF_ERR_UNIMPLEMENTED diff --git a/tools/ocft/README.in b/tools/ocft/README.in index 3f6e16ac3..e3022c8db 100644 --- a/tools/ocft/README.in +++ b/tools/ocft/README.in @@ -1,141 +1,145 @@ INTRODUCTION & DESIGN ~~~~~~~~~~~~~~~~~~~~~ - Ocft is a testing tool for resource agents. Instead of the policy of HA, it mainly concerns whether resource agents run correct locally. It can design types of complicated environments to test the reliability of resource agents. Precisely, it is to display whether resource agents can return to correct or expected value. The advantage of the tool provides us with competence to design conditions which can be recorded or reproduced. Hence it is useful to debuggers. * Components ** Test case generator (@sbindir@/ocft) - Turning configuration files of test case to executable scripts. ** Configuration file (@datadir@/@PACKAGE_NAME@/ocft/configs/) - Every configuration file directs only one resource agent and share the same name with resource agent but contains more test cases. ** The testing script (/var/lib/@PACKAGE_NAME@/ocft/cases/) - After the generator reads configuration files and generates many testing scripts and the script is underway, the test begins. * How to customize the environment of testing - Ocft designs the running conditions through two ways, one is changing the environment variables of resource agents (it is the interface left by OCF itself), the other is modifying the OS environment of resource agents, such as altering the permission of some key file or IP address of the machine. * How to test - Firstly, you need to sketch the all complex and uncommon environments against a certain resource agent and keep in mind what consequences may be caused by these uncommon environments. Secondly, write the designed conditions and foreknown consequences into configuration files, and then run the generator to translate the test case to executable scripts. Finally, you need running these scripts to observe the output and learn the running status of each test case, which will compares the predicated result with the actual one. If they differ, you will be able to find the bugs of the resource agent. HOW TO WRITE CONFIGURATION FILE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - There are only 6 top level options that are all spelled by capital letters and "-". Every top level option contains sub-options that they are initials. * 'CONFIG' (top level option) - Grammar: CONFIG - The design in this option is global and influences every test case. + ** 'Agent' (sub-option) + - Grammar: Agent AGENT_NAME + - The agent name you want to test. + ** 'AgentRoot' (sub-option) - Grammar: AgentRoot /usr/lib/ocf/resource.d/xxx - A few agents will go to "linbit" or "pacemaker" directory, if you define this option, ocft will use it to replace the default directory "heartbeat". ** 'InstallPackage' (sub-option) - Grammar: InstallPackage package [package2 [...]] - It will test whether the system have installed the service of the resource agent. If not, it will download from Internet and have it installed automatically. ** 'HangTimeout' (sub-option) - Grammar: HangTimeout secs - If you alter some key options, some resource agents will get puzzled and stop, which will influence the running of the following test case. Hence timeout setting is needed, if the resource agent stops timeout, the scripts will kill this resource agent. * 'VARIABLE' (top level option) - Garmmar: VARIABLE VAR1=value1 VAR2=value2 ... - Define the global variable here, the variables can be visited everywhere, they can be referenced using $VAR_NAME. Note, the variables in VARIABLE are different from 'Env VAR1=value1', 'Env' can affect the activity of agent, but the variables in VARIABLE just be shared with top level option. * 'SETUP-AGENT' (top level option) - Grammar: SETUP-AGENT bash scripts... ... - Some of Agents may need to be initialized before testing, you can do it here with bash script. * 'CLEANUP-AGENT' (top level option) - Garmmar: CLEANUP-AGENT bash scripts... ... - If SETUP-AGENT set, usually you might be use this option do some cleaning work after test. * 'CASE' & 'CASE-BLOCK' (top level option) - Grammar: CASE "description" & CASE-BLOCK macro_name - Usually, the conditions you designed are more than one and a few 'CASE "..."' will appear in configuration file. It is worth noting that the following sub-options have 2 spellings: One is general, where shell affects the local environment; the other is special, where each options added "@ipaddr". It can remotely execute shell codes. In other words, it is to execute the shell codes from a remote host, which is meaningful when a resource agent needs 2 hosts. This remote shell is not a remote execution only through "ssh", but running a remote shell in the background while the test case is running. The remote shell runs in the background till the end and saves the results during the process. That is to say, you can alternatively carry out local and remote shell code segments. The "CASE-BLOCK" option is a macro definer, the statements in "CASE-BLOCK" will be inserted into "CASE" if you "Include" the "macro_name". ** 'Env' (sub-option) - Grammar: Env VARIABLE=value - It is to set up an environment variable of the resource agent. They usually appear to be OCF_RESKEY_xxx. One point is to be noted is there is no blank by both sides of "=". ** 'Unenv' (sub-option) - Grammer: Unenv VARIABLE [VARIABLE2 [...]] - Remove the environment variable. ** 'Include' (sub-option) - Garmmer: Include macro_name - It will be replaced by statements in 'macro_name', of course, you should define the content of 'macro_name' with 'CASE-BLOCK' first. ** 'Bash' (sub-option) - Grammar: Bash bash_codes - This option is to set up the environment of OS, where you can insert BASH code to customize the system randomly. Note, do not cause unrecoverable consequences to the system. ** 'BashAtExit' (sub-option) - Grammar: BashAtExit bash_codes - This option is to recover the OS environment in order to run another test case correctly. Of cause you can use 'Bash' option to recover it. However, if mistakes occur in the process, the script will quit directly instead of running your recovery codes. If it happens, you ought to use BashAtExit which can restore the system environment before you quit. ** 'RunAgent' (sub-option) - Grammar: RunAgent cmd [ret_value] - This option is to run resource agent. "cmd" is the parameter of the resource agent, such as "start, status, stop ...". The second parameter is optional. It will compare the actual returned value with the expected value when the script has run recourse agent. If differs, bugs will be found. diff --git a/tools/ocft/README.zh_CN.in b/tools/ocft/README.zh_CN.in index 65dac0482..cfd79f407 100644 --- a/tools/ocft/README.zh_CN.in +++ b/tools/ocft/README.zh_CN.in @@ -1,118 +1,122 @@ 1 介绍和设计 ocft是一个测试resource agents的工具。它并不关注HA的策略,而是关注resource agents 是否正常运行在本机。他能对resource agents设计各种复杂环境,来考验resource agnets 是否能正常应对,也就是看resouce agents是否能返回正确的或者说我们所期望的值。 这个工具给我们带来的好处就是我们可以集中的批量的来设计环境,而且这种环境是可被我们 记录、重现的,对Debug人员来说是很有用的。 1.1 组成 1.1.1 解释器 (@sbindir@/ocft) 将test case配置文件转换成可执行的测试脚本。 1.1.2 配置文件 (@datadir@/@PACKAGE_NAME@/ocft/configs/) 每一个configuration file只针对一个resouce agent,配置文件名与resouce agent名相同, 但是它可以容纳很多test case。 1.1.3 测试脚本 (/var/lib/@PACKAGE_NAME@/ocft/cases/) 由generator读取configuration file生成测试脚本,直接运行此脚本就可以开始测试了。 1.2 如何定制环境 ocft 通过两种手段来设计resouce agents的运行环境,一是更改resouce agents的环境变量, 当然这是ocf本身就留给我们的接口。二是更改resource agents所处的系统环境, 比如更改某个关键文件的权限,更改本机ip地址等等... 1.3 如何进行测试 首先你需要针对某个resource agent在脑中勾画各种复杂且异常的环境,并且你能清楚预知 这些异常环境会给resource agent带来什么结果,然后将这些设计好的环境和你预知的结果 都写入配置文件,然后运行generator,将你刚写的test case转换成可执行的脚本。最后运行 这些脚本,观察它们的输出,你可以清楚看到每个test case运行状况,他会比较你的预知结 果和resource agent的实际结果,如果不一样,说明你找到resource agent的bug了。 2 配置 只有6个top level option,它们是由大写字母和'-'构成的,每个top level option都有若干sub-option, 它们是首字母大写。 2.1 'CONFIG' 选项 语法:CONFIG 此option中的设计是全局的,对每个test case都有所影响。 -2.1.1 'AgentRoot' 选项 +2.1.1 'Agent' 选项 +语法:Agent AGENT_NAME +你要测试的Agent的名字。 + +2.1.2 'AgentRoot' 选项 语法:AgentRoot /usr/lib/ocf/resource.d/xxx 一些agent将会被移到 "pacemaker" 或 "linbit" 目录,如果你定义了这个选项,ocft将会用它来 替代默认的目录"heartbeat"。 -2.1.1 'InstallPackage' 选项 +2.1.3 'InstallPackage' 选项 语法:InstallPackage package [package2 [...]] 他会检测系统是否安装了此resource agent的service,如果没有安装,会自动从网络进行安装。 package_name是某个resouce agent在操作系统中必须安装的包。 -2.1.2 'HangTimeout' 选项 +2.1.4 'HangTimeout' 选项 语法:HangTimeout secs 如果你更改了一些很关键的东西,有些resouce agent会不知所措,停在那里不动,那么就会影响 到后面test case的运行,所以你需要设定超时,如果一旦resouce agent停在那超时了,脚本会 杀死这个resouce agent。 2.2 'VARIABLE' 选项 语法: VARIABLE VAR1=value1 VAR2=value2 ... 在此定义全局变量,这些变量可以用于配置文件中的任何地方,引用时在变量名前加上$。请注意,这些 变量不同于Env定义的变量,Env是定义环境变量,可以改变agent的行为,而这些变量只是用于配置文件中 共享。 2.3 'SETUP-AGENT' 选项 语法: SETUP-AGENT bash scripts... ... 一些Agent在测试前可能需要初始化,你可以用bash脚本在这初始化。 2.4 'CLEANUP-AGENT' 选项 语法: CLEANUP-AGENT bash scripts... ... 如果之前定义了SETUP-AGENT, 你可能还需要此选项在测试完后来作一些清除。 2.5 'CASE' & 'CASE-BLOCK' 选项 语法:CASE "description" & CASE-BLOCK macro_name 通常你设计的环境不止一个,那么配置文件中应该会出现许多 'CASE "..."',值得注意的是,以下子 选项每个都有两种写法,一是普通写法,产生的shell代码对本地产生作用,二是特殊写法,就是在每 个选项后加上 "@ipaddr",他可以远程执行shell代码,也就是控制远程机器执行你给的shell代码, 这对需要两台机器以上的resouce agent很有用的,这个远程shell并非简单的用ssh去远程执行,而是在 test case生存期内,后台运行一个远程shell,他始终在后台运行并且保存你的中间结果,也就是说你 可以交替执行本地shell代码段和远程shell代码段。 'CASE-BLOCK'选项是一个宏定义器,它定义的内容将会被插入到"CASE"内容中。 2.5.1 'Env' 选项 语法:Env VARIABLE=value 这是设置resouce agent的环境变量,他们通常是OCF_RESKEY_xxx,注意=号两边不要有空格。 2.5.2 'Unenv' 选项 语法:Unenv VARIABLE 此选项用于删除环境变量。 2.5.3 'Include' 选项 语法:Include macro_name 此选项将会被宏"macro_name"的内容所替代,当然,你得预先用"CASE-BLOCK"来定义宏"macro_name" 的内容。 2.5.4 'Bash' 选项 语法:Bash bash_codes 此选项是用来设置os的环境,你可以嵌入bash代码来对系统作任意设置,不过要注意不要对系统造成 不可恢复的后果就行了。 2.5.5 'BashAtExit' 选项 语法:BashAtExit bash_codes 此选项是用来恢复os的环境,以便另一个test case能正常运行,当然你也可以直接用'Bash'选项来 恢复,但是如果脚本在执行过程中产生某些错误,那么脚本会直接退出,而不会去执行你的恢复代码, 那么你就要用到BashAtExit,他能在你退出前去恢复系统环境。 2.5.6 'RunAgent' 选项 语法:RunAgent cmd [ret_value] 此option会去运行resouce agent,'cmd' 就是resouce agent的参数,如 start,status,stop ... 第二个参数是可选的,它是你对系统环境作出特殊设定以后,你预计resouce agent会返回的值, 如果给出此参数,那么脚本会在运行resouce agent后,会比较此时的返回值和你预期的返回值, 如果不一致,那么说明找到bug了。 diff --git a/tools/ocft/SendArp b/tools/ocft/SendArp index ee46e3941..832897c43 100644 --- a/tools/ocft/SendArp +++ b/tools/ocft/SendArp @@ -1,72 +1,73 @@ # SendArp CONFIG - #AgentRoot /usr/lib/ocf/resource.d/heartbeat + Agent SendArp + AgentRoot /usr/lib/ocf/resource.d/heartbeat InstallPackage resource-agents HangTimeout 15 CASE-BLOCK required_args Env OCF_RESKEY_ip=127.0.0.1 Env OCF_RESKEY_nic=lo CASE-BLOCK default_status AgentRun stop CASE-BLOCK prepare Include required_args Include default_status CASE "check base env" Include prepare AgentRun start OCF_SUCCESS CASE "check base env: unset 'OCF_RESKEY_ip'" Include prepare Unenv OCF_RESKEY_ip AgentRun start OCF_ERR_ARGS CASE "check base env: set worng 'OCF_RESKEY_ip'" Include prepare Env OCF_RESKEY_ip=not_ip_address AgentRun start OCF_ERR_ARGS CASE "check base env: unset 'OCF_RESKEY_nic'" Include prepare Unenv OCF_RESKEY_nic AgentRun start OCF_ERR_ARGS CASE "check base env: set worng 'OCF_RESKEY_nic'" Include prepare Env OCF_RESKEY_nic=not_nic AgentRun start OCF_ERR_ARGS CASE "normal start" Include prepare AgentRun start OCF_SUCCESS CASE "normal stop" Include prepare AgentRun start AgentRun stop OCF_SUCCESS CASE "double start" Include prepare AgentRun start AgentRun start OCF_SUCCESS CASE "double stop" Include prepare AgentRun stop OCF_SUCCESS CASE "monitor with running" Include prepare AgentRun start AgentRun monitor OCF_SUCCESS CASE "monitor with not running" Include prepare AgentRun monitor OCF_NOT_RUNNING CASE "unimplemented command" Include prepare AgentRun no_cmd OCF_ERR_UNIMPLEMENTED diff --git a/tools/ocft/apache b/tools/ocft/apache index f444d5103..c5f8bb90c 100644 --- a/tools/ocft/apache +++ b/tools/ocft/apache @@ -1,66 +1,67 @@ # apache CONFIG - #AgentRoot /usr/lib/ocf/resource.d/heartbeat + Agent apache + AgentRoot /usr/lib/ocf/resource.d/heartbeat InstallPackage apache2 HangTimeout 20 SETUP-AGENT /etc/init.d/apache2 start /etc/init.d/apache2 stop CASE-BLOCK required_args Env OCF_RESKEY_statusurl=http://localhost/info2html.css Env OCF_RESKEY_testregex='This is' CASE-BLOCK default_status AgentRun stop CASE-BLOCK prepare Include required_args Include default_status CASE "check base env" Include prepare AgentRun start OCF_SUCCESS CASE "check base env: unset OCF_RESKEY_statusurl" Include prepare Unenv OCF_RESKEY_statusurl AgentRun start OCF_ERR_CONFIGURED CASE "check base env: unset OCF_RESKEY_testregex" Include prepare Unenv OCF_RESKEY_testregex AgentRun start OCF_ERR_CONFIGURED CASE "normal start" Include prepare AgentRun start OCF_SUCCESS CASE "normal stop" Include prepare AgentRun start AgentRun stop OCF_SUCCESS CASE "double start" Include prepare AgentRun start AgentRun start OCF_SUCCESS CASE "double stop" Include prepare AgentRun stop OCF_SUCCESS CASE "running monitor" Include prepare AgentRun start AgentRun monitor OCF_SUCCESS CASE "not running monitor" Include prepare AgentRun monitor OCF_NOT_RUNNING CASE "unimplemented command" Include prepare AgentRun no_cmd OCF_ERR_UNIMPLEMENTED diff --git a/tools/ocft/caselib.in b/tools/ocft/caselib.in index 0617bfd64..8c8a45ac0 100644 --- a/tools/ocft/caselib.in +++ b/tools/ocft/caselib.in @@ -1,293 +1,294 @@ # # Copyright (c) 2010-2011 Novell Inc, John Shi # All Rights Reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License as # published by the Free Software Foundation. # # This program is distributed in the hope that it would be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # # Further, this software is distributed without any warranty that it is # free of the rightful claim of any third person regarding infringement # or the like. Any license provided herein, whether implied or # otherwise, applies only to this software file. Patent licenses, if # any, provided herein do not apply to combinations of this program with # other software, or any other product whatsoever. # # You should have received a copy of the GNU General Public License # along with this program; if not, write the Free Software Foundation, # Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. quit() { local ret ret="$1" while [ $__OCFT__atexit_num -gt 0 ]; do atexit$__OCFT__atexit_num let __OCFT__atexit_num-- done rm -rf $__OCFT__fakebin exit $ret } agent_install() { local pkg if [ $# -eq 0 ]; then return 0 fi for pkg in "$@"; do if [ -e /etc/SuSE-release ]; then if ! rpm -ql "$pkg" >/dev/null 2>&1; then echo "${__OCFT__showhost}Installing $pkg ..." zypper -q install -y "$pkg" >/dev/null 2>&1 if ! rpm -ql "$pkg" >/dev/null 2>&1; then echo echo "${__OCFT__showhost}ERROR: Install '$pkg' failed." quit 2 fi echo "done" echo fi elif [ -e /etc/debian_version ]; then if ! dpkg -L "$pkg" >/dev/null 2>&1; then echo "${__OCFT__showhost}Installing $pkg ..." apt-get -y install "$pkg" >/dev/null 2>&1 if ! dpkg -L "$pkg" >/dev/null 2>&1; then echo echo "${__OCFT__showhost}ERROR: Install '$pkg' failed." quit 2 fi echo "done" echo fi elif [ -e /etc/redhat-release ]; then if ! rpm -ql "$pkg" >/dev/null 2>&1; then echo "${__OCFT__showhost}Installing $pkg ..." yum -y install "$pkg" >/dev/null 2>&1 if ! rpm -ql "$pkg" >/dev/null 2>&1; then echo echo "${__OCFT__showhost}ERROR: Install '$pkg' failed." quit 2 fi echo "done" echo fi else echo "${__OCFT__showhost}ERROR: Cannot detect your OS type." quit 2 fi done } agent_run() { local agent cmd timeout pid i ret aroot agent="$1" cmd="$2" timeout="$3" aroot=${__OCFT__MYROOT:-$__OCFT__AGENT_ROOT} setsid $aroot/$agent $cmd >/tmp/.ocft_runlog 2>&1 & pid=$! i=0 while [ $i -lt $timeout ]; do if [ ! -e /proc/$pid ]; then break fi sleep 1 let i++ done if [ $i -ge $timeout ]; then kill -SIGTERM -$pid >/dev/null 2>&1 sleep 3 kill -SIGKILL -$pid >/dev/null 2>&1 echo -n "${__OCFT__showhost}ERROR: The agent was hanging, killed it, " - echo "maybe you damaged the agent or system's environment." + echo "maybe you damaged the agent or system's environment, see details below:" + cat /tmp/.ocft_runlog echo quit 1 fi wait $pid } check_success() { local ret msg ret="$1" msg="$2" if [ $ret -ne 0 ]; then echo "${__OCFT__showhost}ERROR: '${msg}' failed, the return code is ${ret}." quit 1 fi } __maxfd() { (echo 0; ls -1 /proc/$$/fd) | sort -rn | head -1 } __getfd() { local host rw fd file host="$1" rw="$2" for fd in /proc/$$/fd/*; do file=$(basename "$(readlink $fd)") if [ "$file" = "${host}_$rw" ]; then basename $fd break fi done } backbash_start() { local host fd rfd wfd host="$1" if [ ! -d "$__OCFT__CASES_DIR" ]; then echo "${__OCFT__showhost}ERROR: Could not found Directory: ${__OCFT__CASES_DIR}." quit 1 fi if lsof $__OCFT__CASES_DIR/${host}_r $__OCFT__CASES_DIR/${host}_w >/dev/null 2>&1; then echo "${__OCFT__showhost}ERROR: Connection exist with $host." quit 1 fi if [ ! -p "$__OCFT__CASES_DIR/${host}_r" ] || [ ! -p "$__OCFT__CASES_DIR/${host}_w" ]; then rm -f $__OCFT__CASES_DIR/${host}_r $__OCFT__CASES_DIR/${host}_w if ! mkfifo $__OCFT__CASES_DIR/${host}_r $__OCFT__CASES_DIR/${host}_w >/dev/null 2>&1; then echo "${__OCFT__showhost}ERROR: Could not create pipe file: $__OCFT__CASES_DIR/${host}_*." quit 1 fi fi ssh root@$host '/bin/bash 2>&1 sed "s/00/001/g" /tmp/.backbash-log echo 000 echo 1' >$__OCFT__CASES_DIR/${host}_r <$__OCFT__CASES_DIR/${host}_w & fd=$(__maxfd) rfd=$(expr $fd + 1) wfd=$(expr $fd + 2) eval "exec ${rfd}<$__OCFT__CASES_DIR/${host}_r ${wfd}>$__OCFT__CASES_DIR/${host}_w" } backbash() { local host rfd wfd ret host="$1" rfd=$(__getfd $host r) wfd=$(__getfd $host w) if [ -z "$rfd" -o -z "$wfd" ]; then echo "${__OCFT__showhost}ERROR: Could not found connection with $host." fi cat >&$wfd <&$wfd cat >&$wfd <&/tmp/.backbash-log sed 's/00/001/g' /tmp/.backbash-log echo 000 echo 0 EOF if [ $? -ne 0 ]; then echo "${__OCFT__showhost}ERROR: Broken connection with $host." quit 1 fi awk -vlive=2 '{ if (sub(/000$/, "")) { if ($0 != "") { gsub("001", "00"); printf("%s", $0); } getline live; exit; } gsub("001", "00"); print; } END { exit(live); }' <&$rfd case $? in 1) quit 1 ;; 2) echo "${__OCFT__showhost}ERROR: Broken connection with $host." quit 1 ;; esac } backbash_stop() { local host rfd wfd host="$1" wfd=$(__getfd $host w) if [ -n "$wfd" ]; then cat >&$wfd <<<'quit 0' fi rm -f $__OCFT__CASES_DIR/${host}_r $__OCFT__CASES_DIR/${host}_w } export OCF_ROOT=@OCF_ROOT_DIR@ export OCF_LIB=@OCF_LIB_DIR@/heartbeat __OCFT__AGENT_ROOT=@OCF_RA_DIR@/heartbeat __OCFT__CASES_DIR=/var/lib/@PACKAGE_NAME@/ocft/cases __OCFT__atexit_num=0 if [ $EUID -ne 0 ]; then echo "${__OCFT__showhost}ERROR: '$0' needs to be run by root." quit 3 fi __OCFT__fakebin=./fakebin mkdir -p $__OCFT__fakebin >/dev/null 2>&1 && ln -sf /bin/true $__OCFT__fakebin/crm_master >/dev/null 2>&1 && ln -sf /bin/true $__OCFT__fakebin/crm_mon >/dev/null 2>&1 if [ $? -ne 0 ]; then echo "${__OCFT__showhost}ERROR: initialize 'fakebin' failed." quit 3 fi export HA_SBIN_DIR=$__OCFT__fakebin . $OCF_LIB/ocf-returncodes || { echo "${__OCFT__showhost}ERROR: $OCF_LIB/ocf-returncodes not found." quit 3 } while read __OCFT__line; do if [ -n "$__OCFT__line" ]; then __OCFT__retn=${__OCFT__line%%=*} __OCFT__reti=$(eval echo \$$__OCFT__retn) __OCFT__retval[__OCFT__reti]=$__OCFT__retn fi done <<<"$(sed 's/#.*//' $OCF_LIB/ocf-returncodes)" diff --git a/tools/ocft/db2 b/tools/ocft/db2 index 9b693508e..7013a992f 100644 --- a/tools/ocft/db2 +++ b/tools/ocft/db2 @@ -1,162 +1,164 @@ # db2 # # This test assumes a db2 ESE instance with two partions and a database. # Default is instance=db2inst1, database=ocft # adapt this in set_testenv below # # Simple steps to generate a test environment (if you don't have one): # # A virtual machine with 1200MB RAM is sufficient # # - download an eval version of DB2 server from IBM # - create an user "db2inst1" in group "db2inst1" # # As root # - install DB2 software in some location # - create instance # cd /instance # ./db2icrt -s ese -u db2inst1 db2inst1 # - adapt profile of db2inst1 as instructed by db2icrt # # As db2inst1 # # allow to run with small memory footprint # db2set DB2_FCM_SETTINGS=FCM_MAXIMIZE_SET_SIZE:FALSE # db2start # db2start dbpartitionnum 1 add dbpartitionnum hostname $(uname -n) port 1 without tablespaces # db2stop # db2start # db2 create database ocft # Done # In order to install a real cluster refer to http://www.linux-ha.org/wiki/db2_(resource_agent) CONFIG + Agent db2 + AgentRoot /usr/lib/ocf/resource.d/heartbeat HangTimeout 40 SETUP-AGENT # nothing CASE-BLOCK set_testenv Env OCFT_instance=db2inst1 Env OCFT_db=ocft CASE-BLOCK crm_setting Env OCF_RESKEY_instance=$OCFT_instance Env OCF_RESKEY_CRM_meta_timeout=30000 CASE-BLOCK default_status AgentRun stop CASE-BLOCK prepare Include set_testenv Include crm_setting Include default_status CASE "check base env" Include prepare AgentRun start OCF_SUCCESS CASE "check base env: invalid 'OCF_RESKEY_instance'" Include prepare Env OCF_RESKEY_instance=no_such AgentRun start OCF_ERR_INSTALLED CASE "invalid instance config" Include prepare Bash eval mv ~$OCFT_instance/sqllib ~$OCFT_instance/sqllib- BashAtExit eval mv ~$OCFT_instance/sqllib- ~$OCFT_instance/sqllib AgentRun start OCF_ERR_INSTALLED CASE "unimplemented command" Include prepare AgentRun no_cmd OCF_ERR_UNIMPLEMENTED CASE "normal start" Include prepare AgentRun start OCF_SUCCESS CASE "normal stop" Include prepare AgentRun start AgentRun stop OCF_SUCCESS CASE "double start" Include prepare AgentRun start AgentRun start OCF_SUCCESS CASE "double stop" Include prepare AgentRun stop OCF_SUCCESS CASE "started: monitor" Include prepare AgentRun start AgentRun monitor OCF_SUCCESS CASE "not started: monitor" Include prepare AgentRun monitor OCF_NOT_RUNNING CASE "killed instance: monitor" Include prepare AgentRun start OCF_SUCCESS AgentRun monitor OCF_SUCCESS BashAtExit rm /tmp/ocft-helper1 Bash echo "su $OCFT_instance -c '. ~$OCFT_instance/sqllib/db2profile; db2nkill 0 >/dev/null 2>&1'" > /tmp/ocft-helper1 Bash sh -x /tmp/ocft-helper1 AgentRun monitor OCF_NOT_RUNNING CASE "overload param instance by admin" Include prepare Env OCF_RESKEY_instance=no_such Env OCF_RESKEY_admin=$OCFT_instance AgentRun start OCF_SUCCESS CASE "check start really activates db" Include prepare AgentRun start OCF_SUCCESS BashAtExit rm /tmp/ocft-helper2 Bash echo "su $OCFT_instance -c '. ~$OCFT_instance/sqllib/db2profile; db2 get snapshot for database on $OCFT_db>/dev/null'" > /tmp/ocft-helper2 Bash sh -x /tmp/ocft-helper2 CASE "multipartion test" Include prepare AgentRun start OCF_SUCCESS AgentRun monitor OCF_SUCCESS # start does not start partion 1 Env OCF_RESKEY_dbpartitionnum=1 AgentRun monitor OCF_NOT_RUNNING # now start 1 AgentRun start OCF_SUCCESS AgentRun monitor OCF_SUCCESS # now stop 1 AgentRun stop OCF_SUCCESS AgentRun monitor OCF_NOT_RUNNING # does not affect 0 Env OCF_RESKEY_dbpartitionnum=0 AgentRun monitor OCF_SUCCESS # fault injection does not work on the 1.0.4 client due to a hardcoded path CASE "simulate hanging db2stop (not meaningful for 1.0.4 agent)" Include prepare AgentRun start OCF_SUCCESS Bash [ ! -f /usr/local/bin/db2stop ] BashAtExit rm /usr/local/bin/db2stop Bash echo -e "#!/bin/sh\necho fake db2stop\nsleep 10000" > /usr/local/bin/db2stop Bash chmod +x /usr/local/bin/db2stop AgentRun stop OCF_SUCCESS # fault injection does not work on the 1.0.4 client due to a hardcoded path CASE "simulate not stopping db2stop (not meaningful for 1.0.4 agent)" Include prepare AgentRun start OCF_SUCCESS Bash [ ! -f /usr/local/bin/db2stop ] BashAtExit rm /usr/local/bin/db2stop Bash echo -e "#!/bin/sh\necho fake db2stop\nexit 0" > /usr/local/bin/db2stop Bash chmod +x /usr/local/bin/db2stop AgentRun stop OCF_SUCCESS diff --git a/tools/ocft/iscsi b/tools/ocft/iscsi index 0b09a2535..c1325a1c6 100644 --- a/tools/ocft/iscsi +++ b/tools/ocft/iscsi @@ -1,81 +1,82 @@ # iscsi CONFIG - #AgentRoot /usr/lib/ocf/resource.d/heartbeat + Agent iscsi + AgentRoot /usr/lib/ocf/resource.d/heartbeat InstallPackage open-iscsi InstallPackage iscsitarget HangTimeout 20 VARIABLE OCFT_disk=/var/run/resource-agents/ocft-iscsi OCFT_target="iqn.2011-03.ocft.localhost:disk0" OCFT_portal="127.0.0.1:3260" SETUP-AGENT dd if=/dev/zero of=$OCFT_disk bs=1024k count=1 2>/dev/null echo Target $OCFT_target >> /etc/ietd.conf echo " Lun 0 Path=$OCFT_disk,Type=fileio" >> /etc/ietd.conf /etc/init.d/iscsitarget start /etc/init.d/open-iscsi start /etc/init.d/iscsitarget restart CLEANUP-AGENT rm -f $OCFT_disk sed -i "/^Target $OCFT_target/,+1d" /etc/ietd.conf CASE-BLOCK required_args Env OCF_RESKEY_portal=$OCFT_portal Env OCF_RESKEY_target=$OCFT_target CASE-BLOCK default_status AgentRun stop CASE-BLOCK prepare Include required_args Include default_status CASE "check base env" Include prepare AgentRun start OCF_SUCCESS CASE "check base env: invalid 'OCF_RESKEY_portal'" Include prepare Unenv OCF_RESKEY_portal AgentRun start OCF_ERR_CONFIGURED CASE "check base env: unset 'OCF_RESKEY_target'" Include prepare Unenv OCF_RESKEY_target AgentRun start OCF_ERR_CONFIGURED CASE "normal start" Include prepare AgentRun start OCF_SUCCESS CASE "normal stop" Include prepare AgentRun start AgentRun stop OCF_SUCCESS CASE "double start" Include prepare AgentRun start AgentRun start OCF_SUCCESS CASE "double stop" Include prepare AgentRun stop OCF_SUCCESS CASE "monitor when running" Include prepare AgentRun start AgentRun monitor OCF_SUCCESS CASE "monitor when not running" Include prepare AgentRun monitor OCF_NOT_RUNNING CASE "unimplemented command" Include prepare AgentRun no_cmd OCF_ERR_UNIMPLEMENTED diff --git a/tools/ocft/mysql b/tools/ocft/mysql index f0b475ed7..27fcb587a 100644 --- a/tools/ocft/mysql +++ b/tools/ocft/mysql @@ -1,76 +1,77 @@ # mysql CONFIG - #AgentRoot /usr/lib/ocf/resource.d/heartbeat + Agent mysql + AgentRoot /usr/lib/ocf/resource.d/heartbeat InstallPackage mysql HangTimeout 20 SETUP-AGENT /etc/init.d/mysql start /etc/init.d/mysql stop CASE-BLOCK crm_setting Env OCF_RESKEY_CRM_meta_timeout=15000 CASE-BLOCK default_status AgentRun stop CASE-BLOCK prepare Include crm_setting Include default_status CASE "check base env" Include prepare AgentRun start OCF_SUCCESS CASE "check base env: invalid 'OCF_RESKEY_binary'" Include prepare Env OCF_RESKEY_binary=no_such AgentRun start OCF_ERR_INSTALLED CASE "normal start" Include prepare AgentRun start OCF_SUCCESS CASE "normal stop" Include prepare AgentRun start AgentRun stop OCF_SUCCESS CASE "double start" Include prepare AgentRun start AgentRun start OCF_SUCCESS CASE "double stop" Include prepare AgentRun stop OCF_SUCCESS CASE "running monitor" Include prepare AgentRun start AgentRun monitor OCF_SUCCESS CASE "not running monitor" Include prepare AgentRun monitor OCF_NOT_RUNNING CASE "check lib file" Include prepare Bash chmod u-w /var/lib/mysql BashAtExit chmod u+w /var/lib/mysql AgentRun start OCF_ERR_PERM CASE "unimplemented command" Include prepare AgentRun no_cmd OCF_ERR_UNIMPLEMENTED CASE "non-existent user" Include prepare Env OCF_RESKEY_user=no_user AgentRun start OCF_ERR_INSTALLED CASE "invalid user" Include prepare Env OCF_RESKEY_user=nobody AgentRun start OCF_ERR_PERM diff --git a/tools/ocft/named b/tools/ocft/named index c1f46249e..90a4351bc 100644 --- a/tools/ocft/named +++ b/tools/ocft/named @@ -1,66 +1,69 @@ #named # To work properly this test requires that standard bind and bin-utils # packages installed. CONFIG + Agent named + AgentRoot /usr/lib/ocf/resource.d/heartbeat InstallPackage bind InstallPackage bind-utils + SETUP-AGENT /etc/init.d/named start /etc/init.d/named stop CASE-BLOCK crm_setting Env OCF_RESKEY_CRM_meta_timeout=15000 CASE-BLOCK default_status AgentRun stop CASE-BLOCK prepare Include crm_setting Include default_status CASE "check base env" Include prepare AgentRun start OCF_SUCCESS CASE "check base env: invalid 'OCF_RESKEY_named'" Include prepare Env OCF_RESKEY_named=no_such AgentRun start OCF_ERR_INSTALLED CASE "normal start" Include prepare AgentRun start OCF_SUCCESS CASE "normal stop" Include prepare AgentRun start AgentRun stop OCF_SUCCESS CASE "double start" Include prepare AgentRun start AgentRun start OCF_SUCCESS CASE "double stop" Include prepare AgentRun stop OCF_SUCCESS CASE "running monitor" Include prepare AgentRun start AgentRun monitor OCF_SUCCESS CASE "not running monitor" Include prepare AgentRun monitor OCF_NOT_RUNNING CASE "unimplemented command" Include prepare AgentRun no_cmd OCF_ERR_UNIMPLEMENTED CASE "non-existent user" Include prepare Env OCF_RESKEY_named_user=no_user AgentRun start OCF_ERR_INSTALLED diff --git a/tools/ocft/nfsserver b/tools/ocft/nfsserver index 2fa905fb8..cd731649d 100644 --- a/tools/ocft/nfsserver +++ b/tools/ocft/nfsserver @@ -1,74 +1,75 @@ # nfsserver CONFIG - #AgentRoot /usr/lib/ocf/resource.d/heartbeat + Agent nfsserver + AgentRoot /usr/lib/ocf/resource.d/heartbeat InstallPackage nfs-kernel-server HangTimeout 20 CASE-BLOCK required_args Env OCF_RESKEY_nfs_init_script=/etc/init.d/nfsserver Env OCF_RESKEY_nfs_ip=127.0.0.1 Env OCF_RESKEY_nfs_shared_infodir=/var/lib/nfs Env OCF_RESKEY_nfs_notify_cmd=/usr/sbin/sm-notify CASE-BLOCK default_status AgentRun stop CASE-BLOCK prepare Include required_args Include default_status CASE "check base env" Include prepare AgentRun start OCF_SUCCESS CASE "check base env: invalid 'OCF_RESKEY_nfs_init_script'" Include prepare Env OCF_RESKEY_nfs_init_script=no_such_script AgentRun start OCF_ERR_INSTALLED CASE "check base env: unset 'OCF_RESKEY_nfs_ip'" Include prepare Unenv OCF_RESKEY_nfs_ip AgentRun start OCF_ERR_CONFIGURED CASE "check base env: unset 'OCF_RESKEY_nfs_shared_infodir'" Include prepare Unenv OCF_RESKEY_nfs_shared_infodir AgentRun start OCF_ERR_CONFIGURED CASE "check base env: invalid 'OCF_RESKEY_nfs_notify_cmd'" Include prepare Env OCF_RESKEY_nfs_notify_cmd=no_such_program AgentRun start OCF_ERR_INSTALLED CASE "normal start" Include prepare AgentRun start OCF_SUCCESS CASE "normal stop" Include prepare AgentRun start AgentRun stop OCF_SUCCESS CASE "double start" Include prepare AgentRun start AgentRun start OCF_SUCCESS CASE "double stop" Include prepare AgentRun stop OCF_SUCCESS CASE "monitor with running" Include prepare AgentRun start AgentRun monitor OCF_SUCCESS CASE "monitor with not running" Include prepare AgentRun monitor OCF_NOT_RUNNING CASE "unimplemented command" Include prepare AgentRun no_cmd OCF_ERR_UNIMPLEMENTED diff --git a/tools/ocft/ocft.in b/tools/ocft/ocft.in index c286b52a8..4be27b9ce 100644 --- a/tools/ocft/ocft.in +++ b/tools/ocft/ocft.in @@ -1,780 +1,796 @@ #!/bin/bash # Copyright (c) 2010-2011 Novell Inc, John Shi # All Rights Reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License as # published by the Free Software Foundation. # # This program is distributed in the hope that it would be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # # Further, this software is distributed without any warranty that it is # free of the rightful claim of any third person regarding infringement # or the like. Any license provided herein, whether implied or # otherwise, applies only to this software file. Patent licenses, if # any, provided herein do not apply to combinations of this program with # other software, or any other product whatsoever. # # You should have received a copy of the GNU General Public License # along with this program; if not, write the Free Software Foundation, # Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. die() { local str str="$1" echo "ERROR: $str" >&2 exit 1 } warn() { local str str="$1" echo "WARNING: $str" >&2 } parse_die() { local str str="$1" die "${agent}: line ${line_num}: ${str}" } # add quotes to string for Here Documents add_quotes() { local typ str a b typ="$1" str="$2" case "$typ" in 1) a=\'; b=\";; 2) a=\"; b=\';; esac echo "$str" | sed "s/$a/$a$b$a$b$a/g; 1 s/^/$a/; $ s/$/$a/" } # split strings explode() { local str str="$1" echo "$str" | awk -F'"' '{ if (NF > 0 && NF%2 == 0) exit(1); for (i=1; i<=NF; i++) { if (i%2 == 0) print $i; else { len = split($i, str, /[ \t]+/); for (j=1; j<=len; j++) { sb = sub(/#.*/, "", str[j]); if (str[j] != "") print str[j]; if (sb) exit(0); } } } }' } # phase 1: parse the string to 'command' and 'argument collection'. line2trunk() { trunk[0]="${line%%[[:blank:]]*}" trunk[1]="${line#*[[:blank:]]}" } # phase 2: split the argument collection. trunk2branch() { local IFS # Some of statements need one parameter at least. if [ "$line" = "${trunk[0]}" ]; then parse_die "missing parameter." fi IFS=$'\n' branch=($(explode "${trunk[1]}")) if [ $? -ne 0 ]; then parse_die "missing '\"'." fi } preparse_cfg() { local agent line trunk branch macro num host agent="$1" if [ ! -r "$opt_cfgsdir/$agent" ]; then die "${agent}: configuration file not found." fi line_num=0 while read -r line; do let line_num++ num=" $line_num" case "$line" in ""|\#*) continue;; esac line2trunk case "${trunk[0]}" in CASE-BLOCK) trunk2branch macro="$CASES_DIR/${agent}_macro.${branch[0]}" continue ;; Include|Include@*) host=$(echo "${trunk[0]}" | awk -F@ '{print $2}') trunk2branch if [ ! -r "$CASES_DIR/${agent}_macro.${branch[0]}" ]; then parse_die "Macro '${branch[0]}' not found." fi if [ -n "$host" ]; then line="$(sed -e 's/^\([^[:blank:]]*\)@[^[:blank:]]*/\1/' -e "s/^[^[:blank:]]*/&@$host/" "$CASES_DIR/${agent}_macro.${branch[0]}")" else line="$(<"$CASES_DIR/${agent}_macro.${branch[0]}")" fi num= ;; *[!A-Z-]*) : ;; *) macro= ;; esac if [ -n "$macro" ]; then echo "$line$num" >>"$macro" else echo "$line$num" >>"$CASES_DIR/${agent}_preparse" fi done <"$opt_cfgsdir/$agent" } case_finish() { local host if [ -n "$sh" ]; then cat >>$sh <>$sh done echo "quit 0" >>$sh fi atexit_num=0 hosts= sh= } agent_finish() { rm -f $CASES_DIR/${agent}_preparse rm -f $CASES_DIR/${agent}_macro.* rm -f $CASES_DIR/${agent}_setup rm -f $CASES_DIR/${agent}_cleanup rm -f $CASES_DIR/${agent}_var rm -f $CASES_DIR/${agent}_hosts + cfg_agent= cfg_agent_root= cfg_install_package=() cfg_hang_timeout=20 } parse_cfg() { local agents i line stat sh trunk branch atexit_num host hosts if [ $# -eq 0 ]; then agents=($opt_cfgsdir/*) else agents=("$@") fi for agent in "${agents[@]}"; do rm -f $CASES_DIR/*_${agent}.sh agent_finish i=0 agent="$(basename "$agent")" echo "Making '$agent': " preparse_cfg "$agent" while read -r line; do line_num="${line##* }" line="${line% *}" line2trunk # state switch case "${trunk[0]}" in CONFIG) case_finish stat=1 continue ;; VARIABLE) case_finish stat=2 continue ;; SETUP-AGENT) case_finish stat=3 continue ;; CLEANUP-AGENT) case_finish stat=4 continue ;; CASE) case_finish trunk2branch echo " - case ${i}: ${branch[0]}" sh="$CASES_DIR/${i}_${agent}.sh" cat >$sh <>$CASES_DIR/${agent}_var ;; 3) echo "$line" >>$CASES_DIR/${agent}_setup ;; 4) echo "$line" >>$CASES_DIR/${agent}_cleanup ;; 5) host=$(echo ${trunk[0]} | awk -F@ '{print $2}') if [ -n "$host" ]; then if ! echo "$hosts" | grep -q "$host"; then echo "$host" >>$CASES_DIR/${agent}_hosts hosts=$hosts$'\n'$host cat >>$sh <>$sh if [ -n "$host" ]; then echo "backbash $host <<'CMD'" >>$sh fi case "${trunk[0]}" in Env|Env@*) cat >>$sh <>$sh <>$sh <>$sh <>$sh <>$sh <>$sh <>$sh <>$sh <>$sh fi ;; *) parse_die "unimplemented statement: ${trunk[0]}" ;; esac done <$CASES_DIR/${agent}_preparse if [ -r "$CASES_DIR/${agent}_setup" ]; then cat >$CASES_DIR/setup_${agent}.sh <>$CASES_DIR/setup_${agent}.sh <>$CASES_DIR/setup_${agent}.sh <$CASES_DIR/cleanup_${agent}.sh <>$CASES_DIR/cleanup_${agent}.sh <>$CASES_DIR/cleanup_${agent}.sh </dev/null 2>&1; then die "cases directory not found." fi export __OCFT__VERBOSE=$opt_verbose if [ $# -eq 0 ]; then agents=($(ls -1 *.sh 2>/dev/null | sed 's/.*_\([^_]*\)\.sh$/\1/' | sort | uniq)) else agents=("$@") fi for shs in "${agents[@]}"; do testsh="setup_${shs}.sh $(ls -1 [0-9]*_${shs}.sh 2>/dev/null | sort -n) cleanup_${shs}.sh" for sh in $testsh; do if [ -r "$sh" ]; then ./$sh ret=$? if [ $ret -eq 3 ]; then die "core function failed, break all tests." fi if [ $ret -eq 2 ]; then warn "core function failed, break all tests of '$shs'." break fi fi done done 2>&1 | while read -r line; do echo "$line" echo "$(date '+%F %T'): $line" | cat -A | sed -r 's/\^\[\[[0-9]+m|\^I|.$//g' >>ocft.log done } delete_cases() { local shs if [ $# -eq 0 ]; then rm -f $CASES_DIR/*.sh else for shs in "$@"; do rm -f $CASES_DIR/*_${shs}.sh done fi } usage() { cat < DONE # * /usr/sbin/ocf-tester -n post2 -o binary="/usr/sbin/postfix" \ # -o config_dir="" /usr/lib/ocf/resource.d/heartbeat/postfix; echo $? -> DONE # * /usr/sbin/ocf-tester -n post3 -o binary="/usr/sbin/postfix" \ # -o config_dir="/etc/postfix" /usr/lib/ocf/resource.d/heartbeat/postfix; echo $? -> DONE # * /usr/sbin/ocf-tester -n post4 -o binary="/usr/sbin/postfix" \ # -o config_dir="/root/postfix/" /usr/lib/ocf/resource.d/heartbeat/postfix; echo $? CONFIG - #AgentRoot /usr/lib/ocf/resource.d/heartbeat + Agent postfix + AgentRoot /usr/lib/ocf/resource.d/heartbeat InstallPackage postfix HangTimeout 20 SETUP-AGENT # nothing CASE-BLOCK crm_setting Env OCF_RESKEY_CRM_meta_timeout=15000 Env OCF_RESKEY_CRM_meta_interval=10000 CASE-BLOCK default_status AgentRun stop CASE-BLOCK prepare Include crm_setting Include default_status CASE "check base env" Include prepare AgentRun start OCF_SUCCESS CASE "check base env: invalid 'OCF_RESKEY_binary'" Include prepare Env OCF_RESKEY_binary=no_such AgentRun start OCF_ERR_INSTALLED CASE "check base env: invalid 'OCF_RESKEY_config_dir'" Include prepare Env OCF_RESKEY_config_dir=no_such AgentRun start OCF_ERR_INSTALLED CASE "check base env: 'OCF_RESKEY_binary'" Include prepare Env OCF_RESKEY_binary=/usr/sbin/postfix AgentRun start AgentRun monitor OCF_SUCCESS CASE "check base env: 'OCF_RESKEY_config_dir' without trailing slash" Include prepare Env OCF_RESKEY_config_dir="/etc/postfix" AgentRun start AgentRun monitor OCF_SUCCESS CASE "check base env: 'OCF_RESKEY_config_dir' with trailing slash" Include prepare Env OCF_RESKEY_config_dir="/etc/postfix/" AgentRun start AgentRun monitor OCF_SUCCESS CASE "normal start" Include prepare AgentRun start OCF_SUCCESS CASE "normal stop" Include prepare AgentRun start AgentRun stop OCF_SUCCESS CASE "double start" Include prepare AgentRun start AgentRun start OCF_SUCCESS CASE "double stop" Include prepare AgentRun stop OCF_SUCCESS CASE "monitor a running resource" Include prepare AgentRun start AgentRun monitor OCF_SUCCESS CASE "(initial) probe a stopped resource" Include prepare Env OCF_RESKEY_CRM_meta_interval=0 AgentRun monitor OCF_NOT_RUNNING CASE "(re-)probe a running resource" Include prepare Env OCF_RESKEY_CRM_meta_interval=0 AgentRun start AgentRun monitor OCF_SUCCESS CASE "unimplemented command" Include prepare AgentRun no_cmd OCF_ERR_UNIMPLEMENTED