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}