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