140e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0 240e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors 340e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright 2018 Intel Corporation 4e37f8451SRapkiewicz, Pawel #pragma once 5e37f8451SRapkiewicz, Pawel 6d7857201SEd Tanous #include "bmcweb_config.h" 7d7857201SEd Tanous 83ccb3adbSEd Tanous #include "app.hpp" 9d7857201SEd Tanous #include "async_resp.hpp" 10d7857201SEd Tanous #include "dbus_singleton.hpp" 117a1dbc48SGeorge Liu #include "dbus_utility.hpp" 12d7857201SEd Tanous #include "error_messages.hpp" 13539d8c6bSEd Tanous #include "generated/enums/action_info.hpp" 14539d8c6bSEd Tanous #include "generated/enums/chassis.hpp" 15539d8c6bSEd Tanous #include "generated/enums/resource.hpp" 16d7857201SEd Tanous #include "http_request.hpp" 171c8fba97SJames Feist #include "led.hpp" 18d7857201SEd Tanous #include "logging.hpp" 193ccb3adbSEd Tanous #include "query.hpp" 203ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 21*f7e62c14SMyung Bae #include "utils/asset_utils.hpp" 223f95a277SMyung Bae #include "utils/chassis_utils.hpp" 233ccb3adbSEd Tanous #include "utils/collection.hpp" 243ccb3adbSEd Tanous #include "utils/dbus_utils.hpp" 25cf7eba09SNan Zhou #include "utils/json_utils.hpp" 261abe55efSEd Tanous 27d7857201SEd Tanous #include <asm-generic/errno.h> 28d7857201SEd Tanous 29d7857201SEd Tanous #include <boost/beast/http/field.hpp> 30d7857201SEd Tanous #include <boost/beast/http/verb.hpp> 31e99073f5SGeorge Liu #include <boost/system/error_code.hpp> 32ef4c65b7SEd Tanous #include <boost/url/format.hpp> 33d7857201SEd Tanous #include <boost/url/url.hpp> 34d7857201SEd Tanous #include <nlohmann/json.hpp> 35d7857201SEd Tanous #include <sdbusplus/message/native_types.hpp> 3686d89ed7SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 371214b7e7SGunnar Mills 38d7857201SEd Tanous #include <algorithm> 397a1dbc48SGeorge Liu #include <array> 40d7857201SEd Tanous #include <format> 41d7857201SEd Tanous #include <functional> 422952f648SJoseph-Jonathan Salzano #include <memory> 43d7857201SEd Tanous #include <optional> 443544d2a7SEd Tanous #include <ranges> 45d7857201SEd Tanous #include <string> 467a1dbc48SGeorge Liu #include <string_view> 47d7857201SEd Tanous #include <utility> 48d7857201SEd Tanous #include <vector> 497a1dbc48SGeorge Liu 501abe55efSEd Tanous namespace redfish 511abe55efSEd Tanous { 52e37f8451SRapkiewicz, Pawel 53504af5a0SPatrick Williams inline chassis::ChassisType translateChassisTypeToRedfish( 54504af5a0SPatrick Williams const std::string_view& chassisType) 552952f648SJoseph-Jonathan Salzano { 562952f648SJoseph-Jonathan Salzano if (chassisType == 572952f648SJoseph-Jonathan Salzano "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Blade") 582952f648SJoseph-Jonathan Salzano { 592952f648SJoseph-Jonathan Salzano return chassis::ChassisType::Blade; 602952f648SJoseph-Jonathan Salzano } 612952f648SJoseph-Jonathan Salzano if (chassisType == 622952f648SJoseph-Jonathan Salzano "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Component") 632952f648SJoseph-Jonathan Salzano { 642952f648SJoseph-Jonathan Salzano return chassis::ChassisType::Component; 652952f648SJoseph-Jonathan Salzano } 662952f648SJoseph-Jonathan Salzano if (chassisType == 672952f648SJoseph-Jonathan Salzano "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Enclosure") 682952f648SJoseph-Jonathan Salzano { 692952f648SJoseph-Jonathan Salzano return chassis::ChassisType::Enclosure; 702952f648SJoseph-Jonathan Salzano } 712952f648SJoseph-Jonathan Salzano if (chassisType == 722952f648SJoseph-Jonathan Salzano "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Module") 732952f648SJoseph-Jonathan Salzano { 742952f648SJoseph-Jonathan Salzano return chassis::ChassisType::Module; 752952f648SJoseph-Jonathan Salzano } 762952f648SJoseph-Jonathan Salzano if (chassisType == 772952f648SJoseph-Jonathan Salzano "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.RackMount") 782952f648SJoseph-Jonathan Salzano { 792952f648SJoseph-Jonathan Salzano return chassis::ChassisType::RackMount; 802952f648SJoseph-Jonathan Salzano } 812952f648SJoseph-Jonathan Salzano if (chassisType == 822952f648SJoseph-Jonathan Salzano "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.StandAlone") 832952f648SJoseph-Jonathan Salzano { 842952f648SJoseph-Jonathan Salzano return chassis::ChassisType::StandAlone; 852952f648SJoseph-Jonathan Salzano } 862952f648SJoseph-Jonathan Salzano if (chassisType == 872952f648SJoseph-Jonathan Salzano "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.StorageEnclosure") 882952f648SJoseph-Jonathan Salzano { 892952f648SJoseph-Jonathan Salzano return chassis::ChassisType::StorageEnclosure; 902952f648SJoseph-Jonathan Salzano } 912952f648SJoseph-Jonathan Salzano if (chassisType == 922952f648SJoseph-Jonathan Salzano "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Zone") 932952f648SJoseph-Jonathan Salzano { 942952f648SJoseph-Jonathan Salzano return chassis::ChassisType::Zone; 952952f648SJoseph-Jonathan Salzano } 962952f648SJoseph-Jonathan Salzano return chassis::ChassisType::Invalid; 972952f648SJoseph-Jonathan Salzano } 982952f648SJoseph-Jonathan Salzano 99e37f8451SRapkiewicz, Pawel /** 1005e577bc1SWilly Tu * @brief Retrieves resources over dbus to link to the chassis 1015e577bc1SWilly Tu * 1025e577bc1SWilly Tu * @param[in] asyncResp - Shared pointer for completing asynchronous 1035e577bc1SWilly Tu * calls 1045e577bc1SWilly Tu * @param[in] path - Chassis dbus path to look for the storage. 1055e577bc1SWilly Tu * 1065e577bc1SWilly Tu * Calls the Association endpoints on the path + "/storage" and add the link of 1075e577bc1SWilly Tu * json["Links"]["Storage@odata.count"] = 1085e577bc1SWilly Tu * {"@odata.id", "/redfish/v1/Storage/" + resourceId} 1095e577bc1SWilly Tu * 1105e577bc1SWilly Tu * @return None. 1115e577bc1SWilly Tu */ 1125e577bc1SWilly Tu inline void getStorageLink(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1135e577bc1SWilly Tu const sdbusplus::message::object_path& path) 1145e577bc1SWilly Tu { 115deae6a78SEd Tanous dbus::utility::getProperty<std::vector<std::string>>( 116deae6a78SEd Tanous "xyz.openbmc_project.ObjectMapper", (path / "storage").str, 117deae6a78SEd Tanous "xyz.openbmc_project.Association", "endpoints", 118d4b054c1SWilly Tu [asyncResp](const boost::system::error_code& ec, 1195e577bc1SWilly Tu const std::vector<std::string>& storageList) { 1205e577bc1SWilly Tu if (ec) 1215e577bc1SWilly Tu { 12262598e31SEd Tanous BMCWEB_LOG_DEBUG("getStorageLink got DBUS response error"); 1235e577bc1SWilly Tu return; 1245e577bc1SWilly Tu } 1255e577bc1SWilly Tu 1265e577bc1SWilly Tu nlohmann::json::array_t storages; 1275e577bc1SWilly Tu for (const std::string& storagePath : storageList) 1285e577bc1SWilly Tu { 1295e577bc1SWilly Tu std::string id = 1305e577bc1SWilly Tu sdbusplus::message::object_path(storagePath).filename(); 1315e577bc1SWilly Tu if (id.empty()) 1325e577bc1SWilly Tu { 1335e577bc1SWilly Tu continue; 1345e577bc1SWilly Tu } 1355e577bc1SWilly Tu 1365e577bc1SWilly Tu nlohmann::json::object_t storage; 137253f11b8SEd Tanous storage["@odata.id"] = 138253f11b8SEd Tanous boost::urls::format("/redfish/v1/Systems/{}/Storage/{}", 139253f11b8SEd Tanous BMCWEB_REDFISH_SYSTEM_URI_NAME, id); 1405e577bc1SWilly Tu storages.emplace_back(std::move(storage)); 1415e577bc1SWilly Tu } 1425e577bc1SWilly Tu asyncResp->res.jsonValue["Links"]["Storage@odata.count"] = 1435e577bc1SWilly Tu storages.size(); 1445e577bc1SWilly Tu asyncResp->res.jsonValue["Links"]["Storage"] = std::move(storages); 1455e577bc1SWilly Tu }); 1465e577bc1SWilly Tu } 1475e577bc1SWilly Tu 1485e577bc1SWilly Tu /** 149beeca0aeSGunnar Mills * @brief Retrieves chassis state properties over dbus 150beeca0aeSGunnar Mills * 151ac106bf6SEd Tanous * @param[in] asyncResp - Shared pointer for completing asynchronous calls. 152beeca0aeSGunnar Mills * 153beeca0aeSGunnar Mills * @return None. 154beeca0aeSGunnar Mills */ 155ac106bf6SEd Tanous inline void getChassisState(std::shared_ptr<bmcweb::AsyncResp> asyncResp) 156beeca0aeSGunnar Mills { 157deae6a78SEd Tanous dbus::utility::getProperty<std::string>( 158deae6a78SEd Tanous "xyz.openbmc_project.State.Chassis", 1591e1e598dSJonathan Doman "/xyz/openbmc_project/state/chassis0", 1601e1e598dSJonathan Doman "xyz.openbmc_project.State.Chassis", "CurrentPowerState", 161ac106bf6SEd Tanous [asyncResp{std::move(asyncResp)}](const boost::system::error_code& ec, 1621e1e598dSJonathan Doman const std::string& chassisState) { 163beeca0aeSGunnar Mills if (ec) 164beeca0aeSGunnar Mills { 165a6e5e0abSCarson Labrado if (ec == boost::system::errc::host_unreachable) 166a6e5e0abSCarson Labrado { 167a6e5e0abSCarson Labrado // Service not available, no error, just don't return 168a6e5e0abSCarson Labrado // chassis state info 16962598e31SEd Tanous BMCWEB_LOG_DEBUG("Service not available {}", ec); 170a6e5e0abSCarson Labrado return; 171a6e5e0abSCarson Labrado } 17262598e31SEd Tanous BMCWEB_LOG_DEBUG("DBUS response error {}", ec); 173ac106bf6SEd Tanous messages::internalError(asyncResp->res); 174beeca0aeSGunnar Mills return; 175beeca0aeSGunnar Mills } 176beeca0aeSGunnar Mills 17762598e31SEd Tanous BMCWEB_LOG_DEBUG("Chassis state: {}", chassisState); 178beeca0aeSGunnar Mills // Verify Chassis State 179bd79bce8SPatrick Williams if (chassisState == 180bd79bce8SPatrick Williams "xyz.openbmc_project.State.Chassis.PowerState.On") 181beeca0aeSGunnar Mills { 182bd79bce8SPatrick Williams asyncResp->res.jsonValue["PowerState"] = 183bd79bce8SPatrick Williams resource::PowerState::On; 184539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 185539d8c6bSEd Tanous resource::State::Enabled; 186beeca0aeSGunnar Mills } 1871e1e598dSJonathan Doman else if (chassisState == 188beeca0aeSGunnar Mills "xyz.openbmc_project.State.Chassis.PowerState.Off") 189beeca0aeSGunnar Mills { 190bd79bce8SPatrick Williams asyncResp->res.jsonValue["PowerState"] = 191bd79bce8SPatrick Williams resource::PowerState::Off; 192539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = 193539d8c6bSEd Tanous resource::State::StandbyOffline; 194beeca0aeSGunnar Mills } 1951e1e598dSJonathan Doman }); 196beeca0aeSGunnar Mills } 197beeca0aeSGunnar Mills 198c181942fSQiang XU /** 199c181942fSQiang XU * Retrieves physical security properties over dbus 200c181942fSQiang XU */ 2017164bc62SChau Ly inline void handlePhysicalSecurityGetSubTree( 2027164bc62SChau Ly const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 203e99073f5SGeorge Liu const boost::system::error_code& ec, 2047164bc62SChau Ly const dbus::utility::MapperGetSubTreeResponse& subtree) 2057164bc62SChau Ly { 206c181942fSQiang XU if (ec) 207c181942fSQiang XU { 2084e0453b1SGunnar Mills // do not add err msg in redfish response, because this is not 209c181942fSQiang XU // mandatory property 21062598e31SEd Tanous BMCWEB_LOG_INFO("DBUS error: no matched iface {}", ec); 211c181942fSQiang XU return; 212c181942fSQiang XU } 213c181942fSQiang XU // Iterate over all retrieved ObjectPaths. 214c181942fSQiang XU for (const auto& object : subtree) 215c181942fSQiang XU { 216840a9ffcSPatrick Williams if (!object.second.empty()) 217c181942fSQiang XU { 21889144a3aSEd Tanous const auto& service = object.second.front(); 2197164bc62SChau Ly 2207164bc62SChau Ly BMCWEB_LOG_DEBUG("Get intrusion status by service "); 2217164bc62SChau Ly 222deae6a78SEd Tanous dbus::utility::getProperty<std::string>( 223deae6a78SEd Tanous service.first, object.first, 2247164bc62SChau Ly "xyz.openbmc_project.Chassis.Intrusion", "Status", 2257164bc62SChau Ly [asyncResp](const boost::system::error_code& ec1, 2267164bc62SChau Ly const std::string& value) { 2277164bc62SChau Ly if (ec1) 2287164bc62SChau Ly { 229bd79bce8SPatrick Williams // do not add err msg in redfish response, because this 230bd79bce8SPatrick Williams // is not 2317164bc62SChau Ly // mandatory property 2327164bc62SChau Ly BMCWEB_LOG_ERROR("DBUS response error {}", ec1); 2337164bc62SChau Ly return; 2347164bc62SChau Ly } 235bd79bce8SPatrick Williams asyncResp->res.jsonValue["PhysicalSecurity"] 236bd79bce8SPatrick Williams ["IntrusionSensorNumber"] = 1; 2377164bc62SChau Ly asyncResp->res 238bd79bce8SPatrick Williams .jsonValue["PhysicalSecurity"]["IntrusionSensor"] = 239bd79bce8SPatrick Williams value; 2407164bc62SChau Ly }); 2417164bc62SChau Ly 242c181942fSQiang XU return; 243c181942fSQiang XU } 244c181942fSQiang XU } 245c181942fSQiang XU } 246c181942fSQiang XU 247cf7eba09SNan Zhou inline void handleChassisCollectionGet( 248cf7eba09SNan Zhou App& app, const crow::Request& req, 249cf7eba09SNan Zhou const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 2501abe55efSEd Tanous { 2513ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 25245ca1b86SEd Tanous { 25345ca1b86SEd Tanous return; 25445ca1b86SEd Tanous } 2558d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 2568d1b46d7Szhanghch05 "#ChassisCollection.ChassisCollection"; 2578d1b46d7Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis"; 2588d1b46d7Szhanghch05 asyncResp->res.jsonValue["Name"] = "Chassis Collection"; 259e37f8451SRapkiewicz, Pawel 26002f6ff19SGunnar Mills collection_util::getCollectionMembers( 2613f95a277SMyung Bae asyncResp, boost::urls::url("/redfish/v1/Chassis"), chassisInterfaces, 26236b5f1edSLakshmi Yadlapati "/xyz/openbmc_project/inventory"); 263cf7eba09SNan Zhou } 264cf7eba09SNan Zhou 265a5617496SJie Yang inline void getChassisContainedBy( 266a5617496SJie Yang const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 267a5617496SJie Yang const std::string& chassisId, const boost::system::error_code& ec, 26828ee563eSMyung Bae const dbus::utility::MapperGetSubTreePathsResponse& upstreamChassisPaths) 269a5617496SJie Yang { 270a5617496SJie Yang if (ec) 271a5617496SJie Yang { 272a5617496SJie Yang if (ec.value() != EBADR) 273a5617496SJie Yang { 27462598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error {}", ec); 275a5617496SJie Yang messages::internalError(asyncResp->res); 276a5617496SJie Yang } 277a5617496SJie Yang return; 278a5617496SJie Yang } 279a5617496SJie Yang if (upstreamChassisPaths.empty()) 280a5617496SJie Yang { 281a5617496SJie Yang return; 282a5617496SJie Yang } 283a5617496SJie Yang if (upstreamChassisPaths.size() > 1) 284a5617496SJie Yang { 2858ece0e45SEd Tanous BMCWEB_LOG_ERROR("{} is contained by multiple chassis", chassisId); 286a5617496SJie Yang messages::internalError(asyncResp->res); 287a5617496SJie Yang return; 288a5617496SJie Yang } 289a5617496SJie Yang 290a5617496SJie Yang sdbusplus::message::object_path upstreamChassisPath( 291a5617496SJie Yang upstreamChassisPaths[0]); 292a5617496SJie Yang std::string upstreamChassis = upstreamChassisPath.filename(); 293a5617496SJie Yang if (upstreamChassis.empty()) 294a5617496SJie Yang { 29562598e31SEd Tanous BMCWEB_LOG_WARNING("Malformed upstream Chassis path {} on {}", 29662598e31SEd Tanous upstreamChassisPath.str, chassisId); 297a5617496SJie Yang return; 298a5617496SJie Yang } 299a5617496SJie Yang 300a5617496SJie Yang asyncResp->res.jsonValue["Links"]["ContainedBy"]["@odata.id"] = 301a5617496SJie Yang boost::urls::format("/redfish/v1/Chassis/{}", upstreamChassis); 302a5617496SJie Yang } 303a5617496SJie Yang 304a5617496SJie Yang inline void getChassisContains( 305a5617496SJie Yang const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 306a5617496SJie Yang const std::string& chassisId, const boost::system::error_code& ec, 30728ee563eSMyung Bae const dbus::utility::MapperGetSubTreePathsResponse& downstreamChassisPaths) 308a5617496SJie Yang { 309a5617496SJie Yang if (ec) 310a5617496SJie Yang { 311a5617496SJie Yang if (ec.value() != EBADR) 312a5617496SJie Yang { 31362598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error {}", ec); 314a5617496SJie Yang messages::internalError(asyncResp->res); 315a5617496SJie Yang } 316a5617496SJie Yang return; 317a5617496SJie Yang } 318a5617496SJie Yang if (downstreamChassisPaths.empty()) 319a5617496SJie Yang { 320a5617496SJie Yang return; 321a5617496SJie Yang } 322a5617496SJie Yang nlohmann::json& jValue = asyncResp->res.jsonValue["Links"]["Contains"]; 323a5617496SJie Yang if (!jValue.is_array()) 324a5617496SJie Yang { 325a5617496SJie Yang // Create the array if it was empty 326a5617496SJie Yang jValue = nlohmann::json::array(); 327a5617496SJie Yang } 328a5617496SJie Yang for (const auto& p : downstreamChassisPaths) 329a5617496SJie Yang { 330a5617496SJie Yang sdbusplus::message::object_path downstreamChassisPath(p); 331a5617496SJie Yang std::string downstreamChassis = downstreamChassisPath.filename(); 332a5617496SJie Yang if (downstreamChassis.empty()) 333a5617496SJie Yang { 33462598e31SEd Tanous BMCWEB_LOG_WARNING("Malformed downstream Chassis path {} on {}", 33562598e31SEd Tanous downstreamChassisPath.str, chassisId); 336a5617496SJie Yang continue; 337a5617496SJie Yang } 338a5617496SJie Yang nlohmann::json link; 339bd79bce8SPatrick Williams link["@odata.id"] = 340bd79bce8SPatrick Williams boost::urls::format("/redfish/v1/Chassis/{}", downstreamChassis); 341a5617496SJie Yang jValue.push_back(std::move(link)); 342a5617496SJie Yang } 343a5617496SJie Yang asyncResp->res.jsonValue["Links"]["Contains@odata.count"] = jValue.size(); 344a5617496SJie Yang } 345a5617496SJie Yang 346bd79bce8SPatrick Williams inline void getChassisConnectivity( 347bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 348bd79bce8SPatrick Williams const std::string& chassisId, const std::string& chassisPath) 349a5617496SJie Yang { 35062598e31SEd Tanous BMCWEB_LOG_DEBUG("Get chassis connectivity"); 351a5617496SJie Yang 35228ee563eSMyung Bae dbus::utility::getAssociatedSubTreePaths( 353a5617496SJie Yang chassisPath + "/contained_by", 35428ee563eSMyung Bae sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), 0, 3553f95a277SMyung Bae chassisInterfaces, 356a5617496SJie Yang std::bind_front(getChassisContainedBy, asyncResp, chassisId)); 357a5617496SJie Yang 35828ee563eSMyung Bae dbus::utility::getAssociatedSubTreePaths( 359a5617496SJie Yang chassisPath + "/containing", 36028ee563eSMyung Bae sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), 0, 3613f95a277SMyung Bae chassisInterfaces, 3623f95a277SMyung Bae std::bind_front(getChassisContains, asyncResp, chassisId)); 363a5617496SJie Yang } 364a5617496SJie Yang 365cf7eba09SNan Zhou /** 366cf7eba09SNan Zhou * ChassisCollection derived class for delivering Chassis Collection Schema 367cf7eba09SNan Zhou * Functions triggers appropriate requests on DBus 368cf7eba09SNan Zhou */ 369cf7eba09SNan Zhou inline void requestRoutesChassisCollection(App& app) 370cf7eba09SNan Zhou { 371cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/") 372cf7eba09SNan Zhou .privileges(redfish::privileges::getChassisCollection) 373cf7eba09SNan Zhou .methods(boost::beast::http::verb::get)( 374cf7eba09SNan Zhou std::bind_front(handleChassisCollectionGet, std::ref(app))); 37562d5e2e4SEd Tanous } 376e37f8451SRapkiewicz, Pawel 377bd79bce8SPatrick Williams inline void getChassisLocationCode( 378bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 379bd79bce8SPatrick Williams const std::string& connectionName, const std::string& path) 380308f70c7SWilly Tu { 381deae6a78SEd Tanous dbus::utility::getProperty<std::string>( 382deae6a78SEd Tanous connectionName, path, 3831e1e598dSJonathan Doman "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode", 3845e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec, 3851e1e598dSJonathan Doman const std::string& property) { 386308f70c7SWilly Tu if (ec) 387308f70c7SWilly Tu { 38862598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error for Location"); 389308f70c7SWilly Tu messages::internalError(asyncResp->res); 390308f70c7SWilly Tu return; 391308f70c7SWilly Tu } 392308f70c7SWilly Tu 393bd79bce8SPatrick Williams asyncResp->res 394bd79bce8SPatrick Williams .jsonValue["Location"]["PartLocation"]["ServiceLabel"] = 3951e1e598dSJonathan Doman property; 3961e1e598dSJonathan Doman }); 397308f70c7SWilly Tu } 398308f70c7SWilly Tu 399308f70c7SWilly Tu inline void getChassisUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 400308f70c7SWilly Tu const std::string& connectionName, 401308f70c7SWilly Tu const std::string& path) 402308f70c7SWilly Tu { 403deae6a78SEd Tanous dbus::utility::getProperty<std::string>( 404deae6a78SEd Tanous connectionName, path, "xyz.openbmc_project.Common.UUID", "UUID", 4055e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec, 4061e1e598dSJonathan Doman const std::string& chassisUUID) { 407308f70c7SWilly Tu if (ec) 408308f70c7SWilly Tu { 40962598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error for UUID"); 410308f70c7SWilly Tu messages::internalError(asyncResp->res); 411308f70c7SWilly Tu return; 412308f70c7SWilly Tu } 4131e1e598dSJonathan Doman asyncResp->res.jsonValue["UUID"] = chassisUUID; 4141e1e598dSJonathan Doman }); 415308f70c7SWilly Tu } 416308f70c7SWilly Tu 4177164bc62SChau Ly inline void handleDecoratorAssetProperties( 41845ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 4197164bc62SChau Ly const std::string& chassisId, const std::string& path, 4207164bc62SChau Ly const dbus::utility::DBusPropertiesMap& propertiesList) 421cf7eba09SNan Zhou { 422*f7e62c14SMyung Bae asset_utils::extractAssetInfo(asyncResp, ""_json_pointer, propertiesList, 423*f7e62c14SMyung Bae true); 4247164bc62SChau Ly 4257164bc62SChau Ly asyncResp->res.jsonValue["Name"] = chassisId; 4267164bc62SChau Ly asyncResp->res.jsonValue["Id"] = chassisId; 42725b54dbaSEd Tanous 42825b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_ALLOW_DEPRECATED_POWER_THERMAL) 42925b54dbaSEd Tanous { 4307164bc62SChau Ly asyncResp->res.jsonValue["Thermal"]["@odata.id"] = 4317164bc62SChau Ly boost::urls::format("/redfish/v1/Chassis/{}/Thermal", chassisId); 4327164bc62SChau Ly // Power object 4337164bc62SChau Ly asyncResp->res.jsonValue["Power"]["@odata.id"] = 4347164bc62SChau Ly boost::urls::format("/redfish/v1/Chassis/{}/Power", chassisId); 43525b54dbaSEd Tanous } 43625b54dbaSEd Tanous 43725b54dbaSEd Tanous if constexpr (BMCWEB_REDFISH_NEW_POWERSUBSYSTEM_THERMALSUBSYSTEM) 43825b54dbaSEd Tanous { 4397164bc62SChau Ly asyncResp->res.jsonValue["ThermalSubsystem"]["@odata.id"] = 4407164bc62SChau Ly boost::urls::format("/redfish/v1/Chassis/{}/ThermalSubsystem", 4417164bc62SChau Ly chassisId); 4427164bc62SChau Ly asyncResp->res.jsonValue["PowerSubsystem"]["@odata.id"] = 44325b54dbaSEd Tanous boost::urls::format("/redfish/v1/Chassis/{}/PowerSubsystem", 44425b54dbaSEd Tanous chassisId); 4457164bc62SChau Ly asyncResp->res.jsonValue["EnvironmentMetrics"]["@odata.id"] = 4467164bc62SChau Ly boost::urls::format("/redfish/v1/Chassis/{}/EnvironmentMetrics", 4477164bc62SChau Ly chassisId); 44825b54dbaSEd Tanous } 4497164bc62SChau Ly // SensorCollection 4507164bc62SChau Ly asyncResp->res.jsonValue["Sensors"]["@odata.id"] = 4517164bc62SChau Ly boost::urls::format("/redfish/v1/Chassis/{}/Sensors", chassisId); 452539d8c6bSEd Tanous asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled; 4537164bc62SChau Ly 4547164bc62SChau Ly nlohmann::json::array_t computerSystems; 4557164bc62SChau Ly nlohmann::json::object_t system; 456bd79bce8SPatrick Williams system["@odata.id"] = 457bd79bce8SPatrick Williams std::format("/redfish/v1/Systems/{}", BMCWEB_REDFISH_SYSTEM_URI_NAME); 4587164bc62SChau Ly computerSystems.emplace_back(std::move(system)); 4597164bc62SChau Ly asyncResp->res.jsonValue["Links"]["ComputerSystems"] = 4607164bc62SChau Ly std::move(computerSystems); 4617164bc62SChau Ly 4627164bc62SChau Ly nlohmann::json::array_t managedBy; 4637164bc62SChau Ly nlohmann::json::object_t manager; 464253f11b8SEd Tanous manager["@odata.id"] = boost::urls::format("/redfish/v1/Managers/{}", 465253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 4667164bc62SChau Ly managedBy.emplace_back(std::move(manager)); 4677164bc62SChau Ly asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy); 4687164bc62SChau Ly getChassisState(asyncResp); 4697164bc62SChau Ly getStorageLink(asyncResp, path); 4707164bc62SChau Ly } 4717164bc62SChau Ly 4722952f648SJoseph-Jonathan Salzano inline void handleChassisProperties( 4732952f648SJoseph-Jonathan Salzano const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 4742952f648SJoseph-Jonathan Salzano const dbus::utility::DBusPropertiesMap& propertiesList) 4752952f648SJoseph-Jonathan Salzano { 4762952f648SJoseph-Jonathan Salzano const std::string* type = nullptr; 4772952f648SJoseph-Jonathan Salzano 4782952f648SJoseph-Jonathan Salzano const bool success = sdbusplus::unpackPropertiesNoThrow( 4792952f648SJoseph-Jonathan Salzano dbus_utils::UnpackErrorPrinter(), propertiesList, "Type", type); 4802952f648SJoseph-Jonathan Salzano 4812952f648SJoseph-Jonathan Salzano if (!success) 4822952f648SJoseph-Jonathan Salzano { 4832952f648SJoseph-Jonathan Salzano messages::internalError(asyncResp->res); 4842952f648SJoseph-Jonathan Salzano return; 4852952f648SJoseph-Jonathan Salzano } 4862952f648SJoseph-Jonathan Salzano 48719ea2864SGunnar Mills // Chassis Type is a required property in Redfish 48819ea2864SGunnar Mills // If there is an error or some enum we don't support just sit it to Rack 48919ea2864SGunnar Mills // Mount 49019ea2864SGunnar Mills asyncResp->res.jsonValue["ChassisType"] = chassis::ChassisType::RackMount; 49119ea2864SGunnar Mills 4922952f648SJoseph-Jonathan Salzano if (type != nullptr) 4932952f648SJoseph-Jonathan Salzano { 4942952f648SJoseph-Jonathan Salzano auto chassisType = translateChassisTypeToRedfish(*type); 4952952f648SJoseph-Jonathan Salzano if (chassisType != chassis::ChassisType::Invalid) 4962952f648SJoseph-Jonathan Salzano { 4972952f648SJoseph-Jonathan Salzano asyncResp->res.jsonValue["ChassisType"] = chassisType; 4982952f648SJoseph-Jonathan Salzano } 4992952f648SJoseph-Jonathan Salzano } 5002952f648SJoseph-Jonathan Salzano } 5012952f648SJoseph-Jonathan Salzano 5027164bc62SChau Ly inline void handleChassisGetSubTree( 5037164bc62SChau Ly const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 5047164bc62SChau Ly const std::string& chassisId, const boost::system::error_code& ec, 5057164bc62SChau Ly const dbus::utility::MapperGetSubTreeResponse& subtree) 5067164bc62SChau Ly { 50762d5e2e4SEd Tanous if (ec) 5081abe55efSEd Tanous { 50962598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error {}", ec); 510f12894f8SJason M. Bills messages::internalError(asyncResp->res); 511daf36e2eSEd Tanous return; 512daf36e2eSEd Tanous } 513daf36e2eSEd Tanous // Iterate over all retrieved ObjectPaths. 514cf7eba09SNan Zhou for (const std::pair< 515cf7eba09SNan Zhou std::string, 516cf7eba09SNan Zhou std::vector<std::pair<std::string, std::vector<std::string>>>>& 5171214b7e7SGunnar Mills object : subtree) 5181abe55efSEd Tanous { 519daf36e2eSEd Tanous const std::string& path = object.first; 520cf7eba09SNan Zhou const std::vector<std::pair<std::string, std::vector<std::string>>>& 5211214b7e7SGunnar Mills connectionNames = object.second; 5227e860f15SJohn Edward Broadbent 523997093ebSGeorge Liu sdbusplus::message::object_path objPath(path); 524997093ebSGeorge Liu if (objPath.filename() != chassisId) 5251abe55efSEd Tanous { 526daf36e2eSEd Tanous continue; 527daf36e2eSEd Tanous } 52826f03899SShawn McCarney 529a5617496SJie Yang getChassisConnectivity(asyncResp, chassisId, path); 530a5617496SJie Yang 53126f6976fSEd Tanous if (connectionNames.empty()) 5321abe55efSEd Tanous { 53362598e31SEd Tanous BMCWEB_LOG_ERROR("Got 0 Connection names"); 534e0d918bcSEd Tanous continue; 535daf36e2eSEd Tanous } 536e0d918bcSEd Tanous 5377164bc62SChau Ly asyncResp->res.jsonValue["@odata.type"] = "#Chassis.v1_22_0.Chassis"; 53849c53ac9SJohnathan Mantey asyncResp->res.jsonValue["@odata.id"] = 539ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/Chassis/{}", chassisId); 54049c53ac9SJohnathan Mantey asyncResp->res.jsonValue["Name"] = "Chassis Collection"; 541cf7eba09SNan Zhou asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"]["target"] = 5427164bc62SChau Ly boost::urls::format("/redfish/v1/Chassis/{}/Actions/Chassis.Reset", 5437164bc62SChau Ly chassisId); 5441476687dSEd Tanous asyncResp->res 545cf7eba09SNan Zhou .jsonValue["Actions"]["#Chassis.Reset"]["@Redfish.ActionInfo"] = 546ef4c65b7SEd Tanous boost::urls::format("/redfish/v1/Chassis/{}/ResetActionInfo", 547ef4c65b7SEd Tanous chassisId); 5486c3e9451SGeorge Liu dbus::utility::getAssociationEndPoints( 5496c3e9451SGeorge Liu path + "/drive", 5507164bc62SChau Ly [asyncResp, chassisId](const boost::system::error_code& ec3, 5516c3e9451SGeorge Liu const dbus::utility::MapperEndPoints& resp) { 55292903bd4SJohn Edward Broadbent if (ec3 || resp.empty()) 55392903bd4SJohn Edward Broadbent { 55492903bd4SJohn Edward Broadbent return; // no drives = no failures 55592903bd4SJohn Edward Broadbent } 55692903bd4SJohn Edward Broadbent 55792903bd4SJohn Edward Broadbent nlohmann::json reference; 558bd79bce8SPatrick Williams reference["@odata.id"] = boost::urls::format( 559bd79bce8SPatrick Williams "/redfish/v1/Chassis/{}/Drives", chassisId); 56092903bd4SJohn Edward Broadbent asyncResp->res.jsonValue["Drives"] = std::move(reference); 56192903bd4SJohn Edward Broadbent }); 56292903bd4SJohn Edward Broadbent 563002d39b4SEd Tanous const std::string& connectionName = connectionNames[0].first; 5641c8fba97SJames Feist 5657164bc62SChau Ly const std::vector<std::string>& interfaces2 = connectionNames[0].second; 566e5ae9c1cSGeorge Liu const std::array<const char*, 3> hasIndicatorLed = { 567e5ae9c1cSGeorge Liu "xyz.openbmc_project.Inventory.Item.Chassis", 5681c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Panel", 5690fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Item.Board.Motherboard"}; 5701c8fba97SJames Feist 571476b9cc5STejas Patil const std::string assetTagInterface = 5720fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.AssetTag"; 573523d4868SLogananth Sundararaj const std::string replaceableInterface = 574523d4868SLogananth Sundararaj "xyz.openbmc_project.Inventory.Decorator.Replaceable"; 575b4d593f1SCarson Labrado const std::string revisionInterface = 576b4d593f1SCarson Labrado "xyz.openbmc_project.Inventory.Decorator.Revision"; 577523d4868SLogananth Sundararaj for (const auto& interface : interfaces2) 578523d4868SLogananth Sundararaj { 579523d4868SLogananth Sundararaj if (interface == assetTagInterface) 580476b9cc5STejas Patil { 581deae6a78SEd Tanous dbus::utility::getProperty<std::string>( 582deae6a78SEd Tanous connectionName, path, assetTagInterface, "AssetTag", 5837164bc62SChau Ly [asyncResp, chassisId](const boost::system::error_code& ec2, 5841e1e598dSJonathan Doman const std::string& property) { 5858a592810SEd Tanous if (ec2) 586476b9cc5STejas Patil { 587bd79bce8SPatrick Williams BMCWEB_LOG_ERROR( 588bd79bce8SPatrick Williams "DBus response error for AssetTag: {}", ec2); 589476b9cc5STejas Patil messages::internalError(asyncResp->res); 590476b9cc5STejas Patil return; 591476b9cc5STejas Patil } 592002d39b4SEd Tanous asyncResp->res.jsonValue["AssetTag"] = property; 5931e1e598dSJonathan Doman }); 594476b9cc5STejas Patil } 595523d4868SLogananth Sundararaj else if (interface == replaceableInterface) 596523d4868SLogananth Sundararaj { 597deae6a78SEd Tanous dbus::utility::getProperty<bool>( 598deae6a78SEd Tanous connectionName, path, replaceableInterface, "HotPluggable", 5997164bc62SChau Ly [asyncResp, chassisId](const boost::system::error_code& ec2, 600523d4868SLogananth Sundararaj const bool property) { 601523d4868SLogananth Sundararaj if (ec2) 602523d4868SLogananth Sundararaj { 60362598e31SEd Tanous BMCWEB_LOG_ERROR( 604bd79bce8SPatrick Williams "DBus response error for HotPluggable: {}", 605bd79bce8SPatrick Williams ec2); 606523d4868SLogananth Sundararaj messages::internalError(asyncResp->res); 607523d4868SLogananth Sundararaj return; 608523d4868SLogananth Sundararaj } 609523d4868SLogananth Sundararaj asyncResp->res.jsonValue["HotPluggable"] = property; 610523d4868SLogananth Sundararaj }); 611523d4868SLogananth Sundararaj } 612b4d593f1SCarson Labrado else if (interface == revisionInterface) 613b4d593f1SCarson Labrado { 614deae6a78SEd Tanous dbus::utility::getProperty<std::string>( 615deae6a78SEd Tanous connectionName, path, revisionInterface, "Version", 616b4d593f1SCarson Labrado [asyncResp, chassisId](const boost::system::error_code& ec2, 617b4d593f1SCarson Labrado const std::string& property) { 618b4d593f1SCarson Labrado if (ec2) 619b4d593f1SCarson Labrado { 620bd79bce8SPatrick Williams BMCWEB_LOG_ERROR( 621bd79bce8SPatrick Williams "DBus response error for Version: {}", ec2); 622b4d593f1SCarson Labrado messages::internalError(asyncResp->res); 623b4d593f1SCarson Labrado return; 624b4d593f1SCarson Labrado } 625b4d593f1SCarson Labrado asyncResp->res.jsonValue["Version"] = property; 626b4d593f1SCarson Labrado }); 627b4d593f1SCarson Labrado } 628523d4868SLogananth Sundararaj } 629476b9cc5STejas Patil 6301c8fba97SJames Feist for (const char* interface : hasIndicatorLed) 6311c8fba97SJames Feist { 6327164bc62SChau Ly if (std::ranges::find(interfaces2, interface) != interfaces2.end()) 6331c8fba97SJames Feist { 634f664fd8aSJanet Adkins if constexpr (BMCWEB_REDFISH_ALLOW_DEPRECATED_INDICATORLED) 635f664fd8aSJanet Adkins { 6361c8fba97SJames Feist getIndicatorLedState(asyncResp); 637f664fd8aSJanet Adkins } 638de8e5144SJanet Adkins getLocationIndicatorActive(asyncResp, objPath); 6391c8fba97SJames Feist break; 6401c8fba97SJames Feist } 6411c8fba97SJames Feist } 6421c8fba97SJames Feist 643deae6a78SEd Tanous dbus::utility::getAllProperties( 64486d89ed7SKrzysztof Grobelny *crow::connections::systemBus, connectionName, path, 64586d89ed7SKrzysztof Grobelny "xyz.openbmc_project.Inventory.Decorator.Asset", 6467164bc62SChau Ly [asyncResp, chassisId, 6477164bc62SChau Ly path](const boost::system::error_code&, 648cf7eba09SNan Zhou const dbus::utility::DBusPropertiesMap& propertiesList) { 6497164bc62SChau Ly handleDecoratorAssetProperties(asyncResp, chassisId, path, 6507164bc62SChau Ly propertiesList); 65186d89ed7SKrzysztof Grobelny }); 6522c37b4b0SSharad Yadav 65346f780f7SEd Tanous dbus::utility::getAllProperties( 6542952f648SJoseph-Jonathan Salzano *crow::connections::systemBus, connectionName, path, 6552952f648SJoseph-Jonathan Salzano "xyz.openbmc_project.Inventory.Item.Chassis", 6562952f648SJoseph-Jonathan Salzano [asyncResp]( 6572952f648SJoseph-Jonathan Salzano const boost::system::error_code&, 6582952f648SJoseph-Jonathan Salzano const dbus::utility::DBusPropertiesMap& propertiesList) { 6592952f648SJoseph-Jonathan Salzano handleChassisProperties(asyncResp, propertiesList); 6602952f648SJoseph-Jonathan Salzano }); 6612952f648SJoseph-Jonathan Salzano 662308f70c7SWilly Tu for (const auto& interface : interfaces2) 6632c37b4b0SSharad Yadav { 664308f70c7SWilly Tu if (interface == "xyz.openbmc_project.Common.UUID") 6652c37b4b0SSharad Yadav { 666308f70c7SWilly Tu getChassisUUID(asyncResp, connectionName, path); 6672c37b4b0SSharad Yadav } 668cf7eba09SNan Zhou else if (interface == 6690fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Decorator.LocationCode") 6702c37b4b0SSharad Yadav { 671002d39b4SEd Tanous getChassisLocationCode(asyncResp, connectionName, path); 6722c37b4b0SSharad Yadav } 6732c37b4b0SSharad Yadav } 6742c37b4b0SSharad Yadav 675daf36e2eSEd Tanous return; 676daf36e2eSEd Tanous } 677e0d918bcSEd Tanous 678daf36e2eSEd Tanous // Couldn't find an object with that name. return an error 679d8a5d5d8SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "Chassis", chassisId); 6807164bc62SChau Ly } 681c181942fSQiang XU 682504af5a0SPatrick Williams inline void handleChassisGet( 683504af5a0SPatrick Williams App& app, const crow::Request& req, 6847164bc62SChau Ly const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 6857164bc62SChau Ly const std::string& chassisId) 6867164bc62SChau Ly { 6877164bc62SChau Ly if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 6887164bc62SChau Ly { 6897164bc62SChau Ly return; 6907164bc62SChau Ly } 6917164bc62SChau Ly 6927164bc62SChau Ly dbus::utility::getSubTree( 6933f95a277SMyung Bae "/xyz/openbmc_project/inventory", 0, chassisInterfaces, 6947164bc62SChau Ly std::bind_front(handleChassisGetSubTree, asyncResp, chassisId)); 6957164bc62SChau Ly 6967164bc62SChau Ly constexpr std::array<std::string_view, 1> interfaces2 = { 6977164bc62SChau Ly "xyz.openbmc_project.Chassis.Intrusion"}; 6987164bc62SChau Ly 6997164bc62SChau Ly dbus::utility::getSubTree( 7007164bc62SChau Ly "/xyz/openbmc_project", 0, interfaces2, 7017164bc62SChau Ly std::bind_front(handlePhysicalSecurityGetSubTree, asyncResp)); 702cf7eba09SNan Zhou } 7031c8fba97SJames Feist 704504af5a0SPatrick Williams inline void handleChassisPatch( 705504af5a0SPatrick Williams App& app, const crow::Request& req, 7067e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 707cf7eba09SNan Zhou const std::string& param) 708cf7eba09SNan Zhou { 7093ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 71045ca1b86SEd Tanous { 71145ca1b86SEd Tanous return; 71245ca1b86SEd Tanous } 7139f8bfa7cSGunnar Mills std::optional<bool> locationIndicatorActive; 7141c8fba97SJames Feist std::optional<std::string> indicatorLed; 7151c8fba97SJames Feist 7167e860f15SJohn Edward Broadbent if (param.empty()) 7171c8fba97SJames Feist { 7181c8fba97SJames Feist return; 7191c8fba97SJames Feist } 7201c8fba97SJames Feist 721afc474aeSMyung Bae if (!json_util::readJsonPatch( // 722afc474aeSMyung Bae req, asyncResp->res, // 723afc474aeSMyung Bae "IndicatorLED", indicatorLed, // 724afc474aeSMyung Bae "LocationIndicatorActive", locationIndicatorActive // 725afc474aeSMyung Bae )) 7261c8fba97SJames Feist { 7271c8fba97SJames Feist return; 7281c8fba97SJames Feist } 7291c8fba97SJames Feist 7309f8bfa7cSGunnar Mills if (!locationIndicatorActive && !indicatorLed) 7311c8fba97SJames Feist { 7321c8fba97SJames Feist return; // delete this when we support more patch properties 7331c8fba97SJames Feist } 734d6aa0093SGunnar Mills if (indicatorLed) 735d6aa0093SGunnar Mills { 736f664fd8aSJanet Adkins if constexpr (BMCWEB_REDFISH_ALLOW_DEPRECATED_INDICATORLED) 737f664fd8aSJanet Adkins { 7387e860f15SJohn Edward Broadbent asyncResp->res.addHeader( 7397e860f15SJohn Edward Broadbent boost::beast::http::field::warning, 7400fda0f12SGeorge Liu "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\""); 741d6aa0093SGunnar Mills } 742f664fd8aSJanet Adkins else 743f664fd8aSJanet Adkins { 744f664fd8aSJanet Adkins messages::propertyUnknown(asyncResp->res, "IndicatorLED"); 745f664fd8aSJanet Adkins return; 746f664fd8aSJanet Adkins } 747f664fd8aSJanet Adkins } 7481c8fba97SJames Feist 7497e860f15SJohn Edward Broadbent const std::string& chassisId = param; 7501c8fba97SJames Feist 751e99073f5SGeorge Liu dbus::utility::getSubTree( 7523f95a277SMyung Bae "/xyz/openbmc_project/inventory", 0, chassisInterfaces, 753cf7eba09SNan Zhou [asyncResp, chassisId, locationIndicatorActive, 7545e7e2dc5SEd Tanous indicatorLed](const boost::system::error_code& ec, 755b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreeResponse& subtree) { 7561c8fba97SJames Feist if (ec) 7571c8fba97SJames Feist { 75862598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error {}", ec); 7591c8fba97SJames Feist messages::internalError(asyncResp->res); 7601c8fba97SJames Feist return; 7611c8fba97SJames Feist } 7621c8fba97SJames Feist 7631c8fba97SJames Feist // Iterate over all retrieved ObjectPaths. 764bd79bce8SPatrick Williams for (const std::pair<std::string, 765bd79bce8SPatrick Williams std::vector<std::pair< 766bd79bce8SPatrick Williams std::string, std::vector<std::string>>>>& 7671214b7e7SGunnar Mills object : subtree) 7681c8fba97SJames Feist { 7691c8fba97SJames Feist const std::string& path = object.first; 770bd79bce8SPatrick Williams const std::vector< 771bd79bce8SPatrick Williams std::pair<std::string, std::vector<std::string>>>& 7721214b7e7SGunnar Mills connectionNames = object.second; 7731c8fba97SJames Feist 774997093ebSGeorge Liu sdbusplus::message::object_path objPath(path); 775997093ebSGeorge Liu if (objPath.filename() != chassisId) 7761c8fba97SJames Feist { 7771c8fba97SJames Feist continue; 7781c8fba97SJames Feist } 7791c8fba97SJames Feist 78026f6976fSEd Tanous if (connectionNames.empty()) 7811c8fba97SJames Feist { 78262598e31SEd Tanous BMCWEB_LOG_ERROR("Got 0 Connection names"); 7831c8fba97SJames Feist continue; 7841c8fba97SJames Feist } 7851c8fba97SJames Feist 78623a21a1cSEd Tanous const std::vector<std::string>& interfaces3 = 7871c8fba97SJames Feist connectionNames[0].second; 7881c8fba97SJames Feist 789e5ae9c1cSGeorge Liu const std::array<const char*, 3> hasIndicatorLed = { 790e5ae9c1cSGeorge Liu "xyz.openbmc_project.Inventory.Item.Chassis", 7911c8fba97SJames Feist "xyz.openbmc_project.Inventory.Item.Panel", 7920fda0f12SGeorge Liu "xyz.openbmc_project.Inventory.Item.Board.Motherboard"}; 7931c8fba97SJames Feist bool indicatorChassis = false; 7941c8fba97SJames Feist for (const char* interface : hasIndicatorLed) 7951c8fba97SJames Feist { 7963544d2a7SEd Tanous if (std::ranges::find(interfaces3, interface) != 7973544d2a7SEd Tanous interfaces3.end()) 7981c8fba97SJames Feist { 7991c8fba97SJames Feist indicatorChassis = true; 8001c8fba97SJames Feist break; 8011c8fba97SJames Feist } 8021c8fba97SJames Feist } 8039f8bfa7cSGunnar Mills if (locationIndicatorActive) 8049f8bfa7cSGunnar Mills { 8059f8bfa7cSGunnar Mills if (indicatorChassis) 8069f8bfa7cSGunnar Mills { 807de8e5144SJanet Adkins setLocationIndicatorActive(asyncResp, path, 808de8e5144SJanet Adkins *locationIndicatorActive); 8099f8bfa7cSGunnar Mills } 8109f8bfa7cSGunnar Mills else 8119f8bfa7cSGunnar Mills { 812002d39b4SEd Tanous messages::propertyUnknown(asyncResp->res, 813002d39b4SEd Tanous "LocationIndicatorActive"); 8149f8bfa7cSGunnar Mills } 8159f8bfa7cSGunnar Mills } 816f664fd8aSJanet Adkins if constexpr (BMCWEB_REDFISH_ALLOW_DEPRECATED_INDICATORLED) 817f664fd8aSJanet Adkins { 8189f8bfa7cSGunnar Mills if (indicatorLed) 8199f8bfa7cSGunnar Mills { 8201c8fba97SJames Feist if (indicatorChassis) 8211c8fba97SJames Feist { 822f23b7296SEd Tanous setIndicatorLedState(asyncResp, *indicatorLed); 8231c8fba97SJames Feist } 8241c8fba97SJames Feist else 8251c8fba97SJames Feist { 826bd79bce8SPatrick Williams messages::propertyUnknown(asyncResp->res, 827bd79bce8SPatrick Williams "IndicatorLED"); 8281c8fba97SJames Feist } 8291c8fba97SJames Feist } 830f664fd8aSJanet Adkins } 8311c8fba97SJames Feist return; 8321c8fba97SJames Feist } 8331c8fba97SJames Feist 834d8a5d5d8SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "Chassis", chassisId); 835e99073f5SGeorge Liu }); 836cf7eba09SNan Zhou } 837cf7eba09SNan Zhou 838cf7eba09SNan Zhou /** 839cf7eba09SNan Zhou * Chassis override class for delivering Chassis Schema 840cf7eba09SNan Zhou * Functions triggers appropriate requests on DBus 841cf7eba09SNan Zhou */ 842cf7eba09SNan Zhou inline void requestRoutesChassis(App& app) 843cf7eba09SNan Zhou { 844cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/") 845cf7eba09SNan Zhou .privileges(redfish::privileges::getChassis) 846cf7eba09SNan Zhou .methods(boost::beast::http::verb::get)( 847cf7eba09SNan Zhou std::bind_front(handleChassisGet, std::ref(app))); 848cf7eba09SNan Zhou 849cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/") 850cf7eba09SNan Zhou .privileges(redfish::privileges::patchChassis) 851cf7eba09SNan Zhou .methods(boost::beast::http::verb::patch)( 852cf7eba09SNan Zhou std::bind_front(handleChassisPatch, std::ref(app))); 8531c8fba97SJames Feist } 854dd99e04bSP.K. Lee 855504af5a0SPatrick Williams inline void doChassisPowerCycle( 856504af5a0SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 857dd99e04bSP.K. Lee { 8587a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 859c3b3c92aSVijay Khemka "xyz.openbmc_project.State.Chassis"}; 860c3b3c92aSVijay Khemka 861c3b3c92aSVijay Khemka // Use mapper to get subtree paths. 8627a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 8637a1dbc48SGeorge Liu "/", 0, interfaces, 864b9d36b47SEd Tanous [asyncResp]( 8657a1dbc48SGeorge Liu const boost::system::error_code& ec, 866b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& chassisList) { 867c3b3c92aSVijay Khemka if (ec) 868c3b3c92aSVijay Khemka { 86962598e31SEd Tanous BMCWEB_LOG_ERROR("[mapper] Bad D-Bus request error: {}", ec); 870c3b3c92aSVijay Khemka messages::internalError(asyncResp->res); 871c3b3c92aSVijay Khemka return; 872c3b3c92aSVijay Khemka } 873c3b3c92aSVijay Khemka 874dd99e04bSP.K. Lee const char* processName = "xyz.openbmc_project.State.Chassis"; 875dd99e04bSP.K. Lee const char* interfaceName = "xyz.openbmc_project.State.Chassis"; 876dd99e04bSP.K. Lee const char* destProperty = "RequestedPowerTransition"; 877dd99e04bSP.K. Lee const std::string propertyValue = 878dd99e04bSP.K. Lee "xyz.openbmc_project.State.Chassis.Transition.PowerCycle"; 879bd79bce8SPatrick Williams std::string objectPath = 880bd79bce8SPatrick Williams "/xyz/openbmc_project/state/chassis_system0"; 881c3b3c92aSVijay Khemka 882c3b3c92aSVijay Khemka /* Look for system reset chassis path */ 883bd79bce8SPatrick Williams if ((std::ranges::find(chassisList, objectPath)) == 884bd79bce8SPatrick Williams chassisList.end()) 885c3b3c92aSVijay Khemka { 886c3b3c92aSVijay Khemka /* We prefer to reset the full chassis_system, but if it doesn't 887c3b3c92aSVijay Khemka * exist on some platforms, fall back to a host-only power reset 888c3b3c92aSVijay Khemka */ 889c3b3c92aSVijay Khemka objectPath = "/xyz/openbmc_project/state/chassis0"; 890c3b3c92aSVijay Khemka } 891dd99e04bSP.K. Lee 892e93abac6SGinu George setDbusProperty(asyncResp, "ResetType", processName, objectPath, 893e93abac6SGinu George interfaceName, destProperty, propertyValue); 8947a1dbc48SGeorge Liu }); 895dd99e04bSP.K. Lee } 896dd99e04bSP.K. Lee 897cf7eba09SNan Zhou inline void handleChassisResetActionInfoPost( 898cf7eba09SNan Zhou App& app, const crow::Request& req, 8997e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 900cf7eba09SNan Zhou const std::string& /*chassisId*/) 901cf7eba09SNan Zhou { 9023ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 90345ca1b86SEd Tanous { 90445ca1b86SEd Tanous return; 90545ca1b86SEd Tanous } 90662598e31SEd Tanous BMCWEB_LOG_DEBUG("Post Chassis Reset."); 907dd99e04bSP.K. Lee 908dd99e04bSP.K. Lee std::string resetType; 909dd99e04bSP.K. Lee 910cf7eba09SNan Zhou if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType)) 911dd99e04bSP.K. Lee { 912dd99e04bSP.K. Lee return; 913dd99e04bSP.K. Lee } 914dd99e04bSP.K. Lee 915dd99e04bSP.K. Lee if (resetType != "PowerCycle") 916dd99e04bSP.K. Lee { 91762598e31SEd Tanous BMCWEB_LOG_DEBUG("Invalid property value for ResetType: {}", resetType); 918002d39b4SEd Tanous messages::actionParameterNotSupported(asyncResp->res, resetType, 919002d39b4SEd Tanous "ResetType"); 920dd99e04bSP.K. Lee 921dd99e04bSP.K. Lee return; 922dd99e04bSP.K. Lee } 923dd99e04bSP.K. Lee doChassisPowerCycle(asyncResp); 924dd99e04bSP.K. Lee } 9251cb1a9e6SAppaRao Puli 9261cb1a9e6SAppaRao Puli /** 927cf7eba09SNan Zhou * ChassisResetAction class supports the POST method for the Reset 928cf7eba09SNan Zhou * action. 929cf7eba09SNan Zhou * Function handles POST method request. 930cf7eba09SNan Zhou * Analyzes POST body before sending Reset request data to D-Bus. 9311cb1a9e6SAppaRao Puli */ 932cf7eba09SNan Zhou 933cf7eba09SNan Zhou inline void requestRoutesChassisResetAction(App& app) 9341cb1a9e6SAppaRao Puli { 935cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/") 936cf7eba09SNan Zhou .privileges(redfish::privileges::postChassis) 937cf7eba09SNan Zhou .methods(boost::beast::http::verb::post)( 938cf7eba09SNan Zhou std::bind_front(handleChassisResetActionInfoPost, std::ref(app))); 939cf7eba09SNan Zhou } 940cf7eba09SNan Zhou 941cf7eba09SNan Zhou inline void handleChassisResetActionInfoGet( 942cf7eba09SNan Zhou App& app, const crow::Request& req, 9437e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 944cf7eba09SNan Zhou const std::string& chassisId) 945cf7eba09SNan Zhou { 9463ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 9471cb1a9e6SAppaRao Puli { 94845ca1b86SEd Tanous return; 94945ca1b86SEd Tanous } 950cf7eba09SNan Zhou asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo"; 951ef4c65b7SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 952ef4c65b7SEd Tanous "/redfish/v1/Chassis/{}/ResetActionInfo", chassisId); 9531476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "Reset Action Info"; 9541476687dSEd Tanous 9551476687dSEd Tanous asyncResp->res.jsonValue["Id"] = "ResetActionInfo"; 9565b9e95a1SNan Zhou nlohmann::json::array_t parameters; 9575b9e95a1SNan Zhou nlohmann::json::object_t parameter; 9585b9e95a1SNan Zhou parameter["Name"] = "ResetType"; 9595b9e95a1SNan Zhou parameter["Required"] = true; 960539d8c6bSEd Tanous parameter["DataType"] = action_info::ParameterTypes::String; 9611476687dSEd Tanous nlohmann::json::array_t allowed; 962ad539545SPatrick Williams allowed.emplace_back("PowerCycle"); 9635b9e95a1SNan Zhou parameter["AllowableValues"] = std::move(allowed); 964ad539545SPatrick Williams parameters.emplace_back(std::move(parameter)); 9655b9e95a1SNan Zhou 9661476687dSEd Tanous asyncResp->res.jsonValue["Parameters"] = std::move(parameters); 967cf7eba09SNan Zhou } 968cf7eba09SNan Zhou 969cf7eba09SNan Zhou /** 970cf7eba09SNan Zhou * ChassisResetActionInfo derived class for delivering Chassis 971cf7eba09SNan Zhou * ResetType AllowableValues using ResetInfo schema. 972cf7eba09SNan Zhou */ 973cf7eba09SNan Zhou inline void requestRoutesChassisResetActionInfo(App& app) 974cf7eba09SNan Zhou { 975cf7eba09SNan Zhou BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/") 976cf7eba09SNan Zhou .privileges(redfish::privileges::getActionInfo) 977cf7eba09SNan Zhou .methods(boost::beast::http::verb::get)( 978cf7eba09SNan Zhou std::bind_front(handleChassisResetActionInfoGet, std::ref(app))); 9791cb1a9e6SAppaRao Puli } 9801cb1a9e6SAppaRao Puli 981e37f8451SRapkiewicz, Pawel } // namespace redfish 982