blob: b9f5327a82534685496c2790facc09e708891064 [file] [log] [blame]
Andrew Geisslerb09463d2017-03-24 15:55:17 -05001#include <cstdlib>
Andrew Geissler0971dea2017-03-28 14:32:40 -05002#include <unistd.h>
Andrew Geissler07d0ed52017-03-28 15:44:18 -05003#include <iostream>
4#include <fstream>
5#include <cstdio>
Andrew Geisslerb09463d2017-03-24 15:55:17 -05006#include <sdbusplus/bus.hpp>
Anthony Wilson32c532e2018-10-25 21:56:07 -05007#include <sdbusplus/exception.hpp>
Andrew Geisslerb09463d2017-03-24 15:55:17 -05008#include <phosphor-logging/log.hpp>
Andrew Geissler0971dea2017-03-28 14:32:40 -05009#include <xyz/openbmc_project/Control/Host/server.hpp>
Andrew Geissler07d0ed52017-03-28 15:44:18 -050010#include <config.h>
Andrew Geisslerb09463d2017-03-24 15:55:17 -050011
Andrew Geisslereeaccf82017-03-28 15:23:27 -050012using namespace std::literals;
Andrew Geisslerb09463d2017-03-24 15:55:17 -050013using namespace phosphor::logging;
Andrew Geissler0971dea2017-03-28 14:32:40 -050014using namespace sdbusplus::xyz::openbmc_project::Control::server;
Anthony Wilson32c532e2018-10-25 21:56:07 -050015using sdbusplus::exception::SdBusError;
Andrew Geissler0971dea2017-03-28 14:32:40 -050016
Andrew Geisslereeaccf82017-03-28 15:23:27 -050017// Required strings for sending the msg to check on host
18constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
19constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
20constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
Andrew Geissler624161c2019-04-09 16:01:01 -050021constexpr auto CONTROL_HOST_DEFAULT_SVC = "xyz.openbmc_project.Control.Host";
Andrew Geisslereeaccf82017-03-28 15:23:27 -050022constexpr auto CONTROL_HOST_PATH = "/xyz/openbmc_project/control/host0";
23constexpr auto CONTROL_HOST_INTERFACE = "xyz.openbmc_project.Control.Host";
Andrew Geissler0971dea2017-03-28 14:32:40 -050024
Andrew Geissler58a18012018-01-19 19:36:05 -080025bool cmdDone = false;
Andrew Geissler0971dea2017-03-28 14:32:40 -050026bool hostRunning = false;
27
28// Function called on host control signals
Andrew Geissler58a18012018-01-19 19:36:05 -080029static int hostControlSignal(sd_bus_message* msg, void* userData,
Andrew Geissler0971dea2017-03-28 14:32:40 -050030 sd_bus_error* retError)
31{
32 std::string cmdCompleted{};
33 std::string cmdStatus{};
34
35 auto sdPlusMsg = sdbusplus::message::message(msg);
36 sdPlusMsg.read(cmdCompleted, cmdStatus);
37
38 log<level::DEBUG>("Host control signal values",
Andrew Geissler58a18012018-01-19 19:36:05 -080039 entry("COMMAND=%s", cmdCompleted.c_str()),
40 entry("STATUS=%s", cmdStatus.c_str()));
Andrew Geissler0971dea2017-03-28 14:32:40 -050041
42 // Verify it's the command this code is interested in and then check status
Andrew Geissler58a18012018-01-19 19:36:05 -080043 if (Host::convertCommandFromString(cmdCompleted) ==
44 Host::Command::Heartbeat)
Andrew Geissler0971dea2017-03-28 14:32:40 -050045 {
46 cmdDone = true;
47
Andrew Geissler58a18012018-01-19 19:36:05 -080048 if (Host::convertResultFromString(cmdStatus) == Host::Result::Success)
Andrew Geissler0971dea2017-03-28 14:32:40 -050049 {
50 hostRunning = true;
51 }
52 }
53
54 return 0;
55}
Andrew Geisslerb09463d2017-03-24 15:55:17 -050056
Andrew Geisslereeaccf82017-03-28 15:23:27 -050057// Send hearbeat to host to determine if it's running
58void sendHeartbeat(sdbusplus::bus::bus& bus)
59{
Andrew Geissler58a18012018-01-19 19:36:05 -080060 auto mapper = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
61 MAPPER_INTERFACE, "GetObject");
Andrew Geisslereeaccf82017-03-28 15:23:27 -050062
63 mapper.append(CONTROL_HOST_PATH,
64 std::vector<std::string>({CONTROL_HOST_INTERFACE}));
Andrew Geisslereeaccf82017-03-28 15:23:27 -050065
66 std::map<std::string, std::vector<std::string>> mapperResponse;
Anthony Wilson32c532e2018-10-25 21:56:07 -050067
68 try
69 {
70 auto mapperResponseMsg = bus.call(mapper);
71 mapperResponseMsg.read(mapperResponse);
72 }
73 catch (const SdBusError& e)
74 {
Andrew Geissler624161c2019-04-09 16:01:01 -050075 log<level::INFO>("Error in mapper call for control host, use default "
76 "service",
77 entry("ERROR=%s", e.what()));
Anthony Wilson32c532e2018-10-25 21:56:07 -050078 }
79
Andrew Geissler624161c2019-04-09 16:01:01 -050080 std::string host;
81 if (!mapperResponse.empty())
Andrew Geisslereeaccf82017-03-28 15:23:27 -050082 {
Andrew Geissler624161c2019-04-09 16:01:01 -050083 log<level::DEBUG>("Use mapper response");
84 host = mapperResponse.begin()->first;
Andrew Geisslereeaccf82017-03-28 15:23:27 -050085 }
Andrew Geissler624161c2019-04-09 16:01:01 -050086 else
87 {
88 log<level::DEBUG>("Use hard coded host");
89 host = CONTROL_HOST_DEFAULT_SVC;
90 }
Andrew Geisslereeaccf82017-03-28 15:23:27 -050091
Andrew Geissler58a18012018-01-19 19:36:05 -080092 auto method = bus.new_method_call(host.c_str(), CONTROL_HOST_PATH,
93 CONTROL_HOST_INTERFACE, "Execute");
Andrew Geisslereeaccf82017-03-28 15:23:27 -050094 method.append(convertForMessage(Host::Command::Heartbeat).c_str());
95
Anthony Wilson32c532e2018-10-25 21:56:07 -050096 try
Andrew Geisslereeaccf82017-03-28 15:23:27 -050097 {
Anthony Wilson32c532e2018-10-25 21:56:07 -050098 auto reply = bus.call(method);
99 }
100 catch (const SdBusError& e)
101 {
102 log<level::ERR>("Error in call to control host Execute",
103 entry("ERROR=%s", e.what()));
104 throw;
Andrew Geisslereeaccf82017-03-28 15:23:27 -0500105 }
106
107 return;
108}
109
Andrew Geissler58a18012018-01-19 19:36:05 -0800110int main(int argc, char* argv[])
Andrew Geisslerb09463d2017-03-24 15:55:17 -0500111{
112 log<level::INFO>("Check if host is running");
113
Andrew Geissler0971dea2017-03-28 14:32:40 -0500114 auto bus = sdbusplus::bus::new_default();
Andrew Geisslerb09463d2017-03-24 15:55:17 -0500115
Andrew Geissler66060bf2019-09-12 13:47:05 -0500116 std::string s = "type='signal',member='CommandComplete',path='"s +
117 CONTROL_HOST_PATH + "',interface='" +
118 CONTROL_HOST_INTERFACE + "'";
Andrew Geisslereeaccf82017-03-28 15:23:27 -0500119
Andrew Geissler0971dea2017-03-28 14:32:40 -0500120 // Setup Signal Handler
Andrew Geissler58a18012018-01-19 19:36:05 -0800121 sdbusplus::bus::match::match hostControlSignals(bus, s.c_str(),
122 hostControlSignal, nullptr);
Andrew Geissler0971dea2017-03-28 14:32:40 -0500123
Andrew Geisslereeaccf82017-03-28 15:23:27 -0500124 sendHeartbeat(bus);
Andrew Geisslerb09463d2017-03-24 15:55:17 -0500125
126 // Wait for signal
Andrew Geissler58a18012018-01-19 19:36:05 -0800127 while (!cmdDone)
Andrew Geissler0971dea2017-03-28 14:32:40 -0500128 {
129 bus.process_discard();
Andrew Geissler58a18012018-01-19 19:36:05 -0800130 if (cmdDone)
131 break;
Andrew Geissler0971dea2017-03-28 14:32:40 -0500132 bus.wait();
133 }
Andrew Geisslerb09463d2017-03-24 15:55:17 -0500134
135 // If host running then create file
Andrew Geissler58a18012018-01-19 19:36:05 -0800136 if (hostRunning)
Andrew Geissler0971dea2017-03-28 14:32:40 -0500137 {
Andrew Geissler0971dea2017-03-28 14:32:40 -0500138 log<level::INFO>("Host is running!");
Andrew Geissler07d0ed52017-03-28 15:44:18 -0500139 // Create file for host instance and create in filesystem to indicate
140 // to services that host is running
Andrew Geissler58a18012018-01-19 19:36:05 -0800141 auto size = std::snprintf(nullptr, 0, HOST_RUNNING_FILE, 0);
Andrew Geissler0135bd52017-05-09 13:54:10 -0500142 size++; // null
143 std::unique_ptr<char[]> buf(new char[size]);
Andrew Geissler58a18012018-01-19 19:36:05 -0800144 std::snprintf(buf.get(), size, HOST_RUNNING_FILE, 0);
Andrew Geissler07d0ed52017-03-28 15:44:18 -0500145 std::ofstream outfile(buf.get());
146 outfile.close();
147 }
148 else
149 {
150 log<level::INFO>("Host is not running!");
Andrew Geissler0971dea2017-03-28 14:32:40 -0500151 }
Andrew Geisslerb09463d2017-03-24 15:55:17 -0500152
153 return 0;
154}