blob: 34d1995611a34f6af61bf1a391b85dac91cae809 [file] [log] [blame]
Matthew Barth9ea8bee2020-06-04 14:27:19 -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 */
16#include "json_parser.hpp"
17
Matthew Barth22ab93b2020-06-08 10:47:56 -050018#include "conditions.hpp"
Matthew Barth9ea8bee2020-06-04 14:27:19 -050019#include "json_config.hpp"
20#include "nonzero_speed_trust.hpp"
21#include "types.hpp"
22
23#include <nlohmann/json.hpp>
24#include <phosphor-logging/log.hpp>
25
26#include <algorithm>
27#include <map>
28#include <memory>
Matthew Barth22ab93b2020-06-08 10:47:56 -050029#include <optional>
Matthew Barth9ea8bee2020-06-04 14:27:19 -050030#include <vector>
31
32namespace phosphor::fan::monitor
33{
34
35using json = nlohmann::json;
36using namespace phosphor::logging;
37
38namespace tClass
39{
40
41// Get a constructed trust group class for a non-zero speed group
42CreateGroupFunction
43 getNonZeroSpeed(const std::vector<trust::GroupDefinition>& group)
44{
45 return [group]() {
46 return std::make_unique<trust::NonzeroSpeed>(std::move(group));
47 };
48}
49
50} // namespace tClass
51
52const std::map<std::string, trustHandler> trusts = {
53 {"nonzerospeed", tClass::getNonZeroSpeed}};
54
55const std::vector<CreateGroupFunction> getTrustGrps(const json& obj)
56{
57 std::vector<CreateGroupFunction> grpFuncs;
58
59 if (obj.contains("sensor_trust_groups"))
60 {
61 for (auto& stg : obj["sensor_trust_groups"])
62 {
63 if (!stg.contains("class") || !stg.contains("group"))
64 {
65 // Log error on missing required parameters
66 log<level::ERR>(
67 "Missing required fan monitor trust group parameters",
68 entry("REQUIRED_PARAMETERS=%s", "{class, group}"));
69 throw std::runtime_error(
70 "Missing required fan trust group parameters");
71 }
72 auto tgClass = stg["class"].get<std::string>();
73 std::vector<trust::GroupDefinition> group;
74 for (auto& member : stg["group"])
75 {
76 // Construct list of group members
77 if (!member.contains("name"))
78 {
79 // Log error on missing required parameter
80 log<level::ERR>(
81 "Missing required fan monitor trust group member name",
82 entry("CLASS=%s", tgClass.c_str()));
83 throw std::runtime_error(
84 "Missing required fan monitor trust group member name");
85 }
86 auto in_trust = true;
87 if (member.contains("in_trust"))
88 {
89 in_trust = member["in_trust"].get<bool>();
90 }
91 group.emplace_back(trust::GroupDefinition{
92 member["name"].get<std::string>(), in_trust});
93 }
94 // The class for fan sensor trust groups
95 // (Must have a supported function within the tClass namespace)
96 std::transform(tgClass.begin(), tgClass.end(), tgClass.begin(),
97 tolower);
98 auto handler = trusts.find(tgClass);
99 if (handler != trusts.end())
100 {
101 // Call function for trust group class
102 grpFuncs.emplace_back(handler->second(group));
103 }
104 else
105 {
106 // Log error on unsupported trust group class
107 log<level::ERR>("Invalid fan monitor trust group class",
108 entry("CLASS=%s", tgClass.c_str()));
109 throw std::runtime_error(
110 "Invalid fan monitor trust group class");
111 }
112 }
113 }
114
115 return grpFuncs;
116}
117
Matthew Barth22ab93b2020-06-08 10:47:56 -0500118const std::vector<SensorDefinition> getSensorDefs(const json& sensors)
119{
120 std::vector<SensorDefinition> sensorDefs;
121
122 for (const auto& sensor : sensors)
123 {
124 if (!sensor.contains("name") || !sensor.contains("has_target"))
125 {
126 // Log error on missing required parameters
127 log<level::ERR>(
128 "Missing required fan sensor definition parameters",
129 entry("REQUIRED_PARAMETERS=%s", "{name, has_target}"));
130 throw std::runtime_error(
131 "Missing required fan sensor definition parameters");
132 }
133 // Target interface is optional and defaults to
134 // 'xyz.openbmc_project.Control.FanSpeed'
135 std::string targetIntf = "xyz.openbmc_project.Control.FanSpeed";
136 if (sensor.contains("target_interface"))
137 {
138 targetIntf = sensor["target_interface"].get<std::string>();
139 }
140 // Factor is optional and defaults to 1
141 auto factor = 1.0;
142 if (sensor.contains("factor"))
143 {
144 factor = sensor["factor"].get<double>();
145 }
146 // Offset is optional and defaults to 0
147 auto offset = 0;
148 if (sensor.contains("offset"))
149 {
150 offset = sensor["offset"].get<int64_t>();
151 }
152
153 sensorDefs.emplace_back(std::tuple(sensor["name"].get<std::string>(),
154 sensor["has_target"].get<bool>(),
155 targetIntf, factor, offset));
156 }
157
158 return sensorDefs;
159}
160
161const std::vector<FanDefinition> getFanDefs(const json& obj)
162{
163 std::vector<FanDefinition> fanDefs;
164
165 for (const auto& fan : obj["fans"])
166 {
167 if (!fan.contains("inventory") ||
168 !fan.contains("allowed_out_of_range_time") ||
169 !fan.contains("deviation") ||
170 !fan.contains("num_sensors_nonfunc_for_fan_nonfunc") ||
171 !fan.contains("sensors"))
172 {
173 // Log error on missing required parameters
174 log<level::ERR>(
175 "Missing required fan monitor definition parameters",
176 entry("REQUIRED_PARAMETERS=%s",
177 "{inventory, allowed_out_of_range_time, deviation, "
178 "num_sensors_nonfunc_for_fan_nonfunc, sensors}"));
179 throw std::runtime_error(
180 "Missing required fan monitor definition parameters");
181 }
182 // Construct the sensor definitions for this fan
183 auto sensorDefs = getSensorDefs(fan["sensors"]);
184
185 // Functional delay is optional and defaults to 0
186 size_t funcDelay = 0;
187 if (fan.contains("functional_delay"))
188 {
189 funcDelay = fan["functional_delay"].get<size_t>();
190 }
191
192 // TODO Handle optional conditions
193 auto cond = std::experimental::optional<Condition>();
194
195 fanDefs.emplace_back(
196 std::tuple(fan["inventory"].get<std::string>(), funcDelay,
197 fan["allowed_out_of_range_time"].get<size_t>(),
198 fan["deviation"].get<size_t>(),
199 fan["num_sensors_nonfunc_for_fan_nonfunc"].get<size_t>(),
200 sensorDefs, cond));
201 }
202
203 return fanDefs;
204}
205
Matthew Barth9ea8bee2020-06-04 14:27:19 -0500206} // namespace phosphor::fan::monitor