blob: 529e29801376787183635ef007e83ba61b2f3c8f [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 Geisslerba0163a2021-08-11 15:09:50 -04006#include <phosphor-logging/log.hpp>
7#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>
Andrew Geisslerba0163a2021-08-11 15:09:50 -040011
12#include <cstdlib>
Andrew Geissler5259f972021-08-30 15:46:55 -050013#include <fstream>
Andrew Geisslerba0163a2021-08-11 15:09:50 -040014#include <string>
15
16constexpr auto HOST_STATE_SVC = "xyz.openbmc_project.State.Host";
17constexpr auto HOST_STATE_PATH = "/xyz/openbmc_project/state/host0";
18constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
19constexpr auto BOOT_STATE_INTF = "xyz.openbmc_project.State.Boot.Progress";
20constexpr auto BOOT_PROGRESS_PROP = "BootProgress";
21
Andrew Geissler556153a2021-08-11 15:29:58 -040022constexpr auto LOGGING_SVC = "xyz.openbmc_project.Logging";
23constexpr auto LOGGING_PATH = "/xyz/openbmc_project/logging";
24constexpr auto LOGGING_CREATE_INTF = "xyz.openbmc_project.Logging.Create";
25
Andrew Geisslerba0163a2021-08-11 15:09:50 -040026using namespace phosphor::logging;
27
28bool wasHostBooting(sdbusplus::bus::bus& bus)
29{
30 try
31 {
32 auto method = bus.new_method_call(HOST_STATE_SVC, HOST_STATE_PATH,
33 PROPERTY_INTERFACE, "Get");
34 method.append(BOOT_STATE_INTF, BOOT_PROGRESS_PROP);
35
36 auto response = bus.call(method);
37
38 std::variant<std::string> bootProgress;
39 response.read(bootProgress);
40
41 if (std::get<std::string>(bootProgress) ==
42 "xyz.openbmc_project.State.Boot.Progress.ProgressStages."
43 "Unspecified")
44 {
45 log<level::INFO>("Host was not booting before BMC reboot");
46 return false;
47 }
48
49 log<level::INFO>("Host was booting before BMC reboot",
50 entry("BOOTPROGRESS=%s",
51 std::get<std::string>(bootProgress).c_str()));
52 }
53 catch (const sdbusplus::exception::exception& e)
54 {
55 log<level::ERR>("Error reading BootProgress",
56 entry("ERROR=%s", e.what()),
57 entry("SERVICE=%s", HOST_STATE_SVC),
58 entry("PATH=%s", HOST_STATE_PATH));
59
60 throw;
61 }
62
63 return true;
64}
65
Andrew Geissler556153a2021-08-11 15:29:58 -040066void createErrorLog(sdbusplus::bus::bus& bus)
67{
68 try
69 {
70 // Create interface requires something for additionalData
71 std::map<std::string, std::string> additionalData;
72 additionalData.emplace("_PID", std::to_string(getpid()));
73
74 static constexpr auto errorMessage =
75 "xyz.openbmc_project.State.Error.HostNotRunning";
76 auto method = bus.new_method_call(LOGGING_SVC, LOGGING_PATH,
77 LOGGING_CREATE_INTF, "Create");
78 auto level =
79 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
80 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level::
81 Error);
82 method.append(errorMessage, level, additionalData);
83 auto resp = bus.call(method);
84 }
85 catch (const sdbusplus::exception::exception& e)
86 {
87 log<level::ERR>("sdbusplus D-Bus call exception",
88 entry("OBJPATH=%s", LOGGING_PATH),
89 entry("INTERFACE=%s", LOGGING_CREATE_INTF),
90 entry("EXCEPTION=%s", e.what()));
91
92 throw std::runtime_error(
93 "Error in invoking D-Bus logging create interface");
94 }
95 catch (std::exception& e)
96 {
97 log<level::ERR>("D-bus call exception",
98 entry("EXCEPTION=%s", e.what()));
99 throw e;
100 }
101}
102
Andrew Geissler5259f972021-08-30 15:46:55 -0500103// Once CHASSIS_ON_FILE is removed, the obmc-chassis-poweron@.target has
104// completed and the phosphor-chassis-state-manager code has processed it.
105bool isChassisTargetComplete()
106{
107 auto size = std::snprintf(nullptr, 0, CHASSIS_ON_FILE, 0);
108 size++; // null
109 std::unique_ptr<char[]> buf(new char[size]);
110 std::snprintf(buf.get(), size, CHASSIS_ON_FILE, 0);
111
112 std::ifstream f(buf.get());
113 return !f.good();
114}
115
Andrew Geisslerba0163a2021-08-11 15:09:50 -0400116int main()
117{
118
119 auto bus = sdbusplus::bus::new_default();
120
Andrew Geissler5259f972021-08-30 15:46:55 -0500121 // Chassis power is on if this service starts but need to wait for the
122 // obmc-chassis-poweron@.target to complete before potentially initiating
123 // another systemd target transition (i.e. Quiesce->Reboot)
124 while (!isChassisTargetComplete())
125 {
126 log<level::DEBUG>("Waiting for chassis on target to complete");
127 std::this_thread::sleep_for(std::chrono::seconds(1));
128
129 // There is no timeout here, wait until it happens or until system
130 // is powered off and this service is stopped
131 }
132
133 log<level::INFO>("Chassis power on has completed, checking if host is "
134 "still running after the BMC reboot");
Andrew Geisslerba0163a2021-08-11 15:09:50 -0400135
136 // Check the last BootProgeress to see if the host was booting before
137 // the BMC reboot occurred
138 if (!wasHostBooting(bus))
139 {
140 return 0;
141 }
142
143 // Host was booting before the BMC reboot so log an error and go to host
144 // quiesce target
Andrew Geissler556153a2021-08-11 15:29:58 -0400145 createErrorLog(bus);
146
Andrew Geisslerba0163a2021-08-11 15:09:50 -0400147 // TODO Move to Host Quiesce
148
149 return 0;
150}