blob: d19c9c104d759aef2ae68bc1c8fa5238e1136139 [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 Barth391ade02021-01-15 14:33:21 -060018#include "group.hpp"
19#include "json_parser.hpp"
20
Matthew Barth3174e722020-09-15 15:13:40 -050021#include <nlohmann/json.hpp>
22#include <phosphor-logging/log.hpp>
23#include <sdbusplus/bus.hpp>
24
Matthew Barth12bae962021-01-15 16:18:11 -060025#include <optional>
26#include <tuple>
27
Matthew Barth3174e722020-09-15 15:13:40 -050028namespace phosphor::fan::control::json
29{
30
31using json = nlohmann::json;
32using namespace phosphor::logging;
33
Matthew Barth391ade02021-01-15 14:33:21 -060034const std::map<configKey, std::unique_ptr<Group>> Event::_availGrps =
35 getConfig<Group>(true);
36
Matthew Barth3174e722020-09-15 15:13:40 -050037Event::Event(sdbusplus::bus::bus& bus, const json& jsonObj) :
Matthew Barth391ade02021-01-15 14:33:21 -060038 ConfigBase(jsonObj), _bus(bus)
Matthew Barth3174e722020-09-15 15:13:40 -050039{
40 if (jsonObj.contains("profiles"))
41 {
42 for (const auto& profile : jsonObj["profiles"])
43 {
44 _profiles.emplace_back(profile.get<std::string>());
45 }
46 }
47
48 // Event could have a precondition
49 if (!jsonObj.contains("precondition"))
50 {
51 // Event groups are optional
52 if (jsonObj.contains("groups"))
53 {
54 setGroups(jsonObj);
55 }
56 setTriggers(jsonObj);
57 // Event actions are optional
58 if (jsonObj.contains("actions"))
59 {
60 setActions(jsonObj);
61 }
62 }
63 else
64 {
65 setPrecond(jsonObj);
66 }
67}
68
69void Event::setPrecond(const json& jsonObj)
70{
71 const auto& precond = jsonObj["precondition"];
72 if (!precond.contains("name") || !precond.contains("groups") ||
73 !precond.contains("triggers") || !precond.contains("events"))
74 {
75 log<level::ERR>("Missing required event precondition attributes",
76 entry("JSON=%s", precond.dump().c_str()));
77 throw std::runtime_error(
78 "Missing required event precondition attributes");
79 }
80 setGroups(precond);
81 setTriggers(precond);
82}
83
84void Event::setGroups(const json& jsonObj)
85{
86 for (const auto& group : jsonObj["groups"])
87 {
88 if (!group.contains("name") || !group.contains("interface") ||
Matthew Barth12bae962021-01-15 16:18:11 -060089 !group.contains("property") || !group["property"].contains("name"))
Matthew Barth3174e722020-09-15 15:13:40 -050090 {
91 log<level::ERR>("Missing required event group attributes",
92 entry("JSON=%s", group.dump().c_str()));
93 throw std::runtime_error("Missing required event group attributes");
94 }
Matthew Barth12bae962021-01-15 16:18:11 -060095
96 // Get the group memebers' data type
97 std::optional<std::string> type = std::nullopt;
98 if (group["property"].contains("type"))
99 {
100 type = group["property"]["type"].get<std::string>();
101 }
102
103 // Get the group memebers' expected value
104 std::optional<PropertyVariantType> value = std::nullopt;
105 if (group["property"].contains("value"))
106 {
107 value = getJsonValue(group["property"]["value"]);
108 }
109
110 // Groups with the same profiles as the event can be used
111 configKey key =
112 std::make_pair(group["name"].get<std::string>(), _profiles);
113 auto grpEntry = _availGrps.find(key);
114 if (grpEntry != _availGrps.end())
115 {
116 eGroup grp;
117 for (const auto& member : grpEntry->second->getMembers())
118 {
119 grp.emplace_back(std::make_tuple(
120 member, group["interface"].get<std::string>(),
121 group["property"]["name"].get<std::string>(), type, value));
122 }
123 _groups.emplace_back(grp);
124 }
125 else
126 {
127 // Groups with no profiles specified can be used in any event
128 key = std::make_pair(group["name"].get<std::string>(),
129 std::vector<std::string>{});
130 grpEntry = _availGrps.find(key);
131 if (grpEntry != _availGrps.end())
132 {
133 eGroup grp;
134 for (const auto& member : grpEntry->second->getMembers())
135 {
136 grp.emplace_back(std::make_tuple(
137 member, group["interface"].get<std::string>(),
138 group["property"]["name"].get<std::string>(), type,
139 value));
140 }
141 _groups.emplace_back(grp);
142 }
143 }
Matthew Barth3174e722020-09-15 15:13:40 -0500144 }
145}
146
147void Event::setTriggers(const json& jsonObj)
148{
149 if (!jsonObj.contains("triggers"))
150 {
151 log<level::ERR>("Missing required event triggers list",
152 entry("JSON=%s", jsonObj.dump().c_str()));
153 throw std::runtime_error("Missing required event triggers list");
154 }
155}
156
157void Event::setActions(const json& jsonObj)
158{
159 for (const auto& action : jsonObj["actions"])
160 {
161 if (!action.contains("name"))
162 {
163 log<level::ERR>("Missing required event action name",
164 entry("JSON=%s", action.dump().c_str()));
165 throw std::runtime_error("Missing required event action name");
166 }
167 }
168}
169
170} // namespace phosphor::fan::control::json