blob: f9a88048fb4d1579f021970a37bc85639de29399 [file] [log] [blame]
Matthew Barthc95c5272020-06-15 19:51:13 -05001/**
2 * Copyright © 2020 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 */
Matthew Barthc95c5272020-06-15 19:51:13 -050016#include "system.hpp"
17
18#include "fan.hpp"
19#include "fan_defs.hpp"
20#include "tach_sensor.hpp"
21#include "trust_manager.hpp"
22#include "types.hpp"
23#ifdef MONITOR_USE_JSON
24#include "json_parser.hpp"
25#endif
26
27#include <nlohmann/json.hpp>
Matthew Barthd06905c2020-06-12 08:13:06 -050028#include <phosphor-logging/log.hpp>
Matthew Barthc95c5272020-06-15 19:51:13 -050029#include <sdbusplus/bus.hpp>
30#include <sdeventplus/event.hpp>
Matthew Barthd06905c2020-06-12 08:13:06 -050031#include <sdeventplus/source/signal.hpp>
Matthew Barthc95c5272020-06-15 19:51:13 -050032
33namespace phosphor::fan::monitor
34{
35
36using json = nlohmann::json;
Matthew Barthd06905c2020-06-12 08:13:06 -050037using namespace phosphor::logging;
Matthew Barthc95c5272020-06-15 19:51:13 -050038
39System::System(Mode mode, sdbusplus::bus::bus& bus,
40 const sdeventplus::Event& event) :
41 _mode(mode),
42 _bus(bus), _event(event)
43{
Matt Spinlere892e392020-10-14 13:21:31 -050044 _powerState = std::make_unique<PGoodState>(
45 bus, std::bind(std::mem_fn(&System::powerStateChanged), this,
46 std::placeholders::_1));
47
Matthew Barthc95c5272020-06-15 19:51:13 -050048 json jsonObj = json::object();
49#ifdef MONITOR_USE_JSON
50 jsonObj = getJsonObj(bus);
51#endif
52 // Retrieve and set trust groups within the trust manager
Matthew Barthd06905c2020-06-12 08:13:06 -050053 setTrustMgr(getTrustGroups(jsonObj));
Matthew Barthc95c5272020-06-15 19:51:13 -050054 // Retrieve fan definitions and create fan objects to be monitored
Matthew Barthd06905c2020-06-12 08:13:06 -050055 setFans(getFanDefinitions(jsonObj));
Matt Spinlere892e392020-10-14 13:21:31 -050056 setFaultConfig(jsonObj);
Matthew Barthd06905c2020-06-12 08:13:06 -050057 log<level::INFO>("Configuration loaded");
Matt Spinlere892e392020-10-14 13:21:31 -050058
59 // Since this doesn't run at standby yet, powerStateChanged
60 // will never be called so for now treat start up as the
61 // pgood. When this does run at standby, the 'atPgood'
62 // rules won't need to be checked here.
63 if (_powerState->isPowerOn())
64 {
65 std::for_each(_powerOffRules.begin(), _powerOffRules.end(),
66 [this](auto& rule) {
67 rule->check(PowerRuleState::atPgood, _fanHealth);
68 });
69 // Runtime rules still need to be checked since fans may already
70 // be missing that could trigger a runtime rule.
71 std::for_each(_powerOffRules.begin(), _powerOffRules.end(),
72 [this](auto& rule) {
73 rule->check(PowerRuleState::runtime, _fanHealth);
74 });
75 }
Matthew Barthd06905c2020-06-12 08:13:06 -050076}
77
78void System::sighupHandler(sdeventplus::source::Signal&,
79 const struct signalfd_siginfo*)
80{
81 try
Matthew Barthc95c5272020-06-15 19:51:13 -050082 {
Matthew Barthd06905c2020-06-12 08:13:06 -050083 json jsonObj = json::object();
84#ifdef MONITOR_USE_JSON
85 jsonObj = getJsonObj(_bus);
86#endif
87 auto trustGrps = getTrustGroups(jsonObj);
88 auto fanDefs = getFanDefinitions(jsonObj);
89 // Set configured trust groups
90 setTrustMgr(trustGrps);
91 // Clear/set configured fan definitions
92 _fans.clear();
Matt Spinlerb63aa092020-10-14 09:45:11 -050093 _fanHealth.clear();
Matthew Barthd06905c2020-06-12 08:13:06 -050094 setFans(fanDefs);
Matt Spinlere892e392020-10-14 13:21:31 -050095 setFaultConfig(jsonObj);
Matthew Barthd06905c2020-06-12 08:13:06 -050096 log<level::INFO>("Configuration reloaded successfully");
Matt Spinlere892e392020-10-14 13:21:31 -050097
98 if (_powerState->isPowerOn())
99 {
100 std::for_each(_powerOffRules.begin(), _powerOffRules.end(),
101 [this](auto& rule) {
102 rule->check(PowerRuleState::runtime, _fanHealth);
103 });
104 }
Matthew Barthd06905c2020-06-12 08:13:06 -0500105 }
106 catch (std::runtime_error& re)
107 {
108 log<level::ERR>("Error reloading config, no config changes made",
109 entry("LOAD_ERROR=%s", re.what()));
Matthew Barthc95c5272020-06-15 19:51:13 -0500110 }
111}
112
113const std::vector<CreateGroupFunction>
114 System::getTrustGroups(const json& jsonObj)
115{
116#ifdef MONITOR_USE_JSON
117 return getTrustGrps(jsonObj);
118#else
119 return trustGroups;
120#endif
121}
122
Matthew Barthd06905c2020-06-12 08:13:06 -0500123void System::setTrustMgr(const std::vector<CreateGroupFunction>& groupFuncs)
124{
125 _trust = std::make_unique<trust::Manager>(groupFuncs);
126}
127
Matthew Barthc95c5272020-06-15 19:51:13 -0500128const std::vector<FanDefinition> System::getFanDefinitions(const json& jsonObj)
129{
130#ifdef MONITOR_USE_JSON
131 return getFanDefs(jsonObj);
132#else
133 return fanDefinitions;
134#endif
135}
136
Matthew Barthd06905c2020-06-12 08:13:06 -0500137void System::setFans(const std::vector<FanDefinition>& fanDefs)
138{
139 for (const auto& fanDef : fanDefs)
140 {
141 // Check if a condition exists on the fan
142 auto condition = std::get<conditionField>(fanDef);
143 if (condition)
144 {
145 // Condition exists, skip adding fan if it fails
146 if (!(*condition)(_bus))
147 {
148 continue;
149 }
150 }
151 _fans.emplace_back(
Matt Spinlerb0412d02020-10-12 16:53:52 -0500152 std::make_unique<Fan>(_mode, _bus, _event, _trust, fanDef, *this));
Matt Spinlerb63aa092020-10-14 09:45:11 -0500153
154 updateFanHealth(*(_fans.back()));
Matthew Barthd06905c2020-06-12 08:13:06 -0500155 }
156}
157
Matt Spinlerb63aa092020-10-14 09:45:11 -0500158void System::updateFanHealth(const Fan& fan)
159{
160 std::vector<bool> sensorStatus;
161 for (const auto& sensor : fan.sensors())
162 {
163 sensorStatus.push_back(sensor->functional());
164 }
165
166 _fanHealth[fan.getName()] =
167 std::make_tuple(fan.present(), std::move(sensorStatus));
168}
169
170void System::fanStatusChange(const Fan& fan)
171{
172 updateFanHealth(fan);
Matt Spinlere892e392020-10-14 13:21:31 -0500173
174 if (_powerState->isPowerOn())
175 {
176 std::for_each(_powerOffRules.begin(), _powerOffRules.end(),
177 [this](auto& rule) {
178 rule->check(PowerRuleState::runtime, _fanHealth);
179 });
180 }
181}
182
183void System::setFaultConfig(const json& jsonObj)
184{
185#ifdef MONITOR_USE_JSON
186 std::shared_ptr<PowerInterfaceBase> powerInterface =
187 std::make_shared<PowerInterface>();
188
189 _powerOffRules = getPowerOffRules(jsonObj, powerInterface);
190#endif
191}
192
193void System::powerStateChanged(bool powerStateOn)
194{
195 if (powerStateOn)
196 {
197 std::for_each(_powerOffRules.begin(), _powerOffRules.end(),
198 [this](auto& rule) {
199 rule->check(PowerRuleState::atPgood, _fanHealth);
200 });
201 std::for_each(_powerOffRules.begin(), _powerOffRules.end(),
202 [this](auto& rule) {
203 rule->check(PowerRuleState::runtime, _fanHealth);
204 });
205 }
206 else
207 {
208 // Cancel any in-progress power off actions
209 std::for_each(_powerOffRules.begin(), _powerOffRules.end(),
210 [this](auto& rule) { rule->cancel(); });
211 }
Matt Spinlerb63aa092020-10-14 09:45:11 -0500212}
213
Matthew Barthc95c5272020-06-15 19:51:13 -0500214} // namespace phosphor::fan::monitor