blob: 0778820f42ff1f4b93bc432433149f461bb6e468 [file] [log] [blame]
/**
* Copyright © 2020 IBM Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "profile.hpp"
#include "sdbusplus.hpp"
#include <nlohmann/json.hpp>
#include <phosphor-logging/log.hpp>
#include <algorithm>
#include <iterator>
#include <numeric>
namespace phosphor::fan::control::json
{
using json = nlohmann::json;
using namespace phosphor::logging;
// String key must be in all lowercase for method lookup
const std::map<std::string, methodHandler> Profile::_methods = {
{"all_of", Profile::allOf}};
Profile::Profile(const json& jsonObj) : ConfigBase(jsonObj), _active(false)
{
setActive(jsonObj);
}
void Profile::setActive(const json& jsonObj)
{
if (!jsonObj.contains("method") || !jsonObj["method"].contains("name"))
{
// Log error on missing profile method
log<level::ERR>("Missing required profile method",
entry("JSON=%s", jsonObj.dump().c_str()));
throw std::runtime_error("Missing required profile method");
}
// The method to use in determining if the profile is active
auto method = jsonObj["method"]["name"].get<std::string>();
std::transform(method.begin(), method.end(), method.begin(), tolower);
auto handler = _methods.find(method);
if (handler != _methods.end())
{
// Call method for determining profile's active state
_active = handler->second(jsonObj["method"]);
}
else
{
// Construct list of available methods
auto methods = std::accumulate(
std::next(_methods.begin()), _methods.end(),
_methods.begin()->first, [](auto list, auto method) {
return std::move(list) + ", " + method.first;
});
log<level::ERR>("Configured method not available",
entry("JSON=%s", jsonObj["method"].dump().c_str()),
entry("METHODS_AVAILABLE=%s", methods.c_str()));
}
}
bool Profile::allOf(const json& method)
{
if (!method.contains("properties"))
{
log<level::ERR>("Missing required all_of method properties list",
entry("JSON=%s", method.dump().c_str()));
throw std::runtime_error(
"Missing required all_of method properties list");
}
return std::all_of(
method["properties"].begin(), method["properties"].end(),
[](const json& obj) {
if (!obj.contains("path") || !obj.contains("interface") ||
!obj.contains("property") || !obj.contains("value"))
{
log<level::ERR>(
"Missing required all_of method property parameters",
entry("JSON=%s", obj.dump().c_str()));
throw std::runtime_error(
"Missing required all_of method parameters");
}
auto variant =
util::SDBusPlus::getPropertyVariant<PropertyVariantType>(
obj["path"].get<std::string>(),
obj["interface"].get<std::string>(),
obj["property"].get<std::string>());
return getJsonValue(obj["value"]) == variant;
});
}
} // namespace phosphor::fan::control::json