diff options
author | Dan Mick <dan.mick@inktank.com> | 2013-07-30 20:53:57 -0700 |
---|---|---|
committer | Sage Weil <sage@inktank.com> | 2013-07-30 22:28:36 -0700 |
commit | 47d0d64d5c36c5b1192032438f141f88490fc26c (patch) | |
tree | 503921b60ed1648a05de0251904adb27c292b3af | |
parent | 736d6a1bde71919f7469218684c12793a9532aeb (diff) | |
download | ceph-47d0d64d5c36c5b1192032438f141f88490fc26c.tar.gz |
Make all AdminSocket commands use argparse/cmdmap.
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>
-rw-r--r-- | src/client/Client.cc | 2 | ||||
-rw-r--r-- | src/client/Client.h | 3 | ||||
-rw-r--r-- | src/common/admin_socket.cc | 8 | ||||
-rw-r--r-- | src/common/admin_socket.h | 3 | ||||
-rw-r--r-- | src/common/ceph_context.cc | 58 | ||||
-rw-r--r-- | src/common/ceph_context.h | 3 | ||||
-rw-r--r-- | src/common/cmdparse.h | 3 | ||||
-rw-r--r-- | src/mon/Monitor.cc | 37 | ||||
-rw-r--r-- | src/mon/Monitor.h | 4 | ||||
-rw-r--r-- | src/osd/OSD.cc | 111 | ||||
-rw-r--r-- | src/osd/OSD.h | 2 | ||||
-rw-r--r-- | src/osdc/Objecter.cc | 2 | ||||
-rw-r--r-- | src/osdc/Objecter.h | 2 | ||||
-rw-r--r-- | src/test/admin_socket.cc | 40 |
14 files changed, 159 insertions, 119 deletions
diff --git a/src/client/Client.cc b/src/client/Client.cc index 5a9c5fdafcc..af465cb78bc 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -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; diff --git a/src/client/Client.h b/src/client/Client.h index bc1fbc0401b..1117ff3b0af 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -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; diff --git a/src/common/admin_socket.cc b/src/common/admin_socket.cc index e73f3ce0a0c..1a507e606bf 100644 --- a/src/common/admin_socket.cc +++ b/src/common/admin_socket.cc @@ -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"); diff --git a/src/common/admin_socket.h b/src/common/admin_socket.h index 30c5eb96ab8..3bc84834348 100644 --- a/src/common/admin_socket.h +++ b/src/common/admin_socket.h @@ -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() {}; }; diff --git a/src/common/ceph_context.cc b/src/common/ceph_context.cc index 6b227d8689e..9602fdf2e40 100644 --- a/src/common/ceph_context.cc +++ b/src/common/ceph_context.cc @@ -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"); diff --git a/src/common/ceph_context.h b/src/common/ceph_context.h index 85618e35219..08efeceaa67 100644 --- a/src/common/ceph_context.h +++ b/src/common/ceph_context.h @@ -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); /** diff --git a/src/common/cmdparse.h b/src/common/cmdparse.h index f258969fb68..58c66b46052 100644 --- a/src/common/cmdparse.h +++ b/src/common/cmdparse.h @@ -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)) diff --git a/src/mon/Monitor.cc b/src/mon/Monitor.cc index 2c21e6eac69..118cf6f4a1e 100644 --- a/src/mon/Monitor.cc +++ b/src/mon/Monitor.cc @@ -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; } diff --git a/src/mon/Monitor.h b/src/mon/Monitor.h index 69dfefe144a..cb1f4138a25 100644 --- a/src/mon/Monitor.h +++ b/src/mon/Monitor.h @@ -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: diff --git a/src/osd/OSD.cc b/src/osd/OSD.cc index 89aa1db34eb..69c181862cc 100644 --- a/src/osd/OSD.cc +++ b/src/osd/OSD.cc @@ -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; diff --git a/src/osd/OSD.h b/src/osd/OSD.h index 478f766d145..5196a1dc1f3 100644 --- a/src/osd/OSD.h +++ b/src/osd/OSD.h @@ -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; diff --git a/src/osdc/Objecter.cc b/src/osdc/Objecter.cc index 8ec1374ec4f..b7530200298 100644 --- a/src/osdc/Objecter.cc +++ b/src/osdc/Objecter.cc @@ -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; diff --git a/src/osdc/Objecter.h b/src/osdc/Objecter.h index aa4a20d8b0b..26485bc665f 100644 --- a/src/osdc/Objecter.h +++ b/src/osdc/Objecter.h @@ -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); }; diff --git a/src/test/admin_socket.cc b/src/test/admin_socket.cc index 8f67918e644..6f2a215b565 100644 --- a/src/test/admin_socket.cc +++ b/src/test/admin_socket.cc @@ -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()); } |