| Ed Tanous | 1da66f7 | 2018-07-27 16:13:37 -0700 | [diff] [blame] | 1 | /* | 
 | 2 | // Copyright (c) 2018 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 |  | 
| Jason M. Bills | 4851d45 | 2019-03-28 11:27:48 -0700 | [diff] [blame] | 18 | #include "registries.hpp" | 
 | 19 | #include "registries/base_message_registry.hpp" | 
 | 20 | #include "registries/openbmc_message_registry.hpp" | 
| James Feist | 4622957 | 2020-02-19 15:11:58 -0800 | [diff] [blame] | 21 | #include "task.hpp" | 
| Ed Tanous | 1da66f7 | 2018-07-27 16:13:37 -0700 | [diff] [blame] | 22 |  | 
| Jason M. Bills | e1f2634 | 2018-07-18 12:12:00 -0700 | [diff] [blame] | 23 | #include <systemd/sd-journal.h> | 
| Adriana Kobylak | 400fd1f | 2021-01-29 09:01:30 -0600 | [diff] [blame] | 24 | #include <unistd.h> | 
| Jason M. Bills | e1f2634 | 2018-07-18 12:12:00 -0700 | [diff] [blame] | 25 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 26 | #include <app.hpp> | 
| Adriana Kobylak | 400fd1f | 2021-01-29 09:01:30 -0600 | [diff] [blame] | 27 | #include <boost/algorithm/string/replace.hpp> | 
| Jason M. Bills | 4851d45 | 2019-03-28 11:27:48 -0700 | [diff] [blame] | 28 | #include <boost/algorithm/string/split.hpp> | 
 | 29 | #include <boost/beast/core/span.hpp> | 
| Adriana Kobylak | 400fd1f | 2021-01-29 09:01:30 -0600 | [diff] [blame] | 30 | #include <boost/beast/http.hpp> | 
| Ed Tanous | 1da66f7 | 2018-07-27 16:13:37 -0700 | [diff] [blame] | 31 | #include <boost/container/flat_map.hpp> | 
| Jason M. Bills | 1ddcf01 | 2019-11-26 14:59:21 -0800 | [diff] [blame] | 32 | #include <boost/system/linux_error.hpp> | 
| Andrew Geissler | cb92c03 | 2018-08-17 07:56:14 -0700 | [diff] [blame] | 33 | #include <error_messages.hpp> | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 34 | #include <registries/privilege_registry.hpp> | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 35 |  | 
| James Feist | 4418c7f | 2019-04-15 11:09:15 -0700 | [diff] [blame] | 36 | #include <filesystem> | 
| Xiaochao Ma | 75710de | 2021-01-21 17:56:02 +0800 | [diff] [blame] | 37 | #include <optional> | 
| Jason M. Bills | cd225da | 2019-05-08 15:31:57 -0700 | [diff] [blame] | 38 | #include <string_view> | 
| Ed Tanous | abf2add | 2019-01-22 16:40:12 -0800 | [diff] [blame] | 39 | #include <variant> | 
| Ed Tanous | 1da66f7 | 2018-07-27 16:13:37 -0700 | [diff] [blame] | 40 |  | 
 | 41 | namespace redfish | 
 | 42 | { | 
 | 43 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 44 | constexpr char const* crashdumpObject = "com.intel.crashdump"; | 
 | 45 | constexpr char const* crashdumpPath = "/com/intel/crashdump"; | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 46 | constexpr char const* crashdumpInterface = "com.intel.crashdump"; | 
 | 47 | constexpr char const* deleteAllInterface = | 
| Jason M. Bills | 5b61b5e | 2019-10-16 10:59:02 -0700 | [diff] [blame] | 48 |     "xyz.openbmc_project.Collection.DeleteAll"; | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 49 | constexpr char const* crashdumpOnDemandInterface = | 
| Jason M. Bills | 424c417 | 2019-03-21 13:50:33 -0700 | [diff] [blame] | 50 |     "com.intel.crashdump.OnDemand"; | 
| Kenny L. Ku | 6eda768 | 2020-06-19 09:48:36 -0700 | [diff] [blame] | 51 | constexpr char const* crashdumpTelemetryInterface = | 
 | 52 |     "com.intel.crashdump.Telemetry"; | 
| Ed Tanous | 1da66f7 | 2018-07-27 16:13:37 -0700 | [diff] [blame] | 53 |  | 
| Jason M. Bills | 4851d45 | 2019-03-28 11:27:48 -0700 | [diff] [blame] | 54 | namespace message_registries | 
 | 55 | { | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 56 | static const Message* getMessageFromRegistry( | 
 | 57 |     const std::string& messageKey, | 
| Jason M. Bills | 4851d45 | 2019-03-28 11:27:48 -0700 | [diff] [blame] | 58 |     const boost::beast::span<const MessageEntry> registry) | 
 | 59 | { | 
 | 60 |     boost::beast::span<const MessageEntry>::const_iterator messageIt = | 
 | 61 |         std::find_if(registry.cbegin(), registry.cend(), | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 62 |                      [&messageKey](const MessageEntry& messageEntry) { | 
| Jason M. Bills | 4851d45 | 2019-03-28 11:27:48 -0700 | [diff] [blame] | 63 |                          return !std::strcmp(messageEntry.first, | 
 | 64 |                                              messageKey.c_str()); | 
 | 65 |                      }); | 
 | 66 |     if (messageIt != registry.cend()) | 
 | 67 |     { | 
 | 68 |         return &messageIt->second; | 
 | 69 |     } | 
 | 70 |  | 
 | 71 |     return nullptr; | 
 | 72 | } | 
 | 73 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 74 | static const Message* getMessage(const std::string_view& messageID) | 
| Jason M. Bills | 4851d45 | 2019-03-28 11:27:48 -0700 | [diff] [blame] | 75 | { | 
 | 76 |     // Redfish MessageIds are in the form | 
 | 77 |     // RegistryName.MajorVersion.MinorVersion.MessageKey, so parse it to find | 
 | 78 |     // the right Message | 
 | 79 |     std::vector<std::string> fields; | 
 | 80 |     fields.reserve(4); | 
 | 81 |     boost::split(fields, messageID, boost::is_any_of(".")); | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 82 |     std::string& registryName = fields[0]; | 
 | 83 |     std::string& messageKey = fields[3]; | 
| Jason M. Bills | 4851d45 | 2019-03-28 11:27:48 -0700 | [diff] [blame] | 84 |  | 
 | 85 |     // Find the right registry and check it for the MessageKey | 
 | 86 |     if (std::string(base::header.registryPrefix) == registryName) | 
 | 87 |     { | 
 | 88 |         return getMessageFromRegistry( | 
 | 89 |             messageKey, boost::beast::span<const MessageEntry>(base::registry)); | 
 | 90 |     } | 
 | 91 |     if (std::string(openbmc::header.registryPrefix) == registryName) | 
 | 92 |     { | 
 | 93 |         return getMessageFromRegistry( | 
 | 94 |             messageKey, | 
 | 95 |             boost::beast::span<const MessageEntry>(openbmc::registry)); | 
 | 96 |     } | 
 | 97 |     return nullptr; | 
 | 98 | } | 
 | 99 | } // namespace message_registries | 
 | 100 |  | 
| James Feist | f615040 | 2019-01-08 10:36:20 -0800 | [diff] [blame] | 101 | namespace fs = std::filesystem; | 
| Ed Tanous | 1da66f7 | 2018-07-27 16:13:37 -0700 | [diff] [blame] | 102 |  | 
| Andrew Geissler | cb92c03 | 2018-08-17 07:56:14 -0700 | [diff] [blame] | 103 | using GetManagedPropertyType = boost::container::flat_map< | 
| Patrick Williams | 19bd78d | 2020-05-13 17:38:24 -0500 | [diff] [blame] | 104 |     std::string, std::variant<std::string, bool, uint8_t, int16_t, uint16_t, | 
 | 105 |                               int32_t, uint32_t, int64_t, uint64_t, double>>; | 
| Andrew Geissler | cb92c03 | 2018-08-17 07:56:14 -0700 | [diff] [blame] | 106 |  | 
 | 107 | using GetManagedObjectsType = boost::container::flat_map< | 
 | 108 |     sdbusplus::message::object_path, | 
 | 109 |     boost::container::flat_map<std::string, GetManagedPropertyType>>; | 
 | 110 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 111 | inline std::string translateSeverityDbusToRedfish(const std::string& s) | 
| Andrew Geissler | cb92c03 | 2018-08-17 07:56:14 -0700 | [diff] [blame] | 112 | { | 
| Ed Tanous | d4d2579 | 2020-09-29 15:15:03 -0700 | [diff] [blame] | 113 |     if ((s == "xyz.openbmc_project.Logging.Entry.Level.Alert") || | 
 | 114 |         (s == "xyz.openbmc_project.Logging.Entry.Level.Critical") || | 
 | 115 |         (s == "xyz.openbmc_project.Logging.Entry.Level.Emergency") || | 
 | 116 |         (s == "xyz.openbmc_project.Logging.Entry.Level.Error")) | 
| Andrew Geissler | cb92c03 | 2018-08-17 07:56:14 -0700 | [diff] [blame] | 117 |     { | 
 | 118 |         return "Critical"; | 
 | 119 |     } | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 120 |     if ((s == "xyz.openbmc_project.Logging.Entry.Level.Debug") || | 
 | 121 |         (s == "xyz.openbmc_project.Logging.Entry.Level.Informational") || | 
 | 122 |         (s == "xyz.openbmc_project.Logging.Entry.Level.Notice")) | 
| Andrew Geissler | cb92c03 | 2018-08-17 07:56:14 -0700 | [diff] [blame] | 123 |     { | 
 | 124 |         return "OK"; | 
 | 125 |     } | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 126 |     if (s == "xyz.openbmc_project.Logging.Entry.Level.Warning") | 
| Andrew Geissler | cb92c03 | 2018-08-17 07:56:14 -0700 | [diff] [blame] | 127 |     { | 
 | 128 |         return "Warning"; | 
 | 129 |     } | 
 | 130 |     return ""; | 
 | 131 | } | 
 | 132 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 133 | inline static int getJournalMetadata(sd_journal* journal, | 
 | 134 |                                      const std::string_view& field, | 
 | 135 |                                      std::string_view& contents) | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 136 | { | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 137 |     const char* data = nullptr; | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 138 |     size_t length = 0; | 
 | 139 |     int ret = 0; | 
 | 140 |     // Get the metadata from the requested field of the journal entry | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 141 |     ret = sd_journal_get_data(journal, field.data(), | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 142 |                               reinterpret_cast<const void**>(&data), &length); | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 143 |     if (ret < 0) | 
 | 144 |     { | 
 | 145 |         return ret; | 
 | 146 |     } | 
| Ed Tanous | 39e7750 | 2019-03-04 17:35:53 -0800 | [diff] [blame] | 147 |     contents = std::string_view(data, length); | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 148 |     // Only use the content after the "=" character. | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 149 |     contents.remove_prefix(std::min(contents.find('=') + 1, contents.size())); | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 150 |     return ret; | 
 | 151 | } | 
 | 152 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 153 | inline static int getJournalMetadata(sd_journal* journal, | 
 | 154 |                                      const std::string_view& field, | 
 | 155 |                                      const int& base, long int& contents) | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 156 | { | 
 | 157 |     int ret = 0; | 
| Ed Tanous | 39e7750 | 2019-03-04 17:35:53 -0800 | [diff] [blame] | 158 |     std::string_view metadata; | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 159 |     // Get the metadata from the requested field of the journal entry | 
 | 160 |     ret = getJournalMetadata(journal, field, metadata); | 
 | 161 |     if (ret < 0) | 
 | 162 |     { | 
 | 163 |         return ret; | 
 | 164 |     } | 
| Ed Tanous | b01bf29 | 2019-03-25 19:25:26 +0000 | [diff] [blame] | 165 |     contents = strtol(metadata.data(), nullptr, base); | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 166 |     return ret; | 
 | 167 | } | 
 | 168 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 169 | inline static bool getEntryTimestamp(sd_journal* journal, | 
 | 170 |                                      std::string& entryTimestamp) | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 171 | { | 
 | 172 |     int ret = 0; | 
 | 173 |     uint64_t timestamp = 0; | 
 | 174 |     ret = sd_journal_get_realtime_usec(journal, ×tamp); | 
 | 175 |     if (ret < 0) | 
 | 176 |     { | 
 | 177 |         BMCWEB_LOG_ERROR << "Failed to read entry timestamp: " | 
 | 178 |                          << strerror(-ret); | 
 | 179 |         return false; | 
 | 180 |     } | 
| Asmitha Karunanithi | 9c620e2 | 2020-08-02 11:55:21 -0500 | [diff] [blame] | 181 |     entryTimestamp = crow::utility::getDateTime( | 
 | 182 |         static_cast<std::time_t>(timestamp / 1000 / 1000)); | 
 | 183 |     return true; | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 184 | } | 
 | 185 |  | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 186 | static bool getSkipParam(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
 | 187 |                          const crow::Request& req, uint64_t& skip) | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 188 | { | 
| James Feist | 5a7e877 | 2020-07-22 09:08:38 -0700 | [diff] [blame] | 189 |     boost::urls::url_view::params_type::iterator it = | 
 | 190 |         req.urlParams.find("$skip"); | 
 | 191 |     if (it != req.urlParams.end()) | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 192 |     { | 
| James Feist | 5a7e877 | 2020-07-22 09:08:38 -0700 | [diff] [blame] | 193 |         std::string skipParam = it->value(); | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 194 |         char* ptr = nullptr; | 
| James Feist | 5a7e877 | 2020-07-22 09:08:38 -0700 | [diff] [blame] | 195 |         skip = std::strtoul(skipParam.c_str(), &ptr, 10); | 
 | 196 |         if (skipParam.empty() || *ptr != '\0') | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 197 |         { | 
 | 198 |  | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 199 |             messages::queryParameterValueTypeError( | 
 | 200 |                 asyncResp->res, std::string(skipParam), "$skip"); | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 201 |             return false; | 
 | 202 |         } | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 203 |     } | 
 | 204 |     return true; | 
 | 205 | } | 
 | 206 |  | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 207 | static constexpr const uint64_t maxEntriesPerPage = 1000; | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 208 | static bool getTopParam(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
 | 209 |                         const crow::Request& req, uint64_t& top) | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 210 | { | 
| James Feist | 5a7e877 | 2020-07-22 09:08:38 -0700 | [diff] [blame] | 211 |     boost::urls::url_view::params_type::iterator it = | 
 | 212 |         req.urlParams.find("$top"); | 
 | 213 |     if (it != req.urlParams.end()) | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 214 |     { | 
| James Feist | 5a7e877 | 2020-07-22 09:08:38 -0700 | [diff] [blame] | 215 |         std::string topParam = it->value(); | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 216 |         char* ptr = nullptr; | 
| James Feist | 5a7e877 | 2020-07-22 09:08:38 -0700 | [diff] [blame] | 217 |         top = std::strtoul(topParam.c_str(), &ptr, 10); | 
 | 218 |         if (topParam.empty() || *ptr != '\0') | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 219 |         { | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 220 |             messages::queryParameterValueTypeError( | 
 | 221 |                 asyncResp->res, std::string(topParam), "$top"); | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 222 |             return false; | 
 | 223 |         } | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 224 |         if (top < 1U || top > maxEntriesPerPage) | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 225 |         { | 
 | 226 |  | 
 | 227 |             messages::queryParameterOutOfRange( | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 228 |                 asyncResp->res, std::to_string(top), "$top", | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 229 |                 "1-" + std::to_string(maxEntriesPerPage)); | 
 | 230 |             return false; | 
 | 231 |         } | 
 | 232 |     } | 
 | 233 |     return true; | 
 | 234 | } | 
 | 235 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 236 | inline static bool getUniqueEntryID(sd_journal* journal, std::string& entryID, | 
 | 237 |                                     const bool firstEntry = true) | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 238 | { | 
 | 239 |     int ret = 0; | 
 | 240 |     static uint64_t prevTs = 0; | 
 | 241 |     static int index = 0; | 
| Jason M. Bills | e85d6b1 | 2019-07-29 17:01:15 -0700 | [diff] [blame] | 242 |     if (firstEntry) | 
 | 243 |     { | 
 | 244 |         prevTs = 0; | 
 | 245 |     } | 
 | 246 |  | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 247 |     // Get the entry timestamp | 
 | 248 |     uint64_t curTs = 0; | 
 | 249 |     ret = sd_journal_get_realtime_usec(journal, &curTs); | 
 | 250 |     if (ret < 0) | 
 | 251 |     { | 
 | 252 |         BMCWEB_LOG_ERROR << "Failed to read entry timestamp: " | 
 | 253 |                          << strerror(-ret); | 
 | 254 |         return false; | 
 | 255 |     } | 
 | 256 |     // If the timestamp isn't unique, increment the index | 
 | 257 |     if (curTs == prevTs) | 
 | 258 |     { | 
 | 259 |         index++; | 
 | 260 |     } | 
 | 261 |     else | 
 | 262 |     { | 
 | 263 |         // Otherwise, reset it | 
 | 264 |         index = 0; | 
 | 265 |     } | 
 | 266 |     // Save the timestamp | 
 | 267 |     prevTs = curTs; | 
 | 268 |  | 
 | 269 |     entryID = std::to_string(curTs); | 
 | 270 |     if (index > 0) | 
 | 271 |     { | 
 | 272 |         entryID += "_" + std::to_string(index); | 
 | 273 |     } | 
 | 274 |     return true; | 
 | 275 | } | 
 | 276 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 277 | static bool getUniqueEntryID(const std::string& logEntry, std::string& entryID, | 
| Jason M. Bills | e85d6b1 | 2019-07-29 17:01:15 -0700 | [diff] [blame] | 278 |                              const bool firstEntry = true) | 
| Jason M. Bills | 9582018 | 2019-04-22 16:25:34 -0700 | [diff] [blame] | 279 | { | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 280 |     static time_t prevTs = 0; | 
| Jason M. Bills | 9582018 | 2019-04-22 16:25:34 -0700 | [diff] [blame] | 281 |     static int index = 0; | 
| Jason M. Bills | e85d6b1 | 2019-07-29 17:01:15 -0700 | [diff] [blame] | 282 |     if (firstEntry) | 
 | 283 |     { | 
 | 284 |         prevTs = 0; | 
 | 285 |     } | 
 | 286 |  | 
| Jason M. Bills | 9582018 | 2019-04-22 16:25:34 -0700 | [diff] [blame] | 287 |     // Get the entry timestamp | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 288 |     std::time_t curTs = 0; | 
| Jason M. Bills | 9582018 | 2019-04-22 16:25:34 -0700 | [diff] [blame] | 289 |     std::tm timeStruct = {}; | 
 | 290 |     std::istringstream entryStream(logEntry); | 
 | 291 |     if (entryStream >> std::get_time(&timeStruct, "%Y-%m-%dT%H:%M:%S")) | 
 | 292 |     { | 
 | 293 |         curTs = std::mktime(&timeStruct); | 
 | 294 |     } | 
 | 295 |     // If the timestamp isn't unique, increment the index | 
 | 296 |     if (curTs == prevTs) | 
 | 297 |     { | 
 | 298 |         index++; | 
 | 299 |     } | 
 | 300 |     else | 
 | 301 |     { | 
 | 302 |         // Otherwise, reset it | 
 | 303 |         index = 0; | 
 | 304 |     } | 
 | 305 |     // Save the timestamp | 
 | 306 |     prevTs = curTs; | 
 | 307 |  | 
 | 308 |     entryID = std::to_string(curTs); | 
 | 309 |     if (index > 0) | 
 | 310 |     { | 
 | 311 |         entryID += "_" + std::to_string(index); | 
 | 312 |     } | 
 | 313 |     return true; | 
 | 314 | } | 
 | 315 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 316 | inline static bool | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 317 |     getTimestampFromID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
 | 318 |                        const std::string& entryID, uint64_t& timestamp, | 
 | 319 |                        uint64_t& index) | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 320 | { | 
 | 321 |     if (entryID.empty()) | 
 | 322 |     { | 
 | 323 |         return false; | 
 | 324 |     } | 
 | 325 |     // Convert the unique ID back to a timestamp to find the entry | 
| Ed Tanous | 39e7750 | 2019-03-04 17:35:53 -0800 | [diff] [blame] | 326 |     std::string_view tsStr(entryID); | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 327 |  | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 328 |     auto underscorePos = tsStr.find('_'); | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 329 |     if (underscorePos != tsStr.npos) | 
 | 330 |     { | 
 | 331 |         // Timestamp has an index | 
 | 332 |         tsStr.remove_suffix(tsStr.size() - underscorePos); | 
| Ed Tanous | 39e7750 | 2019-03-04 17:35:53 -0800 | [diff] [blame] | 333 |         std::string_view indexStr(entryID); | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 334 |         indexStr.remove_prefix(underscorePos + 1); | 
 | 335 |         std::size_t pos; | 
 | 336 |         try | 
 | 337 |         { | 
| Ed Tanous | 39e7750 | 2019-03-04 17:35:53 -0800 | [diff] [blame] | 338 |             index = std::stoul(std::string(indexStr), &pos); | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 339 |         } | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 340 |         catch (std::invalid_argument&) | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 341 |         { | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 342 |             messages::resourceMissingAtURI(asyncResp->res, entryID); | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 343 |             return false; | 
 | 344 |         } | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 345 |         catch (std::out_of_range&) | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 346 |         { | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 347 |             messages::resourceMissingAtURI(asyncResp->res, entryID); | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 348 |             return false; | 
 | 349 |         } | 
 | 350 |         if (pos != indexStr.size()) | 
 | 351 |         { | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 352 |             messages::resourceMissingAtURI(asyncResp->res, entryID); | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 353 |             return false; | 
 | 354 |         } | 
 | 355 |     } | 
 | 356 |     // Timestamp has no index | 
 | 357 |     std::size_t pos; | 
 | 358 |     try | 
 | 359 |     { | 
| Ed Tanous | 39e7750 | 2019-03-04 17:35:53 -0800 | [diff] [blame] | 360 |         timestamp = std::stoull(std::string(tsStr), &pos); | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 361 |     } | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 362 |     catch (std::invalid_argument&) | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 363 |     { | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 364 |         messages::resourceMissingAtURI(asyncResp->res, entryID); | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 365 |         return false; | 
 | 366 |     } | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 367 |     catch (std::out_of_range&) | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 368 |     { | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 369 |         messages::resourceMissingAtURI(asyncResp->res, entryID); | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 370 |         return false; | 
 | 371 |     } | 
 | 372 |     if (pos != tsStr.size()) | 
 | 373 |     { | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 374 |         messages::resourceMissingAtURI(asyncResp->res, entryID); | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 375 |         return false; | 
 | 376 |     } | 
 | 377 |     return true; | 
 | 378 | } | 
 | 379 |  | 
| Jason M. Bills | 9582018 | 2019-04-22 16:25:34 -0700 | [diff] [blame] | 380 | static bool | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 381 |     getRedfishLogFiles(std::vector<std::filesystem::path>& redfishLogFiles) | 
| Jason M. Bills | 9582018 | 2019-04-22 16:25:34 -0700 | [diff] [blame] | 382 | { | 
 | 383 |     static const std::filesystem::path redfishLogDir = "/var/log"; | 
 | 384 |     static const std::string redfishLogFilename = "redfish"; | 
 | 385 |  | 
 | 386 |     // Loop through the directory looking for redfish log files | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 387 |     for (const std::filesystem::directory_entry& dirEnt : | 
| Jason M. Bills | 9582018 | 2019-04-22 16:25:34 -0700 | [diff] [blame] | 388 |          std::filesystem::directory_iterator(redfishLogDir)) | 
 | 389 |     { | 
 | 390 |         // If we find a redfish log file, save the path | 
 | 391 |         std::string filename = dirEnt.path().filename(); | 
 | 392 |         if (boost::starts_with(filename, redfishLogFilename)) | 
 | 393 |         { | 
 | 394 |             redfishLogFiles.emplace_back(redfishLogDir / filename); | 
 | 395 |         } | 
 | 396 |     } | 
 | 397 |     // As the log files rotate, they are appended with a ".#" that is higher for | 
 | 398 |     // the older logs. Since we don't expect more than 10 log files, we | 
 | 399 |     // can just sort the list to get them in order from newest to oldest | 
 | 400 |     std::sort(redfishLogFiles.begin(), redfishLogFiles.end()); | 
 | 401 |  | 
 | 402 |     return !redfishLogFiles.empty(); | 
 | 403 | } | 
 | 404 |  | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 405 | inline void | 
 | 406 |     getDumpEntryCollection(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
 | 407 |                            const std::string& dumpType) | 
| Asmitha Karunanithi | 5cb1dd2 | 2020-05-07 04:35:02 -0500 | [diff] [blame] | 408 | { | 
 | 409 |     std::string dumpPath; | 
 | 410 |     if (dumpType == "BMC") | 
 | 411 |     { | 
 | 412 |         dumpPath = "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/"; | 
 | 413 |     } | 
 | 414 |     else if (dumpType == "System") | 
 | 415 |     { | 
 | 416 |         dumpPath = "/redfish/v1/Systems/system/LogServices/Dump/Entries/"; | 
 | 417 |     } | 
 | 418 |     else | 
 | 419 |     { | 
 | 420 |         BMCWEB_LOG_ERROR << "Invalid dump type" << dumpType; | 
 | 421 |         messages::internalError(asyncResp->res); | 
 | 422 |         return; | 
 | 423 |     } | 
 | 424 |  | 
 | 425 |     crow::connections::systemBus->async_method_call( | 
 | 426 |         [asyncResp, dumpPath, dumpType](const boost::system::error_code ec, | 
 | 427 |                                         GetManagedObjectsType& resp) { | 
 | 428 |             if (ec) | 
 | 429 |             { | 
 | 430 |                 BMCWEB_LOG_ERROR << "DumpEntry resp_handler got error " << ec; | 
 | 431 |                 messages::internalError(asyncResp->res); | 
 | 432 |                 return; | 
 | 433 |             } | 
 | 434 |  | 
 | 435 |             nlohmann::json& entriesArray = asyncResp->res.jsonValue["Members"]; | 
 | 436 |             entriesArray = nlohmann::json::array(); | 
| Asmitha Karunanithi | b47452b | 2020-09-25 02:02:19 -0500 | [diff] [blame] | 437 |             std::string dumpEntryPath = | 
 | 438 |                 "/xyz/openbmc_project/dump/" + | 
 | 439 |                 std::string(boost::algorithm::to_lower_copy(dumpType)) + | 
 | 440 |                 "/entry/"; | 
| Asmitha Karunanithi | 5cb1dd2 | 2020-05-07 04:35:02 -0500 | [diff] [blame] | 441 |  | 
 | 442 |             for (auto& object : resp) | 
 | 443 |             { | 
| Asmitha Karunanithi | b47452b | 2020-09-25 02:02:19 -0500 | [diff] [blame] | 444 |                 if (object.first.str.find(dumpEntryPath) == std::string::npos) | 
| Asmitha Karunanithi | 5cb1dd2 | 2020-05-07 04:35:02 -0500 | [diff] [blame] | 445 |                 { | 
 | 446 |                     continue; | 
 | 447 |                 } | 
 | 448 |                 std::time_t timestamp; | 
 | 449 |                 uint64_t size = 0; | 
 | 450 |                 entriesArray.push_back({}); | 
 | 451 |                 nlohmann::json& thisEntry = entriesArray.back(); | 
| Ed Tanous | 2dfd18e | 2020-12-18 00:41:31 +0000 | [diff] [blame] | 452 |  | 
 | 453 |                 std::string entryID = object.first.filename(); | 
 | 454 |                 if (entryID.empty()) | 
| Asmitha Karunanithi | 5cb1dd2 | 2020-05-07 04:35:02 -0500 | [diff] [blame] | 455 |                 { | 
 | 456 |                     continue; | 
 | 457 |                 } | 
| Asmitha Karunanithi | 5cb1dd2 | 2020-05-07 04:35:02 -0500 | [diff] [blame] | 458 |  | 
 | 459 |                 for (auto& interfaceMap : object.second) | 
 | 460 |                 { | 
 | 461 |                     if (interfaceMap.first == "xyz.openbmc_project.Dump.Entry") | 
 | 462 |                     { | 
 | 463 |  | 
 | 464 |                         for (auto& propertyMap : interfaceMap.second) | 
 | 465 |                         { | 
 | 466 |                             if (propertyMap.first == "Size") | 
 | 467 |                             { | 
 | 468 |                                 auto sizePtr = | 
 | 469 |                                     std::get_if<uint64_t>(&propertyMap.second); | 
 | 470 |                                 if (sizePtr == nullptr) | 
 | 471 |                                 { | 
 | 472 |                                     messages::internalError(asyncResp->res); | 
 | 473 |                                     break; | 
 | 474 |                                 } | 
 | 475 |                                 size = *sizePtr; | 
 | 476 |                                 break; | 
 | 477 |                             } | 
 | 478 |                         } | 
 | 479 |                     } | 
 | 480 |                     else if (interfaceMap.first == | 
 | 481 |                              "xyz.openbmc_project.Time.EpochTime") | 
 | 482 |                     { | 
 | 483 |  | 
 | 484 |                         for (auto& propertyMap : interfaceMap.second) | 
 | 485 |                         { | 
 | 486 |                             if (propertyMap.first == "Elapsed") | 
 | 487 |                             { | 
 | 488 |                                 const uint64_t* usecsTimeStamp = | 
 | 489 |                                     std::get_if<uint64_t>(&propertyMap.second); | 
 | 490 |                                 if (usecsTimeStamp == nullptr) | 
 | 491 |                                 { | 
 | 492 |                                     messages::internalError(asyncResp->res); | 
 | 493 |                                     break; | 
 | 494 |                                 } | 
 | 495 |                                 timestamp = | 
 | 496 |                                     static_cast<std::time_t>(*usecsTimeStamp); | 
 | 497 |                                 break; | 
 | 498 |                             } | 
 | 499 |                         } | 
 | 500 |                     } | 
 | 501 |                 } | 
 | 502 |  | 
| Ed Tanous | d0dbeef | 2021-07-01 08:46:46 -0700 | [diff] [blame] | 503 |                 thisEntry["@odata.type"] = "#LogEntry.v1_7_0.LogEntry"; | 
| Asmitha Karunanithi | 5cb1dd2 | 2020-05-07 04:35:02 -0500 | [diff] [blame] | 504 |                 thisEntry["@odata.id"] = dumpPath + entryID; | 
 | 505 |                 thisEntry["Id"] = entryID; | 
 | 506 |                 thisEntry["EntryType"] = "Event"; | 
 | 507 |                 thisEntry["Created"] = crow::utility::getDateTime(timestamp); | 
 | 508 |                 thisEntry["Name"] = dumpType + " Dump Entry"; | 
 | 509 |  | 
| Asmitha Karunanithi | d337bb7 | 2020-09-21 10:34:02 -0500 | [diff] [blame] | 510 |                 thisEntry["AdditionalDataSizeBytes"] = size; | 
| Asmitha Karunanithi | 5cb1dd2 | 2020-05-07 04:35:02 -0500 | [diff] [blame] | 511 |  | 
 | 512 |                 if (dumpType == "BMC") | 
 | 513 |                 { | 
| Asmitha Karunanithi | d337bb7 | 2020-09-21 10:34:02 -0500 | [diff] [blame] | 514 |                     thisEntry["DiagnosticDataType"] = "Manager"; | 
 | 515 |                     thisEntry["AdditionalDataURI"] = | 
| Abhishek Patel | de8d94a | 2021-05-13 22:57:36 -0500 | [diff] [blame] | 516 |                         "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/" + | 
 | 517 |                         entryID + "/attachment"; | 
| Asmitha Karunanithi | 5cb1dd2 | 2020-05-07 04:35:02 -0500 | [diff] [blame] | 518 |                 } | 
 | 519 |                 else if (dumpType == "System") | 
 | 520 |                 { | 
| Asmitha Karunanithi | d337bb7 | 2020-09-21 10:34:02 -0500 | [diff] [blame] | 521 |                     thisEntry["DiagnosticDataType"] = "OEM"; | 
 | 522 |                     thisEntry["OEMDiagnosticDataType"] = "System"; | 
 | 523 |                     thisEntry["AdditionalDataURI"] = | 
| Abhishek Patel | de8d94a | 2021-05-13 22:57:36 -0500 | [diff] [blame] | 524 |                         "/redfish/v1/Systems/system/LogServices/Dump/Entries/" + | 
 | 525 |                         entryID + "/attachment"; | 
| Asmitha Karunanithi | 5cb1dd2 | 2020-05-07 04:35:02 -0500 | [diff] [blame] | 526 |                 } | 
 | 527 |             } | 
 | 528 |             asyncResp->res.jsonValue["Members@odata.count"] = | 
 | 529 |                 entriesArray.size(); | 
 | 530 |         }, | 
 | 531 |         "xyz.openbmc_project.Dump.Manager", "/xyz/openbmc_project/dump", | 
 | 532 |         "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); | 
 | 533 | } | 
 | 534 |  | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 535 | inline void | 
 | 536 |     getDumpEntryById(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
 | 537 |                      const std::string& entryID, const std::string& dumpType) | 
| Asmitha Karunanithi | 5cb1dd2 | 2020-05-07 04:35:02 -0500 | [diff] [blame] | 538 | { | 
 | 539 |     std::string dumpPath; | 
 | 540 |     if (dumpType == "BMC") | 
 | 541 |     { | 
 | 542 |         dumpPath = "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/"; | 
 | 543 |     } | 
 | 544 |     else if (dumpType == "System") | 
 | 545 |     { | 
 | 546 |         dumpPath = "/redfish/v1/Systems/system/LogServices/Dump/Entries/"; | 
 | 547 |     } | 
 | 548 |     else | 
 | 549 |     { | 
 | 550 |         BMCWEB_LOG_ERROR << "Invalid dump type" << dumpType; | 
 | 551 |         messages::internalError(asyncResp->res); | 
 | 552 |         return; | 
 | 553 |     } | 
 | 554 |  | 
 | 555 |     crow::connections::systemBus->async_method_call( | 
 | 556 |         [asyncResp, entryID, dumpPath, dumpType]( | 
 | 557 |             const boost::system::error_code ec, GetManagedObjectsType& resp) { | 
 | 558 |             if (ec) | 
 | 559 |             { | 
 | 560 |                 BMCWEB_LOG_ERROR << "DumpEntry resp_handler got error " << ec; | 
 | 561 |                 messages::internalError(asyncResp->res); | 
 | 562 |                 return; | 
 | 563 |             } | 
 | 564 |  | 
| Asmitha Karunanithi | b47452b | 2020-09-25 02:02:19 -0500 | [diff] [blame] | 565 |             bool foundDumpEntry = false; | 
 | 566 |             std::string dumpEntryPath = | 
 | 567 |                 "/xyz/openbmc_project/dump/" + | 
 | 568 |                 std::string(boost::algorithm::to_lower_copy(dumpType)) + | 
 | 569 |                 "/entry/"; | 
 | 570 |  | 
| Asmitha Karunanithi | 5cb1dd2 | 2020-05-07 04:35:02 -0500 | [diff] [blame] | 571 |             for (auto& objectPath : resp) | 
 | 572 |             { | 
| Asmitha Karunanithi | b47452b | 2020-09-25 02:02:19 -0500 | [diff] [blame] | 573 |                 if (objectPath.first.str != dumpEntryPath + entryID) | 
| Asmitha Karunanithi | 5cb1dd2 | 2020-05-07 04:35:02 -0500 | [diff] [blame] | 574 |                 { | 
 | 575 |                     continue; | 
 | 576 |                 } | 
 | 577 |  | 
| Asmitha Karunanithi | b47452b | 2020-09-25 02:02:19 -0500 | [diff] [blame] | 578 |                 foundDumpEntry = true; | 
| Asmitha Karunanithi | 5cb1dd2 | 2020-05-07 04:35:02 -0500 | [diff] [blame] | 579 |                 std::time_t timestamp; | 
 | 580 |                 uint64_t size = 0; | 
 | 581 |  | 
 | 582 |                 for (auto& interfaceMap : objectPath.second) | 
 | 583 |                 { | 
 | 584 |                     if (interfaceMap.first == "xyz.openbmc_project.Dump.Entry") | 
 | 585 |                     { | 
 | 586 |                         for (auto& propertyMap : interfaceMap.second) | 
 | 587 |                         { | 
 | 588 |                             if (propertyMap.first == "Size") | 
 | 589 |                             { | 
 | 590 |                                 auto sizePtr = | 
 | 591 |                                     std::get_if<uint64_t>(&propertyMap.second); | 
 | 592 |                                 if (sizePtr == nullptr) | 
 | 593 |                                 { | 
 | 594 |                                     messages::internalError(asyncResp->res); | 
 | 595 |                                     break; | 
 | 596 |                                 } | 
 | 597 |                                 size = *sizePtr; | 
 | 598 |                                 break; | 
 | 599 |                             } | 
 | 600 |                         } | 
 | 601 |                     } | 
 | 602 |                     else if (interfaceMap.first == | 
 | 603 |                              "xyz.openbmc_project.Time.EpochTime") | 
 | 604 |                     { | 
 | 605 |                         for (auto& propertyMap : interfaceMap.second) | 
 | 606 |                         { | 
 | 607 |                             if (propertyMap.first == "Elapsed") | 
 | 608 |                             { | 
 | 609 |                                 const uint64_t* usecsTimeStamp = | 
 | 610 |                                     std::get_if<uint64_t>(&propertyMap.second); | 
 | 611 |                                 if (usecsTimeStamp == nullptr) | 
 | 612 |                                 { | 
 | 613 |                                     messages::internalError(asyncResp->res); | 
 | 614 |                                     break; | 
 | 615 |                                 } | 
 | 616 |                                 timestamp = | 
 | 617 |                                     static_cast<std::time_t>(*usecsTimeStamp); | 
 | 618 |                                 break; | 
 | 619 |                             } | 
 | 620 |                         } | 
 | 621 |                     } | 
 | 622 |                 } | 
 | 623 |  | 
 | 624 |                 asyncResp->res.jsonValue["@odata.type"] = | 
| Ed Tanous | d0dbeef | 2021-07-01 08:46:46 -0700 | [diff] [blame] | 625 |                     "#LogEntry.v1_7_0.LogEntry"; | 
| Asmitha Karunanithi | 5cb1dd2 | 2020-05-07 04:35:02 -0500 | [diff] [blame] | 626 |                 asyncResp->res.jsonValue["@odata.id"] = dumpPath + entryID; | 
 | 627 |                 asyncResp->res.jsonValue["Id"] = entryID; | 
 | 628 |                 asyncResp->res.jsonValue["EntryType"] = "Event"; | 
 | 629 |                 asyncResp->res.jsonValue["Created"] = | 
 | 630 |                     crow::utility::getDateTime(timestamp); | 
 | 631 |                 asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entry"; | 
 | 632 |  | 
| Asmitha Karunanithi | d337bb7 | 2020-09-21 10:34:02 -0500 | [diff] [blame] | 633 |                 asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size; | 
| Asmitha Karunanithi | 5cb1dd2 | 2020-05-07 04:35:02 -0500 | [diff] [blame] | 634 |  | 
 | 635 |                 if (dumpType == "BMC") | 
 | 636 |                 { | 
| Asmitha Karunanithi | d337bb7 | 2020-09-21 10:34:02 -0500 | [diff] [blame] | 637 |                     asyncResp->res.jsonValue["DiagnosticDataType"] = "Manager"; | 
 | 638 |                     asyncResp->res.jsonValue["AdditionalDataURI"] = | 
| Abhishek Patel | de8d94a | 2021-05-13 22:57:36 -0500 | [diff] [blame] | 639 |                         "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/" + | 
 | 640 |                         entryID + "/attachment"; | 
| Asmitha Karunanithi | 5cb1dd2 | 2020-05-07 04:35:02 -0500 | [diff] [blame] | 641 |                 } | 
 | 642 |                 else if (dumpType == "System") | 
 | 643 |                 { | 
| Asmitha Karunanithi | d337bb7 | 2020-09-21 10:34:02 -0500 | [diff] [blame] | 644 |                     asyncResp->res.jsonValue["DiagnosticDataType"] = "OEM"; | 
 | 645 |                     asyncResp->res.jsonValue["OEMDiagnosticDataType"] = | 
| Asmitha Karunanithi | 5cb1dd2 | 2020-05-07 04:35:02 -0500 | [diff] [blame] | 646 |                         "System"; | 
| Asmitha Karunanithi | d337bb7 | 2020-09-21 10:34:02 -0500 | [diff] [blame] | 647 |                     asyncResp->res.jsonValue["AdditionalDataURI"] = | 
| Abhishek Patel | de8d94a | 2021-05-13 22:57:36 -0500 | [diff] [blame] | 648 |                         "/redfish/v1/Systems/system/LogServices/Dump/Entries/" + | 
 | 649 |                         entryID + "/attachment"; | 
| Asmitha Karunanithi | 5cb1dd2 | 2020-05-07 04:35:02 -0500 | [diff] [blame] | 650 |                 } | 
 | 651 |             } | 
| Asmitha Karunanithi | b47452b | 2020-09-25 02:02:19 -0500 | [diff] [blame] | 652 |             if (foundDumpEntry == false) | 
 | 653 |             { | 
 | 654 |                 BMCWEB_LOG_ERROR << "Can't find Dump Entry"; | 
 | 655 |                 messages::internalError(asyncResp->res); | 
 | 656 |                 return; | 
 | 657 |             } | 
| Asmitha Karunanithi | 5cb1dd2 | 2020-05-07 04:35:02 -0500 | [diff] [blame] | 658 |         }, | 
 | 659 |         "xyz.openbmc_project.Dump.Manager", "/xyz/openbmc_project/dump", | 
 | 660 |         "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); | 
 | 661 | } | 
 | 662 |  | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 663 | inline void deleteDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
| Stanley Chu | 9878256 | 2020-11-04 16:10:24 +0800 | [diff] [blame] | 664 |                             const std::string& entryID, | 
| Asmitha Karunanithi | b47452b | 2020-09-25 02:02:19 -0500 | [diff] [blame] | 665 |                             const std::string& dumpType) | 
| Asmitha Karunanithi | 5cb1dd2 | 2020-05-07 04:35:02 -0500 | [diff] [blame] | 666 | { | 
| George Liu | 3de8d8b | 2021-03-22 17:49:39 +0800 | [diff] [blame] | 667 |     auto respHandler = [asyncResp, | 
 | 668 |                         entryID](const boost::system::error_code ec) { | 
| Asmitha Karunanithi | 5cb1dd2 | 2020-05-07 04:35:02 -0500 | [diff] [blame] | 669 |         BMCWEB_LOG_DEBUG << "Dump Entry doDelete callback: Done"; | 
 | 670 |         if (ec) | 
 | 671 |         { | 
| George Liu | 3de8d8b | 2021-03-22 17:49:39 +0800 | [diff] [blame] | 672 |             if (ec.value() == EBADR) | 
 | 673 |             { | 
 | 674 |                 messages::resourceNotFound(asyncResp->res, "LogEntry", entryID); | 
 | 675 |                 return; | 
 | 676 |             } | 
| Asmitha Karunanithi | 5cb1dd2 | 2020-05-07 04:35:02 -0500 | [diff] [blame] | 677 |             BMCWEB_LOG_ERROR << "Dump (DBus) doDelete respHandler got error " | 
 | 678 |                              << ec; | 
 | 679 |             messages::internalError(asyncResp->res); | 
 | 680 |             return; | 
 | 681 |         } | 
 | 682 |     }; | 
 | 683 |     crow::connections::systemBus->async_method_call( | 
 | 684 |         respHandler, "xyz.openbmc_project.Dump.Manager", | 
| Asmitha Karunanithi | b47452b | 2020-09-25 02:02:19 -0500 | [diff] [blame] | 685 |         "/xyz/openbmc_project/dump/" + | 
 | 686 |             std::string(boost::algorithm::to_lower_copy(dumpType)) + "/entry/" + | 
 | 687 |             entryID, | 
| Asmitha Karunanithi | 5cb1dd2 | 2020-05-07 04:35:02 -0500 | [diff] [blame] | 688 |         "xyz.openbmc_project.Object.Delete", "Delete"); | 
 | 689 | } | 
 | 690 |  | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 691 | inline void | 
 | 692 |     createDumpTaskCallback(const crow::Request& req, | 
 | 693 |                            const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
 | 694 |                            const uint32_t& dumpId, const std::string& dumpPath, | 
 | 695 |                            const std::string& dumpType) | 
| Asmitha Karunanithi | a43be80 | 2020-05-07 05:05:36 -0500 | [diff] [blame] | 696 | { | 
 | 697 |     std::shared_ptr<task::TaskData> task = task::TaskData::createTask( | 
| Asmitha Karunanithi | 6145ed6 | 2020-09-17 23:40:03 -0500 | [diff] [blame] | 698 |         [dumpId, dumpPath, dumpType]( | 
| Asmitha Karunanithi | a43be80 | 2020-05-07 05:05:36 -0500 | [diff] [blame] | 699 |             boost::system::error_code err, sdbusplus::message::message& m, | 
 | 700 |             const std::shared_ptr<task::TaskData>& taskData) { | 
| Ed Tanous | cb13a39 | 2020-07-25 19:02:03 +0000 | [diff] [blame] | 701 |             if (err) | 
 | 702 |             { | 
| Asmitha Karunanithi | 6145ed6 | 2020-09-17 23:40:03 -0500 | [diff] [blame] | 703 |                 BMCWEB_LOG_ERROR << "Error in creating a dump"; | 
 | 704 |                 taskData->state = "Cancelled"; | 
 | 705 |                 return task::completed; | 
| Ed Tanous | cb13a39 | 2020-07-25 19:02:03 +0000 | [diff] [blame] | 706 |             } | 
| Asmitha Karunanithi | a43be80 | 2020-05-07 05:05:36 -0500 | [diff] [blame] | 707 |             std::vector<std::pair< | 
 | 708 |                 std::string, | 
 | 709 |                 std::vector<std::pair<std::string, std::variant<std::string>>>>> | 
 | 710 |                 interfacesList; | 
 | 711 |  | 
 | 712 |             sdbusplus::message::object_path objPath; | 
 | 713 |  | 
 | 714 |             m.read(objPath, interfacesList); | 
 | 715 |  | 
| Asmitha Karunanithi | b47452b | 2020-09-25 02:02:19 -0500 | [diff] [blame] | 716 |             if (objPath.str == | 
 | 717 |                 "/xyz/openbmc_project/dump/" + | 
 | 718 |                     std::string(boost::algorithm::to_lower_copy(dumpType)) + | 
 | 719 |                     "/entry/" + std::to_string(dumpId)) | 
| Asmitha Karunanithi | a43be80 | 2020-05-07 05:05:36 -0500 | [diff] [blame] | 720 |             { | 
| Asmitha Karunanithi | b47452b | 2020-09-25 02:02:19 -0500 | [diff] [blame] | 721 |                 nlohmann::json retMessage = messages::success(); | 
 | 722 |                 taskData->messages.emplace_back(retMessage); | 
| Asmitha Karunanithi | a43be80 | 2020-05-07 05:05:36 -0500 | [diff] [blame] | 723 |  | 
| Asmitha Karunanithi | b47452b | 2020-09-25 02:02:19 -0500 | [diff] [blame] | 724 |                 std::string headerLoc = | 
 | 725 |                     "Location: " + dumpPath + std::to_string(dumpId); | 
 | 726 |                 taskData->payload->httpHeaders.emplace_back( | 
 | 727 |                     std::move(headerLoc)); | 
| Asmitha Karunanithi | a43be80 | 2020-05-07 05:05:36 -0500 | [diff] [blame] | 728 |  | 
| Asmitha Karunanithi | b47452b | 2020-09-25 02:02:19 -0500 | [diff] [blame] | 729 |                 taskData->state = "Completed"; | 
 | 730 |                 return task::completed; | 
| Asmitha Karunanithi | a43be80 | 2020-05-07 05:05:36 -0500 | [diff] [blame] | 731 |             } | 
| Asmitha Karunanithi | 6145ed6 | 2020-09-17 23:40:03 -0500 | [diff] [blame] | 732 |             return task::completed; | 
| Asmitha Karunanithi | a43be80 | 2020-05-07 05:05:36 -0500 | [diff] [blame] | 733 |         }, | 
 | 734 |         "type='signal',interface='org.freedesktop.DBus." | 
 | 735 |         "ObjectManager'," | 
 | 736 |         "member='InterfacesAdded', " | 
 | 737 |         "path='/xyz/openbmc_project/dump'"); | 
 | 738 |  | 
 | 739 |     task->startTimer(std::chrono::minutes(3)); | 
 | 740 |     task->populateResp(asyncResp->res); | 
 | 741 |     task->payload.emplace(req); | 
 | 742 | } | 
 | 743 |  | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 744 | inline void createDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
 | 745 |                        const crow::Request& req, const std::string& dumpType) | 
| Asmitha Karunanithi | a43be80 | 2020-05-07 05:05:36 -0500 | [diff] [blame] | 746 | { | 
| Asmitha Karunanithi | a43be80 | 2020-05-07 05:05:36 -0500 | [diff] [blame] | 747 |  | 
 | 748 |     std::string dumpPath; | 
 | 749 |     if (dumpType == "BMC") | 
 | 750 |     { | 
 | 751 |         dumpPath = "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/"; | 
 | 752 |     } | 
 | 753 |     else if (dumpType == "System") | 
 | 754 |     { | 
 | 755 |         dumpPath = "/redfish/v1/Systems/system/LogServices/Dump/Entries/"; | 
 | 756 |     } | 
 | 757 |     else | 
 | 758 |     { | 
 | 759 |         BMCWEB_LOG_ERROR << "Invalid dump type: " << dumpType; | 
 | 760 |         messages::internalError(asyncResp->res); | 
 | 761 |         return; | 
 | 762 |     } | 
 | 763 |  | 
 | 764 |     std::optional<std::string> diagnosticDataType; | 
 | 765 |     std::optional<std::string> oemDiagnosticDataType; | 
 | 766 |  | 
 | 767 |     if (!redfish::json_util::readJson( | 
 | 768 |             req, asyncResp->res, "DiagnosticDataType", diagnosticDataType, | 
 | 769 |             "OEMDiagnosticDataType", oemDiagnosticDataType)) | 
 | 770 |     { | 
 | 771 |         return; | 
 | 772 |     } | 
 | 773 |  | 
 | 774 |     if (dumpType == "System") | 
 | 775 |     { | 
 | 776 |         if (!oemDiagnosticDataType || !diagnosticDataType) | 
 | 777 |         { | 
 | 778 |             BMCWEB_LOG_ERROR << "CreateDump action parameter " | 
 | 779 |                                 "'DiagnosticDataType'/" | 
 | 780 |                                 "'OEMDiagnosticDataType' value not found!"; | 
 | 781 |             messages::actionParameterMissing( | 
 | 782 |                 asyncResp->res, "CollectDiagnosticData", | 
 | 783 |                 "DiagnosticDataType & OEMDiagnosticDataType"); | 
 | 784 |             return; | 
 | 785 |         } | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 786 |         if ((*oemDiagnosticDataType != "System") || | 
 | 787 |             (*diagnosticDataType != "OEM")) | 
| Asmitha Karunanithi | a43be80 | 2020-05-07 05:05:36 -0500 | [diff] [blame] | 788 |         { | 
 | 789 |             BMCWEB_LOG_ERROR << "Wrong parameter values passed"; | 
 | 790 |             messages::invalidObject(asyncResp->res, | 
 | 791 |                                     "System Dump creation parameters"); | 
 | 792 |             return; | 
 | 793 |         } | 
 | 794 |     } | 
 | 795 |     else if (dumpType == "BMC") | 
 | 796 |     { | 
 | 797 |         if (!diagnosticDataType) | 
 | 798 |         { | 
 | 799 |             BMCWEB_LOG_ERROR << "CreateDump action parameter " | 
 | 800 |                                 "'DiagnosticDataType' not found!"; | 
 | 801 |             messages::actionParameterMissing( | 
 | 802 |                 asyncResp->res, "CollectDiagnosticData", "DiagnosticDataType"); | 
 | 803 |             return; | 
 | 804 |         } | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 805 |         if (*diagnosticDataType != "Manager") | 
| Asmitha Karunanithi | a43be80 | 2020-05-07 05:05:36 -0500 | [diff] [blame] | 806 |         { | 
 | 807 |             BMCWEB_LOG_ERROR | 
 | 808 |                 << "Wrong parameter value passed for 'DiagnosticDataType'"; | 
 | 809 |             messages::invalidObject(asyncResp->res, | 
 | 810 |                                     "BMC Dump creation parameters"); | 
 | 811 |             return; | 
 | 812 |         } | 
 | 813 |     } | 
 | 814 |  | 
 | 815 |     crow::connections::systemBus->async_method_call( | 
 | 816 |         [asyncResp, req, dumpPath, dumpType](const boost::system::error_code ec, | 
 | 817 |                                              const uint32_t& dumpId) { | 
 | 818 |             if (ec) | 
 | 819 |             { | 
 | 820 |                 BMCWEB_LOG_ERROR << "CreateDump resp_handler got error " << ec; | 
 | 821 |                 messages::internalError(asyncResp->res); | 
 | 822 |                 return; | 
 | 823 |             } | 
 | 824 |             BMCWEB_LOG_DEBUG << "Dump Created. Id: " << dumpId; | 
 | 825 |  | 
 | 826 |             createDumpTaskCallback(req, asyncResp, dumpId, dumpPath, dumpType); | 
 | 827 |         }, | 
| Asmitha Karunanithi | b47452b | 2020-09-25 02:02:19 -0500 | [diff] [blame] | 828 |         "xyz.openbmc_project.Dump.Manager", | 
 | 829 |         "/xyz/openbmc_project/dump/" + | 
 | 830 |             std::string(boost::algorithm::to_lower_copy(dumpType)), | 
| Asmitha Karunanithi | a43be80 | 2020-05-07 05:05:36 -0500 | [diff] [blame] | 831 |         "xyz.openbmc_project.Dump.Create", "CreateDump"); | 
 | 832 | } | 
 | 833 |  | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 834 | inline void clearDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
 | 835 |                       const std::string& dumpType) | 
| Asmitha Karunanithi | 80319af | 2020-05-07 05:30:21 -0500 | [diff] [blame] | 836 | { | 
| Asmitha Karunanithi | b47452b | 2020-09-25 02:02:19 -0500 | [diff] [blame] | 837 |     std::string dumpTypeLowerCopy = | 
 | 838 |         std::string(boost::algorithm::to_lower_copy(dumpType)); | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 839 |  | 
| Asmitha Karunanithi | 80319af | 2020-05-07 05:30:21 -0500 | [diff] [blame] | 840 |     crow::connections::systemBus->async_method_call( | 
| Asmitha Karunanithi | b47452b | 2020-09-25 02:02:19 -0500 | [diff] [blame] | 841 |         [asyncResp, dumpType](const boost::system::error_code ec, | 
 | 842 |                               const std::vector<std::string>& subTreePaths) { | 
| Asmitha Karunanithi | 80319af | 2020-05-07 05:30:21 -0500 | [diff] [blame] | 843 |             if (ec) | 
 | 844 |             { | 
 | 845 |                 BMCWEB_LOG_ERROR << "resp_handler got error " << ec; | 
 | 846 |                 messages::internalError(asyncResp->res); | 
 | 847 |                 return; | 
 | 848 |             } | 
 | 849 |  | 
 | 850 |             for (const std::string& path : subTreePaths) | 
 | 851 |             { | 
| Ed Tanous | 2dfd18e | 2020-12-18 00:41:31 +0000 | [diff] [blame] | 852 |                 sdbusplus::message::object_path objPath(path); | 
 | 853 |                 std::string logID = objPath.filename(); | 
 | 854 |                 if (logID.empty()) | 
| Asmitha Karunanithi | 80319af | 2020-05-07 05:30:21 -0500 | [diff] [blame] | 855 |                 { | 
| Ed Tanous | 2dfd18e | 2020-12-18 00:41:31 +0000 | [diff] [blame] | 856 |                     continue; | 
| Asmitha Karunanithi | 80319af | 2020-05-07 05:30:21 -0500 | [diff] [blame] | 857 |                 } | 
| Ed Tanous | 2dfd18e | 2020-12-18 00:41:31 +0000 | [diff] [blame] | 858 |                 deleteDumpEntry(asyncResp, logID, dumpType); | 
| Asmitha Karunanithi | 80319af | 2020-05-07 05:30:21 -0500 | [diff] [blame] | 859 |             } | 
 | 860 |         }, | 
 | 861 |         "xyz.openbmc_project.ObjectMapper", | 
 | 862 |         "/xyz/openbmc_project/object_mapper", | 
 | 863 |         "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", | 
| Asmitha Karunanithi | b47452b | 2020-09-25 02:02:19 -0500 | [diff] [blame] | 864 |         "/xyz/openbmc_project/dump/" + dumpTypeLowerCopy, 0, | 
 | 865 |         std::array<std::string, 1>{"xyz.openbmc_project.Dump.Entry." + | 
 | 866 |                                    dumpType}); | 
| Asmitha Karunanithi | 80319af | 2020-05-07 05:30:21 -0500 | [diff] [blame] | 867 | } | 
 | 868 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 869 | inline static void parseCrashdumpParameters( | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 870 |     const std::vector<std::pair<std::string, VariantType>>& params, | 
 | 871 |     std::string& filename, std::string& timestamp, std::string& logfile) | 
| Johnathan Mantey | 043a053 | 2020-03-10 17:15:28 -0700 | [diff] [blame] | 872 | { | 
 | 873 |     for (auto property : params) | 
 | 874 |     { | 
 | 875 |         if (property.first == "Timestamp") | 
 | 876 |         { | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 877 |             const std::string* value = | 
| Patrick Williams | 8d78b7a | 2020-05-13 11:24:20 -0500 | [diff] [blame] | 878 |                 std::get_if<std::string>(&property.second); | 
| Johnathan Mantey | 043a053 | 2020-03-10 17:15:28 -0700 | [diff] [blame] | 879 |             if (value != nullptr) | 
 | 880 |             { | 
 | 881 |                 timestamp = *value; | 
 | 882 |             } | 
 | 883 |         } | 
 | 884 |         else if (property.first == "Filename") | 
 | 885 |         { | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 886 |             const std::string* value = | 
| Patrick Williams | 8d78b7a | 2020-05-13 11:24:20 -0500 | [diff] [blame] | 887 |                 std::get_if<std::string>(&property.second); | 
| Johnathan Mantey | 043a053 | 2020-03-10 17:15:28 -0700 | [diff] [blame] | 888 |             if (value != nullptr) | 
 | 889 |             { | 
 | 890 |                 filename = *value; | 
 | 891 |             } | 
 | 892 |         } | 
 | 893 |         else if (property.first == "Log") | 
 | 894 |         { | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 895 |             const std::string* value = | 
| Patrick Williams | 8d78b7a | 2020-05-13 11:24:20 -0500 | [diff] [blame] | 896 |                 std::get_if<std::string>(&property.second); | 
| Johnathan Mantey | 043a053 | 2020-03-10 17:15:28 -0700 | [diff] [blame] | 897 |             if (value != nullptr) | 
 | 898 |             { | 
 | 899 |                 logfile = *value; | 
 | 900 |             } | 
 | 901 |         } | 
 | 902 |     } | 
 | 903 | } | 
 | 904 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 905 | constexpr char const* postCodeIface = "xyz.openbmc_project.State.Boot.PostCode"; | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 906 | inline void requestRoutesSystemLogServiceCollection(App& app) | 
| Ed Tanous | 1da66f7 | 2018-07-27 16:13:37 -0700 | [diff] [blame] | 907 | { | 
| Jason M. Bills | c4bf637 | 2018-11-05 13:48:27 -0800 | [diff] [blame] | 908 |     /** | 
 | 909 |      * Functions triggers appropriate requests on DBus | 
 | 910 |      */ | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 911 |     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 912 |         .privileges(redfish::privileges::getLogServiceCollection) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 913 |         .methods(boost::beast::http::verb::get)( | 
 | 914 |             [](const crow::Request&, | 
 | 915 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) | 
 | 916 |  | 
 | 917 |             { | 
 | 918 |                 // Collections don't include the static data added by SubRoute | 
 | 919 |                 // because it has a duplicate entry for members | 
 | 920 |                 asyncResp->res.jsonValue["@odata.type"] = | 
 | 921 |                     "#LogServiceCollection.LogServiceCollection"; | 
 | 922 |                 asyncResp->res.jsonValue["@odata.id"] = | 
 | 923 |                     "/redfish/v1/Systems/system/LogServices"; | 
 | 924 |                 asyncResp->res.jsonValue["Name"] = | 
 | 925 |                     "System Log Services Collection"; | 
 | 926 |                 asyncResp->res.jsonValue["Description"] = | 
 | 927 |                     "Collection of LogServices for this Computer System"; | 
 | 928 |                 nlohmann::json& logServiceArray = | 
 | 929 |                     asyncResp->res.jsonValue["Members"]; | 
 | 930 |                 logServiceArray = nlohmann::json::array(); | 
 | 931 |                 logServiceArray.push_back( | 
 | 932 |                     {{"@odata.id", | 
 | 933 |                       "/redfish/v1/Systems/system/LogServices/EventLog"}}); | 
| Asmitha Karunanithi | 5cb1dd2 | 2020-05-07 04:35:02 -0500 | [diff] [blame] | 934 | #ifdef BMCWEB_ENABLE_REDFISH_DUMP_LOG | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 935 |                 logServiceArray.push_back( | 
 | 936 |                     {{"@odata.id", | 
 | 937 |                       "/redfish/v1/Systems/system/LogServices/Dump"}}); | 
| raviteja-b | c9bb686 | 2020-02-03 11:53:32 -0600 | [diff] [blame] | 938 | #endif | 
 | 939 |  | 
| Jason M. Bills | d53dd41 | 2019-02-12 17:16:22 -0800 | [diff] [blame] | 940 | #ifdef BMCWEB_ENABLE_REDFISH_CPU_LOG | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 941 |                 logServiceArray.push_back( | 
 | 942 |                     {{"@odata.id", | 
 | 943 |                       "/redfish/v1/Systems/system/LogServices/Crashdump"}}); | 
| Jason M. Bills | d53dd41 | 2019-02-12 17:16:22 -0800 | [diff] [blame] | 944 | #endif | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 945 |                 asyncResp->res.jsonValue["Members@odata.count"] = | 
 | 946 |                     logServiceArray.size(); | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 947 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 948 |                 crow::connections::systemBus->async_method_call( | 
 | 949 |                     [asyncResp](const boost::system::error_code ec, | 
 | 950 |                                 const std::vector<std::string>& subtreePath) { | 
 | 951 |                         if (ec) | 
 | 952 |                         { | 
 | 953 |                             BMCWEB_LOG_ERROR << ec; | 
 | 954 |                             return; | 
 | 955 |                         } | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 956 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 957 |                         for (auto& pathStr : subtreePath) | 
 | 958 |                         { | 
 | 959 |                             if (pathStr.find("PostCode") != std::string::npos) | 
 | 960 |                             { | 
 | 961 |                                 nlohmann::json& logServiceArrayLocal = | 
 | 962 |                                     asyncResp->res.jsonValue["Members"]; | 
 | 963 |                                 logServiceArrayLocal.push_back( | 
 | 964 |                                     {{"@odata.id", "/redfish/v1/Systems/system/" | 
 | 965 |                                                    "LogServices/PostCodes"}}); | 
 | 966 |                                 asyncResp->res | 
 | 967 |                                     .jsonValue["Members@odata.count"] = | 
 | 968 |                                     logServiceArrayLocal.size(); | 
 | 969 |                                 return; | 
 | 970 |                             } | 
 | 971 |                         } | 
 | 972 |                     }, | 
 | 973 |                     "xyz.openbmc_project.ObjectMapper", | 
 | 974 |                     "/xyz/openbmc_project/object_mapper", | 
 | 975 |                     "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/", | 
 | 976 |                     0, std::array<const char*, 1>{postCodeIface}); | 
 | 977 |             }); | 
 | 978 | } | 
 | 979 |  | 
 | 980 | inline void requestRoutesEventLogService(App& app) | 
 | 981 | { | 
 | 982 |     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/EventLog/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 983 |         .privileges(redfish::privileges::getLogService) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 984 |         .methods( | 
 | 985 |             boost::beast::http::verb:: | 
 | 986 |                 get)([](const crow::Request&, | 
 | 987 |                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { | 
 | 988 |             asyncResp->res.jsonValue["@odata.id"] = | 
 | 989 |                 "/redfish/v1/Systems/system/LogServices/EventLog"; | 
 | 990 |             asyncResp->res.jsonValue["@odata.type"] = | 
 | 991 |                 "#LogService.v1_1_0.LogService"; | 
 | 992 |             asyncResp->res.jsonValue["Name"] = "Event Log Service"; | 
 | 993 |             asyncResp->res.jsonValue["Description"] = | 
 | 994 |                 "System Event Log Service"; | 
 | 995 |             asyncResp->res.jsonValue["Id"] = "EventLog"; | 
 | 996 |             asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull"; | 
| Tejas Patil | 7c8c405 | 2021-06-04 17:43:14 +0530 | [diff] [blame] | 997 |  | 
 | 998 |             std::pair<std::string, std::string> redfishDateTimeOffset = | 
 | 999 |                 crow::utility::getDateTimeOffsetNow(); | 
 | 1000 |  | 
 | 1001 |             asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; | 
 | 1002 |             asyncResp->res.jsonValue["DateTimeLocalOffset"] = | 
 | 1003 |                 redfishDateTimeOffset.second; | 
 | 1004 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1005 |             asyncResp->res.jsonValue["Entries"] = { | 
 | 1006 |                 {"@odata.id", | 
 | 1007 |                  "/redfish/v1/Systems/system/LogServices/EventLog/Entries"}}; | 
 | 1008 |             asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] = { | 
 | 1009 |  | 
 | 1010 |                 {"target", "/redfish/v1/Systems/system/LogServices/EventLog/" | 
 | 1011 |                            "Actions/LogService.ClearLog"}}; | 
 | 1012 |         }); | 
 | 1013 | } | 
 | 1014 |  | 
 | 1015 | inline void requestRoutesJournalEventLogClear(App& app) | 
 | 1016 | { | 
 | 1017 |     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/EventLog/Actions/" | 
 | 1018 |                       "LogService.ClearLog/") | 
| Ed Tanous | 432a890 | 2021-06-14 15:28:56 -0700 | [diff] [blame] | 1019 |         .privileges({{"ConfigureComponents"}}) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1020 |         .methods(boost::beast::http::verb::post)( | 
 | 1021 |             [](const crow::Request&, | 
 | 1022 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { | 
 | 1023 |                 // Clear the EventLog by deleting the log files | 
 | 1024 |                 std::vector<std::filesystem::path> redfishLogFiles; | 
 | 1025 |                 if (getRedfishLogFiles(redfishLogFiles)) | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 1026 |                 { | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1027 |                     for (const std::filesystem::path& file : redfishLogFiles) | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 1028 |                     { | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1029 |                         std::error_code ec; | 
 | 1030 |                         std::filesystem::remove(file, ec); | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 1031 |                     } | 
 | 1032 |                 } | 
| Jason M. Bills | c4bf637 | 2018-11-05 13:48:27 -0800 | [diff] [blame] | 1033 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1034 |                 // Reload rsyslog so it knows to start new log files | 
 | 1035 |                 crow::connections::systemBus->async_method_call( | 
 | 1036 |                     [asyncResp](const boost::system::error_code ec) { | 
 | 1037 |                         if (ec) | 
 | 1038 |                         { | 
 | 1039 |                             BMCWEB_LOG_ERROR << "Failed to reload rsyslog: " | 
 | 1040 |                                              << ec; | 
 | 1041 |                             messages::internalError(asyncResp->res); | 
 | 1042 |                             return; | 
 | 1043 |                         } | 
| Jason M. Bills | c4bf637 | 2018-11-05 13:48:27 -0800 | [diff] [blame] | 1044 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1045 |                         messages::success(asyncResp->res); | 
 | 1046 |                     }, | 
 | 1047 |                     "org.freedesktop.systemd1", "/org/freedesktop/systemd1", | 
 | 1048 |                     "org.freedesktop.systemd1.Manager", "ReloadUnit", | 
 | 1049 |                     "rsyslog.service", "replace"); | 
 | 1050 |             }); | 
 | 1051 | } | 
| Jason M. Bills | c4bf637 | 2018-11-05 13:48:27 -0800 | [diff] [blame] | 1052 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 1053 | static int fillEventLogEntryJson(const std::string& logEntryID, | 
| Ed Tanous | b5a7693 | 2020-09-29 16:16:58 -0700 | [diff] [blame] | 1054 |                                  const std::string& logEntry, | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 1055 |                                  nlohmann::json& logEntryJson) | 
| Jason M. Bills | c4bf637 | 2018-11-05 13:48:27 -0800 | [diff] [blame] | 1056 | { | 
| Jason M. Bills | 9582018 | 2019-04-22 16:25:34 -0700 | [diff] [blame] | 1057 |     // The redfish log format is "<Timestamp> <MessageId>,<MessageArgs>" | 
| Jason M. Bills | cd225da | 2019-05-08 15:31:57 -0700 | [diff] [blame] | 1058 |     // First get the Timestamp | 
| Ed Tanous | f23b729 | 2020-10-15 09:41:17 -0700 | [diff] [blame] | 1059 |     size_t space = logEntry.find_first_of(' '); | 
| Jason M. Bills | cd225da | 2019-05-08 15:31:57 -0700 | [diff] [blame] | 1060 |     if (space == std::string::npos) | 
| Jason M. Bills | 9582018 | 2019-04-22 16:25:34 -0700 | [diff] [blame] | 1061 |     { | 
 | 1062 |         return 1; | 
 | 1063 |     } | 
| Jason M. Bills | cd225da | 2019-05-08 15:31:57 -0700 | [diff] [blame] | 1064 |     std::string timestamp = logEntry.substr(0, space); | 
 | 1065 |     // Then get the log contents | 
| Ed Tanous | f23b729 | 2020-10-15 09:41:17 -0700 | [diff] [blame] | 1066 |     size_t entryStart = logEntry.find_first_not_of(' ', space); | 
| Jason M. Bills | cd225da | 2019-05-08 15:31:57 -0700 | [diff] [blame] | 1067 |     if (entryStart == std::string::npos) | 
 | 1068 |     { | 
 | 1069 |         return 1; | 
 | 1070 |     } | 
 | 1071 |     std::string_view entry(logEntry); | 
 | 1072 |     entry.remove_prefix(entryStart); | 
 | 1073 |     // Use split to separate the entry into its fields | 
 | 1074 |     std::vector<std::string> logEntryFields; | 
 | 1075 |     boost::split(logEntryFields, entry, boost::is_any_of(","), | 
 | 1076 |                  boost::token_compress_on); | 
 | 1077 |     // We need at least a MessageId to be valid | 
 | 1078 |     if (logEntryFields.size() < 1) | 
 | 1079 |     { | 
 | 1080 |         return 1; | 
 | 1081 |     } | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 1082 |     std::string& messageID = logEntryFields[0]; | 
| Jason M. Bills | 9582018 | 2019-04-22 16:25:34 -0700 | [diff] [blame] | 1083 |  | 
| Jason M. Bills | 4851d45 | 2019-03-28 11:27:48 -0700 | [diff] [blame] | 1084 |     // Get the Message from the MessageRegistry | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 1085 |     const message_registries::Message* message = | 
| Jason M. Bills | 4851d45 | 2019-03-28 11:27:48 -0700 | [diff] [blame] | 1086 |         message_registries::getMessage(messageID); | 
| Jason M. Bills | c4bf637 | 2018-11-05 13:48:27 -0800 | [diff] [blame] | 1087 |  | 
| Jason M. Bills | 4851d45 | 2019-03-28 11:27:48 -0700 | [diff] [blame] | 1088 |     std::string msg; | 
 | 1089 |     std::string severity; | 
 | 1090 |     if (message != nullptr) | 
| Jason M. Bills | c4bf637 | 2018-11-05 13:48:27 -0800 | [diff] [blame] | 1091 |     { | 
| Jason M. Bills | 4851d45 | 2019-03-28 11:27:48 -0700 | [diff] [blame] | 1092 |         msg = message->message; | 
 | 1093 |         severity = message->severity; | 
| Jason M. Bills | c4bf637 | 2018-11-05 13:48:27 -0800 | [diff] [blame] | 1094 |     } | 
 | 1095 |  | 
| Jason M. Bills | 15a86ff | 2019-06-18 13:49:54 -0700 | [diff] [blame] | 1096 |     // Get the MessageArgs from the log if there are any | 
 | 1097 |     boost::beast::span<std::string> messageArgs; | 
 | 1098 |     if (logEntryFields.size() > 1) | 
| Jason M. Bills | 4851d45 | 2019-03-28 11:27:48 -0700 | [diff] [blame] | 1099 |     { | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 1100 |         std::string& messageArgsStart = logEntryFields[1]; | 
| Jason M. Bills | 15a86ff | 2019-06-18 13:49:54 -0700 | [diff] [blame] | 1101 |         // If the first string is empty, assume there are no MessageArgs | 
 | 1102 |         std::size_t messageArgsSize = 0; | 
 | 1103 |         if (!messageArgsStart.empty()) | 
| Jason M. Bills | 4851d45 | 2019-03-28 11:27:48 -0700 | [diff] [blame] | 1104 |         { | 
| Jason M. Bills | 15a86ff | 2019-06-18 13:49:54 -0700 | [diff] [blame] | 1105 |             messageArgsSize = logEntryFields.size() - 1; | 
 | 1106 |         } | 
 | 1107 |  | 
| Ed Tanous | 23a21a1 | 2020-07-25 04:45:05 +0000 | [diff] [blame] | 1108 |         messageArgs = {&messageArgsStart, messageArgsSize}; | 
| Jason M. Bills | 15a86ff | 2019-06-18 13:49:54 -0700 | [diff] [blame] | 1109 |  | 
 | 1110 |         // Fill the MessageArgs into the Message | 
 | 1111 |         int i = 0; | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 1112 |         for (const std::string& messageArg : messageArgs) | 
| Jason M. Bills | 15a86ff | 2019-06-18 13:49:54 -0700 | [diff] [blame] | 1113 |         { | 
 | 1114 |             std::string argStr = "%" + std::to_string(++i); | 
 | 1115 |             size_t argPos = msg.find(argStr); | 
 | 1116 |             if (argPos != std::string::npos) | 
 | 1117 |             { | 
 | 1118 |                 msg.replace(argPos, argStr.length(), messageArg); | 
 | 1119 |             } | 
| Jason M. Bills | 4851d45 | 2019-03-28 11:27:48 -0700 | [diff] [blame] | 1120 |         } | 
 | 1121 |     } | 
 | 1122 |  | 
| Jason M. Bills | 9582018 | 2019-04-22 16:25:34 -0700 | [diff] [blame] | 1123 |     // Get the Created time from the timestamp. The log timestamp is in RFC3339 | 
 | 1124 |     // format which matches the Redfish format except for the fractional seconds | 
 | 1125 |     // between the '.' and the '+', so just remove them. | 
| Ed Tanous | f23b729 | 2020-10-15 09:41:17 -0700 | [diff] [blame] | 1126 |     std::size_t dot = timestamp.find_first_of('.'); | 
 | 1127 |     std::size_t plus = timestamp.find_first_of('+'); | 
| Jason M. Bills | 9582018 | 2019-04-22 16:25:34 -0700 | [diff] [blame] | 1128 |     if (dot != std::string::npos && plus != std::string::npos) | 
| Jason M. Bills | c4bf637 | 2018-11-05 13:48:27 -0800 | [diff] [blame] | 1129 |     { | 
| Jason M. Bills | 9582018 | 2019-04-22 16:25:34 -0700 | [diff] [blame] | 1130 |         timestamp.erase(dot, plus - dot); | 
| Jason M. Bills | c4bf637 | 2018-11-05 13:48:27 -0800 | [diff] [blame] | 1131 |     } | 
 | 1132 |  | 
 | 1133 |     // Fill in the log entry with the gathered data | 
| Jason M. Bills | 9582018 | 2019-04-22 16:25:34 -0700 | [diff] [blame] | 1134 |     logEntryJson = { | 
| Ed Tanous | d0dbeef | 2021-07-01 08:46:46 -0700 | [diff] [blame] | 1135 |         {"@odata.type", "#LogEntry.v1_4_0.LogEntry"}, | 
| Ed Tanous | 029573d | 2019-02-01 10:57:49 -0800 | [diff] [blame] | 1136 |         {"@odata.id", | 
| Jason M. Bills | 897967d | 2019-07-29 17:05:30 -0700 | [diff] [blame] | 1137 |          "/redfish/v1/Systems/system/LogServices/EventLog/Entries/" + | 
| Jason M. Bills | 9582018 | 2019-04-22 16:25:34 -0700 | [diff] [blame] | 1138 |              logEntryID}, | 
| Jason M. Bills | c4bf637 | 2018-11-05 13:48:27 -0800 | [diff] [blame] | 1139 |         {"Name", "System Event Log Entry"}, | 
| Jason M. Bills | 9582018 | 2019-04-22 16:25:34 -0700 | [diff] [blame] | 1140 |         {"Id", logEntryID}, | 
 | 1141 |         {"Message", std::move(msg)}, | 
 | 1142 |         {"MessageId", std::move(messageID)}, | 
| Ed Tanous | f23b729 | 2020-10-15 09:41:17 -0700 | [diff] [blame] | 1143 |         {"MessageArgs", messageArgs}, | 
| Jason M. Bills | c4bf637 | 2018-11-05 13:48:27 -0800 | [diff] [blame] | 1144 |         {"EntryType", "Event"}, | 
| Jason M. Bills | 9582018 | 2019-04-22 16:25:34 -0700 | [diff] [blame] | 1145 |         {"Severity", std::move(severity)}, | 
 | 1146 |         {"Created", std::move(timestamp)}}; | 
| Jason M. Bills | c4bf637 | 2018-11-05 13:48:27 -0800 | [diff] [blame] | 1147 |     return 0; | 
 | 1148 | } | 
 | 1149 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1150 | inline void requestRoutesJournalEventLogEntryCollection(App& app) | 
| Jason M. Bills | c4bf637 | 2018-11-05 13:48:27 -0800 | [diff] [blame] | 1151 | { | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1152 |     BMCWEB_ROUTE(app, | 
 | 1153 |                  "/redfish/v1/Systems/system/LogServices/EventLog/Entries/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 1154 |         .privileges(redfish::privileges::getLogEntry) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1155 |         .methods(boost::beast::http::verb::get)( | 
 | 1156 |             [](const crow::Request& req, | 
 | 1157 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { | 
 | 1158 |                 uint64_t skip = 0; | 
 | 1159 |                 uint64_t top = maxEntriesPerPage; // Show max entries by default | 
 | 1160 |                 if (!getSkipParam(asyncResp, req, skip)) | 
| Jason M. Bills | 9582018 | 2019-04-22 16:25:34 -0700 | [diff] [blame] | 1161 |                 { | 
| Jason M. Bills | 9582018 | 2019-04-22 16:25:34 -0700 | [diff] [blame] | 1162 |                     return; | 
 | 1163 |                 } | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1164 |                 if (!getTopParam(asyncResp, req, top)) | 
| Jason M. Bills | 897967d | 2019-07-29 17:05:30 -0700 | [diff] [blame] | 1165 |                 { | 
| Jason M. Bills | 897967d | 2019-07-29 17:05:30 -0700 | [diff] [blame] | 1166 |                     return; | 
 | 1167 |                 } | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1168 |                 // Collections don't include the static data added by SubRoute | 
 | 1169 |                 // because it has a duplicate entry for members | 
 | 1170 |                 asyncResp->res.jsonValue["@odata.type"] = | 
 | 1171 |                     "#LogEntryCollection.LogEntryCollection"; | 
 | 1172 |                 asyncResp->res.jsonValue["@odata.id"] = | 
 | 1173 |                     "/redfish/v1/Systems/system/LogServices/EventLog/Entries"; | 
 | 1174 |                 asyncResp->res.jsonValue["Name"] = "System Event Log Entries"; | 
 | 1175 |                 asyncResp->res.jsonValue["Description"] = | 
 | 1176 |                     "Collection of System Event Log Entries"; | 
| Jason M. Bills | 897967d | 2019-07-29 17:05:30 -0700 | [diff] [blame] | 1177 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1178 |                 nlohmann::json& logEntryArray = | 
| Andrew Geissler | cb92c03 | 2018-08-17 07:56:14 -0700 | [diff] [blame] | 1179 |                     asyncResp->res.jsonValue["Members"]; | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1180 |                 logEntryArray = nlohmann::json::array(); | 
 | 1181 |                 // Go through the log files and create a unique ID for each | 
 | 1182 |                 // entry | 
 | 1183 |                 std::vector<std::filesystem::path> redfishLogFiles; | 
 | 1184 |                 getRedfishLogFiles(redfishLogFiles); | 
 | 1185 |                 uint64_t entryCount = 0; | 
 | 1186 |                 std::string logEntry; | 
 | 1187 |  | 
 | 1188 |                 // Oldest logs are in the last file, so start there and loop | 
 | 1189 |                 // backwards | 
 | 1190 |                 for (auto it = redfishLogFiles.rbegin(); | 
 | 1191 |                      it < redfishLogFiles.rend(); it++) | 
| Andrew Geissler | cb92c03 | 2018-08-17 07:56:14 -0700 | [diff] [blame] | 1192 |                 { | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1193 |                     std::ifstream logStream(*it); | 
 | 1194 |                     if (!logStream.is_open()) | 
| Adriana Kobylak | f86bb90 | 2021-01-11 11:11:05 -0600 | [diff] [blame] | 1195 |                     { | 
 | 1196 |                         continue; | 
 | 1197 |                     } | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1198 |  | 
 | 1199 |                     // Reset the unique ID on the first entry | 
 | 1200 |                     bool firstEntry = true; | 
 | 1201 |                     while (std::getline(logStream, logEntry)) | 
| Adriana Kobylak | f86bb90 | 2021-01-11 11:11:05 -0600 | [diff] [blame] | 1202 |                     { | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1203 |                         entryCount++; | 
 | 1204 |                         // Handle paging using skip (number of entries to skip | 
 | 1205 |                         // from the start) and top (number of entries to | 
 | 1206 |                         // display) | 
 | 1207 |                         if (entryCount <= skip || entryCount > skip + top) | 
| George Liu | ebd4590 | 2020-08-26 14:21:10 +0800 | [diff] [blame] | 1208 |                         { | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1209 |                             continue; | 
| George Liu | ebd4590 | 2020-08-26 14:21:10 +0800 | [diff] [blame] | 1210 |                         } | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1211 |  | 
 | 1212 |                         std::string idStr; | 
 | 1213 |                         if (!getUniqueEntryID(logEntry, idStr, firstEntry)) | 
| George Liu | ebd4590 | 2020-08-26 14:21:10 +0800 | [diff] [blame] | 1214 |                         { | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1215 |                             continue; | 
| George Liu | ebd4590 | 2020-08-26 14:21:10 +0800 | [diff] [blame] | 1216 |                         } | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1217 |  | 
 | 1218 |                         if (firstEntry) | 
 | 1219 |                         { | 
 | 1220 |                             firstEntry = false; | 
 | 1221 |                         } | 
 | 1222 |  | 
 | 1223 |                         logEntryArray.push_back({}); | 
 | 1224 |                         nlohmann::json& bmcLogEntry = logEntryArray.back(); | 
 | 1225 |                         if (fillEventLogEntryJson(idStr, logEntry, | 
 | 1226 |                                                   bmcLogEntry) != 0) | 
| Xiaochao Ma | 75710de | 2021-01-21 17:56:02 +0800 | [diff] [blame] | 1227 |                         { | 
 | 1228 |                             messages::internalError(asyncResp->res); | 
 | 1229 |                             return; | 
 | 1230 |                         } | 
| Adriana Kobylak | f86bb90 | 2021-01-11 11:11:05 -0600 | [diff] [blame] | 1231 |                     } | 
| Andrew Geissler | cb92c03 | 2018-08-17 07:56:14 -0700 | [diff] [blame] | 1232 |                 } | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1233 |                 asyncResp->res.jsonValue["Members@odata.count"] = entryCount; | 
 | 1234 |                 if (skip + top < entryCount) | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 1235 |                 { | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1236 |                     asyncResp->res.jsonValue["Members@odata.nextLink"] = | 
| Adriana Kobylak | f86bb90 | 2021-01-11 11:11:05 -0600 | [diff] [blame] | 1237 |                         "/redfish/v1/Systems/system/LogServices/EventLog/" | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1238 |                         "Entries?$skip=" + | 
 | 1239 |                         std::to_string(skip + top); | 
| Adriana Kobylak | f86bb90 | 2021-01-11 11:11:05 -0600 | [diff] [blame] | 1240 |                 } | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1241 |             }); | 
 | 1242 | } | 
| Chicago Duan | 336e96c | 2019-07-15 14:22:08 +0800 | [diff] [blame] | 1243 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1244 | inline void requestRoutesJournalEventLogEntry(App& app) | 
 | 1245 | { | 
 | 1246 |     BMCWEB_ROUTE( | 
 | 1247 |         app, "/redfish/v1/Systems/system/LogServices/EventLog/Entries/<str>/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 1248 |         .privileges(redfish::privileges::getLogEntry) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1249 |         .methods(boost::beast::http::verb::get)( | 
 | 1250 |             [](const crow::Request&, | 
 | 1251 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
 | 1252 |                const std::string& param) { | 
 | 1253 |                 const std::string& targetID = param; | 
| Xiaochao Ma | 75710de | 2021-01-21 17:56:02 +0800 | [diff] [blame] | 1254 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1255 |                 // Go through the log files and check the unique ID for each | 
 | 1256 |                 // entry to find the target entry | 
 | 1257 |                 std::vector<std::filesystem::path> redfishLogFiles; | 
 | 1258 |                 getRedfishLogFiles(redfishLogFiles); | 
 | 1259 |                 std::string logEntry; | 
| Xiaochao Ma | 75710de | 2021-01-21 17:56:02 +0800 | [diff] [blame] | 1260 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1261 |                 // Oldest logs are in the last file, so start there and loop | 
 | 1262 |                 // backwards | 
 | 1263 |                 for (auto it = redfishLogFiles.rbegin(); | 
 | 1264 |                      it < redfishLogFiles.rend(); it++) | 
 | 1265 |                 { | 
 | 1266 |                     std::ifstream logStream(*it); | 
 | 1267 |                     if (!logStream.is_open()) | 
 | 1268 |                     { | 
 | 1269 |                         continue; | 
 | 1270 |                     } | 
| Xiaochao Ma | 75710de | 2021-01-21 17:56:02 +0800 | [diff] [blame] | 1271 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1272 |                     // Reset the unique ID on the first entry | 
 | 1273 |                     bool firstEntry = true; | 
 | 1274 |                     while (std::getline(logStream, logEntry)) | 
 | 1275 |                     { | 
 | 1276 |                         std::string idStr; | 
 | 1277 |                         if (!getUniqueEntryID(logEntry, idStr, firstEntry)) | 
 | 1278 |                         { | 
 | 1279 |                             continue; | 
 | 1280 |                         } | 
| Xiaochao Ma | 75710de | 2021-01-21 17:56:02 +0800 | [diff] [blame] | 1281 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1282 |                         if (firstEntry) | 
 | 1283 |                         { | 
 | 1284 |                             firstEntry = false; | 
 | 1285 |                         } | 
| Xiaochao Ma | 75710de | 2021-01-21 17:56:02 +0800 | [diff] [blame] | 1286 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1287 |                         if (idStr == targetID) | 
 | 1288 |                         { | 
 | 1289 |                             if (fillEventLogEntryJson( | 
 | 1290 |                                     idStr, logEntry, | 
 | 1291 |                                     asyncResp->res.jsonValue) != 0) | 
 | 1292 |                             { | 
 | 1293 |                                 messages::internalError(asyncResp->res); | 
 | 1294 |                                 return; | 
 | 1295 |                             } | 
 | 1296 |                             return; | 
 | 1297 |                         } | 
 | 1298 |                     } | 
 | 1299 |                 } | 
 | 1300 |                 // Requested ID was not found | 
 | 1301 |                 messages::resourceMissingAtURI(asyncResp->res, targetID); | 
 | 1302 |             }); | 
 | 1303 | } | 
 | 1304 |  | 
 | 1305 | inline void requestRoutesDBusEventLogEntryCollection(App& app) | 
 | 1306 | { | 
 | 1307 |     BMCWEB_ROUTE(app, | 
 | 1308 |                  "/redfish/v1/Systems/system/LogServices/EventLog/Entries/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 1309 |         .privileges(redfish::privileges::getLogEntryCollection) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1310 |         .methods( | 
 | 1311 |             boost::beast::http::verb:: | 
 | 1312 |                 get)([](const crow::Request&, | 
 | 1313 |                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { | 
 | 1314 |             // Collections don't include the static data added by SubRoute | 
 | 1315 |             // because it has a duplicate entry for members | 
 | 1316 |             asyncResp->res.jsonValue["@odata.type"] = | 
 | 1317 |                 "#LogEntryCollection.LogEntryCollection"; | 
 | 1318 |             asyncResp->res.jsonValue["@odata.id"] = | 
 | 1319 |                 "/redfish/v1/Systems/system/LogServices/EventLog/Entries"; | 
 | 1320 |             asyncResp->res.jsonValue["Name"] = "System Event Log Entries"; | 
 | 1321 |             asyncResp->res.jsonValue["Description"] = | 
 | 1322 |                 "Collection of System Event Log Entries"; | 
 | 1323 |  | 
 | 1324 |             // DBus implementation of EventLog/Entries | 
 | 1325 |             // Make call to Logging Service to find all log entry objects | 
| Xiaochao Ma | 75710de | 2021-01-21 17:56:02 +0800 | [diff] [blame] | 1326 |             crow::connections::systemBus->async_method_call( | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1327 |                 [asyncResp](const boost::system::error_code ec, | 
 | 1328 |                             GetManagedObjectsType& resp) { | 
| Xiaochao Ma | 75710de | 2021-01-21 17:56:02 +0800 | [diff] [blame] | 1329 |                     if (ec) | 
 | 1330 |                     { | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1331 |                         // TODO Handle for specific error code | 
 | 1332 |                         BMCWEB_LOG_ERROR | 
 | 1333 |                             << "getLogEntriesIfaceData resp_handler got error " | 
 | 1334 |                             << ec; | 
| Xiaochao Ma | 75710de | 2021-01-21 17:56:02 +0800 | [diff] [blame] | 1335 |                         messages::internalError(asyncResp->res); | 
 | 1336 |                         return; | 
 | 1337 |                     } | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1338 |                     nlohmann::json& entriesArray = | 
 | 1339 |                         asyncResp->res.jsonValue["Members"]; | 
 | 1340 |                     entriesArray = nlohmann::json::array(); | 
 | 1341 |                     for (auto& objectPath : resp) | 
 | 1342 |                     { | 
 | 1343 |                         uint32_t* id = nullptr; | 
 | 1344 |                         std::time_t timestamp{}; | 
 | 1345 |                         std::time_t updateTimestamp{}; | 
 | 1346 |                         std::string* severity = nullptr; | 
 | 1347 |                         std::string* message = nullptr; | 
 | 1348 |                         std::string* filePath = nullptr; | 
 | 1349 |                         bool resolved = false; | 
 | 1350 |                         for (auto& interfaceMap : objectPath.second) | 
 | 1351 |                         { | 
 | 1352 |                             if (interfaceMap.first == | 
 | 1353 |                                 "xyz.openbmc_project.Logging.Entry") | 
 | 1354 |                             { | 
 | 1355 |                                 for (auto& propertyMap : interfaceMap.second) | 
 | 1356 |                                 { | 
 | 1357 |                                     if (propertyMap.first == "Id") | 
 | 1358 |                                     { | 
 | 1359 |                                         id = std::get_if<uint32_t>( | 
 | 1360 |                                             &propertyMap.second); | 
 | 1361 |                                     } | 
 | 1362 |                                     else if (propertyMap.first == "Timestamp") | 
 | 1363 |                                     { | 
 | 1364 |                                         const uint64_t* millisTimeStamp = | 
 | 1365 |                                             std::get_if<uint64_t>( | 
 | 1366 |                                                 &propertyMap.second); | 
 | 1367 |                                         if (millisTimeStamp != nullptr) | 
 | 1368 |                                         { | 
 | 1369 |                                             timestamp = | 
 | 1370 |                                                 crow::utility::getTimestamp( | 
 | 1371 |                                                     *millisTimeStamp); | 
 | 1372 |                                         } | 
 | 1373 |                                     } | 
 | 1374 |                                     else if (propertyMap.first == | 
 | 1375 |                                              "UpdateTimestamp") | 
 | 1376 |                                     { | 
 | 1377 |                                         const uint64_t* millisTimeStamp = | 
 | 1378 |                                             std::get_if<uint64_t>( | 
 | 1379 |                                                 &propertyMap.second); | 
 | 1380 |                                         if (millisTimeStamp != nullptr) | 
 | 1381 |                                         { | 
 | 1382 |                                             updateTimestamp = | 
 | 1383 |                                                 crow::utility::getTimestamp( | 
 | 1384 |                                                     *millisTimeStamp); | 
 | 1385 |                                         } | 
 | 1386 |                                     } | 
 | 1387 |                                     else if (propertyMap.first == "Severity") | 
 | 1388 |                                     { | 
 | 1389 |                                         severity = std::get_if<std::string>( | 
 | 1390 |                                             &propertyMap.second); | 
 | 1391 |                                     } | 
 | 1392 |                                     else if (propertyMap.first == "Message") | 
 | 1393 |                                     { | 
 | 1394 |                                         message = std::get_if<std::string>( | 
 | 1395 |                                             &propertyMap.second); | 
 | 1396 |                                     } | 
 | 1397 |                                     else if (propertyMap.first == "Resolved") | 
 | 1398 |                                     { | 
 | 1399 |                                         bool* resolveptr = std::get_if<bool>( | 
 | 1400 |                                             &propertyMap.second); | 
 | 1401 |                                         if (resolveptr == nullptr) | 
 | 1402 |                                         { | 
 | 1403 |                                             messages::internalError( | 
 | 1404 |                                                 asyncResp->res); | 
 | 1405 |                                             return; | 
 | 1406 |                                         } | 
 | 1407 |                                         resolved = *resolveptr; | 
 | 1408 |                                     } | 
 | 1409 |                                 } | 
 | 1410 |                                 if (id == nullptr || message == nullptr || | 
 | 1411 |                                     severity == nullptr) | 
 | 1412 |                                 { | 
 | 1413 |                                     messages::internalError(asyncResp->res); | 
 | 1414 |                                     return; | 
 | 1415 |                                 } | 
 | 1416 |                             } | 
 | 1417 |                             else if (interfaceMap.first == | 
 | 1418 |                                      "xyz.openbmc_project.Common.FilePath") | 
 | 1419 |                             { | 
 | 1420 |                                 for (auto& propertyMap : interfaceMap.second) | 
 | 1421 |                                 { | 
 | 1422 |                                     if (propertyMap.first == "Path") | 
 | 1423 |                                     { | 
 | 1424 |                                         filePath = std::get_if<std::string>( | 
 | 1425 |                                             &propertyMap.second); | 
 | 1426 |                                     } | 
 | 1427 |                                 } | 
 | 1428 |                             } | 
 | 1429 |                         } | 
 | 1430 |                         // Object path without the | 
 | 1431 |                         // xyz.openbmc_project.Logging.Entry interface, ignore | 
 | 1432 |                         // and continue. | 
 | 1433 |                         if (id == nullptr || message == nullptr || | 
 | 1434 |                             severity == nullptr) | 
 | 1435 |                         { | 
 | 1436 |                             continue; | 
 | 1437 |                         } | 
 | 1438 |                         entriesArray.push_back({}); | 
 | 1439 |                         nlohmann::json& thisEntry = entriesArray.back(); | 
 | 1440 |                         thisEntry["@odata.type"] = "#LogEntry.v1_8_0.LogEntry"; | 
 | 1441 |                         thisEntry["@odata.id"] = | 
 | 1442 |                             "/redfish/v1/Systems/system/" | 
 | 1443 |                             "LogServices/EventLog/Entries/" + | 
 | 1444 |                             std::to_string(*id); | 
 | 1445 |                         thisEntry["Name"] = "System Event Log Entry"; | 
 | 1446 |                         thisEntry["Id"] = std::to_string(*id); | 
 | 1447 |                         thisEntry["Message"] = *message; | 
 | 1448 |                         thisEntry["Resolved"] = resolved; | 
 | 1449 |                         thisEntry["EntryType"] = "Event"; | 
 | 1450 |                         thisEntry["Severity"] = | 
 | 1451 |                             translateSeverityDbusToRedfish(*severity); | 
 | 1452 |                         thisEntry["Created"] = | 
 | 1453 |                             crow::utility::getDateTime(timestamp); | 
 | 1454 |                         thisEntry["Modified"] = | 
 | 1455 |                             crow::utility::getDateTime(updateTimestamp); | 
 | 1456 |                         if (filePath != nullptr) | 
 | 1457 |                         { | 
 | 1458 |                             thisEntry["AdditionalDataURI"] = | 
 | 1459 |                                 "/redfish/v1/Systems/system/LogServices/" | 
 | 1460 |                                 "EventLog/" | 
 | 1461 |                                 "Entries/" + | 
 | 1462 |                                 std::to_string(*id) + "/attachment"; | 
 | 1463 |                         } | 
 | 1464 |                     } | 
 | 1465 |                     std::sort(entriesArray.begin(), entriesArray.end(), | 
 | 1466 |                               [](const nlohmann::json& left, | 
 | 1467 |                                  const nlohmann::json& right) { | 
 | 1468 |                                   return (left["Id"] <= right["Id"]); | 
 | 1469 |                               }); | 
 | 1470 |                     asyncResp->res.jsonValue["Members@odata.count"] = | 
 | 1471 |                         entriesArray.size(); | 
| Xiaochao Ma | 75710de | 2021-01-21 17:56:02 +0800 | [diff] [blame] | 1472 |                 }, | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1473 |                 "xyz.openbmc_project.Logging", "/xyz/openbmc_project/logging", | 
 | 1474 |                 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); | 
 | 1475 |         }); | 
 | 1476 | } | 
| Xiaochao Ma | 75710de | 2021-01-21 17:56:02 +0800 | [diff] [blame] | 1477 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1478 | inline void requestRoutesDBusEventLogEntry(App& app) | 
| Adriana Kobylak | 400fd1f | 2021-01-29 09:01:30 -0600 | [diff] [blame] | 1479 | { | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1480 |     BMCWEB_ROUTE( | 
 | 1481 |         app, "/redfish/v1/Systems/system/LogServices/EventLog/Entries/<str>/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 1482 |         .privileges(redfish::privileges::getLogEntry) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1483 |         .methods(boost::beast::http::verb::get)( | 
 | 1484 |             [](const crow::Request&, | 
 | 1485 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
 | 1486 |                const std::string& param) | 
| Adriana Kobylak | 400fd1f | 2021-01-29 09:01:30 -0600 | [diff] [blame] | 1487 |  | 
| Adriana Kobylak | 400fd1f | 2021-01-29 09:01:30 -0600 | [diff] [blame] | 1488 |             { | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1489 |                 std::string entryID = param; | 
 | 1490 |                 dbus::utility::escapePathForDbus(entryID); | 
| Adriana Kobylak | 400fd1f | 2021-01-29 09:01:30 -0600 | [diff] [blame] | 1491 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1492 |                 // DBus implementation of EventLog/Entries | 
 | 1493 |                 // Make call to Logging Service to find all log entry objects | 
 | 1494 |                 crow::connections::systemBus->async_method_call( | 
 | 1495 |                     [asyncResp, entryID](const boost::system::error_code ec, | 
 | 1496 |                                          GetManagedPropertyType& resp) { | 
 | 1497 |                         if (ec.value() == EBADR) | 
 | 1498 |                         { | 
 | 1499 |                             messages::resourceNotFound( | 
 | 1500 |                                 asyncResp->res, "EventLogEntry", entryID); | 
 | 1501 |                             return; | 
 | 1502 |                         } | 
 | 1503 |                         if (ec) | 
 | 1504 |                         { | 
 | 1505 |                             BMCWEB_LOG_ERROR << "EventLogEntry (DBus) " | 
 | 1506 |                                                 "resp_handler got error " | 
 | 1507 |                                              << ec; | 
 | 1508 |                             messages::internalError(asyncResp->res); | 
 | 1509 |                             return; | 
 | 1510 |                         } | 
 | 1511 |                         uint32_t* id = nullptr; | 
 | 1512 |                         std::time_t timestamp{}; | 
 | 1513 |                         std::time_t updateTimestamp{}; | 
 | 1514 |                         std::string* severity = nullptr; | 
 | 1515 |                         std::string* message = nullptr; | 
 | 1516 |                         std::string* filePath = nullptr; | 
 | 1517 |                         bool resolved = false; | 
| Adriana Kobylak | 400fd1f | 2021-01-29 09:01:30 -0600 | [diff] [blame] | 1518 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1519 |                         for (auto& propertyMap : resp) | 
 | 1520 |                         { | 
 | 1521 |                             if (propertyMap.first == "Id") | 
 | 1522 |                             { | 
 | 1523 |                                 id = std::get_if<uint32_t>(&propertyMap.second); | 
 | 1524 |                             } | 
 | 1525 |                             else if (propertyMap.first == "Timestamp") | 
 | 1526 |                             { | 
 | 1527 |                                 const uint64_t* millisTimeStamp = | 
 | 1528 |                                     std::get_if<uint64_t>(&propertyMap.second); | 
 | 1529 |                                 if (millisTimeStamp != nullptr) | 
 | 1530 |                                 { | 
 | 1531 |                                     timestamp = crow::utility::getTimestamp( | 
 | 1532 |                                         *millisTimeStamp); | 
 | 1533 |                                 } | 
 | 1534 |                             } | 
 | 1535 |                             else if (propertyMap.first == "UpdateTimestamp") | 
 | 1536 |                             { | 
 | 1537 |                                 const uint64_t* millisTimeStamp = | 
 | 1538 |                                     std::get_if<uint64_t>(&propertyMap.second); | 
 | 1539 |                                 if (millisTimeStamp != nullptr) | 
 | 1540 |                                 { | 
 | 1541 |                                     updateTimestamp = | 
 | 1542 |                                         crow::utility::getTimestamp( | 
 | 1543 |                                             *millisTimeStamp); | 
 | 1544 |                                 } | 
 | 1545 |                             } | 
 | 1546 |                             else if (propertyMap.first == "Severity") | 
 | 1547 |                             { | 
 | 1548 |                                 severity = std::get_if<std::string>( | 
 | 1549 |                                     &propertyMap.second); | 
 | 1550 |                             } | 
 | 1551 |                             else if (propertyMap.first == "Message") | 
 | 1552 |                             { | 
 | 1553 |                                 message = std::get_if<std::string>( | 
 | 1554 |                                     &propertyMap.second); | 
 | 1555 |                             } | 
 | 1556 |                             else if (propertyMap.first == "Resolved") | 
 | 1557 |                             { | 
 | 1558 |                                 bool* resolveptr = | 
 | 1559 |                                     std::get_if<bool>(&propertyMap.second); | 
 | 1560 |                                 if (resolveptr == nullptr) | 
 | 1561 |                                 { | 
 | 1562 |                                     messages::internalError(asyncResp->res); | 
 | 1563 |                                     return; | 
 | 1564 |                                 } | 
 | 1565 |                                 resolved = *resolveptr; | 
 | 1566 |                             } | 
 | 1567 |                             else if (propertyMap.first == "Path") | 
 | 1568 |                             { | 
 | 1569 |                                 filePath = std::get_if<std::string>( | 
 | 1570 |                                     &propertyMap.second); | 
 | 1571 |                             } | 
 | 1572 |                         } | 
 | 1573 |                         if (id == nullptr || message == nullptr || | 
 | 1574 |                             severity == nullptr) | 
 | 1575 |                         { | 
 | 1576 |                             messages::internalError(asyncResp->res); | 
 | 1577 |                             return; | 
 | 1578 |                         } | 
 | 1579 |                         asyncResp->res.jsonValue["@odata.type"] = | 
 | 1580 |                             "#LogEntry.v1_8_0.LogEntry"; | 
 | 1581 |                         asyncResp->res.jsonValue["@odata.id"] = | 
 | 1582 |                             "/redfish/v1/Systems/system/LogServices/EventLog/" | 
 | 1583 |                             "Entries/" + | 
 | 1584 |                             std::to_string(*id); | 
 | 1585 |                         asyncResp->res.jsonValue["Name"] = | 
 | 1586 |                             "System Event Log Entry"; | 
 | 1587 |                         asyncResp->res.jsonValue["Id"] = std::to_string(*id); | 
 | 1588 |                         asyncResp->res.jsonValue["Message"] = *message; | 
 | 1589 |                         asyncResp->res.jsonValue["Resolved"] = resolved; | 
 | 1590 |                         asyncResp->res.jsonValue["EntryType"] = "Event"; | 
 | 1591 |                         asyncResp->res.jsonValue["Severity"] = | 
 | 1592 |                             translateSeverityDbusToRedfish(*severity); | 
 | 1593 |                         asyncResp->res.jsonValue["Created"] = | 
 | 1594 |                             crow::utility::getDateTime(timestamp); | 
 | 1595 |                         asyncResp->res.jsonValue["Modified"] = | 
 | 1596 |                             crow::utility::getDateTime(updateTimestamp); | 
 | 1597 |                         if (filePath != nullptr) | 
 | 1598 |                         { | 
 | 1599 |                             asyncResp->res.jsonValue["AdditionalDataURI"] = | 
 | 1600 |                                 "/redfish/v1/Systems/system/LogServices/" | 
 | 1601 |                                 "EventLog/" | 
 | 1602 |                                 "attachment/" + | 
 | 1603 |                                 std::to_string(*id); | 
 | 1604 |                         } | 
 | 1605 |                     }, | 
 | 1606 |                     "xyz.openbmc_project.Logging", | 
 | 1607 |                     "/xyz/openbmc_project/logging/entry/" + entryID, | 
 | 1608 |                     "org.freedesktop.DBus.Properties", "GetAll", ""); | 
 | 1609 |             }); | 
 | 1610 |  | 
 | 1611 |     BMCWEB_ROUTE( | 
 | 1612 |         app, "/redfish/v1/Systems/system/LogServices/EventLog/Entries/<str>/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 1613 |         .privileges(redfish::privileges::patchLogEntry) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1614 |         .methods(boost::beast::http::verb::patch)( | 
 | 1615 |             [](const crow::Request& req, | 
 | 1616 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
 | 1617 |                const std::string& entryId) { | 
 | 1618 |                 std::optional<bool> resolved; | 
 | 1619 |  | 
 | 1620 |                 if (!json_util::readJson(req, asyncResp->res, "Resolved", | 
 | 1621 |                                          resolved)) | 
| Adriana Kobylak | 400fd1f | 2021-01-29 09:01:30 -0600 | [diff] [blame] | 1622 |                 { | 
| Adriana Kobylak | 400fd1f | 2021-01-29 09:01:30 -0600 | [diff] [blame] | 1623 |                     return; | 
 | 1624 |                 } | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1625 |                 BMCWEB_LOG_DEBUG << "Set Resolved"; | 
| Adriana Kobylak | 400fd1f | 2021-01-29 09:01:30 -0600 | [diff] [blame] | 1626 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1627 |                 crow::connections::systemBus->async_method_call( | 
 | 1628 |                     [asyncResp, resolved, | 
 | 1629 |                      entryId](const boost::system::error_code ec) { | 
 | 1630 |                         if (ec) | 
 | 1631 |                         { | 
 | 1632 |                             BMCWEB_LOG_DEBUG << "DBUS response error " << ec; | 
 | 1633 |                             messages::internalError(asyncResp->res); | 
 | 1634 |                             return; | 
 | 1635 |                         } | 
 | 1636 |                     }, | 
 | 1637 |                     "xyz.openbmc_project.Logging", | 
 | 1638 |                     "/xyz/openbmc_project/logging/entry/" + entryId, | 
 | 1639 |                     "org.freedesktop.DBus.Properties", "Set", | 
 | 1640 |                     "xyz.openbmc_project.Logging.Entry", "Resolved", | 
 | 1641 |                     std::variant<bool>(*resolved)); | 
 | 1642 |             }); | 
| Adriana Kobylak | 400fd1f | 2021-01-29 09:01:30 -0600 | [diff] [blame] | 1643 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1644 |     BMCWEB_ROUTE( | 
 | 1645 |         app, "/redfish/v1/Systems/system/LogServices/EventLog/Entries/<str>/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 1646 |         .privileges(redfish::privileges::deleteLogEntry) | 
 | 1647 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1648 |         .methods(boost::beast::http::verb::delete_)( | 
 | 1649 |             [](const crow::Request&, | 
 | 1650 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
 | 1651 |                const std::string& param) | 
| Adriana Kobylak | 400fd1f | 2021-01-29 09:01:30 -0600 | [diff] [blame] | 1652 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1653 |             { | 
 | 1654 |                 BMCWEB_LOG_DEBUG << "Do delete single event entries."; | 
| Adriana Kobylak | 400fd1f | 2021-01-29 09:01:30 -0600 | [diff] [blame] | 1655 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1656 |                 std::string entryID = param; | 
| Adriana Kobylak | 400fd1f | 2021-01-29 09:01:30 -0600 | [diff] [blame] | 1657 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1658 |                 dbus::utility::escapePathForDbus(entryID); | 
| Adriana Kobylak | 400fd1f | 2021-01-29 09:01:30 -0600 | [diff] [blame] | 1659 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1660 |                 // Process response from Logging service. | 
 | 1661 |                 auto respHandler = [asyncResp, entryID]( | 
 | 1662 |                                        const boost::system::error_code ec) { | 
 | 1663 |                     BMCWEB_LOG_DEBUG | 
 | 1664 |                         << "EventLogEntry (DBus) doDelete callback: Done"; | 
 | 1665 |                     if (ec) | 
 | 1666 |                     { | 
 | 1667 |                         if (ec.value() == EBADR) | 
 | 1668 |                         { | 
 | 1669 |                             messages::resourceNotFound(asyncResp->res, | 
 | 1670 |                                                        "LogEntry", entryID); | 
 | 1671 |                             return; | 
 | 1672 |                         } | 
 | 1673 |                         // TODO Handle for specific error code | 
 | 1674 |                         BMCWEB_LOG_ERROR << "EventLogEntry (DBus) doDelete " | 
 | 1675 |                                             "respHandler got error " | 
 | 1676 |                                          << ec; | 
 | 1677 |                         asyncResp->res.result( | 
 | 1678 |                             boost::beast::http::status::internal_server_error); | 
 | 1679 |                         return; | 
 | 1680 |                     } | 
 | 1681 |  | 
 | 1682 |                     asyncResp->res.result(boost::beast::http::status::ok); | 
 | 1683 |                 }; | 
 | 1684 |  | 
 | 1685 |                 // Make call to Logging service to request Delete Log | 
 | 1686 |                 crow::connections::systemBus->async_method_call( | 
 | 1687 |                     respHandler, "xyz.openbmc_project.Logging", | 
 | 1688 |                     "/xyz/openbmc_project/logging/entry/" + entryID, | 
 | 1689 |                     "xyz.openbmc_project.Object.Delete", "Delete"); | 
 | 1690 |             }); | 
 | 1691 | } | 
 | 1692 |  | 
 | 1693 | inline void requestRoutesDBusEventLogEntryDownload(App& app) | 
| Jason M. Bills | c4bf637 | 2018-11-05 13:48:27 -0800 | [diff] [blame] | 1694 | { | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1695 |     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/EventLog/Entries/" | 
 | 1696 |                       "<str>/attachment") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 1697 |         .privileges(redfish::privileges::getLogEntry) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1698 |         .methods(boost::beast::http::verb::get)( | 
 | 1699 |             [](const crow::Request& req, | 
 | 1700 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
 | 1701 |                const std::string& param) | 
| Ed Tanous | 1da66f7 | 2018-07-27 16:13:37 -0700 | [diff] [blame] | 1702 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1703 |             { | 
| Ed Tanous | 753d034 | 2021-07-01 07:57:30 -0700 | [diff] [blame] | 1704 |                 std::string_view acceptHeader = req.getHeaderValue("Accept"); | 
 | 1705 |                 // The iterators in boost/http/rfc7230.hpp end the string if '/' | 
 | 1706 |                 // is found, so replace it with arbitrary character '|' which is | 
 | 1707 |                 // not part of the Accept header syntax. | 
 | 1708 |                 std::string acceptStr = boost::replace_all_copy( | 
 | 1709 |                     std::string(acceptHeader), "/", "|"); | 
 | 1710 |                 boost::beast::http::ext_list acceptTypes{acceptStr}; | 
 | 1711 |                 bool supported = false; | 
 | 1712 |                 for (const auto& type : acceptTypes) | 
 | 1713 |                 { | 
 | 1714 |                     if ((type.first == "*|*") || | 
 | 1715 |                         (type.first == "application|octet-stream")) | 
 | 1716 |                     { | 
 | 1717 |                         supported = true; | 
 | 1718 |                         break; | 
 | 1719 |                     } | 
 | 1720 |                 } | 
 | 1721 |                 if (!supported) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1722 |                 { | 
 | 1723 |                     asyncResp->res.result( | 
 | 1724 |                         boost::beast::http::status::bad_request); | 
 | 1725 |                     return; | 
 | 1726 |                 } | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 1727 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1728 |                 std::string entryID = param; | 
 | 1729 |                 dbus::utility::escapePathForDbus(entryID); | 
 | 1730 |  | 
 | 1731 |                 crow::connections::systemBus->async_method_call( | 
 | 1732 |                     [asyncResp, | 
 | 1733 |                      entryID](const boost::system::error_code ec, | 
 | 1734 |                               const sdbusplus::message::unix_fd& unixfd) { | 
 | 1735 |                         if (ec.value() == EBADR) | 
 | 1736 |                         { | 
 | 1737 |                             messages::resourceNotFound( | 
 | 1738 |                                 asyncResp->res, "EventLogAttachment", entryID); | 
 | 1739 |                             return; | 
 | 1740 |                         } | 
 | 1741 |                         if (ec) | 
 | 1742 |                         { | 
 | 1743 |                             BMCWEB_LOG_DEBUG << "DBUS response error " << ec; | 
 | 1744 |                             messages::internalError(asyncResp->res); | 
 | 1745 |                             return; | 
 | 1746 |                         } | 
 | 1747 |  | 
 | 1748 |                         int fd = -1; | 
 | 1749 |                         fd = dup(unixfd); | 
 | 1750 |                         if (fd == -1) | 
 | 1751 |                         { | 
 | 1752 |                             messages::internalError(asyncResp->res); | 
 | 1753 |                             return; | 
 | 1754 |                         } | 
 | 1755 |  | 
 | 1756 |                         long long int size = lseek(fd, 0, SEEK_END); | 
 | 1757 |                         if (size == -1) | 
 | 1758 |                         { | 
 | 1759 |                             messages::internalError(asyncResp->res); | 
 | 1760 |                             return; | 
 | 1761 |                         } | 
 | 1762 |  | 
 | 1763 |                         // Arbitrary max size of 64kb | 
 | 1764 |                         constexpr int maxFileSize = 65536; | 
 | 1765 |                         if (size > maxFileSize) | 
 | 1766 |                         { | 
 | 1767 |                             BMCWEB_LOG_ERROR | 
 | 1768 |                                 << "File size exceeds maximum allowed size of " | 
 | 1769 |                                 << maxFileSize; | 
 | 1770 |                             messages::internalError(asyncResp->res); | 
 | 1771 |                             return; | 
 | 1772 |                         } | 
 | 1773 |                         std::vector<char> data(static_cast<size_t>(size)); | 
 | 1774 |                         long long int rc = lseek(fd, 0, SEEK_SET); | 
 | 1775 |                         if (rc == -1) | 
 | 1776 |                         { | 
 | 1777 |                             messages::internalError(asyncResp->res); | 
 | 1778 |                             return; | 
 | 1779 |                         } | 
 | 1780 |                         rc = read(fd, data.data(), data.size()); | 
 | 1781 |                         if ((rc == -1) || (rc != size)) | 
 | 1782 |                         { | 
 | 1783 |                             messages::internalError(asyncResp->res); | 
 | 1784 |                             return; | 
 | 1785 |                         } | 
 | 1786 |                         close(fd); | 
 | 1787 |  | 
 | 1788 |                         std::string_view strData(data.data(), data.size()); | 
 | 1789 |                         std::string output = | 
 | 1790 |                             crow::utility::base64encode(strData); | 
 | 1791 |  | 
 | 1792 |                         asyncResp->res.addHeader("Content-Type", | 
 | 1793 |                                                  "application/octet-stream"); | 
 | 1794 |                         asyncResp->res.addHeader("Content-Transfer-Encoding", | 
 | 1795 |                                                  "Base64"); | 
 | 1796 |                         asyncResp->res.body() = std::move(output); | 
 | 1797 |                     }, | 
 | 1798 |                     "xyz.openbmc_project.Logging", | 
 | 1799 |                     "/xyz/openbmc_project/logging/entry/" + entryID, | 
 | 1800 |                     "xyz.openbmc_project.Logging.Entry", "GetEntry"); | 
 | 1801 |             }); | 
 | 1802 | } | 
 | 1803 |  | 
 | 1804 | inline void requestRoutesBMCLogServiceCollection(App& app) | 
 | 1805 | { | 
 | 1806 |     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 1807 |         .privileges(redfish::privileges::getLogService) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1808 |         .methods(boost::beast::http::verb::get)( | 
 | 1809 |             [](const crow::Request&, | 
 | 1810 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { | 
 | 1811 |                 // Collections don't include the static data added by SubRoute | 
 | 1812 |                 // because it has a duplicate entry for members | 
 | 1813 |                 asyncResp->res.jsonValue["@odata.type"] = | 
 | 1814 |                     "#LogServiceCollection.LogServiceCollection"; | 
 | 1815 |                 asyncResp->res.jsonValue["@odata.id"] = | 
 | 1816 |                     "/redfish/v1/Managers/bmc/LogServices"; | 
 | 1817 |                 asyncResp->res.jsonValue["Name"] = | 
 | 1818 |                     "Open BMC Log Services Collection"; | 
 | 1819 |                 asyncResp->res.jsonValue["Description"] = | 
 | 1820 |                     "Collection of LogServices for this Manager"; | 
 | 1821 |                 nlohmann::json& logServiceArray = | 
 | 1822 |                     asyncResp->res.jsonValue["Members"]; | 
 | 1823 |                 logServiceArray = nlohmann::json::array(); | 
| Asmitha Karunanithi | 5cb1dd2 | 2020-05-07 04:35:02 -0500 | [diff] [blame] | 1824 | #ifdef BMCWEB_ENABLE_REDFISH_DUMP_LOG | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1825 |                 logServiceArray.push_back( | 
 | 1826 |                     {{"@odata.id", | 
 | 1827 |                       "/redfish/v1/Managers/bmc/LogServices/Dump"}}); | 
| Asmitha Karunanithi | 5cb1dd2 | 2020-05-07 04:35:02 -0500 | [diff] [blame] | 1828 | #endif | 
| Jason M. Bills | c4bf637 | 2018-11-05 13:48:27 -0800 | [diff] [blame] | 1829 | #ifdef BMCWEB_ENABLE_REDFISH_BMC_JOURNAL | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1830 |                 logServiceArray.push_back( | 
 | 1831 |                     {{"@odata.id", | 
 | 1832 |                       "/redfish/v1/Managers/bmc/LogServices/Journal"}}); | 
| Jason M. Bills | c4bf637 | 2018-11-05 13:48:27 -0800 | [diff] [blame] | 1833 | #endif | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1834 |                 asyncResp->res.jsonValue["Members@odata.count"] = | 
 | 1835 |                     logServiceArray.size(); | 
 | 1836 |             }); | 
 | 1837 | } | 
| Ed Tanous | 1da66f7 | 2018-07-27 16:13:37 -0700 | [diff] [blame] | 1838 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1839 | inline void requestRoutesBMCJournalLogService(App& app) | 
| Ed Tanous | 1da66f7 | 2018-07-27 16:13:37 -0700 | [diff] [blame] | 1840 | { | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1841 |     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/Journal/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 1842 |         .privileges(redfish::privileges::getLogService) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1843 |         .methods(boost::beast::http::verb::get)( | 
 | 1844 |             [](const crow::Request&, | 
 | 1845 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) | 
| Jason M. Bills | e1f2634 | 2018-07-18 12:12:00 -0700 | [diff] [blame] | 1846 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1847 |             { | 
 | 1848 |                 asyncResp->res.jsonValue["@odata.type"] = | 
 | 1849 |                     "#LogService.v1_1_0.LogService"; | 
 | 1850 |                 asyncResp->res.jsonValue["@odata.id"] = | 
 | 1851 |                     "/redfish/v1/Managers/bmc/LogServices/Journal"; | 
 | 1852 |                 asyncResp->res.jsonValue["Name"] = | 
 | 1853 |                     "Open BMC Journal Log Service"; | 
 | 1854 |                 asyncResp->res.jsonValue["Description"] = | 
 | 1855 |                     "BMC Journal Log Service"; | 
 | 1856 |                 asyncResp->res.jsonValue["Id"] = "BMC Journal"; | 
 | 1857 |                 asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull"; | 
| Tejas Patil | 7c8c405 | 2021-06-04 17:43:14 +0530 | [diff] [blame] | 1858 |  | 
 | 1859 |                 std::pair<std::string, std::string> redfishDateTimeOffset = | 
 | 1860 |                     crow::utility::getDateTimeOffsetNow(); | 
 | 1861 |                 asyncResp->res.jsonValue["DateTime"] = | 
 | 1862 |                     redfishDateTimeOffset.first; | 
 | 1863 |                 asyncResp->res.jsonValue["DateTimeLocalOffset"] = | 
 | 1864 |                     redfishDateTimeOffset.second; | 
 | 1865 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1866 |                 asyncResp->res.jsonValue["Entries"] = { | 
 | 1867 |                     {"@odata.id", | 
 | 1868 |                      "/redfish/v1/Managers/bmc/LogServices/Journal/Entries"}}; | 
 | 1869 |             }); | 
 | 1870 | } | 
| Jason M. Bills | e1f2634 | 2018-07-18 12:12:00 -0700 | [diff] [blame] | 1871 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 1872 | static int fillBMCJournalLogEntryJson(const std::string& bmcJournalLogEntryID, | 
 | 1873 |                                       sd_journal* journal, | 
 | 1874 |                                       nlohmann::json& bmcJournalLogEntryJson) | 
| Jason M. Bills | e1f2634 | 2018-07-18 12:12:00 -0700 | [diff] [blame] | 1875 | { | 
 | 1876 |     // Get the Log Entry contents | 
 | 1877 |     int ret = 0; | 
| Jason M. Bills | e1f2634 | 2018-07-18 12:12:00 -0700 | [diff] [blame] | 1878 |  | 
| Jason M. Bills | a8fe54f | 2020-11-20 15:57:55 -0800 | [diff] [blame] | 1879 |     std::string message; | 
 | 1880 |     std::string_view syslogID; | 
 | 1881 |     ret = getJournalMetadata(journal, "SYSLOG_IDENTIFIER", syslogID); | 
 | 1882 |     if (ret < 0) | 
 | 1883 |     { | 
 | 1884 |         BMCWEB_LOG_ERROR << "Failed to read SYSLOG_IDENTIFIER field: " | 
 | 1885 |                          << strerror(-ret); | 
 | 1886 |     } | 
 | 1887 |     if (!syslogID.empty()) | 
 | 1888 |     { | 
 | 1889 |         message += std::string(syslogID) + ": "; | 
 | 1890 |     } | 
 | 1891 |  | 
| Ed Tanous | 39e7750 | 2019-03-04 17:35:53 -0800 | [diff] [blame] | 1892 |     std::string_view msg; | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 1893 |     ret = getJournalMetadata(journal, "MESSAGE", msg); | 
| Jason M. Bills | e1f2634 | 2018-07-18 12:12:00 -0700 | [diff] [blame] | 1894 |     if (ret < 0) | 
 | 1895 |     { | 
 | 1896 |         BMCWEB_LOG_ERROR << "Failed to read MESSAGE field: " << strerror(-ret); | 
 | 1897 |         return 1; | 
 | 1898 |     } | 
| Jason M. Bills | a8fe54f | 2020-11-20 15:57:55 -0800 | [diff] [blame] | 1899 |     message += std::string(msg); | 
| Jason M. Bills | e1f2634 | 2018-07-18 12:12:00 -0700 | [diff] [blame] | 1900 |  | 
 | 1901 |     // Get the severity from the PRIORITY field | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 1902 |     long int severity = 8; // Default to an invalid priority | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 1903 |     ret = getJournalMetadata(journal, "PRIORITY", 10, severity); | 
| Jason M. Bills | e1f2634 | 2018-07-18 12:12:00 -0700 | [diff] [blame] | 1904 |     if (ret < 0) | 
 | 1905 |     { | 
 | 1906 |         BMCWEB_LOG_ERROR << "Failed to read PRIORITY field: " << strerror(-ret); | 
| Jason M. Bills | e1f2634 | 2018-07-18 12:12:00 -0700 | [diff] [blame] | 1907 |     } | 
| Jason M. Bills | e1f2634 | 2018-07-18 12:12:00 -0700 | [diff] [blame] | 1908 |  | 
 | 1909 |     // Get the Created time from the timestamp | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 1910 |     std::string entryTimeStr; | 
 | 1911 |     if (!getEntryTimestamp(journal, entryTimeStr)) | 
| Jason M. Bills | e1f2634 | 2018-07-18 12:12:00 -0700 | [diff] [blame] | 1912 |     { | 
| Jason M. Bills | 16428a1 | 2018-11-02 12:42:29 -0700 | [diff] [blame] | 1913 |         return 1; | 
| Jason M. Bills | e1f2634 | 2018-07-18 12:12:00 -0700 | [diff] [blame] | 1914 |     } | 
| Jason M. Bills | e1f2634 | 2018-07-18 12:12:00 -0700 | [diff] [blame] | 1915 |  | 
 | 1916 |     // Fill in the log entry with the gathered data | 
| Jason M. Bills | c4bf637 | 2018-11-05 13:48:27 -0800 | [diff] [blame] | 1917 |     bmcJournalLogEntryJson = { | 
| Ed Tanous | d0dbeef | 2021-07-01 08:46:46 -0700 | [diff] [blame] | 1918 |         {"@odata.type", "#LogEntry.v1_4_0.LogEntry"}, | 
| Jason M. Bills | c4bf637 | 2018-11-05 13:48:27 -0800 | [diff] [blame] | 1919 |         {"@odata.id", "/redfish/v1/Managers/bmc/LogServices/Journal/Entries/" + | 
 | 1920 |                           bmcJournalLogEntryID}, | 
| Jason M. Bills | e1f2634 | 2018-07-18 12:12:00 -0700 | [diff] [blame] | 1921 |         {"Name", "BMC Journal Entry"}, | 
| Jason M. Bills | c4bf637 | 2018-11-05 13:48:27 -0800 | [diff] [blame] | 1922 |         {"Id", bmcJournalLogEntryID}, | 
| Jason M. Bills | a8fe54f | 2020-11-20 15:57:55 -0800 | [diff] [blame] | 1923 |         {"Message", std::move(message)}, | 
| Jason M. Bills | e1f2634 | 2018-07-18 12:12:00 -0700 | [diff] [blame] | 1924 |         {"EntryType", "Oem"}, | 
| Patrick Williams | 738c1e6 | 2021-02-22 17:14:25 -0600 | [diff] [blame] | 1925 |         {"Severity", severity <= 2   ? "Critical" | 
 | 1926 |                      : severity <= 4 ? "Warning" | 
 | 1927 |                                      : "OK"}, | 
| Ed Tanous | 086be23 | 2019-05-23 11:47:09 -0700 | [diff] [blame] | 1928 |         {"OemRecordFormat", "BMC Journal Entry"}, | 
| Jason M. Bills | e1f2634 | 2018-07-18 12:12:00 -0700 | [diff] [blame] | 1929 |         {"Created", std::move(entryTimeStr)}}; | 
 | 1930 |     return 0; | 
 | 1931 | } | 
 | 1932 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1933 | inline void requestRoutesBMCJournalLogEntryCollection(App& app) | 
| Jason M. Bills | e1f2634 | 2018-07-18 12:12:00 -0700 | [diff] [blame] | 1934 | { | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1935 |     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/Journal/Entries/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 1936 |         .privileges(redfish::privileges::getLogEntryCollection) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1937 |         .methods(boost::beast::http::verb::get)( | 
 | 1938 |             [](const crow::Request& req, | 
 | 1939 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { | 
 | 1940 |                 static constexpr const long maxEntriesPerPage = 1000; | 
 | 1941 |                 uint64_t skip = 0; | 
 | 1942 |                 uint64_t top = maxEntriesPerPage; // Show max entries by default | 
 | 1943 |                 if (!getSkipParam(asyncResp, req, skip)) | 
 | 1944 |                 { | 
 | 1945 |                     return; | 
 | 1946 |                 } | 
 | 1947 |                 if (!getTopParam(asyncResp, req, top)) | 
 | 1948 |                 { | 
 | 1949 |                     return; | 
 | 1950 |                 } | 
 | 1951 |                 // Collections don't include the static data added by SubRoute | 
 | 1952 |                 // because it has a duplicate entry for members | 
 | 1953 |                 asyncResp->res.jsonValue["@odata.type"] = | 
 | 1954 |                     "#LogEntryCollection.LogEntryCollection"; | 
 | 1955 |                 asyncResp->res.jsonValue["@odata.id"] = | 
 | 1956 |                     "/redfish/v1/Managers/bmc/LogServices/Journal/Entries"; | 
 | 1957 |                 asyncResp->res.jsonValue["Name"] = "Open BMC Journal Entries"; | 
 | 1958 |                 asyncResp->res.jsonValue["Description"] = | 
 | 1959 |                     "Collection of BMC Journal Entries"; | 
 | 1960 |                 nlohmann::json& logEntryArray = | 
 | 1961 |                     asyncResp->res.jsonValue["Members"]; | 
 | 1962 |                 logEntryArray = nlohmann::json::array(); | 
| Jason M. Bills | e1f2634 | 2018-07-18 12:12:00 -0700 | [diff] [blame] | 1963 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1964 |                 // Go through the journal and use the timestamp to create a | 
 | 1965 |                 // unique ID for each entry | 
 | 1966 |                 sd_journal* journalTmp = nullptr; | 
 | 1967 |                 int ret = sd_journal_open(&journalTmp, SD_JOURNAL_LOCAL_ONLY); | 
 | 1968 |                 if (ret < 0) | 
 | 1969 |                 { | 
 | 1970 |                     BMCWEB_LOG_ERROR << "failed to open journal: " | 
 | 1971 |                                      << strerror(-ret); | 
 | 1972 |                     messages::internalError(asyncResp->res); | 
 | 1973 |                     return; | 
 | 1974 |                 } | 
 | 1975 |                 std::unique_ptr<sd_journal, decltype(&sd_journal_close)> | 
 | 1976 |                     journal(journalTmp, sd_journal_close); | 
 | 1977 |                 journalTmp = nullptr; | 
 | 1978 |                 uint64_t entryCount = 0; | 
 | 1979 |                 // Reset the unique ID on the first entry | 
 | 1980 |                 bool firstEntry = true; | 
 | 1981 |                 SD_JOURNAL_FOREACH(journal.get()) | 
 | 1982 |                 { | 
 | 1983 |                     entryCount++; | 
 | 1984 |                     // Handle paging using skip (number of entries to skip from | 
 | 1985 |                     // the start) and top (number of entries to display) | 
 | 1986 |                     if (entryCount <= skip || entryCount > skip + top) | 
 | 1987 |                     { | 
 | 1988 |                         continue; | 
 | 1989 |                     } | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 1990 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1991 |                     std::string idStr; | 
 | 1992 |                     if (!getUniqueEntryID(journal.get(), idStr, firstEntry)) | 
 | 1993 |                     { | 
 | 1994 |                         continue; | 
 | 1995 |                     } | 
| Jason M. Bills | e1f2634 | 2018-07-18 12:12:00 -0700 | [diff] [blame] | 1996 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 1997 |                     if (firstEntry) | 
 | 1998 |                     { | 
 | 1999 |                         firstEntry = false; | 
 | 2000 |                     } | 
| Jason M. Bills | 193ad2f | 2018-09-26 15:08:52 -0700 | [diff] [blame] | 2001 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2002 |                     logEntryArray.push_back({}); | 
 | 2003 |                     nlohmann::json& bmcJournalLogEntry = logEntryArray.back(); | 
 | 2004 |                     if (fillBMCJournalLogEntryJson(idStr, journal.get(), | 
 | 2005 |                                                    bmcJournalLogEntry) != 0) | 
 | 2006 |                     { | 
 | 2007 |                         messages::internalError(asyncResp->res); | 
 | 2008 |                         return; | 
 | 2009 |                     } | 
 | 2010 |                 } | 
 | 2011 |                 asyncResp->res.jsonValue["Members@odata.count"] = entryCount; | 
 | 2012 |                 if (skip + top < entryCount) | 
 | 2013 |                 { | 
 | 2014 |                     asyncResp->res.jsonValue["Members@odata.nextLink"] = | 
 | 2015 |                         "/redfish/v1/Managers/bmc/LogServices/Journal/" | 
 | 2016 |                         "Entries?$skip=" + | 
 | 2017 |                         std::to_string(skip + top); | 
 | 2018 |                 } | 
 | 2019 |             }); | 
 | 2020 | } | 
| Jason M. Bills | e1f2634 | 2018-07-18 12:12:00 -0700 | [diff] [blame] | 2021 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2022 | inline void requestRoutesBMCJournalLogEntry(App& app) | 
| Jason M. Bills | e1f2634 | 2018-07-18 12:12:00 -0700 | [diff] [blame] | 2023 | { | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2024 |     BMCWEB_ROUTE(app, | 
 | 2025 |                  "/redfish/v1/Managers/bmc/LogServices/Journal/Entries/<str>/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 2026 |         .privileges(redfish::privileges::getLogEntry) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2027 |         .methods(boost::beast::http::verb::get)( | 
 | 2028 |             [](const crow::Request&, | 
 | 2029 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
 | 2030 |                const std::string& entryID) { | 
 | 2031 |                 // Convert the unique ID back to a timestamp to find the entry | 
 | 2032 |                 uint64_t ts = 0; | 
 | 2033 |                 uint64_t index = 0; | 
 | 2034 |                 if (!getTimestampFromID(asyncResp, entryID, ts, index)) | 
 | 2035 |                 { | 
 | 2036 |                     return; | 
 | 2037 |                 } | 
| Jason M. Bills | e1f2634 | 2018-07-18 12:12:00 -0700 | [diff] [blame] | 2038 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2039 |                 sd_journal* journalTmp = nullptr; | 
 | 2040 |                 int ret = sd_journal_open(&journalTmp, SD_JOURNAL_LOCAL_ONLY); | 
 | 2041 |                 if (ret < 0) | 
 | 2042 |                 { | 
 | 2043 |                     BMCWEB_LOG_ERROR << "failed to open journal: " | 
 | 2044 |                                      << strerror(-ret); | 
 | 2045 |                     messages::internalError(asyncResp->res); | 
 | 2046 |                     return; | 
 | 2047 |                 } | 
 | 2048 |                 std::unique_ptr<sd_journal, decltype(&sd_journal_close)> | 
 | 2049 |                     journal(journalTmp, sd_journal_close); | 
 | 2050 |                 journalTmp = nullptr; | 
 | 2051 |                 // Go to the timestamp in the log and move to the entry at the | 
 | 2052 |                 // index tracking the unique ID | 
 | 2053 |                 std::string idStr; | 
 | 2054 |                 bool firstEntry = true; | 
 | 2055 |                 ret = sd_journal_seek_realtime_usec(journal.get(), ts); | 
 | 2056 |                 if (ret < 0) | 
 | 2057 |                 { | 
 | 2058 |                     BMCWEB_LOG_ERROR << "failed to seek to an entry in journal" | 
 | 2059 |                                      << strerror(-ret); | 
 | 2060 |                     messages::internalError(asyncResp->res); | 
 | 2061 |                     return; | 
 | 2062 |                 } | 
 | 2063 |                 for (uint64_t i = 0; i <= index; i++) | 
 | 2064 |                 { | 
 | 2065 |                     sd_journal_next(journal.get()); | 
 | 2066 |                     if (!getUniqueEntryID(journal.get(), idStr, firstEntry)) | 
 | 2067 |                     { | 
 | 2068 |                         messages::internalError(asyncResp->res); | 
 | 2069 |                         return; | 
 | 2070 |                     } | 
 | 2071 |                     if (firstEntry) | 
 | 2072 |                     { | 
 | 2073 |                         firstEntry = false; | 
 | 2074 |                     } | 
 | 2075 |                 } | 
 | 2076 |                 // Confirm that the entry ID matches what was requested | 
 | 2077 |                 if (idStr != entryID) | 
 | 2078 |                 { | 
 | 2079 |                     messages::resourceMissingAtURI(asyncResp->res, entryID); | 
 | 2080 |                     return; | 
 | 2081 |                 } | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 2082 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2083 |                 if (fillBMCJournalLogEntryJson(entryID, journal.get(), | 
 | 2084 |                                                asyncResp->res.jsonValue) != 0) | 
| Jason M. Bills | 5b61b5e | 2019-10-16 10:59:02 -0700 | [diff] [blame] | 2085 |                 { | 
 | 2086 |                     messages::internalError(asyncResp->res); | 
 | 2087 |                     return; | 
 | 2088 |                 } | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2089 |             }); | 
 | 2090 | } | 
 | 2091 |  | 
 | 2092 | inline void requestRoutesBMCDumpService(App& app) | 
 | 2093 | { | 
 | 2094 |     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/Dump/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 2095 |         .privileges(redfish::privileges::getLogService) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2096 |         .methods(boost::beast::http::verb::get)( | 
 | 2097 |             [](const crow::Request&, | 
 | 2098 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { | 
 | 2099 |                 asyncResp->res.jsonValue["@odata.id"] = | 
 | 2100 |                     "/redfish/v1/Managers/bmc/LogServices/Dump"; | 
 | 2101 |                 asyncResp->res.jsonValue["@odata.type"] = | 
 | 2102 |                     "#LogService.v1_2_0.LogService"; | 
 | 2103 |                 asyncResp->res.jsonValue["Name"] = "Dump LogService"; | 
 | 2104 |                 asyncResp->res.jsonValue["Description"] = "BMC Dump LogService"; | 
 | 2105 |                 asyncResp->res.jsonValue["Id"] = "Dump"; | 
 | 2106 |                 asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull"; | 
| Tejas Patil | 7c8c405 | 2021-06-04 17:43:14 +0530 | [diff] [blame] | 2107 |  | 
 | 2108 |                 std::pair<std::string, std::string> redfishDateTimeOffset = | 
 | 2109 |                     crow::utility::getDateTimeOffsetNow(); | 
 | 2110 |                 asyncResp->res.jsonValue["DateTime"] = | 
 | 2111 |                     redfishDateTimeOffset.first; | 
 | 2112 |                 asyncResp->res.jsonValue["DateTimeLocalOffset"] = | 
 | 2113 |                     redfishDateTimeOffset.second; | 
 | 2114 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2115 |                 asyncResp->res.jsonValue["Entries"] = { | 
 | 2116 |                     {"@odata.id", | 
 | 2117 |                      "/redfish/v1/Managers/bmc/LogServices/Dump/Entries"}}; | 
 | 2118 |                 asyncResp->res.jsonValue["Actions"] = { | 
 | 2119 |                     {"#LogService.ClearLog", | 
 | 2120 |                      {{"target", "/redfish/v1/Managers/bmc/LogServices/Dump/" | 
 | 2121 |                                  "Actions/LogService.ClearLog"}}}, | 
 | 2122 |                     {"#LogService.CollectDiagnosticData", | 
 | 2123 |                      {{"target", "/redfish/v1/Managers/bmc/LogServices/Dump/" | 
 | 2124 |                                  "Actions/LogService.CollectDiagnosticData"}}}}; | 
 | 2125 |             }); | 
 | 2126 | } | 
 | 2127 |  | 
 | 2128 | inline void requestRoutesBMCDumpEntryCollection(App& app) | 
 | 2129 | { | 
 | 2130 |  | 
 | 2131 |     /** | 
 | 2132 |      * Functions triggers appropriate requests on DBus | 
 | 2133 |      */ | 
 | 2134 |     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 2135 |         .privileges(redfish::privileges::getLogEntryCollection) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2136 |         .methods(boost::beast::http::verb::get)( | 
 | 2137 |             [](const crow::Request&, | 
 | 2138 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { | 
 | 2139 |                 asyncResp->res.jsonValue["@odata.type"] = | 
 | 2140 |                     "#LogEntryCollection.LogEntryCollection"; | 
 | 2141 |                 asyncResp->res.jsonValue["@odata.id"] = | 
 | 2142 |                     "/redfish/v1/Managers/bmc/LogServices/Dump/Entries"; | 
 | 2143 |                 asyncResp->res.jsonValue["Name"] = "BMC Dump Entries"; | 
 | 2144 |                 asyncResp->res.jsonValue["Description"] = | 
 | 2145 |                     "Collection of BMC Dump Entries"; | 
 | 2146 |  | 
 | 2147 |                 getDumpEntryCollection(asyncResp, "BMC"); | 
 | 2148 |             }); | 
 | 2149 | } | 
 | 2150 |  | 
 | 2151 | inline void requestRoutesBMCDumpEntry(App& app) | 
 | 2152 | { | 
 | 2153 |     BMCWEB_ROUTE(app, | 
 | 2154 |                  "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/<str>/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 2155 |         .privileges(redfish::privileges::getLogEntry) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2156 |         .methods(boost::beast::http::verb::get)( | 
 | 2157 |             [](const crow::Request&, | 
 | 2158 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
 | 2159 |                const std::string& param) { | 
 | 2160 |                 getDumpEntryById(asyncResp, param, "BMC"); | 
 | 2161 |             }); | 
 | 2162 |     BMCWEB_ROUTE(app, | 
 | 2163 |                  "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/<str>/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 2164 |         .privileges(redfish::privileges::deleteLogEntry) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2165 |         .methods(boost::beast::http::verb::delete_)( | 
 | 2166 |             [](const crow::Request&, | 
 | 2167 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
 | 2168 |                const std::string& param) { | 
 | 2169 |                 deleteDumpEntry(asyncResp, param, "bmc"); | 
 | 2170 |             }); | 
 | 2171 | } | 
 | 2172 |  | 
 | 2173 | inline void requestRoutesBMCDumpCreate(App& app) | 
 | 2174 | { | 
 | 2175 |  | 
 | 2176 |     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/Dump/" | 
 | 2177 |                       "Actions/" | 
 | 2178 |                       "LogService.CollectDiagnosticData/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 2179 |         .privileges(redfish::privileges::postLogService) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2180 |         .methods(boost::beast::http::verb::post)( | 
 | 2181 |             [](const crow::Request& req, | 
 | 2182 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { | 
 | 2183 |                 createDump(asyncResp, req, "BMC"); | 
 | 2184 |             }); | 
 | 2185 | } | 
 | 2186 |  | 
 | 2187 | inline void requestRoutesBMCDumpClear(App& app) | 
 | 2188 | { | 
 | 2189 |     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/Dump/" | 
 | 2190 |                       "Actions/" | 
 | 2191 |                       "LogService.ClearLog/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 2192 |         .privileges(redfish::privileges::postLogService) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2193 |         .methods(boost::beast::http::verb::post)( | 
 | 2194 |             [](const crow::Request&, | 
 | 2195 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { | 
 | 2196 |                 clearDump(asyncResp, "BMC"); | 
 | 2197 |             }); | 
 | 2198 | } | 
 | 2199 |  | 
 | 2200 | inline void requestRoutesSystemDumpService(App& app) | 
 | 2201 | { | 
 | 2202 |     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/Dump/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 2203 |         .privileges(redfish::privileges::getLogService) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2204 |         .methods(boost::beast::http::verb::get)( | 
 | 2205 |             [](const crow::Request&, | 
 | 2206 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) | 
 | 2207 |  | 
 | 2208 |             { | 
 | 2209 |                 asyncResp->res.jsonValue["@odata.id"] = | 
 | 2210 |                     "/redfish/v1/Systems/system/LogServices/Dump"; | 
 | 2211 |                 asyncResp->res.jsonValue["@odata.type"] = | 
 | 2212 |                     "#LogService.v1_2_0.LogService"; | 
 | 2213 |                 asyncResp->res.jsonValue["Name"] = "Dump LogService"; | 
 | 2214 |                 asyncResp->res.jsonValue["Description"] = | 
 | 2215 |                     "System Dump LogService"; | 
 | 2216 |                 asyncResp->res.jsonValue["Id"] = "Dump"; | 
 | 2217 |                 asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull"; | 
| Tejas Patil | 7c8c405 | 2021-06-04 17:43:14 +0530 | [diff] [blame] | 2218 |  | 
 | 2219 |                 std::pair<std::string, std::string> redfishDateTimeOffset = | 
 | 2220 |                     crow::utility::getDateTimeOffsetNow(); | 
 | 2221 |                 asyncResp->res.jsonValue["DateTime"] = | 
 | 2222 |                     redfishDateTimeOffset.first; | 
 | 2223 |                 asyncResp->res.jsonValue["DateTimeLocalOffset"] = | 
 | 2224 |                     redfishDateTimeOffset.second; | 
 | 2225 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2226 |                 asyncResp->res.jsonValue["Entries"] = { | 
 | 2227 |                     {"@odata.id", | 
 | 2228 |                      "/redfish/v1/Systems/system/LogServices/Dump/Entries"}}; | 
 | 2229 |                 asyncResp->res.jsonValue["Actions"] = { | 
 | 2230 |                     {"#LogService.ClearLog", | 
 | 2231 |                      {{"target", | 
 | 2232 |                        "/redfish/v1/Systems/system/LogServices/Dump/Actions/" | 
 | 2233 |                        "LogService.ClearLog"}}}, | 
 | 2234 |                     {"#LogService.CollectDiagnosticData", | 
 | 2235 |                      {{"target", | 
 | 2236 |                        "/redfish/v1/Systems/system/LogServices/Dump/Actions/" | 
 | 2237 |                        "LogService.CollectDiagnosticData"}}}}; | 
 | 2238 |             }); | 
 | 2239 | } | 
 | 2240 |  | 
 | 2241 | inline void requestRoutesSystemDumpEntryCollection(App& app) | 
 | 2242 | { | 
 | 2243 |  | 
 | 2244 |     /** | 
 | 2245 |      * Functions triggers appropriate requests on DBus | 
 | 2246 |      */ | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 2247 |     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/") | 
 | 2248 |         .privileges(redfish::privileges::getLogEntryCollection) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2249 |         .methods(boost::beast::http::verb::get)( | 
 | 2250 |             [](const crow::Request&, | 
| John Edward Broadbent | 864d6a1 | 2021-06-09 10:12:48 -0700 | [diff] [blame] | 2251 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2252 |                 asyncResp->res.jsonValue["@odata.type"] = | 
 | 2253 |                     "#LogEntryCollection.LogEntryCollection"; | 
 | 2254 |                 asyncResp->res.jsonValue["@odata.id"] = | 
 | 2255 |                     "/redfish/v1/Systems/system/LogServices/Dump/Entries"; | 
 | 2256 |                 asyncResp->res.jsonValue["Name"] = "System Dump Entries"; | 
 | 2257 |                 asyncResp->res.jsonValue["Description"] = | 
 | 2258 |                     "Collection of System Dump Entries"; | 
 | 2259 |  | 
 | 2260 |                 getDumpEntryCollection(asyncResp, "System"); | 
 | 2261 |             }); | 
 | 2262 | } | 
 | 2263 |  | 
 | 2264 | inline void requestRoutesSystemDumpEntry(App& app) | 
 | 2265 | { | 
 | 2266 |     BMCWEB_ROUTE(app, | 
| John Edward Broadbent | 864d6a1 | 2021-06-09 10:12:48 -0700 | [diff] [blame] | 2267 |                  "/redfish/v1/Systems/system/LogServices/Dump/Entries/<str>/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 2268 |         .privileges(redfish::privileges::getLogEntry) | 
 | 2269 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2270 |         .methods(boost::beast::http::verb::get)( | 
 | 2271 |             [](const crow::Request&, | 
 | 2272 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
 | 2273 |                const std::string& param) { | 
 | 2274 |                 getDumpEntryById(asyncResp, param, "System"); | 
 | 2275 |             }); | 
 | 2276 |  | 
 | 2277 |     BMCWEB_ROUTE(app, | 
| John Edward Broadbent | 864d6a1 | 2021-06-09 10:12:48 -0700 | [diff] [blame] | 2278 |                  "/redfish/v1/Systems/system/LogServices/Dump/Entries/<str>/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 2279 |         .privileges(redfish::privileges::deleteLogEntry) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2280 |         .methods(boost::beast::http::verb::delete_)( | 
 | 2281 |             [](const crow::Request&, | 
 | 2282 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
 | 2283 |                const std::string& param) { | 
 | 2284 |                 deleteDumpEntry(asyncResp, param, "system"); | 
 | 2285 |             }); | 
 | 2286 | } | 
 | 2287 |  | 
 | 2288 | inline void requestRoutesSystemDumpCreate(App& app) | 
 | 2289 | { | 
 | 2290 |     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/Dump/" | 
 | 2291 |                       "Actions/" | 
 | 2292 |                       "LogService.CollectDiagnosticData/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 2293 |         .privileges(redfish::privileges::postLogService) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2294 |         .methods(boost::beast::http::verb::post)( | 
 | 2295 |             [](const crow::Request& req, | 
 | 2296 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) | 
 | 2297 |  | 
 | 2298 |             { createDump(asyncResp, req, "System"); }); | 
 | 2299 | } | 
 | 2300 |  | 
 | 2301 | inline void requestRoutesSystemDumpClear(App& app) | 
 | 2302 | { | 
 | 2303 |     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/Dump/" | 
 | 2304 |                       "Actions/" | 
 | 2305 |                       "LogService.ClearLog/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 2306 |         .privileges(redfish::privileges::postLogService) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2307 |         .methods(boost::beast::http::verb::post)( | 
 | 2308 |             [](const crow::Request&, | 
 | 2309 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) | 
 | 2310 |  | 
 | 2311 |             { clearDump(asyncResp, "System"); }); | 
 | 2312 | } | 
 | 2313 |  | 
 | 2314 | inline void requestRoutesCrashdumpService(App& app) | 
 | 2315 | { | 
 | 2316 |     // Note: Deviated from redfish privilege registry for GET & HEAD | 
 | 2317 |     // method for security reasons. | 
 | 2318 |     /** | 
 | 2319 |      * Functions triggers appropriate requests on DBus | 
 | 2320 |      */ | 
 | 2321 |     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/Crashdump/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 2322 |         // This is incorrect, should be: | 
 | 2323 |         //.privileges(redfish::privileges::getLogService) | 
| Ed Tanous | 432a890 | 2021-06-14 15:28:56 -0700 | [diff] [blame] | 2324 |         .privileges({{"ConfigureManager"}}) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2325 |         .methods( | 
 | 2326 |             boost::beast::http::verb:: | 
 | 2327 |                 get)([](const crow::Request&, | 
 | 2328 |                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { | 
 | 2329 |             // Copy over the static data to include the entries added by | 
 | 2330 |             // SubRoute | 
 | 2331 |             asyncResp->res.jsonValue["@odata.id"] = | 
 | 2332 |                 "/redfish/v1/Systems/system/LogServices/Crashdump"; | 
 | 2333 |             asyncResp->res.jsonValue["@odata.type"] = | 
 | 2334 |                 "#LogService.v1_2_0.LogService"; | 
 | 2335 |             asyncResp->res.jsonValue["Name"] = "Open BMC Oem Crashdump Service"; | 
 | 2336 |             asyncResp->res.jsonValue["Description"] = "Oem Crashdump Service"; | 
 | 2337 |             asyncResp->res.jsonValue["Id"] = "Oem Crashdump"; | 
 | 2338 |             asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull"; | 
 | 2339 |             asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3; | 
| Tejas Patil | 7c8c405 | 2021-06-04 17:43:14 +0530 | [diff] [blame] | 2340 |  | 
 | 2341 |             std::pair<std::string, std::string> redfishDateTimeOffset = | 
 | 2342 |                 crow::utility::getDateTimeOffsetNow(); | 
 | 2343 |             asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; | 
 | 2344 |             asyncResp->res.jsonValue["DateTimeLocalOffset"] = | 
 | 2345 |                 redfishDateTimeOffset.second; | 
 | 2346 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2347 |             asyncResp->res.jsonValue["Entries"] = { | 
 | 2348 |                 {"@odata.id", | 
 | 2349 |                  "/redfish/v1/Systems/system/LogServices/Crashdump/Entries"}}; | 
 | 2350 |             asyncResp->res.jsonValue["Actions"] = { | 
 | 2351 |                 {"#LogService.ClearLog", | 
 | 2352 |                  {{"target", "/redfish/v1/Systems/system/LogServices/Crashdump/" | 
 | 2353 |                              "Actions/LogService.ClearLog"}}}, | 
 | 2354 |                 {"#LogService.CollectDiagnosticData", | 
 | 2355 |                  {{"target", "/redfish/v1/Systems/system/LogServices/Crashdump/" | 
 | 2356 |                              "Actions/LogService.CollectDiagnosticData"}}}}; | 
 | 2357 |         }); | 
 | 2358 | } | 
 | 2359 |  | 
 | 2360 | void inline requestRoutesCrashdumpClear(App& app) | 
 | 2361 | { | 
 | 2362 |     BMCWEB_ROUTE(app, | 
 | 2363 |                  "/redfish/v1/Systems/system/LogServices/Crashdump/Actions/" | 
 | 2364 |                  "LogService.ClearLog/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 2365 |         // This is incorrect, should be: | 
 | 2366 |         //.privileges(redfish::privileges::postLogService) | 
| Ed Tanous | 432a890 | 2021-06-14 15:28:56 -0700 | [diff] [blame] | 2367 |         .privileges({{"ConfigureComponents"}}) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2368 |         .methods(boost::beast::http::verb::post)( | 
 | 2369 |             [](const crow::Request&, | 
 | 2370 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { | 
 | 2371 |                 crow::connections::systemBus->async_method_call( | 
 | 2372 |                     [asyncResp](const boost::system::error_code ec, | 
 | 2373 |                                 const std::string&) { | 
 | 2374 |                         if (ec) | 
 | 2375 |                         { | 
 | 2376 |                             messages::internalError(asyncResp->res); | 
 | 2377 |                             return; | 
 | 2378 |                         } | 
 | 2379 |                         messages::success(asyncResp->res); | 
 | 2380 |                     }, | 
 | 2381 |                     crashdumpObject, crashdumpPath, deleteAllInterface, | 
 | 2382 |                     "DeleteAll"); | 
 | 2383 |             }); | 
 | 2384 | } | 
| Jason M. Bills | 5b61b5e | 2019-10-16 10:59:02 -0700 | [diff] [blame] | 2385 |  | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 2386 | static void | 
 | 2387 |     logCrashdumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
 | 2388 |                       const std::string& logID, nlohmann::json& logEntryJson) | 
| Jason M. Bills | e855dd2 | 2019-10-08 11:37:48 -0700 | [diff] [blame] | 2389 | { | 
| Johnathan Mantey | 043a053 | 2020-03-10 17:15:28 -0700 | [diff] [blame] | 2390 |     auto getStoredLogCallback = | 
 | 2391 |         [asyncResp, logID, &logEntryJson]( | 
 | 2392 |             const boost::system::error_code ec, | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 2393 |             const std::vector<std::pair<std::string, VariantType>>& params) { | 
| Johnathan Mantey | 043a053 | 2020-03-10 17:15:28 -0700 | [diff] [blame] | 2394 |             if (ec) | 
| Jason M. Bills | 1ddcf01 | 2019-11-26 14:59:21 -0800 | [diff] [blame] | 2395 |             { | 
| Johnathan Mantey | 043a053 | 2020-03-10 17:15:28 -0700 | [diff] [blame] | 2396 |                 BMCWEB_LOG_DEBUG << "failed to get log ec: " << ec.message(); | 
 | 2397 |                 if (ec.value() == | 
 | 2398 |                     boost::system::linux_error::bad_request_descriptor) | 
 | 2399 |                 { | 
 | 2400 |                     messages::resourceNotFound(asyncResp->res, "LogEntry", | 
 | 2401 |                                                logID); | 
 | 2402 |                 } | 
 | 2403 |                 else | 
 | 2404 |                 { | 
 | 2405 |                     messages::internalError(asyncResp->res); | 
 | 2406 |                 } | 
 | 2407 |                 return; | 
| Jason M. Bills | 1ddcf01 | 2019-11-26 14:59:21 -0800 | [diff] [blame] | 2408 |             } | 
| Jason M. Bills | e855dd2 | 2019-10-08 11:37:48 -0700 | [diff] [blame] | 2409 |  | 
| Johnathan Mantey | 043a053 | 2020-03-10 17:15:28 -0700 | [diff] [blame] | 2410 |             std::string timestamp{}; | 
 | 2411 |             std::string filename{}; | 
 | 2412 |             std::string logfile{}; | 
| Ed Tanous | 2c70f80 | 2020-09-28 14:29:23 -0700 | [diff] [blame] | 2413 |             parseCrashdumpParameters(params, filename, timestamp, logfile); | 
| Johnathan Mantey | 043a053 | 2020-03-10 17:15:28 -0700 | [diff] [blame] | 2414 |  | 
 | 2415 |             if (filename.empty() || timestamp.empty()) | 
 | 2416 |             { | 
 | 2417 |                 messages::resourceMissingAtURI(asyncResp->res, logID); | 
 | 2418 |                 return; | 
 | 2419 |             } | 
 | 2420 |  | 
 | 2421 |             std::string crashdumpURI = | 
 | 2422 |                 "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/" + | 
 | 2423 |                 logID + "/" + filename; | 
| Ed Tanous | d0dbeef | 2021-07-01 08:46:46 -0700 | [diff] [blame] | 2424 |             logEntryJson = {{"@odata.type", "#LogEntry.v1_7_0.LogEntry"}, | 
| Johnathan Mantey | 043a053 | 2020-03-10 17:15:28 -0700 | [diff] [blame] | 2425 |                             {"@odata.id", "/redfish/v1/Systems/system/" | 
 | 2426 |                                           "LogServices/Crashdump/Entries/" + | 
 | 2427 |                                               logID}, | 
 | 2428 |                             {"Name", "CPU Crashdump"}, | 
 | 2429 |                             {"Id", logID}, | 
 | 2430 |                             {"EntryType", "Oem"}, | 
| Jason M. Bills | 8e6c099 | 2021-03-11 16:26:53 -0800 | [diff] [blame] | 2431 |                             {"AdditionalDataURI", std::move(crashdumpURI)}, | 
 | 2432 |                             {"DiagnosticDataType", "OEM"}, | 
 | 2433 |                             {"OEMDiagnosticDataType", "PECICrashdump"}, | 
| Johnathan Mantey | 043a053 | 2020-03-10 17:15:28 -0700 | [diff] [blame] | 2434 |                             {"Created", std::move(timestamp)}}; | 
 | 2435 |         }; | 
| Jason M. Bills | e855dd2 | 2019-10-08 11:37:48 -0700 | [diff] [blame] | 2436 |     crow::connections::systemBus->async_method_call( | 
| Jason M. Bills | 5b61b5e | 2019-10-16 10:59:02 -0700 | [diff] [blame] | 2437 |         std::move(getStoredLogCallback), crashdumpObject, | 
 | 2438 |         crashdumpPath + std::string("/") + logID, | 
| Johnathan Mantey | 043a053 | 2020-03-10 17:15:28 -0700 | [diff] [blame] | 2439 |         "org.freedesktop.DBus.Properties", "GetAll", crashdumpInterface); | 
| Jason M. Bills | e855dd2 | 2019-10-08 11:37:48 -0700 | [diff] [blame] | 2440 | } | 
 | 2441 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2442 | inline void requestRoutesCrashdumpEntryCollection(App& app) | 
| Ed Tanous | 1da66f7 | 2018-07-27 16:13:37 -0700 | [diff] [blame] | 2443 | { | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2444 |     // Note: Deviated from redfish privilege registry for GET & HEAD | 
 | 2445 |     // method for security reasons. | 
| Ed Tanous | 1da66f7 | 2018-07-27 16:13:37 -0700 | [diff] [blame] | 2446 |     /** | 
 | 2447 |      * Functions triggers appropriate requests on DBus | 
 | 2448 |      */ | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2449 |     BMCWEB_ROUTE(app, | 
 | 2450 |                  "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 2451 |         // This is incorrect, should be. | 
 | 2452 |         //.privileges(redfish::privileges::postLogEntryCollection) | 
| Ed Tanous | 432a890 | 2021-06-14 15:28:56 -0700 | [diff] [blame] | 2453 |         .privileges({{"ConfigureComponents"}}) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2454 |         .methods( | 
 | 2455 |             boost::beast::http::verb:: | 
 | 2456 |                 get)([](const crow::Request&, | 
 | 2457 |                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { | 
 | 2458 |             // Collections don't include the static data added by SubRoute | 
 | 2459 |             // because it has a duplicate entry for members | 
 | 2460 |             auto getLogEntriesCallback = [asyncResp]( | 
 | 2461 |                                              const boost::system::error_code ec, | 
 | 2462 |                                              const std::vector<std::string>& | 
 | 2463 |                                                  resp) { | 
| Johnathan Mantey | 043a053 | 2020-03-10 17:15:28 -0700 | [diff] [blame] | 2464 |                 if (ec) | 
 | 2465 |                 { | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2466 |                     if (ec.value() != | 
 | 2467 |                         boost::system::errc::no_such_file_or_directory) | 
 | 2468 |                     { | 
 | 2469 |                         BMCWEB_LOG_DEBUG << "failed to get entries ec: " | 
 | 2470 |                                          << ec.message(); | 
 | 2471 |                         messages::internalError(asyncResp->res); | 
 | 2472 |                         return; | 
 | 2473 |                     } | 
| Johnathan Mantey | 043a053 | 2020-03-10 17:15:28 -0700 | [diff] [blame] | 2474 |                 } | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2475 |                 asyncResp->res.jsonValue["@odata.type"] = | 
 | 2476 |                     "#LogEntryCollection.LogEntryCollection"; | 
 | 2477 |                 asyncResp->res.jsonValue["@odata.id"] = | 
 | 2478 |                     "/redfish/v1/Systems/system/LogServices/Crashdump/Entries"; | 
 | 2479 |                 asyncResp->res.jsonValue["Name"] = "Open BMC Crashdump Entries"; | 
 | 2480 |                 asyncResp->res.jsonValue["Description"] = | 
 | 2481 |                     "Collection of Crashdump Entries"; | 
 | 2482 |                 nlohmann::json& logEntryArray = | 
 | 2483 |                     asyncResp->res.jsonValue["Members"]; | 
 | 2484 |                 logEntryArray = nlohmann::json::array(); | 
 | 2485 |                 std::vector<std::string> logIDs; | 
 | 2486 |                 // Get the list of log entries and build up an empty array big | 
 | 2487 |                 // enough to hold them | 
 | 2488 |                 for (const std::string& objpath : resp) | 
| Johnathan Mantey | 043a053 | 2020-03-10 17:15:28 -0700 | [diff] [blame] | 2489 |                 { | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2490 |                     // Get the log ID | 
 | 2491 |                     std::size_t lastPos = objpath.rfind('/'); | 
 | 2492 |                     if (lastPos == std::string::npos) | 
 | 2493 |                     { | 
 | 2494 |                         continue; | 
 | 2495 |                     } | 
 | 2496 |                     logIDs.emplace_back(objpath.substr(lastPos + 1)); | 
| Johnathan Mantey | 043a053 | 2020-03-10 17:15:28 -0700 | [diff] [blame] | 2497 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2498 |                     // Add a space for the log entry to the array | 
 | 2499 |                     logEntryArray.push_back({}); | 
 | 2500 |                 } | 
 | 2501 |                 // Now go through and set up async calls to fill in the entries | 
 | 2502 |                 size_t index = 0; | 
 | 2503 |                 for (const std::string& logID : logIDs) | 
| Johnathan Mantey | 043a053 | 2020-03-10 17:15:28 -0700 | [diff] [blame] | 2504 |                 { | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2505 |                     // Add the log entry to the array | 
 | 2506 |                     logCrashdumpEntry(asyncResp, logID, logEntryArray[index++]); | 
| Johnathan Mantey | 043a053 | 2020-03-10 17:15:28 -0700 | [diff] [blame] | 2507 |                 } | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2508 |                 asyncResp->res.jsonValue["Members@odata.count"] = | 
 | 2509 |                     logEntryArray.size(); | 
| Johnathan Mantey | 043a053 | 2020-03-10 17:15:28 -0700 | [diff] [blame] | 2510 |             }; | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2511 |             crow::connections::systemBus->async_method_call( | 
 | 2512 |                 std::move(getLogEntriesCallback), | 
 | 2513 |                 "xyz.openbmc_project.ObjectMapper", | 
 | 2514 |                 "/xyz/openbmc_project/object_mapper", | 
 | 2515 |                 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "", 0, | 
 | 2516 |                 std::array<const char*, 1>{crashdumpInterface}); | 
 | 2517 |         }); | 
 | 2518 | } | 
| Ed Tanous | 1da66f7 | 2018-07-27 16:13:37 -0700 | [diff] [blame] | 2519 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2520 | inline void requestRoutesCrashdumpEntry(App& app) | 
| Ed Tanous | 1da66f7 | 2018-07-27 16:13:37 -0700 | [diff] [blame] | 2521 | { | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2522 |     // Note: Deviated from redfish privilege registry for GET & HEAD | 
 | 2523 |     // method for security reasons. | 
| Ed Tanous | 1da66f7 | 2018-07-27 16:13:37 -0700 | [diff] [blame] | 2524 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2525 |     BMCWEB_ROUTE( | 
 | 2526 |         app, "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/<str>/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 2527 |         // this is incorrect, should be | 
 | 2528 |         // .privileges(redfish::privileges::getLogEntry) | 
| Ed Tanous | 432a890 | 2021-06-14 15:28:56 -0700 | [diff] [blame] | 2529 |         .privileges({{"ConfigureComponents"}}) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2530 |         .methods(boost::beast::http::verb::get)( | 
 | 2531 |             [](const crow::Request&, | 
 | 2532 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
 | 2533 |                const std::string& param) { | 
 | 2534 |                 const std::string& logID = param; | 
 | 2535 |                 logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue); | 
 | 2536 |             }); | 
 | 2537 | } | 
| Ed Tanous | 1da66f7 | 2018-07-27 16:13:37 -0700 | [diff] [blame] | 2538 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2539 | inline void requestRoutesCrashdumpFile(App& app) | 
 | 2540 | { | 
 | 2541 |     // Note: Deviated from redfish privilege registry for GET & HEAD | 
 | 2542 |     // method for security reasons. | 
 | 2543 |     BMCWEB_ROUTE( | 
 | 2544 |         app, | 
 | 2545 |         "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/<str>/<str>/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 2546 |         .privileges(redfish::privileges::getLogEntry) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2547 |         .methods(boost::beast::http::verb::get)( | 
 | 2548 |             [](const crow::Request&, | 
 | 2549 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
 | 2550 |                const std::string& logID, const std::string& fileName) { | 
 | 2551 |                 auto getStoredLogCallback = | 
 | 2552 |                     [asyncResp, logID, fileName]( | 
 | 2553 |                         const boost::system::error_code ec, | 
 | 2554 |                         const std::vector<std::pair<std::string, VariantType>>& | 
 | 2555 |                             resp) { | 
 | 2556 |                         if (ec) | 
 | 2557 |                         { | 
 | 2558 |                             BMCWEB_LOG_DEBUG << "failed to get log ec: " | 
 | 2559 |                                              << ec.message(); | 
 | 2560 |                             messages::internalError(asyncResp->res); | 
 | 2561 |                             return; | 
 | 2562 |                         } | 
| Jason M. Bills | 8e6c099 | 2021-03-11 16:26:53 -0800 | [diff] [blame] | 2563 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2564 |                         std::string dbusFilename{}; | 
 | 2565 |                         std::string dbusTimestamp{}; | 
 | 2566 |                         std::string dbusFilepath{}; | 
| Jason M. Bills | 8e6c099 | 2021-03-11 16:26:53 -0800 | [diff] [blame] | 2567 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2568 |                         parseCrashdumpParameters(resp, dbusFilename, | 
 | 2569 |                                                  dbusTimestamp, dbusFilepath); | 
 | 2570 |  | 
 | 2571 |                         if (dbusFilename.empty() || dbusTimestamp.empty() || | 
 | 2572 |                             dbusFilepath.empty()) | 
 | 2573 |                         { | 
 | 2574 |                             messages::resourceMissingAtURI(asyncResp->res, | 
 | 2575 |                                                            fileName); | 
 | 2576 |                             return; | 
 | 2577 |                         } | 
 | 2578 |  | 
 | 2579 |                         // Verify the file name parameter is correct | 
 | 2580 |                         if (fileName != dbusFilename) | 
 | 2581 |                         { | 
 | 2582 |                             messages::resourceMissingAtURI(asyncResp->res, | 
 | 2583 |                                                            fileName); | 
 | 2584 |                             return; | 
 | 2585 |                         } | 
 | 2586 |  | 
 | 2587 |                         if (!std::filesystem::exists(dbusFilepath)) | 
 | 2588 |                         { | 
 | 2589 |                             messages::resourceMissingAtURI(asyncResp->res, | 
 | 2590 |                                                            fileName); | 
 | 2591 |                             return; | 
 | 2592 |                         } | 
 | 2593 |                         std::ifstream ifs(dbusFilepath, std::ios::in | | 
 | 2594 |                                                             std::ios::binary | | 
 | 2595 |                                                             std::ios::ate); | 
 | 2596 |                         std::ifstream::pos_type fileSize = ifs.tellg(); | 
 | 2597 |                         if (fileSize < 0) | 
 | 2598 |                         { | 
 | 2599 |                             messages::generalError(asyncResp->res); | 
 | 2600 |                             return; | 
 | 2601 |                         } | 
 | 2602 |                         ifs.seekg(0, std::ios::beg); | 
 | 2603 |  | 
 | 2604 |                         auto crashData = std::make_unique<char[]>( | 
 | 2605 |                             static_cast<unsigned int>(fileSize)); | 
 | 2606 |  | 
 | 2607 |                         ifs.read(crashData.get(), static_cast<int>(fileSize)); | 
 | 2608 |  | 
 | 2609 |                         // The cast to std::string is intentional in order to | 
 | 2610 |                         // use the assign() that applies move mechanics | 
 | 2611 |                         asyncResp->res.body().assign( | 
 | 2612 |                             static_cast<std::string>(crashData.get())); | 
 | 2613 |  | 
 | 2614 |                         // Configure this to be a file download when accessed | 
 | 2615 |                         // from a browser | 
 | 2616 |                         asyncResp->res.addHeader("Content-Disposition", | 
 | 2617 |                                                  "attachment"); | 
 | 2618 |                     }; | 
 | 2619 |                 crow::connections::systemBus->async_method_call( | 
 | 2620 |                     std::move(getStoredLogCallback), crashdumpObject, | 
 | 2621 |                     crashdumpPath + std::string("/") + logID, | 
 | 2622 |                     "org.freedesktop.DBus.Properties", "GetAll", | 
 | 2623 |                     crashdumpInterface); | 
 | 2624 |             }); | 
 | 2625 | } | 
 | 2626 |  | 
 | 2627 | inline void requestRoutesCrashdumpCollect(App& app) | 
 | 2628 | { | 
 | 2629 |     // Note: Deviated from redfish privilege registry for GET & HEAD | 
 | 2630 |     // method for security reasons. | 
 | 2631 |     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/Crashdump/" | 
 | 2632 |                       "Actions/LogService.CollectDiagnosticData/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 2633 |         // The below is incorrect;  Should be ConfigureManager | 
 | 2634 |         //.privileges(redfish::privileges::postLogService) | 
| Ed Tanous | 432a890 | 2021-06-14 15:28:56 -0700 | [diff] [blame] | 2635 |         .privileges({{"ConfigureComponents"}}) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2636 |         .methods( | 
 | 2637 |             boost::beast::http::verb:: | 
 | 2638 |                 post)([](const crow::Request& req, | 
 | 2639 |                          const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { | 
 | 2640 |             std::string diagnosticDataType; | 
 | 2641 |             std::string oemDiagnosticDataType; | 
 | 2642 |             if (!redfish::json_util::readJson( | 
 | 2643 |                     req, asyncResp->res, "DiagnosticDataType", | 
 | 2644 |                     diagnosticDataType, "OEMDiagnosticDataType", | 
 | 2645 |                     oemDiagnosticDataType)) | 
| James Feist | 4622957 | 2020-02-19 15:11:58 -0800 | [diff] [blame] | 2646 |             { | 
| James Feist | 4622957 | 2020-02-19 15:11:58 -0800 | [diff] [blame] | 2647 |                 return; | 
 | 2648 |             } | 
| Ed Tanous | 1da66f7 | 2018-07-27 16:13:37 -0700 | [diff] [blame] | 2649 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2650 |             if (diagnosticDataType != "OEM") | 
 | 2651 |             { | 
 | 2652 |                 BMCWEB_LOG_ERROR | 
 | 2653 |                     << "Only OEM DiagnosticDataType supported for Crashdump"; | 
 | 2654 |                 messages::actionParameterValueFormatError( | 
 | 2655 |                     asyncResp->res, diagnosticDataType, "DiagnosticDataType", | 
 | 2656 |                     "CollectDiagnosticData"); | 
 | 2657 |                 return; | 
 | 2658 |             } | 
 | 2659 |  | 
 | 2660 |             auto collectCrashdumpCallback = [asyncResp, req]( | 
 | 2661 |                                                 const boost::system::error_code | 
 | 2662 |                                                     ec, | 
 | 2663 |                                                 const std::string&) { | 
 | 2664 |                 if (ec) | 
 | 2665 |                 { | 
 | 2666 |                     if (ec.value() == | 
 | 2667 |                         boost::system::errc::operation_not_supported) | 
 | 2668 |                     { | 
 | 2669 |                         messages::resourceInStandby(asyncResp->res); | 
 | 2670 |                     } | 
 | 2671 |                     else if (ec.value() == | 
 | 2672 |                              boost::system::errc::device_or_resource_busy) | 
 | 2673 |                     { | 
 | 2674 |                         messages::serviceTemporarilyUnavailable(asyncResp->res, | 
 | 2675 |                                                                 "60"); | 
 | 2676 |                     } | 
 | 2677 |                     else | 
 | 2678 |                     { | 
 | 2679 |                         messages::internalError(asyncResp->res); | 
 | 2680 |                     } | 
 | 2681 |                     return; | 
 | 2682 |                 } | 
 | 2683 |                 std::shared_ptr<task::TaskData> task = | 
 | 2684 |                     task::TaskData::createTask( | 
 | 2685 |                         [](boost::system::error_code err, | 
 | 2686 |                            sdbusplus::message::message&, | 
 | 2687 |                            const std::shared_ptr<task::TaskData>& taskData) { | 
 | 2688 |                             if (!err) | 
 | 2689 |                             { | 
 | 2690 |                                 taskData->messages.emplace_back( | 
 | 2691 |                                     messages::taskCompletedOK( | 
 | 2692 |                                         std::to_string(taskData->index))); | 
 | 2693 |                                 taskData->state = "Completed"; | 
 | 2694 |                             } | 
 | 2695 |                             return task::completed; | 
 | 2696 |                         }, | 
 | 2697 |                         "type='signal',interface='org.freedesktop.DBus." | 
 | 2698 |                         "Properties'," | 
 | 2699 |                         "member='PropertiesChanged',arg0namespace='com.intel." | 
 | 2700 |                         "crashdump'"); | 
 | 2701 |                 task->startTimer(std::chrono::minutes(5)); | 
 | 2702 |                 task->populateResp(asyncResp->res); | 
 | 2703 |                 task->payload.emplace(req); | 
 | 2704 |             }; | 
 | 2705 |  | 
 | 2706 |             if (oemDiagnosticDataType == "OnDemand") | 
 | 2707 |             { | 
 | 2708 |                 crow::connections::systemBus->async_method_call( | 
 | 2709 |                     std::move(collectCrashdumpCallback), crashdumpObject, | 
 | 2710 |                     crashdumpPath, crashdumpOnDemandInterface, | 
 | 2711 |                     "GenerateOnDemandLog"); | 
 | 2712 |             } | 
 | 2713 |             else if (oemDiagnosticDataType == "Telemetry") | 
 | 2714 |             { | 
 | 2715 |                 crow::connections::systemBus->async_method_call( | 
 | 2716 |                     std::move(collectCrashdumpCallback), crashdumpObject, | 
 | 2717 |                     crashdumpPath, crashdumpTelemetryInterface, | 
 | 2718 |                     "GenerateTelemetryLog"); | 
 | 2719 |             } | 
 | 2720 |             else | 
 | 2721 |             { | 
 | 2722 |                 BMCWEB_LOG_ERROR << "Unsupported OEMDiagnosticDataType: " | 
 | 2723 |                                  << oemDiagnosticDataType; | 
 | 2724 |                 messages::actionParameterValueFormatError( | 
 | 2725 |                     asyncResp->res, oemDiagnosticDataType, | 
 | 2726 |                     "OEMDiagnosticDataType", "CollectDiagnosticData"); | 
 | 2727 |                 return; | 
 | 2728 |             } | 
 | 2729 |         }); | 
 | 2730 | } | 
| Kenny L. Ku | 6eda768 | 2020-06-19 09:48:36 -0700 | [diff] [blame] | 2731 |  | 
| Andrew Geissler | cb92c03 | 2018-08-17 07:56:14 -0700 | [diff] [blame] | 2732 | /** | 
 | 2733 |  * DBusLogServiceActionsClear class supports POST method for ClearLog action. | 
 | 2734 |  */ | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2735 | inline void requestRoutesDBusLogServiceActionsClear(App& app) | 
| Andrew Geissler | cb92c03 | 2018-08-17 07:56:14 -0700 | [diff] [blame] | 2736 | { | 
| Andrew Geissler | cb92c03 | 2018-08-17 07:56:14 -0700 | [diff] [blame] | 2737 |     /** | 
 | 2738 |      * Function handles POST method request. | 
 | 2739 |      * The Clear Log actions does not require any parameter.The action deletes | 
 | 2740 |      * all entries found in the Entries collection for this Log Service. | 
 | 2741 |      */ | 
| Andrew Geissler | cb92c03 | 2018-08-17 07:56:14 -0700 | [diff] [blame] | 2742 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2743 |     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/EventLog/Actions/" | 
 | 2744 |                       "LogService.ClearLog/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 2745 |         .privileges(redfish::privileges::postLogService) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2746 |         .methods(boost::beast::http::verb::post)( | 
 | 2747 |             [](const crow::Request&, | 
 | 2748 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { | 
 | 2749 |                 BMCWEB_LOG_DEBUG << "Do delete all entries."; | 
| Andrew Geissler | cb92c03 | 2018-08-17 07:56:14 -0700 | [diff] [blame] | 2750 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2751 |                 // Process response from Logging service. | 
 | 2752 |                 auto respHandler = [asyncResp]( | 
 | 2753 |                                        const boost::system::error_code ec) { | 
 | 2754 |                     BMCWEB_LOG_DEBUG | 
 | 2755 |                         << "doClearLog resp_handler callback: Done"; | 
 | 2756 |                     if (ec) | 
 | 2757 |                     { | 
 | 2758 |                         // TODO Handle for specific error code | 
 | 2759 |                         BMCWEB_LOG_ERROR << "doClearLog resp_handler got error " | 
 | 2760 |                                          << ec; | 
 | 2761 |                         asyncResp->res.result( | 
 | 2762 |                             boost::beast::http::status::internal_server_error); | 
 | 2763 |                         return; | 
 | 2764 |                     } | 
| Andrew Geissler | cb92c03 | 2018-08-17 07:56:14 -0700 | [diff] [blame] | 2765 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2766 |                     asyncResp->res.result( | 
 | 2767 |                         boost::beast::http::status::no_content); | 
 | 2768 |                 }; | 
 | 2769 |  | 
 | 2770 |                 // Make call to Logging service to request Clear Log | 
 | 2771 |                 crow::connections::systemBus->async_method_call( | 
 | 2772 |                     respHandler, "xyz.openbmc_project.Logging", | 
 | 2773 |                     "/xyz/openbmc_project/logging", | 
 | 2774 |                     "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll"); | 
 | 2775 |             }); | 
 | 2776 | } | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 2777 |  | 
 | 2778 | /**************************************************** | 
 | 2779 |  * Redfish PostCode interfaces | 
 | 2780 |  * using DBUS interface: getPostCodesTS | 
 | 2781 |  ******************************************************/ | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2782 | inline void requestRoutesPostCodesLogService(App& app) | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 2783 | { | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2784 |     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/PostCodes/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 2785 |         .privileges(redfish::privileges::getLogService) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2786 |         .methods(boost::beast::http::verb::get)( | 
 | 2787 |             [](const crow::Request&, | 
 | 2788 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { | 
 | 2789 |                 asyncResp->res.jsonValue = { | 
 | 2790 |                     {"@odata.id", | 
 | 2791 |                      "/redfish/v1/Systems/system/LogServices/PostCodes"}, | 
 | 2792 |                     {"@odata.type", "#LogService.v1_1_0.LogService"}, | 
 | 2793 |                     {"Name", "POST Code Log Service"}, | 
 | 2794 |                     {"Description", "POST Code Log Service"}, | 
 | 2795 |                     {"Id", "BIOS POST Code Log"}, | 
 | 2796 |                     {"OverWritePolicy", "WrapsWhenFull"}, | 
 | 2797 |                     {"Entries", | 
 | 2798 |                      {{"@odata.id", "/redfish/v1/Systems/system/LogServices/" | 
 | 2799 |                                     "PostCodes/Entries"}}}}; | 
| Tejas Patil | 7c8c405 | 2021-06-04 17:43:14 +0530 | [diff] [blame] | 2800 |  | 
 | 2801 |                 std::pair<std::string, std::string> redfishDateTimeOffset = | 
 | 2802 |                     crow::utility::getDateTimeOffsetNow(); | 
 | 2803 |                 asyncResp->res.jsonValue["DateTime"] = | 
 | 2804 |                     redfishDateTimeOffset.first; | 
 | 2805 |                 asyncResp->res.jsonValue["DateTimeLocalOffset"] = | 
 | 2806 |                     redfishDateTimeOffset.second; | 
 | 2807 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2808 |                 asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] = { | 
 | 2809 |                     {"target", | 
 | 2810 |                      "/redfish/v1/Systems/system/LogServices/PostCodes/" | 
 | 2811 |                      "Actions/LogService.ClearLog"}}; | 
 | 2812 |             }); | 
 | 2813 | } | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 2814 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2815 | inline void requestRoutesPostCodesClear(App& app) | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 2816 | { | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2817 |     BMCWEB_ROUTE(app, | 
 | 2818 |                  "/redfish/v1/Systems/system/LogServices/PostCodes/Actions/" | 
 | 2819 |                  "LogService.ClearLog/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 2820 |         // The following privilege is incorrect;  It should be ConfigureManager | 
 | 2821 |         //.privileges(redfish::privileges::postLogService) | 
| Ed Tanous | 432a890 | 2021-06-14 15:28:56 -0700 | [diff] [blame] | 2822 |         .privileges({{"ConfigureComponents"}}) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2823 |         .methods(boost::beast::http::verb::post)( | 
 | 2824 |             [](const crow::Request&, | 
 | 2825 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { | 
 | 2826 |                 BMCWEB_LOG_DEBUG << "Do delete all postcodes entries."; | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 2827 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 2828 |                 // Make call to post-code service to request clear all | 
 | 2829 |                 crow::connections::systemBus->async_method_call( | 
 | 2830 |                     [asyncResp](const boost::system::error_code ec) { | 
 | 2831 |                         if (ec) | 
 | 2832 |                         { | 
 | 2833 |                             // TODO Handle for specific error code | 
 | 2834 |                             BMCWEB_LOG_ERROR | 
 | 2835 |                                 << "doClearPostCodes resp_handler got error " | 
 | 2836 |                                 << ec; | 
 | 2837 |                             asyncResp->res.result(boost::beast::http::status:: | 
 | 2838 |                                                       internal_server_error); | 
 | 2839 |                             messages::internalError(asyncResp->res); | 
 | 2840 |                             return; | 
 | 2841 |                         } | 
 | 2842 |                     }, | 
 | 2843 |                     "xyz.openbmc_project.State.Boot.PostCode0", | 
 | 2844 |                     "/xyz/openbmc_project/State/Boot/PostCode0", | 
 | 2845 |                     "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll"); | 
 | 2846 |             }); | 
 | 2847 | } | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 2848 |  | 
 | 2849 | static void fillPostCodeEntry( | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 2850 |     const std::shared_ptr<bmcweb::AsyncResp>& aResp, | 
| Manojkiran Eda | 6c9a279 | 2021-02-27 14:25:04 +0530 | [diff] [blame] | 2851 |     const boost::container::flat_map< | 
 | 2852 |         uint64_t, std::tuple<uint64_t, std::vector<uint8_t>>>& postcode, | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 2853 |     const uint16_t bootIndex, const uint64_t codeIndex = 0, | 
 | 2854 |     const uint64_t skip = 0, const uint64_t top = 0) | 
 | 2855 | { | 
 | 2856 |     // Get the Message from the MessageRegistry | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 2857 |     const message_registries::Message* message = | 
| Manojkiran Eda | 4a0bf53 | 2021-04-21 22:46:14 +0530 | [diff] [blame] | 2858 |         message_registries::getMessage("OpenBMC.0.2.BIOSPOSTCode"); | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 2859 |  | 
 | 2860 |     uint64_t currentCodeIndex = 0; | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 2861 |     nlohmann::json& logEntryArray = aResp->res.jsonValue["Members"]; | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 2862 |  | 
 | 2863 |     uint64_t firstCodeTimeUs = 0; | 
| Manojkiran Eda | 6c9a279 | 2021-02-27 14:25:04 +0530 | [diff] [blame] | 2864 |     for (const std::pair<uint64_t, std::tuple<uint64_t, std::vector<uint8_t>>>& | 
 | 2865 |              code : postcode) | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 2866 |     { | 
 | 2867 |         currentCodeIndex++; | 
 | 2868 |         std::string postcodeEntryID = | 
 | 2869 |             "B" + std::to_string(bootIndex) + "-" + | 
 | 2870 |             std::to_string(currentCodeIndex); // 1 based index in EntryID string | 
 | 2871 |  | 
 | 2872 |         uint64_t usecSinceEpoch = code.first; | 
 | 2873 |         uint64_t usTimeOffset = 0; | 
 | 2874 |  | 
 | 2875 |         if (1 == currentCodeIndex) | 
 | 2876 |         { // already incremented | 
 | 2877 |             firstCodeTimeUs = code.first; | 
 | 2878 |         } | 
 | 2879 |         else | 
 | 2880 |         { | 
 | 2881 |             usTimeOffset = code.first - firstCodeTimeUs; | 
 | 2882 |         } | 
 | 2883 |  | 
 | 2884 |         // skip if no specific codeIndex is specified and currentCodeIndex does | 
 | 2885 |         // not fall between top and skip | 
 | 2886 |         if ((codeIndex == 0) && | 
 | 2887 |             (currentCodeIndex <= skip || currentCodeIndex > top)) | 
 | 2888 |         { | 
 | 2889 |             continue; | 
 | 2890 |         } | 
 | 2891 |  | 
| Gunnar Mills | 4e0453b | 2020-07-08 14:00:30 -0500 | [diff] [blame] | 2892 |         // skip if a specific codeIndex is specified and does not match the | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 2893 |         // currentIndex | 
 | 2894 |         if ((codeIndex > 0) && (currentCodeIndex != codeIndex)) | 
 | 2895 |         { | 
 | 2896 |             // This is done for simplicity. 1st entry is needed to calculate | 
 | 2897 |             // time offset. To improve efficiency, one can get to the entry | 
 | 2898 |             // directly (possibly with flatmap's nth method) | 
 | 2899 |             continue; | 
 | 2900 |         } | 
 | 2901 |  | 
 | 2902 |         // currentCodeIndex is within top and skip or equal to specified code | 
 | 2903 |         // index | 
 | 2904 |  | 
 | 2905 |         // Get the Created time from the timestamp | 
 | 2906 |         std::string entryTimeStr; | 
| Asmitha Karunanithi | 9c620e2 | 2020-08-02 11:55:21 -0500 | [diff] [blame] | 2907 |         entryTimeStr = crow::utility::getDateTime( | 
 | 2908 |             static_cast<std::time_t>(usecSinceEpoch / 1000 / 1000)); | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 2909 |  | 
 | 2910 |         // assemble messageArgs: BootIndex, TimeOffset(100us), PostCode(hex) | 
 | 2911 |         std::ostringstream hexCode; | 
 | 2912 |         hexCode << "0x" << std::setfill('0') << std::setw(2) << std::hex | 
| Manojkiran Eda | 6c9a279 | 2021-02-27 14:25:04 +0530 | [diff] [blame] | 2913 |                 << std::get<0>(code.second); | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 2914 |         std::ostringstream timeOffsetStr; | 
 | 2915 |         // Set Fixed -Point Notation | 
 | 2916 |         timeOffsetStr << std::fixed; | 
 | 2917 |         // Set precision to 4 digits | 
 | 2918 |         timeOffsetStr << std::setprecision(4); | 
 | 2919 |         // Add double to stream | 
 | 2920 |         timeOffsetStr << static_cast<double>(usTimeOffset) / 1000 / 1000; | 
 | 2921 |         std::vector<std::string> messageArgs = { | 
 | 2922 |             std::to_string(bootIndex), timeOffsetStr.str(), hexCode.str()}; | 
 | 2923 |  | 
 | 2924 |         // Get MessageArgs template from message registry | 
 | 2925 |         std::string msg; | 
 | 2926 |         if (message != nullptr) | 
 | 2927 |         { | 
 | 2928 |             msg = message->message; | 
 | 2929 |  | 
 | 2930 |             // fill in this post code value | 
 | 2931 |             int i = 0; | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 2932 |             for (const std::string& messageArg : messageArgs) | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 2933 |             { | 
 | 2934 |                 std::string argStr = "%" + std::to_string(++i); | 
 | 2935 |                 size_t argPos = msg.find(argStr); | 
 | 2936 |                 if (argPos != std::string::npos) | 
 | 2937 |                 { | 
 | 2938 |                     msg.replace(argPos, argStr.length(), messageArg); | 
 | 2939 |                 } | 
 | 2940 |             } | 
 | 2941 |         } | 
 | 2942 |  | 
| Tim Lee | d4342a9 | 2020-04-27 11:47:58 +0800 | [diff] [blame] | 2943 |         // Get Severity template from message registry | 
 | 2944 |         std::string severity; | 
 | 2945 |         if (message != nullptr) | 
 | 2946 |         { | 
 | 2947 |             severity = message->severity; | 
 | 2948 |         } | 
 | 2949 |  | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 2950 |         // add to AsyncResp | 
 | 2951 |         logEntryArray.push_back({}); | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 2952 |         nlohmann::json& bmcLogEntry = logEntryArray.back(); | 
| Ed Tanous | d0dbeef | 2021-07-01 08:46:46 -0700 | [diff] [blame] | 2953 |         bmcLogEntry = {{"@odata.type", "#LogEntry.v1_4_0.LogEntry"}, | 
| Gunnar Mills | 743e9a1 | 2020-10-26 12:44:53 -0500 | [diff] [blame] | 2954 |                        {"@odata.id", "/redfish/v1/Systems/system/LogServices/" | 
 | 2955 |                                      "PostCodes/Entries/" + | 
 | 2956 |                                          postcodeEntryID}, | 
 | 2957 |                        {"Name", "POST Code Log Entry"}, | 
 | 2958 |                        {"Id", postcodeEntryID}, | 
 | 2959 |                        {"Message", std::move(msg)}, | 
| Manojkiran Eda | 4a0bf53 | 2021-04-21 22:46:14 +0530 | [diff] [blame] | 2960 |                        {"MessageId", "OpenBMC.0.2.BIOSPOSTCode"}, | 
| Gunnar Mills | 743e9a1 | 2020-10-26 12:44:53 -0500 | [diff] [blame] | 2961 |                        {"MessageArgs", std::move(messageArgs)}, | 
 | 2962 |                        {"EntryType", "Event"}, | 
 | 2963 |                        {"Severity", std::move(severity)}, | 
 | 2964 |                        {"Created", entryTimeStr}}; | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 2965 |     } | 
 | 2966 | } | 
 | 2967 |  | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 2968 | static void getPostCodeForEntry(const std::shared_ptr<bmcweb::AsyncResp>& aResp, | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 2969 |                                 const uint16_t bootIndex, | 
 | 2970 |                                 const uint64_t codeIndex) | 
 | 2971 | { | 
 | 2972 |     crow::connections::systemBus->async_method_call( | 
| Manojkiran Eda | 6c9a279 | 2021-02-27 14:25:04 +0530 | [diff] [blame] | 2973 |         [aResp, bootIndex, | 
 | 2974 |          codeIndex](const boost::system::error_code ec, | 
 | 2975 |                     const boost::container::flat_map< | 
 | 2976 |                         uint64_t, std::tuple<uint64_t, std::vector<uint8_t>>>& | 
 | 2977 |                         postcode) { | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 2978 |             if (ec) | 
 | 2979 |             { | 
 | 2980 |                 BMCWEB_LOG_DEBUG << "DBUS POST CODE PostCode response error"; | 
 | 2981 |                 messages::internalError(aResp->res); | 
 | 2982 |                 return; | 
 | 2983 |             } | 
 | 2984 |  | 
 | 2985 |             // skip the empty postcode boots | 
 | 2986 |             if (postcode.empty()) | 
 | 2987 |             { | 
 | 2988 |                 return; | 
 | 2989 |             } | 
 | 2990 |  | 
 | 2991 |             fillPostCodeEntry(aResp, postcode, bootIndex, codeIndex); | 
 | 2992 |  | 
 | 2993 |             aResp->res.jsonValue["Members@odata.count"] = | 
 | 2994 |                 aResp->res.jsonValue["Members"].size(); | 
 | 2995 |         }, | 
| Jonathan Doman | 1512476 | 2021-01-07 17:54:17 -0800 | [diff] [blame] | 2996 |         "xyz.openbmc_project.State.Boot.PostCode0", | 
 | 2997 |         "/xyz/openbmc_project/State/Boot/PostCode0", | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 2998 |         "xyz.openbmc_project.State.Boot.PostCode", "GetPostCodesWithTimeStamp", | 
 | 2999 |         bootIndex); | 
 | 3000 | } | 
 | 3001 |  | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 3002 | static void getPostCodeForBoot(const std::shared_ptr<bmcweb::AsyncResp>& aResp, | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 3003 |                                const uint16_t bootIndex, | 
 | 3004 |                                const uint16_t bootCount, | 
 | 3005 |                                const uint64_t entryCount, const uint64_t skip, | 
 | 3006 |                                const uint64_t top) | 
 | 3007 | { | 
 | 3008 |     crow::connections::systemBus->async_method_call( | 
 | 3009 |         [aResp, bootIndex, bootCount, entryCount, skip, | 
 | 3010 |          top](const boost::system::error_code ec, | 
| Manojkiran Eda | 6c9a279 | 2021-02-27 14:25:04 +0530 | [diff] [blame] | 3011 |               const boost::container::flat_map< | 
 | 3012 |                   uint64_t, std::tuple<uint64_t, std::vector<uint8_t>>>& | 
 | 3013 |                   postcode) { | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 3014 |             if (ec) | 
 | 3015 |             { | 
 | 3016 |                 BMCWEB_LOG_DEBUG << "DBUS POST CODE PostCode response error"; | 
 | 3017 |                 messages::internalError(aResp->res); | 
 | 3018 |                 return; | 
 | 3019 |             } | 
 | 3020 |  | 
 | 3021 |             uint64_t endCount = entryCount; | 
 | 3022 |             if (!postcode.empty()) | 
 | 3023 |             { | 
 | 3024 |                 endCount = entryCount + postcode.size(); | 
 | 3025 |  | 
 | 3026 |                 if ((skip < endCount) && ((top + skip) > entryCount)) | 
 | 3027 |                 { | 
 | 3028 |                     uint64_t thisBootSkip = | 
 | 3029 |                         std::max(skip, entryCount) - entryCount; | 
 | 3030 |                     uint64_t thisBootTop = | 
 | 3031 |                         std::min(top + skip, endCount) - entryCount; | 
 | 3032 |  | 
 | 3033 |                     fillPostCodeEntry(aResp, postcode, bootIndex, 0, | 
 | 3034 |                                       thisBootSkip, thisBootTop); | 
 | 3035 |                 } | 
 | 3036 |                 aResp->res.jsonValue["Members@odata.count"] = endCount; | 
 | 3037 |             } | 
 | 3038 |  | 
 | 3039 |             // continue to previous bootIndex | 
 | 3040 |             if (bootIndex < bootCount) | 
 | 3041 |             { | 
 | 3042 |                 getPostCodeForBoot(aResp, static_cast<uint16_t>(bootIndex + 1), | 
 | 3043 |                                    bootCount, endCount, skip, top); | 
 | 3044 |             } | 
 | 3045 |             else | 
 | 3046 |             { | 
 | 3047 |                 aResp->res.jsonValue["Members@odata.nextLink"] = | 
 | 3048 |                     "/redfish/v1/Systems/system/LogServices/PostCodes/" | 
 | 3049 |                     "Entries?$skip=" + | 
 | 3050 |                     std::to_string(skip + top); | 
 | 3051 |             } | 
 | 3052 |         }, | 
| Jonathan Doman | 1512476 | 2021-01-07 17:54:17 -0800 | [diff] [blame] | 3053 |         "xyz.openbmc_project.State.Boot.PostCode0", | 
 | 3054 |         "/xyz/openbmc_project/State/Boot/PostCode0", | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 3055 |         "xyz.openbmc_project.State.Boot.PostCode", "GetPostCodesWithTimeStamp", | 
 | 3056 |         bootIndex); | 
 | 3057 | } | 
 | 3058 |  | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 3059 | static void | 
 | 3060 |     getCurrentBootNumber(const std::shared_ptr<bmcweb::AsyncResp>& aResp, | 
 | 3061 |                          const uint64_t skip, const uint64_t top) | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 3062 | { | 
 | 3063 |     uint64_t entryCount = 0; | 
 | 3064 |     crow::connections::systemBus->async_method_call( | 
 | 3065 |         [aResp, entryCount, skip, | 
 | 3066 |          top](const boost::system::error_code ec, | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 3067 |               const std::variant<uint16_t>& bootCount) { | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 3068 |             if (ec) | 
 | 3069 |             { | 
 | 3070 |                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec; | 
 | 3071 |                 messages::internalError(aResp->res); | 
 | 3072 |                 return; | 
 | 3073 |             } | 
 | 3074 |             auto pVal = std::get_if<uint16_t>(&bootCount); | 
 | 3075 |             if (pVal) | 
 | 3076 |             { | 
 | 3077 |                 getPostCodeForBoot(aResp, 1, *pVal, entryCount, skip, top); | 
 | 3078 |             } | 
 | 3079 |             else | 
 | 3080 |             { | 
 | 3081 |                 BMCWEB_LOG_DEBUG << "Post code boot index failed."; | 
 | 3082 |             } | 
 | 3083 |         }, | 
| Jonathan Doman | 1512476 | 2021-01-07 17:54:17 -0800 | [diff] [blame] | 3084 |         "xyz.openbmc_project.State.Boot.PostCode0", | 
 | 3085 |         "/xyz/openbmc_project/State/Boot/PostCode0", | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 3086 |         "org.freedesktop.DBus.Properties", "Get", | 
 | 3087 |         "xyz.openbmc_project.State.Boot.PostCode", "CurrentBootCycleCount"); | 
 | 3088 | } | 
 | 3089 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 3090 | inline void requestRoutesPostCodesEntryCollection(App& app) | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 3091 | { | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 3092 |     BMCWEB_ROUTE(app, | 
 | 3093 |                  "/redfish/v1/Systems/system/LogServices/PostCodes/Entries/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 3094 |         .privileges(redfish::privileges::getLogEntryCollection) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 3095 |         .methods(boost::beast::http::verb::get)( | 
 | 3096 |             [](const crow::Request& req, | 
 | 3097 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { | 
 | 3098 |                 asyncResp->res.jsonValue["@odata.type"] = | 
 | 3099 |                     "#LogEntryCollection.LogEntryCollection"; | 
 | 3100 |                 asyncResp->res.jsonValue["@odata.id"] = | 
 | 3101 |                     "/redfish/v1/Systems/system/LogServices/PostCodes/Entries"; | 
 | 3102 |                 asyncResp->res.jsonValue["Name"] = "BIOS POST Code Log Entries"; | 
 | 3103 |                 asyncResp->res.jsonValue["Description"] = | 
 | 3104 |                     "Collection of POST Code Log Entries"; | 
 | 3105 |                 asyncResp->res.jsonValue["Members"] = nlohmann::json::array(); | 
 | 3106 |                 asyncResp->res.jsonValue["Members@odata.count"] = 0; | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 3107 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 3108 |                 uint64_t skip = 0; | 
 | 3109 |                 uint64_t top = maxEntriesPerPage; // Show max entries by default | 
 | 3110 |                 if (!getSkipParam(asyncResp, req, skip)) | 
 | 3111 |                 { | 
 | 3112 |                     return; | 
 | 3113 |                 } | 
 | 3114 |                 if (!getTopParam(asyncResp, req, top)) | 
 | 3115 |                 { | 
 | 3116 |                     return; | 
 | 3117 |                 } | 
 | 3118 |                 getCurrentBootNumber(asyncResp, skip, top); | 
 | 3119 |             }); | 
 | 3120 | } | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 3121 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 3122 | inline void requestRoutesPostCodesEntry(App& app) | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 3123 | { | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 3124 |     BMCWEB_ROUTE( | 
 | 3125 |         app, "/redfish/v1/Systems/system/LogServices/PostCodes/Entries/<str>/") | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame^] | 3126 |         .privileges(redfish::privileges::getLogEntry) | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 3127 |         .methods(boost::beast::http::verb::get)( | 
 | 3128 |             [](const crow::Request&, | 
 | 3129 |                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
 | 3130 |                const std::string& targetID) { | 
 | 3131 |                 size_t bootPos = targetID.find('B'); | 
 | 3132 |                 if (bootPos == std::string::npos) | 
 | 3133 |                 { | 
 | 3134 |                     // Requested ID was not found | 
 | 3135 |                     messages::resourceMissingAtURI(asyncResp->res, targetID); | 
 | 3136 |                     return; | 
 | 3137 |                 } | 
 | 3138 |                 std::string_view bootIndexStr(targetID); | 
 | 3139 |                 bootIndexStr.remove_prefix(bootPos + 1); | 
 | 3140 |                 uint16_t bootIndex = 0; | 
 | 3141 |                 uint64_t codeIndex = 0; | 
 | 3142 |                 size_t dashPos = bootIndexStr.find('-'); | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 3143 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 3144 |                 if (dashPos == std::string::npos) | 
 | 3145 |                 { | 
 | 3146 |                     return; | 
 | 3147 |                 } | 
 | 3148 |                 std::string_view codeIndexStr(bootIndexStr); | 
 | 3149 |                 bootIndexStr.remove_suffix(dashPos); | 
 | 3150 |                 codeIndexStr.remove_prefix(dashPos + 1); | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 3151 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 3152 |                 bootIndex = static_cast<uint16_t>( | 
 | 3153 |                     strtoul(std::string(bootIndexStr).c_str(), nullptr, 0)); | 
 | 3154 |                 codeIndex = | 
 | 3155 |                     strtoul(std::string(codeIndexStr).c_str(), nullptr, 0); | 
 | 3156 |                 if (bootIndex == 0 || codeIndex == 0) | 
 | 3157 |                 { | 
 | 3158 |                     BMCWEB_LOG_DEBUG << "Get Post Code invalid entry string " | 
 | 3159 |                                      << targetID; | 
 | 3160 |                 } | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 3161 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 3162 |                 asyncResp->res.jsonValue["@odata.type"] = | 
 | 3163 |                     "#LogEntry.v1_4_0.LogEntry"; | 
 | 3164 |                 asyncResp->res.jsonValue["@odata.id"] = | 
 | 3165 |                     "/redfish/v1/Systems/system/LogServices/PostCodes/" | 
 | 3166 |                     "Entries"; | 
 | 3167 |                 asyncResp->res.jsonValue["Name"] = "BIOS POST Code Log Entries"; | 
 | 3168 |                 asyncResp->res.jsonValue["Description"] = | 
 | 3169 |                     "Collection of POST Code Log Entries"; | 
 | 3170 |                 asyncResp->res.jsonValue["Members"] = nlohmann::json::array(); | 
 | 3171 |                 asyncResp->res.jsonValue["Members@odata.count"] = 0; | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 3172 |  | 
| John Edward Broadbent | 7e860f1 | 2021-04-08 15:57:16 -0700 | [diff] [blame] | 3173 |                 getPostCodeForEntry(asyncResp, bootIndex, codeIndex); | 
 | 3174 |             }); | 
 | 3175 | } | 
| ZhikuiRen | a3316fc | 2020-01-29 14:58:08 -0800 | [diff] [blame] | 3176 |  | 
| Ed Tanous | 1da66f7 | 2018-07-27 16:13:37 -0700 | [diff] [blame] | 3177 | } // namespace redfish |