Skip to content

Commit

Permalink
Dev: unittests: Add unit test for previous commit
Browse files Browse the repository at this point in the history
  • Loading branch information
liangxin1300 committed Dec 19, 2024
1 parent 9423c24 commit 28fe540
Show file tree
Hide file tree
Showing 3 changed files with 396 additions and 0 deletions.
1 change: 1 addition & 0 deletions data-manifest
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ test/unittests/test_bootstrap.py
test/unittests/test_bugs.py
test/unittests/test_cib.py
test/unittests/test_cliformat.py
test/unittests/test_cluster_fs.py
test/unittests/test.conf
test/unittests/test_corosync_config_format.py
test/unittests/test_corosync.py
Expand Down
311 changes: 311 additions & 0 deletions test/unittests/test_cluster_fs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,311 @@
import unittest
from unittest import mock

from crmsh import cluster_fs, utils, ra


class TestClusterFSManager(unittest.TestCase):

@mock.patch("crmsh.cluster_fs.ClusterFSManager._verify_options")
def setUp(self, mock_verify_options):
ocfs2_context_one_device = mock.Mock(ocfs2_devices=["/dev/sda1"], gfs2_devices=[], use_cluster_lvm2=False, stage=None)
gfs2_context_one_device_clvm2 = mock.Mock(ocfs2_devices=[], gfs2_devices=["/dev/sda1"], use_cluster_lvm2=True)
self.ocfs2_instance_one_device = cluster_fs.ClusterFSManager(ocfs2_context_one_device)
self.gfs2_instance_one_device_clvm2 = cluster_fs.ClusterFSManager(gfs2_context_one_device_clvm2)

ocfs2_gfs2_both_context = mock.Mock(ocfs2_devices=["/dev/sda1"], gfs2_devices=["/dev/sda2"])
self.instance_both = cluster_fs.ClusterFSManager(ocfs2_gfs2_both_context)

ocfs2_stage_without_device_context = mock.Mock(ocfs2_devices=[], gfs2_devices=[], stage="ocfs2")
self.instance_ocfs2_stage_without_device = cluster_fs.ClusterFSManager(ocfs2_stage_without_device_context)

gfs2_stage_without_device_context = mock.Mock(ocfs2_devices=[], gfs2_devices=[], stage="gfs2")
self.instance_gfs2_stage_without_device = cluster_fs.ClusterFSManager(gfs2_stage_without_device_context)

ocfs2_stage_with_device_context = mock.Mock(ocfs2_devices=["/dev/sda1"], gfs2_devices=[], stage="ocfs2", use_cluster_lvm2=False)
self.instance_ocfs2_stage_with_device = cluster_fs.ClusterFSManager(ocfs2_stage_with_device_context)

ocfs2_stage_with_device_clvm2_context = mock.Mock(ocfs2_devices=["/dev/sda1"], gfs2_devices=[], stage="ocfs2", use_cluster_lvm2=True)
self.instance_ocfs2_stage_with_device_clvm2 = cluster_fs.ClusterFSManager(ocfs2_stage_with_device_clvm2_context)

clvm2_without_device_context = mock.Mock(ocfs2_devices=[], gfs2_devices=[], use_cluster_lvm2=True)
self.instance_clvm2_without_device = cluster_fs.ClusterFSManager(clvm2_without_device_context)

multi_ocfs2_devices_without_clvm2_context = mock.Mock(ocfs2_devices=["/dev/sda1", "/dev/sda2"], gfs2_devices=[], use_cluster_lvm2=False)
self.multi_ocfs2_devices_without_clvm2 = cluster_fs.ClusterFSManager(multi_ocfs2_devices_without_clvm2_context)

multi_gfs2_devices_without_clvm2_context = mock.Mock(ocfs2_devices=[], gfs2_devices=["/dev/sda1", "/dev/sda2"], use_cluster_lvm2=False)
self.multi_gfs2_devices_without_clvm2 = cluster_fs.ClusterFSManager(multi_gfs2_devices_without_clvm2_context)

gfs2_context_one_device_with_mount_point = mock.Mock(ocfs2_devices=[], gfs2_devices=["/dev/sda1"], use_cluster_lvm2=False, mount_point="/mnt/gfs2")
self.gfs2_instance_one_device_with_mount_point = cluster_fs.ClusterFSManager(gfs2_context_one_device_with_mount_point)

@mock.patch("crmsh.utils.package_is_installed")
@mock.patch("crmsh.utils.list_cluster_nodes")
def test_verify_packages_local(self, mock_list_cluster_nodes, mock_package_is_installed):
mock_package_is_installed.return_value = True
self.ocfs2_instance_one_device._verify_packages()
mock_list_cluster_nodes.assert_not_called()
mock_package_is_installed.assert_called_once_with("ocfs2-tools", None)

@mock.patch("crmsh.utils.package_is_installed")
@mock.patch("crmsh.utils.list_cluster_nodes")
def test_verify_packages_remote(self, mock_list_cluster_nodes, mock_package_is_installed):
mock_list_cluster_nodes.return_value = ["node1", "node2"]
mock_package_is_installed.return_value = False
with self.assertRaises(cluster_fs.Error) as context:
self.instance_ocfs2_stage_with_device_clvm2._verify_packages()
self.assertIn("Missing required package for configuring OCFS2 on node1: ocfs2-tools", str(context.exception))

def test_verify_options(self):
with self.assertRaises(cluster_fs.Error) as context:
self.instance_both._verify_options()
self.assertIn("Can't use -g and -o options together", str(context.exception))

with self.assertRaises(cluster_fs.Error) as context:
self.instance_ocfs2_stage_without_device._verify_options()
self.assertIn("ocfs2 stage require -o option", str(context.exception))

with self.assertRaises(cluster_fs.Error) as context:
self.instance_gfs2_stage_without_device._verify_options()
self.assertIn("gfs2 stage require -g option", str(context.exception))

with self.assertRaises(cluster_fs.Error) as context:
self.instance_clvm2_without_device._verify_options()
self.assertIn("-C option only valid together with -o or -g option", str(context.exception))
with self.assertRaises(cluster_fs.Error) as context:
self.multi_ocfs2_devices_without_clvm2._verify_options()
self.assertIn("Without Cluster LVM2 (-C option), -o option only support one device", str(context.exception))

with self.assertRaises(cluster_fs.Error) as context:
self.multi_gfs2_devices_without_clvm2._verify_options()
self.assertIn("Without Cluster LVM2 (-C option), -g option only support one device", str(context.exception))

@mock.patch("crmsh.utils.has_mount_point_used")
def test_verify_options_mount_point(self, mock_has_mount_point_used):
mock_has_mount_point_used.return_value = True
with self.assertRaises(cluster_fs.Error) as context:
self.gfs2_instance_one_device_with_mount_point._verify_options()
self.assertIn("Mount point /mnt/gfs2 already mounted", str(context.exception))

@mock.patch("crmsh.utils.is_block_device")
def test_verify_devices_not_block_device(self, mock_is_block_device):
mock_is_block_device.return_value = False
with self.assertRaises(cluster_fs.Error) as context:
self.ocfs2_instance_one_device._verify_devices()
self.assertIn("/dev/sda1 doesn't look like a block device", str(context.exception))

@mock.patch("crmsh.utils.is_dev_used_for_lvm")
@mock.patch("crmsh.utils.is_block_device")
def test_verify_devices_clvm2_with_lv(self, mock_is_block_device, mock_is_dev_used_for_lvm):
mock_is_block_device.return_value = True
mock_is_dev_used_for_lvm.return_value = True
with self.assertRaises(cluster_fs.Error) as context:
self.gfs2_instance_one_device_clvm2._verify_devices()
self.assertIn("/dev/sda1 is a Logical Volume, cannot be used with the -C option", str(context.exception))

@mock.patch("crmsh.utils.has_disk_mounted")
@mock.patch("crmsh.utils.is_dev_used_for_lvm")
@mock.patch("crmsh.utils.is_block_device")
def test_verify_devices_already_mounted(self, mock_is_block_device, mock_is_dev_used_for_lvm, mock_has_disk_mounted):
mock_is_block_device.return_value = True
mock_is_dev_used_for_lvm.return_value = False
mock_has_disk_mounted.return_value = True
with self.assertRaises(cluster_fs.Error) as context:
self.ocfs2_instance_one_device._verify_devices()
self.assertIn("/dev/sda1 is already mounted", str(context.exception))

@mock.patch("crmsh.sh.cluster_shell")
def test_check_if_already_configured_return(self, mock_cluster_shell):
self.ocfs2_instance_one_device._check_if_already_configured()
mock_cluster_shell.assert_not_called()

@mock.patch("logging.Logger.warning")
@mock.patch("crmsh.sh.cluster_shell")
def test_check_if_already_configured(self, mock_cluster_shell, mock_warning):
mock_cluster_shell_inst = mock.Mock()
mock_cluster_shell.return_value = mock_cluster_shell_inst
mock_cluster_shell_inst.get_stdout_or_raise_error.return_value = """
fstype=ocfs2
data
"""
with self.assertRaises(utils.TerminateSubCommand):
self.instance_ocfs2_stage_with_device._check_if_already_configured()
mock_warning.assert_called_once_with("Already configured %s related resources", "OCFS2")

def test_pre_verify(self):
self.ocfs2_instance_one_device._verify_packages = mock.Mock()
self.ocfs2_instance_one_device._check_if_already_configured = mock.Mock()
self.ocfs2_instance_one_device._verify_devices = mock.Mock()
self.ocfs2_instance_one_device._pre_verify()
self.ocfs2_instance_one_device._verify_packages.assert_called_once()
self.ocfs2_instance_one_device._check_if_already_configured.assert_called_once()
self.ocfs2_instance_one_device._verify_devices.assert_called_once()

@mock.patch("crmsh.sbd.SBDUtils.get_sbd_device_from_config")
@mock.patch("crmsh.cluster_fs.ServiceManager")
def test_check_device_with_sbd_device(self, mock_service_manager, mock_get_sbd_device_from_config):
mock_service_manager_inst = mock.Mock()
mock_service_manager.return_value = mock_service_manager_inst
mock_service_manager_inst.service_is_enabled.return_value = True
mock_get_sbd_device_from_config.return_value = "/dev/sda1"
with self.assertRaises(cluster_fs.Error) as context:
self.instance_ocfs2_stage_with_device._check_device_with_sbd_device()
self.assertEqual(str(context.exception), '/dev/sda1 cannot be the same with SBD device')

@mock.patch("crmsh.bootstrap.confirm")
@mock.patch("crmsh.utils.has_dev_partitioned")
def test_confirm_to_overwrite_device_no_overwrite(self, mock_has_dev_partitioned, mock_confirm):
mock_has_dev_partitioned.return_value = True
mock_confirm.return_value = False
with self.assertRaises(utils.TerminateSubCommand):
self.ocfs2_instance_one_device._confirm_to_overwrite_device()
mock_confirm.assert_called_once_with("Found a partition table in /dev/sda1 - overwrite?")

@mock.patch("crmsh.sh.cluster_shell")
@mock.patch("crmsh.bootstrap.confirm")
@mock.patch("crmsh.utils.get_dev_fs_type")
@mock.patch("crmsh.utils.has_dev_partitioned")
def test_confirm_to_overwrite_device(self, mock_has_dev_partitioned, mock_get_dev_fs_type, mock_confirm, mock_cluster_shell):
mock_has_dev_partitioned.return_value = False
mock_get_dev_fs_type.return_value = "ext4"
mock_confirm.return_value = True
mock_cluster_shell_inst = mock.Mock()
mock_cluster_shell.return_value = mock_cluster_shell_inst
mock_cluster_shell_inst.get_stdout_or_raise_error.return_value = None
self.ocfs2_instance_one_device._confirm_to_overwrite_device()
mock_confirm.assert_called_once_with("/dev/sda1 contains a ext4 file system - overwrite?")
mock_cluster_shell_inst.get_stdout_or_raise_error.assert_called_once_with("wipefs -a /dev/sda1")

@mock.patch("crmsh.utils.has_stonith_running")
def test_init_verify_no_stonith(self, mock_has_stonith_running):
mock_has_stonith_running.return_value = False
with self.assertRaises(cluster_fs.Error) as context:
self.instance_ocfs2_stage_with_device.init_verify()
self.assertIn("OCFS2 requires stonith device configured and running", str(context.exception))

def test_gen_ra_scripts_unsupport_type(self):
with self.assertRaises(cluster_fs.Error) as context:
self.ocfs2_instance_one_device._gen_ra_scripts("unsupport", {})
self.assertIn("Unsupported RA type: unsupport", str(context.exception))

@mock.patch("crmsh.utils.gen_unused_id")
def test_gen_ra_scripts(self, mock_gen_unused_id):
mock_gen_unused_id.return_value = "dlm"
_id, scripts = self.ocfs2_instance_one_device._gen_ra_scripts("DLM", {"id": "dlm"})
self.assertEqual(_id, "dlm")
self.assertEqual(scripts, ra.DLM_RA_SCRIPTS.format(id="dlm"))

@mock.patch("crmsh.sh.cluster_shell")
@mock.patch("crmsh.log.LoggerUtils.status_long")
@mock.patch("logging.Logger.debug")
@mock.patch("crmsh.corosync.get_value")
def test_mkfs_ocfs2(self, mock_get_value, mock_debug, mock_status_long, mock_cluster_shell):
mock_get_value.return_value = "hacluster"
mock_status_long.return_value.__enter__ = mock.Mock()
mock_status_long.return_value.__exit__ = mock.Mock()
mock_cluster_shell_inst = mock.Mock()
mock_cluster_shell.return_value = mock_cluster_shell_inst
mock_cluster_shell_inst.get_stdout_or_raise_error.return_value = ""
self.ocfs2_instance_one_device.target_device = "/dev/sda1"
self.ocfs2_instance_one_device._mkfs()
mock_debug.assert_called_once_with("mkfs command: %s", "mkfs.ocfs2 --cluster-stack pcmk --cluster-name hacluster -N 8 -x /dev/sda1")
mock_status_long.assert_called_once_with("Creating ocfs2 filesystem on /dev/sda1")

@mock.patch("crmsh.utils.randomword")
@mock.patch("crmsh.sh.cluster_shell")
@mock.patch("crmsh.log.LoggerUtils.status_long")
@mock.patch("logging.Logger.debug")
@mock.patch("crmsh.corosync.get_value")
def test_mkfs_gfs2(self, mock_get_value, mock_debug, mock_status_long, mock_cluster_shell, mock_randomword):
mock_randomword.return_value = "exezoy"
mock_get_value.return_value = "hacluster"
mock_status_long.return_value.__enter__ = mock.Mock()
mock_status_long.return_value.__exit__ = mock.Mock()
mock_cluster_shell_inst = mock.Mock()
mock_cluster_shell.return_value = mock_cluster_shell_inst
mock_cluster_shell_inst.get_stdout_or_raise_error.return_value = ""
self.gfs2_instance_one_device_clvm2.target_device = "/dev/sda1"
self.gfs2_instance_one_device_clvm2._mkfs()
mock_debug.assert_called_once_with("mkfs command: %s", "mkfs.gfs2 -t hacluster:FS_exezoy -p lock_dlm -j 8 /dev/sda1 -O")
mock_status_long.assert_called_once_with("Creating gfs2 filesystem on /dev/sda1")

@mock.patch("crmsh.utils.set_property")
@mock.patch("crmsh.utils.get_property")
@mock.patch("crmsh.utils.all_exist_id")
@mock.patch("logging.Logger.info")
def test_init(self, mock_info, mock_all_exist_id, mock_get_property, mock_set_property):
mock_all_exist_id.return_value = ["ocfs2"]
mock_get_property.return_value = "good"
self.ocfs2_instance_one_device.init_verify = mock.Mock()
self.ocfs2_instance_one_device._configure_resource_stack = mock.Mock()
self.ocfs2_instance_one_device.init()
mock_info.assert_called_once_with("Configuring %s", "OCFS2")
mock_set_property.assert_called_once_with("no-quorum-policy", "freeze")

@mock.patch("logging.Logger.info")
def test_configure_resource_stack_lvm2(self, mock_info):
self.gfs2_instance_one_device_clvm2._config_dlm = mock.Mock()
self.gfs2_instance_one_device_clvm2._config_lvmlockd = mock.Mock()
self.gfs2_instance_one_device_clvm2._create_lv = mock.Mock(return_value="/dev/vg/lv")
self.gfs2_instance_one_device_clvm2._vg_change = mock.Mock()
self.gfs2_instance_one_device_clvm2._vg_change.return_value.__enter__ = mock.Mock()
self.gfs2_instance_one_device_clvm2._vg_change.return_value.__exit__ = mock.Mock()
self.gfs2_instance_one_device_clvm2._mkfs = mock.Mock()
self.gfs2_instance_one_device_clvm2._config_lvmactivate = mock.Mock()
self.gfs2_instance_one_device_clvm2._config_fs = mock.Mock()
self.gfs2_instance_one_device_clvm2.mount_point = "/mnt/gfs2"
self.gfs2_instance_one_device_clvm2._configure_resource_stack()
mock_info.assert_called_once_with('%s device %s mounted on %s', 'GFS2', '/dev/vg/lv', '/mnt/gfs2')

@mock.patch("logging.Logger.info")
def test_configure_resource_stack(self, mock_info):
self.ocfs2_instance_one_device._config_dlm = mock.Mock()
self.ocfs2_instance_one_device._mkfs = mock.Mock()
self.ocfs2_instance_one_device._config_fs = mock.Mock()
self.ocfs2_instance_one_device.mount_point = "/mnt/ocfs2"
self.ocfs2_instance_one_device._configure_resource_stack()
mock_info.assert_called_once_with('%s device %s mounted on %s', 'OCFS2', '/dev/sda1', '/mnt/ocfs2')

@mock.patch("crmsh.sh.cluster_shell")
def test_find_target_on_join_none(self, mock_cluster_shell):
mock_cluster_shell_inst = mock.Mock()
mock_cluster_shell.return_value = mock_cluster_shell_inst
mock_cluster_shell_inst.get_stdout_or_raise_error.return_value = "data"
self.assertIsNone(self.ocfs2_instance_one_device._find_target_on_join("node1"))
mock_cluster_shell_inst.get_stdout_or_raise_error.assert_called_once_with("crm configure show", "node1")

@mock.patch("crmsh.sh.cluster_shell")
def test_find_target_on_join(self, mock_cluster_shell):
mock_cluster_shell_inst = mock.Mock()
mock_cluster_shell.return_value = mock_cluster_shell_inst
mock_cluster_shell_inst.get_stdout_or_raise_error.return_value = """
primitive gfs2-clusterfs Filesystem \
params directory="/srv/clusterfs" fstype=gfs2 device="/dev/sda6" \
op monitor interval=20 timeout=40 \
"""
expected_dict = {"cluster_fs_type": "gfs2", "device": "/dev/sda6"}
self.assertDictEqual(self.ocfs2_instance_one_device._find_target_on_join("node1"), expected_dict)
mock_cluster_shell_inst.get_stdout_or_raise_error.assert_called_once_with("crm configure show", "node1")

@mock.patch("crmsh.log.LoggerUtils.status_long")
def test_join_return(self, mock_status_long):
self.ocfs2_instance_one_device._find_target_on_join = mock.Mock(return_value=None)
self.ocfs2_instance_one_device.join("node1")
mock_status_long.assert_not_called()

@mock.patch("crmsh.utils.compare_uuid_with_peer_dev")
@mock.patch("crmsh.utils.is_dev_a_plain_raw_disk_or_partition")
@mock.patch("crmsh.xmlutil.CrmMonXmlParser")
@mock.patch("crmsh.log.LoggerUtils.status_long")
def test_join(self, mock_status_long, mock_crmmonxmlparser, mock_is_dev_a_plain_raw_disk_or_partition, mock_compare_uuid_with_peer_dev):
mock_crmmonxmlparser_inst = mock.Mock()
mock_crmmonxmlparser.return_value = mock_crmmonxmlparser_inst
mock_crmmonxmlparser_inst.is_resource_configured = mock.Mock(return_value=True)
self.ocfs2_instance_one_device._find_target_on_join = mock.Mock(return_value={"cluster_fs_type": "ocfs2", "device": "/dev/sda1"})
self.ocfs2_instance_one_device._verify_packages = mock.Mock()
mock_status_long.return_value.__enter__ = mock.Mock()
mock_status_long.return_value.__exit__ = mock.Mock()
mock_is_dev_a_plain_raw_disk_or_partition.return_value = True
self.ocfs2_instance_one_device.join("node1")
mock_status_long.assert_called_once_with("Verify OCFS2 environment on /dev/sda1")
Loading

0 comments on commit 28fe540

Please sign in to comment.