diff --git a/crmsh/crash_test/check.py b/crmsh/crash_test/check.py deleted file mode 100644 index 850a4560e..000000000 --- a/crmsh/crash_test/check.py +++ /dev/null @@ -1,317 +0,0 @@ -import re -import os - -from crmsh import utils as crmshutils -from crmsh import bootstrap as crmshboot -from crmsh import completers - -from . import utils -from . import task -from . import config -from ..service_manager import ServiceManager -from ..sh import ShellUtils - - -def fix(context): - """ - Check configuration and fix the abnormal options - """ - if context.check_conf: - candidate = check_sbd() - if candidate != "": - correct_sbd(context, candidate) - print() - - -def check_sbd(): - """ - Check the sbd device and find a possible fix for incorrect disk - - Only support one path SBD_DEVICE in the current version - """ - print("\n============ Checking the SBD device ============") - task_inst = task.TaskCheck("Checking SBD device") - - with task_inst.run(): - - if not os.path.exists(config.SBD_CONF): - task_inst.info("SBD configuration file {} not found.". - format(config.SBD_CONF)) - return "" - - sbd_options = crmshutils.parse_sysconfig(config.SBD_CONF) - - if not "SBD_DEVICE" in sbd_options: - task_inst.info("SBD DEVICE not used.") - return "" - - dev = sbd_options["SBD_DEVICE"] - - if not os.path.exists(dev): - task_inst.warn("SBD device '{}' is not exist.".format(dev)) - else: - if utils.is_valid_sbd(dev): - task_inst.info("'{}' is a valid SBD device.".format(dev)) - return "" - else: - task_inst.warn("Device '{}' is not valid for SBD, may need initialize." - .format(dev)) - - candidate = utils.find_candidate_sbd(dev) - - if candidate == "": - task_inst.warn("Fail to find a valid candidate SBD device.") - return "" - - task_inst.info("Found '{}' with SBD header exist.".format(candidate)) - - return candidate - - -def correct_sbd(context, can): - """ - Fix the sbd device conf with candidate device - - Only support one path SBD_DEVICE in the current version - """ - - task_inst = task.TaskFixSBD(can, context.force) - try: - task_inst.pre_check() - task_inst.print_header() - with task_inst.backup(): - task_inst.run() - task_inst.verify() - except task.TaskError as err: - task_inst.error(str(err)) - raise crmshutils.TerminateSubCommand - - -def check(context): - """ - Check environment and cluster state if related options are enabled - """ - if context.cluster_check: - check_cluster() - print() - - -def check_environment(): - """ - A set of functions to check environment - """ - print("\n============ Checking environment ============") - check_my_hostname_resolves() - check_time_service() - check_firewall() - - -def check_my_hostname_resolves(): - """ - check if the hostname is resolvable - """ - task_inst = task.TaskCheck("Checking hostname resolvable") - with task_inst.run(): - if not crmshboot.my_hostname_resolves(): - task_inst.error('''Hostname "{}" is unresolvable. - Please add an entry to /etc/hosts or configure DNS.'''.format(utils.this_node())) - - -def check_time_service(): - """ - Check time service - """ - task_inst = task.TaskCheck("Checking time service") - with task_inst.run(): - service_manager = ServiceManager() - timekeepers = ('chronyd.service', 'ntp.service', 'ntpd.service') - timekeeper = None - for tk in timekeepers: - if service_manager.service_is_available(tk): - timekeeper = tk - break - else: - task_inst.warn("No NTP service found.") - return - - task_inst.info("{} is available".format(timekeeper)) - if service_manager.service_is_enabled(timekeeper): - task_inst.info("{} is enabled".format(timekeeper)) - else: - task_inst.warn("{} is disabled".format(timekeeper)) - if service_manager.service_is_active(timekeeper): - task_inst.info("{} is active".format(timekeeper)) - else: - task_inst.warn("{} is not active".format(timekeeper)) - - -def check_port_open(task, firewall_type): - """ - Check whether corosync port is blocked by iptables - """ - ports = utils.corosync_port_list() - if not ports: - task.error("Can not get corosync's port") - return - - if firewall_type == "firewalld": - rc, out, err = ShellUtils().get_stdout_stderr('firewall-cmd --list-port') - if rc != 0: - task.error(err) - return - for p in ports: - if re.search(' {}/udp'.format(p), out): - task.info("UDP port {} is opened in firewalld".format(p)) - else: - task.error("UDP port {} should open in firewalld".format(p)) - - -def check_firewall(): - """ - Check the firewall status - """ - task_inst = task.TaskCheck("Checking firewall") - with task_inst.run(): - for item in ("firewalld", ): - if crmshutils.package_is_installed(item): - task_inst.info("{}.service is available".format(item)) - if ServiceManager().service_is_active(item): - task_inst.info("{}.service is active".format(item)) - check_port_open(task_inst, item) - else: - task_inst.warn("{}.service is not active".format(item)) - break - else: - task_inst.warn("Failed to detect firewall") - - -def check_cluster(): - """ - A set of functions to check cluster state - """ - print("\n============ Checking cluster state ============") - if not check_cluster_service(): - return - check_fencing() - check_nodes() - check_resources() - - -def check_cluster_service(quiet=False): - """ - Check service status of pacemaker/corosync - """ - task_inst = task.TaskCheck("Checking cluster service", quiet=quiet) - with task_inst.run(): - service_manager = ServiceManager() - if service_manager.service_is_enabled("pacemaker"): - task_inst.info("pacemaker.service is enabled") - else: - task_inst.warn("pacemaker.service is disabled") - - if service_manager.service_is_enabled("corosync"): - task_inst.warn("corosync.service is enabled") - - for s in ("corosync", "pacemaker"): - if service_manager.service_is_active(s): - task_inst.info("{}.service is running".format(s)) - else: - task_inst.error("{}.service is not running!".format(s)) - return task_inst.passed - - -def check_fencing(): - """ - Check STONITH/Fence: - Whether stonith is enabled - Whether stonith resource is configured and running - """ - task_inst = task.TaskCheck("Checking STONITH/Fence") - with task_inst.run(): - if not utils.FenceInfo().fence_enabled: - task_inst.warn("stonith is disabled") - return - - task_inst.info("stonith is enabled") - rc, outp, _ = ShellUtils().get_stdout_stderr("crm_mon -r1 | grep '(stonith:.*):'") - if rc != 0: - task_inst.warn("No stonith resource configured!") - return - - res = re.search(r'([^\s]+)\s+\(stonith:(.*)\):\s+(\w+)', outp) - res_name, res_agent, res_state = res.groups() - common_msg = "stonith resource {}({})".format(res_name, res_agent) - state_msg = "{} is {}".format(common_msg, res_state) - - task_inst.info("{} is configured".format(common_msg)) - if res_state == "Started": - task_inst.info(state_msg) - else: - task_inst.warn(state_msg) - - if re.search(r'sbd$', res_agent): - if ServiceManager().service_is_active("sbd"): - task_inst.info("sbd service is running") - else: - task_inst.warn("sbd service is not running!") - - -def check_nodes(): - """ - Check nodes info: - Current DC - Quorum status - Online/OFFLINE/UNCLEAN nodes - """ - task_inst = task.TaskCheck("Checking nodes") - with task_inst.run(): - rc, outp, errp = ShellUtils().get_stdout_stderr("crm_mon -1") - if rc != 0: - task_inst.error("run \"crm_mon -1\" error: {}".format(errp)) - return - # check DC - res = re.search(r'Current DC: (.*) \(', outp) - if res: - task_inst.info("DC node: {}".format(res.group(1))) - - # check quorum - if re.search(r'partition with quorum', outp): - task_inst.info("Cluster have quorum") - else: - task_inst.warn("Cluster lost quorum!") - - # check Online nodes - res = re.search(r'Online:\s+(\[.*\])', outp) - if res: - task_inst.info("Online nodes: {}".format(res.group(1))) - - # check OFFLINE nodes - res = re.search(r'OFFLINE:\s+(\[.*\])', outp) - if res: - task_inst.warn("OFFLINE nodes: {}".format(res.group(1))) - - # check UNCLEAN nodes - res = re.findall(r'Node (.*): UNCLEAN', outp) - for item in res: - task_inst.warn('Node {} is UNCLEAN!'.format(item)) - - -def check_resources(): - """ - Check items of Started/Stopped/FAILED resources - """ - task_inst = task.TaskCheck("Checking resources") - with task_inst.run(): - started_list = completers.resources(["stop"]) - stopped_list = completers.resources(["start"]) - # TODO need suitable method to get failed resources list - failed_list = [] - if started_list: - task_inst.info("Started resources: {}".format(','.join(started_list))) - if stopped_list: - task_inst.info("Stopped resources: {}".format(','.join(stopped_list))) - if failed_list: - task_inst.warn("Failed resources: {}".format(','.join(failed_list))) - - if not (started_list or stopped_list or failed_list): - task_inst.info("No resources configured") diff --git a/crmsh/crash_test/config.py b/crmsh/crash_test/config.py index 4d900fdf1..3a7704c8d 100644 --- a/crmsh/crash_test/config.py +++ b/crmsh/crash_test/config.py @@ -5,4 +5,3 @@ REMOVE_PORT = "firewall-cmd --zone=public --remove-port={port}/udp" ADD_PORT = "firewall-cmd --zone=public --add-port={port}/udp" SBD_CONF = "/etc/sysconfig/sbd" -SBD_CHECK_CMD = "sbd -d {dev} dump" diff --git a/crmsh/crash_test/main.py b/crmsh/crash_test/main.py index dde177cd9..eb8dfadc8 100644 --- a/crmsh/crash_test/main.py +++ b/crmsh/crash_test/main.py @@ -3,7 +3,6 @@ import argparse from argparse import RawDescriptionHelpFormatter -from . import check from . import utils from . import task from crmsh import utils as crmshutils @@ -30,8 +29,6 @@ def __init__(self): self.current_case = None # set by argparse(functions) - self.check_conf = None - self.cluster_check = None self.sbd = None self.corosync = None self.pacemakerd = None @@ -142,9 +139,6 @@ def parse_argument(context): context.jsonfile, context.report_path)) - #parser.add_argument('-c', '--check-conf', dest='check_conf', action='store_true', - # help='Validate the configurations') - group_mutual = parser.add_mutually_exclusive_group() group_mutual.add_argument('--kill-sbd', dest='sbd', action='store_true', help='Kill sbd daemon') @@ -198,8 +192,6 @@ def run(context): os.makedirs(context.var_dir, exist_ok=True) try: - check.fix(context) - check.check(context) kill_process(context) fence_node(context) split_brain(context) diff --git a/crmsh/crash_test/utils.py b/crmsh/crash_test/utils.py index f992a81b7..f8a05611c 100644 --- a/crmsh/crash_test/utils.py +++ b/crmsh/crash_test/utils.py @@ -11,6 +11,7 @@ from crmsh import log from crmsh.sh import ShellUtils from crmsh import constants +from crmsh import xmlutil logger = log.setup_logger(__name__) @@ -151,12 +152,7 @@ def online_nodes(): """ Get online node list """ - rc, stdout, stderr = ShellUtils().get_stdout_stderr('crm_mon -1') - if rc == 0 and stdout: - res = re.search(r'Online:\s+\[\s(.*)\s\]', stdout) - if res: - return res.group(1).split() - return [] + return xmlutil.CrmMonXmlParser().get_node_list(online=True, node_type='member') def peer_node_list(): @@ -186,17 +182,6 @@ def str_to_datetime(str_time, fmt): return datetime.strptime(str_time, fmt) -def corosync_port_list(): - """ - Get corosync ports using corosync-cmapctl - """ - ports = [] - rc, out, _ = ShellUtils().get_stdout_stderr("corosync-cmapctl totem.interface") - if rc == 0 and out: - ports = re.findall(r'(?:mcastport.*) ([0-9]+)', out) - return ports - - def get_handler(logger, _type): """ Get logger specific handler @@ -233,72 +218,6 @@ def get_process_status(s): return False, -1 -def _find_match_count(str1, str2): - """ - Find the max match number of s1 and s2 - """ - leng = min(len(str1), len(str2)) - num = 0 - - for i in range(leng): - if str1[i] == str2[i]: - num += 1 - else: - break - - return num - - -def is_valid_sbd(dev): - """ - Check whether the device is a initialized SBD device - - dev: dev path - return 'True' if 'dev' is a initialized SBD device - """ - if not os.path.exists(dev): - return False - - rc, out, err = ShellUtils().get_stdout_stderr(config.SBD_CHECK_CMD.format(dev=dev)) - if rc != 0 and err: - msg_error(err) - return False - - return True - - -def find_candidate_sbd(dev): - """ - Find the devices that already have SBD header - - return the path of candidate SBD device - """ - ddir = os.path.dirname(dev) - dname = os.path.basename(dev) - - dev_list = glob.glob(ddir + "/*") - if len(dev_list) == 0: - return "" - - can_filter = filter(is_valid_sbd, dev_list) - candidates = list(can_filter) - - if len(candidates) == 0: - return "" - - index = 0 - i = 0 - max_match = -1 - num_list = map(_find_match_count, [dev] * len(candidates), candidates) - for num in num_list: - if num > max_match: - max_match = num - index = i - i += 1 - - return candidates[index] - - def warning_ask(warn_string): from . import main if main.ctx.force: diff --git a/crmsh/utils.py b/crmsh/utils.py index f9e209bd2..cc22b1b87 100644 --- a/crmsh/utils.py +++ b/crmsh/utils.py @@ -2731,31 +2731,14 @@ def is_dlm_running(peer=None): """ Check if dlm ra controld is running """ - return is_resource_running(constants.DLM_CONTROLD_RA, peer=peer) - - -def has_resource_configured(ra_type, peer=None): - """ - Check if the RA configured - """ - out = sh.cluster_shell().get_stdout_or_raise_error("crm_mon -1rR", peer) - return re.search(ra_type, out) is not None - - -def is_resource_running(ra_type, peer=None): - """ - Check if the RA running - """ - out = sh.cluster_shell().get_stdout_or_raise_error("crm_mon -1rR", peer) - patt = f"\\({ra_type}\\):\\s*Started" - return re.search(patt, out) is not None + return xmlutil.CrmMonXmlParser(peer).is_resource_started(constants.DLM_CONTROLD_RA) def is_dlm_configured(peer=None): """ Check if dlm configured """ - return has_resource_configured(constants.DLM_CONTROLD_RA, peer=peer) + return xmlutil.CrmMonXmlParser(peer).is_resource_configured(constants.DLM_CONTROLD_RA) def is_quorate(peer=None): diff --git a/data-manifest b/data-manifest index 59c42d01e..91014113c 100644 --- a/data-manifest +++ b/data-manifest @@ -193,7 +193,6 @@ test/unittests/test_cluster_fs.py test/unittests/test.conf test/unittests/test_corosync_config_format.py test/unittests/test_corosync.py -test/unittests/test_crashtest_check.py test/unittests/test_crashtest_main.py test/unittests/test_crashtest_task.py test/unittests/test_crashtest_utils.py diff --git a/test/unittests/test_crashtest_check.py b/test/unittests/test_crashtest_check.py deleted file mode 100644 index a4a5b4b70..000000000 --- a/test/unittests/test_crashtest_check.py +++ /dev/null @@ -1,785 +0,0 @@ -import os -import sys - -try: - from unittest import mock, TestCase -except ImportError: - import mock - -from crmsh import utils as crmshutils -from crmsh.crash_test import check, config - - -class TestCheck(TestCase): - - @mock.patch('crmsh.crash_test.check.check_cluster') - def test_check(self, mock_cluster_check): - ctx = mock.Mock(cluster_check=True) - check.check(ctx) - mock_cluster_check.assert_called_once_with() - - @mock.patch('crmsh.crash_test.check.check_firewall') - @mock.patch('crmsh.crash_test.check.check_time_service') - @mock.patch('crmsh.crash_test.check.check_my_hostname_resolves') - def test_check_environment(self, mock_hostname, mock_time, mock_firewall): - check.check_environment() - mock_hostname.assert_called_once_with() - mock_time.assert_called_once_with() - mock_firewall.assert_called_once_with() - - @mock.patch('crmsh.crash_test.utils.this_node') - @mock.patch('crmsh.crash_test.check.crmshboot.my_hostname_resolves') - @mock.patch('crmsh.crash_test.task.TaskCheck') - def test_check_my_hostname_resolves(self, mock_task_check, mock_hostname, mock_this_node): - mock_task_inst = mock.Mock() - mock_task_check.return_value = mock_task_inst - mock_task_inst.run.return_value.__enter__ = mock.Mock() - mock_task_inst.run.return_value.__exit__ = mock.Mock() - mock_hostname.return_value = False - mock_this_node.return_value = "node1" - - check.check_my_hostname_resolves() - - mock_task_check.assert_called_once_with("Checking hostname resolvable") - mock_hostname.assert_called_once_with() - mock_task_inst.error.assert_called_once_with('Hostname "node1" is unresolvable.\n Please add an entry to /etc/hosts or configure DNS.') - - @mock.patch('crmsh.service_manager.ServiceManager.service_is_active') - @mock.patch('crmsh.service_manager.ServiceManager.service_is_enabled') - @mock.patch('crmsh.service_manager.ServiceManager.service_is_available') - @mock.patch('crmsh.crash_test.task.TaskCheck') - def test_check_time_service_none(self, mock_task, mock_service_available, mock_service_enabled, mock_service_active): - mock_task_inst = mock.Mock() - mock_task.return_value = mock_task_inst - mock_task_inst.run.return_value.__enter__ = mock.Mock() - mock_task_inst.run.return_value.__exit__ = mock.Mock() - mock_service_available.side_effect = [False, False, False] - - check.check_time_service() - - mock_task.assert_called_once_with("Checking time service") - mock_service_available.assert_has_calls([ - mock.call('chronyd.service'), - mock.call('ntp.service'), - mock.call('ntpd.service') - ]) - mock_task_inst.warn.assert_called_once_with("No NTP service found.") - - @mock.patch('crmsh.service_manager.ServiceManager.service_is_active') - @mock.patch('crmsh.service_manager.ServiceManager.service_is_enabled') - @mock.patch('crmsh.service_manager.ServiceManager.service_is_available') - @mock.patch('crmsh.crash_test.task.TaskCheck') - def test_check_time_service_warn(self, mock_task, mock_service_available, mock_service_enabled, mock_service_active): - mock_task_inst = mock.Mock() - mock_task.return_value = mock_task_inst - mock_task_inst.run.return_value.__enter__ = mock.Mock() - mock_task_inst.run.return_value.__exit__ = mock.Mock() - mock_service_available.return_value = True - mock_service_enabled.return_value = False - mock_service_active.return_value = False - - check.check_time_service() - - mock_task.assert_called_once_with("Checking time service") - mock_service_available.assert_called_once_with("chronyd.service") - mock_task_inst.info.assert_called_once_with("chronyd.service is available") - mock_task_inst.warn.assert_has_calls([ - mock.call("chronyd.service is disabled"), - mock.call("chronyd.service is not active"), - ]) - - @mock.patch('crmsh.service_manager.ServiceManager.service_is_active') - @mock.patch('crmsh.service_manager.ServiceManager.service_is_enabled') - @mock.patch('crmsh.service_manager.ServiceManager.service_is_available') - @mock.patch('crmsh.crash_test.task.TaskCheck') - def test_check_time_service(self, mock_task, mock_service_available, mock_service_enabled, mock_service_active): - mock_task_inst = mock.Mock() - mock_task.return_value = mock_task_inst - mock_task_inst.run.return_value.__enter__ = mock.Mock() - mock_task_inst.run.return_value.__exit__ = mock.Mock() - mock_service_available.return_value = True - mock_service_enabled.return_value = True - mock_service_active.return_value = True - - check.check_time_service() - - mock_task.assert_called_once_with("Checking time service") - mock_service_available.assert_called_once_with("chronyd.service") - mock_task_inst.info.assert_has_calls([ - mock.call("chronyd.service is available"), - mock.call("chronyd.service is enabled"), - mock.call("chronyd.service is active") - ]) - - @mock.patch('crmsh.sh.ShellUtils.get_stdout_stderr') - @mock.patch('crmsh.crash_test.utils.corosync_port_list') - def test_check_port_open_return(self, mock_corosync_port, mock_run): - mock_corosync_port.return_value = ["1234", "5678"] - mock_run.return_value = (1, None, "error") - task_inst = mock.Mock() - - check.check_port_open(task_inst, "firewalld") - - mock_corosync_port.assert_called_once_with() - task_inst.error.assert_called_once_with("error") - mock_run.assert_called_once_with("firewall-cmd --list-port") - - @mock.patch('crmsh.crash_test.utils.corosync_port_list') - def test_check_port_open_fail_to_get_port(self, mock_corosync_port): - mock_corosync_port.return_value = [] - task_inst = mock.Mock() - - check.check_port_open(task_inst, "firewalld") - - mock_corosync_port.assert_called_once_with() - task_inst.error.assert_called_once_with("Can not get corosync's port") - - @mock.patch('crmsh.sh.ShellUtils.get_stdout_stderr') - @mock.patch('crmsh.crash_test.utils.corosync_port_list') - def test_check_port_open(self, mock_corosync_port, mock_run): - mock_corosync_port.return_value = ["1234", "5678"] - output_cmd = """ - 1234/udp - 4444/tcp - """ - mock_run.return_value = (0, output_cmd, None) - task_inst = mock.Mock() - - check.check_port_open(task_inst, "firewalld") - - mock_corosync_port.assert_called_once_with() - task_inst.error.assert_called_once_with("UDP port 5678 should open in firewalld") - mock_run.assert_called_once_with("firewall-cmd --list-port") - task_inst.info.assert_called_once_with("UDP port 1234 is opened in firewalld") - - @mock.patch('crmsh.crash_test.check.crmshutils.package_is_installed') - @mock.patch('crmsh.crash_test.task.TaskCheck') - def test_check_firewall_not_intalled(self, mock_task, mock_installed): - mock_task_inst = mock.Mock() - mock_task.return_value = mock_task_inst - mock_task_inst.run.return_value.__enter__ = mock.Mock() - mock_task_inst.run.return_value.__exit__ = mock.Mock() - mock_installed.side_effect = [False, False] - - check.check_firewall() - - mock_task.assert_called_once_with("Checking firewall") - mock_installed.assert_called_once_with("firewalld") - mock_task_inst.warn.assert_called_once_with("Failed to detect firewall") - - @mock.patch('crmsh.service_manager.ServiceManager.service_is_active') - @mock.patch('crmsh.crash_test.check.crmshutils.package_is_installed') - @mock.patch('crmsh.crash_test.task.TaskCheck') - def test_check_firewall_warn(self, mock_task, mock_installed, mock_active): - mock_task_inst = mock.Mock() - mock_task.return_value = mock_task_inst - mock_task_inst.run.return_value.__enter__ = mock.Mock() - mock_task_inst.run.return_value.__exit__ = mock.Mock() - mock_installed.return_value = True - mock_active.return_value = False - - check.check_firewall() - - mock_task.assert_called_once_with("Checking firewall") - mock_installed.assert_called_once_with("firewalld") - mock_task_inst.info.assert_called_once_with("firewalld.service is available") - mock_task_inst.warn.assert_called_once_with("firewalld.service is not active") - - @mock.patch('crmsh.crash_test.check.check_port_open') - @mock.patch('crmsh.service_manager.ServiceManager.service_is_active') - @mock.patch('crmsh.crash_test.check.crmshutils.package_is_installed') - @mock.patch('crmsh.crash_test.task.TaskCheck') - def test_check_firewall(self, mock_task, mock_installed, mock_active, mock_check_port): - mock_task_inst = mock.Mock() - mock_task.return_value = mock_task_inst - mock_task_inst.run.return_value.__enter__ = mock.Mock() - mock_task_inst.run.return_value.__exit__ = mock.Mock() - mock_installed.return_value = True - mock_active.return_value = True - - check.check_firewall() - - mock_task.assert_called_once_with("Checking firewall") - mock_installed.assert_called_once_with("firewalld") - mock_task_inst.info.assert_has_calls([ - mock.call("firewalld.service is available"), - mock.call("firewalld.service is active") - ]) - mock_active.assert_called_once_with("firewalld") - mock_check_port.assert_called_once_with(mock_task_inst, "firewalld") - - @mock.patch('crmsh.crash_test.check.check_cluster_service') - def test_check_cluster_return(self, mock_check_cluster): - mock_check_cluster.return_value = False - check.check_cluster() - mock_check_cluster.assert_called_once_with() - - @mock.patch('crmsh.crash_test.check.check_resources') - @mock.patch('crmsh.crash_test.check.check_nodes') - @mock.patch('crmsh.crash_test.check.check_fencing') - @mock.patch('crmsh.crash_test.check.check_cluster_service') - def test_check_cluster(self, mock_check_cluster, mock_check_fencing, mock_check_nodes, mock_check_resources): - mock_check_cluster.return_value = True - check.check_cluster() - mock_check_cluster.assert_called_once_with() - mock_check_fencing.assert_called_once_with() - mock_check_nodes.assert_called_once_with() - mock_check_resources.assert_called_once_with() - - @mock.patch('crmsh.service_manager.ServiceManager.service_is_active') - @mock.patch('crmsh.service_manager.ServiceManager.service_is_enabled') - @mock.patch('crmsh.crash_test.task.TaskCheck') - def test_check_cluster_service_pacemaker_disable(self, mock_task, mock_enabled, mock_active): - mock_task_inst = mock.Mock(passed=False) - mock_task.return_value = mock_task_inst - mock_task_inst.run.return_value.__enter__ = mock.Mock() - mock_task_inst.run.return_value.__exit__ = mock.Mock() - mock_enabled.side_effect = [False, True] - mock_active.side_effect = [True, False] - - res = check.check_cluster_service() - self.assertEqual(res, False) - - mock_task.assert_called_once_with("Checking cluster service", quiet=False) - mock_enabled.assert_has_calls([ - mock.call("pacemaker"), - mock.call("corosync") - ]) - mock_task_inst.warn.assert_has_calls([ - mock.call("pacemaker.service is disabled"), - mock.call("corosync.service is enabled") - ]) - mock_active.assert_has_calls([ - mock.call("corosync"), - mock.call("pacemaker") - ]) - mock_task_inst.info.assert_called_once_with("corosync.service is running") - mock_task_inst.error.assert_called_once_with("pacemaker.service is not running!") - - @mock.patch('crmsh.service_manager.ServiceManager.service_is_active') - @mock.patch('crmsh.service_manager.ServiceManager.service_is_enabled') - @mock.patch('crmsh.crash_test.task.TaskCheck') - def test_check_cluster_service(self, mock_task, mock_enabled, mock_active): - mock_task_inst = mock.Mock(passed=True) - mock_task.return_value = mock_task_inst - mock_task_inst.run.return_value.__enter__ = mock.Mock() - mock_task_inst.run.return_value.__exit__ = mock.Mock() - mock_enabled.side_effect = [True, True] - mock_active.side_effect = [True, True] - - res = check.check_cluster_service() - self.assertEqual(res, True) - - mock_task.assert_called_once_with("Checking cluster service", quiet=False) - mock_enabled.assert_has_calls([ - mock.call("pacemaker"), - mock.call("corosync") - ]) - mock_active.assert_has_calls([ - mock.call("corosync"), - mock.call("pacemaker") - ]) - mock_task_inst.info.assert_has_calls([ - mock.call("pacemaker.service is enabled"), - mock.call("corosync.service is running"), - mock.call("pacemaker.service is running") - ]) - mock_task_inst.warn.assert_called_once_with("corosync.service is enabled") - - @mock.patch('crmsh.crash_test.utils.FenceInfo') - @mock.patch('crmsh.crash_test.task.TaskCheck') - def test_check_fencing_no_stonith(self, mock_task, mock_fence_info): - mock_task_inst = mock.Mock() - mock_task.return_value = mock_task_inst - mock_task_inst.run.return_value.__enter__ = mock.Mock() - mock_task_inst.run.return_value.__exit__ = mock.Mock() - mock_fence_info_inst = mock.Mock(fence_enabled=False) - mock_fence_info.return_value = mock_fence_info_inst - - check.check_fencing() - - mock_task.assert_called_once_with("Checking STONITH/Fence") - mock_fence_info.assert_called_once_with() - mock_task_inst.warn.assert_called_once_with("stonith is disabled") - - @mock.patch('crmsh.sh.ShellUtils.get_stdout_stderr') - @mock.patch('crmsh.crash_test.utils.FenceInfo') - @mock.patch('crmsh.crash_test.task.TaskCheck') - def test_check_fencing_no_resources(self, mock_task, mock_fence_info, mock_run): - mock_task_inst = mock.Mock() - mock_task.return_value = mock_task_inst - mock_task_inst.run.return_value.__enter__ = mock.Mock() - mock_task_inst.run.return_value.__exit__ = mock.Mock() - mock_fence_info_inst = mock.Mock(fence_enabled=True) - mock_fence_info.return_value = mock_fence_info_inst - mock_run.return_value = (1, None, None) - - check.check_fencing() - - mock_task.assert_called_once_with("Checking STONITH/Fence") - mock_fence_info.assert_called_once_with() - mock_run.assert_called_once_with("crm_mon -r1 | grep '(stonith:.*):'") - mock_task_inst.info.assert_called_once_with("stonith is enabled") - mock_task_inst.warn.assert_called_once_with("No stonith resource configured!") - - @mock.patch('crmsh.service_manager.ServiceManager.service_is_active') - @mock.patch('crmsh.sh.ShellUtils.get_stdout_stderr') - @mock.patch('crmsh.crash_test.utils.FenceInfo') - @mock.patch('crmsh.crash_test.task.TaskCheck') - def test_check_fencing_has_warn(self, mock_task, mock_fence_info, mock_run, mock_active): - mock_task_inst = mock.Mock() - mock_task.return_value = mock_task_inst - mock_task_inst.run.return_value.__enter__ = mock.Mock() - mock_task_inst.run.return_value.__exit__ = mock.Mock() - mock_fence_info_inst = mock.Mock(fence_enabled=True) - mock_fence_info.return_value = mock_fence_info_inst - mock_run.return_value = (0, "* stonith-sbd (stonith:fence_sbd): Stopped (disabled)", None) - mock_active.return_value = False - - check.check_fencing() - - mock_task.assert_called_once_with("Checking STONITH/Fence") - mock_fence_info.assert_called_once_with() - mock_run.assert_called_once_with("crm_mon -r1 | grep '(stonith:.*):'") - mock_task_inst.info.assert_has_calls([ - mock.call("stonith is enabled"), - mock.call("stonith resource stonith-sbd(fence_sbd) is configured") - ]) - mock_task_inst.warn.assert_has_calls([ - mock.call("stonith resource stonith-sbd(fence_sbd) is Stopped"), - mock.call("sbd service is not running!") - ]) - - @mock.patch('crmsh.service_manager.ServiceManager.service_is_active') - @mock.patch('crmsh.sh.ShellUtils.get_stdout_stderr') - @mock.patch('crmsh.crash_test.utils.FenceInfo') - @mock.patch('crmsh.crash_test.task.TaskCheck') - def test_check_fencing(self, mock_task, mock_fence_info, mock_run, mock_active): - mock_task_inst = mock.Mock() - mock_task.return_value = mock_task_inst - mock_task_inst.run.return_value.__enter__ = mock.Mock() - mock_task_inst.run.return_value.__exit__ = mock.Mock() - mock_fence_info_inst = mock.Mock(fence_enabled=True) - mock_fence_info.return_value = mock_fence_info_inst - mock_run.return_value = (0, "* stonith-sbd (stonith:fence_sbd): Started node2", None) - mock_active.return_value = True - - check.check_fencing() - - mock_task.assert_called_once_with("Checking STONITH/Fence") - mock_fence_info.assert_called_once_with() - mock_run.assert_called_once_with("crm_mon -r1 | grep '(stonith:.*):'") - mock_task_inst.info.assert_has_calls([ - mock.call("stonith is enabled"), - mock.call("stonith resource stonith-sbd(fence_sbd) is configured"), - mock.call("stonith resource stonith-sbd(fence_sbd) is Started"), - mock.call("sbd service is running") - ]) - mock_active.assert_called_once_with("sbd") - - @mock.patch('crmsh.sh.ShellUtils.get_stdout_stderr') - @mock.patch('crmsh.crash_test.task.TaskCheck') - def test_check_nodes_error(self, mock_task, mock_run): - mock_task_inst = mock.Mock() - mock_task.return_value = mock_task_inst - mock_task_inst.run.return_value.__enter__ = mock.Mock() - mock_task_inst.run.return_value.__exit__ = mock.Mock() - mock_run.return_value = (1, None, "error data") - - check.check_nodes() - - mock_task.assert_called_once_with("Checking nodes") - mock_run.assert_called_once_with("crm_mon -1") - mock_task_inst.error.assert_called_once_with("run \"crm_mon -1\" error: error data") - - @mock.patch('crmsh.sh.ShellUtils.get_stdout_stderr') - @mock.patch('crmsh.crash_test.task.TaskCheck') - def test_check_nodes(self, mock_task, mock_run): - mock_task_inst = mock.Mock() - mock_task.return_value = mock_task_inst - mock_task_inst.run.return_value.__enter__ = mock.Mock() - mock_task_inst.run.return_value.__exit__ = mock.Mock() - output = """ -Cluster Summary: - * Stack: corosync - * Current DC: 15sp2-1 (version 2.0.3+20200511.2b248d828-1.10-2.0.3+20200511.2b248d828) - partition with quorum - * Last updated: Tue Nov 3 14:09:29 2020 - * Last change: Tue Nov 3 13:47:29 2020 by root via cibadmin on 15sp2-1 - * 2 nodes configured - * 1 resource instance configured (1 DISABLED) - -Node List: - * Online: [ 15sp2-1 ] - * OFFLINE: [ 15sp2-2 ] - """ - mock_run.return_value = (0, output, None) - - check.check_nodes() - - mock_task.assert_called_once_with("Checking nodes") - mock_run.assert_called_once_with("crm_mon -1") - mock_task_inst.info.assert_has_calls([ - mock.call("DC node: 15sp2-1"), - mock.call("Cluster have quorum"), - mock.call("Online nodes: [ 15sp2-1 ]") - ]) - mock_task_inst.warn.assert_called_once_with("OFFLINE nodes: [ 15sp2-2 ]") - - @mock.patch('crmsh.sh.ShellUtils.get_stdout_stderr') - @mock.patch('crmsh.crash_test.task.TaskCheck') - def test_check_nodes_warn(self, mock_task, mock_run): - mock_task_inst = mock.Mock() - mock_task.return_value = mock_task_inst - mock_task_inst.run.return_value.__enter__ = mock.Mock() - mock_task_inst.run.return_value.__exit__ = mock.Mock() - output = """ -Cluster Summary: - * Stack: corosync - * Current DC: NONE - * Last updated: Tue Nov 3 14:16:49 2020 - * Last change: Tue Nov 3 14:09:29 2020 by root via cibadmin on 15sp2-1 - * 2 nodes configured - * 1 resource instance configured (1 DISABLED) - -Node List: - * Node 15sp2-1: UNCLEAN (offline) - * Node 15sp2-2: UNCLEAN (offline) - -Active Resources: - * No active resources - """ - mock_run.return_value = (0, output, None) - - check.check_nodes() - - mock_task.assert_called_once_with("Checking nodes") - mock_run.assert_called_once_with("crm_mon -1") - mock_task_inst.warn.assert_has_calls([ - mock.call("Cluster lost quorum!"), - mock.call("Node 15sp2-1 is UNCLEAN!"), - mock.call("Node 15sp2-2 is UNCLEAN!") - ]) - - @mock.patch('crmsh.crash_test.check.completers.resources') - @mock.patch('crmsh.crash_test.task.TaskCheck') - def test_check_resources(self, mock_task, mock_resources): - mock_task_inst = mock.Mock() - mock_task.return_value = mock_task_inst - mock_task_inst.run.return_value.__enter__ = mock.Mock() - mock_task_inst.run.return_value.__exit__ = mock.Mock() - mock_resources.side_effect = [["r1", "r2"], ["r3", "r4"]] - - check.check_resources() - - mock_task.assert_called_once_with("Checking resources") - mock_task_inst.info.assert_has_calls([ - mock.call("Started resources: r1,r2"), - mock.call("Stopped resources: r3,r4") - ]) - - # Test fix() - @classmethod - @mock.patch('crmsh.crash_test.check.correct_sbd') - @mock.patch('crmsh.crash_test.check.check_sbd') - def test_fix_no_candidate(cls, mock_check_sbd, mock_correct_sbd): - """ - Test fix() has no valid candidate - """ - dev = "/dev/disk/by-id/scsi-SATA_ST2000LM007-1R81_WDZ5J42A" - ctx = mock.Mock(fix_conf=True) - mock_check_sbd.return_value = dev - check.fix(ctx) - mock_correct_sbd.assert_called_once_with(ctx, dev) - - @classmethod - @mock.patch('crmsh.crash_test.check.correct_sbd') - @mock.patch('crmsh.crash_test.check.check_sbd') - def test_fix_has_candidate(cls, mock_check_sbd, mock_correct_sbd): - """ - Test fix() has valid candidate - """ - ctx = mock.Mock(fix_conf=True) - mock_check_sbd.return_value = "" - mock_correct_sbd.return_value = "" - check.fix(ctx) - mock_correct_sbd.assert_not_called() - - # Test check_sbd() - @classmethod - @mock.patch('crmsh.crash_test.task.TaskCheck.print_result') - @mock.patch('crmsh.crash_test.utils.msg_info') - @mock.patch('os.path.exists') - def test_check_sbd_no_conf(cls, mock_os_path_exists, - mock_utils_msg_info, mock_run): - """ - Test no configuration file - """ - mock_os_path_exists.return_value = False - check.check_sbd() - mock_utils_msg_info.assert_called_with("SBD configuration file {} not found.". - format(config.SBD_CONF), to_stdout=False) - mock_run.assert_called_once_with() - - @classmethod - @mock.patch('crmsh.crash_test.task.TaskCheck.print_result') - @mock.patch('crmsh.crash_test.utils.msg_info') - @mock.patch('crmsh.utils.parse_sysconfig') - @mock.patch('os.path.exists') - def test_check_sbd_not_configured(cls, mock_os_path_exists, mock_utils_parse_sysconf, - mock_utils_msg_info, mock_run): - """ - Test SBD device not configured - """ - mock_os_path_exists.return_value = True - mock_utils_parse_sysconf.return_value = {} - check.check_sbd() - mock_utils_msg_info.assert_called_with("SBD DEVICE not used.", to_stdout=False) - mock_run.assert_called_once_with() - - @classmethod - @mock.patch('crmsh.crash_test.task.TaskCheck.print_result') - @mock.patch('crmsh.crash_test.utils.is_valid_sbd') - @mock.patch('crmsh.crash_test.utils.msg_info') - @mock.patch('crmsh.sh.ShellUtils.get_stdout_stderr') - @mock.patch('crmsh.utils.parse_sysconfig') - @mock.patch('os.path.exists') - def test_check_sbd_exist_and_valid(cls, mock_os_path_exists, - mock_utils_parse_sysconf, mock_find_hexdump, - mock_msg_info, mock_is_valid_sbd, mock_run): - """ - Test configured SBD device exist and valid - """ - dev = "/dev/disk/by-id/scsi-SATA_ST2000LM007-1R81_WDZ5J42A" - mock_os_path_exists.side_effect = [True, True, True] - mock_utils_parse_sysconf.return_value = {"SBD_DEVICE": dev} - mock_find_hexdump.return_value = (0, "/usr/bin/hexdump", None) - mock_is_valid_sbd.return_value = True - - check.check_sbd() - mock_msg_info.assert_called_with("'{}' is a valid SBD device.".format(dev), - to_stdout=False) - mock_run.assert_called_once_with() - - @classmethod - @mock.patch('crmsh.crash_test.task.TaskCheck.print_result') - @mock.patch('crmsh.crash_test.utils.find_candidate_sbd') - @mock.patch('crmsh.crash_test.utils.is_valid_sbd') - @mock.patch('crmsh.crash_test.utils.msg_warn') - @mock.patch('crmsh.sh.ShellUtils.get_stdout_stderr') - @mock.patch('crmsh.utils.parse_sysconfig') - @mock.patch('os.path.exists') - def test_check_sbd_exist_and_not_valid_but_no_can(cls, mock_os_path_exists, - mock_utils_parse_sysconf, mock_find_hexdump, - mock_msg_warn, mock_is_valid_sbd, - mock_find_can_sbd, mock_run): - """ - Test configured SBD device not valid and no candidate - """ - dev = "/dev/disk/by-id/scsi-SATA_ST2000LM007-1R81_WDZ5J42A" - mock_os_path_exists.side_effect = [True, True, True] - mock_utils_parse_sysconf.return_value = {"SBD_DEVICE": dev} - mock_find_hexdump.return_value = (0, "/usr/bin/hexdump", None) - mock_is_valid_sbd.return_value = False - mock_find_can_sbd.return_value = "" - - check.check_sbd() - mock_msg_warn.assert_has_calls( - [mock.call("Device '{}' is not valid for SBD, may need initialize.". - format(dev), to_stdout=False), - mock.call("Fail to find a valid candidate SBD device.", - to_stdout=False)]) - mock_run.assert_called_once_with() - - @classmethod - @mock.patch('crmsh.crash_test.task.TaskCheck.print_result') - @mock.patch('crmsh.crash_test.utils.find_candidate_sbd') - @mock.patch('crmsh.crash_test.utils.is_valid_sbd') - @mock.patch('crmsh.crash_test.utils.msg_info') - @mock.patch('crmsh.crash_test.utils.msg_warn') - @mock.patch('crmsh.sh.ShellUtils.get_stdout_stderr') - @mock.patch('crmsh.utils.parse_sysconfig') - @mock.patch('os.path.exists') - def test_check_sbd_exist_and_not_exist_has_can(cls, mock_os_path_exists, - mock_utils_parse_sysconf, mock_find_hexdump, - mock_msg_warn, mock_msg_info, mock_is_valid_sbd, - mock_find_can_sbd, mock_run): - """ - Test configured SBD device not valid but has candidate - """ - dev = "/dev/disk/by-id/scsi-SATA_ST2000LM007-1R81_WDZ5J42A" - candev = "/dev/disk/by-id/scsi-SATA_ST2037LM010-2R82_WDZ5J36B" - mock_os_path_exists.side_effect = [True, False] - mock_utils_parse_sysconf.return_value = {"SBD_DEVICE": dev} - mock_find_hexdump.return_value = (0, "/usr/bin/hexdump", None) - mock_is_valid_sbd.return_value = False - mock_find_can_sbd.return_value = candev - - check.check_sbd() - mock_msg_warn.assert_called_once_with( - "SBD device '{}' is not exist.".format(dev), - to_stdout=False) - mock_msg_info.assert_called_with("Found '{}' with SBD header exist.".format(candev), - to_stdout=False) - mock_run.assert_called_once_with() - - @classmethod - @mock.patch('crmsh.crash_test.task.TaskCheck.print_result') - @mock.patch('crmsh.crash_test.utils.find_candidate_sbd') - @mock.patch('crmsh.crash_test.utils.is_valid_sbd') - @mock.patch('crmsh.crash_test.utils.msg_info') - @mock.patch('crmsh.crash_test.utils.msg_warn') - @mock.patch('crmsh.sh.ShellUtils.get_stdout_stderr') - @mock.patch('crmsh.utils.parse_sysconfig') - @mock.patch('os.path.exists') - def test_check_sbd_exist_and_not_valid_has_can(cls, mock_os_path_exists, - mock_utils_parse_sysconf, mock_find_hexdump, - mock_msg_warn, mock_msg_info, mock_is_valid_sbd, - mock_find_can_sbd, mock_run): - """ - Test configured SBD device not valid but has candidate - """ - dev = "/dev/disk/by-id/scsi-SATA_ST2000LM007-1R81_WDZ5J42A" - candev = "/dev/disk/by-id/scsi-SATA_ST2037LM010-2R82_WDZ5J36B" - mock_os_path_exists.side_effect = [True, True, True] - mock_utils_parse_sysconf.return_value = {"SBD_DEVICE": dev} - mock_find_hexdump.return_value = (0, "/usr/bin/hexdump", None) - mock_is_valid_sbd.return_value = False - mock_find_can_sbd.return_value = candev - - check.check_sbd() - mock_msg_warn.assert_called_once_with( - "Device '{}' is not valid for SBD, may need initialize.".format(dev), - to_stdout=False) - mock_msg_info.assert_called_with("Found '{}' with SBD header exist.".format(candev), - to_stdout=False) - mock_run.assert_called_once_with() - - # Test correct_sbd() - @mock.patch('crmsh.crash_test.task.Task.error') - @mock.patch('crmsh.crash_test.utils.msg_info') - @mock.patch('crmsh.utils.parse_sysconfig') - @mock.patch('os.path.exists') - @mock.patch('crmsh.crash_test.main.Context') - def test_correct_sbd_exception_no_conf(self, mock_context, mock_os_path_exists, - mock_utils_parse_sysconf, mock_msg_info, - mock_error): - """ - Test correct_sbd with exception - """ - dev = "/dev/disk/by-id/scsi-SATA_ST2000LM007-1R81_WDZ5J42A" - mock_context = mock.Mock(yes=True) - mock_os_path_exists.side_effect = [False, True] - mock_utils_parse_sysconf.retrun_value = {"SBD_DEVICE": dev} - - with self.assertRaises(crmshutils.TerminateSubCommand): - check.correct_sbd(mock_context, dev) - - mock_msg_info.assert_called_once_with('Replace SBD_DEVICE with candidate {}'. - format(dev), to_stdout=False) - mock_error.assert_called_once_with('Configure file {} not exist!'. - format(config.SBD_CONF)) - - @mock.patch('crmsh.crash_test.task.Task.error') - @mock.patch('crmsh.crash_test.utils.msg_info') - @mock.patch('crmsh.utils.parse_sysconfig') - @mock.patch('os.path.exists') - @mock.patch('crmsh.crash_test.main.Context') - def test_correct_sbd_exception_no_dev(self, mock_context, mock_os_path_exists, - mock_utils_parse_sysconf, mock_msg_info, - mock_error): - """ - Test correct_sbd with exception - """ - dev = "/dev/disk/by-id/scsi-SATA_ST2000LM007-1R81_WDZ5J42A" - mock_context = mock.Mock(yes=True) - mock_os_path_exists.side_effect = [True, False] - mock_utils_parse_sysconf.retrun_value = {"SBD_DEVICE": dev} - - with self.assertRaises(crmshutils.TerminateSubCommand): - check.correct_sbd(mock_context, dev) - - mock_msg_info.assert_called_once_with('Replace SBD_DEVICE with candidate {}'. - format(dev), to_stdout=False) - mock_error.assert_called_once_with('Device {} not exist!'.format(dev)) - - @classmethod - @mock.patch('builtins.open') - @mock.patch('crmsh.crash_test.task.TaskFixSBD.verify') - @mock.patch('tempfile.mkstemp') - @mock.patch('os.remove') - @mock.patch('shutil.move') - @mock.patch('shutil.copymode') - @mock.patch('shutil.copyfile') - @mock.patch('crmsh.crash_test.utils.msg_info') - @mock.patch('crmsh.utils.parse_sysconfig') - @mock.patch('os.path.exists') - @mock.patch('crmsh.crash_test.main.Context') - def test_correct_sbd(cls, mock_context, mock_os_path_exists, - mock_utils_parse_sysconf, mock_msg_info, mock_copyfile, - mock_copymode, mock_move, mock_remove, - mock_mkstemp, mock_sbd_verify, mock_open): - """ - Test correct_sbd - """ - dev = "/dev/disk/by-id/scsi-SATA_ST2000LM007-1R81_WDZ5J42A" - bak = "/tmp/tmpmby3ty9g" - edit = "/tmp/tmpnic4t30s" - mock_context.return_value = mock.Mock(yes=True) - mock_os_path_exists.side_effect = [True, True] - mock_utils_parse_sysconf.retrun_value = {"SBD_DEVICE": dev} - mock_open.side_effect = [ - mock.mock_open(read_data="data1").return_value, - mock.mock_open(read_data="SBD_DEVICE={}".format(dev)).return_value - ] - mock_mkstemp.side_effect = [(1, bak), (2, edit)] - - check.correct_sbd(mock_context, dev) - - mock_msg_info.assert_called_once_with('Replace SBD_DEVICE with candidate {}'. - format(dev), to_stdout=False) - mock_copyfile.assert_called_once_with(config.SBD_CONF, bak) - mock_copymode.assert_called_once_with(config.SBD_CONF, edit) - mock_move.assert_called_once_with(edit, config.SBD_CONF) - mock_remove.assert_called() - mock_sbd_verify.assert_called_once_with() - - @classmethod - @mock.patch('builtins.open') - @mock.patch('crmsh.crash_test.task.Task.error') - @mock.patch('tempfile.mkstemp') - @mock.patch('shutil.copymode') - @mock.patch('shutil.copyfile') - @mock.patch('crmsh.crash_test.utils.msg_info') - @mock.patch('crmsh.utils.parse_sysconfig') - @mock.patch('os.path.exists') - @mock.patch('crmsh.crash_test.main.Context') - def test_correct_sbd_run_exception(cls, mock_context, mock_os_path_exists, - mock_utils_parse_sysconf, mock_msg_info, mock_copyfile, - mock_copymode, mock_mkstemp, mock_msg_error, - mock_open): - """ - Test correct_sbd - """ - dev = "/dev/disk/by-id/scsi-SATA_ST2000LM007-1R81_WDZ5J42A" - bak = "/tmp/tmpmby3ty9g" - edit = "/tmp/tmpnic4t30s" - mock_context.return_value = mock.Mock(yes=True) - mock_os_path_exists.side_effect = [True, True] - mock_utils_parse_sysconf.retrun_value = {"SBD_DEVICE": dev} - mock_open.side_effect = [ - mock.mock_open(read_data="data1").return_value, - mock.mock_open(read_data="data2").return_value - ] - mock_mkstemp.side_effect = [(1, bak), (2, edit)] - mock_copymode.side_effect = Exception('Copy file error!') - - with cls.assertRaises(cls, crmshutils.TerminateSubCommand): - check.correct_sbd(mock_context, dev) - - mock_msg_info.assert_called_once_with('Replace SBD_DEVICE with candidate {}'. - format(dev), to_stdout=False) - mock_copyfile.assert_has_calls([mock.call(config.SBD_CONF, bak), - mock.call(bak, config.SBD_CONF)]) - mock_copymode.assert_called_once_with(config.SBD_CONF, edit) - mock_msg_error.assert_called_once_with('Fail to modify file {}'. - format(config.SBD_CONF)) diff --git a/test/unittests/test_crashtest_main.py b/test/unittests/test_crashtest_main.py index 02ae7b3f8..cfd57c5c2 100644 --- a/test/unittests/test_crashtest_main.py +++ b/test/unittests/test_crashtest_main.py @@ -77,15 +77,13 @@ def test_run_non_root(self, mock_setup, mock_parse, mock_is_root, mock_log_fatal @mock.patch('crmsh.crash_test.main.split_brain') @mock.patch('crmsh.crash_test.main.fence_node') @mock.patch('crmsh.crash_test.main.kill_process') - @mock.patch('crmsh.crash_test.main.check.check') - @mock.patch('crmsh.crash_test.main.check.fix') @mock.patch('os.makedirs') @mock.patch('os.path.exists') @mock.patch('crmsh.crash_test.utils.is_root') @mock.patch('crmsh.crash_test.main.parse_argument') @mock.patch('crmsh.crash_test.main.setup_basic_context') def test_run(self, mock_setup, mock_parse, mock_is_root, mock_exists, mock_mkdir, - mock_fix, mock_check, mock_kill, mock_fence, mock_sb): + mock_kill, mock_fence, mock_sb): mock_is_root.return_value = True ctx = mock.Mock(var_dir="/var/lib/crash_test") mock_exists.return_value = False @@ -97,37 +95,10 @@ def test_run(self, mock_setup, mock_parse, mock_is_root, mock_exists, mock_mkdir mock_is_root.assert_called_once_with() mock_exists.assert_called_once_with(ctx.var_dir) mock_mkdir.assert_called_once_with(ctx.var_dir, exist_ok=True) - mock_check.assert_called_once_with(ctx) - mock_fix.assert_called_once_with(ctx) mock_kill.assert_called_once_with(ctx) mock_fence.assert_called_once_with(ctx) mock_sb.assert_called_once_with(ctx) - @mock.patch('crmsh.crash_test.utils.json_dumps') - @mock.patch('crmsh.crash_test.main.check.check') - @mock.patch('crmsh.crash_test.main.check.fix') - @mock.patch('os.path.exists') - @mock.patch('crmsh.crash_test.utils.is_root') - @mock.patch('crmsh.crash_test.main.parse_argument') - @mock.patch('crmsh.crash_test.main.setup_basic_context') - def test_run_except(self, mock_setup, mock_parse, mock_is_root, mock_exists, - mock_fix, mock_check, mock_dumps): - mock_is_root.return_value = True - ctx = mock.Mock(var_dir="/var/lib/crash_test") - mock_exists.return_value = True - mock_check.side_effect = KeyboardInterrupt - - with self.assertRaises(KeyboardInterrupt): - main.run(ctx) - - mock_setup.assert_called_once_with(ctx) - mock_parse.assert_called_once_with(ctx) - mock_is_root.assert_called_once_with() - mock_exists.assert_called_once_with(ctx.var_dir) - mock_check.assert_called_once_with(ctx) - mock_fix.assert_called_once_with(ctx) - mock_dumps.assert_called_once_with() - @mock.patch('crmsh.crash_test.task.TaskKill') def test_kill_porcess_return_pacemaker_loop(self, mock_task_kill): ctx = mock.Mock(pacemakerd=True, loop=True, sbd=None, corosync=None) diff --git a/test/unittests/test_crashtest_utils.py b/test/unittests/test_crashtest_utils.py index 5f2f947a9..c5d9ef862 100644 --- a/test/unittests/test_crashtest_utils.py +++ b/test/unittests/test_crashtest_utils.py @@ -231,24 +231,6 @@ def test_str_to_datetime(self, mock_datetime): utils.str_to_datetime("Mon Nov 2 15:37:11 2020", "%a %b %d %H:%M:%S %Y") mock_datetime.strptime.assert_called_once_with("Mon Nov 2 15:37:11 2020", "%a %b %d %H:%M:%S %Y") - @mock.patch('crmsh.sh.ShellUtils.get_stdout_stderr') - def test_corosync_port_list(self, mock_run): - output = """ -totem.interface.0.bindnetaddr (str) = 10.10.10.121 -totem.interface.0.mcastaddr (str) = 239.101.40.63 -totem.interface.0.mcastport (u16) = 5405 -totem.interface.0.ttl (u8) = 1 -totem.interface.1.bindnetaddr (str) = 20.20.20.121 -totem.interface.1.mcastaddr (str) = 239.6.213.31 -totem.interface.1.mcastport (u16) = 5407 -totem.interface.1.ttl (u8) = 1 - """ - mock_run.return_value = (0, output, None) - result = utils.corosync_port_list() - expected = ['5405', '5407'] - self.assertListEqual(result, expected) - mock_run.assert_called_once_with("corosync-cmapctl totem.interface") - def test_get_handler(self): mock_handler1 = mock.Mock(_name="test1_handler") mock_handler2 = mock.Mock(_name="test2_handler") @@ -367,23 +349,14 @@ def test_check_node_status(self, mock_run, mock_error): ]) mock_error.assert_not_called() - @mock.patch('crmsh.sh.ShellUtils.get_stdout_stderr') - def test_online_nodes_empty(self, mock_run): - mock_run.return_value = (0, "data", None) - res = utils.online_nodes() - self.assertEqual(res, []) - mock_run.assert_called_once_with("crm_mon -1") - - @mock.patch('crmsh.sh.ShellUtils.get_stdout_stderr') - def test_online_nodes(self, mock_run): - output = """ -Node List: - * Online: [ 15sp2-1 15sp2-2 ] - """ - mock_run.return_value = (0, output, None) + @mock.patch('crmsh.xmlutil.CrmMonXmlParser') + def test_online_nodes(self, mock_crmmon_parser): + mock_inst = mock.Mock() + mock_crmmon_parser.return_value = mock_inst + mock_inst.get_node_list.return_value = ["node1", "node2"] res = utils.online_nodes() - self.assertEqual(res, ["15sp2-1", "15sp2-2"]) - mock_run.assert_called_once_with("crm_mon -1") + self.assertEqual(res, ["node1", "node2"]) + mock_inst.get_node_list.assert_called_once_with(online=True, node_type='member') @mock.patch('crmsh.crash_test.utils.online_nodes') def test_peer_node_list_empty(self, mock_online): @@ -400,145 +373,3 @@ def test_peer_node_list(self, mock_online, mock_this_node): res = utils.peer_node_list() self.assertEqual(res, ["node2"]) mock_online.assert_called_once_with() - - # Test is_valid_sbd(): - @classmethod - @mock.patch('os.path.exists') - def test_is_valid_sbd_not_exist(cls, mock_os_path_exists): - """ - Test device not exist - """ - dev = "/dev/disk/by-id/scsi-device1" - mock_os_path_exists.return_value = False - - res = utils.is_valid_sbd(dev) - assert res is False - - @classmethod - @mock.patch('crmsh.crash_test.utils.msg_error') - @mock.patch('crmsh.sh.ShellUtils.get_stdout_stderr') - @mock.patch('os.path.exists') - def test_is_valid_sbd_cmd_error(cls, mock_os_path_exists, - mock_sbd_check_header, mock_msg_err): - """ - Test device is not valid sbd - """ - dev = "/dev/disk/by-id/scsi-device1" - mock_os_path_exists.return_value = True - mock_sbd_check_header.return_value = (-1, None, "Unknown error!") - mock_msg_err.return_value = "" - - res = utils.is_valid_sbd(dev) - mock_msg_err.assert_called_once_with("Unknown error!") - assert res is False - - @classmethod - @mock.patch('crmsh.crash_test.utils.msg_error') - @mock.patch('crmsh.sh.ShellUtils.get_stdout_stderr') - @mock.patch('os.path.exists') - def test_is_valid_sbd_not_sbd(cls, mock_os_path_exists, - mock_sbd_check_header, mock_msg_err): - """ - Test device is not SBD device - """ - dev = "/dev/disk/by-id/scsi-device1" - err_output = """ -==Dumping header on disk {} -==Header on disk {} NOT dumped -sbd failed; please check the logs. -""".format(dev, dev) - mock_os_path_exists.return_value = True - mock_sbd_check_header.return_value = (1, "==Dumping header on disk {}".format(dev), - err_output) - - res = utils.is_valid_sbd(dev) - assert res is False - mock_msg_err.assert_called_once_with(err_output) - - @classmethod - @mock.patch('crmsh.sh.ShellUtils.get_stdout_stderr') - @mock.patch('os.path.exists') - def test_is_valid_sbd_is_sbd(cls, mock_os_path_exists, - mock_sbd_check_header): - """ - Test device is not SBD device - """ - dev = "/dev/disk/by-id/scsi-device1" - std_output = """ -==Dumping header on disk {} -Header version : 2.1 -UUID : f4c99362-6522-46fc-8ce4-7db60aff19bb -Number of slots : 255 -Sector size : 512 -Timeout (watchdog) : 5 -Timeout (allocate) : 2 -Timeout (loop) : 1 -Timeout (msgwait) : 10 -==Header on disk {} is dumped -""".format(dev, dev) - mock_os_path_exists.return_value = True - mock_sbd_check_header.return_value = (0, std_output, None) - - res = utils.is_valid_sbd(dev) - assert res is True - - # Test find_candidate_sbd() and _find_match_count() - @classmethod - @mock.patch('glob.glob') - @mock.patch('os.path.basename') - @mock.patch('os.path.dirname') - def test_find_candidate_no_dev(cls, mock_os_path_dname, mock_os_path_bname, - mock_glob): - """ - Test no suitable device - """ - mock_os_path_dname.return_value = "/dev/disk/by-id" - mock_os_path_bname.return_value = "scsi-label_CN_devA" - mock_glob.return_value = [] - - res = utils.find_candidate_sbd("/not-exist-folder/not-exist-dev") - assert res == "" - - @classmethod - @mock.patch('crmsh.crash_test.utils.is_valid_sbd') - @mock.patch('glob.glob') - @mock.patch('os.path.basename') - @mock.patch('os.path.dirname') - def test_find_candidate_no_can(cls, mock_os_path_dname, mock_os_path_bname, - mock_glob, mock_is_valid_sbd): - """ - Test no valid candidate device - """ - mock_os_path_dname.return_value = "/dev/disk/by-id" - mock_os_path_bname.return_value = "scsi-label_CN_devA" - mock_glob.return_value = ["/dev/disk/by-id/scsi-label_DE_devA", - "/dev/disk/by-id/scsi-label_DE_devB", - "/dev/disk/by-id/scsi-label_DE_devC", - "/dev/disk/by-id/scsi-label_DE_devD"] - mock_is_valid_sbd.side_effect = [False, False, False, False] - - res = utils.find_candidate_sbd("/dev/disk/by-id/scsi-label_CN_devA") - assert res == "" - - @classmethod - @mock.patch('crmsh.crash_test.utils.is_valid_sbd') - @mock.patch('glob.glob') - @mock.patch('os.path.basename') - @mock.patch('os.path.dirname') - def test_find_candidate_has_multi(cls, mock_os_path_dname, mock_os_path_bname, - mock_glob, mock_is_valid_sbd): - """ - Test has multiple valid candidate devices - """ - mock_os_path_dname.return_value = "/dev/disk/by-id" - mock_os_path_bname.return_value = "scsi-label_CN_devA" - mock_glob.return_value = ["/dev/disk/by-id/scsi-label_DE_devA", - "/dev/disk/by-id/scsi-label_DE_devB", - "/dev/disk/by-id/scsi-label_CN_devC", - "/dev/disk/by-id/scsi-label_CN_devD", - "/dev/disk/by-id/scsi-mp_China_devE", - "/dev/disk/by-id/scsi-mp_China_devF"] - mock_is_valid_sbd.side_effect = [True, False, False, True, True, False] - - res = utils.find_candidate_sbd("/dev/disk/by-id/scsi-label_CN_devA") - assert res == "/dev/disk/by-id/scsi-label_CN_devD" diff --git a/test/unittests/test_utils.py b/test/unittests/test_utils.py index 5cc7492e5..3fdde301f 100644 --- a/test/unittests/test_utils.py +++ b/test/unittests/test_utils.py @@ -1052,11 +1052,13 @@ def test_set_dlm_option(mock_get_dict, mock_run): mock_run_inst.get_stdout_or_raise_error.assert_called_once_with('dlm_tool set_config "key2=test"', None) -@mock.patch('crmsh.utils.has_resource_configured') -def test_is_dlm_configured(mock_configured): - mock_configured.return_value = True +@mock.patch('crmsh.xmlutil.CrmMonXmlParser') +def test_is_dlm_configured(mock_crmmon): + mock_crmmon_inst = mock.Mock() + mock_crmmon.return_value = mock_crmmon_inst + mock_crmmon_inst.is_resource_configured.return_value = True assert utils.is_dlm_configured() is True - mock_configured.assert_called_once_with(constants.DLM_CONTROLD_RA, peer=None) + mock_crmmon_inst.is_resource_configured.assert_called_once_with(constants.DLM_CONTROLD_RA) @mock.patch('crmsh.sh.cluster_shell')