]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
Make all AdminSocket commands use argparse/cmdmap.
authorDan Mick <dan.mick@inktank.com>
Wed, 31 Jul 2013 03:53:57 +0000 (20:53 -0700)
committerSage Weil <sage@inktank.com>
Wed, 31 Jul 2013 05:28:36 +0000 (22:28 -0700)
Fixes regression in daemon commands with arguments; also resolves
reported bug with existing daemon code for arguments with
embedded spaces.

Fixes: #5503
Fixes: #5800
Signed-off-by: Dan Mick <dan.mick@inktank.com>
Reviewed-by: Sage Weil <sage@inktank.com>
14 files changed:
src/client/Client.cc
src/client/Client.h
src/common/admin_socket.cc
src/common/admin_socket.h
src/common/ceph_context.cc
src/common/ceph_context.h
src/common/cmdparse.h
src/mon/Monitor.cc
src/mon/Monitor.h
src/osd/OSD.cc
src/osd/OSD.h
src/osdc/Objecter.cc
src/osdc/Objecter.h
src/test/admin_socket.cc

index 5a9c5fdafcca2087a7ba8fa2dbe307b4f6e28cab..af465cb78bc2921d19ddf0c755c1801729f89b12 100644 (file)
@@ -102,7 +102,7 @@ Client::CommandHook::CommandHook(Client *client) :
 {
 }
 
-bool Client::CommandHook::call(std::string command, std::string args,
+bool Client::CommandHook::call(std::string command, cmdmap_t& cmdmap,
                               std::string format, bufferlist& out)
 {
   stringstream ss;
index bc1fbc0401b5c1a3a559686904c0c67fd02a57c9..1117ff3b0af40fd9a36d31e37d4e67de0a33a227 100644 (file)
@@ -45,6 +45,7 @@ using namespace __gnu_cxx;
 #include "common/Finisher.h"
 
 #include "common/compiler_extensions.h"
+#include "common/cmdparse.h"
 
 #include "osdc/ObjectCacher.h"
 
@@ -196,7 +197,7 @@ class Client : public Dispatcher {
     Client *m_client;
   public:
     CommandHook(Client *client);
-    bool call(std::string command, std::string args, std::string format,
+    bool call(std::string command, cmdmap_t &cmdmap, std::string format,
              bufferlist& out);
   };
   CommandHook m_command_hook;
index e73f3ce0a0c2a5b8bb26b8a3a0997053dea06c68..1a507e606bfa0c8cd06a35b6e7bc2855de5c151b 100644 (file)
@@ -353,7 +353,7 @@ bool AdminSocket::do_accept()
     string args;
     if (match != c)
       args = c.substr(match.length() + 1);
-    bool success = p->second->call(match, args, format, out);
+    bool success = p->second->call(match, cmdmap, format, out);
     if (!success) {
       ldout(m_cct, 0) << "AdminSocket: request '" << match << "' args '" << args
                      << "' to " << p->second << " failed" << dendl;
@@ -417,7 +417,7 @@ int AdminSocket::unregister_command(std::string command)
 
 class VersionHook : public AdminSocketHook {
 public:
-  virtual bool call(std::string command, std::string args, std::string format,
+  virtual bool call(std::string command, cmdmap_t &cmdmap, std::string format,
                    bufferlist& out) {
     if (command == "0") {
       out.append(CEPH_ADMIN_SOCK_VERSION);
@@ -441,7 +441,7 @@ class HelpHook : public AdminSocketHook {
   AdminSocket *m_as;
 public:
   HelpHook(AdminSocket *as) : m_as(as) {}
-  bool call(string command, string args, string format, bufferlist& out) {
+  bool call(string command, cmdmap_t &cmdmap, string format, bufferlist& out) {
     Formatter *f = new_formatter(format);
     f->open_object_section("help");
     for (map<string,string>::iterator p = m_as->m_help.begin();
@@ -463,7 +463,7 @@ class GetdescsHook : public AdminSocketHook {
   AdminSocket *m_as;
 public:
   GetdescsHook(AdminSocket *as) : m_as(as) {}
-  bool call(string command, string args, string format, bufferlist& out) {
+  bool call(string command, cmdmap_t &cmdmap, string format, bufferlist& out) {
     int cmdnum = 0;
     JSONFormatter jf(false);
     jf.open_object_section("command_descriptions");
index 30c5eb96ab8d65c692ee15f06689ba4201776d03..3bc8483434818e851ef142db87eeee983799c74f 100644 (file)
@@ -21,6 +21,7 @@
 #include <string>
 #include <map>
 #include "include/buffer.h"
+#include "common/cmdparse.h"
 
 class AdminSocket;
 class CephContext;
@@ -29,7 +30,7 @@ class CephContext;
 
 class AdminSocketHook {
 public:
-  virtual bool call(std::string command, std::string args, std::string format,
+  virtual bool call(std::string command, cmdmap_t &cmdmap, std::string format,
                    bufferlist& out) = 0;
   virtual ~AdminSocketHook() {};
 };
index 6b227d8689e31b1e448c5c81022eae825cbc80ed..9602fdf2e40d8b92ebd1f1b3c93694e5796156a7 100644 (file)
@@ -156,18 +156,25 @@ class CephContextHook : public AdminSocketHook {
 public:
   CephContextHook(CephContext *cct) : m_cct(cct) {}
 
-  bool call(std::string command, std::string args, std::string format,
+  bool call(std::string command, cmdmap_t& cmdmap, std::string format,
            bufferlist& out) {
-    m_cct->do_command(command, args, format, &out);
+    m_cct->do_command(command, cmdmap, format, &out);
     return true;
   }
 };
 
-void CephContext::do_command(std::string command, std::string args,
+void CephContext::do_command(std::string command, cmdmap_t& cmdmap,
                             std::string format, bufferlist *out)
 {
   Formatter *f = new_formatter(format);
-  lgeneric_dout(this, 1) << "do_command '" << command << "' '" << args << "'" << dendl;
+  stringstream ss;
+  for (cmdmap_t::iterator it = cmdmap.begin(); it != cmdmap.end(); ++it) {
+    if (it->first != "prefix") {
+      ss << it->first  << ":" << cmd_vartype_stringify(it->second) << " ";
+    }
+  }
+  lgeneric_dout(this, 1) << "do_command '" << command << "' '"
+                        << ss.str() << dendl;
   if (command == "perfcounters_dump" || command == "1" ||
       command == "perf dump") {
     _perf_counters_collection->dump_formatted(f, false);
@@ -182,14 +189,17 @@ void CephContext::do_command(std::string command, std::string args,
       _conf->show_config(f);
     }
     else if (command == "config set") {
-      std::string var = args;
-      size_t pos = var.find(' ');
-      if (pos == string::npos) {
+      std::string var;
+      std::vector<std::string> val;
+
+      if (!(cmd_getval(this, cmdmap, "var", var)) ||
+          !(cmd_getval(this, cmdmap, "val", val))) {
         f->dump_string("error", "syntax error: 'config set <var> <value>'");
       } else {
-        std::string val = var.substr(pos+1);
-        var.resize(pos);
-        int r = _conf->set_val(var.c_str(), val.c_str());
+       // val may be multiple words
+       ostringstream argss;
+       std::copy(val.begin(), val.end(), ostream_iterator<string>(argss, " "));
+        int r = _conf->set_val(var.c_str(), argss.str().c_str());
         if (r < 0) {
           f->dump_stream("error") << "error setting '" << var << "' to '" << val << "': " << cpp_strerror(r);
         } else {
@@ -199,15 +209,20 @@ void CephContext::do_command(std::string command, std::string args,
         }
       }
     } else if (command == "config get") {
-        char buf[4096];
-        memset(buf, 0, sizeof(buf));
-        char *tmp = buf;
-        int r = _conf->get_val(args.c_str(), &tmp, sizeof(buf));
-        if (r < 0) {
-            f->dump_stream("error") << "error getting '" << args << "': " << cpp_strerror(r);
-        } else {
-            f->dump_string(args.c_str(), buf);
-        }
+      std::string var;
+      if (!cmd_getval(this, cmdmap, "var", var)) {
+       f->dump_string("error", "syntax error: 'config get <var>'");
+      } else {
+       char buf[4096];
+       memset(buf, 0, sizeof(buf));
+       char *tmp = buf;
+       int r = _conf->get_val(var.c_str(), &tmp, sizeof(buf));
+       if (r < 0) {
+           f->dump_stream("error") << "error getting '" << var << "': " << cpp_strerror(r);
+       } else {
+           f->dump_string(var.c_str(), buf);
+       }
+      }
     } else if (command == "log flush") {
       _log->flush();
     }
@@ -224,7 +239,8 @@ void CephContext::do_command(std::string command, std::string args,
   }
   f->flush(*out);
   delete f;
-  lgeneric_dout(this, 1) << "do_command '" << command << "' '" << args << "' result is " << out->length() << " bytes" << dendl;
+  lgeneric_dout(this, 1) << "do_command '" << command << "' '" << ss.str()
+                        << "result is " << out->length() << " bytes" << dendl;
 };
 
 
@@ -262,7 +278,7 @@ CephContext::CephContext(uint32_t module_type_)
   _admin_socket->register_command("2", "2", _admin_hook, "");
   _admin_socket->register_command("perf schema", "perf schema", _admin_hook, "dump perfcounters schema");
   _admin_socket->register_command("config show", "config show", _admin_hook, "dump current config settings");
-  _admin_socket->register_command("config set", "config set name=var,type=CephString name=val,type=CephString",  _admin_hook, "config set <field> <val>: set a config variable");
+  _admin_socket->register_command("config set", "config set name=var,type=CephString name=val,type=CephString,n=N",  _admin_hook, "config set <field> <val> [<val> ...]: set a config variable");
   _admin_socket->register_command("config get", "config get name=var,type=CephString", _admin_hook, "config get <field>: get the config value");
   _admin_socket->register_command("log flush", "log flush", _admin_hook, "flush log entries to log file");
   _admin_socket->register_command("log dump", "log dump", _admin_hook, "dump recent log entries to log file");
index 85618e35219340b6f59d8feaf6692302afc1135f..08efeceaa674b4b63eb12c3623899fec42db26f9 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "include/buffer.h"
 #include "include/atomic.h"
+#include "common/cmdparse.h"
 
 class AdminSocket;
 class CephContextServiceThread;
@@ -97,7 +98,7 @@ public:
   /**
    * process an admin socket command
    */
-  void do_command(std::string command, std::string args, std::string foramt,
+  void do_command(std::string command, cmdmap_t& cmdmap, std::string format,
                  bufferlist *out);
 
   /**
index f258969fb687434f1244f7b26bc39510d6b118ab..58c66b46052d133e3a8415e180e48d19a2afddda 100644 (file)
@@ -11,7 +11,8 @@
 #include <stdexcept>
 #include "common/Formatter.h"
 #include "common/BackTrace.h"
-#include "common/ceph_context.h"
+
+class CephContext;
 
 /* this is handy; can't believe it's not standard */
 #define ARRAY_SIZE(a)  (sizeof(a) / sizeof(*a))
index 2c21e6eac69aa58f73574104797c6413b067a30e..118cf6f4a1ee59cbe265665e3a9cb82d50a66e37 100644 (file)
@@ -225,16 +225,16 @@ class AdminHook : public AdminSocketHook {
   Monitor *mon;
 public:
   AdminHook(Monitor *m) : mon(m) {}
-  bool call(std::string command, std::string args, std::string format,
+  bool call(std::string command, cmdmap_t& cmdmap, std::string format,
            bufferlist& out) {
     stringstream ss;
-    mon->do_admin_command(command, args, format, ss);
+    mon->do_admin_command(command, cmdmap, format, ss);
     out.append(ss);
     return true;
   }
 };
 
-void Monitor::do_admin_command(string command, string args, string format,
+void Monitor::do_admin_command(string command, cmdmap_t& cmdmap, string format,
                               ostream& ss)
 {
   Mutex::Locker l(lock);
@@ -246,7 +246,9 @@ void Monitor::do_admin_command(string command, string args, string format,
   else if (command == "quorum_status")
     _quorum_status(f.get(), ss);
   else if (command == "sync_force") {
-    if (args != "--yes-i-really-mean-it") {
+    string validate;
+    if ((!cmd_getval(g_ceph_context, cmdmap, "validate", validate)) ||
+       (validate != "--yes-i-really-mean-it")) {
       ss << "are you SURE? this will mean the monitor store will be erased "
             "the next time the monitor is restarted.  pass "
             "'--yes-i-really-mean-it' if you really do.";
@@ -254,7 +256,7 @@ void Monitor::do_admin_command(string command, string args, string format,
     }
     sync_force(f.get(), ss);
   } else if (command.find("add_bootstrap_peer_hint") == 0)
-    _add_bootstrap_peer_hint(command, args, ss);
+    _add_bootstrap_peer_hint(command, cmdmap, ss);
   else
     assert(0 == "bad AdminSocket command binding");
 }
@@ -485,10 +487,19 @@ int Monitor::preinit()
   r = admin_socket->register_command("quorum_status", "quorum_status",
                                     admin_hook, "show current quorum status");
   assert(r == 0);
+  r = admin_socket->register_command("sync_force",
+                                    "sync_force name=validate,"
+                                    "type=CephChoices,"
+                                    "strings=--yes-i-really-mean-it",
+                                    admin_hook,
+                                    "force sync of and clear monitor store");
+  assert(r == 0);
   r = admin_socket->register_command("add_bootstrap_peer_hint",
-                                    "add_bootstrap_peer_hint name=addr,type=CephIPAddr",
+                                    "add_bootstrap_peer_hint name=addr,"
+                                    "type=CephIPAddr",
                                     admin_hook,
-                                    "add peer address as potential bootstrap peer for cluster bringup");
+                                    "add peer address as potential bootstrap"
+                                    " peer for cluster bringup");
   assert(r == 0);
   lock.Lock();
 
@@ -577,6 +588,7 @@ void Monitor::shutdown()
     AdminSocket* admin_socket = cct->get_admin_socket();
     admin_socket->unregister_command("mon_status");
     admin_socket->unregister_command("quorum_status");
+    admin_socket->unregister_command("sync_force");
     admin_socket->unregister_command("add_bootstrap_peer_hint");
     delete admin_hook;
     admin_hook = NULL;
@@ -684,14 +696,17 @@ void Monitor::bootstrap()
   }
 }
 
-void Monitor::_add_bootstrap_peer_hint(string cmd, string args, ostream& ss)
+void Monitor::_add_bootstrap_peer_hint(string cmd, cmdmap_t& cmdmap, ostream& ss)
 {
-  dout(10) << "_add_bootstrap_peer_hint '" << cmd << "' '" << args << "'" << dendl;
+  string addrstr;
+  cmd_getval(g_ceph_context, cmdmap, "addr", addrstr);
+  dout(10) << "_add_bootstrap_peer_hint '" << cmd << "' '"
+           << addrstr << "'" << dendl;
 
   entity_addr_t addr;
   const char *end = 0;
-  if (!addr.parse(args.c_str(), &end)) {
-    ss << "failed to parse addr '" << args << "'; syntax is 'add_bootstrap_peer_hint ip[:port]'";
+  if (!addr.parse(addrstr.c_str(), &end)) {
+    ss << "failed to parse addr '" << addrstr << "'; syntax is 'add_bootstrap_peer_hint ip[:port]'";
     return;
   }
 
index 69dfefe144a8a7639d5b24236cb938d80bc98f09..cb1f4138a252401647ea10b98a7d0f204c75fd44 100644 (file)
@@ -586,7 +586,7 @@ public:
   bool _allowed_command(MonSession *s, map<std::string, cmd_vartype>& cmd);
   void _mon_status(Formatter *f, ostream& ss);
   void _quorum_status(Formatter *f, ostream& ss);
-  void _add_bootstrap_peer_hint(string cmd, string args, ostream& ss);
+  void _add_bootstrap_peer_hint(string cmd, cmdmap_t& cmdmap, ostream& ss);
   void handle_command(class MMonCommand *m);
   void handle_route(MRoute *m);
 
@@ -750,7 +750,7 @@ public:
   int write_fsid();
   int write_fsid(MonitorDBStore::Transaction &t);
 
-  void do_admin_command(std::string command, std::string args,
+  void do_admin_command(std::string command, cmdmap_t& cmdmap,
                        std::string format, ostream& ss);
 
 private:
index 89aa1db34eb1e0c0aab9af53793c4d5749c50da1..69c181862ccf8d9decdf80517ff53733130bf88d 100644 (file)
@@ -997,16 +997,17 @@ class OSDSocketHook : public AdminSocketHook {
   OSD *osd;
 public:
   OSDSocketHook(OSD *o) : osd(o) {}
-  bool call(std::string command, std::string args, std::string format,
+  bool call(std::string command, cmdmap_t& cmdmap, std::string format,
            bufferlist& out) {
     stringstream ss;
-    bool r = osd->asok_command(command, args, format, ss);
+    bool r = osd->asok_command(command, cmdmap, format, ss);
     out.append(ss);
     return r;
   }
 };
 
-bool OSD::asok_command(string command, string args, string format, ostream& ss)
+bool OSD::asok_command(string command, cmdmap_t& cmdmap, string format,
+                      ostream& ss)
 {
   if (format == "")
     format = "json-pretty";
@@ -1089,15 +1090,15 @@ class TestOpsSocketHook : public AdminSocketHook {
   ObjectStore *store;
 public:
   TestOpsSocketHook(OSDService *s, ObjectStore *st) : service(s), store(st) {}
-  bool call(std::string command, std::string args, std::string format,
+  bool call(std::string command, cmdmap_t& cmdmap, std::string format,
            bufferlist& out) {
     stringstream ss;
-    test_ops(service, store, command, args, ss);
+    test_ops(service, store, command, cmdmap, ss);
     out.append(ss);
     return true;
   }
   void test_ops(OSDService *service, ObjectStore *store, std::string command,
-     std::string args, ostream &ss);
+     cmdmap_t& cmdmap, ostream &ss);
 
 };
 
@@ -1249,10 +1250,12 @@ int OSD::init()
   assert(r == 0);
 
   test_ops_hook = new TestOpsSocketHook(&(this->service), this->store);
+  // Note: pools are CephString instead of CephPoolname because
+  // these commands traditionally support both pool names and numbers
   r = admin_socket->register_command(
    "setomapval",
    "setomapval " \
-   "name=pool,type=CephPoolname " \
+   "name=pool,type=CephString " \
    "name=objname,type=CephObjectname " \
    "name=key,type=CephString "\
    "name=val,type=CephString",
@@ -1262,7 +1265,7 @@ int OSD::init()
   r = admin_socket->register_command(
     "rmomapkey",
     "rmomapkey " \
-    "name=pool,type=CephPoolname " \
+    "name=pool,type=CephString " \
     "name=objname,type=CephObjectname " \
     "name=key,type=CephString",
     test_ops_hook,
@@ -1271,7 +1274,7 @@ int OSD::init()
   r = admin_socket->register_command(
     "setomapheader",
     "setomapheader " \
-    "name=pool,type=CephPoolname " \
+    "name=pool,type=CephString " \
     "name=objname,type=CephObjectname " \
     "name=header,type=CephString",
     test_ops_hook,
@@ -1281,7 +1284,7 @@ int OSD::init()
   r = admin_socket->register_command(
     "getomap",
     "getomap " \
-    "name=pool,type=CephPoolname " \
+    "name=pool,type=CephString " \
     "name=objname,type=CephObjectname",
     test_ops_hook,
     "output entire object map");
@@ -1290,7 +1293,7 @@ int OSD::init()
   r = admin_socket->register_command(
     "truncobj",
     "truncobj " \
-    "name=pool,type=CephPoolname " \
+    "name=pool,type=CephString " \
     "name=objname,type=CephObjectname " \
     "name=len,type=CephInt",
     test_ops_hook,
@@ -1300,7 +1303,7 @@ int OSD::init()
   r = admin_socket->register_command(
     "injectdataerr",
     "injectdataerr " \
-    "name=pool,type=CephPoolname " \
+    "name=pool,type=CephString " \
     "name=objname,type=CephObjectname",
     test_ops_hook,
     "inject data error into omap");
@@ -1309,7 +1312,7 @@ int OSD::init()
   r = admin_socket->register_command(
     "injectmdataerr",
     "injectmdataerr " \
-    "name=pool,type=CephPoolname " \
+    "name=pool,type=CephString " \
     "name=objname,type=CephObjectname",
     test_ops_hook,
     "inject metadata error");
@@ -3111,7 +3114,7 @@ void OSD::check_ops_in_flight()
 //   injectmdataerr [namespace/]<obj-name>
 //   injectdataerr [namespace/]<obj-name>
 void TestOpsSocketHook::test_ops(OSDService *service, ObjectStore *store,
-     std::string command, std::string args, ostream &ss)
+     std::string command, cmdmap_t& cmdmap, ostream &ss)
 {
   //Test support
   //Support changing the omap on a single osd by using the Admin Socket to
@@ -3121,40 +3124,36 @@ void TestOpsSocketHook::test_ops(OSDService *service, ObjectStore *store,
       command == "truncobj" || command == "injectmdataerr" ||
       command == "injectdataerr"
     ) {
-    std::vector<std::string> argv;
     pg_t rawpg, pgid;
     int64_t pool;
     OSDMapRef curmap = service->get_osdmap();
     int r;
 
-    argv.push_back(command);
-    string_to_vec(argv, args);
-    int argc = argv.size();
+    string poolstr;
 
-    if (argc < 3) {
-      ss << "Illegal request";
+    cmd_getval(g_ceph_context, cmdmap, "pool", poolstr);
+    pool = curmap->const_lookup_pg_pool_name(poolstr.c_str());
+    //If we can't find it by name then maybe id specified
+    if (pool < 0 && isdigit(poolstr[0]))
+      pool = atoll(poolstr.c_str());
+    if (pool < 0) {
+      ss << "Invalid pool" << poolstr;
       return;
     }
-    pool = curmap->const_lookup_pg_pool_name(argv[1].c_str());
-    //If we can't find it my name then maybe id specified
-    if (pool < 0 && isdigit(argv[1].c_str()[0]))
-      pool = atoll(argv[1].c_str());
     r = -1;
     string objname, nspace;
-    objname = string(argv[2]);
-    if (pool >= 0) {
-        std::size_t found = argv[2].find_first_of('/');
-        if (found != string::npos) {
-          nspace = argv[2].substr(0, found);
-          objname = argv[2].substr(found+1);
-        }
-        object_locator_t oloc(pool, nspace);
-        r = curmap->object_locator_to_pg(object_t(objname), oloc,  rawpg);
+    cmd_getval(g_ceph_context, cmdmap, "objname", objname);
+    std::size_t found = objname.find_first_of('/');
+    if (found != string::npos) {
+      nspace = objname.substr(0, found);
+      objname = objname.substr(found+1);
     }
+    object_locator_t oloc(pool, nspace);
+    r = curmap->object_locator_to_pg(object_t(objname), oloc,  rawpg);
+
     if (r < 0) {
-        ss << "Invalid pool " << argv[1];
-        return;
+      ss << "Invalid namespace/objname";
+      return;
     }
     pgid = curmap->raw_pg_to_pg(rawpg);
 
@@ -3162,15 +3161,13 @@ void TestOpsSocketHook::test_ops(OSDService *service, ObjectStore *store,
     ObjectStore::Transaction t;
 
     if (command == "setomapval") {
-      if (argc != 5) {
-        ss << "usage: setomapval <pool> [namespace/]<obj-name> <key> <val>";
-        return;
-      }
       map<string, bufferlist> newattrs;
       bufferlist val;
-      string key(argv[3]);
-      val.append(argv[4]);
+      string key, valstr;
+      cmd_getval(g_ceph_context, cmdmap, "key", key);
+      cmd_getval(g_ceph_context, cmdmap, "val", valstr);
+
+      val.append(valstr);
       newattrs[key] = val;
       t.omap_setkeys(coll_t(pgid), obj, newattrs);
       r = store->apply_transaction(t);
@@ -3179,13 +3176,11 @@ void TestOpsSocketHook::test_ops(OSDService *service, ObjectStore *store,
       else
         ss << "ok";
     } else if (command == "rmomapkey") {
-      if (argc != 4) {
-        ss << "usage: rmomapkey <pool> [namespace/]<obj-name> <key>";
-        return;
-      }
+      string key;
       set<string> keys;
+      cmd_getval(g_ceph_context, cmdmap, "key", key);
 
-      keys.insert(string(argv[3]));
+      keys.insert(key);
       t.omap_rmkeys(coll_t(pgid), obj, keys);
       r = store->apply_transaction(t);
       if (r < 0)
@@ -3193,13 +3188,11 @@ void TestOpsSocketHook::test_ops(OSDService *service, ObjectStore *store,
       else
         ss << "ok";
     } else if (command == "setomapheader") {
-      if (argc != 4) {
-        ss << "usage: setomapheader <pool> [namespace/]<obj-name> <header>";
-        return;
-      }
       bufferlist newheader;
+      string headerstr;
 
-      newheader.append(argv[3]);
+      cmd_getval(g_ceph_context, cmdmap, "header", headerstr);
+      newheader.append(headerstr);
       t.omap_setheader(coll_t(pgid), obj, newheader);
       r = store->apply_transaction(t);
       if (r < 0)
@@ -3207,10 +3200,6 @@ void TestOpsSocketHook::test_ops(OSDService *service, ObjectStore *store,
       else
         ss << "ok";
     } else if (command == "getomap") {
-      if (argc != 3) {
-        ss << "usage: getomap <pool> [namespace/]<obj-name>";
-        return;
-      }
       //Debug: Output entire omap
       bufferlist hdrbl;
       map<string, bufferlist> keyvals;
@@ -3225,11 +3214,9 @@ void TestOpsSocketHook::test_ops(OSDService *service, ObjectStore *store,
           ss << "error=" << r;
       }
     } else if (command == "truncobj") {
-      if (argc != 4) {
-       ss << "usage: truncobj <pool> [namespace/]<obj-name> <val>";
-       return;
-      }
-      t.truncate(coll_t(pgid), obj, atoi(argv[3].c_str()));
+      int64_t trunclen;
+      cmd_getval(g_ceph_context, cmdmap, "len", trunclen);
+      t.truncate(coll_t(pgid), obj, trunclen);
       r = store->apply_transaction(t);
       if (r < 0)
        ss << "error=" << r;
index 478f766d1454213fbe2f7e8b49fdbfed253457ec..5196a1dc1f3ca1e23950d008d1fb88cbaa180ceb 100644 (file)
@@ -622,7 +622,7 @@ protected:
   // asok
   friend class OSDSocketHook;
   class OSDSocketHook *asok_hook;
-  bool asok_command(string command, string args, string format, ostream& ss);
+  bool asok_command(string command, cmdmap_t& cmdmap, string format, ostream& ss);
 
 public:
   ClassHandler  *class_handler;
index 8ec1374ec4fe66e95221def0d5eeed533c2aea72..b753020029881c3f82342206bf82460f64c2e185 100644 (file)
@@ -2335,7 +2335,7 @@ Objecter::RequestStateHook::RequestStateHook(Objecter *objecter) :
 {
 }
 
-bool Objecter::RequestStateHook::call(std::string command, std::string args,
+bool Objecter::RequestStateHook::call(std::string command, cmdmap_t& cmdmap,
                                      std::string format, bufferlist& out)
 {
   stringstream ss;
index aa4a20d8b0bec9999c4303b78a894b1ade3360e7..26485bc665fc1006bbba891cc14f853b379e258c 100644 (file)
@@ -726,7 +726,7 @@ class Objecter {
     Objecter *m_objecter;
   public:
     RequestStateHook(Objecter *objecter);
-    bool call(std::string command, std::string args, std::string format,
+    bool call(std::string command, cmdmap_t& cmdmap, std::string format,
              bufferlist& out);
   };
 
index 8f67918e644e41fffcd1d352c441b38f83f45bcb..6f2a215b565dfe9e176c7c85ef4eb5809bfd8e23 100644 (file)
@@ -70,10 +70,19 @@ TEST(AdminSocket, SendNoOp) {
 }
 
 class MyTest : public AdminSocketHook {
-  bool call(std::string command, std::string args, std::string format, bufferlist& result) {
+  bool call(std::string command, cmdmap_t& cmdmap, std::string format, bufferlist& result) {
+    std::vector<std::string> args;
+    cmd_getval(g_ceph_context, cmdmap, "args", args);
     result.append(command);
     result.append("|");
-    result.append(args);
+    string resultstr;
+    for (std::vector<std::string>::iterator it = args.begin();
+        it != args.end(); ++it) {
+      if (it != args.begin())
+       resultstr += ' ';
+      resultstr += *it;
+    }
+    result.append(resultstr);
     return true;
   }
 };
@@ -93,10 +102,19 @@ TEST(AdminSocket, RegisterCommand) {
 }
 
 class MyTest2 : public AdminSocketHook {
-  bool call(std::string command, std::string args, std::string format, bufferlist& result) {
+  bool call(std::string command, cmdmap_t& cmdmap, std::string format, bufferlist& result) {
+    std::vector<std::string> args;
+    cmd_getval(g_ceph_context, cmdmap, "args", args);
     result.append(command);
     result.append("|");
-    result.append(args);
+    string resultstr;
+    for (std::vector<std::string>::iterator it = args.begin();
+        it != args.end(); ++it) {
+      if (it != args.begin())
+       resultstr += ' ';
+      resultstr += *it;
+    }
+    result.append(resultstr);
     return true;
   }
 };
@@ -108,23 +126,23 @@ TEST(AdminSocket, RegisterCommandPrefixes) {
   ASSERT_EQ(true, asoct.shutdown());
   ASSERT_EQ(true, asoct.init(get_rand_socket_path()));
   AdminSocketClient client(get_rand_socket_path());
-  ASSERT_EQ(0, asoct.m_asokc->register_command("test", "test", new MyTest(), ""));
-  ASSERT_EQ(0, asoct.m_asokc->register_command("test command", "test command", new MyTest2(), ""));
+  ASSERT_EQ(0, asoct.m_asokc->register_command("test", "test name=args,type=CephString,n=N", new MyTest(), ""));
+  ASSERT_EQ(0, asoct.m_asokc->register_command("test command", "test command name=args,type=CephString,n=N", new MyTest2(), ""));
   string result;
   ASSERT_EQ("", client.do_request("{\"prefix\":\"test\"}", &result));
   ASSERT_EQ("test|", result);
   ASSERT_EQ("", client.do_request("{\"prefix\":\"test command\"}", &result));
   ASSERT_EQ("test command|", result);
-  ASSERT_EQ("", client.do_request("{\"prefix\":\"test command post\"}", &result));
+  ASSERT_EQ("", client.do_request("{\"prefix\":\"test command\",\"args\":[\"post\"]}", &result));
   ASSERT_EQ("test command|post", result);
-  ASSERT_EQ("", client.do_request("{\"prefix\":\"test command  post\"}", &result));
+  ASSERT_EQ("", client.do_request("{\"prefix\":\"test command\",\"args\":[\" post\"]}", &result));
   ASSERT_EQ("test command| post", result);
-  ASSERT_EQ("", client.do_request("{\"prefix\":\"test this thing\"}", &result));
+  ASSERT_EQ("", client.do_request("{\"prefix\":\"test\",\"args\":[\"this thing\"]}", &result));
   ASSERT_EQ("test|this thing", result);
 
-  ASSERT_EQ("", client.do_request("{\"prefix\":\"test  command post\"}", &result));
+  ASSERT_EQ("", client.do_request("{\"prefix\":\"test\",\"args\":[\" command post\"]}", &result));
   ASSERT_EQ("test| command post", result);
-  ASSERT_EQ("", client.do_request("{\"prefix\":\"test  this thing\"}", &result));
+  ASSERT_EQ("", client.do_request("{\"prefix\":\"test\",\"args\":[\" this thing\"]}", &result));
   ASSERT_EQ("test| this thing", result);
   ASSERT_EQ(true, asoct.shutdown());
 }