]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mon: noforward flag for commands that are not supposed to be forwarded
authorMykola Golub <mgolub@mirantis.com>
Wed, 21 Jan 2015 13:47:25 +0000 (15:47 +0200)
committerSage Weil <sage@redhat.com>
Mon, 9 Feb 2015 06:12:55 +0000 (22:12 -0800)
For not a monitor leader, if a received command is not supported
locally, but is supported by the leader, it is forwarded to the
leader.

For some commands that may have undesirable behaviour. E.g. for the
recently added "ceph tell mon.x version", if the mon.x is not a leader
and does not support "version" command yet, but the leader does, the
user will receive the version of the leader, and can't be actually
sure about a non leader version.

Fix this by adding noforward flag to commands that are not supposed to
be forwarded. Set the flag for "version" command. Although there are
other non-forwardable commands (like injectargs) it is not necessary
to add the flag to them, as the commands are too old to suffer from
the describe problem.

Signed-off-by: Mykola Golub <mgolub@mirantis.com>
src/mon/MonCommands.h
src/mon/Monitor.cc
src/mon/Monitor.h

index b671e063fea25c6e1071213a873f5338275a6ae3..2314b2f7a6f50a094987d4081f78be1915b0f895 100644 (file)
  * separating spaces in the quoted string.
  *
  * The monitor marshals this JSON into a std::map<string, cmd_vartype>
-* where cmd_vartype is a boost::variant type-enforcing discriminated
-* type, so the monitor is expected to know the type of each argument.
-* See cmdparse.cc/h for more details.
-*/
+ * where cmd_vartype is a boost::variant type-enforcing discriminated
+ * type, so the monitor is expected to know the type of each argument.
+ * See cmdparse.cc/h for more details.
+ *
+ * The flags parameter for COMMAND_FLAGS macro may be:
+ *
+ *  NONE      - no falgs
+ *  NOFORWARD - command may not be forwarded
+ */
+
+#ifndef COMMAND_FLAGS
+#define COMMAND_FLAGS(flags)
+#endif
 
 /*
  * pg commands PgMonitor.cc
  */
 
 COMMAND("pg stat", "show placement group status.", "pg", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("pg getmap", "get binary pg map to -o/stdout", "pg", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("pg send_pg_creates", "trigger pg creates to be issued",\
        "pg", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("pg dump " \
        "name=dumpcontents,type=CephChoices,strings=all|summary|sum|delta|pools|osds|pgs|pgs_brief,n=N,req=false", \
        "show human-readable versions of pg map (only 'all' valid with plain)", "pg", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("pg dump_json " \
        "name=dumpcontents,type=CephChoices,strings=all|summary|sum|pools|osds|pgs,n=N,req=false", \
        "show human-readable version of pg map in json only",\
        "pg", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("pg dump_pools_json", "show pg pools info in json only",\
        "pg", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("pg dump_stuck " \
        "name=stuckops,type=CephChoices,strings=inactive|unclean|stale|undersized|degraded,n=N,req=false " \
        "name=threshold,type=CephInt,req=false",
        "show information about stuck pgs",\
        "pg", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("pg map name=pgid,type=CephPgid", "show mapping of pg to osds", \
        "pg", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("pg scrub name=pgid,type=CephPgid", "start scrub on <pgid>", \
        "pg", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("pg deep-scrub name=pgid,type=CephPgid", "start deep-scrub on <pgid>", \
        "pg", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("pg repair name=pgid,type=CephPgid", "start repair on <pgid>", \
        "pg", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("pg debug " \
        "name=debugop,type=CephChoices,strings=unfound_objects_exist|degraded_pgs_exist", \
        "show debug info about pgs", "pg", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("pg force_create_pg name=pgid,type=CephPgid", \
        "force creation of pg <pgid>", "pg", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("pg set_full_ratio name=ratio,type=CephFloat,range=0.0|1.0", \
        "set ratio at which pgs are considered full", "pg", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("pg set_nearfull_ratio name=ratio,type=CephFloat,range=0.0|1.0", \
        "set ratio at which pgs are considered nearly full", \
        "pg", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 
 /*
  * auth commands AuthMonitor.cc
@@ -153,114 +177,152 @@ COMMAND("pg set_nearfull_ratio name=ratio,type=CephFloat,range=0.0|1.0", \
 COMMAND("auth export name=entity,type=CephString,req=false", \
                "write keyring for requested entity, or master keyring if none given", \
        "auth", "rx", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("auth get name=entity,type=CephString", \
        "write keyring file with requested key", "auth", "rx", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("auth get-key name=entity,type=CephString", "display requested key", \
        "auth", "rx", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("auth print-key name=entity,type=CephString", "display requested key", \
        "auth", "rx", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("auth print_key name=entity,type=CephString", "display requested key", \
        "auth", "rx", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("auth list", "list authentication state", "auth", "rx", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("auth import", "auth import: read keyring file from -i <file>", \
        "auth", "rwx", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("auth add " \
        "name=entity,type=CephString " \
        "name=caps,type=CephString,n=N,req=false", \
        "add auth info for <entity> from input file, or random key if no " \
         "input is given, and/or any caps specified in the command",
        "auth", "rwx", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("auth get-or-create-key " \
        "name=entity,type=CephString " \
        "name=caps,type=CephString,n=N,req=false", \
        "get, or add, key for <name> from system/caps pairs specified in the command.  If key already exists, any given caps must match the existing caps for that key.", \
        "auth", "rwx", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("auth get-or-create " \
        "name=entity,type=CephString " \
        "name=caps,type=CephString,n=N,req=false", \
        "add auth info for <entity> from input file, or random key if no input given, and/or any caps specified in the command", \
        "auth", "rwx", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("auth caps " \
        "name=entity,type=CephString " \
        "name=caps,type=CephString,n=N", \
        "update caps for <name> from caps specified in the command", \
        "auth", "rwx", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("auth del " \
        "name=entity,type=CephString", \
        "delete all caps for <name>", \
        "auth", "rwx", "cli,rest")
+COMMAND_FLAGS(NONE)
 
 /*
  * Monitor commands (Monitor.cc)
  */
 COMMAND("compact", "cause compaction of monitor's leveldb storage", \
        "mon", "rw", "cli,rest")
+COMMAND_FLAGS(NOFORWARD)
 COMMAND("scrub", "scrub the monitor stores", "mon", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("fsid", "show cluster FSID/UUID", "mon", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("log name=logtext,type=CephString,n=N", \
        "log supplied text to the monitor log", "mon", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("injectargs " \
        "name=injected_args,type=CephString,n=N", \
        "inject config arguments into monitor", "mon", "rw", "cli,rest")
+COMMAND_FLAGS(NOFORWARD)
 COMMAND("status", "show cluster status", "mon", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("health name=detail,type=CephChoices,strings=detail,req=false", \
        "show cluster health", "mon", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("df name=detail,type=CephChoices,strings=detail,req=false", \
        "show cluster free space stats", "mon", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("report name=tags,type=CephString,n=N,req=false", \
        "report full status of cluster, optional title tag strings", \
        "mon", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("quorum_status", "report status of monitor quorum", \
        "mon", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("mon_status", "report status of monitors", "mon", "r", "cli,rest")
+COMMAND_FLAGS(NOFORWARD)
 COMMAND("sync force " \
        "name=validate1,type=CephChoices,strings=--yes-i-really-mean-it,req=false " \
        "name=validate2,type=CephChoices,strings=--i-know-what-i-am-doing,req=false", \
        "force sync of and clear monitor store", "mon", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("heap " \
        "name=heapcmd,type=CephChoices,strings=dump|start_profiler|stop_profiler|release|stats", \
        "show heap usage info (available only if compiled with tcmalloc)", \
        "mon", "rw", "cli,rest")
+COMMAND_FLAGS(NOFORWARD)
 COMMAND("quorum name=quorumcmd,type=CephChoices,strings=enter|exit,n=1", \
        "enter or exit quorum", "mon", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("tell " \
        "name=target,type=CephName " \
        "name=args,type=CephString,n=N", \
        "send a command to a specific daemon", "mon", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("version", "show mon daemon version", "mon", "r", "cli,rest")
+COMMAND_FLAGS(NOFORWARD)
 
 /*
  * MDS commands (MDSMonitor.cc)
  */
 
 COMMAND("mds stat", "show MDS status", "mds", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("mds dump " 
        "name=epoch,type=CephInt,req=false,range=0", \
        "dump info, optionally from epoch", "mds", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("mds getmap " \
        "name=epoch,type=CephInt,req=false,range=0", \
        "get MDS map, optionally from epoch", "mds", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("mds tell " \
        "name=who,type=CephString " \
        "name=args,type=CephString,n=N", \
        "send command to particular mds", "mds", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("mds compat show", "show mds compatibility settings", \
        "mds", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("mds stop name=who,type=CephString", "stop mds", \
        "mds", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("mds deactivate name=who,type=CephString", "stop mds", \
        "mds", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("mds set_max_mds " \
        "name=maxmds,type=CephInt,range=0", \
        "set max MDS index", "mds", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("mds set " \
        "name=var,type=CephChoices,strings=max_mds|max_file_size|allow_new_snaps|inline_data " \
        "name=val,type=CephString "                                     \
        "name=confirm,type=CephString,req=false",                       \
        "set mds parameter <var> to <val>", "mds", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("mds setmap " \
        "name=epoch,type=CephInt,range=0", \
        "set mds map; must supply correct epoch number", "mds", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 // arbitrary limit 0-20 below; worth standing on head to make it
 // relate to actual state definitions?
 // #include "include/ceph_fs.h"
@@ -268,53 +330,68 @@ COMMAND("mds set_state " \
        "name=gid,type=CephInt,range=0 " \
        "name=state,type=CephInt,range=0|20", \
        "set mds state of <gid> to <numeric-state>", "mds", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("mds fail name=who,type=CephString", \
        "force mds to status failed", "mds", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("mds rm " \
        "name=gid,type=CephInt,range=0 " \
        "name=who,type=CephName", \
        "remove nonactive mds", "mds", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("mds rmfailed name=who,type=CephInt,range=0", "remove failed mds", \
        "mds", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("mds cluster_down", "take MDS cluster down", "mds", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("mds cluster_up", "bring MDS cluster up", "mds", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("mds compat rm_compat " \
        "name=feature,type=CephInt,range=0", \
        "remove compatible feature", "mds", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("mds compat rm_incompat " \
        "name=feature,type=CephInt,range=0", \
        "remove incompatible feature", "mds", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("mds add_data_pool " \
        "name=pool,type=CephString", \
        "add data pool <pool>", "mds", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("mds remove_data_pool " \
        "name=pool,type=CephString", \
        "remove data pool <pool>", "mds", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("mds newfs " \
        "name=metadata,type=CephInt,range=0 " \
        "name=data,type=CephInt,range=0 " \
        "name=sure,type=CephChoices,strings=--yes-i-really-mean-it,req=false", \
        "make new filesystem using pools <metadata> and <data>", \
        "mds", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("fs new " \
        "name=fs_name,type=CephString " \
        "name=metadata,type=CephString " \
        "name=data,type=CephString ", \
        "make new filesystem using named pools <metadata> and <data>", \
        "fs", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("fs rm " \
        "name=fs_name,type=CephString " \
        "name=sure,type=CephChoices,strings=--yes-i-really-mean-it,req=false", \
        "disable the named filesystem", \
        "fs", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("fs reset " \
        "name=fs_name,type=CephString " \
        "name=sure,type=CephChoices,strings=--yes-i-really-mean-it,req=false", \
        "disaster recovery only: reset to a single-MDS map", \
        "fs", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("fs ls ", \
        "list filesystems", \
        "fs", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 /*
  * Monmap commands
  */
@@ -322,165 +399,210 @@ COMMAND("mon dump " \
        "name=epoch,type=CephInt,range=0,req=false", \
        "dump formatted monmap (optionally from epoch)", \
        "mon", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("mon stat", "summarize monitor status", "mon", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("mon getmap " \
        "name=epoch,type=CephInt,range=0,req=false", \
        "get monmap", "mon", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("mon add " \
        "name=name,type=CephString " \
        "name=addr,type=CephIPAddr", \
        "add new monitor named <name> at <addr>", "mon", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("mon remove " \
        "name=name,type=CephString", \
        "remove monitor named <name>", "mon", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 
 
 /*
  * OSD commands
  */
 COMMAND("osd stat", "print summary of OSD map", "osd", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd dump " \
        "name=epoch,type=CephInt,range=0,req=false",
        "print summary of OSD map", "osd", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd tree " \
        "name=epoch,type=CephInt,range=0,req=false", \
        "print OSD tree", "osd", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd ls " \
        "name=epoch,type=CephInt,range=0,req=false", \
        "show all OSD ids", "osd", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd getmap " \
        "name=epoch,type=CephInt,range=0,req=false", \
        "get OSD map", "osd", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd getcrushmap " \
        "name=epoch,type=CephInt,range=0,req=false", \
        "get CRUSH map", "osd", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd perf", \
         "print dump of OSD perf summary stats", \
         "osd", \
         "r", \
         "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd blocked-by", \
        "print histogram of which OSDs are blocking their peers", \
        "osd", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd getmaxosd", "show largest OSD id", "osd", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd find " \
        "name=id,type=CephInt,range=0", \
        "find osd <id> in the CRUSH map and show its location", \
        "osd", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd metadata " \
        "name=id,type=CephInt,range=0", \
        "fetch metadata for osd <id>", \
        "osd", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd map " \
        "name=pool,type=CephPoolname " \
        "name=object,type=CephObjectname", \
        "find pg for <object> in <pool>", "osd", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd scrub " \
        "name=who,type=CephString", \
        "initiate scrub on osd <who>", "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd deep-scrub " \
        "name=who,type=CephString", \
        "initiate deep scrub on osd <who>", "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd repair " \
        "name=who,type=CephString", \
        "initiate repair on osd <who>", "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd lspools " \
        "name=auid,type=CephInt,req=false", \
        "list pools", "osd", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd blacklist ls", "show blacklisted clients", "osd", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd crush rule list", "list crush rules", "osd", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd crush rule ls", "list crush rules", "osd", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd crush rule dump " \
        "name=name,type=CephString,goodchars=[A-Za-z0-9-_.],req=false", \
        "dump crush rule <name> (default all)", \
        "osd", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd crush dump", \
        "dump crush map", \
        "osd", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd setcrushmap", "set crush map from input file", \
        "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd crush set", "set crush map from input file", \
        "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd crush add-bucket " \
        "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_FLAGS(NONE)
 COMMAND("osd crush rename-bucket " \
        "name=srcname,type=CephString,goodchars=[A-Za-z0-9-_.] " \
        "name=dstname,type=CephString,goodchars=[A-Za-z0-9-_.]", \
        "rename bucket <srcname> to <dstname>", \
        "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd crush set " \
        "name=id,type=CephOsdName " \
        "name=weight,type=CephFloat,range=0.0 " \
        "name=args,type=CephString,n=N,goodchars=[A-Za-z0-9-_.=]", \
        "update crushmap position and weight for <name> to <weight> with location <args>", \
        "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd crush add " \
        "name=id,type=CephOsdName " \
        "name=weight,type=CephFloat,range=0.0 " \
        "name=args,type=CephString,n=N,goodchars=[A-Za-z0-9-_.=]", \
        "add or update crushmap position and weight for <name> with <weight> and location <args>", \
        "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd crush create-or-move " \
        "name=id,type=CephOsdName " \
        "name=weight,type=CephFloat,range=0.0 " \
        "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_FLAGS(NONE)
 COMMAND("osd crush move " \
        "name=name,type=CephString,goodchars=[A-Za-z0-9-_.] " \
        "name=args,type=CephString,n=N,goodchars=[A-Za-z0-9-_.=]", \
        "move existing entry for <name> to location <args>", \
        "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd crush link " \
        "name=name,type=CephString " \
        "name=args,type=CephString,n=N,goodchars=[A-Za-z0-9-_.=]", \
        "link existing entry for <name> under location <args>", \
        "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd crush rm " \
        "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_FLAGS(NONE)
 COMMAND("osd crush remove " \
        "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_FLAGS(NONE)
 COMMAND("osd crush unlink " \
        "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_FLAGS(NONE)
 COMMAND("osd crush reweight-all",
        "recalculate the weights for the tree to ensure they sum correctly",
        "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd crush reweight " \
        "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")
+COMMAND_FLAGS(NONE)
 COMMAND("osd crush reweight-subtree " \
        "name=name,type=CephString,goodchars=[A-Za-z0-9-_.] " \
        "name=weight,type=CephFloat,range=0.0", \
        "change all leaf items beneath <name> to <weight> in crush map", \
        "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd crush tunables " \
        "name=profile,type=CephChoices,strings=legacy|argonaut|bobtail|firefly|hammer|optimal|default", \
        "set crush tunables values to <profile>", "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd crush set-tunable "                                   \
        "name=tunable,type=CephChoices,strings=straw_calc_version " \
        "name=value,type=CephInt",
        "set crush tunable <tunable> to <value>",
        "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd crush get-tunable "                             \
        "name=tunable,type=CephChoices,strings=straw_calc_version",
        "get crush tunable <tunable>",
        "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd crush show-tunables", \
        "show current crush tunables", "osd", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd crush rule create-simple " \
        "name=name,type=CephString,goodchars=[A-Za-z0-9-_.] " \
        "name=root,type=CephString,goodchars=[A-Za-z0-9-_.] " \
@@ -488,99 +610,126 @@ COMMAND("osd crush rule create-simple " \
        "name=mode,type=CephChoices,strings=firstn|indep,req=false",
        "create crush rule <name> to start from <root>, replicate across buckets of type <type>, using a choose mode of <firstn|indep> (default firstn; indep best for erasure pools)", \
        "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd crush rule create-erasure " \
        "name=name,type=CephString,goodchars=[A-Za-z0-9-_.] " \
        "name=profile,type=CephString,req=false,goodchars=[A-Za-z0-9-_.=]", \
        "create crush rule <name> for erasure coded pool created with <profile> (default default)", \
        "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd crush rule rm " \
        "name=name,type=CephString,goodchars=[A-Za-z0-9-_.] ",  \
        "remove crush rule <name>", "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd setmaxosd " \
        "name=newmax,type=CephInt,range=0", \
        "set new maximum osd value", "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd pause", "pause osd", "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd unpause", "unpause osd", "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd erasure-code-profile set " \
        "name=name,type=CephString,goodchars=[A-Za-z0-9-_.] " \
        "name=profile,type=CephString,n=N,req=false", \
        "create erasure code profile <name> with [<key[=value]> ...] pairs. Add a --force at the end to override an existing profile (VERY DANGEROUS)", \
        "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd erasure-code-profile get " \
        "name=name,type=CephString,goodchars=[A-Za-z0-9-_.]", \
        "get erasure code profile <name>", \
        "osd", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd erasure-code-profile rm " \
        "name=name,type=CephString,goodchars=[A-Za-z0-9-_.]", \
        "remove erasure code profile <name>", \
        "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd erasure-code-profile ls", \
        "list all erasure code profiles", \
        "osd", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd set " \
        "name=key,type=CephChoices,strings=full|pause|noup|nodown|noout|noin|nobackfill|norebalance|norecover|noscrub|nodeep-scrub|notieragent", \
        "set <key>", "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd unset " \
        "name=key,type=CephChoices,strings=full|pause|noup|nodown|noout|noin|nobackfill|norebalance|norecover|noscrub|nodeep-scrub|notieragent", \
        "unset <key>", "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd cluster_snap", "take cluster snapshot (disabled)", \
        "osd", "r", "")
+COMMAND_FLAGS(NONE)
 COMMAND("osd down " \
        "type=CephString,name=ids,n=N", \
        "set osd(s) <id> [<id>...] down", "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd out " \
        "name=ids,type=CephString,n=N", \
        "set osd(s) <id> [<id>...] out", "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd in " \
        "name=ids,type=CephString,n=N", \
        "set osd(s) <id> [<id>...] in", "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd rm " \
        "name=ids,type=CephString,n=N", \
        "remove osd(s) <id> [<id>...] in", "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd reweight " \
        "name=id,type=CephInt,range=0 " \
        "type=CephFloat,name=weight,range=0.0|1.0", \
        "reweight osd to 0.0 < <weight> < 1.0", "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd pg-temp " \
        "name=pgid,type=CephPgid " \
        "name=id,type=CephString,n=N,req=false", \
        "set pg_temp mapping pgid:[<id> [<id>...]] (developers only)", \
         "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd primary-temp " \
        "name=pgid,type=CephPgid " \
        "name=id,type=CephString", \
         "set primary_temp mapping pgid:<id>|-1 (developers only)", \
         "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd primary-affinity " \
        "name=id,type=CephOsdName " \
        "type=CephFloat,name=weight,range=0.0|1.0", \
        "adjust osd primary-affinity from 0.0 <= <weight> <= 1.0", \
        "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd lost " \
        "name=id,type=CephInt,range=0 " \
        "name=sure,type=CephChoices,strings=--yes-i-really-mean-it,req=false", \
        "mark osd as permanently lost. THIS DESTROYS DATA IF NO MORE REPLICAS EXIST, BE CAREFUL", \
        "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd create " \
        "name=uuid,type=CephUUID,req=false", \
        "create new osd (with optional UUID)", "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd blacklist " \
        "name=blacklistop,type=CephChoices,strings=add|rm " \
        "name=addr,type=CephEntityAddr " \
        "name=expire,type=CephFloat,range=0.0,req=false", \
        "add (optionally until <expire> seconds from now) or remove <addr> from blacklist", \
        "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd pool mksnap " \
        "name=pool,type=CephPoolname " \
        "name=snap,type=CephString", \
        "make snapshot <snap> in <pool>", "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd pool rmsnap " \
        "name=pool,type=CephPoolname " \
        "name=snap,type=CephString", \
        "remove snapshot <snap> from <pool>", "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd pool ls " \
        "name=detail,type=CephChoices,strings=detail,req=false", \
        "list pools", "osd", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd pool create " \
        "name=pool,type=CephPoolname " \
        "name=pg_num,type=CephInt,range=0 " \
@@ -590,26 +739,31 @@ COMMAND("osd pool create " \
        "name=ruleset,type=CephString,req=false " \
         "name=expected_num_objects,type=CephInt,req=false", \
        "create pool", "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd pool delete " \
        "name=pool,type=CephPoolname " \
        "name=pool2,type=CephPoolname,req=false " \
        "name=sure,type=CephChoices,strings=--yes-i-really-really-mean-it,req=false", \
        "delete pool", \
        "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd pool rename " \
        "name=srcpool,type=CephPoolname " \
        "name=destpool,type=CephPoolname", \
        "rename <srcpool> to <destpool>", "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd pool get " \
        "name=pool,type=CephPoolname " \
        "name=var,type=CephChoices,strings=size|min_size|crash_replay_interval|pg_num|pgp_num|crush_ruleset|hit_set_type|hit_set_period|hit_set_count|hit_set_fpp|auid|target_max_objects|target_max_bytes|cache_target_dirty_ratio|cache_target_full_ratio|cache_min_flush_age|cache_min_evict_age|erasure_code_profile|min_read_recency_for_promote|write_fadvise_dontneed", \
        "get pool parameter <var>", "osd", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd pool set " \
        "name=pool,type=CephPoolname " \
        "name=var,type=CephChoices,strings=size|min_size|crash_replay_interval|pg_num|pgp_num|crush_ruleset|hashpspool|nodelete|nopgchange|nosizechange|hit_set_type|hit_set_period|hit_set_count|hit_set_fpp|debug_fake_ec_pool|target_max_bytes|target_max_objects|cache_target_dirty_ratio|cache_target_full_ratio|cache_min_flush_age|cache_min_evict_age|auid|min_read_recency_for_promote|write_fadvise_dontneed " \
        "name=val,type=CephString " \
        "name=force,type=CephChoices,strings=--yes-i-really-mean-it,req=false", \
        "set pool parameter <var> to <val>", "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 // 'val' is a CephString because it can include a unit.  Perhaps
 // there should be a Python type for validation/conversion of strings
 // with units.
@@ -618,29 +772,36 @@ COMMAND("osd pool set-quota " \
        "name=field,type=CephChoices,strings=max_objects|max_bytes " \
        "name=val,type=CephString",
        "set object or byte limit on pool", "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd pool get-quota " \
         "name=pool,type=CephPoolname ",
         "obtain object or byte limits for pool",
         "osd", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd pool stats " \
         "name=name,type=CephString,req=false",
         "obtain stats from all pools, or from specified pool",
         "osd", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd reweight-by-utilization " \
        "name=oload,type=CephInt,range=100,req=false", \
        "reweight OSDs by utilization [overload-percentage-for-consideration, default 120]", \
        "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd reweight-by-pg " \
        "name=oload,type=CephInt,range=100 " \
        "name=pools,type=CephPoolname,n=N,req=false", \
        "reweight OSDs by PG distribution [overload-percentage-for-consideration, default 120]", \
        "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd thrash " \
        "name=num_epochs,type=CephInt,range=0", \
        "thrash OSDs for <num_epochs>", "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd df " \
        "name=output_method,type=CephChoices,strings=plain|tree,req=false", \
        "show OSD utilization", "osd", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 
 // tiering
 COMMAND("osd tier add " \
@@ -649,22 +810,27 @@ COMMAND("osd tier add " \
        "name=force_nonempty,type=CephChoices,strings=--force-nonempty,req=false",
        "add the tier <tierpool> (the second one) to base pool <pool> (the first one)", \
        "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd tier remove " \
        "name=pool,type=CephPoolname " \
        "name=tierpool,type=CephPoolname",
        "remove the tier <tierpool> (the second one) from base pool <pool> (the first one)", \
        "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd tier cache-mode " \
        "name=pool,type=CephPoolname " \
        "name=mode,type=CephChoices,strings=none|writeback|forward|readonly|readforward|readproxy", \
        "specify the caching mode for cache tier <pool>", "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd tier set-overlay " \
        "name=pool,type=CephPoolname " \
        "name=overlaypool,type=CephPoolname", \
        "set the overlay pool for base pool <pool> to be <overlaypool>", "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("osd tier remove-overlay " \
        "name=pool,type=CephPoolname ", \
        "remove the overlay pool for base pool <pool>", "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 
 COMMAND("osd tier add-cache " \
        "name=pool,type=CephPoolname " \
@@ -672,6 +838,7 @@ COMMAND("osd tier add-cache " \
        "name=size,type=CephInt,range=0", \
        "add a cache <tierpool> (the second one) of size <size> to existing pool <pool> (the first one)", \
        "osd", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 
 /*
  * mon/ConfigKeyService.cc
@@ -680,14 +847,19 @@ COMMAND("osd tier add-cache " \
 COMMAND("config-key get " \
        "name=key,type=CephString", \
        "get <key>", "config-key", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("config-key put " \
        "name=key,type=CephString " \
        "name=val,type=CephString,req=false", \
        "put <key>, value <val>", "config-key", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("config-key del " \
        "name=key,type=CephString", \
        "delete <key>", "config-key", "rw", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("config-key exists " \
        "name=key,type=CephString", \
        "check for <key>'s existence", "config-key", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
 COMMAND("config-key list ", "list keys", "config-key", "r", "cli,rest")
+COMMAND_FLAGS(NONE)
index 1d6030826b49c66e65b642c82fae3699cb651fef..f9448c7e4bb7b79c511b0c62205ef8e19094b052 100644 (file)
@@ -97,12 +97,18 @@ const string Monitor::MONITOR_STORE_PREFIX = "monitor_store";
 
 
 #undef COMMAND
+#undef COMMAND_FLAGS
 MonCommand mon_commands[] = {
-#define COMMAND(parsesig, helptext, modulename, req_perms, avail) \
-  {parsesig, helptext, modulename, req_perms, avail},
+#define COMMAND(parsesig, helptext, modulename, req_perms, avail)      \
+  {parsesig, helptext, modulename, req_perms, avail,
+#define COMMAND_FLAGS(flag)    \
+  MonCommand::FLAG_##flag},
 #include <mon/MonCommands.h>
 };
+#undef COMMAND
 MonCommand classic_mon_commands[] = {
+#define COMMAND(parsesig, helptext, modulename, req_perms, avail)      \
+  {parsesig, helptext, modulename, req_perms, avail},
 #include <mon/DumplingMonCommands.h>
 };
 
@@ -2588,16 +2594,41 @@ void Monitor::handle_command(MMonCommand *m)
     reply_command(m, -EINVAL, "command not known", 0);
     return;
   }
-  // validate command is in our map & matches, or forward
+  // validate command is in our map & matches, or forward if it is allowed
   const MonCommand *mon_cmd = _get_moncommand(prefix, mon_commands,
                                               ARRAY_SIZE(mon_commands));
-  if (!is_leader() && (!mon_cmd ||
-      (*leader_cmd != *mon_cmd))) {
-    dout(10) << "We don't match leader, forwarding request " << m << dendl;
-    forward_request_leader(m);
+  if (!is_leader()) {
+    if (!mon_cmd) {
+      if (leader_cmd->has_flag(MonCommand::FLAG_NOFORWARD)) {
+       reply_command(m, -EINVAL,
+                     "command not locally supported and not allowed to forward",
+                     0);
+       return;
+      }
+      dout(10) << "Command not locally supported, forwarding request "
+              << m << dendl;
+      forward_request_leader(m);
+      return;
+    } else if (!mon_cmd->is_compat(leader_cmd)) {
+      if (mon_cmd->has_flag(MonCommand::FLAG_NOFORWARD)) {
+       reply_command(m, -EINVAL,
+                     "command not compatible with leader and not allowed to forward",
+                     0);
+       return;
+      }
+      dout(10) << "Command not compatible with leader, forwarding request "
+              << m << dendl;
+      forward_request_leader(m);
+      return;
+    }
+  }
+
+  if (session->proxy_con && mon_cmd->has_flag(MonCommand::FLAG_NOFORWARD)) {
+    dout(10) << "Got forward for noforward command " << m << dendl;
+    reply_command(m, -EINVAL, "forward for noforward command", rdata, 0);
     return;
   }
-  
+
   /* what we perceive as being the service the command falls under */
   string service(mon_cmd->module);
 
index cb5c1af610f3aaf46174bd649587a2b4ee4c417f..3541232b050b09dfbe670793543986eab583a2d1 100644 (file)
@@ -934,6 +934,17 @@ struct MonCommand {
   string module;
   string req_perms;
   string availability;
+  uint64_t flags;
+
+  // MonCommand flags
+  enum {
+    FLAG_NONE      = (0 << 0),
+    FLAG_NOFORWARD = (1 << 0),
+  };
+
+  bool has_flag(uint64_t flag) const { return (flags & flag) != 0; }
+  void set_flag(uint64_t flag) { flags |= flag; }
+  void unset_flag(uint64_t flag) { flags &= ~flag; }
 
   void encode(bufferlist &bl) const {
     /*
@@ -954,30 +965,36 @@ struct MonCommand {
     ::decode(req_perms, bl);
     ::decode(availability, bl);
   }
-  bool operator==(const MonCommand& o) const {
-    return cmdstring == o.cmdstring && helpstring == o.helpstring &&
-       module == o.module && req_perms == o.req_perms &&
-       availability == o.availability;
-  }
-  bool operator!=(const MonCommand& o) const {
-    return !(*this == o);
+  bool is_compat(const MonCommand* o) const {
+    return cmdstring == o->cmdstring && helpstring == o->helpstring &&
+       module == o->module && req_perms == o->req_perms &&
+       availability == o->availability;
   }
 
   static void encode_array(const MonCommand *cmds, int size, bufferlist &bl) {
-    ENCODE_START(1, 1, bl);
+    ENCODE_START(2, 1, bl);
     uint16_t s = size;
     ::encode(s, bl);
     ::encode_array_nohead(cmds, size, bl);
+    for (int i = 0; i < size; i++)
+      ::encode(cmds[i].flags, bl);
     ENCODE_FINISH(bl);
   }
   static void decode_array(MonCommand **cmds, int *size,
                            bufferlist::iterator &bl) {
-    DECODE_START(1, bl);
+    DECODE_START(2, bl);
     uint16_t s = 0;
     ::decode(s, bl);
     *size = s;
     *cmds = new MonCommand[*size];
     ::decode_array_nohead(*cmds, *size, bl);
+    if (struct_v >= 2) {
+      for (int i = 0; i < *size; i++)
+       ::decode((*cmds)[i].flags, bl);
+    } else {
+      for (int i = 0; i < *size; i++)
+       (*cmds)[i].flags = 0;
+    }
     DECODE_FINISH(bl);
   }