blob: d19c9c104d759aef2ae68bc1c8fa5238e1136139 [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 "event.hpp"
#include "group.hpp"
#include "json_parser.hpp"
#include <nlohmann/json.hpp>
#include <phosphor-logging/log.hpp>
#include <sdbusplus/bus.hpp>
#include <optional>
#include <tuple>
namespace phosphor::fan::control::json
{
using json = nlohmann::json;
using namespace phosphor::logging;
const std::map<configKey, std::unique_ptr<Group>> Event::_availGrps =
getConfig<Group>(true);
Event::Event(sdbusplus::bus::bus& bus, const json& jsonObj) :
ConfigBase(jsonObj), _bus(bus)
{
if (jsonObj.contains("profiles"))
{
for (const auto& profile : jsonObj["profiles"])
{
_profiles.emplace_back(profile.get<std::string>());
}
}
// Event could have a precondition
if (!jsonObj.contains("precondition"))
{
// Event groups are optional
if (jsonObj.contains("groups"))
{
setGroups(jsonObj);
}
setTriggers(jsonObj);
// Event actions are optional
if (jsonObj.contains("actions"))
{
setActions(jsonObj);
}
}
else
{
setPrecond(jsonObj);
}
}
void Event::setPrecond(const json& jsonObj)
{
const auto& precond = jsonObj["precondition"];
if (!precond.contains("name") || !precond.contains("groups") ||
!precond.contains("triggers") || !precond.contains("events"))
{
log<level::ERR>("Missing required event precondition attributes",
entry("JSON=%s", precond.dump().c_str()));
throw std::runtime_error(
"Missing required event precondition attributes");
}
setGroups(precond);
setTriggers(precond);
}
void Event::setGroups(const json& jsonObj)
{
for (const auto& group : jsonObj["groups"])
{
if (!group.contains("name") || !group.contains("interface") ||
!group.contains("property") || !group["property"].contains("name"))
{
log<level::ERR>("Missing required event group attributes",
entry("JSON=%s", group.dump().c_str()));
throw std::runtime_error("Missing required event group attributes");
}
// Get the group memebers' data type
std::optional<std::string> type = std::nullopt;
if (group["property"].contains("type"))
{
type = group["property"]["type"].get<std::string>();
}
// Get the group memebers' expected value
std::optional<PropertyVariantType> value = std::nullopt;
if (group["property"].contains("value"))
{
value = getJsonValue(group["property"]["value"]);
}
// Groups with the same profiles as the event can be used
configKey key =
std::make_pair(group["name"].get<std::string>(), _profiles);
auto grpEntry = _availGrps.find(key);
if (grpEntry != _availGrps.end())
{
eGroup grp;
for (const auto& member : grpEntry->second->getMembers())
{
grp.emplace_back(std::make_tuple(
member, group["interface"].get<std::string>(),
group["property"]["name"].get<std::string>(), type, value));
}
_groups.emplace_back(grp);
}
else
{
// Groups with no profiles specified can be used in any event
key = std::make_pair(group["name"].get<std::string>(),
std::vector<std::string>{});
grpEntry = _availGrps.find(key);
if (grpEntry != _availGrps.end())
{
eGroup grp;
for (const auto& member : grpEntry->second->getMembers())
{
grp.emplace_back(std::make_tuple(
member, group["interface"].get<std::string>(),
group["property"]["name"].get<std::string>(), type,
value));
}
_groups.emplace_back(grp);
}
}
}
}
void Event::setTriggers(const json& jsonObj)
{
if (!jsonObj.contains("triggers"))
{
log<level::ERR>("Missing required event triggers list",
entry("JSON=%s", jsonObj.dump().c_str()));
throw std::runtime_error("Missing required event triggers list");
}
}
void Event::setActions(const json& jsonObj)
{
for (const auto& action : jsonObj["actions"])
{
if (!action.contains("name"))
{
log<level::ERR>("Missing required event action name",
entry("JSON=%s", action.dump().c_str()));
throw std::runtime_error("Missing required event action name");
}
}
}
} // namespace phosphor::fan::control::json