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