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