1 #pragma once 2 3 #include "config.h" 4 5 #include "settings.hpp" 6 #include "xyz/openbmc_project/State/Host/server.hpp" 7 8 #include <cereal/access.hpp> 9 #include <cereal/cereal.hpp> 10 #include <phosphor-logging/lg2.hpp> 11 #include <sdbusplus/bus.hpp> 12 #include <xyz/openbmc_project/Control/Boot/RebootAttempts/server.hpp> 13 #include <xyz/openbmc_project/State/Boot/Progress/server.hpp> 14 #include <xyz/openbmc_project/State/OperatingSystem/Status/server.hpp> 15 16 #include <experimental/filesystem> 17 #include <functional> 18 #include <string> 19 20 namespace phosphor 21 { 22 namespace state 23 { 24 namespace manager 25 { 26 27 using HostInherit = sdbusplus::server::object::object< 28 sdbusplus::xyz::openbmc_project::State::server::Host, 29 sdbusplus::xyz::openbmc_project::State::Boot::server::Progress, 30 sdbusplus::xyz::openbmc_project::Control::Boot::server::RebootAttempts, 31 sdbusplus::xyz::openbmc_project::State::OperatingSystem::server::Status>; 32 33 PHOSPHOR_LOG2_USING; 34 35 namespace sdbusRule = sdbusplus::bus::match::rules; 36 namespace fs = std::experimental::filesystem; 37 38 /** @class Host 39 * @brief OpenBMC host state management implementation. 40 * @details A concrete implementation for xyz.openbmc_project.State.Host 41 * DBus API. 42 */ 43 class Host : public HostInherit 44 { 45 public: 46 /** @brief Constructs Host State Manager 47 * 48 * @note This constructor passes 'true' to the base class in order to 49 * defer dbus object registration until we can run 50 * determineInitialState() and set our properties 51 * 52 * @param[in] bus - The Dbus bus object 53 * @param[in] objPath - The Dbus object path 54 */ 55 Host(sdbusplus::bus::bus& bus, const char* objPath) : 56 HostInherit(bus, objPath, true), bus(bus), 57 systemdSignalJobRemoved( 58 bus, 59 sdbusRule::type::signal() + sdbusRule::member("JobRemoved") + 60 sdbusRule::path("/org/freedesktop/systemd1") + 61 sdbusRule::interface("org.freedesktop.systemd1.Manager"), 62 std::bind(std::mem_fn(&Host::sysStateChangeJobRemoved), this, 63 std::placeholders::_1)), 64 systemdSignalJobNew( 65 bus, 66 sdbusRule::type::signal() + sdbusRule::member("JobNew") + 67 sdbusRule::path("/org/freedesktop/systemd1") + 68 sdbusRule::interface("org.freedesktop.systemd1.Manager"), 69 std::bind(std::mem_fn(&Host::sysStateChangeJobNew), this, 70 std::placeholders::_1)), 71 settings(bus) 72 { 73 // Enable systemd signals 74 subscribeToSystemdSignals(); 75 76 // Will throw exception on fail 77 determineInitialState(); 78 79 attemptsLeft(BOOT_COUNT_MAX_ALLOWED); 80 81 // We deferred this until we could get our property correct 82 this->emit_object_added(); 83 } 84 85 /** @brief Set value of HostTransition */ 86 Transition requestedHostTransition(Transition value) override; 87 88 /** @brief Set Value for boot progress */ 89 ProgressStages bootProgress(ProgressStages value) override; 90 91 /** @brief Set Value for Operating System Status */ 92 OSStatus operatingSystemState(OSStatus value) override; 93 94 /** @brief Set value of CurrentHostState */ 95 HostState currentHostState(HostState value) override; 96 97 /** 98 * @brief Set host reboot count to default 99 * 100 * OpenBMC software controls the number of allowed reboot attempts so 101 * any external set request of this property will be overridden by 102 * this function and set to the default. 103 * 104 * The only code responsible for decrementing the boot count resides 105 * within this process and that will use the sub class interface 106 * directly 107 * 108 * @param[in] value - Reboot count value, will be ignored 109 * 110 * @return Default number of reboot attempts left 111 */ 112 uint32_t attemptsLeft(uint32_t value) override 113 { 114 // value is ignored in this implementation 115 (void)(value); 116 debug("External request to reset reboot count"); 117 return (sdbusplus::xyz::openbmc_project::Control::Boot::server:: 118 RebootAttempts::attemptsLeft(BOOT_COUNT_MAX_ALLOWED)); 119 } 120 121 private: 122 /** 123 * @brief subscribe to the systemd signals 124 * 125 * This object needs to capture when it's systemd targets complete 126 * so it can keep it's state updated 127 * 128 **/ 129 void subscribeToSystemdSignals(); 130 131 /** 132 * @brief Determine initial host state and set internally 133 * 134 * @return Will throw exceptions on failure 135 **/ 136 void determineInitialState(); 137 138 /** @brief Execute the transition request 139 * 140 * This function assumes the state has been validated and the host 141 * is in an appropriate state for the transition to be started. 142 * 143 * @param[in] tranReq - Transition requested 144 */ 145 void executeTransition(Transition tranReq); 146 147 /** 148 * @brief Determine if target is active 149 * 150 * This function determines if the target is active and 151 * helps prevent misleading log recorded states. 152 * 153 * @param[in] target - Target string to check on 154 * 155 * @return boolean corresponding to state active 156 **/ 157 bool stateActive(const std::string& target); 158 159 /** 160 * @brief Determine if auto reboot flag is set 161 * 162 * @return boolean corresponding to current auto_reboot setting 163 **/ 164 bool isAutoReboot(); 165 166 /** @brief Check if systemd state change is relevant to this object 167 * 168 * Instance specific interface to handle the detected systemd state 169 * change 170 * 171 * @param[in] msg - Data associated with subscribed signal 172 * 173 */ 174 void sysStateChangeJobRemoved(sdbusplus::message::message& msg); 175 176 /** @brief Check if JobNew systemd signal is relevant to this object 177 * 178 * In certain instances phosphor-state-manager needs to monitor for the 179 * entry into a systemd target. This function will be used for these cases. 180 * 181 * Instance specific interface to handle the detected systemd state 182 * change 183 * 184 * @param[in] msg - Data associated with subscribed signal 185 * 186 */ 187 void sysStateChangeJobNew(sdbusplus::message::message& msg); 188 189 /** @brief Decrement reboot count 190 * 191 * This is used internally to this application to decrement the boot 192 * count on each boot attempt. The host will use the external 193 * attemptsLeft() interface to reset the count when a boot is successful 194 * 195 * @return number of reboot count attempts left 196 */ 197 uint32_t decrementRebootCount(); 198 199 // Allow cereal class access to allow these next two function to be 200 // private 201 friend class cereal::access; 202 203 /** @brief Function required by Cereal to perform serialization. 204 * 205 * @tparam Archive - Cereal archive type (binary in our case). 206 * @param[in] archive - reference to Cereal archive. 207 * @param[in] version - Class version that enables handling 208 * a serialized data across code levels 209 */ 210 template <class Archive> 211 void save(Archive& archive, const std::uint32_t version) const 212 { 213 // version is not used currently 214 (void)(version); 215 archive(convertForMessage(sdbusplus::xyz::openbmc_project::State:: 216 server::Host::requestedHostTransition()), 217 convertForMessage(sdbusplus::xyz::openbmc_project::State::Boot:: 218 server::Progress::bootProgress()), 219 convertForMessage( 220 sdbusplus::xyz::openbmc_project::State::OperatingSystem:: 221 server::Status::operatingSystemState())); 222 } 223 224 /** @brief Function required by Cereal to perform deserialization. 225 * 226 * @tparam Archive - Cereal archive type (binary in our case). 227 * @param[in] archive - reference to Cereal archive. 228 * @param[in] version - Class version that enables handling 229 * a serialized data across code levels 230 */ 231 template <class Archive> 232 void load(Archive& archive, const std::uint32_t version) 233 { 234 // version is not used currently 235 (void)(version); 236 std::string reqTranState; 237 std::string bootProgress; 238 std::string osState; 239 archive(reqTranState, bootProgress, osState); 240 auto reqTran = Host::convertTransitionFromString(reqTranState); 241 // When restoring, set the requested state with persistent value 242 // but don't call the override which would execute it 243 sdbusplus::xyz::openbmc_project::State::server::Host:: 244 requestedHostTransition(reqTran); 245 sdbusplus::xyz::openbmc_project::State::Boot::server::Progress:: 246 bootProgress(Host::convertProgressStagesFromString(bootProgress)); 247 sdbusplus::xyz::openbmc_project::State::OperatingSystem::server:: 248 Status::operatingSystemState( 249 Host::convertOSStatusFromString(osState)); 250 } 251 252 /** @brief Serialize and persist requested host state 253 * 254 * @param[in] dir - pathname of file where the serialized host state will 255 * be placed. 256 * 257 * @return fs::path - pathname of persisted requested host state. 258 */ 259 fs::path serialize(const fs::path& dir = fs::path(HOST_STATE_PERSIST_PATH)); 260 261 /** @brief Deserialze a persisted requested host state. 262 * 263 * @param[in] path - pathname of persisted host state file 264 * 265 * @return bool - true if the deserialization was successful, false 266 * otherwise. 267 */ 268 bool deserialize(const fs::path& path); 269 270 /** @brief Persistent sdbusplus DBus bus connection. */ 271 sdbusplus::bus::bus& bus; 272 273 /** @brief Used to subscribe to dbus systemd JobRemoved signal **/ 274 sdbusplus::bus::match_t systemdSignalJobRemoved; 275 276 /** @brief Used to subscribe to dbus systemd JobNew signal **/ 277 sdbusplus::bus::match_t systemdSignalJobNew; 278 279 // Settings objects of interest 280 settings::Objects settings; 281 }; 282 283 } // namespace manager 284 } // namespace state 285 } // namespace phosphor 286