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