1e37f8451SRapkiewicz, Pawel /* 2e37f8451SRapkiewicz, Pawel // Copyright (c) 2018 Intel Corporation 3e37f8451SRapkiewicz, Pawel // 4e37f8451SRapkiewicz, Pawel // Licensed under the Apache License, Version 2.0 (the "License"); 5e37f8451SRapkiewicz, Pawel // you may not use this file except in compliance with the License. 6e37f8451SRapkiewicz, Pawel // You may obtain a copy of the License at 7e37f8451SRapkiewicz, Pawel // 8e37f8451SRapkiewicz, Pawel // http://www.apache.org/licenses/LICENSE-2.0 9e37f8451SRapkiewicz, Pawel // 10e37f8451SRapkiewicz, Pawel // Unless required by applicable law or agreed to in writing, software 11e37f8451SRapkiewicz, Pawel // distributed under the License is distributed on an "AS IS" BASIS, 12e37f8451SRapkiewicz, Pawel // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e37f8451SRapkiewicz, Pawel // See the License for the specific language governing permissions and 14e37f8451SRapkiewicz, Pawel // limitations under the License. 15e37f8451SRapkiewicz, Pawel */ 16e37f8451SRapkiewicz, Pawel #pragma once 17e37f8451SRapkiewicz, Pawel 183ccb3adbSEd Tanous #include "app.hpp" 197a1dbc48SGeorge Liu #include "dbus_utility.hpp" 201c8fba97SJames Feist #include "led.hpp" 213ccb3adbSEd Tanous #include "query.hpp" 227164bc62SChau Ly #include "redfish_util.hpp" 233ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 243ccb3adbSEd Tanous #include "utils/collection.hpp" 253ccb3adbSEd Tanous #include "utils/dbus_utils.hpp" 26cf7eba09SNan Zhou #include "utils/json_utils.hpp" 271abe55efSEd Tanous 28e99073f5SGeorge Liu #include <boost/system/error_code.hpp> 29ef4c65b7SEd Tanous #include <boost/url/format.hpp> 301e1e598dSJonathan Doman #include <sdbusplus/asio/property.hpp> 31fc903b3dSAndrew Geissler #include <sdbusplus/message.hpp> 3286d89ed7SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 331214b7e7SGunnar Mills 347a1dbc48SGeorge Liu #include <array> 353544d2a7SEd Tanous #include <ranges> 367a1dbc48SGeorge Liu #include <string_view> 377a1dbc48SGeorge Liu 381abe55efSEd Tanous namespace redfish 391abe55efSEd Tanous { 40e37f8451SRapkiewicz, Pawel 41e37f8451SRapkiewicz, Pawel /** 425e577bc1SWilly Tu * @brief Retrieves resources over dbus to link to the chassis 435e577bc1SWilly Tu * 445e577bc1SWilly Tu * @param[in] asyncResp - Shared pointer for completing asynchronous 455e577bc1SWilly Tu * calls 465e577bc1SWilly Tu * @param[in] path - Chassis dbus path to look for the storage. 475e577bc1SWilly Tu * 485e577bc1SWilly Tu * Calls the Association endpoints on the path + "/storage" and add the link of 495e577bc1SWilly Tu * json["Links"]["Storage@odata.count"] = 505e577bc1SWilly Tu * {"@odata.id", "/redfish/v1/Storage/" + resourceId} 515e577bc1SWilly Tu * 525e577bc1SWilly Tu * @return None. 535e577bc1SWilly Tu */ 545e577bc1SWilly Tu inline void getStorageLink(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 555e577bc1SWilly Tu const sdbusplus::message::object_path& path) 565e577bc1SWilly Tu { 575e577bc1SWilly Tu sdbusplus::asio::getProperty<std::vector<std::string>>( 585e577bc1SWilly Tu *crow::connections::systemBus, "xyz.openbmc_project.ObjectMapper", 595e577bc1SWilly Tu (path / "storage").str, "xyz.openbmc_project.Association", "endpoints", 60d4b054c1SWilly Tu [asyncResp](const boost::system::error_code& ec, 615e577bc1SWilly Tu const std::vector<std::string>& storageList) { 625e577bc1SWilly Tu if (ec) 635e577bc1SWilly Tu { 6462598e31SEd Tanous BMCWEB_LOG_DEBUG("getStorageLink got DBUS response error"); 655e577bc1SWilly Tu return; 665e577bc1SWilly Tu } 675e577bc1SWilly Tu 685e577bc1SWilly Tu nlohmann::json::array_t storages; 695e577bc1SWilly Tu for (const std::string& storagePath : storageList) 705e577bc1SWilly Tu { 715e577bc1SWilly Tu std::string id = 725e577bc1SWilly Tu sdbusplus::message::object_path(storagePath).filename(); 735e577bc1SWilly Tu if (id.empty()) 745e577bc1SWilly Tu { 755e577bc1SWilly Tu continue; 765e577bc1SWilly Tu } 775e577bc1SWilly Tu 785e577bc1SWilly Tu nlohmann::json::object_t storage; 795e577bc1SWilly Tu storage["@odata.id"] = boost::urls::format( 805e577bc1SWilly Tu "/redfish/v1/Systems/system/Storage/{}", id); 815e577bc1SWilly Tu storages.emplace_back(std::move(storage)); 825e577bc1SWilly Tu } 835e577bc1SWilly Tu asyncResp->res.jsonValue["Links"]["Storage@odata.count"] = 845e577bc1SWilly Tu storages.size(); 855e577bc1SWilly Tu asyncResp->res.jsonValue["Links"]["Storage"] = std::move(storages); 865e577bc1SWilly Tu }); 875e577bc1SWilly Tu } 885e577bc1SWilly Tu 895e577bc1SWilly Tu /** 90beeca0aeSGunnar Mills * @brief Retrieves chassis state properties over dbus 91beeca0aeSGunnar Mills * 92ac106bf6SEd Tanous * @param[in] asyncResp - Shared pointer for completing asynchronous calls. 93beeca0aeSGunnar Mills * 94beeca0aeSGunnar Mills * @return None. 95beeca0aeSGunnar Mills */ 96ac106bf6SEd Tanous inline void getChassisState(std::shared_ptr<bmcweb::AsyncResp> asyncResp) 97beeca0aeSGunnar Mills { 981e1e598dSJonathan Doman // crow::connections::systemBus->async_method_call( 991e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 1001e1e598dSJonathan Doman *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis", 1011e1e598dSJonathan Doman "/xyz/openbmc_project/state/chassis0", 1021e1e598dSJonathan Doman "xyz.openbmc_project.State.Chassis", "CurrentPowerState", 103ac106bf6SEd Tanous [asyncResp{std::move(asyncResp)}](const boost::system::error_code& ec, 1041e1e598dSJonathan Doman const std::string& chassisState) { 105beeca0aeSGunnar Mills if (ec) 106beeca0aeSGunnar Mills { 107a6e5e0abSCarson Labrado if (ec == boost::system::errc::host_unreachable) 108a6e5e0abSCarson Labrado { 109a6e5e0abSCarson Labrado // Service not available, no error, just don't return 110a6e5e0abSCarson Labrado // chassis state info 11162598e31SEd Tanous BMCWEB_LOG_DEBUG("Service not available {}", ec); 112a6e5e0abSCarson Labrado return; 113a6e5e0abSCarson Labrado } 11462598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error {}", ec); 115ac106bf6SEd Tanous messages::internalError(asyncResp->res); 116beeca0aeSGunnar Mills return; 117beeca0aeSGunnar Mills } 118beeca0aeSGunnar Mills 11962598e31SEd Tanous BMCWEB_LOG_DEBUG("Chassis state: {}", chassisState); 120beeca0aeSGunnar Mills // Verify Chassis State 121002d39b4SEd Tanous if (chassisState == "xyz.openbmc_project.State.Chassis.PowerState.On") 122beeca0aeSGunnar Mills { 123ac106bf6SEd Tanous asyncResp->res.jsonValue["PowerState"] = "On"; 124ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; 125beeca0aeSGunnar Mills } 1261e1e598dSJonathan Doman else if (chassisState == 127beeca0aeSGunnar Mills "xyz.openbmc_project.State.Chassis.PowerState.Off") 128beeca0aeSGunnar Mills { 129ac106bf6SEd Tanous asyncResp->res.jsonValue["PowerState"] = "Off"; 130ac106bf6SEd Tanous asyncResp->res.jsonValue["Status"]["State"] = "StandbyOffline"; 131beeca0aeSGunnar Mills } 1321e1e598dSJonathan Doman }); 133beeca0aeSGunnar Mills } 134beeca0aeSGunnar Mills 135c181942fSQiang XU /** 136c181942fSQiang XU * Retrieves physical security properties over dbus 137c181942fSQiang XU */ 1387164bc62SChau Ly inline void handlePhysicalSecurityGetSubTree( 1397164bc62SChau Ly const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 140e99073f5SGeorge Liu const boost::system::error_code& ec, 1417164bc62SChau Ly const dbus::utility::MapperGetSubTreeResponse& subtree) 1427164bc62SChau Ly { 143c181942fSQiang XU if (ec) 144c181942fSQiang XU { 1454e0453b1SGunnar Mills // do not add err msg in redfish response, because this is not 146c181942fSQiang XU // mandatory property 14762598e31SEd Tanous BMCWEB_LOG_INFO("DBUS error: no matched iface {}", ec); 148c181942fSQiang XU return; 149c181942fSQiang XU } 150c181942fSQiang XU // Iterate over all retrieved ObjectPaths. 151c181942fSQiang XU for (const auto& object : subtree) 152c181942fSQiang XU { 153840a9ffcSPatrick Williams if (!object.second.empty()) 154c181942fSQiang XU { 15589144a3aSEd Tanous const auto& service = object.second.front(); 1567164bc62SChau Ly 1577164bc62SChau Ly BMCWEB_LOG_DEBUG("Get intrusion status by service "); 1587164bc62SChau Ly 1597164bc62SChau Ly sdbusplus::asio::getProperty<std::string>( 1607164bc62SChau Ly *crow::connections::systemBus, service.first, object.first, 1617164bc62SChau Ly "xyz.openbmc_project.Chassis.Intrusion", "Status", 1627164bc62SChau Ly [asyncResp](const boost::system::error_code& ec1, 1637164bc62SChau Ly const std::string& value) { 1647164bc62SChau Ly if (ec1) 1657164bc62SChau Ly { 1667164bc62SChau Ly // do not add err msg in redfish response, because this is 1677164bc62SChau Ly // not 1687164bc62SChau Ly // mandatory property 1697164bc62SChau Ly BMCWEB_LOG_ERROR("DBUS response error {}", ec1); 1707164bc62SChau Ly return; 1717164bc62SChau Ly } 1727164bc62SChau Ly asyncResp->res 1737164bc62SChau Ly .jsonValue["PhysicalSecurity"]["IntrusionSensorNumber"] = 1; 1747164bc62SChau Ly asyncResp->res 1757164bc62SChau Ly .jsonValue["PhysicalSecurity"]["IntrusionSensor"] = value; 1767164bc62SChau Ly }); 1777164bc62SChau Ly 178c181942fSQiang XU return; 179c181942fSQiang XU } 180c181942fSQiang XU } 181c181942fSQiang XU } 182c181942fSQiang XU 183cf7eba09SNan Zhou inline void handleChassisCollectionGet( 184cf7eba09SNan Zhou App& app, const crow::Request& req, 185cf7eba09SNan Zhou const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1861abe55efSEd Tanous { 1873ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 18845ca1b86SEd Tanous { 18945ca1b86SEd Tanous return; 19045ca1b86SEd Tanous } 1918d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1928d1b46d7Szhanghch05 "#ChassisCollection.ChassisCollection"; 1938d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis"; 1948d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Chassis Collection"; 195e37f8451SRapkiewicz, Pawel 1967a1dbc48SGeorge Liu constexpr std::array<std::string_view, 2> interfaces{ 1977a1dbc48SGeorge Liu "xyz.openbmc_project.Inventory.Item.Board", 1987a1dbc48SGeorge Liu "xyz.openbmc_project.Inventory.Item.Chassis"}; 19902f6ff19SGunnar Mills collection_util::getCollectionMembers( 20036b5f1edSLakshmi Yadlapati asyncResp, boost::urls::url("/redfish/v1/Chassis"), interfaces, 20136b5f1edSLakshmi Yadlapati "/xyz/openbmc_project/inventory"); 202cf7eba09SNan Zhou } 203cf7eba09SNan Zhou 204a5617496SJie Yang inline void getChassisContainedBy( 205a5617496SJie Yang const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 206a5617496SJie Yang const std::string& chassisId, const boost::system::error_code& ec, 207a5617496SJie Yang const dbus::utility::MapperEndPoints& upstreamChassisPaths) 208a5617496SJie Yang { 209a5617496SJie Yang if (ec) 210a5617496SJie Yang { 211a5617496SJie Yang if (ec.value() != EBADR) 212a5617496SJie Yang { 21362598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error {}", ec); 214a5617496SJie Yang messages::internalError(asyncResp->res); 215a5617496SJie Yang } 216a5617496SJie Yang return; 217a5617496SJie Yang } 218a5617496SJie Yang if (upstreamChassisPaths.empty()) 219a5617496SJie Yang { 220a5617496SJie Yang return; 221a5617496SJie Yang } 222a5617496SJie Yang if (upstreamChassisPaths.size() > 1) 223a5617496SJie Yang { 2248ece0e45SEd Tanous BMCWEB_LOG_ERROR("{} is contained by multiple chassis", chassisId); 225a5617496SJie Yang messages::internalError(asyncResp->res); 226a5617496SJie Yang return; 227a5617496SJie Yang } 228a5617496SJie Yang 229a5617496SJie Yang sdbusplus::message::object_path upstreamChassisPath( 230a5617496SJie Yang upstreamChassisPaths[0]); 231a5617496SJie Yang std::string upstreamChassis = upstreamChassisPath.filename(); 232a5617496SJie Yang if (upstreamChassis.empty()) 233a5617496SJie Yang { 23462598e31SEd Tanous BMCWEB_LOG_WARNING("Malformed upstream Chassis path {} on {}", 23562598e31SEd Tanous upstreamChassisPath.str, chassisId); 236a5617496SJie Yang return; 237a5617496SJie Yang } 238a5617496SJie Yang 239a5617496SJie Yang asyncResp->res.jsonValue["Links"]["ContainedBy"]["@odata.id"] = 240a5617496SJie Yang boost::urls::format("/redfish/v1/Chassis/{}", upstreamChassis); 241a5617496SJie Yang } 242a5617496SJie Yang 243a5617496SJie Yang inline void getChassisContains( 244a5617496SJie Yang const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 245a5617496SJie Yang const std::string& chassisId, const boost::system::error_code& ec, 246a5617496SJie Yang const dbus::utility::MapperEndPoints& downstreamChassisPaths) 247a5617496SJie Yang { 248a5617496SJie Yang if (ec) 249a5617496SJie Yang { 250a5617496SJie Yang if (ec.value() != EBADR) 251a5617496SJie Yang { 25262598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error {}", ec); 253a5617496SJie Yang messages::internalError(asyncResp->res); 254a5617496SJie Yang } 255a5617496SJie Yang return; 256a5617496SJie Yang } 257a5617496SJie Yang if (downstreamChassisPaths.empty()) 258a5617496SJie Yang { 259a5617496SJie Yang return; 260a5617496SJie Yang } 261a5617496SJie Yang nlohmann::json& jValue = asyncResp->res.jsonValue["Links"]["Contains"]; 262a5617496SJie Yang if (!jValue.is_array()) 263a5617496SJie Yang { 264a5617496SJie Yang // Create the array if it was empty 265a5617496SJie Yang jValue = nlohmann::json::array(); 266a5617496SJie Yang } 267a5617496SJie Yang for (const auto& p : downstreamChassisPaths) 268a5617496SJie Yang { 269a5617496SJie Yang sdbusplus::message::object_path downstreamChassisPath(p); 270a5617496SJie Yang std::string downstreamChassis = downstreamChassisPath.filename(); 271a5617496SJie Yang if (downstreamChassis.empty()) 272a5617496SJie Yang { 27362598e31SEd Tanous BMCWEB_LOG_WARNING("Malformed downstream Chassis path {} on {}", 27462598e31SEd Tanous downstreamChassisPath.str, chassisId); 275a5617496SJie Yang continue; 276a5617496SJie Yang } 277a5617496SJie Yang nlohmann::json link; 278a5617496SJie Yang link["@odata.id"] = boost::urls::format("/redfish/v1/Chassis/{}", 279a5617496SJie Yang downstreamChassis); 280a5617496SJie Yang jValue.push_back(std::move(link)); 281a5617496SJie Yang } 282a5617496SJie Yang asyncResp->res.jsonValue["Links"]["Contains@odata.count"] = jValue.size(); 283a5617496SJie Yang } 284a5617496SJie Yang 285a5617496SJie Yang inline void 286a5617496SJie Yang getChassisConnectivity(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 287a5617496SJie Yang const std::string& chassisId, 288a5617496SJie Yang const std::string& chassisPath) 289a5617496SJie Yang { 29062598e31SEd Tanous BMCWEB_LOG_DEBUG("Get chassis connectivity"); 291a5617496SJie Yang 292a5617496SJie Yang dbus::utility::getAssociationEndPoints( 293a5617496SJie Yang chassisPath + "/contained_by", 294a5617496SJie Yang std::bind_front(getChassisContainedBy, asyncResp, chassisId)); 295a5617496SJie Yang 296a5617496SJie Yang dbus::utility::getAssociationEndPoints( 297a5617496SJie Yang chassisPath + "/containing", 298a5617496SJie Yang std::bind_front(getChassisContains, asyncResp, chassisId)); 299a5617496SJie Yang } 300a5617496SJie Yang 301cf7eba09SNan Zhou /** 302cf7eba09SNan Zhou * ChassisCollection derived class for delivering Chassis Collection Schema 303cf7eba09SNan Zhou * Functions triggers appropriate requests on DBus 304cf7eba09SNan Zhou */ 305cf7eba09SNan Zhou inline void requestRoutesChassisCollection(App& app) 306cf7eba09SNan Zhou { 307cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/") 308cf7eba09SNan Zhou .privileges(redfish::privileges::getChassisCollection) 309cf7eba09SNan Zhou .methods(boost::beast::http::verb::get)( 310cf7eba09SNan Zhou std::bind_front(handleChassisCollectionGet, std::ref(app))); 31162d5e2e4SEd Tanous } 312e37f8451SRapkiewicz, Pawel 313308f70c7SWilly Tu inline void 314308f70c7SWilly Tu getChassisLocationCode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 315308f70c7SWilly Tu const std::string& connectionName, 316308f70c7SWilly Tu const std::string& path) 317308f70c7SWilly Tu { 3181e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 3191e1e598dSJonathan Doman *crow::connections::systemBus, connectionName, path, 3201e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode", 3215e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec, 3221e1e598dSJonathan Doman const std::string& property) { 323308f70c7SWilly Tu if (ec) 324308f70c7SWilly Tu { 32562598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error for Location"); 326308f70c7SWilly Tu messages::internalError(asyncResp->res); 327308f70c7SWilly Tu return; 328308f70c7SWilly Tu } 329308f70c7SWilly Tu 330002d39b4SEd Tanous asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] = 3311e1e598dSJonathan Doman property; 3321e1e598dSJonathan Doman }); 333308f70c7SWilly Tu } 334308f70c7SWilly Tu 335308f70c7SWilly Tu inline void getChassisUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 336308f70c7SWilly Tu const std::string& connectionName, 337308f70c7SWilly Tu const std::string& path) 338308f70c7SWilly Tu { 3391e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 3401e1e598dSJonathan Doman *crow::connections::systemBus, connectionName, path, 3411e1e598dSJonathan Doman "xyz.openbmc_project.Common.UUID", "UUID", 3425e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec, 3431e1e598dSJonathan Doman const std::string& chassisUUID) { 344308f70c7SWilly Tu if (ec) 345308f70c7SWilly Tu { 34662598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error for UUID"); 347308f70c7SWilly Tu messages::internalError(asyncResp->res); 348308f70c7SWilly Tu return; 349308f70c7SWilly Tu } 3501e1e598dSJonathan Doman asyncResp->res.jsonValue["UUID"] = chassisUUID; 3511e1e598dSJonathan Doman }); 352308f70c7SWilly Tu } 353308f70c7SWilly Tu 3547164bc62SChau Ly inline void handleDecoratorAssetProperties( 35545ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 3567164bc62SChau Ly const std::string& chassisId, const std::string& path, 3577164bc62SChau Ly const dbus::utility::DBusPropertiesMap& propertiesList) 358cf7eba09SNan Zhou { 3597164bc62SChau Ly const std::string* partNumber = nullptr; 3607164bc62SChau Ly const std::string* serialNumber = nullptr; 3617164bc62SChau Ly const std::string* manufacturer = nullptr; 3627164bc62SChau Ly const std::string* model = nullptr; 3637164bc62SChau Ly const std::string* sparePartNumber = nullptr; 3647164bc62SChau Ly 3657164bc62SChau Ly const bool success = sdbusplus::unpackPropertiesNoThrow( 3667164bc62SChau Ly dbus_utils::UnpackErrorPrinter(), propertiesList, "PartNumber", 3677164bc62SChau Ly partNumber, "SerialNumber", serialNumber, "Manufacturer", manufacturer, 3687164bc62SChau Ly "Model", model, "SparePartNumber", sparePartNumber); 3697164bc62SChau Ly 3707164bc62SChau Ly if (!success) 37145ca1b86SEd Tanous { 3727164bc62SChau Ly messages::internalError(asyncResp->res); 37345ca1b86SEd Tanous return; 37445ca1b86SEd Tanous } 375734bfe90SGunnar Mills 3767164bc62SChau Ly if (partNumber != nullptr) 3777164bc62SChau Ly { 3787164bc62SChau Ly asyncResp->res.jsonValue["PartNumber"] = *partNumber; 3797164bc62SChau Ly } 3807164bc62SChau Ly 3817164bc62SChau Ly if (serialNumber != nullptr) 3827164bc62SChau Ly { 3837164bc62SChau Ly asyncResp->res.jsonValue["SerialNumber"] = *serialNumber; 3847164bc62SChau Ly } 3857164bc62SChau Ly 3867164bc62SChau Ly if (manufacturer != nullptr) 3877164bc62SChau Ly { 3887164bc62SChau Ly asyncResp->res.jsonValue["Manufacturer"] = *manufacturer; 3897164bc62SChau Ly } 3907164bc62SChau Ly 3917164bc62SChau Ly if (model != nullptr) 3927164bc62SChau Ly { 3937164bc62SChau Ly asyncResp->res.jsonValue["Model"] = *model; 3947164bc62SChau Ly } 3957164bc62SChau Ly 3967164bc62SChau Ly // SparePartNumber is optional on D-Bus 3977164bc62SChau Ly // so skip if it is empty 3987164bc62SChau Ly if (sparePartNumber != nullptr && !sparePartNumber->empty()) 3997164bc62SChau Ly { 4007164bc62SChau Ly asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber; 4017164bc62SChau Ly } 4027164bc62SChau Ly 4037164bc62SChau Ly asyncResp->res.jsonValue["Name"] = chassisId; 4047164bc62SChau Ly asyncResp->res.jsonValue["Id"] = chassisId; 405*25b54dbaSEd Tanous 406*25b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_ALLOW_DEPRECATED_POWER_THERMAL) 407*25b54dbaSEd Tanous { 4087164bc62SChau Ly asyncResp->res.jsonValue["Thermal"]["@odata.id"] = 4097164bc62SChau Ly boost::urls::format("/redfish/v1/Chassis/{}/Thermal", chassisId); 4107164bc62SChau Ly // Power object 4117164bc62SChau Ly asyncResp->res.jsonValue["Power"]["@odata.id"] = 4127164bc62SChau Ly boost::urls::format("/redfish/v1/Chassis/{}/Power", chassisId); 413*25b54dbaSEd Tanous } 414*25b54dbaSEd Tanous 415*25b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_NEW_POWERSUBSYSTEM_THERMALSUBSYSTEM) 416*25b54dbaSEd Tanous { 4177164bc62SChau Ly asyncResp->res.jsonValue["ThermalSubsystem"]["@odata.id"] = 4187164bc62SChau Ly boost::urls::format("/redfish/v1/Chassis/{}/ThermalSubsystem", 4197164bc62SChau Ly chassisId); 4207164bc62SChau Ly asyncResp->res.jsonValue["PowerSubsystem"]["@odata.id"] = 421*25b54dbaSEd Tanous boost::urls::format("/redfish/v1/Chassis/{}/PowerSubsystem", 422*25b54dbaSEd Tanous chassisId); 4237164bc62SChau Ly asyncResp->res.jsonValue["EnvironmentMetrics"]["@odata.id"] = 4247164bc62SChau Ly boost::urls::format("/redfish/v1/Chassis/{}/EnvironmentMetrics", 4257164bc62SChau Ly chassisId); 426*25b54dbaSEd Tanous } 4277164bc62SChau Ly // SensorCollection 4287164bc62SChau Ly asyncResp->res.jsonValue["Sensors"]["@odata.id"] = 4297164bc62SChau Ly boost::urls::format("/redfish/v1/Chassis/{}/Sensors", chassisId); 4307164bc62SChau Ly asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; 4317164bc62SChau Ly 4327164bc62SChau Ly nlohmann::json::array_t computerSystems; 4337164bc62SChau Ly nlohmann::json::object_t system; 4347164bc62SChau Ly system["@odata.id"] = "/redfish/v1/Systems/system"; 4357164bc62SChau Ly computerSystems.emplace_back(std::move(system)); 4367164bc62SChau Ly asyncResp->res.jsonValue["Links"]["ComputerSystems"] = 4377164bc62SChau Ly std::move(computerSystems); 4387164bc62SChau Ly 4397164bc62SChau Ly nlohmann::json::array_t managedBy; 4407164bc62SChau Ly nlohmann::json::object_t manager; 4417164bc62SChau Ly manager["@odata.id"] = "/redfish/v1/Managers/bmc"; 4427164bc62SChau Ly managedBy.emplace_back(std::move(manager)); 4437164bc62SChau Ly asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy); 4447164bc62SChau Ly getChassisState(asyncResp); 4457164bc62SChau Ly getStorageLink(asyncResp, path); 4467164bc62SChau Ly } 4477164bc62SChau Ly 4487164bc62SChau Ly inline void handleChassisGetSubTree( 4497164bc62SChau Ly const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 4507164bc62SChau Ly const std::string& chassisId, const boost::system::error_code& ec, 4517164bc62SChau Ly const dbus::utility::MapperGetSubTreeResponse& subtree) 4527164bc62SChau Ly { 45362d5e2e4SEd Tanous if (ec) 4541abe55efSEd Tanous { 45562598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error {}", ec); 456f12894f8SJason M. Bills messages::internalError(asyncResp->res); 457daf36e2eSEd Tanous return; 458daf36e2eSEd Tanous } 459daf36e2eSEd Tanous // Iterate over all retrieved ObjectPaths. 460cf7eba09SNan Zhou for (const std::pair< 461cf7eba09SNan Zhou std::string, 462cf7eba09SNan Zhou std::vector<std::pair<std::string, std::vector<std::string>>>>& 4631214b7e7SGunnar Mills object : subtree) 4641abe55efSEd Tanous { 465daf36e2eSEd Tanous const std::string& path = object.first; 466cf7eba09SNan Zhou const std::vector<std::pair<std::string, std::vector<std::string>>>& 4671214b7e7SGunnar Mills connectionNames = object.second; 4687e860f15SJohn Edward Broadbent 469997093ebSGeorge Liu sdbusplus::message::object_path objPath(path); 470997093ebSGeorge Liu if (objPath.filename() != chassisId) 4711abe55efSEd Tanous { 472daf36e2eSEd Tanous continue; 473daf36e2eSEd Tanous } 47426f03899SShawn McCarney 475a5617496SJie Yang getChassisConnectivity(asyncResp, chassisId, path); 476a5617496SJie Yang 47726f6976fSEd Tanous if (connectionNames.empty()) 4781abe55efSEd Tanous { 47962598e31SEd Tanous BMCWEB_LOG_ERROR("Got 0 Connection names"); 480e0d918bcSEd Tanous continue; 481daf36e2eSEd Tanous } 482e0d918bcSEd Tanous 4837164bc62SChau Ly asyncResp->res.jsonValue["@odata.type"] = "#Chassis.v1_22_0.Chassis"; 48449c53ac9SJohnathan Mantey asyncResp->res.jsonValue["@odata.id"] = 485ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/Chassis/{}", chassisId); 48649c53ac9SJohnathan Mantey asyncResp->res.jsonValue["Name"] = "Chassis Collection"; 48749c53ac9SJohnathan Mantey asyncResp->res.jsonValue["ChassisType"] = "RackMount"; 488cf7eba09SNan Zhou asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"]["target"] = 4897164bc62SChau Ly boost::urls::format("/redfish/v1/Chassis/{}/Actions/Chassis.Reset", 4907164bc62SChau Ly chassisId); 4911476687dSEd Tanous asyncResp->res 492cf7eba09SNan Zhou .jsonValue["Actions"]["#Chassis.Reset"]["@Redfish.ActionInfo"] = 493ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/Chassis/{}/ResetActionInfo", 494ef4c65b7SEd Tanous chassisId); 4956c3e9451SGeorge Liu dbus::utility::getAssociationEndPoints( 4966c3e9451SGeorge Liu path + "/drive", 4977164bc62SChau Ly [asyncResp, chassisId](const boost::system::error_code& ec3, 4986c3e9451SGeorge Liu const dbus::utility::MapperEndPoints& resp) { 49992903bd4SJohn Edward Broadbent if (ec3 || resp.empty()) 50092903bd4SJohn Edward Broadbent { 50192903bd4SJohn Edward Broadbent return; // no drives = no failures 50292903bd4SJohn Edward Broadbent } 50392903bd4SJohn Edward Broadbent 50492903bd4SJohn Edward Broadbent nlohmann::json reference; 5057164bc62SChau Ly reference["@odata.id"] = 5067164bc62SChau Ly boost::urls::format("/redfish/v1/Chassis/{}/Drives", chassisId); 50792903bd4SJohn Edward Broadbent asyncResp->res.jsonValue["Drives"] = std::move(reference); 50892903bd4SJohn Edward Broadbent }); 50992903bd4SJohn Edward Broadbent 510002d39b4SEd Tanous const std::string& connectionName = connectionNames[0].first; 5111c8fba97SJames Feist 5127164bc62SChau Ly const std::vector<std::string>& interfaces2 = connectionNames[0].second; 513e5ae9c1cSGeorge Liu const std::array<const char*, 3> hasIndicatorLed = { 514e5ae9c1cSGeorge Liu "xyz.openbmc_project.Inventory.Item.Chassis", 5151c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Panel", 5160fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Item.Board.Motherboard"}; 5171c8fba97SJames Feist 518476b9cc5STejas Patil const std::string assetTagInterface = 5190fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.AssetTag"; 520523d4868SLogananth Sundararaj const std::string replaceableInterface = 521523d4868SLogananth Sundararaj "xyz.openbmc_project.Inventory.Decorator.Replaceable"; 522b4d593f1SCarson Labrado const std::string revisionInterface = 523b4d593f1SCarson Labrado "xyz.openbmc_project.Inventory.Decorator.Revision"; 524523d4868SLogananth Sundararaj for (const auto& interface : interfaces2) 525523d4868SLogananth Sundararaj { 526523d4868SLogananth Sundararaj if (interface == assetTagInterface) 527476b9cc5STejas Patil { 5281e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 529002d39b4SEd Tanous *crow::connections::systemBus, connectionName, path, 530002d39b4SEd Tanous assetTagInterface, "AssetTag", 5317164bc62SChau Ly [asyncResp, chassisId](const boost::system::error_code& ec2, 5321e1e598dSJonathan Doman const std::string& property) { 5338a592810SEd Tanous if (ec2) 534476b9cc5STejas Patil { 5357164bc62SChau Ly BMCWEB_LOG_ERROR("DBus response error for AssetTag: {}", 5367164bc62SChau Ly ec2); 537476b9cc5STejas Patil messages::internalError(asyncResp->res); 538476b9cc5STejas Patil return; 539476b9cc5STejas Patil } 540002d39b4SEd Tanous asyncResp->res.jsonValue["AssetTag"] = property; 5411e1e598dSJonathan Doman }); 542476b9cc5STejas Patil } 543523d4868SLogananth Sundararaj else if (interface == replaceableInterface) 544523d4868SLogananth Sundararaj { 545523d4868SLogananth Sundararaj sdbusplus::asio::getProperty<bool>( 546523d4868SLogananth Sundararaj *crow::connections::systemBus, connectionName, path, 547523d4868SLogananth Sundararaj replaceableInterface, "HotPluggable", 5487164bc62SChau Ly [asyncResp, chassisId](const boost::system::error_code& ec2, 549523d4868SLogananth Sundararaj const bool property) { 550523d4868SLogananth Sundararaj if (ec2) 551523d4868SLogananth Sundararaj { 55262598e31SEd Tanous BMCWEB_LOG_ERROR( 5537164bc62SChau Ly "DBus response error for HotPluggable: {}", ec2); 554523d4868SLogananth Sundararaj messages::internalError(asyncResp->res); 555523d4868SLogananth Sundararaj return; 556523d4868SLogananth Sundararaj } 557523d4868SLogananth Sundararaj asyncResp->res.jsonValue["HotPluggable"] = property; 558523d4868SLogananth Sundararaj }); 559523d4868SLogananth Sundararaj } 560b4d593f1SCarson Labrado else if (interface == revisionInterface) 561b4d593f1SCarson Labrado { 562b4d593f1SCarson Labrado sdbusplus::asio::getProperty<std::string>( 563b4d593f1SCarson Labrado *crow::connections::systemBus, connectionName, path, 564b4d593f1SCarson Labrado revisionInterface, "Version", 565b4d593f1SCarson Labrado [asyncResp, chassisId](const boost::system::error_code& ec2, 566b4d593f1SCarson Labrado const std::string& property) { 567b4d593f1SCarson Labrado if (ec2) 568b4d593f1SCarson Labrado { 569b4d593f1SCarson Labrado BMCWEB_LOG_ERROR("DBus response error for Version: {}", 570b4d593f1SCarson Labrado ec2); 571b4d593f1SCarson Labrado messages::internalError(asyncResp->res); 572b4d593f1SCarson Labrado return; 573b4d593f1SCarson Labrado } 574b4d593f1SCarson Labrado asyncResp->res.jsonValue["Version"] = property; 575b4d593f1SCarson Labrado }); 576b4d593f1SCarson Labrado } 577523d4868SLogananth Sundararaj } 578476b9cc5STejas Patil 5791c8fba97SJames Feist for (const char* interface : hasIndicatorLed) 5801c8fba97SJames Feist { 5817164bc62SChau Ly if (std::ranges::find(interfaces2, interface) != interfaces2.end()) 5821c8fba97SJames Feist { 5831c8fba97SJames Feist getIndicatorLedState(asyncResp); 58459a17e4fSGeorge Liu getSystemLocationIndicatorActive(asyncResp); 5851c8fba97SJames Feist break; 5861c8fba97SJames Feist } 5871c8fba97SJames Feist } 5881c8fba97SJames Feist 58986d89ed7SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 59086d89ed7SKrzysztof Grobelny *crow::connections::systemBus, connectionName, path, 59186d89ed7SKrzysztof Grobelny "xyz.openbmc_project.Inventory.Decorator.Asset", 5927164bc62SChau Ly [asyncResp, chassisId, 5937164bc62SChau Ly path](const boost::system::error_code&, 594cf7eba09SNan Zhou const dbus::utility::DBusPropertiesMap& propertiesList) { 5957164bc62SChau Ly handleDecoratorAssetProperties(asyncResp, chassisId, path, 5967164bc62SChau Ly propertiesList); 59786d89ed7SKrzysztof Grobelny }); 5982c37b4b0SSharad Yadav 599308f70c7SWilly Tu for (const auto& interface : interfaces2) 6002c37b4b0SSharad Yadav { 601308f70c7SWilly Tu if (interface == "xyz.openbmc_project.Common.UUID") 6022c37b4b0SSharad Yadav { 603308f70c7SWilly Tu getChassisUUID(asyncResp, connectionName, path); 6042c37b4b0SSharad Yadav } 605cf7eba09SNan Zhou else if (interface == 6060fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode") 6072c37b4b0SSharad Yadav { 608002d39b4SEd Tanous getChassisLocationCode(asyncResp, connectionName, path); 6092c37b4b0SSharad Yadav } 6102c37b4b0SSharad Yadav } 6112c37b4b0SSharad Yadav 612daf36e2eSEd Tanous return; 613daf36e2eSEd Tanous } 614e0d918bcSEd Tanous 615daf36e2eSEd Tanous // Couldn't find an object with that name. return an error 616d8a5d5d8SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "Chassis", chassisId); 6177164bc62SChau Ly } 618c181942fSQiang XU 6197164bc62SChau Ly inline void 6207164bc62SChau Ly handleChassisGet(App& app, const crow::Request& req, 6217164bc62SChau Ly const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 6227164bc62SChau Ly const std::string& chassisId) 6237164bc62SChau Ly { 6247164bc62SChau Ly if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 6257164bc62SChau Ly { 6267164bc62SChau Ly return; 6277164bc62SChau Ly } 6287164bc62SChau Ly constexpr std::array<std::string_view, 2> interfaces = { 6297164bc62SChau Ly "xyz.openbmc_project.Inventory.Item.Board", 6307164bc62SChau Ly "xyz.openbmc_project.Inventory.Item.Chassis"}; 6317164bc62SChau Ly 6327164bc62SChau Ly dbus::utility::getSubTree( 6337164bc62SChau Ly "/xyz/openbmc_project/inventory", 0, interfaces, 6347164bc62SChau Ly std::bind_front(handleChassisGetSubTree, asyncResp, chassisId)); 6357164bc62SChau Ly 6367164bc62SChau Ly constexpr std::array<std::string_view, 1> interfaces2 = { 6377164bc62SChau Ly "xyz.openbmc_project.Chassis.Intrusion"}; 6387164bc62SChau Ly 6397164bc62SChau Ly dbus::utility::getSubTree( 6407164bc62SChau Ly "/xyz/openbmc_project", 0, interfaces2, 6417164bc62SChau Ly std::bind_front(handlePhysicalSecurityGetSubTree, asyncResp)); 642cf7eba09SNan Zhou } 6431c8fba97SJames Feist 644cf7eba09SNan Zhou inline void 645cf7eba09SNan Zhou handleChassisPatch(App& app, const crow::Request& req, 6467e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 647cf7eba09SNan Zhou const std::string& param) 648cf7eba09SNan Zhou { 6493ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 65045ca1b86SEd Tanous { 65145ca1b86SEd Tanous return; 65245ca1b86SEd Tanous } 6539f8bfa7cSGunnar Mills std::optional<bool> locationIndicatorActive; 6541c8fba97SJames Feist std::optional<std::string> indicatorLed; 6551c8fba97SJames Feist 6567e860f15SJohn Edward Broadbent if (param.empty()) 6571c8fba97SJames Feist { 6581c8fba97SJames Feist return; 6591c8fba97SJames Feist } 6601c8fba97SJames Feist 66115ed6780SWilly Tu if (!json_util::readJsonPatch( 6627e860f15SJohn Edward Broadbent req, asyncResp->res, "LocationIndicatorActive", 6637e860f15SJohn Edward Broadbent locationIndicatorActive, "IndicatorLED", indicatorLed)) 6641c8fba97SJames Feist { 6651c8fba97SJames Feist return; 6661c8fba97SJames Feist } 6671c8fba97SJames Feist 6689f8bfa7cSGunnar Mills // TODO (Gunnar): Remove IndicatorLED after enough time has passed 6699f8bfa7cSGunnar Mills if (!locationIndicatorActive && !indicatorLed) 6701c8fba97SJames Feist { 6711c8fba97SJames Feist return; // delete this when we support more patch properties 6721c8fba97SJames Feist } 673d6aa0093SGunnar Mills if (indicatorLed) 674d6aa0093SGunnar Mills { 6757e860f15SJohn Edward Broadbent asyncResp->res.addHeader( 6767e860f15SJohn Edward Broadbent boost::beast::http::field::warning, 6770fda0f12SGeorge Liu "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\""); 678d6aa0093SGunnar Mills } 6791c8fba97SJames Feist 680e99073f5SGeorge Liu constexpr std::array<std::string_view, 2> interfaces = { 6811c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Board", 6821c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Chassis"}; 6831c8fba97SJames Feist 6847e860f15SJohn Edward Broadbent const std::string& chassisId = param; 6851c8fba97SJames Feist 686e99073f5SGeorge Liu dbus::utility::getSubTree( 687e99073f5SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 688cf7eba09SNan Zhou [asyncResp, chassisId, locationIndicatorActive, 6895e7e2dc5SEd Tanous indicatorLed](const boost::system::error_code& ec, 690b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtree) { 6911c8fba97SJames Feist if (ec) 6921c8fba97SJames Feist { 69362598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error {}", ec); 6941c8fba97SJames Feist messages::internalError(asyncResp->res); 6951c8fba97SJames Feist return; 6961c8fba97SJames Feist } 6971c8fba97SJames Feist 6981c8fba97SJames Feist // Iterate over all retrieved ObjectPaths. 699cf7eba09SNan Zhou for (const std::pair< 700cf7eba09SNan Zhou std::string, 701cf7eba09SNan Zhou std::vector<std::pair<std::string, std::vector<std::string>>>>& 7021214b7e7SGunnar Mills object : subtree) 7031c8fba97SJames Feist { 7041c8fba97SJames Feist const std::string& path = object.first; 705cf7eba09SNan Zhou const std::vector<std::pair<std::string, std::vector<std::string>>>& 7061214b7e7SGunnar Mills connectionNames = object.second; 7071c8fba97SJames Feist 708997093ebSGeorge Liu sdbusplus::message::object_path objPath(path); 709997093ebSGeorge Liu if (objPath.filename() != chassisId) 7101c8fba97SJames Feist { 7111c8fba97SJames Feist continue; 7121c8fba97SJames Feist } 7131c8fba97SJames Feist 71426f6976fSEd Tanous if (connectionNames.empty()) 7151c8fba97SJames Feist { 71662598e31SEd Tanous BMCWEB_LOG_ERROR("Got 0 Connection names"); 7171c8fba97SJames Feist continue; 7181c8fba97SJames Feist } 7191c8fba97SJames Feist 72023a21a1cSEd Tanous const std::vector<std::string>& interfaces3 = 7211c8fba97SJames Feist connectionNames[0].second; 7221c8fba97SJames Feist 723e5ae9c1cSGeorge Liu const std::array<const char*, 3> hasIndicatorLed = { 724e5ae9c1cSGeorge Liu "xyz.openbmc_project.Inventory.Item.Chassis", 7251c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Panel", 7260fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Item.Board.Motherboard"}; 7271c8fba97SJames Feist bool indicatorChassis = false; 7281c8fba97SJames Feist for (const char* interface : hasIndicatorLed) 7291c8fba97SJames Feist { 7303544d2a7SEd Tanous if (std::ranges::find(interfaces3, interface) != 7313544d2a7SEd Tanous interfaces3.end()) 7321c8fba97SJames Feist { 7331c8fba97SJames Feist indicatorChassis = true; 7341c8fba97SJames Feist break; 7351c8fba97SJames Feist } 7361c8fba97SJames Feist } 7379f8bfa7cSGunnar Mills if (locationIndicatorActive) 7389f8bfa7cSGunnar Mills { 7399f8bfa7cSGunnar Mills if (indicatorChassis) 7409f8bfa7cSGunnar Mills { 74159a17e4fSGeorge Liu setSystemLocationIndicatorActive(asyncResp, 742002d39b4SEd Tanous *locationIndicatorActive); 7439f8bfa7cSGunnar Mills } 7449f8bfa7cSGunnar Mills else 7459f8bfa7cSGunnar Mills { 746002d39b4SEd Tanous messages::propertyUnknown(asyncResp->res, 747002d39b4SEd Tanous "LocationIndicatorActive"); 7489f8bfa7cSGunnar Mills } 7499f8bfa7cSGunnar Mills } 7509f8bfa7cSGunnar Mills if (indicatorLed) 7519f8bfa7cSGunnar Mills { 7521c8fba97SJames Feist if (indicatorChassis) 7531c8fba97SJames Feist { 754f23b7296SEd Tanous setIndicatorLedState(asyncResp, *indicatorLed); 7551c8fba97SJames Feist } 7561c8fba97SJames Feist else 7571c8fba97SJames Feist { 758cf7eba09SNan Zhou messages::propertyUnknown(asyncResp->res, "IndicatorLED"); 7591c8fba97SJames Feist } 7601c8fba97SJames Feist } 7611c8fba97SJames Feist return; 7621c8fba97SJames Feist } 7631c8fba97SJames Feist 764d8a5d5d8SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "Chassis", chassisId); 765e99073f5SGeorge Liu }); 766cf7eba09SNan Zhou } 767cf7eba09SNan Zhou 768cf7eba09SNan Zhou /** 769cf7eba09SNan Zhou * Chassis override class for delivering Chassis Schema 770cf7eba09SNan Zhou * Functions triggers appropriate requests on DBus 771cf7eba09SNan Zhou */ 772cf7eba09SNan Zhou inline void requestRoutesChassis(App& app) 773cf7eba09SNan Zhou { 774cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/") 775cf7eba09SNan Zhou .privileges(redfish::privileges::getChassis) 776cf7eba09SNan Zhou .methods(boost::beast::http::verb::get)( 777cf7eba09SNan Zhou std::bind_front(handleChassisGet, std::ref(app))); 778cf7eba09SNan Zhou 779cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/") 780cf7eba09SNan Zhou .privileges(redfish::privileges::patchChassis) 781cf7eba09SNan Zhou .methods(boost::beast::http::verb::patch)( 782cf7eba09SNan Zhou std::bind_front(handleChassisPatch, std::ref(app))); 7831c8fba97SJames Feist } 784dd99e04bSP.K. Lee 7858d1b46d7Szhanghch05 inline void 7868d1b46d7Szhanghch05 doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 787dd99e04bSP.K. Lee { 7887a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 789c3b3c92aSVijay Khemka "xyz.openbmc_project.State.Chassis"}; 790c3b3c92aSVijay Khemka 791c3b3c92aSVijay Khemka // Use mapper to get subtree paths. 7927a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 7937a1dbc48SGeorge Liu "/", 0, interfaces, 794b9d36b47SEd Tanous [asyncResp]( 7957a1dbc48SGeorge Liu const boost::system::error_code& ec, 796b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& chassisList) { 797c3b3c92aSVijay Khemka if (ec) 798c3b3c92aSVijay Khemka { 79962598e31SEd Tanous BMCWEB_LOG_ERROR("[mapper] Bad D-Bus request error: {}", ec); 800c3b3c92aSVijay Khemka messages::internalError(asyncResp->res); 801c3b3c92aSVijay Khemka return; 802c3b3c92aSVijay Khemka } 803c3b3c92aSVijay Khemka 804dd99e04bSP.K. Lee const char* processName = "xyz.openbmc_project.State.Chassis"; 805dd99e04bSP.K. Lee const char* interfaceName = "xyz.openbmc_project.State.Chassis"; 806dd99e04bSP.K. Lee const char* destProperty = "RequestedPowerTransition"; 807dd99e04bSP.K. Lee const std::string propertyValue = 808dd99e04bSP.K. Lee "xyz.openbmc_project.State.Chassis.Transition.PowerCycle"; 809002d39b4SEd Tanous std::string objectPath = "/xyz/openbmc_project/state/chassis_system0"; 810c3b3c92aSVijay Khemka 811c3b3c92aSVijay Khemka /* Look for system reset chassis path */ 8123544d2a7SEd Tanous if ((std::ranges::find(chassisList, objectPath)) == chassisList.end()) 813c3b3c92aSVijay Khemka { 814c3b3c92aSVijay Khemka /* We prefer to reset the full chassis_system, but if it doesn't 815c3b3c92aSVijay Khemka * exist on some platforms, fall back to a host-only power reset 816c3b3c92aSVijay Khemka */ 817c3b3c92aSVijay Khemka objectPath = "/xyz/openbmc_project/state/chassis0"; 818c3b3c92aSVijay Khemka } 819dd99e04bSP.K. Lee 820d02aad39SEd Tanous setDbusProperty(asyncResp, processName, objectPath, interfaceName, 821d02aad39SEd Tanous destProperty, "ResetType", propertyValue); 8227a1dbc48SGeorge Liu }); 823dd99e04bSP.K. Lee } 824dd99e04bSP.K. Lee 825cf7eba09SNan Zhou inline void handleChassisResetActionInfoPost( 826cf7eba09SNan Zhou App& app, const crow::Request& req, 8277e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 828cf7eba09SNan Zhou const std::string& /*chassisId*/) 829cf7eba09SNan Zhou { 8303ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 83145ca1b86SEd Tanous { 83245ca1b86SEd Tanous return; 83345ca1b86SEd Tanous } 83462598e31SEd Tanous BMCWEB_LOG_DEBUG("Post Chassis Reset."); 835dd99e04bSP.K. Lee 836dd99e04bSP.K. Lee std::string resetType; 837dd99e04bSP.K. Lee 838cf7eba09SNan Zhou if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType)) 839dd99e04bSP.K. Lee { 840dd99e04bSP.K. Lee return; 841dd99e04bSP.K. Lee } 842dd99e04bSP.K. Lee 843dd99e04bSP.K. Lee if (resetType != "PowerCycle") 844dd99e04bSP.K. Lee { 84562598e31SEd Tanous BMCWEB_LOG_DEBUG("Invalid property value for ResetType: {}", resetType); 846002d39b4SEd Tanous messages::actionParameterNotSupported(asyncResp->res, resetType, 847002d39b4SEd Tanous "ResetType"); 848dd99e04bSP.K. Lee 849dd99e04bSP.K. Lee return; 850dd99e04bSP.K. Lee } 851dd99e04bSP.K. Lee doChassisPowerCycle(asyncResp); 852dd99e04bSP.K. Lee } 8531cb1a9e6SAppaRao Puli 8541cb1a9e6SAppaRao Puli /** 855cf7eba09SNan Zhou * ChassisResetAction class supports the POST method for the Reset 856cf7eba09SNan Zhou * action. 857cf7eba09SNan Zhou * Function handles POST method request. 858cf7eba09SNan Zhou * Analyzes POST body before sending Reset request data to D-Bus. 8591cb1a9e6SAppaRao Puli */ 860cf7eba09SNan Zhou 861cf7eba09SNan Zhou inline void requestRoutesChassisResetAction(App& app) 8621cb1a9e6SAppaRao Puli { 863cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/") 864cf7eba09SNan Zhou .privileges(redfish::privileges::postChassis) 865cf7eba09SNan Zhou .methods(boost::beast::http::verb::post)( 866cf7eba09SNan Zhou std::bind_front(handleChassisResetActionInfoPost, std::ref(app))); 867cf7eba09SNan Zhou } 868cf7eba09SNan Zhou 869cf7eba09SNan Zhou inline void handleChassisResetActionInfoGet( 870cf7eba09SNan Zhou App& app, const crow::Request& req, 8717e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 872cf7eba09SNan Zhou const std::string& chassisId) 873cf7eba09SNan Zhou { 8743ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 8751cb1a9e6SAppaRao Puli { 87645ca1b86SEd Tanous return; 87745ca1b86SEd Tanous } 878cf7eba09SNan Zhou asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo"; 879ef4c65b7SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 880ef4c65b7SEd Tanous "/redfish/v1/Chassis/{}/ResetActionInfo", chassisId); 8811476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "Reset Action Info"; 8821476687dSEd Tanous 8831476687dSEd Tanous asyncResp->res.jsonValue["Id"] = "ResetActionInfo"; 8845b9e95a1SNan Zhou nlohmann::json::array_t parameters; 8855b9e95a1SNan Zhou nlohmann::json::object_t parameter; 8865b9e95a1SNan Zhou parameter["Name"] = "ResetType"; 8875b9e95a1SNan Zhou parameter["Required"] = true; 8885b9e95a1SNan Zhou parameter["DataType"] = "String"; 8891476687dSEd Tanous nlohmann::json::array_t allowed; 890ad539545SPatrick Williams allowed.emplace_back("PowerCycle"); 8915b9e95a1SNan Zhou parameter["AllowableValues"] = std::move(allowed); 892ad539545SPatrick Williams parameters.emplace_back(std::move(parameter)); 8935b9e95a1SNan Zhou 8941476687dSEd Tanous asyncResp->res.jsonValue["Parameters"] = std::move(parameters); 895cf7eba09SNan Zhou } 896cf7eba09SNan Zhou 897cf7eba09SNan Zhou /** 898cf7eba09SNan Zhou * ChassisResetActionInfo derived class for delivering Chassis 899cf7eba09SNan Zhou * ResetType AllowableValues using ResetInfo schema. 900cf7eba09SNan Zhou */ 901cf7eba09SNan Zhou inline void requestRoutesChassisResetActionInfo(App& app) 902cf7eba09SNan Zhou { 903cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/") 904cf7eba09SNan Zhou .privileges(redfish::privileges::getActionInfo) 905cf7eba09SNan Zhou .methods(boost::beast::http::verb::get)( 906cf7eba09SNan Zhou std::bind_front(handleChassisResetActionInfoGet, std::ref(app))); 9071cb1a9e6SAppaRao Puli } 9081cb1a9e6SAppaRao Puli 909e37f8451SRapkiewicz, Pawel } // namespace redfish 910