summaryrefslogtreecommitdiffstats
path: root/test/unittests/test_ratrace.py
blob: 6734b89ef3c0e903551b71b213b8ba6318862c9f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
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")