1e37f8451SRapkiewicz, Pawel /* 26be832e2SEd Tanous Copyright (c) 2018 Intel Corporation 36be832e2SEd Tanous 46be832e2SEd Tanous Licensed under the Apache License, Version 2.0 (the "License"); 56be832e2SEd Tanous you may not use this file except in compliance with the License. 66be832e2SEd Tanous You may obtain a copy of the License at 76be832e2SEd Tanous 86be832e2SEd Tanous http://www.apache.org/licenses/LICENSE-2.0 96be832e2SEd Tanous 106be832e2SEd Tanous Unless required by applicable law or agreed to in writing, software 116be832e2SEd Tanous distributed under the License is distributed on an "AS IS" BASIS, 126be832e2SEd Tanous WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136be832e2SEd Tanous See the License for the specific language governing permissions and 146be832e2SEd Tanous limitations under the License. 15e37f8451SRapkiewicz, Pawel */ 16e37f8451SRapkiewicz, Pawel #pragma once 17e37f8451SRapkiewicz, Pawel 183ccb3adbSEd Tanous #include "app.hpp" 197a1dbc48SGeorge Liu #include "dbus_utility.hpp" 20539d8c6bSEd Tanous #include "generated/enums/action_info.hpp" 21539d8c6bSEd Tanous #include "generated/enums/chassis.hpp" 22539d8c6bSEd Tanous #include "generated/enums/resource.hpp" 231c8fba97SJames Feist #include "led.hpp" 243ccb3adbSEd Tanous #include "query.hpp" 257164bc62SChau Ly #include "redfish_util.hpp" 263ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 273ccb3adbSEd Tanous #include "utils/collection.hpp" 283ccb3adbSEd Tanous #include "utils/dbus_utils.hpp" 29cf7eba09SNan Zhou #include "utils/json_utils.hpp" 301abe55efSEd Tanous 31e99073f5SGeorge Liu #include <boost/system/error_code.hpp> 32ef4c65b7SEd Tanous #include <boost/url/format.hpp> 331e1e598dSJonathan Doman #include <sdbusplus/asio/property.hpp> 34fc903b3dSAndrew Geissler #include <sdbusplus/message.hpp> 3586d89ed7SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 361214b7e7SGunnar Mills 377a1dbc48SGeorge Liu #include <array> 383544d2a7SEd Tanous #include <ranges> 397a1dbc48SGeorge Liu #include <string_view> 407a1dbc48SGeorge Liu 411abe55efSEd Tanous namespace redfish 421abe55efSEd Tanous { 43e37f8451SRapkiewicz, Pawel 44e37f8451SRapkiewicz, Pawel /** 455e577bc1SWilly Tu * @brief Retrieves resources over dbus to link to the chassis 465e577bc1SWilly Tu * 475e577bc1SWilly Tu * @param[in] asyncResp - Shared pointer for completing asynchronous 485e577bc1SWilly Tu * calls 495e577bc1SWilly Tu * @param[in] path - Chassis dbus path to look for the storage. 505e577bc1SWilly Tu * 515e577bc1SWilly Tu * Calls the Association endpoints on the path + "/storage" and add the link of 525e577bc1SWilly Tu * json["Links"]["Storage@odata.count"] = 535e577bc1SWilly Tu * {"@odata.id", "/redfish/v1/Storage/" + resourceId} 545e577bc1SWilly Tu * 555e577bc1SWilly Tu * @return None. 565e577bc1SWilly Tu */ 575e577bc1SWilly Tu inline void getStorageLink(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 585e577bc1SWilly Tu const sdbusplus::message::object_path& path) 595e577bc1SWilly Tu { 605e577bc1SWilly Tu sdbusplus::asio::getProperty<std::vector<std::string>>( 615e577bc1SWilly Tu *crow::connections::systemBus, "xyz.openbmc_project.ObjectMapper", 625e577bc1SWilly Tu (path / "storage").str, "xyz.openbmc_project.Association", "endpoints", 63d4b054c1SWilly Tu [asyncResp](const boost::system::error_code& ec, 645e577bc1SWilly Tu const std::vector<std::string>& storageList) { 655e577bc1SWilly Tu if (ec) 665e577bc1SWilly Tu { 6762598e31SEd Tanous BMCWEB_LOG_DEBUG("getStorageLink got DBUS response error"); 685e577bc1SWilly Tu return; 695e577bc1SWilly Tu } 705e577bc1SWilly Tu 715e577bc1SWilly Tu nlohmann::json::array_t storages; 725e577bc1SWilly Tu for (const std::string& storagePath : storageList) 735e577bc1SWilly Tu { 745e577bc1SWilly Tu std::string id = 755e577bc1SWilly Tu sdbusplus::message::object_path(storagePath).filename(); 765e577bc1SWilly Tu if (id.empty()) 775e577bc1SWilly Tu { 785e577bc1SWilly Tu continue; 795e577bc1SWilly Tu } 805e577bc1SWilly Tu 815e577bc1SWilly Tu nlohmann::json::object_t storage; 82253f11b8SEd Tanous storage["@odata.id"] = 83253f11b8SEd Tanous boost::urls::format("/redfish/v1/Systems/{}/Storage/{}", 84253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, id); 855e577bc1SWilly Tu storages.emplace_back(std::move(storage)); 865e577bc1SWilly Tu } 875e577bc1SWilly Tu asyncResp->res.jsonValue["Links"]["Storage@odata.count"] = 885e577bc1SWilly Tu storages.size(); 895e577bc1SWilly Tu asyncResp->res.jsonValue["Links"]["Storage"] = std::move(storages); 905e577bc1SWilly Tu }); 915e577bc1SWilly Tu } 925e577bc1SWilly Tu 935e577bc1SWilly Tu /** 94beeca0aeSGunnar Mills * @brief Retrieves chassis state properties over dbus 95beeca0aeSGunnar Mills * 96ac106bf6SEd Tanous * @param[in] asyncResp - Shared pointer for completing asynchronous calls. 97beeca0aeSGunnar Mills * 98beeca0aeSGunnar Mills * @return None. 99beeca0aeSGunnar Mills */ 100ac106bf6SEd Tanous inline void getChassisState(std::shared_ptr<bmcweb::AsyncResp> asyncResp) 101beeca0aeSGunnar Mills { 1021e1e598dSJonathan Doman // crow::connections::systemBus->async_method_call( 1031e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 1041e1e598dSJonathan Doman *crow::connections::systemBus, "xyz.openbmc_project.State.Chassis", 1051e1e598dSJonathan Doman "/xyz/openbmc_project/state/chassis0", 1061e1e598dSJonathan Doman "xyz.openbmc_project.State.Chassis", "CurrentPowerState", 107ac106bf6SEd Tanous [asyncResp{std::move(asyncResp)}](const boost::system::error_code& ec, 1081e1e598dSJonathan Doman const std::string& chassisState) { 109beeca0aeSGunnar Mills if (ec) 110beeca0aeSGunnar Mills { 111a6e5e0abSCarson Labrado if (ec == boost::system::errc::host_unreachable) 112a6e5e0abSCarson Labrado { 113a6e5e0abSCarson Labrado // Service not available, no error, just don't return 114a6e5e0abSCarson Labrado // chassis state info 11562598e31SEd Tanous BMCWEB_LOG_DEBUG("Service not available {}", ec); 116a6e5e0abSCarson Labrado return; 117a6e5e0abSCarson Labrado } 11862598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error {}", ec); 119ac106bf6SEd Tanous messages::internalError(asyncResp->res); 120beeca0aeSGunnar Mills return; 121beeca0aeSGunnar Mills } 122beeca0aeSGunnar Mills 12362598e31SEd Tanous BMCWEB_LOG_DEBUG("Chassis state: {}", chassisState); 124beeca0aeSGunnar Mills // Verify Chassis State 125bd79bce8SPatrick Williams if (chassisState == 126bd79bce8SPatrick Williams "xyz.openbmc_project.State.Chassis.PowerState.On") 127beeca0aeSGunnar Mills { 128bd79bce8SPatrick Williams asyncResp->res.jsonValue["PowerState"] = 129bd79bce8SPatrick Williams resource::PowerState::On; 130539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 131539d8c6bSEd Tanous resource::State::Enabled; 132beeca0aeSGunnar Mills } 1331e1e598dSJonathan Doman else if (chassisState == 134beeca0aeSGunnar Mills "xyz.openbmc_project.State.Chassis.PowerState.Off") 135beeca0aeSGunnar Mills { 136bd79bce8SPatrick Williams asyncResp->res.jsonValue["PowerState"] = 137bd79bce8SPatrick Williams resource::PowerState::Off; 138539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 139539d8c6bSEd Tanous resource::State::StandbyOffline; 140beeca0aeSGunnar Mills } 1411e1e598dSJonathan Doman }); 142beeca0aeSGunnar Mills } 143beeca0aeSGunnar Mills 144c181942fSQiang XU /** 145c181942fSQiang XU * Retrieves physical security properties over dbus 146c181942fSQiang XU */ 1477164bc62SChau Ly inline void handlePhysicalSecurityGetSubTree( 1487164bc62SChau Ly const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 149e99073f5SGeorge Liu const boost::system::error_code& ec, 1507164bc62SChau Ly const dbus::utility::MapperGetSubTreeResponse& subtree) 1517164bc62SChau Ly { 152c181942fSQiang XU if (ec) 153c181942fSQiang XU { 1544e0453b1SGunnar Mills // do not add err msg in redfish response, because this is not 155c181942fSQiang XU // mandatory property 15662598e31SEd Tanous BMCWEB_LOG_INFO("DBUS error: no matched iface {}", ec); 157c181942fSQiang XU return; 158c181942fSQiang XU } 159c181942fSQiang XU // Iterate over all retrieved ObjectPaths. 160c181942fSQiang XU for (const auto& object : subtree) 161c181942fSQiang XU { 162840a9ffcSPatrick Williams if (!object.second.empty()) 163c181942fSQiang XU { 16489144a3aSEd Tanous const auto& service = object.second.front(); 1657164bc62SChau Ly 1667164bc62SChau Ly BMCWEB_LOG_DEBUG("Get intrusion status by service "); 1677164bc62SChau Ly 1687164bc62SChau Ly sdbusplus::asio::getProperty<std::string>( 1697164bc62SChau Ly *crow::connections::systemBus, service.first, object.first, 1707164bc62SChau Ly "xyz.openbmc_project.Chassis.Intrusion", "Status", 1717164bc62SChau Ly [asyncResp](const boost::system::error_code& ec1, 1727164bc62SChau Ly const std::string& value) { 1737164bc62SChau Ly if (ec1) 1747164bc62SChau Ly { 175bd79bce8SPatrick Williams // do not add err msg in redfish response, because this 176bd79bce8SPatrick Williams // is not 1777164bc62SChau Ly // mandatory property 1787164bc62SChau Ly BMCWEB_LOG_ERROR("DBUS response error {}", ec1); 1797164bc62SChau Ly return; 1807164bc62SChau Ly } 181bd79bce8SPatrick Williams asyncResp->res.jsonValue["PhysicalSecurity"] 182bd79bce8SPatrick Williams ["IntrusionSensorNumber"] = 1; 1837164bc62SChau Ly asyncResp->res 184bd79bce8SPatrick Williams .jsonValue["PhysicalSecurity"]["IntrusionSensor"] = 185bd79bce8SPatrick Williams value; 1867164bc62SChau Ly }); 1877164bc62SChau Ly 188c181942fSQiang XU return; 189c181942fSQiang XU } 190c181942fSQiang XU } 191c181942fSQiang XU } 192c181942fSQiang XU 193cf7eba09SNan Zhou inline void handleChassisCollectionGet( 194cf7eba09SNan Zhou App& app, const crow::Request& req, 195cf7eba09SNan Zhou const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1961abe55efSEd Tanous { 1973ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 19845ca1b86SEd Tanous { 19945ca1b86SEd Tanous return; 20045ca1b86SEd Tanous } 2018d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 2028d1b46d7Szhanghch05 "#ChassisCollection.ChassisCollection"; 2038d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis"; 2048d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Chassis Collection"; 205e37f8451SRapkiewicz, Pawel 2067a1dbc48SGeorge Liu constexpr std::array<std::string_view, 2> interfaces{ 2077a1dbc48SGeorge Liu "xyz.openbmc_project.Inventory.Item.Board", 2087a1dbc48SGeorge Liu "xyz.openbmc_project.Inventory.Item.Chassis"}; 20902f6ff19SGunnar Mills collection_util::getCollectionMembers( 21036b5f1edSLakshmi Yadlapati asyncResp, boost::urls::url("/redfish/v1/Chassis"), interfaces, 21136b5f1edSLakshmi Yadlapati "/xyz/openbmc_project/inventory"); 212cf7eba09SNan Zhou } 213cf7eba09SNan Zhou 214a5617496SJie Yang inline void getChassisContainedBy( 215a5617496SJie Yang const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 216a5617496SJie Yang const std::string& chassisId, const boost::system::error_code& ec, 21728ee563eSMyung Bae const dbus::utility::MapperGetSubTreePathsResponse& upstreamChassisPaths) 218a5617496SJie Yang { 219a5617496SJie Yang if (ec) 220a5617496SJie Yang { 221a5617496SJie Yang if (ec.value() != EBADR) 222a5617496SJie Yang { 22362598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error {}", ec); 224a5617496SJie Yang messages::internalError(asyncResp->res); 225a5617496SJie Yang } 226a5617496SJie Yang return; 227a5617496SJie Yang } 228a5617496SJie Yang if (upstreamChassisPaths.empty()) 229a5617496SJie Yang { 230a5617496SJie Yang return; 231a5617496SJie Yang } 232a5617496SJie Yang if (upstreamChassisPaths.size() > 1) 233a5617496SJie Yang { 2348ece0e45SEd Tanous BMCWEB_LOG_ERROR("{} is contained by multiple chassis", chassisId); 235a5617496SJie Yang messages::internalError(asyncResp->res); 236a5617496SJie Yang return; 237a5617496SJie Yang } 238a5617496SJie Yang 239a5617496SJie Yang sdbusplus::message::object_path upstreamChassisPath( 240a5617496SJie Yang upstreamChassisPaths[0]); 241a5617496SJie Yang std::string upstreamChassis = upstreamChassisPath.filename(); 242a5617496SJie Yang if (upstreamChassis.empty()) 243a5617496SJie Yang { 24462598e31SEd Tanous BMCWEB_LOG_WARNING("Malformed upstream Chassis path {} on {}", 24562598e31SEd Tanous upstreamChassisPath.str, chassisId); 246a5617496SJie Yang return; 247a5617496SJie Yang } 248a5617496SJie Yang 249a5617496SJie Yang asyncResp->res.jsonValue["Links"]["ContainedBy"]["@odata.id"] = 250a5617496SJie Yang boost::urls::format("/redfish/v1/Chassis/{}", upstreamChassis); 251a5617496SJie Yang } 252a5617496SJie Yang 253a5617496SJie Yang inline void getChassisContains( 254a5617496SJie Yang const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 255a5617496SJie Yang const std::string& chassisId, const boost::system::error_code& ec, 25628ee563eSMyung Bae const dbus::utility::MapperGetSubTreePathsResponse& downstreamChassisPaths) 257a5617496SJie Yang { 258a5617496SJie Yang if (ec) 259a5617496SJie Yang { 260a5617496SJie Yang if (ec.value() != EBADR) 261a5617496SJie Yang { 26262598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error {}", ec); 263a5617496SJie Yang messages::internalError(asyncResp->res); 264a5617496SJie Yang } 265a5617496SJie Yang return; 266a5617496SJie Yang } 267a5617496SJie Yang if (downstreamChassisPaths.empty()) 268a5617496SJie Yang { 269a5617496SJie Yang return; 270a5617496SJie Yang } 271a5617496SJie Yang nlohmann::json& jValue = asyncResp->res.jsonValue["Links"]["Contains"]; 272a5617496SJie Yang if (!jValue.is_array()) 273a5617496SJie Yang { 274a5617496SJie Yang // Create the array if it was empty 275a5617496SJie Yang jValue = nlohmann::json::array(); 276a5617496SJie Yang } 277a5617496SJie Yang for (const auto& p : downstreamChassisPaths) 278a5617496SJie Yang { 279a5617496SJie Yang sdbusplus::message::object_path downstreamChassisPath(p); 280a5617496SJie Yang std::string downstreamChassis = downstreamChassisPath.filename(); 281a5617496SJie Yang if (downstreamChassis.empty()) 282a5617496SJie Yang { 28362598e31SEd Tanous BMCWEB_LOG_WARNING("Malformed downstream Chassis path {} on {}", 28462598e31SEd Tanous downstreamChassisPath.str, chassisId); 285a5617496SJie Yang continue; 286a5617496SJie Yang } 287a5617496SJie Yang nlohmann::json link; 288bd79bce8SPatrick Williams link["@odata.id"] = 289bd79bce8SPatrick Williams boost::urls::format("/redfish/v1/Chassis/{}", downstreamChassis); 290a5617496SJie Yang jValue.push_back(std::move(link)); 291a5617496SJie Yang } 292a5617496SJie Yang asyncResp->res.jsonValue["Links"]["Contains@odata.count"] = jValue.size(); 293a5617496SJie Yang } 294a5617496SJie Yang 295bd79bce8SPatrick Williams inline void getChassisConnectivity( 296bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 297bd79bce8SPatrick Williams const std::string& chassisId, const std::string& chassisPath) 298a5617496SJie Yang { 29962598e31SEd Tanous BMCWEB_LOG_DEBUG("Get chassis connectivity"); 300a5617496SJie Yang 30128ee563eSMyung Bae constexpr std::array<std::string_view, 2> interfaces{ 30228ee563eSMyung Bae "xyz.openbmc_project.Inventory.Item.Board", 30328ee563eSMyung Bae "xyz.openbmc_project.Inventory.Item.Chassis"}; 30428ee563eSMyung Bae 30528ee563eSMyung Bae dbus::utility::getAssociatedSubTreePaths( 306a5617496SJie Yang chassisPath + "/contained_by", 30728ee563eSMyung Bae sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), 0, 30828ee563eSMyung Bae interfaces, 309a5617496SJie Yang std::bind_front(getChassisContainedBy, asyncResp, chassisId)); 310a5617496SJie Yang 31128ee563eSMyung Bae dbus::utility::getAssociatedSubTreePaths( 312a5617496SJie Yang chassisPath + "/containing", 31328ee563eSMyung Bae sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), 0, 31428ee563eSMyung Bae interfaces, std::bind_front(getChassisContains, asyncResp, chassisId)); 315a5617496SJie Yang } 316a5617496SJie Yang 317cf7eba09SNan Zhou /** 318cf7eba09SNan Zhou * ChassisCollection derived class for delivering Chassis Collection Schema 319cf7eba09SNan Zhou * Functions triggers appropriate requests on DBus 320cf7eba09SNan Zhou */ 321cf7eba09SNan Zhou inline void requestRoutesChassisCollection(App& app) 322cf7eba09SNan Zhou { 323cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/") 324cf7eba09SNan Zhou .privileges(redfish::privileges::getChassisCollection) 325cf7eba09SNan Zhou .methods(boost::beast::http::verb::get)( 326cf7eba09SNan Zhou std::bind_front(handleChassisCollectionGet, std::ref(app))); 32762d5e2e4SEd Tanous } 328e37f8451SRapkiewicz, Pawel 329bd79bce8SPatrick Williams inline void getChassisLocationCode( 330bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 331bd79bce8SPatrick Williams const std::string& connectionName, const std::string& path) 332308f70c7SWilly Tu { 3331e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 3341e1e598dSJonathan Doman *crow::connections::systemBus, connectionName, path, 3351e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode", 3365e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec, 3371e1e598dSJonathan Doman const std::string& property) { 338308f70c7SWilly Tu if (ec) 339308f70c7SWilly Tu { 34062598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error for Location"); 341308f70c7SWilly Tu messages::internalError(asyncResp->res); 342308f70c7SWilly Tu return; 343308f70c7SWilly Tu } 344308f70c7SWilly Tu 345bd79bce8SPatrick Williams asyncResp->res 346bd79bce8SPatrick Williams .jsonValue["Location"]["PartLocation"]["ServiceLabel"] = 3471e1e598dSJonathan Doman property; 3481e1e598dSJonathan Doman }); 349308f70c7SWilly Tu } 350308f70c7SWilly Tu 351308f70c7SWilly Tu inline void getChassisUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 352308f70c7SWilly Tu const std::string& connectionName, 353308f70c7SWilly Tu const std::string& path) 354308f70c7SWilly Tu { 3551e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 3561e1e598dSJonathan Doman *crow::connections::systemBus, connectionName, path, 3571e1e598dSJonathan Doman "xyz.openbmc_project.Common.UUID", "UUID", 3585e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec, 3591e1e598dSJonathan Doman const std::string& chassisUUID) { 360308f70c7SWilly Tu if (ec) 361308f70c7SWilly Tu { 36262598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error for UUID"); 363308f70c7SWilly Tu messages::internalError(asyncResp->res); 364308f70c7SWilly Tu return; 365308f70c7SWilly Tu } 3661e1e598dSJonathan Doman asyncResp->res.jsonValue["UUID"] = chassisUUID; 3671e1e598dSJonathan Doman }); 368308f70c7SWilly Tu } 369308f70c7SWilly Tu 3707164bc62SChau Ly inline void handleDecoratorAssetProperties( 37145ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 3727164bc62SChau Ly const std::string& chassisId, const std::string& path, 3737164bc62SChau Ly const dbus::utility::DBusPropertiesMap& propertiesList) 374cf7eba09SNan Zhou { 3757164bc62SChau Ly const std::string* partNumber = nullptr; 3767164bc62SChau Ly const std::string* serialNumber = nullptr; 3777164bc62SChau Ly const std::string* manufacturer = nullptr; 3787164bc62SChau Ly const std::string* model = nullptr; 3797164bc62SChau Ly const std::string* sparePartNumber = nullptr; 3807164bc62SChau Ly 3817164bc62SChau Ly const bool success = sdbusplus::unpackPropertiesNoThrow( 3827164bc62SChau Ly dbus_utils::UnpackErrorPrinter(), propertiesList, "PartNumber", 3837164bc62SChau Ly partNumber, "SerialNumber", serialNumber, "Manufacturer", manufacturer, 3847164bc62SChau Ly "Model", model, "SparePartNumber", sparePartNumber); 3857164bc62SChau Ly 3867164bc62SChau Ly if (!success) 38745ca1b86SEd Tanous { 3887164bc62SChau Ly messages::internalError(asyncResp->res); 38945ca1b86SEd Tanous return; 39045ca1b86SEd Tanous } 391734bfe90SGunnar Mills 3927164bc62SChau Ly if (partNumber != nullptr) 3937164bc62SChau Ly { 3947164bc62SChau Ly asyncResp->res.jsonValue["PartNumber"] = *partNumber; 3957164bc62SChau Ly } 3967164bc62SChau Ly 3977164bc62SChau Ly if (serialNumber != nullptr) 3987164bc62SChau Ly { 3997164bc62SChau Ly asyncResp->res.jsonValue["SerialNumber"] = *serialNumber; 4007164bc62SChau Ly } 4017164bc62SChau Ly 4027164bc62SChau Ly if (manufacturer != nullptr) 4037164bc62SChau Ly { 4047164bc62SChau Ly asyncResp->res.jsonValue["Manufacturer"] = *manufacturer; 4057164bc62SChau Ly } 4067164bc62SChau Ly 4077164bc62SChau Ly if (model != nullptr) 4087164bc62SChau Ly { 4097164bc62SChau Ly asyncResp->res.jsonValue["Model"] = *model; 4107164bc62SChau Ly } 4117164bc62SChau Ly 4127164bc62SChau Ly // SparePartNumber is optional on D-Bus 4137164bc62SChau Ly // so skip if it is empty 4147164bc62SChau Ly if (sparePartNumber != nullptr && !sparePartNumber->empty()) 4157164bc62SChau Ly { 4167164bc62SChau Ly asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber; 4177164bc62SChau Ly } 4187164bc62SChau Ly 4197164bc62SChau Ly asyncResp->res.jsonValue["Name"] = chassisId; 4207164bc62SChau Ly asyncResp->res.jsonValue["Id"] = chassisId; 42125b54dbaSEd Tanous 42225b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_ALLOW_DEPRECATED_POWER_THERMAL) 42325b54dbaSEd Tanous { 4247164bc62SChau Ly asyncResp->res.jsonValue["Thermal"]["@odata.id"] = 4257164bc62SChau Ly boost::urls::format("/redfish/v1/Chassis/{}/Thermal", chassisId); 4267164bc62SChau Ly // Power object 4277164bc62SChau Ly asyncResp->res.jsonValue["Power"]["@odata.id"] = 4287164bc62SChau Ly boost::urls::format("/redfish/v1/Chassis/{}/Power", chassisId); 42925b54dbaSEd Tanous } 43025b54dbaSEd Tanous 43125b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_NEW_POWERSUBSYSTEM_THERMALSUBSYSTEM) 43225b54dbaSEd Tanous { 4337164bc62SChau Ly asyncResp->res.jsonValue["ThermalSubsystem"]["@odata.id"] = 4347164bc62SChau Ly boost::urls::format("/redfish/v1/Chassis/{}/ThermalSubsystem", 4357164bc62SChau Ly chassisId); 4367164bc62SChau Ly asyncResp->res.jsonValue["PowerSubsystem"]["@odata.id"] = 43725b54dbaSEd Tanous boost::urls::format("/redfish/v1/Chassis/{}/PowerSubsystem", 43825b54dbaSEd Tanous chassisId); 4397164bc62SChau Ly asyncResp->res.jsonValue["EnvironmentMetrics"]["@odata.id"] = 4407164bc62SChau Ly boost::urls::format("/redfish/v1/Chassis/{}/EnvironmentMetrics", 4417164bc62SChau Ly chassisId); 44225b54dbaSEd Tanous } 4437164bc62SChau Ly // SensorCollection 4447164bc62SChau Ly asyncResp->res.jsonValue["Sensors"]["@odata.id"] = 4457164bc62SChau Ly boost::urls::format("/redfish/v1/Chassis/{}/Sensors", chassisId); 446539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled; 4477164bc62SChau Ly 4487164bc62SChau Ly nlohmann::json::array_t computerSystems; 4497164bc62SChau Ly nlohmann::json::object_t system; 450bd79bce8SPatrick Williams system["@odata.id"] = 451bd79bce8SPatrick Williams std::format("/redfish/v1/Systems/{}", BMCWEB_REDFISH_SYSTEM_URI_NAME); 4527164bc62SChau Ly computerSystems.emplace_back(std::move(system)); 4537164bc62SChau Ly asyncResp->res.jsonValue["Links"]["ComputerSystems"] = 4547164bc62SChau Ly std::move(computerSystems); 4557164bc62SChau Ly 4567164bc62SChau Ly nlohmann::json::array_t managedBy; 4577164bc62SChau Ly nlohmann::json::object_t manager; 458253f11b8SEd Tanous manager["@odata.id"] = boost::urls::format("/redfish/v1/Managers/{}", 459253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 4607164bc62SChau Ly managedBy.emplace_back(std::move(manager)); 4617164bc62SChau Ly asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy); 4627164bc62SChau Ly getChassisState(asyncResp); 4637164bc62SChau Ly getStorageLink(asyncResp, path); 4647164bc62SChau Ly } 4657164bc62SChau Ly 4667164bc62SChau Ly inline void handleChassisGetSubTree( 4677164bc62SChau Ly const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 4687164bc62SChau Ly const std::string& chassisId, const boost::system::error_code& ec, 4697164bc62SChau Ly const dbus::utility::MapperGetSubTreeResponse& subtree) 4707164bc62SChau Ly { 47162d5e2e4SEd Tanous if (ec) 4721abe55efSEd Tanous { 47362598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error {}", ec); 474f12894f8SJason M. Bills messages::internalError(asyncResp->res); 475daf36e2eSEd Tanous return; 476daf36e2eSEd Tanous } 477daf36e2eSEd Tanous // Iterate over all retrieved ObjectPaths. 478cf7eba09SNan Zhou for (const std::pair< 479cf7eba09SNan Zhou std::string, 480cf7eba09SNan Zhou std::vector<std::pair<std::string, std::vector<std::string>>>>& 4811214b7e7SGunnar Mills object : subtree) 4821abe55efSEd Tanous { 483daf36e2eSEd Tanous const std::string& path = object.first; 484cf7eba09SNan Zhou const std::vector<std::pair<std::string, std::vector<std::string>>>& 4851214b7e7SGunnar Mills connectionNames = object.second; 4867e860f15SJohn Edward Broadbent 487997093ebSGeorge Liu sdbusplus::message::object_path objPath(path); 488997093ebSGeorge Liu if (objPath.filename() != chassisId) 4891abe55efSEd Tanous { 490daf36e2eSEd Tanous continue; 491daf36e2eSEd Tanous } 49226f03899SShawn McCarney 493a5617496SJie Yang getChassisConnectivity(asyncResp, chassisId, path); 494a5617496SJie Yang 49526f6976fSEd Tanous if (connectionNames.empty()) 4961abe55efSEd Tanous { 49762598e31SEd Tanous BMCWEB_LOG_ERROR("Got 0 Connection names"); 498e0d918bcSEd Tanous continue; 499daf36e2eSEd Tanous } 500e0d918bcSEd Tanous 5017164bc62SChau Ly asyncResp->res.jsonValue["@odata.type"] = "#Chassis.v1_22_0.Chassis"; 50249c53ac9SJohnathan Mantey asyncResp->res.jsonValue["@odata.id"] = 503ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/Chassis/{}", chassisId); 50449c53ac9SJohnathan Mantey asyncResp->res.jsonValue["Name"] = "Chassis Collection"; 505539d8c6bSEd Tanous asyncResp->res.jsonValue["ChassisType"] = 506539d8c6bSEd Tanous chassis::ChassisType::RackMount; 507cf7eba09SNan Zhou asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"]["target"] = 5087164bc62SChau Ly boost::urls::format("/redfish/v1/Chassis/{}/Actions/Chassis.Reset", 5097164bc62SChau Ly chassisId); 5101476687dSEd Tanous asyncResp->res 511cf7eba09SNan Zhou .jsonValue["Actions"]["#Chassis.Reset"]["@Redfish.ActionInfo"] = 512ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/Chassis/{}/ResetActionInfo", 513ef4c65b7SEd Tanous chassisId); 5146c3e9451SGeorge Liu dbus::utility::getAssociationEndPoints( 5156c3e9451SGeorge Liu path + "/drive", 5167164bc62SChau Ly [asyncResp, chassisId](const boost::system::error_code& ec3, 5176c3e9451SGeorge Liu const dbus::utility::MapperEndPoints& resp) { 51892903bd4SJohn Edward Broadbent if (ec3 || resp.empty()) 51992903bd4SJohn Edward Broadbent { 52092903bd4SJohn Edward Broadbent return; // no drives = no failures 52192903bd4SJohn Edward Broadbent } 52292903bd4SJohn Edward Broadbent 52392903bd4SJohn Edward Broadbent nlohmann::json reference; 524bd79bce8SPatrick Williams reference["@odata.id"] = boost::urls::format( 525bd79bce8SPatrick Williams "/redfish/v1/Chassis/{}/Drives", chassisId); 52692903bd4SJohn Edward Broadbent asyncResp->res.jsonValue["Drives"] = std::move(reference); 52792903bd4SJohn Edward Broadbent }); 52892903bd4SJohn Edward Broadbent 529002d39b4SEd Tanous const std::string& connectionName = connectionNames[0].first; 5301c8fba97SJames Feist 5317164bc62SChau Ly const std::vector<std::string>& interfaces2 = connectionNames[0].second; 532e5ae9c1cSGeorge Liu const std::array<const char*, 3> hasIndicatorLed = { 533e5ae9c1cSGeorge Liu "xyz.openbmc_project.Inventory.Item.Chassis", 5341c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Panel", 5350fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Item.Board.Motherboard"}; 5361c8fba97SJames Feist 537476b9cc5STejas Patil const std::string assetTagInterface = 5380fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.AssetTag"; 539523d4868SLogananth Sundararaj const std::string replaceableInterface = 540523d4868SLogananth Sundararaj "xyz.openbmc_project.Inventory.Decorator.Replaceable"; 541b4d593f1SCarson Labrado const std::string revisionInterface = 542b4d593f1SCarson Labrado "xyz.openbmc_project.Inventory.Decorator.Revision"; 543523d4868SLogananth Sundararaj for (const auto& interface : interfaces2) 544523d4868SLogananth Sundararaj { 545523d4868SLogananth Sundararaj if (interface == assetTagInterface) 546476b9cc5STejas Patil { 5471e1e598dSJonathan Doman sdbusplus::asio::getProperty<std::string>( 548002d39b4SEd Tanous *crow::connections::systemBus, connectionName, path, 549002d39b4SEd Tanous assetTagInterface, "AssetTag", 5507164bc62SChau Ly [asyncResp, chassisId](const boost::system::error_code& ec2, 5511e1e598dSJonathan Doman const std::string& property) { 5528a592810SEd Tanous if (ec2) 553476b9cc5STejas Patil { 554bd79bce8SPatrick Williams BMCWEB_LOG_ERROR( 555bd79bce8SPatrick Williams "DBus response error for AssetTag: {}", ec2); 556476b9cc5STejas Patil messages::internalError(asyncResp->res); 557476b9cc5STejas Patil return; 558476b9cc5STejas Patil } 559002d39b4SEd Tanous asyncResp->res.jsonValue["AssetTag"] = property; 5601e1e598dSJonathan Doman }); 561476b9cc5STejas Patil } 562523d4868SLogananth Sundararaj else if (interface == replaceableInterface) 563523d4868SLogananth Sundararaj { 564523d4868SLogananth Sundararaj sdbusplus::asio::getProperty<bool>( 565523d4868SLogananth Sundararaj *crow::connections::systemBus, connectionName, path, 566523d4868SLogananth Sundararaj replaceableInterface, "HotPluggable", 5677164bc62SChau Ly [asyncResp, chassisId](const boost::system::error_code& ec2, 568523d4868SLogananth Sundararaj const bool property) { 569523d4868SLogananth Sundararaj if (ec2) 570523d4868SLogananth Sundararaj { 57162598e31SEd Tanous BMCWEB_LOG_ERROR( 572bd79bce8SPatrick Williams "DBus response error for HotPluggable: {}", 573bd79bce8SPatrick Williams ec2); 574523d4868SLogananth Sundararaj messages::internalError(asyncResp->res); 575523d4868SLogananth Sundararaj return; 576523d4868SLogananth Sundararaj } 577523d4868SLogananth Sundararaj asyncResp->res.jsonValue["HotPluggable"] = property; 578523d4868SLogananth Sundararaj }); 579523d4868SLogananth Sundararaj } 580b4d593f1SCarson Labrado else if (interface == revisionInterface) 581b4d593f1SCarson Labrado { 582b4d593f1SCarson Labrado sdbusplus::asio::getProperty<std::string>( 583b4d593f1SCarson Labrado *crow::connections::systemBus, connectionName, path, 584b4d593f1SCarson Labrado revisionInterface, "Version", 585b4d593f1SCarson Labrado [asyncResp, chassisId](const boost::system::error_code& ec2, 586b4d593f1SCarson Labrado const std::string& property) { 587b4d593f1SCarson Labrado if (ec2) 588b4d593f1SCarson Labrado { 589bd79bce8SPatrick Williams BMCWEB_LOG_ERROR( 590bd79bce8SPatrick Williams "DBus response error for Version: {}", ec2); 591b4d593f1SCarson Labrado messages::internalError(asyncResp->res); 592b4d593f1SCarson Labrado return; 593b4d593f1SCarson Labrado } 594b4d593f1SCarson Labrado asyncResp->res.jsonValue["Version"] = property; 595b4d593f1SCarson Labrado }); 596b4d593f1SCarson Labrado } 597523d4868SLogananth Sundararaj } 598476b9cc5STejas Patil 5991c8fba97SJames Feist for (const char* interface : hasIndicatorLed) 6001c8fba97SJames Feist { 6017164bc62SChau Ly if (std::ranges::find(interfaces2, interface) != interfaces2.end()) 6021c8fba97SJames Feist { 6031c8fba97SJames Feist getIndicatorLedState(asyncResp); 60459a17e4fSGeorge Liu getSystemLocationIndicatorActive(asyncResp); 6051c8fba97SJames Feist break; 6061c8fba97SJames Feist } 6071c8fba97SJames Feist } 6081c8fba97SJames Feist 60986d89ed7SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 61086d89ed7SKrzysztof Grobelny *crow::connections::systemBus, connectionName, path, 61186d89ed7SKrzysztof Grobelny "xyz.openbmc_project.Inventory.Decorator.Asset", 6127164bc62SChau Ly [asyncResp, chassisId, 6137164bc62SChau Ly path](const boost::system::error_code&, 614cf7eba09SNan Zhou const dbus::utility::DBusPropertiesMap& propertiesList) { 6157164bc62SChau Ly handleDecoratorAssetProperties(asyncResp, chassisId, path, 6167164bc62SChau Ly propertiesList); 61786d89ed7SKrzysztof Grobelny }); 6182c37b4b0SSharad Yadav 619308f70c7SWilly Tu for (const auto& interface : interfaces2) 6202c37b4b0SSharad Yadav { 621308f70c7SWilly Tu if (interface == "xyz.openbmc_project.Common.UUID") 6222c37b4b0SSharad Yadav { 623308f70c7SWilly Tu getChassisUUID(asyncResp, connectionName, path); 6242c37b4b0SSharad Yadav } 625cf7eba09SNan Zhou else if (interface == 6260fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode") 6272c37b4b0SSharad Yadav { 628002d39b4SEd Tanous getChassisLocationCode(asyncResp, connectionName, path); 6292c37b4b0SSharad Yadav } 6302c37b4b0SSharad Yadav } 6312c37b4b0SSharad Yadav 632daf36e2eSEd Tanous return; 633daf36e2eSEd Tanous } 634e0d918bcSEd Tanous 635daf36e2eSEd Tanous // Couldn't find an object with that name. return an error 636d8a5d5d8SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "Chassis", chassisId); 6377164bc62SChau Ly } 638c181942fSQiang XU 6397164bc62SChau Ly inline void 6407164bc62SChau Ly handleChassisGet(App& app, const crow::Request& req, 6417164bc62SChau Ly const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 6427164bc62SChau Ly const std::string& chassisId) 6437164bc62SChau Ly { 6447164bc62SChau Ly if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 6457164bc62SChau Ly { 6467164bc62SChau Ly return; 6477164bc62SChau Ly } 6487164bc62SChau Ly constexpr std::array<std::string_view, 2> interfaces = { 6497164bc62SChau Ly "xyz.openbmc_project.Inventory.Item.Board", 6507164bc62SChau Ly "xyz.openbmc_project.Inventory.Item.Chassis"}; 6517164bc62SChau Ly 6527164bc62SChau Ly dbus::utility::getSubTree( 6537164bc62SChau Ly "/xyz/openbmc_project/inventory", 0, interfaces, 6547164bc62SChau Ly std::bind_front(handleChassisGetSubTree, asyncResp, chassisId)); 6557164bc62SChau Ly 6567164bc62SChau Ly constexpr std::array<std::string_view, 1> interfaces2 = { 6577164bc62SChau Ly "xyz.openbmc_project.Chassis.Intrusion"}; 6587164bc62SChau Ly 6597164bc62SChau Ly dbus::utility::getSubTree( 6607164bc62SChau Ly "/xyz/openbmc_project", 0, interfaces2, 6617164bc62SChau Ly std::bind_front(handlePhysicalSecurityGetSubTree, asyncResp)); 662cf7eba09SNan Zhou } 6631c8fba97SJames Feist 664cf7eba09SNan Zhou inline void 665cf7eba09SNan Zhou handleChassisPatch(App& app, const crow::Request& req, 6667e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 667cf7eba09SNan Zhou const std::string& param) 668cf7eba09SNan Zhou { 6693ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 67045ca1b86SEd Tanous { 67145ca1b86SEd Tanous return; 67245ca1b86SEd Tanous } 6739f8bfa7cSGunnar Mills std::optional<bool> locationIndicatorActive; 6741c8fba97SJames Feist std::optional<std::string> indicatorLed; 6751c8fba97SJames Feist 6767e860f15SJohn Edward Broadbent if (param.empty()) 6771c8fba97SJames Feist { 6781c8fba97SJames Feist return; 6791c8fba97SJames Feist } 6801c8fba97SJames Feist 681*afc474aeSMyung Bae if (!json_util::readJsonPatch( // 682*afc474aeSMyung Bae req, asyncResp->res, // 683*afc474aeSMyung Bae "IndicatorLED", indicatorLed, // 684*afc474aeSMyung Bae "LocationIndicatorActive", locationIndicatorActive // 685*afc474aeSMyung Bae )) 6861c8fba97SJames Feist { 6871c8fba97SJames Feist return; 6881c8fba97SJames Feist } 6891c8fba97SJames Feist 6909f8bfa7cSGunnar Mills // TODO (Gunnar): Remove IndicatorLED after enough time has passed 6919f8bfa7cSGunnar Mills if (!locationIndicatorActive && !indicatorLed) 6921c8fba97SJames Feist { 6931c8fba97SJames Feist return; // delete this when we support more patch properties 6941c8fba97SJames Feist } 695d6aa0093SGunnar Mills if (indicatorLed) 696d6aa0093SGunnar Mills { 6977e860f15SJohn Edward Broadbent asyncResp->res.addHeader( 6987e860f15SJohn Edward Broadbent boost::beast::http::field::warning, 6990fda0f12SGeorge Liu "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\""); 700d6aa0093SGunnar Mills } 7011c8fba97SJames Feist 702e99073f5SGeorge Liu constexpr std::array<std::string_view, 2> interfaces = { 7031c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Board", 7041c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Chassis"}; 7051c8fba97SJames Feist 7067e860f15SJohn Edward Broadbent const std::string& chassisId = param; 7071c8fba97SJames Feist 708e99073f5SGeorge Liu dbus::utility::getSubTree( 709e99073f5SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 710cf7eba09SNan Zhou [asyncResp, chassisId, locationIndicatorActive, 7115e7e2dc5SEd Tanous indicatorLed](const boost::system::error_code& ec, 712b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtree) { 7131c8fba97SJames Feist if (ec) 7141c8fba97SJames Feist { 71562598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error {}", ec); 7161c8fba97SJames Feist messages::internalError(asyncResp->res); 7171c8fba97SJames Feist return; 7181c8fba97SJames Feist } 7191c8fba97SJames Feist 7201c8fba97SJames Feist // Iterate over all retrieved ObjectPaths. 721bd79bce8SPatrick Williams for (const std::pair<std::string, 722bd79bce8SPatrick Williams std::vector<std::pair< 723bd79bce8SPatrick Williams std::string, std::vector<std::string>>>>& 7241214b7e7SGunnar Mills object : subtree) 7251c8fba97SJames Feist { 7261c8fba97SJames Feist const std::string& path = object.first; 727bd79bce8SPatrick Williams const std::vector< 728bd79bce8SPatrick Williams std::pair<std::string, std::vector<std::string>>>& 7291214b7e7SGunnar Mills connectionNames = object.second; 7301c8fba97SJames Feist 731997093ebSGeorge Liu sdbusplus::message::object_path objPath(path); 732997093ebSGeorge Liu if (objPath.filename() != chassisId) 7331c8fba97SJames Feist { 7341c8fba97SJames Feist continue; 7351c8fba97SJames Feist } 7361c8fba97SJames Feist 73726f6976fSEd Tanous if (connectionNames.empty()) 7381c8fba97SJames Feist { 73962598e31SEd Tanous BMCWEB_LOG_ERROR("Got 0 Connection names"); 7401c8fba97SJames Feist continue; 7411c8fba97SJames Feist } 7421c8fba97SJames Feist 74323a21a1cSEd Tanous const std::vector<std::string>& interfaces3 = 7441c8fba97SJames Feist connectionNames[0].second; 7451c8fba97SJames Feist 746e5ae9c1cSGeorge Liu const std::array<const char*, 3> hasIndicatorLed = { 747e5ae9c1cSGeorge Liu "xyz.openbmc_project.Inventory.Item.Chassis", 7481c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Panel", 7490fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Item.Board.Motherboard"}; 7501c8fba97SJames Feist bool indicatorChassis = false; 7511c8fba97SJames Feist for (const char* interface : hasIndicatorLed) 7521c8fba97SJames Feist { 7533544d2a7SEd Tanous if (std::ranges::find(interfaces3, interface) != 7543544d2a7SEd Tanous interfaces3.end()) 7551c8fba97SJames Feist { 7561c8fba97SJames Feist indicatorChassis = true; 7571c8fba97SJames Feist break; 7581c8fba97SJames Feist } 7591c8fba97SJames Feist } 7609f8bfa7cSGunnar Mills if (locationIndicatorActive) 7619f8bfa7cSGunnar Mills { 7629f8bfa7cSGunnar Mills if (indicatorChassis) 7639f8bfa7cSGunnar Mills { 764bd79bce8SPatrick Williams setSystemLocationIndicatorActive( 765bd79bce8SPatrick Williams asyncResp, *locationIndicatorActive); 7669f8bfa7cSGunnar Mills } 7679f8bfa7cSGunnar Mills else 7689f8bfa7cSGunnar Mills { 769002d39b4SEd Tanous messages::propertyUnknown(asyncResp->res, 770002d39b4SEd Tanous "LocationIndicatorActive"); 7719f8bfa7cSGunnar Mills } 7729f8bfa7cSGunnar Mills } 7739f8bfa7cSGunnar Mills if (indicatorLed) 7749f8bfa7cSGunnar Mills { 7751c8fba97SJames Feist if (indicatorChassis) 7761c8fba97SJames Feist { 777f23b7296SEd Tanous setIndicatorLedState(asyncResp, *indicatorLed); 7781c8fba97SJames Feist } 7791c8fba97SJames Feist else 7801c8fba97SJames Feist { 781bd79bce8SPatrick Williams messages::propertyUnknown(asyncResp->res, 782bd79bce8SPatrick Williams "IndicatorLED"); 7831c8fba97SJames Feist } 7841c8fba97SJames Feist } 7851c8fba97SJames Feist return; 7861c8fba97SJames Feist } 7871c8fba97SJames Feist 788d8a5d5d8SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "Chassis", chassisId); 789e99073f5SGeorge Liu }); 790cf7eba09SNan Zhou } 791cf7eba09SNan Zhou 792cf7eba09SNan Zhou /** 793cf7eba09SNan Zhou * Chassis override class for delivering Chassis Schema 794cf7eba09SNan Zhou * Functions triggers appropriate requests on DBus 795cf7eba09SNan Zhou */ 796cf7eba09SNan Zhou inline void requestRoutesChassis(App& app) 797cf7eba09SNan Zhou { 798cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/") 799cf7eba09SNan Zhou .privileges(redfish::privileges::getChassis) 800cf7eba09SNan Zhou .methods(boost::beast::http::verb::get)( 801cf7eba09SNan Zhou std::bind_front(handleChassisGet, std::ref(app))); 802cf7eba09SNan Zhou 803cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/") 804cf7eba09SNan Zhou .privileges(redfish::privileges::patchChassis) 805cf7eba09SNan Zhou .methods(boost::beast::http::verb::patch)( 806cf7eba09SNan Zhou std::bind_front(handleChassisPatch, std::ref(app))); 8071c8fba97SJames Feist } 808dd99e04bSP.K. Lee 8098d1b46d7Szhanghch05 inline void 8108d1b46d7Szhanghch05 doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 811dd99e04bSP.K. Lee { 8127a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 813c3b3c92aSVijay Khemka "xyz.openbmc_project.State.Chassis"}; 814c3b3c92aSVijay Khemka 815c3b3c92aSVijay Khemka // Use mapper to get subtree paths. 8167a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 8177a1dbc48SGeorge Liu "/", 0, interfaces, 818b9d36b47SEd Tanous [asyncResp]( 8197a1dbc48SGeorge Liu const boost::system::error_code& ec, 820b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& chassisList) { 821c3b3c92aSVijay Khemka if (ec) 822c3b3c92aSVijay Khemka { 82362598e31SEd Tanous BMCWEB_LOG_ERROR("[mapper] Bad D-Bus request error: {}", ec); 824c3b3c92aSVijay Khemka messages::internalError(asyncResp->res); 825c3b3c92aSVijay Khemka return; 826c3b3c92aSVijay Khemka } 827c3b3c92aSVijay Khemka 828dd99e04bSP.K. Lee const char* processName = "xyz.openbmc_project.State.Chassis"; 829dd99e04bSP.K. Lee const char* interfaceName = "xyz.openbmc_project.State.Chassis"; 830dd99e04bSP.K. Lee const char* destProperty = "RequestedPowerTransition"; 831dd99e04bSP.K. Lee const std::string propertyValue = 832dd99e04bSP.K. Lee "xyz.openbmc_project.State.Chassis.Transition.PowerCycle"; 833bd79bce8SPatrick Williams std::string objectPath = 834bd79bce8SPatrick Williams "/xyz/openbmc_project/state/chassis_system0"; 835c3b3c92aSVijay Khemka 836c3b3c92aSVijay Khemka /* Look for system reset chassis path */ 837bd79bce8SPatrick Williams if ((std::ranges::find(chassisList, objectPath)) == 838bd79bce8SPatrick Williams chassisList.end()) 839c3b3c92aSVijay Khemka { 840c3b3c92aSVijay Khemka /* We prefer to reset the full chassis_system, but if it doesn't 841c3b3c92aSVijay Khemka * exist on some platforms, fall back to a host-only power reset 842c3b3c92aSVijay Khemka */ 843c3b3c92aSVijay Khemka objectPath = "/xyz/openbmc_project/state/chassis0"; 844c3b3c92aSVijay Khemka } 845dd99e04bSP.K. Lee 846e93abac6SGinu George setDbusProperty(asyncResp, "ResetType", processName, objectPath, 847e93abac6SGinu George interfaceName, destProperty, propertyValue); 8487a1dbc48SGeorge Liu }); 849dd99e04bSP.K. Lee } 850dd99e04bSP.K. Lee 851cf7eba09SNan Zhou inline void handleChassisResetActionInfoPost( 852cf7eba09SNan Zhou App& app, const crow::Request& req, 8537e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 854cf7eba09SNan Zhou const std::string& /*chassisId*/) 855cf7eba09SNan Zhou { 8563ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 85745ca1b86SEd Tanous { 85845ca1b86SEd Tanous return; 85945ca1b86SEd Tanous } 86062598e31SEd Tanous BMCWEB_LOG_DEBUG("Post Chassis Reset."); 861dd99e04bSP.K. Lee 862dd99e04bSP.K. Lee std::string resetType; 863dd99e04bSP.K. Lee 864cf7eba09SNan Zhou if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType)) 865dd99e04bSP.K. Lee { 866dd99e04bSP.K. Lee return; 867dd99e04bSP.K. Lee } 868dd99e04bSP.K. Lee 869dd99e04bSP.K. Lee if (resetType != "PowerCycle") 870dd99e04bSP.K. Lee { 87162598e31SEd Tanous BMCWEB_LOG_DEBUG("Invalid property value for ResetType: {}", resetType); 872002d39b4SEd Tanous messages::actionParameterNotSupported(asyncResp->res, resetType, 873002d39b4SEd Tanous "ResetType"); 874dd99e04bSP.K. Lee 875dd99e04bSP.K. Lee return; 876dd99e04bSP.K. Lee } 877dd99e04bSP.K. Lee doChassisPowerCycle(asyncResp); 878dd99e04bSP.K. Lee } 8791cb1a9e6SAppaRao Puli 8801cb1a9e6SAppaRao Puli /** 881cf7eba09SNan Zhou * ChassisResetAction class supports the POST method for the Reset 882cf7eba09SNan Zhou * action. 883cf7eba09SNan Zhou * Function handles POST method request. 884cf7eba09SNan Zhou * Analyzes POST body before sending Reset request data to D-Bus. 8851cb1a9e6SAppaRao Puli */ 886cf7eba09SNan Zhou 887cf7eba09SNan Zhou inline void requestRoutesChassisResetAction(App& app) 8881cb1a9e6SAppaRao Puli { 889cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/") 890cf7eba09SNan Zhou .privileges(redfish::privileges::postChassis) 891cf7eba09SNan Zhou .methods(boost::beast::http::verb::post)( 892cf7eba09SNan Zhou std::bind_front(handleChassisResetActionInfoPost, std::ref(app))); 893cf7eba09SNan Zhou } 894cf7eba09SNan Zhou 895cf7eba09SNan Zhou inline void handleChassisResetActionInfoGet( 896cf7eba09SNan Zhou App& app, const crow::Request& req, 8977e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 898cf7eba09SNan Zhou const std::string& chassisId) 899cf7eba09SNan Zhou { 9003ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 9011cb1a9e6SAppaRao Puli { 90245ca1b86SEd Tanous return; 90345ca1b86SEd Tanous } 904cf7eba09SNan Zhou asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo"; 905ef4c65b7SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 906ef4c65b7SEd Tanous "/redfish/v1/Chassis/{}/ResetActionInfo", chassisId); 9071476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "Reset Action Info"; 9081476687dSEd Tanous 9091476687dSEd Tanous asyncResp->res.jsonValue["Id"] = "ResetActionInfo"; 9105b9e95a1SNan Zhou nlohmann::json::array_t parameters; 9115b9e95a1SNan Zhou nlohmann::json::object_t parameter; 9125b9e95a1SNan Zhou parameter["Name"] = "ResetType"; 9135b9e95a1SNan Zhou parameter["Required"] = true; 914539d8c6bSEd Tanous parameter["DataType"] = action_info::ParameterTypes::String; 9151476687dSEd Tanous nlohmann::json::array_t allowed; 916ad539545SPatrick Williams allowed.emplace_back("PowerCycle"); 9175b9e95a1SNan Zhou parameter["AllowableValues"] = std::move(allowed); 918ad539545SPatrick Williams parameters.emplace_back(std::move(parameter)); 9195b9e95a1SNan Zhou 9201476687dSEd Tanous asyncResp->res.jsonValue["Parameters"] = std::move(parameters); 921cf7eba09SNan Zhou } 922cf7eba09SNan Zhou 923cf7eba09SNan Zhou /** 924cf7eba09SNan Zhou * ChassisResetActionInfo derived class for delivering Chassis 925cf7eba09SNan Zhou * ResetType AllowableValues using ResetInfo schema. 926cf7eba09SNan Zhou */ 927cf7eba09SNan Zhou inline void requestRoutesChassisResetActionInfo(App& app) 928cf7eba09SNan Zhou { 929cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/") 930cf7eba09SNan Zhou .privileges(redfish::privileges::getActionInfo) 931cf7eba09SNan Zhou .methods(boost::beast::http::verb::get)( 932cf7eba09SNan Zhou std::bind_front(handleChassisResetActionInfoGet, std::ref(app))); 9331cb1a9e6SAppaRao Puli } 9341cb1a9e6SAppaRao Puli 935e37f8451SRapkiewicz, Pawel } // namespace redfish 936