Process system state changes

Use the system state signal to know when to change the state
of the host

The signal we look at may change with future skeleton
refactors but this is the best signal for now

Change-Id: Ibba7cc5628994425520c21cdf122d2710f8164aa
Signed-off-by: Andrew Geissler <andrewg@us.ibm.com>
diff --git a/host_state_manager.cpp b/host_state_manager.cpp
index 640ea94..1d5351a 100644
--- a/host_state_manager.cpp
+++ b/host_state_manager.cpp
@@ -17,8 +17,8 @@
 /* Map a transition to it's systemd target */
 const std::map<server::Host::Transition,std::string> SYSTEMD_TARGET_TABLE =
 {
-        {server::Host::Transition::Off,"obmc-chassis-stop@0.target"},
-        {server::Host::Transition::On,"obmc-chassis-start@0.target"}
+        {server::Host::Transition::Off, "obmc-chassis-stop@0.target"},
+        {server::Host::Transition::On, "obmc-chassis-start@0.target"}
 };
 
 constexpr auto SYSTEMD_SERVICE   = "org.freedesktop.systemd1";
@@ -29,6 +29,13 @@
 constexpr auto SYSTEM_OBJ_PATH  = "/org/openbmc/managers/System";
 constexpr auto SYSTEM_INTERFACE = SYSTEM_SERVICE;
 
+/* Map a system state to the HostState */
+/* TODO:Issue 774 - Use systemd target signals to control host states */
+const std::map<std::string, server::Host::HostState> SYS_HOST_STATE_TABLE = {
+        {"HOST_BOOTING", server::Host::HostState::Running},
+        {"HOST_POWERED_OFF", server::Host::HostState::Off}
+};
+
 // TODO - Will be rewritten once sdbusplus client bindings are in place
 //        and persistent storage design is in place
 void Host::determineInitialState()
@@ -47,12 +54,12 @@
     if(sysState == "HOST_BOOTED")
     {
         std::cout << "HOST is BOOTED " << sysState << std::endl;
-        server::Host::currentHostState(HostState::Running);
+        currentHostState(HostState::Running);
     }
     else
     {
         std::cout << "HOST is not BOOTED " << sysState << std::endl;
-        server::Host::currentHostState(HostState::Off);
+        currentHostState(HostState::Off);
     }
 
     // Set transition initially to Off
@@ -79,6 +86,30 @@
     return;
 }
 
+int Host::handleSysStateChange(sd_bus_message *msg, void *usrData,
+                               sd_bus_error *retError)
+{
+    const char *newState = nullptr;
+    auto sdPlusMsg = sdbusplus::message::message(msg);
+    sdPlusMsg.read(newState);
+
+    std::cout << "The System State has changed to " << newState << std::endl;
+
+    auto it = SYS_HOST_STATE_TABLE.find(newState);
+    if(it != SYS_HOST_STATE_TABLE.end())
+    {
+        HostState gotoState = it->second;
+        auto hostInst = static_cast<Host*>(usrData);
+        hostInst->currentHostState(gotoState);
+    }
+    else
+    {
+        std::cout << "Not a relevant state change for host" << std::endl;
+    }
+
+    return 0;
+}
+
 Host::Transition Host::requestedHostTransition(Transition value)
 {
     std::cout << "Someone is setting the RequestedHostTransition field"
@@ -91,10 +122,8 @@
 
 Host::HostState Host::currentHostState(HostState value)
 {
-    std::cout << "Someone is being bad and trying to set the HostState field"
-              << std::endl;
-
-    return server::Host::currentHostState();
+    std::cout << "Changing HostState" << std::endl;
+    return server::Host::currentHostState(value);
 }
 
 } // namespace manager
diff --git a/host_state_manager.hpp b/host_state_manager.hpp
index 8f0733b..515409e 100644
--- a/host_state_manager.hpp
+++ b/host_state_manager.hpp
@@ -35,7 +35,11 @@
                 sdbusplus::server::object::object<
                     sdbusplus::xyz::openbmc_project::State::server::Host>(
                             bus, objPath, true),
-                bus(bus)
+                bus(bus),
+                stateSignal(bus,
+                            "type='signal',member='GotoSystemState'",
+                            handleSysStateChange,
+                            this)
         {
             // Will throw exception on fail
             determineInitialState();
@@ -67,8 +71,25 @@
          */
         void executeTransition(Transition tranReq);
 
+        /** @brief Callback function on system state changes
+         *
+         *  Check if the state is relevant to the Host and if so, update
+         *  corresponding host object's state
+         *
+         * @param[in] msg        - Data associated with subscribed signal
+         * @param[in] userData   - Pointer to this object instance
+         * @param[in] retError   - Return error data
+         *
+         */
+        static int handleSysStateChange(sd_bus_message* msg,
+                                        void* userData,
+                                        sd_bus_error* retError);
+
         /** @brief Persistent sdbusplus DBus bus connection. */
         sdbusplus::bus::bus& bus;
+
+        /** @brief Used to subscribe to dbus system state changes */
+        sdbusplus::server::match::match stateSignal;
 };
 
 } // namespace manager