blob: 062c840dd35913606aa50649477d22159747919a [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>
Vijay Khemkae2795302020-07-15 17:28:45 -070014#include <map>
15#include <string>
16
17namespace phosphor
18{
19namespace health
20{
21
Sui Chen036f1612021-07-22 01:31:49 -070022const char* InventoryPath = "/xyz/openbmc_project/inventory";
23
24// Used for identifying the BMC inventory creation signal
25const char* BMCActivationPath = "/xyz/openbmc_project/inventory/bmc/activation";
26
27bool FindSystemInventoryInObjectMapper(sdbusplus::bus::bus& bus)
28{
29 sdbusplus::message::message msg =
30 bus.new_method_call("xyz.openbmc_project.ObjectMapper",
31 "/xyz/openbmc_project/object_mapper",
32 "xyz.openbmc_project.ObjectMapper", "GetObject");
33 msg.append(InventoryPath);
34 msg.append(std::vector<std::string>{});
35
36 try
37 {
38 sdbusplus::message::message reply = bus.call(msg, 0);
39 return true;
40 }
41 catch (const std::exception& e)
42 {}
43 return false;
44}
45
Vijay Khemkae2795302020-07-15 17:28:45 -070046using Json = nlohmann::json;
47using ValueIface = sdbusplus::xyz::openbmc_project::Sensor::server::Value;
48
49using CriticalInterface =
50 sdbusplus::xyz::openbmc_project::Sensor::Threshold::server::Critical;
51
52using WarningInterface =
53 sdbusplus::xyz::openbmc_project::Sensor::Threshold::server::Warning;
54
Sui Chen670cc132021-04-13 09:27:22 -070055using AssociationDefinitionInterface =
56 sdbusplus::xyz::openbmc_project::Association::server::Definitions;
57
Vijay Khemkae2795302020-07-15 17:28:45 -070058using healthIfaces =
59 sdbusplus::server::object::object<ValueIface, CriticalInterface,
Sui Chen670cc132021-04-13 09:27:22 -070060 WarningInterface,
61 AssociationDefinitionInterface>;
62
63using AssociationTuple = std::tuple<std::string, std::string, std::string>;
Vijay Khemkae2795302020-07-15 17:28:45 -070064
Vijay Khemka15537762020-07-22 11:44:56 -070065struct HealthConfig
66{
67 std::string name;
68 uint16_t freq;
69 uint16_t windowSize;
70 double criticalHigh;
71 double warningHigh;
72 bool criticalLog;
73 bool warningLog;
74 std::string criticalTgt;
75 std::string warningTgt;
Bruceleequantatwaf9acbd2020-10-12 15:21:42 +080076 std::string path;
Vijay Khemka15537762020-07-22 11:44:56 -070077};
78
Vijay Khemkae2795302020-07-15 17:28:45 -070079class HealthSensor : public healthIfaces
80{
81 public:
82 HealthSensor() = delete;
83 HealthSensor(const HealthSensor&) = delete;
84 HealthSensor& operator=(const HealthSensor&) = delete;
85 HealthSensor(HealthSensor&&) = delete;
86 HealthSensor& operator=(HealthSensor&&) = delete;
87 virtual ~HealthSensor() = default;
88
89 /** @brief Constructs HealthSensor
90 *
91 * @param[in] bus - Handle to system dbus
92 * @param[in] objPath - The Dbus path of health sensor
93 */
Vijay Khemka15537762020-07-22 11:44:56 -070094 HealthSensor(sdbusplus::bus::bus& bus, const char* objPath,
Sui Chen670cc132021-04-13 09:27:22 -070095 HealthConfig& sensorConfig,
96 const std::vector<std::string>& bmcIds) :
Vijay Khemka15537762020-07-22 11:44:56 -070097 healthIfaces(bus, objPath),
Vijay Khemkab38fd582020-07-23 13:21:23 -070098 bus(bus), sensorConfig(sensorConfig),
99 timerEvent(sdeventplus::Event::get_default()),
100 readTimer(timerEvent, std::bind(&HealthSensor::readHealthSensor, this))
Vijay Khemka15537762020-07-22 11:44:56 -0700101 {
Sui Chen670cc132021-04-13 09:27:22 -0700102 initHealthSensor(bmcIds);
Vijay Khemka15537762020-07-22 11:44:56 -0700103 }
Vijay Khemkae2795302020-07-15 17:28:45 -0700104
Vijay Khemka15537762020-07-22 11:44:56 -0700105 /** @brief list of sensor data values */
106 std::deque<double> valQueue;
Sui Chen670cc132021-04-13 09:27:22 -0700107 /** @brief Initialize sensor, set default value and association */
108 void initHealthSensor(const std::vector<std::string>& bmcIds);
Vijay Khemkae2795302020-07-15 17:28:45 -0700109 /** @brief Set sensor value utilization to health sensor D-bus */
Vijay Khemka15537762020-07-22 11:44:56 -0700110 void setSensorValueToDbus(const double value);
Vijay Khemkae2795302020-07-15 17:28:45 -0700111 /** @brief Set Sensor Threshold to D-bus at beginning */
Vijay Khemka15537762020-07-22 11:44:56 -0700112 void setSensorThreshold(double criticalHigh, double warningHigh);
Vijay Khemkab7a7b8a2020-07-29 12:22:01 -0700113 /** @brief Check Sensor threshold and update alarm and log */
114 void checkSensorThreshold(const double value);
Vijay Khemkae2795302020-07-15 17:28:45 -0700115
116 private:
Vijay Khemkab38fd582020-07-23 13:21:23 -0700117 /** @brief sdbusplus bus client connection. */
Vijay Khemkae2795302020-07-15 17:28:45 -0700118 sdbusplus::bus::bus& bus;
Vijay Khemkab38fd582020-07-23 13:21:23 -0700119 /** @brief Sensor config from config file */
Vijay Khemka15537762020-07-22 11:44:56 -0700120 HealthConfig& sensorConfig;
Vijay Khemkab38fd582020-07-23 13:21:23 -0700121 /** @brief the Event Loop structure */
122 sdeventplus::Event timerEvent;
123 /** @brief Sensor Read Timer */
124 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> readTimer;
Vijay Khemkab38fd582020-07-23 13:21:23 -0700125 /** @brief Read sensor at regular intrval */
126 void readHealthSensor();
Vijay Khemkae2795302020-07-15 17:28:45 -0700127};
128
129class HealthMon
130{
131 public:
132 HealthMon() = delete;
133 HealthMon(const HealthMon&) = delete;
134 HealthMon& operator=(const HealthMon&) = delete;
135 HealthMon(HealthMon&&) = delete;
136 HealthMon& operator=(HealthMon&&) = delete;
137 virtual ~HealthMon() = default;
138
Sui Chen036f1612021-07-22 01:31:49 -0700139 /** @brief Recreates sensor objects and their association if possible
140 */
141 void recreateSensors();
142
Vijay Khemkae2795302020-07-15 17:28:45 -0700143 /** @brief Constructs HealthMon
144 *
145 * @param[in] bus - Handle to system dbus
146 */
147 HealthMon(sdbusplus::bus::bus& bus) : bus(bus)
148 {
Sui Chen670cc132021-04-13 09:27:22 -0700149 // Read JSON file
Vijay Khemkae2795302020-07-15 17:28:45 -0700150 sensorConfigs = getHealthConfig();
Sui Chen036f1612021-07-22 01:31:49 -0700151 recreateSensors();
Vijay Khemkae2795302020-07-15 17:28:45 -0700152 }
153
Sui Chen670cc132021-04-13 09:27:22 -0700154 /** @brief Parse Health config JSON file */
Vijay Khemkae2795302020-07-15 17:28:45 -0700155 Json parseConfigFile(std::string configFile);
156
Sui Chen670cc132021-04-13 09:27:22 -0700157 /** @brief Read config for each health sensor component */
Vijay Khemkae2795302020-07-15 17:28:45 -0700158 void getConfigData(Json& data, HealthConfig& cfg);
159
160 /** @brief Map of the object HealthSensor */
161 std::unordered_map<std::string, std::shared_ptr<HealthSensor>>
162 healthSensors;
163
164 /** @brief Create sensors for health monitoring */
Sui Chen670cc132021-04-13 09:27:22 -0700165 void createHealthSensors(const std::vector<std::string>& bmcIds);
Vijay Khemkae2795302020-07-15 17:28:45 -0700166
167 private:
168 sdbusplus::bus::bus& bus;
169 std::vector<HealthConfig> sensorConfigs;
170 std::vector<HealthConfig> getHealthConfig();
171};
172
173} // namespace health
174} // namespace phosphor