Create file to indicate host requested off/reboot

Create a file to ensure the soft power off service is
not run when the host is requesting a power off
or reboot.  There's no need to notify the host (i.e.
soft power off) when they are initiating it.

Change-Id: Ic9f8e7110d30f477ceae38bba9d684559d9503d3
Signed-off-by: Andrew Geissler <andrewg@us.ibm.com>
diff --git a/chassishandler.cpp b/chassishandler.cpp
index ef5647c..5dc23b2 100644
--- a/chassishandler.cpp
+++ b/chassishandler.cpp
@@ -11,6 +11,8 @@
 #include <endian.h>
 #include <sstream>
 #include <array>
+#include <fstream>
+#include <experimental/filesystem>
 #include <phosphor-logging/log.hpp>
 #include <xyz/openbmc_project/State/Host/server.hpp>
 #include "config.h"
@@ -44,7 +46,7 @@
 static constexpr size_t PREFIX_OFFSET = 21;
 static constexpr size_t GATEWAY_OFFSET = 22;
 
-
+using namespace phosphor::logging;
 
 
 void register_netfn_chassis_functions() __attribute__((constructor));
@@ -76,6 +78,8 @@
 // Phosphor Host State manager
 namespace State = sdbusplus::xyz::openbmc_project::State::server;
 
+namespace fs = std::experimental::filesystem;
+
 int dbus_get_property(const char *name, char **buf)
 {
     sd_bus_error error = SD_BUS_ERROR_NULL;
@@ -577,8 +581,6 @@
 //------------------------------------------
 int initiate_state_transition(State::Host::Transition transition)
 {
-    using namespace phosphor::logging;
-
     // OpenBMC Host State Manager dbus framework
     constexpr auto HOST_STATE_MANAGER_ROOT  = "/xyz/openbmc_project/state/host0";
     constexpr auto HOST_STATE_MANAGER_IFACE = "xyz.openbmc_project.State.Host";
@@ -852,6 +854,29 @@
 }
 
 //----------------------------------------------------------------------
+// Create file to indicate there is no need for softoff notification to host
+//----------------------------------------------------------------------
+void indicate_no_softoff_needed()
+{
+    fs::path path{HOST_INBAND_REQUEST_DIR};
+    if (!fs::is_directory(path))
+    {
+        fs::create_directory(path);
+    }
+
+    // Add the host instance (default 0 for now) to the file name
+    std::string file{HOST_INBAND_REQUEST_FILE};
+    auto size = std::snprintf(nullptr,0,file.c_str(),0);
+    size++; // null
+    std::unique_ptr<char[]> buf(new char[size]);
+    std::snprintf(buf.get(),size,file.c_str(),0);
+
+    // Append file name to directory and create it
+    path /= buf.get();
+    std::ofstream(path.c_str());
+}
+
+//----------------------------------------------------------------------
 // Chassis Control commands
 //----------------------------------------------------------------------
 ipmi_ret_t ipmi_chassis_control(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
@@ -879,13 +904,28 @@
             // Need to Nudge SoftPowerOff application that it needs to stop the
             // watchdog timer if running.
             rc = stop_soft_off_timer();
-            if (!rc)
+            // Only request the Off transition if the soft power off
+            // application is not running
+            if (rc < 0)
             {
-                fprintf(stderr, "Error stopping watchdog timer");
+                log<level::INFO>("Did not find soft off service so request "
+                                 "Host:Transition:Off");
+
+                // First create a file to indicate to the soft off application
+                // that it should not run since this is a direct user initiated
+                // power off request (i.e. a power off request that is not
+                // originating via a soft power off SMS request)
+                indicate_no_softoff_needed();
+
+                // Now request the shutdown
+                rc = initiate_state_transition(State::Host::Transition::Off);
             }
-            // Does not matter if we are able to stop the timer,
-            // just get going and do the hard power off
-            rc = initiate_state_transition(State::Host::Transition::Off);
+            else
+            {
+                log<level::INFO>("Soft off is running, so let that stop "
+                                 "the host");
+            }
+
             break;
 
         case CMD_HARD_RESET:
@@ -893,6 +933,13 @@
             // SPEC has a section that says certain implementations can trigger
             // PowerOn if power is Off when a command to power cycle is
             // requested
+
+            // First create a file to indicate to the soft off application
+            // that it should not run since this is a direct user initiated
+            // power reboot request (i.e. a reboot request that is not
+            // originating via a soft power off SMS request)
+            indicate_no_softoff_needed();
+
             rc = initiate_state_transition(State::Host::Transition::Reboot);
             break;
         default: