]> git.proxmox.com Git - ceph.git/blame - ceph/qa/tasks/mgr/dashboard/test_cluster_configuration.py
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / qa / tasks / mgr / dashboard / test_cluster_configuration.py
CommitLineData
11fdf7f2
TL
1from __future__ import absolute_import
2
f6b5b4d7 3from .helper import DashboardTestCase
11fdf7f2
TL
4
5
6class ClusterConfigurationTest(DashboardTestCase):
7
8 def test_list(self):
9 data = self._get('/api/cluster_conf')
10 self.assertStatus(200)
11 self.assertIsInstance(data, list)
12 self.assertGreater(len(data), 1000)
13 for conf in data:
14 self._validate_single(conf)
15
16 def test_get(self):
17 data = self._get('/api/cluster_conf/admin_socket')
18 self.assertStatus(200)
19 self._validate_single(data)
20 self.assertIn('enum_values', data)
21
22 data = self._get('/api/cluster_conf/fantasy_name')
23 self.assertStatus(404)
24
25 def test_get_specific_db_config_option(self):
26 config_name = 'mon_allow_pool_delete'
27
28 orig_value = self._get_config_by_name(config_name)
29
30 self._ceph_cmd(['config', 'set', 'mon', config_name, 'true'])
f67539c2
TL
31 self.wait_until_equal(
32 lambda: self._get_config_by_name(config_name),
33 [{'section': 'mon', 'value': 'true'}],
34 timeout=30,
35 period=1)
11fdf7f2
TL
36
37 self._ceph_cmd(['config', 'set', 'mon', config_name, 'false'])
f67539c2
TL
38 self.wait_until_equal(
39 lambda: self._get_config_by_name(config_name),
40 [{'section': 'mon', 'value': 'false'}],
41 timeout=30,
42 period=1)
11fdf7f2
TL
43
44 # restore value
45 if orig_value:
46 self._ceph_cmd(['config', 'set', 'mon', config_name, orig_value[0]['value']])
47
81eedcae
TL
48 def test_filter_config_options(self):
49 config_names = ['osd_scrub_during_recovery', 'osd_scrub_begin_hour', 'osd_scrub_end_hour']
50 data = self._get('/api/cluster_conf/filter?names={}'.format(','.join(config_names)))
51 self.assertStatus(200)
52 self.assertIsInstance(data, list)
53 self.assertEqual(len(data), 3)
54 for conf in data:
55 self._validate_single(conf)
56 self.assertIn(conf['name'], config_names)
57
58 def test_filter_config_options_empty_names(self):
59 self._get('/api/cluster_conf/filter?names=')
60 self.assertStatus(404)
61 self.assertEqual(self._resp.json()['detail'], 'Config options `` not found')
62
63 def test_filter_config_options_unknown_name(self):
64 self._get('/api/cluster_conf/filter?names=abc')
65 self.assertStatus(404)
66 self.assertEqual(self._resp.json()['detail'], 'Config options `abc` not found')
67
68 def test_filter_config_options_contains_unknown_name(self):
69 config_names = ['osd_scrub_during_recovery', 'osd_scrub_begin_hour', 'abc']
70 data = self._get('/api/cluster_conf/filter?names={}'.format(','.join(config_names)))
71 self.assertStatus(200)
72 self.assertIsInstance(data, list)
73 self.assertEqual(len(data), 2)
74 for conf in data:
75 self._validate_single(conf)
76 self.assertIn(conf['name'], config_names)
77
11fdf7f2
TL
78 def test_create(self):
79 config_name = 'debug_ms'
80 orig_value = self._get_config_by_name(config_name)
81
82 # remove all existing settings for equal preconditions
83 self._clear_all_values_for_config_option(config_name)
84
85 expected_result = [{'section': 'mon', 'value': '0/3'}]
86
87 self._post('/api/cluster_conf', {
88 'name': config_name,
89 'value': expected_result
90 })
91 self.assertStatus(201)
f67539c2
TL
92 self.wait_until_equal(
93 lambda: self._get_config_by_name(config_name),
94 expected_result,
95 timeout=30,
96 period=1)
11fdf7f2
TL
97
98 # reset original value
99 self._clear_all_values_for_config_option(config_name)
100 self._reset_original_values(config_name, orig_value)
101
81eedcae
TL
102 def test_delete(self):
103 config_name = 'debug_ms'
104 orig_value = self._get_config_by_name(config_name)
105
106 # set a config option
107 expected_result = [{'section': 'mon', 'value': '0/3'}]
108 self._post('/api/cluster_conf', {
109 'name': config_name,
110 'value': expected_result
111 })
112 self.assertStatus(201)
f67539c2
TL
113 self.wait_until_equal(
114 lambda: self._get_config_by_name(config_name),
115 expected_result,
116 timeout=30,
117 period=1)
81eedcae
TL
118
119 # delete it and check if it's deleted
120 self._delete('/api/cluster_conf/{}?section={}'.format(config_name, 'mon'))
121 self.assertStatus(204)
f67539c2
TL
122 self.wait_until_equal(
123 lambda: self._get_config_by_name(config_name),
124 None,
125 timeout=30,
126 period=1)
81eedcae
TL
127
128 # reset original value
129 self._clear_all_values_for_config_option(config_name)
130 self._reset_original_values(config_name, orig_value)
131
11fdf7f2 132 def test_create_cant_update_at_runtime(self):
81eedcae 133 config_name = 'public_bind_addr' # not updatable
11fdf7f2
TL
134 config_value = [{'section': 'global', 'value': 'true'}]
135 orig_value = self._get_config_by_name(config_name)
136
137 # try to set config option and check if it fails
138 self._post('/api/cluster_conf', {
139 'name': config_name,
140 'value': config_value
141 })
142 self.assertStatus(400)
143 self.assertError(code='config_option_not_updatable_at_runtime',
144 component='cluster_configuration',
145 detail='Config option {} is/are not updatable at runtime'.format(
146 config_name))
147
148 # check if config option value is still the original one
f67539c2
TL
149 self.wait_until_equal(
150 lambda: self._get_config_by_name(config_name),
151 orig_value,
152 timeout=30,
153 period=1)
11fdf7f2
TL
154
155 def test_create_two_values(self):
156 config_name = 'debug_ms'
157 orig_value = self._get_config_by_name(config_name)
158
159 # remove all existing settings for equal preconditions
160 self._clear_all_values_for_config_option(config_name)
161
162 expected_result = [{'section': 'mon', 'value': '0/3'},
163 {'section': 'osd', 'value': '0/5'}]
164
165 self._post('/api/cluster_conf', {
166 'name': config_name,
167 'value': expected_result
168 })
169 self.assertStatus(201)
f67539c2
TL
170 self.wait_until_equal(
171 lambda: self._get_config_by_name(config_name),
172 expected_result,
173 timeout=30,
174 period=1)
11fdf7f2
TL
175
176 # reset original value
177 self._clear_all_values_for_config_option(config_name)
178 self._reset_original_values(config_name, orig_value)
179
180 def test_create_can_handle_none_values(self):
181 config_name = 'debug_ms'
182 orig_value = self._get_config_by_name(config_name)
183
184 # remove all existing settings for equal preconditions
185 self._clear_all_values_for_config_option(config_name)
186
187 self._post('/api/cluster_conf', {
188 'name': config_name,
189 'value': [{'section': 'mon', 'value': '0/3'},
190 {'section': 'osd', 'value': None}]
191 })
192 self.assertStatus(201)
193
194 expected_result = [{'section': 'mon', 'value': '0/3'}]
f67539c2
TL
195 self.wait_until_equal(
196 lambda: self._get_config_by_name(config_name),
197 expected_result,
198 timeout=30,
199 period=1)
11fdf7f2
TL
200
201 # reset original value
202 self._clear_all_values_for_config_option(config_name)
203 self._reset_original_values(config_name, orig_value)
204
205 def test_create_can_handle_boolean_values(self):
206 config_name = 'mon_allow_pool_delete'
207 orig_value = self._get_config_by_name(config_name)
208
209 # remove all existing settings for equal preconditions
210 self._clear_all_values_for_config_option(config_name)
211
212 expected_result = [{'section': 'mon', 'value': 'true'}]
213
214 self._post('/api/cluster_conf', {
215 'name': config_name,
216 'value': [{'section': 'mon', 'value': True}]})
217 self.assertStatus(201)
218
f67539c2
TL
219 self.wait_until_equal(
220 lambda: self._get_config_by_name(config_name),
221 expected_result,
222 timeout=30,
223 period=1)
11fdf7f2
TL
224
225 # reset original value
226 self._clear_all_values_for_config_option(config_name)
227 self._reset_original_values(config_name, orig_value)
228
229 def test_bulk_set(self):
230 expected_result = {
231 'osd_max_backfills': {'section': 'osd', 'value': '1'},
232 'osd_recovery_max_active': {'section': 'osd', 'value': '3'},
233 'osd_recovery_max_single_start': {'section': 'osd', 'value': '1'},
234 'osd_recovery_sleep': {'section': 'osd', 'value': '2.000000'}
235 }
236 orig_values = dict()
237
238 for config_name in expected_result:
239 orig_values[config_name] = self._get_config_by_name(config_name)
240
241 # remove all existing settings for equal preconditions
242 self._clear_all_values_for_config_option(config_name)
243
244 self._put('/api/cluster_conf', {'options': expected_result})
245 self.assertStatus(200)
246
247 for config_name, value in expected_result.items():
f67539c2
TL
248 self.wait_until_equal(
249 lambda: self._get_config_by_name(config_name),
250 [value],
251 timeout=30,
252 period=1)
11fdf7f2
TL
253
254 # reset original value
255 self._clear_all_values_for_config_option(config_name)
256 self._reset_original_values(config_name, orig_values[config_name])
257
258 def test_bulk_set_cant_update_at_runtime(self):
259 config_options = {
81eedcae
TL
260 'public_bind_addr': {'section': 'global', 'value': '1.2.3.4:567'}, # not updatable
261 'public_network': {'section': 'global', 'value': '10.0.0.0/8'} # not updatable
11fdf7f2
TL
262 }
263 orig_values = dict()
264
265 for config_name in config_options:
266 orig_values[config_name] = self._get_config_by_name(config_name)
267
268 # try to set config options and see if it fails
269 self._put('/api/cluster_conf', {'options': config_options})
270 self.assertStatus(400)
271 self.assertError(code='config_option_not_updatable_at_runtime',
272 component='cluster_configuration',
273 detail='Config option {} is/are not updatable at runtime'.format(
274 ', '.join(config_options.keys())))
275
276 # check if config option values are still the original ones
277 for config_name, value in orig_values.items():
f67539c2
TL
278 self.wait_until_equal(
279 lambda: self._get_config_by_name(config_name),
280 value,
281 timeout=30,
282 period=1)
11fdf7f2
TL
283
284 def test_bulk_set_cant_update_at_runtime_partial(self):
285 config_options = {
81eedcae 286 'public_bind_addr': {'section': 'global', 'value': 'true'}, # not updatable
11fdf7f2
TL
287 'log_to_stderr': {'section': 'global', 'value': 'true'} # updatable
288 }
289 orig_values = dict()
290
291 for config_name in config_options:
292 orig_values[config_name] = self._get_config_by_name(config_name)
293
294 # try to set config options and see if it fails
295 self._put('/api/cluster_conf', {'options': config_options})
296 self.assertStatus(400)
297 self.assertError(code='config_option_not_updatable_at_runtime',
298 component='cluster_configuration',
299 detail='Config option {} is/are not updatable at runtime'.format(
81eedcae 300 'public_bind_addr'))
11fdf7f2
TL
301
302 # check if config option values are still the original ones
303 for config_name, value in orig_values.items():
f67539c2
TL
304 self.wait_until_equal(
305 lambda: self._get_config_by_name(config_name),
306 value,
307 timeout=30,
308 period=1)
11fdf7f2 309
81eedcae
TL
310 def test_check_existence(self):
311 """
312 This test case is intended to check the existence of all hard coded config options used by
313 the dashboard.
81eedcae
TL
314 If you include further hard coded options in the dashboard, feel free to add them to the
315 list.
316 """
317 hard_coded_options = [
318 'osd_max_backfills', # osd-recv-speed
319 'osd_recovery_max_active', # osd-recv-speed
320 'osd_recovery_max_single_start', # osd-recv-speed
321 'osd_recovery_sleep', # osd-recv-speed
322 'osd_scrub_during_recovery', # osd-pg-scrub
323 'osd_scrub_begin_hour', # osd-pg-scrub
324 'osd_scrub_end_hour', # osd-pg-scrub
325 'osd_scrub_begin_week_day', # osd-pg-scrub
326 'osd_scrub_end_week_day', # osd-pg-scrub
327 'osd_scrub_min_interval', # osd-pg-scrub
328 'osd_scrub_max_interval', # osd-pg-scrub
329 'osd_deep_scrub_interval', # osd-pg-scrub
330 'osd_scrub_auto_repair', # osd-pg-scrub
331 'osd_max_scrubs', # osd-pg-scrub
332 'osd_scrub_priority', # osd-pg-scrub
333 'osd_scrub_sleep', # osd-pg-scrub
334 'osd_scrub_auto_repair_num_errors', # osd-pg-scrub
335 'osd_debug_deep_scrub_sleep', # osd-pg-scrub
336 'osd_deep_scrub_keys', # osd-pg-scrub
337 'osd_deep_scrub_large_omap_object_key_threshold', # osd-pg-scrub
338 'osd_deep_scrub_large_omap_object_value_sum_threshold', # osd-pg-scrub
339 'osd_deep_scrub_randomize_ratio', # osd-pg-scrub
340 'osd_deep_scrub_stride', # osd-pg-scrub
341 'osd_deep_scrub_update_digest_min_age', # osd-pg-scrub
81eedcae
TL
342 'osd_requested_scrub_priority', # osd-pg-scrub
343 'osd_scrub_backoff_ratio', # osd-pg-scrub
344 'osd_scrub_chunk_max', # osd-pg-scrub
345 'osd_scrub_chunk_min', # osd-pg-scrub
346 'osd_scrub_cost', # osd-pg-scrub
347 'osd_scrub_interval_randomize_ratio', # osd-pg-scrub
348 'osd_scrub_invalid_stats', # osd-pg-scrub
349 'osd_scrub_load_threshold', # osd-pg-scrub
494da23a
TL
350 'osd_scrub_max_preemptions', # osd-pg-scrub
351 'mon_allow_pool_delete' # pool-list
81eedcae
TL
352 ]
353
354 for config_option in hard_coded_options:
355 self._get('/api/cluster_conf/{}'.format(config_option))
356 self.assertStatus(200)
357
11fdf7f2
TL
358 def _validate_single(self, data):
359 self.assertIn('name', data)
360 self.assertIn('daemon_default', data)
361 self.assertIn('long_desc', data)
362 self.assertIn('level', data)
363 self.assertIn('default', data)
364 self.assertIn('see_also', data)
365 self.assertIn('tags', data)
366 self.assertIn('min', data)
367 self.assertIn('max', data)
368 self.assertIn('services', data)
369 self.assertIn('type', data)
370 self.assertIn('desc', data)
f67539c2
TL
371 self.assertIn(data['type'], ['str', 'bool', 'float', 'int', 'size', 'uint', 'addr',
372 'addrvec', 'uuid', 'secs', 'millisecs'])
11fdf7f2
TL
373
374 if 'value' in data:
375 self.assertIn('source', data)
376 self.assertIsInstance(data['value'], list)
377
378 for entry in data['value']:
379 self.assertIsInstance(entry, dict)
380 self.assertIn('section', entry)
381 self.assertIn('value', entry)
382
11fdf7f2
TL
383 def _get_config_by_name(self, conf_name):
384 data = self._get('/api/cluster_conf/{}'.format(conf_name))
385 if 'value' in data:
386 return data['value']
387 return None
388
389 def _clear_all_values_for_config_option(self, config_name):
390 values = self._get_config_by_name(config_name)
391 if values:
392 for value in values:
393 self._ceph_cmd(['config', 'rm', value['section'], config_name])
394
395 def _reset_original_values(self, config_name, orig_values):
396 if orig_values:
397 for value in orig_values:
398 self._ceph_cmd(['config', 'set', value['section'], config_name, value['value']])