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