summaryrefslogtreecommitdiffstats
path: root/host_check_main.cpp
blob: 182c501e956ce1ba2470edc83cb1d2e075cc5764 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include <cstdlib>
#include <unistd.h>
#include <iostream>
#include <fstream>
#include <cstdio>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/exception.hpp>
#include <phosphor-logging/log.hpp>
#include <xyz/openbmc_project/Control/Host/server.hpp>
#include <config.h>

using namespace std::literals;
using namespace phosphor::logging;
using namespace sdbusplus::xyz::openbmc_project::Control::server;
using sdbusplus::exception::SdBusError;

// Required strings for sending the msg to check on host
constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
constexpr auto CONTROL_HOST_DEFAULT_SVC = "xyz.openbmc_project.Control.Host";
constexpr auto CONTROL_HOST_PATH = "/xyz/openbmc_project/control/host0";
constexpr auto CONTROL_HOST_INTERFACE = "xyz.openbmc_project.Control.Host";

bool cmdDone = false;
bool hostRunning = false;

// Function called on host control signals
static int hostControlSignal(sd_bus_message* msg, void* userData,
                             sd_bus_error* retError)
{
    std::string cmdCompleted{};
    std::string cmdStatus{};

    auto sdPlusMsg = sdbusplus::message::message(msg);
    sdPlusMsg.read(cmdCompleted, cmdStatus);

    log<level::DEBUG>("Host control signal values",
                      entry("COMMAND=%s", cmdCompleted.c_str()),
                      entry("STATUS=%s", cmdStatus.c_str()));

    // Verify it's the command this code is interested in and then check status
    if (Host::convertCommandFromString(cmdCompleted) ==
        Host::Command::Heartbeat)
    {
        cmdDone = true;

        if (Host::convertResultFromString(cmdStatus) == Host::Result::Success)
        {
            hostRunning = true;
        }
    }

    return 0;
}

// Send hearbeat to host to determine if it's running
void sendHeartbeat(sdbusplus::bus::bus& bus)
{
    auto mapper = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
                                      MAPPER_INTERFACE, "GetObject");

    mapper.append(CONTROL_HOST_PATH,
                  std::vector<std::string>({CONTROL_HOST_INTERFACE}));

    std::map<std::string, std::vector<std::string>> mapperResponse;

    try
    {
        auto mapperResponseMsg = bus.call(mapper);
        mapperResponseMsg.read(mapperResponse);
    }
    catch (const SdBusError& e)
    {
        log<level::INFO>("Error in mapper call for control host, use default "
                         "service",
                         entry("ERROR=%s", e.what()));
    }

    std::string host;
    if (!mapperResponse.empty())
    {
        log<level::DEBUG>("Use mapper response");
        host = mapperResponse.begin()->first;
    }
    else
    {
        log<level::DEBUG>("Use hard coded host");
        host = CONTROL_HOST_DEFAULT_SVC;
    }

    auto method = bus.new_method_call(host.c_str(), CONTROL_HOST_PATH,
                                      CONTROL_HOST_INTERFACE, "Execute");
    method.append(convertForMessage(Host::Command::Heartbeat).c_str());

    try
    {
        auto reply = bus.call(method);
    }
    catch (const SdBusError& e)
    {
        log<level::ERR>("Error in call to control host Execute",
                        entry("ERROR=%s", e.what()));
        throw;
    }

    return;
}

int main(int argc, char* argv[])
{
    log<level::INFO>("Check if host is running");

    auto bus = sdbusplus::bus::new_default();

    auto s = "type='signal',member='CommandComplete',path='"s +
             CONTROL_HOST_PATH + "',interface='" + CONTROL_HOST_INTERFACE + "'";

    // Setup Signal Handler
    sdbusplus::bus::match::match hostControlSignals(bus, s.c_str(),
                                                    hostControlSignal, nullptr);

    sendHeartbeat(bus);

    // Wait for signal
    while (!cmdDone)
    {
        bus.process_discard();
        if (cmdDone)
            break;
        bus.wait();
    }

    // If host running then create file
    if (hostRunning)
    {
        log<level::INFO>("Host is running!");
        // Create file for host instance and create in filesystem to indicate
        // to services that host is running
        auto size = std::snprintf(nullptr, 0, HOST_RUNNING_FILE, 0);
        size++; // null
        std::unique_ptr<char[]> buf(new char[size]);
        std::snprintf(buf.get(), size, HOST_RUNNING_FILE, 0);
        std::ofstream outfile(buf.get());
        outfile.close();
    }
    else
    {
        log<level::INFO>("Host is not running!");
    }

    return 0;
}
OpenPOWER on IntegriCloud