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 // SensorCollection 388 asyncResp->res.jsonValue["Sensors"]["@odata.id"] = 389 "/redfish/v1/Chassis/" + chassisId + "/Sensors"; 390 asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; 391 392 nlohmann::json::array_t computerSystems; 393 nlohmann::json::object_t system; 394 system["@odata.id"] = "/redfish/v1/Systems/system"; 395 computerSystems.push_back(std::move(system)); 396 asyncResp->res.jsonValue["Links"]["ComputerSystems"] = 397 std::move(computerSystems); 398 399 nlohmann::json::array_t managedBy; 400 nlohmann::json::object_t manager; 401 manager["@odata.id"] = "/redfish/v1/Managers/bmc"; 402 managedBy.push_back(std::move(manager)); 403 asyncResp->res.jsonValue["Links"]["ManagedBy"] = 404 std::move(managedBy); 405 getChassisState(asyncResp); 406 }, 407 connectionName, path, "org.freedesktop.DBus.Properties", 408 "GetAll", "xyz.openbmc_project.Inventory.Decorator.Asset"); 409 410 for (const auto& interface : interfaces2) 411 { 412 if (interface == "xyz.openbmc_project.Common.UUID") 413 { 414 getChassisUUID(asyncResp, connectionName, path); 415 } 416 else if (interface == 417 "xyz.openbmc_project.Inventory.Decorator.LocationCode") 418 { 419 getChassisLocationCode(asyncResp, connectionName, path); 420 } 421 } 422 423 return; 424 } 425 426 // Couldn't find an object with that name. return an error 427 messages::resourceNotFound(asyncResp->res, "#Chassis.v1_16_0.Chassis", 428 chassisId); 429 }, 430 "xyz.openbmc_project.ObjectMapper", 431 "/xyz/openbmc_project/object_mapper", 432 "xyz.openbmc_project.ObjectMapper", "GetSubTree", 433 "/xyz/openbmc_project/inventory", 0, interfaces); 434 435 getPhysicalSecurityData(asyncResp); 436 } 437 438 inline void 439 handleChassisPatch(App& app, const crow::Request& req, 440 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 441 const std::string& param) 442 { 443 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 444 { 445 return; 446 } 447 std::optional<bool> locationIndicatorActive; 448 std::optional<std::string> indicatorLed; 449 450 if (param.empty()) 451 { 452 return; 453 } 454 455 if (!json_util::readJsonPatch( 456 req, asyncResp->res, "LocationIndicatorActive", 457 locationIndicatorActive, "IndicatorLED", indicatorLed)) 458 { 459 return; 460 } 461 462 // TODO (Gunnar): Remove IndicatorLED after enough time has passed 463 if (!locationIndicatorActive && !indicatorLed) 464 { 465 return; // delete this when we support more patch properties 466 } 467 if (indicatorLed) 468 { 469 asyncResp->res.addHeader( 470 boost::beast::http::field::warning, 471 "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\""); 472 } 473 474 const std::array<const char*, 2> interfaces = { 475 "xyz.openbmc_project.Inventory.Item.Board", 476 "xyz.openbmc_project.Inventory.Item.Chassis"}; 477 478 const std::string& chassisId = param; 479 480 crow::connections::systemBus->async_method_call( 481 [asyncResp, chassisId, locationIndicatorActive, 482 indicatorLed](const boost::system::error_code ec, 483 const dbus::utility::MapperGetSubTreeResponse& subtree) { 484 if (ec) 485 { 486 messages::internalError(asyncResp->res); 487 return; 488 } 489 490 // Iterate over all retrieved ObjectPaths. 491 for (const std::pair< 492 std::string, 493 std::vector<std::pair<std::string, std::vector<std::string>>>>& 494 object : subtree) 495 { 496 const std::string& path = object.first; 497 const std::vector<std::pair<std::string, std::vector<std::string>>>& 498 connectionNames = object.second; 499 500 sdbusplus::message::object_path objPath(path); 501 if (objPath.filename() != chassisId) 502 { 503 continue; 504 } 505 506 if (connectionNames.empty()) 507 { 508 BMCWEB_LOG_ERROR << "Got 0 Connection names"; 509 continue; 510 } 511 512 const std::vector<std::string>& interfaces3 = 513 connectionNames[0].second; 514 515 const std::array<const char*, 2> hasIndicatorLed = { 516 "xyz.openbmc_project.Inventory.Item.Panel", 517 "xyz.openbmc_project.Inventory.Item.Board.Motherboard"}; 518 bool indicatorChassis = false; 519 for (const char* interface : hasIndicatorLed) 520 { 521 if (std::find(interfaces3.begin(), interfaces3.end(), 522 interface) != interfaces3.end()) 523 { 524 indicatorChassis = true; 525 break; 526 } 527 } 528 if (locationIndicatorActive) 529 { 530 if (indicatorChassis) 531 { 532 setLocationIndicatorActive(asyncResp, 533 *locationIndicatorActive); 534 } 535 else 536 { 537 messages::propertyUnknown(asyncResp->res, 538 "LocationIndicatorActive"); 539 } 540 } 541 if (indicatorLed) 542 { 543 if (indicatorChassis) 544 { 545 setIndicatorLedState(asyncResp, *indicatorLed); 546 } 547 else 548 { 549 messages::propertyUnknown(asyncResp->res, "IndicatorLED"); 550 } 551 } 552 return; 553 } 554 555 messages::resourceNotFound(asyncResp->res, "#Chassis.v1_14_0.Chassis", 556 chassisId); 557 }, 558 "xyz.openbmc_project.ObjectMapper", 559 "/xyz/openbmc_project/object_mapper", 560 "xyz.openbmc_project.ObjectMapper", "GetSubTree", 561 "/xyz/openbmc_project/inventory", 0, interfaces); 562 } 563 564 /** 565 * Chassis override class for delivering Chassis Schema 566 * Functions triggers appropriate requests on DBus 567 */ 568 inline void requestRoutesChassis(App& app) 569 { 570 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/") 571 .privileges(redfish::privileges::getChassis) 572 .methods(boost::beast::http::verb::get)( 573 std::bind_front(handleChassisGet, std::ref(app))); 574 575 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/") 576 .privileges(redfish::privileges::patchChassis) 577 .methods(boost::beast::http::verb::patch)( 578 std::bind_front(handleChassisPatch, std::ref(app))); 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 ec2) { 623 // Use "Set" method to set the property value. 624 if (ec2) 625 { 626 BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: " << ec2; 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 inline void handleChassisResetActionInfoPost( 641 App& app, const crow::Request& req, 642 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 643 const std::string& /*chassisId*/) 644 { 645 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 646 { 647 return; 648 } 649 BMCWEB_LOG_DEBUG << "Post Chassis Reset."; 650 651 std::string resetType; 652 653 if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType)) 654 { 655 return; 656 } 657 658 if (resetType != "PowerCycle") 659 { 660 BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: " 661 << resetType; 662 messages::actionParameterNotSupported(asyncResp->res, resetType, 663 "ResetType"); 664 665 return; 666 } 667 doChassisPowerCycle(asyncResp); 668 } 669 670 /** 671 * ChassisResetAction class supports the POST method for the Reset 672 * action. 673 * Function handles POST method request. 674 * Analyzes POST body before sending Reset request data to D-Bus. 675 */ 676 677 inline void requestRoutesChassisResetAction(App& app) 678 { 679 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/") 680 .privileges(redfish::privileges::postChassis) 681 .methods(boost::beast::http::verb::post)( 682 std::bind_front(handleChassisResetActionInfoPost, std::ref(app))); 683 } 684 685 inline void handleChassisResetActionInfoGet( 686 App& app, const crow::Request& req, 687 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 688 const std::string& chassisId) 689 { 690 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 691 { 692 return; 693 } 694 asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo"; 695 asyncResp->res.jsonValue["@odata.id"] = 696 "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"; 697 asyncResp->res.jsonValue["Name"] = "Reset Action Info"; 698 699 asyncResp->res.jsonValue["Id"] = "ResetActionInfo"; 700 nlohmann::json::array_t parameters; 701 nlohmann::json::object_t parameter; 702 parameter["Name"] = "ResetType"; 703 parameter["Required"] = true; 704 parameter["DataType"] = "String"; 705 nlohmann::json::array_t allowed; 706 allowed.push_back("PowerCycle"); 707 parameter["AllowableValues"] = std::move(allowed); 708 parameters.push_back(std::move(parameter)); 709 710 asyncResp->res.jsonValue["Parameters"] = std::move(parameters); 711 } 712 713 /** 714 * ChassisResetActionInfo derived class for delivering Chassis 715 * ResetType AllowableValues using ResetInfo schema. 716 */ 717 inline void requestRoutesChassisResetActionInfo(App& app) 718 { 719 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/") 720 .privileges(redfish::privileges::getActionInfo) 721 .methods(boost::beast::http::verb::get)( 722 std::bind_front(handleChassisResetActionInfoGet, std::ref(app))); 723 } 724 725 } // namespace redfish 726