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