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