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 class ShutdownAlarmMonitor
57 {
58   public:
59     ShutdownAlarmMonitor() = delete;
60     ~ShutdownAlarmMonitor() = default;
61     ShutdownAlarmMonitor(const ShutdownAlarmMonitor&) = delete;
62     ShutdownAlarmMonitor& operator=(const ShutdownAlarmMonitor&) = delete;
63     ShutdownAlarmMonitor(ShutdownAlarmMonitor&&) = delete;
64     ShutdownAlarmMonitor& operator=(ShutdownAlarmMonitor&&) = delete;
65 
66     /**
67      * @brief Constructor
68      *
69      * @param[in] bus - The sdbusplus bus object
70      * @param[in] event - The sdeventplus event object
71      * @param[in] powerState - The PowerState object
72      */
73     ShutdownAlarmMonitor(sdbusplus::bus::bus& bus, sdeventplus::Event& event,
74                          std::shared_ptr<phosphor::fan::PowerState> powerState);
75 
76   private:
77     /**
78      * @brief The propertiesChanged handled for the shutdown interfaces.
79      *
80      * If the power is on, the new alarm values will be checked to see
81      * if the shutdown timer needs to be started or stopped.
82      */
83     void propertiesChanged(sdbusplus::message::message& message);
84 
85     /**
86      * @brief Checks an alarm value to see if a shutdown timer needs
87      *        to be started or stopped.
88      *
89      * If the alarm is on and the timer isn't running, start it.
90      * If the alarm is off and the timer is running, stop it.
91      *
92      * @param[in] value - The alarm property value
93      * @param[in] alarmKey - The alarm key
94      */
95     void checkAlarm(bool value, const AlarmKey& alarmKey);
96 
97     /**
98      * @brief Checks all currently known alarm properties on D-Bus.
99      *
100      * May result in starting or stopping shutdown timers.
101      */
102     void checkAlarms();
103 
104     /**
105      * @brief Finds all shutdown alarm interfaces currently on
106      *        D-Bus and adds them to the alarms map.
107      */
108     void findAlarms();
109 
110     /**
111      * @brief Starts a shutdown timer.
112      *
113      * @param[in] alarmKey - The alarm key
114      */
115     void startTimer(const AlarmKey& alarmKey);
116 
117     /**
118      * @brief Stops a shutdown timer.
119      *
120      * @param[in] alarmKey - The alarm key
121      */
122     void stopTimer(const AlarmKey& alarmKey);
123 
124     /**
125      * @brief The function called when the timer expires.
126      *
127      * @param[in] alarmKey - The alarm key
128      */
129     void timerExpired(const AlarmKey& alarmKey);
130 
131     /**
132      * @brief The power state changed handler.
133      *
134      * Checks alarms when power is turned on, and clears
135      * any running timers on a power off.
136      *
137      * @param[in] powerStateOn - If the power is now on or off.
138      */
139     void powerStateChanged(bool powerStateOn);
140 
141     /**
142      * @brief Returns the ShutdownType for the passed in interface
143      *
144      * @param[in] interface - The D-Bus interface name
145      * @return The interface, or std::nullopt if the interface isn't one
146      *         of the shutdown interfaces.
147      */
148     std::optional<ShutdownType>
149         getShutdownType(const std::string& interface) const;
150 
151     /**
152      * @brief Creates a phosphor-logging event log
153      *
154      * @param[in] alarmKey - The alarm key
155      * @param[in] alarmValue - The alarm property value
156      * @param[in] sensorValue - The sensor value behind the alarm.
157      * @param[in] isPowerOffError - If this is committed at the time of the
158      *                              power off.
159      */
160     void createEventLog(const AlarmKey& alarmKey, bool alarmValue,
161                         const std::optional<double>& sensorValue,
162                         bool isPowerOffError = false);
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 PowerState object to track power state changes.
176      */
177     std::shared_ptr<phosphor::fan::PowerState> _powerState;
178 
179     /**
180      * @brief The match for properties changing on the HardShutdown
181      *        interface.
182      */
183     sdbusplus::bus::match::match hardShutdownMatch;
184 
185     /**
186      * @brief The match for properties changing on the SoftShutdown
187      *        interface.
188      */
189     sdbusplus::bus::match::match softShutdownMatch;
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