blob: 9579f30e132d79667069abe5a5a1a24204b0084c [file] [log] [blame]
Andrew Geissler5259f972021-08-30 15:46:55 -05001#include "config.h"
2
Andrew Geissler556153a2021-08-11 15:29:58 -04003#include <unistd.h>
4
5#include <phosphor-logging/elog.hpp>
Andrew Geissler8ffdb262021-09-20 15:25:19 -05006#include <phosphor-logging/lg2.hpp>
Andrew Geisslerba0163a2021-08-11 15:09:50 -04007#include <sdbusplus/bus.hpp>
8#include <sdbusplus/exception.hpp>
Andrew Geissler556153a2021-08-11 15:29:58 -04009#include <xyz/openbmc_project/Logging/Create/server.hpp>
10#include <xyz/openbmc_project/Logging/Entry/server.hpp>
NodeMan9780db4752022-05-04 09:06:40 -050011#include <xyz/openbmc_project/State/Boot/Progress/server.hpp>
Andrew Geisslerba0163a2021-08-11 15:09:50 -040012
13#include <cstdlib>
Andrew Geissler5259f972021-08-30 15:46:55 -050014#include <fstream>
Andrew Geisslerba0163a2021-08-11 15:09:50 -040015#include <string>
16
Andrew Geissler8ffdb262021-09-20 15:25:19 -050017namespace phosphor
18{
19namespace state
20{
21namespace manager
22{
23
24PHOSPHOR_LOG2_USING;
25
Andrew Geisslerba0163a2021-08-11 15:09:50 -040026constexpr auto HOST_STATE_SVC = "xyz.openbmc_project.State.Host";
27constexpr auto HOST_STATE_PATH = "/xyz/openbmc_project/state/host0";
28constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
29constexpr auto BOOT_STATE_INTF = "xyz.openbmc_project.State.Boot.Progress";
30constexpr auto BOOT_PROGRESS_PROP = "BootProgress";
31
Andrew Geissler556153a2021-08-11 15:29:58 -040032constexpr auto LOGGING_SVC = "xyz.openbmc_project.Logging";
33constexpr auto LOGGING_PATH = "/xyz/openbmc_project/logging";
34constexpr auto LOGGING_CREATE_INTF = "xyz.openbmc_project.Logging.Create";
35
Andrew Geissler7b01b0b2021-08-11 16:14:49 -040036constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
37constexpr auto SYSTEMD_OBJ_PATH = "/org/freedesktop/systemd1";
38constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
39constexpr auto HOST_STATE_QUIESCE_TGT = "obmc-host-quiesce@0.target";
40
Patrick Williamsf053e6f2022-07-22 19:26:54 -050041bool wasHostBooting(sdbusplus::bus_t& bus)
Andrew Geisslerba0163a2021-08-11 15:09:50 -040042{
43 try
44 {
NodeMan9780db4752022-05-04 09:06:40 -050045 using ProgressStages = sdbusplus::xyz::openbmc_project::State::Boot::
46 server::Progress::ProgressStages;
47
Andrew Geisslerba0163a2021-08-11 15:09:50 -040048 auto method = bus.new_method_call(HOST_STATE_SVC, HOST_STATE_PATH,
49 PROPERTY_INTERFACE, "Get");
50 method.append(BOOT_STATE_INTF, BOOT_PROGRESS_PROP);
51
52 auto response = bus.call(method);
53
NodeMan9780db4752022-05-04 09:06:40 -050054 std::variant<ProgressStages> bootProgressV;
55 response.read(bootProgressV);
56 auto bootProgress = std::get<ProgressStages>(bootProgressV);
Andrew Geisslerba0163a2021-08-11 15:09:50 -040057
NodeMan9780db4752022-05-04 09:06:40 -050058 if (bootProgress == ProgressStages::Unspecified)
Andrew Geisslerba0163a2021-08-11 15:09:50 -040059 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -050060 info("Host was not booting before BMC reboot");
Andrew Geisslerba0163a2021-08-11 15:09:50 -040061 return false;
62 }
63
Andrew Geissler8ffdb262021-09-20 15:25:19 -050064 info("Host was booting before BMC reboot: {BOOTPROGRESS}",
NodeMan9780db4752022-05-04 09:06:40 -050065 "BOOTPROGRESS", bootProgress);
Andrew Geisslerba0163a2021-08-11 15:09:50 -040066 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -050067 catch (const sdbusplus::exception_t& e)
Andrew Geisslerba0163a2021-08-11 15:09:50 -040068 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -050069 error("Error reading BootProgress, error {ERROR}, service {SERVICE}, "
70 "path {PATH}",
71 "ERROR", e, "SERVICE", HOST_STATE_SVC, "PATH", HOST_STATE_PATH);
Andrew Geisslerba0163a2021-08-11 15:09:50 -040072
73 throw;
74 }
75
76 return true;
77}
78
Patrick Williamsf053e6f2022-07-22 19:26:54 -050079void createErrorLog(sdbusplus::bus_t& bus)
Andrew Geissler556153a2021-08-11 15:29:58 -040080{
81 try
82 {
83 // Create interface requires something for additionalData
84 std::map<std::string, std::string> additionalData;
85 additionalData.emplace("_PID", std::to_string(getpid()));
86
87 static constexpr auto errorMessage =
88 "xyz.openbmc_project.State.Error.HostNotRunning";
89 auto method = bus.new_method_call(LOGGING_SVC, LOGGING_PATH,
90 LOGGING_CREATE_INTF, "Create");
Patrick Williams7e969cb2023-08-23 16:24:23 -050091 method.append(errorMessage,
92 sdbusplus::server::xyz::openbmc_project::logging::Entry::
93 Level::Error,
94 additionalData);
Andrew Geissler556153a2021-08-11 15:29:58 -040095 auto resp = bus.call(method);
96 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -050097 catch (const sdbusplus::exception_t& e)
Andrew Geissler556153a2021-08-11 15:29:58 -040098 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -050099 error(
100 "sdbusplus D-Bus call exception, error {ERROR}, objpath {OBJPATH}, "
101 "interface {INTERFACE}",
102 "ERROR", e, "OBJPATH", LOGGING_PATH, "INTERFACE",
103 LOGGING_CREATE_INTF);
Andrew Geissler556153a2021-08-11 15:29:58 -0400104
105 throw std::runtime_error(
106 "Error in invoking D-Bus logging create interface");
107 }
Patrick Williams8583b3b2021-10-06 12:19:20 -0500108 catch (const std::exception& e)
Andrew Geissler556153a2021-08-11 15:29:58 -0400109 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500110 error("D-bus call exception: {ERROR}", "ERROR", e);
Andrew Geissler556153a2021-08-11 15:29:58 -0400111 throw e;
112 }
113}
114
Andrew Geissler5259f972021-08-30 15:46:55 -0500115// Once CHASSIS_ON_FILE is removed, the obmc-chassis-poweron@.target has
116// completed and the phosphor-chassis-state-manager code has processed it.
117bool isChassisTargetComplete()
118{
119 auto size = std::snprintf(nullptr, 0, CHASSIS_ON_FILE, 0);
120 size++; // null
121 std::unique_ptr<char[]> buf(new char[size]);
122 std::snprintf(buf.get(), size, CHASSIS_ON_FILE, 0);
123
124 std::ifstream f(buf.get());
125 return !f.good();
126}
127
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500128void moveToHostQuiesce(sdbusplus::bus_t& bus)
Andrew Geissler7b01b0b2021-08-11 16:14:49 -0400129{
130 try
131 {
132 auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH,
133 SYSTEMD_INTERFACE, "StartUnit");
134
135 method.append(HOST_STATE_QUIESCE_TGT);
136 method.append("replace");
137
138 bus.call_noreply(method);
139 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500140 catch (const sdbusplus::exception_t& e)
Andrew Geissler7b01b0b2021-08-11 16:14:49 -0400141 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500142 error("sdbusplus call exception starting quiesce target: {ERROR}",
143 "ERROR", e);
Andrew Geissler7b01b0b2021-08-11 16:14:49 -0400144
145 throw std::runtime_error(
146 "Error in invoking D-Bus systemd StartUnit method");
147 }
148}
149
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500150} // namespace manager
151} // namespace state
152} // namespace phosphor
153
Andrew Geisslerba0163a2021-08-11 15:09:50 -0400154int main()
155{
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500156 using namespace phosphor::state::manager;
157 PHOSPHOR_LOG2_USING;
Andrew Geisslerba0163a2021-08-11 15:09:50 -0400158
159 auto bus = sdbusplus::bus::new_default();
160
Andrew Geissler5259f972021-08-30 15:46:55 -0500161 // Chassis power is on if this service starts but need to wait for the
162 // obmc-chassis-poweron@.target to complete before potentially initiating
163 // another systemd target transition (i.e. Quiesce->Reboot)
164 while (!isChassisTargetComplete())
165 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500166 debug("Waiting for chassis on target to complete");
Andrew Geissler5259f972021-08-30 15:46:55 -0500167 std::this_thread::sleep_for(std::chrono::seconds(1));
168
169 // There is no timeout here, wait until it happens or until system
170 // is powered off and this service is stopped
171 }
172
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500173 info("Chassis power on has completed, checking if host is "
174 "still running after the BMC reboot");
Andrew Geisslerba0163a2021-08-11 15:09:50 -0400175
176 // Check the last BootProgeress to see if the host was booting before
177 // the BMC reboot occurred
178 if (!wasHostBooting(bus))
179 {
180 return 0;
181 }
182
183 // Host was booting before the BMC reboot so log an error and go to host
184 // quiesce target
Andrew Geissler556153a2021-08-11 15:29:58 -0400185 createErrorLog(bus);
Andrew Geissler7b01b0b2021-08-11 16:14:49 -0400186 moveToHostQuiesce(bus);
Andrew Geisslerba0163a2021-08-11 15:09:50 -0400187
188 return 0;
189}