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 "json_parser.hpp" 17 18 #include "conditions.hpp" 19 #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> 29 #include <optional> 30 #include <vector> 31 32 namespace phosphor::fan::monitor 33 { 34 35 using json = nlohmann::json; 36 using namespace phosphor::logging; 37 38 namespace tClass 39 { 40 41 // Get a constructed trust group class for a non-zero speed group 42 CreateGroupFunction 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 52 const std::map<std::string, trustHandler> trusts = { 53 {"nonzerospeed", tClass::getNonZeroSpeed}}; 54 const std::map<std::string, condHandler> conditions = { 55 {"propertiesmatch", condition::getPropertiesMatch}}; 56 57 const std::vector<CreateGroupFunction> getTrustGrps(const json& obj) 58 { 59 std::vector<CreateGroupFunction> grpFuncs; 60 61 if (obj.contains("sensor_trust_groups")) 62 { 63 for (auto& stg : obj["sensor_trust_groups"]) 64 { 65 if (!stg.contains("class") || !stg.contains("group")) 66 { 67 // Log error on missing required parameters 68 log<level::ERR>( 69 "Missing required fan monitor trust group parameters", 70 entry("REQUIRED_PARAMETERS=%s", "{class, group}")); 71 throw std::runtime_error( 72 "Missing required fan trust group parameters"); 73 } 74 auto tgClass = stg["class"].get<std::string>(); 75 std::vector<trust::GroupDefinition> group; 76 for (auto& member : stg["group"]) 77 { 78 // Construct list of group members 79 if (!member.contains("name")) 80 { 81 // Log error on missing required parameter 82 log<level::ERR>( 83 "Missing required fan monitor trust group member name", 84 entry("CLASS=%s", tgClass.c_str())); 85 throw std::runtime_error( 86 "Missing required fan monitor trust group member name"); 87 } 88 auto in_trust = true; 89 if (member.contains("in_trust")) 90 { 91 in_trust = member["in_trust"].get<bool>(); 92 } 93 group.emplace_back(trust::GroupDefinition{ 94 member["name"].get<std::string>(), in_trust}); 95 } 96 // The class for fan sensor trust groups 97 // (Must have a supported function within the tClass namespace) 98 std::transform(tgClass.begin(), tgClass.end(), tgClass.begin(), 99 tolower); 100 auto handler = trusts.find(tgClass); 101 if (handler != trusts.end()) 102 { 103 // Call function for trust group class 104 grpFuncs.emplace_back(handler->second(group)); 105 } 106 else 107 { 108 // Log error on unsupported trust group class 109 log<level::ERR>("Invalid fan monitor trust group class", 110 entry("CLASS=%s", tgClass.c_str())); 111 throw std::runtime_error( 112 "Invalid fan monitor trust group class"); 113 } 114 } 115 } 116 117 return grpFuncs; 118 } 119 120 const std::vector<SensorDefinition> getSensorDefs(const json& sensors) 121 { 122 std::vector<SensorDefinition> sensorDefs; 123 124 for (const auto& sensor : sensors) 125 { 126 if (!sensor.contains("name") || !sensor.contains("has_target")) 127 { 128 // Log error on missing required parameters 129 log<level::ERR>( 130 "Missing required fan sensor definition parameters", 131 entry("REQUIRED_PARAMETERS=%s", "{name, has_target}")); 132 throw std::runtime_error( 133 "Missing required fan sensor definition parameters"); 134 } 135 // Target interface is optional and defaults to 136 // 'xyz.openbmc_project.Control.FanSpeed' 137 std::string targetIntf = "xyz.openbmc_project.Control.FanSpeed"; 138 if (sensor.contains("target_interface")) 139 { 140 targetIntf = sensor["target_interface"].get<std::string>(); 141 } 142 // Factor is optional and defaults to 1 143 auto factor = 1.0; 144 if (sensor.contains("factor")) 145 { 146 factor = sensor["factor"].get<double>(); 147 } 148 // Offset is optional and defaults to 0 149 auto offset = 0; 150 if (sensor.contains("offset")) 151 { 152 offset = sensor["offset"].get<int64_t>(); 153 } 154 155 sensorDefs.emplace_back(std::tuple(sensor["name"].get<std::string>(), 156 sensor["has_target"].get<bool>(), 157 targetIntf, factor, offset)); 158 } 159 160 return sensorDefs; 161 } 162 163 const std::vector<FanDefinition> getFanDefs(const json& obj) 164 { 165 std::vector<FanDefinition> fanDefs; 166 167 for (const auto& fan : obj["fans"]) 168 { 169 if (!fan.contains("inventory") || 170 !fan.contains("allowed_out_of_range_time") || 171 !fan.contains("deviation") || 172 !fan.contains("num_sensors_nonfunc_for_fan_nonfunc") || 173 !fan.contains("sensors")) 174 { 175 // Log error on missing required parameters 176 log<level::ERR>( 177 "Missing required fan monitor definition parameters", 178 entry("REQUIRED_PARAMETERS=%s", 179 "{inventory, allowed_out_of_range_time, deviation, " 180 "num_sensors_nonfunc_for_fan_nonfunc, sensors}")); 181 throw std::runtime_error( 182 "Missing required fan monitor definition parameters"); 183 } 184 // Construct the sensor definitions for this fan 185 auto sensorDefs = getSensorDefs(fan["sensors"]); 186 187 // Functional delay is optional and defaults to 0 188 size_t funcDelay = 0; 189 if (fan.contains("functional_delay")) 190 { 191 funcDelay = fan["functional_delay"].get<size_t>(); 192 } 193 194 // Handle optional conditions 195 auto cond = std::optional<Condition>(); 196 if (fan.contains("condition")) 197 { 198 if (!fan["condition"].contains("name")) 199 { 200 // Log error on missing required parameter 201 log<level::ERR>( 202 "Missing required fan monitor condition parameter", 203 entry("REQUIRED_PARAMETER=%s", "{name}")); 204 throw std::runtime_error( 205 "Missing required fan monitor condition parameter"); 206 } 207 auto name = fan["condition"]["name"].get<std::string>(); 208 // The function for fan monitoring condition 209 // (Must have a supported function within the condition namespace) 210 std::transform(name.begin(), name.end(), name.begin(), tolower); 211 auto handler = conditions.find(name); 212 if (handler != conditions.end()) 213 { 214 cond = handler->second(fan["condition"]); 215 } 216 else 217 { 218 log<level::INFO>( 219 "No handler found for configured condition", 220 entry("CONDITION_NAME=%s", name.c_str()), 221 entry("JSON_DUMP=%s", fan["condition"].dump().c_str())); 222 } 223 } 224 225 fanDefs.emplace_back( 226 std::tuple(fan["inventory"].get<std::string>(), funcDelay, 227 fan["allowed_out_of_range_time"].get<size_t>(), 228 fan["deviation"].get<size_t>(), 229 fan["num_sensors_nonfunc_for_fan_nonfunc"].get<size_t>(), 230 sensorDefs, cond)); 231 } 232 233 return fanDefs; 234 } 235 236 } // namespace phosphor::fan::monitor 237