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 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"] = boost::urls::format("/redfish/v1/Registries/{}", 60 memberName); 61 members.emplace_back(std::move(member)); 62 } 63 } 64 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 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"] = dmtf + registry + 127 " 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 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 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 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