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