Project

General

Profile

Actions

Bug #10439

closed

'ceph tell' should fail if daemon is not found

Added by Mykola Golub over 9 years ago. Updated about 9 years ago.

Status:
Resolved
Priority:
Normal
Assignee:
Joao Eduardo Luis
Category:
ceph cli
Target version:
-
% Done:

0%

Source:
Community (dev)
Tags:
Backport:
Regression:
Severity:
3 - minor
Reviewed:
Affected Versions:
ceph-qa-suite:
Pull request ID:
Crash signature (v1):
Crash signature (v2):

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

Actions #1

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.

Actions #2

Updated by Joao Eduardo Luis over 9 years ago

  • Status changed from New to Fix Under Review
  • Assignee set to Joao Eduardo Luis
Actions #3

Updated by Sage Weil about 9 years ago

  • Status changed from Fix Under Review to Resolved
Actions

Also available in: Atom PDF