xref: /openbmc/bmcweb/features/redfish/lib/storage.hpp (revision 26f6976f3905d7b20690bbf794fba746c1929ed3)
1a25aeccfSNikhil Potade /*
2a25aeccfSNikhil Potade // Copyright (c) 2019 Intel Corporation
3a25aeccfSNikhil Potade //
4a25aeccfSNikhil Potade // Licensed under the Apache License, Version 2.0 (the "License");
5a25aeccfSNikhil Potade // you may not use this file except in compliance with the License.
6a25aeccfSNikhil Potade // You may obtain a copy of the License at
7a25aeccfSNikhil Potade //
8a25aeccfSNikhil Potade //      http://www.apache.org/licenses/LICENSE-2.0
9a25aeccfSNikhil Potade //
10a25aeccfSNikhil Potade // Unless required by applicable law or agreed to in writing, software
11a25aeccfSNikhil Potade // distributed under the License is distributed on an "AS IS" BASIS,
12a25aeccfSNikhil Potade // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a25aeccfSNikhil Potade // See the License for the specific language governing permissions and
14a25aeccfSNikhil Potade // limitations under the License.
15a25aeccfSNikhil Potade */
16a25aeccfSNikhil Potade #pragma once
17a25aeccfSNikhil Potade 
182ad9c2f6SJames Feist #include "health.hpp"
19e284a7c1SJames Feist #include "openbmc_dbus_rest.hpp"
202ad9c2f6SJames Feist 
217e860f15SJohn Edward Broadbent #include <app.hpp>
22168e20c1SEd Tanous #include <dbus_utility.hpp>
23ed398213SEd Tanous #include <registries/privilege_registry.hpp>
241e1e598dSJonathan Doman #include <sdbusplus/asio/property.hpp>
25a25aeccfSNikhil Potade 
26a25aeccfSNikhil Potade namespace redfish
27a25aeccfSNikhil Potade {
287e860f15SJohn Edward Broadbent inline void requestRoutesStorageCollection(App& app)
29a25aeccfSNikhil Potade {
307e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Storage/")
31ed398213SEd Tanous         .privileges(redfish::privileges::getStorageCollection)
327e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
337e860f15SJohn Edward Broadbent             [](const crow::Request&,
347e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
358d1b46d7Szhanghch05                 asyncResp->res.jsonValue["@odata.type"] =
368d1b46d7Szhanghch05                     "#StorageCollection.StorageCollection";
378d1b46d7Szhanghch05                 asyncResp->res.jsonValue["@odata.id"] =
388d1b46d7Szhanghch05                     "/redfish/v1/Systems/system/Storage";
398d1b46d7Szhanghch05                 asyncResp->res.jsonValue["Name"] = "Storage Collection";
408d1b46d7Szhanghch05                 asyncResp->res.jsonValue["Members"] = {
41a25aeccfSNikhil Potade                     {{"@odata.id", "/redfish/v1/Systems/system/Storage/1"}}};
428d1b46d7Szhanghch05                 asyncResp->res.jsonValue["Members@odata.count"] = 1;
437e860f15SJohn Edward Broadbent             });
44a25aeccfSNikhil Potade }
45a25aeccfSNikhil Potade 
467e860f15SJohn Edward Broadbent inline void requestRoutesStorage(App& app)
47a25aeccfSNikhil Potade {
487e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Storage/1/")
49ed398213SEd Tanous         .privileges(redfish::privileges::getStorage)
507e860f15SJohn Edward Broadbent         .methods(
517e860f15SJohn Edward Broadbent             boost::beast::http::verb::
527e860f15SJohn Edward Broadbent                 get)([](const crow::Request&,
537e860f15SJohn Edward Broadbent                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
548d1b46d7Szhanghch05             asyncResp->res.jsonValue["@odata.type"] = "#Storage.v1_7_1.Storage";
558d1b46d7Szhanghch05             asyncResp->res.jsonValue["@odata.id"] =
568d1b46d7Szhanghch05                 "/redfish/v1/Systems/system/Storage/1";
578d1b46d7Szhanghch05             asyncResp->res.jsonValue["Name"] = "Storage";
588d1b46d7Szhanghch05             asyncResp->res.jsonValue["Id"] = "1";
598d1b46d7Szhanghch05             asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
60a25aeccfSNikhil Potade 
61e284a7c1SJames Feist             auto health = std::make_shared<HealthPopulate>(asyncResp);
62e284a7c1SJames Feist             health->populate();
63e284a7c1SJames Feist 
64a25aeccfSNikhil Potade             crow::connections::systemBus->async_method_call(
657e860f15SJohn Edward Broadbent                 [asyncResp,
667e860f15SJohn Edward Broadbent                  health](const boost::system::error_code ec,
67a25aeccfSNikhil Potade                          const std::vector<std::string>& storageList) {
68a25aeccfSNikhil Potade                     nlohmann::json& storageArray =
69a25aeccfSNikhil Potade                         asyncResp->res.jsonValue["Drives"];
70a25aeccfSNikhil Potade                     storageArray = nlohmann::json::array();
717e860f15SJohn Edward Broadbent                     auto& count =
727e860f15SJohn Edward Broadbent                         asyncResp->res.jsonValue["Drives@odata.count"];
73e284a7c1SJames Feist                     count = 0;
742ad9c2f6SJames Feist 
75a25aeccfSNikhil Potade                     if (ec)
76a25aeccfSNikhil Potade                     {
77a25aeccfSNikhil Potade                         BMCWEB_LOG_ERROR << "Drive mapper call error";
78a25aeccfSNikhil Potade                         messages::internalError(asyncResp->res);
79a25aeccfSNikhil Potade                         return;
80a25aeccfSNikhil Potade                     }
812ad9c2f6SJames Feist 
82e284a7c1SJames Feist                     health->inventory.insert(health->inventory.end(),
83e284a7c1SJames Feist                                              storageList.begin(),
84e284a7c1SJames Feist                                              storageList.end());
852ad9c2f6SJames Feist 
86a25aeccfSNikhil Potade                     for (const std::string& objpath : storageList)
87a25aeccfSNikhil Potade                     {
88f23b7296SEd Tanous                         std::size_t lastPos = objpath.rfind('/');
89a25aeccfSNikhil Potade                         if (lastPos == std::string::npos ||
90a25aeccfSNikhil Potade                             (objpath.size() <= lastPos + 1))
91a25aeccfSNikhil Potade                         {
927e860f15SJohn Edward Broadbent                             BMCWEB_LOG_ERROR << "Failed to find '/' in "
937e860f15SJohn Edward Broadbent                                              << objpath;
94a25aeccfSNikhil Potade                             continue;
95a25aeccfSNikhil Potade                         }
96a25aeccfSNikhil Potade 
97a25aeccfSNikhil Potade                         storageArray.push_back(
98a25aeccfSNikhil Potade                             {{"@odata.id",
99be13ceceSJames Feist                               "/redfish/v1/Systems/system/Storage/1/Drives/" +
100a25aeccfSNikhil Potade                                   objpath.substr(lastPos + 1)}});
101a25aeccfSNikhil Potade                     }
102a25aeccfSNikhil Potade 
103e284a7c1SJames Feist                     count = storageArray.size();
104a25aeccfSNikhil Potade                 },
105a25aeccfSNikhil Potade                 "xyz.openbmc_project.ObjectMapper",
106a25aeccfSNikhil Potade                 "/xyz/openbmc_project/object_mapper",
107a25aeccfSNikhil Potade                 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
108a25aeccfSNikhil Potade                 "/xyz/openbmc_project/inventory", int32_t(0),
109a25aeccfSNikhil Potade                 std::array<const char*, 1>{
110a25aeccfSNikhil Potade                     "xyz.openbmc_project.Inventory.Item.Drive"});
111e284a7c1SJames Feist 
112e284a7c1SJames Feist             crow::connections::systemBus->async_method_call(
113e284a7c1SJames Feist                 [asyncResp,
114e284a7c1SJames Feist                  health](const boost::system::error_code ec,
115e284a7c1SJames Feist                          const crow::openbmc_mapper::GetSubTreeType& subtree) {
116*26f6976fSEd Tanous                     if (ec || subtree.empty())
117e284a7c1SJames Feist                     {
118d819a420SJames Feist                         // doesn't have to be there
119e284a7c1SJames Feist                         return;
120e284a7c1SJames Feist                     }
121e284a7c1SJames Feist 
122e284a7c1SJames Feist                     nlohmann::json& root =
123e284a7c1SJames Feist                         asyncResp->res.jsonValue["StorageControllers"];
124e284a7c1SJames Feist                     root = nlohmann::json::array();
125e284a7c1SJames Feist                     for (const auto& [path, interfaceDict] : subtree)
126e284a7c1SJames Feist                     {
127f23b7296SEd Tanous                         std::size_t lastPos = path.rfind('/');
128e284a7c1SJames Feist                         if (lastPos == std::string::npos ||
129e284a7c1SJames Feist                             (path.size() <= lastPos + 1))
130e284a7c1SJames Feist                         {
1317e860f15SJohn Edward Broadbent                             BMCWEB_LOG_ERROR << "Failed to find '/' in "
1327e860f15SJohn Edward Broadbent                                              << path;
133e284a7c1SJames Feist                             return;
134e284a7c1SJames Feist                         }
135e284a7c1SJames Feist 
136e284a7c1SJames Feist                         if (interfaceDict.size() != 1)
137e284a7c1SJames Feist                         {
138e284a7c1SJames Feist                             BMCWEB_LOG_ERROR << "Connection size "
139e284a7c1SJames Feist                                              << interfaceDict.size()
140e284a7c1SJames Feist                                              << ", greater than 1";
141e284a7c1SJames Feist                             messages::internalError(asyncResp->res);
142e284a7c1SJames Feist                             return;
143e284a7c1SJames Feist                         }
144e284a7c1SJames Feist 
145e284a7c1SJames Feist                         const std::string& connectionName =
146e284a7c1SJames Feist                             interfaceDict.front().first;
147e284a7c1SJames Feist 
148e284a7c1SJames Feist                         size_t index = root.size();
149e284a7c1SJames Feist                         nlohmann::json& storageController =
150e284a7c1SJames Feist                             root.emplace_back(nlohmann::json::object());
151e284a7c1SJames Feist 
152e284a7c1SJames Feist                         std::string id = path.substr(lastPos + 1);
153e284a7c1SJames Feist 
154e284a7c1SJames Feist                         storageController["@odata.type"] =
155e284a7c1SJames Feist                             "#Storage.v1_7_0.StorageController";
156e284a7c1SJames Feist                         storageController["@odata.id"] =
1570fda0f12SGeorge Liu                             "/redfish/v1/Systems/system/Storage/1#/StorageControllers/" +
158e284a7c1SJames Feist                             std::to_string(index);
159e284a7c1SJames Feist                         storageController["Name"] = id;
160e284a7c1SJames Feist                         storageController["MemberId"] = id;
161e284a7c1SJames Feist                         storageController["Status"]["State"] = "Enabled";
162e284a7c1SJames Feist 
1631e1e598dSJonathan Doman                         sdbusplus::asio::getProperty<bool>(
1641e1e598dSJonathan Doman                             *crow::connections::systemBus, connectionName, path,
1651e1e598dSJonathan Doman                             "xyz.openbmc_project.Inventory.Item", "Present",
1661e1e598dSJonathan Doman                             [asyncResp,
1671e1e598dSJonathan Doman                              index](const boost::system::error_code ec2,
1681e1e598dSJonathan Doman                                     bool enabled) {
1697e860f15SJohn Edward Broadbent                                 // this interface isn't necessary, only check it
1707e860f15SJohn Edward Broadbent                                 // if we get a good return
17123a21a1cSEd Tanous                                 if (ec2)
172e284a7c1SJames Feist                                 {
173e284a7c1SJames Feist                                     return;
174e284a7c1SJames Feist                                 }
1751e1e598dSJonathan Doman                                 if (!enabled)
176e284a7c1SJames Feist                                 {
177e284a7c1SJames Feist                                     asyncResp->res
178e284a7c1SJames Feist                                         .jsonValue["StorageControllers"][index]
1797e860f15SJohn Edward Broadbent                                                   ["Status"]["State"] =
1807e860f15SJohn Edward Broadbent                                         "Disabled";
181e284a7c1SJames Feist                                 }
1821e1e598dSJonathan Doman                             });
183e284a7c1SJames Feist 
184e284a7c1SJames Feist                         crow::connections::systemBus->async_method_call(
1857e860f15SJohn Edward Broadbent                             [asyncResp, index](
1867e860f15SJohn Edward Broadbent                                 const boost::system::error_code ec2,
187168e20c1SEd Tanous                                 const std::vector<
188168e20c1SEd Tanous                                     std::pair<std::string,
189168e20c1SEd Tanous                                               dbus::utility::DbusVariantType>>&
1907e860f15SJohn Edward Broadbent                                     propertiesList) {
1917e860f15SJohn Edward Broadbent                                 if (ec2)
1927e860f15SJohn Edward Broadbent                                 {
1937e860f15SJohn Edward Broadbent                                     // this interface isn't necessary
1947e860f15SJohn Edward Broadbent                                     return;
1957e860f15SJohn Edward Broadbent                                 }
1967e860f15SJohn Edward Broadbent                                 for (const std::pair<
1977e860f15SJohn Edward Broadbent                                          std::string,
198168e20c1SEd Tanous                                          dbus::utility::DbusVariantType>&
199168e20c1SEd Tanous                                          property : propertiesList)
2007e860f15SJohn Edward Broadbent                                 {
2017e860f15SJohn Edward Broadbent                                     // Store DBus properties that are also
2027e860f15SJohn Edward Broadbent                                     // Redfish properties with same name and a
2037e860f15SJohn Edward Broadbent                                     // string value
2047e860f15SJohn Edward Broadbent                                     const std::string& propertyName =
2057e860f15SJohn Edward Broadbent                                         property.first;
2067e860f15SJohn Edward Broadbent                                     nlohmann::json& object =
2077e860f15SJohn Edward Broadbent                                         asyncResp->res
2087e860f15SJohn Edward Broadbent                                             .jsonValue["StorageControllers"]
2097e860f15SJohn Edward Broadbent                                                       [index];
2107e860f15SJohn Edward Broadbent                                     if ((propertyName == "PartNumber") ||
2117e860f15SJohn Edward Broadbent                                         (propertyName == "SerialNumber") ||
2127e860f15SJohn Edward Broadbent                                         (propertyName == "Manufacturer") ||
2137e860f15SJohn Edward Broadbent                                         (propertyName == "Model"))
2147e860f15SJohn Edward Broadbent                                     {
2157e860f15SJohn Edward Broadbent                                         const std::string* value =
2167e860f15SJohn Edward Broadbent                                             std::get_if<std::string>(
2177e860f15SJohn Edward Broadbent                                                 &property.second);
2187e860f15SJohn Edward Broadbent                                         if (value == nullptr)
2197e860f15SJohn Edward Broadbent                                         {
2207e860f15SJohn Edward Broadbent                                             // illegal property
2217e860f15SJohn Edward Broadbent                                             messages::internalError(
2227e860f15SJohn Edward Broadbent                                                 asyncResp->res);
2237e860f15SJohn Edward Broadbent                                             return;
2247e860f15SJohn Edward Broadbent                                         }
2257e860f15SJohn Edward Broadbent                                         object[propertyName] = *value;
2267e860f15SJohn Edward Broadbent                                     }
2277e860f15SJohn Edward Broadbent                                 }
2287e860f15SJohn Edward Broadbent                             },
2297e860f15SJohn Edward Broadbent                             connectionName, path,
2307e860f15SJohn Edward Broadbent                             "org.freedesktop.DBus.Properties", "GetAll",
2317e860f15SJohn Edward Broadbent                             "xyz.openbmc_project.Inventory.Decorator.Asset");
2327e860f15SJohn Edward Broadbent                     }
2337e860f15SJohn Edward Broadbent 
2347e860f15SJohn Edward Broadbent                     // this is done after we know the json array will no longer
2357e860f15SJohn Edward Broadbent                     // be resized, as json::array uses vector underneath and we
2367e860f15SJohn Edward Broadbent                     // need references to its members that won't change
2377e860f15SJohn Edward Broadbent                     size_t count = 0;
2387e860f15SJohn Edward Broadbent                     for (const auto& [path, interfaceDict] : subtree)
2397e860f15SJohn Edward Broadbent                     {
2407e860f15SJohn Edward Broadbent                         auto subHealth = std::make_shared<HealthPopulate>(
2417e860f15SJohn Edward Broadbent                             asyncResp, root[count]["Status"]);
2427e860f15SJohn Edward Broadbent                         subHealth->inventory.emplace_back(path);
2437e860f15SJohn Edward Broadbent                         health->inventory.emplace_back(path);
2447e860f15SJohn Edward Broadbent                         health->children.emplace_back(subHealth);
2457e860f15SJohn Edward Broadbent                         count++;
2467e860f15SJohn Edward Broadbent                     }
2477e860f15SJohn Edward Broadbent                 },
2487e860f15SJohn Edward Broadbent                 "xyz.openbmc_project.ObjectMapper",
2497e860f15SJohn Edward Broadbent                 "/xyz/openbmc_project/object_mapper",
2507e860f15SJohn Edward Broadbent                 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
2517e860f15SJohn Edward Broadbent                 "/xyz/openbmc_project/inventory", int32_t(0),
2527e860f15SJohn Edward Broadbent                 std::array<const char*, 1>{
2537e860f15SJohn Edward Broadbent                     "xyz.openbmc_project.Inventory.Item.StorageController"});
2547e860f15SJohn Edward Broadbent         });
2557e860f15SJohn Edward Broadbent }
2567e860f15SJohn Edward Broadbent 
25703913171SWilly Tu inline void getDriveAsset(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
25803913171SWilly Tu                           const std::string& connectionName,
25903913171SWilly Tu                           const std::string& path)
26003913171SWilly Tu {
26103913171SWilly Tu     crow::connections::systemBus->async_method_call(
262168e20c1SEd Tanous         [asyncResp](const boost::system::error_code ec,
263168e20c1SEd Tanous                     const std::vector<
264168e20c1SEd Tanous                         std::pair<std::string, dbus::utility::DbusVariantType>>&
26503913171SWilly Tu                         propertiesList) {
26603913171SWilly Tu             if (ec)
26703913171SWilly Tu             {
26803913171SWilly Tu                 // this interface isn't necessary
26903913171SWilly Tu                 return;
27003913171SWilly Tu             }
271168e20c1SEd Tanous             for (const std::pair<std::string, dbus::utility::DbusVariantType>&
27203913171SWilly Tu                      property : propertiesList)
27303913171SWilly Tu             {
27403913171SWilly Tu                 // Store DBus properties that are also
27503913171SWilly Tu                 // Redfish properties with same name and a
27603913171SWilly Tu                 // string value
27703913171SWilly Tu                 const std::string& propertyName = property.first;
27803913171SWilly Tu                 if ((propertyName == "PartNumber") ||
27903913171SWilly Tu                     (propertyName == "SerialNumber") ||
28003913171SWilly Tu                     (propertyName == "Manufacturer") ||
28103913171SWilly Tu                     (propertyName == "Model"))
28203913171SWilly Tu                 {
28303913171SWilly Tu                     const std::string* value =
28403913171SWilly Tu                         std::get_if<std::string>(&property.second);
28503913171SWilly Tu                     if (value == nullptr)
28603913171SWilly Tu                     {
28703913171SWilly Tu                         // illegal property
28803913171SWilly Tu                         messages::internalError(asyncResp->res);
28903913171SWilly Tu                         return;
29003913171SWilly Tu                     }
29103913171SWilly Tu                     asyncResp->res.jsonValue[propertyName] = *value;
29203913171SWilly Tu                 }
29303913171SWilly Tu             }
29403913171SWilly Tu         },
29503913171SWilly Tu         connectionName, path, "org.freedesktop.DBus.Properties", "GetAll",
29603913171SWilly Tu         "xyz.openbmc_project.Inventory.Decorator.Asset");
29703913171SWilly Tu }
29803913171SWilly Tu 
29903913171SWilly Tu inline void getDrivePresent(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
30003913171SWilly Tu                             const std::string& connectionName,
30103913171SWilly Tu                             const std::string& path)
30203913171SWilly Tu {
3031e1e598dSJonathan Doman     sdbusplus::asio::getProperty<bool>(
3041e1e598dSJonathan Doman         *crow::connections::systemBus, connectionName, path,
3051e1e598dSJonathan Doman         "xyz.openbmc_project.Inventory.Item", "Present",
30603913171SWilly Tu         [asyncResp, path](const boost::system::error_code ec,
3071e1e598dSJonathan Doman                           const bool enabled) {
30803913171SWilly Tu             // this interface isn't necessary, only check it if
30903913171SWilly Tu             // we get a good return
31003913171SWilly Tu             if (ec)
31103913171SWilly Tu             {
31203913171SWilly Tu                 return;
31303913171SWilly Tu             }
31403913171SWilly Tu 
3151e1e598dSJonathan Doman             if (!enabled)
31603913171SWilly Tu             {
31703913171SWilly Tu                 asyncResp->res.jsonValue["Status"]["State"] = "Disabled";
31803913171SWilly Tu             }
3191e1e598dSJonathan Doman         });
32003913171SWilly Tu }
32103913171SWilly Tu 
32203913171SWilly Tu inline void getDriveState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
32303913171SWilly Tu                           const std::string& connectionName,
32403913171SWilly Tu                           const std::string& path)
32503913171SWilly Tu {
3261e1e598dSJonathan Doman     sdbusplus::asio::getProperty<bool>(
3271e1e598dSJonathan Doman         *crow::connections::systemBus, connectionName, path,
3281e1e598dSJonathan Doman         "xyz.openbmc_project.State.Drive", "Rebuilding",
3291e1e598dSJonathan Doman         [asyncResp](const boost::system::error_code ec, const bool updating) {
33003913171SWilly Tu             // this interface isn't necessary, only check it
33103913171SWilly Tu             // if we get a good return
33203913171SWilly Tu             if (ec)
33303913171SWilly Tu             {
33403913171SWilly Tu                 return;
33503913171SWilly Tu             }
33603913171SWilly Tu 
33703913171SWilly Tu             // updating and disabled in the backend shouldn't be
33803913171SWilly Tu             // able to be set at the same time, so we don't need
33903913171SWilly Tu             // to check for the race condition of these two
34003913171SWilly Tu             // calls
3411e1e598dSJonathan Doman             if (updating)
34203913171SWilly Tu             {
34303913171SWilly Tu                 asyncResp->res.jsonValue["Status"]["State"] = "Updating";
34403913171SWilly Tu             }
3451e1e598dSJonathan Doman         });
34603913171SWilly Tu }
34703913171SWilly Tu 
3487e860f15SJohn Edward Broadbent inline void requestRoutesDrive(App& app)
3497e860f15SJohn Edward Broadbent {
3507e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Storage/1/Drives/<str>/")
351ed398213SEd Tanous         .privileges(redfish::privileges::getDrive)
3527e860f15SJohn Edward Broadbent         .methods(
3537e860f15SJohn Edward Broadbent             boost::beast::http::verb::get)([](const crow::Request&,
3547e860f15SJohn Edward Broadbent                                               const std::shared_ptr<
3557e860f15SJohn Edward Broadbent                                                   bmcweb::AsyncResp>& asyncResp,
3567e860f15SJohn Edward Broadbent                                               const std::string& driveId) {
3577e860f15SJohn Edward Broadbent             crow::connections::systemBus->async_method_call(
358e284a7c1SJames Feist                 [asyncResp,
3597e860f15SJohn Edward Broadbent                  driveId](const boost::system::error_code ec,
3607e860f15SJohn Edward Broadbent                           const crow::openbmc_mapper::GetSubTreeType& subtree) {
3617e860f15SJohn Edward Broadbent                     if (ec)
3627e860f15SJohn Edward Broadbent                     {
3637e860f15SJohn Edward Broadbent                         BMCWEB_LOG_ERROR << "Drive mapper call error";
3647e860f15SJohn Edward Broadbent                         messages::internalError(asyncResp->res);
3657e860f15SJohn Edward Broadbent                         return;
3667e860f15SJohn Edward Broadbent                     }
3677e860f15SJohn Edward Broadbent 
36803913171SWilly Tu                     auto drive = std::find_if(
3697e860f15SJohn Edward Broadbent                         subtree.begin(), subtree.end(),
37003913171SWilly Tu                         [&driveId](const std::pair<
37103913171SWilly Tu                                    std::string,
37203913171SWilly Tu                                    std::vector<std::pair<
37303913171SWilly Tu                                        std::string, std::vector<std::string>>>>&
37403913171SWilly Tu                                        object) {
37503913171SWilly Tu                             return sdbusplus::message::object_path(object.first)
37603913171SWilly Tu                                        .filename() == driveId;
3777e860f15SJohn Edward Broadbent                         });
3787e860f15SJohn Edward Broadbent 
37903913171SWilly Tu                     if (drive == subtree.end())
3807e860f15SJohn Edward Broadbent                     {
3817e860f15SJohn Edward Broadbent                         messages::resourceNotFound(asyncResp->res, "Drive",
3827e860f15SJohn Edward Broadbent                                                    driveId);
3837e860f15SJohn Edward Broadbent                         return;
3847e860f15SJohn Edward Broadbent                     }
3857e860f15SJohn Edward Broadbent 
38603913171SWilly Tu                     const std::string& path = drive->first;
3877e860f15SJohn Edward Broadbent                     const std::vector<
3887e860f15SJohn Edward Broadbent                         std::pair<std::string, std::vector<std::string>>>&
38903913171SWilly Tu                         connectionNames = drive->second;
3907e860f15SJohn Edward Broadbent 
3917e860f15SJohn Edward Broadbent                     asyncResp->res.jsonValue["@odata.type"] =
3927e860f15SJohn Edward Broadbent                         "#Drive.v1_7_0.Drive";
3937e860f15SJohn Edward Broadbent                     asyncResp->res.jsonValue["@odata.id"] =
3947e860f15SJohn Edward Broadbent                         "/redfish/v1/Systems/system/Storage/1/Drives/" +
3957e860f15SJohn Edward Broadbent                         driveId;
3967e860f15SJohn Edward Broadbent                     asyncResp->res.jsonValue["Name"] = driveId;
3977e860f15SJohn Edward Broadbent                     asyncResp->res.jsonValue["Id"] = driveId;
3987e860f15SJohn Edward Broadbent 
3997e860f15SJohn Edward Broadbent                     if (connectionNames.size() != 1)
4007e860f15SJohn Edward Broadbent                     {
4017e860f15SJohn Edward Broadbent                         BMCWEB_LOG_ERROR << "Connection size "
4027e860f15SJohn Edward Broadbent                                          << connectionNames.size()
40303913171SWilly Tu                                          << ", not equal to 1";
4047e860f15SJohn Edward Broadbent                         messages::internalError(asyncResp->res);
4057e860f15SJohn Edward Broadbent                         return;
4067e860f15SJohn Edward Broadbent                     }
4077e860f15SJohn Edward Broadbent 
4087e860f15SJohn Edward Broadbent                     getMainChassisId(
4097e860f15SJohn Edward Broadbent                         asyncResp,
4107e860f15SJohn Edward Broadbent                         [](const std::string& chassisId,
4117e860f15SJohn Edward Broadbent                            const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
4127e860f15SJohn Edward Broadbent                             aRsp->res.jsonValue["Links"]["Chassis"] = {
4137e860f15SJohn Edward Broadbent                                 {"@odata.id",
4147e860f15SJohn Edward Broadbent                                  "/redfish/v1/Chassis/" + chassisId}};
4157e860f15SJohn Edward Broadbent                         });
4167e860f15SJohn Edward Broadbent 
417a25aeccfSNikhil Potade                     // default it to Enabled
418a25aeccfSNikhil Potade                     asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
419a25aeccfSNikhil Potade 
4202ad9c2f6SJames Feist                     auto health = std::make_shared<HealthPopulate>(asyncResp);
421e284a7c1SJames Feist                     health->inventory.emplace_back(path);
4222ad9c2f6SJames Feist                     health->populate();
4232ad9c2f6SJames Feist 
42403913171SWilly Tu                     const std::string& connectionName =
42503913171SWilly Tu                         connectionNames[0].first;
42622984074SJames Feist 
42703913171SWilly Tu                     getDriveAsset(asyncResp, connectionName, path);
42803913171SWilly Tu                     getDrivePresent(asyncResp, connectionName, path);
42903913171SWilly Tu                     getDriveState(asyncResp, connectionName, path);
430a25aeccfSNikhil Potade                 },
431a25aeccfSNikhil Potade                 "xyz.openbmc_project.ObjectMapper",
432a25aeccfSNikhil Potade                 "/xyz/openbmc_project/object_mapper",
433a25aeccfSNikhil Potade                 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
434a25aeccfSNikhil Potade                 "/xyz/openbmc_project/inventory", int32_t(0),
435a25aeccfSNikhil Potade                 std::array<const char*, 1>{
436a25aeccfSNikhil Potade                     "xyz.openbmc_project.Inventory.Item.Drive"});
4377e860f15SJohn Edward Broadbent         });
438a25aeccfSNikhil Potade }
439a25aeccfSNikhil Potade } // namespace redfish
440