blob: eec4acc9552635b89f07432758d46a121342d29f [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>
7#include <phosphor-logging/log.hpp>
Andrew Geissler0971dea2017-03-28 14:32:40 -05008#include <xyz/openbmc_project/Control/Host/server.hpp>
Andrew Geissler07d0ed52017-03-28 15:44:18 -05009#include <config.h>
Andrew Geisslerb09463d2017-03-24 15:55:17 -050010
Andrew Geisslereeaccf82017-03-28 15:23:27 -050011using namespace std::literals;
Andrew Geisslerb09463d2017-03-24 15:55:17 -050012using namespace phosphor::logging;
Andrew Geissler0971dea2017-03-28 14:32:40 -050013using namespace sdbusplus::xyz::openbmc_project::Control::server;
14
Andrew Geisslereeaccf82017-03-28 15:23:27 -050015// Required strings for sending the msg to check on host
16constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
17constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
18constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
19constexpr auto CONTROL_HOST_PATH = "/xyz/openbmc_project/control/host0";
20constexpr auto CONTROL_HOST_INTERFACE = "xyz.openbmc_project.Control.Host";
Andrew Geissler0971dea2017-03-28 14:32:40 -050021
22bool cmdDone = false;
23bool hostRunning = false;
24
25// Function called on host control signals
26static int hostControlSignal(sd_bus_message* msg,
27 void* userData,
28 sd_bus_error* retError)
29{
30 std::string cmdCompleted{};
31 std::string cmdStatus{};
32
33 auto sdPlusMsg = sdbusplus::message::message(msg);
34 sdPlusMsg.read(cmdCompleted, cmdStatus);
35
36 log<level::DEBUG>("Host control signal values",
37 entry("COMMAND=%s",cmdCompleted.c_str()),
38 entry("STATUS=%s",cmdStatus.c_str()));
39
40 // Verify it's the command this code is interested in and then check status
41 if(Host::convertCommandFromString(cmdCompleted) == Host::Command::Heartbeat)
42 {
43 cmdDone = true;
44
45 if(Host::convertResultFromString(cmdStatus) == Host::Result::Success)
46 {
47 hostRunning = true;
48 }
49 }
50
51 return 0;
52}
Andrew Geisslerb09463d2017-03-24 15:55:17 -050053
Andrew Geisslereeaccf82017-03-28 15:23:27 -050054// Send hearbeat to host to determine if it's running
55void sendHeartbeat(sdbusplus::bus::bus& bus)
56{
57 auto mapper = bus.new_method_call(MAPPER_BUSNAME,
58 MAPPER_PATH,
59 MAPPER_INTERFACE,
60 "GetObject");
61
62 mapper.append(CONTROL_HOST_PATH,
63 std::vector<std::string>({CONTROL_HOST_INTERFACE}));
64 auto mapperResponseMsg = bus.call(mapper);
65
66 if (mapperResponseMsg.is_method_error())
67 {
68 log<level::ERR>("Error in mapper call for control host");
69 // TODO openbmc/openbmc#851 - Once available, throw returned error
70 throw std::runtime_error("Error in mapper call for control host");
71 }
72
73 std::map<std::string, std::vector<std::string>> mapperResponse;
74 mapperResponseMsg.read(mapperResponse);
75 if (mapperResponse.empty())
76 {
77 log<level::ERR>("Error reading mapper resp for control host");
78 // TODO openbmc/openbmc#851 - Once available, throw returned error
79 throw std::runtime_error("Error reading mapper resp for control host");
80 }
81
82 const auto& host = mapperResponse.begin()->first;
83
84 auto method = bus.new_method_call(host.c_str(),
85 CONTROL_HOST_PATH,
86 CONTROL_HOST_INTERFACE,
87 "Execute");
88 method.append(convertForMessage(Host::Command::Heartbeat).c_str());
89
90 auto reply = bus.call(method);
91 if (reply.is_method_error())
92 {
93 log<level::ERR>("Error in call to control host Execute");
94 throw std::runtime_error("Error in call to control host Execute");
95 }
96
97 return;
98}
99
Andrew Geisslerb09463d2017-03-24 15:55:17 -0500100int main(int argc, char *argv[])
101{
102 log<level::INFO>("Check if host is running");
103
Andrew Geissler0971dea2017-03-28 14:32:40 -0500104 auto bus = sdbusplus::bus::new_default();
Andrew Geisslerb09463d2017-03-24 15:55:17 -0500105
Andrew Geisslereeaccf82017-03-28 15:23:27 -0500106 auto s = "type='signal',member='CommandComplete',path='"s +
107 CONTROL_HOST_PATH + "',interface='" +
108 CONTROL_HOST_INTERFACE + "'";
109
Andrew Geissler0971dea2017-03-28 14:32:40 -0500110 // Setup Signal Handler
111 sdbusplus::bus::match::match hostControlSignals(bus,
Andrew Geisslereeaccf82017-03-28 15:23:27 -0500112 s.c_str(),
Andrew Geissler0971dea2017-03-28 14:32:40 -0500113 hostControlSignal,
114 nullptr);
115
Andrew Geisslereeaccf82017-03-28 15:23:27 -0500116 sendHeartbeat(bus);
Andrew Geisslerb09463d2017-03-24 15:55:17 -0500117
118 // Wait for signal
Andrew Geissler0971dea2017-03-28 14:32:40 -0500119 while(!cmdDone)
120 {
121 bus.process_discard();
122 if (cmdDone) break;
123 bus.wait();
124 }
Andrew Geisslerb09463d2017-03-24 15:55:17 -0500125
126 // If host running then create file
Andrew Geissler0971dea2017-03-28 14:32:40 -0500127 if(hostRunning)
128 {
Andrew Geissler0971dea2017-03-28 14:32:40 -0500129 log<level::INFO>("Host is running!");
Andrew Geissler07d0ed52017-03-28 15:44:18 -0500130 // Create file for host instance and create in filesystem to indicate
131 // to services that host is running
132 auto size = std::snprintf(nullptr,0,HOST_RUNNING_FILE,0);
Andrew Geissler0135bd52017-05-09 13:54:10 -0500133 size++; // null
134 std::unique_ptr<char[]> buf(new char[size]);
Andrew Geissler07d0ed52017-03-28 15:44:18 -0500135 std::snprintf(buf.get(),size,HOST_RUNNING_FILE,0);
136 std::ofstream outfile(buf.get());
137 outfile.close();
138 }
139 else
140 {
141 log<level::INFO>("Host is not running!");
Andrew Geissler0971dea2017-03-28 14:32:40 -0500142 }
Andrew Geisslerb09463d2017-03-24 15:55:17 -0500143
144 return 0;
145}