| John Wedig | 2098dab | 2021-09-14 13:56:28 -0700 | [diff] [blame] | 1 |  | 
|  | 2 | #include "estoraged.hpp" | 
| John Wedig | d32b966 | 2022-04-13 18:12:25 -0700 | [diff] [blame] | 3 | #include "getConfig.hpp" | 
|  | 4 | #include "util.hpp" | 
| John Wedig | 2098dab | 2021-09-14 13:56:28 -0700 | [diff] [blame] | 5 |  | 
| John Wedig | d32b966 | 2022-04-13 18:12:25 -0700 | [diff] [blame] | 6 | #include <boost/asio/deadline_timer.hpp> | 
| John Wedig | 67a4744 | 2022-04-05 17:21:29 -0700 | [diff] [blame] | 7 | #include <boost/asio/io_context.hpp> | 
| John Wedig | d32b966 | 2022-04-13 18:12:25 -0700 | [diff] [blame] | 8 | #include <boost/asio/post.hpp> | 
|  | 9 | #include <boost/container/flat_map.hpp> | 
|  | 10 | #include <boost/container/throw_exception.hpp> | 
| John Edward Broadbent | 4e13b0a | 2021-11-15 15:21:59 -0800 | [diff] [blame] | 11 | #include <phosphor-logging/lg2.hpp> | 
| John Wedig | 67a4744 | 2022-04-05 17:21:29 -0700 | [diff] [blame] | 12 | #include <sdbusplus/asio/connection.hpp> | 
|  | 13 | #include <sdbusplus/asio/object_server.hpp> | 
| John Wedig | 2098dab | 2021-09-14 13:56:28 -0700 | [diff] [blame] | 14 | #include <sdbusplus/bus.hpp> | 
| John Wedig | d32b966 | 2022-04-13 18:12:25 -0700 | [diff] [blame] | 15 | #include <sdbusplus/bus/match.hpp> | 
| John Edward Broadbent | e35e736 | 2022-03-22 16:14:24 -0700 | [diff] [blame] | 16 | #include <util.hpp> | 
| John Wedig | 2098dab | 2021-09-14 13:56:28 -0700 | [diff] [blame] | 17 |  | 
| John Wedig | d32b966 | 2022-04-13 18:12:25 -0700 | [diff] [blame] | 18 | #include <cstdlib> | 
| John Wedig | 2098dab | 2021-09-14 13:56:28 -0700 | [diff] [blame] | 19 | #include <filesystem> | 
|  | 20 | #include <iostream> | 
| John Wedig | 67a4744 | 2022-04-05 17:21:29 -0700 | [diff] [blame] | 21 | #include <memory> | 
| John Wedig | 2098dab | 2021-09-14 13:56:28 -0700 | [diff] [blame] | 22 | #include <string> | 
|  | 23 |  | 
| John Wedig | d32b966 | 2022-04-13 18:12:25 -0700 | [diff] [blame] | 24 | /* | 
|  | 25 | * Get the configuration objects from Entity Manager and create new D-Bus | 
|  | 26 | * objects for each one. This function can be called multiple times, in case | 
|  | 27 | * new configuration objects show up later. | 
|  | 28 | * | 
|  | 29 | * Note: Currently, eStoraged can only support 1 eMMC device. | 
|  | 30 | * Additional changes will be needed to support more than 1 eMMC, or to support | 
|  | 31 | * more types of storage devices. | 
|  | 32 | */ | 
|  | 33 | void createStorageObjects( | 
|  | 34 | boost::asio::io_context& io, sdbusplus::asio::object_server& objectServer, | 
|  | 35 | boost::container::flat_map< | 
|  | 36 | std::string, std::unique_ptr<estoraged::EStoraged>>& storageObjects, | 
|  | 37 | std::shared_ptr<sdbusplus::asio::connection>& dbusConnection) | 
| John Wedig | 2098dab | 2021-09-14 13:56:28 -0700 | [diff] [blame] | 38 | { | 
| John Wedig | d32b966 | 2022-04-13 18:12:25 -0700 | [diff] [blame] | 39 | auto getter = std::make_shared<estoraged::GetStorageConfiguration>( | 
|  | 40 | dbusConnection, | 
|  | 41 | [&io, &objectServer, &storageObjects]( | 
|  | 42 | const estoraged::ManagedStorageType& storageConfigurations) { | 
|  | 43 | size_t numConfigObj = storageConfigurations.size(); | 
|  | 44 | if (numConfigObj > 1) | 
|  | 45 | { | 
|  | 46 | lg2::error( | 
|  | 47 | "eStoraged can only manage 1 eMMC device; found {NUM}", | 
|  | 48 | "NUM", numConfigObj, "REDFISH_MESSAGE_ID", | 
|  | 49 | std::string("OpenBMC.0.1.CreateStorageObjectsFail")); | 
|  | 50 | return; | 
|  | 51 | } | 
|  | 52 |  | 
|  | 53 | for (const std::pair<sdbusplus::message::object_path, | 
|  | 54 | estoraged::StorageData>& storage : | 
|  | 55 | storageConfigurations) | 
|  | 56 | { | 
|  | 57 | const std::string& path = storage.first.str; | 
|  | 58 |  | 
|  | 59 | if (storageObjects.find(path) != storageObjects.end()) | 
|  | 60 | { | 
|  | 61 | /* | 
|  | 62 | * We've already created this object, or at least | 
|  | 63 | * attempted to. | 
|  | 64 | */ | 
|  | 65 | continue; | 
|  | 66 | } | 
|  | 67 |  | 
|  | 68 | /* Get the properties from the config object. */ | 
|  | 69 | const estoraged::StorageData& data = storage.second; | 
|  | 70 |  | 
|  | 71 | /* Look for the device file. */ | 
|  | 72 | const std::filesystem::path blockDevDir{"/sys/block"}; | 
|  | 73 | std::filesystem::path deviceFile, sysfsDir; | 
|  | 74 | std::string luksName; | 
|  | 75 | bool found = estoraged::util::findDevice( | 
|  | 76 | data, blockDevDir, deviceFile, sysfsDir, luksName); | 
|  | 77 | if (!found) | 
|  | 78 | { | 
|  | 79 | lg2::error( | 
|  | 80 | "Device not found for path {PATH}", "PATH", path, | 
|  | 81 | "REDFISH_MESSAGE_ID", | 
|  | 82 | std::string("OpenBMC.0.1.CreateStorageObjectsFail")); | 
|  | 83 | /* | 
|  | 84 | * Set a NULL pointer as a placeholder, so that we don't | 
|  | 85 | * try and fail again later. | 
|  | 86 | */ | 
|  | 87 | storageObjects[path] = nullptr; | 
|  | 88 | continue; | 
|  | 89 | } | 
|  | 90 |  | 
|  | 91 | uint64_t size = | 
|  | 92 | estoraged::util::findSizeOfBlockDevice(deviceFile); | 
|  | 93 |  | 
|  | 94 | uint8_t lifeleft = | 
|  | 95 | estoraged::util::findPredictedMediaLifeLeftPercent( | 
|  | 96 | sysfsDir); | 
|  | 97 | /* Create the storage object. */ | 
|  | 98 | storageObjects[path] = std::make_unique<estoraged::EStoraged>( | 
| John Wedig | 6c0d8ce | 2022-04-22 14:00:43 -0700 | [diff] [blame^] | 99 | objectServer, path, deviceFile, luksName, size, lifeleft); | 
| John Wedig | d32b966 | 2022-04-13 18:12:25 -0700 | [diff] [blame] | 100 | lg2::info("Created eStoraged object for path {PATH}", "PATH", | 
|  | 101 | path, "REDFISH_MESSAGE_ID", | 
|  | 102 | std::string("OpenBMC.0.1.CreateStorageObjects")); | 
|  | 103 | } | 
|  | 104 | }); | 
|  | 105 | getter->getConfiguration(); | 
| John Wedig | 2098dab | 2021-09-14 13:56:28 -0700 | [diff] [blame] | 106 | } | 
|  | 107 |  | 
| John Wedig | d32b966 | 2022-04-13 18:12:25 -0700 | [diff] [blame] | 108 | int main(void) | 
| John Wedig | 2098dab | 2021-09-14 13:56:28 -0700 | [diff] [blame] | 109 | { | 
| Ed Tanous | 82897c3 | 2022-02-21 14:11:59 -0800 | [diff] [blame] | 110 | try | 
| John Wedig | 2098dab | 2021-09-14 13:56:28 -0700 | [diff] [blame] | 111 | { | 
| John Wedig | 67a4744 | 2022-04-05 17:21:29 -0700 | [diff] [blame] | 112 | // setup connection to dbus | 
|  | 113 | boost::asio::io_context io; | 
|  | 114 | auto conn = std::make_shared<sdbusplus::asio::connection>(io); | 
|  | 115 | // request D-Bus server name. | 
| John Wedig | d32b966 | 2022-04-13 18:12:25 -0700 | [diff] [blame] | 116 | conn->request_name("xyz.openbmc_project.eStoraged"); | 
|  | 117 | sdbusplus::asio::object_server server(conn); | 
|  | 118 | boost::container::flat_map<std::string, | 
|  | 119 | std::unique_ptr<estoraged::EStoraged>> | 
|  | 120 | storageObjects; | 
| Ed Tanous | 82897c3 | 2022-02-21 14:11:59 -0800 | [diff] [blame] | 121 |  | 
| John Wedig | d32b966 | 2022-04-13 18:12:25 -0700 | [diff] [blame] | 122 | boost::asio::post(io, [&]() { | 
|  | 123 | createStorageObjects(io, server, storageObjects, conn); | 
|  | 124 | }); | 
|  | 125 |  | 
|  | 126 | /* | 
|  | 127 | * Set up an event handler to process any new configuration objects | 
|  | 128 | * that show up later. | 
|  | 129 | */ | 
|  | 130 | boost::asio::deadline_timer filterTimer(io); | 
|  | 131 | std::function<void(sdbusplus::message::message&)> eventHandler = | 
|  | 132 | [&](sdbusplus::message::message& message) { | 
|  | 133 | if (message.is_method_error()) | 
|  | 134 | { | 
|  | 135 | lg2::error("eventHandler callback method error"); | 
|  | 136 | return; | 
|  | 137 | } | 
|  | 138 | /* | 
|  | 139 | * This implicitly cancels the timer, if it's already pending. | 
|  | 140 | * If there's a burst of events within a short period, we want | 
|  | 141 | * to handle them all at once. So, we will wait this long for no | 
|  | 142 | * more events to occur, before processing them. | 
|  | 143 | */ | 
|  | 144 | filterTimer.expires_from_now(boost::posix_time::seconds(1)); | 
|  | 145 |  | 
|  | 146 | filterTimer.async_wait( | 
|  | 147 | [&](const boost::system::error_code& ec) { | 
|  | 148 | if (ec == boost::asio::error::operation_aborted) | 
|  | 149 | { | 
|  | 150 | /* we were canceled */ | 
|  | 151 | return; | 
|  | 152 | } | 
|  | 153 | if (ec) | 
|  | 154 | { | 
|  | 155 | lg2::error("timer error"); | 
|  | 156 | return; | 
|  | 157 | } | 
|  | 158 | createStorageObjects(io, server, storageObjects, conn); | 
|  | 159 | }); | 
|  | 160 | }; | 
|  | 161 |  | 
|  | 162 | auto match = std::make_unique<sdbusplus::bus::match::match>( | 
|  | 163 | static_cast<sdbusplus::bus::bus&>(*conn), | 
|  | 164 | "type='signal',member='PropertiesChanged',path_namespace='" + | 
|  | 165 | std::string("/xyz/openbmc_project/inventory") + | 
|  | 166 | "',arg0namespace='" + estoraged::emmcConfigInterface + "'", | 
|  | 167 | eventHandler); | 
|  | 168 |  | 
| Ed Tanous | 82897c3 | 2022-02-21 14:11:59 -0800 | [diff] [blame] | 169 | lg2::info("Storage management service is running", "REDFISH_MESSAGE_ID", | 
|  | 170 | std::string("OpenBMC.1.0.ServiceStarted")); | 
|  | 171 |  | 
| John Wedig | 67a4744 | 2022-04-05 17:21:29 -0700 | [diff] [blame] | 172 | io.run(); | 
|  | 173 | return 0; | 
| John Wedig | 2098dab | 2021-09-14 13:56:28 -0700 | [diff] [blame] | 174 | } | 
| Ed Tanous | 82897c3 | 2022-02-21 14:11:59 -0800 | [diff] [blame] | 175 | catch (const std::exception& e) | 
| John Wedig | 2098dab | 2021-09-14 13:56:28 -0700 | [diff] [blame] | 176 | { | 
| Ed Tanous | 82897c3 | 2022-02-21 14:11:59 -0800 | [diff] [blame] | 177 | lg2::error(e.what(), "REDFISH_MESSAGE_ID", | 
|  | 178 | std::string("OpenBMC.1.0.ServiceException")); | 
| John Wedig | 2098dab | 2021-09-14 13:56:28 -0700 | [diff] [blame] | 179 |  | 
| Ed Tanous | 82897c3 | 2022-02-21 14:11:59 -0800 | [diff] [blame] | 180 | return 2; | 
|  | 181 | } | 
| John Wedig | 2098dab | 2021-09-14 13:56:28 -0700 | [diff] [blame] | 182 | return 1; | 
|  | 183 | } |