]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/insights/tests/test_health.py
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / pybind / mgr / insights / tests / test_health.py
1 import unittest
2 from tests import mock
3 from ..health import *
4
5 class HealthChecksTest(unittest.TestCase):
6 def test_check_accum_empty(self):
7 # health checks accum initially empty reports empty
8 h = HealthCheckAccumulator()
9 self.assertEqual(h.checks(), {})
10
11 h = HealthCheckAccumulator({})
12 self.assertEqual(h.checks(), {})
13
14 def _get_init_checks(self):
15 return HealthCheckAccumulator({
16 "C0": {
17 "S0": {
18 "summary": ["s0", "s1"],
19 "detail": ("d0", "d1")
20 }
21 }
22 })
23
24 def test_check_init(self):
25 # initialization with lists and tuples is OK
26 h = self._get_init_checks()
27 self.assertEqual(h.checks(), {
28 "C0": {
29 "S0": {
30 "summary": set(["s0", "s1"]),
31 "detail": set(["d0", "d1"])
32 }
33 }
34 })
35
36 def _get_merged_checks(self):
37 h = self._get_init_checks()
38 h.merge(HealthCheckAccumulator({
39 "C0": {
40 "S0": {
41 "summary": ["s0", "s1", "s2"],
42 "detail": ("d2",)
43 },
44 "S1": {
45 "summary": ["s0", "s1", "s2"],
46 "detail": ()
47 }
48 },
49 "C1": {
50 "S0": {
51 "summary": [],
52 "detail": ("d0", "d1", "d2")
53 }
54 }
55 }))
56 return h
57
58 def test_check_merge(self):
59 # merging combines and de-duplicates
60 h = self._get_merged_checks()
61 self.assertEqual(h.checks(), {
62 "C0": {
63 "S0": {
64 "summary": set(["s0", "s1", "s2"]),
65 "detail": set(["d0", "d1", "d2"])
66 },
67 "S1": {
68 "summary": set(["s0", "s1", "s2"]),
69 "detail": set([])
70 }
71 },
72 "C1": {
73 "S0": {
74 "summary": set([]),
75 "detail": set(["d0", "d1", "d2"])
76 }
77 }
78 })
79
80 def test_check_add_no_change(self):
81 # returns false when nothing changes
82 h = self._get_merged_checks()
83
84 self.assertFalse(h.add({}))
85
86 self.assertFalse(h.add({
87 "C0": {
88 "severity": "S0",
89 "summary": { "message": "s0" },
90 "detail": []
91 }
92 }))
93
94 self.assertFalse(h.add({
95 "C0": {
96 "severity": "S0",
97 "summary": { "message": "s1" },
98 "detail": [{ "message": "d1" }]
99 }
100 }))
101
102 self.assertFalse(h.add({
103 "C0": {
104 "severity": "S0",
105 "summary": { "message": "s0" },
106 "detail": [{ "message": "d1" }, { "message": "d2" }]
107 }
108 }))
109
110 def test_check_add_changed(self):
111 # new checks report change
112 h = self._get_merged_checks()
113
114 self.assertTrue(h.add({
115 "C0": {
116 "severity": "S0",
117 "summary": { "message": "s3" },
118 "detail": []
119 }
120 }))
121
122 self.assertTrue(h.add({
123 "C0": {
124 "severity": "S0",
125 "summary": { "message": "s1" },
126 "detail": [{ "message": "d4" }]
127 }
128 }))
129
130 self.assertTrue(h.add({
131 "C0": {
132 "severity": "S2",
133 "summary": { "message": "s0" },
134 "detail": [{ "message": "d0" }]
135 }
136 }))
137
138 self.assertTrue(h.add({
139 "C2": {
140 "severity": "S0",
141 "summary": { "message": "s0" },
142 "detail": [{ "message": "d0" }, { "message": "d1" }]
143 }
144 }))
145
146 self.assertEqual(h.checks(), {
147 "C0": {
148 "S0": {
149 "summary": set(["s0", "s1", "s2", "s3"]),
150 "detail": set(["d0", "d1", "d2", "d4"])
151 },
152 "S1": {
153 "summary": set(["s0", "s1", "s2"]),
154 "detail": set([])
155 },
156 "S2": {
157 "summary": set(["s0"]),
158 "detail": set(["d0"])
159 }
160 },
161 "C1": {
162 "S0": {
163 "summary": set([]),
164 "detail": set(["d0", "d1", "d2"])
165 }
166 },
167 "C2": {
168 "S0": {
169 "summary": set(["s0"]),
170 "detail": set(["d0", "d1"])
171 }
172 }
173 })
174
175 class HealthHistoryTest(unittest.TestCase):
176 def _now(self):
177 # return some time truncated at 30 minutes past the hour. this lets us
178 # fiddle with time offsets without worrying about accidentally landing
179 # on exactly the top of the hour which is the edge of a time slot for
180 # tracking health history.
181 dt = datetime.datetime.utcnow()
182 return datetime.datetime(
183 year = dt.year,
184 month = dt.month,
185 day = dt.day,
186 hour = dt.hour,
187 minute = 30)
188
189 def test_empty_slot(self):
190 now = self._now()
191
192 HealthHistorySlot._now = mock.Mock(return_value=now)
193 h = HealthHistorySlot()
194
195 # reports no historical checks
196 self.assertEqual(h.health(), { "checks": {} })
197
198 # an empty slot doesn't need to be flushed
199 self.assertFalse(h.need_flush())
200
201 def test_expires(self):
202 now = self._now()
203
204 HealthHistorySlot._now = mock.Mock(return_value=now)
205 h = HealthHistorySlot()
206 self.assertFalse(h.expired())
207
208 # an hour from now it would be expired
209 future = now + datetime.timedelta(hours = 1)
210 HealthHistorySlot._now = mock.Mock(return_value=future)
211 self.assertTrue(h.expired())
212
213 def test_need_flush(self):
214 now = self._now()
215
216 HealthHistorySlot._now = mock.Mock(return_value=now)
217 h = HealthHistorySlot()
218 self.assertFalse(h.need_flush())
219
220 self.assertTrue(h.add(dict(checks = {
221 "C0": {
222 "severity": "S0",
223 "summary": { "message": "s0" },
224 "detail": [{ "message": "d0" }]
225 }
226 })))
227 # no flush needed, yet...
228 self.assertFalse(h.need_flush())
229
230 # after persist period time elapses, a flush is needed
231 future = now + PERSIST_PERIOD
232 HealthHistorySlot._now = mock.Mock(return_value=future)
233 self.assertTrue(h.need_flush())
234
235 # mark flush resets
236 h.mark_flushed()
237 self.assertFalse(h.need_flush())
238
239 def test_need_flush_edge(self):
240 # test needs flush is true because it has expired, not because it has
241 # been dirty for the persistence period
242 dt = datetime.datetime.utcnow()
243 now = datetime.datetime(
244 year = dt.year,
245 month = dt.month,
246 day = dt.day,
247 hour = dt.hour,
248 minute = 59,
249 second = 59)
250 HealthHistorySlot._now = mock.Mock(return_value=now)
251 h = HealthHistorySlot()
252 self.assertFalse(h.expired())
253 self.assertFalse(h.need_flush())
254
255 # now it is dirty, but it doesn't need a flush
256 self.assertTrue(h.add(dict(checks = {
257 "C0": {
258 "severity": "S0",
259 "summary": { "message": "s0" },
260 "detail": [{ "message": "d0" }]
261 }
262 })))
263 self.assertFalse(h.expired())
264 self.assertFalse(h.need_flush())
265
266 # advance time past the hour so it expires, but not past the persistence
267 # period deadline for the last event that set the dirty bit
268 self.assertTrue(PERSIST_PERIOD.total_seconds() > 5)
269 future = now + datetime.timedelta(seconds = 5)
270 HealthHistorySlot._now = mock.Mock(return_value=future)
271
272 self.assertTrue(h.expired())
273 self.assertTrue(h.need_flush())