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