Browse Source

[102b] rebased

Francis Dupont 8 years ago
parent
commit
e38e8d974c

+ 31 - 1
doc/guide/ctrl-channel.xml

@@ -113,6 +113,22 @@ will be sent to Kea and the responses received from Kea printed to standard outp
     <section id="commands-common">
       <title>Commands Supported by Both the DHCPv4 and DHCPv6 Servers</title>
 
+      <section id="command-build-report">
+        <title>build-report</title>
+        <para>
+          The <emphasis>build-report</emphasis> command returns
+          on the control channel what the command line
+          <command>-W</command> argument displays, i.e. the embedded
+          content of the <filename>config.report</filename> file.
+          This command does not take any parameters.
+        </para>
+<screen>
+{
+    "command": "build-report"
+}
+</screen>
+      </section> <!-- end of command-build-report -->
+
       <section id="command-config-get">
         <title>config-get</title>
 
@@ -315,7 +331,21 @@ will be sent to Kea and the responses received from Kea printed to standard outp
       </para>
     </section> <!-- end of command-shutdown -->
 
-
+      <section id="command-version-get">
+        <title>version-get</title>
+        <para>
+          The <emphasis>version-get</emphasis> command returns on the control
+          channel what the command line <command>-v</command> argument
+          displays with in arguments the extended version, i.e., what
+          the command line <command>-V</command> argument displays. This command
+          does not take any parameters.
+        </para>
+<screen>
+{
+    "command": "version-get"
+}
+</screen>
+      </section> <!-- end of command-version-get -->
 
     </section> <!-- end of commands supported by both servers -->
 

+ 4 - 2
doc/guide/dhcp4-srv.xml

@@ -195,7 +195,7 @@ opening curly bracket (or brace). Each configuration consists of
 one or more objects. In this specific example, we have only one
 object, called Dhcp4. This is a simplified configuration, as usually
 there will be additional objects, like <command>Logging</command> or
-<command>DhcpDns</command>, but we omit them now for clarity. The Dhcp4
+<command>DhcpDdns</command>, but we omit them now for clarity. The Dhcp4
 configuration starts with the <command>"Dhcp4": {</command> line
 and ends with the corresponding closing brace (in the above example,
 the brace after the last comment).  Everything defined between those
@@ -2475,7 +2475,7 @@ It is merely echoed by the server
      indicates that the server will use the "client identifier" for lease
      lookups and "chaddr" if the first lookup returns no results. The
      <command>false</command> means that the server will only
-     use the "chaddr" to search for client"s lease. Whether the DHCID for
+     use the "chaddr" to search for client's lease. Whether the DHCID for
      DNS updates is generated from the "client identifier" or "chaddr" is
      controlled through the same parameter accordingly.</para>
 
@@ -3723,12 +3723,14 @@ src/lib/dhcpsrv/cfg_host_operations.cc -->
 
       <para>The DHCPv4 server supports the following operational commands:
         <itemizedlist>
+            <listitem>build-report</listitem>
             <listitem>config-get</listitem>
             <listitem>config-write</listitem>
             <listitem>leases-reclaim</listitem>
             <listitem>list-commands</listitem>
             <listitem>set-config</listitem>
             <listitem>shutdown</listitem>
+            <listitem>version-get</listitem>
         </itemizedlist>
          as described in <xref linkend="commands-common"/>.  In addition,
          it supports the following statistics related commands:

+ 4 - 2
doc/guide/dhcp6-srv.xml

@@ -196,7 +196,7 @@ opening curly bracket (or brace). Each configuration consists of
 one or more objects. In this specific example, we have only one
 object, called Dhcp6. This is a simplified configuration, as usually
 there will be additional objects, like <command>Logging</command> or
-<command>DhcpDns</command>, but we omit them now for clarity. The Dhcp6
+<command>DhcpDdns</command>, but we omit them now for clarity. The Dhcp6
 configuration starts with the <command>"Dhcp6": {</command> line
 and ends with the corresponding closing brace (in the above example,
 the brace after the last comment).  Everything defined between those
@@ -2892,7 +2892,7 @@ should include options from the isc option space:
     <userinput>"option-data": [
     {
         "name": "vendor-opts",
-        "data": 4491"
+        "data": 4491
     },
     {
         "name": "tftp-servers",
@@ -4131,12 +4131,14 @@ If not specified, the default value is:
 
       <para>The DHCPv6 server supports the following operational commands:
         <itemizedlist>
+            <listitem>build-report</listitem>
             <listitem>config-get</listitem>
             <listitem>config-write</listitem>
             <listitem>leases-reclaim</listitem>
             <listitem>list-commands</listitem>
             <listitem>set-config</listitem>
             <listitem>shutdown</listitem>
+            <listitem>version-get</listitem>
         </itemizedlist>
          as described in <xref linkend="commands-common"/>.  In addition,
          it supports the following statistics related commands:

+ 20 - 0
src/bin/agent/ca_controller.cc

@@ -8,6 +8,7 @@
 
 #include <agent/ca_controller.h>
 #include <agent/ca_process.h>
+#include <agent/ca_command_mgr.h>
 #include <agent/parser_context.h>
 
 using namespace isc::process;
@@ -47,6 +48,25 @@ CtrlAgentController::parseFile(const std::string& name) {
     return (parser.parseFile(name, ParserContext::PARSER_AGENT));
 }
 
+void
+CtrlAgentController::registerCommands() {
+    CtrlAgentCommandMgr::instance().registerCommand(VERSION_GET_COMMAND,
+        boost::bind(&DControllerBase::versionGetHandler, this, _1, _2));
+
+    CtrlAgentCommandMgr::instance().registerCommand(BUILD_REPORT_COMMAND,
+        boost::bind(&DControllerBase::buildReportHandler, this, _1, _2));
+
+    CtrlAgentCommandMgr::instance().registerCommand(SHUT_DOWN_COMMAND,
+        boost::bind(&DControllerBase::shutdownHandler, this, _1, _2));
+}
+
+void
+CtrlAgentController::deregisterCommands() {
+    CtrlAgentCommandMgr::instance().deregisterCommand(VERSION_GET_COMMAND);
+    CtrlAgentCommandMgr::instance().deregisterCommand(BUILD_REPORT_COMMAND);
+    CtrlAgentCommandMgr::instance().deregisterCommand(SHUT_DOWN_COMMAND);
+}
+
 CtrlAgentController::CtrlAgentController()
     : DControllerBase(agent_app_name_, agent_bin_name_) {
 }

+ 17 - 2
src/bin/agent/ca_controller.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2016-2017 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -47,6 +47,19 @@ public:
     isc::data::ConstElementPtr
     parseFile(const std::string& name);
 
+    /// @brief Register commands.
+    ///
+    /// For all commands in the commands_ set at the exception of
+    /// list-commands register the command with the generic
+    /// @ref isc::process::DControllerBase::executeCommand() handler.
+    void registerCommands();
+
+    /// @brief Deregister commands.
+    ///
+    /// For all commands in the commands_ set at the exception of
+    /// list-commands deregister the command.
+    void deregisterCommands();
+
 private:
 
     /// @brief Creates an instance of the Control Agent application
@@ -64,9 +77,11 @@ private:
     /// @brief Constructor is declared private to maintain the integrity of
     /// the singleton instance.
     CtrlAgentController();
-
 };
 
+// @Defines a shared pointer to CtrlAgentController
+typedef boost::shared_ptr<CtrlAgentController> CtrlAgentControllerPtr;
+
 } // namespace isc::agent
 } // namespace isc
 

+ 19 - 8
src/bin/agent/ca_process.cc

@@ -6,6 +6,7 @@
 
 #include <config.h>
 #include <agent/ca_process.h>
+#include <agent/ca_controller.h>
 #include <agent/ca_response_creator_factory.h>
 #include <agent/ca_log.h>
 #include <asiolink/io_address.h>
@@ -47,13 +48,20 @@ CtrlAgentProcess::run() {
 
     try {
 
+        // Register commands.
+        CtrlAgentControllerPtr controller =
+            boost::dynamic_pointer_cast<CtrlAgentController>(
+                CtrlAgentController::instance());
+        controller->registerCommands();
+
         // Create response creator factory first. It will be used to generate
         // response creators. Each response creator will be used to generate
         // answer to specific request.
         HttpResponseCreatorFactoryPtr rcf(new CtrlAgentResponseCreatorFactory());
 
         DCfgContextBasePtr base_ctx = getCfgMgr()->getContext();
-        CtrlAgentCfgContextPtr ctx = boost::dynamic_pointer_cast<CtrlAgentCfgContext>(base_ctx);
+        CtrlAgentCfgContextPtr ctx =
+            boost::dynamic_pointer_cast<CtrlAgentCfgContext>(base_ctx);
         if (!ctx) {
             isc_throw(Unexpected, "Interal logic error: bad context type");
         }
@@ -99,6 +107,16 @@ CtrlAgentProcess::run() {
                   "Process run method failed: " << ex.what());
     }
 
+    try {
+        // Deregister commands.
+        CtrlAgentControllerPtr controller =
+            boost::dynamic_pointer_cast<CtrlAgentController>(
+                CtrlAgentController::instance());
+        controller->deregisterCommands();
+    } catch (const std::exception&) {
+        // What to do? Simply ignore...
+    }
+
     LOG_DEBUG(agent_logger, DBGLVL_START_SHUT, CTRL_AGENT_RUN_EXIT);
 }
 
@@ -118,13 +136,6 @@ CtrlAgentProcess::configure(isc::data::ConstElementPtr config_set,
     return (answer);
 }
 
-isc::data::ConstElementPtr
-CtrlAgentProcess::command(const std::string& command,
-                          isc::data::ConstElementPtr /*args*/) {
-    return (isc::config::createAnswer(COMMAND_INVALID, "Unrecognized command: "
-                                      + command));
-}
-
 
 CtrlAgentCfgMgrPtr
 CtrlAgentProcess::getCtrlAgentCfgMgr() {

+ 0 - 20
src/bin/agent/ca_process.h

@@ -87,26 +87,6 @@ public:
     configure(isc::data::ConstElementPtr config_set,
               bool check_only = false);
 
-    /// @brief Processes the given command.
-    ///
-    /// This method is called to execute any custom commands supported by the
-    /// process. This method must not throw, it should catch any processing
-    /// errors and return a success or failure answer as described below.
-    ///
-    /// @param command is a string label representing the command to execute.
-    /// @param args is a set of arguments (if any) required for the given
-    /// command.
-    /// @return an Element that contains the results of command composed
-    /// of an integer status value:
-    ///
-    /// - COMMAND_SUCCESS indicates a command was successful.
-    /// - COMMAND_ERROR indicates a valid command failed execute.
-    /// - COMMAND_INVALID indicates a command is not valid.
-    ///
-    /// and a string explanation of the outcome.
-    virtual isc::data::ConstElementPtr
-    command(const std::string& command, isc::data::ConstElementPtr args);
-
     /// @brief Returns a pointer to the configuration manager.
     CtrlAgentCfgMgrPtr getCtrlAgentCfgMgr();
 };

+ 0 - 13
src/bin/d2/d2_process.cc

@@ -362,19 +362,6 @@ D2Process::reconfigureQueueMgr() {
     }
 }
 
-isc::data::ConstElementPtr
-D2Process::command(const std::string& command,
-                   isc::data::ConstElementPtr args) {
-    // @todo This is the initial implementation.  If and when D2 is extended
-    // to support its own commands, this implementation must change. Otherwise
-    // it should reject all commands as it does now.
-    LOG_DEBUG(d2_logger, DBGLVL_TRACE_BASIC, DHCP_DDNS_COMMAND)
-        .arg(command).arg(args ? args->str() : "(no args)");
-
-    return (isc::config::createAnswer(COMMAND_INVALID, "Unrecognized command: "
-                                      + command));
-}
-
 D2Process::~D2Process() {
 };
 

+ 0 - 14
src/bin/d2/d2_process.h

@@ -161,20 +161,6 @@ public:
     configure(isc::data::ConstElementPtr config_set,
               bool check_only = false);
 
-    /// @brief Processes the given command.
-    ///
-    /// This method is called to execute any custom commands supported by the
-    /// process. This method must not throw, it should catch any processing
-    /// errors and return a success or failure answer as described below.
-    ///
-    /// @param command is a string label representing the command to execute.
-    /// @param args is a set of arguments (if any) required for the given
-    /// command. It can be a NULL pointer if no arguments exist for a command.
-    /// @return an Element that contains the results of command composed
-    /// of an integer status value (0 means successful, non-zero means failure),
-    /// and a string explanation of the outcome.
-    virtual isc::data::ConstElementPtr command(const std::string& command,
-                                               isc::data::ConstElementPtr args);
     /// @brief Destructor
     virtual ~D2Process();
 

+ 0 - 29
src/bin/d2/tests/d2_controller_unittests.cc

@@ -199,35 +199,6 @@ TEST_F(D2ControllerTest, configUpdateTests) {
     EXPECT_EQ(1, rcode);
 }
 
-/// @brief Command execution tests.
-/// This really tests just the ability of the handler to invoke the necessary
-/// chain of methods and to handle error conditions.
-/// This test verifies that:
-/// 1. That an unrecognized command is detected and returns a status of
-/// d2::COMMAND_INVALID.
-/// 2. Shutdown command is recognized and returns a d2::COMMAND_SUCCESS status.
-TEST_F(D2ControllerTest, executeCommandTests) {
-    int rcode = -1;
-    isc::data::ConstElementPtr answer;
-    isc::data::ElementPtr arg_set;
-
-    // Initialize the application process.
-    ASSERT_NO_THROW(initProcess());
-    EXPECT_TRUE(checkProcess());
-
-    // Verify that an unknown command returns an COMMAND_INVALID response.
-    std::string bogus_command("bogus");
-    answer = executeCommand(bogus_command, arg_set);
-    isc::config::parseAnswer(rcode, answer);
-    EXPECT_EQ(COMMAND_INVALID, rcode);
-
-    // Verify that shutdown command returns COMMAND_SUCCESS response.
-    //answer = executeCommand(SHUT_DOWN_COMMAND, isc::data::ElementPtr());
-    answer = executeCommand(SHUT_DOWN_COMMAND, arg_set);
-    isc::config::parseAnswer(rcode, answer);
-    EXPECT_EQ(COMMAND_SUCCESS, rcode);
-}
-
 // Tests that the original configuration is retained after a SIGHUP triggered
 // reconfiguration fails due to invalid config content.
 TEST_F(D2ControllerTest, invalidConfigReload) {

+ 0 - 14
src/bin/d2/tests/d2_process_unittests.cc

@@ -394,20 +394,6 @@ TEST_F(D2ProcessTest, badConfigureRecovery) {
     EXPECT_FALSE(getReconfQueueFlag());
 }
 
-/// @brief Verifies basic command method behavior.
-/// @TODO IF the D2Process is extended to support extra commands this testing
-/// will need to augmented accordingly.
-TEST_F(D2ProcessTest, command) {
-    // Verify that the process will process unsupported command and
-    // return a failure response.
-    int rcode = -1;
-    string args = "{ \"arg1\": 77 } ";
-    isc::data::ElementPtr json = isc::data::Element::fromJSON(args);
-    isc::data::ConstElementPtr answer = command("bogus_command", json);
-    parseAnswer(rcode, answer);
-    EXPECT_EQ(COMMAND_INVALID, rcode);
-}
-
 /// @brief Tests shutdown command argument parsing
 /// The shutdown command supports an optional "type" argument. This test
 /// checks that for valid values, the shutdown() method: sets the shutdown

+ 34 - 0
src/bin/dhcp4/ctrl_dhcp4_srv.cc

@@ -15,6 +15,7 @@
 #include <dhcpsrv/cfg_db_access.h>
 #include <config/command_mgr.h>
 #include <stats/stats_mgr.h>
+#include <cfgrpt/config_report.h>
 
 using namespace isc::data;
 using namespace isc::hooks;
@@ -206,6 +207,25 @@ ControlledDhcpv4Srv::commandSetConfigHandler(const string&,
 }
 
 ConstElementPtr
+ControlledDhcpv4Srv::commandVersionGetHandler(const string&, ConstElementPtr) {
+    ElementPtr extended = Element::create(Dhcpv4Srv::getVersion(true));
+    ElementPtr arguments = Element::createMap();
+    arguments->set("extended", extended);
+    ConstElementPtr answer = isc::config::createAnswer(0,
+                                Dhcpv4Srv::getVersion(false),
+                                arguments);
+    return (answer);
+}
+
+ConstElementPtr
+ControlledDhcpv4Srv::commandBuildReportHandler(const string&,
+                                               ConstElementPtr) {
+    ConstElementPtr answer =
+        isc::config::createAnswer(0, isc::detail::getConfigReport());
+    return (answer);
+}
+
+ConstElementPtr
 ControlledDhcpv4Srv::commandLeasesReclaimHandler(const string&,
                                                  ConstElementPtr args) {
     int status_code = 1;
@@ -262,6 +282,12 @@ ControlledDhcpv4Srv::processCommand(const string& command,
         } else if (command == "config-get") {
             return (srv->commandConfigGetHandler(command, args));
 
+        } else if (command == "version-get") {
+            return (srv->commandVersionGetHandler(command, args));
+
+        } else if (command == "build-report") {
+            return (srv->commandBuildReportHandler(command, args));
+
         } else if (command == "leases-reclaim") {
             return (srv->commandLeasesReclaimHandler(command, args));
 
@@ -398,6 +424,9 @@ ControlledDhcpv4Srv::ControlledDhcpv4Srv(uint16_t port /*= DHCP4_SERVER_PORT*/)
 
     // These are the commands always supported by the DHCPv4 server.
     // Please keep the list in alphabetic order.
+    CommandMgr::instance().registerCommand("build-report",
+        boost::bind(&ControlledDhcpv4Srv::commandBuildReportHandler, this, _1, _2));
+
     CommandMgr::instance().registerCommand("config-get",
         boost::bind(&ControlledDhcpv4Srv::commandConfigGetHandler, this, _1, _2));
 
@@ -418,6 +447,9 @@ ControlledDhcpv4Srv::ControlledDhcpv4Srv(uint16_t port /*= DHCP4_SERVER_PORT*/)
     CommandMgr::instance().registerCommand("shutdown",
         boost::bind(&ControlledDhcpv4Srv::commandShutdownHandler, this, _1, _2));
 
+    CommandMgr::instance().registerCommand("version-get",
+        boost::bind(&ControlledDhcpv4Srv::commandVersionGetHandler, this, _1, _2));
+
     // Register statistic related commands
     CommandMgr::instance().registerCommand("statistic-get",
         boost::bind(&StatsMgr::statisticGetHandler, _1, _2));
@@ -457,6 +489,7 @@ ControlledDhcpv4Srv::~ControlledDhcpv4Srv() {
         CommandMgr::instance().closeCommandSocket();
 
         // Deregister any registered commands (please keep in alphabetic order)
+        CommandMgr::instance().deregisterCommand("build-report");
         CommandMgr::instance().deregisterCommand("config-get");
         CommandMgr::instance().deregisterCommand("config-write");
         CommandMgr::instance().deregisterCommand("leases-reclaim");
@@ -469,6 +502,7 @@ ControlledDhcpv4Srv::~ControlledDhcpv4Srv() {
         CommandMgr::instance().deregisterCommand("statistic-remove-all");
         CommandMgr::instance().deregisterCommand("statistic-reset");
         CommandMgr::instance().deregisterCommand("statistic-reset-all");
+        CommandMgr::instance().deregisterCommand("version-get");
 
     } catch (...) {
         // Don't want to throw exceptions from the destructor. The server

+ 25 - 0
src/bin/dhcp4/ctrl_dhcp4_srv.h

@@ -187,6 +187,31 @@ private:
     commandSetConfigHandler(const std::string& command,
                             isc::data::ConstElementPtr args);
 
+    /// @brief handler for processing 'version-get' command
+    ///
+    /// This handler processes version-get command, which returns
+    /// over the control channel the -v and -V command line arguments.
+    /// @param command (parameter ignored)
+    /// @param args (parameter ignored) 
+    ///
+    /// @return status of the command with the version in text and
+    /// the extended version in arguments.
+    isc::data::ConstElementPtr
+    commandVersionGetHandler(const std::string& command,
+                             isc::data::ConstElementPtr args);
+
+    /// @brief handler for processing 'build-report' command
+    ///
+    /// This handler processes build-report command, which returns
+    /// over the control channel the -W command line argument.
+    /// @param command (parameter ignored)
+    /// @param args (parameter ignored) 
+    ///
+    /// @return status of the command with the config report
+    isc::data::ConstElementPtr
+    commandBuildReportHandler(const std::string& command,
+                              isc::data::ConstElementPtr args);
+
     /// @brief Handler for processing 'leases-reclaim' command
     ///
     /// This handler processes leases-reclaim command, which triggers

+ 29 - 0
src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc

@@ -381,12 +381,20 @@ TEST_F(CtrlChannelDhcpv4SrvTest, commandsRegistration) {
     std::string command_list = answer->get("arguments")->str();
 
     EXPECT_TRUE(command_list.find("\"list-commands\"") != string::npos);
+    EXPECT_TRUE(command_list.find("\"build-report\"") != string::npos);
+    EXPECT_TRUE(command_list.find("\"config-get\"") != string::npos);
+    EXPECT_TRUE(command_list.find("\"config-write\"") != string::npos);
+    EXPECT_TRUE(command_list.find("\"leases-reclaim\"") != string::npos);
+    EXPECT_TRUE(command_list.find("\"libreload\"") != string::npos);
+    EXPECT_TRUE(command_list.find("\"set-config\"") != string::npos);
+    EXPECT_TRUE(command_list.find("\"shutdown\"") != string::npos);
     EXPECT_TRUE(command_list.find("\"statistic-get\"") != string::npos);
     EXPECT_TRUE(command_list.find("\"statistic-get-all\"") != string::npos);
     EXPECT_TRUE(command_list.find("\"statistic-remove\"") != string::npos);
     EXPECT_TRUE(command_list.find("\"statistic-remove-all\"") != string::npos);
     EXPECT_TRUE(command_list.find("\"statistic-reset\"") != string::npos);
     EXPECT_TRUE(command_list.find("\"statistic-reset-all\"") != string::npos);
+    EXPECT_TRUE(command_list.find("\"version-get\"") != string::npos);
 
     // Ok, and now delete the server. It should deregister its commands.
     server_.reset();
@@ -482,6 +490,25 @@ TEST_F(CtrlChannelDhcpv4SrvTest, controlLeasesReclaim) {
     EXPECT_TRUE(lease1->stateExpiredReclaimed());
 }
 
+// This test verifies that the DHCP server handles version-get commands
+TEST_F(CtrlChannelDhcpv4SrvTest, getversion) {
+    createUnixChannelServer();
+
+    std::string response;
+
+    // Send the version-get command
+    sendUnixCommand("{ \"command\": \"version-get\" }", response);
+    EXPECT_TRUE(response.find("\"result\": 0") != string::npos);
+    EXPECT_TRUE(response.find("log4cplus") != string::npos);
+    EXPECT_FALSE(response.find("GTEST_VERSION") != string::npos);
+
+    // Send the build-report command
+    sendUnixCommand("{ \"command\": \"build-report\" }", response);
+    EXPECT_TRUE(response.find("\"result\": 0") != string::npos);
+    EXPECT_TRUE(response.find("GTEST_VERSION") != string::npos);
+}
+
+// This test verifies that the DHCP server immediately removed expired
 // This test verifies that the DHCP server immediately removed expired
 // leases on leases-reclaim command with remove = true
 TEST_F(CtrlChannelDhcpv4SrvTest, controlLeasesReclaimRemove) {
@@ -722,6 +749,7 @@ TEST_F(CtrlChannelDhcpv4SrvTest, listCommands) {
     EXPECT_NO_THROW(rsp = Element::fromJSON(response));
 
     // We expect the server to report at least the following commands:
+    checkListCommands(rsp, "build-report");
     checkListCommands(rsp, "config-get");
     checkListCommands(rsp, "config-write");
     checkListCommands(rsp, "list-commands");
@@ -735,6 +763,7 @@ TEST_F(CtrlChannelDhcpv4SrvTest, listCommands) {
     checkListCommands(rsp, "statistic-remove-all");
     checkListCommands(rsp, "statistic-reset");
     checkListCommands(rsp, "statistic-reset-all");
+    checkListCommands(rsp, "version-get");
 }
 
 // Tests if the server returns its configuration using config-get.

+ 34 - 1
src/bin/dhcp6/ctrl_dhcp6_srv.cc

@@ -16,6 +16,7 @@
 #include <dhcp6/json_config_parser.h>
 #include <hooks/hooks_manager.h>
 #include <stats/stats_mgr.h>
+#include <cfgrpt/config_report.h>
 
 using namespace isc::config;
 using namespace isc::data;
@@ -212,6 +213,24 @@ ControlledDhcpv6Srv::commandSetConfigHandler(const string&,
 
 
 ConstElementPtr
+ControlledDhcpv6Srv::commandVersionGetHandler(const string&, ConstElementPtr) {
+    ElementPtr extended = Element::create(Dhcpv6Srv::getVersion(true));
+    ElementPtr arguments = Element::createMap();
+    arguments->set("extended", extended);
+    ConstElementPtr answer = isc::config::createAnswer(0,
+                                Dhcpv6Srv::getVersion(false),
+                                arguments);
+    return (answer);
+}
+
+ConstElementPtr
+ControlledDhcpv6Srv::commandBuildReportHandler(const string&, ConstElementPtr) {
+    ConstElementPtr answer =
+        isc::config::createAnswer(0, isc::detail::getConfigReport());
+    return (answer);
+}
+
+ConstElementPtr
 ControlledDhcpv6Srv::commandLeasesReclaimHandler(const string&,
                                                  ConstElementPtr args) {
     int status_code = 1;
@@ -268,6 +287,12 @@ ControlledDhcpv6Srv::processCommand(const std::string& command,
         } else if (command == "config-get") {
             return (srv->commandConfigGetHandler(command, args));
 
+        } else if (command == "version-get") {
+            return (srv->commandVersionGetHandler(command, args));
+
+        } else if (command == "build-report") {
+            return (srv->commandBuildReportHandler(command, args));
+
         } else if (command == "leases-reclaim") {
             return (srv->commandLeasesReclaimHandler(command, args));
 
@@ -427,6 +452,9 @@ ControlledDhcpv6Srv::ControlledDhcpv6Srv(uint16_t port)
 
     // These are the commands always supported by the DHCPv6 server.
     // Please keep the list in alphabetic order.
+    CommandMgr::instance().registerCommand("build-report",
+        boost::bind(&ControlledDhcpv6Srv::commandBuildReportHandler, this, _1, _2));
+
     CommandMgr::instance().registerCommand("config-get",
         boost::bind(&ControlledDhcpv6Srv::commandConfigGetHandler, this, _1, _2));
 
@@ -447,6 +475,9 @@ ControlledDhcpv6Srv::ControlledDhcpv6Srv(uint16_t port)
     CommandMgr::instance().registerCommand("shutdown",
         boost::bind(&ControlledDhcpv6Srv::commandShutdownHandler, this, _1, _2));
 
+    CommandMgr::instance().registerCommand("version-get",
+        boost::bind(&ControlledDhcpv6Srv::commandVersionGetHandler, this, _1, _2));
+
     // Register statistic related commands
     CommandMgr::instance().registerCommand("statistic-get",
         boost::bind(&StatsMgr::statisticGetHandler, _1, _2));
@@ -485,10 +516,11 @@ ControlledDhcpv6Srv::~ControlledDhcpv6Srv() {
         CommandMgr::instance().closeCommandSocket();
 
         // Deregister any registered commands (please keep in alphabetic order)
+        CommandMgr::instance().deregisterCommand("build-report");
         CommandMgr::instance().deregisterCommand("config-get");
         CommandMgr::instance().deregisterCommand("config-write");
-        CommandMgr::instance().deregisterCommand("libreload");
         CommandMgr::instance().deregisterCommand("leases-reclaim");
+        CommandMgr::instance().deregisterCommand("libreload");
         CommandMgr::instance().deregisterCommand("set-config");
         CommandMgr::instance().deregisterCommand("shutdown");
         CommandMgr::instance().deregisterCommand("statistic-get");
@@ -497,6 +529,7 @@ ControlledDhcpv6Srv::~ControlledDhcpv6Srv() {
         CommandMgr::instance().deregisterCommand("statistic-remove-all");
         CommandMgr::instance().deregisterCommand("statistic-reset");
         CommandMgr::instance().deregisterCommand("statistic-reset-all");
+        CommandMgr::instance().deregisterCommand("version-get");
 
     } catch (...) {
         // Don't want to throw exceptions from the destructor. The server

+ 25 - 0
src/bin/dhcp6/ctrl_dhcp6_srv.h

@@ -187,6 +187,31 @@ private:
     commandSetConfigHandler(const std::string& command,
                             isc::data::ConstElementPtr args);
 
+    /// @brief handler for processing 'version-get' command
+    ///
+    /// This handler processes version-get command, which returns
+    /// over the control channel the -v and -V command line arguments.
+    /// @param command (parameter ignored)
+    /// @param args (parameter ignored) 
+    ///
+    /// @return status of the command with the version in text and
+    /// the extended version in arguments.
+    isc::data::ConstElementPtr
+    commandVersionGetHandler(const std::string& command,
+                             isc::data::ConstElementPtr args);
+
+    /// @brief handler for processing 'build-report' command
+    ///
+    /// This handler processes build-report command, which returns
+    /// over the control channel the -W command line argument.
+    /// @param command (parameter ignored)
+    /// @param args (parameter ignored) 
+    ///
+    /// @return status of the command with the config report
+    isc::data::ConstElementPtr
+    commandBuildReportHandler(const std::string& command,
+                              isc::data::ConstElementPtr args);
+
     /// @brief Handler for processing 'leases-reclaim' command
     ///
     /// This handler processes leases-reclaim command, which triggers

+ 26 - 0
src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc

@@ -602,12 +602,20 @@ TEST_F(CtrlDhcpv6SrvTest, commandsRegistration) {
     std::string command_list = answer->get("arguments")->str();
 
     EXPECT_TRUE(command_list.find("\"list-commands\"") != string::npos);
+    EXPECT_TRUE(command_list.find("\"build-report\"") != string::npos);
+    EXPECT_TRUE(command_list.find("\"config-get\"") != string::npos);
+    EXPECT_TRUE(command_list.find("\"config-write\"") != string::npos);
+    EXPECT_TRUE(command_list.find("\"leases-reclaim\"") != string::npos);
+    EXPECT_TRUE(command_list.find("\"libreload\"") != string::npos);
+    EXPECT_TRUE(command_list.find("\"set-config\"") != string::npos);
+    EXPECT_TRUE(command_list.find("\"shutdown\"") != string::npos);
     EXPECT_TRUE(command_list.find("\"statistic-get\"") != string::npos);
     EXPECT_TRUE(command_list.find("\"statistic-get-all\"") != string::npos);
     EXPECT_TRUE(command_list.find("\"statistic-remove\"") != string::npos);
     EXPECT_TRUE(command_list.find("\"statistic-remove-all\"") != string::npos);
     EXPECT_TRUE(command_list.find("\"statistic-reset\"") != string::npos);
     EXPECT_TRUE(command_list.find("\"statistic-reset-all\"") != string::npos);
+    EXPECT_TRUE(command_list.find("\"version-get\"") != string::npos);
 
     // Ok, and now delete the server. It should deregister its commands.
     srv.reset();
@@ -645,6 +653,24 @@ TEST_F(CtrlChannelDhcpv6SrvTest, controlChannelShutdown) {
     EXPECT_EQ("{ \"result\": 0, \"text\": \"Shutting down.\" }",response);
 }
 
+// This test verifies that the DHCP server handles version-get commands
+TEST_F(CtrlChannelDhcpv6SrvTest, getversion) {
+    createUnixChannelServer();
+
+    std::string response;
+
+    // Send the version-get command
+    sendUnixCommand("{ \"command\": \"version-get\" }", response);
+    EXPECT_TRUE(response.find("\"result\": 0") != string::npos);
+    EXPECT_TRUE(response.find("log4cplus") != string::npos);
+    EXPECT_FALSE(response.find("GTEST_VERSION") != string::npos);
+
+    // Send the build-report command
+    sendUnixCommand("{ \"command\": \"build-report\" }", response);
+    EXPECT_TRUE(response.find("\"result\": 0") != string::npos);
+    EXPECT_TRUE(response.find("GTEST_VERSION") != string::npos);
+}
+
 // This test verifies that the DHCP server immediately reclaims expired
 // leases on leases-reclaim command
 TEST_F(CtrlChannelDhcpv6SrvTest, controlLeasesReclaim) {

+ 1 - 1
src/bin/shell/tests/shell_process_tests.sh.in

@@ -178,6 +178,6 @@ version_test() {
 
 version_test "shell.version"
 shell_command_test "shell.list-commands" "list-commands" \
-    "[ { \"arguments\": [ \"list-commands\" ], \"result\": 0 } ]" ""
+    "[ { \"arguments\": [ \"build-report\", \"list-commands\", \"shutdown\", \"version-get\" ], \"result\": 0 } ]" ""
 shell_command_test "shell.bogus" "give-me-a-beer" \
     "[ { \"result\": 1, \"text\": \"'give-me-a-beer' command not supported.\" } ]" ""

+ 53 - 1
src/lib/cc/command_interpreter.cc

@@ -8,8 +8,9 @@
 
 #include <exceptions/exceptions.h>
 #include <cc/command_interpreter.h>
-#include <string>
 #include <cc/data.h>
+#include <string>
+#include <set>
 
 using namespace std;
 
@@ -171,5 +172,56 @@ parseCommand(ConstElementPtr& arg, ConstElementPtr command) {
     return (cmd->stringValue());
 }
 
+ConstElementPtr
+combineCommandsLists(const ConstElementPtr& response1,
+                     const ConstElementPtr& response2) {
+    // Usually when this method is called there should be two non-null
+    // responses. If there is just a single response, return this
+    // response.
+    if (!response1 && response2) {
+        return (response2);
+
+    } else if (response1 && !response2) {
+        return (response1);
+
+    } else if (!response1 && !response2) {
+        return (ConstElementPtr());
+
+    } else {
+        // Both responses are non-null so we need to combine the lists
+        // of supported commands if the status codes are 0.
+        int status_code;
+        ConstElementPtr args1 = parseAnswer(status_code, response1);
+        if (status_code != 0) {
+            return (response1);
+        }
+
+        ConstElementPtr args2 = parseAnswer(status_code, response2);
+        if (status_code != 0) {
+            return (response2);
+        }
+
+        const std::vector<ElementPtr> vec1 = args1->listValue();
+        const std::vector<ElementPtr> vec2 = args2->listValue();
+
+        // Storing command names in a set guarantees that the non-unique
+        // command names are aggregated.
+        std::set<std::string> combined_set;
+        for (auto v = vec1.cbegin(); v != vec1.cend(); ++v) {
+            combined_set.insert((*v)->stringValue());
+        }
+        for (auto v = vec2.cbegin(); v != vec2.cend(); ++v) {
+            combined_set.insert((*v)->stringValue());
+        }
+
+        // Create a combined list of commands.
+        ElementPtr combined_list = Element::createList();
+        for (auto s = combined_set.cbegin(); s != combined_set.cend(); ++s) {
+            combined_list->add(Element::create(*s));
+        }
+        return (createAnswer(CONTROL_RESULT_SUCCESS, combined_list));
+    }
+}
+
 }
 }

+ 17 - 0
src/lib/cc/command_interpreter.h

@@ -126,6 +126,23 @@ isc::data::ConstElementPtr createCommand(const std::string& command,
 std::string parseCommand(isc::data::ConstElementPtr& arg,
                          isc::data::ConstElementPtr command);
 
+/// @brief Combines lists of commands carried in two responses.
+///
+/// This method is used to combine list of commands returned by the
+/// two command managers.
+///
+/// If the same command appears in two responses only a single
+/// instance is returned in the combined response.
+///
+/// @param response1 First command response.
+/// @param response2 Second command response.
+///
+/// @return Pointer to the 'list-commands' response holding combined
+/// list of commands.
+isc::data::ConstElementPtr
+combineCommandsLists(const isc::data::ConstElementPtr& response1,
+                     const isc::data::ConstElementPtr& response2);
+
 }; // end of namespace isc::config
 }; // end of namespace isc
 

+ 0 - 52
src/lib/config/base_command_mgr.cc

@@ -8,7 +8,6 @@
 #include <config/base_command_mgr.h>
 #include <config/config_log.h>
 #include <boost/bind.hpp>
-#include <set>
 
 using namespace isc::data;
 
@@ -88,57 +87,6 @@ BaseCommandMgr::processCommand(const isc::data::ConstElementPtr& cmd) {
 }
 
 ConstElementPtr
-BaseCommandMgr::combineCommandsLists(const ConstElementPtr& response1,
-                                     const ConstElementPtr& response2) const {
-    // Usually when this method is called there should be two non-null
-    // responses. If there is just a single response, return this
-    // response.
-    if (!response1 && response2) {
-        return (response2);
-
-    } else if (response1 && !response2) {
-        return (response1);
-
-    } else if (!response1 && !response2) {
-        return (ConstElementPtr());
-
-    } else {
-        // Both responses are non-null so we need to combine the lists
-        // of supported commands if the status codes are 0.
-        int status_code;
-        ConstElementPtr args1 = parseAnswer(status_code, response1);
-        if (status_code != 0) {
-            return (response1);
-        }
-
-        ConstElementPtr args2 = parseAnswer(status_code, response2);
-        if (status_code != 0) {
-            return (response2);
-        }
-
-        const std::vector<ElementPtr> vec1 = args1->listValue();
-        const std::vector<ElementPtr> vec2 = args2->listValue();
-
-        // Storing command names in a set guarantees that the non-unique
-        // command names are aggregated.
-        std::set<std::string> combined_set;
-        for (auto v = vec1.cbegin(); v != vec1.cend(); ++v) {
-            combined_set.insert((*v)->stringValue());
-        }
-        for (auto v = vec2.cbegin(); v != vec2.cend(); ++v) {
-            combined_set.insert((*v)->stringValue());
-        }
-
-        // Create a combined list of commands.
-        ElementPtr combined_list = Element::createList();
-        for (auto s = combined_set.cbegin(); s != combined_set.cend(); ++s) {
-            combined_list->add(Element::create(*s));
-        }
-        return (createAnswer(CONTROL_RESULT_SUCCESS, combined_list));
-    }
-}
-
-ConstElementPtr
 BaseCommandMgr::handleCommand(const std::string& cmd_name,
                               const ConstElementPtr& params) {
     auto it = handlers_.find(cmd_name);

+ 0 - 21
src/lib/config/base_command_mgr.h

@@ -118,27 +118,6 @@ public:
 
 protected:
 
-    /// @brief Combines lists of commands carried in two responses.
-    ///
-    /// This method is used to combine list of commands returned by the
-    /// hook library with the commands supported by the local Command
-    /// Manager. This method should also be used within the hook library
-    /// to combine commands supported by this hook library with the
-    /// commands returned by other hook libraries attached to the server
-    /// at the same time.
-    ///
-    /// If the same command appears in two responses only a single
-    /// instance is returned in the combined response.
-    ///
-    /// @param response1 First command response.
-    /// @param response2 Second command response.
-    ///
-    /// @return Pointer to the 'list-commands' response holding combined
-    /// list of commands.
-    isc::data::ConstElementPtr
-    combineCommandsLists(const isc::data::ConstElementPtr& response1,
-                         const isc::data::ConstElementPtr& response2) const;
-
     /// @brief Handles the command having a given name and arguments.
     ///
     /// This method can be overridden in the derived classes to provide

+ 1 - 1
src/lib/log/logger_impl.cc

@@ -82,7 +82,7 @@ LoggerImpl::~LoggerImpl() {
 std::string
 LoggerImpl::getVersion() {
     std::ostringstream ver;
-    ver << "log4plus ";
+    ver << "log4cplus ";
     ver << log4cplus::versionStr;
     return (ver.str());
 }

+ 47 - 59
src/lib/process/d_controller.cc

@@ -29,6 +29,9 @@
 #include <sstream>
 #include <unistd.h>
 
+using namespace isc::data;
+using namespace isc::config;
+
 namespace isc {
 namespace process {
 
@@ -54,9 +57,9 @@ DControllerBase::setController(const DControllerBasePtr& controller) {
     controller_ = controller;
 }
 
-isc::data::ConstElementPtr
+ConstElementPtr
 DControllerBase::parseFile(const std::string&) {
-    isc::data::ConstElementPtr elements;
+    ConstElementPtr elements;
     return (elements);
 }
 
@@ -125,8 +128,7 @@ DControllerBase::launch(int argc, char* argv[], const bool test_mode) {
 
     // Step 3 is to load configuration from file.
     int rcode;
-    isc::data::ConstElementPtr comment
-        = isc::config::parseAnswer(rcode, configFromFile());
+    ConstElementPtr comment = parseAnswer(rcode, configFromFile());
     if (rcode != 0) {
         LOG_FATAL(dctl_logger, DCTL_CONFIG_FILE_LOAD_FAIL)
                   .arg(app_name_).arg(comment->stringValue());
@@ -169,7 +171,7 @@ DControllerBase::checkConfigOnly() {
             // Basic sanity check: file name must not be empty.
             isc_throw(InvalidUsage, "JSON configuration file not specified");
         }
-        isc::data::ConstElementPtr whole_config = parseFile(config_file);
+        ConstElementPtr whole_config = parseFile(config_file);
         if (!whole_config) {
             // No fallback to fromJSONFile
             isc_throw(InvalidUsage, "No configuration found");
@@ -179,7 +181,7 @@ DControllerBase::checkConfigOnly() {
         }
 
         // Check the logic next.
-        isc::data::ConstElementPtr module_config;
+        ConstElementPtr module_config;
         module_config = whole_config->get(getAppName());
         if (!module_config) {
             isc_throw(InvalidUsage, "Config file " << config_file <<
@@ -189,10 +191,9 @@ DControllerBase::checkConfigOnly() {
         // Get an application process object.
         initProcess();
 
-        isc::data::ConstElementPtr answer;
-        answer = checkConfig(module_config);
+        ConstElementPtr answer = checkConfig(module_config);
         int rcode = 0;
-        answer = isc::config::parseAnswer(rcode, answer);
+        answer = parseAnswer(rcode, answer);
         if (rcode != 0) {
             isc_throw(InvalidUsage, "Error encountered: "
                       << answer->stringValue());
@@ -312,15 +313,15 @@ DControllerBase::initProcess() {
     process_->init();
 }
 
-isc::data::ConstElementPtr
+ConstElementPtr
 DControllerBase::configFromFile() {
     // Rollback any previous staging configuration. For D2, only a
     // logger configuration is used here.
     isc::dhcp::CfgMgr::instance().rollback();
     // Will hold configuration.
-    isc::data::ConstElementPtr module_config;
+    ConstElementPtr module_config;
     // Will receive configuration result.
-    isc::data::ConstElementPtr answer;
+    ConstElementPtr answer;
     try {
         std::string config_file = getConfigFile();
         if (config_file.empty()) {
@@ -331,10 +332,10 @@ DControllerBase::configFromFile() {
 
         // If parseFile returns an empty pointer, then pass the file onto the
         // original JSON parser.
-        isc::data::ConstElementPtr whole_config = parseFile(config_file);
+        ConstElementPtr whole_config = parseFile(config_file);
         if (!whole_config) {
             // Read contents of the file and parse it as JSON
-            whole_config = isc::data::Element::fromJSONFile(config_file, true);
+            whole_config = Element::fromJSONFile(config_file, true);
         }
 
         // Let's configure logging before applying the configuration,
@@ -358,7 +359,7 @@ DControllerBase::configFromFile() {
 
         answer = updateConfig(module_config);
         int rcode = 0;
-        isc::config::parseAnswer(rcode, answer);
+        parseAnswer(rcode, answer);
         if (!rcode) {
             // Configuration successful, so apply the logging configuration
             // to log4cplus.
@@ -370,9 +371,8 @@ DControllerBase::configFromFile() {
         // Rollback logging configuration.
         isc::dhcp::CfgMgr::instance().rollback();
         // build an error result
-        isc::data::ConstElementPtr error =
-            isc::config::createAnswer(1,
-                std::string("Configuration parsing failed: ") + ex.what());
+        ConstElementPtr error = createAnswer(COMMAND_ERROR,
+                 std::string("Configuration parsing failed: ") + ex.what());
         return (error);
     }
 
@@ -394,55 +394,45 @@ DControllerBase::runProcess() {
 }
 
 // Instance method for handling new config
-isc::data::ConstElementPtr
-DControllerBase::updateConfig(isc::data::ConstElementPtr new_config) {
+ConstElementPtr
+DControllerBase::updateConfig(ConstElementPtr new_config) {
     return (process_->configure(new_config, false));
 }
 
 // Instance method for checking new config
-isc::data::ConstElementPtr
-DControllerBase::checkConfig(isc::data::ConstElementPtr new_config) {
+ConstElementPtr
+DControllerBase::checkConfig(ConstElementPtr new_config) {
     return (process_->configure(new_config, true));
 }
 
+ConstElementPtr
+DControllerBase::versionGetHandler(const std::string&, ConstElementPtr args) {
+    ConstElementPtr answer;
 
-// Instance method for executing commands
-isc::data::ConstElementPtr
-DControllerBase::executeCommand(const std::string& command,
-                            isc::data::ConstElementPtr args) {
-    // Shutdown is universal.  If its not that, then try it as
-    // a custom command supported by the derivation.  If that
-    // doesn't pan out either, than send to it the application
-    // as it may be supported there.
-    isc::data::ConstElementPtr answer;
-    if (command.compare(SHUT_DOWN_COMMAND) == 0) {
-        answer = shutdownProcess(args);
-    } else {
-        // It wasn't shutdown, so it may be a custom controller command.
-        int rcode = 0;
-        answer = customControllerCommand(command, args);
-        isc::config::parseAnswer(rcode, answer);
-        if (rcode == COMMAND_INVALID)
-        {
-            // It wasn't a controller command, so it may be an application command.
-            answer = process_->command(command, args);
-        }
-    }
-
+    // For version-get put the extended version in arguments
+    ElementPtr extended = Element::create(getVersion(true));
+    ElementPtr arguments = Element::createMap();
+    arguments->set("extended", extended);
+    answer = createAnswer(COMMAND_SUCCESS, getVersion(false), arguments);
     return (answer);
 }
 
-isc::data::ConstElementPtr
-DControllerBase::customControllerCommand(const std::string& command,
-                                     isc::data::ConstElementPtr /* args */) {
+ConstElementPtr
+DControllerBase::buildReportHandler(const std::string&, ConstElementPtr args) {
+    return (createAnswer(COMMAND_SUCCESS, isc::detail::getConfigReport()));
+}
 
-    // Default implementation always returns invalid command.
-    return (isc::config::createAnswer(COMMAND_INVALID,
-                                      "Unrecognized command: " + command));
+ConstElementPtr
+DControllerBase::shutdownHandler(const std::string&, ConstElementPtr args) {
+    // Shutdown is universal.  If its not that, then try it as
+    // a custom command supported by the derivation.  If that
+    // doesn't pan out either, than send to it the application
+    // as it may be supported there.
+    return (shutdownProcess(args));
 }
 
-isc::data::ConstElementPtr
-DControllerBase::shutdownProcess(isc::data::ConstElementPtr args) {
+ConstElementPtr
+DControllerBase::shutdownProcess(ConstElementPtr args) {
     if (process_) {
         return (process_->shutdown(args));
     }
@@ -450,7 +440,7 @@ DControllerBase::shutdownProcess(isc::data::ConstElementPtr args) {
     // Not really a failure, but this condition is worth noting. In reality
     // it should be pretty hard to cause this.
     LOG_WARN(dctl_logger, DCTL_NOT_RUNNING).arg(app_name_);
-    return (isc::config::createAnswer(0, "Process has not been initialized."));
+    return (createAnswer(COMMAND_SUCCESS, "Process has not been initialized"));
 }
 
 void
@@ -498,9 +488,7 @@ DControllerBase::processSignal(int signum) {
             LOG_INFO(dctl_logger, DCTL_CFG_FILE_RELOAD_SIGNAL_RECVD)
                      .arg(signum).arg(getConfigFile());
             int rcode;
-            isc::data::ConstElementPtr comment = isc::config::
-                                                 parseAnswer(rcode,
-                                                             configFromFile());
+            ConstElementPtr comment = parseAnswer(rcode, configFromFile());
             if (rcode != 0) {
                 LOG_ERROR(dctl_logger, DCTL_CFG_FILE_RELOAD_ERROR)
                           .arg(comment->stringValue());
@@ -514,8 +502,8 @@ DControllerBase::processSignal(int signum) {
         {
             LOG_DEBUG(dctl_logger, DBGLVL_START_SHUT,
                       DCTL_SHUTDOWN_SIGNAL_RECVD).arg(signum);
-            isc::data::ElementPtr arg_set;
-            executeCommand(SHUT_DOWN_COMMAND, arg_set);
+            ElementPtr arg_set;
+            shutdownHandler(SHUT_DOWN_COMMAND, arg_set);
             break;
         }
 

+ 37 - 53
src/lib/process/d_controller.h

@@ -19,6 +19,8 @@
 #include <boost/shared_ptr.hpp>
 #include <boost/noncopyable.hpp>
 
+#include <string>
+#include <set>
 
 namespace isc {
 namespace process {
@@ -216,39 +218,6 @@ public:
     /// non-zero means failure), and a string explanation of the outcome.
     virtual isc::data::ConstElementPtr configFromFile();
 
-    /// @brief Instance method invoked by the command event handler and  which
-    /// processes the actual command directive.
-    ///
-    /// It supports the execution of:
-    ///
-    ///   1. Stock controller commands - commands common to all DControllerBase
-    /// derivations.  Currently there is only one, the shutdown command.
-    ///
-    ///   2. Custom controller commands - commands that the deriving controller
-    /// class implements.  These commands are executed by the deriving
-    /// controller.
-    ///
-    ///   3. Custom application commands - commands supported by the application
-    /// process implementation.  These commands are executed by the application
-    /// process.
-    ///
-    /// @param command is a string label representing the command to execute.
-    /// @param args is a set of arguments (if any) required for the given
-    /// command.
-    ///
-    /// @return an Element that contains the results of command composed
-    /// of an integer status value and a string explanation of the outcome.
-    /// The status value is one of the following:
-    ///   COMMAND_SUCCESS - Command executed successfully
-    ///   COMMAND_ERROR - Command is valid but suffered an operational
-    ///   failure.
-    ///   COMMAND_INVALID - Command is not recognized as valid be either
-    ///   the controller or the application process.
-    virtual isc::data::ConstElementPtr executeCommand(const std::string&
-                                                      command,
-                                                      isc::data::
-                                                      ConstElementPtr args);
-
     /// @brief Fetches the name of the application under control.
     ///
     /// @return returns the controller service name string
@@ -263,6 +232,41 @@ public:
         return (bin_name_);
     }
 
+    /// @brief handler for version-get command
+    ///
+    /// This method handles the version-get command. It returns the basic and
+    /// extended version.
+    ///
+    /// @param command (ignored)
+    /// @param args (ignored)
+    /// @return answer with version details.
+    isc::data::ConstElementPtr
+    versionGetHandler(const std::string& command,
+                      isc::data::ConstElementPtr args);
+
+    /// @brief handler for 'build-report' command
+    ///
+    /// This method handles build-report command. It returns the output printed
+    /// by configure script which contains most compilation parameters.
+    ///
+    /// @param command (ignored)
+    /// @param args (ignored)
+    /// @return answer with build report
+    isc::data::ConstElementPtr
+    buildReportHandler(const std::string& command,
+                       isc::data::ConstElementPtr args);
+
+    /// @brief handler for 'shutdown' command
+    ///
+    /// This method handles shutdown command. It initiates the shutdown procedure
+    /// using CPL methods.
+    /// @param command (ignored)
+    /// @param args (ignored)
+    /// @return answer confirming that the shutdown procedure is started
+    isc::data::ConstElementPtr
+    shutdownHandler(const std::string& command,
+                    isc::data::ConstElementPtr args);
+
 protected:
     /// @brief Virtual method that provides derivations the opportunity to
     /// support additional command line options.  It is invoked during command
@@ -287,26 +291,6 @@ protected:
     /// Note this value is subsequently wrapped in a smart pointer.
     virtual DProcessBase* createProcess() = 0;
 
-    /// @brief Virtual method that provides derivations the opportunity to
-    /// support custom external commands executed by the controller.  This
-    /// method is invoked by the processCommand if the received command is
-    /// not a stock controller command.
-    ///
-    /// @param command is a string label representing the command to execute.
-    /// @param args is a set of arguments (if any) required for the given
-    /// command.
-    ///
-    /// @return an Element that contains the results of command composed
-    /// of an integer status value and a string explanation of the outcome.
-    /// The status value is one of the following:
-    ///   COMMAND_SUCCESS - Command executed successfully
-    ///   COMMAND_ERROR - Command is valid but suffered an operational
-    ///   failure.
-    ///   COMMAND_INVALID - Command is not recognized as a valid custom
-    ///   controller command.
-    virtual isc::data::ConstElementPtr customControllerCommand(
-            const std::string& command, isc::data::ConstElementPtr args);
-
     /// @brief Virtual method which can be used to contribute derivation
     /// specific usage text.  It is invoked by the usage() method under
     /// invalid usage conditions.

+ 6 - 20
src/lib/process/d_process.h

@@ -25,6 +25,12 @@ public:
         isc::Exception(file, line, what) { };
 };
 
+/// @brief String value for the version-get command.
+static const std::string VERSION_GET_COMMAND("version-get");
+
+/// @brief String value for the build-report command.
+static const std::string BUILD_REPORT_COMMAND("build-report");
+
 /// @brief String value for the shutdown command.
 static const std::string SHUT_DOWN_COMMAND("shutdown");
 
@@ -121,26 +127,6 @@ public:
     configure(isc::data::ConstElementPtr config_set,
               bool check_only = false) = 0;
 
-    /// @brief Processes the given command.
-    ///
-    /// This method is called to execute any custom commands supported by the
-    /// process. This method must not throw, it should catch any processing
-    /// errors and return a success or failure answer as described below.
-    ///
-    /// @param command is a string label representing the command to execute.
-    /// @param args is a set of arguments (if any) required for the given
-    /// command.
-    /// @return an Element that contains the results of command composed
-    /// of an integer status value: 
-    ///
-    /// - COMMAND_SUCCESS indicates a command was successful.
-    /// - COMMAND_ERROR indicates a valid command failed execute.
-    /// - COMMAND_INVALID indicates a command is not valid.
-    ///
-    /// and a string explanation of the outcome.
-    virtual isc::data::ConstElementPtr command(
-            const std::string& command, isc::data::ConstElementPtr args) = 0;
-
     /// @brief Destructor
     virtual ~DProcessBase(){};
 

+ 0 - 64
src/lib/process/tests/d_controller_unittests.cc

@@ -290,70 +290,6 @@ TEST_F(DStubControllerTest, configUpdateTests) {
     EXPECT_EQ(1, rcode);
 }
 
-/// @brief Command execution tests.
-/// This really tests just the ability of the handler to invoke the necessary
-/// chain of methods and to handle error conditions.
-/// This test verifies that:
-/// 1. That an unrecognized command is detected and returns a status of
-/// process::COMMAND_INVALID.
-/// 2. Shutdown command is recognized and returns a process::COMMAND_SUCCESS
-/// status.
-/// 3. A valid, custom controller command is recognized a
-/// process::COMMAND_SUCCESS
-/// status.
-/// 4. A valid, custom process command is recognized a
-/// process::COMMAND_SUCCESS status.
-/// 5. That a valid controller command that fails returns a
-/// process::COMMAND_ERROR.
-/// 6. That a valid process command that fails returns a process::COMMAND_ERROR.
-TEST_F(DStubControllerTest, executeCommandTests) {
-    int rcode = -1;
-    isc::data::ConstElementPtr answer;
-    isc::data::ElementPtr arg_set;
-
-    // Initialize the application process.
-    ASSERT_NO_THROW(initProcess());
-    EXPECT_TRUE(checkProcess());
-
-    // Verify that an unknown command returns an process::COMMAND_INVALID
-    // response.
-    std::string bogus_command("bogus");
-    answer = executeCommand(bogus_command, arg_set);
-    isc::config::parseAnswer(rcode, answer);
-    EXPECT_EQ(COMMAND_INVALID, rcode);
-
-    // Verify that shutdown command returns process::COMMAND_SUCCESS response.
-    answer = executeCommand(SHUT_DOWN_COMMAND, arg_set);
-    isc::config::parseAnswer(rcode, answer);
-    EXPECT_EQ(COMMAND_SUCCESS, rcode);
-
-    // Verify that a valid custom controller command returns
-    // process::COMMAND_SUCCESS response.
-    answer = executeCommand(DStubController::stub_ctl_command_, arg_set);
-    isc::config::parseAnswer(rcode, answer);
-    EXPECT_EQ(COMMAND_SUCCESS, rcode);
-
-    // Verify that a valid custom process command returns
-    // process::COMMAND_SUCCESS response.
-    answer = executeCommand(DStubProcess::stub_proc_command_, arg_set);
-    isc::config::parseAnswer(rcode, answer);
-    EXPECT_EQ(COMMAND_SUCCESS, rcode);
-
-    // Verify that a valid custom controller command that fails returns
-    // a process::COMMAND_ERROR.
-    SimFailure::set(SimFailure::ftControllerCommand);
-    answer = executeCommand(DStubController::stub_ctl_command_, arg_set);
-    isc::config::parseAnswer(rcode, answer);
-    EXPECT_EQ(COMMAND_ERROR, rcode);
-
-    // Verify that a valid custom process command that fails returns
-    // a process::COMMAND_ERROR.
-    SimFailure::set(SimFailure::ftProcessCommand);
-    answer = executeCommand(DStubProcess::stub_proc_command_, arg_set);
-    isc::config::parseAnswer(rcode, answer);
-    EXPECT_EQ(COMMAND_ERROR, rcode);
-}
-
 // Tests that registered signals are caught and handled.
 TEST_F(DStubControllerTest, ioSignals) {
     // Tell test controller just to record the signals, don't call the

+ 1 - 8
src/lib/process/testutils/d_test_stubs.h

@@ -499,18 +499,11 @@ public:
         return (getController()->checkConfig(new_config));
     }
 
-    /// @Wrapper to invoke the Controller's executeCommand method.  Please
-    /// refer to DControllerBase::executeCommand for details.
-    isc::data::ConstElementPtr executeCommand(const std::string& command,
-                                       isc::data::ConstElementPtr args){
-        return (getController()->executeCommand(command, args));
-    }
-
     /// @brief Callback that will generate shutdown command via the
     /// command callback function.
     static void genShutdownCallback() {
         isc::data::ElementPtr arg_set;
-        getController()->executeCommand(SHUT_DOWN_COMMAND, arg_set);
+        getController()->shutdownHandler(SHUT_DOWN_COMMAND, arg_set);
     }
 
     /// @brief Callback that throws an exception.