]> git.proxmox.com Git - ceph.git/blame - ceph/qa/tasks/mgr/dashboard/test_health.py
import quincy beta 17.1.0
[ceph.git] / ceph / qa / tasks / mgr / dashboard / test_health.py
CommitLineData
11fdf7f2
TL
1# -*- coding: utf-8 -*-
2from __future__ import absolute_import
3
f67539c2
TL
4from .helper import (DashboardTestCase, JAny, JLeaf, JList, JObj,
5 addrvec_schema, module_options_schema)
11fdf7f2
TL
6
7
8class HealthTest(DashboardTestCase):
9 CEPHFS = True
10
81eedcae
TL
11 __pg_info_schema = JObj({
12 'object_stats': JObj({
13 'num_objects': int,
14 'num_object_copies': int,
15 'num_objects_degraded': int,
16 'num_objects_misplaced': int,
17 'num_objects_unfound': int
18 }),
19 'pgs_per_osd': float,
20 'statuses': JObj({}, allow_unknown=True, unknown_schema=int)
21 })
22
801d1391
TL
23 __mdsmap_schema = JObj({
24 'session_autoclose': int,
25 'balancer': str,
26 'up': JObj({}, allow_unknown=True),
27 'last_failure_osd_epoch': int,
28 'in': JList(int),
29 'last_failure': int,
30 'max_file_size': int,
31 'explicitly_allowed_features': int,
32 'damaged': JList(int),
33 'tableserver': int,
34 'failed': JList(int),
35 'metadata_pool': int,
36 'epoch': int,
37 'stopped': JList(int),
38 'max_mds': int,
39 'compat': JObj({
40 'compat': JObj({}, allow_unknown=True),
41 'ro_compat': JObj({}, allow_unknown=True),
42 'incompat': JObj({}, allow_unknown=True)
43 }),
f67539c2 44 'required_client_features': JObj({}, allow_unknown=True),
801d1391
TL
45 'data_pools': JList(int),
46 'info': JObj({}, allow_unknown=True),
47 'fs_name': str,
48 'created': str,
49 'standby_count_wanted': int,
50 'enabled': bool,
51 'modified': str,
52 'session_timeout': int,
53 'flags': int,
20effc67
TL
54 'flags_state': JObj({
55 'joinable': bool,
56 'allow_snaps': bool,
57 'allow_multimds_snaps': bool,
58 'allow_standby_replay': bool
59 }),
801d1391
TL
60 'ever_allowed_features': int,
61 'root': int
62 })
63
11fdf7f2
TL
64 def test_minimal_health(self):
65 data = self._get('/api/health/minimal')
66 self.assertStatus(200)
67 schema = JObj({
68 'client_perf': JObj({
69 'read_bytes_sec': int,
70 'read_op_per_sec': int,
71 'recovering_bytes_per_sec': int,
72 'write_bytes_sec': int,
73 'write_op_per_sec': int
74 }),
75 'df': JObj({
76 'stats': JObj({
77 'total_avail_bytes': int,
78 'total_bytes': int,
11fdf7f2
TL
79 'total_used_raw_bytes': int,
80 })
81 }),
82 'fs_map': JObj({
83 'filesystems': JList(
84 JObj({
801d1391 85 'mdsmap': self.__mdsmap_schema
11fdf7f2
TL
86 }),
87 ),
801d1391 88 'standbys': JList(JObj({}, allow_unknown=True)),
11fdf7f2
TL
89 }),
90 'health': JObj({
9f95a23c
TL
91 'checks': JList(JObj({}, allow_unknown=True)),
92 'mutes': JList(JObj({}, allow_unknown=True)),
11fdf7f2
TL
93 'status': str,
94 }),
95 'hosts': int,
9f95a23c
TL
96 'iscsi_daemons': JObj({
97 'up': int,
98 'down': int
99 }),
11fdf7f2
TL
100 'mgr_map': JObj({
101 'active_name': str,
102 'standbys': JList(JLeaf(dict))
103 }),
104 'mon_status': JObj({
105 'monmap': JObj({
106 'mons': JList(JLeaf(dict)),
107 }),
108 'quorum': JList(int)
109 }),
110 'osd_map': JObj({
111 'osds': JList(
112 JObj({
113 'in': int,
114 'up': int,
20effc67 115 'state': JList(str)
11fdf7f2
TL
116 })),
117 }),
81eedcae 118 'pg_info': self.__pg_info_schema,
11fdf7f2
TL
119 'pools': JList(JLeaf(dict)),
120 'rgw': int,
121 'scrub_status': str
122 })
123 self.assertSchema(data, schema)
124
125 def test_full_health(self):
126 data = self._get('/api/health/full')
127 self.assertStatus(200)
128 module_info_schema = JObj({
129 'can_run': bool,
130 'error_string': str,
131 'name': str,
f67539c2 132 'module_options': module_options_schema
11fdf7f2
TL
133 })
134 schema = JObj({
135 'client_perf': JObj({
136 'read_bytes_sec': int,
137 'read_op_per_sec': int,
138 'recovering_bytes_per_sec': int,
139 'write_bytes_sec': int,
140 'write_op_per_sec': int
141 }),
142 'df': JObj({
143 'pools': JList(JObj({
144 'stats': JObj({
145 'stored': int,
9f95a23c
TL
146 'stored_data': int,
147 'stored_omap': int,
11fdf7f2
TL
148 'objects': int,
149 'kb_used': int,
150 'bytes_used': int,
9f95a23c
TL
151 'data_bytes_used': int,
152 'omap_bytes_used': int,
11fdf7f2
TL
153 'percent_used': float,
154 'max_avail': int,
155 'quota_objects': int,
156 'quota_bytes': int,
157 'dirty': int,
158 'rd': int,
159 'rd_bytes': int,
160 'wr': int,
161 'wr_bytes': int,
162 'compress_bytes_used': int,
163 'compress_under_bytes': int,
f6b5b4d7
TL
164 'stored_raw': int,
165 'avail_raw': int
11fdf7f2
TL
166 }),
167 'name': str,
168 'id': int
169 })),
170 'stats': JObj({
171 'total_avail_bytes': int,
172 'total_bytes': int,
11fdf7f2
TL
173 'total_used_bytes': int,
174 'total_used_raw_bytes': int,
81eedcae
TL
175 'total_used_raw_ratio': float,
176 'num_osds': int,
9f95a23c
TL
177 'num_per_pool_osds': int,
178 'num_per_pool_omap_osds': int
11fdf7f2
TL
179 })
180 }),
181 'fs_map': JObj({
182 'compat': JObj({
183 'compat': JObj({}, allow_unknown=True, unknown_schema=str),
184 'incompat': JObj(
185 {}, allow_unknown=True, unknown_schema=str),
186 'ro_compat': JObj(
187 {}, allow_unknown=True, unknown_schema=str)
188 }),
189 'default_fscid': int,
190 'epoch': int,
191 'feature_flags': JObj(
192 {}, allow_unknown=True, unknown_schema=bool),
193 'filesystems': JList(
194 JObj({
195 'id': int,
801d1391 196 'mdsmap': self.__mdsmap_schema
11fdf7f2
TL
197 }),
198 ),
199 'standbys': JList(JObj({}, allow_unknown=True)),
200 }),
201 'health': JObj({
9f95a23c
TL
202 'checks': JList(JObj({}, allow_unknown=True)),
203 'mutes': JList(JObj({}, allow_unknown=True)),
11fdf7f2
TL
204 'status': str,
205 }),
206 'hosts': int,
9f95a23c
TL
207 'iscsi_daemons': JObj({
208 'up': int,
209 'down': int
210 }),
11fdf7f2
TL
211 'mgr_map': JObj({
212 'active_addr': str,
213 'active_addrs': JObj({
f67539c2 214 'addrvec': addrvec_schema
11fdf7f2
TL
215 }),
216 'active_change': str, # timestamp
9f95a23c 217 'active_mgr_features': int,
11fdf7f2
TL
218 'active_gid': int,
219 'active_name': str,
9f95a23c 220 'always_on_modules': JObj({}, allow_unknown=True),
11fdf7f2
TL
221 'available': bool,
222 'available_modules': JList(module_info_schema),
223 'epoch': int,
224 'modules': JList(str),
225 'services': JObj(
226 {'dashboard': str}, # This module should always be present
227 allow_unknown=True, unknown_schema=str
228 ),
229 'standbys': JList(JObj({
230 'available_modules': JList(module_info_schema),
231 'gid': int,
9f95a23c
TL
232 'name': str,
233 'mgr_features': int
234 }, allow_unknown=True))
235 }, allow_unknown=True),
11fdf7f2
TL
236 'mon_status': JObj({
237 'election_epoch': int,
238 'extra_probe_peers': JList(JAny(none=True)),
239 'feature_map': JObj(
240 {}, allow_unknown=True, unknown_schema=JList(JObj({
241 'features': str,
242 'num': int,
243 'release': str
244 }))
245 ),
246 'features': JObj({
247 'quorum_con': str,
248 'quorum_mon': JList(str),
249 'required_con': str,
250 'required_mon': JList(str)
251 }),
252 'monmap': JObj({
f67539c2 253 # @TODO: expand on monmap schema
11fdf7f2
TL
254 'mons': JList(JLeaf(dict)),
255 }, allow_unknown=True),
256 'name': str,
257 'outside_quorum': JList(int),
258 'quorum': JList(int),
259 'quorum_age': int,
260 'rank': int,
261 'state': str,
f67539c2
TL
262 # @TODO: What type should be expected here?
263 'sync_provider': JList(JAny(none=True)),
264 'stretch_mode': bool
11fdf7f2
TL
265 }),
266 'osd_map': JObj({
f67539c2 267 # @TODO: define schema for crush map and osd_metadata, among
11fdf7f2
TL
268 # others
269 'osds': JList(
270 JObj({
271 'in': int,
272 'up': int,
273 }, allow_unknown=True)),
274 }, allow_unknown=True),
81eedcae 275 'pg_info': self.__pg_info_schema,
11fdf7f2
TL
276 'pools': JList(JLeaf(dict)),
277 'rgw': int,
278 'scrub_status': str
279 })
280 self.assertSchema(data, schema)
281
282 cluster_pools = self.ceph_cluster.mon_manager.list_pools()
283 self.assertEqual(len(cluster_pools), len(data['pools']))
284 for pool in data['pools']:
285 self.assertIn(pool['pool_name'], cluster_pools)
286
287 @DashboardTestCase.RunAs('test', 'test', ['pool-manager'])
288 def test_health_permissions(self):
289 data = self._get('/api/health/full')
290 self.assertStatus(200)
291
292 schema = JObj({
293 'client_perf': JObj({}, allow_unknown=True),
294 'df': JObj({}, allow_unknown=True),
295 'health': JObj({
9f95a23c
TL
296 'checks': JList(JObj({}, allow_unknown=True)),
297 'mutes': JList(JObj({}, allow_unknown=True)),
11fdf7f2
TL
298 'status': str
299 }),
300 'pools': JList(JLeaf(dict)),
301 })
302 self.assertSchema(data, schema)
303
304 cluster_pools = self.ceph_cluster.mon_manager.list_pools()
305 self.assertEqual(len(cluster_pools), len(data['pools']))
306 for pool in data['pools']:
307 self.assertIn(pool['pool_name'], cluster_pools)