]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
admin_socket: register command prefixes
authorSage Weil <sage@inktank.com>
Thu, 31 May 2012 03:08:23 +0000 (20:08 -0700)
committerSage Weil <sage@inktank.com>
Thu, 31 May 2012 03:38:38 +0000 (20:38 -0700)
Allow any command prefix to be registered, provided it is separated by a
space.  Previously, we always matched against the first word.

Signed-off-by: Sage Weil <sage@inktank.com>
src/common/admin_socket.cc
src/common/admin_socket.h
src/test/admin_socket.cc

index 5eaf68d441a8d51e74bdab990115e2dc0c5c35e1..526f41eb94cfead838b292d803aa99bce303a2b0 100644 (file)
@@ -254,7 +254,7 @@ bool AdminSocket::do_accept()
     return false;
   }
 
-  char cmd[80];
+  char cmd[1024];
   int pos = 0;
   string c;
   while (1) {
@@ -305,17 +305,35 @@ bool AdminSocket::do_accept()
     firstword = c.substr(0, c.find(" "));
 
   m_lock.Lock();
-  map<string,AdminSocketHook*>::iterator p = m_hooks.find(firstword);
+  map<string,AdminSocketHook*>::iterator p;
+  string match = c;
+  while (match.size()) {
+    p = m_hooks.find(match);
+    if (p != m_hooks.end())
+      break;
+    
+    // drop right-most word
+    size_t pos = match.rfind(' ');
+    if (pos == std::string::npos) {
+      match.clear();  // we fail
+      break;
+    } else {
+      match.resize(pos);
+    }
+  }
+
   bufferlist out;
-  if (p == m_hooks.end()) {
-    lderr(m_cct) << "AdminSocket: request '" << firstword << "' not defined" << dendl;
+  if (match.size() == 0) {
+    lderr(m_cct) << "AdminSocket: request '" << c << "' not defined" << dendl;
   } else {
     bool success = p->second->call(c, out);
     if (!success) {
-      ldout(m_cct, 0) << "AdminSocket: request '" << c << "' to " << p->second << " failed" << dendl;
+      ldout(m_cct, 0) << "AdminSocket: request '" << c << "' (" << match
+                     << ") to " << p->second << " failed" << dendl;
       out.append("failed");
     } else {
-      ldout(m_cct, 20) << "AdminSocket: request '" << c << "' to " << p->second
+      ldout(m_cct, 20) << "AdminSocket: request '" << c << "' (" << match
+                      << ") to " << p->second
                       << " returned " << out.length() << " bytes" << dendl;
     }
     uint32_t len = htonl(out.length());
index a7ba1f8e25cdf83c420eb348f183a67257fd6864..00828ad2df9267452bebc8b9e33f336c48b86679 100644 (file)
@@ -42,6 +42,15 @@ public:
   /**
    * register an admin socket command
    *
+   * The command is registered under a command string.  Incoming
+   * commands are split by space and matched against the longest
+   * registered command.  For example, if 'foo' and 'foo bar' are
+   * registered, and an incoming command is 'foo bar baz', it is
+   * matched with 'foo bar', while 'foo fud' will match 'foo'.
+   *
+   * The entire incoming command string is passed to the registred
+   * hook.
+   *
    * @param command command string
    * @param hook implementaiton
    * @param help help text.  if empty, command will not be included in 'help' output.
index 68893a392015598dcf6d397a1de71a2caedaa8b9..05a9efa50e934aad6b7d31f75be20b0e314c79b1 100644 (file)
@@ -89,3 +89,38 @@ TEST(AdminSocket, RegisterCommand) {
   ASSERT_EQ("yes", result);
   ASSERT_EQ(true, asoct.shutdown());
 }
+
+class MyTest2 : public AdminSocketHook {
+  bool call(std::string command, bufferlist& result) {
+    result.append("yessir");
+    return true;
+  }
+};
+
+TEST(AdminSocket, RegisterCommandPrefixes) {
+  std::auto_ptr<AdminSocket>
+      asokc(new AdminSocket(g_ceph_context));
+  AdminSocketTest asoct(asokc.get());
+  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", new MyTest(), ""));
+  ASSERT_EQ(0, asoct.m_asokc->register_command("test command", new MyTest2(), ""));
+  string result;
+  ASSERT_EQ("", client.do_request("test", &result));
+  ASSERT_EQ("yes", result);
+  ASSERT_EQ("", client.do_request("test command", &result));
+  ASSERT_EQ("yessir", result);
+  ASSERT_EQ("", client.do_request("test command post", &result));
+  ASSERT_EQ("yessir", result);
+  ASSERT_EQ("", client.do_request("test command  post", &result));
+  ASSERT_EQ("yessir", result);
+  ASSERT_EQ("", client.do_request("test this thing", &result));
+  ASSERT_EQ("yes", result);
+
+  ASSERT_EQ("", client.do_request("test  command post", &result));
+  ASSERT_EQ("yes", result);
+  ASSERT_EQ("", client.do_request("test  this thing", &result));
+  ASSERT_EQ("yes", result);
+  ASSERT_EQ(true, asoct.shutdown());
+}