blob: 56b22fb8c62dbafd145c8dbe401b873f0bf0200c [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 Geissler769a62f2019-12-06 13:36:08 -060010#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{
Andrew Geissler769a62f2019-12-06 13:36:08 -060032 // retError and userData are not used
33 (void)(retError);
34 (void)(userData);
Andrew Geissler0971dea2017-03-28 14:32:40 -050035 std::string cmdCompleted{};
36 std::string cmdStatus{};
37
38 auto sdPlusMsg = sdbusplus::message::message(msg);
39 sdPlusMsg.read(cmdCompleted, cmdStatus);
40
41 log<level::DEBUG>("Host control signal values",
Andrew Geissler58a18012018-01-19 19:36:05 -080042 entry("COMMAND=%s", cmdCompleted.c_str()),
43 entry("STATUS=%s", cmdStatus.c_str()));
Andrew Geissler0971dea2017-03-28 14:32:40 -050044
45 // Verify it's the command this code is interested in and then check status
Andrew Geissler58a18012018-01-19 19:36:05 -080046 if (Host::convertCommandFromString(cmdCompleted) ==
47 Host::Command::Heartbeat)
Andrew Geissler0971dea2017-03-28 14:32:40 -050048 {
49 cmdDone = true;
50
Andrew Geissler58a18012018-01-19 19:36:05 -080051 if (Host::convertResultFromString(cmdStatus) == Host::Result::Success)
Andrew Geissler0971dea2017-03-28 14:32:40 -050052 {
53 hostRunning = true;
54 }
55 }
56
57 return 0;
58}
Andrew Geisslerb09463d2017-03-24 15:55:17 -050059
Andrew Geisslereeaccf82017-03-28 15:23:27 -050060// Send hearbeat to host to determine if it's running
61void sendHeartbeat(sdbusplus::bus::bus& bus)
62{
Andrew Geissler58a18012018-01-19 19:36:05 -080063 auto mapper = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
64 MAPPER_INTERFACE, "GetObject");
Andrew Geisslereeaccf82017-03-28 15:23:27 -050065
66 mapper.append(CONTROL_HOST_PATH,
67 std::vector<std::string>({CONTROL_HOST_INTERFACE}));
Andrew Geisslereeaccf82017-03-28 15:23:27 -050068
69 std::map<std::string, std::vector<std::string>> mapperResponse;
Anthony Wilson32c532e2018-10-25 21:56:07 -050070
71 try
72 {
73 auto mapperResponseMsg = bus.call(mapper);
74 mapperResponseMsg.read(mapperResponse);
75 }
76 catch (const SdBusError& e)
77 {
Andrew Geissler624161c2019-04-09 16:01:01 -050078 log<level::INFO>("Error in mapper call for control host, use default "
79 "service",
80 entry("ERROR=%s", e.what()));
Anthony Wilson32c532e2018-10-25 21:56:07 -050081 }
82
Andrew Geissler624161c2019-04-09 16:01:01 -050083 std::string host;
84 if (!mapperResponse.empty())
Andrew Geisslereeaccf82017-03-28 15:23:27 -050085 {
Andrew Geissler624161c2019-04-09 16:01:01 -050086 log<level::DEBUG>("Use mapper response");
87 host = mapperResponse.begin()->first;
Andrew Geisslereeaccf82017-03-28 15:23:27 -050088 }
Andrew Geissler624161c2019-04-09 16:01:01 -050089 else
90 {
91 log<level::DEBUG>("Use hard coded host");
92 host = CONTROL_HOST_DEFAULT_SVC;
93 }
Andrew Geisslereeaccf82017-03-28 15:23:27 -050094
Andrew Geissler58a18012018-01-19 19:36:05 -080095 auto method = bus.new_method_call(host.c_str(), CONTROL_HOST_PATH,
96 CONTROL_HOST_INTERFACE, "Execute");
Andrew Geisslereeaccf82017-03-28 15:23:27 -050097 method.append(convertForMessage(Host::Command::Heartbeat).c_str());
98
Anthony Wilson32c532e2018-10-25 21:56:07 -050099 try
Andrew Geisslereeaccf82017-03-28 15:23:27 -0500100 {
Anthony Wilson32c532e2018-10-25 21:56:07 -0500101 auto reply = bus.call(method);
102 }
103 catch (const SdBusError& e)
104 {
105 log<level::ERR>("Error in call to control host Execute",
106 entry("ERROR=%s", e.what()));
107 throw;
Andrew Geisslereeaccf82017-03-28 15:23:27 -0500108 }
109
110 return;
111}
112
Andrew Geissler769a62f2019-12-06 13:36:08 -0600113int main()
Andrew Geisslerb09463d2017-03-24 15:55:17 -0500114{
115 log<level::INFO>("Check if host is running");
116
Andrew Geissler0971dea2017-03-28 14:32:40 -0500117 auto bus = sdbusplus::bus::new_default();
Andrew Geisslerb09463d2017-03-24 15:55:17 -0500118
Andrew Geissler66060bf2019-09-12 13:47:05 -0500119 std::string s = "type='signal',member='CommandComplete',path='"s +
120 CONTROL_HOST_PATH + "',interface='" +
121 CONTROL_HOST_INTERFACE + "'";
Andrew Geisslereeaccf82017-03-28 15:23:27 -0500122
Andrew Geissler0971dea2017-03-28 14:32:40 -0500123 // Setup Signal Handler
Andrew Geissler58a18012018-01-19 19:36:05 -0800124 sdbusplus::bus::match::match hostControlSignals(bus, s.c_str(),
125 hostControlSignal, nullptr);
Andrew Geissler0971dea2017-03-28 14:32:40 -0500126
Andrew Geisslereeaccf82017-03-28 15:23:27 -0500127 sendHeartbeat(bus);
Andrew Geisslerb09463d2017-03-24 15:55:17 -0500128
129 // Wait for signal
Andrew Geissler58a18012018-01-19 19:36:05 -0800130 while (!cmdDone)
Andrew Geissler0971dea2017-03-28 14:32:40 -0500131 {
132 bus.process_discard();
Andrew Geissler58a18012018-01-19 19:36:05 -0800133 if (cmdDone)
134 break;
Andrew Geissler0971dea2017-03-28 14:32:40 -0500135 bus.wait();
136 }
Andrew Geisslerb09463d2017-03-24 15:55:17 -0500137
138 // If host running then create file
Andrew Geissler58a18012018-01-19 19:36:05 -0800139 if (hostRunning)
Andrew Geissler0971dea2017-03-28 14:32:40 -0500140 {
Andrew Geissler0971dea2017-03-28 14:32:40 -0500141 log<level::INFO>("Host is running!");
Andrew Geissler07d0ed52017-03-28 15:44:18 -0500142 // Create file for host instance and create in filesystem to indicate
143 // to services that host is running
Andrew Geissler58a18012018-01-19 19:36:05 -0800144 auto size = std::snprintf(nullptr, 0, HOST_RUNNING_FILE, 0);
Andrew Geissler0135bd52017-05-09 13:54:10 -0500145 size++; // null
146 std::unique_ptr<char[]> buf(new char[size]);
Andrew Geissler58a18012018-01-19 19:36:05 -0800147 std::snprintf(buf.get(), size, HOST_RUNNING_FILE, 0);
Andrew Geissler07d0ed52017-03-28 15:44:18 -0500148 std::ofstream outfile(buf.get());
149 outfile.close();
150 }
151 else
152 {
153 log<level::INFO>("Host is not running!");
Andrew Geissler0971dea2017-03-28 14:32:40 -0500154 }
Andrew Geisslerb09463d2017-03-24 15:55:17 -0500155
156 return 0;
157}