]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/pybind/test_ceph_argparse.py
import ceph pacific 16.2.5
[ceph.git] / ceph / src / test / pybind / test_ceph_argparse.py
CommitLineData
9f95a23c 1#!/usr/bin/env python3
b3b6e05e 2# -*- mode:python; tab-width:4; indent-tabs-mode:nil; coding:utf-8 -*-
7c673cae
FG
3# vim: ts=4 sw=4 smarttab expandtab fileencoding=utf-8
4#
5# Ceph - scalable distributed file system
6#
7# Copyright (C) 2013,2014 Cloudwatt <libre.licensing@cloudwatt.com>
8# Copyright (C) 2014 Red Hat <contact@redhat.com>
9#
10# Author: Loic Dachary <loic@dachary.org>
11#
12# This library is free software; you can redistribute it and/or
13# modify it under the terms of the GNU Lesser General Public
14# License as published by the Free Software Foundation; either
15# version 2.1 of the License, or (at your option) any later version.
16#
17
b3b6e05e
TL
18from nose.tools import assert_equal, assert_raises, \
19 assert_not_in, assert_in, \
20 assert_regexp_matches, \
21 nottest
9f95a23c 22from unittest import TestCase
7c673cae 23
9f95a23c
TL
24from ceph_argparse import validate_command, parse_json_funcsigs, validate, \
25 parse_funcsig, ArgumentError, ArgumentTooFew, ArgumentMissing, \
26 ArgumentNumber, ArgumentValid
7c673cae
FG
27
28import os
9f95a23c 29import random
7c673cae 30import re
9f95a23c 31import string
94b18763 32import sys
1adf2230
AA
33try:
34 from StringIO import StringIO
35except ImportError:
36 from io import StringIO
7c673cae 37
b3b6e05e 38
7c673cae
FG
39def get_command_descriptions(what):
40 CEPH_BIN = os.environ['CEPH_BIN']
41 if CEPH_BIN == "":
42 CEPH_BIN = "."
43 return os.popen(CEPH_BIN + "/get_command_descriptions " + "--" + what).read()
44
b3b6e05e 45
7c673cae
FG
46def test_parse_json_funcsigs():
47 commands = get_command_descriptions("all")
48 cmd_json = parse_json_funcsigs(commands, 'cli')
49
50 # syntax error https://github.com/ceph/ceph/pull/585
51 commands = get_command_descriptions("pull585")
52 assert_raises(TypeError, parse_json_funcsigs, commands, 'cli')
53
b3b6e05e 54
7c673cae
FG
55sigdict = parse_json_funcsigs(get_command_descriptions("all"), 'cli')
56
57
58class TestArgparse:
59
60 def assert_valid_command(self, args):
61 result = validate_command(sigdict, args)
94b18763 62 assert_not_in(result, [{}, None])
7c673cae
FG
63
64 def check_1_natural_arg(self, prefix, command):
65 self.assert_valid_command([prefix, command, '1'])
66 assert_equal({}, validate_command(sigdict, [prefix, command]))
67 assert_equal({}, validate_command(sigdict, [prefix, command, '-1']))
68 assert_equal({}, validate_command(sigdict, [prefix, command, '1',
69 '1']))
70
71 def check_0_or_1_natural_arg(self, prefix, command):
72 self.assert_valid_command([prefix, command, '1'])
73 self.assert_valid_command([prefix, command])
74 assert_equal({}, validate_command(sigdict, [prefix, command, '-1']))
75 assert_equal({}, validate_command(sigdict, [prefix, command, '1',
76 '1']))
77
78 def check_1_string_arg(self, prefix, command):
79 assert_equal({}, validate_command(sigdict, [prefix, command]))
80 self.assert_valid_command([prefix, command, 'string'])
81 assert_equal({}, validate_command(sigdict, [prefix,
82 command,
83 'string',
84 'toomany']))
85
11fdf7f2
TL
86 def check_0_or_1_string_arg(self, prefix, command):
87 self.assert_valid_command([prefix, command, 'string'])
88 self.assert_valid_command([prefix, command])
89 assert_equal({}, validate_command(sigdict, [prefix, command, 'string',
90 'toomany']))
91
7c673cae
FG
92 def check_1_or_more_string_args(self, prefix, command):
93 assert_equal({}, validate_command(sigdict, [prefix,
94 command]))
95 self.assert_valid_command([prefix,
96 command,
97 'string'])
98 self.assert_valid_command([prefix,
99 command,
100 'string',
101 'more string'])
102
103 def check_no_arg(self, prefix, command):
104 self.assert_valid_command([prefix,
105 command])
106 assert_equal({}, validate_command(sigdict, [prefix,
107 command,
108 'toomany']))
109
11fdf7f2 110 def capture_output(self, args, stdout=None, stderr=None):
94b18763
FG
111 if stdout:
112 stdout = StringIO()
113 sys.stdout = stdout
114 if stderr:
115 stderr = StringIO()
116 sys.stderr = stderr
117 ret = validate_command(sigdict, args)
118 if stdout:
119 stdout = stdout.getvalue().strip()
120 if stderr:
121 stderr = stderr.getvalue().strip()
122 return ret, stdout, stderr
123
7c673cae
FG
124
125class TestBasic:
126
127 def test_non_ascii_in_non_options(self):
128 # ArgumentPrefix("no match for {0}".format(s)) is not able to convert
129 # unicode str parameter into str. and validate_command() should not
130 # choke on it.
94b18763
FG
131 assert_equal({}, validate_command(sigdict, [u'章鱼和鱿鱼']))
132 assert_equal({}, validate_command(sigdict, [u'–w']))
7c673cae
FG
133 # actually we always pass unicode strings to validate_command() in "ceph"
134 # CLI, but we also use bytestrings in our tests, so make sure it does not
135 # break.
94b18763
FG
136 assert_equal({}, validate_command(sigdict, ['章鱼和鱿鱼']))
137 assert_equal({}, validate_command(sigdict, ['–w']))
7c673cae
FG
138
139
140class TestPG(TestArgparse):
141
142 def test_stat(self):
143 self.assert_valid_command(['pg', 'stat'])
144
145 def test_getmap(self):
146 self.assert_valid_command(['pg', 'getmap'])
147
148 def test_dump(self):
b3b6e05e
TL
149 valid_commands = {
150 'pg dump': {'prefix': 'pg dump'},
151 'pg dump all summary sum delta pools osds pgs pgs_brief':
152 {'prefix': 'pg dump',
153 'dumpcontents':
154 'all summary sum delta pools osds pgs pgs_brief'.split()
155 },
156 'pg dump --dumpcontents summary,sum':
157 {'prefix': 'pg dump',
158 'dumpcontents': 'summary,sum'.split(',')
159 }
160 }
161 for command, expected_result in valid_commands.items():
162 actual_result = validate_command(sigdict, command.split())
163 expected_result['target'] = ('mon-mgr', '')
164 assert_equal(expected_result, actual_result)
165 invalid_commands = ['pg dump invalid']
166 for command in invalid_commands:
167 actual_result = validate_command(sigdict, command.split())
168 assert_equal({}, actual_result)
7c673cae
FG
169
170 def test_dump_json(self):
171 self.assert_valid_command(['pg', 'dump_json'])
172 self.assert_valid_command(['pg', 'dump_json',
173 'all',
174 'summary',
175 'sum',
176 'pools',
177 'osds',
178 'pgs'])
179 assert_equal({}, validate_command(sigdict, ['pg', 'dump_json',
180 'invalid']))
181
182 def test_dump_pools_json(self):
183 self.assert_valid_command(['pg', 'dump_pools_json'])
184
185 def test_dump_pools_stuck(self):
186 self.assert_valid_command(['pg', 'dump_stuck'])
187 self.assert_valid_command(['pg', 'dump_stuck',
188 'inactive',
189 'unclean',
190 'stale'])
191 assert_equal({}, validate_command(sigdict, ['pg', 'dump_stuck',
192 'invalid']))
193 self.assert_valid_command(['pg', 'dump_stuck',
194 'inactive',
195 '1234'])
196
197 def one_pgid(self, command):
198 self.assert_valid_command(['pg', command, '1.1'])
199 assert_equal({}, validate_command(sigdict, ['pg', command]))
200 assert_equal({}, validate_command(sigdict, ['pg', command, '1']))
201
202 def test_map(self):
203 self.one_pgid('map')
204
205 def test_scrub(self):
206 self.one_pgid('scrub')
207
208 def test_deep_scrub(self):
209 self.one_pgid('deep-scrub')
210
211 def test_repair(self):
212 self.one_pgid('repair')
213
214 def test_debug(self):
215 self.assert_valid_command(['pg',
216 'debug',
217 'unfound_objects_exist'])
218 self.assert_valid_command(['pg',
219 'debug',
220 'degraded_pgs_exist'])
221 assert_equal({}, validate_command(sigdict, ['pg', 'debug']))
222 assert_equal({}, validate_command(sigdict, ['pg', 'debug',
223 'invalid']))
224
94b18763
FG
225 def test_pg_missing_args_output(self):
226 ret, _, stderr = self.capture_output(['pg'], stderr=True)
227 assert_equal({}, ret)
228 assert_regexp_matches(stderr, re.compile('no valid command found.* closest matches'))
229
230 def test_pg_wrong_arg_output(self):
231 ret, _, stderr = self.capture_output(['pg', 'map', 'bad-pgid'],
232 stderr=True)
233 assert_equal({}, ret)
234 assert_in("Invalid command", stderr)
235
7c673cae
FG
236
237class TestAuth(TestArgparse):
238
239 def test_export(self):
240 self.assert_valid_command(['auth', 'export'])
241 self.assert_valid_command(['auth',
242 'export',
243 'string'])
244 assert_equal({}, validate_command(sigdict, ['auth',
245 'export',
246 'string',
247 'toomany']))
248
249 def test_get(self):
250 self.check_1_string_arg('auth', 'get')
251
252 def test_get_key(self):
253 self.check_1_string_arg('auth', 'get-key')
254
255 def test_print_key(self):
256 self.check_1_string_arg('auth', 'print-key')
257 self.check_1_string_arg('auth', 'print_key')
258
259 def test_list(self):
260 self.check_no_arg('auth', 'list')
261
262 def test_import(self):
263 self.check_no_arg('auth', 'import')
264
265 def test_add(self):
266 self.check_1_or_more_string_args('auth', 'add')
267
268 def test_get_or_create_key(self):
269 self.check_1_or_more_string_args('auth', 'get-or-create-key')
b3b6e05e
TL
270 prefix = 'auth get-or-create-key'
271 entity = 'client.test'
272 caps = ['mon',
273 'allow r',
274 'osd',
275 'allow rw pool=nfs-ganesha namespace=test, allow rw tag cephfs data=user_test_fs',
276 'mds',
277 'allow rw path=/']
278 cmd = prefix.split() + [entity] + caps
279 assert_equal(
280 {
281 'prefix': prefix,
282 'entity': entity,
283 'caps': caps
284 }, validate_command(sigdict, cmd))
7c673cae
FG
285
286 def test_get_or_create(self):
287 self.check_1_or_more_string_args('auth', 'get-or-create')
288
289 def test_caps(self):
290 assert_equal({}, validate_command(sigdict, ['auth',
291 'caps']))
292 assert_equal({}, validate_command(sigdict, ['auth',
293 'caps',
294 'string']))
295 self.assert_valid_command(['auth',
296 'caps',
297 'string',
298 'more string'])
299
300 def test_del(self):
301 self.check_1_string_arg('auth', 'del')
302
303
304class TestMonitor(TestArgparse):
305
306 def test_compact(self):
307 self.assert_valid_command(['compact'])
308
7c673cae
FG
309 def test_fsid(self):
310 self.assert_valid_command(['fsid'])
311
312 def test_log(self):
313 assert_equal({}, validate_command(sigdict, ['log']))
314 self.assert_valid_command(['log', 'a logtext'])
315 self.assert_valid_command(['log', 'a logtext', 'and another'])
316
317 def test_injectargs(self):
318 assert_equal({}, validate_command(sigdict, ['injectargs']))
319 self.assert_valid_command(['injectargs', 'one'])
320 self.assert_valid_command(['injectargs', 'one', 'two'])
321
322 def test_status(self):
323 self.assert_valid_command(['status'])
324
325 def test_health(self):
326 self.assert_valid_command(['health'])
327 self.assert_valid_command(['health', 'detail'])
328 assert_equal({}, validate_command(sigdict, ['health', 'invalid']))
329 assert_equal({}, validate_command(sigdict, ['health', 'detail',
330 'toomany']))
331
332 def test_df(self):
333 self.assert_valid_command(['df'])
334 self.assert_valid_command(['df', 'detail'])
335 assert_equal({}, validate_command(sigdict, ['df', 'invalid']))
336 assert_equal({}, validate_command(sigdict, ['df', 'detail',
337 'toomany']))
338
339 def test_report(self):
340 self.assert_valid_command(['report'])
341 self.assert_valid_command(['report', 'tag1'])
342 self.assert_valid_command(['report', 'tag1', 'tag2'])
343
344 def test_quorum_status(self):
345 self.assert_valid_command(['quorum_status'])
346
7c673cae
FG
347 def test_tell(self):
348 assert_equal({}, validate_command(sigdict, ['tell']))
349 assert_equal({}, validate_command(sigdict, ['tell', 'invalid']))
350 for name in ('osd', 'mon', 'client', 'mds'):
351 assert_equal({}, validate_command(sigdict, ['tell', name]))
352 assert_equal({}, validate_command(sigdict, ['tell',
353 name + ".42"]))
354 self.assert_valid_command(['tell', name + ".42", 'something'])
355 self.assert_valid_command(['tell', name + ".42",
356 'something',
357 'something else'])
358
359
360class TestMDS(TestArgparse):
361
362 def test_stat(self):
363 self.check_no_arg('mds', 'stat')
364
7c673cae
FG
365 def test_compat_show(self):
366 self.assert_valid_command(['mds', 'compat', 'show'])
367 assert_equal({}, validate_command(sigdict, ['mds', 'compat']))
368 assert_equal({}, validate_command(sigdict, ['mds', 'compat',
369 'show', 'toomany']))
370
7c673cae
FG
371 def test_set_state(self):
372 self.assert_valid_command(['mds', 'set_state', '1', '2'])
373 assert_equal({}, validate_command(sigdict, ['mds', 'set_state']))
374 assert_equal({}, validate_command(sigdict, ['mds', 'set_state', '-1']))
375 assert_equal({}, validate_command(sigdict, ['mds', 'set_state',
376 '1', '-1']))
377 assert_equal({}, validate_command(sigdict, ['mds', 'set_state',
378 '1', '21']))
379
380 def test_fail(self):
381 self.check_1_string_arg('mds', 'fail')
382
383 def test_rm(self):
384 # Valid: single GID argument present
385 self.assert_valid_command(['mds', 'rm', '1'])
386
387 # Missing GID arg: invalid
388 assert_equal({}, validate_command(sigdict, ['mds', 'rm']))
389 # Extra arg: invalid
390 assert_equal({}, validate_command(sigdict, ['mds', 'rm', '1', 'mds.42']))
391
392 def test_rmfailed(self):
393 self.assert_valid_command(['mds', 'rmfailed', '0'])
394 self.assert_valid_command(['mds', 'rmfailed', '0', '--yes-i-really-mean-it'])
395 assert_equal({}, validate_command(sigdict, ['mds', 'rmfailed', '0',
396 '--yes-i-really-mean-it',
397 'toomany']))
398
7c673cae
FG
399 def test_compat_rm_compat(self):
400 self.assert_valid_command(['mds', 'compat', 'rm_compat', '1'])
401 assert_equal({}, validate_command(sigdict, ['mds',
402 'compat',
403 'rm_compat']))
404 assert_equal({}, validate_command(sigdict, ['mds',
405 'compat',
406 'rm_compat', '-1']))
407 assert_equal({}, validate_command(sigdict, ['mds',
408 'compat',
409 'rm_compat', '1', '1']))
410
411 def test_incompat_rm_incompat(self):
412 self.assert_valid_command(['mds', 'compat', 'rm_incompat', '1'])
413 assert_equal({}, validate_command(sigdict, ['mds',
414 'compat',
415 'rm_incompat']))
416 assert_equal({}, validate_command(sigdict, ['mds',
417 'compat',
418 'rm_incompat', '-1']))
419 assert_equal({}, validate_command(sigdict, ['mds',
420 'compat',
421 'rm_incompat', '1', '1']))
422
7c673cae
FG
423
424class TestFS(TestArgparse):
425
426 def test_dump(self):
427 self.check_0_or_1_natural_arg('fs', 'dump')
428
429 def test_fs_new(self):
430 self.assert_valid_command(['fs', 'new', 'default', 'metadata', 'data'])
431
11fdf7f2
TL
432 def test_fs_set_max_mds(self):
433 self.assert_valid_command(['fs', 'set', 'default', 'max_mds', '1'])
434 self.assert_valid_command(['fs', 'set', 'default', 'max_mds', '2'])
435
436 def test_fs_set_cluster_down(self):
437 self.assert_valid_command(['fs', 'set', 'default', 'down', 'true'])
438
439 def test_fs_set_cluster_up(self):
440 self.assert_valid_command(['fs', 'set', 'default', 'down', 'false'])
441
442 def test_fs_set_cluster_joinable(self):
443 self.assert_valid_command(['fs', 'set', 'default', 'joinable', 'true'])
444
445 def test_fs_set_cluster_not_joinable(self):
446 self.assert_valid_command(['fs', 'set', 'default', 'joinable', 'false'])
447
448 def test_fs_set(self):
449 self.assert_valid_command(['fs', 'set', 'default', 'max_file_size', '2'])
450 self.assert_valid_command(['fs', 'set', 'default', 'allow_new_snaps', 'no'])
451 assert_equal({}, validate_command(sigdict, ['fs',
452 'set',
453 'invalid']))
454
455 def test_fs_add_data_pool(self):
456 self.assert_valid_command(['fs', 'add_data_pool', 'default', '1'])
457 self.assert_valid_command(['fs', 'add_data_pool', 'default', 'foo'])
458
459 def test_fs_remove_data_pool(self):
460 self.assert_valid_command(['fs', 'rm_data_pool', 'default', '1'])
461 self.assert_valid_command(['fs', 'rm_data_pool', 'default', 'foo'])
462
7c673cae
FG
463 def test_fs_rm(self):
464 self.assert_valid_command(['fs', 'rm', 'default'])
465 self.assert_valid_command(['fs', 'rm', 'default', '--yes-i-really-mean-it'])
466 assert_equal({}, validate_command(sigdict, ['fs', 'rm', 'default', '--yes-i-really-mean-it', 'toomany']))
467
468 def test_fs_ls(self):
469 self.assert_valid_command(['fs', 'ls'])
470 assert_equal({}, validate_command(sigdict, ['fs', 'ls', 'toomany']))
471
472 def test_fs_set_default(self):
473 self.assert_valid_command(['fs', 'set-default', 'cephfs'])
474 assert_equal({}, validate_command(sigdict, ['fs', 'set-default']))
475 assert_equal({}, validate_command(sigdict, ['fs', 'set-default', 'cephfs', 'toomany']))
476
11fdf7f2 477
7c673cae
FG
478class TestMon(TestArgparse):
479
480 def test_dump(self):
481 self.check_0_or_1_natural_arg('mon', 'dump')
482
483 def test_stat(self):
484 self.check_no_arg('mon', 'stat')
485
486 def test_getmap(self):
487 self.check_0_or_1_natural_arg('mon', 'getmap')
488
489 def test_add(self):
490 self.assert_valid_command(['mon', 'add', 'name', '1.2.3.4:1234'])
491 assert_equal({}, validate_command(sigdict, ['mon', 'add']))
492 assert_equal({}, validate_command(sigdict, ['mon', 'add', 'name']))
493 assert_equal({}, validate_command(sigdict, ['mon', 'add',
494 'name',
495 '400.500.600.700']))
7c673cae
FG
496
497 def test_remove(self):
498 self.assert_valid_command(['mon', 'remove', 'name'])
499 assert_equal({}, validate_command(sigdict, ['mon', 'remove']))
500 assert_equal({}, validate_command(sigdict, ['mon', 'remove',
501 'name', 'toomany']))
502
503
504class TestOSD(TestArgparse):
505
506 def test_stat(self):
507 self.check_no_arg('osd', 'stat')
508
509 def test_dump(self):
510 self.check_0_or_1_natural_arg('osd', 'dump')
511
512 def test_osd_tree(self):
513 self.check_0_or_1_natural_arg('osd', 'tree')
b3b6e05e
TL
514 cmd = 'osd tree down,out'
515 assert_equal(
516 {
517 'prefix': 'osd tree',
518 'states': ['down', 'out']
519 }, validate_command(sigdict, cmd.split()))
7c673cae
FG
520
521 def test_osd_ls(self):
522 self.check_0_or_1_natural_arg('osd', 'ls')
523
524 def test_osd_getmap(self):
525 self.check_0_or_1_natural_arg('osd', 'getmap')
526
527 def test_osd_getcrushmap(self):
528 self.check_0_or_1_natural_arg('osd', 'getcrushmap')
529
530 def test_perf(self):
531 self.check_no_arg('osd', 'perf')
532
533 def test_getmaxosd(self):
534 self.check_no_arg('osd', 'getmaxosd')
535
536 def test_find(self):
537 self.check_1_natural_arg('osd', 'find')
538
539 def test_map(self):
540 self.assert_valid_command(['osd', 'map', 'poolname', 'objectname'])
541 self.assert_valid_command(['osd', 'map', 'poolname', 'objectname', 'nspace'])
542 assert_equal({}, validate_command(sigdict, ['osd', 'map']))
543 assert_equal({}, validate_command(sigdict, ['osd', 'map', 'poolname']))
544 assert_equal({}, validate_command(sigdict, ['osd', 'map',
545 'poolname', 'objectname', 'nspace',
546 'toomany']))
547
548 def test_metadata(self):
549 self.check_0_or_1_natural_arg('osd', 'metadata')
550
551 def test_scrub(self):
552 self.check_1_string_arg('osd', 'scrub')
553
554 def test_deep_scrub(self):
555 self.check_1_string_arg('osd', 'deep-scrub')
556
557 def test_repair(self):
558 self.check_1_string_arg('osd', 'repair')
559
560 def test_lspools(self):
561 self.assert_valid_command(['osd', 'lspools'])
7c673cae 562 assert_equal({}, validate_command(sigdict, ['osd', 'lspools',
11fdf7f2 563 'toomany']))
7c673cae 564
f67539c2
TL
565 def test_blocklist_ls(self):
566 self.assert_valid_command(['osd', 'blocklist', 'ls'])
567 assert_equal({}, validate_command(sigdict, ['osd', 'blocklist']))
568 assert_equal({}, validate_command(sigdict, ['osd', 'blocklist',
7c673cae
FG
569 'ls', 'toomany']))
570
571 def test_crush_rule(self):
572 assert_equal({}, validate_command(sigdict, ['osd', 'crush']))
573 assert_equal({}, validate_command(sigdict, ['osd', 'crush', 'rule']))
574 for subcommand in ('list', 'ls'):
575 self.assert_valid_command(['osd', 'crush', 'rule', subcommand])
576 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
577 'rule', subcommand,
578 'toomany']))
579
580 def test_crush_rule_dump(self):
581 self.assert_valid_command(['osd', 'crush', 'rule', 'dump'])
582 self.assert_valid_command(['osd', 'crush', 'rule', 'dump', 'RULE'])
583 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
584 'rule', 'dump',
585 'RULE',
586 'toomany']))
587
588 def test_crush_dump(self):
589 self.assert_valid_command(['osd', 'crush', 'dump'])
590 assert_equal({}, validate_command(sigdict, ['osd', 'crush']))
591 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
592 'dump',
593 'toomany']))
594
595 def test_setcrushmap(self):
596 self.check_no_arg('osd', 'setcrushmap')
597
598 def test_crush_add_bucket(self):
599 self.assert_valid_command(['osd', 'crush', 'add-bucket',
600 'name', 'type'])
11fdf7f2
TL
601 self.assert_valid_command(['osd', 'crush', 'add-bucket',
602 'name', 'type', 'root=foo-root', 'host=foo-host'])
7c673cae
FG
603 assert_equal({}, validate_command(sigdict, ['osd', 'crush']))
604 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
605 'add-bucket']))
7c673cae
FG
606 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
607 'add-bucket', '^^^',
608 'type']))
609
610 def test_crush_rename_bucket(self):
611 self.assert_valid_command(['osd', 'crush', 'rename-bucket',
612 'srcname', 'dstname'])
613 assert_equal({}, validate_command(sigdict, ['osd', 'crush']))
614 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
615 'rename-bucket']))
616 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
617 'rename-bucket',
618 'srcname']))
619 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
620 'rename-bucket', 'srcname',
621 'dstname',
622 'toomany']))
623 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
624 'rename-bucket', '^^^',
625 'dstname']))
626 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
627 'rename-bucket', 'srcname',
628 '^^^^']))
629
630 def check_crush_setter(self, setter):
631 self.assert_valid_command(['osd', 'crush', setter,
632 '*', '2.3', 'AZaz09-_.='])
633 self.assert_valid_command(['osd', 'crush', setter,
634 'osd.0', '2.3', 'AZaz09-_.='])
635 self.assert_valid_command(['osd', 'crush', setter,
636 '0', '2.3', 'AZaz09-_.='])
637 self.assert_valid_command(['osd', 'crush', setter,
638 '0', '2.3', 'AZaz09-_.=', 'AZaz09-_.='])
639 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
640 setter,
641 'osd.0']))
642 ret = validate_command(sigdict, ['osd', 'crush',
643 setter,
644 'osd.0',
645 '-1.0'])
646 assert ret in [None, {}]
647 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
648 setter,
649 'osd.0',
650 '1.0',
651 '^^^']))
652
653 def test_crush_set(self):
654 assert_equal({}, validate_command(sigdict, ['osd', 'crush']))
655 self.check_crush_setter('set')
656
657 def test_crush_add(self):
658 assert_equal({}, validate_command(sigdict, ['osd', 'crush']))
659 self.check_crush_setter('add')
660
661 def test_crush_create_or_move(self):
662 assert_equal({}, validate_command(sigdict, ['osd', 'crush']))
663 self.check_crush_setter('create-or-move')
664
665 def test_crush_move(self):
666 self.assert_valid_command(['osd', 'crush', 'move',
667 'AZaz09-_.', 'AZaz09-_.='])
668 self.assert_valid_command(['osd', 'crush', 'move',
669 '0', 'AZaz09-_.=', 'AZaz09-_.='])
670 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
671 'move']))
672 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
673 'move', 'AZaz09-_.']))
674 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
675 'move', '^^^',
676 'AZaz09-_.=']))
677 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
678 'move', 'AZaz09-_.',
679 '^^^']))
680
681 def test_crush_link(self):
682 self.assert_valid_command(['osd', 'crush', 'link',
683 'name', 'AZaz09-_.='])
684 self.assert_valid_command(['osd', 'crush', 'link',
685 'name', 'AZaz09-_.=', 'AZaz09-_.='])
686 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
687 'link']))
688 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
689 'link',
690 'name']))
691
692 def test_crush_rm(self):
693 for alias in ('rm', 'remove', 'unlink'):
694 self.assert_valid_command(['osd', 'crush', alias, 'AZaz09-_.'])
695 self.assert_valid_command(['osd', 'crush', alias,
696 'AZaz09-_.', 'AZaz09-_.'])
697 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
698 alias]))
699 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
700 alias,
701 'AZaz09-_.',
702 'AZaz09-_.',
703 'toomany']))
704
705 def test_crush_reweight(self):
706 self.assert_valid_command(['osd', 'crush', 'reweight',
707 'AZaz09-_.', '2.3'])
708 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
709 'reweight']))
710 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
711 'reweight',
712 'AZaz09-_.']))
713 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
714 'reweight',
715 'AZaz09-_.',
716 '-1.0']))
717 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
718 'reweight',
719 '^^^',
720 '2.3']))
721
722 def test_crush_tunables(self):
723 for tunable in ('legacy', 'argonaut', 'bobtail', 'firefly',
724 'optimal', 'default'):
725 self.assert_valid_command(['osd', 'crush', 'tunables',
726 tunable])
727 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
728 'tunables']))
729 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
730 'tunables',
731 'default', 'toomany']))
732
733 def test_crush_rule_create_simple(self):
734 self.assert_valid_command(['osd', 'crush', 'rule', 'create-simple',
735 'AZaz09-_.', 'AZaz09-_.', 'AZaz09-_.'])
736 assert_equal({}, validate_command(sigdict, ['osd', 'crush', 'rule',
737 'create-simple']))
738 assert_equal({}, validate_command(sigdict, ['osd', 'crush', 'rule',
739 'create-simple',
740 'AZaz09-_.']))
741 assert_equal({}, validate_command(sigdict, ['osd', 'crush', 'rule',
742 'create-simple',
743 'AZaz09-_.',
744 'AZaz09-_.']))
745 assert_equal({}, validate_command(sigdict, ['osd', 'crush', 'rule',
746 'create-simple',
747 '^^^',
748 'AZaz09-_.',
749 'AZaz09-_.']))
750 assert_equal({}, validate_command(sigdict, ['osd', 'crush', 'rule',
751 'create-simple',
752 'AZaz09-_.',
753 '|||',
754 'AZaz09-_.']))
755 assert_equal({}, validate_command(sigdict, ['osd', 'crush', 'rule',
756 'create-simple',
757 'AZaz09-_.',
758 'AZaz09-_.',
759 '+++']))
760 assert_equal({}, validate_command(sigdict, ['osd', 'crush', 'rule',
761 'create-simple',
762 'AZaz09-_.',
763 'AZaz09-_.',
764 'AZaz09-_.',
765 'toomany']))
766
767 def test_crush_rule_create_erasure(self):
768 self.assert_valid_command(['osd', 'crush', 'rule', 'create-erasure',
769 'AZaz09-_.'])
770 self.assert_valid_command(['osd', 'crush', 'rule', 'create-erasure',
771 'AZaz09-_.', 'whatever'])
772 assert_equal({}, validate_command(sigdict, ['osd', 'crush', 'rule',
773 'create-erasure']))
774 assert_equal({}, validate_command(sigdict, ['osd', 'crush', 'rule',
775 'create-erasure',
776 '^^^']))
777 assert_equal({}, validate_command(sigdict, ['osd', 'crush', 'rule',
778 'create-erasure',
779 'name', '^^^']))
780
781 def test_crush_rule_rm(self):
782 self.assert_valid_command(['osd', 'crush', 'rule', 'rm', 'AZaz09-_.'])
783 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
784 'rule', 'rm']))
785 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
786 'rule', 'rm',
787 '^^^^']))
788 assert_equal({}, validate_command(sigdict, ['osd', 'crush',
789 'rule', 'rm',
790 'AZaz09-_.',
791 'toomany']))
792
793 def test_setmaxosd(self):
794 self.check_1_natural_arg('osd', 'setmaxosd')
795
796 def test_pause(self):
797 self.check_no_arg('osd', 'pause')
798
799 def test_unpause(self):
800 self.check_no_arg('osd', 'unpause')
801
802 def test_erasure_code_profile_set(self):
803 self.assert_valid_command(['osd', 'erasure-code-profile', 'set',
804 'name'])
805 self.assert_valid_command(['osd', 'erasure-code-profile', 'set',
806 'name', 'A=B'])
807 self.assert_valid_command(['osd', 'erasure-code-profile', 'set',
808 'name', 'A=B', 'C=D'])
809 assert_equal({}, validate_command(sigdict, ['osd',
810 'erasure-code-profile',
811 'set']))
812 assert_equal({}, validate_command(sigdict, ['osd',
813 'erasure-code-profile',
814 'set',
815 '^^^^']))
816
817 def test_erasure_code_profile_get(self):
818 self.assert_valid_command(['osd', 'erasure-code-profile', 'get',
819 'name'])
820 assert_equal({}, validate_command(sigdict, ['osd',
821 'erasure-code-profile',
822 'get']))
823 assert_equal({}, validate_command(sigdict, ['osd',
824 'erasure-code-profile',
825 'get',
826 '^^^^']))
827
828 def test_erasure_code_profile_rm(self):
829 self.assert_valid_command(['osd', 'erasure-code-profile', 'rm',
830 'name'])
831 assert_equal({}, validate_command(sigdict, ['osd',
832 'erasure-code-profile',
833 'rm']))
834 assert_equal({}, validate_command(sigdict, ['osd',
835 'erasure-code-profile',
836 'rm',
837 '^^^^']))
838
839 def test_erasure_code_profile_ls(self):
840 self.assert_valid_command(['osd', 'erasure-code-profile', 'ls'])
841 assert_equal({}, validate_command(sigdict, ['osd',
842 'erasure-code-profile',
843 'ls',
844 'toomany']))
845
846 def test_set_unset(self):
847 for action in ('set', 'unset'):
848 for flag in ('pause', 'noup', 'nodown', 'noout', 'noin',
849 'nobackfill', 'norecover', 'noscrub', 'nodeep-scrub'):
850 self.assert_valid_command(['osd', action, flag])
851 assert_equal({}, validate_command(sigdict, ['osd', action]))
852 assert_equal({}, validate_command(sigdict, ['osd', action,
853 'invalid']))
854 assert_equal({}, validate_command(sigdict, ['osd', action,
855 'pause', 'toomany']))
856
7c673cae
FG
857 def test_down(self):
858 self.check_1_or_more_string_args('osd', 'down')
859
860 def test_out(self):
861 self.check_1_or_more_string_args('osd', 'out')
862
863 def test_in(self):
864 self.check_1_or_more_string_args('osd', 'in')
865
866 def test_rm(self):
867 self.check_1_or_more_string_args('osd', 'rm')
868
869 def test_reweight(self):
870 self.assert_valid_command(['osd', 'reweight', '1', '0.1'])
871 assert_equal({}, validate_command(sigdict, ['osd', 'reweight']))
872 assert_equal({}, validate_command(sigdict, ['osd', 'reweight',
873 '1']))
874 assert_equal({}, validate_command(sigdict, ['osd', 'reweight',
875 '1', '2.0']))
876 assert_equal({}, validate_command(sigdict, ['osd', 'reweight',
877 '-1', '0.1']))
878 assert_equal({}, validate_command(sigdict, ['osd', 'reweight',
879 '1', '0.1',
880 'toomany']))
881
882 def test_lost(self):
883 self.assert_valid_command(['osd', 'lost', '1',
884 '--yes-i-really-mean-it'])
885 self.assert_valid_command(['osd', 'lost', '1'])
886 assert_equal({}, validate_command(sigdict, ['osd', 'lost']))
887 assert_equal({}, validate_command(sigdict, ['osd', 'lost',
888 '1',
889 'what?']))
890 assert_equal({}, validate_command(sigdict, ['osd', 'lost',
891 '-1',
892 '--yes-i-really-mean-it']))
893 assert_equal({}, validate_command(sigdict, ['osd', 'lost',
894 '1',
895 '--yes-i-really-mean-it',
896 'toomany']))
897
898 def test_create(self):
899 uuid = '12345678123456781234567812345678'
900 self.assert_valid_command(['osd', 'create'])
901 self.assert_valid_command(['osd', 'create',
902 uuid])
903 assert_equal({}, validate_command(sigdict, ['osd', 'create',
904 'invalid']))
905 assert_equal({}, validate_command(sigdict, ['osd', 'create',
906 uuid,
907 'toomany']))
908
f67539c2 909 def test_blocklist(self):
7c673cae 910 for action in ('add', 'rm'):
f67539c2 911 self.assert_valid_command(['osd', 'blocklist', action,
7c673cae 912 '1.2.3.4/567'])
f67539c2 913 self.assert_valid_command(['osd', 'blocklist', action,
7c673cae 914 '1.2.3.4'])
f67539c2 915 self.assert_valid_command(['osd', 'blocklist', action,
7c673cae 916 '1.2.3.4/567', '600.40'])
f67539c2 917 self.assert_valid_command(['osd', 'blocklist', action,
7c673cae 918 '1.2.3.4', '600.40'])
f67539c2 919 assert_equal({}, validate_command(sigdict, ['osd', 'blocklist',
7c673cae
FG
920 action,
921 'invalid',
922 '600.40']))
f67539c2 923 assert_equal({}, validate_command(sigdict, ['osd', 'blocklist',
7c673cae
FG
924 action,
925 '1.2.3.4/567',
926 '-1.0']))
f67539c2 927 assert_equal({}, validate_command(sigdict, ['osd', 'blocklist',
7c673cae
FG
928 action,
929 '1.2.3.4/567',
930 '600.40',
931 'toomany']))
932
933 def test_pool_mksnap(self):
934 self.assert_valid_command(['osd', 'pool', 'mksnap',
935 'poolname', 'snapname'])
936 assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'mksnap']))
937 assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'mksnap',
938 'poolname']))
939 assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'mksnap',
940 'poolname', 'snapname',
941 'toomany']))
942
943 def test_pool_rmsnap(self):
944 self.assert_valid_command(['osd', 'pool', 'rmsnap',
945 'poolname', 'snapname'])
946 assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'rmsnap']))
947 assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'rmsnap',
948 'poolname']))
949 assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'rmsnap',
950 'poolname', 'snapname',
951 'toomany']))
952
11fdf7f2
TL
953 def test_pool_kwargs(self):
954 """
955 Use the pool creation command to exercise keyword-style arguments
956 since it has lots of parameters
957 """
958 # Simply use a keyword arg instead of a positional arg, in its
959 # normal order (pgp_num after pg_num)
960 assert_equal(
961 {
962 "prefix": "osd pool create",
963 "pool": "foo",
964 "pg_num": 8,
965 "pgp_num": 16
966 }, validate_command(sigdict, [
967 'osd', 'pool', 'create', "foo", "8", "--pgp_num", "16"]))
968
969 # Again, but using the "--foo=bar" style
970 assert_equal(
971 {
972 "prefix": "osd pool create",
973 "pool": "foo",
974 "pg_num": 8,
975 "pgp_num": 16
976 }, validate_command(sigdict, [
977 'osd', 'pool', 'create', "foo", "8", "--pgp_num=16"]))
978
979 # Specify keyword args in a different order than their definitions
980 # (pgp_num after pool_type)
981 assert_equal(
982 {
983 "prefix": "osd pool create",
984 "pool": "foo",
985 "pg_num": 8,
986 "pgp_num": 16,
987 "pool_type": "replicated"
988 }, validate_command(sigdict, [
989 'osd', 'pool', 'create', "foo", "8",
990 "--pool_type", "replicated",
991 "--pgp_num", "16"]))
992
993 # Use a keyword argument that doesn't exist, should fail validation
994 assert_equal({}, validate_command(sigdict,
995 ['osd', 'pool', 'create', "foo", "8", "--foo=bar"]))
996
997 def test_foo(self):
998 # Long form of a boolean argument (--foo=true)
999 assert_equal(
1000 {
1001 "prefix": "osd pool delete",
1002 "pool": "foo",
1003 "pool2": "foo",
1004 "yes_i_really_really_mean_it": True
1005 }, validate_command(sigdict, [
1006 'osd', 'pool', 'delete', "foo", "foo",
1007 "--yes-i-really-really-mean-it=true"]))
1008
1009 def test_pool_bool_args(self):
1010 """
1011 Use pool deletion to exercise boolean arguments since it has
1012 the --yes-i-really-really-mean-it flags
1013 """
1014
1015 # Short form of a boolean argument (--foo)
1016 assert_equal(
1017 {
1018 "prefix": "osd pool delete",
1019 "pool": "foo",
1020 "pool2": "foo",
1021 "yes_i_really_really_mean_it": True
1022 }, validate_command(sigdict, [
1023 'osd', 'pool', 'delete', "foo", "foo",
1024 "--yes-i-really-really-mean-it"]))
1025
1026 # Long form of a boolean argument (--foo=true)
1027 assert_equal(
1028 {
1029 "prefix": "osd pool delete",
1030 "pool": "foo",
1031 "pool2": "foo",
1032 "yes_i_really_really_mean_it": True
1033 }, validate_command(sigdict, [
1034 'osd', 'pool', 'delete', "foo", "foo",
1035 "--yes-i-really-really-mean-it=true"]))
1036
1037 # Negative form of a boolean argument (--foo=false)
1038 assert_equal(
1039 {
1040 "prefix": "osd pool delete",
1041 "pool": "foo",
1042 "pool2": "foo",
1043 "yes_i_really_really_mean_it": False
1044 }, validate_command(sigdict, [
1045 'osd', 'pool', 'delete', "foo", "foo",
1046 "--yes-i-really-really-mean-it=false"]))
1047
1048 # Invalid value boolean argument (--foo=somethingelse)
1049 assert_equal({}, validate_command(sigdict, [
1050 'osd', 'pool', 'delete', "foo", "foo",
1051 "--yes-i-really-really-mean-it=rhubarb"]))
1052
7c673cae
FG
1053 def test_pool_create(self):
1054 self.assert_valid_command(['osd', 'pool', 'create',
1055 'poolname', '128'])
1056 self.assert_valid_command(['osd', 'pool', 'create',
1057 'poolname', '128', '128'])
1058 self.assert_valid_command(['osd', 'pool', 'create',
1059 'poolname', '128', '128',
1060 'replicated'])
1061 self.assert_valid_command(['osd', 'pool', 'create',
1062 'poolname', '128', '128',
1063 'erasure', 'A-Za-z0-9-_.', 'ruleset^^'])
9f95a23c 1064 self.assert_valid_command(['osd', 'pool', 'create', 'poolname'])
7c673cae 1065 assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'create']))
9f95a23c
TL
1066 # invalid pg_num and pgp_num, like "-1", could spill over to
1067 # erasure_code_profile and rule as they are valid profile and rule
1068 # names, so validate_commands() cannot identify such cases.
1069 # but if they are matched by profile and rule, the "rule" argument
1070 # won't get a chance to be matched anymore.
7c673cae 1071 assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'create',
9f95a23c
TL
1072 'poolname',
1073 '-1', '-1',
1074 'ruleset']))
7c673cae
FG
1075 assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'create',
1076 'poolname',
1077 '128', '128',
1078 'erasure', '^^^',
1079 'ruleset']))
1080 assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'create',
1081 'poolname',
1082 '128', '128',
1083 'erasure', 'profile',
1084 'ruleset',
1085 'toomany']))
1086 assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'create',
1087 'poolname',
1088 '128', '128',
1089 'INVALID', 'profile',
1090 'ruleset']))
1091
1092 def test_pool_delete(self):
1093 self.assert_valid_command(['osd', 'pool', 'delete',
1094 'poolname', 'poolname',
1095 '--yes-i-really-really-mean-it'])
1096 self.assert_valid_command(['osd', 'pool', 'delete',
1097 'poolname', 'poolname'])
1098 self.assert_valid_command(['osd', 'pool', 'delete',
1099 'poolname'])
1100 assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'delete']))
7c673cae
FG
1101 assert_equal({}, validate_command(sigdict,
1102 ['osd', 'pool', 'delete',
1103 'poolname', 'poolname',
1104 '--yes-i-really-really-mean-it',
1105 'toomany']))
1106
1107 def test_pool_rename(self):
1108 self.assert_valid_command(['osd', 'pool', 'rename',
1109 'poolname', 'othername'])
1110 assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'rename']))
1111 assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'rename',
1112 'poolname']))
1113 assert_equal({}, validate_command(sigdict, ['osd', 'pool', 'rename',
1114 'poolname', 'othername',
1115 'toomany']))
1116
1117 def test_pool_get(self):
11fdf7f2
TL
1118 for var in ('size', 'min_size',
1119 'pg_num', 'pgp_num', 'crush_rule', 'fast_read',
7c673cae
FG
1120 'scrub_min_interval', 'scrub_max_interval',
1121 'deep_scrub_interval', 'recovery_priority',
1122 'recovery_op_priority'):
1123 self.assert_valid_command(['osd', 'pool', 'get', 'poolname', var])
1124 assert_equal({}, validate_command(sigdict, ['osd', 'pool']))
1125 assert_equal({}, validate_command(sigdict, ['osd', 'pool',
1126 'get']))
1127 assert_equal({}, validate_command(sigdict, ['osd', 'pool',
1128 'get', 'poolname']))
1129 assert_equal({}, validate_command(sigdict, ['osd', 'pool',
1130 'get', 'poolname',
1131 'size', 'toomany']))
1132 assert_equal({}, validate_command(sigdict, ['osd', 'pool',
1133 'get', 'poolname',
1134 'invalid']))
1135
1136 def test_pool_set(self):
11fdf7f2 1137 for var in ('size', 'min_size',
31f18b77 1138 'pg_num', 'pgp_num', 'crush_rule',
11fdf7f2 1139 'hashpspool', 'fast_read',
7c673cae
FG
1140 'scrub_min_interval', 'scrub_max_interval',
1141 'deep_scrub_interval', 'recovery_priority',
1142 'recovery_op_priority'):
1143 self.assert_valid_command(['osd', 'pool',
1144 'set', 'poolname', var, 'value'])
1145 assert_equal({}, validate_command(sigdict, ['osd', 'pool',
1146 'set']))
1147 assert_equal({}, validate_command(sigdict, ['osd', 'pool',
1148 'set', 'poolname']))
1149 assert_equal({}, validate_command(sigdict, ['osd', 'pool',
1150 'set', 'poolname',
1151 'size', 'value',
1152 'toomany']))
1153
1154 def test_pool_set_quota(self):
1155 for field in ('max_objects', 'max_bytes'):
1156 self.assert_valid_command(['osd', 'pool', 'set-quota',
1157 'poolname', field, '10K'])
1158 assert_equal({}, validate_command(sigdict, ['osd', 'pool',
1159 'set-quota']))
1160 assert_equal({}, validate_command(sigdict, ['osd', 'pool',
1161 'set-quota',
1162 'poolname']))
1163 assert_equal({}, validate_command(sigdict, ['osd', 'pool',
1164 'set-quota',
1165 'poolname',
1166 'max_objects']))
1167 assert_equal({}, validate_command(sigdict, ['osd', 'pool',
1168 'set-quota',
1169 'poolname',
1170 'invalid',
1171 '10K']))
1172 assert_equal({}, validate_command(sigdict, ['osd', 'pool',
1173 'set-quota',
1174 'poolname',
1175 'max_objects',
1176 '10K',
1177 'toomany']))
1178
1179 def test_reweight_by_utilization(self):
1180 self.assert_valid_command(['osd', 'reweight-by-utilization'])
1181 self.assert_valid_command(['osd', 'reweight-by-utilization', '100'])
1182 self.assert_valid_command(['osd', 'reweight-by-utilization', '100', '.1'])
7c673cae
FG
1183 assert_equal({}, validate_command(sigdict, ['osd',
1184 'reweight-by-utilization',
1185 '100',
1186 'toomany']))
1187
1188 def test_tier_op(self):
1189 for op in ('add', 'remove', 'set-overlay'):
1190 self.assert_valid_command(['osd', 'tier', op,
1191 'poolname', 'othername'])
1192 assert_equal({}, validate_command(sigdict, ['osd', 'tier', op]))
1193 assert_equal({}, validate_command(sigdict, ['osd', 'tier', op,
1194 'poolname']))
1195 assert_equal({}, validate_command(sigdict, ['osd', 'tier', op,
1196 'poolname',
1197 'othername',
1198 'toomany']))
1199
1200 def test_tier_cache_mode(self):
b3b6e05e 1201 for mode in ('none', 'writeback', 'readonly', 'readproxy'):
7c673cae
FG
1202 self.assert_valid_command(['osd', 'tier', 'cache-mode',
1203 'poolname', mode])
1204 assert_equal({}, validate_command(sigdict, ['osd', 'tier',
1205 'cache-mode']))
1206 assert_equal({}, validate_command(sigdict, ['osd', 'tier',
1207 'cache-mode',
1208 'invalid']))
1209
1210 def test_tier_remove_overlay(self):
1211 self.assert_valid_command(['osd', 'tier', 'remove-overlay',
1212 'poolname'])
1213 assert_equal({}, validate_command(sigdict, ['osd', 'tier',
1214 'remove-overlay']))
1215 assert_equal({}, validate_command(sigdict, ['osd', 'tier',
1216 'remove-overlay',
1217 'poolname',
1218 'toomany']))
1219
1220 def set_ratio(self, command):
1221 self.assert_valid_command(['osd',
1222 command,
1223 '0.0'])
1224 assert_equal({}, validate_command(sigdict, ['osd', command]))
1225 assert_equal({}, validate_command(sigdict, ['osd',
1226 command,
1227 '2.0']))
1228
1229 def test_set_full_ratio(self):
1230 self.set_ratio('set-full-ratio')
1231
1232 def test_set_backfillfull_ratio(self):
1233 self.set_ratio('set-backfillfull-ratio')
1234
1235 def test_set_nearfull_ratio(self):
1236 self.set_ratio('set-nearfull-ratio')
1237
1238
1239class TestConfigKey(TestArgparse):
1240
1241 def test_get(self):
1242 self.check_1_string_arg('config-key', 'get')
1243
1244 def test_put(self):
1245 self.assert_valid_command(['config-key', 'put',
1246 'key'])
1247 self.assert_valid_command(['config-key', 'put',
1248 'key', 'value'])
1249 assert_equal({}, validate_command(sigdict, ['config-key', 'put']))
1250 assert_equal({}, validate_command(sigdict, ['config-key', 'put',
1251 'key', 'value',
1252 'toomany']))
1253
1254 def test_del(self):
1255 self.check_1_string_arg('config-key', 'del')
1256
1257 def test_exists(self):
1258 self.check_1_string_arg('config-key', 'exists')
1259
1260 def test_dump(self):
11fdf7f2 1261 self.check_0_or_1_string_arg('config-key', 'dump')
7c673cae
FG
1262
1263 def test_list(self):
1264 self.check_no_arg('config-key', 'list')
9f95a23c
TL
1265
1266
1267class TestValidate(TestCase):
1268
1269 ARGS = 0
1270 KWARGS = 1
1271 KWARGS_EQ = 2
1272 MIXED = 3
1273
1274 def setUp(self):
1275 self.prefix = ['some', 'random', 'cmd']
1276 self.args_dict = [
1277 {'name': 'variable_one', 'type': 'CephString'},
1278 {'name': 'variable_two', 'type': 'CephString'},
1279 {'name': 'variable_three', 'type': 'CephString'},
1280 {'name': 'variable_four', 'type': 'CephInt'},
1281 {'name': 'variable_five', 'type': 'CephString'}]
1282 self.args = []
1283 for d in self.args_dict:
1284 if d['type'] == 'CephInt':
1285 val = "{}".format(random.randint(0, 100))
1286 elif d['type'] == 'CephString':
1287 letters = string.ascii_letters
1288 str_len = random.randint(5, 10)
1289 val = ''.join(random.choice(letters) for _ in range(str_len))
1290 else:
1291 self.skipTest()
1292
1293 self.args.append((d['name'], val))
1294
1295 self.sig = parse_funcsig(self.prefix + self.args_dict)
1296
b3b6e05e 1297 @nottest
9f95a23c
TL
1298 def arg_kwarg_test(self, prefix, args, sig, arg_type=0):
1299 """
1300 Runs validate in different arg/kargs ways.
1301
1302 :param prefix: List of prefix commands (that can't be kwarged)
1303 :param args: a list of kwarg, arg pairs: [(k1, v1), (k2, v2), ...]
1304 :param sig: The sig to match
1305 :param arg_type: how to build the args to send. As positional args (ARGS),
1306 as long kwargs (KWARGS [--k v]), other style long kwargs
1307 (KWARGS_EQ (--k=v]), and mixed (MIXED) where there will be
1308 a random mix of the above.
1309 :return: None, the method will assert.
1310 """
1311 final_args = list(prefix)
1312 for k, v in args:
1313 a_type = arg_type
1314 if a_type == self.MIXED:
1315 a_type = random.choice((self.ARGS,
b3b6e05e
TL
1316 self.KWARGS,
1317 self.KWARGS_EQ))
9f95a23c
TL
1318 if a_type == self.ARGS:
1319 final_args.append(v)
1320 elif a_type == self.KWARGS:
1321 final_args.extend(["--{}".format(k), v])
1322 else:
1323 final_args.append("--{}={}".format(k, v))
1324
1325 try:
1326 validate(final_args, sig)
1327 except (ArgumentError, ArgumentMissing,
1328 ArgumentNumber, ArgumentTooFew, ArgumentValid) as ex:
1329 self.fail("Validation failed: {}".format(str(ex)))
1330
1331 def test_args_and_kwargs_validate(self):
1332 for arg_type in (self.ARGS, self.KWARGS, self.KWARGS_EQ, self.MIXED):
1333 self.arg_kwarg_test(self.prefix, self.args, self.sig, arg_type)
1334
7c673cae 1335# Local Variables:
9f95a23c
TL
1336# compile-command: "cd ../../..; cmake --build build --target get_command_descriptions -j4 &&
1337# CEPH_BIN=build/bin \
1338# PYTHONPATH=src/pybind nosetests --stop \
1339# src/test/pybind/test_ceph_argparse.py:TestOSD.test_rm"
7c673cae 1340# End: