xref: /openbmc/bmcweb/features/redfish/lib/storage.hpp (revision 7e860f1550c8686eec42f7a75bc5f2ef51e756ad)
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 
21*7e860f15SJohn Edward Broadbent #include <app.hpp>
22a25aeccfSNikhil Potade 
23a25aeccfSNikhil Potade namespace redfish
24a25aeccfSNikhil Potade {
25*7e860f15SJohn Edward Broadbent inline void requestRoutesStorageCollection(App& app)
26a25aeccfSNikhil Potade {
27*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Storage/")
28*7e860f15SJohn Edward Broadbent         .privileges({"Login"})
29*7e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
30*7e860f15SJohn Edward Broadbent             [](const crow::Request&,
31*7e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
328d1b46d7Szhanghch05                 asyncResp->res.jsonValue["@odata.type"] =
338d1b46d7Szhanghch05                     "#StorageCollection.StorageCollection";
348d1b46d7Szhanghch05                 asyncResp->res.jsonValue["@odata.id"] =
358d1b46d7Szhanghch05                     "/redfish/v1/Systems/system/Storage";
368d1b46d7Szhanghch05                 asyncResp->res.jsonValue["Name"] = "Storage Collection";
378d1b46d7Szhanghch05                 asyncResp->res.jsonValue["Members"] = {
38a25aeccfSNikhil Potade                     {{"@odata.id", "/redfish/v1/Systems/system/Storage/1"}}};
398d1b46d7Szhanghch05                 asyncResp->res.jsonValue["Members@odata.count"] = 1;
40*7e860f15SJohn Edward Broadbent             });
41a25aeccfSNikhil Potade }
42a25aeccfSNikhil Potade 
43*7e860f15SJohn Edward Broadbent inline void requestRoutesStorage(App& app)
44a25aeccfSNikhil Potade {
45*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Storage/1/")
46*7e860f15SJohn Edward Broadbent         .privileges({"Login"})
47*7e860f15SJohn Edward Broadbent         .methods(
48*7e860f15SJohn Edward Broadbent             boost::beast::http::verb::
49*7e860f15SJohn Edward Broadbent                 get)([](const crow::Request&,
50*7e860f15SJohn Edward Broadbent                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
518d1b46d7Szhanghch05             asyncResp->res.jsonValue["@odata.type"] = "#Storage.v1_7_1.Storage";
528d1b46d7Szhanghch05             asyncResp->res.jsonValue["@odata.id"] =
538d1b46d7Szhanghch05                 "/redfish/v1/Systems/system/Storage/1";
548d1b46d7Szhanghch05             asyncResp->res.jsonValue["Name"] = "Storage";
558d1b46d7Szhanghch05             asyncResp->res.jsonValue["Id"] = "1";
568d1b46d7Szhanghch05             asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
57a25aeccfSNikhil Potade 
58e284a7c1SJames Feist             auto health = std::make_shared<HealthPopulate>(asyncResp);
59e284a7c1SJames Feist             health->populate();
60e284a7c1SJames Feist 
61a25aeccfSNikhil Potade             crow::connections::systemBus->async_method_call(
62*7e860f15SJohn Edward Broadbent                 [asyncResp,
63*7e860f15SJohn Edward Broadbent                  health](const boost::system::error_code ec,
64a25aeccfSNikhil Potade                          const std::vector<std::string>& storageList) {
65a25aeccfSNikhil Potade                     nlohmann::json& storageArray =
66a25aeccfSNikhil Potade                         asyncResp->res.jsonValue["Drives"];
67a25aeccfSNikhil Potade                     storageArray = nlohmann::json::array();
68*7e860f15SJohn Edward Broadbent                     auto& count =
69*7e860f15SJohn Edward Broadbent                         asyncResp->res.jsonValue["Drives@odata.count"];
70e284a7c1SJames Feist                     count = 0;
712ad9c2f6SJames Feist 
72a25aeccfSNikhil Potade                     if (ec)
73a25aeccfSNikhil Potade                     {
74a25aeccfSNikhil Potade                         BMCWEB_LOG_ERROR << "Drive mapper call error";
75a25aeccfSNikhil Potade                         messages::internalError(asyncResp->res);
76a25aeccfSNikhil Potade                         return;
77a25aeccfSNikhil Potade                     }
782ad9c2f6SJames Feist 
79e284a7c1SJames Feist                     health->inventory.insert(health->inventory.end(),
80e284a7c1SJames Feist                                              storageList.begin(),
81e284a7c1SJames Feist                                              storageList.end());
822ad9c2f6SJames Feist 
83a25aeccfSNikhil Potade                     for (const std::string& objpath : storageList)
84a25aeccfSNikhil Potade                     {
85f23b7296SEd Tanous                         std::size_t lastPos = objpath.rfind('/');
86a25aeccfSNikhil Potade                         if (lastPos == std::string::npos ||
87a25aeccfSNikhil Potade                             (objpath.size() <= lastPos + 1))
88a25aeccfSNikhil Potade                         {
89*7e860f15SJohn Edward Broadbent                             BMCWEB_LOG_ERROR << "Failed to find '/' in "
90*7e860f15SJohn Edward Broadbent                                              << objpath;
91a25aeccfSNikhil Potade                             continue;
92a25aeccfSNikhil Potade                         }
93a25aeccfSNikhil Potade 
94a25aeccfSNikhil Potade                         storageArray.push_back(
95a25aeccfSNikhil Potade                             {{"@odata.id",
96be13ceceSJames Feist                               "/redfish/v1/Systems/system/Storage/1/Drives/" +
97a25aeccfSNikhil Potade                                   objpath.substr(lastPos + 1)}});
98a25aeccfSNikhil Potade                     }
99a25aeccfSNikhil Potade 
100e284a7c1SJames Feist                     count = storageArray.size();
101a25aeccfSNikhil Potade                 },
102a25aeccfSNikhil Potade                 "xyz.openbmc_project.ObjectMapper",
103a25aeccfSNikhil Potade                 "/xyz/openbmc_project/object_mapper",
104a25aeccfSNikhil Potade                 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
105a25aeccfSNikhil Potade                 "/xyz/openbmc_project/inventory", int32_t(0),
106a25aeccfSNikhil Potade                 std::array<const char*, 1>{
107a25aeccfSNikhil Potade                     "xyz.openbmc_project.Inventory.Item.Drive"});
108e284a7c1SJames Feist 
109e284a7c1SJames Feist             crow::connections::systemBus->async_method_call(
110e284a7c1SJames Feist                 [asyncResp,
111e284a7c1SJames Feist                  health](const boost::system::error_code ec,
112e284a7c1SJames Feist                          const crow::openbmc_mapper::GetSubTreeType& subtree) {
113e284a7c1SJames Feist                     if (ec || !subtree.size())
114e284a7c1SJames Feist                     {
115d819a420SJames Feist                         // doesn't have to be there
116e284a7c1SJames Feist                         return;
117e284a7c1SJames Feist                     }
118e284a7c1SJames Feist 
119e284a7c1SJames Feist                     nlohmann::json& root =
120e284a7c1SJames Feist                         asyncResp->res.jsonValue["StorageControllers"];
121e284a7c1SJames Feist                     root = nlohmann::json::array();
122e284a7c1SJames Feist                     for (const auto& [path, interfaceDict] : subtree)
123e284a7c1SJames Feist                     {
124f23b7296SEd Tanous                         std::size_t lastPos = path.rfind('/');
125e284a7c1SJames Feist                         if (lastPos == std::string::npos ||
126e284a7c1SJames Feist                             (path.size() <= lastPos + 1))
127e284a7c1SJames Feist                         {
128*7e860f15SJohn Edward Broadbent                             BMCWEB_LOG_ERROR << "Failed to find '/' in "
129*7e860f15SJohn Edward Broadbent                                              << path;
130e284a7c1SJames Feist                             return;
131e284a7c1SJames Feist                         }
132e284a7c1SJames Feist 
133e284a7c1SJames Feist                         if (interfaceDict.size() != 1)
134e284a7c1SJames Feist                         {
135e284a7c1SJames Feist                             BMCWEB_LOG_ERROR << "Connection size "
136e284a7c1SJames Feist                                              << interfaceDict.size()
137e284a7c1SJames Feist                                              << ", greater than 1";
138e284a7c1SJames Feist                             messages::internalError(asyncResp->res);
139e284a7c1SJames Feist                             return;
140e284a7c1SJames Feist                         }
141e284a7c1SJames Feist 
142e284a7c1SJames Feist                         const std::string& connectionName =
143e284a7c1SJames Feist                             interfaceDict.front().first;
144e284a7c1SJames Feist 
145e284a7c1SJames Feist                         size_t index = root.size();
146e284a7c1SJames Feist                         nlohmann::json& storageController =
147e284a7c1SJames Feist                             root.emplace_back(nlohmann::json::object());
148e284a7c1SJames Feist 
149e284a7c1SJames Feist                         std::string id = path.substr(lastPos + 1);
150e284a7c1SJames Feist 
151e284a7c1SJames Feist                         storageController["@odata.type"] =
152e284a7c1SJames Feist                             "#Storage.v1_7_0.StorageController";
153e284a7c1SJames Feist                         storageController["@odata.id"] =
154e284a7c1SJames Feist                             "/redfish/v1/Systems/system/Storage/1"
155e284a7c1SJames Feist                             "#/StorageControllers/" +
156e284a7c1SJames Feist                             std::to_string(index);
157e284a7c1SJames Feist                         storageController["Name"] = id;
158e284a7c1SJames Feist                         storageController["MemberId"] = id;
159e284a7c1SJames Feist                         storageController["Status"]["State"] = "Enabled";
160e284a7c1SJames Feist 
161e284a7c1SJames Feist                         crow::connections::systemBus->async_method_call(
162*7e860f15SJohn Edward Broadbent                             [asyncResp,
163*7e860f15SJohn Edward Broadbent                              index](const boost::system::error_code ec2,
164e284a7c1SJames Feist                                     const std::variant<bool> present) {
165*7e860f15SJohn Edward Broadbent                                 // this interface isn't necessary, only check it
166*7e860f15SJohn Edward Broadbent                                 // if we get a good return
16723a21a1cSEd Tanous                                 if (ec2)
168e284a7c1SJames Feist                                 {
169e284a7c1SJames Feist                                     return;
170e284a7c1SJames Feist                                 }
171*7e860f15SJohn Edward Broadbent                                 const bool* enabled =
172*7e860f15SJohn Edward Broadbent                                     std::get_if<bool>(&present);
173e284a7c1SJames Feist                                 if (enabled == nullptr)
174e284a7c1SJames Feist                                 {
175*7e860f15SJohn Edward Broadbent                                     BMCWEB_LOG_DEBUG
176*7e860f15SJohn Edward Broadbent                                         << "Illegal property present";
177e284a7c1SJames Feist                                     messages::internalError(asyncResp->res);
178e284a7c1SJames Feist                                     return;
179e284a7c1SJames Feist                                 }
180e284a7c1SJames Feist                                 if (!(*enabled))
181e284a7c1SJames Feist                                 {
182e284a7c1SJames Feist                                     asyncResp->res
183e284a7c1SJames Feist                                         .jsonValue["StorageControllers"][index]
184*7e860f15SJohn Edward Broadbent                                                   ["Status"]["State"] =
185*7e860f15SJohn Edward Broadbent                                         "Disabled";
186e284a7c1SJames Feist                                 }
187e284a7c1SJames Feist                             },
188*7e860f15SJohn Edward Broadbent                             connectionName, path,
189*7e860f15SJohn Edward Broadbent                             "org.freedesktop.DBus.Properties", "Get",
190*7e860f15SJohn Edward Broadbent                             "xyz.openbmc_project.Inventory.Item", "Present");
191e284a7c1SJames Feist 
192e284a7c1SJames Feist                         crow::connections::systemBus->async_method_call(
193*7e860f15SJohn Edward Broadbent                             [asyncResp, index](
194*7e860f15SJohn Edward Broadbent                                 const boost::system::error_code ec2,
195*7e860f15SJohn Edward Broadbent                                 const std::vector<std::pair<
196*7e860f15SJohn Edward Broadbent                                     std::string,
197*7e860f15SJohn Edward Broadbent                                     std::variant<bool, std::string, uint64_t>>>&
198*7e860f15SJohn Edward Broadbent                                     propertiesList) {
199*7e860f15SJohn Edward Broadbent                                 if (ec2)
200*7e860f15SJohn Edward Broadbent                                 {
201*7e860f15SJohn Edward Broadbent                                     // this interface isn't necessary
202*7e860f15SJohn Edward Broadbent                                     return;
203*7e860f15SJohn Edward Broadbent                                 }
204*7e860f15SJohn Edward Broadbent                                 for (const std::pair<
205*7e860f15SJohn Edward Broadbent                                          std::string,
206*7e860f15SJohn Edward Broadbent                                          std::variant<bool, std::string,
207*7e860f15SJohn Edward Broadbent                                                       uint64_t>>& property :
208*7e860f15SJohn Edward Broadbent                                      propertiesList)
209*7e860f15SJohn Edward Broadbent                                 {
210*7e860f15SJohn Edward Broadbent                                     // Store DBus properties that are also
211*7e860f15SJohn Edward Broadbent                                     // Redfish properties with same name and a
212*7e860f15SJohn Edward Broadbent                                     // string value
213*7e860f15SJohn Edward Broadbent                                     const std::string& propertyName =
214*7e860f15SJohn Edward Broadbent                                         property.first;
215*7e860f15SJohn Edward Broadbent                                     nlohmann::json& object =
216*7e860f15SJohn Edward Broadbent                                         asyncResp->res
217*7e860f15SJohn Edward Broadbent                                             .jsonValue["StorageControllers"]
218*7e860f15SJohn Edward Broadbent                                                       [index];
219*7e860f15SJohn Edward Broadbent                                     if ((propertyName == "PartNumber") ||
220*7e860f15SJohn Edward Broadbent                                         (propertyName == "SerialNumber") ||
221*7e860f15SJohn Edward Broadbent                                         (propertyName == "Manufacturer") ||
222*7e860f15SJohn Edward Broadbent                                         (propertyName == "Model"))
223*7e860f15SJohn Edward Broadbent                                     {
224*7e860f15SJohn Edward Broadbent                                         const std::string* value =
225*7e860f15SJohn Edward Broadbent                                             std::get_if<std::string>(
226*7e860f15SJohn Edward Broadbent                                                 &property.second);
227*7e860f15SJohn Edward Broadbent                                         if (value == nullptr)
228*7e860f15SJohn Edward Broadbent                                         {
229*7e860f15SJohn Edward Broadbent                                             // illegal property
230*7e860f15SJohn Edward Broadbent                                             messages::internalError(
231*7e860f15SJohn Edward Broadbent                                                 asyncResp->res);
232*7e860f15SJohn Edward Broadbent                                             return;
233*7e860f15SJohn Edward Broadbent                                         }
234*7e860f15SJohn Edward Broadbent                                         object[propertyName] = *value;
235*7e860f15SJohn Edward Broadbent                                     }
236*7e860f15SJohn Edward Broadbent                                 }
237*7e860f15SJohn Edward Broadbent                             },
238*7e860f15SJohn Edward Broadbent                             connectionName, path,
239*7e860f15SJohn Edward Broadbent                             "org.freedesktop.DBus.Properties", "GetAll",
240*7e860f15SJohn Edward Broadbent                             "xyz.openbmc_project.Inventory.Decorator.Asset");
241*7e860f15SJohn Edward Broadbent                     }
242*7e860f15SJohn Edward Broadbent 
243*7e860f15SJohn Edward Broadbent                     // this is done after we know the json array will no longer
244*7e860f15SJohn Edward Broadbent                     // be resized, as json::array uses vector underneath and we
245*7e860f15SJohn Edward Broadbent                     // need references to its members that won't change
246*7e860f15SJohn Edward Broadbent                     size_t count = 0;
247*7e860f15SJohn Edward Broadbent                     for (const auto& [path, interfaceDict] : subtree)
248*7e860f15SJohn Edward Broadbent                     {
249*7e860f15SJohn Edward Broadbent                         auto subHealth = std::make_shared<HealthPopulate>(
250*7e860f15SJohn Edward Broadbent                             asyncResp, root[count]["Status"]);
251*7e860f15SJohn Edward Broadbent                         subHealth->inventory.emplace_back(path);
252*7e860f15SJohn Edward Broadbent                         health->inventory.emplace_back(path);
253*7e860f15SJohn Edward Broadbent                         health->children.emplace_back(subHealth);
254*7e860f15SJohn Edward Broadbent                         count++;
255*7e860f15SJohn Edward Broadbent                     }
256*7e860f15SJohn Edward Broadbent                 },
257*7e860f15SJohn Edward Broadbent                 "xyz.openbmc_project.ObjectMapper",
258*7e860f15SJohn Edward Broadbent                 "/xyz/openbmc_project/object_mapper",
259*7e860f15SJohn Edward Broadbent                 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
260*7e860f15SJohn Edward Broadbent                 "/xyz/openbmc_project/inventory", int32_t(0),
261*7e860f15SJohn Edward Broadbent                 std::array<const char*, 1>{
262*7e860f15SJohn Edward Broadbent                     "xyz.openbmc_project.Inventory.Item.StorageController"});
263*7e860f15SJohn Edward Broadbent         });
264*7e860f15SJohn Edward Broadbent }
265*7e860f15SJohn Edward Broadbent 
266*7e860f15SJohn Edward Broadbent inline void requestRoutesDrive(App& app)
267*7e860f15SJohn Edward Broadbent {
268*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Storage/1/Drives/<str>/")
269*7e860f15SJohn Edward Broadbent         .privileges({"Login"})
270*7e860f15SJohn Edward Broadbent         .methods(
271*7e860f15SJohn Edward Broadbent             boost::beast::http::verb::get)([](const crow::Request&,
272*7e860f15SJohn Edward Broadbent                                               const std::shared_ptr<
273*7e860f15SJohn Edward Broadbent                                                   bmcweb::AsyncResp>& asyncResp,
274*7e860f15SJohn Edward Broadbent                                               const std::string& driveId) {
275*7e860f15SJohn Edward Broadbent             crow::connections::systemBus->async_method_call(
276e284a7c1SJames Feist                 [asyncResp,
277*7e860f15SJohn Edward Broadbent                  driveId](const boost::system::error_code ec,
278*7e860f15SJohn Edward Broadbent                           const crow::openbmc_mapper::GetSubTreeType& subtree) {
279*7e860f15SJohn Edward Broadbent                     if (ec)
280*7e860f15SJohn Edward Broadbent                     {
281*7e860f15SJohn Edward Broadbent                         BMCWEB_LOG_ERROR << "Drive mapper call error";
282*7e860f15SJohn Edward Broadbent                         messages::internalError(asyncResp->res);
283*7e860f15SJohn Edward Broadbent                         return;
284*7e860f15SJohn Edward Broadbent                     }
285*7e860f15SJohn Edward Broadbent 
286*7e860f15SJohn Edward Broadbent                     auto object2 = std::find_if(
287*7e860f15SJohn Edward Broadbent                         subtree.begin(), subtree.end(),
288*7e860f15SJohn Edward Broadbent                         [&driveId](auto& object) {
289*7e860f15SJohn Edward Broadbent                             const std::string& path = object.first;
290*7e860f15SJohn Edward Broadbent                             return boost::ends_with(path, "/" + driveId);
291*7e860f15SJohn Edward Broadbent                         });
292*7e860f15SJohn Edward Broadbent 
293*7e860f15SJohn Edward Broadbent                     if (object2 == subtree.end())
294*7e860f15SJohn Edward Broadbent                     {
295*7e860f15SJohn Edward Broadbent                         messages::resourceNotFound(asyncResp->res, "Drive",
296*7e860f15SJohn Edward Broadbent                                                    driveId);
297*7e860f15SJohn Edward Broadbent                         return;
298*7e860f15SJohn Edward Broadbent                     }
299*7e860f15SJohn Edward Broadbent 
300*7e860f15SJohn Edward Broadbent                     const std::string& path = object2->first;
301*7e860f15SJohn Edward Broadbent                     const std::vector<
302*7e860f15SJohn Edward Broadbent                         std::pair<std::string, std::vector<std::string>>>&
303*7e860f15SJohn Edward Broadbent                         connectionNames = object2->second;
304*7e860f15SJohn Edward Broadbent 
305*7e860f15SJohn Edward Broadbent                     asyncResp->res.jsonValue["@odata.type"] =
306*7e860f15SJohn Edward Broadbent                         "#Drive.v1_7_0.Drive";
307*7e860f15SJohn Edward Broadbent                     asyncResp->res.jsonValue["@odata.id"] =
308*7e860f15SJohn Edward Broadbent                         "/redfish/v1/Systems/system/Storage/1/Drives/" +
309*7e860f15SJohn Edward Broadbent                         driveId;
310*7e860f15SJohn Edward Broadbent                     asyncResp->res.jsonValue["Name"] = driveId;
311*7e860f15SJohn Edward Broadbent                     asyncResp->res.jsonValue["Id"] = driveId;
312*7e860f15SJohn Edward Broadbent 
313*7e860f15SJohn Edward Broadbent                     if (connectionNames.size() != 1)
314*7e860f15SJohn Edward Broadbent                     {
315*7e860f15SJohn Edward Broadbent                         BMCWEB_LOG_ERROR << "Connection size "
316*7e860f15SJohn Edward Broadbent                                          << connectionNames.size()
317*7e860f15SJohn Edward Broadbent                                          << ", greater than 1";
318*7e860f15SJohn Edward Broadbent                         messages::internalError(asyncResp->res);
319*7e860f15SJohn Edward Broadbent                         return;
320*7e860f15SJohn Edward Broadbent                     }
321*7e860f15SJohn Edward Broadbent 
322*7e860f15SJohn Edward Broadbent                     getMainChassisId(
323*7e860f15SJohn Edward Broadbent                         asyncResp,
324*7e860f15SJohn Edward Broadbent                         [](const std::string& chassisId,
325*7e860f15SJohn Edward Broadbent                            const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
326*7e860f15SJohn Edward Broadbent                             aRsp->res.jsonValue["Links"]["Chassis"] = {
327*7e860f15SJohn Edward Broadbent                                 {"@odata.id",
328*7e860f15SJohn Edward Broadbent                                  "/redfish/v1/Chassis/" + chassisId}};
329*7e860f15SJohn Edward Broadbent                         });
330*7e860f15SJohn Edward Broadbent 
331*7e860f15SJohn Edward Broadbent                     const std::string& connectionName =
332*7e860f15SJohn Edward Broadbent                         connectionNames[0].first;
333*7e860f15SJohn Edward Broadbent                     crow::connections::systemBus->async_method_call(
334*7e860f15SJohn Edward Broadbent                         [asyncResp](
335*7e860f15SJohn Edward Broadbent                             const boost::system::error_code ec2,
336e284a7c1SJames Feist                             const std::vector<std::pair<
337e284a7c1SJames Feist                                 std::string,
3381214b7e7SGunnar Mills                                 std::variant<bool, std::string, uint64_t>>>&
3391214b7e7SGunnar Mills                                 propertiesList) {
34023a21a1cSEd Tanous                             if (ec2)
341e284a7c1SJames Feist                             {
342e284a7c1SJames Feist                                 // this interface isn't necessary
343e284a7c1SJames Feist                                 return;
344e284a7c1SJames Feist                             }
345e284a7c1SJames Feist                             for (const std::pair<
346e284a7c1SJames Feist                                      std::string,
3471214b7e7SGunnar Mills                                      std::variant<bool, std::string, uint64_t>>&
3481214b7e7SGunnar Mills                                      property : propertiesList)
349e284a7c1SJames Feist                             {
350e284a7c1SJames Feist                                 // Store DBus properties that are also
351e284a7c1SJames Feist                                 // Redfish properties with same name and a
352e284a7c1SJames Feist                                 // string value
353e284a7c1SJames Feist                                 const std::string& propertyName =
354e284a7c1SJames Feist                                     property.first;
355e284a7c1SJames Feist                                 if ((propertyName == "PartNumber") ||
356e284a7c1SJames Feist                                     (propertyName == "SerialNumber") ||
357e284a7c1SJames Feist                                     (propertyName == "Manufacturer") ||
358e284a7c1SJames Feist                                     (propertyName == "Model"))
359e284a7c1SJames Feist                                 {
360e284a7c1SJames Feist                                     const std::string* value =
361e284a7c1SJames Feist                                         std::get_if<std::string>(
362e284a7c1SJames Feist                                             &property.second);
363e284a7c1SJames Feist                                     if (value == nullptr)
364e284a7c1SJames Feist                                     {
365e284a7c1SJames Feist                                         // illegal property
366e284a7c1SJames Feist                                         messages::internalError(asyncResp->res);
367601af5edSChicago Duan                                         return;
368e284a7c1SJames Feist                                     }
369*7e860f15SJohn Edward Broadbent                                     asyncResp->res.jsonValue[propertyName] =
370*7e860f15SJohn Edward Broadbent                                         *value;
371e284a7c1SJames Feist                                 }
372e284a7c1SJames Feist                             }
373e284a7c1SJames Feist                         },
374e284a7c1SJames Feist                         connectionName, path, "org.freedesktop.DBus.Properties",
375e284a7c1SJames Feist                         "GetAll",
376e284a7c1SJames Feist                         "xyz.openbmc_project.Inventory.Decorator.Asset");
377a25aeccfSNikhil Potade 
378a25aeccfSNikhil Potade                     // default it to Enabled
379a25aeccfSNikhil Potade                     asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
380a25aeccfSNikhil Potade 
3812ad9c2f6SJames Feist                     auto health = std::make_shared<HealthPopulate>(asyncResp);
382e284a7c1SJames Feist                     health->inventory.emplace_back(path);
3832ad9c2f6SJames Feist                     health->populate();
3842ad9c2f6SJames Feist 
385a25aeccfSNikhil Potade                     crow::connections::systemBus->async_method_call(
386cb13a392SEd Tanous                         [asyncResp, path](const boost::system::error_code ec2,
387a25aeccfSNikhil Potade                                           const std::variant<bool> present) {
388*7e860f15SJohn Edward Broadbent                             // this interface isn't necessary, only check it if
389*7e860f15SJohn Edward Broadbent                             // we get a good return
390cb13a392SEd Tanous                             if (ec2)
391a25aeccfSNikhil Potade                             {
3922ad9c2f6SJames Feist                                 return;
3932ad9c2f6SJames Feist                             }
394a25aeccfSNikhil Potade                             const bool* enabled = std::get_if<bool>(&present);
395a25aeccfSNikhil Potade                             if (enabled == nullptr)
396a25aeccfSNikhil Potade                             {
397a25aeccfSNikhil Potade                                 BMCWEB_LOG_DEBUG << "Illegal property present";
398a25aeccfSNikhil Potade                                 messages::internalError(asyncResp->res);
399a25aeccfSNikhil Potade                                 return;
400a25aeccfSNikhil Potade                             }
401a25aeccfSNikhil Potade                             if (!(*enabled))
402a25aeccfSNikhil Potade                             {
403a25aeccfSNikhil Potade                                 asyncResp->res.jsonValue["Status"]["State"] =
404a25aeccfSNikhil Potade                                     "Disabled";
405a25aeccfSNikhil Potade                             }
406a25aeccfSNikhil Potade                         },
407a25aeccfSNikhil Potade                         connectionName, path, "org.freedesktop.DBus.Properties",
408a25aeccfSNikhil Potade                         "Get", "xyz.openbmc_project.Inventory.Item", "Present");
40922984074SJames Feist 
41022984074SJames Feist                     crow::connections::systemBus->async_method_call(
411cb13a392SEd Tanous                         [asyncResp](const boost::system::error_code ec2,
41222984074SJames Feist                                     const std::variant<bool> rebuilding) {
413*7e860f15SJohn Edward Broadbent                             // this interface isn't necessary, only check it if
414*7e860f15SJohn Edward Broadbent                             // we get a good return
415cb13a392SEd Tanous                             if (ec2)
41622984074SJames Feist                             {
41722984074SJames Feist                                 return;
41822984074SJames Feist                             }
419*7e860f15SJohn Edward Broadbent                             const bool* updating =
420*7e860f15SJohn Edward Broadbent                                 std::get_if<bool>(&rebuilding);
42122984074SJames Feist                             if (updating == nullptr)
42222984074SJames Feist                             {
42322984074SJames Feist                                 BMCWEB_LOG_DEBUG << "Illegal property present";
42422984074SJames Feist                                 messages::internalError(asyncResp->res);
42522984074SJames Feist                                 return;
42622984074SJames Feist                             }
42722984074SJames Feist 
42822984074SJames Feist                             // updating and disabled in the backend shouldn't be
429*7e860f15SJohn Edward Broadbent                             // able to be set at the same time, so we don't need
430*7e860f15SJohn Edward Broadbent                             // to check for the race condition of these two
431*7e860f15SJohn Edward Broadbent                             // calls
43222984074SJames Feist                             if ((*updating))
43322984074SJames Feist                             {
43422984074SJames Feist                                 asyncResp->res.jsonValue["Status"]["State"] =
43522984074SJames Feist                                     "Updating";
43622984074SJames Feist                             }
43722984074SJames Feist                         },
43822984074SJames Feist                         connectionName, path, "org.freedesktop.DBus.Properties",
43922984074SJames Feist                         "Get", "xyz.openbmc_project.State.Drive", "Rebuilding");
440a25aeccfSNikhil Potade                 },
441a25aeccfSNikhil Potade                 "xyz.openbmc_project.ObjectMapper",
442a25aeccfSNikhil Potade                 "/xyz/openbmc_project/object_mapper",
443a25aeccfSNikhil Potade                 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
444a25aeccfSNikhil Potade                 "/xyz/openbmc_project/inventory", int32_t(0),
445a25aeccfSNikhil Potade                 std::array<const char*, 1>{
446a25aeccfSNikhil Potade                     "xyz.openbmc_project.Inventory.Item.Drive"});
447*7e860f15SJohn Edward Broadbent         });
448a25aeccfSNikhil Potade }
449a25aeccfSNikhil Potade } // namespace redfish
450