Bug #10439
closed'ceph tell' should fail if daemon is not found
0%
Description
Right now if a daemon specified to 'ceph tell' command does not match 'osd.{number}' format and is not a mon daemon, the command is still sent to one of the mons.
Example:
% ceph tell osd.0 health
no valid command found; 10 closest matches:
...
Error EINVAL: invalid command
(it fails because osd daemon does not support 'health' command, expected)
% ceph tell osd.999 health
Error ENOENT: problem getting command descriptions from osd.999
(it fails because osd daemon 999 does not exist, expected)
% ceph tell osd.foo health
HEALTH_OK
(a mon daemon returns health, unexpected)
% ceph tell gibberish health
HEALTH_OK
(a mon daemon returns health, unexpected)
A more correct behavior looks like to return a error in the last two cases.
See some discussin at https://github.com/ceph/ceph/pull/3272
Updated by Joao Eduardo Luis over 9 years ago
the problem lies in pybind/ceph_argparse.py, function 'find_cmd_target()'.
The following snippet takes a relaxed approach at determining the target of a command, with the function returning
'mon', ''in the end in the absence of a correct signature match.
sig = parse_funcsig(['tell', {'name':'target', 'type':'CephName'}]) try: valid_dict = validate(childargs, sig, partial=True) except ArgumentError: pass else: if len(valid_dict) == 2: # revalidate to isolate type and id name = CephName() # if this fails, something is horribly wrong, as it just # validated successfully above name.valid(valid_dict['target']) return name.nametype, name.nameid
For instance, a properly formed 'tell' will be correctly parsed by 'validate()':
(Pdb) validate('tell mon.* health'.split(), sig, partial=True) {'prefix': 'tell', 'target': 'mon.*'}
but an incorrect 'tell' will silently fail:
(Pdb) validate('tell health'.split(), sig, partial=True) {'prefix': 'tell'} (Pdb) validate('tell foo health'.split(), sig, partial=True) {'prefix': 'tell'}
Tightening the requirements of 'validate()' with 'partial=False' will catch the erroneous target format:
(Pdb) validate('tell foo health'.split(), sig, partial=False) *** ArgumentFormat: CephName: no . in foo (Pdb) validate('tell health'.split(), sig, partial=False) *** ArgumentFormat: CephName: no . in health
but will result in an ArgumentError exception on properly formed commands:
(Pdb) validate('tell mon.* health'.split(), sig, partial=False) *** ArgumentError: unused arguments: ['health']
Although this exception is handled by the 'try' block, it's not in a way that indicates that it was the meant use case for the except clause.
Updated by Joao Eduardo Luis over 9 years ago
- Status changed from New to Fix Under Review
- Assignee set to Joao Eduardo Luis
Updated by Sage Weil about 9 years ago
- Status changed from Fix Under Review to Resolved