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 = &registries::base::header;
92         url = registries::base::url;
93     }
94     else if (registry == "TaskEvent")
95     {
96         header = &registries::task_event::header;
97         url = registries::task_event::url;
98     }
99     else if (registry == "OpenBMC")
100     {
101         header = &registries::openbmc::header;
102         dmtf.clear();
103     }
104     else if (registry == "ResourceEvent")
105     {
106         header = &registries::resource_event::header;
107         url = registries::resource_event::url;
108     }
109     else if (registry == "Telemetry")
110     {
111         header = &registries::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 = &registries::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 = &registries::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 = &registries::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 = &registries::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 = &registries::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