summaryrefslogtreecommitdiffstats
path: root/test/unittests/test_ratrace.py
diff options
context:
space:
mode:
Diffstat (limited to 'test/unittests/test_ratrace.py')
-rw-r--r--test/unittests/test_ratrace.py131
1 files changed, 131 insertions, 0 deletions
diff --git a/test/unittests/test_ratrace.py b/test/unittests/test_ratrace.py
new file mode 100644
index 0000000..6734b89
--- /dev/null
+++ b/test/unittests/test_ratrace.py
@@ -0,0 +1,131 @@
+import unittest
+from lxml import etree
+try:
+ from unittest import mock
+except ImportError:
+ import mock
+from crmsh import cibconfig
+from crmsh.ui_context import Context
+from crmsh.ui_resource import RscMgmt
+from crmsh.ui_root import Root
+
+
+class TestRATrace(unittest.TestCase):
+ """Unit tests for enabling/disabling RA tracing."""
+
+ context = Context(Root())
+ factory = cibconfig.cib_factory
+
+ def setUp(self):
+ self.factory._push_state()
+
+ def tearDown(self):
+ self.factory._pop_state()
+
+ @mock.patch('logging.Logger.error')
+ def test_ratrace_resource(self, mock_error):
+ """Check setting RA tracing for a resource."""
+ xml = '''<primitive class="ocf" id="r1" provider="pacemaker" type="Dummy"/>'''
+ obj = self.factory.create_from_node(etree.fromstring(xml))
+
+ # Trace the resource.
+ RscMgmt()._trace_resource(self.context, obj.obj_id, obj, '/var/lib/heartbeat/trace_ra')
+ self.assertEqual(obj.node.xpath('operations/op/@id'), ['r1-start-0', 'r1-stop-0'])
+ self.assertEqual(obj.node.xpath('operations/op[@id="r1-start-0"]/instance_attributes/nvpair[@name="trace_ra"]/@value'), ['1'])
+ self.assertEqual(obj.node.xpath('operations/op[@id="r1-stop-0"]/instance_attributes/nvpair[@name="trace_ra"]/@value'), ['1'])
+
+ # Untrace the resource.
+ RscMgmt()._untrace_resource(self.context, obj.obj_id, obj)
+ self.assertEqual(obj.node.xpath('operations/op/@id'), [])
+ self.assertEqual(obj.node.xpath('.//*[@name="trace_ra"]'), [])
+
+ @mock.patch('logging.Logger.error')
+ def test_ratrace_op(self, mock_error):
+ """Check setting RA tracing for a specific operation."""
+ xml = '''<primitive class="ocf" id="r1" provider="pacemaker" type="Dummy">
+ <operations>
+ <op id="r1-monitor-10" interval="10" name="monitor"/>
+ </operations>
+ </primitive>'''
+ obj = self.factory.create_from_node(etree.fromstring(xml))
+
+ # Trace the operation.
+ RscMgmt()._trace_op(self.context, obj.obj_id, obj, 'monitor', '/var/lib/heartbeat/trace_ra')
+ self.assertEqual(obj.node.xpath('operations/op/@id'), ['r1-monitor-10'])
+ self.assertEqual(obj.node.xpath('operations/op[@id="r1-monitor-10"]/instance_attributes/nvpair[@name="trace_ra"]/@value'), ['1'])
+
+ # Untrace the operation.
+ RscMgmt()._untrace_op(self.context, obj.obj_id, obj, 'monitor')
+ self.assertEqual(obj.node.xpath('operations/op/@id'), ['r1-monitor-10'])
+ self.assertEqual(obj.node.xpath('.//*[@name="trace_ra"]'), [])
+
+ # Try untracing a non-existent operation.
+ with self.assertRaises(ValueError) as err:
+ RscMgmt()._untrace_op(self.context, obj.obj_id, obj, 'invalid-op')
+ self.assertEqual(str(err.exception), "Operation invalid-op not found in r1")
+
+ @mock.patch('logging.Logger.error')
+ def test_ratrace_new(self, mock_error):
+ """Check setting RA tracing for an operation that is not in CIB."""
+ xml = '''<primitive class="ocf" id="r1" provider="pacemaker" type="Dummy">
+ </primitive>'''
+ obj = self.factory.create_from_node(etree.fromstring(xml))
+
+ # Trace a regular operation that is not yet defined in CIB. The request
+ # should succeed and introduce an op node for the operation.
+ RscMgmt()._trace_op(self.context, obj.obj_id, obj, 'start', '/var/lib/heartbeat/trace_ra')
+ self.assertEqual(obj.node.xpath('operations/op/@id'), ['r1-start-0'])
+ self.assertEqual(obj.node.xpath('operations/op[@id="r1-start-0"]/instance_attributes/nvpair[@name="trace_ra"]/@value'), ['1'])
+
+ # Try tracing the monitor operation in the same way. The request should
+ # get rejected because no explicit interval is specified.
+ with self.assertRaises(ValueError) as err:
+ RscMgmt()._trace_op(self.context, obj.obj_id, obj, 'monitor', '/var/lib/heartbeat/trace_ra')
+ self.assertEqual(str(err.exception), "No monitor operation configured for r1")
+
+ @mock.patch('logging.Logger.error')
+ def test_ratrace_op_stateful(self, mock_error):
+ """Check setting RA tracing for an operation on a stateful resource."""
+ xml = '''<primitive class="ocf" id="r1" provider="pacemaker" type="Dummy">
+ <operations>
+ <op id="r1-monitor-10" interval="10" name="monitor" role="Master"/>
+ <op id="r1-monitor-11" interval="11" name="monitor" role="Slave"/>
+ </operations>
+ </primitive>'''
+ obj = self.factory.create_from_node(etree.fromstring(xml))
+
+ # Trace the operation.
+ RscMgmt()._trace_op(self.context, obj.obj_id, obj, 'monitor', '/var/lib/heartbeat/trace_ra')
+ self.assertEqual(obj.node.xpath('operations/op/@id'), ['r1-monitor-10', 'r1-monitor-11'])
+ self.assertEqual(obj.node.xpath('operations/op[@id="r1-monitor-10"]/instance_attributes/nvpair[@name="trace_ra"]/@value'), ['1'])
+ self.assertEqual(obj.node.xpath('operations/op[@id="r1-monitor-11"]/instance_attributes/nvpair[@name="trace_ra"]/@value'), ['1'])
+
+ # Untrace the operation.
+ RscMgmt()._untrace_op(self.context, obj.obj_id, obj, 'monitor')
+ self.assertEqual(obj.node.xpath('operations/op/@id'), ['r1-monitor-10', 'r1-monitor-11'])
+ self.assertEqual(obj.node.xpath('.//*[@name="trace_ra"]'), [])
+
+ @mock.patch('logging.Logger.error')
+ def test_ratrace_op_interval(self, mock_error):
+ """Check setting RA tracing for an operation+interval."""
+ xml = '''<primitive class="ocf" id="r1" provider="pacemaker" type="Dummy">
+ <operations>
+ <op id="r1-monitor-10" interval="10" name="monitor"/>
+ </operations>
+ </primitive>'''
+ obj = self.factory.create_from_node(etree.fromstring(xml))
+
+ # Trace the operation.
+ RscMgmt()._trace_op_interval(self.context, obj.obj_id, obj, 'monitor', '10', '/var/lib/heartbeat/trace_ra')
+ self.assertEqual(obj.node.xpath('operations/op/@id'), ['r1-monitor-10'])
+ self.assertEqual(obj.node.xpath('operations/op[@id="r1-monitor-10"]/instance_attributes/nvpair[@name="trace_ra"]/@value'), ['1'])
+
+ # Untrace the operation.
+ RscMgmt()._untrace_op_interval(self.context, obj.obj_id, obj, 'monitor', '10')
+ self.assertEqual(obj.node.xpath('operations/op/@id'), ['r1-monitor-10'])
+ self.assertEqual(obj.node.xpath('.//*[@name="trace_ra"]'), [])
+
+ # Try untracing a non-existent operation.
+ with self.assertRaises(ValueError) as err:
+ RscMgmt()._untrace_op_interval(self.context, obj.obj_id, obj, 'invalid-op', '10')
+ self.assertEqual(str(err.exception), "Operation invalid-op with interval 10 not found in r1")