xref: /openbmc/bmcweb/redfish-core/lib/chassis.hpp (revision 10f270b4)
1 /*
2 // Copyright (c) 2018 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16 #pragma once
17 
18 #include "health.hpp"
19 #include "led.hpp"
20 #include "node.hpp"
21 
22 #include <boost/container/flat_map.hpp>
23 #include <utils/collection.hpp>
24 
25 #include <variant>
26 
27 namespace redfish
28 {
29 
30 /**
31  * @brief Retrieves chassis state properties over dbus
32  *
33  * @param[in] aResp - Shared pointer for completing asynchronous calls.
34  *
35  * @return None.
36  */
37 inline void getChassisState(std::shared_ptr<bmcweb::AsyncResp> aResp)
38 {
39     crow::connections::systemBus->async_method_call(
40         [aResp{std::move(aResp)}](
41             const boost::system::error_code ec,
42             const std::variant<std::string>& chassisState) {
43             if (ec)
44             {
45                 BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
46                 messages::internalError(aResp->res);
47                 return;
48             }
49 
50             const std::string* s = std::get_if<std::string>(&chassisState);
51             BMCWEB_LOG_DEBUG << "Chassis state: " << *s;
52             if (s != nullptr)
53             {
54                 // Verify Chassis State
55                 if (*s == "xyz.openbmc_project.State.Chassis.PowerState.On")
56                 {
57                     aResp->res.jsonValue["PowerState"] = "On";
58                     aResp->res.jsonValue["Status"]["State"] = "Enabled";
59                 }
60                 else if (*s ==
61                          "xyz.openbmc_project.State.Chassis.PowerState.Off")
62                 {
63                     aResp->res.jsonValue["PowerState"] = "Off";
64                     aResp->res.jsonValue["Status"]["State"] = "StandbyOffline";
65                 }
66             }
67         },
68         "xyz.openbmc_project.State.Chassis",
69         "/xyz/openbmc_project/state/chassis0",
70         "org.freedesktop.DBus.Properties", "Get",
71         "xyz.openbmc_project.State.Chassis", "CurrentPowerState");
72 }
73 
74 /**
75  * DBus types primitives for several generic DBus interfaces
76  * TODO(Pawel) consider move this to separate file into boost::dbus
77  */
78 // Note, this is not a very useful Variant, but because it isn't used to get
79 // values, it should be as simple as possible
80 // TODO(ed) invent a nullvariant type
81 using VariantType = std::variant<bool, std::string, uint64_t, uint32_t>;
82 using ManagedObjectsType = std::vector<std::pair<
83     sdbusplus::message::object_path,
84     std::vector<std::pair<std::string,
85                           std::vector<std::pair<std::string, VariantType>>>>>>;
86 
87 using PropertiesType = boost::container::flat_map<std::string, VariantType>;
88 
89 inline void getIntrusionByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
90                                   const std::string& service,
91                                   const std::string& objPath)
92 {
93     BMCWEB_LOG_DEBUG << "Get intrusion status by service \n";
94 
95     crow::connections::systemBus->async_method_call(
96         [aResp{std::move(aResp)}](const boost::system::error_code ec,
97                                   const std::variant<std::string>& value) {
98             if (ec)
99             {
100                 // do not add err msg in redfish response, because this is not
101                 //     mandatory property
102                 BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n";
103                 return;
104             }
105 
106             const std::string* status = std::get_if<std::string>(&value);
107 
108             if (status == nullptr)
109             {
110                 BMCWEB_LOG_ERROR << "intrusion status read error \n";
111                 return;
112             }
113 
114             aResp->res.jsonValue["PhysicalSecurity"] = {
115                 {"IntrusionSensorNumber", 1}, {"IntrusionSensor", *status}};
116         },
117         service, objPath, "org.freedesktop.DBus.Properties", "Get",
118         "xyz.openbmc_project.Chassis.Intrusion", "Status");
119 }
120 
121 /**
122  * Retrieves physical security properties over dbus
123  */
124 inline void getPhysicalSecurityData(std::shared_ptr<bmcweb::AsyncResp> aResp)
125 {
126     crow::connections::systemBus->async_method_call(
127         [aResp{std::move(aResp)}](
128             const boost::system::error_code ec,
129             const std::vector<std::pair<
130                 std::string,
131                 std::vector<std::pair<std::string, std::vector<std::string>>>>>&
132                 subtree) {
133             if (ec)
134             {
135                 // do not add err msg in redfish response, because this is not
136                 //     mandatory property
137                 BMCWEB_LOG_ERROR << "DBUS error: no matched iface " << ec
138                                  << "\n";
139                 return;
140             }
141             // Iterate over all retrieved ObjectPaths.
142             for (const auto& object : subtree)
143             {
144                 for (const auto& service : object.second)
145                 {
146                     getIntrusionByService(aResp, service.first, object.first);
147                     return;
148                 }
149             }
150         },
151         "xyz.openbmc_project.ObjectMapper",
152         "/xyz/openbmc_project/object_mapper",
153         "xyz.openbmc_project.ObjectMapper", "GetSubTree",
154         "/xyz/openbmc_project/Intrusion", 1,
155         std::array<const char*, 1>{"xyz.openbmc_project.Chassis.Intrusion"});
156 }
157 
158 /**
159  * ChassisCollection derived class for delivering Chassis Collection Schema
160  */
161 class ChassisCollection : public Node
162 {
163   public:
164     ChassisCollection(App& app) : Node(app, "/redfish/v1/Chassis/")
165     {
166         entityPrivileges = {
167             {boost::beast::http::verb::get, {{"Login"}}},
168             {boost::beast::http::verb::head, {{"Login"}}},
169             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
170             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
171             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
172             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
173     }
174 
175   private:
176     /**
177      * Functions triggers appropriate requests on DBus
178      */
179     void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
180                const crow::Request&, const std::vector<std::string>&) override
181     {
182         asyncResp->res.jsonValue["@odata.type"] =
183             "#ChassisCollection.ChassisCollection";
184         asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
185         asyncResp->res.jsonValue["Name"] = "Chassis Collection";
186 
187         collection_util::getCollectionMembers(
188             asyncResp, "/redfish/v1/Chassis",
189             {"xyz.openbmc_project.Inventory.Item.Board",
190              "xyz.openbmc_project.Inventory.Item.Chassis"});
191     }
192 };
193 
194 /**
195  * Chassis override class for delivering Chassis Schema
196  */
197 class Chassis : public Node
198 {
199   public:
200     Chassis(App& app) : Node(app, "/redfish/v1/Chassis/<str>/", std::string())
201     {
202         entityPrivileges = {
203             {boost::beast::http::verb::get, {{"Login"}}},
204             {boost::beast::http::verb::head, {{"Login"}}},
205             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
206             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
207             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
208             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
209     }
210 
211   private:
212     /**
213      * Functions triggers appropriate requests on DBus
214      */
215     void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
216                const crow::Request&,
217                const std::vector<std::string>& params) override
218     {
219         const std::array<const char*, 2> interfaces = {
220             "xyz.openbmc_project.Inventory.Item.Board",
221             "xyz.openbmc_project.Inventory.Item.Chassis"};
222 
223         // Check if there is required param, truly entering this shall be
224         // impossible.
225         if (params.size() != 1)
226         {
227             messages::internalError(asyncResp->res);
228             return;
229         }
230         const std::string& chassisId = params[0];
231 
232         crow::connections::systemBus->async_method_call(
233             [asyncResp, chassisId(std::string(chassisId))](
234                 const boost::system::error_code ec,
235                 const crow::openbmc_mapper::GetSubTreeType& subtree) {
236                 if (ec)
237                 {
238                     messages::internalError(asyncResp->res);
239                     return;
240                 }
241                 // Iterate over all retrieved ObjectPaths.
242                 for (const std::pair<
243                          std::string,
244                          std::vector<
245                              std::pair<std::string, std::vector<std::string>>>>&
246                          object : subtree)
247                 {
248                     const std::string& path = object.first;
249                     const std::vector<
250                         std::pair<std::string, std::vector<std::string>>>&
251                         connectionNames = object.second;
252                     sdbusplus::message::object_path objPath(path);
253                     if (objPath.filename() != chassisId)
254                     {
255                         continue;
256                     }
257 
258                     auto health = std::make_shared<HealthPopulate>(asyncResp);
259 
260                     crow::connections::systemBus->async_method_call(
261                         [health](const boost::system::error_code ec2,
262                                  std::variant<std::vector<std::string>>& resp) {
263                             if (ec2)
264                             {
265                                 return; // no sensors = no failures
266                             }
267                             std::vector<std::string>* data =
268                                 std::get_if<std::vector<std::string>>(&resp);
269                             if (data == nullptr)
270                             {
271                                 return;
272                             }
273                             health->inventory = std::move(*data);
274                         },
275                         "xyz.openbmc_project.ObjectMapper",
276                         path + "/all_sensors",
277                         "org.freedesktop.DBus.Properties", "Get",
278                         "xyz.openbmc_project.Association", "endpoints");
279 
280                     health->populate();
281 
282                     if (connectionNames.size() < 1)
283                     {
284                         BMCWEB_LOG_ERROR << "Got 0 Connection names";
285                         continue;
286                     }
287 
288                     asyncResp->res.jsonValue["@odata.type"] =
289                         "#Chassis.v1_14_0.Chassis";
290                     asyncResp->res.jsonValue["@odata.id"] =
291                         "/redfish/v1/Chassis/" + chassisId;
292                     asyncResp->res.jsonValue["Name"] = "Chassis Collection";
293                     asyncResp->res.jsonValue["ChassisType"] = "RackMount";
294                     asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"] = {
295                         {"target", "/redfish/v1/Chassis/" + chassisId +
296                                        "/Actions/Chassis.Reset"},
297                         {"@Redfish.ActionInfo", "/redfish/v1/Chassis/" +
298                                                     chassisId +
299                                                     "/ResetActionInfo"}};
300                     asyncResp->res.jsonValue["PCIeDevices"] = {
301                         {"@odata.id",
302                          "/redfish/v1/Systems/system/PCIeDevices"}};
303 
304                     const std::string& connectionName =
305                         connectionNames[0].first;
306 
307                     const std::vector<std::string>& interfaces2 =
308                         connectionNames[0].second;
309                     const std::array<const char*, 2> hasIndicatorLed = {
310                         "xyz.openbmc_project.Inventory.Item.Panel",
311                         "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
312 
313                     for (const char* interface : hasIndicatorLed)
314                     {
315                         if (std::find(interfaces2.begin(), interfaces2.end(),
316                                       interface) != interfaces2.end())
317                         {
318                             getIndicatorLedState(asyncResp);
319                             getLocationIndicatorActive(asyncResp);
320                             break;
321                         }
322                     }
323 
324                     const std::string locationInterface =
325                         "xyz.openbmc_project.Inventory.Decorator.LocationCode";
326                     if (std::find(interfaces2.begin(), interfaces2.end(),
327                                   locationInterface) != interfaces2.end())
328                     {
329                         crow::connections::systemBus->async_method_call(
330                             [asyncResp, chassisId(std::string(chassisId))](
331                                 const boost::system::error_code ec,
332                                 const std::variant<std::string>& property) {
333                                 if (ec)
334                                 {
335                                     BMCWEB_LOG_DEBUG
336                                         << "DBUS response error for Location";
337                                     messages::internalError(asyncResp->res);
338                                     return;
339                                 }
340 
341                                 const std::string* value =
342                                     std::get_if<std::string>(&property);
343                                 if (value == nullptr)
344                                 {
345                                     BMCWEB_LOG_DEBUG << "Null value returned "
346                                                         "for locaton code";
347                                     messages::internalError(asyncResp->res);
348                                     return;
349                                 }
350                                 asyncResp->res
351                                     .jsonValue["Location"]["PartLocation"]
352                                               ["ServiceLabel"] = *value;
353                             },
354                             connectionName, path,
355                             "org.freedesktop.DBus.Properties", "Get",
356                             locationInterface, "LocationCode");
357                     }
358 
359                     crow::connections::systemBus->async_method_call(
360                         [asyncResp, chassisId(std::string(chassisId))](
361                             const boost::system::error_code /*ec2*/,
362                             const std::vector<std::pair<
363                                 std::string, VariantType>>& propertiesList) {
364                             for (const std::pair<std::string, VariantType>&
365                                      property : propertiesList)
366                             {
367                                 // Store DBus properties that are also Redfish
368                                 // properties with same name and a string value
369                                 const std::string& propertyName =
370                                     property.first;
371                                 if ((propertyName == "PartNumber") ||
372                                     (propertyName == "SerialNumber") ||
373                                     (propertyName == "Manufacturer") ||
374                                     (propertyName == "Model"))
375                                 {
376                                     const std::string* value =
377                                         std::get_if<std::string>(
378                                             &property.second);
379                                     if (value != nullptr)
380                                     {
381                                         asyncResp->res.jsonValue[propertyName] =
382                                             *value;
383                                     }
384                                 }
385                             }
386                             asyncResp->res.jsonValue["Name"] = chassisId;
387                             asyncResp->res.jsonValue["Id"] = chassisId;
388                             asyncResp->res.jsonValue["Thermal"] = {
389                                 {"@odata.id", "/redfish/v1/Chassis/" +
390                                                   chassisId + "/Thermal"}};
391                             // Power object
392                             asyncResp->res.jsonValue["Power"] = {
393                                 {"@odata.id", "/redfish/v1/Chassis/" +
394                                                   chassisId + "/Power"}};
395                             // SensorCollection
396                             asyncResp->res.jsonValue["Sensors"] = {
397                                 {"@odata.id", "/redfish/v1/Chassis/" +
398                                                   chassisId + "/Sensors"}};
399                             asyncResp->res.jsonValue["Status"] = {
400                                 {"State", "Enabled"},
401                             };
402 
403                             asyncResp->res
404                                 .jsonValue["Links"]["ComputerSystems"] = {
405                                 {{"@odata.id", "/redfish/v1/Systems/system"}}};
406                             asyncResp->res.jsonValue["Links"]["ManagedBy"] = {
407                                 {{"@odata.id", "/redfish/v1/Managers/bmc"}}};
408                             getChassisState(asyncResp);
409                         },
410                         connectionName, path, "org.freedesktop.DBus.Properties",
411                         "GetAll",
412                         "xyz.openbmc_project.Inventory.Decorator.Asset");
413                     return;
414                 }
415 
416                 // Couldn't find an object with that name.  return an error
417                 messages::resourceNotFound(
418                     asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId);
419             },
420             "xyz.openbmc_project.ObjectMapper",
421             "/xyz/openbmc_project/object_mapper",
422             "xyz.openbmc_project.ObjectMapper", "GetSubTree",
423             "/xyz/openbmc_project/inventory", 0, interfaces);
424 
425         getPhysicalSecurityData(asyncResp);
426     }
427 
428     void doPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
429                  const crow::Request& req,
430                  const std::vector<std::string>& params) override
431     {
432         std::optional<bool> locationIndicatorActive;
433         std::optional<std::string> indicatorLed;
434 
435         if (params.size() != 1)
436         {
437             return;
438         }
439 
440         if (!json_util::readJson(req, asyncResp->res, "LocationIndicatorActive",
441                                  locationIndicatorActive, "IndicatorLED",
442                                  indicatorLed))
443         {
444             return;
445         }
446 
447         // TODO (Gunnar): Remove IndicatorLED after enough time has passed
448         if (!locationIndicatorActive && !indicatorLed)
449         {
450             return; // delete this when we support more patch properties
451         }
452         if (indicatorLed)
453         {
454             asyncResp->res.addHeader(boost::beast::http::field::warning,
455                                      "299 - \"IndicatorLED is deprecated. Use "
456                                      "LocationIndicatorActive instead.\"");
457         }
458 
459         const std::array<const char*, 2> interfaces = {
460             "xyz.openbmc_project.Inventory.Item.Board",
461             "xyz.openbmc_project.Inventory.Item.Chassis"};
462 
463         const std::string& chassisId = params[0];
464 
465         crow::connections::systemBus->async_method_call(
466             [asyncResp, chassisId, locationIndicatorActive, indicatorLed](
467                 const boost::system::error_code ec,
468                 const crow::openbmc_mapper::GetSubTreeType& subtree) {
469                 if (ec)
470                 {
471                     messages::internalError(asyncResp->res);
472                     return;
473                 }
474 
475                 // Iterate over all retrieved ObjectPaths.
476                 for (const std::pair<
477                          std::string,
478                          std::vector<
479                              std::pair<std::string, std::vector<std::string>>>>&
480                          object : subtree)
481                 {
482                     const std::string& path = object.first;
483                     const std::vector<
484                         std::pair<std::string, std::vector<std::string>>>&
485                         connectionNames = object.second;
486 
487                     if (!boost::ends_with(path, chassisId))
488                     {
489                         continue;
490                     }
491 
492                     if (connectionNames.size() < 1)
493                     {
494                         BMCWEB_LOG_ERROR << "Got 0 Connection names";
495                         continue;
496                     }
497 
498                     const std::vector<std::string>& interfaces3 =
499                         connectionNames[0].second;
500 
501                     const std::array<const char*, 2> hasIndicatorLed = {
502                         "xyz.openbmc_project.Inventory.Item.Panel",
503                         "xyz.openbmc_project.Inventory.Item.Board."
504                         "Motherboard"};
505                     bool indicatorChassis = false;
506                     for (const char* interface : hasIndicatorLed)
507                     {
508                         if (std::find(interfaces3.begin(), interfaces3.end(),
509                                       interface) != interfaces3.end())
510                         {
511                             indicatorChassis = true;
512                             break;
513                         }
514                     }
515                     if (locationIndicatorActive)
516                     {
517                         if (indicatorChassis)
518                         {
519                             setLocationIndicatorActive(
520                                 asyncResp, *locationIndicatorActive);
521                         }
522                         else
523                         {
524                             messages::propertyUnknown(
525                                 asyncResp->res, "LocationIndicatorActive");
526                         }
527                     }
528                     if (indicatorLed)
529                     {
530                         if (indicatorChassis)
531                         {
532                             setIndicatorLedState(asyncResp, *indicatorLed);
533                         }
534                         else
535                         {
536                             messages::propertyUnknown(asyncResp->res,
537                                                       "IndicatorLED");
538                         }
539                     }
540                     return;
541                 }
542 
543                 messages::resourceNotFound(
544                     asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId);
545             },
546             "xyz.openbmc_project.ObjectMapper",
547             "/xyz/openbmc_project/object_mapper",
548             "xyz.openbmc_project.ObjectMapper", "GetSubTree",
549             "/xyz/openbmc_project/inventory", 0, interfaces);
550     }
551 };
552 
553 inline void
554     doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
555 {
556     const char* busName = "xyz.openbmc_project.ObjectMapper";
557     const char* path = "/xyz/openbmc_project/object_mapper";
558     const char* interface = "xyz.openbmc_project.ObjectMapper";
559     const char* method = "GetSubTreePaths";
560 
561     const std::array<const char*, 1> interfaces = {
562         "xyz.openbmc_project.State.Chassis"};
563 
564     // Use mapper to get subtree paths.
565     crow::connections::systemBus->async_method_call(
566         [asyncResp](const boost::system::error_code ec,
567                     const std::vector<std::string>& chassisList) {
568             if (ec)
569             {
570                 BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec;
571                 messages::internalError(asyncResp->res);
572                 return;
573             }
574 
575             const char* processName = "xyz.openbmc_project.State.Chassis";
576             const char* interfaceName = "xyz.openbmc_project.State.Chassis";
577             const char* destProperty = "RequestedPowerTransition";
578             const std::string propertyValue =
579                 "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
580             std::string objectPath =
581                 "/xyz/openbmc_project/state/chassis_system0";
582 
583             /* Look for system reset chassis path */
584             if ((std::find(chassisList.begin(), chassisList.end(),
585                            objectPath)) == chassisList.end())
586             {
587                 /* We prefer to reset the full chassis_system, but if it doesn't
588                  * exist on some platforms, fall back to a host-only power reset
589                  */
590                 objectPath = "/xyz/openbmc_project/state/chassis0";
591             }
592 
593             crow::connections::systemBus->async_method_call(
594                 [asyncResp](const boost::system::error_code ec) {
595                     // Use "Set" method to set the property value.
596                     if (ec)
597                     {
598                         BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: "
599                                          << ec;
600                         messages::internalError(asyncResp->res);
601                         return;
602                     }
603 
604                     messages::success(asyncResp->res);
605                 },
606                 processName, objectPath, "org.freedesktop.DBus.Properties",
607                 "Set", interfaceName, destProperty,
608                 std::variant<std::string>{propertyValue});
609         },
610         busName, path, interface, method, "/", 0, interfaces);
611 }
612 
613 /**
614  * ChassisResetAction class supports the POST method for the Reset
615  * action.
616  */
617 class ChassisResetAction : public Node
618 {
619   public:
620     ChassisResetAction(App& app) :
621         Node(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/",
622              std::string())
623     {
624         entityPrivileges = {
625             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
626     }
627 
628   private:
629     /**
630      * Function handles POST method request.
631      * Analyzes POST body before sending Reset request data to D-Bus.
632      */
633     void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
634                 const crow::Request& req,
635                 const std::vector<std::string>&) override
636     {
637         BMCWEB_LOG_DEBUG << "Post Chassis Reset.";
638 
639         std::string resetType;
640 
641         if (!json_util::readJson(req, asyncResp->res, "ResetType", resetType))
642         {
643             return;
644         }
645 
646         if (resetType != "PowerCycle")
647         {
648             BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: "
649                              << resetType;
650             messages::actionParameterNotSupported(asyncResp->res, resetType,
651                                                   "ResetType");
652 
653             return;
654         }
655         doChassisPowerCycle(asyncResp);
656     }
657 };
658 
659 /**
660  * ChassisResetActionInfo derived class for delivering Chassis
661  * ResetType AllowableValues using ResetInfo schema.
662  */
663 class ChassisResetActionInfo : public Node
664 {
665   public:
666     /*
667      * Default Constructor
668      */
669     ChassisResetActionInfo(App& app) :
670         Node(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/", std::string())
671     {
672         entityPrivileges = {
673             {boost::beast::http::verb::get, {{"Login"}}},
674             {boost::beast::http::verb::head, {{"Login"}}},
675             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
676             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
677             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
678             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
679     }
680 
681   private:
682     /**
683      * Functions triggers appropriate requests on DBus
684      */
685     void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
686                const crow::Request&,
687                const std::vector<std::string>& params) override
688     {
689         if (params.size() != 1)
690         {
691             messages::internalError(asyncResp->res);
692             return;
693         }
694         const std::string& chassisId = params[0];
695 
696         asyncResp->res.jsonValue = {
697             {"@odata.type", "#ActionInfo.v1_1_2.ActionInfo"},
698             {"@odata.id",
699              "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"},
700             {"Name", "Reset Action Info"},
701             {"Id", "ResetActionInfo"},
702             {"Parameters",
703              {{{"Name", "ResetType"},
704                {"Required", true},
705                {"DataType", "String"},
706                {"AllowableValues", {"PowerCycle"}}}}}};
707     }
708 };
709 
710 } // namespace redfish
711