1 /*
2 // Copyright (c) 2019 Intel 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 #pragma once
17
18 #include "app.hpp"
19 #include "query.hpp"
20 #include "registries.hpp"
21 #include "registries/base_message_registry.hpp"
22 #include "registries/openbmc_message_registry.hpp"
23 #include "registries/privilege_registry.hpp"
24 #include "registries/resource_event_message_registry.hpp"
25 #include "registries/task_event_message_registry.hpp"
26 #include "registries/telemetry_message_registry.hpp"
27
28 #include <boost/url/format.hpp>
29
30 #include <array>
31
32 namespace redfish
33 {
34
handleMessageRegistryFileCollectionGet(crow::App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)35 inline void handleMessageRegistryFileCollectionGet(
36 crow::App& app, const crow::Request& req,
37 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
38 {
39 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
40 {
41 return;
42 }
43 // Collections don't include the static data added by SubRoute
44 // because it has a duplicate entry for members
45
46 asyncResp->res.jsonValue["@odata.type"] =
47 "#MessageRegistryFileCollection.MessageRegistryFileCollection";
48 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Registries";
49 asyncResp->res.jsonValue["Name"] = "MessageRegistryFile Collection";
50 asyncResp->res.jsonValue["Description"] =
51 "Collection of MessageRegistryFiles";
52 asyncResp->res.jsonValue["Members@odata.count"] = 5;
53
54 nlohmann::json& members = asyncResp->res.jsonValue["Members"];
55 for (const char* memberName : std::to_array(
56 {"Base", "TaskEvent", "ResourceEvent", "OpenBMC", "Telemetry"}))
57 {
58 nlohmann::json::object_t member;
59 member["@odata.id"] =
60 boost::urls::format("/redfish/v1/Registries/{}", memberName);
61 members.emplace_back(std::move(member));
62 }
63 }
64
requestRoutesMessageRegistryFileCollection(App & app)65 inline void requestRoutesMessageRegistryFileCollection(App& app)
66 {
67 /**
68 * Functions triggers appropriate requests on DBus
69 */
70 BMCWEB_ROUTE(app, "/redfish/v1/Registries/")
71 .privileges(redfish::privileges::getMessageRegistryFileCollection)
72 .methods(boost::beast::http::verb::get)(std::bind_front(
73 handleMessageRegistryFileCollectionGet, std::ref(app)));
74 }
75
handleMessageRoutesMessageRegistryFileGet(crow::App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & registry)76 inline void handleMessageRoutesMessageRegistryFileGet(
77 crow::App& app, const crow::Request& req,
78 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
79 const std::string& registry)
80 {
81 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
82 {
83 return;
84 }
85 const registries::Header* header = nullptr;
86 std::string dmtf = "DMTF ";
87 const char* url = nullptr;
88
89 if (registry == "Base")
90 {
91 header = ®istries::base::header;
92 url = registries::base::url;
93 }
94 else if (registry == "TaskEvent")
95 {
96 header = ®istries::task_event::header;
97 url = registries::task_event::url;
98 }
99 else if (registry == "OpenBMC")
100 {
101 header = ®istries::openbmc::header;
102 dmtf.clear();
103 }
104 else if (registry == "ResourceEvent")
105 {
106 header = ®istries::resource_event::header;
107 url = registries::resource_event::url;
108 }
109 else if (registry == "Telemetry")
110 {
111 header = ®istries::telemetry::header;
112 url = registries::telemetry::url;
113 }
114 else
115 {
116 messages::resourceNotFound(asyncResp->res, "MessageRegistryFile",
117 registry);
118 return;
119 }
120
121 asyncResp->res.jsonValue["@odata.id"] =
122 boost::urls::format("/redfish/v1/Registries/{}", registry);
123 asyncResp->res.jsonValue["@odata.type"] =
124 "#MessageRegistryFile.v1_1_0.MessageRegistryFile";
125 asyncResp->res.jsonValue["Name"] = registry + " Message Registry File";
126 asyncResp->res.jsonValue["Description"] =
127 dmtf + registry + " Message Registry File Location";
128 asyncResp->res.jsonValue["Id"] = header->registryPrefix;
129 asyncResp->res.jsonValue["Registry"] = header->id;
130 nlohmann::json::array_t languages;
131 languages.emplace_back(header->language);
132 asyncResp->res.jsonValue["Languages@odata.count"] = languages.size();
133 asyncResp->res.jsonValue["Languages"] = std::move(languages);
134 nlohmann::json::array_t locationMembers;
135 nlohmann::json::object_t location;
136 location["Language"] = header->language;
137 location["Uri"] = "/redfish/v1/Registries/" + registry + "/" + registry;
138
139 if (url != nullptr)
140 {
141 location["PublicationUri"] = url;
142 }
143 locationMembers.emplace_back(std::move(location));
144 asyncResp->res.jsonValue["Location@odata.count"] = locationMembers.size();
145 asyncResp->res.jsonValue["Location"] = std::move(locationMembers);
146 }
147
requestRoutesMessageRegistryFile(App & app)148 inline void requestRoutesMessageRegistryFile(App& app)
149 {
150 BMCWEB_ROUTE(app, "/redfish/v1/Registries/<str>/")
151 .privileges(redfish::privileges::getMessageRegistryFile)
152 .methods(boost::beast::http::verb::get)(std::bind_front(
153 handleMessageRoutesMessageRegistryFileGet, std::ref(app)));
154 }
155
handleMessageRegistryGet(crow::App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & registry,const std::string & registryMatch)156 inline void handleMessageRegistryGet(
157 crow::App& app, const crow::Request& req,
158 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
159 const std::string& registry, const std::string& registryMatch)
160
161 {
162 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
163 {
164 return;
165 }
166 const registries::Header* header = nullptr;
167 std::vector<const registries::MessageEntry*> registryEntries;
168 if (registry == "Base")
169 {
170 header = ®istries::base::header;
171 for (const registries::MessageEntry& entry : registries::base::registry)
172 {
173 registryEntries.emplace_back(&entry);
174 }
175 }
176 else if (registry == "TaskEvent")
177 {
178 header = ®istries::task_event::header;
179 for (const registries::MessageEntry& entry :
180 registries::task_event::registry)
181 {
182 registryEntries.emplace_back(&entry);
183 }
184 }
185 else if (registry == "OpenBMC")
186 {
187 header = ®istries::openbmc::header;
188 for (const registries::MessageEntry& entry :
189 registries::openbmc::registry)
190 {
191 registryEntries.emplace_back(&entry);
192 }
193 }
194 else if (registry == "ResourceEvent")
195 {
196 header = ®istries::resource_event::header;
197 for (const registries::MessageEntry& entry :
198 registries::resource_event::registry)
199 {
200 registryEntries.emplace_back(&entry);
201 }
202 }
203 else if (registry == "Telemetry")
204 {
205 header = ®istries::telemetry::header;
206 for (const registries::MessageEntry& entry :
207 registries::telemetry::registry)
208 {
209 registryEntries.emplace_back(&entry);
210 }
211 }
212 else
213 {
214 messages::resourceNotFound(asyncResp->res, "MessageRegistryFile",
215 registry);
216 return;
217 }
218
219 if (registry != registryMatch)
220 {
221 messages::resourceNotFound(asyncResp->res, header->type, registryMatch);
222 return;
223 }
224
225 asyncResp->res.jsonValue["@Redfish.Copyright"] = header->copyright;
226 asyncResp->res.jsonValue["@odata.type"] = header->type;
227 asyncResp->res.jsonValue["Id"] = header->id;
228 asyncResp->res.jsonValue["Name"] = header->name;
229 asyncResp->res.jsonValue["Language"] = header->language;
230 asyncResp->res.jsonValue["Description"] = header->description;
231 asyncResp->res.jsonValue["RegistryPrefix"] = header->registryPrefix;
232 asyncResp->res.jsonValue["RegistryVersion"] = header->registryVersion;
233 asyncResp->res.jsonValue["OwningEntity"] = header->owningEntity;
234
235 nlohmann::json& messageObj = asyncResp->res.jsonValue["Messages"];
236
237 // Go through the Message Registry and populate each Message
238 for (const registries::MessageEntry* message : registryEntries)
239 {
240 nlohmann::json& obj = messageObj[message->first];
241 obj["Description"] = message->second.description;
242 obj["Message"] = message->second.message;
243 obj["Severity"] = message->second.messageSeverity;
244 obj["MessageSeverity"] = message->second.messageSeverity;
245 obj["NumberOfArgs"] = message->second.numberOfArgs;
246 obj["Resolution"] = message->second.resolution;
247 if (message->second.numberOfArgs > 0)
248 {
249 nlohmann::json& messageParamArray = obj["ParamTypes"];
250 messageParamArray = nlohmann::json::array();
251 for (const char* str : message->second.paramTypes)
252 {
253 if (str == nullptr)
254 {
255 break;
256 }
257 messageParamArray.push_back(str);
258 }
259 }
260 }
261 }
262
requestRoutesMessageRegistry(App & app)263 inline void requestRoutesMessageRegistry(App& app)
264 {
265 BMCWEB_ROUTE(app, "/redfish/v1/Registries/<str>/<str>/")
266 .privileges(redfish::privileges::getMessageRegistryFile)
267 .methods(boost::beast::http::verb::get)(
268 std::bind_front(handleMessageRegistryGet, std::ref(app)));
269 }
270 } // namespace redfish
271