Blame SOURCES/bz1164402-03-sbd-fix-check-if-atb-is-required-when-enabling-sbd.patch

15f218
From 66b5e393aebd84b08047f33d09bc4cbce730e205 Mon Sep 17 00:00:00 2001
15f218
From: Ondrej Mular <omular@redhat.com>
15f218
Date: Tue, 23 Aug 2016 11:19:20 +0200
15f218
Subject: [PATCH] sbd: fix check if ATB is required when enabling sbd
15f218
15f218
---
15f218
 pcs/common/report_codes.py |   1 +
15f218
 pcs/lib/commands/sbd.py    |   3 +-
15f218
 pcs/lib/reports.py         |  12 +++
15f218
 pcs/lib/sbd.py             |  39 ++++++++-
15f218
 pcs/test/test_lib_sbd.py   | 193 +++++++--------------------------------------
15f218
 5 files changed, 80 insertions(+), 168 deletions(-)
15f218
15f218
diff --git a/pcs/common/report_codes.py b/pcs/common/report_codes.py
15f218
index 5e46a1f..e6a86ec 100644
15f218
--- a/pcs/common/report_codes.py
15f218
+++ b/pcs/common/report_codes.py
15f218
@@ -155,6 +155,7 @@ SBD_DISABLING_STARTED = "SBD_DISABLING_STARTED"
15f218
 SBD_ENABLING_STARTED = "SBD_ENABLING_STARTED"
15f218
 SBD_NOT_INSTALLED = "SBD_NOT_INSTALLED"
15f218
 SBD_NOT_ENABLED = "SBD_NOT_ENABLED"
15f218
+SBD_REQUIRES_ATB = "SBD_REQUIRES_ATB"
15f218
 SERVICE_DISABLE_ERROR = "SERVICE_DISABLE_ERROR"
15f218
 SERVICE_DISABLE_STARTED = "SERVICE_DISABLE_STARTED"
15f218
 SERVICE_DISABLE_SUCCESS = "SERVICE_DISABLE_SUCCESS"
15f218
diff --git a/pcs/lib/commands/sbd.py b/pcs/lib/commands/sbd.py
15f218
index 265ebb5..2acb104 100644
15f218
--- a/pcs/lib/commands/sbd.py
15f218
+++ b/pcs/lib/commands/sbd.py
15f218
@@ -159,7 +159,8 @@ def enable_sbd(
15f218
 
15f218
     # enable ATB if needed
15f218
     corosync_conf = lib_env.get_corosync_conf()
15f218
-    if sbd.atb_has_to_be_enabled(lib_env.cmd_runner(), corosync_conf):
15f218
+    if sbd.atb_has_to_be_enabled_pre_enable_check(corosync_conf):
15f218
+        lib_env.report_processor.process(reports.sbd_requires_atb())
15f218
         corosync_conf.set_quorum_options(
15f218
             lib_env.report_processor, {"auto_tie_breaker": "1"}
15f218
         )
15f218
diff --git a/pcs/lib/reports.py b/pcs/lib/reports.py
15f218
index 568bb7e..a701679 100644
15f218
--- a/pcs/lib/reports.py
15f218
+++ b/pcs/lib/reports.py
15f218
@@ -1928,3 +1928,15 @@ def quorum_cannot_disable_atb_due_to_sbd(
15f218
         "unable to disable auto_tie_breaker: SBD fencing will have no effect",
15f218
         forceable=forceable
15f218
     )
15f218
+
15f218
+
15f218
+def sbd_requires_atb():
15f218
+    """
15f218
+    Warning that ATB will be enabled in order to make SBD fencing effective.
15f218
+    """
15f218
+    return ReportItem.warning(
15f218
+        report_codes.SBD_REQUIRES_ATB,
15f218
+        "auto_tie_breaker quorum option will be enabled to make SBD fencing "
15f218
+        "effective. Cluster has to be offline to be able to make this change."
15f218
+    )
15f218
+
15f218
diff --git a/pcs/lib/sbd.py b/pcs/lib/sbd.py
15f218
index c9f013b..39de740 100644
15f218
--- a/pcs/lib/sbd.py
15f218
+++ b/pcs/lib/sbd.py
15f218
@@ -46,6 +46,25 @@ def _run_parallel_and_raise_lib_error_on_failure(func, param_list):
15f218
         raise LibraryError(*report_list)
15f218
 
15f218
 
15f218
+def _even_number_of_nodes_and_no_qdevice(
15f218
+    corosync_conf_facade, node_number_modifier=0
15f218
+):
15f218
+    """
15f218
+    Returns True whenever cluster has no quorum device configured and number of
15f218
+    nodes + node_number_modifier is even number, False otherwise.
15f218
+
15f218
+    corosync_conf_facade --
15f218
+    node_number_modifier -- this value will be added to current number of nodes.
15f218
+        This can be useful to test whenever is ATB needed when adding/removing
15f218
+        node.
15f218
+    """
15f218
+    return (
15f218
+        not corosync_conf_facade.has_quorum_device()
15f218
+        and
15f218
+        (len(corosync_conf_facade.get_nodes()) + node_number_modifier) % 2 == 0
15f218
+    )
15f218
+
15f218
+
15f218
 def is_auto_tie_breaker_needed(
15f218
     runner, corosync_conf_facade, node_number_modifier=0
15f218
 ):
15f218
@@ -60,15 +79,29 @@ def is_auto_tie_breaker_needed(
15f218
         node.
15f218
     """
15f218
     return (
15f218
-        not corosync_conf_facade.has_quorum_device()
15f218
-        and
15f218
-        (len(corosync_conf_facade.get_nodes()) + node_number_modifier) % 2 == 0
15f218
+        _even_number_of_nodes_and_no_qdevice(
15f218
+            corosync_conf_facade, node_number_modifier
15f218
+        )
15f218
         and
15f218
         is_sbd_installed(runner)
15f218
         and
15f218
         is_sbd_enabled(runner)
15f218
     )
15f218
 
15f218
+
15f218
+def atb_has_to_be_enabled_pre_enable_check(corosync_conf_facade):
15f218
+    """
15f218
+    Returns True whenever quorum option auto_tie_breaker is needed to be enabled
15f218
+    for proper working of SBD fencing. False if it is not needed. This function
15f218
+    doesn't check if sbd is installed nor enabled.
15f218
+     """
15f218
+    return (
15f218
+        not corosync_conf_facade.is_enabled_auto_tie_breaker()
15f218
+        and
15f218
+        _even_number_of_nodes_and_no_qdevice(corosync_conf_facade)
15f218
+    )
15f218
+
15f218
+
15f218
 def atb_has_to_be_enabled(runner, corosync_conf_facade, node_number_modifier=0):
15f218
     """
15f218
     Return True whenever quorum option auto tie breaker has to be enabled for
15f218
diff --git a/pcs/test/test_lib_sbd.py b/pcs/test/test_lib_sbd.py
15f218
index fd29484..516e0bd 100644
15f218
--- a/pcs/test/test_lib_sbd.py
15f218
+++ b/pcs/test/test_lib_sbd.py
15f218
@@ -86,195 +86,60 @@ class RunParallelAndRaiseLibErrorOnFailureTest(TestCase):
15f218
         )
15f218
 
15f218
 
15f218
-@mock.patch("pcs.lib.sbd.is_sbd_installed")
15f218
-@mock.patch("pcs.lib.sbd.is_sbd_enabled")
15f218
-class IsAutoTieBreakerNeededTest(TestCase):
15f218
+class EvenNumberOfNodesAndNoQdevice(TestCase):
15f218
     def setUp(self):
15f218
-        self.runner = "runner"
15f218
         self.mock_corosync_conf = mock.MagicMock(spec_set=CorosyncConfigFacade)
15f218
 
15f218
     def _set_ret_vals(self, nodes, qdevice):
15f218
         self.mock_corosync_conf.get_nodes.return_value = nodes
15f218
         self.mock_corosync_conf.has_quorum_device.return_value = qdevice
15f218
 
15f218
-    def test_sbd_enabled_even_nodes_has_qdevice(
15f218
-        self, mock_enabled, mock_installed
15f218
-    ):
15f218
-        mock_enabled.return_value = True
15f218
-        mock_installed.return_value = True
15f218
-        self._set_ret_vals([1, 2], True)
15f218
-        self.assertFalse(lib_sbd.is_auto_tie_breaker_needed(
15f218
-            self.runner, self.mock_corosync_conf
15f218
-        ))
15f218
-
15f218
-    def test_sbd_enabled_even_nodes_no_qdevice(
15f218
-        self, mock_enabled, mock_installed
15f218
-    ):
15f218
-        mock_enabled.return_value = True
15f218
-        mock_installed.return_value = True
15f218
-        self._set_ret_vals([1, 2], False)
15f218
-        self.assertTrue(lib_sbd.is_auto_tie_breaker_needed(
15f218
-            self.runner, self.mock_corosync_conf
15f218
-        ))
15f218
-
15f218
-    def test_sbd_not_installed_even_nodes_no_qdevice(
15f218
-        self, mock_enabled, mock_installed
15f218
-    ):
15f218
-        mock_enabled.return_value = False
15f218
-        mock_installed.return_value = False
15f218
+    def test_even_num_no_qdevice(self):
15f218
         self._set_ret_vals([1, 2], False)
15f218
-        self.assertFalse(lib_sbd.is_auto_tie_breaker_needed(
15f218
-            self.runner, self.mock_corosync_conf
15f218
-        ))
15f218
-
15f218
-    def test_sbd_enabled_odd_nodes_has_qdevice(
15f218
-        self, mock_enabled, mock_installed
15f218
-    ):
15f218
-        mock_enabled.return_value = True
15f218
-        mock_installed.return_value = True
15f218
-        self._set_ret_vals([1, 2, 3], True)
15f218
-        self.assertFalse(lib_sbd.is_auto_tie_breaker_needed(
15f218
-            self.runner, self.mock_corosync_conf
15f218
-        ))
15f218
-
15f218
-    def test_sbd_enabled_odd_nodes_no_qdevice(
15f218
-        self, mock_enabled, mock_installed
15f218
-    ):
15f218
-        mock_enabled.return_value = True
15f218
-        mock_installed.return_value = True
15f218
-        self._set_ret_vals([1, 2, 3], False)
15f218
-        self.assertFalse(lib_sbd.is_auto_tie_breaker_needed(
15f218
-            self.runner, self.mock_corosync_conf
15f218
+        self.assertTrue(lib_sbd._even_number_of_nodes_and_no_qdevice(
15f218
+            self.mock_corosync_conf
15f218
         ))
15f218
 
15f218
-    def test_sbd_disabled_even_nodes_has_qdevice(
15f218
-        self, mock_enabled, mock_installed
15f218
-    ):
15f218
-        mock_enabled.return_value = False
15f218
-        mock_installed.return_value = True
15f218
+    def test_even_num_qdevice(self):
15f218
         self._set_ret_vals([1, 2], True)
15f218
-        self.assertFalse(lib_sbd.is_auto_tie_breaker_needed(
15f218
-            self.runner, self.mock_corosync_conf
15f218
-        ))
15f218
-
15f218
-    def test_sbd_disabled_even_nodes_no_qdevice(
15f218
-        self, mock_enabled, mock_installed
15f218
-    ):
15f218
-        mock_enabled.return_value = False
15f218
-        mock_installed.return_value = True
15f218
-        self._set_ret_vals([1, 2], False)
15f218
-        self.assertFalse(lib_sbd.is_auto_tie_breaker_needed(
15f218
-            self.runner, self.mock_corosync_conf
15f218
+        self.assertFalse(lib_sbd._even_number_of_nodes_and_no_qdevice(
15f218
+            self.mock_corosync_conf
15f218
         ))
15f218
 
15f218
-    def test_sbd_disabled_odd_nodes_has_qdevice(
15f218
-        self, mock_enabled, mock_installed
15f218
-    ):
15f218
-        mock_enabled.return_value = False
15f218
-        mock_installed.return_value = True
15f218
-        self._set_ret_vals([1, 2, 3], True)
15f218
-        self.assertFalse(lib_sbd.is_auto_tie_breaker_needed(
15f218
-            self.runner, self.mock_corosync_conf
15f218
-        ))
15f218
-
15f218
-    def test_sbd_disabled_odd_nodes_no_qdevice(
15f218
-        self, mock_enabled, mock_installed
15f218
-    ):
15f218
-        mock_enabled.return_value = False
15f218
-        mock_installed.return_value = True
15f218
+    def test_odd_num_no_qdevice(self):
15f218
         self._set_ret_vals([1, 2, 3], False)
15f218
-        self.assertFalse(lib_sbd.is_auto_tie_breaker_needed(
15f218
-            self.runner, self.mock_corosync_conf
15f218
+        self.assertFalse(lib_sbd._even_number_of_nodes_and_no_qdevice(
15f218
+            self.mock_corosync_conf
15f218
         ))
15f218
 
15f218
-    def test_sbd_enabled_odd_nodes_no_qdevice_plus_node(
15f218
-        self, mock_enabled, mock_installed
15f218
-    ):
15f218
-        mock_enabled.return_value = True
15f218
-        mock_installed.return_value = True
15f218
-        self._set_ret_vals([1, 2, 3], False)
15f218
-        self.assertTrue(lib_sbd.is_auto_tie_breaker_needed(
15f218
-            self.runner, self.mock_corosync_conf, 1
15f218
-        ))
15f218
-
15f218
-    def test_sbd_not_installed_odd_nodes_no_qdevice_plus_node(
15f218
-        self, mock_enabled, mock_installed
15f218
-    ):
15f218
-        mock_enabled.return_value = False
15f218
-        mock_installed.return_value = False
15f218
-        self._set_ret_vals([1, 2, 3], False)
15f218
-        self.assertFalse(lib_sbd.is_auto_tie_breaker_needed(
15f218
-            self.runner, self.mock_corosync_conf, 1
15f218
-        ))
15f218
-
15f218
-    def test_sbd_enabled_odd_nodes_no_qdevice_minus_node(
15f218
-        self, mock_enabled, mock_installed
15f218
-    ):
15f218
-        mock_enabled.return_value = True
15f218
-        mock_installed.return_value = True
15f218
-        self._set_ret_vals([1, 2, 3], False)
15f218
-        self.assertTrue(lib_sbd.is_auto_tie_breaker_needed(
15f218
-            self.runner, self.mock_corosync_conf, -1
15f218
-        ))
15f218
-
15f218
-    def test_sbd_enabled_odd_nodes_no_qdevice_plus_2_nodes(
15f218
-        self, mock_enabled, mock_installed
15f218
-    ):
15f218
-        mock_enabled.return_value = True
15f218
-        mock_installed.return_value = True
15f218
-        self._set_ret_vals([1, 2, 3], False)
15f218
-        self.assertFalse(lib_sbd.is_auto_tie_breaker_needed(
15f218
-            self.runner, self.mock_corosync_conf, 2
15f218
-        ))
15f218
-
15f218
-    def test_sbd_enabled_odd_nodes_no_qdevice_minus_2_nodes(
15f218
-        self, mock_enabled, mock_installed
15f218
-    ):
15f218
-        mock_enabled.return_value = True
15f218
-        mock_installed.return_value = True
15f218
-        self._set_ret_vals([1, 2, 3], False)
15f218
-        self.assertFalse(lib_sbd.is_auto_tie_breaker_needed(
15f218
-            self.runner, self.mock_corosync_conf, -2
15f218
+    def test_odd_num_qdevice(self):
15f218
+        self._set_ret_vals([1, 2, 3], True)
15f218
+        self.assertFalse(lib_sbd._even_number_of_nodes_and_no_qdevice(
15f218
+            self.mock_corosync_conf
15f218
         ))
15f218
 
15f218
-    def test_sbd_enabled_even_nodes_no_qdevice_plus_node(
15f218
-        self, mock_enabled, mock_installed
15f218
-    ):
15f218
-        mock_enabled.return_value = True
15f218
-        mock_installed.return_value = True
15f218
+    def test_even_num_no_qdevice_plus_one(self):
15f218
         self._set_ret_vals([1, 2], False)
15f218
-        self.assertFalse(lib_sbd.is_auto_tie_breaker_needed(
15f218
-            self.runner, self.mock_corosync_conf, 1
15f218
+        self.assertFalse(lib_sbd._even_number_of_nodes_and_no_qdevice(
15f218
+            self.mock_corosync_conf, 1
15f218
         ))
15f218
 
15f218
-    def test_sbd_enabled_even_nodes_no_qdevice_minus_node(
15f218
-        self, mock_enabled, mock_installed
15f218
-    ):
15f218
-        mock_enabled.return_value = True
15f218
-        mock_installed.return_value = True
15f218
-        self._set_ret_vals([1, 2], False)
15f218
-        self.assertFalse(lib_sbd.is_auto_tie_breaker_needed(
15f218
-            self.runner, self.mock_corosync_conf, -1
15f218
+    def test_even_num_qdevice_plus_one(self):
15f218
+        self._set_ret_vals([1, 2], True)
15f218
+        self.assertFalse(lib_sbd._even_number_of_nodes_and_no_qdevice(
15f218
+            self.mock_corosync_conf, 1
15f218
         ))
15f218
 
15f218
-    def test_sbd_enabled_even_nodes_no_qdevice_plus_2_nodes(
15f218
-        self, mock_enabled, mock_installed
15f218
-    ):
15f218
-        mock_enabled.return_value = True
15f218
-        mock_installed.return_value = True
15f218
-        self._set_ret_vals([1, 2], False)
15f218
-        self.assertTrue(lib_sbd.is_auto_tie_breaker_needed(
15f218
-            self.runner, self.mock_corosync_conf, 2
15f218
+    def test_odd_num_no_qdevice_plus_one(self):
15f218
+        self._set_ret_vals([1, 2, 3], False)
15f218
+        self.assertTrue(lib_sbd._even_number_of_nodes_and_no_qdevice(
15f218
+            self.mock_corosync_conf, 1
15f218
         ))
15f218
 
15f218
-    def test_sbd_enabled_even_nodes_no_qdevice_minus_2_nodes(
15f218
-        self, mock_enabled, mock_installed
15f218
-    ):
15f218
-        mock_enabled.return_value = True
15f218
-        mock_installed.return_value = True
15f218
-        self._set_ret_vals([1, 2, 3, 4], False)
15f218
-        self.assertTrue(lib_sbd.is_auto_tie_breaker_needed(
15f218
-            self.runner, self.mock_corosync_conf, -2
15f218
+    def test_odd_num_qdevice_plus_one(self):
15f218
+        self._set_ret_vals([1, 2, 3], True)
15f218
+        self.assertFalse(lib_sbd._even_number_of_nodes_and_no_qdevice(
15f218
+            self.mock_corosync_conf, 1
15f218
         ))
15f218
 
15f218
 
15f218
-- 
15f218
1.8.3.1
15f218