blob: 311e6e22d3fd853b82cb86c85df779b3d83da9ea [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";
21constexpr auto CONTROL_HOST_PATH = "/xyz/openbmc_project/control/host0";
22constexpr auto CONTROL_HOST_INTERFACE = "xyz.openbmc_project.Control.Host";
Andrew Geissler0971dea2017-03-28 14:32:40 -050023
Andrew Geissler58a18012018-01-19 19:36:05 -080024bool cmdDone = false;
Andrew Geissler0971dea2017-03-28 14:32:40 -050025bool hostRunning = false;
26
27// Function called on host control signals
Andrew Geissler58a18012018-01-19 19:36:05 -080028static int hostControlSignal(sd_bus_message* msg, void* userData,
Andrew Geissler0971dea2017-03-28 14:32:40 -050029 sd_bus_error* retError)
30{
31 std::string cmdCompleted{};
32 std::string cmdStatus{};
33
34 auto sdPlusMsg = sdbusplus::message::message(msg);
35 sdPlusMsg.read(cmdCompleted, cmdStatus);
36
37 log<level::DEBUG>("Host control signal values",
Andrew Geissler58a18012018-01-19 19:36:05 -080038 entry("COMMAND=%s", cmdCompleted.c_str()),
39 entry("STATUS=%s", cmdStatus.c_str()));
Andrew Geissler0971dea2017-03-28 14:32:40 -050040
41 // Verify it's the command this code is interested in and then check status
Andrew Geissler58a18012018-01-19 19:36:05 -080042 if (Host::convertCommandFromString(cmdCompleted) ==
43 Host::Command::Heartbeat)
Andrew Geissler0971dea2017-03-28 14:32:40 -050044 {
45 cmdDone = true;
46
Andrew Geissler58a18012018-01-19 19:36:05 -080047 if (Host::convertResultFromString(cmdStatus) == Host::Result::Success)
Andrew Geissler0971dea2017-03-28 14:32:40 -050048 {
49 hostRunning = true;
50 }
51 }
52
53 return 0;
54}
Andrew Geisslerb09463d2017-03-24 15:55:17 -050055
Andrew Geisslereeaccf82017-03-28 15:23:27 -050056// Send hearbeat to host to determine if it's running
57void sendHeartbeat(sdbusplus::bus::bus& bus)
58{
Andrew Geissler58a18012018-01-19 19:36:05 -080059 auto mapper = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
60 MAPPER_INTERFACE, "GetObject");
Andrew Geisslereeaccf82017-03-28 15:23:27 -050061
62 mapper.append(CONTROL_HOST_PATH,
63 std::vector<std::string>({CONTROL_HOST_INTERFACE}));
Andrew Geisslereeaccf82017-03-28 15:23:27 -050064
65 std::map<std::string, std::vector<std::string>> mapperResponse;
Anthony Wilson32c532e2018-10-25 21:56:07 -050066
67 try
68 {
69 auto mapperResponseMsg = bus.call(mapper);
70 mapperResponseMsg.read(mapperResponse);
71 }
72 catch (const SdBusError& e)
73 {
74 log<level::ERR>("Error in mapper call for control host",
75 entry("ERROR=%s", e.what()));
76 throw;
77 }
78
Andrew Geisslereeaccf82017-03-28 15:23:27 -050079 if (mapperResponse.empty())
80 {
81 log<level::ERR>("Error reading mapper resp for control host");
82 // TODO openbmc/openbmc#851 - Once available, throw returned error
83 throw std::runtime_error("Error reading mapper resp for control host");
84 }
85
86 const auto& host = mapperResponse.begin()->first;
87
Andrew Geissler58a18012018-01-19 19:36:05 -080088 auto method = bus.new_method_call(host.c_str(), CONTROL_HOST_PATH,
89 CONTROL_HOST_INTERFACE, "Execute");
Andrew Geisslereeaccf82017-03-28 15:23:27 -050090 method.append(convertForMessage(Host::Command::Heartbeat).c_str());
91
Anthony Wilson32c532e2018-10-25 21:56:07 -050092 try
Andrew Geisslereeaccf82017-03-28 15:23:27 -050093 {
Anthony Wilson32c532e2018-10-25 21:56:07 -050094 auto reply = bus.call(method);
95 }
96 catch (const SdBusError& e)
97 {
98 log<level::ERR>("Error in call to control host Execute",
99 entry("ERROR=%s", e.what()));
100 throw;
Andrew Geisslereeaccf82017-03-28 15:23:27 -0500101 }
102
103 return;
104}
105
Andrew Geissler58a18012018-01-19 19:36:05 -0800106int main(int argc, char* argv[])
Andrew Geisslerb09463d2017-03-24 15:55:17 -0500107{
108 log<level::INFO>("Check if host is running");
109
Andrew Geissler0971dea2017-03-28 14:32:40 -0500110 auto bus = sdbusplus::bus::new_default();
Andrew Geisslerb09463d2017-03-24 15:55:17 -0500111
Andrew Geisslereeaccf82017-03-28 15:23:27 -0500112 auto s = "type='signal',member='CommandComplete',path='"s +
Andrew Geissler58a18012018-01-19 19:36:05 -0800113 CONTROL_HOST_PATH + "',interface='" + CONTROL_HOST_INTERFACE + "'";
Andrew Geisslereeaccf82017-03-28 15:23:27 -0500114
Andrew Geissler0971dea2017-03-28 14:32:40 -0500115 // Setup Signal Handler
Andrew Geissler58a18012018-01-19 19:36:05 -0800116 sdbusplus::bus::match::match hostControlSignals(bus, s.c_str(),
117 hostControlSignal, nullptr);
Andrew Geissler0971dea2017-03-28 14:32:40 -0500118
Andrew Geisslereeaccf82017-03-28 15:23:27 -0500119 sendHeartbeat(bus);
Andrew Geisslerb09463d2017-03-24 15:55:17 -0500120
121 // Wait for signal
Andrew Geissler58a18012018-01-19 19:36:05 -0800122 while (!cmdDone)
Andrew Geissler0971dea2017-03-28 14:32:40 -0500123 {
124 bus.process_discard();
Andrew Geissler58a18012018-01-19 19:36:05 -0800125 if (cmdDone)
126 break;
Andrew Geissler0971dea2017-03-28 14:32:40 -0500127 bus.wait();
128 }
Andrew Geisslerb09463d2017-03-24 15:55:17 -0500129
130 // If host running then create file
Andrew Geissler58a18012018-01-19 19:36:05 -0800131 if (hostRunning)
Andrew Geissler0971dea2017-03-28 14:32:40 -0500132 {
Andrew Geissler0971dea2017-03-28 14:32:40 -0500133 log<level::INFO>("Host is running!");
Andrew Geissler07d0ed52017-03-28 15:44:18 -0500134 // Create file for host instance and create in filesystem to indicate
135 // to services that host is running
Andrew Geissler58a18012018-01-19 19:36:05 -0800136 auto size = std::snprintf(nullptr, 0, HOST_RUNNING_FILE, 0);
Andrew Geissler0135bd52017-05-09 13:54:10 -0500137 size++; // null
138 std::unique_ptr<char[]> buf(new char[size]);
Andrew Geissler58a18012018-01-19 19:36:05 -0800139 std::snprintf(buf.get(), size, HOST_RUNNING_FILE, 0);
Andrew Geissler07d0ed52017-03-28 15:44:18 -0500140 std::ofstream outfile(buf.get());
141 outfile.close();
142 }
143 else
144 {
145 log<level::INFO>("Host is not running!");
Andrew Geissler0971dea2017-03-28 14:32:40 -0500146 }
Andrew Geisslerb09463d2017-03-24 15:55:17 -0500147
148 return 0;
149}