blob: 6b9d68739ada4311a035d50b8890d6102249b1c2 [file] [log] [blame]
Andrew Geissler36529022016-11-29 15:23:54 -06001#pragma once
2
Andrew Geisslere426b582020-05-28 12:40:55 -05003#include "config.h"
4
5#include "settings.hpp"
6#include "xyz/openbmc_project/State/Host/server.hpp"
7
Andrew Geissler033fc3b2017-08-30 15:11:44 -05008#include <cereal/access.hpp>
Vishwanatha Subbanna0a838732017-10-05 12:43:19 +05309#include <cereal/cereal.hpp>
Andrew Geissler8ffdb262021-09-20 15:25:19 -050010#include <phosphor-logging/lg2.hpp>
Andrew Geisslere426b582020-05-28 12:40:55 -050011#include <sdbusplus/bus.hpp>
Dhruvaraj Subhashchandran2710e732017-06-19 06:43:22 -050012#include <xyz/openbmc_project/Control/Boot/RebootAttempts/server.hpp>
Andrew Geisslere426b582020-05-28 12:40:55 -050013#include <xyz/openbmc_project/State/Boot/Progress/server.hpp>
Dhruvaraj Subhashchandran2710e732017-06-19 06:43:22 -050014#include <xyz/openbmc_project/State/OperatingSystem/Status/server.hpp>
Andrew Geisslere426b582020-05-28 12:40:55 -050015
Patrick Williams6ed41ea2022-04-05 15:50:21 -050016#include <filesystem>
Andrew Geisslere426b582020-05-28 12:40:55 -050017#include <functional>
18#include <string>
Andrew Geissler36529022016-11-29 15:23:54 -060019
20namespace phosphor
21{
22namespace state
23{
24namespace manager
25{
26
Patrick Williamsd22706f2017-05-04 05:42:49 -050027using HostInherit = sdbusplus::server::object::object<
Andrew Geissler58a18012018-01-19 19:36:05 -080028 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>;
Dhruvaraj Subhashchandran2710e732017-06-19 06:43:22 -050032
Andrew Geissler8ffdb262021-09-20 15:25:19 -050033PHOSPHOR_LOG2_USING;
Andrew Geissler7b90a622017-08-08 11:41:08 -050034
Patrick Williamsd22706f2017-05-04 05:42:49 -050035namespace sdbusRule = sdbusplus::bus::match::rules;
Patrick Williams6ed41ea2022-04-05 15:50:21 -050036namespace fs = std::filesystem;
Patrick Williamsd22706f2017-05-04 05:42:49 -050037
Andrew Geissler36529022016-11-29 15:23:54 -060038/** @class Host
39 * @brief OpenBMC host state management implementation.
40 * @details A concrete implementation for xyz.openbmc_project.State.Host
41 * DBus API.
42 */
Patrick Williamsd22706f2017-05-04 05:42:49 -050043class Host : public HostInherit
Andrew Geissler36529022016-11-29 15:23:54 -060044{
Andrew Geissler58a18012018-01-19 19:36:05 -080045 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
Andrew Geissler58a18012018-01-19 19:36:05 -080053 * @param[in] objPath - The Dbus object path
Allen.Wang79b45002022-02-10 17:59:20 +080054 * @param[in] id - The Host id
Andrew Geissler58a18012018-01-19 19:36:05 -080055 */
Allen.Wang79b45002022-02-10 17:59:20 +080056 Host(sdbusplus::bus::bus& bus, const char* objPath, size_t id) :
Patrick Williams76070742022-04-05 15:20:12 -050057 HostInherit(bus, objPath, HostInherit::action::defer_emit), bus(bus),
Andrew Geisslere4039a82020-02-11 15:51:59 -060058 systemdSignalJobRemoved(
Andrew Geissler58a18012018-01-19 19:36:05 -080059 bus,
60 sdbusRule::type::signal() + sdbusRule::member("JobRemoved") +
61 sdbusRule::path("/org/freedesktop/systemd1") +
62 sdbusRule::interface("org.freedesktop.systemd1.Manager"),
Andrew Geisslere4039a82020-02-11 15:51:59 -060063 std::bind(std::mem_fn(&Host::sysStateChangeJobRemoved), this,
Andrew Geissler58a18012018-01-19 19:36:05 -080064 std::placeholders::_1)),
Andrew Geissler47b96122020-02-11 16:13:13 -060065 systemdSignalJobNew(
66 bus,
67 sdbusRule::type::signal() + sdbusRule::member("JobNew") +
68 sdbusRule::path("/org/freedesktop/systemd1") +
69 sdbusRule::interface("org.freedesktop.systemd1.Manager"),
70 std::bind(std::mem_fn(&Host::sysStateChangeJobNew), this,
71 std::placeholders::_1)),
Potin Laic328a4c2022-03-18 23:49:37 +080072 settings(bus, id), id(id)
Andrew Geissler58a18012018-01-19 19:36:05 -080073 {
74 // Enable systemd signals
75 subscribeToSystemdSignals();
Andrew Geissler4da7e002017-01-24 15:21:40 -060076
Allen.Wang79b45002022-02-10 17:59:20 +080077 // create map of target name base on host id
78 createSystemdTargetMaps();
79
Andrew Geissler58a18012018-01-19 19:36:05 -080080 // Will throw exception on fail
81 determineInitialState();
Andrew Geissleref3c1842016-12-01 12:33:09 -060082
Andrew Geissler58a18012018-01-19 19:36:05 -080083 attemptsLeft(BOOT_COUNT_MAX_ALLOWED);
Dhruvaraj Subhashchandran2710e732017-06-19 06:43:22 -050084
Andrew Geissler58a18012018-01-19 19:36:05 -080085 // We deferred this until we could get our property correct
86 this->emit_object_added();
87 }
Andrew Geissleref3c1842016-12-01 12:33:09 -060088
Andrew Geissler58a18012018-01-19 19:36:05 -080089 /** @brief Set value of HostTransition */
90 Transition requestedHostTransition(Transition value) override;
Andrew Geissleref3c1842016-12-01 12:33:09 -060091
Andrew Geissler58a18012018-01-19 19:36:05 -080092 /** @brief Set Value for boot progress */
93 ProgressStages bootProgress(ProgressStages value) override;
Dhruvaraj Subhashchandran4e6534f2017-09-19 06:13:20 -050094
Andrew Geissler58a18012018-01-19 19:36:05 -080095 /** @brief Set Value for Operating System Status */
96 OSStatus operatingSystemState(OSStatus value) override;
Dhruvaraj Subhashchandran4e6534f2017-09-19 06:13:20 -050097
Andrew Geissler58a18012018-01-19 19:36:05 -080098 /** @brief Set value of CurrentHostState */
99 HostState currentHostState(HostState value) override;
Andrew Geissler36529022016-11-29 15:23:54 -0600100
Andrew Geissler58a18012018-01-19 19:36:05 -0800101 /**
102 * @brief Set host reboot count to default
103 *
104 * OpenBMC software controls the number of allowed reboot attempts so
105 * any external set request of this property will be overridden by
106 * this function and set to the default.
107 *
108 * The only code responsible for decrementing the boot count resides
109 * within this process and that will use the sub class interface
110 * directly
111 *
112 * @param[in] value - Reboot count value, will be ignored
113 *
114 * @return Default number of reboot attempts left
115 */
116 uint32_t attemptsLeft(uint32_t value) override
117 {
Andrew Geissler769a62f2019-12-06 13:36:08 -0600118 // value is ignored in this implementation
119 (void)(value);
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500120 debug("External request to reset reboot count");
Andrew Geissler58a18012018-01-19 19:36:05 -0800121 return (sdbusplus::xyz::openbmc_project::Control::Boot::server::
Andrew Geissler7b90a622017-08-08 11:41:08 -0500122 RebootAttempts::attemptsLeft(BOOT_COUNT_MAX_ALLOWED));
Andrew Geissler58a18012018-01-19 19:36:05 -0800123 }
Andrew Geissler7b90a622017-08-08 11:41:08 -0500124
Andrew Geissler58a18012018-01-19 19:36:05 -0800125 private:
126 /**
127 * @brief subscribe to the systemd signals
128 *
129 * This object needs to capture when it's systemd targets complete
130 * so it can keep it's state updated
131 *
132 **/
133 void subscribeToSystemdSignals();
Andrew Geissler4da7e002017-01-24 15:21:40 -0600134
Andrew Geissler58a18012018-01-19 19:36:05 -0800135 /**
136 * @brief Determine initial host state and set internally
137 *
138 * @return Will throw exceptions on failure
139 **/
140 void determineInitialState();
Andrew Geissler4da7e002017-01-24 15:21:40 -0600141
Allen.Wang79b45002022-02-10 17:59:20 +0800142 /**
143 * create systemd target instance names and mapping table
144 **/
145 void createSystemdTargetMaps();
146
Andrew Geissler58a18012018-01-19 19:36:05 -0800147 /** @brief Execute the transition request
148 *
149 * This function assumes the state has been validated and the host
150 * is in an appropriate state for the transition to be started.
151 *
152 * @param[in] tranReq - Transition requested
153 */
154 void executeTransition(Transition tranReq);
Andrew Geissler0cd2eaf2016-12-07 10:50:13 -0600155
Andrew Geissler58a18012018-01-19 19:36:05 -0800156 /**
157 * @brief Determine if target is active
158 *
159 * This function determines if the target is active and
160 * helps prevent misleading log recorded states.
161 *
162 * @param[in] target - Target string to check on
163 *
164 * @return boolean corresponding to state active
165 **/
166 bool stateActive(const std::string& target);
Josh D. King929ef702017-03-02 10:58:11 -0600167
Andrew Geissler58a18012018-01-19 19:36:05 -0800168 /**
169 * @brief Determine if auto reboot flag is set
170 *
171 * @return boolean corresponding to current auto_reboot setting
172 **/
173 bool isAutoReboot();
Michael Tritz206a8332017-02-06 16:01:23 -0600174
Andrew Geissler58a18012018-01-19 19:36:05 -0800175 /** @brief Check if systemd state change is relevant to this object
176 *
177 * Instance specific interface to handle the detected systemd state
178 * change
179 *
180 * @param[in] msg - Data associated with subscribed signal
181 *
182 */
Andrew Geisslere4039a82020-02-11 15:51:59 -0600183 void sysStateChangeJobRemoved(sdbusplus::message::message& msg);
Andrew Geissler4da7e002017-01-24 15:21:40 -0600184
Andrew Geissler47b96122020-02-11 16:13:13 -0600185 /** @brief Check if JobNew systemd signal is relevant to this object
186 *
187 * In certain instances phosphor-state-manager needs to monitor for the
188 * entry into a systemd target. This function will be used for these cases.
189 *
190 * Instance specific interface to handle the detected systemd state
191 * change
192 *
193 * @param[in] msg - Data associated with subscribed signal
194 *
195 */
196 void sysStateChangeJobNew(sdbusplus::message::message& msg);
197
Andrew Geissler58a18012018-01-19 19:36:05 -0800198 /** @brief Decrement reboot count
199 *
200 * This is used internally to this application to decrement the boot
201 * count on each boot attempt. The host will use the external
202 * attemptsLeft() interface to reset the count when a boot is successful
203 *
204 * @return number of reboot count attempts left
205 */
206 uint32_t decrementRebootCount();
Andrew Geissler7b90a622017-08-08 11:41:08 -0500207
Andrew Geissler58a18012018-01-19 19:36:05 -0800208 // Allow cereal class access to allow these next two function to be
209 // private
210 friend class cereal::access;
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500211
Andrew Geissler58a18012018-01-19 19:36:05 -0800212 /** @brief Function required by Cereal to perform serialization.
213 *
214 * @tparam Archive - Cereal archive type (binary in our case).
215 * @param[in] archive - reference to Cereal archive.
216 * @param[in] version - Class version that enables handling
217 * a serialized data across code levels
218 */
219 template <class Archive>
220 void save(Archive& archive, const std::uint32_t version) const
221 {
Andrew Geissler769a62f2019-12-06 13:36:08 -0600222 // version is not used currently
223 (void)(version);
Andrew Geissler58a18012018-01-19 19:36:05 -0800224 archive(convertForMessage(sdbusplus::xyz::openbmc_project::State::
225 server::Host::requestedHostTransition()),
226 convertForMessage(sdbusplus::xyz::openbmc_project::State::Boot::
227 server::Progress::bootProgress()),
228 convertForMessage(
229 sdbusplus::xyz::openbmc_project::State::OperatingSystem::
230 server::Status::operatingSystemState()));
231 }
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500232
Andrew Geissler58a18012018-01-19 19:36:05 -0800233 /** @brief Function required by Cereal to perform deserialization.
234 *
235 * @tparam Archive - Cereal archive type (binary in our case).
236 * @param[in] archive - reference to Cereal archive.
237 * @param[in] version - Class version that enables handling
238 * a serialized data across code levels
239 */
240 template <class Archive>
241 void load(Archive& archive, const std::uint32_t version)
242 {
Andrew Geissler769a62f2019-12-06 13:36:08 -0600243 // version is not used currently
244 (void)(version);
Andrew Geissler58a18012018-01-19 19:36:05 -0800245 std::string reqTranState;
246 std::string bootProgress;
247 std::string osState;
248 archive(reqTranState, bootProgress, osState);
249 auto reqTran = Host::convertTransitionFromString(reqTranState);
250 // When restoring, set the requested state with persistent value
251 // but don't call the override which would execute it
252 sdbusplus::xyz::openbmc_project::State::server::Host::
253 requestedHostTransition(reqTran);
254 sdbusplus::xyz::openbmc_project::State::Boot::server::Progress::
255 bootProgress(Host::convertProgressStagesFromString(bootProgress));
256 sdbusplus::xyz::openbmc_project::State::OperatingSystem::server::
257 Status::operatingSystemState(
258 Host::convertOSStatusFromString(osState));
259 }
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500260
Andrew Geissler58a18012018-01-19 19:36:05 -0800261 /** @brief Serialize and persist requested host state
262 *
263 * @param[in] dir - pathname of file where the serialized host state will
264 * be placed.
265 *
266 * @return fs::path - pathname of persisted requested host state.
267 */
268 fs::path serialize(const fs::path& dir = fs::path(HOST_STATE_PERSIST_PATH));
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500269
Andrew Geissler58a18012018-01-19 19:36:05 -0800270 /** @brief Deserialze a persisted requested host state.
271 *
272 * @param[in] path - pathname of persisted host state file
273 *
274 * @return bool - true if the deserialization was successful, false
275 * otherwise.
276 */
277 bool deserialize(const fs::path& path);
Andrew Geissler033fc3b2017-08-30 15:11:44 -0500278
Allen.Wang79b45002022-02-10 17:59:20 +0800279 /**
280 * @brief Get target name of a HostState
281 *
282 * @param[in] state - The state of the host
283 *
284 * @return string - systemd target name of the state
285 */
286 const std::string& getTarget(HostState state);
287
288 /**
289 * @brief Get target name of a TransitionRequest
290 *
291 * @param[in] tranReq - Transition requested
292 *
293 * @return string - systemd target name of Requested transition
294 */
295 const std::string& getTarget(Transition tranReq);
296
Andrew Geissler58a18012018-01-19 19:36:05 -0800297 /** @brief Persistent sdbusplus DBus bus connection. */
298 sdbusplus::bus::bus& bus;
Andrew Geissleref621162016-12-08 12:56:21 -0600299
Andrew Geisslere4039a82020-02-11 15:51:59 -0600300 /** @brief Used to subscribe to dbus systemd JobRemoved signal **/
301 sdbusplus::bus::match_t systemdSignalJobRemoved;
Deepak Kodihalli3dd08a52017-07-25 07:34:44 -0500302
Andrew Geissler47b96122020-02-11 16:13:13 -0600303 /** @brief Used to subscribe to dbus systemd JobNew signal **/
304 sdbusplus::bus::match_t systemdSignalJobNew;
305
Potin Laic328a4c2022-03-18 23:49:37 +0800306 // Settings host objects of interest
307 settings::HostObjects settings;
Allen.Wang79b45002022-02-10 17:59:20 +0800308
309 /** @brief Host id. **/
310 const size_t id = 0;
311
312 /** @brief HostState to systemd target mapping table. **/
313 std::map<HostState, std::string> stateTargetTable;
314
315 /** @brief Requested Transition to systemd target mapping table. **/
316 std::map<Transition, std::string> transitionTargetTable;
Andrew Geissler36529022016-11-29 15:23:54 -0600317};
318
319} // namespace manager
320} // namespace state
321} // namespace phosphor