Blame SOURCES/bz2158790-01-fix-stonith-watchdog-timeout-validation.patch

9183b6
From bbf53f713189eb2233efa03bf3aa9c96eb79ba82 Mon Sep 17 00:00:00 2001
9183b6
From: Miroslav Lisik <mlisik@redhat.com>
9183b6
Date: Thu, 5 Jan 2023 16:21:44 +0100
9183b6
Subject: [PATCH 2/2] Fix stonith-watchdog-timeout validation
9183b6
9183b6
---
9183b6
 CHANGELOG.md                                  |  2 +
9183b6
 pcs/lib/cluster_property.py                   | 25 ++++-
9183b6
 pcs/lib/sbd.py                                | 15 ++-
9183b6
 .../lib/commands/test_cluster_property.py     | 50 ++++++++--
9183b6
 pcs_test/tier0/lib/test_cluster_property.py   | 98 ++++++++++++++-----
9183b6
 pcs_test/tier1/test_cluster_property.py       | 14 ++-
9183b6
 6 files changed, 159 insertions(+), 45 deletions(-)
9183b6
9183b6
diff --git a/CHANGELOG.md b/CHANGELOG.md
9183b6
index 47212f00..0945d727 100644
9183b6
--- a/CHANGELOG.md
9183b6
+++ b/CHANGELOG.md
9183b6
@@ -11,6 +11,7 @@
9183b6
 - Graceful stopping pcsd service using `systemctl stop pcsd` command
9183b6
 - Displaying bool and integer values in `pcs resource config` command
9183b6
   ([rhbz#2151164], [ghissue#604])
9183b6
+- Allow time values in stonith-watchdog-time property ([rhbz#2158790])
9183b6
 
9183b6
 ### Changed
9183b6
 - Resource/stonith agent self-validation of instance attributes is now
9183b6
@@ -22,6 +23,7 @@
9183b6
 [rhbz#2151164]: https://bugzilla.redhat.com/show_bug.cgi?id=2151164
9183b6
 [rhbz#2151524]: https://bugzilla.redhat.com/show_bug.cgi?id=2151524
9183b6
 [rhbz#2159454]: https://bugzilla.redhat.com/show_bug.cgi?id=2159454
9183b6
+[rhbz#2158790]: https://bugzilla.redhat.com/show_bug.cgi?id=2158790
9183b6
 
9183b6
 
9183b6
 ## [0.11.4] - 2022-11-21
9183b6
diff --git a/pcs/lib/cluster_property.py b/pcs/lib/cluster_property.py
9183b6
index 3bbc093d..d3c8a896 100644
9183b6
--- a/pcs/lib/cluster_property.py
9183b6
+++ b/pcs/lib/cluster_property.py
9183b6
@@ -7,6 +7,7 @@ from lxml.etree import _Element
9183b6
 
9183b6
 from pcs.common import reports
9183b6
 from pcs.common.services.interfaces import ServiceManagerInterface
9183b6
+from pcs.common.tools import timeout_to_seconds
9183b6
 from pcs.common.types import StringSequence
9183b6
 from pcs.lib import (
9183b6
     sbd,
9183b6
@@ -37,8 +38,21 @@ def _validate_stonith_watchdog_timeout_property(
9183b6
     force: bool = False,
9183b6
 ) -> reports.ReportItemList:
9183b6
     report_list: reports.ReportItemList = []
9183b6
+    original_value = value
9183b6
+    # if value is not empty, try to convert time interval string
9183b6
+    if value:
9183b6
+        seconds = timeout_to_seconds(value)
9183b6
+        if seconds is None:
9183b6
+            # returns empty list because this should be reported by
9183b6
+            # ValueTimeInterval validator
9183b6
+            return report_list
9183b6
+        value = str(seconds)
9183b6
     if sbd.is_sbd_enabled(service_manager):
9183b6
-        report_list.extend(sbd.validate_stonith_watchdog_timeout(value, force))
9183b6
+        report_list.extend(
9183b6
+            sbd.validate_stonith_watchdog_timeout(
9183b6
+                validate.ValuePair(original_value, value), force
9183b6
+            )
9183b6
+        )
9183b6
     else:
9183b6
         if value not in ["", "0"]:
9183b6
             report_list.append(
9183b6
@@ -123,9 +137,6 @@ def validate_set_cluster_properties(
9183b6
             # unknow properties are reported by NamesIn validator
9183b6
             continue
9183b6
         property_metadata = possible_properties_dict[property_name]
9183b6
-        if property_metadata.name == "stonith-watchdog-timeout":
9183b6
-            # needs extra validation
9183b6
-            continue
9183b6
         if property_metadata.type == "boolean":
9183b6
             validators.append(
9183b6
                 validate.ValuePcmkBoolean(
9183b6
@@ -153,9 +164,13 @@ def validate_set_cluster_properties(
9183b6
                 )
9183b6
             )
9183b6
         elif property_metadata.type == "time":
9183b6
+            # make stonith-watchdog-timeout value not forcable
9183b6
             validators.append(
9183b6
                 validate.ValueTimeInterval(
9183b6
-                    property_metadata.name, severity=severity
9183b6
+                    property_metadata.name,
9183b6
+                    severity=severity
9183b6
+                    if property_metadata.name != "stonith-watchdog-timeout"
9183b6
+                    else reports.ReportItemSeverity.error(),
9183b6
                 )
9183b6
             )
9183b6
     report_list.extend(
9183b6
diff --git a/pcs/lib/sbd.py b/pcs/lib/sbd.py
9183b6
index 1e3cfb37..38cd8767 100644
9183b6
--- a/pcs/lib/sbd.py
9183b6
+++ b/pcs/lib/sbd.py
9183b6
@@ -1,6 +1,9 @@
9183b6
 import re
9183b6
 from os import path
9183b6
-from typing import Optional
9183b6
+from typing import (
9183b6
+    Optional,
9183b6
+    Union,
9183b6
+)
9183b6
 
9183b6
 from pcs import settings
9183b6
 from pcs.common import reports
9183b6
@@ -392,7 +395,10 @@ def _get_local_sbd_watchdog_timeout() -> int:
9183b6
 
9183b6
 
9183b6
 def validate_stonith_watchdog_timeout(
9183b6
-    stonith_watchdog_timeout: str, force: bool = False
9183b6
+    stonith_watchdog_timeout: Union[
9183b6
+        validate.TypeOptionValue, validate.ValuePair
9183b6
+    ],
9183b6
+    force: bool = False,
9183b6
 ) -> reports.ReportItemList:
9183b6
     """
9183b6
     Check sbd status and config when user is setting stonith-watchdog-timeout
9183b6
@@ -401,6 +407,7 @@ def validate_stonith_watchdog_timeout(
9183b6
 
9183b6
     stonith_watchdog_timeout -- value to be validated
9183b6
     """
9183b6
+    stonith_watchdog_timeout = validate.ValuePair.get(stonith_watchdog_timeout)
9183b6
     severity = reports.get_severity(reports.codes.FORCE, force)
9183b6
     if _is_device_set_local():
9183b6
         return (
9183b6
@@ -412,11 +419,11 @@ def validate_stonith_watchdog_timeout(
9183b6
                     ),
9183b6
                 )
9183b6
             ]
9183b6
-            if stonith_watchdog_timeout not in ["", "0"]
9183b6
+            if stonith_watchdog_timeout.normalized not in ["", "0"]
9183b6
             else []
9183b6
         )
9183b6
 
9183b6
-    if stonith_watchdog_timeout in ["", "0"]:
9183b6
+    if stonith_watchdog_timeout.normalized in ["", "0"]:
9183b6
         return [
9183b6
             reports.ReportItem(
9183b6
                 severity,
9183b6
diff --git a/pcs_test/tier0/lib/commands/test_cluster_property.py b/pcs_test/tier0/lib/commands/test_cluster_property.py
9183b6
index 94c0938a..781222ab 100644
9183b6
--- a/pcs_test/tier0/lib/commands/test_cluster_property.py
9183b6
+++ b/pcs_test/tier0/lib/commands/test_cluster_property.py
9183b6
@@ -120,6 +120,34 @@ class StonithWatchdogTimeoutMixin(LoadMetadataMixin):
9183b6
         )
9183b6
         self.env_assist.assert_reports([])
9183b6
 
9183b6
+    def _set_invalid_value(self, forced=False):
9183b6
+        self.config.remove("services.is_enabled")
9183b6
+        self.env_assist.assert_raise_library_error(
9183b6
+            lambda: cluster_property.set_properties(
9183b6
+                self.env_assist.get_env(),
9183b6
+                {"stonith-watchdog-timeout": "15x"},
9183b6
+                [] if not forced else [reports.codes.FORCE],
9183b6
+            )
9183b6
+        )
9183b6
+        self.env_assist.assert_reports(
9183b6
+            [
9183b6
+                fixture.error(
9183b6
+                    reports.codes.INVALID_OPTION_VALUE,
9183b6
+                    option_name="stonith-watchdog-timeout",
9183b6
+                    option_value="15x",
9183b6
+                    allowed_values="time interval (e.g. 1, 2s, 3m, 4h, ...)",
9183b6
+                    cannot_be_empty=False,
9183b6
+                    forbidden_characters=None,
9183b6
+                ),
9183b6
+            ]
9183b6
+        )
9183b6
+
9183b6
+    def test_set_invalid_value(self):
9183b6
+        self._set_invalid_value(forced=False)
9183b6
+
9183b6
+    def test_set_invalid_value_forced(self):
9183b6
+        self._set_invalid_value(forced=True)
9183b6
+
9183b6
 
9183b6
 class TestSetStonithWatchdogTimeoutSBDIsDisabled(
9183b6
     StonithWatchdogTimeoutMixin, TestCase
9183b6
@@ -132,6 +160,9 @@ class TestSetStonithWatchdogTimeoutSBDIsDisabled(
9183b6
     def test_set_zero(self):
9183b6
         self._set_success({"stonith-watchdog-timeout": "0"})
9183b6
 
9183b6
+    def test_set_zero_time_suffix(self):
9183b6
+        self._set_success({"stonith-watchdog-timeout": "0s"})
9183b6
+
9183b6
     def test_set_not_zero_or_empty(self):
9183b6
         self.env_assist.assert_raise_library_error(
9183b6
             lambda: cluster_property.set_properties(
9183b6
@@ -231,12 +262,12 @@ class TestSetStonithWatchdogTimeoutSBDIsEnabledWatchdogOnly(
9183b6
     def test_set_zero_forced(self):
9183b6
         self.config.env.push_cib(
9183b6
             crm_config=fixture_crm_config_properties(
9183b6
-                [("cib-bootstrap-options", {"stonith-watchdog-timeout": "0"})]
9183b6
+                [("cib-bootstrap-options", {"stonith-watchdog-timeout": "0s"})]
9183b6
             )
9183b6
         )
9183b6
         cluster_property.set_properties(
9183b6
             self.env_assist.get_env(),
9183b6
-            {"stonith-watchdog-timeout": "0"},
9183b6
+            {"stonith-watchdog-timeout": "0s"},
9183b6
             [reports.codes.FORCE],
9183b6
         )
9183b6
         self.env_assist.assert_reports(
9183b6
@@ -271,7 +302,7 @@ class TestSetStonithWatchdogTimeoutSBDIsEnabledWatchdogOnly(
9183b6
         self.env_assist.assert_raise_library_error(
9183b6
             lambda: cluster_property.set_properties(
9183b6
                 self.env_assist.get_env(),
9183b6
-                {"stonith-watchdog-timeout": "9"},
9183b6
+                {"stonith-watchdog-timeout": "9s"},
9183b6
                 [],
9183b6
             )
9183b6
         )
9183b6
@@ -281,7 +312,7 @@ class TestSetStonithWatchdogTimeoutSBDIsEnabledWatchdogOnly(
9183b6
                     reports.codes.STONITH_WATCHDOG_TIMEOUT_TOO_SMALL,
9183b6
                     force_code=reports.codes.FORCE,
9183b6
                     cluster_sbd_watchdog_timeout=10,
9183b6
-                    entered_watchdog_timeout="9",
9183b6
+                    entered_watchdog_timeout="9s",
9183b6
                 )
9183b6
             ]
9183b6
         )
9183b6
@@ -289,12 +320,12 @@ class TestSetStonithWatchdogTimeoutSBDIsEnabledWatchdogOnly(
9183b6
     def test_too_small_forced(self):
9183b6
         self.config.env.push_cib(
9183b6
             crm_config=fixture_crm_config_properties(
9183b6
-                [("cib-bootstrap-options", {"stonith-watchdog-timeout": "9"})]
9183b6
+                [("cib-bootstrap-options", {"stonith-watchdog-timeout": "9s"})]
9183b6
             )
9183b6
         )
9183b6
         cluster_property.set_properties(
9183b6
             self.env_assist.get_env(),
9183b6
-            {"stonith-watchdog-timeout": "9"},
9183b6
+            {"stonith-watchdog-timeout": "9s"},
9183b6
             [reports.codes.FORCE],
9183b6
         )
9183b6
         self.env_assist.assert_reports(
9183b6
@@ -302,13 +333,13 @@ class TestSetStonithWatchdogTimeoutSBDIsEnabledWatchdogOnly(
9183b6
                 fixture.warn(
9183b6
                     reports.codes.STONITH_WATCHDOG_TIMEOUT_TOO_SMALL,
9183b6
                     cluster_sbd_watchdog_timeout=10,
9183b6
-                    entered_watchdog_timeout="9",
9183b6
+                    entered_watchdog_timeout="9s",
9183b6
                 )
9183b6
             ]
9183b6
         )
9183b6
 
9183b6
     def test_more_than_timeout(self):
9183b6
-        self._set_success({"stonith-watchdog-timeout": "11"})
9183b6
+        self._set_success({"stonith-watchdog-timeout": "11s"})
9183b6
 
9183b6
 
9183b6
 @mock.patch("pcs.lib.sbd.get_local_sbd_device_list", lambda: ["dev1", "dev2"])
9183b6
@@ -323,6 +354,9 @@ class TestSetStonithWatchdogTimeoutSBDIsEnabledSharedDevices(
9183b6
     def test_set_to_zero(self):
9183b6
         self._set_success({"stonith-watchdog-timeout": "0"})
9183b6
 
9183b6
+    def test_set_to_zero_time_suffix(self):
9183b6
+        self._set_success({"stonith-watchdog-timeout": "0min"})
9183b6
+
9183b6
     def test_set_not_zero_or_empty(self):
9183b6
         self.env_assist.assert_raise_library_error(
9183b6
             lambda: cluster_property.set_properties(
9183b6
diff --git a/pcs_test/tier0/lib/test_cluster_property.py b/pcs_test/tier0/lib/test_cluster_property.py
9183b6
index 2feb728d..8d6f90b1 100644
9183b6
--- a/pcs_test/tier0/lib/test_cluster_property.py
9183b6
+++ b/pcs_test/tier0/lib/test_cluster_property.py
9183b6
@@ -83,6 +83,7 @@ FIXTURE_VALID_OPTIONS_DICT = {
9183b6
     "integer_param": "10",
9183b6
     "percentage_param": "20%",
9183b6
     "select_param": "s3",
9183b6
+    "stonith-watchdog-timeout": "0",
9183b6
     "time_param": "5min",
9183b6
 }
9183b6
 
9183b6
@@ -96,6 +97,8 @@ FIXTURE_INVALID_OPTIONS_DICT = {
9183b6
     "have-watchdog": "100",
9183b6
 }
9183b6
 
9183b6
+STONITH_WATCHDOG_TIMEOUT_UNSET_VALUES = ["", "0", "0s"]
9183b6
+
9183b6
 
9183b6
 def _fixture_parameter(name, param_type, default, enum_values):
9183b6
     return ResourceAgentParameter(
9183b6
@@ -239,6 +242,7 @@ class TestValidateSetClusterProperties(TestCase):
9183b6
         sbd_enabled=False,
9183b6
         sbd_devices=False,
9183b6
         force=False,
9183b6
+        valid_value=True,
9183b6
     ):
9183b6
         self.mock_is_sbd_enabled.return_value = sbd_enabled
9183b6
         self.mock_sbd_devices.return_value = ["devices"] if sbd_devices else []
9183b6
@@ -254,9 +258,13 @@ class TestValidateSetClusterProperties(TestCase):
9183b6
             ),
9183b6
             expected_report_list,
9183b6
         )
9183b6
-        if "stonith-watchdog-timeout" in new_properties and (
9183b6
-            new_properties["stonith-watchdog-timeout"]
9183b6
-            or "stonith-watchdog-timeout" in configured_properties
9183b6
+        if (
9183b6
+            "stonith-watchdog-timeout" in new_properties
9183b6
+            and (
9183b6
+                new_properties["stonith-watchdog-timeout"]
9183b6
+                or "stonith-watchdog-timeout" in configured_properties
9183b6
+            )
9183b6
+            and valid_value
9183b6
         ):
9183b6
             self.mock_is_sbd_enabled.assert_called_once_with(
9183b6
                 self.mock_service_manager
9183b6
@@ -266,7 +274,10 @@ class TestValidateSetClusterProperties(TestCase):
9183b6
                 if sbd_devices:
9183b6
                     self.mock_sbd_timeout.assert_not_called()
9183b6
                 else:
9183b6
-                    if new_properties["stonith-watchdog-timeout"] in ["", "0"]:
9183b6
+                    if (
9183b6
+                        new_properties["stonith-watchdog-timeout"]
9183b6
+                        in STONITH_WATCHDOG_TIMEOUT_UNSET_VALUES
9183b6
+                    ):
9183b6
                         self.mock_sbd_timeout.assert_not_called()
9183b6
                     else:
9183b6
                         self.mock_sbd_timeout.assert_called_once_with()
9183b6
@@ -280,6 +291,8 @@ class TestValidateSetClusterProperties(TestCase):
9183b6
             self.mock_sbd_timeout.assert_not_called()
9183b6
 
9183b6
         self.mock_is_sbd_enabled.reset_mock()
9183b6
+        self.mock_sbd_devices.reset_mock()
9183b6
+        self.mock_sbd_timeout.reset_mock()
9183b6
 
9183b6
     def test_no_properties_to_set_or_unset(self):
9183b6
         self.assert_validate_set(
9183b6
@@ -328,7 +341,7 @@ class TestValidateSetClusterProperties(TestCase):
9183b6
         )
9183b6
 
9183b6
     def test_unset_stonith_watchdog_timeout_sbd_disabled(self):
9183b6
-        for value in ["0", ""]:
9183b6
+        for value in STONITH_WATCHDOG_TIMEOUT_UNSET_VALUES:
9183b6
             with self.subTest(value=value):
9183b6
                 self.assert_validate_set(
9183b6
                     ["stonith-watchdog-timeout"],
9183b6
@@ -349,22 +362,27 @@ class TestValidateSetClusterProperties(TestCase):
9183b6
         )
9183b6
 
9183b6
     def test_set_ok_stonith_watchdog_timeout_sbd_enabled_without_devices(self):
9183b6
-        self.assert_validate_set(
9183b6
-            [], {"stonith-watchdog-timeout": "15"}, [], sbd_enabled=True
9183b6
-        )
9183b6
+        for value in ["15", "15s"]:
9183b6
+            with self.subTest(value=value):
9183b6
+                self.assert_validate_set(
9183b6
+                    [],
9183b6
+                    {"stonith-watchdog-timeout": value},
9183b6
+                    [],
9183b6
+                    sbd_enabled=True,
9183b6
+                )
9183b6
 
9183b6
     def test_set_small_stonith_watchdog_timeout_sbd_enabled_without_devices(
9183b6
         self,
9183b6
     ):
9183b6
         self.assert_validate_set(
9183b6
             [],
9183b6
-            {"stonith-watchdog-timeout": "9"},
9183b6
+            {"stonith-watchdog-timeout": "9s"},
9183b6
             [
9183b6
                 fixture.error(
9183b6
                     reports.codes.STONITH_WATCHDOG_TIMEOUT_TOO_SMALL,
9183b6
                     force_code=reports.codes.FORCE,
9183b6
                     cluster_sbd_watchdog_timeout=10,
9183b6
-                    entered_watchdog_timeout="9",
9183b6
+                    entered_watchdog_timeout="9s",
9183b6
                 )
9183b6
             ],
9183b6
             sbd_enabled=True,
9183b6
@@ -387,28 +405,54 @@ class TestValidateSetClusterProperties(TestCase):
9183b6
             force=True,
9183b6
         )
9183b6
 
9183b6
-    def test_set_not_a_number_stonith_watchdog_timeout_sbd_enabled_without_devices(
9183b6
+    def _set_invalid_value_stonith_watchdog_timeout(
9183b6
+        self, sbd_enabled=False, sbd_devices=False
9183b6
+    ):
9183b6
+        for value in ["invalid", "10x"]:
9183b6
+            with self.subTest(value=value):
9183b6
+                self.assert_validate_set(
9183b6
+                    [],
9183b6
+                    {"stonith-watchdog-timeout": value},
9183b6
+                    [
9183b6
+                        fixture.error(
9183b6
+                            reports.codes.INVALID_OPTION_VALUE,
9183b6
+                            option_name="stonith-watchdog-timeout",
9183b6
+                            option_value=value,
9183b6
+                            allowed_values="time interval (e.g. 1, 2s, 3m, 4h, ...)",
9183b6
+                            cannot_be_empty=False,
9183b6
+                            forbidden_characters=None,
9183b6
+                        )
9183b6
+                    ],
9183b6
+                    sbd_enabled=sbd_enabled,
9183b6
+                    sbd_devices=sbd_devices,
9183b6
+                    valid_value=False,
9183b6
+                )
9183b6
+
9183b6
+    def test_set_invalid_value_stonith_watchdog_timeout_sbd_enabled_without_devices(
9183b6
         self,
9183b6
     ):
9183b6
+        self._set_invalid_value_stonith_watchdog_timeout(
9183b6
+            sbd_enabled=True, sbd_devices=False
9183b6
+        )
9183b6
 
9183b6
-        self.assert_validate_set(
9183b6
-            [],
9183b6
-            {"stonith-watchdog-timeout": "invalid"},
9183b6
-            [
9183b6
-                fixture.error(
9183b6
-                    reports.codes.STONITH_WATCHDOG_TIMEOUT_TOO_SMALL,
9183b6
-                    force_code=reports.codes.FORCE,
9183b6
-                    cluster_sbd_watchdog_timeout=10,
9183b6
-                    entered_watchdog_timeout="invalid",
9183b6
-                )
9183b6
-            ],
9183b6
-            sbd_enabled=True,
9183b6
+    def test_set_invalid_value_stonith_watchdog_timeout_sbd_enabled_with_devices(
9183b6
+        self,
9183b6
+    ):
9183b6
+        self._set_invalid_value_stonith_watchdog_timeout(
9183b6
+            sbd_enabled=True, sbd_devices=True
9183b6
+        )
9183b6
+
9183b6
+    def test_set_invalid_value_stonith_watchdog_timeout_sbd_disabled(
9183b6
+        self,
9183b6
+    ):
9183b6
+        self._set_invalid_value_stonith_watchdog_timeout(
9183b6
+            sbd_enabled=False, sbd_devices=False
9183b6
         )
9183b6
 
9183b6
     def test_unset_stonith_watchdog_timeout_sbd_enabled_without_devices(
9183b6
         self,
9183b6
     ):
9183b6
-        for value in ["0", ""]:
9183b6
+        for value in STONITH_WATCHDOG_TIMEOUT_UNSET_VALUES:
9183b6
             with self.subTest(value=value):
9183b6
                 self.assert_validate_set(
9183b6
                     ["stonith-watchdog-timeout"],
9183b6
@@ -426,7 +470,7 @@ class TestValidateSetClusterProperties(TestCase):
9183b6
     def test_unset_stonith_watchdog_timeout_sbd_enabled_without_devices_forced(
9183b6
         self,
9183b6
     ):
9183b6
-        for value in ["0", ""]:
9183b6
+        for value in STONITH_WATCHDOG_TIMEOUT_UNSET_VALUES:
9183b6
             with self.subTest(value=value):
9183b6
                 self.assert_validate_set(
9183b6
                     ["stonith-watchdog-timeout"],
9183b6
@@ -459,7 +503,7 @@ class TestValidateSetClusterProperties(TestCase):
9183b6
     def test_set_stonith_watchdog_timeout_sbd_enabled_with_devices_forced(self):
9183b6
         self.assert_validate_set(
9183b6
             [],
9183b6
-            {"stonith-watchdog-timeout": 15},
9183b6
+            {"stonith-watchdog-timeout": "15s"},
9183b6
             [
9183b6
                 fixture.warn(
9183b6
                     reports.codes.STONITH_WATCHDOG_TIMEOUT_CANNOT_BE_SET,
9183b6
@@ -472,7 +516,7 @@ class TestValidateSetClusterProperties(TestCase):
9183b6
         )
9183b6
 
9183b6
     def test_unset_stonith_watchdog_timeout_sbd_enabled_with_devices(self):
9183b6
-        for value in ["0", ""]:
9183b6
+        for value in STONITH_WATCHDOG_TIMEOUT_UNSET_VALUES:
9183b6
             with self.subTest(value=value):
9183b6
                 self.assert_validate_set(
9183b6
                     ["stonith-watchdog-timeout"],
9183b6
diff --git a/pcs_test/tier1/test_cluster_property.py b/pcs_test/tier1/test_cluster_property.py
9183b6
index 39d70b9d..cb2d8f5c 100644
9183b6
--- a/pcs_test/tier1/test_cluster_property.py
9183b6
+++ b/pcs_test/tier1/test_cluster_property.py
9183b6
@@ -169,7 +169,7 @@ class TestPropertySet(PropertyMixin, TestCase):
9183b6
 
9183b6
     def test_set_stonith_watchdog_timeout(self):
9183b6
         self.assert_pcs_fail(
9183b6
-            "property set stonith-watchdog-timeout=5".split(),
9183b6
+            "property set stonith-watchdog-timeout=5s".split(),
9183b6
             stderr_full=(
9183b6
                 "Error: stonith-watchdog-timeout can only be unset or set to 0 "
9183b6
                 "while SBD is disabled\n"
9183b6
@@ -179,6 +179,18 @@ class TestPropertySet(PropertyMixin, TestCase):
9183b6
         )
9183b6
         self.assert_resources_xml_in_cib(UNCHANGED_CRM_CONFIG)
9183b6
 
9183b6
+    def test_set_stonith_watchdog_timeout_invalid_value(self):
9183b6
+        self.assert_pcs_fail(
9183b6
+            "property set stonith-watchdog-timeout=5x".split(),
9183b6
+            stderr_full=(
9183b6
+                "Error: '5x' is not a valid stonith-watchdog-timeout value, use"
9183b6
+                " time interval (e.g. 1, 2s, 3m, 4h, ...)\n"
9183b6
+                "Error: Errors have occurred, therefore pcs is unable to "
9183b6
+                "continue\n"
9183b6
+            ),
9183b6
+        )
9183b6
+        self.assert_resources_xml_in_cib(UNCHANGED_CRM_CONFIG)
9183b6
+
9183b6
 
9183b6
 class TestPropertyUnset(PropertyMixin, TestCase):
9183b6
     def test_success(self):
9183b6
-- 
9183b6
2.39.0
9183b6