1 /**
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  */
16 #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>
28 #include <phosphor-logging/log.hpp>
29 #include <sdbusplus/bus.hpp>
30 #include <sdeventplus/event.hpp>
31 #include <sdeventplus/source/signal.hpp>
32 
33 namespace phosphor::fan::monitor
34 {
35 
36 using json = nlohmann::json;
37 using namespace phosphor::logging;
38 
39 System::System(Mode mode, sdbusplus::bus::bus& bus,
40                const sdeventplus::Event& event) :
41     _mode(mode),
42     _bus(bus), _event(event)
43 {
44     json jsonObj = json::object();
45 #ifdef MONITOR_USE_JSON
46     jsonObj = getJsonObj(bus);
47 #endif
48     // Retrieve and set trust groups within the trust manager
49     setTrustMgr(getTrustGroups(jsonObj));
50     // Retrieve fan definitions and create fan objects to be monitored
51     setFans(getFanDefinitions(jsonObj));
52     log<level::INFO>("Configuration loaded");
53 }
54 
55 void System::sighupHandler(sdeventplus::source::Signal&,
56                            const struct signalfd_siginfo*)
57 {
58     try
59     {
60         json jsonObj = json::object();
61 #ifdef MONITOR_USE_JSON
62         jsonObj = getJsonObj(_bus);
63 #endif
64         auto trustGrps = getTrustGroups(jsonObj);
65         auto fanDefs = getFanDefinitions(jsonObj);
66         // Set configured trust groups
67         setTrustMgr(trustGrps);
68         // Clear/set configured fan definitions
69         _fans.clear();
70         _fanHealth.clear();
71         setFans(fanDefs);
72         log<level::INFO>("Configuration reloaded successfully");
73     }
74     catch (std::runtime_error& re)
75     {
76         log<level::ERR>("Error reloading config, no config changes made",
77                         entry("LOAD_ERROR=%s", re.what()));
78     }
79 }
80 
81 const std::vector<CreateGroupFunction>
82     System::getTrustGroups(const json& jsonObj)
83 {
84 #ifdef MONITOR_USE_JSON
85     return getTrustGrps(jsonObj);
86 #else
87     return trustGroups;
88 #endif
89 }
90 
91 void System::setTrustMgr(const std::vector<CreateGroupFunction>& groupFuncs)
92 {
93     _trust = std::make_unique<trust::Manager>(groupFuncs);
94 }
95 
96 const std::vector<FanDefinition> System::getFanDefinitions(const json& jsonObj)
97 {
98 #ifdef MONITOR_USE_JSON
99     return getFanDefs(jsonObj);
100 #else
101     return fanDefinitions;
102 #endif
103 }
104 
105 void System::setFans(const std::vector<FanDefinition>& fanDefs)
106 {
107     for (const auto& fanDef : fanDefs)
108     {
109         // Check if a condition exists on the fan
110         auto condition = std::get<conditionField>(fanDef);
111         if (condition)
112         {
113             // Condition exists, skip adding fan if it fails
114             if (!(*condition)(_bus))
115             {
116                 continue;
117             }
118         }
119         _fans.emplace_back(
120             std::make_unique<Fan>(_mode, _bus, _event, _trust, fanDef, *this));
121 
122         updateFanHealth(*(_fans.back()));
123     }
124 }
125 
126 void System::updateFanHealth(const Fan& fan)
127 {
128     std::vector<bool> sensorStatus;
129     for (const auto& sensor : fan.sensors())
130     {
131         sensorStatus.push_back(sensor->functional());
132     }
133 
134     _fanHealth[fan.getName()] =
135         std::make_tuple(fan.present(), std::move(sensorStatus));
136 }
137 
138 void System::fanStatusChange(const Fan& fan)
139 {
140     updateFanHealth(fan);
141 }
142 
143 } // namespace phosphor::fan::monitor
144