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 #include "alarm_timestamps.hpp"
18 #include "power_state.hpp"
19 #include "types.hpp"
20 
21 #include <sdbusplus/bus.hpp>
22 #include <sdbusplus/bus/match.hpp>
23 #include <sdeventplus/clock.hpp>
24 #include <sdeventplus/event.hpp>
25 #include <sdeventplus/utility/timer.hpp>
26 
27 #include <chrono>
28 #include <optional>
29 
30 namespace sensor::monitor
31 {
32 
33 /**
34  * @class ShutdownAlarmMonitor
35  *
36  * This class finds all instances of the D-Bus interfaces
37  *   xyz.openbmc_project.Sensor.Threshold.SoftShutdown
38  *   xyz.openbmc_project.Sensor.Threshold.HardShutdown
39  *
40  * and then watches the high and low alarm properties.  If they trip
41  * the code will start a timer, at the end of which the system will
42  * be shut down.  The timer values can be modified with configure.ac
43  * options.  If the alarm is cleared before the timer expires, then
44  * the timer is stopped.
45  *
46  * Event logs are also created when the alarms trip and clear.
47  *
48  * Note that the SoftShutdown alarm code actually implements a hard shutdown.
49  * This is because in the system this is being written for, the host is
50  * driving the shutdown process (i.e. doing a soft shutdown) based on an alert
51  * it receives via another channel.  If the soft shutdown timer expires, it
52  * means that the host didn't do a soft shutdown in the time allowed and
53  * now a hard shutdown is required.  This behavior could be modified with
54  * compile flags if anyone needs a different behavior in the future.
55  *
56  * It currently uses the PGoodState class to check for power state.
57  * If a different property is ever desired, a new class can be
58  * derived from PowerState and a compile option can be used.
59  *
60  */
61 class ShutdownAlarmMonitor
62 {
63   public:
64     ShutdownAlarmMonitor() = delete;
65     ~ShutdownAlarmMonitor() = default;
66     ShutdownAlarmMonitor(const ShutdownAlarmMonitor&) = delete;
67     ShutdownAlarmMonitor& operator=(const ShutdownAlarmMonitor&) = delete;
68     ShutdownAlarmMonitor(ShutdownAlarmMonitor&&) = delete;
69     ShutdownAlarmMonitor& operator=(ShutdownAlarmMonitor&&) = delete;
70 
71     /**
72      * @brief Constructor
73      *
74      * @param[in] bus - The sdbusplus bus object
75      * @param[in] event - The sdeventplus event object
76      */
77     ShutdownAlarmMonitor(sdbusplus::bus::bus& bus, sdeventplus::Event& event);
78 
79   private:
80     /**
81      * @brief The propertiesChanged handled for the shutdown interfaces.
82      *
83      * If the power is on, the new alarm values will be checked to see
84      * if the shutdown timer needs to be started or stopped.
85      */
86     void propertiesChanged(sdbusplus::message::message& message);
87 
88     /**
89      * @brief Checks an alarm value to see if a shutdown timer needs
90      *        to be started or stopped.
91      *
92      * If the alarm is on and the timer isn't running, start it.
93      * If the alarm is off and the timer is running, stop it.
94      *
95      * @param[in] value - The alarm property value
96      * @param[in] alarmKey - The alarm key
97      */
98     void checkAlarm(bool value, const AlarmKey& alarmKey);
99 
100     /**
101      * @brief Checks all currently known alarm properties on D-Bus.
102      *
103      * May result in starting or stopping shutdown timers.
104      */
105     void checkAlarms();
106 
107     /**
108      * @brief Finds all shutdown alarm interfaces currently on
109      *        D-Bus and adds them to the alarms map.
110      */
111     void findAlarms();
112 
113     /**
114      * @brief Starts a shutdown timer.
115      *
116      * @param[in] alarmKey - The alarm key
117      */
118     void startTimer(const AlarmKey& alarmKey);
119 
120     /**
121      * @brief Stops a shutdown timer.
122      *
123      * @param[in] alarmKey - The alarm key
124      */
125     void stopTimer(const AlarmKey& alarmKey);
126 
127     /**
128      * @brief The function called when the timer expires.
129      *
130      * @param[in] alarmKey - The alarm key
131      */
132     void timerExpired(const AlarmKey& alarmKey);
133 
134     /**
135      * @brief The power state changed handler.
136      *
137      * Checks alarms when power is turned on, and clears
138      * any running timers on a power off.
139      *
140      * @param[in] powerStateOn - If the power is now on or off.
141      */
142     void powerStateChanged(bool powerStateOn);
143 
144     /**
145      * @brief Returns the ShutdownType for the passed in interface
146      *
147      * @param[in] interface - The D-Bus interface name
148      * @return The interface, or std::nullopt if the interface isn't one
149      *         of the shutdown interfaces.
150      */
151     std::optional<ShutdownType>
152         getShutdownType(const std::string& interface) const;
153 
154     /**
155      * @brief Creates a phosphor-logging event log
156      *
157      * @param[in] alarmKey - The alarm key
158      * @param[in] alarmValue - The alarm property value
159      * @param[in] sensorValue - The sensor value behind the alarm.
160      */
161     void createEventLog(const AlarmKey& alarmKey, bool alarmValue,
162                         const std::optional<double>& sensorValue);
163 
164     /**
165      * @brief The sdbusplus bus object
166      */
167     sdbusplus::bus::bus& bus;
168 
169     /**
170      * @brief The sdeventplus Event object
171      */
172     sdeventplus::Event& event;
173 
174     /**
175      * @brief The match for properties changing on the HardShutdown
176      *        interface.
177      */
178     sdbusplus::bus::match::match hardShutdownMatch;
179 
180     /**
181      * @brief The match for properties changing on the SoftShutdown
182      *        interface.
183      */
184     sdbusplus::bus::match::match softShutdownMatch;
185 
186     /**
187      * @brief The PowerState object to track power state changes.
188      */
189     std::unique_ptr<phosphor::fan::PowerState> _powerState;
190 
191     /**
192      * @brief The map of alarms.
193      */
194     std::map<AlarmKey, std::unique_ptr<sdeventplus::utility::Timer<
195                            sdeventplus::ClockId::Monotonic>>>
196         alarms;
197 
198     /**
199      * @brief The running alarm timer timestamps.
200      */
201     AlarmTimestamps timestamps;
202 };
203 
204 } // namespace sensor::monitor
205