xref: /openbmc/bmcweb/redfish-core/lib/message_registries.hpp (revision 40e9b92ec19acffb46f83a6e55b18974da5d708e)
1 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: Copyright OpenBMC Authors
3 // SPDX-FileCopyrightText: Copyright 2019 Intel Corporation
4 #pragma once
5 
6 #include "app.hpp"
7 #include "query.hpp"
8 #include "registries.hpp"
9 #include "registries_selector.hpp"
10 
11 #include <boost/url/format.hpp>
12 
13 #include <array>
14 #include <format>
15 
16 namespace redfish
17 {
18 
19 inline void handleMessageRegistryFileCollectionGet(
20     crow::App& app, const crow::Request& req,
21     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
22 {
23     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
24     {
25         return;
26     }
27     // Collections don't include the static data added by SubRoute
28     // because it has a duplicate entry for members
29 
30     asyncResp->res.jsonValue["@odata.type"] =
31         "#MessageRegistryFileCollection.MessageRegistryFileCollection";
32     asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Registries";
33     asyncResp->res.jsonValue["Name"] = "MessageRegistryFile Collection";
34     asyncResp->res.jsonValue["Description"] =
35         "Collection of MessageRegistryFiles";
36 
37     nlohmann::json& members = asyncResp->res.jsonValue["Members"];
38 
39     static constexpr const auto registryFiles = std::to_array(
40         {"Base", "TaskEvent", "ResourceEvent", "OpenBMC", "Telemetry",
41          "HeartbeatEvent"});
42 
43     for (const char* memberName : registryFiles)
44     {
45         nlohmann::json::object_t member;
46         member["@odata.id"] =
47             boost::urls::format("/redfish/v1/Registries/{}", memberName);
48         members.emplace_back(std::move(member));
49     }
50     asyncResp->res.jsonValue["Members@odata.count"] = members.size();
51 }
52 
53 inline void requestRoutesMessageRegistryFileCollection(App& app)
54 {
55     /**
56      * Functions triggers appropriate requests on DBus
57      */
58     BMCWEB_ROUTE(app, "/redfish/v1/Registries/")
59         .privileges(redfish::privileges::getMessageRegistryFileCollection)
60         .methods(boost::beast::http::verb::get)(std::bind_front(
61             handleMessageRegistryFileCollectionGet, std::ref(app)));
62 }
63 
64 inline void handleMessageRoutesMessageRegistryFileGet(
65     crow::App& app, const crow::Request& req,
66     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
67     const std::string& registry)
68 {
69     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
70     {
71         return;
72     }
73     std::string dmtf = "DMTF ";
74     std::optional<registries::HeaderAndUrl> headerAndUrl =
75         registries::getRegistryHeaderAndUrlFromPrefix(registry);
76 
77     if (!headerAndUrl)
78     {
79         messages::resourceNotFound(asyncResp->res, "MessageRegistryFile",
80                                    registry);
81         return;
82     }
83     if (registry == "OpenBMC")
84     {
85         dmtf.clear();
86     }
87     const registries::Header& header = headerAndUrl->header;
88     const char* url = headerAndUrl->url;
89 
90     asyncResp->res.jsonValue["@odata.id"] =
91         boost::urls::format("/redfish/v1/Registries/{}", registry);
92     asyncResp->res.jsonValue["@odata.type"] =
93         "#MessageRegistryFile.v1_1_0.MessageRegistryFile";
94     asyncResp->res.jsonValue["Name"] = registry + " Message Registry File";
95     asyncResp->res.jsonValue["Description"] =
96         dmtf + registry + " Message Registry File Location";
97     asyncResp->res.jsonValue["Id"] = header.registryPrefix;
98     asyncResp->res.jsonValue["Registry"] =
99         std::format("{}.{}.{}", header.registryPrefix, header.versionMajor,
100                     header.versionMinor);
101     nlohmann::json::array_t languages;
102     languages.emplace_back(header.language);
103     asyncResp->res.jsonValue["Languages@odata.count"] = languages.size();
104     asyncResp->res.jsonValue["Languages"] = std::move(languages);
105     nlohmann::json::array_t locationMembers;
106     nlohmann::json::object_t location;
107     location["Language"] = header.language;
108     location["Uri"] = "/redfish/v1/Registries/" + registry + "/" + registry;
109 
110     if (url != nullptr)
111     {
112         location["PublicationUri"] = url;
113     }
114     locationMembers.emplace_back(std::move(location));
115     asyncResp->res.jsonValue["Location@odata.count"] = locationMembers.size();
116     asyncResp->res.jsonValue["Location"] = std::move(locationMembers);
117 }
118 
119 inline void requestRoutesMessageRegistryFile(App& app)
120 {
121     BMCWEB_ROUTE(app, "/redfish/v1/Registries/<str>/")
122         .privileges(redfish::privileges::getMessageRegistryFile)
123         .methods(boost::beast::http::verb::get)(std::bind_front(
124             handleMessageRoutesMessageRegistryFileGet, std::ref(app)));
125 }
126 
127 inline void handleMessageRegistryGet(
128     crow::App& app, const crow::Request& req,
129     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
130     const std::string& registry, const std::string& registryMatch)
131 
132 {
133     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
134     {
135         return;
136     }
137 
138     std::optional<registries::HeaderAndUrl> headerAndUrl =
139         registries::getRegistryHeaderAndUrlFromPrefix(registry);
140     if (!headerAndUrl)
141     {
142         messages::resourceNotFound(asyncResp->res, "MessageRegistryFile",
143                                    registry);
144         return;
145     }
146 
147     const registries::Header& header = headerAndUrl->header;
148     if (registry != registryMatch)
149     {
150         messages::resourceNotFound(asyncResp->res, header.type, registryMatch);
151         return;
152     }
153 
154     asyncResp->res.jsonValue["@Redfish.Copyright"] = header.copyright;
155     asyncResp->res.jsonValue["@odata.type"] = header.type;
156     asyncResp->res.jsonValue["Id"] =
157         std::format("{}.{}.{}.{}", header.registryPrefix, header.versionMajor,
158                     header.versionMinor, header.versionPatch);
159     asyncResp->res.jsonValue["Name"] = header.name;
160     asyncResp->res.jsonValue["Language"] = header.language;
161     asyncResp->res.jsonValue["Description"] = header.description;
162     asyncResp->res.jsonValue["RegistryPrefix"] = header.registryPrefix;
163     asyncResp->res.jsonValue["RegistryVersion"] =
164         std::format("{}.{}.{}", header.versionMajor, header.versionMinor,
165                     header.versionPatch);
166     asyncResp->res.jsonValue["OwningEntity"] = header.owningEntity;
167 
168     nlohmann::json& messageObj = asyncResp->res.jsonValue["Messages"];
169 
170     // Go through the Message Registry and populate each Message
171     const std::span<const registries::MessageEntry> registryEntries =
172         registries::getRegistryFromPrefix(registry);
173 
174     for (const registries::MessageEntry& message : registryEntries)
175     {
176         nlohmann::json& obj = messageObj[message.first];
177         obj["Description"] = message.second.description;
178         obj["Message"] = message.second.message;
179         obj["Severity"] = message.second.messageSeverity;
180         obj["MessageSeverity"] = message.second.messageSeverity;
181         obj["NumberOfArgs"] = message.second.numberOfArgs;
182         obj["Resolution"] = message.second.resolution;
183         if (message.second.numberOfArgs > 0)
184         {
185             nlohmann::json& messageParamArray = obj["ParamTypes"];
186             messageParamArray = nlohmann::json::array();
187             for (const char* str : message.second.paramTypes)
188             {
189                 if (str == nullptr)
190                 {
191                     break;
192                 }
193                 messageParamArray.push_back(str);
194             }
195         }
196     }
197 }
198 
199 inline void requestRoutesMessageRegistry(App& app)
200 {
201     BMCWEB_ROUTE(app, "/redfish/v1/Registries/<str>/<str>/")
202         .privileges(redfish::privileges::getMessageRegistryFile)
203         .methods(boost::beast::http::verb::get)(
204             std::bind_front(handleMessageRegistryGet, std::ref(app)));
205 }
206 } // namespace redfish
207