Parcourir la source

[1596] Handle pid parameter in auth

Michal 'vorner' Vaner il y a 13 ans
Parent
commit
94ca32cb24

+ 7 - 1
src/bin/auth/auth.spec.pre.in

@@ -97,7 +97,13 @@
       {
         "command_name": "shutdown",
         "command_description": "Shut down authoritative DNS server",
-        "command_args": []
+        "command_args": [
+          {
+            "item_name": "pid",
+            "item_type": "integer",
+            "item_optional": true
+          }
+        ]
       },
       {
         "command_name": "sendstats",

+ 1 - 1
src/bin/auth/auth_srv.h

@@ -343,7 +343,7 @@ public:
     ///
     /// \param type Type of a counter to get the value of
     ///
-    /// \return the value of the counter.
+
     uint64_t getCounter(const AuthCounters::ServerCounterType type) const;
 
     /// \brief Get the value of per Opcode counter in the Auth Counters.

+ 24 - 9
src/bin/auth/command.cc

@@ -12,10 +12,9 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
-#include <string>
-
-#include <boost/scoped_ptr.hpp>
-#include <boost/shared_ptr.hpp>
+#include <auth/command.h>
+#include <auth/auth_log.h>
+#include <auth/auth_srv.h>
 
 #include <exceptions/exceptions.h>
 
@@ -27,9 +26,13 @@
 
 #include <config/ccsession.h>
 
-#include <auth/auth_log.h>
-#include <auth/auth_srv.h>
-#include <auth/command.h>
+#include <string>
+
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+
+#include <sys/types.h>
+#include <unistd.h>
 
 using boost::scoped_ptr;
 using namespace isc::auth;
@@ -104,10 +107,22 @@ public:
     virtual void exec(AuthSrv& server, isc::data::ConstElementPtr args) = 0;
 };
 
-// Handle the "shutdown" command.  No argument is assumed.
+// Handle the "shutdown" command. An optional parameter "pid" is used to
+// see if it is really for our instance.
 class ShutdownCommand : public AuthCommand {
 public:
-    virtual void exec(AuthSrv& server, isc::data::ConstElementPtr) {
+    virtual void exec(AuthSrv& server, isc::data::ConstElementPtr args) {
+        // Is the pid argument provided?
+        if (args && args->getType() ==
+            isc::data::Element::map && args->contains("pid")) {
+            // If it is, we check it is the same as our PID
+            int pid(args->get("pid")->intValue());
+            pid_t my_pid(getpid());
+            if (my_pid != pid) {
+                // It is not for us
+                return;
+            }
+        }
         server.stop();
     }
 };

+ 65 - 16
src/bin/auth/tests/command_unittest.cc

@@ -14,14 +14,9 @@
 
 #include <config.h>
 
-#include <cassert>
-#include <cstdlib>
-#include <string>
-#include <stdexcept>
-
-#include <boost/bind.hpp>
-
-#include <gtest/gtest.h>
+#include <auth/auth_srv.h>
+#include <auth/auth_config.h>
+#include <auth/command.h>
 
 #include <dns/name.h>
 #include <dns/rrclass.h>
@@ -33,14 +28,22 @@
 
 #include <datasrc/memory_datasrc.h>
 
-#include <auth/auth_srv.h>
-#include <auth/auth_config.h>
-#include <auth/command.h>
-
 #include <asiolink/asiolink.h>
 
 #include <testutils/mockups.h>
 
+#include <cassert>
+#include <cstdlib>
+#include <string>
+#include <stdexcept>
+
+#include <boost/bind.hpp>
+
+#include <gtest/gtest.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+
 using namespace std;
 using namespace isc::dns;
 using namespace isc::data;
@@ -50,7 +53,11 @@ using namespace isc::config;
 namespace {
 class AuthCommandTest : public ::testing::Test {
 protected:
-    AuthCommandTest() : server(false, xfrout), rcode(-1) {
+    AuthCommandTest() :
+        server(false, xfrout),
+        rcode(-1),
+        itimer_(server.getIOService())
+    {
         server.setStatisticsSession(&statistics_session);
     }
     void checkAnswer(const int expected_code) {
@@ -61,9 +68,13 @@ protected:
     MockXfroutClient xfrout;
     AuthSrv server;
     ConstElementPtr result;
+    // The shutdown command parameter
+    ConstElementPtr param;
     int rcode;
+    isc::asiolink::IntervalTimer itimer_;
 public:
     void stopServer();          // need to be public for boost::bind
+    void dontStopServer();          // need to be public for boost::bind
 };
 
 TEST_F(AuthCommandTest, unknownCommand) {
@@ -92,14 +103,52 @@ TEST_F(AuthCommandTest, sendStatistics) {
 
 void
 AuthCommandTest::stopServer() {
-    result = execAuthServerCommand(server, "shutdown", ConstElementPtr());
+    result = execAuthServerCommand(server, "shutdown", param);
     parseAnswer(rcode, result);
     assert(rcode == 0); // make sure the test stops when something is wrong
 }
 
 TEST_F(AuthCommandTest, shutdown) {
-    isc::asiolink::IntervalTimer itimer(server.getIOService());
-    itimer.setup(boost::bind(&AuthCommandTest::stopServer, this), 1);
+    // Param defaults to empty/null pointer on creation
+    itimer_.setup(boost::bind(&AuthCommandTest::stopServer, this), 1);
+    server.getIOService().run();
+    EXPECT_EQ(0, rcode);
+}
+
+TEST_F(AuthCommandTest, shutdownCorrectPID) {
+    // Put the pid parameter there
+    pid_t pid(getpid());
+    ElementPtr param(new isc::data::MapElement());
+    param->set("pid", ConstElementPtr(new isc::data::IntElement(pid)));
+    this->param = param;
+    // With the correct PID, it should act exactly the same as in case
+    // of no parameter
+    itimer_.setup(boost::bind(&AuthCommandTest::stopServer, this), 1);
+    server.getIOService().run();
+    EXPECT_EQ(0, rcode);
+}
+
+// This is like stopServer, but the server should not stop after the
+// command, it should be running
+void
+AuthCommandTest::dontStopServer() {
+    result = execAuthServerCommand(server, "shutdown", param);
+    parseAnswer(rcode, result);
+    EXPECT_EQ(0, rcode);
+    rcode = -1;
+    // We run the stopServer now, to really stop the server.
+    // If it had stopped already, it won't be run and the rcode -1 will
+    // be left here.
+    param = ConstElementPtr();
+    itimer_.cancel();
+    itimer_.setup(boost::bind(&AuthCommandTest::stopServer, this), 1);
+}
+
+TEST_F(AuthCommandTest, shutdownIncorrectPID) {
+    // The PID = 0 should be taken by init, so we are not init and the
+    // PID should be different
+    param = Element::fromJSON("{\"pid\": 0}");
+    itimer_.setup(boost::bind(&AuthCommandTest::dontStopServer, this), 1);
     server.getIOService().run();
     EXPECT_EQ(0, rcode);
 }