~ubuntu-branches/ubuntu/utopic/pacemaker/utopic-proposed

« back to all changes in this revision

Viewing changes to fencing/regression.py.in

  • Committer: Package Import Robot
  • Author(s): Andres Rodriguez
  • Date: 2013-07-16 16:40:24 UTC
  • mfrom: (1.1.11) (2.2.3 experimental)
  • Revision ID: package-import@ubuntu.com-20130716164024-lvwrf4xivk1wdr3c
Tags: 1.1.9+git20130321-1ubuntu1
* Resync from debian expiremental.
* debian/control:
  - Use lower version for Build-Depends on libcorosync-dev
    and libqb-dev.
  - Build-Depends on libcfg-dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python
 
2
 
 
3
#
 
4
# This program is free software; you can redistribute it and/or
 
5
# modify it under the terms of the GNU General Public License
 
6
# as published by the Free Software Foundation; either version 2
 
7
# of the License, or (at your option) any later version.
 
8
#
 
9
# This program is distributed in the hope that it will be useful,
 
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
# GNU General Public License for more details.
 
13
#
 
14
# You should have received a copy of the GNU General Public License
 
15
# along with this program; if not, write to the Free Software
 
16
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.
 
17
 
 
18
 
 
19
import os
 
20
import sys
 
21
import subprocess
 
22
import shlex
 
23
import time
 
24
 
 
25
def output_from_command(command):
 
26
        test = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 
27
        test.wait()
 
28
 
 
29
        return test.communicate()[0].split("\n")
 
30
 
 
31
class Test:
 
32
        def __init__(self, name, description, verbose = 0, with_cpg = 0):
 
33
                self.name = name
 
34
                self.description = description
 
35
                self.cmds = []
 
36
                self.verbose = verbose
 
37
 
 
38
                self.result_txt = ""
 
39
                self.cmd_tool_output = ""
 
40
                self.result_exitcode = 0;
 
41
 
 
42
                self.stonith_options = "-s"
 
43
                self.enable_corosync = 0
 
44
 
 
45
                if with_cpg:
 
46
                        self.stonith_options = "-c"
 
47
                        self.enable_corosync = 1
 
48
 
 
49
                self.stonith_process = None
 
50
                self.stonith_output = ""
 
51
                self.stonith_patterns = []
 
52
                self.negative_stonith_patterns = []
 
53
 
 
54
                self.executed = 0
 
55
 
 
56
                rsc_classes = output_from_command("crm_resource --list-standards")
 
57
 
 
58
        def __new_cmd(self, cmd, args, exitcode, stdout_match = "", no_wait = 0, stdout_negative_match = "", kill=None):
 
59
                self.cmds.append(
 
60
                        {
 
61
                                "cmd" : cmd,
 
62
                                "kill" : kill,
 
63
                                "args" : args,
 
64
                                "expected_exitcode" : exitcode,
 
65
                                "stdout_match" : stdout_match,
 
66
                                "stdout_negative_match" : stdout_negative_match,
 
67
                                "no_wait" : no_wait,
 
68
                        }
 
69
                )
 
70
 
 
71
        def stop_pacemaker(self):
 
72
                cmd = shlex.split("killall -9 -q pacemakerd")
 
73
                test = subprocess.Popen(cmd, stdout=subprocess.PIPE)
 
74
                test.wait()
 
75
 
 
76
        def start_environment(self):
 
77
                ### make sure we are in full control here ###
 
78
                self.stop_pacemaker()
 
79
 
 
80
                cmd = shlex.split("killall -9 -q stonithd")
 
81
                test = subprocess.Popen(cmd, stdout=subprocess.PIPE)
 
82
                test.wait()
 
83
 
 
84
                if self.verbose:
 
85
                        print "Starting stonithd with %s" % self.stonith_options
 
86
 
 
87
                self.stonith_process = subprocess.Popen(
 
88
                        shlex.split("@CRM_DAEMON_DIR@/stonithd %s -V" % self.stonith_options),
 
89
                        stdout=subprocess.PIPE,
 
90
                        stderr=subprocess.PIPE)
 
91
 
 
92
                time.sleep(1)
 
93
 
 
94
        def clean_environment(self):
 
95
                if self.stonith_process:
 
96
                        self.stonith_process.terminate()
 
97
 
 
98
                self.stonith_output = self.stonith_process.communicate()[1]
 
99
                self.stonith_process = None
 
100
 
 
101
                if self.verbose:
 
102
                        print self.stonith_output
 
103
 
 
104
        def add_stonith_log_pattern(self, pattern):
 
105
                self.stonith_patterns.append(pattern)
 
106
 
 
107
        def add_stonith_negative_log_pattern(self, pattern):
 
108
                self.negative_stonith_patterns.append(pattern)
 
109
 
 
110
        def add_cmd(self, cmd, args):
 
111
                self.__new_cmd(cmd, args, 0, "")
 
112
 
 
113
        def add_cmd_no_wait(self, cmd, args):
 
114
                self.__new_cmd(cmd, args, 0, "", 1)
 
115
 
 
116
        def add_cmd_check_stdout(self, cmd, args, match, no_match = ""):
 
117
                self.__new_cmd(cmd, args, 0, match, 0, no_match)
 
118
 
 
119
        def add_expected_fail_cmd(self, cmd, args, exitcode = 255):
 
120
                self.__new_cmd(cmd, args, exitcode, "")
 
121
 
 
122
        def get_exitcode(self):
 
123
                return self.result_exitcode
 
124
 
 
125
        def print_result(self, filler):
 
126
                print "%s%s" % (filler, self.result_txt)
 
127
 
 
128
        def run_cmd(self, args):
 
129
                cmd = shlex.split(args['args'])
 
130
                cmd.insert(0, args['cmd'])
 
131
 
 
132
                if self.verbose:
 
133
                        print "\n\nRunning: "+" ".join(cmd)
 
134
                test = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 
135
 
 
136
                if args['kill']:
 
137
                        if self.verbose:
 
138
                                print "Also running: "+args['kill']
 
139
                        subprocess.Popen(shlex.split(args['kill']))
 
140
 
 
141
                if args['no_wait'] == 0:
 
142
                        test.wait()
 
143
                else:
 
144
                        return 0
 
145
 
 
146
                output_res = test.communicate()
 
147
                output = output_res[0] + output_res[1]
 
148
 
 
149
                if self.verbose:
 
150
                        print output
 
151
 
 
152
                if args['stdout_match'] != "" and output.count(args['stdout_match']) == 0:
 
153
                        test.returncode = -2
 
154
                        print "STDOUT string '%s' was not found in cmd output: %s" % (args['stdout_match'], output)
 
155
 
 
156
                if args['stdout_negative_match'] != "" and output.count(args['stdout_negative_match']) != 0:
 
157
                        test.returncode = -2
 
158
                        print "STDOUT string '%s' was found in cmd output: %s" % (args['stdout_negative_match'], output)
 
159
 
 
160
                return test.returncode;
 
161
 
 
162
 
 
163
        def count_negative_matches(self, outline):
 
164
                count = 0
 
165
                for line in self.negative_stonith_patterns:
 
166
                        if outline.count(line):
 
167
                                count = 1
 
168
                                if self.verbose:
 
169
                                        print "This pattern should not have matched = '%s" % (line)
 
170
                return count
 
171
 
 
172
        def match_stonith_patterns(self):
 
173
                negative_matches = 0
 
174
                cur = 0
 
175
                pats = self.stonith_patterns
 
176
                total_patterns = len(self.stonith_patterns)
 
177
 
 
178
                if len(self.stonith_patterns) == 0:
 
179
                        return
 
180
 
 
181
                for line in self.stonith_output.split("\n"):
 
182
                        negative_matches = negative_matches + self.count_negative_matches(line)
 
183
                        if len(pats) == 0:
 
184
                                continue
 
185
                        cur = -1
 
186
                        for p in pats:
 
187
                                cur = cur + 1
 
188
                                if line.count(pats[cur]):
 
189
                                        del pats[cur]
 
190
                                        break
 
191
 
 
192
                if len(pats) > 0 or negative_matches:
 
193
                        if self.verbose:
 
194
                                for p in pats:
 
195
                                        print "Pattern Not Matched = '%s'" % p
 
196
 
 
197
                        self.result_txt = "FAILURE - '%s' failed. %d patterns out of %d not matched. %d negative matches." % (self.name, len(pats), total_patterns, negative_matches)
 
198
                        self.result_exitcode = -1
 
199
 
 
200
        def run(self):
 
201
                res = 0
 
202
                i = 1
 
203
                self.start_environment()
 
204
 
 
205
                if self.verbose:
 
206
                        print "\n--- START TEST - %s" % self.name
 
207
 
 
208
                self.result_txt = "SUCCESS - '%s'" % (self.name)
 
209
                self.result_exitcode = 0
 
210
                for cmd in self.cmds:
 
211
                        res = self.run_cmd(cmd)
 
212
                        if res != cmd['expected_exitcode']:
 
213
                                print "Step %d FAILED - command returned %d, expected %d" % (i, res, cmd['expected_exitcode'])
 
214
                                self.result_txt = "FAILURE - '%s' failed at step %d. Command: %s %s" % (self.name, i, cmd['cmd'], cmd['args'])
 
215
                                self.result_exitcode = -1
 
216
                                break
 
217
                        else:
 
218
                                if self.verbose:
 
219
                                        print "Step %d SUCCESS" % (i)
 
220
                        i = i + 1
 
221
                self.clean_environment()
 
222
 
 
223
                if self.result_exitcode == 0:
 
224
                        self.match_stonith_patterns()
 
225
 
 
226
                print self.result_txt
 
227
                if self.verbose:
 
228
                        print "--- END TEST - %s\n" % self.name
 
229
 
 
230
                self.executed = 1
 
231
                return res
 
232
 
 
233
class Tests:
 
234
        def __init__(self, verbose = 0):
 
235
                self.tests = []
 
236
                self.verbose = verbose
 
237
                self.autogen_corosync_cfg = 0
 
238
                if not os.path.exists("/etc/corosync/corosync.conf"):
 
239
                        self.autogen_corosync_cfg = 1
 
240
 
 
241
        def new_test(self, name, description, with_cpg = 0):
 
242
                test = Test(name, description, self.verbose, with_cpg)
 
243
                self.tests.append(test)
 
244
                return test
 
245
 
 
246
        def print_list(self):
 
247
                print "\n==== %d TESTS FOUND ====" % (len(self.tests))
 
248
                print "%35s - %s" % ("TEST NAME", "TEST DESCRIPTION")
 
249
                print "%35s - %s" % ("--------------------", "--------------------")
 
250
                for test in self.tests:
 
251
                        print "%35s - %s" % (test.name, test.description)
 
252
                print "==== END OF LIST ====\n"
 
253
 
 
254
 
 
255
        def start_corosync(self):
 
256
                if self.verbose:
 
257
                        print "Starting corosync"
 
258
 
 
259
                test = subprocess.Popen("corosync", stdout=subprocess.PIPE)
 
260
                test.wait()
 
261
                time.sleep(10)
 
262
 
 
263
        def stop_corosync(self):
 
264
                cmd = shlex.split("killall -9 -q corosync")
 
265
                test = subprocess.Popen(cmd, stdout=subprocess.PIPE)
 
266
                test.wait()
 
267
 
 
268
        def run_single(self, name):
 
269
                for test in self.tests:
 
270
                        if test.name == name:
 
271
                                test.run()
 
272
                                break;
 
273
 
 
274
        def run_tests_matching(self, pattern):
 
275
                for test in self.tests:
 
276
                        if test.name.count(pattern) != 0:
 
277
                                test.run()
 
278
 
 
279
        def run_cpg_only(self):
 
280
                for test in self.tests:
 
281
                        if test.enable_corosync:
 
282
                                test.run()
 
283
 
 
284
        def run_no_cpg(self):
 
285
                for test in self.tests:
 
286
                        if not test.enable_corosync:
 
287
                                test.run()
 
288
 
 
289
        def run_tests(self):
 
290
                for test in self.tests:
 
291
                        test.run()
 
292
 
 
293
        def exit(self):
 
294
                for test in self.tests:
 
295
                        if test.executed == 0:
 
296
                                continue
 
297
 
 
298
                        if test.get_exitcode() != 0:
 
299
                                sys.exit(-1)
 
300
 
 
301
                sys.exit(0)
 
302
 
 
303
        def print_results(self):
 
304
                failures = 0;
 
305
                success = 0;
 
306
                print "\n\n======= FINAL RESULTS =========="
 
307
                print "\n--- FAILURE RESULTS:"
 
308
                for test in self.tests:
 
309
                        if test.executed == 0:
 
310
                                continue
 
311
 
 
312
                        if test.get_exitcode() != 0:
 
313
                                failures = failures + 1
 
314
                                test.print_result("    ")
 
315
                        else:
 
316
                                success = success + 1
 
317
 
 
318
                if failures == 0:
 
319
                        print "    None"
 
320
 
 
321
                print "\n--- TOTALS\n    Pass:%d\n    Fail:%d\n" % (success, failures)
 
322
        def build_api_sanity_tests(self):
 
323
                verbose_arg = ""
 
324
                if self.verbose:
 
325
                        verbose_arg = "-V"
 
326
 
 
327
                test = self.new_test("standalone_low_level_api_test", "Sanity test client api in standalone mode.")
 
328
                test.add_cmd("@CRM_DAEMON_DIR@/stonith-test", "-t %s" % (verbose_arg))
 
329
 
 
330
                test = self.new_test("cpg_low_level_api_test", "Sanity test client api using mainloop and cpg.", 1)
 
331
                test.add_cmd("@CRM_DAEMON_DIR@/stonith-test", "-m %s" % (verbose_arg))
 
332
 
 
333
        def build_custom_timeout_tests(self):
 
334
                # custom timeout without topology
 
335
                test = self.new_test("cpg_custom_timeout_1",
 
336
                                "Verify per device timeouts work as expected without using topology.", 1)
 
337
                test.add_cmd("stonith_admin", "-R false1 -a fence_false -o \"pcmk_host_list=node1 node2 node3\"")
 
338
                test.add_cmd("stonith_admin", "-R true1  -a fence_true -o \"pcmk_host_list=node3\" -o \"pcmk_off_timeout=1\"")
 
339
                test.add_cmd("stonith_admin", "-R false2 -a fence_false -o \"pcmk_host_list=node3\" -o \"pcmk_off_timeout=4\"")
 
340
                test.add_cmd("stonith_admin", "-F node3 -t 2")
 
341
                # timeout is 2+1+4 = 7
 
342
                test.add_stonith_log_pattern("remote op timeout set to 7")
 
343
 
 
344
                # custom timeout _WITH_ topology
 
345
                test = self.new_test("cpg_custom_timeout_2",
 
346
                                "Verify per device timeouts work as expected _WITH_ topology.", 1)
 
347
                test.add_cmd("stonith_admin", "-R false1 -a fence_false -o \"pcmk_host_list=node1 node2 node3\"")
 
348
                test.add_cmd("stonith_admin", "-R true1  -a fence_true -o \"pcmk_host_list=node3\" -o \"pcmk_off_timeout=1\"")
 
349
                test.add_cmd("stonith_admin", "-R false2 -a fence_false -o \"pcmk_host_list=node3\" -o \"pcmk_off_timeout=4000\"")
 
350
                test.add_cmd("stonith_admin", "-r node3 -i 1 -v false1")
 
351
                test.add_cmd("stonith_admin", "-r node3 -i 2 -v true1")
 
352
                test.add_cmd("stonith_admin", "-r node3 -i 3 -v false2")
 
353
                test.add_cmd("stonith_admin", "-F node3 -t 2")
 
354
                # timeout is 2+1+4000 = 4003
 
355
                test.add_stonith_log_pattern("remote op timeout set to 4003")
 
356
 
 
357
        def build_fence_merge_tests(self):
 
358
 
 
359
                ### Simple test that overlapping fencing operations get merged
 
360
                test = self.new_test("cpg_custom_merge_single",
 
361
                                "Verify overlapping identical fencing operations are merged, no fencing levels used.", 1)
 
362
                test.add_cmd("stonith_admin", "-R false1 -a fence_false -o \"pcmk_host_list=node3\"")
 
363
                test.add_cmd("stonith_admin", "-R true1  -a fence_true -o \"pcmk_host_list=node3\" ")
 
364
                test.add_cmd("stonith_admin", "-R false2 -a fence_false -o \"pcmk_host_list=node3\"")
 
365
                test.add_cmd_no_wait("stonith_admin", "-F node3 -t 10")
 
366
                test.add_cmd("stonith_admin", "-F node3 -t 10")
 
367
                ### one merger will happen
 
368
                test.add_stonith_log_pattern("Merging stonith action off for node node3 originating from client")
 
369
                ### the pattern below signifies that both the original and duplicate operation completed
 
370
                test.add_stonith_log_pattern("Operation off of node3 by")
 
371
                test.add_stonith_log_pattern("Operation off of node3 by")
 
372
 
 
373
                ### Test that multiple mergers occur
 
374
                test = self.new_test("cpg_custom_merge_multiple",
 
375
                                "Verify multiple overlapping identical fencing operations are merged", 1)
 
376
                test.add_cmd("stonith_admin", "-R false1 -a fence_false -o \"pcmk_host_list=node3\"")
 
377
                test.add_cmd("stonith_admin", "-R true1  -a fence_true -o \"pcmk_host_list=node3\" ")
 
378
                test.add_cmd("stonith_admin", "-R false2 -a fence_false -o \"pcmk_host_list=node3\"")
 
379
                test.add_cmd_no_wait("stonith_admin", "-F node3 -t 10")
 
380
                test.add_cmd_no_wait("stonith_admin", "-F node3 -t 10")
 
381
                test.add_cmd_no_wait("stonith_admin", "-F node3 -t 10")
 
382
                test.add_cmd_no_wait("stonith_admin", "-F node3 -t 10")
 
383
                test.add_cmd("stonith_admin", "-F node3 -t 10")
 
384
                ### 4 mergers should occur
 
385
                test.add_stonith_log_pattern("Merging stonith action off for node node3 originating from client")
 
386
                test.add_stonith_log_pattern("Merging stonith action off for node node3 originating from client")
 
387
                test.add_stonith_log_pattern("Merging stonith action off for node node3 originating from client")
 
388
                test.add_stonith_log_pattern("Merging stonith action off for node node3 originating from client")
 
389
                ### the pattern below signifies that both the original and duplicate operation completed
 
390
                test.add_stonith_log_pattern("Operation off of node3 by")
 
391
                test.add_stonith_log_pattern("Operation off of node3 by")
 
392
                test.add_stonith_log_pattern("Operation off of node3 by")
 
393
                test.add_stonith_log_pattern("Operation off of node3 by")
 
394
                test.add_stonith_log_pattern("Operation off of node3 by")
 
395
 
 
396
                ### Test that multiple mergers occur with topologies used
 
397
                test = self.new_test("cpg_custom_merge_with_topology",
 
398
                                "Verify multiple overlapping identical fencing operations are merged with fencing levels.", 1)
 
399
                test.add_cmd("stonith_admin", "-R false1 -a fence_false -o \"pcmk_host_list=node3\"")
 
400
                test.add_cmd("stonith_admin", "-R true1  -a fence_true -o \"pcmk_host_list=node3\" ")
 
401
                test.add_cmd("stonith_admin", "-R false2 -a fence_false -o \"pcmk_host_list=node3\"")
 
402
                test.add_cmd("stonith_admin", "-r node3 -i 1 -v false1")
 
403
                test.add_cmd("stonith_admin", "-r node3 -i 1 -v false2")
 
404
                test.add_cmd("stonith_admin", "-r node3 -i 2 -v true1")
 
405
                test.add_cmd_no_wait("stonith_admin", "-F node3 -t 10")
 
406
                test.add_cmd_no_wait("stonith_admin", "-F node3 -t 10")
 
407
                test.add_cmd_no_wait("stonith_admin", "-F node3 -t 10")
 
408
                test.add_cmd_no_wait("stonith_admin", "-F node3 -t 10")
 
409
                test.add_cmd("stonith_admin", "-F node3 -t 10")
 
410
                ### 4 mergers should occur
 
411
                test.add_stonith_log_pattern("Merging stonith action off for node node3 originating from client")
 
412
                test.add_stonith_log_pattern("Merging stonith action off for node node3 originating from client")
 
413
                test.add_stonith_log_pattern("Merging stonith action off for node node3 originating from client")
 
414
                test.add_stonith_log_pattern("Merging stonith action off for node node3 originating from client")
 
415
                ### the pattern below signifies that both the original and duplicate operation completed
 
416
                test.add_stonith_log_pattern("Operation off of node3 by")
 
417
                test.add_stonith_log_pattern("Operation off of node3 by")
 
418
                test.add_stonith_log_pattern("Operation off of node3 by")
 
419
                test.add_stonith_log_pattern("Operation off of node3 by")
 
420
                test.add_stonith_log_pattern("Operation off of node3 by")
 
421
 
 
422
 
 
423
                test = self.new_test("cpg_custom_no_merge",
 
424
                                "Verify differing fencing operations are not merged", 1)
 
425
                test.add_cmd("stonith_admin", "-R false1 -a fence_false -o \"pcmk_host_list=node3 node2\"")
 
426
                test.add_cmd("stonith_admin", "-R true1  -a fence_true -o \"pcmk_host_list=node3 node2\" ")
 
427
                test.add_cmd("stonith_admin", "-R false2 -a fence_false -o \"pcmk_host_list=node3 node2\"")
 
428
                test.add_cmd("stonith_admin", "-r node3 -i 1 -v false1")
 
429
                test.add_cmd("stonith_admin", "-r node3 -i 1 -v false2")
 
430
                test.add_cmd("stonith_admin", "-r node3 -i 2 -v true1")
 
431
                test.add_cmd_no_wait("stonith_admin", "-F node2 -t 10")
 
432
                test.add_cmd("stonith_admin", "-F node3 -t 10")
 
433
                test.add_stonith_negative_log_pattern("Merging stonith action off for node node3 originating from client")
 
434
 
 
435
        def build_standalone_tests(self):
 
436
                test_types = [
 
437
                        {
 
438
                                "prefix" : "standalone" ,
 
439
                                "use_cpg" : 0,
 
440
                        },
 
441
                        {
 
442
                                "prefix" : "cpg" ,
 
443
                                "use_cpg" : 1,
 
444
                        },
 
445
                ]
 
446
 
 
447
                # test what happens when all devices timeout
 
448
                for test_type in test_types:
 
449
                        test = self.new_test("%s_fence_multi_device_failure" % test_type["prefix"],
 
450
                                        "Verify that all devices timeout, a fencing failure is returned.", test_type["use_cpg"])
 
451
                        test.add_cmd("stonith_admin", "-R false1 -a fence_false -o \"pcmk_host_list=node1 node2 node3\"")
 
452
                        test.add_cmd("stonith_admin", "-R false2  -a fence_false -o \"pcmk_host_list=node1 node2 node3\"")
 
453
                        test.add_cmd("stonith_admin", "-R false3 -a fence_false -o \"pcmk_host_list=node1 node2 node3\"")
 
454
                        test.add_expected_fail_cmd("stonith_admin", "-F node3 -t 2", 194)
 
455
 
 
456
                        if test_type["use_cpg"] == 1:
 
457
                                test.add_stonith_log_pattern("remote op timeout set to 6")
 
458
 
 
459
                        test.add_stonith_log_pattern("for host 'node3' with device 'false1' returned: -62")
 
460
                        test.add_stonith_log_pattern("for host 'node3' with device 'false2' returned: -62")
 
461
                        test.add_stonith_log_pattern("for host 'node3' with device 'false3' returned: -62")
 
462
 
 
463
                # test what happens when multiple devices can fence a node, but the first device fails.
 
464
                for test_type in test_types:
 
465
                        test = self.new_test("%s_fence_device_failure_rollover" % test_type["prefix"],
 
466
                                        "Verify that when one fence device fails for a node, the others are tried.", test_type["use_cpg"])
 
467
                        test.add_cmd("stonith_admin", "-R false1 -a fence_false -o \"pcmk_host_list=node1 node2 node3\"")
 
468
                        test.add_cmd("stonith_admin", "-R true1  -a fence_true -o \"pcmk_host_list=node1 node2 node3\"")
 
469
                        test.add_cmd("stonith_admin", "-R false2 -a fence_false -o \"pcmk_host_list=node1 node2 node3\"")
 
470
                        test.add_cmd("stonith_admin", "-F node3 -t 2")
 
471
 
 
472
                        if test_type["use_cpg"] == 1:
 
473
                                test.add_stonith_log_pattern("remote op timeout set to 6")
 
474
 
 
475
                # simple topology test for one device
 
476
                for test_type in test_types:
 
477
                        if test_type["use_cpg"] == 0:
 
478
                                continue
 
479
 
 
480
                        test = self.new_test("%s_topology_simple" % test_type["prefix"],
 
481
                                        "Verify all fencing devices at a level are used.", test_type["use_cpg"])
 
482
                        test.add_cmd("stonith_admin", "-R true  -a fence_true -o \"pcmk_host_list=node1 node2 node3\"")
 
483
 
 
484
                        test.add_cmd("stonith_admin", "-r node3 -i 1 -v true")
 
485
                        test.add_cmd("stonith_admin", "-F node3 -t 2")
 
486
 
 
487
                        test.add_stonith_log_pattern("remote op timeout set to 2")
 
488
                        test.add_stonith_log_pattern("for host 'node3' with device 'true' returned: 0")
 
489
 
 
490
                # test what happens when the first fencing level has multiple devices.
 
491
                for test_type in test_types:
 
492
                        if test_type["use_cpg"] == 0:
 
493
                                continue
 
494
 
 
495
                        test = self.new_test("%s_topology_device_fails" % test_type["prefix"],
 
496
                                        "Verify if one device in a level fails, the other is tried.", test_type["use_cpg"])
 
497
                        test.add_cmd("stonith_admin", "-R false  -a fence_false -o \"pcmk_host_list=node1 node2 node3\"")
 
498
                        test.add_cmd("stonith_admin", "-R true  -a fence_true -o \"pcmk_host_list=node1 node2 node3\"")
 
499
 
 
500
                        test.add_cmd("stonith_admin", "-r node3 -i 1 -v false")
 
501
                        test.add_cmd("stonith_admin", "-r node3 -i 2 -v true")
 
502
                        test.add_cmd("stonith_admin", "-F node3 -t 20")
 
503
 
 
504
                        test.add_stonith_log_pattern("remote op timeout set to 4")
 
505
                        test.add_stonith_log_pattern("for host 'node3' with device 'false' returned: -62")
 
506
                        test.add_stonith_log_pattern("for host 'node3' with device 'true' returned: 0")
 
507
 
 
508
                # test what happens when the first fencing level fails.
 
509
                for test_type in test_types:
 
510
                        if test_type["use_cpg"] == 0:
 
511
                                continue
 
512
 
 
513
                        test = self.new_test("%s_topology_multi_level_fails" % test_type["prefix"],
 
514
                                        "Verify if one level fails, the next leve is tried.", test_type["use_cpg"])
 
515
                        test.add_cmd("stonith_admin", "-R true1  -a fence_true -o \"pcmk_host_list=node1 node2 node3\"")
 
516
                        test.add_cmd("stonith_admin", "-R true2  -a fence_true -o \"pcmk_host_list=node1 node2 node3\"")
 
517
                        test.add_cmd("stonith_admin", "-R true3  -a fence_true -o \"pcmk_host_list=node1 node2 node3\"")
 
518
                        test.add_cmd("stonith_admin", "-R true4  -a fence_true -o \"pcmk_host_list=node1 node2 node3\"")
 
519
                        test.add_cmd("stonith_admin", "-R false1 -a fence_false -o \"pcmk_host_list=node1 node2 node3\"")
 
520
                        test.add_cmd("stonith_admin", "-R false2 -a fence_false -o \"pcmk_host_list=node1 node2 node3\"")
 
521
 
 
522
                        test.add_cmd("stonith_admin", "-r node3 -i 1 -v false1")
 
523
                        test.add_cmd("stonith_admin", "-r node3 -i 1 -v true1")
 
524
                        test.add_cmd("stonith_admin", "-r node3 -i 2 -v true2")
 
525
                        test.add_cmd("stonith_admin", "-r node3 -i 2 -v false2")
 
526
                        test.add_cmd("stonith_admin", "-r node3 -i 3 -v true3")
 
527
                        test.add_cmd("stonith_admin", "-r node3 -i 3 -v true4")
 
528
 
 
529
                        test.add_cmd("stonith_admin", "-F node3 -t 2")
 
530
 
 
531
                        test.add_stonith_log_pattern("remote op timeout set to 12")
 
532
                        test.add_stonith_log_pattern("for host 'node3' with device 'false1' returned: -62")
 
533
                        test.add_stonith_log_pattern("for host 'node3' with device 'false2' returned: -62")
 
534
                        test.add_stonith_log_pattern("for host 'node3' with device 'true3' returned: 0")
 
535
                        test.add_stonith_log_pattern("for host 'node3' with device 'true4' returned: 0")
 
536
 
 
537
 
 
538
                # test what happens when the first fencing level had devices that no one has registered
 
539
                for test_type in test_types:
 
540
                        if test_type["use_cpg"] == 0:
 
541
                                continue
 
542
 
 
543
                        test = self.new_test("%s_topology_missing_devices" % test_type["prefix"],
 
544
                                        "Verify topology can continue with missing devices.", test_type["use_cpg"])
 
545
                        test.add_cmd("stonith_admin", "-R true2  -a fence_true -o \"pcmk_host_list=node1 node2 node3\"")
 
546
                        test.add_cmd("stonith_admin", "-R true3  -a fence_true -o \"pcmk_host_list=node1 node2 node3\"")
 
547
                        test.add_cmd("stonith_admin", "-R true4  -a fence_true -o \"pcmk_host_list=node1 node2 node3\"")
 
548
                        test.add_cmd("stonith_admin", "-R false2 -a fence_false -o \"pcmk_host_list=node1 node2 node3\"")
 
549
 
 
550
                        test.add_cmd("stonith_admin", "-r node3 -i 1 -v false1")
 
551
                        test.add_cmd("stonith_admin", "-r node3 -i 1 -v true1")
 
552
                        test.add_cmd("stonith_admin", "-r node3 -i 2 -v true2")
 
553
                        test.add_cmd("stonith_admin", "-r node3 -i 2 -v false2")
 
554
                        test.add_cmd("stonith_admin", "-r node3 -i 3 -v true3")
 
555
                        test.add_cmd("stonith_admin", "-r node3 -i 3 -v true4")
 
556
 
 
557
                        test.add_cmd("stonith_admin", "-F node3 -t 2")
 
558
 
 
559
                # Test what happens if multiple fencing levels are defined, and then the first one is removed.
 
560
                for test_type in test_types:
 
561
                        if test_type["use_cpg"] == 0:
 
562
                                continue
 
563
 
 
564
                        test = self.new_test("%s_topology_level_removal" % test_type["prefix"],
 
565
                                        "Verify level removal works.", test_type["use_cpg"])
 
566
                        test.add_cmd("stonith_admin", "-R true1  -a fence_true -o \"pcmk_host_list=node1 node2 node3\"")
 
567
                        test.add_cmd("stonith_admin", "-R true2  -a fence_true -o \"pcmk_host_list=node1 node2 node3\"")
 
568
                        test.add_cmd("stonith_admin", "-R true3  -a fence_true -o \"pcmk_host_list=node1 node2 node3\"")
 
569
                        test.add_cmd("stonith_admin", "-R true4  -a fence_true -o \"pcmk_host_list=node1 node2 node3\"")
 
570
                        test.add_cmd("stonith_admin", "-R false1 -a fence_false -o \"pcmk_host_list=node1 node2 node3\"")
 
571
                        test.add_cmd("stonith_admin", "-R false2 -a fence_false -o \"pcmk_host_list=node1 node2 node3\"")
 
572
 
 
573
                        test.add_cmd("stonith_admin", "-r node3 -i 1 -v false1")
 
574
                        test.add_cmd("stonith_admin", "-r node3 -i 1 -v true1")
 
575
 
 
576
                        test.add_cmd("stonith_admin", "-r node3 -i 2 -v true2")
 
577
                        test.add_cmd("stonith_admin", "-r node3 -i 2 -v false2")
 
578
 
 
579
                        test.add_cmd("stonith_admin", "-r node3 -i 3 -v true3")
 
580
                        test.add_cmd("stonith_admin", "-r node3 -i 3 -v true4")
 
581
 
 
582
                        # Now remove level 2, verify none of the devices in level two are hit.
 
583
                        test.add_cmd("stonith_admin", "-d node3 -i 2")
 
584
 
 
585
                        test.add_cmd("stonith_admin", "-F node3 -t 20")
 
586
 
 
587
                        test.add_stonith_log_pattern("remote op timeout set to 8")
 
588
                        test.add_stonith_log_pattern("for host 'node3' with device 'false1' returned: -62")
 
589
                        test.add_stonith_negative_log_pattern("for host 'node3' with device 'false2' returned: -62")
 
590
                        test.add_stonith_negative_log_pattern("for host 'node3' with device 'false2' returned: -1001")
 
591
                        test.add_stonith_log_pattern("for host 'node3' with device 'true3' returned: 0")
 
592
                        test.add_stonith_log_pattern("for host 'node3' with device 'true4' returned: 0")
 
593
 
 
594
                # test the stonith builds the correct list of devices that can fence a node.
 
595
                for test_type in test_types:
 
596
                        test = self.new_test("%s_list_devices" % test_type["prefix"],
 
597
                                        "Verify list of devices that can fence a node is correct", test_type["use_cpg"])
 
598
                        test.add_cmd("stonith_admin", "-R true1  -a fence_true -o \"pcmk_host_list=node3\"")
 
599
                        test.add_cmd("stonith_admin", "-R true2 -a fence_true -o \"pcmk_host_list=node1 node2 node3\"")
 
600
                        test.add_cmd("stonith_admin", "-R true3 -a fence_true -o \"pcmk_host_list=node1 node2 node3\"")
 
601
 
 
602
                        test.add_cmd_check_stdout("stonith_admin", "-l node1 -V", "true2", "true1")
 
603
                        test.add_cmd_check_stdout("stonith_admin", "-l node1 -V", "true3", "true1")
 
604
 
 
605
                # simple test of device monitor
 
606
                for test_type in test_types:
 
607
                        test = self.new_test("%s_monitor" % test_type["prefix"],
 
608
                                        "Verify device is reachable", test_type["use_cpg"])
 
609
                        test.add_cmd("stonith_admin", "-R true1  -a fence_true -o \"pcmk_host_list=node3\"")
 
610
                        test.add_cmd("stonith_admin", "-R false1  -a fence_false -o \"pcmk_host_list=node3\"")
 
611
 
 
612
                        test.add_cmd("stonith_admin", "-Q true1")
 
613
                        test.add_cmd("stonith_admin", "-Q false1")
 
614
                        test.add_expected_fail_cmd("stonith_admin", "-Q true2", 237)
 
615
 
 
616
                # Verify monitor occurs for duration of timeout period on failure
 
617
                for test_type in test_types:
 
618
                        test = self.new_test("%s_monitor_timeout" % test_type["prefix"],
 
619
                                        "Verify monitor uses duration of timeout period given.", test_type["use_cpg"])
 
620
                        test.add_cmd("stonith_admin", "-R true1  -a fence_dummy_monitor_fail -o \"pcmk_host_list=node3\"")
 
621
                        test.add_expected_fail_cmd("stonith_admin", "-Q true1 -t 5", 23)
 
622
                        test.add_stonith_log_pattern("Attempt 2 to execute")
 
623
 
 
624
                # Verify monitor occurs for duration of timeout period on failure, but stops at max retries
 
625
                for test_type in test_types:
 
626
                        test = self.new_test("%s_monitor_timeout_max_retries" % test_type["prefix"],
 
627
                                        "Verify monitor retries until max retry value or timeout is hit.", test_type["use_cpg"])
 
628
                        test.add_cmd("stonith_admin", "-R true1  -a fence_dummy_monitor_fail -o \"pcmk_host_list=node3\"")
 
629
                        test.add_expected_fail_cmd("stonith_admin", "-Q true1 -t 15", 23)
 
630
                        test.add_stonith_log_pattern("Attempted to execute agent fence_dummy_monitor_fail (list) the maximum number of times")
 
631
 
 
632
                # simple register test
 
633
                for test_type in test_types:
 
634
                        test = self.new_test("%s_register" % test_type["prefix"],
 
635
                                        "Verify devices can be registered and un-registered", test_type["use_cpg"])
 
636
                        test.add_cmd("stonith_admin", "-R true1  -a fence_true -o \"pcmk_host_list=node3\"")
 
637
 
 
638
                        test.add_cmd("stonith_admin", "-Q true1")
 
639
 
 
640
                        test.add_cmd("stonith_admin", "-D true1")
 
641
 
 
642
                        test.add_expected_fail_cmd("stonith_admin", "-Q true1", 237)
 
643
 
 
644
 
 
645
                # simple reboot test
 
646
                for test_type in test_types:
 
647
                        test = self.new_test("%s_reboot" % test_type["prefix"],
 
648
                                        "Verify devices can be rebooted", test_type["use_cpg"])
 
649
                        test.add_cmd("stonith_admin", "-R true1  -a fence_true -o \"pcmk_host_list=node3\"")
 
650
 
 
651
                        test.add_cmd("stonith_admin", "-B node3 -t 2")
 
652
 
 
653
                        test.add_cmd("stonith_admin", "-D true1")
 
654
 
 
655
                        test.add_expected_fail_cmd("stonith_admin", "-Q true1", 237)
 
656
 
 
657
                # test fencing history.
 
658
                for test_type in test_types:
 
659
                        if test_type["use_cpg"] == 0:
 
660
                                continue
 
661
                        test = self.new_test("%s_fence_history" % test_type["prefix"],
 
662
                                        "Verify last fencing operation is returned.", test_type["use_cpg"])
 
663
                        test.add_cmd("stonith_admin", "-R true1  -a fence_true -o \"pcmk_host_list=node3\"")
 
664
 
 
665
                        test.add_cmd("stonith_admin", "-F node3 -t 2 -V")
 
666
 
 
667
                        test.add_cmd_check_stdout("stonith_admin", "-H node3", "was able to turn off node node3", "")
 
668
 
 
669
                # simple test of dynamic list query
 
670
                for test_type in test_types:
 
671
                        test = self.new_test("%s_dynamic_list_query" % test_type["prefix"],
 
672
                                        "Verify dynamic list of fencing devices can be retrieved.", test_type["use_cpg"])
 
673
                        test.add_cmd("stonith_admin", "-R true1  -a fence_true")
 
674
                        test.add_cmd("stonith_admin", "-R true2  -a fence_true")
 
675
                        test.add_cmd("stonith_admin", "-R true3  -a fence_true")
 
676
 
 
677
                        test.add_cmd_check_stdout("stonith_admin", "-l fake_port_1", "3 devices found")
 
678
 
 
679
 
 
680
                # fence using dynamic list query
 
681
                for test_type in test_types:
 
682
                        test = self.new_test("%s_fence_dynamic_list_query" % test_type["prefix"],
 
683
                                        "Verify dynamic list of fencing devices can be retrieved.", test_type["use_cpg"])
 
684
                        test.add_cmd("stonith_admin", "-R true1  -a fence_true")
 
685
                        test.add_cmd("stonith_admin", "-R true2  -a fence_true")
 
686
                        test.add_cmd("stonith_admin", "-R true3  -a fence_true")
 
687
 
 
688
                        test.add_cmd("stonith_admin", "-F fake_port_1 -t 5 -V");
 
689
 
 
690
                # simple test of  query using status action
 
691
                for test_type in test_types:
 
692
                        test = self.new_test("%s_status_query" % test_type["prefix"],
 
693
                                        "Verify dynamic list of fencing devices can be retrieved.", test_type["use_cpg"])
 
694
                        test.add_cmd("stonith_admin", "-R true1  -a fence_true -o \"pcmk_host_check=status\"")
 
695
                        test.add_cmd("stonith_admin", "-R true2  -a fence_true -o \"pcmk_host_check=status\"")
 
696
                        test.add_cmd("stonith_admin", "-R true3  -a fence_true -o \"pcmk_host_check=status\"")
 
697
 
 
698
                        test.add_cmd_check_stdout("stonith_admin", "-l fake_port_1", "3 devices found")
 
699
 
 
700
 
 
701
        def build_nodeid_tests(self):
 
702
                our_uname = output_from_command("uname -n")
 
703
                if our_uname:
 
704
                        our_uname = our_uname[0]
 
705
 
 
706
                ### verify nodeid is supplied when nodeid is in the metadata parameters
 
707
                test = self.new_test("cpg_supply_nodeid",
 
708
                                "Verify nodeid is given when fence agent has nodeid as parameter", 1)
 
709
 
 
710
                test.add_cmd("stonith_admin", "-R true1 -a fence_dummy_metadata_helper -o \"pcmk_host_list=%s\"" % (our_uname))
 
711
                test.add_cmd("stonith_admin", "-F %s -t 3" % (our_uname))
 
712
                test.add_stonith_log_pattern("For stonith action (off) for victim %s, adding nodeid" % (our_uname))
 
713
 
 
714
                ### verify nodeid is _NOT_ supplied when nodeid is not in the metadata parameters
 
715
                test = self.new_test("cpg_do_not_supply_nodeid",
 
716
                                "Verify nodeid is _NOT_ given when fence agent does not have nodeid as parameter", 1)
 
717
 
 
718
                test.add_cmd("stonith_admin", "-R true1 -a fence_true -o \"pcmk_host_list=%s\"" % (our_uname))
 
719
                test.add_cmd("stonith_admin", "-F %s -t 3" % (our_uname))
 
720
                test.add_stonith_negative_log_pattern("For stonith action (off) for victim %s, adding nodeid" % (our_uname))
 
721
 
 
722
                ### verify nodeid use doesn't explode standalone mode
 
723
                test = self.new_test("standalone_do_not_supply_nodeid",
 
724
                                "Verify nodeid in metadata parameter list doesn't kill standalone mode", 0)
 
725
 
 
726
                test.add_cmd("stonith_admin", "-R true1 -a fence_dummy_metadata_helper -o \"pcmk_host_list=%s\"" % (our_uname))
 
727
                test.add_cmd("stonith_admin", "-F %s -t 3" % (our_uname))
 
728
                test.add_stonith_negative_log_pattern("For stonith action (off) for victim %s, adding nodeid" % (our_uname))
 
729
 
 
730
 
 
731
        def build_unfence_tests(self):
 
732
                our_uname = output_from_command("uname -n")
 
733
                if our_uname:
 
734
                        our_uname = our_uname[0]
 
735
 
 
736
                ### Simple test unfencing works
 
737
                test = self.new_test("cpg_unfence_simple",
 
738
                                "Verify simple unfencing.", 1)
 
739
                test.add_cmd("stonith_admin", "-R false1 -a fence_false -o \"pcmk_host_list=node3\"")
 
740
                test.add_cmd("stonith_admin", "-R true1  -a fence_true -o \"pcmk_host_list=node3\" ")
 
741
                test.add_cmd("stonith_admin", "-R false2 -a fence_false -o \"pcmk_host_list=node3\"")
 
742
                test.add_cmd("stonith_admin", "-U node3 -t 3")
 
743
 
 
744
                ### verify unfencing using on_target device
 
745
                test = self.new_test("cpg_unfence_on_target_1",
 
746
                                "Verify unfencing with on_target = true", 1)
 
747
                test.add_cmd("stonith_admin", "-R true1 -a fence_dummy_metadata_helper -o \"pcmk_host_list=%s\"" % (our_uname))
 
748
                test.add_cmd("stonith_admin", "-U %s -t 3" % (our_uname))
 
749
                test.add_stonith_log_pattern("(on) to be executed on the target node")
 
750
 
 
751
 
 
752
                ### verify failure of unfencing using on_target device
 
753
                test = self.new_test("cpg_unfence_on_target_2",
 
754
                                "Verify failure unfencing with on_target = true", 1)
 
755
                test.add_cmd("stonith_admin", "-R true1 -a fence_dummy_metadata_helper -o \"pcmk_host_list=%s node_fake_1234\"" % (our_uname))
 
756
                test.add_expected_fail_cmd("stonith_admin", "-U node_fake_1234 -t 3", 194)
 
757
                test.add_stonith_log_pattern("(on) to be executed on the target node")
 
758
 
 
759
 
 
760
                ### verify unfencing using on_target device with topology
 
761
                test = self.new_test("cpg_unfence_on_target_3",
 
762
                                "Verify unfencing with on_target = true using topology", 1)
 
763
 
 
764
                test.add_cmd("stonith_admin", "-R false1 -a fence_false -o \"pcmk_host_list=%s node3\"" % (our_uname))
 
765
                test.add_cmd("stonith_admin", "-R false2 -a fence_false -o \"pcmk_host_list=%s node3\"" % (our_uname))
 
766
                test.add_cmd("stonith_admin", "-R true1 -a fence_dummy_metadata_helper -o \"pcmk_host_list=%s node3\"" % (our_uname))
 
767
 
 
768
                test.add_cmd("stonith_admin", "-r %s -i 1 -v false1" % (our_uname))
 
769
                test.add_cmd("stonith_admin", "-r %s -i 2 -v false2" % (our_uname))
 
770
                test.add_cmd("stonith_admin", "-r %s -i 3 -v true1" % (our_uname))
 
771
 
 
772
                test.add_cmd("stonith_admin", "-U %s -t 3" % (our_uname))
 
773
                test.add_stonith_log_pattern("(on) to be executed on the target node")
 
774
 
 
775
                ### verify unfencing using on_target device with topology fails
 
776
                test = self.new_test("cpg_unfence_on_target_4",
 
777
                                "Verify unfencing failure with on_target = true using topology", 1)
 
778
 
 
779
                test.add_cmd("stonith_admin", "-R false1 -a fence_false -o \"pcmk_host_list=%s node_fake\"" % (our_uname))
 
780
                test.add_cmd("stonith_admin", "-R false2 -a fence_false -o \"pcmk_host_list=%s node_fake\"" % (our_uname))
 
781
                test.add_cmd("stonith_admin", "-R true1 -a fence_dummy_metadata_helper -o \"pcmk_host_list=%s node_fake\"" % (our_uname))
 
782
 
 
783
                test.add_cmd("stonith_admin", "-r node_fake -i 1 -v false1")
 
784
                test.add_cmd("stonith_admin", "-r node_fake -i 2 -v false2")
 
785
                test.add_cmd("stonith_admin", "-r node_fake -i 3 -v true1")
 
786
 
 
787
                test.add_expected_fail_cmd("stonith_admin", "-U node_fake -t 3", 194)
 
788
                test.add_stonith_log_pattern("(on) to be executed on the target node")
 
789
 
 
790
 
 
791
                ### verify use of on_target = true for "on" action does not interfere with "off" action
 
792
                test = self.new_test("cpg_unfence_on_target_ignored",
 
793
                                "Verify on target is ignored for other actions", 1)
 
794
                test.add_cmd("stonith_admin", "-R false1 -a fence_false -o \"pcmk_host_list=%s node_fake\"" % (our_uname))
 
795
                test.add_cmd("stonith_admin", "-R false2 -a fence_false -o \"pcmk_host_list=%s node_fake\"" % (our_uname))
 
796
                test.add_cmd("stonith_admin", "-R true1 -a fence_dummy_metadata_helper -o \"pcmk_host_list=%s node_fake\"" % (our_uname))
 
797
                test.add_cmd("stonith_admin", "-r node_fake -i 1 -v false1")
 
798
                test.add_cmd("stonith_admin", "-r node_fake -i 2 -v false2")
 
799
                test.add_cmd("stonith_admin", "-r node_fake -i 3 -v true1")
 
800
                test.add_cmd("stonith_admin", "-F node_fake -t 3")
 
801
                test.add_stonith_log_pattern("(on) to be executed on the target node")
 
802
 
 
803
        def setup_environment(self, use_corosync):
 
804
                if self.autogen_corosync_cfg and use_corosync:
 
805
                        corosync_conf = ("""
 
806
totem {
 
807
        version: 2
 
808
        crypto_cipher: none
 
809
        crypto_hash: none
 
810
 
 
811
        nodeid:         101
 
812
        secauth:        off
 
813
 
 
814
        interface {
 
815
                ttl: 1
 
816
                ringnumber: 0
 
817
                mcastport: 6666
 
818
                mcastaddr: 226.94.1.1
 
819
                bindnetaddr: 127.0.0.1
 
820
        }
 
821
}
 
822
 
 
823
logging {
 
824
        debug: off
 
825
        fileline: off
 
826
        to_syslog: no
 
827
        to_stderr: no
 
828
        syslog_facility: daemon
 
829
        timestamp: on
 
830
        to_logfile: yes
 
831
        logfile: /var/log/corosync.log
 
832
        logfile_priority: info
 
833
}
 
834
""")
 
835
 
 
836
                        os.system("cat <<-END >>/etc/corosync/corosync.conf\n%s\nEND" % (corosync_conf))
 
837
 
 
838
 
 
839
                if use_corosync:
 
840
                        ### make sure we are in control ###
 
841
                        self.stop_corosync()
 
842
                        self.start_corosync()
 
843
 
 
844
                monitor_fail_agent = ("""#!/usr/bin/python
 
845
import sys
 
846
def main():
 
847
    for line in sys.stdin.readlines():
 
848
        if line.count("monitor") > 0:
 
849
            sys.exit(-1);
 
850
    sys.exit(-1)
 
851
if __name__ == "__main__":
 
852
    main()
 
853
""")
 
854
                on_target_agent = ("""#!/usr/bin/python
 
855
import sys
 
856
def main():
 
857
    for line in sys.stdin.readlines():
 
858
        off_hit = 0
 
859
        nodeid_found = 0
 
860
        if line.count("monitor") > 0:
 
861
            sys.exit(0)
 
862
        if line.count("metadata") > 0:
 
863
            print '<resource-agent name="fence_dummy_metadata_helper" shortdesc="Dummy Fence agent for testing">'
 
864
            print '  <longdesc>dummy description.</longdesc>'
 
865
            print '  <vendor-url>http://www.example.com</vendor-url>'
 
866
            print '  <parameters>'
 
867
            print '    <parameter name="action" unique="0" required="1">'
 
868
            print '      <getopt mixed="-o, --action=[action]"/>'
 
869
            print '      <content type="string" default="reboot"/>'
 
870
            print '      <shortdesc lang="en">Fencing Action</shortdesc>'
 
871
            print '    </parameter>'
 
872
            print '    <parameter name="nodeid" unique="0" required="0">'
 
873
            print '      <content type="string"/>'
 
874
            print '      <shortdesc lang="en">Corosync nodeid of the fence victim</shortdesc>'
 
875
            print '    </parameter>'
 
876
            print '    <parameter name="port" unique="0" required="0">'
 
877
            print '      <getopt mixed="-n, --plug=[id]"/>'
 
878
            print '      <content type="string"/>'
 
879
            print '      <shortdesc lang="en">Physical plug number or name of virtual machine</shortdesc>'
 
880
            print '    </parameter>'
 
881
            print '  </parameters>'
 
882
            print '  <actions>'
 
883
            print '    <action name="on" on_target="1"/>'
 
884
            print '    <action name="off"/>'
 
885
            print '    <action name="monitor"/>'
 
886
            print '    <action name="metadata"/>'
 
887
            print '  </actions>'
 
888
            print '</resource-agent>'
 
889
            sys.exit(0)
 
890
        if line.count("on") > 0:
 
891
            sys.exit(0)
 
892
        if line.count("off") > 0:
 
893
            off_hit = 1
 
894
        if line.count("nodeid") > 0:
 
895
            nodeid_found = 1
 
896
 
 
897
    if off_hit and nodeid_found:
 
898
        sys.exit(0)
 
899
    sys.exit(-1)
 
900
if __name__ == "__main__":
 
901
    main()
 
902
""")
 
903
 
 
904
                os.system("cat <<-END >>/usr/sbin/fence_dummy_metadata_helper\n%s\nEND" % (on_target_agent))
 
905
                os.system("chmod 711 /usr/sbin/fence_dummy_metadata_helper")
 
906
 
 
907
                os.system("cat <<-END >>/usr/sbin/fence_dummy_monitor_fail\n%s\nEND" % (monitor_fail_agent))
 
908
                os.system("chmod 711 /usr/sbin/fence_dummy_monitor_fail")
 
909
                os.system("cp /usr/share/pacemaker/tests/cts/fence_false /usr/sbin/fence_false")
 
910
                os.system("cp /usr/share/pacemaker/tests/cts/fence_true /usr/sbin/fence_true")
 
911
 
 
912
        def cleanup_environment(self, use_corosync):
 
913
                if use_corosync:
 
914
                        self.stop_corosync()
 
915
 
 
916
                        if self.verbose and os.path.exists('/var/log/corosync.log'):
 
917
                                print "Daemon output"
 
918
                                f = open('/var/log/corosync.log', 'r')
 
919
                                for line in f.readlines():
 
920
                                        print line.strip()
 
921
                                os.remove('/var/log/corosync.log')
 
922
 
 
923
                if self.autogen_corosync_cfg:
 
924
                        os.system("rm -f /etc/corosync/corosync.conf")
 
925
 
 
926
                os.system("rm -f /usr/sbin/fence_dummy_metadata_helper")
 
927
                os.system("rm -f /usr/sbin/fence_dummy_monitor_fail")
 
928
 
 
929
class TestOptions:
 
930
        def __init__(self):
 
931
                self.options = {}
 
932
                self.options['list-tests'] = 0
 
933
                self.options['run-all'] = 1
 
934
                self.options['run-only'] = ""
 
935
                self.options['run-only-pattern'] = ""
 
936
                self.options['verbose'] = 0
 
937
                self.options['invalid-arg'] = ""
 
938
                self.options['cpg-only'] = 0
 
939
                self.options['no-cpg'] = 0
 
940
                self.options['show-usage'] = 0
 
941
 
 
942
        def build_options(self, argv):
 
943
                args = argv[1:]
 
944
                skip = 0
 
945
                for i in range(0, len(args)):
 
946
                        if skip:
 
947
                                skip = 0
 
948
                                continue
 
949
                        elif args[i] == "-h" or args[i] == "--help":
 
950
                                self.options['show-usage'] = 1
 
951
                        elif args[i] == "-l" or args[i] == "--list-tests":
 
952
                                self.options['list-tests'] = 1
 
953
                        elif args[i] == "-V" or args[i] == "--verbose":
 
954
                                self.options['verbose'] = 1
 
955
                        elif args[i] == "-n" or args[i] == "--no-cpg":
 
956
                                self.options['no-cpg'] = 1
 
957
                        elif args[i] == "-c" or args[i] == "--cpg-only":
 
958
                                self.options['cpg-only'] = 1
 
959
                        elif args[i] == "-r" or args[i] == "--run-only":
 
960
                                self.options['run-only'] = args[i+1]
 
961
                                skip = 1
 
962
                        elif args[i] == "-p" or args[i] == "--run-only-pattern":
 
963
                                self.options['run-only-pattern'] = args[i+1]
 
964
                                skip = 1
 
965
 
 
966
        def show_usage(self):
 
967
                print "usage: " + sys.argv[0] + " [options]"
 
968
                print "If no options are provided, all tests will run"
 
969
                print "Options:"
 
970
                print "\t [--help | -h]                        Show usage"
 
971
                print "\t [--list-tests | -l]                  Print out all registered tests."
 
972
                print "\t [--cpg-only | -c]                    Only run tests that require corosync."
 
973
                print "\t [--no-cpg | -n]                      Only run tests that do not require corosync"
 
974
                print "\t [--run-only | -r 'testname']         Run a specific test"
 
975
                print "\t [--verbose | -V]                     Verbose output"
 
976
                print "\t [--run-only-pattern | -p 'string']   Run only tests containing the string value"
 
977
                print "\n\tExample: Run only the test 'start_top'"
 
978
                print "\t\t python ./regression.py --run-only start_stop"
 
979
                print "\n\tExample: Run only the tests with the string 'systemd' present in them"
 
980
                print "\t\t python ./regression.py --run-only-pattern systemd"
 
981
 
 
982
def main(argv):
 
983
        o = TestOptions()
 
984
        o.build_options(argv)
 
985
 
 
986
        use_corosync = 1
 
987
 
 
988
        tests = Tests(o.options['verbose'])
 
989
        tests.build_standalone_tests()
 
990
        tests.build_custom_timeout_tests()
 
991
        tests.build_api_sanity_tests()
 
992
        tests.build_fence_merge_tests()
 
993
        tests.build_unfence_tests()
 
994
        tests.build_nodeid_tests()
 
995
 
 
996
        if o.options['list-tests']:
 
997
                tests.print_list()
 
998
                sys.exit(0)
 
999
        elif o.options['show-usage']:
 
1000
                o.show_usage()
 
1001
                sys.exit(0)
 
1002
 
 
1003
        print "Starting ..."
 
1004
 
 
1005
        if o.options['no-cpg']:
 
1006
                use_corosync = 0
 
1007
 
 
1008
        tests.setup_environment(use_corosync)
 
1009
 
 
1010
        if o.options['run-only-pattern'] != "":
 
1011
                tests.run_tests_matching(o.options['run-only-pattern'])
 
1012
                tests.print_results()
 
1013
        elif o.options['run-only'] != "":
 
1014
                tests.run_single(o.options['run-only'])
 
1015
                tests.print_results()
 
1016
        elif o.options['no-cpg']:
 
1017
                tests.run_no_cpg()
 
1018
                tests.print_results()
 
1019
        elif o.options['cpg-only']:
 
1020
                tests.run_cpg_only()
 
1021
                tests.print_results()
 
1022
        else:
 
1023
                tests.run_tests()
 
1024
                tests.print_results()
 
1025
 
 
1026
        tests.cleanup_environment(use_corosync)
 
1027
        tests.exit()
 
1028
if __name__=="__main__":
 
1029
        main(sys.argv)