blob: c57c8aa9ed2ce267be98d6f68df6dd8bbfbe5cfb [file] [log] [blame]
Andrew Geissler36529022016-11-29 15:23:54 -06001#pragma once
2
Michael Tritz206a8332017-02-06 16:01:23 -06003#include <string>
Patrick Williamsd22706f2017-05-04 05:42:49 -05004#include <functional>
Andrew Geissler033fc3b2017-08-30 15:11:44 -05005#include <experimental/filesystem>
6#include <cereal/access.hpp>
Vishwanatha Subbanna0a838732017-10-05 12:43:19 +05307#include <cereal/cereal.hpp>
Andrew Geissler36529022016-11-29 15:23:54 -06008#include <sdbusplus/bus.hpp>
Andrew Geissler7b90a622017-08-08 11:41:08 -05009#include <phosphor-logging/log.hpp>
Dhruvaraj Subhashchandran2710e732017-06-19 06:43:22 -050010#include <xyz/openbmc_project/State/Boot/Progress/server.hpp>
11#include <xyz/openbmc_project/Control/Boot/RebootAttempts/server.hpp>
12#include <xyz/openbmc_project/State/OperatingSystem/Status/server.hpp>
Andrew Geissler36529022016-11-29 15:23:54 -060013#include "xyz/openbmc_project/State/Host/server.hpp"
Deepak Kodihalli3dd08a52017-07-25 07:34:44 -050014#include "settings.hpp"
Dhruvaraj Subhashchandran2710e732017-06-19 06:43:22 -050015#include "config.h"
Andrew Geissler36529022016-11-29 15:23:54 -060016
17namespace phosphor
18{
19namespace state
20{
21namespace manager
22{
23
Patrick Williamsd22706f2017-05-04 05:42:49 -050024using HostInherit = sdbusplus::server::object::object<
Andrew Geissler58a18012018-01-19 19:36:05 -080025 sdbusplus::xyz::openbmc_project::State::server::Host,
26 sdbusplus::xyz::openbmc_project::State::Boot::server::Progress,
27 sdbusplus::xyz::openbmc_project::Control::Boot::server::RebootAttempts,
28 sdbusplus::xyz::openbmc_project::State::OperatingSystem::server::Status>;
Dhruvaraj Subhashchandran2710e732017-06-19 06:43:22 -050029
Andrew Geissler7b90a622017-08-08 11:41:08 -050030using namespace phosphor::logging;
31
Patrick Williamsd22706f2017-05-04 05:42:49 -050032namespace sdbusRule = sdbusplus::bus::match::rules;
Andrew Geissler033fc3b2017-08-30 15:11:44 -050033namespace fs = std::experimental::filesystem;
Patrick Williamsd22706f2017-05-04 05:42:49 -050034
Andrew Geissler36529022016-11-29 15:23:54 -060035/** @class Host
36 * @brief OpenBMC host state management implementation.
37 * @details A concrete implementation for xyz.openbmc_project.State.Host
38 * DBus API.
39 */
Patrick Williamsd22706f2017-05-04 05:42:49 -050040class Host : public HostInherit
Andrew Geissler36529022016-11-29 15:23:54 -060041{
Andrew Geissler58a18012018-01-19 19:36:05 -080042 public:
43 /** @brief Constructs Host State Manager
44 *
45 * @note This constructor passes 'true' to the base class in order to
46 * defer dbus object registration until we can run
47 * determineInitialState() and set our properties
48 *
49 * @param[in] bus - The Dbus bus object
Andrew Geissler58a18012018-01-19 19:36:05 -080050 * @param[in] objPath - The Dbus object path
51 */
Andrew Geissler769a62f2019-12-06 13:36:08 -060052 Host(sdbusplus::bus::bus& bus, const char* objPath) :
Andrew Geissler58a18012018-01-19 19:36:05 -080053 HostInherit(bus, objPath, true), bus(bus),
Andrew Geisslere4039a82020-02-11 15:51:59 -060054 systemdSignalJobRemoved(
Andrew Geissler58a18012018-01-19 19:36:05 -080055 bus,
56 sdbusRule::type::signal() + sdbusRule::member("JobRemoved") +
57 sdbusRule::path("/org/freedesktop/systemd1") +
58 sdbusRule::interface("org.freedesktop.systemd1.Manager"),
Andrew Geisslere4039a82020-02-11 15:51:59 -060059 std::bind(std::mem_fn(&Host::sysStateChangeJobRemoved), this,
Andrew Geissler58a18012018-01-19 19:36:05 -080060 std::placeholders::_1)),
Andrew Geissler47b96122020-02-11 16:13:13 -060061 systemdSignalJobNew(
62 bus,
63 sdbusRule::type::signal() + sdbusRule::member("JobNew") +
64 sdbusRule::path("/org/freedesktop/systemd1") +
65 sdbusRule::interface("org.freedesktop.systemd1.Manager"),
66 std::bind(std::mem_fn(&Host::sysStateChangeJobNew), this,
67 std::placeholders::_1)),
Andrew Geissler58a18012018-01-19 19:36:05 -080068 settings(bus)
69 {
70 // Enable systemd signals
71 subscribeToSystemdSignals();
Andrew Geissler4da7e002017-01-24 15:21:40 -060072
Andrew Geissler58a18012018-01-19 19:36:05 -080073 // Will throw exception on fail
74 determineInitialState();
Andrew Geissleref3c1842016-12-01 12:33:09 -060075
Andrew Geissler58a18012018-01-19 19:36:05 -080076 attemptsLeft(BOOT_COUNT_MAX_ALLOWED);
Dhruvaraj Subhashchandran2710e732017-06-19 06:43:22 -050077
Andrew Geissler58a18012018-01-19 19:36:05 -080078 // We deferred this until we could get our property correct
79 this->emit_object_added();
80 }
Andrew Geissleref3c1842016-12-01 12:33:09 -060081
Andrew Geissler58a18012018-01-19 19:36:05 -080082 /** @brief Set value of HostTransition */
83 Transition requestedHostTransition(Transition value) override;
Andrew Geissleref3c1842016-12-01 12:33:09 -060084
Andrew Geissler58a18012018-01-19 19:36:05 -080085 /** @brief Set Value for boot progress */
86 ProgressStages bootProgress(ProgressStages value) override;
Dhruvaraj Subhashchandran4e6534f2017-09-19 06:13:20 -050087
Andrew Geissler58a18012018-01-19 19:36:05 -080088 /** @brief Set Value for Operating System Status */
89 OSStatus operatingSystemState(OSStatus value) override;
Dhruvaraj Subhashchandran4e6534f2017-09-19 06:13:20 -050090
Andrew Geissler58a18012018-01-19 19:36:05 -080091 /** @brief Set value of CurrentHostState */
92 HostState currentHostState(HostState value) override;
Andrew Geissler36529022016-11-29 15:23:54 -060093
Andrew Geissler58a18012018-01-19 19:36:05 -080094 /**
95 * @brief Set host reboot count to default
96 *
97 * OpenBMC software controls the number of allowed reboot attempts so
98 * any external set request of this property will be overridden by
99 * this function and set to the default.
100 *
101 * The only code responsible for decrementing the boot count resides
102 * within this process and that will use the sub class interface
103 * directly
104 *
105 * @param[in] value - Reboot count value, will be ignored
106 *
107 * @return Default number of reboot attempts left
108 */
109 uint32_t attemptsLeft(uint32_t value) override
110 {
Andrew Geissler769a62f2019-12-06 13:36:08 -0600111 // value is ignored in this implementation
112 (void)(value);
Andrew Geissler58a18012018-01-19 19:36:05 -0800113 log<level::DEBUG>("External request to reset reboot count");
114 return (sdbusplus::xyz::openbmc_project::Control::Boot::server::
Andrew Geissler7b90a622017-08-08 11:41:08 -0500115 RebootAttempts::attemptsLeft(BOOT_COUNT_MAX_ALLOWED));
Andrew Geissler58a18012018-01-19 19:36:05 -0800116 }
Andrew Geissler7b90a622017-08-08 11:41:08 -0500117
Andrew Geissler58a18012018-01-19 19:36:05 -0800118 private:
119 /**
120 * @brief subscribe to the systemd signals
121 *
122 * This object needs to capture when it's systemd targets complete
123 * so it can keep it's state updated
124 *
125 **/
126 void subscribeToSystemdSignals();
Andrew Geissler4da7e002017-01-24 15:21:40 -0600127
Andrew Geissler58a18012018-01-19 19:36:05 -0800128 /**
129 * @brief Determine initial host state and set internally
130 *
131 * @return Will throw exceptions on failure
132 **/
133 void determineInitialState();
Andrew Geissler4da7e002017-01-24 15:21:40 -0600134
Andrew Geissler58a18012018-01-19 19:36:05 -0800135 /** @brief Execute the transition request
136 *
137 * This function assumes the state has been validated and the host
138 * is in an appropriate state for the transition to be started.
139 *
140 * @param[in] tranReq - Transition requested
141 */
142 void executeTransition(Transition tranReq);
Andrew Geissler0cd2eaf2016-12-07 10:50:13 -0600143
Andrew Geissler58a18012018-01-19 19:36:05 -0800144 /**
145 * @brief Determine if target is active
146 *
147 * This function determines if the target is active and
148 * helps prevent misleading log recorded states.
149 *
150 * @param[in] target - Target string to check on
151 *
152 * @return boolean corresponding to state active
153 **/
154 bool stateActive(const std::string& target);
Josh D. King929ef702017-03-02 10:58:11 -0600155
Andrew Geissler58a18012018-01-19 19:36:05 -0800156 /**
157 * @brief Determine if auto reboot flag is set
158 *
159 * @return boolean corresponding to current auto_reboot setting
160 **/
161 bool isAutoReboot();
Michael Tritz206a8332017-02-06 16:01:23 -0600162
Andrew Geissler58a18012018-01-19 19:36:05 -0800163 /** @brief Check if systemd state change is relevant to this object
164 *
165 * Instance specific interface to handle the detected systemd state
166 * change
167 *
168 * @param[in] msg - Data associated with subscribed signal
169 *
170 */
Andrew Geisslere4039a82020-02-11 15:51:59 -0600171 void sysStateChangeJobRemoved(sdbusplus::message::message& msg);
Andrew Geissler4da7e002017-01-24 15:21:40 -0600172
Andrew Geissler47b96122020-02-11 16:13:13 -0600173 /** @brief Check if JobNew systemd signal is relevant to this object
174 *
175 * In certain instances phosphor-state-manager needs to monitor for the
176 * entry into a systemd target. This function will be used for these cases.
177 *
178 * Instance specific interface to handle the detected systemd state
179 * change
180 *
181 * @param[in] msg - Data associated with subscribed signal
182 *
183 */
184 void sysStateChangeJobNew(sdbusplus::message::message& msg);
185
Andrew Geissler58a18012018-01-19 19:36:05 -0800186 /** @brief Decrement reboot count
187 *
188 * This is used internally to this application to decrement the boot
189 * count on each boot attempt. The host will use the external
190 * attemptsLeft() interface to reset the count when a boot is successful
191 *
192 * @return number of reboot count attempts left
193 */
194 uint32_t decrementRebootCount();
Andrew Geissler7b90a622017-08-08 11:41:08 -0500195
Andrew Geissler58a18012018-01-19 19:36:05 -0800196 // Allow cereal class access to allow these next two function to be
197 // private
198 friend class cereal::access;
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500199
Andrew Geissler58a18012018-01-19 19:36:05 -0800200 /** @brief Function required by Cereal to perform serialization.
201 *
202 * @tparam Archive - Cereal archive type (binary in our case).
203 * @param[in] archive - reference to Cereal archive.
204 * @param[in] version - Class version that enables handling
205 * a serialized data across code levels
206 */
207 template <class Archive>
208 void save(Archive& archive, const std::uint32_t version) const
209 {
Andrew Geissler769a62f2019-12-06 13:36:08 -0600210 // version is not used currently
211 (void)(version);
Andrew Geissler58a18012018-01-19 19:36:05 -0800212 archive(convertForMessage(sdbusplus::xyz::openbmc_project::State::
213 server::Host::requestedHostTransition()),
214 convertForMessage(sdbusplus::xyz::openbmc_project::State::Boot::
215 server::Progress::bootProgress()),
216 convertForMessage(
217 sdbusplus::xyz::openbmc_project::State::OperatingSystem::
218 server::Status::operatingSystemState()));
219 }
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500220
Andrew Geissler58a18012018-01-19 19:36:05 -0800221 /** @brief Function required by Cereal to perform deserialization.
222 *
223 * @tparam Archive - Cereal archive type (binary in our case).
224 * @param[in] archive - reference to Cereal archive.
225 * @param[in] version - Class version that enables handling
226 * a serialized data across code levels
227 */
228 template <class Archive>
229 void load(Archive& archive, const std::uint32_t version)
230 {
Andrew Geissler769a62f2019-12-06 13:36:08 -0600231 // version is not used currently
232 (void)(version);
Andrew Geissler58a18012018-01-19 19:36:05 -0800233 std::string reqTranState;
234 std::string bootProgress;
235 std::string osState;
236 archive(reqTranState, bootProgress, osState);
237 auto reqTran = Host::convertTransitionFromString(reqTranState);
238 // When restoring, set the requested state with persistent value
239 // but don't call the override which would execute it
240 sdbusplus::xyz::openbmc_project::State::server::Host::
241 requestedHostTransition(reqTran);
242 sdbusplus::xyz::openbmc_project::State::Boot::server::Progress::
243 bootProgress(Host::convertProgressStagesFromString(bootProgress));
244 sdbusplus::xyz::openbmc_project::State::OperatingSystem::server::
245 Status::operatingSystemState(
246 Host::convertOSStatusFromString(osState));
247 }
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500248
Andrew Geissler58a18012018-01-19 19:36:05 -0800249 /** @brief Serialize and persist requested host state
250 *
251 * @param[in] dir - pathname of file where the serialized host state will
252 * be placed.
253 *
254 * @return fs::path - pathname of persisted requested host state.
255 */
256 fs::path serialize(const fs::path& dir = fs::path(HOST_STATE_PERSIST_PATH));
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500257
Andrew Geissler58a18012018-01-19 19:36:05 -0800258 /** @brief Deserialze a persisted requested host state.
259 *
260 * @param[in] path - pathname of persisted host state file
261 *
262 * @return bool - true if the deserialization was successful, false
263 * otherwise.
264 */
265 bool deserialize(const fs::path& path);
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500266
Andrew Geissler58a18012018-01-19 19:36:05 -0800267 /** @brief Persistent sdbusplus DBus bus connection. */
268 sdbusplus::bus::bus& bus;
Andrew Geissleref621162016-12-08 12:56:21 -0600269
Andrew Geisslere4039a82020-02-11 15:51:59 -0600270 /** @brief Used to subscribe to dbus systemd JobRemoved signal **/
271 sdbusplus::bus::match_t systemdSignalJobRemoved;
Deepak Kodihalli3dd08a52017-07-25 07:34:44 -0500272
Andrew Geissler47b96122020-02-11 16:13:13 -0600273 /** @brief Used to subscribe to dbus systemd JobNew signal **/
274 sdbusplus::bus::match_t systemdSignalJobNew;
275
Andrew Geissler58a18012018-01-19 19:36:05 -0800276 // Settings objects of interest
277 settings::Objects settings;
Andrew Geissler36529022016-11-29 15:23:54 -0600278};
279
280} // namespace manager
281} // namespace state
282} // namespace phosphor