|
|
a3a2ad |
From b3b7bf416724f424a280c63f94121fb47e7397e6 Mon Sep 17 00:00:00 2001
|
|
|
a3a2ad |
From: Tomas Jelinek <tojeline@redhat.com>
|
|
|
a3a2ad |
Date: Mon, 11 Dec 2017 08:54:26 +0100
|
|
|
a3a2ad |
Subject: [PATCH] warn when a stonith device has method=cycle set
|
|
|
a3a2ad |
|
|
|
a3a2ad |
---
|
|
|
a3a2ad |
pcs/status.py | 21 ++++++++++++++--
|
|
|
a3a2ad |
pcs/test/test_status.py | 47 ++++++++++++++++++++++++-----------
|
|
|
a3a2ad |
pcsd/cluster_entity.rb | 22 +++++++++++++++++
|
|
|
a3a2ad |
pcsd/test/cib1.xml | 2 ++
|
|
|
a3a2ad |
pcsd/test/test_cluster_entity.rb | 53 ++++++++++++++++++++++++++++++++++++++++
|
|
|
a3a2ad |
5 files changed, 129 insertions(+), 16 deletions(-)
|
|
|
a3a2ad |
|
|
|
a3a2ad |
diff --git a/pcs/status.py b/pcs/status.py
|
|
|
a3a2ad |
index ec10d61..8a517be 100644
|
|
|
a3a2ad |
--- a/pcs/status.py
|
|
|
a3a2ad |
+++ b/pcs/status.py
|
|
|
a3a2ad |
@@ -125,6 +125,7 @@ def status_stonith_check():
|
|
|
a3a2ad |
stonith_enabled = True
|
|
|
a3a2ad |
stonith_devices = []
|
|
|
a3a2ad |
stonith_devices_id_action = []
|
|
|
a3a2ad |
+ stonith_devices_id_method_cycle = []
|
|
|
a3a2ad |
sbd_running = False
|
|
|
a3a2ad |
|
|
|
a3a2ad |
cib = utils.get_cib_dom()
|
|
|
a3a2ad |
@@ -155,6 +156,14 @@ def status_stonith_check():
|
|
|
a3a2ad |
stonith_devices_id_action.append(
|
|
|
a3a2ad |
resource.getAttribute("id")
|
|
|
a3a2ad |
)
|
|
|
a3a2ad |
+ if (
|
|
|
a3a2ad |
+ nvpair.getAttribute("name") == "method"
|
|
|
a3a2ad |
+ and
|
|
|
a3a2ad |
+ nvpair.getAttribute("value") == "cycle"
|
|
|
a3a2ad |
+ ):
|
|
|
a3a2ad |
+ stonith_devices_id_method_cycle.append(
|
|
|
a3a2ad |
+ resource.getAttribute("id")
|
|
|
a3a2ad |
+ )
|
|
|
a3a2ad |
|
|
|
a3a2ad |
if not utils.usefile:
|
|
|
a3a2ad |
# check if SBD daemon is running
|
|
|
a3a2ad |
@@ -171,14 +180,22 @@ def status_stonith_check():
|
|
|
a3a2ad |
|
|
|
a3a2ad |
if stonith_devices_id_action:
|
|
|
a3a2ad |
print(
|
|
|
a3a2ad |
- "WARNING: following stonith devices have the 'action' attribute"
|
|
|
a3a2ad |
- " set, it is recommended to set {0} instead: {1}".format(
|
|
|
a3a2ad |
+ "WARNING: following stonith devices have the 'action' option set, "
|
|
|
a3a2ad |
+ "it is recommended to set {0} instead: {1}".format(
|
|
|
a3a2ad |
", ".join(
|
|
|
a3a2ad |
["'{0}'".format(x) for x in _STONITH_ACTION_REPLACED_BY]
|
|
|
a3a2ad |
),
|
|
|
a3a2ad |
", ".join(sorted(stonith_devices_id_action))
|
|
|
a3a2ad |
)
|
|
|
a3a2ad |
)
|
|
|
a3a2ad |
+ if stonith_devices_id_method_cycle:
|
|
|
a3a2ad |
+ print(
|
|
|
a3a2ad |
+ "WARNING: following stonith devices have the 'method' option set "
|
|
|
a3a2ad |
+ "to 'cycle' which is potentially dangerous, please consider using "
|
|
|
a3a2ad |
+ "'onoff': {0}".format(
|
|
|
a3a2ad |
+ ", ".join(sorted(stonith_devices_id_method_cycle))
|
|
|
a3a2ad |
+ )
|
|
|
a3a2ad |
+ )
|
|
|
a3a2ad |
|
|
|
a3a2ad |
# Parse crm_mon for status
|
|
|
a3a2ad |
def nodes_status(argv):
|
|
|
a3a2ad |
diff --git a/pcs/test/test_status.py b/pcs/test/test_status.py
|
|
|
a3a2ad |
index b412b91..1a4fb70 100644
|
|
|
a3a2ad |
--- a/pcs/test/test_status.py
|
|
|
a3a2ad |
+++ b/pcs/test/test_status.py
|
|
|
a3a2ad |
@@ -21,45 +21,64 @@ class StonithWarningTest(TestCase, AssertPcsMixin):
|
|
|
a3a2ad |
shutil.copy(self.empty_cib, self.temp_cib)
|
|
|
a3a2ad |
self.pcs_runner = PcsRunner(self.temp_cib)
|
|
|
a3a2ad |
|
|
|
a3a2ad |
- def fixture_stonith(self, action=False):
|
|
|
a3a2ad |
+ def fixture_stonith_action(self):
|
|
|
a3a2ad |
self.assert_pcs_success(
|
|
|
a3a2ad |
- "stonith create S fence_apc ipaddr=i login=l {0} --force".format(
|
|
|
a3a2ad |
- "action=reboot" if action else ""
|
|
|
a3a2ad |
- ),
|
|
|
a3a2ad |
+ "stonith create Sa fence_apc ipaddr=i login=l action=reboot --force",
|
|
|
a3a2ad |
"Warning: stonith option 'action' is deprecated and should not be"
|
|
|
a3a2ad |
" used, use pcmk_off_action, pcmk_reboot_action instead\n"
|
|
|
a3a2ad |
- if action
|
|
|
a3a2ad |
- else ""
|
|
|
a3a2ad |
+ )
|
|
|
a3a2ad |
+
|
|
|
a3a2ad |
+ def fixture_stonith_cycle(self):
|
|
|
a3a2ad |
+ self.assert_pcs_success(
|
|
|
a3a2ad |
+ "stonith create Sc fence_ipmilan method=cycle"
|
|
|
a3a2ad |
)
|
|
|
a3a2ad |
|
|
|
a3a2ad |
def fixture_resource(self):
|
|
|
a3a2ad |
self.assert_pcs_success(
|
|
|
a3a2ad |
- "resource create dummy ocf:pacemaker:Dummy action=reboot --force",
|
|
|
a3a2ad |
- "Warning: invalid resource option 'action', allowed options are: "
|
|
|
a3a2ad |
- "envfile, fail_start_on, fake, op_sleep, passwd, state,"
|
|
|
a3a2ad |
- " trace_file, trace_ra\n"
|
|
|
a3a2ad |
+ "resource create dummy ocf:pacemaker:Dummy action=reboot "
|
|
|
a3a2ad |
+ "method=cycle --force"
|
|
|
a3a2ad |
+ ,
|
|
|
a3a2ad |
+ "Warning: invalid resource options: 'action', 'method', allowed "
|
|
|
a3a2ad |
+ "options are: envfile, fail_start_on, fake, op_sleep, passwd, "
|
|
|
a3a2ad |
+ "state, trace_file, trace_ra\n"
|
|
|
a3a2ad |
)
|
|
|
a3a2ad |
|
|
|
a3a2ad |
def test_warning_stonith_action(self):
|
|
|
a3a2ad |
- self.fixture_stonith(action=True)
|
|
|
a3a2ad |
+ self.fixture_stonith_action()
|
|
|
a3a2ad |
+ self.fixture_resource()
|
|
|
a3a2ad |
self.assert_pcs_success(
|
|
|
a3a2ad |
"status",
|
|
|
a3a2ad |
stdout_start=dedent("""\
|
|
|
a3a2ad |
Cluster name: test99
|
|
|
a3a2ad |
- WARNING: following stonith devices have the 'action' attribute set, it is recommended to set 'pcmk_off_action', 'pcmk_reboot_action' instead: S
|
|
|
a3a2ad |
+ WARNING: following stonith devices have the 'action' option set, it is recommended to set 'pcmk_off_action', 'pcmk_reboot_action' instead: Sa
|
|
|
a3a2ad |
Stack: unknown
|
|
|
a3a2ad |
Current DC: NONE
|
|
|
a3a2ad |
""")
|
|
|
a3a2ad |
)
|
|
|
a3a2ad |
|
|
|
a3a2ad |
- def test_action_ignored_for_non_stonith_resources(self):
|
|
|
a3a2ad |
- self.fixture_stonith(action=False)
|
|
|
a3a2ad |
+ def test_warning_stonith_method_cycle(self):
|
|
|
a3a2ad |
+ self.fixture_stonith_cycle()
|
|
|
a3a2ad |
self.fixture_resource()
|
|
|
a3a2ad |
+ self.assert_pcs_success(
|
|
|
a3a2ad |
+ "status",
|
|
|
a3a2ad |
+ stdout_start=dedent("""\
|
|
|
a3a2ad |
+ Cluster name: test99
|
|
|
a3a2ad |
+ WARNING: following stonith devices have the 'method' option set to 'cycle' which is potentially dangerous, please consider using 'onoff': Sc
|
|
|
a3a2ad |
+ Stack: unknown
|
|
|
a3a2ad |
+ Current DC: NONE
|
|
|
a3a2ad |
+ """)
|
|
|
a3a2ad |
+ )
|
|
|
a3a2ad |
|
|
|
a3a2ad |
+ def test_stonith_warnings(self):
|
|
|
a3a2ad |
+ self.fixture_stonith_action()
|
|
|
a3a2ad |
+ self.fixture_stonith_cycle()
|
|
|
a3a2ad |
+ self.fixture_resource()
|
|
|
a3a2ad |
self.assert_pcs_success(
|
|
|
a3a2ad |
"status",
|
|
|
a3a2ad |
stdout_start=dedent("""\
|
|
|
a3a2ad |
Cluster name: test99
|
|
|
a3a2ad |
+ WARNING: following stonith devices have the 'action' option set, it is recommended to set 'pcmk_off_action', 'pcmk_reboot_action' instead: Sa
|
|
|
a3a2ad |
+ WARNING: following stonith devices have the 'method' option set to 'cycle' which is potentially dangerous, please consider using 'onoff': Sc
|
|
|
a3a2ad |
Stack: unknown
|
|
|
a3a2ad |
Current DC: NONE
|
|
|
a3a2ad |
""")
|
|
|
a3a2ad |
diff --git a/pcsd/cluster_entity.rb b/pcsd/cluster_entity.rb
|
|
|
a3a2ad |
index 21092c5..3675719 100644
|
|
|
a3a2ad |
--- a/pcsd/cluster_entity.rb
|
|
|
a3a2ad |
+++ b/pcsd/cluster_entity.rb
|
|
|
a3a2ad |
@@ -516,6 +516,28 @@ module ClusterEntity
|
|
|
a3a2ad |
@utilization << ClusterEntity::NvPair.from_dom(e)
|
|
|
a3a2ad |
}
|
|
|
a3a2ad |
@stonith = @_class == 'stonith'
|
|
|
a3a2ad |
+ if @stonith
|
|
|
a3a2ad |
+ @instance_attr.each{ |attr|
|
|
|
a3a2ad |
+ if attr.name == 'action'
|
|
|
a3a2ad |
+ @warning_list << {
|
|
|
a3a2ad |
+ :message => (
|
|
|
a3a2ad |
+ 'This fence-device has the "action" option set, it is ' +
|
|
|
a3a2ad |
+ 'recommended to set "pcmk_off_action", "pcmk_reboot_action" ' +
|
|
|
a3a2ad |
+ 'instead'
|
|
|
a3a2ad |
+ )
|
|
|
a3a2ad |
+ }
|
|
|
a3a2ad |
+ end
|
|
|
a3a2ad |
+ if attr.name == 'method' and attr.value == 'cycle'
|
|
|
a3a2ad |
+ @warning_list << {
|
|
|
a3a2ad |
+ :message => (
|
|
|
a3a2ad |
+ 'This fence-device has the "method" option set to "cycle" ' +
|
|
|
a3a2ad |
+ 'which is potentially dangerous, please consider using ' +
|
|
|
a3a2ad |
+ '"onoff"'
|
|
|
a3a2ad |
+ )
|
|
|
a3a2ad |
+ }
|
|
|
a3a2ad |
+ end
|
|
|
a3a2ad |
+ }
|
|
|
a3a2ad |
+ end
|
|
|
a3a2ad |
if @id and rsc_status
|
|
|
a3a2ad |
@crm_status = rsc_status[@id] || []
|
|
|
a3a2ad |
end
|
|
|
a3a2ad |
diff --git a/pcsd/test/cib1.xml b/pcsd/test/cib1.xml
|
|
|
a3a2ad |
index f603f24..03749ab 100644
|
|
|
a3a2ad |
--- a/pcsd/test/cib1.xml
|
|
|
a3a2ad |
+++ b/pcsd/test/cib1.xml
|
|
|
a3a2ad |
@@ -28,6 +28,8 @@
|
|
|
a3a2ad |
<primitive class="stonith" id="node2-stonith" type="fence_xvm">
|
|
|
a3a2ad |
<instance_attributes id="node2-stonith-instance_attributes">
|
|
|
a3a2ad |
<nvpair id="node2-stonith-instance_attributes-domain" name="domain" value="node2"/>
|
|
|
a3a2ad |
+ <nvpair id="node2-stonith-instance_attributes-action" name="action" value="monitor"/>
|
|
|
a3a2ad |
+ <nvpair id="node2-stonith-instance_attributes-method" name="method" value="cycle"/>
|
|
|
a3a2ad |
</instance_attributes>
|
|
|
a3a2ad |
<operations>
|
|
|
a3a2ad |
<op id="node2-stonith-monitor-interval-60s" interval="60s" name="monitor"/>
|
|
|
a3a2ad |
diff --git a/pcsd/test/test_cluster_entity.rb b/pcsd/test/test_cluster_entity.rb
|
|
|
a3a2ad |
index 2b67e19..60719ef 100644
|
|
|
a3a2ad |
--- a/pcsd/test/test_cluster_entity.rb
|
|
|
a3a2ad |
+++ b/pcsd/test/test_cluster_entity.rb
|
|
|
a3a2ad |
@@ -719,6 +719,59 @@ class TestPrimitive < Test::Unit::TestCase
|
|
|
a3a2ad |
assert(obj.operations.empty?)
|
|
|
a3a2ad |
end
|
|
|
a3a2ad |
|
|
|
a3a2ad |
+ def test_init_stonith_with_warnings
|
|
|
a3a2ad |
+ obj = ClusterEntity::Primitive.new(
|
|
|
a3a2ad |
+ @cib.elements["//primitive[@id='node2-stonith']"]
|
|
|
a3a2ad |
+ )
|
|
|
a3a2ad |
+ assert_nil(obj.parent)
|
|
|
a3a2ad |
+ assert_nil(obj.get_master)
|
|
|
a3a2ad |
+ assert_nil(obj.get_clone)
|
|
|
a3a2ad |
+ assert_nil(obj.get_group)
|
|
|
a3a2ad |
+ assert(obj.meta_attr.empty?)
|
|
|
a3a2ad |
+ assert_equal('node2-stonith', obj.id)
|
|
|
a3a2ad |
+ assert(obj.error_list.empty?)
|
|
|
a3a2ad |
+ assert_equal(
|
|
|
a3a2ad |
+ obj.warning_list,
|
|
|
a3a2ad |
+ [
|
|
|
a3a2ad |
+ {
|
|
|
a3a2ad |
+ :message => (
|
|
|
a3a2ad |
+ 'This fence-device has the "action" option set, it is ' +
|
|
|
a3a2ad |
+ 'recommended to set "pcmk_off_action", "pcmk_reboot_action" instead'
|
|
|
a3a2ad |
+ )
|
|
|
a3a2ad |
+ },
|
|
|
a3a2ad |
+ {
|
|
|
a3a2ad |
+ :message => (
|
|
|
a3a2ad |
+ 'This fence-device has the "method" option set to "cycle" which ' +
|
|
|
a3a2ad |
+ 'is potentially dangerous, please consider using "onoff"'
|
|
|
a3a2ad |
+ )
|
|
|
a3a2ad |
+ }
|
|
|
a3a2ad |
+ ]
|
|
|
a3a2ad |
+ )
|
|
|
a3a2ad |
+ assert_equal('stonith:fence_xvm', obj.agentname)
|
|
|
a3a2ad |
+ assert_equal('stonith', obj._class)
|
|
|
a3a2ad |
+ assert_nil(obj.provider)
|
|
|
a3a2ad |
+ assert_equal('fence_xvm', obj.type)
|
|
|
a3a2ad |
+ assert(obj.stonith)
|
|
|
a3a2ad |
+ instance_attr = ClusterEntity::NvSet.new << ClusterEntity::NvPair.new(
|
|
|
a3a2ad |
+ 'node2-stonith-instance_attributes-domain',
|
|
|
a3a2ad |
+ 'domain',
|
|
|
a3a2ad |
+ 'node2'
|
|
|
a3a2ad |
+ )
|
|
|
a3a2ad |
+ instance_attr << ClusterEntity::NvPair.new(
|
|
|
a3a2ad |
+ 'node2-stonith-instance_attributes-action',
|
|
|
a3a2ad |
+ 'action',
|
|
|
a3a2ad |
+ 'monitor'
|
|
|
a3a2ad |
+ )
|
|
|
a3a2ad |
+ instance_attr << ClusterEntity::NvPair.new(
|
|
|
a3a2ad |
+ 'node2-stonith-instance_attributes-method',
|
|
|
a3a2ad |
+ 'method',
|
|
|
a3a2ad |
+ 'cycle'
|
|
|
a3a2ad |
+ )
|
|
|
a3a2ad |
+ assert_equal_NvSet(instance_attr, obj.instance_attr)
|
|
|
a3a2ad |
+ assert(obj.crm_status.empty?)
|
|
|
a3a2ad |
+ assert(obj.operations.empty?)
|
|
|
a3a2ad |
+ end
|
|
|
a3a2ad |
+
|
|
|
a3a2ad |
def test_init_stonith_with_crm
|
|
|
a3a2ad |
obj = ClusterEntity::Primitive.new(
|
|
|
a3a2ad |
@cib.elements["//primitive[@id='node1-stonith']"],
|
|
|
a3a2ad |
--
|
|
|
a3a2ad |
1.8.3.1
|
|
|
a3a2ad |
|