12098dabeSJohn Wedig
22098dabeSJohn Wedig #include "estoraged.hpp"
3d32b9667SJohn Wedig #include "getConfig.hpp"
4d32b9667SJohn Wedig #include "util.hpp"
52098dabeSJohn Wedig
6d32b9667SJohn Wedig #include <boost/asio/deadline_timer.hpp>
767a47446SJohn Wedig #include <boost/asio/io_context.hpp>
8d32b9667SJohn Wedig #include <boost/asio/post.hpp>
9d32b9667SJohn Wedig #include <boost/container/flat_map.hpp>
10d32b9667SJohn Wedig #include <boost/container/throw_exception.hpp>
114e13b0a1SJohn Edward Broadbent #include <phosphor-logging/lg2.hpp>
1267a47446SJohn Wedig #include <sdbusplus/asio/connection.hpp>
1367a47446SJohn Wedig #include <sdbusplus/asio/object_server.hpp>
142098dabeSJohn Wedig #include <sdbusplus/bus.hpp>
15d32b9667SJohn Wedig #include <sdbusplus/bus/match.hpp>
16e35e7361SJohn Edward Broadbent #include <util.hpp>
172098dabeSJohn Wedig
18d32b9667SJohn Wedig #include <cstdlib>
192098dabeSJohn Wedig #include <filesystem>
202098dabeSJohn Wedig #include <iostream>
2167a47446SJohn Wedig #include <memory>
22043af59fSTom Tung #include <optional>
232098dabeSJohn Wedig #include <string>
242098dabeSJohn Wedig
25d32b9667SJohn Wedig /*
26d32b9667SJohn Wedig * Get the configuration objects from Entity Manager and create new D-Bus
27d32b9667SJohn Wedig * objects for each one. This function can be called multiple times, in case
28d32b9667SJohn Wedig * new configuration objects show up later.
29d32b9667SJohn Wedig *
30d32b9667SJohn Wedig * Note: Currently, eStoraged can only support 1 eMMC device.
31d32b9667SJohn Wedig * Additional changes will be needed to support more than 1 eMMC, or to support
32d32b9667SJohn Wedig * more types of storage devices.
33d32b9667SJohn Wedig */
createStorageObjects(sdbusplus::asio::object_server & objectServer,boost::container::flat_map<std::string,std::unique_ptr<estoraged::EStoraged>> & storageObjects,std::shared_ptr<sdbusplus::asio::connection> & dbusConnection)34d32b9667SJohn Wedig void createStorageObjects(
3561cf4260SJohn Wedig sdbusplus::asio::object_server& objectServer,
36d32b9667SJohn Wedig boost::container::flat_map<
37d32b9667SJohn Wedig std::string, std::unique_ptr<estoraged::EStoraged>>& storageObjects,
38d32b9667SJohn Wedig std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
392098dabeSJohn Wedig {
40d32b9667SJohn Wedig auto getter = std::make_shared<estoraged::GetStorageConfiguration>(
41d32b9667SJohn Wedig dbusConnection,
4261cf4260SJohn Wedig [&objectServer, &storageObjects](
43d32b9667SJohn Wedig const estoraged::ManagedStorageType& storageConfigurations) {
44d32b9667SJohn Wedig size_t numConfigObj = storageConfigurations.size();
45d32b9667SJohn Wedig if (numConfigObj > 1)
46d32b9667SJohn Wedig {
47*15b63e12SPatrick Williams lg2::error(
48*15b63e12SPatrick Williams "eStoraged can only manage 1 eMMC device; found {NUM}",
49d32b9667SJohn Wedig "NUM", numConfigObj, "REDFISH_MESSAGE_ID",
50d32b9667SJohn Wedig std::string("OpenBMC.0.1.CreateStorageObjectsFail"));
51d32b9667SJohn Wedig return;
522098dabeSJohn Wedig }
532098dabeSJohn Wedig
54d32b9667SJohn Wedig for (const std::pair<sdbusplus::message::object_path,
55d32b9667SJohn Wedig estoraged::StorageData>& storage :
56d32b9667SJohn Wedig storageConfigurations)
572098dabeSJohn Wedig {
58d32b9667SJohn Wedig const std::string& path = storage.first.str;
59d32b9667SJohn Wedig
60d32b9667SJohn Wedig if (storageObjects.find(path) != storageObjects.end())
612098dabeSJohn Wedig {
62d32b9667SJohn Wedig /*
63d32b9667SJohn Wedig * We've already created this object, or at least
64d32b9667SJohn Wedig * attempted to.
65d32b9667SJohn Wedig */
66d32b9667SJohn Wedig continue;
672098dabeSJohn Wedig }
68d32b9667SJohn Wedig
69d32b9667SJohn Wedig /* Get the properties from the config object. */
70d32b9667SJohn Wedig const estoraged::StorageData& data = storage.second;
71d32b9667SJohn Wedig
72d32b9667SJohn Wedig /* Look for the device file. */
73d32b9667SJohn Wedig const std::filesystem::path blockDevDir{"/sys/block"};
74*15b63e12SPatrick Williams auto deviceInfo =
75*15b63e12SPatrick Williams estoraged::util::findDevice(data, blockDevDir);
76043af59fSTom Tung if (!deviceInfo)
77d32b9667SJohn Wedig {
78*15b63e12SPatrick Williams lg2::error(
79*15b63e12SPatrick Williams "Device not found for path {PATH}", "PATH", path,
80d32b9667SJohn Wedig "REDFISH_MESSAGE_ID",
81d32b9667SJohn Wedig std::string("OpenBMC.0.1.CreateStorageObjectsFail"));
82d32b9667SJohn Wedig /*
83d32b9667SJohn Wedig * Set a NULL pointer as a placeholder, so that we don't
84d32b9667SJohn Wedig * try and fail again later.
85d32b9667SJohn Wedig */
86d32b9667SJohn Wedig storageObjects[path] = nullptr;
87d32b9667SJohn Wedig continue;
882098dabeSJohn Wedig }
89d32b9667SJohn Wedig
90043af59fSTom Tung std::filesystem::path deviceFile =
91043af59fSTom Tung std::move(deviceInfo->deviceFile);
92*15b63e12SPatrick Williams std::filesystem::path sysfsDir =
93*15b63e12SPatrick Williams std::move(deviceInfo->sysfsDir);
94043af59fSTom Tung std::string luksName = std::move(deviceInfo->luksName);
95043af59fSTom Tung std::string locationCode = std::move(deviceInfo->locationCode);
96043af59fSTom Tung uint64_t eraseMaxGeometry = deviceInfo->eraseMaxGeometry;
97043af59fSTom Tung uint64_t eraseMinGeometry = deviceInfo->eraseMinGeometry;
98043af59fSTom Tung
99*15b63e12SPatrick Williams uint64_t size =
100*15b63e12SPatrick Williams estoraged::util::findSizeOfBlockDevice(deviceFile);
101d32b9667SJohn Wedig
102d32b9667SJohn Wedig uint8_t lifeleft =
103*15b63e12SPatrick Williams estoraged::util::findPredictedMediaLifeLeftPercent(
104*15b63e12SPatrick Williams sysfsDir);
105*15b63e12SPatrick Williams std::string partNumber =
106*15b63e12SPatrick Williams estoraged::util::getPartNumber(sysfsDir);
107b4838308SJohn Wedig std::string serialNumber =
108b4838308SJohn Wedig estoraged::util::getSerialNumber(sysfsDir);
109c0d66eb7SJohn Wedig const std::string& driveType = deviceInfo->driveType;
110c0d66eb7SJohn Wedig const std::string& driveProtocol = deviceInfo->driveProtocol;
111d32b9667SJohn Wedig /* Create the storage object. */
112d32b9667SJohn Wedig storageObjects[path] = std::make_unique<estoraged::EStoraged>(
113b4838308SJohn Wedig objectServer, path, deviceFile, luksName, size, lifeleft,
114043af59fSTom Tung partNumber, serialNumber, locationCode, eraseMaxGeometry,
115c0d66eb7SJohn Wedig eraseMinGeometry, driveType, driveProtocol);
116*15b63e12SPatrick Williams lg2::info("Created eStoraged object for path {PATH}", "PATH",
117*15b63e12SPatrick Williams path, "REDFISH_MESSAGE_ID",
118d32b9667SJohn Wedig std::string("OpenBMC.0.1.CreateStorageObjects"));
119d32b9667SJohn Wedig }
120d32b9667SJohn Wedig });
121d32b9667SJohn Wedig getter->getConfiguration();
122d32b9667SJohn Wedig }
123d32b9667SJohn Wedig
main(void)124d32b9667SJohn Wedig int main(void)
125d32b9667SJohn Wedig {
12682897c35SEd Tanous try
12782897c35SEd Tanous {
12867a47446SJohn Wedig // setup connection to dbus
12967a47446SJohn Wedig boost::asio::io_context io;
13067a47446SJohn Wedig auto conn = std::make_shared<sdbusplus::asio::connection>(io);
13167a47446SJohn Wedig // request D-Bus server name.
132d32b9667SJohn Wedig conn->request_name("xyz.openbmc_project.eStoraged");
133d32b9667SJohn Wedig sdbusplus::asio::object_server server(conn);
134d32b9667SJohn Wedig boost::container::flat_map<std::string,
135d32b9667SJohn Wedig std::unique_ptr<estoraged::EStoraged>>
136d32b9667SJohn Wedig storageObjects;
1372098dabeSJohn Wedig
138*15b63e12SPatrick Williams boost::asio::post(io, [&]() {
139*15b63e12SPatrick Williams createStorageObjects(server, storageObjects, conn);
140*15b63e12SPatrick Williams });
141d32b9667SJohn Wedig
142d32b9667SJohn Wedig /*
143d32b9667SJohn Wedig * Set up an event handler to process any new configuration objects
144d32b9667SJohn Wedig * that show up later.
145d32b9667SJohn Wedig */
146d32b9667SJohn Wedig boost::asio::deadline_timer filterTimer(io);
147e3ef765dSPatrick Williams std::function<void(sdbusplus::message_t&)> eventHandler =
148e3ef765dSPatrick Williams [&](sdbusplus::message_t& message) {
149d32b9667SJohn Wedig if (message.is_method_error())
150d32b9667SJohn Wedig {
151d32b9667SJohn Wedig lg2::error("eventHandler callback method error");
152d32b9667SJohn Wedig return;
153d32b9667SJohn Wedig }
154d32b9667SJohn Wedig /*
155d32b9667SJohn Wedig * This implicitly cancels the timer, if it's already pending.
156d32b9667SJohn Wedig * If there's a burst of events within a short period, we want
157d32b9667SJohn Wedig * to handle them all at once. So, we will wait this long for no
158d32b9667SJohn Wedig * more events to occur, before processing them.
159d32b9667SJohn Wedig */
160d32b9667SJohn Wedig filterTimer.expires_from_now(boost::posix_time::seconds(1));
161d32b9667SJohn Wedig
162*15b63e12SPatrick Williams filterTimer.async_wait(
163*15b63e12SPatrick Williams [&](const boost::system::error_code& ec) {
164d32b9667SJohn Wedig if (ec == boost::asio::error::operation_aborted)
165d32b9667SJohn Wedig {
166d32b9667SJohn Wedig /* we were canceled */
167d32b9667SJohn Wedig return;
168d32b9667SJohn Wedig }
169d32b9667SJohn Wedig if (ec)
170d32b9667SJohn Wedig {
171d32b9667SJohn Wedig lg2::error("timer error");
172d32b9667SJohn Wedig return;
173d32b9667SJohn Wedig }
17461cf4260SJohn Wedig createStorageObjects(server, storageObjects, conn);
175d32b9667SJohn Wedig });
176d32b9667SJohn Wedig };
177d32b9667SJohn Wedig
178e3ef765dSPatrick Williams auto match = std::make_unique<sdbusplus::bus::match_t>(
179e3ef765dSPatrick Williams static_cast<sdbusplus::bus_t&>(*conn),
180d32b9667SJohn Wedig "type='signal',member='PropertiesChanged',path_namespace='" +
181d32b9667SJohn Wedig std::string("/xyz/openbmc_project/inventory") +
182d32b9667SJohn Wedig "',arg0namespace='" + estoraged::emmcConfigInterface + "'",
183d32b9667SJohn Wedig eventHandler);
184d32b9667SJohn Wedig
1854e13b0a1SJohn Edward Broadbent lg2::info("Storage management service is running", "REDFISH_MESSAGE_ID",
186e6ffe704SJohn Edward Broadbent std::string("OpenBMC.1.0.ServiceStarted"));
1872098dabeSJohn Wedig
18867a47446SJohn Wedig io.run();
18967a47446SJohn Wedig return 0;
19082897c35SEd Tanous }
19182897c35SEd Tanous catch (const std::exception& e)
19282897c35SEd Tanous {
19382897c35SEd Tanous lg2::error(e.what(), "REDFISH_MESSAGE_ID",
19482897c35SEd Tanous std::string("OpenBMC.1.0.ServiceException"));
1952098dabeSJohn Wedig
19682897c35SEd Tanous return 2;
19782897c35SEd Tanous }
1982098dabeSJohn Wedig return 1;
1992098dabeSJohn Wedig }
200