main.cpp (fa5cb6f7186851db5b3a77bfb07452d440827eee) | main.cpp (d32b966771e03788af7b912d4cf701d98c391097) |
---|---|
1 2#include "estoraged.hpp" | 1 2#include "estoraged.hpp" |
3#include "getConfig.hpp" 4#include "util.hpp" |
|
3 | 5 |
4#include <unistd.h> 5 | 6#include <boost/asio/deadline_timer.hpp> |
6#include <boost/asio/io_context.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> |
|
7#include <phosphor-logging/lg2.hpp> 8#include <sdbusplus/asio/connection.hpp> 9#include <sdbusplus/asio/object_server.hpp> 10#include <sdbusplus/bus.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> |
|
11#include <util.hpp> 12 | 16#include <util.hpp> 17 |
18#include <cstdlib> |
|
13#include <filesystem> 14#include <iostream> 15#include <memory> 16#include <string> 17 | 19#include <filesystem> 20#include <iostream> 21#include <memory> 22#include <string> 23 |
18static void usage(std::string_view name) | 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 */ 33void 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) |
19{ | 38{ |
20 std::cerr 21 << "Usage: " << name 22 << "eStorageD service on the BMC\n\n" 23 " -b <blockDevice> The phyical encrypted device\n" 24 " If omitted, default is /dev/mmcblk0.\n" 25 " -c <containerName> The LUKS container name to be created\n" 26 " If omitted, default is luks-<devName>" 27 " -s <sysfsDevice> The interface to kernel data\n" 28 " structures dealing with this drive.\n" 29 " If omitted, default is\n" 30 " /sys/block/mmcblk0/device/\n"; | 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>( 99 objectServer, deviceFile, luksName, size, lifeleft); 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(); |
31} 32 | 106} 107 |
33int main(int argc, char** argv) | 108int main(void) |
34{ | 109{ |
35 std::string physicalBlockDev = "/dev/mmcblk0"; 36 std::string sysfsDev = "/sys/block/mmcblk0/device"; 37 std::string containerBlockDev; 38 int opt = 0; 39 while ((opt = getopt(argc, argv, "b:c:s:")) != -1) 40 { 41 switch (opt) 42 { 43 case 'b': 44 physicalBlockDev = optarg; 45 break; 46 case 'c': 47 containerBlockDev = optarg; 48 break; 49 case 's': 50 sysfsDev = optarg; 51 break; 52 default: 53 usage(*argv); 54 exit(EXIT_FAILURE); 55 } 56 } | |
57 try 58 { | 110 try 111 { |
59 /* Get the filename of the device (without "/dev/"). */ 60 std::string deviceName = 61 std::filesystem::path(physicalBlockDev).filename().string(); 62 /* If containerName arg wasn't provided, create one based on deviceName. 63 */ 64 if (containerBlockDev.empty()) 65 { 66 containerBlockDev = "luks-" + deviceName; 67 } 68 | |
69 // setup connection to dbus 70 boost::asio::io_context io; 71 auto conn = std::make_shared<sdbusplus::asio::connection>(io); 72 // request D-Bus server name. | 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. |
73 std::string busName = "xyz.openbmc_project.eStoraged"; 74 conn->request_name(busName.c_str()); 75 auto server = sdbusplus::asio::object_server(conn); | 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; |
76 | 121 |
77 estoraged::EStoraged esObject{ 78 server, physicalBlockDev, containerBlockDev, 79 estoraged::util::findSizeOfBlockDevice(physicalBlockDev), 80 estoraged::util::findPredictedMediaLifeLeftPercent(sysfsDev)}; | 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 |
81 lg2::info("Storage management service is running", "REDFISH_MESSAGE_ID", 82 std::string("OpenBMC.1.0.ServiceStarted")); 83 84 io.run(); 85 return 0; 86 } 87 catch (const std::exception& e) 88 { 89 lg2::error(e.what(), "REDFISH_MESSAGE_ID", 90 std::string("OpenBMC.1.0.ServiceException")); 91 92 return 2; 93 } 94 return 1; 95} | 169 lg2::info("Storage management service is running", "REDFISH_MESSAGE_ID", 170 std::string("OpenBMC.1.0.ServiceStarted")); 171 172 io.run(); 173 return 0; 174 } 175 catch (const std::exception& e) 176 { 177 lg2::error(e.what(), "REDFISH_MESSAGE_ID", 178 std::string("OpenBMC.1.0.ServiceException")); 179 180 return 2; 181 } 182 return 1; 183} |