diff --git a/cts/lab/CTSlab.py.in b/cts/lab/CTSlab.py.in index 2815535ec2..127ec78acb 100644 --- a/cts/lab/CTSlab.py.in +++ b/cts/lab/CTSlab.py.in @@ -1,135 +1,135 @@ #!@PYTHON@ """ Command-line interface to Pacemaker's Cluster Test Suite (CTS) """ __copyright__ = "Copyright 2001-2023 the Pacemaker project contributors" __license__ = "GNU General Public License version 2 or later (GPLv2+) WITHOUT ANY WARRANTY" import sys, signal, os pdir = os.path.dirname(sys.path[0]) sys.path.insert(0, pdir) # So that things work from the source directory try: from cts.CM_corosync import * - from cts.CTStests import TestList from cts.CTSscenarios import * from pacemaker._cts.CTS import CtsLab from pacemaker._cts.audits import audit_list from pacemaker._cts.logging import LogFactory + from pacemaker._cts.tests import test_list except ImportError as e: sys.stderr.write("abort: %s\n" % e) sys.stderr.write("check your install and PYTHONPATH; couldn't find cts libraries in:\n%s\n" % ' '.join(sys.path)) sys.exit(1) # These are globals so they can be used by the signal handler. scenario = None LogFactory().add_stderr() def sig_handler(signum, frame) : LogFactory().log("Interrupted by signal %d"%signum) if scenario: scenario.summarize() if signum == 15 : if scenario: scenario.TearDown() sys.exit(1) def plural_s(n, uppercase=False): if n == 1: return "" elif uppercase: return "S" else: return "s" if __name__ == '__main__': Environment = CtsLab(sys.argv[1:]) NumIter = Environment["iterations"] Tests = [] # Set the signal handler signal.signal(15, sig_handler) signal.signal(10, sig_handler) # Create the Cluster Manager object cm = None if Environment["Stack"] == "corosync 2+": cm = crm_corosync() else: LogFactory().log("Unknown stack: "+Environment["stack"]) sys.exit(1) if Environment["TruncateLog"]: if Environment["OutputFile"] is None: LogFactory().log("Ignoring truncate request because no output file specified") else: LogFactory().log("Truncating %s" % Environment["OutputFile"]) with open(Environment["OutputFile"], "w") as outputfile: outputfile.truncate(0) Audits = audit_list(cm) if Environment["ListTests"]: - Tests = TestList(cm, Audits) + Tests = test_list(cm, Audits) LogFactory().log("Total %d tests"%len(Tests)) for test in Tests : LogFactory().log(str(test.name)); sys.exit(0) elif len(Environment["tests"]) == 0: - Tests = TestList(cm, Audits) + Tests = test_list(cm, Audits) else: Chosen = Environment["tests"] for TestCase in Chosen: match = None - for test in TestList(cm, Audits): + for test in test_list(cm, Audits): if test.name == TestCase: match = test if not match: LogFactory().log("--choose: No applicable/valid tests chosen") sys.exit(1) else: Tests.append(match) # Scenario selection if Environment["scenario"] == "basic-sanity": scenario = RandomTests(cm, [ BasicSanityCheck(Environment) ], Audits, Tests) elif Environment["scenario"] == "all-once": NumIter = len(Tests) scenario = AllOnce( cm, [ BootCluster(Environment) ], Audits, Tests) elif Environment["scenario"] == "sequence": scenario = Sequence( cm, [ BootCluster(Environment) ], Audits, Tests) elif Environment["scenario"] == "boot": scenario = Boot(cm, [ LeaveBooted(Environment)], Audits, []) else: scenario = RandomTests( cm, [ BootCluster(Environment) ], Audits, Tests) LogFactory().log(">>>>>>>>>>>>>>>> BEGINNING " + repr(NumIter) + " TEST" + plural_s(NumIter, True) + " ") LogFactory().log("Stack: %s (%s)" % (Environment["Stack"], Environment["Name"])) LogFactory().log("Schema: %s" % Environment["Schema"]) LogFactory().log("Scenario: %s" % scenario.__doc__) LogFactory().log("CTS Exerciser: %s" % Environment["cts-exerciser"]) LogFactory().log("CTS Logfile: %s" % Environment["OutputFile"]) LogFactory().log("Random Seed: %s" % Environment["RandSeed"]) LogFactory().log("Syslog variant: %s" % Environment["syslogd"].strip()) LogFactory().log("System log files: %s" % Environment["LogFileName"]) if "IPBase" in Environment: LogFactory().log("Base IP for resources: %s" % Environment["IPBase"]) LogFactory().log("Cluster starts at boot: %d" % Environment["at-boot"]) Environment.dump() rc = Environment.run(scenario, NumIter) sys.exit(rc) diff --git a/cts/lab/CTStests.py b/cts/lab/CTStests.py deleted file mode 100644 index 885300b86f..0000000000 --- a/cts/lab/CTStests.py +++ /dev/null @@ -1,63 +0,0 @@ -""" Test-specific classes for Pacemaker's Cluster Test Suite (CTS) -""" - -__copyright__ = "Copyright 2000-2023 the Pacemaker project contributors" -__license__ = "GNU General Public License version 2 or later (GPLv2+) WITHOUT ANY WARRANTY" - -# -# SPECIAL NOTE: -# -# Tests may NOT implement any cluster-manager-specific code in them. -# EXTEND the ClusterManager object to provide the base capabilities -# the test needs if you need to do something that the current CM classes -# do not. Otherwise you screw up the whole point of the object structure -# in CTS. -# -# Thank you. -# - -import re -import time - -from stat import * - -from pacemaker import BuildOptions -from pacemaker._cts.CTS import NodeStatus -from pacemaker._cts.audits import AuditResource -from pacemaker._cts.tests import * -from pacemaker._cts.timer import Timer - -AllTestClasses = [ ] -AllTestClasses.append(FlipTest) -AllTestClasses.append(RestartTest) -AllTestClasses.append(StonithdTest) -AllTestClasses.append(StartOnebyOne) -AllTestClasses.append(SimulStart) -AllTestClasses.append(SimulStop) -AllTestClasses.append(StopOnebyOne) -AllTestClasses.append(RestartOnebyOne) -AllTestClasses.append(PartialStart) -AllTestClasses.append(StandbyTest) -AllTestClasses.append(MaintenanceMode) -AllTestClasses.append(ResourceRecover) -AllTestClasses.append(ComponentFail) -AllTestClasses.append(SplitBrainTest) -AllTestClasses.append(Reattach) -AllTestClasses.append(ResyncCIB) -AllTestClasses.append(NearQuorumPointTest) -AllTestClasses.append(RemoteBasic) -AllTestClasses.append(RemoteStonithd) -AllTestClasses.append(RemoteMigrate) -AllTestClasses.append(RemoteRscFailure) - - -def TestList(cm, audits): - result = [] - for testclass in AllTestClasses: - bound_test = testclass(cm) - if bound_test.is_applicable(): - bound_test.audits = audits - result.append(bound_test) - return result - -# vim:ts=4:sw=4:et: diff --git a/cts/lab/Makefile.am b/cts/lab/Makefile.am index f620266d65..f049ed04b9 100644 --- a/cts/lab/Makefile.am +++ b/cts/lab/Makefile.am @@ -1,30 +1,29 @@ # # Copyright 2001-2023 the Pacemaker project contributors # # The version control history for this file may have further details. # # This source code is licensed under the GNU General Public License version 2 # or later (GPLv2+) WITHOUT ANY WARRANTY. # MAINTAINERCLEANFILES = Makefile.in noinst_SCRIPTS = cluster_test \ OCFIPraTest.py # Commands intended to be run only via other commands halibdir = $(CRM_DAEMON_DIR) dist_halib_SCRIPTS = cts-log-watcher ctslibdir = $(pythondir)/cts ctslib_PYTHON = __init__.py \ CIB.py \ cib_xml.py \ ClusterManager.py \ CM_corosync.py \ - CTSscenarios.py \ - CTStests.py + CTSscenarios.py ctsdir = $(datadir)/$(PACKAGE)/tests/cts cts_SCRIPTS = CTSlab.py \ cts diff --git a/python/pacemaker/_cts/tests/__init__.py b/python/pacemaker/_cts/tests/__init__.py index 3c2fb6a51b..9703401b94 100644 --- a/python/pacemaker/_cts/tests/__init__.py +++ b/python/pacemaker/_cts/tests/__init__.py @@ -1,34 +1,86 @@ """ Test classes for the `pacemaker._cts` package. """ __copyright__ = "Copyright 2023 the Pacemaker project contributors" __license__ = "GNU Lesser General Public License version 2.1 or later (LGPLv2.1+)" from pacemaker._cts.tests.componentfail import ComponentFail from pacemaker._cts.tests.ctstest import CTSTest from pacemaker._cts.tests.fliptest import FlipTest from pacemaker._cts.tests.maintenancemode import MaintenanceMode from pacemaker._cts.tests.nearquorumpointtest import NearQuorumPointTest from pacemaker._cts.tests.partialstart import PartialStart from pacemaker._cts.tests.reattach import Reattach from pacemaker._cts.tests.restartonebyone import RestartOnebyOne from pacemaker._cts.tests.resourcerecover import ResourceRecover from pacemaker._cts.tests.restarttest import RestartTest from pacemaker._cts.tests.resynccib import ResyncCIB from pacemaker._cts.tests.remotebasic import RemoteBasic from pacemaker._cts.tests.remotedriver import RemoteDriver from pacemaker._cts.tests.remotemigrate import RemoteMigrate from pacemaker._cts.tests.remoterscfailure import RemoteRscFailure from pacemaker._cts.tests.remotestonithd import RemoteStonithd from pacemaker._cts.tests.simulstart import SimulStart from pacemaker._cts.tests.simulstop import SimulStop from pacemaker._cts.tests.simulstartlite import SimulStartLite from pacemaker._cts.tests.simulstoplite import SimulStopLite from pacemaker._cts.tests.splitbraintest import SplitBrainTest from pacemaker._cts.tests.standbytest import StandbyTest from pacemaker._cts.tests.starttest import StartTest from pacemaker._cts.tests.startonebyone import StartOnebyOne from pacemaker._cts.tests.stonithdtest import StonithdTest from pacemaker._cts.tests.stoponebyone import StopOnebyOne from pacemaker._cts.tests.stoptest import StopTest + +def test_list(cm, audits): + """ Return a list of test class objects that are enabled and whose + is_applicable methods return True. These are the tests that + should be run. + """ + + # cm is a reasonable name here. + # pylint: disable=invalid-name + + # A list of all enabled test classes, in the order that they should + # be run (if we're doing --once). There are various other ways of + # specifying which tests should be run, in which case the order here + # will not matter. + # + # Note that just because a test is listed here doesn't mean it will + # definitely be run - is_applicable is still taken into consideration. + # Also note that there are other tests that are excluded from this + # list for various reasons. + enabled_test_classes = [ FlipTest, + RestartTest, + StonithdTest, + StartOnebyOne, + SimulStart, + SimulStop, + StopOnebyOne, + RestartOnebyOne, + PartialStart, + StandbyTest, + MaintenanceMode, + ResourceRecover, + ComponentFail, + SplitBrainTest, + Reattach, + ResyncCIB, + NearQuorumPointTest, + RemoteBasic, + RemoteStonithd, + RemoteMigrate, + RemoteRscFailure, + ] + + result = [] + + for testclass in enabled_test_classes: + bound_test = testclass(cm) + + if bound_test.is_applicable(): + bound_test.audits = audits + result.append(bound_test) + + return result