diff options
| author | Andrew Geissler <andrewg@us.ibm.com> | 2017-01-24 15:21:40 -0600 |
|---|---|---|
| committer | Patrick Williams <patrick@stwcx.xyz> | 2017-02-01 18:41:52 +0000 |
| commit | 4da7e00bb9b2284a4b83e0f97db96fb08fc5572e (patch) | |
| tree | 11c44a3ac539e324cb38e590f66392dfb75111f7 | |
| parent | 0029a5d2ca4b58a7da01d6489aa8ea4c22bf7705 (diff) | |
| download | phosphor-state-manager-4da7e00bb9b2284a4b83e0f97db96fb08fc5572e.tar.gz phosphor-state-manager-4da7e00bb9b2284a4b83e0f97db96fb08fc5572e.zip | |
Use systemd targets to track host states
Change-Id: I5ab174d945c1dfb265a02f9095d3eaeb0ba562db
Signed-off-by: Andrew Geissler <andrewg@us.ibm.com>
| -rw-r--r-- | host_state_manager.cpp | 68 | ||||
| -rw-r--r-- | host_state_manager.hpp | 66 |
2 files changed, 91 insertions, 43 deletions
diff --git a/host_state_manager.cpp b/host_state_manager.cpp index e16d0de..2d35886 100644 --- a/host_state_manager.cpp +++ b/host_state_manager.cpp @@ -17,11 +17,14 @@ namespace server = sdbusplus::xyz::openbmc_project::State::server; using namespace phosphor::logging; +constexpr auto HOST_STATE_POWEROFF_TGT = "obmc-chassis-stop@0.target"; +constexpr auto HOST_STATE_POWERON_TGT = "obmc-chassis-start@0.target"; + /* 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, HOST_STATE_POWEROFF_TGT}, + {server::Host::Transition::On, HOST_STATE_POWERON_TGT} }; constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1"; @@ -33,12 +36,22 @@ 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} }; +void Host::subscribeToSystemdSignals() +{ + auto method = this->bus.new_method_call(SYSTEMD_SERVICE, + SYSTEMD_OBJ_PATH, + SYSTEMD_INTERFACE, + "Subscribe"); + this->bus.call_noreply(method); + + return; +} + // TODO - Will be rewritten once sdbusplus client bindings are in place // and persistent storage design is in place void Host::determineInitialState() @@ -90,40 +103,49 @@ void Host::executeTransition(Transition tranReq) method.append(sysdUnit); method.append("replace"); - this->bus.call(method); + this->bus.call_noreply(method); return; } -int Host::handleSysStateChange(sd_bus_message *msg, void *usrData, - sd_bus_error *retError) +int Host::sysStateChangeSignal(sd_bus_message *msg, void *userData, + sd_bus_error *retError) +{ + return static_cast<Host*>(userData)->sysStateChange(msg, retError); +} + +int Host::sysStateChange(sd_bus_message* msg, + sd_bus_error* retError) { - const char *newState = nullptr; + uint32_t newStateID {}; + sdbusplus::message::object_path newStateObjPath; + std::string newStateUnit{}; + std::string newStateResult{}; + auto sdPlusMsg = sdbusplus::message::message(msg); - sdPlusMsg.read(newState); + //Read the msg and populate each variable + sdPlusMsg.read(newStateID, newStateObjPath, newStateUnit, newStateResult); - auto it = SYS_HOST_STATE_TABLE.find(newState); - if(it != SYS_HOST_STATE_TABLE.end()) + if((newStateUnit == HOST_STATE_POWEROFF_TGT) && + (newStateResult == "done")) { - // This is a state change we're interested in so process it - Host::HostState gotoState = it->second; - // Grab the host object instance from the userData - auto hostInst = static_cast<Host*>(usrData); - hostInst->currentHostState(gotoState); + log<level::INFO>("Recieved signal that host is off"); + this->currentHostState(server::Host::HostState::Off); // Check if we need to start a new transition (i.e. a Reboot) - if((gotoState == server::Host::HostState::Off) && - (hostInst->server::Host::requestedHostTransition() == - Transition::Reboot)) + if(this->server::Host::requestedHostTransition() == + Transition::Reboot) { log<level::DEBUG>("Reached intermediate state, going to next"); - hostInst->executeTransition(server::Host::Transition::On); - } - else - { - log<level::DEBUG>("Reached final state"); + this->executeTransition(server::Host::Transition::On); } } + else if((newStateUnit == HOST_STATE_POWERON_TGT) && + (newStateResult == "done")) + { + log<level::INFO>("Recieved signal that host is running"); + this->currentHostState(server::Host::HostState::Running); + } return 0; } diff --git a/host_state_manager.hpp b/host_state_manager.hpp index 515409e..597efa5 100644 --- a/host_state_manager.hpp +++ b/host_state_manager.hpp @@ -36,11 +36,17 @@ class Host : public sdbusplus::server::object::object< sdbusplus::xyz::openbmc_project::State::server::Host>( bus, objPath, true), bus(bus), - stateSignal(bus, - "type='signal',member='GotoSystemState'", - handleSysStateChange, - this) + systemdSignals(bus, + "type='signal'," + "member='JobRemoved'," + "path='/org/freedesktop/systemd1'," + "interface='org.freedesktop.systemd1.Manager'", + sysStateChangeSignal, + this) { + // Enable systemd signals + subscribeToSystemdSignals(); + // Will throw exception on fail determineInitialState(); @@ -48,13 +54,6 @@ class Host : public sdbusplus::server::object::object< this->emit_object_added(); } - /** - * @brief Determine initial host state and set internally - * - * @return Will throw exceptions on failure - **/ - void determineInitialState(); - /** @brief Set value of HostTransition */ Transition requestedHostTransition(Transition value) override; @@ -62,6 +61,22 @@ class Host : public sdbusplus::server::object::object< HostState currentHostState(HostState value) override; private: + /** + * @brief subscribe to the systemd signals + * + * This object needs to capture when it's systemd targets complete + * so it can keep it's state updated + * + **/ + void subscribeToSystemdSignals(); + + /** + * @brief Determine initial host state and set internally + * + * @return Will throw exceptions on failure + **/ + void determineInitialState(); + /** @brief Execute the transition request * * This function assumes the state has been validated and the host @@ -71,25 +86,36 @@ class Host : public sdbusplus::server::object::object< */ void executeTransition(Transition tranReq); - /** @brief Callback function on system state changes + /** @brief Callback function on systemd state changes * - * Check if the state is relevant to the Host and if so, update - * corresponding host object's state + * Will just do a call into the appropriate object for processing * - * @param[in] msg - Data associated with subscribed signal - * @param[in] userData - Pointer to this object instance - * @param[in] retError - Return error data + * @param[in] msg - Data associated with subscribed signal + * @param[in] userData - Pointer to this object instance + * @param[out] retError - Not used but required with signal API * */ - static int handleSysStateChange(sd_bus_message* msg, + static int sysStateChangeSignal(sd_bus_message* msg, void* userData, sd_bus_error* retError); + /** @brief Check if systemd state change is relevant to this object + * + * Instance specific interface to handle the detected systemd state + * change + * + * @param[in] msg - Data associated with subscribed signal + * @param[out] retError - Not used but required with signal API + * + */ + int sysStateChange(sd_bus_message* msg, + 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; + /** @brief Used to subscribe to dbus systemd signals **/ + sdbusplus::server::match::match systemdSignals; }; } // namespace manager |

