Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions crmsh/migration.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ def check_unsupported_resource_agents(handler: CheckResultHandler):
('* ' + ':'.join(x for x in resource_agent if x is not None) for resource_agent in class_unsupported_resource_agents)
)
_check_ocfs2(handler, cib)
_check_obseleted_sap_ascs_ers_mount(handler, cib)


def _check_saphana_resource_agent(handler: CheckResultHandler, resource_agents: typing.Iterable[cibquery.ResourceAgent]):
Expand Down Expand Up @@ -430,3 +431,55 @@ def _check_ocfs2(handler: CheckResultHandler, cib: lxml.etree.Element):
if cibquery.has_primitive_filesystem_with_fstype(cib, 'ocfs2'):
handler.handle_problem(False, 'OCFS2 is not supported in SLES 16. Please use GFS2.', [
])


def _check_obseleted_sap_ascs_ers_mount(handler: CheckResultHandler, cib: lxml.etree.Element):
"""
Checks for Filesystem resources that are part of a resource group with an
SAPInstance resource where IS_ERS=true, and the Filesystem resource starts
before the SAPInstance resource. This setup is not supported for ENSA2.
"""
# 1. Find all SAPInstance primitives with IS_ERS=true
ers_primitives = cib.xpath(
'/cib/configuration/resources//primitive[@class="ocf" and @provider="suse" and @type="SAPInstance"]'
'[instance_attributes/nvpair[@name="IS_ERS" and @value="true"]]'
)
if not ers_primitives:
return

# 2. Find all Filesystem primitive IDs
fs_ids = {
p.get('id') for p in cib.xpath('/cib/configuration/resources//primitive[@class="ocf" and @provider="heartbeat" and @type="Filesystem"]')
}
if not fs_ids:
return

# 3. Find all groups in the CIB
groups = cib.xpath('/cib/configuration/resources//group')
for group in groups:
group_id = group.get('id')
# Primitives returned by xpath are in document order
group_primitives_ids = [p.get('id') for p in group.xpath('.//primitive')]
group_primitive_id_set = set(group_primitives_ids)

# Check if the group contains both an ERS instance and a Filesystem resource
ers_in_group = [p for p in ers_primitives if p.get('id') in group_primitive_id_set]
if not ers_in_group:
continue
fs_in_group = [fs_id for fs_id in fs_ids if fs_id in group_primitive_id_set]
if not ers_in_group or not fs_in_group:
continue

# 4. Check ordering constraints for each pair
for ers_primitive in ers_in_group:
ers_id = ers_primitive.get('id')
for fs_id in fs_in_group:
ers_index = group_primitives_ids.index(ers_id)
fs_index = group_primitives_ids.index(fs_id)
if fs_index < ers_index:
# Implicit order is fs -> ers
handler.handle_problem(
False,
"Cluster-controlled filesystem setup for SAP ENSA2 is not supported in SLES 16. Please migrate to simple-mount setup.",
[f'* Filesystem resource "{fs_id}" is ordered to start before SAPInstance ERS resource "{ers_id}" in group "{group_id}".']
)
63 changes: 63 additions & 0 deletions test/unittests/test_migration.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import unittest
from unittest import mock

import lxml.etree

from crmsh import migration, cibquery


Expand Down Expand Up @@ -66,3 +68,64 @@ def check_fn(x):
self._handler.handle_problem.reset_mock()
check_fn('foo 1.0.0')
self._handler.handle_problem.assert_called()


class TestCheckObsoletedSapAscsErsMount(unittest.TestCase):
XML_DATA = '''<?xml version="1.0" ?>
<cib crm_feature_set="3.16.1" validate-with="pacemaker-3.9" epoch="9" num_updates="0" admin_epoch="0" cib-last-written="Fri Sep 26 15:02:50 2025" update-origin="ha-1-1" update-client="cibadmin" update-user="root" have-quorum="1" dc-uuid="1">
<configuration>
<crm_config>
<cluster_property_set id="cib-bootstrap-options">
<nvpair id="cib-bootstrap-options-have-watchdog" name="have-watchdog" value="false"/>
<nvpair id="cib-bootstrap-options-dc-version" name="dc-version" value="2.1.5+20221208.a3f44794f-150500.4.9-2.1.5+20221208.a3f44794f"/>
<nvpair id="cib-bootstrap-options-cluster-infrastructure" name="cluster-infrastructure" value="corosync"/>
<nvpair id="cib-bootstrap-options-cluster-name" name="cluster-name" value="hacluster"/>
<nvpair name="stonith-enabled" value="false" id="cib-bootstrap-options-stonith-enabled"/>
</cluster_property_set>
</crm_config>
<nodes>
<node id="1" uname="ha-1-1"/>
</nodes>
<resources>
<group id="ers_group">
<primitive id="fs_ers" class="ocf" provider="heartbeat" type="Filesystem">
<instance_attributes id="fs_ers-instance_attributes">
<nvpair name="device" value="tmpfs" id="fs_ers-instance_attributes-device"/>
<nvpair name="directory" value="/mnt/dummy" id="fs_ers-instance_attributes-directory"/>
<nvpair name="fstype" value="tmpfs" id="fs_ers-instance_attributes-fstype"/>
</instance_attributes>
</primitive>
<primitive id="ers_instance" class="ocf" provider="suse" type="SAPInstance">
<instance_attributes id="ers_instance-instance_attributes">
<nvpair name="IS_ERS" value="true" id="ers_instance-instance_attributes-IS_ERS"/>
</instance_attributes>
</primitive>
</group>
</resources>
<rsc_defaults>
<meta_attributes id="build-resource-defaults">
<nvpair id="build-resource-stickiness" name="resource-stickiness" value="1"/>
<nvpair name="migration-threshold" value="3" id="rsc-options-migration-threshold"/>
</meta_attributes>
</rsc_defaults>
<op_defaults>
<meta_attributes id="op-options">
<nvpair name="timeout" value="600" id="op-options-timeout"/>
<nvpair name="record-pending" value="true" id="op-options-record-pending"/>
</meta_attributes>
</op_defaults>
</configuration>
</cib>
'''

def setUp(self):
self.handler = mock.Mock(migration.CheckResultHandler)
self.cib = lxml.etree.fromstring(self.XML_DATA)

def test_check_obseleted_sap_ascs_ers_mount(self):
migration._check_obseleted_sap_ascs_ers_mount(self.handler, self.cib)
self.handler.handle_problem.assert_called_once_with(
False,
"Cluster-controlled filesystem setup for SAP ENSA2 is not supported in SLES 16. Please migrate to simple-mount setup.",
['* Filesystem resource "fs_ers" is ordered to start before SAPInstance ERS resource "ers_instance" in group "ers_group".']
)