xref: /openbmc/bmcweb/features/redfish/lib/storage.hpp (revision cb13a39253848ece442971301ade9c09d98bf08e)
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 
21a25aeccfSNikhil Potade #include <node.hpp>
22a25aeccfSNikhil Potade 
23a25aeccfSNikhil Potade namespace redfish
24a25aeccfSNikhil Potade {
25a25aeccfSNikhil Potade class StorageCollection : public Node
26a25aeccfSNikhil Potade {
27a25aeccfSNikhil Potade   public:
2852cc112dSEd Tanous     StorageCollection(App& app) :
29a25aeccfSNikhil Potade         Node(app, "/redfish/v1/Systems/system/Storage/")
30a25aeccfSNikhil Potade     {
31a25aeccfSNikhil Potade         entityPrivileges = {
32a25aeccfSNikhil Potade             {boost::beast::http::verb::get, {{"Login"}}},
33a25aeccfSNikhil Potade             {boost::beast::http::verb::head, {{"Login"}}},
34a25aeccfSNikhil Potade             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
35a25aeccfSNikhil Potade             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
36a25aeccfSNikhil Potade             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
37a25aeccfSNikhil Potade             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
38a25aeccfSNikhil Potade     }
39a25aeccfSNikhil Potade 
40a25aeccfSNikhil Potade   private:
41*cb13a392SEd Tanous     void doGet(crow::Response& res, const crow::Request&,
42*cb13a392SEd Tanous                const std::vector<std::string>&) override
43a25aeccfSNikhil Potade     {
44a25aeccfSNikhil Potade         res.jsonValue["@odata.type"] = "#StorageCollection.StorageCollection";
45a25aeccfSNikhil Potade         res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system/Storage";
46a25aeccfSNikhil Potade         res.jsonValue["Name"] = "Storage Collection";
47a25aeccfSNikhil Potade         res.jsonValue["Members"] = {
48a25aeccfSNikhil Potade             {{"@odata.id", "/redfish/v1/Systems/system/Storage/1"}}};
49a25aeccfSNikhil Potade         res.jsonValue["Members@odata.count"] = 1;
50a25aeccfSNikhil Potade         res.end();
51a25aeccfSNikhil Potade     }
52a25aeccfSNikhil Potade };
53a25aeccfSNikhil Potade 
54a25aeccfSNikhil Potade class Storage : public Node
55a25aeccfSNikhil Potade {
56a25aeccfSNikhil Potade   public:
5752cc112dSEd Tanous     Storage(App& app) : Node(app, "/redfish/v1/Systems/system/Storage/1/")
58a25aeccfSNikhil Potade     {
59a25aeccfSNikhil Potade         entityPrivileges = {
60a25aeccfSNikhil Potade             {boost::beast::http::verb::get, {{"Login"}}},
61a25aeccfSNikhil Potade             {boost::beast::http::verb::head, {{"Login"}}},
62a25aeccfSNikhil Potade             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
63a25aeccfSNikhil Potade             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
64a25aeccfSNikhil Potade             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
65a25aeccfSNikhil Potade             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
66a25aeccfSNikhil Potade     }
67a25aeccfSNikhil Potade 
68a25aeccfSNikhil Potade   private:
69*cb13a392SEd Tanous     void doGet(crow::Response& res, const crow::Request&,
70*cb13a392SEd Tanous                const std::vector<std::string>&) override
71a25aeccfSNikhil Potade     {
72a25aeccfSNikhil Potade         res.jsonValue["@odata.type"] = "#Storage.v1_7_1.Storage";
73a25aeccfSNikhil Potade         res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system/Storage/1";
74e284a7c1SJames Feist         res.jsonValue["Name"] = "Storage";
75a25aeccfSNikhil Potade         res.jsonValue["Id"] = "1";
762ad9c2f6SJames Feist         res.jsonValue["Status"]["State"] = "Enabled";
77a25aeccfSNikhil Potade 
78a25aeccfSNikhil Potade         auto asyncResp = std::make_shared<AsyncResp>(res);
79e284a7c1SJames Feist         auto health = std::make_shared<HealthPopulate>(asyncResp);
80e284a7c1SJames Feist         health->populate();
81e284a7c1SJames Feist 
82a25aeccfSNikhil Potade         crow::connections::systemBus->async_method_call(
83e284a7c1SJames Feist             [asyncResp, health](const boost::system::error_code ec,
84a25aeccfSNikhil Potade                                 const std::vector<std::string>& storageList) {
85a25aeccfSNikhil Potade                 nlohmann::json& storageArray =
86a25aeccfSNikhil Potade                     asyncResp->res.jsonValue["Drives"];
87a25aeccfSNikhil Potade                 storageArray = nlohmann::json::array();
88e284a7c1SJames Feist                 auto& count = asyncResp->res.jsonValue["Drives@odata.count"];
89e284a7c1SJames Feist                 count = 0;
902ad9c2f6SJames Feist 
91a25aeccfSNikhil Potade                 if (ec)
92a25aeccfSNikhil Potade                 {
93a25aeccfSNikhil Potade                     BMCWEB_LOG_ERROR << "Drive mapper call error";
94a25aeccfSNikhil Potade                     messages::internalError(asyncResp->res);
95a25aeccfSNikhil Potade                     return;
96a25aeccfSNikhil Potade                 }
972ad9c2f6SJames Feist 
98e284a7c1SJames Feist                 health->inventory.insert(health->inventory.end(),
99e284a7c1SJames Feist                                          storageList.begin(),
100e284a7c1SJames Feist                                          storageList.end());
1012ad9c2f6SJames Feist 
102a25aeccfSNikhil Potade                 for (const std::string& objpath : storageList)
103a25aeccfSNikhil Potade                 {
104a25aeccfSNikhil Potade                     std::size_t lastPos = objpath.rfind("/");
105a25aeccfSNikhil Potade                     if (lastPos == std::string::npos ||
106a25aeccfSNikhil Potade                         (objpath.size() <= lastPos + 1))
107a25aeccfSNikhil Potade                     {
108a25aeccfSNikhil Potade                         BMCWEB_LOG_ERROR << "Failed to find '/' in " << objpath;
109a25aeccfSNikhil Potade                         continue;
110a25aeccfSNikhil Potade                     }
111a25aeccfSNikhil Potade 
112a25aeccfSNikhil Potade                     storageArray.push_back(
113a25aeccfSNikhil Potade                         {{"@odata.id",
114be13ceceSJames Feist                           "/redfish/v1/Systems/system/Storage/1/Drives/" +
115a25aeccfSNikhil Potade                               objpath.substr(lastPos + 1)}});
116a25aeccfSNikhil Potade                 }
117a25aeccfSNikhil Potade 
118e284a7c1SJames Feist                 count = storageArray.size();
119a25aeccfSNikhil Potade             },
120a25aeccfSNikhil Potade             "xyz.openbmc_project.ObjectMapper",
121a25aeccfSNikhil Potade             "/xyz/openbmc_project/object_mapper",
122a25aeccfSNikhil Potade             "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
123a25aeccfSNikhil Potade             "/xyz/openbmc_project/inventory", int32_t(0),
124a25aeccfSNikhil Potade             std::array<const char*, 1>{
125a25aeccfSNikhil Potade                 "xyz.openbmc_project.Inventory.Item.Drive"});
126e284a7c1SJames Feist 
127e284a7c1SJames Feist         crow::connections::systemBus->async_method_call(
128e284a7c1SJames Feist             [asyncResp,
129e284a7c1SJames Feist              health](const boost::system::error_code ec,
130e284a7c1SJames Feist                      const crow::openbmc_mapper::GetSubTreeType& subtree) {
131e284a7c1SJames Feist                 if (ec || !subtree.size())
132e284a7c1SJames Feist                 {
133d819a420SJames Feist                     // doesn't have to be there
134e284a7c1SJames Feist                     return;
135e284a7c1SJames Feist                 }
136e284a7c1SJames Feist 
137e284a7c1SJames Feist                 nlohmann::json& root =
138e284a7c1SJames Feist                     asyncResp->res.jsonValue["StorageControllers"];
139e284a7c1SJames Feist                 root = nlohmann::json::array();
140e284a7c1SJames Feist                 for (const auto& [path, interfaceDict] : subtree)
141e284a7c1SJames Feist                 {
142e284a7c1SJames Feist                     std::size_t lastPos = path.rfind("/");
143e284a7c1SJames Feist                     if (lastPos == std::string::npos ||
144e284a7c1SJames Feist                         (path.size() <= lastPos + 1))
145e284a7c1SJames Feist                     {
146e284a7c1SJames Feist                         BMCWEB_LOG_ERROR << "Failed to find '/' in " << path;
147e284a7c1SJames Feist                         return;
148e284a7c1SJames Feist                     }
149e284a7c1SJames Feist 
150e284a7c1SJames Feist                     if (interfaceDict.size() != 1)
151e284a7c1SJames Feist                     {
152e284a7c1SJames Feist                         BMCWEB_LOG_ERROR << "Connection size "
153e284a7c1SJames Feist                                          << interfaceDict.size()
154e284a7c1SJames Feist                                          << ", greater than 1";
155e284a7c1SJames Feist                         messages::internalError(asyncResp->res);
156e284a7c1SJames Feist                         return;
157e284a7c1SJames Feist                     }
158e284a7c1SJames Feist 
159e284a7c1SJames Feist                     const std::string& connectionName =
160e284a7c1SJames Feist                         interfaceDict.front().first;
161e284a7c1SJames Feist 
162e284a7c1SJames Feist                     size_t index = root.size();
163e284a7c1SJames Feist                     nlohmann::json& storageController =
164e284a7c1SJames Feist                         root.emplace_back(nlohmann::json::object());
165e284a7c1SJames Feist 
166e284a7c1SJames Feist                     std::string id = path.substr(lastPos + 1);
167e284a7c1SJames Feist 
168e284a7c1SJames Feist                     storageController["@odata.type"] =
169e284a7c1SJames Feist                         "#Storage.v1_7_0.StorageController";
170e284a7c1SJames Feist                     storageController["@odata.id"] =
171e284a7c1SJames Feist                         "/redfish/v1/Systems/system/Storage/1"
172e284a7c1SJames Feist                         "#/StorageControllers/" +
173e284a7c1SJames Feist                         std::to_string(index);
174e284a7c1SJames Feist                     storageController["Name"] = id;
175e284a7c1SJames Feist                     storageController["MemberId"] = id;
176e284a7c1SJames Feist                     storageController["Status"]["State"] = "Enabled";
177e284a7c1SJames Feist 
178e284a7c1SJames Feist                     crow::connections::systemBus->async_method_call(
17923a21a1cSEd Tanous                         [asyncResp, index](const boost::system::error_code ec2,
180e284a7c1SJames Feist                                            const std::variant<bool> present) {
181e284a7c1SJames Feist                             // this interface isn't necessary, only check it if
182e284a7c1SJames Feist                             // we get a good return
18323a21a1cSEd Tanous                             if (ec2)
184e284a7c1SJames Feist                             {
185e284a7c1SJames Feist                                 return;
186e284a7c1SJames Feist                             }
187e284a7c1SJames Feist                             const bool* enabled = std::get_if<bool>(&present);
188e284a7c1SJames Feist                             if (enabled == nullptr)
189e284a7c1SJames Feist                             {
190e284a7c1SJames Feist                                 BMCWEB_LOG_DEBUG << "Illegal property present";
191e284a7c1SJames Feist                                 messages::internalError(asyncResp->res);
192e284a7c1SJames Feist                                 return;
193e284a7c1SJames Feist                             }
194e284a7c1SJames Feist                             if (!(*enabled))
195e284a7c1SJames Feist                             {
196e284a7c1SJames Feist                                 asyncResp->res
197e284a7c1SJames Feist                                     .jsonValue["StorageControllers"][index]
198e284a7c1SJames Feist                                               ["Status"]["State"] = "Disabled";
199e284a7c1SJames Feist                             }
200e284a7c1SJames Feist                         },
201e284a7c1SJames Feist                         connectionName, path, "org.freedesktop.DBus.Properties",
202e284a7c1SJames Feist                         "Get", "xyz.openbmc_project.Inventory.Item", "Present");
203e284a7c1SJames Feist 
204e284a7c1SJames Feist                     crow::connections::systemBus->async_method_call(
205e284a7c1SJames Feist                         [asyncResp,
20623a21a1cSEd Tanous                          index](const boost::system::error_code ec2,
207e284a7c1SJames Feist                                 const std::vector<std::pair<
208e284a7c1SJames Feist                                     std::string,
2091214b7e7SGunnar Mills                                     std::variant<bool, std::string, uint64_t>>>&
2101214b7e7SGunnar Mills                                     propertiesList) {
21123a21a1cSEd Tanous                             if (ec2)
212e284a7c1SJames Feist                             {
213e284a7c1SJames Feist                                 // this interface isn't necessary
214e284a7c1SJames Feist                                 return;
215e284a7c1SJames Feist                             }
216e284a7c1SJames Feist                             for (const std::pair<
217e284a7c1SJames Feist                                      std::string,
2181214b7e7SGunnar Mills                                      std::variant<bool, std::string, uint64_t>>&
2191214b7e7SGunnar Mills                                      property : propertiesList)
220e284a7c1SJames Feist                             {
221e284a7c1SJames Feist                                 // Store DBus properties that are also
222e284a7c1SJames Feist                                 // Redfish properties with same name and a
223e284a7c1SJames Feist                                 // string value
224e284a7c1SJames Feist                                 const std::string& propertyName =
225e284a7c1SJames Feist                                     property.first;
226e284a7c1SJames Feist                                 nlohmann::json& object =
227e284a7c1SJames Feist                                     asyncResp->res
228e284a7c1SJames Feist                                         .jsonValue["StorageControllers"][index];
229e284a7c1SJames Feist                                 if ((propertyName == "PartNumber") ||
230e284a7c1SJames Feist                                     (propertyName == "SerialNumber") ||
231e284a7c1SJames Feist                                     (propertyName == "Manufacturer") ||
232e284a7c1SJames Feist                                     (propertyName == "Model"))
233e284a7c1SJames Feist                                 {
234e284a7c1SJames Feist                                     const std::string* value =
235e284a7c1SJames Feist                                         std::get_if<std::string>(
236e284a7c1SJames Feist                                             &property.second);
237e284a7c1SJames Feist                                     if (value == nullptr)
238e284a7c1SJames Feist                                     {
239e284a7c1SJames Feist                                         // illegal property
240e284a7c1SJames Feist                                         messages::internalError(asyncResp->res);
241e284a7c1SJames Feist                                         continue;
242e284a7c1SJames Feist                                     }
243e284a7c1SJames Feist                                     object[propertyName] = *value;
244e284a7c1SJames Feist                                 }
245e284a7c1SJames Feist                             }
246e284a7c1SJames Feist                         },
247e284a7c1SJames Feist                         connectionName, path, "org.freedesktop.DBus.Properties",
248e284a7c1SJames Feist                         "GetAll",
249e284a7c1SJames Feist                         "xyz.openbmc_project.Inventory.Decorator.Asset");
250e284a7c1SJames Feist                 }
251e284a7c1SJames Feist 
252e284a7c1SJames Feist                 // this is done after we know the json array will no longer be
253e284a7c1SJames Feist                 // resized, as json::array uses vector underneath and we need
254e284a7c1SJames Feist                 // references to its members that won't change
255e284a7c1SJames Feist                 size_t count = 0;
256e284a7c1SJames Feist                 for (const auto& [path, interfaceDict] : subtree)
257e284a7c1SJames Feist                 {
258e284a7c1SJames Feist                     auto subHealth = std::make_shared<HealthPopulate>(
259e284a7c1SJames Feist                         asyncResp, root[count]["Status"]);
260e284a7c1SJames Feist                     subHealth->inventory.emplace_back(path);
261e284a7c1SJames Feist                     health->inventory.emplace_back(path);
262e284a7c1SJames Feist                     health->children.emplace_back(subHealth);
263e284a7c1SJames Feist                     count++;
264e284a7c1SJames Feist                 }
265e284a7c1SJames Feist             },
266e284a7c1SJames Feist             "xyz.openbmc_project.ObjectMapper",
267e284a7c1SJames Feist             "/xyz/openbmc_project/object_mapper",
268e284a7c1SJames Feist             "xyz.openbmc_project.ObjectMapper", "GetSubTree",
269e284a7c1SJames Feist             "/xyz/openbmc_project/inventory", int32_t(0),
270e284a7c1SJames Feist             std::array<const char*, 1>{
271e284a7c1SJames Feist                 "xyz.openbmc_project.Inventory.Item.StorageController"});
272a25aeccfSNikhil Potade     }
273a25aeccfSNikhil Potade };
274a25aeccfSNikhil Potade 
275a25aeccfSNikhil Potade class Drive : public Node
276a25aeccfSNikhil Potade {
277a25aeccfSNikhil Potade   public:
27852cc112dSEd Tanous     Drive(App& app) :
279be13ceceSJames Feist         Node(app, "/redfish/v1/Systems/system/Storage/1/Drives/<str>/",
280a25aeccfSNikhil Potade              std::string())
281a25aeccfSNikhil Potade     {
282a25aeccfSNikhil Potade         entityPrivileges = {
283a25aeccfSNikhil Potade             {boost::beast::http::verb::get, {{"Login"}}},
284a25aeccfSNikhil Potade             {boost::beast::http::verb::head, {{"Login"}}},
285a25aeccfSNikhil Potade             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
286a25aeccfSNikhil Potade             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
287a25aeccfSNikhil Potade             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
288a25aeccfSNikhil Potade             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
289a25aeccfSNikhil Potade     }
290a25aeccfSNikhil Potade 
291a25aeccfSNikhil Potade   private:
292*cb13a392SEd Tanous     void doGet(crow::Response& res, const crow::Request&,
293a25aeccfSNikhil Potade                const std::vector<std::string>& params) override
294a25aeccfSNikhil Potade     {
295e284a7c1SJames Feist         auto asyncResp = std::make_shared<AsyncResp>(res);
296e284a7c1SJames Feist         if (params.size() != 1)
297e284a7c1SJames Feist         {
298e284a7c1SJames Feist             messages::internalError(asyncResp->res);
299e284a7c1SJames Feist             return;
300e284a7c1SJames Feist         }
301a25aeccfSNikhil Potade         const std::string& driveId = params[0];
302a25aeccfSNikhil Potade 
303a25aeccfSNikhil Potade         crow::connections::systemBus->async_method_call(
304e284a7c1SJames Feist             [asyncResp,
305e284a7c1SJames Feist              driveId](const boost::system::error_code ec,
306e284a7c1SJames Feist                       const crow::openbmc_mapper::GetSubTreeType& subtree) {
307a25aeccfSNikhil Potade                 if (ec)
308a25aeccfSNikhil Potade                 {
309a25aeccfSNikhil Potade                     BMCWEB_LOG_ERROR << "Drive mapper call error";
310a25aeccfSNikhil Potade                     messages::internalError(asyncResp->res);
311a25aeccfSNikhil Potade                     return;
312a25aeccfSNikhil Potade                 }
313a25aeccfSNikhil Potade 
31423a21a1cSEd Tanous                 auto object2 = std::find_if(
315a25aeccfSNikhil Potade                     subtree.begin(), subtree.end(), [&driveId](auto& object) {
316a25aeccfSNikhil Potade                         const std::string& path = object.first;
317a25aeccfSNikhil Potade                         return boost::ends_with(path, "/" + driveId);
318a25aeccfSNikhil Potade                     });
319a25aeccfSNikhil Potade 
32023a21a1cSEd Tanous                 if (object2 == subtree.end())
321a25aeccfSNikhil Potade                 {
322a25aeccfSNikhil Potade                     messages::resourceNotFound(asyncResp->res, "Drive",
323a25aeccfSNikhil Potade                                                driveId);
324a25aeccfSNikhil Potade                     return;
325a25aeccfSNikhil Potade                 }
326a25aeccfSNikhil Potade 
32723a21a1cSEd Tanous                 const std::string& path = object2->first;
328a25aeccfSNikhil Potade                 const std::vector<
3291214b7e7SGunnar Mills                     std::pair<std::string, std::vector<std::string>>>&
33023a21a1cSEd Tanous                     connectionNames = object2->second;
331a25aeccfSNikhil Potade 
332a25aeccfSNikhil Potade                 asyncResp->res.jsonValue["@odata.type"] = "#Drive.v1_7_0.Drive";
333a25aeccfSNikhil Potade                 asyncResp->res.jsonValue["@odata.id"] =
334be13ceceSJames Feist                     "/redfish/v1/Systems/system/Storage/1/Drives/" + driveId;
3352ad9c2f6SJames Feist                 asyncResp->res.jsonValue["Name"] = driveId;
3362ad9c2f6SJames Feist                 asyncResp->res.jsonValue["Id"] = driveId;
337a25aeccfSNikhil Potade 
338a25aeccfSNikhil Potade                 if (connectionNames.size() != 1)
339a25aeccfSNikhil Potade                 {
340a25aeccfSNikhil Potade                     BMCWEB_LOG_ERROR << "Connection size "
341a25aeccfSNikhil Potade                                      << connectionNames.size()
342a25aeccfSNikhil Potade                                      << ", greater than 1";
343a25aeccfSNikhil Potade                     messages::internalError(asyncResp->res);
344a25aeccfSNikhil Potade                     return;
345a25aeccfSNikhil Potade                 }
346a25aeccfSNikhil Potade 
347a25aeccfSNikhil Potade                 getMainChassisId(
348a25aeccfSNikhil Potade                     asyncResp, [](const std::string& chassisId,
349a25aeccfSNikhil Potade                                   std::shared_ptr<AsyncResp> aRsp) {
350a25aeccfSNikhil Potade                         aRsp->res.jsonValue["Links"]["Chassis"] = {
351a25aeccfSNikhil Potade                             {"@odata.id", "/redfish/v1/Chassis/" + chassisId}};
352a25aeccfSNikhil Potade                     });
353a25aeccfSNikhil Potade 
354a25aeccfSNikhil Potade                 const std::string& connectionName = connectionNames[0].first;
355a25aeccfSNikhil Potade                 crow::connections::systemBus->async_method_call(
356*cb13a392SEd Tanous                     [asyncResp](const boost::system::error_code ec2,
357a25aeccfSNikhil Potade                                 const std::vector<std::pair<
358a25aeccfSNikhil Potade                                     std::string,
3591214b7e7SGunnar Mills                                     std::variant<bool, std::string, uint64_t>>>&
3601214b7e7SGunnar Mills                                     propertiesList) {
361*cb13a392SEd Tanous                         if (ec2)
362a25aeccfSNikhil Potade                         {
363a25aeccfSNikhil Potade                             // this interface isn't necessary
364a25aeccfSNikhil Potade                             return;
365a25aeccfSNikhil Potade                         }
366a25aeccfSNikhil Potade                         for (const std::pair<std::string,
367a25aeccfSNikhil Potade                                              std::variant<bool, std::string,
368a25aeccfSNikhil Potade                                                           uint64_t>>& property :
369a25aeccfSNikhil Potade                              propertiesList)
370a25aeccfSNikhil Potade                         {
371a25aeccfSNikhil Potade                             // Store DBus properties that are also
372a25aeccfSNikhil Potade                             // Redfish properties with same name and a
373a25aeccfSNikhil Potade                             // string value
374a25aeccfSNikhil Potade                             const std::string& propertyName = property.first;
375a25aeccfSNikhil Potade                             if ((propertyName == "PartNumber") ||
376a25aeccfSNikhil Potade                                 (propertyName == "SerialNumber") ||
377a25aeccfSNikhil Potade                                 (propertyName == "Manufacturer") ||
378a25aeccfSNikhil Potade                                 (propertyName == "Model"))
379a25aeccfSNikhil Potade                             {
380a25aeccfSNikhil Potade                                 const std::string* value =
381a25aeccfSNikhil Potade                                     std::get_if<std::string>(&property.second);
382a25aeccfSNikhil Potade                                 if (value == nullptr)
383a25aeccfSNikhil Potade                                 {
384a25aeccfSNikhil Potade                                     // illegal property
385a25aeccfSNikhil Potade                                     messages::internalError(asyncResp->res);
386a25aeccfSNikhil Potade                                     continue;
387a25aeccfSNikhil Potade                                 }
388a25aeccfSNikhil Potade                                 asyncResp->res.jsonValue[propertyName] = *value;
389a25aeccfSNikhil Potade                             }
390a25aeccfSNikhil Potade                         }
391a25aeccfSNikhil Potade                     },
392a25aeccfSNikhil Potade                     connectionName, path, "org.freedesktop.DBus.Properties",
393a25aeccfSNikhil Potade                     "GetAll", "xyz.openbmc_project.Inventory.Decorator.Asset");
394a25aeccfSNikhil Potade 
395a25aeccfSNikhil Potade                 // default it to Enabled
396a25aeccfSNikhil Potade                 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
397a25aeccfSNikhil Potade 
3982ad9c2f6SJames Feist                 auto health = std::make_shared<HealthPopulate>(asyncResp);
399e284a7c1SJames Feist                 health->inventory.emplace_back(path);
4002ad9c2f6SJames Feist                 health->populate();
4012ad9c2f6SJames Feist 
402a25aeccfSNikhil Potade                 crow::connections::systemBus->async_method_call(
403*cb13a392SEd Tanous                     [asyncResp, path](const boost::system::error_code ec2,
404a25aeccfSNikhil Potade                                       const std::variant<bool> present) {
405a25aeccfSNikhil Potade                         // this interface isn't necessary, only check it if we
406a25aeccfSNikhil Potade                         // get a good return
407*cb13a392SEd Tanous                         if (ec2)
408a25aeccfSNikhil Potade                         {
4092ad9c2f6SJames Feist                             return;
4102ad9c2f6SJames Feist                         }
411a25aeccfSNikhil Potade                         const bool* enabled = std::get_if<bool>(&present);
412a25aeccfSNikhil Potade                         if (enabled == nullptr)
413a25aeccfSNikhil Potade                         {
414a25aeccfSNikhil Potade                             BMCWEB_LOG_DEBUG << "Illegal property present";
415a25aeccfSNikhil Potade                             messages::internalError(asyncResp->res);
416a25aeccfSNikhil Potade                             return;
417a25aeccfSNikhil Potade                         }
418a25aeccfSNikhil Potade                         if (!(*enabled))
419a25aeccfSNikhil Potade                         {
420a25aeccfSNikhil Potade                             asyncResp->res.jsonValue["Status"]["State"] =
421a25aeccfSNikhil Potade                                 "Disabled";
422a25aeccfSNikhil Potade                         }
423a25aeccfSNikhil Potade                     },
424a25aeccfSNikhil Potade                     connectionName, path, "org.freedesktop.DBus.Properties",
425a25aeccfSNikhil Potade                     "Get", "xyz.openbmc_project.Inventory.Item", "Present");
42622984074SJames Feist 
42722984074SJames Feist                 crow::connections::systemBus->async_method_call(
428*cb13a392SEd Tanous                     [asyncResp](const boost::system::error_code ec2,
42922984074SJames Feist                                 const std::variant<bool> rebuilding) {
43022984074SJames Feist                         // this interface isn't necessary, only check it if we
43122984074SJames Feist                         // get a good return
432*cb13a392SEd Tanous                         if (ec2)
43322984074SJames Feist                         {
43422984074SJames Feist                             return;
43522984074SJames Feist                         }
43622984074SJames Feist                         const bool* updating = std::get_if<bool>(&rebuilding);
43722984074SJames Feist                         if (updating == nullptr)
43822984074SJames Feist                         {
43922984074SJames Feist                             BMCWEB_LOG_DEBUG << "Illegal property present";
44022984074SJames Feist                             messages::internalError(asyncResp->res);
44122984074SJames Feist                             return;
44222984074SJames Feist                         }
44322984074SJames Feist 
44422984074SJames Feist                         // updating and disabled in the backend shouldn't be
44522984074SJames Feist                         // able to be set at the same time, so we don't need to
44622984074SJames Feist                         // check for the race condition of these two calls
44722984074SJames Feist                         if ((*updating))
44822984074SJames Feist                         {
44922984074SJames Feist                             asyncResp->res.jsonValue["Status"]["State"] =
45022984074SJames Feist                                 "Updating";
45122984074SJames Feist                         }
45222984074SJames Feist                     },
45322984074SJames Feist                     connectionName, path, "org.freedesktop.DBus.Properties",
45422984074SJames Feist                     "Get", "xyz.openbmc_project.State.Drive", "Rebuilding");
455a25aeccfSNikhil Potade             },
456a25aeccfSNikhil Potade             "xyz.openbmc_project.ObjectMapper",
457a25aeccfSNikhil Potade             "/xyz/openbmc_project/object_mapper",
458a25aeccfSNikhil Potade             "xyz.openbmc_project.ObjectMapper", "GetSubTree",
459a25aeccfSNikhil Potade             "/xyz/openbmc_project/inventory", int32_t(0),
460a25aeccfSNikhil Potade             std::array<const char*, 1>{
461a25aeccfSNikhil Potade                 "xyz.openbmc_project.Inventory.Item.Drive"});
462a25aeccfSNikhil Potade     }
463a25aeccfSNikhil Potade };
464a25aeccfSNikhil Potade } // namespace redfish
465