blob: e055abcea0e750d585822ed2c56bbaf0223f8450 [file] [log] [blame]
Andrew Geisslere426b582020-05-28 12:40:55 -05001#include "config.h"
2
Andrew Geissler0971dea2017-03-28 14:32:40 -05003#include <unistd.h>
Andrew Geisslere426b582020-05-28 12:40:55 -05004
5#include <phosphor-logging/log.hpp>
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 Geissler0971dea2017-03-28 14:32:40 -05008#include <xyz/openbmc_project/Control/Host/server.hpp>
Andrew Geisslere426b582020-05-28 12:40:55 -05009
10#include <cstdio>
11#include <cstdlib>
12#include <fstream>
13#include <iostream>
Andrew Geisslerb09463d2017-03-24 15:55:17 -050014
Andrew Geisslereeaccf82017-03-28 15:23:27 -050015using namespace std::literals;
Andrew Geisslerb09463d2017-03-24 15:55:17 -050016using namespace phosphor::logging;
Andrew Geissler0971dea2017-03-28 14:32:40 -050017using namespace sdbusplus::xyz::openbmc_project::Control::server;
Anthony Wilson32c532e2018-10-25 21:56:07 -050018using sdbusplus::exception::SdBusError;
Andrew Geissler0971dea2017-03-28 14:32:40 -050019
Andrew Geisslereeaccf82017-03-28 15:23:27 -050020// Required strings for sending the msg to check on host
21constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
22constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
23constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
Andrew Geissler624161c2019-04-09 16:01:01 -050024constexpr auto CONTROL_HOST_DEFAULT_SVC = "xyz.openbmc_project.Control.Host";
Andrew Geisslereeaccf82017-03-28 15:23:27 -050025constexpr auto CONTROL_HOST_PATH = "/xyz/openbmc_project/control/host0";
26constexpr auto CONTROL_HOST_INTERFACE = "xyz.openbmc_project.Control.Host";
Andrew Geissler0971dea2017-03-28 14:32:40 -050027
Andrew Geissler58a18012018-01-19 19:36:05 -080028bool cmdDone = false;
Andrew Geissler0971dea2017-03-28 14:32:40 -050029bool hostRunning = false;
30
31// Function called on host control signals
Andrew Geissler58a18012018-01-19 19:36:05 -080032static int hostControlSignal(sd_bus_message* msg, void* userData,
Andrew Geissler0971dea2017-03-28 14:32:40 -050033 sd_bus_error* retError)
34{
Andrew Geissler769a62f2019-12-06 13:36:08 -060035 // retError and userData are not used
36 (void)(retError);
37 (void)(userData);
Andrew Geissler0971dea2017-03-28 14:32:40 -050038 std::string cmdCompleted{};
39 std::string cmdStatus{};
40
41 auto sdPlusMsg = sdbusplus::message::message(msg);
42 sdPlusMsg.read(cmdCompleted, cmdStatus);
43
44 log<level::DEBUG>("Host control signal values",
Andrew Geissler58a18012018-01-19 19:36:05 -080045 entry("COMMAND=%s", cmdCompleted.c_str()),
46 entry("STATUS=%s", cmdStatus.c_str()));
Andrew Geissler0971dea2017-03-28 14:32:40 -050047
48 // Verify it's the command this code is interested in and then check status
Andrew Geissler58a18012018-01-19 19:36:05 -080049 if (Host::convertCommandFromString(cmdCompleted) ==
50 Host::Command::Heartbeat)
Andrew Geissler0971dea2017-03-28 14:32:40 -050051 {
52 cmdDone = true;
53
Andrew Geissler58a18012018-01-19 19:36:05 -080054 if (Host::convertResultFromString(cmdStatus) == Host::Result::Success)
Andrew Geissler0971dea2017-03-28 14:32:40 -050055 {
56 hostRunning = true;
57 }
58 }
59
60 return 0;
61}
Andrew Geisslerb09463d2017-03-24 15:55:17 -050062
Andrew Geisslereeaccf82017-03-28 15:23:27 -050063// Send hearbeat to host to determine if it's running
64void sendHeartbeat(sdbusplus::bus::bus& bus)
65{
Andrew Geissler58a18012018-01-19 19:36:05 -080066 auto mapper = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
67 MAPPER_INTERFACE, "GetObject");
Andrew Geisslereeaccf82017-03-28 15:23:27 -050068
69 mapper.append(CONTROL_HOST_PATH,
70 std::vector<std::string>({CONTROL_HOST_INTERFACE}));
Andrew Geisslereeaccf82017-03-28 15:23:27 -050071
72 std::map<std::string, std::vector<std::string>> mapperResponse;
Anthony Wilson32c532e2018-10-25 21:56:07 -050073
74 try
75 {
76 auto mapperResponseMsg = bus.call(mapper);
77 mapperResponseMsg.read(mapperResponse);
78 }
79 catch (const SdBusError& e)
80 {
Andrew Geissler624161c2019-04-09 16:01:01 -050081 log<level::INFO>("Error in mapper call for control host, use default "
82 "service",
83 entry("ERROR=%s", e.what()));
Anthony Wilson32c532e2018-10-25 21:56:07 -050084 }
85
Andrew Geissler624161c2019-04-09 16:01:01 -050086 std::string host;
87 if (!mapperResponse.empty())
Andrew Geisslereeaccf82017-03-28 15:23:27 -050088 {
Andrew Geissler624161c2019-04-09 16:01:01 -050089 log<level::DEBUG>("Use mapper response");
90 host = mapperResponse.begin()->first;
Andrew Geisslereeaccf82017-03-28 15:23:27 -050091 }
Andrew Geissler624161c2019-04-09 16:01:01 -050092 else
93 {
94 log<level::DEBUG>("Use hard coded host");
95 host = CONTROL_HOST_DEFAULT_SVC;
96 }
Andrew Geisslereeaccf82017-03-28 15:23:27 -050097
Andrew Geissler58a18012018-01-19 19:36:05 -080098 auto method = bus.new_method_call(host.c_str(), CONTROL_HOST_PATH,
99 CONTROL_HOST_INTERFACE, "Execute");
Andrew Geisslereeaccf82017-03-28 15:23:27 -0500100 method.append(convertForMessage(Host::Command::Heartbeat).c_str());
101
Anthony Wilson32c532e2018-10-25 21:56:07 -0500102 try
Andrew Geisslereeaccf82017-03-28 15:23:27 -0500103 {
Anthony Wilson32c532e2018-10-25 21:56:07 -0500104 auto reply = bus.call(method);
105 }
106 catch (const SdBusError& e)
107 {
108 log<level::ERR>("Error in call to control host Execute",
109 entry("ERROR=%s", e.what()));
110 throw;
Andrew Geisslereeaccf82017-03-28 15:23:27 -0500111 }
112
113 return;
114}
115
Andrew Geissler769a62f2019-12-06 13:36:08 -0600116int main()
Andrew Geisslerb09463d2017-03-24 15:55:17 -0500117{
118 log<level::INFO>("Check if host is running");
119
Andrew Geissler0971dea2017-03-28 14:32:40 -0500120 auto bus = sdbusplus::bus::new_default();
Andrew Geisslerb09463d2017-03-24 15:55:17 -0500121
Andrew Geissler66060bf2019-09-12 13:47:05 -0500122 std::string s = "type='signal',member='CommandComplete',path='"s +
123 CONTROL_HOST_PATH + "',interface='" +
124 CONTROL_HOST_INTERFACE + "'";
Andrew Geisslereeaccf82017-03-28 15:23:27 -0500125
Andrew Geissler0971dea2017-03-28 14:32:40 -0500126 // Setup Signal Handler
Andrew Geissler58a18012018-01-19 19:36:05 -0800127 sdbusplus::bus::match::match hostControlSignals(bus, s.c_str(),
128 hostControlSignal, nullptr);
Andrew Geissler0971dea2017-03-28 14:32:40 -0500129
Andrew Geisslereeaccf82017-03-28 15:23:27 -0500130 sendHeartbeat(bus);
Andrew Geisslerb09463d2017-03-24 15:55:17 -0500131
132 // Wait for signal
Andrew Geissler58a18012018-01-19 19:36:05 -0800133 while (!cmdDone)
Andrew Geissler0971dea2017-03-28 14:32:40 -0500134 {
135 bus.process_discard();
Andrew Geissler58a18012018-01-19 19:36:05 -0800136 if (cmdDone)
137 break;
Andrew Geissler0971dea2017-03-28 14:32:40 -0500138 bus.wait();
139 }
Andrew Geisslerb09463d2017-03-24 15:55:17 -0500140
141 // If host running then create file
Andrew Geissler58a18012018-01-19 19:36:05 -0800142 if (hostRunning)
Andrew Geissler0971dea2017-03-28 14:32:40 -0500143 {
Andrew Geissler0971dea2017-03-28 14:32:40 -0500144 log<level::INFO>("Host is running!");
Andrew Geissler07d0ed52017-03-28 15:44:18 -0500145 // Create file for host instance and create in filesystem to indicate
146 // to services that host is running
Andrew Geissler58a18012018-01-19 19:36:05 -0800147 auto size = std::snprintf(nullptr, 0, HOST_RUNNING_FILE, 0);
Andrew Geissler0135bd52017-05-09 13:54:10 -0500148 size++; // null
149 std::unique_ptr<char[]> buf(new char[size]);
Andrew Geissler58a18012018-01-19 19:36:05 -0800150 std::snprintf(buf.get(), size, HOST_RUNNING_FILE, 0);
Andrew Geissler07d0ed52017-03-28 15:44:18 -0500151 std::ofstream outfile(buf.get());
152 outfile.close();
153 }
154 else
155 {
156 log<level::INFO>("Host is not running!");
Andrew Geissler0971dea2017-03-28 14:32:40 -0500157 }
Andrew Geisslerb09463d2017-03-24 15:55:17 -0500158
159 return 0;
160}