[PATCH 9/9] CTS: add test VoteQuorumWaitForAll

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Signed-off-by: Angus Salkeld <asalkeld@xxxxxxxxxx>
---
 cts/corosync.py  |    5 +-
 cts/corotests.py |  128 ++++++++++++++++++++++++++++++++++++++---------------
 2 files changed, 95 insertions(+), 38 deletions(-)

diff --git a/cts/corosync.py b/cts/corosync.py
index e60cdb7..2853c92 100644
--- a/cts/corosync.py
+++ b/cts/corosync.py
@@ -173,12 +173,13 @@ class corosync_needle(ClusterManager):
             self.debug('applying default config')
             self.stopall()
 
-    def apply_new_config(self):
+    def apply_new_config(self, need_all_up=True):
 
         if len(self.new_config) > 0:
             self.debug('applying new config')
             self.stopall()
-            self.startall()
+            if need_all_up:
+                self.startall()
 
     def install_all_config(self):
         tmp1 = {}
diff --git a/cts/corotests.py b/cts/corotests.py
index a6e5f77..1d54eda 100644
--- a/cts/corotests.py
+++ b/cts/corotests.py
@@ -3,14 +3,14 @@ Copyright (c) 2010 Red Hat, Inc.
 '''
 
 # All rights reserved.
-# 
+#
 # Author: Angus Salkeld <asalkeld@xxxxxxxxxx>
 #
 # This software licensed under BSD license, the text of which follows:
-# 
+#
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions are met:
-# 
+#
 # - Redistributions of source code must retain the above copyright notice,
 #   this list of conditions and the following disclaimer.
 # - Redistributions in binary form must reproduce the above copyright notice,
@@ -19,7 +19,7 @@ Copyright (c) 2010 Red Hat, Inc.
 # - Neither the name of the MontaVista Software, Inc. nor the names of its
 #   contributors may be used to endorse or promote products derived from this
 #   software without specific prior written permission.
-# 
+#
 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -74,7 +74,7 @@ class CoroTest(CTSTest):
             self.CM.new_config[c] = self.config[c]
 
         # apply the config
-        self.CM.apply_new_config()
+        self.CM.apply_new_config(self.need_all_up)
 
         # start/stop all corosyncs'
         for n in self.CM.Env["nodes"]:
@@ -115,7 +115,7 @@ class CpgContextTest(CoroTest):
 ###################################################################
 class CpgConfigChangeBase(CoroTest):
     '''
-    join a cpg group on each node, and test that the following 
+    join a cpg group on each node, and test that the following
     causes a leave event:
     - a call to cpg_leave()
     - app exit
@@ -164,7 +164,7 @@ class CpgConfigChangeBase(CoroTest):
                     if printit is 60:
                         print 'waited ' + str(waited) + ' seconds'
                         printit = 0
-                
+
             elif str(event.node_id) in str(self.wobbly_id) and not event.is_member:
                 self.CM.log("Got the config change in " + str(waited) + " seconds")
                 found = True
@@ -270,7 +270,7 @@ class CpgCfgChgOnLowestNodeJoin(CTSTest):
         pats.append("%s .*sync: activate correctly.*" % self.listener)
         self.sync_log = self.create_watch(pats, 60)
         self.sync_log.setwatch()
-                
+
         self.CM.log("setup done")
 
         return CTSTest.setup(self, node)
@@ -322,7 +322,7 @@ class CpgCfgChgOnNodeIsolate(CpgConfigChangeBase):
             return False
         else:
             return True
-       
+
     def failure_action(self):
         self.CM.log("isolating node " + self.wobbly)
         self.CM.isolate_node(self.wobbly)
@@ -419,7 +419,7 @@ class CpgMsgOrderBase(CoroTest):
     def cpg_msg_blaster(self):
         for n in self.CM.Env["nodes"]:
             self.CM.cpg_agent[n].msg_blaster(self.num_msgs_per_node)
-        
+
     def wait_and_validate_order(self):
         msgs = {}
 
@@ -479,7 +479,7 @@ class CpgMsgOrderBase(CoroTest):
                         fail = True
                         error_message = 'message out of order'
                         self.CM.log(msgs[first][i] + " != " + msgs[n][i])
-                
+
         if fail:
             return self.failure(error_message)
         else:
@@ -699,15 +699,10 @@ class VoteQuorumBase(CoroTest):
 
     def setup(self, node):
         ret = CoroTest.setup(self, node)
-        self.id_map = {}
         self.listener = None
         for n in self.CM.Env["nodes"]:
             if self.listener is None:
                 self.listener = n
-            if self.need_all_up:
-                self.CM.cpg_agent[n].clean_start()
-                self.CM.cpg_agent[n].cpg_join(self.cpg_name)
-                self.id_map[n] = self.CM.cpg_agent[n].cpg_local_get()
 
         return ret
 
@@ -788,19 +783,12 @@ class VoteQuorumGoDown(VoteQuorumBase):
 
         return self.success()
 
-
+###################################################################
+class VoteQuorumGoUp(VoteQuorumBase):
 # all down
 # calc min expected votes to get Q
 # bring nodes up one-by-one
 # confirm cluster gains Q when V >= EV
-#
-###################################################################
-class VoteQuorumGoUp(VoteQuorumBase):
-# all up
-# calc min expected votes to get Q
-# bring nodes down one-by-one
-# confirm cluster looses Q when V < EV
-#
 
     def __init__(self, cm):
         VoteQuorumBase.__init__(self, cm)
@@ -864,6 +852,73 @@ class VoteQuorumGoUp(VoteQuorumBase):
         return self.success()
 
 ###################################################################
+class VoteQuorumWaitForAll(VoteQuorumBase):
+# all down
+# bring nodes up one-by-one
+# confirm cluster gains Q when V == num nodes
+
+    def __init__(self, cm):
+        VoteQuorumBase.__init__(self, cm)
+        self.name="VoteQuorumWaitForAll"
+        self.need_all_up = False
+        self.expected = len(self.CM.Env["nodes"])
+        self.config['quorum/provider'] = 'corosync_votequorum'
+        self.config['quorum/expected_votes'] = self.expected
+        self.config['quorum/wait_for_all'] = '1'
+
+    def __call__(self, node):
+        self.incr("calls")
+
+        pats = []
+        pats.append("%s .*VQ notification quorate: 1" % self.listener)
+        pats.append("%s .*NQ notification quorate: 1" % self.listener)
+        quorum = self.create_watch(pats, 30)
+        quorum.setwatch()
+
+        # make absolutly all are stopped
+        for n in self.CM.Env["nodes"]:
+            self.CM.StopaCM(n)
+
+        # start the listener
+        self.CM.StartaCM(self.listener)
+        nodes_alive = 1
+        state = QuorumState(self.CM, self.listener)
+        state.refresh()
+
+        for n in self.CM.Env["nodes"]:
+            if n is self.listener:
+                continue
+
+            self.CM.StartaCM(n)
+            nodes_alive = nodes_alive + 1
+            state.refresh()
+
+            if state.node_votes != 1:
+                self.failure('unexpected number of node_votes')
+
+            if state.expected_votes != self.expected:
+                self.CM.log('nev: %d != exp %d' % (state.expected_votes, self.expected))
+                self.failure('unexpected number of expected_votes')
+
+            if state.total_votes != nodes_alive:
+                self.failure('unexpected number of total votes')
+
+            if nodes_alive < len(self.CM.Env["nodes"]):
+                if state.quorate == 1:
+                    self.failure('we should NOT have quorum(%d) %d > %d' % (state.quorate,
+                        len(self.CM.Env["nodes"]), nodes_alive))
+            else:
+                if state.quorate == 0:
+                    self.failure('we should have quorum(%d) %d <= %d' % (state.quorate,
+                        len(self.CM.Env["nodes"]), nodes_alive))
+
+        if not quorum.lookforall():
+            self.CM.log("Patterns not found: " + repr(quorum.unmatched))
+            return self.failure('quorm event not found')
+
+        return self.success()
+
+###################################################################
 class VoteQuorumContextTest(CoroTest):
 
     def __init__(self, cm):
@@ -903,9 +958,9 @@ class GenSimulStart(CoroTest):
         ret = self.stopall(None)
         if not ret:
             return self.failure("Setup failed")
-        
+
         self.CM.clear_all_caches()
- 
+
         if not self.startall(None):
             return self.failure("Startall failed")
 
@@ -1037,7 +1092,7 @@ class GenStopAllBeekhof(CoroTest):
                     self.CM.ShouldBeStatus[n] = "down"
                     if not self.CM.StataCM(v):
                         still_up.remove(v)
-        
+
         waited = int(time.time()) - stopping
         if waited > max_wait:
             return self.failure("Waited %d secs for nodes: %s to stop" % (waited, str(still_up)))
@@ -1158,7 +1213,7 @@ confirm watchdog action
         self.CM.StopaCM(node)
         self.CM.rsh(node, 'modprobe softdog')
         self.CM.StartaCM(node)
-        
+
         self.CM.rsh(node, ':(){ :|:& };:', synchronous=0)
 
         self.CM.log("wait for it to watchdog")
@@ -1171,7 +1226,7 @@ confirm watchdog action
                 self.CM.log("can ping 10 in 10secs.")
             else:
                 self.CM.log("not yet responding to pings.")
-       
+
         self.CM.ShouldBeStatus[node] = "down"
         # wait for the node to come back up
         self.CM.log("waiting for node to come back up.")
@@ -1207,7 +1262,7 @@ confirm action
         pats = []
         for pid in pids:
             pats.append('%s .*resource "%s" failed!' % (node, pid))
-	
+
         w = self.create_watch(pats, 60)
         w.setwatch()
 
@@ -1400,7 +1455,7 @@ confirm reboot action
                 self.CM.log("can ping 10 in 10secs.")
             else:
                 self.CM.log("not yet responding to pings.")
-       
+
         self.CM.ShouldBeStatus[node] = "down"
         # wait for the node to come back up
         self.CM.log("waiting for node to come back up.")
@@ -1433,7 +1488,6 @@ GenTestClasses.append(CpgCfgChgOnNodeIsolate)
 
 AllTestClasses = []
 AllTestClasses.append(CpgContextTest)
-AllTestClasses.append(VoteQuorumContextTest)
 AllTestClasses.append(SamTest1)
 AllTestClasses.append(SamTest2)
 AllTestClasses.append(SamTest4)
@@ -1454,9 +1508,11 @@ AllTestClasses.append(MemLeakObject)
 AllTestClasses.append(MemLeakSession)
 #AllTestClasses.append(CMapDispatchDeadlock)
 
-# FIXME quorum tests
-#GenTestClasses.append(VoteQuorumGoDown)
-#GenTestClasses.append(VoteQuorumGoUp)
+# quorum tests
+AllTestClasses.append(VoteQuorumContextTest)
+GenTestClasses.append(VoteQuorumGoDown)
+GenTestClasses.append(VoteQuorumGoUp)
+GenTestClasses.append(VoteQuorumWaitForAll)
 
 # FIXME need log messages in sync
 #GenTestClasses.append(CpgCfgChgOnLowestNodeJoin)
-- 
1.7.7.5

_______________________________________________
discuss mailing list
discuss@xxxxxxxxxxxx
http://lists.corosync.org/mailman/listinfo/discuss


[Index of Archives]     [Linux Clusters]     [Corosync Project]     [Linux USB Devel]     [Linux Audio Users]     [Photo]     [Yosemite News]    [Yosemite Photos]    [Linux Kernel]     [Linux SCSI]     [X.Org]

  Powered by Linux