blob: b5013c81db9a7fa0e5220d20a4e9d001b4bc67d5 [file] [log] [blame]
Vijay Khemkae2795302020-07-15 17:28:45 -07001#include <nlohmann/json.hpp>
Patrick Williams957e03c2021-09-02 16:38:42 -05002#include <phosphor-logging/lg2.hpp>
Vijay Khemkae2795302020-07-15 17:28:45 -07003#include <sdbusplus/bus.hpp>
Sui Chen670cc132021-04-13 09:27:22 -07004#include <sdbusplus/message.hpp>
Vijay Khemkab38fd582020-07-23 13:21:23 -07005#include <sdeventplus/clock.hpp>
Vijay Khemkae2795302020-07-15 17:28:45 -07006#include <sdeventplus/event.hpp>
Vijay Khemkab38fd582020-07-23 13:21:23 -07007#include <sdeventplus/utility/timer.hpp>
Sui Chen670cc132021-04-13 09:27:22 -07008#include <xyz/openbmc_project/Association/Definitions/server.hpp>
Vijay Khemkae2795302020-07-15 17:28:45 -07009#include <xyz/openbmc_project/Sensor/Threshold/Critical/server.hpp>
10#include <xyz/openbmc_project/Sensor/Threshold/Warning/server.hpp>
11#include <xyz/openbmc_project/Sensor/Value/server.hpp>
12
Vijay Khemka15537762020-07-22 11:44:56 -070013#include <deque>
Konstantin Aladysheva6cd7042021-12-21 15:36:01 +030014#include <limits>
Vijay Khemkae2795302020-07-15 17:28:45 -070015#include <map>
16#include <string>
17
18namespace phosphor
19{
20namespace health
21{
22
Sui Chen036f1612021-07-22 01:31:49 -070023const char* InventoryPath = "/xyz/openbmc_project/inventory";
24
25// Used for identifying the BMC inventory creation signal
26const char* BMCActivationPath = "/xyz/openbmc_project/inventory/bmc/activation";
27
28bool FindSystemInventoryInObjectMapper(sdbusplus::bus::bus& bus)
29{
30 sdbusplus::message::message msg =
31 bus.new_method_call("xyz.openbmc_project.ObjectMapper",
32 "/xyz/openbmc_project/object_mapper",
33 "xyz.openbmc_project.ObjectMapper", "GetObject");
34 msg.append(InventoryPath);
35 msg.append(std::vector<std::string>{});
36
37 try
38 {
39 sdbusplus::message::message reply = bus.call(msg, 0);
40 return true;
41 }
42 catch (const std::exception& e)
43 {}
44 return false;
45}
46
Vijay Khemkae2795302020-07-15 17:28:45 -070047using Json = nlohmann::json;
48using ValueIface = sdbusplus::xyz::openbmc_project::Sensor::server::Value;
49
50using CriticalInterface =
51 sdbusplus::xyz::openbmc_project::Sensor::Threshold::server::Critical;
52
53using WarningInterface =
54 sdbusplus::xyz::openbmc_project::Sensor::Threshold::server::Warning;
55
Sui Chen670cc132021-04-13 09:27:22 -070056using AssociationDefinitionInterface =
57 sdbusplus::xyz::openbmc_project::Association::server::Definitions;
58
Vijay Khemkae2795302020-07-15 17:28:45 -070059using healthIfaces =
60 sdbusplus::server::object::object<ValueIface, CriticalInterface,
Sui Chen670cc132021-04-13 09:27:22 -070061 WarningInterface,
62 AssociationDefinitionInterface>;
63
64using AssociationTuple = std::tuple<std::string, std::string, std::string>;
Vijay Khemkae2795302020-07-15 17:28:45 -070065
Vijay Khemka15537762020-07-22 11:44:56 -070066struct HealthConfig
67{
68 std::string name;
69 uint16_t freq;
70 uint16_t windowSize;
Konstantin Aladysheva6cd7042021-12-21 15:36:01 +030071 double criticalHigh = std::numeric_limits<double>::quiet_NaN();
72 double warningHigh = std::numeric_limits<double>::quiet_NaN();
Vijay Khemka15537762020-07-22 11:44:56 -070073 bool criticalLog;
74 bool warningLog;
75 std::string criticalTgt;
76 std::string warningTgt;
Bruceleequantatwaf9acbd2020-10-12 15:21:42 +080077 std::string path;
Vijay Khemka15537762020-07-22 11:44:56 -070078};
79
Vijay Khemkae2795302020-07-15 17:28:45 -070080class HealthSensor : public healthIfaces
81{
82 public:
83 HealthSensor() = delete;
84 HealthSensor(const HealthSensor&) = delete;
85 HealthSensor& operator=(const HealthSensor&) = delete;
86 HealthSensor(HealthSensor&&) = delete;
87 HealthSensor& operator=(HealthSensor&&) = delete;
88 virtual ~HealthSensor() = default;
89
90 /** @brief Constructs HealthSensor
91 *
92 * @param[in] bus - Handle to system dbus
93 * @param[in] objPath - The Dbus path of health sensor
94 */
Vijay Khemka15537762020-07-22 11:44:56 -070095 HealthSensor(sdbusplus::bus::bus& bus, const char* objPath,
Sui Chen670cc132021-04-13 09:27:22 -070096 HealthConfig& sensorConfig,
97 const std::vector<std::string>& bmcIds) :
Vijay Khemka15537762020-07-22 11:44:56 -070098 healthIfaces(bus, objPath),
Vijay Khemkab38fd582020-07-23 13:21:23 -070099 bus(bus), sensorConfig(sensorConfig),
100 timerEvent(sdeventplus::Event::get_default()),
101 readTimer(timerEvent, std::bind(&HealthSensor::readHealthSensor, this))
Vijay Khemka15537762020-07-22 11:44:56 -0700102 {
Sui Chen670cc132021-04-13 09:27:22 -0700103 initHealthSensor(bmcIds);
Vijay Khemka15537762020-07-22 11:44:56 -0700104 }
Vijay Khemkae2795302020-07-15 17:28:45 -0700105
Vijay Khemka15537762020-07-22 11:44:56 -0700106 /** @brief list of sensor data values */
107 std::deque<double> valQueue;
Sui Chen670cc132021-04-13 09:27:22 -0700108 /** @brief Initialize sensor, set default value and association */
109 void initHealthSensor(const std::vector<std::string>& bmcIds);
Vijay Khemkae2795302020-07-15 17:28:45 -0700110 /** @brief Set sensor value utilization to health sensor D-bus */
Vijay Khemka15537762020-07-22 11:44:56 -0700111 void setSensorValueToDbus(const double value);
Vijay Khemkae2795302020-07-15 17:28:45 -0700112 /** @brief Set Sensor Threshold to D-bus at beginning */
Vijay Khemka15537762020-07-22 11:44:56 -0700113 void setSensorThreshold(double criticalHigh, double warningHigh);
Vijay Khemkab7a7b8a2020-07-29 12:22:01 -0700114 /** @brief Check Sensor threshold and update alarm and log */
115 void checkSensorThreshold(const double value);
Vijay Khemkae2795302020-07-15 17:28:45 -0700116
117 private:
Vijay Khemkab38fd582020-07-23 13:21:23 -0700118 /** @brief sdbusplus bus client connection. */
Vijay Khemkae2795302020-07-15 17:28:45 -0700119 sdbusplus::bus::bus& bus;
Vijay Khemkab38fd582020-07-23 13:21:23 -0700120 /** @brief Sensor config from config file */
Vijay Khemka15537762020-07-22 11:44:56 -0700121 HealthConfig& sensorConfig;
Vijay Khemkab38fd582020-07-23 13:21:23 -0700122 /** @brief the Event Loop structure */
123 sdeventplus::Event timerEvent;
124 /** @brief Sensor Read Timer */
125 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> readTimer;
Vijay Khemkab38fd582020-07-23 13:21:23 -0700126 /** @brief Read sensor at regular intrval */
127 void readHealthSensor();
Potin Lai156ecf32022-07-11 17:09:10 +0800128 /** @brief Start configured threshold systemd unit */
129 void startUnit(const std::string& sysdUnit);
Vijay Khemkae2795302020-07-15 17:28:45 -0700130};
131
132class HealthMon
133{
134 public:
135 HealthMon() = delete;
136 HealthMon(const HealthMon&) = delete;
137 HealthMon& operator=(const HealthMon&) = delete;
138 HealthMon(HealthMon&&) = delete;
139 HealthMon& operator=(HealthMon&&) = delete;
140 virtual ~HealthMon() = default;
141
Sui Chen036f1612021-07-22 01:31:49 -0700142 /** @brief Recreates sensor objects and their association if possible
143 */
144 void recreateSensors();
145
Vijay Khemkae2795302020-07-15 17:28:45 -0700146 /** @brief Constructs HealthMon
147 *
148 * @param[in] bus - Handle to system dbus
149 */
150 HealthMon(sdbusplus::bus::bus& bus) : bus(bus)
151 {
Sui Chen670cc132021-04-13 09:27:22 -0700152 // Read JSON file
Vijay Khemkae2795302020-07-15 17:28:45 -0700153 sensorConfigs = getHealthConfig();
Sui Chen036f1612021-07-22 01:31:49 -0700154 recreateSensors();
Vijay Khemkae2795302020-07-15 17:28:45 -0700155 }
156
Sui Chen670cc132021-04-13 09:27:22 -0700157 /** @brief Parse Health config JSON file */
Vijay Khemkae2795302020-07-15 17:28:45 -0700158 Json parseConfigFile(std::string configFile);
159
Sui Chen670cc132021-04-13 09:27:22 -0700160 /** @brief Read config for each health sensor component */
Vijay Khemkae2795302020-07-15 17:28:45 -0700161 void getConfigData(Json& data, HealthConfig& cfg);
162
163 /** @brief Map of the object HealthSensor */
164 std::unordered_map<std::string, std::shared_ptr<HealthSensor>>
165 healthSensors;
166
167 /** @brief Create sensors for health monitoring */
Sui Chen670cc132021-04-13 09:27:22 -0700168 void createHealthSensors(const std::vector<std::string>& bmcIds);
Vijay Khemkae2795302020-07-15 17:28:45 -0700169
170 private:
171 sdbusplus::bus::bus& bus;
172 std::vector<HealthConfig> sensorConfigs;
173 std::vector<HealthConfig> getHealthConfig();
174};
175
176} // namespace health
177} // namespace phosphor