diff options
author | Sage Weil <sage@inktank.com> | 2013-07-16 15:24:03 -0700 |
---|---|---|
committer | Sage Weil <sage@inktank.com> | 2013-07-16 15:24:03 -0700 |
commit | 62d9983bce7c837ef10e31ac99b562efb380a5ba (patch) | |
tree | e8c82d86de5e2eef467948432e6d21c91ae8b5c2 | |
parent | c449a8b3257e6be2916d229f91cb10910f01d854 (diff) | |
parent | 4d9d0ffb892b69baa54316f0102f2f4f89666a90 (diff) | |
download | ceph-62d9983bce7c837ef10e31ac99b562efb380a5ba.tar.gz |
Merge branch 'wip-4779' into next
Reviewed-by: Sage Weil <sage@inktank.com># Please enter a commit message to explain why this merge is necessary,
-rw-r--r-- | src/crush/CrushWrapper.cc | 27 | ||||
-rw-r--r-- | src/crush/CrushWrapper.h | 8 | ||||
-rw-r--r-- | src/mon/MonCommands.h | 33 | ||||
-rw-r--r-- | src/mon/OSDMonitor.cc | 6 | ||||
-rw-r--r-- | src/pybind/ceph_argparse.py | 47 |
5 files changed, 85 insertions, 36 deletions
diff --git a/src/crush/CrushWrapper.cc b/src/crush/CrushWrapper.cc index 8a9addfb6c2..e96e6123aab 100644 --- a/src/crush/CrushWrapper.cc +++ b/src/crush/CrushWrapper.cc @@ -333,6 +333,9 @@ int CrushWrapper::insert_item(CephContext *cct, int item, float weight, string n ldout(cct, 5) << "insert_item item " << item << " weight " << weight << " name " << name << " loc " << loc << dendl; + if (!is_valid_crush_name(name)) + return -EINVAL; + if (name_exists(name)) { if (get_item_id(name) != item) { ldout(cct, 10) << "device name '" << name << "' already exists as id " @@ -473,6 +476,10 @@ int CrushWrapper::create_or_move_item(CephContext *cct, int item, float weight, { int ret = 0; int old_iweight; + + if (!is_valid_crush_name(name)) + return -EINVAL; + if (check_item_loc(cct, item, loc, &old_iweight)) { ldout(cct, 5) << "create_or_move_item " << item << " already at " << loc << dendl; } else { @@ -497,6 +504,9 @@ int CrushWrapper::update_item(CephContext *cct, int item, float weight, string n << " name " << name << " loc " << loc << dendl; int ret = 0; + if (!is_valid_crush_name(name)) + return -EINVAL; + // compare quantized (fixed-point integer) weights! int iweight = (int)(weight * (float)0x10000); int old_iweight; @@ -1109,3 +1119,20 @@ void CrushWrapper::generate_test_instances(list<CrushWrapper*>& o) o.push_back(new CrushWrapper); // fixme } + + +bool CrushWrapper::is_valid_crush_name(const string& s) +{ + if (s.empty()) + return false; + for (string::const_iterator p = s.begin(); p != s.end(); ++p) { + if (!(*p == '-') && + !(*p == '_') && + !(*p == '.') && + !(*p >= '0' && *p <= '9') && + !(*p >= 'A' && *p <= 'Z') && + !(*p >= 'a' && *p <= 'z')) + return false; + } + return true; +} diff --git a/src/crush/CrushWrapper.h b/src/crush/CrushWrapper.h index f5a88c8bdd5..3d07a281956 100644 --- a/src/crush/CrushWrapper.h +++ b/src/crush/CrushWrapper.h @@ -200,10 +200,13 @@ public: return p->second.c_str(); return 0; } - void set_item_name(int i, const string& name) { + int set_item_name(int i, const string& name) { + if (!is_valid_crush_name(name)) + return -EINVAL; name_map[i] = name; if (have_rmaps) name_rmap[name] = i; + return 0; } // rule names @@ -790,6 +793,9 @@ public: void dump_rules(Formatter *f) const; void list_rules(Formatter *f) const; static void generate_test_instances(list<CrushWrapper*>& o); + + + static bool is_valid_crush_name(const string& s); }; WRITE_CLASS_ENCODER(CrushWrapper) diff --git a/src/mon/MonCommands.h b/src/mon/MonCommands.h index 9236462edd9..90b9c7ee74a 100644 --- a/src/mon/MonCommands.h +++ b/src/mon/MonCommands.h @@ -357,55 +357,55 @@ COMMAND("osd setcrushmap", "set crush map from input file", \ COMMAND("osd crush set", "set crush map from input file", \ "osd", "rw", "cli,rest") COMMAND("osd crush add-bucket " \ - "name=name,type=CephString " \ + "name=name,type=CephString,goodchars=[A-Za-z0-9-_.] " \ "name=type,type=CephString", \ "add no-parent (probably root) crush bucket <name> of type <type>", \ "osd", "rw", "cli,rest") COMMAND("osd crush set " \ "name=id,type=CephOsdName " \ "name=weight,type=CephFloat,range=0.0 " \ - "name=args,type=CephString,n=N", \ + "name=args,type=CephString,n=N,goodchars=[A-Za-z0-9-_.=]", \ "set crushmap entry for <name> to <weight> with location <args>", \ "osd", "rw", "cli,rest") COMMAND("osd crush add " \ "name=id,type=CephOsdName " \ "name=weight,type=CephFloat,range=0.0 " \ - "name=args,type=CephString,n=N", \ + "name=args,type=CephString,n=N,goodchars=[A-Za-z0-9-_.=]", \ "add crushmap entry for <name> with <weight> and location <args>", \ "osd", "rw", "cli,rest") COMMAND("osd crush create-or-move " \ "name=id,type=CephOsdName " \ "name=weight,type=CephFloat,range=0.0 " \ - "name=args,type=CephString,n=N", \ + "name=args,type=CephString,n=N,goodchars=[A-Za-z0-9-_.=]", \ "create entry or move existing entry for <name> <weight> at/to location <args>", \ "osd", "rw", "cli,rest") COMMAND("osd crush move " \ "name=id,type=CephOsdName " \ - "name=args,type=CephString,n=N", \ + "name=args,type=CephString,n=N,goodchars=[A-Za-z0-9-_.=]", \ "move existing entry for <name> to location <args>", \ "osd", "rw", "cli,rest") COMMAND("osd crush link " \ "name=name,type=CephString " \ - "name=args,type=CephString,n=N", \ + "name=args,type=CephString,n=N,goodchars=[A-Za-z0-9-_.=]", \ "link existing entry for <name> under location <args>", \ "osd", "rw", "cli,rest") COMMAND("osd crush rm " \ - "name=name,type=CephString " \ - "name=ancestor,type=CephString,req=false", \ + "name=name,type=CephString,goodchars=[A-Za-z0-9-_.] " \ + "name=ancestor,type=CephString,req=false,goodchars=[A-Za-z0-9-_.]", \ "remove <name> from crush map (everywhere, or just at <ancestor>",\ "osd", "rw", "cli,rest") COMMAND("osd crush remove " \ - "name=name,type=CephString " \ - "name=ancestor,type=CephString,req=false", \ + "name=name,type=CephString,goodchars=[A-Za-z0-9-_.] " \ + "name=ancestor,type=CephString,req=false,goodchars=[A-Za-z0-9-_.]", \ "remove <name> from crush map (everywhere, or just at <ancestor>", \ "osd", "rw", "cli,rest") COMMAND("osd crush unlink " \ - "name=name,type=CephString " \ - "name=ancestor,type=CephString,req=false", \ + "name=name,type=CephString,goodchars=[A-Za-z0-9-_.] " \ + "name=ancestor,type=CephString,req=false,goodchars=[A-Za-z0-9-_.]", \ "unlink <name> from crush map (everywhere, or just at <ancestor>", \ "osd", "rw", "cli,rest") COMMAND("osd crush reweight " \ - "name=name,type=CephString " \ + "name=name,type=CephString,goodchars=[A-Za-z0-9-_.] " \ "name=weight,type=CephFloat,range=0.0", \ "change <name>'s weight to <weight> in crush map", \ "osd", "rw", "cli,rest") @@ -413,12 +413,13 @@ COMMAND("osd crush tunables " \ "name=profile,type=CephChoices,strings=legacy|argonaut|bobtail|optimal|default", \ "set crush tunables values to <profile>", "osd", "rw", "cli,rest") COMMAND("osd crush rule create-simple " \ - "name=name,type=CephString " \ - "name=root,type=CephString " \ - "name=type,type=CephString", \ + "name=name,type=CephString,goodchars=[A-Za-z0-9-_.] " \ + "name=root,type=CephString,goodchars=[A-Za-z0-9-_.] " \ + "name=type,type=CephString,goodchars=[A-Za-z0-9-_.]", "create crush rule <name> in <root> of type <type>", \ "osd", "rw", "cli,rest") COMMAND("osd crush rule rm " \ + "name=name,type=CephString,goodchars=[A-Za-z0-9-_.] " \ "name=name,type=CephString", \ "remove crush rule <name>", "osd", "rw", "cli,rest") COMMAND("osd setmaxosd " \ diff --git a/src/mon/OSDMonitor.cc b/src/mon/OSDMonitor.cc index eb674b7bc4c..0ba211c0fae 100644 --- a/src/mon/OSDMonitor.cc +++ b/src/mon/OSDMonitor.cc @@ -2670,7 +2670,11 @@ bool OSDMonitor::prepare_command(MMonCommand *m) int bucketno = newcrush.add_bucket(0, CRUSH_BUCKET_STRAW, CRUSH_HASH_DEFAULT, type, 0, NULL, NULL); - newcrush.set_item_name(bucketno, name); + err = newcrush.set_item_name(bucketno, name); + if (err < 0) { + ss << "error setting bucket name to '" << name << "'"; + goto reply; + } pending_inc.crush.clear(); newcrush.encode(pending_inc.crush); diff --git a/src/pybind/ceph_argparse.py b/src/pybind/ceph_argparse.py index 15b04a8e06c..72b36dd50a5 100644 --- a/src/pybind/ceph_argparse.py +++ b/src/pybind/ceph_argparse.py @@ -15,6 +15,7 @@ Foundation. See file COPYING. import copy import json import os +import re import socket import stat import sys @@ -175,21 +176,31 @@ class CephFloat(CephArgtype): class CephString(CephArgtype): """ - String; pretty generic. + String; pretty generic. goodchars is a RE char class of valid chars """ - def __init__(self, badchars=''): - self.badchars = badchars + def __init__(self, goodchars=''): + from string import printable + try: + re.compile(goodchars) + except: + raise ValueError('CephString(): "{0}" is not a valid RE'.\ + format(goodchars)) + self.goodchars = goodchars + self.goodset = frozenset( + [c for c in printable if re.match(goodchars, c)] + ) def valid(self, s, partial=False): - for c in self.badchars: - if c in s: - raise ArgumentFormat("bad char {0} in {1}".format(c, s)) + sset = set(s) + if self.goodset and not sset <= self.goodset: + raise ArgumentFormat("invalid chars {0} in {1}".\ + format(''.join(sset - self.goodset), s)) self.val = s def __str__(self): b = '' - if len(self.badchars): - b = '(without chars in {0})'.format(self.badchars) + if self.goodchars: + b += '(goodchars {0})'.format(self.goodchars) return '<string{0}>'.format(b) class CephSocketpath(CephArgtype): @@ -790,7 +801,7 @@ def validate(args, signature, partial=False): # hm, but it was required, so quit if partial: return d - raise ArgumentFormat('{0} not valid argument {1}: {2}'.format(str(myarg), desc, e)) + raise e # valid arg acquired. Store in dict, as a list if multivalued if desc.N: @@ -848,19 +859,19 @@ def validate_command(parsed_args, sigdict, args, verbose=False): sig = cmd['sig'] helptext = cmd['help'] try: - valid_dict = validate(args, sig, verbose) + valid_dict = validate(args, sig) found = cmd break + except ArgumentPrefix: + # ignore prefix mismatches; we just haven't found + # the right command yet + pass except ArgumentError as e: # prefixes matched, but some other arg didn't; - # this is interesting information if verbose - if verbose: - print >> sys.stderr, '{0}: invalid command'.\ - format(' '.join(args)) - print >> sys.stderr, '{0}'.format(e) - print >> sys.stderr, "did you mean {0}?\n\t{1}".\ - format(concise_sig(sig), helptext) - pass + # stop now, because we have the right command but + # some other input is invalid + print >> sys.stderr, "Invalid command: ", str(e) + return {} if found: break |