blob: b5e986de63b04ad9292fae987792dc600483221a [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 Barthe5578602021-03-30 12:53:24 -050018#include "config_base.hpp"
Matthew Barth391ade02021-01-15 14:33:21 -060019#include "group.hpp"
Matthew Barthe5578602021-03-30 12:53:24 -050020#include "manager.hpp"
21
22#include <fmt/format.h>
Matthew Barth391ade02021-01-15 14:33:21 -060023
Matthew Barth3174e722020-09-15 15:13:40 -050024#include <nlohmann/json.hpp>
25#include <phosphor-logging/log.hpp>
26#include <sdbusplus/bus.hpp>
27
Matthew Barthe5578602021-03-30 12:53:24 -050028#include <algorithm>
Matthew Barth12bae962021-01-15 16:18:11 -060029#include <optional>
Matthew Barth12bae962021-01-15 16:18:11 -060030
Matthew Barth3174e722020-09-15 15:13:40 -050031namespace phosphor::fan::control::json
32{
33
34using json = nlohmann::json;
35using namespace phosphor::logging;
36
Matthew Barth44ab7692021-03-26 11:40:10 -050037Event::Event(const json& jsonObj, sdbusplus::bus::bus& bus,
38 std::map<configKey, std::unique_ptr<Group>>& groups) :
39 ConfigBase(jsonObj),
40 _bus(bus)
Matthew Barth3174e722020-09-15 15:13:40 -050041{
Matthew Barth3174e722020-09-15 15:13:40 -050042 // Event could have a precondition
43 if (!jsonObj.contains("precondition"))
44 {
45 // Event groups are optional
46 if (jsonObj.contains("groups"))
47 {
Matthew Barth44ab7692021-03-26 11:40:10 -050048 setGroups(jsonObj, groups);
Matthew Barth3174e722020-09-15 15:13:40 -050049 }
50 setTriggers(jsonObj);
51 // Event actions are optional
52 if (jsonObj.contains("actions"))
53 {
54 setActions(jsonObj);
55 }
56 }
57 else
58 {
Matthew Barth44ab7692021-03-26 11:40:10 -050059 setPrecond(jsonObj, groups);
Matthew Barth3174e722020-09-15 15:13:40 -050060 }
61}
62
Matthew Barth44ab7692021-03-26 11:40:10 -050063void Event::setPrecond(const json& jsonObj,
64 std::map<configKey, std::unique_ptr<Group>>& groups)
Matthew Barth3174e722020-09-15 15:13:40 -050065{
66 const auto& precond = jsonObj["precondition"];
67 if (!precond.contains("name") || !precond.contains("groups") ||
68 !precond.contains("triggers") || !precond.contains("events"))
69 {
70 log<level::ERR>("Missing required event precondition attributes",
71 entry("JSON=%s", precond.dump().c_str()));
72 throw std::runtime_error(
73 "Missing required event precondition attributes");
74 }
Matthew Barth44ab7692021-03-26 11:40:10 -050075 setGroups(precond, groups);
Matthew Barth3174e722020-09-15 15:13:40 -050076 setTriggers(precond);
77}
78
Matthew Barth44ab7692021-03-26 11:40:10 -050079void Event::setGroups(const json& jsonObj,
80 std::map<configKey, std::unique_ptr<Group>>& groups)
Matthew Barth3174e722020-09-15 15:13:40 -050081{
82 for (const auto& group : jsonObj["groups"])
83 {
84 if (!group.contains("name") || !group.contains("interface") ||
Matthew Barth12bae962021-01-15 16:18:11 -060085 !group.contains("property") || !group["property"].contains("name"))
Matthew Barth3174e722020-09-15 15:13:40 -050086 {
87 log<level::ERR>("Missing required event group attributes",
88 entry("JSON=%s", group.dump().c_str()));
89 throw std::runtime_error("Missing required event group attributes");
90 }
Matthew Barth12bae962021-01-15 16:18:11 -060091
Matthew Barthe5578602021-03-30 12:53:24 -050092 // Get the group members' interface
93 auto intf = group["interface"].get<std::string>();
94
95 // Get the group members' property name
96 auto prop = group["property"]["name"].get<std::string>();
97
98 // Get the group members' data type
Matthew Barth12bae962021-01-15 16:18:11 -060099 std::optional<std::string> type = std::nullopt;
100 if (group["property"].contains("type"))
101 {
102 type = group["property"]["type"].get<std::string>();
103 }
104
Matthew Barthe5578602021-03-30 12:53:24 -0500105 // Get the group members' expected value
Matthew Barth12bae962021-01-15 16:18:11 -0600106 std::optional<PropertyVariantType> value = std::nullopt;
107 if (group["property"].contains("value"))
108 {
109 value = getJsonValue(group["property"]["value"]);
110 }
111
Matthew Barth0206c722021-03-30 15:20:05 -0500112 configKey eventProfile =
Matthew Barth12bae962021-01-15 16:18:11 -0600113 std::make_pair(group["name"].get<std::string>(), _profiles);
Matthew Barth0206c722021-03-30 15:20:05 -0500114 auto grpEntry = std::find_if(
115 groups.begin(), groups.end(), [&eventProfile](const auto& grp) {
116 return Manager::inConfig(grp.first, eventProfile);
Matthew Barthe5578602021-03-30 12:53:24 -0500117 });
Matthew Barth44ab7692021-03-26 11:40:10 -0500118 if (grpEntry != groups.end())
Matthew Barth12bae962021-01-15 16:18:11 -0600119 {
Matthew Barthe5578602021-03-30 12:53:24 -0500120 auto grp = Group(*grpEntry->second);
121 grp.setInterface(intf);
122 grp.setProperty(prop);
123 grp.setType(type);
124 grp.setValue(value);
Matthew Barth12bae962021-01-15 16:18:11 -0600125 _groups.emplace_back(grp);
126 }
Matthew Barthe5578602021-03-30 12:53:24 -0500127 }
128
129 if (_groups.empty())
130 {
131 auto msg = fmt::format(
132 "No groups configured for event {} in its active profile(s)",
133 getName());
134 log<level::ERR>(msg.c_str());
135 throw std::runtime_error(msg);
Matthew Barth3174e722020-09-15 15:13:40 -0500136 }
137}
138
139void Event::setTriggers(const json& jsonObj)
140{
141 if (!jsonObj.contains("triggers"))
142 {
143 log<level::ERR>("Missing required event triggers list",
144 entry("JSON=%s", jsonObj.dump().c_str()));
145 throw std::runtime_error("Missing required event triggers list");
146 }
147}
148
149void Event::setActions(const json& jsonObj)
150{
151 for (const auto& action : jsonObj["actions"])
152 {
153 if (!action.contains("name"))
154 {
155 log<level::ERR>("Missing required event action name",
156 entry("JSON=%s", action.dump().c_str()));
157 throw std::runtime_error("Missing required event action name");
158 }
159 }
160}
161
162} // namespace phosphor::fan::control::json