1e37f8451SRapkiewicz, Pawel /* 2*6be832e2SEd Tanous Copyright (c) 2018 Intel Corporation 3*6be832e2SEd Tanous 4*6be832e2SEd Tanous Licensed under the Apache License, Version 2.0 (the "License"); 5*6be832e2SEd Tanous you may not use this file except in compliance with the License. 6*6be832e2SEd Tanous You may obtain a copy of the License at 7*6be832e2SEd Tanous 8*6be832e2SEd Tanous http://www.apache.org/licenses/LICENSE-2.0 9*6be832e2SEd Tanous 10*6be832e2SEd Tanous Unless required by applicable law or agreed to in writing, software 11*6be832e2SEd Tanous distributed under the License is distributed on an "AS IS" BASIS, 12*6be832e2SEd Tanous WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*6be832e2SEd Tanous See the License for the specific language governing permissions and 14*6be832e2SEd 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 68115ed6780SWilly Tu if (!json_util::readJsonPatch( 6827e860f15SJohn Edward Broadbent req, asyncResp->res, "LocationIndicatorActive", 6837e860f15SJohn Edward Broadbent locationIndicatorActive, "IndicatorLED", indicatorLed)) 6841c8fba97SJames Feist { 6851c8fba97SJames Feist return; 6861c8fba97SJames Feist } 6871c8fba97SJames Feist 6889f8bfa7cSGunnar Mills // TODO (Gunnar): Remove IndicatorLED after enough time has passed 6899f8bfa7cSGunnar Mills if (!locationIndicatorActive && !indicatorLed) 6901c8fba97SJames Feist { 6911c8fba97SJames Feist return; // delete this when we support more patch properties 6921c8fba97SJames Feist } 693d6aa0093SGunnar Mills if (indicatorLed) 694d6aa0093SGunnar Mills { 6957e860f15SJohn Edward Broadbent asyncResp->res.addHeader( 6967e860f15SJohn Edward Broadbent boost::beast::http::field::warning, 6970fda0f12SGeorge Liu "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\""); 698d6aa0093SGunnar Mills } 6991c8fba97SJames Feist 700e99073f5SGeorge Liu constexpr std::array<std::string_view, 2> interfaces = { 7011c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Board", 7021c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Chassis"}; 7031c8fba97SJames Feist 7047e860f15SJohn Edward Broadbent const std::string& chassisId = param; 7051c8fba97SJames Feist 706e99073f5SGeorge Liu dbus::utility::getSubTree( 707e99073f5SGeorge Liu "/xyz/openbmc_project/inventory", 0, interfaces, 708cf7eba09SNan Zhou [asyncResp, chassisId, locationIndicatorActive, 7095e7e2dc5SEd Tanous indicatorLed](const boost::system::error_code& ec, 710b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtree) { 7111c8fba97SJames Feist if (ec) 7121c8fba97SJames Feist { 71362598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error {}", ec); 7141c8fba97SJames Feist messages::internalError(asyncResp->res); 7151c8fba97SJames Feist return; 7161c8fba97SJames Feist } 7171c8fba97SJames Feist 7181c8fba97SJames Feist // Iterate over all retrieved ObjectPaths. 719bd79bce8SPatrick Williams for (const std::pair<std::string, 720bd79bce8SPatrick Williams std::vector<std::pair< 721bd79bce8SPatrick Williams std::string, std::vector<std::string>>>>& 7221214b7e7SGunnar Mills object : subtree) 7231c8fba97SJames Feist { 7241c8fba97SJames Feist const std::string& path = object.first; 725bd79bce8SPatrick Williams const std::vector< 726bd79bce8SPatrick Williams std::pair<std::string, std::vector<std::string>>>& 7271214b7e7SGunnar Mills connectionNames = object.second; 7281c8fba97SJames Feist 729997093ebSGeorge Liu sdbusplus::message::object_path objPath(path); 730997093ebSGeorge Liu if (objPath.filename() != chassisId) 7311c8fba97SJames Feist { 7321c8fba97SJames Feist continue; 7331c8fba97SJames Feist } 7341c8fba97SJames Feist 73526f6976fSEd Tanous if (connectionNames.empty()) 7361c8fba97SJames Feist { 73762598e31SEd Tanous BMCWEB_LOG_ERROR("Got 0 Connection names"); 7381c8fba97SJames Feist continue; 7391c8fba97SJames Feist } 7401c8fba97SJames Feist 74123a21a1cSEd Tanous const std::vector<std::string>& interfaces3 = 7421c8fba97SJames Feist connectionNames[0].second; 7431c8fba97SJames Feist 744e5ae9c1cSGeorge Liu const std::array<const char*, 3> hasIndicatorLed = { 745e5ae9c1cSGeorge Liu "xyz.openbmc_project.Inventory.Item.Chassis", 7461c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Panel", 7470fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Item.Board.Motherboard"}; 7481c8fba97SJames Feist bool indicatorChassis = false; 7491c8fba97SJames Feist for (const char* interface : hasIndicatorLed) 7501c8fba97SJames Feist { 7513544d2a7SEd Tanous if (std::ranges::find(interfaces3, interface) != 7523544d2a7SEd Tanous interfaces3.end()) 7531c8fba97SJames Feist { 7541c8fba97SJames Feist indicatorChassis = true; 7551c8fba97SJames Feist break; 7561c8fba97SJames Feist } 7571c8fba97SJames Feist } 7589f8bfa7cSGunnar Mills if (locationIndicatorActive) 7599f8bfa7cSGunnar Mills { 7609f8bfa7cSGunnar Mills if (indicatorChassis) 7619f8bfa7cSGunnar Mills { 762bd79bce8SPatrick Williams setSystemLocationIndicatorActive( 763bd79bce8SPatrick Williams asyncResp, *locationIndicatorActive); 7649f8bfa7cSGunnar Mills } 7659f8bfa7cSGunnar Mills else 7669f8bfa7cSGunnar Mills { 767002d39b4SEd Tanous messages::propertyUnknown(asyncResp->res, 768002d39b4SEd Tanous "LocationIndicatorActive"); 7699f8bfa7cSGunnar Mills } 7709f8bfa7cSGunnar Mills } 7719f8bfa7cSGunnar Mills if (indicatorLed) 7729f8bfa7cSGunnar Mills { 7731c8fba97SJames Feist if (indicatorChassis) 7741c8fba97SJames Feist { 775f23b7296SEd Tanous setIndicatorLedState(asyncResp, *indicatorLed); 7761c8fba97SJames Feist } 7771c8fba97SJames Feist else 7781c8fba97SJames Feist { 779bd79bce8SPatrick Williams messages::propertyUnknown(asyncResp->res, 780bd79bce8SPatrick Williams "IndicatorLED"); 7811c8fba97SJames Feist } 7821c8fba97SJames Feist } 7831c8fba97SJames Feist return; 7841c8fba97SJames Feist } 7851c8fba97SJames Feist 786d8a5d5d8SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "Chassis", chassisId); 787e99073f5SGeorge Liu }); 788cf7eba09SNan Zhou } 789cf7eba09SNan Zhou 790cf7eba09SNan Zhou /** 791cf7eba09SNan Zhou * Chassis override class for delivering Chassis Schema 792cf7eba09SNan Zhou * Functions triggers appropriate requests on DBus 793cf7eba09SNan Zhou */ 794cf7eba09SNan Zhou inline void requestRoutesChassis(App& app) 795cf7eba09SNan Zhou { 796cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/") 797cf7eba09SNan Zhou .privileges(redfish::privileges::getChassis) 798cf7eba09SNan Zhou .methods(boost::beast::http::verb::get)( 799cf7eba09SNan Zhou std::bind_front(handleChassisGet, std::ref(app))); 800cf7eba09SNan Zhou 801cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/") 802cf7eba09SNan Zhou .privileges(redfish::privileges::patchChassis) 803cf7eba09SNan Zhou .methods(boost::beast::http::verb::patch)( 804cf7eba09SNan Zhou std::bind_front(handleChassisPatch, std::ref(app))); 8051c8fba97SJames Feist } 806dd99e04bSP.K. Lee 8078d1b46d7Szhanghch05 inline void 8088d1b46d7Szhanghch05 doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 809dd99e04bSP.K. Lee { 8107a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 811c3b3c92aSVijay Khemka "xyz.openbmc_project.State.Chassis"}; 812c3b3c92aSVijay Khemka 813c3b3c92aSVijay Khemka // Use mapper to get subtree paths. 8147a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 8157a1dbc48SGeorge Liu "/", 0, interfaces, 816b9d36b47SEd Tanous [asyncResp]( 8177a1dbc48SGeorge Liu const boost::system::error_code& ec, 818b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& chassisList) { 819c3b3c92aSVijay Khemka if (ec) 820c3b3c92aSVijay Khemka { 82162598e31SEd Tanous BMCWEB_LOG_ERROR("[mapper] Bad D-Bus request error: {}", ec); 822c3b3c92aSVijay Khemka messages::internalError(asyncResp->res); 823c3b3c92aSVijay Khemka return; 824c3b3c92aSVijay Khemka } 825c3b3c92aSVijay Khemka 826dd99e04bSP.K. Lee const char* processName = "xyz.openbmc_project.State.Chassis"; 827dd99e04bSP.K. Lee const char* interfaceName = "xyz.openbmc_project.State.Chassis"; 828dd99e04bSP.K. Lee const char* destProperty = "RequestedPowerTransition"; 829dd99e04bSP.K. Lee const std::string propertyValue = 830dd99e04bSP.K. Lee "xyz.openbmc_project.State.Chassis.Transition.PowerCycle"; 831bd79bce8SPatrick Williams std::string objectPath = 832bd79bce8SPatrick Williams "/xyz/openbmc_project/state/chassis_system0"; 833c3b3c92aSVijay Khemka 834c3b3c92aSVijay Khemka /* Look for system reset chassis path */ 835bd79bce8SPatrick Williams if ((std::ranges::find(chassisList, objectPath)) == 836bd79bce8SPatrick Williams chassisList.end()) 837c3b3c92aSVijay Khemka { 838c3b3c92aSVijay Khemka /* We prefer to reset the full chassis_system, but if it doesn't 839c3b3c92aSVijay Khemka * exist on some platforms, fall back to a host-only power reset 840c3b3c92aSVijay Khemka */ 841c3b3c92aSVijay Khemka objectPath = "/xyz/openbmc_project/state/chassis0"; 842c3b3c92aSVijay Khemka } 843dd99e04bSP.K. Lee 844e93abac6SGinu George setDbusProperty(asyncResp, "ResetType", processName, objectPath, 845e93abac6SGinu George interfaceName, destProperty, propertyValue); 8467a1dbc48SGeorge Liu }); 847dd99e04bSP.K. Lee } 848dd99e04bSP.K. Lee 849cf7eba09SNan Zhou inline void handleChassisResetActionInfoPost( 850cf7eba09SNan Zhou App& app, const crow::Request& req, 8517e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 852cf7eba09SNan Zhou const std::string& /*chassisId*/) 853cf7eba09SNan Zhou { 8543ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 85545ca1b86SEd Tanous { 85645ca1b86SEd Tanous return; 85745ca1b86SEd Tanous } 85862598e31SEd Tanous BMCWEB_LOG_DEBUG("Post Chassis Reset."); 859dd99e04bSP.K. Lee 860dd99e04bSP.K. Lee std::string resetType; 861dd99e04bSP.K. Lee 862cf7eba09SNan Zhou if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType)) 863dd99e04bSP.K. Lee { 864dd99e04bSP.K. Lee return; 865dd99e04bSP.K. Lee } 866dd99e04bSP.K. Lee 867dd99e04bSP.K. Lee if (resetType != "PowerCycle") 868dd99e04bSP.K. Lee { 86962598e31SEd Tanous BMCWEB_LOG_DEBUG("Invalid property value for ResetType: {}", resetType); 870002d39b4SEd Tanous messages::actionParameterNotSupported(asyncResp->res, resetType, 871002d39b4SEd Tanous "ResetType"); 872dd99e04bSP.K. Lee 873dd99e04bSP.K. Lee return; 874dd99e04bSP.K. Lee } 875dd99e04bSP.K. Lee doChassisPowerCycle(asyncResp); 876dd99e04bSP.K. Lee } 8771cb1a9e6SAppaRao Puli 8781cb1a9e6SAppaRao Puli /** 879cf7eba09SNan Zhou * ChassisResetAction class supports the POST method for the Reset 880cf7eba09SNan Zhou * action. 881cf7eba09SNan Zhou * Function handles POST method request. 882cf7eba09SNan Zhou * Analyzes POST body before sending Reset request data to D-Bus. 8831cb1a9e6SAppaRao Puli */ 884cf7eba09SNan Zhou 885cf7eba09SNan Zhou inline void requestRoutesChassisResetAction(App& app) 8861cb1a9e6SAppaRao Puli { 887cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/") 888cf7eba09SNan Zhou .privileges(redfish::privileges::postChassis) 889cf7eba09SNan Zhou .methods(boost::beast::http::verb::post)( 890cf7eba09SNan Zhou std::bind_front(handleChassisResetActionInfoPost, std::ref(app))); 891cf7eba09SNan Zhou } 892cf7eba09SNan Zhou 893cf7eba09SNan Zhou inline void handleChassisResetActionInfoGet( 894cf7eba09SNan Zhou App& app, const crow::Request& req, 8957e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 896cf7eba09SNan Zhou const std::string& chassisId) 897cf7eba09SNan Zhou { 8983ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 8991cb1a9e6SAppaRao Puli { 90045ca1b86SEd Tanous return; 90145ca1b86SEd Tanous } 902cf7eba09SNan Zhou asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo"; 903ef4c65b7SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 904ef4c65b7SEd Tanous "/redfish/v1/Chassis/{}/ResetActionInfo", chassisId); 9051476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "Reset Action Info"; 9061476687dSEd Tanous 9071476687dSEd Tanous asyncResp->res.jsonValue["Id"] = "ResetActionInfo"; 9085b9e95a1SNan Zhou nlohmann::json::array_t parameters; 9095b9e95a1SNan Zhou nlohmann::json::object_t parameter; 9105b9e95a1SNan Zhou parameter["Name"] = "ResetType"; 9115b9e95a1SNan Zhou parameter["Required"] = true; 912539d8c6bSEd Tanous parameter["DataType"] = action_info::ParameterTypes::String; 9131476687dSEd Tanous nlohmann::json::array_t allowed; 914ad539545SPatrick Williams allowed.emplace_back("PowerCycle"); 9155b9e95a1SNan Zhou parameter["AllowableValues"] = std::move(allowed); 916ad539545SPatrick Williams parameters.emplace_back(std::move(parameter)); 9175b9e95a1SNan Zhou 9181476687dSEd Tanous asyncResp->res.jsonValue["Parameters"] = std::move(parameters); 919cf7eba09SNan Zhou } 920cf7eba09SNan Zhou 921cf7eba09SNan Zhou /** 922cf7eba09SNan Zhou * ChassisResetActionInfo derived class for delivering Chassis 923cf7eba09SNan Zhou * ResetType AllowableValues using ResetInfo schema. 924cf7eba09SNan Zhou */ 925cf7eba09SNan Zhou inline void requestRoutesChassisResetActionInfo(App& app) 926cf7eba09SNan Zhou { 927cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/") 928cf7eba09SNan Zhou .privileges(redfish::privileges::getActionInfo) 929cf7eba09SNan Zhou .methods(boost::beast::http::verb::get)( 930cf7eba09SNan Zhou std::bind_front(handleChassisResetActionInfoGet, std::ref(app))); 9311cb1a9e6SAppaRao Puli } 9321cb1a9e6SAppaRao Puli 933e37f8451SRapkiewicz, Pawel } // namespace redfish 934