xref: /openbmc/estoraged/src/main.cpp (revision c0d66eb7)
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         {
4704c28fadSPatrick Williams             lg2::error("eStoraged can only manage 1 eMMC device; found {NUM}",
48d32b9667SJohn Wedig                        "NUM", numConfigObj, "REDFISH_MESSAGE_ID",
49d32b9667SJohn Wedig                        std::string("OpenBMC.0.1.CreateStorageObjectsFail"));
50d32b9667SJohn Wedig             return;
512098dabeSJohn Wedig         }
522098dabeSJohn Wedig 
53d32b9667SJohn Wedig         for (const std::pair<sdbusplus::message::object_path,
54d32b9667SJohn Wedig                              estoraged::StorageData>& storage :
55d32b9667SJohn Wedig              storageConfigurations)
562098dabeSJohn Wedig         {
57d32b9667SJohn Wedig             const std::string& path = storage.first.str;
58d32b9667SJohn Wedig 
59d32b9667SJohn Wedig             if (storageObjects.find(path) != storageObjects.end())
602098dabeSJohn Wedig             {
61d32b9667SJohn Wedig                 /*
62d32b9667SJohn Wedig                  * We've already created this object, or at least
63d32b9667SJohn Wedig                  * attempted to.
64d32b9667SJohn Wedig                  */
65d32b9667SJohn Wedig                 continue;
662098dabeSJohn Wedig             }
67d32b9667SJohn Wedig 
68d32b9667SJohn Wedig             /* Get the properties from the config object. */
69d32b9667SJohn Wedig             const estoraged::StorageData& data = storage.second;
70d32b9667SJohn Wedig 
71d32b9667SJohn Wedig             /* Look for the device file. */
72d32b9667SJohn Wedig             const std::filesystem::path blockDevDir{"/sys/block"};
73043af59fSTom Tung             auto deviceInfo = estoraged::util::findDevice(data, blockDevDir);
74043af59fSTom Tung             if (!deviceInfo)
75d32b9667SJohn Wedig             {
7604c28fadSPatrick Williams                 lg2::error("Device not found for path {PATH}", "PATH", path,
77d32b9667SJohn Wedig                            "REDFISH_MESSAGE_ID",
78d32b9667SJohn Wedig                            std::string("OpenBMC.0.1.CreateStorageObjectsFail"));
79d32b9667SJohn Wedig                 /*
80d32b9667SJohn Wedig                  * Set a NULL pointer as a placeholder, so that we don't
81d32b9667SJohn Wedig                  * try and fail again later.
82d32b9667SJohn Wedig                  */
83d32b9667SJohn Wedig                 storageObjects[path] = nullptr;
84d32b9667SJohn Wedig                 continue;
852098dabeSJohn Wedig             }
86d32b9667SJohn Wedig 
87043af59fSTom Tung             std::filesystem::path deviceFile =
88043af59fSTom Tung                 std::move(deviceInfo->deviceFile);
89043af59fSTom Tung             std::filesystem::path sysfsDir = std::move(deviceInfo->sysfsDir);
90043af59fSTom Tung             std::string luksName = std::move(deviceInfo->luksName);
91043af59fSTom Tung             std::string locationCode = std::move(deviceInfo->locationCode);
92043af59fSTom Tung             uint64_t eraseMaxGeometry = deviceInfo->eraseMaxGeometry;
93043af59fSTom Tung             uint64_t eraseMinGeometry = deviceInfo->eraseMinGeometry;
94043af59fSTom Tung 
9504c28fadSPatrick Williams             uint64_t size = estoraged::util::findSizeOfBlockDevice(deviceFile);
96d32b9667SJohn Wedig 
97d32b9667SJohn Wedig             uint8_t lifeleft =
9804c28fadSPatrick Williams                 estoraged::util::findPredictedMediaLifeLeftPercent(sysfsDir);
9904c28fadSPatrick Williams             std::string partNumber = estoraged::util::getPartNumber(sysfsDir);
100b4838308SJohn Wedig             std::string serialNumber =
101b4838308SJohn Wedig                 estoraged::util::getSerialNumber(sysfsDir);
102*c0d66eb7SJohn Wedig             const std::string& driveType = deviceInfo->driveType;
103*c0d66eb7SJohn Wedig             const std::string& driveProtocol = deviceInfo->driveProtocol;
104d32b9667SJohn Wedig             /* Create the storage object. */
105d32b9667SJohn Wedig             storageObjects[path] = std::make_unique<estoraged::EStoraged>(
106b4838308SJohn Wedig                 objectServer, path, deviceFile, luksName, size, lifeleft,
107043af59fSTom Tung                 partNumber, serialNumber, locationCode, eraseMaxGeometry,
108*c0d66eb7SJohn Wedig                 eraseMinGeometry, driveType, driveProtocol);
10904c28fadSPatrick Williams             lg2::info("Created eStoraged object for path {PATH}", "PATH", path,
11004c28fadSPatrick Williams                       "REDFISH_MESSAGE_ID",
111d32b9667SJohn Wedig                       std::string("OpenBMC.0.1.CreateStorageObjects"));
112d32b9667SJohn Wedig         }
113d32b9667SJohn Wedig     });
114d32b9667SJohn Wedig     getter->getConfiguration();
115d32b9667SJohn Wedig }
116d32b9667SJohn Wedig 
main(void)117d32b9667SJohn Wedig int main(void)
118d32b9667SJohn Wedig {
11982897c35SEd Tanous     try
12082897c35SEd Tanous     {
12167a47446SJohn Wedig         // setup connection to dbus
12267a47446SJohn Wedig         boost::asio::io_context io;
12367a47446SJohn Wedig         auto conn = std::make_shared<sdbusplus::asio::connection>(io);
12467a47446SJohn Wedig         // request D-Bus server name.
125d32b9667SJohn Wedig         conn->request_name("xyz.openbmc_project.eStoraged");
126d32b9667SJohn Wedig         sdbusplus::asio::object_server server(conn);
127d32b9667SJohn Wedig         boost::container::flat_map<std::string,
128d32b9667SJohn Wedig                                    std::unique_ptr<estoraged::EStoraged>>
129d32b9667SJohn Wedig             storageObjects;
1302098dabeSJohn Wedig 
13161cf4260SJohn Wedig         boost::asio::post(
13261cf4260SJohn Wedig             io, [&]() { createStorageObjects(server, storageObjects, conn); });
133d32b9667SJohn Wedig 
134d32b9667SJohn Wedig         /*
135d32b9667SJohn Wedig          * Set up an event handler to process any new configuration objects
136d32b9667SJohn Wedig          * that show up later.
137d32b9667SJohn Wedig          */
138d32b9667SJohn Wedig         boost::asio::deadline_timer filterTimer(io);
139e3ef765dSPatrick Williams         std::function<void(sdbusplus::message_t&)> eventHandler =
140e3ef765dSPatrick Williams             [&](sdbusplus::message_t& message) {
141d32b9667SJohn Wedig             if (message.is_method_error())
142d32b9667SJohn Wedig             {
143d32b9667SJohn Wedig                 lg2::error("eventHandler callback method error");
144d32b9667SJohn Wedig                 return;
145d32b9667SJohn Wedig             }
146d32b9667SJohn Wedig             /*
147d32b9667SJohn Wedig              * This implicitly cancels the timer, if it's already pending.
148d32b9667SJohn Wedig              * If there's a burst of events within a short period, we want
149d32b9667SJohn Wedig              * to handle them all at once. So, we will wait this long for no
150d32b9667SJohn Wedig              * more events to occur, before processing them.
151d32b9667SJohn Wedig              */
152d32b9667SJohn Wedig             filterTimer.expires_from_now(boost::posix_time::seconds(1));
153d32b9667SJohn Wedig 
15404c28fadSPatrick Williams             filterTimer.async_wait([&](const boost::system::error_code& ec) {
155d32b9667SJohn Wedig                 if (ec == boost::asio::error::operation_aborted)
156d32b9667SJohn Wedig                 {
157d32b9667SJohn Wedig                     /* we were canceled */
158d32b9667SJohn Wedig                     return;
159d32b9667SJohn Wedig                 }
160d32b9667SJohn Wedig                 if (ec)
161d32b9667SJohn Wedig                 {
162d32b9667SJohn Wedig                     lg2::error("timer error");
163d32b9667SJohn Wedig                     return;
164d32b9667SJohn Wedig                 }
16561cf4260SJohn Wedig                 createStorageObjects(server, storageObjects, conn);
166d32b9667SJohn Wedig             });
167d32b9667SJohn Wedig         };
168d32b9667SJohn Wedig 
169e3ef765dSPatrick Williams         auto match = std::make_unique<sdbusplus::bus::match_t>(
170e3ef765dSPatrick Williams             static_cast<sdbusplus::bus_t&>(*conn),
171d32b9667SJohn Wedig             "type='signal',member='PropertiesChanged',path_namespace='" +
172d32b9667SJohn Wedig                 std::string("/xyz/openbmc_project/inventory") +
173d32b9667SJohn Wedig                 "',arg0namespace='" + estoraged::emmcConfigInterface + "'",
174d32b9667SJohn Wedig             eventHandler);
175d32b9667SJohn Wedig 
1764e13b0a1SJohn Edward Broadbent         lg2::info("Storage management service is running", "REDFISH_MESSAGE_ID",
177e6ffe704SJohn Edward Broadbent                   std::string("OpenBMC.1.0.ServiceStarted"));
1782098dabeSJohn Wedig 
17967a47446SJohn Wedig         io.run();
18067a47446SJohn Wedig         return 0;
18182897c35SEd Tanous     }
18282897c35SEd Tanous     catch (const std::exception& e)
18382897c35SEd Tanous     {
18482897c35SEd Tanous         lg2::error(e.what(), "REDFISH_MESSAGE_ID",
18582897c35SEd Tanous                    std::string("OpenBMC.1.0.ServiceException"));
1862098dabeSJohn Wedig 
18782897c35SEd Tanous         return 2;
18882897c35SEd Tanous     }
1892098dabeSJohn Wedig     return 1;
1902098dabeSJohn Wedig }
191