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 "profile.hpp" 17 18 #include "sdbusplus.hpp" 19 20 #include <nlohmann/json.hpp> 21 #include <phosphor-logging/log.hpp> 22 #include <sdbusplus/bus.hpp> 23 24 #include <algorithm> 25 #include <iterator> 26 #include <numeric> 27 28 namespace phosphor::fan::control::json 29 { 30 31 using json = nlohmann::json; 32 using namespace phosphor::logging; 33 34 // String key must be in all lowercase for method lookup 35 const std::map<std::string, methodHandler> Profile::_methods = { 36 {"all_of", Profile::allOf}}; 37 38 Profile::Profile(sdbusplus::bus::bus& bus, const json& jsonObj) : 39 ConfigBase(jsonObj), _bus(bus), _active(false) 40 { 41 setActive(jsonObj); 42 } 43 44 void Profile::setActive(const json& jsonObj) 45 { 46 if (!jsonObj.contains("method") || !jsonObj["method"].contains("name")) 47 { 48 // Log error on missing profile method 49 log<level::ERR>("Missing required profile method", 50 entry("JSON=%s", jsonObj.dump().c_str())); 51 throw std::runtime_error("Missing required profile method"); 52 } 53 // The method to use in determining if the profile is active 54 auto method = jsonObj["method"]["name"].get<std::string>(); 55 std::transform(method.begin(), method.end(), method.begin(), tolower); 56 auto handler = _methods.find(method); 57 if (handler != _methods.end()) 58 { 59 // Call method for determining profile's active state 60 _active = handler->second(jsonObj["method"]); 61 } 62 else 63 { 64 // Construct list of available methods 65 auto methods = std::accumulate( 66 std::next(_methods.begin()), _methods.end(), 67 _methods.begin()->first, [](auto list, auto method) { 68 return std::move(list) + ", " + method.first; 69 }); 70 log<level::ERR>("Configured method not available", 71 entry("JSON=%s", jsonObj["method"].dump().c_str()), 72 entry("METHODS_AVAILABLE=%s", methods.c_str())); 73 } 74 } 75 76 bool Profile::allOf(const json& method) 77 { 78 if (!method.contains("properties")) 79 { 80 log<level::ERR>("Missing required all_of method properties list", 81 entry("JSON=%s", method.dump().c_str())); 82 throw std::runtime_error( 83 "Missing required all_of method properties list"); 84 } 85 86 return std::all_of( 87 method["properties"].begin(), method["properties"].end(), 88 [](const json& obj) { 89 if (!obj.contains("path") || !obj.contains("interface") || 90 !obj.contains("property") || !obj.contains("value")) 91 { 92 log<level::ERR>( 93 "Missing required all_of method property parameters", 94 entry("JSON=%s", obj.dump().c_str())); 95 throw std::runtime_error( 96 "Missing required all_of method parameters"); 97 } 98 auto variant = 99 util::SDBusPlus::getPropertyVariant<PropertyVariantType>( 100 obj["path"].get<std::string>(), 101 obj["interface"].get<std::string>(), 102 obj["property"].get<std::string>()); 103 104 return getJsonValue(obj["value"]) == variant; 105 }); 106 } 107 108 } // namespace phosphor::fan::control::json 109