blob: 971c875069549fc6c71fea231bb971c4746d95e7 [file] [log] [blame]
Matthew Barth3174e722020-09-15 15:13:40 -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 "event.hpp"
17
Matthew Barth776ca562021-03-31 09:50:58 -050018#include "action.hpp"
Matthew Barthe5578602021-03-30 12:53:24 -050019#include "config_base.hpp"
Matthew Barth391ade02021-01-15 14:33:21 -060020#include "group.hpp"
Matthew Barthe5578602021-03-30 12:53:24 -050021#include "manager.hpp"
22
23#include <fmt/format.h>
Matthew Barth391ade02021-01-15 14:33:21 -060024
Matthew Barth3174e722020-09-15 15:13:40 -050025#include <nlohmann/json.hpp>
26#include <phosphor-logging/log.hpp>
27#include <sdbusplus/bus.hpp>
28
Matthew Barthe5578602021-03-30 12:53:24 -050029#include <algorithm>
Matthew Barth12bae962021-01-15 16:18:11 -060030#include <optional>
Matthew Barth12bae962021-01-15 16:18:11 -060031
Matthew Barth3174e722020-09-15 15:13:40 -050032namespace phosphor::fan::control::json
33{
34
35using json = nlohmann::json;
36using namespace phosphor::logging;
37
Matthew Barth44ab7692021-03-26 11:40:10 -050038Event::Event(const json& jsonObj, sdbusplus::bus::bus& bus,
39 std::map<configKey, std::unique_ptr<Group>>& groups) :
40 ConfigBase(jsonObj),
41 _bus(bus)
Matthew Barth3174e722020-09-15 15:13:40 -050042{
Matthew Barth3174e722020-09-15 15:13:40 -050043 // Event could have a precondition
44 if (!jsonObj.contains("precondition"))
45 {
46 // Event groups are optional
47 if (jsonObj.contains("groups"))
48 {
Matthew Barth44ab7692021-03-26 11:40:10 -050049 setGroups(jsonObj, groups);
Matthew Barth3174e722020-09-15 15:13:40 -050050 }
51 setTriggers(jsonObj);
52 // Event actions are optional
53 if (jsonObj.contains("actions"))
54 {
55 setActions(jsonObj);
56 }
57 }
58 else
59 {
Matthew Barth44ab7692021-03-26 11:40:10 -050060 setPrecond(jsonObj, groups);
Matthew Barth3174e722020-09-15 15:13:40 -050061 }
62}
63
Matthew Barth44ab7692021-03-26 11:40:10 -050064void Event::setPrecond(const json& jsonObj,
65 std::map<configKey, std::unique_ptr<Group>>& groups)
Matthew Barth3174e722020-09-15 15:13:40 -050066{
67 const auto& precond = jsonObj["precondition"];
68 if (!precond.contains("name") || !precond.contains("groups") ||
69 !precond.contains("triggers") || !precond.contains("events"))
70 {
71 log<level::ERR>("Missing required event precondition attributes",
72 entry("JSON=%s", precond.dump().c_str()));
73 throw std::runtime_error(
74 "Missing required event precondition attributes");
75 }
Matthew Barth44ab7692021-03-26 11:40:10 -050076 setGroups(precond, groups);
Matthew Barth3174e722020-09-15 15:13:40 -050077 setTriggers(precond);
78}
79
Matthew Barth44ab7692021-03-26 11:40:10 -050080void Event::setGroups(const json& jsonObj,
81 std::map<configKey, std::unique_ptr<Group>>& groups)
Matthew Barth3174e722020-09-15 15:13:40 -050082{
83 for (const auto& group : jsonObj["groups"])
84 {
85 if (!group.contains("name") || !group.contains("interface") ||
Matthew Barth12bae962021-01-15 16:18:11 -060086 !group.contains("property") || !group["property"].contains("name"))
Matthew Barth3174e722020-09-15 15:13:40 -050087 {
88 log<level::ERR>("Missing required event group attributes",
89 entry("JSON=%s", group.dump().c_str()));
90 throw std::runtime_error("Missing required event group attributes");
91 }
Matthew Barth12bae962021-01-15 16:18:11 -060092
Matthew Barthe5578602021-03-30 12:53:24 -050093 // Get the group members' interface
94 auto intf = group["interface"].get<std::string>();
95
96 // Get the group members' property name
97 auto prop = group["property"]["name"].get<std::string>();
98
99 // Get the group members' data type
Matthew Barth12bae962021-01-15 16:18:11 -0600100 std::optional<std::string> type = std::nullopt;
101 if (group["property"].contains("type"))
102 {
103 type = group["property"]["type"].get<std::string>();
104 }
105
Matthew Barthe5578602021-03-30 12:53:24 -0500106 // Get the group members' expected value
Matthew Barth12bae962021-01-15 16:18:11 -0600107 std::optional<PropertyVariantType> value = std::nullopt;
108 if (group["property"].contains("value"))
109 {
110 value = getJsonValue(group["property"]["value"]);
111 }
112
Matthew Barth0206c722021-03-30 15:20:05 -0500113 configKey eventProfile =
Matthew Barth12bae962021-01-15 16:18:11 -0600114 std::make_pair(group["name"].get<std::string>(), _profiles);
Matthew Barth0206c722021-03-30 15:20:05 -0500115 auto grpEntry = std::find_if(
116 groups.begin(), groups.end(), [&eventProfile](const auto& grp) {
117 return Manager::inConfig(grp.first, eventProfile);
Matthew Barthe5578602021-03-30 12:53:24 -0500118 });
Matthew Barth44ab7692021-03-26 11:40:10 -0500119 if (grpEntry != groups.end())
Matthew Barth12bae962021-01-15 16:18:11 -0600120 {
Matthew Barthe5578602021-03-30 12:53:24 -0500121 auto grp = Group(*grpEntry->second);
122 grp.setInterface(intf);
123 grp.setProperty(prop);
124 grp.setType(type);
125 grp.setValue(value);
Matthew Barth12bae962021-01-15 16:18:11 -0600126 _groups.emplace_back(grp);
127 }
Matthew Barthe5578602021-03-30 12:53:24 -0500128 }
129
130 if (_groups.empty())
131 {
132 auto msg = fmt::format(
133 "No groups configured for event {} in its active profile(s)",
134 getName());
135 log<level::ERR>(msg.c_str());
136 throw std::runtime_error(msg);
Matthew Barth3174e722020-09-15 15:13:40 -0500137 }
138}
139
140void Event::setTriggers(const json& jsonObj)
141{
142 if (!jsonObj.contains("triggers"))
143 {
144 log<level::ERR>("Missing required event triggers list",
145 entry("JSON=%s", jsonObj.dump().c_str()));
146 throw std::runtime_error("Missing required event triggers list");
147 }
148}
149
150void Event::setActions(const json& jsonObj)
151{
152 for (const auto& action : jsonObj["actions"])
153 {
154 if (!action.contains("name"))
155 {
156 log<level::ERR>("Missing required event action name",
157 entry("JSON=%s", action.dump().c_str()));
158 throw std::runtime_error("Missing required event action name");
159 }
Matthew Barth776ca562021-03-31 09:50:58 -0500160 auto actObj =
161 ActionFactory::getAction(action["name"].get<std::string>(), action);
162 if (actObj)
163 {
164 _actions.emplace_back(std::move(actObj));
165 }
Matthew Barth3174e722020-09-15 15:13:40 -0500166 }
167}
168
169} // namespace phosphor::fan::control::json