diff --git a/tools/ocft/ChangeLog b/tools/ocft/ChangeLog index 3ae2c1b23..97559820d 100644 --- a/tools/ocft/ChangeLog +++ b/tools/ocft/ChangeLog @@ -1,49 +1,54 @@ +0.43: + - 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 bbf21d306..65cab5831 100644 --- a/tools/ocft/Filesystem +++ b/tools/ocft/Filesystem @@ -1,114 +1,109 @@ # Filesystem # by dejan@suse.de on # Tue Feb 15 18:50:04 CET 2011 CONFIG #AgentRoot /usr/lib/ocf/resource.d/heartbeat HangTimeout 20 -CASE-BLOCK tempvars - Var OCFT_fs=/var/run/resource-agents/ocft-Filesystem-fs - Var OCFT_loop=/dev/loop0 - Var OCFT_dir=/var/run/resource-agents/ocft-Filesystem-mnt - -CASE-BLOCK required_args - Include tempvars - Var OCF_RESKEY_device=$OCFT_loop - Var OCF_RESKEY_fstype=ext2 - Var OCF_RESKEY_directory=$OCFT_dir - -SETUP-AGENT +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 - Var OCF_RESKEY_device=/dev/no_such_device + Env OCF_RESKEY_device=/dev/no_such_device AgentRun start OCF_ERR_INSTALLED CASE "check base env: unset 'OCF_RESKEY_device'" Include prepare - Unvar OCF_RESKEY_device + 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 - Var OCF_CHECK_LEVEL=10 + Env OCF_CHECK_LEVEL=10 AgentRun monitor OCF_SUCCESS CASE "monitor depth 20 with running" Include prepare AgentRun start - Var OCF_CHECK_LEVEL=20 + 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 - Var OCF_CHECK_LEVEL=20 + Env OCF_CHECK_LEVEL=20 AgentRun monitor OCF_ERR_GENERIC CASE "unimplemented command" Include prepare AgentRun no_cmd OCF_ERR_UNIMPLEMENTED -CASE "meta-data and cleanup" - Include prepare - Bash rmdir $OCFT_dir - Bash rm $OCFT_fs - Bash losetup -d $OCFT_loop - AgentRun meta-data OCF_SUCCESS diff --git a/tools/ocft/IPaddr2 b/tools/ocft/IPaddr2 index e4ff6972d..3a0c3ea5a 100644 --- a/tools/ocft/IPaddr2 +++ b/tools/ocft/IPaddr2 @@ -1,91 +1,91 @@ # IPaddr2 CONFIG #AgentRoot /usr/lib/ocf/resource.d/heartbeat InstallPackage iproute2 HangTimeout 20 CASE-BLOCK required_args - Var OCF_RESKEY_ip=127.0.0.3 + 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 - Unvar OCF_RESKEY_ip + Unenv OCF_RESKEY_ip AgentRun start OCF_ERR_CONFIGURED CASE "check base env: set invalid 'OCF_RESKEY_ip'" Include prepare - Var OCF_RESKEY_ip=not_ip_address + Env OCF_RESKEY_ip=not_ip_address AgentRun start OCF_ERR_CONFIGURED CASE "check base env: set 'OCF_RESKEY_cidr_netmask'" Include prepare - Var OCF_RESKEY_cidr_netmask=8 + Env OCF_RESKEY_cidr_netmask=8 AgentRun start OCF_SUCCESS CASE "check base env: set invalid 'OCF_RESKEY_cidr_netmask'" Include prepare - Var OCF_RESKEY_cidr_netmask=not_netmask + Env OCF_RESKEY_cidr_netmask=not_netmask AgentRun start OCF_ERR_CONFIGURED CASE "check base env: set 'OCF_RESKEY_broadcast'" Include prepare - Var OCF_RESKEY_broadcast=127.255.255.255 + Env OCF_RESKEY_broadcast=127.255.255.255 AgentRun start OCF_SUCCESS CASE "check base env: set invalid 'OCF_RESKEY_broadcast'" Include prepare - Var OCF_RESKEY_broadcast=not_broadcast + Env OCF_RESKEY_broadcast=not_broadcast AgentRun start OCF_ERR_CONFIGURED CASE "check base env: set 'OCF_RESKEY_nic'" Include prepare - Var OCF_RESKEY_nic=lo + Env OCF_RESKEY_nic=lo AgentRun start OCF_SUCCESS CASE "check base env: set invalid 'OCF_RESKEY_nic'" Include prepare - Var OCF_RESKEY_nic=not_nic + 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 51434a454..cf3145b26 100644 --- a/tools/ocft/IPsrcaddr +++ b/tools/ocft/IPsrcaddr @@ -1,61 +1,61 @@ # IPsrcaddr CONFIG #AgentRoot /usr/lib/ocf/resource.d/heartbeat InstallPackage iproute2 HangTimeout 20 CASE-BLOCK required_args - Var OCF_RESKEY_ipaddress=127.0.0.3 + 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 - Unvar OCF_RESKEY_ipaddress + Unenv OCF_RESKEY_ipaddress AgentRun start OCF_ERR_CONFIGURED CASE "check base env: set invalid 'OCF_RESKEY_ipaddress'" Include prepare - Var OCF_RESKEY_ipaddress=not_ip_address + 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 99354858b..e5a41a4a6 100644 --- a/tools/ocft/LVM +++ b/tools/ocft/LVM @@ -1,91 +1,84 @@ # LVM # by dejan@suse.de on # Wed Feb 16 13:15:01 CET 2011 CONFIG #AgentRoot /usr/lib/ocf/resource.d/heartbeat HangTimeout 20 -CASE-BLOCK tempvars - Var OCFT_pv=/var/run/resource-agents/ocft-LVM-pv - Var OCFT_vg=ocft-vg - Var OCFT_lv=ocft-lv - Var OCFT_loop=/dev/loop0 - -CASE-BLOCK required_args - Include tempvars - Var OCF_RESKEY_volgrpname=$OCFT_vg - -SETUP-AGENT +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 - Var OCF_RESKEY_volgrpname=/dev/no_such_device + Env OCF_RESKEY_volgrpname=/dev/no_such_device AgentRun start OCF_ERR_GENERIC CASE "check base env: unset 'OCF_RESKEY_volgrpname'" Include prepare - Unvar OCF_RESKEY_volgrpname + 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 -CASE "meta-data and cleanup" - Include prepare - Bash vgchange -an $OCFT_vg - Bash lvremove -f /dev/$OCFT_vg/$OCFT_lv - Bash vgremove -f $OCFT_vg - Bash losetup -d $OCFT_loop - Bash rm $OCFT_pv - Bash rm /tmp/.LVM_set - AgentRun meta-data OCF_SUCCESS diff --git a/tools/ocft/MailTo b/tools/ocft/MailTo index 9031c5102..f9beae268 100644 --- a/tools/ocft/MailTo +++ b/tools/ocft/MailTo @@ -1,56 +1,56 @@ # MailTo CONFIG #AgentRoot /usr/lib/ocf/resource.d/heartbeat InstallPackage mailx HangTimeout 20 CASE-BLOCK required_args - Var OCF_RESKEY_email=root@localhost + 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 - Unvar OCF_RESKEY_email + 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 8d69a5dd6..3f6e16ac3 100644 --- a/tools/ocft/README.in +++ b/tools/ocft/README.in @@ -1,126 +1,141 @@ 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 4 top level options that are all spelled by capital letters and "-". + - 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. ** '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. The initialization will only be executed once, if you want to reinitialize it, - you can manually delete the flag file at /tmp/.[AGENT_NAME]_set. + - 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". - ** 'Var' (sub-option) - - Grammar: Var VARIABLE=value + ** '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 "=". - ** 'Unvar' (sub-option) - - Grammer: Unvar VARIABLE [VARIABLE2 [...]] + ** '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 3d0893779..65dac0482 100644 --- a/tools/ocft/README.zh_CN.in +++ b/tools/ocft/README.zh_CN.in @@ -1,102 +1,118 @@ 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 配置 -只有四个top level option,它们是由大写字母和'-'构成的,每个top level option都有若干sub-option, +只有6个top level option,它们是由大写字母和'-'构成的,每个top level option都有若干sub-option, 它们是首字母大写。 2.1 'CONFIG' 选项 语法:CONFIG 此option中的设计是全局的,对每个test case都有所影响。 2.1.1 'AgentRoot' 选项 语法:AgentRoot /usr/lib/ocf/resource.d/xxx 一些agent将会被移到 "pacemaker" 或 "linbit" 目录,如果你定义了这个选项,ocft将会用它来 替代默认的目录"heartbeat"。 2.1.1 'InstallPackage' 选项 语法:InstallPackage package [package2 [...]] 他会检测系统是否安装了此resource agent的service,如果没有安装,会自动从网络进行安装。 package_name是某个resouce agent在操作系统中必须安装的包。 2.1.2 'HangTimeout' 选项 语法:HangTimeout secs 如果你更改了一些很关键的东西,有些resouce agent会不知所措,停在那里不动,那么就会影响 到后面test case的运行,所以你需要设定超时,如果一旦resouce agent停在那超时了,脚本会 杀死这个resouce agent。 -2.2 'SETUP-AGENT' 选项 +2.2 'VARIABLE' 选项 +语法: +VARIABLE + VAR1=value1 + VAR2=value2 + ... +在此定义全局变量,这些变量可以用于配置文件中的任何地方,引用时在变量名前加上$。请注意,这些 +变量不同于Env定义的变量,Env是定义环境变量,可以改变agent的行为,而这些变量只是用于配置文件中 +共享。 + +2.3 'SETUP-AGENT' 选项 语法: SETUP-AGENT bash scripts... ... -一些Agent在测试前可能需要初始化,你可以用bash脚本在这初始化。初始化动作只会被执行一次, -如果你想要再次执行,你可以手动删除标志文件 /tmp/.[AGENT_NAME]_set。 +一些Agent在测试前可能需要初始化,你可以用bash脚本在这初始化。 + +2.4 'CLEANUP-AGENT' 选项 +语法: +CLEANUP-AGENT + bash scripts... + ... +如果之前定义了SETUP-AGENT, 你可能还需要此选项在测试完后来作一些清除。 -2.3 'CASE' & 'CASE-BLOCK' 选项 +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.3.1 'Var' 选项 -语法:Var VARIABLE=value +2.5.1 'Env' 选项 +语法:Env VARIABLE=value 这是设置resouce agent的环境变量,他们通常是OCF_RESKEY_xxx,注意=号两边不要有空格。 -2.3.2 'Unvar' 选项 -语法:Unvar VARIABLE +2.5.2 'Unenv' 选项 +语法:Unenv VARIABLE 此选项用于删除环境变量。 -2.3.3 'Include' 选项 +2.5.3 'Include' 选项 语法:Include macro_name 此选项将会被宏"macro_name"的内容所替代,当然,你得预先用"CASE-BLOCK"来定义宏"macro_name" 的内容。 -2.3.4 'Bash' 选项 +2.5.4 'Bash' 选项 语法:Bash bash_codes 此选项是用来设置os的环境,你可以嵌入bash代码来对系统作任意设置,不过要注意不要对系统造成 不可恢复的后果就行了。 -2.3.5 'BashAtExit' 选项 +2.5.5 'BashAtExit' 选项 语法:BashAtExit bash_codes 此选项是用来恢复os的环境,以便另一个test case能正常运行,当然你也可以直接用'Bash'选项来 恢复,但是如果脚本在执行过程中产生某些错误,那么脚本会直接退出,而不会去执行你的恢复代码, 那么你就要用到BashAtExit,他能在你退出前去恢复系统环境。 -2.3.6 'RunAgent' 选项 +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 448d6d4d8..ee46e3941 100644 --- a/tools/ocft/SendArp +++ b/tools/ocft/SendArp @@ -1,72 +1,72 @@ # SendArp CONFIG #AgentRoot /usr/lib/ocf/resource.d/heartbeat InstallPackage resource-agents HangTimeout 15 CASE-BLOCK required_args - Var OCF_RESKEY_ip=127.0.0.1 - Var OCF_RESKEY_nic=lo + 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 - Unvar OCF_RESKEY_ip + Unenv OCF_RESKEY_ip AgentRun start OCF_ERR_ARGS CASE "check base env: set worng 'OCF_RESKEY_ip'" Include prepare - Var OCF_RESKEY_ip=not_ip_address + Env OCF_RESKEY_ip=not_ip_address AgentRun start OCF_ERR_ARGS CASE "check base env: unset 'OCF_RESKEY_nic'" Include prepare - Unvar OCF_RESKEY_nic + Unenv OCF_RESKEY_nic AgentRun start OCF_ERR_ARGS CASE "check base env: set worng 'OCF_RESKEY_nic'" Include prepare - Var OCF_RESKEY_nic=not_nic + 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 dc8ca2652..f444d5103 100644 --- a/tools/ocft/apache +++ b/tools/ocft/apache @@ -1,66 +1,66 @@ # apache CONFIG #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 - Var OCF_RESKEY_statusurl=http://localhost/info2html.css - Var OCF_RESKEY_testregex='This is' + 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 - Unvar OCF_RESKEY_statusurl + Unenv OCF_RESKEY_statusurl AgentRun start OCF_ERR_CONFIGURED CASE "check base env: unset OCF_RESKEY_testregex" Include prepare - Unvar OCF_RESKEY_testregex + 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 ab464f64a..0617bfd64 100644 --- a/tools/ocft/caselib.in +++ b/tools/ocft/caselib.in @@ -1,307 +1,293 @@ # -# Copyright (c) 2010 Novell Inc, John Shi +# 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 [ $atexit_num -gt 0 ]; do - atexit$atexit_num - let atexit_num-- + while [ $__OCFT__atexit_num -gt 0 ]; do + atexit$__OCFT__atexit_num + let __OCFT__atexit_num-- done - rm -rf $fakebin + 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 -n "${showhost}Installing $pkg ..." + 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 "${showhost}ERROR: Install '$pkg' failed, break this case." + 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 -n "${showhost}Installing $pkg ..." + 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 "${showhost}ERROR: Install '$pkg' failed, break this case." + 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 -n "${showhost}Installing $pkg ..." + echo "${__OCFT__showhost}Installing $pkg ..." yum -y install "$pkg" >/dev/null 2>&1 if ! rpm -ql "$pkg" >/dev/null 2>&1; then echo - echo "${showhost}ERROR: Install '$pkg' failed, break this case." + echo "${__OCFT__showhost}ERROR: Install '$pkg' failed." quit 2 fi echo "done" echo fi else - echo "${showhost}ERROR: Cannot detect your OS type, break this case." + echo "${__OCFT__showhost}ERROR: Cannot detect your OS type." quit 2 fi done } -agent_setup() -{ - local agent - agent="$1" - - if [ ! -e "/tmp/.${agent}_set" ]; then - touch "/tmp/.${agent}_set" - echo -n "${showhost}Initialing ${agent}..." - bash >/dev/null - echo "done" - echo - fi -} - agent_run() { local agent cmd timeout pid i ret aroot agent="$1" cmd="$2" timeout="$3" - aroot=${MYROOT:-$AGENT_ROOT} + 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 "${showhost}ERROR: The agent was hanging, killed it, " - echo "maybe you damaged the agent or system's environment, break this CASE." + echo -n "${__OCFT__showhost}ERROR: The agent was hanging, killed it, " + echo "maybe you damaged the agent or system's environment." echo quit 1 fi wait $pid } check_success() { local ret msg ret="$1" msg="$2" if [ $ret -ne 0 ]; then - echo "${showhost}ERROR: '${msg}' failed, the return code is ${ret}, break this CASE." + 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 "$CASES_DIR" ]; then - echo "${showhost}ERROR: Could not found Directory: ${CASES_DIR}." + if [ ! -d "$__OCFT__CASES_DIR" ]; then + echo "${__OCFT__showhost}ERROR: Could not found Directory: ${__OCFT__CASES_DIR}." quit 1 fi - if lsof $CASES_DIR/${host}_r $CASES_DIR/${host}_w >/dev/null 2>&1; then - echo "${showhost}ERROR: Connection exist with $host, break this CASE." + 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 "$CASES_DIR/${host}_r" ] || [ ! -p "$CASES_DIR/${host}_w" ]; then - rm -f $CASES_DIR/${host}_r $CASES_DIR/${host}_w - if ! mkfifo $CASES_DIR/${host}_r $CASES_DIR/${host}_w >/dev/null 2>&1; then - echo "${showhost}ERROR: Could not create pipe file: $CASES_DIR/${host}_*, break this CASE." + 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' >$CASES_DIR/${host}_r <$CASES_DIR/${host}_w & + 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}<$CASES_DIR/${host}_r ${wfd}>$CASES_DIR/${host}_w" + 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 "${showhost}ERROR: Could not found connection with $host, break this CASE." + 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 "${showhost}ERROR: Broken connection with $host, break this CASE." + 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 "${showhost}ERROR: Broken connection with $host, break this CASE." + 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 $CASES_DIR/${host}_r $CASES_DIR/${host}_w + 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 -AGENT_ROOT=@OCF_RA_DIR@/heartbeat -CASES_DIR=/var/lib/@PACKAGE_NAME@/ocft/cases +__OCFT__AGENT_ROOT=@OCF_RA_DIR@/heartbeat +__OCFT__CASES_DIR=/var/lib/@PACKAGE_NAME@/ocft/cases -atexit_num=0 +__OCFT__atexit_num=0 if [ $EUID -ne 0 ]; then - echo "${showhost}ERROR: '$0' needs to be run by root, break this CASE." + echo "${__OCFT__showhost}ERROR: '$0' needs to be run by root." quit 3 fi -fakebin=./fakebin +__OCFT__fakebin=./fakebin -mkdir -p $fakebin >/dev/null 2>&1 && -ln -sf /bin/true $fakebin/crm_master >/dev/null 2>&1 && -ln -sf /bin/true $fakebin/crm_mon >/dev/null 2>&1 +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 "${showhost}ERROR: initialize 'fakebin' failed, break this CASE." + echo "${__OCFT__showhost}ERROR: initialize 'fakebin' failed." quit 3 fi -export HA_SBIN_DIR=$fakebin +export HA_SBIN_DIR=$__OCFT__fakebin . $OCF_LIB/ocf-returncodes || { - echo "${showhost}ERROR: $OCF_LIB/ocf-returncodes not found, break this CASE." + echo "${__OCFT__showhost}ERROR: $OCF_LIB/ocf-returncodes not found." quit 3 } -while read line; do - if [ -n "$line" ]; then - retn=${line%%=*} - reti=$(eval echo \$$retn) - retval[reti]=$retn +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 4bcd23ab1..9b693508e 100644 --- a/tools/ocft/db2 +++ b/tools/ocft/db2 @@ -1,162 +1,162 @@ # 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 HangTimeout 40 SETUP-AGENT # nothing CASE-BLOCK set_testenv - Var OCFT_instance=db2inst1 - Var OCFT_db=ocft + Env OCFT_instance=db2inst1 + Env OCFT_db=ocft CASE-BLOCK crm_setting - Var OCF_RESKEY_instance=$OCFT_instance - Var OCF_RESKEY_CRM_meta_timeout=30000 + 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 - Var OCF_RESKEY_instance=no_such + 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 - Var OCF_RESKEY_instance=no_such - Var OCF_RESKEY_admin=$OCFT_instance + 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 - Var OCF_RESKEY_dbpartitionnum=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 - Var OCF_RESKEY_dbpartitionnum=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 fea6f74c0..0b09a2535 100644 --- a/tools/ocft/iscsi +++ b/tools/ocft/iscsi @@ -1,86 +1,81 @@ # iscsi CONFIG #AgentRoot /usr/lib/ocf/resource.d/heartbeat InstallPackage open-iscsi InstallPackage iscsitarget HangTimeout 20 -CASE-BLOCK tempvars - Var OCFT_disk=/var/run/resource-agents/ocft-iscsi - Var OCFT_target="iqn.2011-03.ocft.localhost:disk0" - Var OCFT_portal="127.0.0.1:3260" - -CASE-BLOCK required_args - Include tempvars - Var OCF_RESKEY_portal=$OCFT_portal - Var OCF_RESKEY_target=$OCFT_target - -SETUP-AGENT +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 - Unvar OCF_RESKEY_portal + Unenv OCF_RESKEY_portal AgentRun start OCF_ERR_CONFIGURED CASE "check base env: unset 'OCF_RESKEY_target'" Include prepare - Unvar OCF_RESKEY_target + 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 -CASE "meta-data and cleanup" - Include prepare - Bash rm -f $OCFT_disk - Bash sed -i "/^Target $OCFT_target/,+1d" /etc/ietd.conf - AgentRun meta-data OCF_SUCCESS diff --git a/tools/ocft/mysql b/tools/ocft/mysql index 6cb5dffc4..f0b475ed7 100644 --- a/tools/ocft/mysql +++ b/tools/ocft/mysql @@ -1,76 +1,76 @@ # mysql CONFIG #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 - Var OCF_RESKEY_CRM_meta_timeout=15000 + 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 - Var OCF_RESKEY_binary=no_such + 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 - Var OCF_RESKEY_user=no_user + Env OCF_RESKEY_user=no_user AgentRun start OCF_ERR_INSTALLED CASE "invalid user" Include prepare - Var OCF_RESKEY_user=nobody + Env OCF_RESKEY_user=nobody AgentRun start OCF_ERR_PERM diff --git a/tools/ocft/named b/tools/ocft/named index 7785eba9f..c1f46249e 100644 --- a/tools/ocft/named +++ b/tools/ocft/named @@ -1,66 +1,66 @@ #named # To work properly this test requires that standard bind and bin-utils # packages installed. CONFIG InstallPackage bind InstallPackage bind-utils SETUP-AGENT /etc/init.d/named start /etc/init.d/named stop CASE-BLOCK crm_setting - Var OCF_RESKEY_CRM_meta_timeout=15000 + 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 - Var OCF_RESKEY_named=no_such + 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 - Var OCF_RESKEY_named_user=no_user + Env OCF_RESKEY_named_user=no_user AgentRun start OCF_ERR_INSTALLED diff --git a/tools/ocft/nfsserver b/tools/ocft/nfsserver index bd7d47bfa..2fa905fb8 100644 --- a/tools/ocft/nfsserver +++ b/tools/ocft/nfsserver @@ -1,74 +1,74 @@ # nfsserver CONFIG #AgentRoot /usr/lib/ocf/resource.d/heartbeat InstallPackage nfs-kernel-server HangTimeout 20 CASE-BLOCK required_args - Var OCF_RESKEY_nfs_init_script=/etc/init.d/nfsserver - Var OCF_RESKEY_nfs_ip=127.0.0.1 - Var OCF_RESKEY_nfs_shared_infodir=/var/lib/nfs - Var OCF_RESKEY_nfs_notify_cmd=/usr/sbin/sm-notify + 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 - Var OCF_RESKEY_nfs_init_script=no_such_script + 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 - Unvar OCF_RESKEY_nfs_ip + Unenv OCF_RESKEY_nfs_ip AgentRun start OCF_ERR_CONFIGURED CASE "check base env: unset 'OCF_RESKEY_nfs_shared_infodir'" Include prepare - Unvar OCF_RESKEY_nfs_shared_infodir + Unenv OCF_RESKEY_nfs_shared_infodir AgentRun start OCF_ERR_CONFIGURED CASE "check base env: invalid 'OCF_RESKEY_nfs_notify_cmd'" Include prepare - Var OCF_RESKEY_nfs_notify_cmd=no_such_program + 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 c9e788ec9..c286b52a8 100644 --- a/tools/ocft/ocft.in +++ b/tools/ocft/ocft.in @@ -1,666 +1,780 @@ #!/bin/bash -# Copyright (c) 2010 Novell Inc, John Shi +# 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 - rm -f $CASES_DIR/${agent}_macro.* - rm -f $CASES_DIR/${agent}.preparse - 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 - if ! touch "$macro"; then - die "No permission to create macro file: ${macro}." - fi echo "$line$num" >>"$macro" else - echo "$line$num" >>"$CASES_DIR/${agent}.preparse" + echo "$line$num" >>"$CASES_DIR/${agent}_preparse" fi done <"$opt_cfgsdir/$agent" - - rm -f $CASES_DIR/${agent}_macro.* } 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_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")" - rm -f $CASES_DIR/*_${agent}.sh - rm -f $CASES_DIR/${agent}_setup 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 ;; - SETUP-AGENT) + VARIABLE) case_finish stat=2 continue ;; + SETUP-AGENT) + case_finish + stat=3 + continue + ;; + CLEANUP-AGENT) + case_finish + stat=4 + continue + ;; CASE) case_finish trunk2branch - sh="$CASES_DIR/${i}_${agent}.sh" echo " - case ${i}: ${branch[0]}" + sh="$CASES_DIR/${i}_${agent}.sh" cat >$sh <>$sh <>$sh <>$sh <>$CASES_DIR/${agent}_setup + if echo "$line" | grep -q '^__OCFT__'; then + parse_die "reserved key word '__OCFT__'." + fi + echo "declare $line" >>$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 <>$sh <>$sh fi fi echo " # CASE statement: $line" >>$sh if [ -n "$host" ]; then echo "backbash $host <<'CMD'" >>$sh fi case "${trunk[0]}" in - Var|Var@*) + 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 - rm -f $CASES_DIR/${agent}.preparse - rm -f $CASES_DIR/${agent}_setup + 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 + 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 - for sh in $(ls -1 *_${shs}.sh 2>/dev/null | sort -n); do - ./$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 + 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 | while read -r line; do + 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 InstallPackage postfix HangTimeout 20 SETUP-AGENT # nothing CASE-BLOCK crm_setting - Var OCF_RESKEY_CRM_meta_timeout=15000 - Var OCF_RESKEY_CRM_meta_interval=10000 + 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 - Var OCF_RESKEY_binary=no_such + Env OCF_RESKEY_binary=no_such AgentRun start OCF_ERR_INSTALLED CASE "check base env: invalid 'OCF_RESKEY_config_dir'" Include prepare - Var OCF_RESKEY_config_dir=no_such + Env OCF_RESKEY_config_dir=no_such AgentRun start OCF_ERR_INSTALLED CASE "check base env: 'OCF_RESKEY_binary'" Include prepare - Var OCF_RESKEY_binary=/usr/sbin/postfix + 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 - Var OCF_RESKEY_config_dir="/etc/postfix" + 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 - Var OCF_RESKEY_config_dir="/etc/postfix/" + 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 - Var OCF_RESKEY_CRM_meta_interval=0 + Env OCF_RESKEY_CRM_meta_interval=0 AgentRun monitor OCF_NOT_RUNNING CASE "(re-)probe a running resource" Include prepare - Var OCF_RESKEY_CRM_meta_interval=0 + Env OCF_RESKEY_CRM_meta_interval=0 AgentRun start AgentRun monitor OCF_SUCCESS CASE "unimplemented command" Include prepare AgentRun no_cmd OCF_ERR_UNIMPLEMENTED