1 /**
2  * Copyright © 2021 IBM Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include "power_state.hpp"
19 
20 #include <sdbusplus/bus.hpp>
21 #include <sdbusplus/bus/match.hpp>
22 #include <sdeventplus/event.hpp>
23 
24 namespace sensor::monitor
25 {
26 
27 using InterfaceName = std::string;
28 using PropertyName = std::string;
29 using ErrorName = std::string;
30 using ErrorStatus = std::string;
31 using ObjectPath = std::string;
32 using InterfaceKey = std::tuple<ObjectPath, InterfaceName>;
33 
34 /**
35  * @class ThresholdAlarmLogger
36  *
37  * This class watches the threshold interfaces
38  *    openbmc_project.Sensor.Threshold.Warning
39  *    openbmc_project.Sensor.Threshold.Critical
40  *    openbmc_project.Sensor.Threshold.PerformanceLoss
41  *
42  * and creates event logs when their high and low alarm
43  * properties set and clear.  The error names of the
44  * event logs are based on the sensor type and look like:
45  *
46  * xyz.openbmc_project.Sensor.Threshold.Error.TemperatureWarningHigh
47  * xyz.openbmc_project.Sensor.Threshold.Error.TemperatureWarningHighClear
48  *
49  * Event logs are only created when the power is on.
50  */
51 class ThresholdAlarmLogger
52 {
53   public:
54     ThresholdAlarmLogger() = delete;
55     ~ThresholdAlarmLogger() = default;
56     ThresholdAlarmLogger(const ThresholdAlarmLogger&) = default;
57     ThresholdAlarmLogger& operator=(const ThresholdAlarmLogger&) = default;
58     ThresholdAlarmLogger(ThresholdAlarmLogger&&) = default;
59     ThresholdAlarmLogger& operator=(ThresholdAlarmLogger&&) = default;
60 
61     /**
62      * @brief Constructor
63      *
64      * Looks for existing active threshold alarms.
65      *
66      * @param[in] bus - The sdbusplus bus object
67      * @param[in] event - The sdeventplus event object
68      * @param[in] powerState - The PowerState object
69      */
70     ThresholdAlarmLogger(sdbusplus::bus_t& bus, sdeventplus::Event& event,
71                          std::shared_ptr<phosphor::fan::PowerState> powerState);
72 
73   private:
74     /**
75      * @brief The propertiesChanged handler for all of the thresholds
76      *        interfaces.
77      *
78      * Creates event logs for high/low alarm sets and clears.
79      *
80      * @param[in] msg - The signal message payload.
81      */
82     void propertiesChanged(sdbusplus::message_t& msg);
83 
84     /**
85      * @brief The interfacesRemoved removed handler for the threshold
86      *        interfaces.
87      *
88      * Removes that threshold from the alarms map
89      *
90      * @param[in] msg - The signal message payload.
91      */
92     void interfacesRemoved(sdbusplus::message_t& msg);
93 
94     /**
95      * @brief The interfacesAdded handler for the threshold
96      *        interfaces.
97      *
98      * Checks the alarm when it shows up on D-Bus.
99      *
100      * @param[in] msg - The signal message payload.
101      */
102     void interfacesAdded(sdbusplus::message_t& msg);
103 
104     /**
105      * @brief Checks for alarms in the D-Bus data passed in,
106      *        and creates an event log if necessary.
107      *
108      * @param[in] sensorPath - D-Bus path of the sensor
109      * @param[in] interface - The threshold interface name
110      * @param[in] properties - The map of property values on the interface
111      */
112     void checkProperties(
113         const std::string& sensorPath, const std::string& interface,
114         const std::map<std::string, std::variant<bool>>& properties);
115 
116     /**
117      * @brief Checks for active alarms on the path and threshold interface
118      *        passed in and creates event logs if necessary.
119      *
120      * @param[in] interface - The threshold interface
121      * @param[in] sensorPath - The sensor D-Bus path
122      * @param[in] service - The D-Bus service that owns the interface
123      */
124     void checkThresholds(const std::string& interface,
125                          const std::string& sensorPath,
126                          const std::string& service);
127 
128     /**
129      * @brief Checks for all active alarms on all existing
130      *        threshold interfaces and creates event logs
131      *        if necessary.
132      */
133     void checkThresholds();
134 
135     /**
136      * @brief Creates an event log for the alarm set/clear
137      *
138      * @param[in] sensorPath - The sensor object path
139      * @param[in] interface - The threshold interface
140      * @param[in] alarmProperty - The alarm property name
141      * @param[in] alarmValue - The alarm value
142      */
143     void createEventLog(const std::string& sensorPath,
144                         const std::string& interface,
145                         const std::string& alarmProperty, bool alarmValue);
146 
147     /**
148      * @brief Returns the type of the sensor using the path segment
149      *        that precedes the sensor name.
150      *
151      * /xyz/openbmc_project/sensors/voltage/vout -> type == voltage
152      *
153      * @param[in] sensorPath - The sensor object path name
154      *
155      * @return std::string The type segment
156      */
157     std::string getSensorType(std::string sensorPath);
158 
159     /**
160      * @brief Allows for skipping event logs based on the sensor type.
161      *
162      * Specifically for the 'utilization' type because its provider
163      * doesn't support configurable thresholds yet.
164      *
165      * @param[in] type - The sensor type, like 'temperature'.
166      * @return bool - If it can be skipped or not.
167      */
168     bool skipSensorType(const std::string& type);
169 
170     /**
171      * @brief Returns the inventory path to use for a FRU callout
172      *        for the alarm exceeded errors.
173      *
174      * It finds the path by looking for 'inventory' or 'chassis'
175      * association objects on the sensor that point to a FRU.
176      *
177      * @param[in] std::string - The sensor object path
178      * @return std::string - The inventory path for the FRU callout.
179      *                       May be empty if none found.
180      */
181     std::string getCallout(const std::string& sensorPath);
182 
183     /**
184      * @brief The power state changed handler.
185      *
186      * Checks alarms when power is turned on.
187      *
188      * @param[in] powerStateOn - If the power is now on or off.
189      */
190     void powerStateChanged(bool powerStateOn);
191 
192     /**
193      * @brief The sdbusplus bus object
194      */
195     sdbusplus::bus_t& bus;
196 
197     /**
198      * @brief The sdeventplus Event object
199      */
200     sdeventplus::Event& event;
201 
202     /**
203      * @brief The PowerState object to track power state changes.
204      */
205     std::shared_ptr<phosphor::fan::PowerState> _powerState;
206 
207     /**
208      * @brief The Warning interface match object
209      */
210     sdbusplus::bus::match_t warningMatch;
211 
212     /**
213      * @brief The Critical interface match object
214      */
215     sdbusplus::bus::match_t criticalMatch;
216 
217     /**
218      * @brief The PerformanceLoss interface match object
219      */
220     sdbusplus::bus::match_t perfLossMatch;
221 
222     /**
223      * @brief The InterfacesRemoved match object
224      */
225     sdbusplus::bus::match_t ifacesRemovedMatch;
226 
227     /**
228      * @brief The InterfacesAdded match object
229      */
230     sdbusplus::bus::match_t ifacesAddedMatch;
231 
232     /**
233      * @brief The current alarm values
234      */
235     std::map<InterfaceKey, std::map<PropertyName, bool>> alarms;
236 };
237 
238 } // namespace sensor::monitor
239