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